pax_global_header00006660000000000000000000000064134736015110014513gustar00rootroot0000000000000052 comment=6efb71bea773837c6fc4aae0c8270b2d70e3e69f cc65-2.18/000077500000000000000000000000001347360151100122055ustar00rootroot00000000000000cc65-2.18/.gitattributes000066400000000000000000000000141347360151100150730ustar00rootroot00000000000000* text=auto cc65-2.18/.gitignore000066400000000000000000000001061347360151100141720ustar00rootroot00000000000000/bin/ /html/ /info/ /lib/ /libwrk/ /target/ /testwrk/ /wrk/ /cc65.zip cc65-2.18/.travis.yml000066400000000000000000000006121347360151100143150ustar00rootroot00000000000000language: - 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 QUIET=1 - make -C src clean - make bin USER_CFLAGS=-Werror CROSS_COMPILE=i686-w64-mingw32- - make doc zip after_success: - make -f Makefile.travis cc65-2.18/LICENSE000066400000000000000000000014501347360151100132120ustar00rootroot00000000000000This 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. 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. cc65-2.18/Makefile000066400000000000000000000012061347360151100136440ustar00rootroot00000000000000.PHONY: all mostlyclean clean install zip avail unavail bin lib doc html info samples .SUFFIXES: all mostlyclean clean install zip: @$(MAKE) -C src --no-print-directory $@ @$(MAKE) -C libsrc --no-print-directory $@ @$(MAKE) -C doc --no-print-directory $@ @$(MAKE) -C samples --no-print-directory $@ avail unavail bin: @$(MAKE) -C src --no-print-directory $@ lib: @$(MAKE) -C libsrc --no-print-directory $@ doc html info: @$(MAKE) -C doc --no-print-directory $@ samples: @$(MAKE) -C samples --no-print-directory $@ %65: @$(MAKE) -C src --no-print-directory $@ %: @$(MAKE) -C libsrc --no-print-directory $@ cc65-2.18/Makefile.travis000066400000000000000000000020511347360151100151520ustar00rootroot00000000000000.PHONY: all gh-pages sf-files .SUFFIXES: all: gh-pages sf-files GH_NAME = Oliver Schmidt GH_MAIL = ol.sc@web.de GH_PATH = ../doc gh-pages: ifdef GH_TOKEN @echo 'git clone https://$$(GH_TOKEN)@github.com/cc65/doc.git $(GH_PATH)' @git clone https://$(GH_TOKEN)@github.com/cc65/doc.git $(GH_PATH) cd $(GH_PATH) && git config user.name "$(GH_NAME)" cd $(GH_PATH) && git config user.email "$(GH_MAIL)" cd $(GH_PATH) && git config push.default simple $(RM) $(GH_PATH)/*.* cp html/*.* $(GH_PATH) cd $(GH_PATH) && git add -A -cd $(GH_PATH) && git commit -m "Updated from commit $(TRAVIS_COMMIT)." cd $(GH_PATH) && git push -q endif SF_USER = oliverschmidt SF_HOST = frs.sourceforge.net SF_FILE = /home/frs/project/cc65/cc65-snapshot-win32.zip SCPFLAGS = -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -q sf-files: ifdef SF_PASS echo $(TRAVIS_COMMIT) | zip -z cc65 @echo 'sshpass -p $$(SF_PASS) scp $(SCPFLAGS) cc65.zip $(SF_USER)@$(SF_HOST):$(SF_FILE)' @sshpass -p $(SF_PASS) scp $(SCPFLAGS) cc65.zip $(SF_USER)@$(SF_HOST):$(SF_FILE) endif cc65-2.18/README.md000066400000000000000000000023601347360151100134650ustar00rootroot00000000000000[Windows Snapshot](https://sourceforge.net/projects/cc65/files/cc65-snapshot-win32.zip) [Documentation](https://cc65.github.io/doc) [Wiki](https://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 other tools. cc65 has C and runtime library support for many of the old 6502 machines, including - the following Commodore machines: - VIC20 - C16/C116 and Plus/4 - C64 - C128 - CBM 510 (aka P500) - the 600/700 family - newer PET machines (not 2001). - the Apple ]\[+ and successors. - the Atari 8 bit machines. - the Atari 2600 console. - the Atari 5200 console. - GEOS for the C64, C128 and Apple //e. - the Bit Corporation Gamate console. - the NEC PC-Engine (aka TurboGrafx-16) console. - the Nintendo Entertainment System (NES) console. - the Watara Supervision console. - the VTech Creativision console. - the Oric Atmos. - the Oric Telestrat. - 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. cc65-2.18/asminc/000077500000000000000000000000001347360151100134575ustar00rootroot00000000000000cc65-2.18/asminc/_file.inc000066400000000000000000000007241347360151100152330ustar00rootroot00000000000000; ; _file.inc ; ; (C) Copyright 2002 Ullrich von Bassewitz (uz@cc65.org) ; ; Assembler include file that makes the constants and structures in _file.h ; available for asm code. ; Struct _FILE .struct _FILE f_fd .byte f_flags .byte f_pushback .byte .endstruct ; Flags field _FCLOSED = $00 _FOPEN = $01 _FEOF = $02 _FERROR = $04 _FPUSHBACK = $08 ; File table .global __filetab cc65-2.18/asminc/_heap.inc000066400000000000000000000015601347360151100152300ustar00rootroot00000000000000; ; _heap.inc ; ; (c) Copyright 2003, Ullrich von Bassewitz (uz@cc65.org) ; ; Assembler include file that makes the constants and structures in _heap.h ; available for asm code. ; Struct freeblock ; NOTE: For performance reasons, the asm code often uses increment/decrement ; operators to access other offsets, so just changing offsets here will ; probably not work. .struct freeblock size .word next .addr prev .addr .endstruct ; Struct usedblock ; See notes above .struct usedblock size .word start .addr .endstruct HEAP_MIN_BLOCKSIZE = .sizeof (freeblock) ; Minimum size of an allocated block HEAP_ADMIN_SPACE = .sizeof (usedblock) ; Additional space for used bock ; Variables .global __heaporg .global __heapptr .global __heapend .global __heapfirst .global __heaplast cc65-2.18/asminc/accelerator.inc000066400000000000000000000032441347360151100164410ustar00rootroot00000000000000; ; Accelerator definitions. ; ; --------------------------------------------------------------------------- ; Speed definitions for all accelerator, to be used as input for the 'set' ; functions. SPEED_SLOW = $00 SPEED_FAST = $FF SPEED_1X = SPEED_SLOW SPEED_2X = 2 - 1 SPEED_3X = 3 - 1 SPEED_4X = 4 - 1 SPEED_5X = 5 - 1 SPEED_6X = 6 - 1 SPEED_7X = 7 - 1 SPEED_8X = 8 - 1 SPEED_10X = 10 - 1 SPEED_12X = 12 - 1 SPEED_16X = 16 - 1 SPEED_20X = 20 - 1 ; --------------------------------------------------------------------------- ; C64/C128 Super CPU cartridge SuperCPU_Slow := $D07A SuperCPU_Fast := $D07B SuperCPU_Speed_Mode := $D0B8 SuperCPU_Detect := $D0BC ; --------------------------------------------------------------------------- ; C64DTV C64DTV_Extended_Regs := $D03F C64DTV_Slow = $00 C64DTV_Fast = $03 ; --------------------------------------------------------------------------- ; C128 native and C128 in C64 mode C128_VICIIE_CLK := $D030 ; --------------------------------------------------------------------------- ; C64 Chameleon cartridge CHAMELEON_CFGTUR := $D0F3 CHAMELEON_CFGENA := $D0FE CHAMELEON_ENABLE_REGS = $2A CHAMELEON_DISABLE_REGS = $FF CHAMELEON_CFGTUR_LIMIT_1MHZ = %00001100 CHAMELEON_CFGTUR_LIMIT_NONE = %10000000 ; --------------------------------------------------------------------------- ; C65/C64DX in C64 mode C65_VICIII_KEY := $D02F C65_VICIII_CTRL_B := $D031 C65_VICIII_UNLOCK_1 = $A5 C65_VICIII_UNLOCK_2 = $96 ; --------------------------------------------------------------------------- ; C64 Turbo Master cartridge TURBOMASTER_DETECT := $BF53 TURBOMASTER_SPEED_REG := $00 cc65-2.18/asminc/apple2.inc000066400000000000000000000044541347360151100153440ustar00rootroot00000000000000 ;----------------------------------------------------------------------------- ; Zero page stuff WNDLFT := $20 ; Text window left WNDWDTH := $21 ; Text window width WNDTOP := $22 ; Text window top WNDBTM := $23 ; Text window bottom+1 CH := $24 ; Cursor horizontal position CV := $25 ; Cursor vertical position BASL := $28 ; Text base address low BASH := $29 ; Text base address high INVFLG := $32 ; Normal/inverse(/flash) PROMPT := $33 ; Used by GETLN RNDL := $4E ; Random counter low RNDH := $4F ; Random counter high HIMEM := $73 ; Highest available memory address+1 ;----------------------------------------------------------------------------- ; Vectors DOSWARM := $03D0 ; DOS warmstart vector BRKVec := $03F0 ; Break vector SOFTEV := $03F2 ; Vector for warm start PWREDUP := $03F4 ; This must be = EOR #$A5 of SOFTEV+1 ;----------------------------------------------------------------------------- ; Hardware ; Keyboard input KBD := $C000 ; Read keyboard KBDSTRB := $C010 ; Clear keyboard strobe ; 80 column video switches CLR80COL:= $C000 ; Disable 80 column store SET80COL:= $C001 ; Enable 80 column store RD80COL := $C018 ; >127 if 80 column store enabled RD80VID := $C01F ; >127 if 80 column video enabled ; Character set switches CLRALTCHAR := $C00E ; Normal Apple II char set SETALTCHAR := $C00F ; Norm/inv LC, no flash ALTCHARSET := $C01E ; >127 if alt charset switched in ; Language card switches RDLCBNK2:= $C011 ; >127 if LC bank 2 in use RDLCRAM := $C012 ; >127 if LC is read enabled ROMIN := $C081 ; Swap in D000-FFFF ROM LCBANK2 := $C083 ; Swap in LC bank 2 LCBANK1 := $C08B ; Swap in LC bank 1 ; Video mode switches TXTCLR := $C050 ; Display graphics TXTSET := $C051 ; Display text MIXCLR := $C052 ; Disable 4 lines of text MIXSET := $C053 ; Enable 4 lines of text LOWSCR := $C054 ; Page 1 HISCR := $C055 ; Page 2 LORES := $C056 ; Lores graphics HIRES := $C057 ; Hires graphics ; Game controller BUTN0 := $C061 ; Open-Apple Key BUTN1 := $C062 ; Closed-Apple Key cc65-2.18/asminc/apple2.mac000066400000000000000000000024101347360151100153210ustar00rootroot00000000000000; Convert characters to screen codes ; Helper macro that converts and outputs one character .macro _scrcode char .if (char < 256) .byte (char + 128) .else .error "scrcode: Character constant out of range" .endif .endmacro .macro scrcode arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 ; Bail out if next argument is empty .if .blank (arg1) .exitmacro .endif ; Check for a string .if .match ({arg1}, "") ; Walk over all string chars .repeat .strlen (arg1), i _scrcode {.strat (arg1, i)} .endrepeat ; Check for a number .elseif .match (.left (1, {arg1}), 0) ; Just output the number _scrcode arg1 ; Check for a character .elseif .match (.left (1, {arg1}), 'a') ; Just output the character _scrcode arg1 ; Anything else is an error .else .error "scrcode: invalid argument type" .endif ; Call the macro recursively with the remaining args scrcode arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 .endmacro cc65-2.18/asminc/atari.inc000066400000000000000000001351121347360151100152550ustar00rootroot00000000000000;------------------------------------------------------------------------- ; Atari System Equates ; by Freddy Offenga, Christian Groessler, and Christian Krueger ; ; References: ; - Atari 400/800 OS rev.B source code, Atari 1979 ; - Atari OS manual - XL addendum ; - Atari XL/XE rev.2 source code, Atari 1984 ; - Mapping the Atari - revised edition, Ian Chadwick 1985 ; - SpartaDOS-X User Guide (Aug-8-2016) ; ; ##old## old OS rev.B label - moved or deleted ; ##1200xl## new label introduced in 1200XL OS (rev.10/11) ; ##rev2## new label introduced in XL/XE OS rev.2 ;------------------------------------------------------------------------- ;------------------------------------------------------------------------- ; Configuration Equates ;------------------------------------------------------------------------- MAXDEV = 33 ;offset to last possible entry of HATABS IOCBSZ = 16 ;length of IOCB SEIOCB = 0*IOCBSZ ;##rev2## screen editor IOCB index MAXIOC = 8*IOCBSZ ;first invalid IOCB index DSCTSZ = 128 ;##rev2## disk sector size LEDGE = 2 ;left edge REDGE = 39 ;right edge INIML = $0700 ;##rev2## initial MEMLO ICSORG = $CC00 ;##rev2## international character set origin DCSORG = $E000 ;##rev2## domestic character set origin ; IOCB Command Code Equates OPEN = $03 ;open GETREC = $05 ;get record GETCHR = $07 ;get character(s) PUTREC = $09 ;put record PUTCHR = $0B ;put character(s) CLOSE = $0C ;close STATIS = $0D ;status SPECIL = $0E ;special ; DOS IOCB command codes RENAME = $20 ;rename disk file DELETE = $21 ;delete disk file LOCKFL = $23 ;lock file (set to read-only) UNLOCK = $24 ;unlock file POINT = $25 ;point sector NOTE = $26 ;note sector GETFL = $27 ;get file length CHDIR_MYDOS = $29 ;change directory (MyDOS) MKDIR = $2A ;make directory (MyDOS/SpartaDOS) RMDIR = $2B ;remove directory (SpartaDOS) CHDIR_SPDOS = $2C ;change directory (SpartaDOS) FORMAT = $FE ;format GETCWD = $30 ;get current directory (MyDOS/SpartaDOS) ; Special Entry Command Equates ; DOS Commands ; Command line table, Index values for (DOSVEC),Y -- COMTAB ; Compatible with OS/A+, DOS XL and SpartaDOS COMTAB = 0 ;DOS entry jump vector ZCRNAME = 3 ;file name crunch routine jump vector BUFOFF = 10 ;next parameter buffer offset COMFNAM = 33 ;destination buffer for crunch routine LBUF = 63 ;command line input buffer ; Screen IOCB Commands DRAWLN = $11 ;draw line FILLIN = $12 ;draw line with right fill ; ICAX1 Auxiliary Byte 1 Equates APPEND = $01 ;open write append (D:) DIRECT = $02 ;open for directory access (D:) OPNIN = $04 ;open for input (all devices) OPNOT = $08 ;open for output (all devices) MXDMOD = $10 ;open for mixed mode (E:, S:) INSCLR = $20 ;open for input without clearing screen ; Device Code Equates CASSET = 'C' ;cassette DISK = 'D' ;disk SCREDT = 'E' ;screen editor KBD = 'K' ;keyboard PRINTR = 'P' ;printer DISPLY = 'S' ;screen display ; SIO Command Code Equates SIO_FORMAT = $21 ;format disk (default density) SIO_FORMATS = $22 ;1050: format medium density SIO_CONFIG = $44 ;configure drive SIO_CONFIGSF = $4B ;slow/fast configure drive?? SIO_RDPERCOM = $4E ;read PERCOM block (XF551) SIO_WRPERCOM = $4F ;write PERCOM block (XF551) SIO_WRITE = $50 ;write sector SIO_READ = $52 ;read sector SIO_STAT = $53 ;get status information SIO_VERIFY = $56 ;verify sector SIO_WRITEV = $57 ;write sector with verify SIO_WRITETRK = $60 ;write track (Speedy) SIO_READTRK = $62 ;read track (Speedy) ; SIO Status Code (DSTATS) ; Input: data direction ; Bit #7 - W (write operation) ; #6 - R (read operation) ; Output: status code ; $01 (001) -- OPERATION COMPLETE (NO ERRORS) ; $8A (138) -- DEVICE TIMEOUT (DOESN'T RESPOND) ; $8B (139) -- DEVICE NAK ; $8C (140) -- SERIAL BUS INPUT FRAMING ERROR ; $8E (142) -- SERIAL BUS DATA FRAME OVERRUN ERROR ; $8F (143) -- SERIAL BUS DATA FRAME CHECKSUM ERROR ; $90 (144) -- DEVICE DONE ERROR ; Character and Key Code Equates CLS = $7D ;##rev2## clear screen EOL = $9B ;end of line (RETURN) HELP = $11 ;##1200xl## key code for HELP CNTLF1 = $83 ;##1200xl## key code for CTRL-F1 CNTLF2 = $84 ;##1200xl## key code for CTRL-F2 CNTLF3 = $93 ;##1200xl## key code for CTRL-F3 CNTLF4 = $94 ;##1200xl## key code for CTRL-F4 CNTL1 = $9F ;##1200xl## key code for CTRL-1 ; Status Code Equates SUCCES = 1 ;($01) succesful operation BRKABT = 128 ;($80) BREAK key abort PRVOPN = 129 ;($81) IOCB already open error NONDEV = 130 ;($82) nonexistent device error WRONLY = 131 ;($83) IOCB opened for write only error NVALID = 132 ;($84) invalid command error NOTOPN = 133 ;($85) device/file not open error BADIOC = 134 ;($86) invalid IOCB index error RDONLY = 135 ;($87) IOCB opened for read only error EOFERR = 136 ;($88) end of file error TRNRCD = 137 ;($89) truncated record error TIMOUT = 138 ;($8A) peripheral device timeout error DNACK = 139 ;($8B) device does not acknowledge command FRMERR = 140 ;($8C) serial bus framing error CRSROR = 141 ;($8D) cursor overrange error OVRRUN = 142 ;($8E) serial bus data overrun error CHKERR = 143 ;($8F) serial bus checksum error DERROR = 144 ;($90) device done (operation incomplete) BADMOD = 145 ;($91) bad screen mode number error FNCNOT = 146 ;($92) function not implemented in handler SCRMEM = 147 ;($93) insufficient memory for screen mode DSKFMT = 148 ;($94) SpartaDOS: unrecognized disk format INCVER = 149 ;($95) SpartaDOS: disk was made with incompat. version DIRNFD = 150 ;($96) SpartaDOS: directory not found FEXIST = 151 ;($97) SpartaDOS: file exists NOTBIN = 152 ;($98) SpartaDOS: file not binary LSYMND = 154 ;($9A) SDX: loader symbol not defined BADPRM = 156 ;($9C) SDX: bad parameter OUTOFM = 158 ;($9E) SDX: out of memory INVDEV = 160 ;($A0) invalid device number TMOF = 161 ;($A1) too many open files DSKFLL = 162 ;($A2) disk full FATLIO = 163 ;($A3) fatal I/O error FNMSMT = 164 ;($A4) internal file number mismatch INVFNM = 165 ;($A5) invalid file name PDLERR = 166 ;($A6) point data length error EPERM = 167 ;($A7) permission denied DINVCM = 168 ;($A8) command invalid for disk DIRFLL = 169 ;($A9) directory full FNTFND = 170 ;($AA) file not found PNTINV = 171 ;($AB) point invalid BADDSK = 173 ;($AD) bad disk INCFMT = 176 ;($B0) DOS 3: incompatible file system XNTBIN = 180 ;($B4) XDOS: file not binary ; DCB Device Bus Equates DISKID = $31 ;##rev2## disk bus ID PDEVN = $40 ;##rev2## printer bus ID CASET = $60 ;##rev2## cassette bus ID ; Bus Command Equates FOMAT = '!' ;##rev2## format command PUTSEC = 'P' ;##rev2## put sector command READ = 'R' ;##rev2## read command STATC = 'S' ;##rev2## status command WRITE = 'W' ;##rev2## write command ; Command Auxiliary Byte Equates DOUBLE = 'D' ;##rev2## print 20 characters double width NORMAL = 'N' ;##rev2## print 40 characters normally PLOT = 'P' ;##rev2## plot SIDWAY = 'S' ;##rev2## print 16 characters sideways ; Bus Response Equates ACK = 'A' ;##rev2## device acknowledged COMPLT = 'C' ;##rev2## device succesfully completed operation ERROR = 'E' ;##rev2## device incurred error NACK = 'N' ;##rev2## device did not understand ; Floating Point Miscellaneous Equates FPREC = 6 ;precision FMPREC = FPREC-1 ;##rev2## length of mantissa ; Cassette Record Type Equates HDR = $FB ;##rev2## header DTA = $FC ;##rev2## data record DT1 = $FA ;##rev2## last data record EOT = $FE ;##rev2## end of tape (file) TONE1 = 2 ;##rev2## record TONE2 = 1 ;##rev2## playback ; Cassette Timing Equates WLEADN = 1152 ;##rev2## NTSC 19.2 second WRITE file leader RLEADN = 576 ;##rev2## NTSC 9.6 second READ file leader WIRGLN = 180 ;##rev2## NTSC 3.0 second WRITE IRG RIRGLN = 120 ;##rev2## NTSC 2.0 second READ IRG WSIRGN = 15 ;##rev2## NTSC 0.25 second WRITE short IRG RSIRGN = 10 ;##rev2## NTSC 0.16 second READ short IRG BEEPNN = 30 ;##rev2## NTSC 0.5 second beep duration BEEPFN = 10 ;##rev2## NTSC 0.16 seconrd beep duration WLEADP = 960 ;##rev2## PAL 19.2 second WRITE file leader RLEADP = 480 ;##rev2## PAL 9.6 second READ file leader WIRGLP = 150 ;##rev2## PAL 3.0 second WRITE IRG RIRGLP = 100 ;##rev2## PAL 2.0 second READ IRG WSIRGP = 13 ;##rev2## PAL 0.25 second WRITE short IRG RSIRGP = 8 ;##rev2## PAL 0.16 second READ short IRG BEEPNP = 25 ;##rev2## PAL 0.5 second beep duration BEEPFP = 8 ;##rev2## PAL 0.16 seconrd beep duration WIRGHI = 0 ;##rev2## high WRITE IRG RIRGHI = 0 ;##rev2## high READ IRG ; Power-up Validation Byte Value Equates PUPVL1 = $5C ;##rev2## power-up validation value 1 PUPVL2 = $93 ;##rev2## power-up validation value 2 PUPVL3 = $25 ;##rev2## power-up validation value 3 ; Relocating Loader Miscellaneous Equates DATAER = 156 ;##rev2## end of record appears before END MEMERR = 157 ;##rev2## memory insufficient for load error ; Miscellaneous Equates IOCFRE = $FF ;IOCB free indication B19200 = $0028 ;##rev2## 19200 baud POKEY counter value B00600 = $05CC ;##rev2## 600 baud POKEY counter value HITONE = $05 ;##rev2## FSK high freq. POKEY counter value LOTONE = $07 ;##rev2## FSK low freq. POKEY counter value NCOMLO = $34 ;##rev2## PIA lower NOT COMMAND line command NCOMHI = $3C ;##rev2## PIA raise NOT COMMAND line command MOTRGO = $34 ;##rev2## PIA cassette motor ON command MOTRST = $3C ;##rev2## PIA cassette motor OFF command NODAT = $00 ;##rev2## SIO immediate operation GETDAT = $40 ;##rev2## SIO read data frame PUTDAT = $80 ;##rev2## SIO write data frame CRETRI = 13 ;##rev2## number of command frame retries DRETRI = 1 ;##rev2## number of device retries CTIM = 2 ;##rev2## command frame ACK timeout NBUFSZ = 40 ;##rev2## print normal buffer size DBUFSZ = 20 ;##rev2## print double buffer size SBUFSZ = 29 ;##rev2## print sideways buffer size ;------------------------------------------------------------------------- ; Page Zero Address Equates ;------------------------------------------------------------------------- LINZBS = $00 ;LINBUG RAM (WILL BE REPLACED BY MONITOR RAM) LNFLG = $00 ;##1200xl## 1-byte LNBUG flag (0 = not LNBUG) NGFLAG = $01 ;##1200xl## 1-byte memory status (0 = failure) ; Not Cleared CASINI = $02 ;CASSETTE INIT LOCATION RAMLO = $04 ;RAM POINTER FOR MEMORY TEST TRAMSZ = $06 ;TEMPORARY REGISTER FOR RAM SIZE ;TSTDAT = $07 ;##old## RAM TEST DATA REGISTER CMCMD = $07 ;##rev2## 1-byte command communications ; Cleared upon Coldstart only WARMST = $08 ;WARM START FLAG BOOTQ = $09 ;SUCCESSFUL BOOT FLAG DOSVEC = $0A ;DISK SOFTWARE START VECTOR DOSINI = $0C ;DISK SOFTWARE INIT ADDRESS APPMHI = $0E ;APPLICATIONS MEMORY HI LIMIT ; Cleared upon Coldstart or Warmstart INTZBS = $10 ;INTERRUPT HANDLER POKMSK = $10 ;SYSTEM MASK FOR POKEY IRQ ENABLE (shadow of IRQEN) BRKKEY = $11 ;BREAK KEY FLAG RTCLOK = $12 ;REAL TIME CLOCK (IN 16 MSEC UNITS> BUFADR = $15 ;INDIRECT BUFFER ADDRESS REGISTER ICCOMT = $17 ;COMMAND FOR VECTOR DSKFMS = $18 ;DISK FILE MANAGER POINTER DSKUTL = $1A ;DISK UTILITIES POINTER ABUFPT = $1C ;##1200xl## 4-byte ACMI buffer pointer area ;PTIMOT = $1C ;##old## PRINTER TIME OUT REGISTER ;PBPNT = $1D ;##old## PRINT BUFFER POINTER ;PBUFSZ = $1E ;##old## PRINT BUFFER SIZE ;PTEMP = $1F ;##old## TEMPORARY REGISTER ZIOCB = $20 ;ZERO PAGE I/O CONTROL BLOCK IOCBAS = $20 ;16-byte page zero IOCB ICHIDZ = $20 ;HANDLER INDEX NUMBER (FF = IOCB FREE) ICDNOZ = $21 ;DEVICE NUMBER (DRIVE NUMBER) ICCOMZ = $22 ;COMMAND CODE ICSTAZ = $23 ;STATUS OF LAST IOCB ACTION ICBALZ = $24 ;BUFFER ADDRESS LOW BYTE ICBAHZ = $25 ;1-byte high buffer address ICPTLZ = $26 ;PUT BYTE ROUTINE ADDRESS -1 ICPTHZ = $27 ;1-byte high PUT-BYTE routine address ICBLLZ = $28 ;BUFFER LENGTH LOW BYTE ICBLHZ = $29 ;1-byte high buffer length ICAX1Z = $2A ;AUXILIARY INFORMATION FIRST BYTE ICAX2Z = $2B ;1-byte second auxiliary information ICSPRZ = $2C ;4-byte spares ENTVEC = $2C ;##rev2## 2-byte (not used) ICIDNO = $2E ;IOCB NUMBER X 16 CIOCHR = $2F ;CHARACTER BYTE FOR CURRENT OPERATION STATUS = $30 ;INTERNAL STATUS STORAGE CHKSUM = $31 ;CHECKSUM (SINGLE BYTE SUM WITH CARRY) BUFRLO = $32 ;POINTER TO DATA BUFFER (LO BYTE) BUFRHI = $33 ;POINTER TO DATA BUFFER (HI BYTE) BFENLO = $34 ;NEXT BYTE PAST END OF THE DATA BUFFER LO BFENHI = $35 ;NEXT BYTE PAST END OF THE DATA BUFFER HI ;CRETRY = $36 ;##old## NUMBER OF COMMAND FRAME RETRIES ;DRETRY = $37 ;##old## NUMBER OF DEVICE RETRIES LTEMP = $36 ;##1200xl## 2-byte loader temporary BUFRFL = $38 ;DATA BUFFER FULL FLAG RECVDN = $39 ;RECEIVE DONE FLAG XMTDON = $3A ;TRANSMISSION DONE FLAG CHKSNT = $3B ;CHECKSUM SENT FLAG NOCKSM = $3C ;NO CHECKSUM FOLLOWS DATA FLAG BPTR = $3D ;1-byte cassette buffer pointer FTYPE = $3E ;1-byte cassette IRG type FEOF = $3F ;1-byte cassette EOF flag (0 = quiet) FREQ = $40 ;1-byte cassette beep counter SOUNDR = $41 ;NOISY I/0 FLAG. (ZERO IS QUIET) CRITIC = $42 ;DEFINES CRITICAL SECTION (CRITICAL IF NON-Z) FMSZPG = $43 ;DISK FILE MANAGER SYSTEM ZERO PAGE ;CKEY = $4A ;##old## FLAG SET WHEN GAME START PRESSED ZCHAIN = $4A ;##1200xl## 2-byte handler linkage chain pointer ;CASSBT = $4B ;##old## CASSETTE BOOT FLAG DSTAT = $4C ;DISPLAY STATUS ATRACT = $4D ;ATRACT FLAG DRKMSK = $4E ;DARK ATRACT MASK COLRSH = $4F ;ATRACT COLOR SHIFTER (EOR'ED WITH PLAYFIELD TMPCHR = $50 ;1-byte temporary character HOLD1 = $51 ;1-byte temporary LMARGN = $52 ;left margin (normally 2, cc65 C startup code sets it to 0) RMARGN = $53 ;right margin (normally 39 if no XEP80 is used) ROWCRS = $54 ;1-byte cursor row COLCRS = $55 ;2-byte cursor column DINDEX = $57 ;1-byte display mode SAVMSC = $58 ;2-byte saved memory scan counter OLDROW = $5A ;1-byte prior row OLDCOL = $5B ;2-byte prior column OLDCHR = $5D ;DATA UNDER CURSOR OLDADR = $5E ;2-byte saved cursor memory address FKDEF = $60 ;##1200xl## 2-byte function key definition table ;NEWROW = $60 ;##old## POINT DRAW GOES TO ;NEWCOL = $61 ;##old## PALNTS = $62 ;##1200xl## 1-byte PAL/NTSC indicator (0 = NTSC) LOGCOL = $63 ;POINTS AT COLUMN IN LOGICAL LINE ADRESS = $64 ;2-byte temporary address MLTTMP = $66 ;1-byte temporary OPNTMP = $66 ;FIRST BYTE IS USED IN OPEN AS TEMP TOADR = $66 ;##rev2## 2-byte destination address SAVADR = $68 ;2-byte saved address FRMADR = $68 ;##rev2## 2-byte source address RAMTOP = $6A ;RAM SIZE DEFINED BY POWER ON LOGIC BUFCNT = $6B ;BUFFER COUNT BUFSTR = $6C ;EDITOR GETCH POINTER BITMSK = $6E ;BIT MASK SHFAMT = $6F ;1-byte shift amount for pixel justifucation ROWAC = $70 ;2-byte draw working row COLAC = $72 ;2-byte draw working column ENDPT = $74 ;2-byte end point DELTAR = $76 ;1-byte row difference DELTAC = $77 ;2-byte column difference KEYDEF = $79 ;##1200xl## 2-byte key definition table address ;ROWINC = $79 ;##old## ;COLINC = $7A ;##old## SWPFLG = $7B ;NON-0 1F TXT AND REGULAR RAM IS SWAPPED HOLDCH = $7C ;CH IS MOVED HERE IN KGETCH BEFORE CNTL & SH INSDAT = $7D ;1-byte temporary COUNTR = $7E ;2-byte draw iteration count ; Floating Point Package Page Zero Address Equates FR0 = $D4 ;6-byte register 0 FR0M = $D5 ;##rev2## 5-byte register 0 mantissa QTEMP = $D9 ;##rev2## 1-byte temporary FRE = $DA ;6-byte (internal) register E FR1 = $E0 ;FP REG1 FR1M = $E1 ;##rev2## 5-byte register 1 mantissa FR2 = $E6 ;6-byte (internal) register 2 FRX = $EC ;1-byte temporary EEXP = $ED ;VALUE OF E FRSIGN = $EE ;##rev2## 1-byte floating point sign NSIGN = $EE ;SIGN OF # PLYCNT = $EF ;##rev2## 1-byte polynomial degree ESIGN = $EF ;SIGN OF EXPONENT SGNFLG = $F0 ;##rev2## 1-byte sign flag FCHRFLG = $F0 ;1ST CHAR FLAG XFMFLG = $F1 ;##rev2## 1-byte transform flag DIGRT = $F1 ;# OF DIGITS RIGHT OF DECIMAL CIX = $F2 ;CURRENT INPUT INDEX INBUFF = $F3 ;POINTS TO USER'S LINE INPUT BUFFER ZTEMP1 = $F5 ;2-byte temporary ZTEMP4 = $F7 ;2-byte temporary ZTEMP3 = $F9 ;2-byte temporary ;DEGFLG = $FB ;##old## same as RADFLG ;RADFLG = $FB ;##old## 0=RADIANS, 6=DEGREES FLPTR = $FC ;2-byte floating point number pointer FPTR2 = $FE ;2-byte floating point number pointer ;------------------------------------------------------------------------- ; Page Two Address Equates ;------------------------------------------------------------------------- INTABS = $0200 ;INTERRUPT RAM VDSLST = $0200 ;DISPLAY LIST NMI VECTOR VPRCED = $0202 ;PROCEED LINE IRQ VECTOR VINTER = $0204 ;INTERRUPT LINE IRQ VECTOR VBREAK = $0206 ;SOFTWARE BREAK (00) INSTRUCTION IRQ VECTOR VKEYBD = $0208 ;POKEY KEYBOARD IRQ VECTOR VSERIN = $020A ;POKEY SERIAL INPUT READY IRQ VSEROR = $020C ;POKEY SERIAL OUTPUT READY IRQ VSEROC = $020E ;POKEY SERIAL OUTPUT COMPLETE IRQ VTIMR1 = $0210 ;POKEY TIMER 1 IRQ VTIMR2 = $0212 ;POKEY TIMER 2 IRQ VTIMR4 = $0214 ;POKEY TIMER 4 IRQ VIMIRQ = $0216 ;IMMEDIATE IRQ VECTOR CDTMV1 = $0218 ;COUNT DOWN TIMER 1 CDTMV2 = $021A ;COUNT DOWN TIMER 2 CDTMV3 = $021C ;COUNT DOWN TIMER 3 CDTMV4 = $021E ;COUNT DOWN TIMER 4 CDTMV5 = $0220 ;COUNT DOWN TIMER 5 VVBLKI = $0222 ;IMMEDIATE VERTICAL BLANK NMI VECTOR VVBLKD = $0224 ;DEFERRED VERTICAL BLANK NMI VECTOR CDTMA1 = $0226 ;COUNT DOWN TIMER 1 JSR ADDRESS CDTMA2 = $0228 ;COUNT DOWN TIMER 2 JSR ADDRESS CDTMF3 = $022A ;COUNT DOWN TIMER 3 FLAG SRTIMR = $022B ;SOFTWARE REPEAT TIMER CDTMF4 = $022C ;COUNT DOWN TIMER 4 FLAG INTEMP = $022D ;IAN'S TEMP CDTMF5 = $022E ;COUNT DOWN TIMER FLAG 5 SDMCTL = $022F ;SAVE DMACTL REGISTER SDLSTL = $0230 ;SAVE DISPLAY LIST LOW BYTE SDLSTH = $0231 ;SAVE DISPLAY LIST HI BYTE SSKCTL = $0232 ;SKCTL REGISTER RAM LCOUNT = $0233 ;##1200xl## 1-byte relocating loader record LPENH = $0234 ;LIGHT PEN HORIZONTAL VALUE LPENV = $0235 ;LIGHT PEN VERTICAL VALUE BRKKY = $0236 ;BREAK KEY VECTOR ;RELADR = $0238 ;##1200xl## 2-byte relocatable loader address VPIRQ = $0238 ;##rev2## 2-byte parallel device IRQ vector CDEVIC = $023A ;COMMAND FRAME BUFFER - DEVICE CCOMND = $023B ;COMMAND CAUX1 = $023C ;COMMAND AUX BYTE 1 CAUX2 = $023D ;COMMAND AUX BYTE 2 TEMP = $023E ;TEMPORARY RAM CELL ERRFLG = $023F ;ERROR FLAG - ANY DEVICE ERROR EXCEPT TIME OUT DFLAGS = $0240 ;DISK FLAGS FROM SECTOR ONE DBSECT = $0241 ;NUMBER OF DISK BOOT SECTORS BOOTAD = $0242 ;ADDRESS WHERE DISK BOOT LOADER WILL BE PUT COLDST = $0244 ;COLDSTART FLAG (1=IN MIDDLE OF COLDSTART> RECLEN = $0245 ;##1200xl## 1-byte relocating loader record length DSKTIM = $0246 ;DISK TIME OUT REGISTER ;LINBUF = $0247 ;##old## CHAR LINE BUFFER PDVMSK = $0247 ;##rev2## 1-byte parallel device selection mask SHPDVS = $0248 ;##rev2## 1-byte PDVS (parallel device select) PDIMSK = $0249 ;##rev2## 1-byte parallel device IRQ selection RELADR = $024A ;##rev2## 2-byte relocating loader relative adr. PPTMPA = $024C ;##rev2## 1-byte parallel device handler temporary PPTMPX = $024D ;##rev2## 1-byte parallel device handler temporary CHSALT = $026B ;##1200xl## 1-byte character set alternate VSFLAG = $026C ;##1200xl## 1-byte fine vertical scroll count KEYDIS = $026D ;##1200xl## 1-byte keyboard disable FINE = $026E ;##1200xl## 1-byte fine scrolling mode GPRIOR = $026F ;GLOBAL PRIORITY CELL PADDL0 = $0270 ;1-byte potentiometer 0 PADDL1 = $0271 ;1-byte potentiometer 1 PADDL2 = $0272 ;1-byte potentiometer 2 PADDL3 = $0273 ;1-byte potentiometer 3 PADDL4 = $0274 ;1-byte potentiometer 4 PADDL5 = $0275 ;1-byte potentiometer 5 PADDL6 = $0276 ;1-byte potentiometer 6 PADDL7 = $0277 ;1-byte potentiometer 7 STICK0 = $0278 ;1-byte joystick 0 STICK1 = $0279 ;1-byte joystick 1 STICK2 = $027A ;1-byte joystick 2 STICK3 = $027B ;1-byte joystick 3 PTRIG0 = $027C ;1-byte paddle trigger 0 PTRIG1 = $027D ;1-byte paddle trigger 1 PTRIG2 = $027E ;1-byte paddle trigger 2 PTRIG3 = $027F ;1-byte paddle trigger 3 PTRIG4 = $0280 ;1-byte paddle trigger 4 PTRIG5 = $0281 ;1-byte paddle trigger 5 PTRIG6 = $0281 ;1-byte paddle trigger 6 PTRIG7 = $0283 ;1-byte paddle trigger 7 STRIG0 = $0284 ;1-byte joystick trigger 0 STRIG1 = $0285 ;1-byte joystick trigger 1 STRIG2 = $0286 ;1-byte joystick trigger 2 STRIG3 = $0287 ;1-byte joystick trigger 3 ;CSTAT = $0288 ;##old## cassette status register HIBYTE = $0288 ;##1200xl## 1-byte relocating loader high byte WMODE = $0289 ;1-byte cassette WRITE mode BLIM = $028A ;1-byte cassette buffer limit IMASK = $028B ;##rev2## (not used) JVECK = $028C ;2-byte jump vector or temporary NEWADR = $028E ;##1200xl## 2-byte relocating address TXTROW = $0290 ;TEXT ROWCRS TXTCOL = $0291 ;TEXT COLCRS TINDEX = $0293 ;TEXT INDEX TXTMSC = $0294 ;FOOLS CONVRT INTO NEW MSC TXTOLD = $0296 ;OLDROW & OLDCOL FOR TEXT (AND THEN SOME) ;TMPX1 = $029C ;##old## 1-byte temporary register CRETRY = $029C ;##1200xl## 1-byte number of command frame retries HOLD3 = $029D ;1-byte temporary SUBTMP = $029E ;1-byte temporary HOLD2 = $029F ;1-byte (not used) DMASK = $02A0 ;1-byte display (pixel location) mask TMPLBT = $02A1 ;1-byte (not used) ESCFLG = $02A2 ;ESCAPE FLAG TABMAP = $02A3 ;15-byte (120 bit) tab stop bit map LOGMAP = $02B2 ;LOGICAL LINE START BIT MAP INVFLG = $02B6 ;INVERSE VIDEO FLAG (TOGGLED BY ATARI KEY) FILFLG = $02B7 ;RIGHT FILL FLAG FOR DRAW TMPROW = $02B8 ;1-byte temporary row TMPCOL = $02B9 ;2-byte temporary column SCRFLG = $02BB ;SET IF SCROLL OCCURS HOLD4 = $02BC ;TEMP CELL USED IN DRAW ONLY ;HOLD5 = $02BD ;##old## DITTO DRETRY = $02BD ;##1200xl## 1-byte number of device retries SHFLOK = $02BE ;1-byte shift/control lock flags BOTSCR = $02BF ;BOTTOM OF SCREEN 24 NORM 4 SPLIT PCOLR0 = $02C0 ;1-byte player-missile 0 color/luminance PCOLR1 = $02C1 ;1-byte player-missile 1 color/luminance PCOLR2 = $02C2 ;1-byte player-missile 2 color/luminance PCOLR3 = $02C3 ;1-byte player-missile 3 color/luminance COLOR0 = $02C4 ;1-byte playfield 0 color/luminance COLOR1 = $02C5 ;1-byte playfield 1 color/luminance COLOR2 = $02C6 ;1-byte playfield 2 color/luminance COLOR3 = $02C7 ;1-byte playfield 3 color/luminance COLOR4 = $02C8 ;1-byte background color/luminance PARMBL = $02C9 ;##rev2## 6-byte relocating loader parameter RUNADR = $02C9 ;##1200xl## 2-byte run address HIUSED = $02CB ;##1200xl## 2-byte highest non-zero page address ZHIUSE = $02CD ;##1200xl## 2-byte highest zero page address OLDPAR = $02CF ;##rev2## 6-byte relocating loader parameter GBYTEA = $02CF ;##1200xl## 2-byte GET-BYTE routine address LOADAD = $02D1 ;##1200xl## 2-byte non-zero page load address ZLOADA = $02D3 ;##1200xl## 2-byte zero page load address DSCTLN = $02D5 ;##1200xl## 2-byte disk sector length ACMISR = $02D7 ;##1200xl## 2-byte ACMI interrupt service routine KRPDEL = $02D9 ;##1200xl## 1-byte auto-repeat delay KEYREP = $02DA ;##1200xl## 1-byte auto-repeat rate NOCLIK = $02DB ;##1200xl## 1-byte key click disable HELPFG = $02DC ;##1200xl## 1-byte HELP key flag (0 = no HELP) DMASAV = $02DD ;##1200xl## 1-byte SDMCTL save/restore PBPNT = $02DE ;##1200xl## 1-byte printer buffer pointer PBUFSZ = $02DF ;##1200xl## 1-byte printer buffer size GLBABS = $02E0 ;4-byte global variables for non-DOS users RUNAD = $02E0 ;##map## 2-byte binary file run address INITAD = $02E2 ;##map## 2-byte binary file initialization address RAMSIZ = $02E4 ;RAM SIZE (HI BYTE ONLY) MEMTOP = $02E5 ;TOP OF AVAILABLE USER MEMORY MEMLO = $02E7 ;BOTTOM OF AVAILABLE USER MEMORY HNDLOD = $02E9 ;##1200xl## 1-byte user load flag DVSTAT = $02EA ;STATUS BUFFER CBAUDL = $02EE ;1-byte low cassette baud rate CBAUDH = $02EF ;1-byte high cassette baud rate CRSINH = $02F0 ;CURSOR INHIBIT (00 = CURSOR ON) KEYDEL = $02F1 ;KEY DELAY CH1 = $02F2 ;1-byte prior keyboard character CHACT = $02F3 ;CHACTL REGISTER RAM CHBAS = $02F4 ;CHBAS REGISTER RAM NEWROW = $02F5 ;##1200xl## 1-byte draw destination row NEWCOL = $02F6 ;##1200xl## 2-byte draw destination column ROWINC = $02F8 ;##1200xl## 1-byte draw row increment COLINC = $02F9 ;##1200xl## 1-byte draw column increment CHAR = $02FA ;1-byte internal character ATACHR = $02FB ;ATASCII CHARACTER CH = $02FC ;GLOBAL VARIABLE FOR KEYBOARD FILDAT = $02FD ;RIGHT FILL DATA DSPFLG = $02FE ;DISPLAY FLAG DISPLAY CNTLS IF NON-ZERO SSFLAG = $02FF ;START/STOP FLAG FOR PAGING (CNTL 1). CLEARE ;------------------------------------------------------------------------- ; Page Three Address Equates ;------------------------------------------------------------------------- DCB = $0300 ;DEVICE CONTROL BLOCK DDEVIC = $0300 ;PERIPHERAL UNIT 1 BUS I.D. NUMBER DUNIT = $0301 ;UNIT NUMBER DCOMND = $0302 ;BUS COMMAND DSTATS = $0303 ;COMMAND TYPE/STATUS RETURN DBUFLO = $0304 ;1-byte low data buffer address DBUFHI = $0305 ;1-byte high data buffer address DTIMLO = $0306 ;DEVICE TIME OUT IN 1 SECOND UNITS DUNUSE = $0307 ;UNUSED BYTE DBYTLO = $0308 ;1-byte low number of bytes to transfer DBYTHI = $0309 ;1-byte high number of bytes to transfer DAUX1 = $030A ;1-byte first command auxiliary DAUX2 = $030B ;1-byte second command auxiliary TIMER1 = $030C ;INITIAL TIMER VALUE ;ADDCOR = $030E ;##old## ADDITION CORRECTION JMPERS = $030E ;##1200xl## 1-byte jumper options CASFLG = $030F ;CASSETTE MODE WHEN SET TIMER2 = $0310 ;2-byte final baud rate timer value TEMP1 = $0312 ;TEMPORARY STORAGE REGISTER ;TEMP2 = $0314 ;##old## TEMPORARY STORAGE REGISTER TEMP2 = $0313 ;##1200xl## 1-byte temporary PTIMOT = $0314 ;##1200xl## 1-byte printer timeout TEMP3 = $0315 ;TEMPORARY STORAGE REGISTER SAVIO = $0316 ;SAVE SERIAL IN DATA PORT TIMFLG = $0317 ;TIME OUT FLAG FOR BAUD RATE CORRECTION STACKP = $0318 ;SIO STACK POINTER SAVE CELL TSTAT = $0319 ;TEMPORARY STATUS HOLDER HATABS = $031A ;35-byte handler address table (was 38 bytes) PUPBT1 = $033D ;##1200xl## 1-byte power-up validation byte 1 PUPBT2 = $033E ;##1200xl## 1-byte power-up validation byte 2 PUPBT3 = $033F ;##1200xl## 1-byte power-up validation byte 3 IOCB = $0340 ;I/O CONTROL BLOCKS ICHID = $0340 ;HANDLER INDEX NUMBER (FF=IOCB FREE) ICDNO = $0341 ;DEVICE NUMBER (DRIVE NUMBER) ICCOM = $0342 ;COMMAND CODE ICSTA = $0343 ;STATUS OF LAST IOCB ACTION ICBAL = $0344 ;1-byte low buffer address ICBAH = $0345 ;1-byte high buffer address ICPTL = $0346 ;1-byte low PUT-BYTE routine address - 1 ICPTH = $0347 ;1-byte high PUT-BYTE routine address - 1 ICBLL = $0348 ;1-byte low buffer length ICBLH = $0349 ;1-byte high buffer length ICAX1 = $034A ;1-byte first auxiliary information ICAX2 = $034B ;1-byte second auxiliary information ICAX3 = $034C ;1-byte third auxiliary information ICAX4 = $034D ;1-byte fourth auxiliary information ICAX5 = $034E ;1-byte fifth auxiliary information ICSPR = $034F ;SPARE BYTE PRNBUF = $03C0 ;PRINTER BUFFER SUPERF = $03E8 ;##1200xl## 1-byte editor super function flag CKEY = $03E9 ;##1200xl## 1-byte cassette boot request flag CASSBT = $03EA ;##1200xl## 1-byte cassette boot flag CARTCK = $03EB ;##1200xl## 1-byte cartridge equivalence check DERRF = $03EC ;##rev2## 1-byte screen OPEN error flag ; Remainder of Page Three Not Cleared upon Reset ACMVAR = $03ED ;##1200xl## 11 bytes reserved for ACMI BASICF = $03F8 ;##rev2## 1-byte BASIC switch flag MINTLK = $03F9 ;##1200xl## 1-byte ACMI module interlock GINTLK = $03FA ;##1200xl## 1-byte cartridge interlock CHLINK = $03FB ;##1200xl## 2-byte loaded handler chain link CASBUF = $03FD ;CASSETTE BUFFER ;------------------------------------------------------------------------- ; Page Four/Five Address Equates ;------------------------------------------------------------------------- ; USER AREA STARTS HERE AND GOES TO END OF PAGE FIVE USAREA = $0480 ;128 bytes reserved for application LBPR1 = $057E ;LBUFF PREFIX 1 LBPR2 = $057F ;LBUFF PREFIX 2 LBUFF = $0580 ;128-byte line buffer PLYARG = $05E0 ;6-byte floating point polynomial argument FPSCR = $05E6 ;6-byte floating point temporary FPSCR1 = $05EC ;6-byte floating point temporary ;LBFEND = $05FF ;##old## END OF LBUFF DOS = $0700 ;------------------------------------------------------------------------- ; SpartaDOS-X Definitions ;------------------------------------------------------------------------- SDX_FLAG = DOS ; 'S' for SpartaDOS SDX_VERSION = $0701 ; SD version (e.g. $32 = 3.2, $40 = 4.0) ; address $0702 contains sub-version, e.g. ; 8 in case of SDX 4.48 SDX_KERNEL = $0703 ; SDX kernel entry point SDX_BLOCK_IO = $0706 ; block I/O entry point SDX_MISC = $0709 ; "misc" entry point SDX_DEVICE = $0761 SDX_DATE = $077B ; day, month, year (3 bytes) SDX_TIME = $077E ; hour, min, sec (3 bytes) SDX_DATESET = $0781 SDX_PATH = $07A0 ; 64 bytes SDX_IFSYMBOL = $07EB ; only valid on SDX 4.40 or newer SDX_S_LOOKUP = SDX_IFSYMBOL ; alternative name for SDX_IFSYMBOL ; values for SDX_DEVICE SDX_CLK_DEV = $10 ; clock device ; clock device functions SDX_KD_GETTD = 100 ; get time and date SDX_KD_SETTD = 101 ; set time and date ;------------------------------------------------------------------------- ; Cartridge Address Equates ;------------------------------------------------------------------------- CARTCS = $BFFA ;##rev2## 2-byte cartridge coldstart address CART = $BFFC ;##rev2## 1-byte cartridge present indicator ;0=Cart Exists CARTFG = $BFFD ;##rev2## 1-byte cartridge flags ;D7 0=Not a Diagnostic Cart ; 1=Is a Diagnostic cart and control is ; given to cart before any OS is init. ;D2 0=Init but Do not Start Cart ; 1=Init and Start Cart ;D0 0=Do not boot disk ; 1=Boot Disk CARTAD = $BFFE ;##rev2## 2-byte cartridge start vector ;------------------------------------------------------------------------- ; CTIA/GTIA Address Equates ;------------------------------------------------------------------------- GTIA = $D000 ;CTIA/GTIA area .include "atari_gtia.inc" ;------------------------------------------------------------------------- ; PBI Address Equates ;------------------------------------------------------------------------- PBI = $D100 ;##rev2## parallel bus interface area ; Read Addresses PDVI = $D1FF ;##rev2## parallel device IRQ status ; Write Addresses PDVS = $D1FF ;##rev2## parallel device select ;------------------------------------------------------------------------- ; POKEY Address Equates ;------------------------------------------------------------------------- POKEY = $D200 ;POKEY area .include "atari_pokey.inc" ; POKEY KBCODE Values KEY_NONE = $FF KEY_0 = $32 KEY_1 = $1F KEY_2 = $1E KEY_3 = $1A KEY_4 = $18 KEY_5 = $1D KEY_6 = $1B KEY_7 = $33 KEY_8 = $35 KEY_9 = $30 KEY_A = $3F KEY_B = $15 KEY_C = $12 KEY_D = $3A KEY_E = $2A KEY_F = $38 KEY_G = $3D KEY_H = $39 KEY_I = $0D KEY_J = $01 KEY_K = $05 KEY_L = $00 KEY_M = $25 KEY_N = $23 KEY_O = $08 KEY_P = $0A KEY_Q = $2F KEY_R = $28 KEY_S = $3E KEY_T = $2D KEY_U = $0B KEY_V = $10 KEY_W = $2E KEY_X = $16 KEY_Y = $2B KEY_Z = $17 KEY_COMMA = $20 KEY_PERIOD = $22 KEY_SLASH = $26 KEY_SEMICOLON = $02 KEY_PLUS = $06 KEY_ASTERISK = $07 KEY_DASH = $0E KEY_EQUALS = $0F KEY_LESSTHAN = $36 KEY_GREATERTHAN = $37 KEY_ESC = $1C KEY_TAB = $2C KEY_SPACE = $21 KEY_RETURN = $0C KEY_DELETE = $34 KEY_CAPS = $3C KEY_INVERSE = $27 KEY_HELP = $11 KEY_F1 = $03 KEY_F2 = $04 KEY_F3 = $13 KEY_F4 = $14 KEY_SHIFT = $40 KEY_CTRL = $80 ; Composed keys KEY_EXCLAMATIONMARK = KEY_1 | KEY_SHIFT KEY_QUOTE = KEY_2 | KEY_SHIFT KEY_HASH = KEY_3 | KEY_SHIFT KEY_DOLLAR = KEY_4 | KEY_SHIFT KEY_PERCENT = KEY_5 | KEY_SHIFT KEY_AMPERSAND = KEY_6 | KEY_SHIFT KEY_APOSTROPHE = KEY_7 | KEY_SHIFT KEY_AT = KEY_8 | KEY_SHIFT KEY_OPENINGPARAN = KEY_9 | KEY_SHIFT KEY_CLOSINGPARAN = KEY_0 | KEY_SHIFT KEY_UNDERLINE = KEY_DASH | KEY_SHIFT KEY_BAR = KEY_EQUALS | KEY_SHIFT KEY_COLON = KEY_SEMICOLON | KEY_SHIFT KEY_BACKSLASH = KEY_PLUS | KEY_SHIFT KEY_CIRCUMFLEX = KEY_ASTERISK | KEY_SHIFT KEY_OPENINGBRACKET = KEY_COMMA | KEY_SHIFT KEY_CLOSINGBRACKET = KEY_PERIOD | KEY_SHIFT KEY_QUESTIONMARK = KEY_SLASH | KEY_SHIFT KEY_CLEAR = KEY_LESSTHAN | KEY_SHIFT KEY_INSERT = KEY_GREATERTHAN | KEY_SHIFT KEY_UP = KEY_UNDERLINE | KEY_CTRL KEY_DOWN = KEY_EQUALS | KEY_CTRL KEY_LEFT = KEY_PLUS | KEY_CTRL KEY_RIGHT = KEY_ASTERISK | KEY_CTRL ;------------------------------------------------------------------------- ; ANTIC Address Equates ;------------------------------------------------------------------------- ANTIC = $D400 ;ANTIC area .include "atari_antic.inc" ; PBI RAM Address Equates PBIRAM = $D600 ;##rev2## parallel bus interface RAM area ; Parallel Device Address Equates PDID1 = $D803 ;##rev2## parallel device ID 1 PDIDV = $D805 ;##rev2## parallel device I/O vector PDIRQV = $D808 ;##rev2## parallel device IRQ vector PDID2 = $D80B ;##rev2## parallel device ID 2 PDVV = $D80D ;##rev2## parallel device vector table ;------------------------------------------------------------------------- ; PIA Address Equates ;------------------------------------------------------------------------- PIA = $D300 ;PIA area PORTA = $D300 ;port A direction register or jacks one/two PORTB = $D301 ;port B direction register or memory management PACTL = $D302 ;port A control PBCTL = $D303 ;port B control ;------------------------------------------------------------------------- ; Floating Point Package Address Equates ;------------------------------------------------------------------------- AFP = $D800 ;convert ASCII to floating point FASC = $D8E6 ;convert floating point to ASCII IFP = $D9AA ;convert integer to floating point FPI = $D9D2 ;convert floating point to integer ZFR0 = $DA44 ;zero FR0 ZF1 = $DA46 ;zero floating point number FSUB = $DA60 ;subtract floating point numbers FADD = $DA66 ;add floating point numbers FMUL = $DADB ;multiply floating point numbers FDIV = $DB28 ;divide floating point numbers PLYEVL = $DD40 ;evaluate floating point polynomial FLD0R = $DD89 ;load floating point number FLD0P = $DD8D ;load floating point number FLD1R = $DD98 ;load floating point number PLD1P = $DD9C ;load floating point number FST0R = $DDA7 ;store floating point number FST0P = $DDAB ;store floating point number FMOVE = $DDB6 ;move floating point number LOG = $DECD ;calculate floating point logarithm LOG10 = $DED1 ;calculate floating point base 10 logarithm EXP = $DDC0 ;calculate floating point exponential EXP10 = $DDCC ;calculate floating point base 10 exponential ;------------------------------------------------------------------------- ; Device Handler Vector Table Address Equates ;------------------------------------------------------------------------- EDITRV = $E400 ;editor handler vector table SCRENV = $E410 ;screen handler vector table KEYBDV = $E420 ;keyboard handler vector table PRINTV = $E430 ;printer handler vector table CASETV = $E440 ;cassette handler vector table ;------------------------------------------------------------------------- ; Jump Vector Address Equates ;------------------------------------------------------------------------- DISKIV = $E450 ;vector to initialize DIO DSKINV = $E453 ;vector to DIO .ifdef __ATARIXL__ .ifndef SHRAM_HANDLERS .import CIO_handler, SIO_handler, SETVBV_handler .endif .define CIOV CIO_handler .define SIOV SIO_handler .define SETVBV SETVBV_handler CIOV_org = $E456 ;vector to CIO SIOV_org = $E459 ;vector to SIO SETVBV_org = $E45C ;vector to set VBLANK parameters .else CIOV = $E456 ;vector to CIO SIOV = $E459 ;vector to SIO SETVBV = $E45C ;vector to set VBLANK parameters ; aliases in order not to have to sprinkle common code with .ifdefs CIOV_org = CIOV SIOV_org = SIOV SETVBV_org = SETVBV .endif SYSVBV = $E45F ;vector to process immediate VBLANK XITVBV = $E462 ;vector to process deferred VBLANK SIOINV = $E465 ;vector to initialize SIO SENDEV = $E468 ;vector to enable SEND INTINV = $E46B ;vector to initialize interrupt handler CIOINV = $E46E ;vector to initialize CIO BLKBDV = $E471 ;vector to power-up display WARMSV = $E474 ;vector to warmstart COLDSV = $E477 ;vector to coldstart RBLOKV = $E47A ;vector to read cassette block CSOPIV = $E47D ;vector to open cassette for input VCTABL = $E480 ;RAM vector initial value table PUPDIV = $E480 ;##rev2## vector to power-up display SLFTSV = $E483 ;##rev2## vector to self-test PHENTV = $E486 ;##rev2## vector to enter peripheral handler PHUNLV = $E489 ;##rev2## vector to unlink peripheral handler PHINIV = $E48C ;##rev2## vector to initialize peripheral handler GPDVV = $E48F ;##rev2## generic parallel device handler vector ; NOTE: OS rom self-test labels are not included in this file ;------------------------------------------------------------------------- ; Some misc. stuff from the 400/800 rev.B source ;------------------------------------------------------------------------- ; THE FOLLOWING ARE IN BASIC CARTRIDGE: SIN = $BD81 ;FR0 <- SIN (FR0) DEGFLG (0=RAD,6=DEG) CARRY COS = $BD73 ;FR0 <- COS (FR0) CARRY ATAN = $BE43 ;FR0 <- ATAN(FR0) CARRY SQR = $BEB1 ;FR0 <- ROOT(FR0) CARRY RADON = 0 ;INDICATES RADIANS DEGON = 6 ;INDICATES DEGREES ASCZER = '0' ;ASCII ZERO COLON = $3A ;ASCII COLON CR = $9B ;SYSTEM EOL (CARRIAGE RETURN) ;------------------------------------------------------------------------- ; 6502 ;------------------------------------------------------------------------- NMIVEC = $FFFA RESVEC = $FFFC IRQVEC = $FFFE ;------------------------------------------------------------------------- ; BASIC ;------------------------------------------------------------------------- LOMEM = $80 ;2-byte low memory pointer VNTP = $82 ;2-byte variable name table address VNTD = $84 ;2-byte variable name table end + 1 VVTP = $86 ;2-byte variable value table STMTAB = $88 ;2-byte statement table address STMCUR = $8A ;2-byte current statement pointer STARP = $8C ;2-byte string and array table pointer RUNSTK = $8E ;2-byte runtime stack address BMEMTOP = $90 ;2-byte top of memory pointer STOPLN = $BA ;2-byte stopped line number ERRSAVE = $C3 ;1-byte error code PTABW = $C9 ;1-byte tab width ;------------------------------------------------------------------------- ; ATASCII CHARACTER DEFS ;------------------------------------------------------------------------- ATCLR = $7D ;CLEAR SCREEN CHARACTER ATRUB = $7E ;BACK SPACE (RUBOUT) ATTAB = $7F ;TAB ATEOL = $9B ;END-OF-LINE ATDELL = $9C ;delete line ATINSL = $9D ;insert line ATCTAB = $9E ;clear TAB ATSTAB = $9F ;set TAB ATBEL = $FD ;CONSOLE BELL ATDEL = $FE ;delete char. ATINS = $FF ;insert char. ATURW = $1C ;UP-ARROW ATDRW = $1D ;DOWN-ARROW ATLRW = $1E ;LEFT-ARROW ATRRW = $1F ;RIGHT-ARROW ATESC = $1B ;ESCAPE ;------------------------------------------------------------------------- ; OFFSETS INTO SECTSIZETAB (DIO functions) ;------------------------------------------------------------------------- sst_flag = 0 ; length 1 sst_sectsize = 1 ; 2 sst_driveno = 3 ; 1 (drive #) sst_size = 4 ; size of one entry ; if changed, adapt diopncls.s ;------------------------------------------------------------------------- ; OFFSETS INTO dio_phys_pos ;------------------------------------------------------------------------- diopp_head = 0 ; head diopp_track = 1 ; track / cylinder diopp_sector = 3 ; sector diopp_size = 5 ; size of structure ;------------------------------------------------------------------------- ; VALUES for dos_type ;------------------------------------------------------------------------- SPARTADOS = 0 REALDOS = 1 BWDOS = 2 OSADOS = 3 ; OS/A+ XDOS = 4 ATARIDOS = 5 MYDOS = 6 NODOS = 255 ; The DOSes with dos_type below or equal MAX_DOS_WITH_CMDLINE do support ; command line arguments. MAX_DOS_WITH_CMDLINE = XDOS ;------------------------------------------------------------------------- ; XDOS defines (version 2.4, taken from xdos24.pdf) ;------------------------------------------------------------------------- XOPT = $070B ; XDOS options XCAR = $070C ; XDOS cartridge address (+ $70D) XPAT = $086F ; XDOS bugfix and patch number XVER = $0870 ; XDOS version number XFILE = $087D ; XDOS filename buffer XLINE = $0880 ; XDOS DUP input line XGLIN = $0871 ; get line XSKIP = $0874 ; skip parameter .ifdef __ATARIXL__ .ifndef SHRAM_HANDLERS .import XMOVE_handler .endif .define XMOVE XMOVE_handler XMOVE_org = $0877 ; move filename .else XMOVE = $0877 ; move filename .endif XGNUM = $087A ; get number ;------------------------------------------------------------------------- ; End of atari.inc ;------------------------------------------------------------------------- cc65-2.18/asminc/atari.mac000066400000000000000000000033571347360151100152510ustar00rootroot00000000000000; Convert characters to screen codes ; Helper macro that converts and outputs one character .macro _scrcode char .if (char >= 0) .and (char <= 31) .byte (char + 64) .elseif (char >= 32) .and (char <= 95) .byte (char - 32) .elseif (char >= 96) .and (char <= 127) .byte char .elseif (char >= 128) .and (char <= 159) .byte (char + 64) .elseif (char >= 160) .and (char <= 223) .byte (char - 32) .elseif (char >= 224) .and (char <= 255) .byte char .else .error "scrcode: Character constant out of range" .endif .endmacro .macro scrcode arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 ; Bail out if next argument is empty .if .blank (arg1) .exitmacro .endif ; Check for a string .if .match ({arg1}, "") ; Walk over all string chars .repeat .strlen (arg1), i _scrcode {.strat (arg1, i)} .endrepeat ; Check for a number .elseif .match (.left (1, {arg1}), 0) ; Just output the number _scrcode arg1 ; Check for a character .elseif .match (.left (1, {arg1}), 'a') ; Just output the character _scrcode arg1 ; Anything else is an error .else .error "scrcode: invalid argument type" .endif ; Call the macro recursively with the remaining args scrcode arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 .endmacro cc65-2.18/asminc/atari2600.inc000066400000000000000000000003011347360151100155540ustar00rootroot00000000000000; Atari 2600 TIA & RIOT read / write registers ; ; Florent Flament (contact@florentflament.com), 2017 ; TIA & RIOT registers mapping .include "atari2600_tia.inc" .include "atari2600_riot.inc" cc65-2.18/asminc/atari2600_riot.inc000066400000000000000000000006001347360151100166130ustar00rootroot00000000000000; Atari 2600 RIOT read / write registers ; ; Source: DASM - vcs.h ; Details available in: Stella Programmer's Guide by Steve Wright ; ; Florent Flament (contact@florentflament.com), 2017 ; Read registers SWCHA := $0280 SWACNT := $0281 SWCHB := $0282 SWBCNT := $0283 INTIM := $0284 TIMINT := $0285 ; Write registers TIM1T := $0294 TIM8T := $0295 TIM64T := $0296 T1024T := $0297 cc65-2.18/asminc/atari2600_tia.inc000066400000000000000000000020311347360151100164130ustar00rootroot00000000000000; Atari 2600 TIA read / write registers ; ; Source: DASM - vcs.h ; Details available in: Stella Programmer's Guide by Steve Wright ; ; Florent Flament (contact@florentflament.com), 2017 ; Read registers VSYNC := $00 VBLANK := $01 WSYNC := $02 RSYNC := $03 NUSIZ0 := $04 NUSIZ1 := $05 COLUP0 := $06 COLUP1 := $07 COLUPF := $08 COLUBK := $09 CTRLPF := $0A REFP0 := $0B REFP1 := $0C PF0 := $0D PF1 := $0E PF2 := $0F RESP0 := $10 RESP1 := $11 RESM0 := $12 RESM1 := $13 RESBL := $14 AUDC0 := $15 AUDC1 := $16 AUDF0 := $17 AUDF1 := $18 AUDV0 := $19 AUDV1 := $1A GRP0 := $1B GRP1 := $1C ENAM0 := $1D ENAM1 := $1E ENABL := $1F HMP0 := $20 HMP1 := $21 HMM0 := $22 HMM1 := $23 HMBL := $24 VDELP0 := $25 VDELP1 := $26 VDELBL := $27 RESMP0 := $28 RESMP1 := $29 HMOVE := $2A HMCLR := $2B CXCLR := $2C ; Write registers CXM0P := $00 CXM1P := $01 CXP0FB := $02 CXP1FB := $03 CXM0FB := $04 CXM1FB := $05 CXBLPF := $06 CXPPMM := $07 INPT0 := $08 INPT1 := $09 INPT2 := $0A INPT3 := $0B INPT4 := $0C INPT5 := $0D cc65-2.18/asminc/atari5200.inc000066400000000000000000000103551347360151100155650ustar00rootroot00000000000000;------------------------------------------------------------------------- ; Atari 5200 System Equates ; by Christian Groessler ; taken from EQUATES.INC from Atari Inc. ;------------------------------------------------------------------------- ;------------------------------------------------------------------------- ; ATASCII CHARACTER DEFS ;------------------------------------------------------------------------- ATEOL = $9B ; END-OF-LINE, used by CONIO ;------------------------------------------------------------------------- ; CONIO CHARACTER DEFS ;------------------------------------------------------------------------- CH_ULCORNER = $0B ; '+' sign CH_URCORNER = $0B CH_LLCORNER = $0B CH_LRCORNER = $0B CH_HLINE = $0D ; dash CH_VLINE = $01 ; exclamation mark ;------------------------------------------------------------------------- ; Zero Page ;------------------------------------------------------------------------- POKMSK = $00 ; Mask for Pokey IRQ enable RTCLOK = $01 ; 60 hz. clock JUMP = $01 CRITIC = $03 ; Critical section ATRACT = $04 ; Attract Mode SDLSTL = $05 ; DLISTL Shadow SDLSTH = $06 ; DLISTH " SDMCTL = $07 ; DMACTL " PCOLR0 = $08 ; COLPM0 Shadow PCOLR1 = $09 ; COLPM1 " PCOLR2 = $0A ; COLPM2 " PCOLR3 = $0B ; COLPM3 " COLOR0 = $0C ; COLPF0 Shadow COLOR1 = $0D ; COLPF1 " COLOR2 = $0E ; COLPF2 " COLOR3 = $0F ; COLPF3 " COLOR4 = $10 ; COLBK " PADDL0 = $11 ; POT0 Shadow PADDL1 = $12 ; POT1 " PADDL2 = $13 ; POT2 " PADDL3 = $14 ; POT3 " PADDL4 = $15 ; POT4 " PADDL5 = $16 ; POT5 " PADDL6 = $17 ; POT6 " PADDL7 = $18 ; POT7 " ; cc65 runtime zero page variables ROWCRS_5200 = $19 COLCRS_5200 = $1A SAVMSC = $1B ; pointer to screen memory (conio) ;------------------------------------------------------------------------- ; Page #2 ;------------------------------------------------------------------------- ;Interrupt Vectors VIMIRQ = $0200 ; Immediate IRQ ; Preset $FC03 (SYSIRQ) VVBLKI = $0202 ; Vblank immediate ; Preset $FCB8 (SYSVBL) VVBLKD = $0204 ; Vblank deferred ; Preset $FCB2 (XITVBL) VDSLST = $0206 ; Display List ; Preset $FEA1 (OSDLI) VKYBDI = $0208 ; Keyboard immediate ; Preset $FD02 (SYSKBD) VKYBDF = $020A ; Deferred Keyboard ; Preset $FCB2 (XITVBL) VTRIGR = $020C ; Soft Trigger VBRKOP = $020E ; BRK Opcode VSERIN = $0210 ; Serial in Ready VSEROR = $0212 ; Serial Out Ready VSEROC = $0214 ; Serial Output complete VTIMR1 = $0216 ; Pokey Timer 1 VTIMR2 = $0218 ; Pokey Timer 2 VTIMR4 = $021A ; Pokey Timer 4 ;------------------------------------------------------------------------- ; CTIA/GTIA Address Equates ;------------------------------------------------------------------------- GTIA = $C000 ; CTIA/GTIA area .include "atari_gtia.inc" ;------------------------------------------------------------------------- ; ANTIC Address Equates ;------------------------------------------------------------------------- ANTIC = $D400 ; ANTIC area .include "atari_antic.inc" ;------------------------------------------------------------------------- ; POKEY Address Equates ;------------------------------------------------------------------------- POKEY = $E800 ; POKEY area .include "atari_pokey.inc" ;------------------------------------------------------------------------- ; conio color defines ;------------------------------------------------------------------------- COLOR_WHITE = 0 COLOR_RED = 1 COLOR_GREEN = 2 COLOR_BLACK = 3 ;------------------------------------------------------------------------- ; Cartridge Parameters ;------------------------------------------------------------------------- CARTNM = $BFE8 ; Cartridge Name Area COPYD = $BFFC ; Copyright Decade in Cart COPYR = $BFFD ; Copyright Year in Cart ; $FF=Diagnostic Cart GOCART = $BFFE ; Cartridge Start Vector CHRORG = $F800 ; Character Generator Base cc65-2.18/asminc/atari_antic.inc000066400000000000000000000064011347360151100164310ustar00rootroot00000000000000;------------------------------------------------------------------------- ; ANTIC Address Equates ;------------------------------------------------------------------------- ; Read Addresses VCOUNT = ANTIC + $0B ;vertical line counter PENH = ANTIC + $0C ;light pen horizontal position PENV = ANTIC + $0D ;light pen vertical position NMIST = ANTIC + $0F ;NMI interrupt status ; Write Addresses DMACTL = ANTIC + $00 ;DMA control CHACTL = ANTIC + $01 ;character control DLISTL = ANTIC + $02 ;low display list address DLISTH = ANTIC + $03 ;high display list address HSCROL = ANTIC + $04 ;horizontal scroll VSCROL = ANTIC + $05 ;vertical scroll PMBASE = ANTIC + $07 ;player-missile base address CHBASE = ANTIC + $09 ;character base address WSYNC = ANTIC + $0A ;wait for HBLANK synchronization NMIEN = ANTIC + $0E ;NMI enable NMIRES = ANTIC + $0F ;NMI interrupt reset ;------------------------------------------------------------------------- ; Antic opcodes ;------------------------------------------------------------------------- ; usage example: ; ; ScreenDL: ; .byte DL_BLK8 ; .byte DL_BLK8 ; .byte DL_CHR40x8x1 | DL_LMS | DL_DLI ; .word ScreenAlignment ; .byte DL_BLK1 | DL_DLI ; .byte DL_MAP320x1x1 | DL_LMS ; .word Screen ; ; .repeat 99 ; .byte DL_MAP320x1x1 ; .endrepeat ; .byte DL_MAP320x1x1 | DL_LMS ; .word Screen + 40 * 100 ; 100 lines a 40 byte, 'Screen' has to be aligned correctly! ; .repeat 92 ; .byte DL_MAP320x1x1 ; .endrepeat ; ; .byte DL_JVB ; absolute instructions (non mode lines) DL_JMP = 1 DL_JVB = 65 ; DL_BLKn display n empty lines (just background) DL_BLK1 = 0 DL_BLK2 = 16 DL_BLK3 = 32 DL_BLK4 = 48 DL_BLK5 = 64 DL_BLK6 = 80 DL_BLK7 = 96 DL_BLK8 = 112 ; absolute instructions (mode lines) DL_CHR40x8x1 = 2 ; monochrome, 40 character & 8 scanlines per mode line (GR. 0) DL_CHR40x10x1 = 3 ; monochrome, 40 character & 10 scanlines per mode line DL_CHR40x8x4 = 4 ; colour, 40 character & 8 scanlines per mode line (GR. 12) DL_CHR40x16x4 = 5 ; colour, 40 character & 16 scanlines per mode line (GR. 13) DL_CHR20x8x2 = 6 ; colour (duochrome per character), 20 character & 8 scanlines per mode line (GR. 1) DL_CHR20x16x2 = 7 ; colour (duochrome per character), 20 character & 16 scanlines per mode line (GR. 2) DL_MAP40x8x4 = 8 ; colour, 40 pixel & 8 scanlines per mode line (GR. 3) DL_MAP80x4x2 = 9 ; 'duochrome', 80 pixel & 4 scanlines per mode line (GR.4) DL_MAP80x4x4 = 10 ; colour, 80 pixel & 4 scanlines per mode line (GR.5) DL_MAP160x2x2 = 11 ; 'duochrome', 160 pixel & 2 scanlines per mode line (GR.6) DL_MAP160x1x2 = 12 ; 'duochrome', 160 pixel & 1 scanline per mode line (GR.14) DL_MAP160x2x4 = 13 ; 4 colours, 160 pixel & 2 scanlines per mode line (GR.7) DL_MAP160x1x4 = 14 ; 4 colours, 160 pixel & 1 scanline per mode line (GR.15) DL_MAP320x1x1 = 15 ; monochrome, 320 pixel & 1 scanline per mode line (GR.8) ; modifiers on mode lines... DL_HSCROL = 16 DL_VSCROL = 32 DL_LMS = 64 ; general modifier... DL_DLI = 128 cc65-2.18/asminc/atari_gtia.inc000066400000000000000000000105061347360151100162600ustar00rootroot00000000000000;------------------------------------------------------------------------- ; CTIA/GTIA Address Equates ;------------------------------------------------------------------------- ; Read/Write Addresses CONSOL = GTIA + $1F ;console switches and speaker control ; Read Addresses M0PF = GTIA + $00 ;missile 0 and playfield collision M1PF = GTIA + $01 ;missile 1 and playfield collision M2PF = GTIA + $02 ;missile 2 and playfield collision M3PF = GTIA + $03 ;missile 3 and playfield collision P0PF = GTIA + $04 ;player 0 and playfield collision P1PF = GTIA + $05 ;player 1 and playfield collision P2PF = GTIA + $06 ;player 2 and playfield collision P3PF = GTIA + $07 ;player 3 and playfield collision M0PL = GTIA + $08 ;missile 0 and player collision M1PL = GTIA + $09 ;missile 1 and player collision M2PL = GTIA + $0A ;missile 2 and player collision M3PL = GTIA + $0B ;missile 3 and player collision P0PL = GTIA + $0C ;player 0 and player collision P1PL = GTIA + $0D ;player 1 and player collision P2PL = GTIA + $0E ;player 2 and player collision P3PL = GTIA + $0F ;player 3 and player collision TRIG0 = GTIA + $10 ;joystick trigger 0 TRIG1 = GTIA + $11 ;joystick trigger 1 TRIG2 = GTIA + $12 ;cartridge interlock TRIG3 = GTIA + $13 ;ACMI module interlock PAL = GTIA + $14 ;##rev2## PAL/NTSC indicator ; Write Addresses HPOSP0 = GTIA + $00 ;player 0 horizontal position HPOSP1 = GTIA + $01 ;player 1 horizontal position HPOSP2 = GTIA + $02 ;player 2 horizontal position HPOSP3 = GTIA + $03 ;player 3 horizontal position HPOSM0 = GTIA + $04 ;missile 0 horizontal position HPOSM1 = GTIA + $05 ;missile 1 horizontal position HPOSM2 = GTIA + $06 ;missile 2 horizontal position HPOSM3 = GTIA + $07 ;missile 3 horizontal position SIZEP0 = GTIA + $08 ;player 0 size SIZEP1 = GTIA + $09 ;player 1 size SIZEP2 = GTIA + $0A ;player 2 size SIZEP3 = GTIA + $0B ;player 3 size SIZEM = GTIA + $0C ;missile sizes GRAFP0 = GTIA + $0D ;player 0 graphics GRAFP1 = GTIA + $0E ;player 1 graphics GRAFP2 = GTIA + $0F ;player 2 graphics GRAFP3 = GTIA + $10 ;player 3 graphics GRAFM = GTIA + $11 ;missile graphics COLPM0 = GTIA + $12 ;player-missile 0 color/luminance COLPM1 = GTIA + $13 ;player-missile 1 color/luminance COLPM2 = GTIA + $14 ;player-missile 2 color/luminance COLPM3 = GTIA + $15 ;player-missile 3 color/luminance COLPF0 = GTIA + $16 ;playfield 0 color/luminance COLPF1 = GTIA + $17 ;playfield 1 color/luminance COLPF2 = GTIA + $18 ;playfield 2 color/luminance COLPF3 = GTIA + $19 ;playfield 3 color/luminance COLBK = GTIA + $1A ;background color/luminance PRIOR = GTIA + $1B ;priority select VDELAY = GTIA + $1C ;vertical delay GRACTL = GTIA + $1D ;graphic control HITCLR = GTIA + $1E ;collision clear ; Hue values HUE_GREY = 0 HUE_GOLD = 1 HUE_GOLDORANGE = 2 HUE_REDORANGE = 3 HUE_ORANGE = 4 HUE_MAGENTA = 5 HUE_PURPLE = 6 HUE_BLUE = 7 HUE_BLUE2 = 8 HUE_CYAN = 9 HUE_BLUEGREEN = 10 HUE_BLUEGREEN2 = 11 HUE_GREEN = 12 HUE_YELLOWGREEN = 13 HUE_YELLOW = 14 HUE_YELLOWRED = 15 ; Color defines, similar to c64 colors (untested) GTIA_COLOR_BLACK = (HUE_GREY << 4) GTIA_COLOR_WHITE = (HUE_GREY << 4 | 7 << 1) GTIA_COLOR_RED = (HUE_REDORANGE << 4 | 1 << 1) GTIA_COLOR_CYAN = (HUE_CYAN << 4 | 3 << 1) GTIA_COLOR_VIOLET = (HUE_PURPLE << 4 | 4 << 1) GTIA_COLOR_GREEN = (HUE_GREEN << 4 | 2 << 1) GTIA_COLOR_BLUE = (HUE_BLUE << 4 | 2 << 1) GTIA_COLOR_YELLOW = (HUE_YELLOW << 4 | 7 << 1) GTIA_COLOR_ORANGE = (HUE_ORANGE << 4 | 5 << 1) GTIA_COLOR_BROWN = (HUE_YELLOW << 4 | 2 << 1) GTIA_COLOR_LIGHTRED = (HUE_REDORANGE << 4 | 6 << 1) GTIA_COLOR_GRAY1 = (HUE_GREY << 4 | 2 << 1) GTIA_COLOR_GRAY2 = (HUE_GREY << 4 | 3 << 1) GTIA_COLOR_LIGHTGREEN = (HUE_GREEN << 4 | 6 << 1) GTIA_COLOR_LIGHTBLUE = (HUE_BLUE << 4 | 6 << 1) GTIA_COLOR_GRAY3 = (HUE_GREY << 4 | 5 << 1) cc65-2.18/asminc/atari_pokey.inc000066400000000000000000000033061347360151100164630ustar00rootroot00000000000000;------------------------------------------------------------------------- ; POKEY Address Equates ;------------------------------------------------------------------------- ; Read Addresses POT0 = POKEY + $00 ;potentiometer 0 POT1 = POKEY + $01 ;potentiometer 1 POT2 = POKEY + $02 ;potentiometer 2 POT3 = POKEY + $03 ;potentiometer 3 POT4 = POKEY + $04 ;potentiometer 4 POT5 = POKEY + $05 ;potentiometer 5 POT6 = POKEY + $06 ;potentiometer 6 POT7 = POKEY + $07 ;potentiometer 7 ALLPOT = POKEY + $08 ;potentiometer port status KBCODE = POKEY + $09 ;keyboard code RANDOM = POKEY + $0A ;random number generator SERIN = POKEY + $0D ;serial port input IRQST = POKEY + $0E ;IRQ interrupt status SKSTAT = POKEY + $0F ;serial port and keyboard status ; Write Addresses AUDF1 = POKEY + $00 ;channel 1 audio frequency AUDC1 = POKEY + $01 ;channel 1 audio control AUDF2 = POKEY + $02 ;channel 2 audio frequency AUDC2 = POKEY + $03 ;channel 2 audio control AUDF3 = POKEY + $04 ;channel 3 audio frequency AUDC3 = POKEY + $05 ;channel 3 audio control AUDF4 = POKEY + $06 ;channel 4 audio frequency AUDC4 = POKEY + $07 ;channel 4 audio control AUDCTL = POKEY + $08 ;audio control STIMER = POKEY + $09 ;start timers SKRES = POKEY + $0A ;reset SKSTAT status POTGO = POKEY + $0B ;start potentiometer scan sequence SEROUT = POKEY + $0D ;serial port output IRQEN = POKEY + $0E ;IRQ interrupt enable SKCTL = POKEY + $0F ;serial port and keyboard control cc65-2.18/asminc/atmos.inc000066400000000000000000000064771347360151100153130ustar00rootroot00000000000000; ; Oric Atmos definitions ; BASIC 1.1 addresses ; ; --------------------------------------------------------------------------- ; Constants SCREEN_XSIZE = 40 ; screen columns SCREEN_YSIZE = 28 ; screen rows FUNCTKEY = $A5 FNAME_LEN = 16 ; maximum length of file-name ; --------------------------------------------------------------------------- ; Zero page SCRPTR := $12 BASIC_BUF := $35 CHARGOT := $E8 TXTPTR := $E9 ; --------------------------------------------------------------------------- ; Low memory MODEKEY := $0209 CAPSLOCK := $020C ; $7F = not locked, $FF = locked PATTERN := $0213 IRQVec := $0245 ; "fast" interrupt vector JOINFLAG := $025A ; 0 = don't joiu, $4A = join BASIC programs VERIFYFLAG := $025B ; 0 = load, 1 = verify CURS_Y := $0268 CURS_X := $0269 STATUS := $026A BACKGRND := $026B FOREGRND := $026C TIMER3 := $0276 CFILE_NAME := $027F CFOUND_NAME := $0293 FILESTART := $02A9 FILEEND := $02AB AUTORUN := $02AD ; $00 = only load, $C7 = autorun LANGFLAG := $02AE ; $00 = BASIC, $80 = machine code LOADERR := $02B1 KEYBUF := $02DF PARMERR := $02E0 PARAM1 := $02E1 ; & $02E2 PARAM2 := $02E3 ; & $02E4 PARAM3 := $02E5 ; & $02E6 BANGVEC := $02F5 ; --------------------------------------------------------------------------- ; I/O locations ; 6522 .struct VIA ; Versatile Interface Adapter .res $0300 PRB .byte ; Port Register B PRA .byte ; Port Register A DDRB .byte ; Data Direction Register B DDRA .byte ; Data Direction Register A T1 .word ; Timer 1 T1L .word ; Timer 1 Latch T2 .word ; Timer 2 SR .byte ; Shift Register ACR .byte ; Auxiliary Control Register PCR .byte ; Peripheral Control Register IFR .byte ; Interrupt Flags Register IER .byte ; Interrupt Enable Register PRA2 .byte ; Port Register A without handshaking .endstruct ; 6551 .struct ACIA ; Asynchronous Communications Interface Adapter .res $031C DATA .byte STATUS .byte CMD .byte ; Command register CTRL .byte ; Control register .endstruct SCREEN := $BB80 ; --------------------------------------------------------------------------- ; ROM entries GETLINE := $C592 TEXT := $EC21 HIRES := $EC33 CURSET := $F0C8 CURMOV := $F0FD DRAW := $F110 CHAR := $F12D POINT := $F1C8 PAPER := $F204 INK := $F210 PRINT := $F77C ; Sound Effects PING := $FA9F PING1 := $FA85 SHOOT := $FAB5 SHOOT1 := $FA9B EXPLODE := $FACB EXPLODE1 := $FAB1 ZAP := $FAE1 ZAP1 := $FAC7 TICK := $FB14 TICK1 := $FAFA TOCK := $FB2A TOCK1 := $FB10 cc65-2.18/asminc/c128.inc000066400000000000000000000155331347360151100146360ustar00rootroot00000000000000; ; C128 generic definitions. Stolen from Elite128 ; ; --------------------------------------------------------------------------- ; Zero page, Commodore stuff TXTPTR := $3D ; Pointer into BASIC source code TIME := $A0 ; 60HZ clock FNAM_LEN := $B7 ; Length of filename SECADR := $B9 ; Secondary address DEVNUM := $BA ; Device number FNAM := $BB ; Address of filename FNAM_BANK := $C7 ; Bank for filename KEY_COUNT := $D0 ; Number of keys in input buffer FKEY_COUNT := $D1 ; Characters for function key MODE := $D7 ; 40-/80-column mode (bit 7: 80 columns) GRAPHM := $D8 ; Graphics mode flags (bits 5-7) CHARDIS := $D9 ; Bit 2 shadow for location $01 CURS_X := $EC ; Cursor column CURS_Y := $EB ; Cursor row SCREEN_PTR := $E0 ; Pointer to current char in text screen CRAM_PTR := $E2 ; Pointer to current char in color RAM CHARCOLOR := $F1 RVS := $F3 ; Reverse output flag SCROLL := $F8 ; Disable scrolling flag BASIC_BUF := $0200 ; Location of command-line BASIC_BUF_LEN = 162 ; Maximum length of command-line FETCH := $02A2 ; Fetch subroutine in RAM FETVEC := $02AA ; Vector patch location for FETCH STASH := $02AF ; Stash routine in RAM STAVEC := $02B9 ; Vector patch location for STASH IRQInd := $02FD ; JMP $0000 -- used as indirect IRQ vector PALFLAG := $0A03 ; $FF=PAL, $00=NTSC INIT_STATUS := $0A04 ; Flags: Reset/Restore initiation status VM2 := $0A2D ; VIC-IIe shadow for $D018 -- graphics mode FKEY_LEN := $1000 ; Function key lengths FKEY_TEXT := $100A ; Function key texts KBDREPEAT := $028a KBDREPEATRATE := $028b KBDREPEATDELAY := $028c ; --------------------------------------------------------------------------- ; Vectors IRQVec := $0314 BRKVec := $0316 NMIVec := $0318 KeyStoreVec := $033C ; --------------------------------------------------------------------------- ; I/O: VIC VIC := $D000 VIC_SPR0_X := $D000 VIC_SPR0_Y := $D001 VIC_SPR1_X := $D002 VIC_SPR1_Y := $D003 VIC_SPR2_X := $D004 VIC_SPR2_Y := $D005 VIC_SPR3_X := $D006 VIC_SPR3_Y := $D007 VIC_SPR4_X := $D008 VIC_SPR4_Y := $D009 VIC_SPR5_X := $D00A VIC_SPR5_Y := $D00B VIC_SPR6_X := $D00C VIC_SPR6_Y := $D00D VIC_SPR7_X := $D00E VIC_SPR7_Y := $D00F VIC_SPR_HI_X := $D010 VIC_SPR_ENA := $D015 VIC_SPR_EXP_Y := $D017 VIC_SPR_EXP_X := $D01D VIC_SPR_MCOLOR := $D01C VIC_SPR_BG_PRIO := $D01B VIC_SPR_MCOLOR0 := $D025 VIC_SPR_MCOLOR1 := $D026 VIC_SPR0_COLOR := $D027 VIC_SPR1_COLOR := $D028 VIC_SPR2_COLOR := $D029 VIC_SPR3_COLOR := $D02A VIC_SPR4_COLOR := $D02B VIC_SPR5_COLOR := $D02C VIC_SPR6_COLOR := $D02D VIC_SPR7_COLOR := $D02E VIC_CTRL1 := $D011 VIC_CTRL2 := $D016 VIC_HLINE := $D012 VIC_LPEN_X := $D013 VIC_LPEN_Y := $D014 VIC_VIDEO_ADR := $D018 VIC_IRR := $D019 ; Interrupt request register VIC_IMR := $D01A ; Interrupt mask register VIC_BORDERCOLOR := $D020 VIC_BG_COLOR0 := $D021 VIC_BG_COLOR1 := $D022 VIC_BG_COLOR2 := $D023 VIC_BG_COLOR3 := $D024 ; 128 stuff: VIC_KBD_128 := $D02F ; Extended kbd bits (visible in 64 mode) VIC_CLK_128 := $D030 ; Clock rate register (visible in 64 mode) ; --------------------------------------------------------------------------- ; I/O: SID SID := $D400 SID_S1Lo := $D400 SID_S1Hi := $D401 SID_PB1Lo := $D402 SID_PB1Hi := $D403 SID_Ctl1 := $D404 SID_AD1 := $D405 SID_SUR1 := $D406 SID_S2Lo := $D407 SID_S2Hi := $D408 SID_PB2Lo := $D409 SID_PB2Hi := $D40A SID_Ctl2 := $D40B SID_AD2 := $D40C SID_SUR2 := $D40D SID_S3Lo := $D40E SID_S3Hi := $D40F SID_PB3Lo := $D410 SID_PB3Hi := $D411 SID_Ctl3 := $D412 SID_AD3 := $D413 SID_SUR3 := $D414 SID_FltLo := $D415 SID_FltHi := $D416 SID_FltCtl := $D417 SID_Amp := $D418 SID_ADConv1 := $D419 SID_ADConv2 := $D41A SID_Noise := $D41B SID_Read3 := $D41C ; --------------------------------------------------------------------------- ; I/O: VDC (128 only) VDC_INDEX := $D600 ; register address port VDC_DATA := $D601 ; data port ; Registers VDC_DATA_HI = 18 ; video RAM address (big endian) VDC_DATA_LO = 19 VDC_CSET = 28 VDC_RAM_RW = 31 ; RAM port ; --------------------------------------------------------------------------- ; I/O: Complex Interface Adapters CIA1 := $DC00 CIA1_PRA := $DC00 ; Port A CIA1_PRB := $DC01 ; Port B CIA1_DDRA := $DC02 ; Data direction register for port A CIA1_DDRB := $DC03 ; Data direction register for port B CIA1_TA := $DC04 ; 16-bit timer A CIA1_TB := $DC06 ; 16-bit timer B CIA1_TOD10 := $DC08 ; Time-of-day tenths of a second CIA1_TODSEC := $DC09 ; Time-of-day seconds CIA1_TODMIN := $DC0A ; Time-of-day minutes CIA1_TODHR := $DC0B ; Time-of-day hours CIA1_SDR := $DC0C ; Serial data register CIA1_ICR := $DC0D ; Interrupt control register CIA1_CRA := $DC0E ; Control register for timer A CIA1_CRB := $DC0F ; Control register for timer B CIA2 := $DD00 CIA2_PRA := $DD00 CIA2_PRB := $DD01 CIA2_DDRA := $DD02 CIA2_DDRB := $DD03 CIA2_TA := $DD04 CIA2_TB := $DD06 CIA2_TOD10 := $DD08 CIA2_TODSEC := $DD09 CIA2_TODMIN := $DD0A CIA2_TODHR := $DD0B CIA2_SDR := $DD0C CIA2_ICR := $DD0D CIA2_CRA := $DD0E CIA2_CRB := $DD0F ; --------------------------------------------------------------------------- ; I/O: MMU MMU_CR := $FF00 MMU_CFG_CC65 := %00001110 ; Bank 0 with kernal ROM MMU_CFG_RAM0 := %00111111 ; Bank 0 full RAM MMU_CFG_RAM1 := %01111111 ; Bank 1 full RAM MMU_CFG_RAM2 := %10111111 ; Bank 2 full RAM MMU_CFG_RAM3 := %11111111 ; Bank 3 full RAM MMU_CFG_IFROM := %01010111 ; Bank 1 with Internal Function RAM/ROM MMU_CFG_EFROM := %01101011 ; Bank 1 with External Function RAM/ROM ; --------------------------------------------------------------------------- ; Super CPU SCPU_VIC_Bank1 := $D075 SCPU_Slow := $D07A SCPU_Fast := $D07B SCPU_EnableRegs := $D07E SCPU_DisableRegs:= $D07F SCPU_Detect := $D0BC cc65-2.18/asminc/c16.inc000066400000000000000000000002141347360151100145400ustar00rootroot00000000000000; ; C16 generic definitions. ; ; The C16 and Plus/4 are identical, so just include the Plus/4 include file. .include "plus4.inc" cc65-2.18/asminc/c64.inc000066400000000000000000000145061347360151100145540ustar00rootroot00000000000000; ; C64 generic definitions. Stolen from Elite128 ; ; --------------------------------------------------------------------------- ; 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 SECADR := $B9 ; Secondary address DEVNUM := $BA ; Device number FNAM := $BB ; Pointer to filename KEY_COUNT := $C6 ; Number of keys in input buffer RVS := $C7 ; Reverse flag CURS_FLAG := $CC ; 1 = cursor off CURS_BLINK := $CD ; Blink counter CURS_CHAR := $CE ; Character under the cursor CURS_STATE := $CF ; Cursor blink state 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 CHARCOLOR := $286 CURS_COLOR := $287 ; Color under the cursor PALFLAG := $2A6 ; $01 = PAL, $00 = NTSC KBDREPEAT := $28a KBDREPEATRATE := $28b KBDREPEATDELAY := $28c ; --------------------------------------------------------------------------- ; Vector and other locations IRQVec := $0314 BRKVec := $0316 NMIVec := $0318 ; --------------------------------------------------------------------------- ; Screen size XSIZE = 40 YSIZE = 25 ; --------------------------------------------------------------------------- ; I/O: VIC VIC := $D000 VIC_SPR0_X := $D000 VIC_SPR0_Y := $D001 VIC_SPR1_X := $D002 VIC_SPR1_Y := $D003 VIC_SPR2_X := $D004 VIC_SPR2_Y := $D005 VIC_SPR3_X := $D006 VIC_SPR3_Y := $D007 VIC_SPR4_X := $D008 VIC_SPR4_Y := $D009 VIC_SPR5_X := $D00A VIC_SPR5_Y := $D00B VIC_SPR6_X := $D00C VIC_SPR6_Y := $D00D VIC_SPR7_X := $D00E VIC_SPR7_Y := $D00F VIC_SPR_HI_X := $D010 VIC_SPR_ENA := $D015 VIC_SPR_EXP_Y := $D017 VIC_SPR_EXP_X := $D01D VIC_SPR_MCOLOR := $D01C VIC_SPR_BG_PRIO := $D01B VIC_SPR_MCOLOR0 := $D025 VIC_SPR_MCOLOR1 := $D026 VIC_SPR0_COLOR := $D027 VIC_SPR1_COLOR := $D028 VIC_SPR2_COLOR := $D029 VIC_SPR3_COLOR := $D02A VIC_SPR4_COLOR := $D02B VIC_SPR5_COLOR := $D02C VIC_SPR6_COLOR := $D02D VIC_SPR7_COLOR := $D02E VIC_CTRL1 := $D011 VIC_CTRL2 := $D016 VIC_HLINE := $D012 VIC_LPEN_X := $D013 VIC_LPEN_Y := $D014 VIC_VIDEO_ADR := $D018 VIC_IRR := $D019 ; Interrupt request register VIC_IMR := $D01A ; Interrupt mask register VIC_BORDERCOLOR := $D020 VIC_BG_COLOR0 := $D021 VIC_BG_COLOR1 := $D022 VIC_BG_COLOR2 := $D023 VIC_BG_COLOR3 := $D024 ; 128 stuff: VIC_KBD_128 := $D02F ; Extended kbd bits (visible in 64 mode) VIC_CLK_128 := $D030 ; Clock rate register (visible in 64 mode) ; --------------------------------------------------------------------------- ; I/O: SID SID := $D400 SID_S1Lo := $D400 SID_S1Hi := $D401 SID_PB1Lo := $D402 SID_PB1Hi := $D403 SID_Ctl1 := $D404 SID_AD1 := $D405 SID_SUR1 := $D406 SID_S2Lo := $D407 SID_S2Hi := $D408 SID_PB2Lo := $D409 SID_PB2Hi := $D40A SID_Ctl2 := $D40B SID_AD2 := $D40C SID_SUR2 := $D40D SID_S3Lo := $D40E SID_S3Hi := $D40F SID_PB3Lo := $D410 SID_PB3Hi := $D411 SID_Ctl3 := $D412 SID_AD3 := $D413 SID_SUR3 := $D414 SID_FltLo := $D415 SID_FltHi := $D416 SID_FltCtl := $D417 SID_Amp := $D418 SID_ADConv1 := $D419 SID_ADConv2 := $D41A SID_Noise := $D41B SID_Read3 := $D41C ; --------------------------------------------------------------------------- ; I/O: VDC (128 only) VDC_INDEX := $D600 VDC_DATA := $D601 ; --------------------------------------------------------------------------- ; I/O: Complex Interface Adapters CIA1 := $DC00 CIA1_PRA := $DC00 ; Port A CIA1_PRB := $DC01 ; Port B CIA1_DDRA := $DC02 ; Data direction register for port A CIA1_DDRB := $DC03 ; Data direction register for port B CIA1_TA := $DC04 ; 16-bit timer A CIA1_TB := $DC06 ; 16-bit timer B CIA1_TOD10 := $DC08 ; Time-of-day tenths of a second CIA1_TODSEC := $DC09 ; Time-of-day seconds CIA1_TODMIN := $DC0A ; Time-of-day minutes CIA1_TODHR := $DC0B ; Time-of-day hours CIA1_SDR := $DC0C ; Serial data register CIA1_ICR := $DC0D ; Interrupt control register CIA1_CRA := $DC0E ; Control register for timer A CIA1_CRB := $DC0F ; Control register for timer B CIA2 := $DD00 CIA2_PRA := $DD00 CIA2_PRB := $DD01 CIA2_DDRA := $DD02 CIA2_DDRB := $DD03 CIA2_TA := $DD04 CIA2_TB := $DD06 CIA2_TOD10 := $DD08 CIA2_TODSEC := $DD09 CIA2_TODMIN := $DD0A CIA2_TODHR := $DD0B CIA2_SDR := $DD0C CIA2_ICR := $DD0D CIA2_CRA := $DD0E CIA2_CRB := $DD0F ; --------------------------------------------------------------------------- ; Super CPU SCPU_VIC_Bank1 := $D075 SCPU_Slow := $D07A SCPU_Fast := $D07B SCPU_EnableRegs := $D07E SCPU_DisableRegs:= $D07F SCPU_Detect := $D0BC ; --------------------------------------------------------------------------- ; Processor Port at $01 LORAM = $01 ; Enable the basic rom HIRAM = $02 ; Enable the kernal rom IOEN = $04 ; Enable I/O CASSDATA = $08 ; Cassette data CASSPLAY = $10 ; Cassette: Play CASSMOT = $20 ; Cassette motor on TP_FAST = $80 ; Switch Rossmoeller TurboProcess to fast mode RAMONLY = $F8 ; (~(LORAM | HIRAM | IOEN)) & $FF cc65-2.18/asminc/cbm.mac000066400000000000000000000026341347360151100147070ustar00rootroot00000000000000; Convert characters to screen codes ; Macro that converts one character. ; scrbyte() can be used as an instruction operand .define scrbyte(code) (<(.strat ("h@dbdlhh", code >> 5) << 4) ^ code) ; Helper macro that stores one character .macro _scrcode char .if (char < 256) .byte scrbyte {char} .else .error "scrcode: Character constant out of range" .endif .endmacro .macro scrcode arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 ; Bail out if next argument is empty .if .blank ({arg1}) .exitmacro .endif ; Check for a string .if .match ({arg1}, "") ; Walk over all string chars .repeat .strlen (arg1), i _scrcode {.strat (arg1, i)} .endrepeat ; Check for a number .elseif .match (.left (1, {arg1}), 0) ; Just output the number _scrcode arg1 ; Check for a character .elseif .match (.left (1, {arg1}), 'a') ; Just output the character _scrcode arg1 ; Anything else is an error .else .error "scrcode: invalid argument type" .endif ; Call the macro recursively with the remaining args scrcode arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 .endmacro cc65-2.18/asminc/cbm510.inc000066400000000000000000000104521347360151100151430ustar00rootroot00000000000000; ; Zero page variables and I/O definitions for the CBM 510 ; ; Taken from a kernal disassembly done by myself in 2000/2001. ; ; 2001-09-13, Ullrich von Bassewitz ; 2014-04-02, Greg King ;----------------------------------------------------------------------------- ; Zeropage stuff ExecReg := $00 ; Controls execution memory bank IndReg := $01 ; Controls indirect indexed load-store bank TXTPTR := $85 ; Far pointer into BASIC source code FNAM := $90 ; Far pointer to LOAD/SAVE file-name FNAM_LEN := $9D ; Holds length of file-name ; --------------------------------------------------------------------------- ; Screen size XSIZE = 40 YSIZE = 25 ;----------------------------------------------------------------------------- ; I/O Definitions ; Note: These numbers aren't addresses. They are offsets from the start of ; each chip's register set. They are used in the indirect indexed addressing ; mode. ; I/O $d800: VIC-II VIC_SPR0_X = $00 VIC_SPR0_Y = $01 VIC_SPR1_X = $02 VIC_SPR1_Y = $03 VIC_SPR2_X = $04 VIC_SPR2_Y = $05 VIC_SPR3_X = $06 VIC_SPR3_Y = $07 VIC_SPR4_X = $08 VIC_SPR4_Y = $09 VIC_SPR5_X = $0A VIC_SPR5_Y = $0B VIC_SPR6_X = $0C VIC_SPR6_Y = $0D VIC_SPR7_X = $0E VIC_SPR7_Y = $0F VIC_SPR_HI_X = $10 VIC_SPR_ENA = $15 VIC_SPR_EXP_Y = $17 VIC_SPR_EXP_X = $1D VIC_SPR_MCOLOR = $1C VIC_SPR_BG_PRIO = $1B VIC_SPR_MCOLOR0 = $25 VIC_SPR_MCOLOR1 = $26 VIC_SPR0_COLOR = $27 VIC_SPR1_COLOR = $28 VIC_SPR2_COLOR = $29 VIC_SPR3_COLOR = $2A VIC_SPR4_COLOR = $2B VIC_SPR5_COLOR = $2C VIC_SPR6_COLOR = $2D VIC_SPR7_COLOR = $2E VIC_CTRL1 = $11 VIC_CTRL2 = $16 VIC_HLINE = $12 VIC_LPEN_X = $13 VIC_LPEN_Y = $14 VIC_VIDEO_ADR = $18 VIC_IRR = $19 ; Interrupt request register VIC_IMR = $1A ; Interrupt mask register VIC_BORDERCOLOR = $20 VIC_BG_COLOR0 = $21 VIC_BG_COLOR1 = $22 VIC_BG_COLOR2 = $23 VIC_BG_COLOR3 = $24 ; I/O $da00: SID 6581 SID_S1Lo = $00 SID_S1Hi = $01 SID_PB1Lo = $02 SID_PB1Hi = $03 SID_Ctl1 = $04 SID_AD1 = $05 SID_SUR1 = $06 SID_S2Lo = $07 SID_S2Hi = $08 SID_PB2Lo = $09 SID_PB2Hi = $0A SID_Ctl2 = $0B SID_AD2 = $0C SID_SUR2 = $0D SID_S3Lo = $0E SID_S3Hi = $0F SID_PB3Lo = $10 SID_PB3Hi = $11 SID_Ctl3 = $12 SID_AD3 = $13 SID_SUR3 = $14 SID_FltLo = $15 SID_FltHi = $16 SID_FltCtl = $17 SID_Amp = $18 SID_ADConv1 = $19 SID_ADConv2 = $1A SID_Noise = $1B SID_Read3 = $1C ; I/O $db00: CIA 6526, Inter Process Communication ; I/O $dc00: CIA 6526 .struct CIA PRA .byte PRB .byte DDRA .byte DDRB .byte .union .struct TALO .byte TAHI .byte .endstruct TA .word .endunion .union .struct TBLO .byte TBHI .byte .endstruct TB .word .endunion TOD10 .byte TODSEC .byte TODMIN .byte TODHR .byte SDR .byte ICR .byte CRA .byte CRB .byte .endstruct ; I/O $dd00: ACIA 6551 .struct ACIA DATA .byte STATUS .byte CMD .byte CTRL .BYTE .endstruct ; I/O $de00: Triport #1 6525 ; I/O $df00: Triport #2 6525 .struct TPI PRA .byte PRB .byte .union PRC .byte INT .byte .endunion DDRA .byte DDRB .byte .union DDRC .byte IMR .byte .endunion CR .byte AIR .byte .endstruct ;----------------------------------------------------------------------------- ; Our video memory address COLOR_RAM := $D400 ; System bank ;----------------------------------------------------------------------------- BASIC_BUF := $FB5E ; Bank 0 location of command-line BASIC_BUF_LEN = 162 ; Maximum length of command-line cc65-2.18/asminc/cbm610.inc000066400000000000000000000050541347360151100151460ustar00rootroot00000000000000; ; Zero page variables and I/O definitions for the CBM 610 ; ; Taken from a kernal disassembly done by myself in 1987. ; ; 1998-09-28, Ullrich von Bassewitz ; 2014-04-02, Greg King ; --------------------------------------------------------------------------- ; Zeropage stuff ExecReg := $00 ; Controls execution memory bank IndReg := $01 ; Controls indirect indexed load-store bank TXTPTR := $85 ; Far pointer into BASIC source code FNAM := $90 ; Far pointer to LOAD/SAVE file-name FNAM_LEN := $9D ; Holds length of file-name ; --------------------------------------------------------------------------- ; Screen size XSIZE = 80 YSIZE = 25 ; --------------------------------------------------------------------------- ; I/O definitions ; I/O $d800: CRTC 6545 .struct CRTC ADDR .byte DATA .byte .endstruct ; I/O $db00: CIA 6526, Inter Process Communication ; ; IPCcia = $db00 .struct CIA PRA .byte PRB .byte DDRA .byte DDRB .byte .union .struct TALO .byte TAHI .byte .endstruct TA .word .endunion .union .struct TBLO .byte TBHI .byte .endstruct TB .word .endunion TOD10 .byte TODSEC .byte TODMIN .byte TODHR .byte SDR .byte ICR .byte CRA .byte CRB .byte .endstruct ; I/O $dc00: CIA 6526 ; ; cia = $dc00 ; I/O $dd00: ACIA 6551 ; ; acia = $dd00 .struct ACIA DATA .byte STATUS .byte CMD .byte CTRL .BYTE .endstruct ; I/O $de00: Triport #1 6525 ; ; tpi1 = $de00 .struct TPI PRA .byte PRB .byte .union PRC .byte INT .byte .endunion DDRA .byte DDRB .byte .union DDRC .byte IMR .byte .endunion CR .byte AIR .byte .endstruct ; I/O $df00: Triport #2 6525 ; tpi2 = $df00 ;----------------------------------------------------------------------------- BASIC_BUF := $FA5E ; Bank 1 location of command-line BASIC_BUF_LEN = 162 ; Maximum length of command-line cc65-2.18/asminc/cbm_filetype.inc000066400000000000000000000021771347360151100166230ustar00rootroot00000000000000; ; Definitions for CBM file types. From cbm.h ; ; Ullrich von Bassewitz, 2012-06-03 ; ; Define bitmapped constants for the table entries .enum CBM_T_REG = $10 ; Bit set for regular files CBM_T_SEQ = $10 ; Sequential file CBM_T_PRG = $11 ; Program file CBM_T_USR = $12 ; User file CBM_T_REL = $13 ; Relative file CBM_T_VRP = $14 ; Vorpal fast-loadable format CBM_T_DEL = $00 ; Deleted file CBM_T_CBM = $01 ; 1581 sub-partition CBM_T_DIR = $02 ; IDE64 and CMD sub-directory CBM_T_LNK = $03 ; IDE64 soft-link CBM_T_OTHER = $04 ; File-type not recognized CBM_T_HEADER = $05 ; Disk header / title .endenum ; The following function maps the start character for a file type to ; one of the file types above. Note: 'd' will always mapped to CBM_T_DEL. ; The calling function has to look at the following character to determine ; if the file type is actually CBM_T_DIR. ; ; unsigned char __fastcall__ _cbm_filetype (unsigned char c); .global __cbm_filetype cc65-2.18/asminc/cbm_kernal.inc000066400000000000000000000056131347360151100162540ustar00rootroot00000000000000; ; Olli Savia ; ; Commodore kernal functions ; .if .def(__C128__) ; C128 Extended jump table C64MODE := $FF4D SWAPPER := $FF5F SETBNK := $FF68 .endif .if .def(__C64__) || .def(__C128__) || .def(__C16__) CINT := $FF81 IOINIT := $FF84 RAMTAS := $FF87 .elseif .def(__VIC20__) CINT := $E518 ; No entries are in the kernal jump table of the Vic20 for these three (3) functions. IOINIT := $FDF9 ; The entries for these functions have been set to point directly to the functions RAMTAS := $FD8D ; in the kernal to maintain compatibility with the other Commodore platforms. .elseif .def(__CBM510__) || .def(__CBM610__) IOINIT := $FF7B CINT := $FF7E .endif .if .def(__VIC20__) || .def(__C64__) || .def(__C128__) || .def(__C16__) RESTOR := $FF8A VECTOR := $FF8D .elseif .def(__CBM510__) || .def(__CBM610__) VECTOR := $FF84 RESTOR := $FF87 .endif .if .def(__CBM510__) || .def(__CBM610__) || .def(__VIC20__) || .def(__C64__) || .def(__C128__) || .def(__C16__) SETMSG := $FF90 SECOND := $FF93 TKSA := $FF96 MEMTOP := $FF99 MEMBOT := $FF9C SCNKEY := $FF9F SETTMO := $FFA2 ACPTR := $FFA5 CIOUT := $FFA8 UNTLK := $FFAB UNLSN := $FFAE LISTEN := $FFB1 TALK := $FFB4 READST := $FFB7 SETLFS := $FFBA SETNAM := $FFBD OPEN := $FFC0 CLOSE := $FFC3 .endif ; Available on all platforms including PET CHKIN := $FFC6 CKOUT := $FFC9 CHKOUT := $FFC9 CLRCH := $FFCC CLRCHN := $FFCC BASIN := $FFCF CHRIN := $FFCF BSOUT := $FFD2 CHROUT := $FFD2 .if .def(__CBM510__) || .def(__CBM610__) || .def(__VIC20__) || .def(__C64__) || .def(__C128__) || .def(__C16__) LOAD := $FFD5 SAVE := $FFD8 SETTIM := $FFDB RDTIM := $FFDE .endif ; Available on all platforms including PET STOP := $FFE1 GETIN := $FFE4 CLALL := $FFE7 UDTIM := $FFEA .if .def(__CBM510__) || .def(__CBM610__) || .def(__VIC20__) || .def(__C64__) || .def(__C128__) || .def(__C16__) SCREEN := $FFED PLOT := $FFF0 IOBASE := $FFF3 .endif ; --------------------------------------------------------------------------- ; Kernal routines, direct entries .if .def(__VIC20__) CLRSCR := $E55F KBDREAD := $E5CF .elseif .def(__C64__) CLRSCR := $E544 KBDREAD := $E5B4 NMIEXIT := $FEBC .elseif .def(__C128__) CLRSCR := $C142 KBDREAD := $C006 NMIEXIT := $FF33 NEWLINE := $C363 PRINT := $C322 CURS_SET := $CD57 CURS_ON := $CD6F CURS_OFF := $CD9F INDFET := $FF74 .elseif .def(__C16__) CLRSCR := $D88B KBDREAD := $D8C1 .endif cc65-2.18/asminc/cpu.mac000066400000000000000000000015131347360151100147300ustar00rootroot00000000000000; CPU bitmask constants CPU_ISET_NONE = $0001 CPU_ISET_6502 = $0002 CPU_ISET_6502X = $0004 CPU_ISET_65SC02 = $0008 CPU_ISET_65C02 = $0010 CPU_ISET_65816 = $0020 CPU_ISET_SWEET16 = $0040 CPU_ISET_HUC6280 = $0080 ;CPU_ISET_M740 = $0100 not actually implemented CPU_ISET_4510 = $0200 ; CPU capabilities CPU_NONE = CPU_ISET_NONE CPU_6502 = CPU_ISET_6502 CPU_6502X = CPU_ISET_6502|CPU_ISET_6502X CPU_65SC02 = CPU_ISET_6502|CPU_ISET_65SC02 CPU_65C02 = CPU_ISET_6502|CPU_ISET_65SC02|CPU_ISET_65C02 CPU_65816 = CPU_ISET_6502|CPU_ISET_65SC02|CPU_ISET_65816 CPU_SWEET16 = CPU_ISET_SWEET16 CPU_HUC6280 = CPU_ISET_6502|CPU_ISET_65SC02|CPU_ISET_65C02|CPU_ISET_HUC6280 CPU_4510 = CPU_ISET_6502|CPU_ISET_65SC02|CPU_ISET_65C02|CPU_ISET_4510 cc65-2.18/asminc/creativision.inc000066400000000000000000000027561347360151100166630ustar00rootroot00000000000000;* ;** VTech Creativision Definitions ;* ;** Screen SCREEN_ROWS = 24 SCREEN_COLS = 32 SCREEN_PTR = $3A CURSOR_X = $3C CURSOR_Y = $3D ;** VDP VDP_DATA_R = $2000 VDP_STATUS_R = $2001 VDP_DATA_W = $3000 VDP_CONTROL_W = $3001 ;** PIA PIA0_DATA = $1000 PIA0_STATUS = $1001 PIA1_DATA = $1002 PIA1_STATUS = $1003 ;** General CH_VLINE = 33 CH_HLINE = 34 CH_ULCORNER = 35 CH_URCORNER = 36 CH_LLCORNER = 37 CH_LRCORNER = 38 ;** I/O (Zero-page variables) ZP_KEYBOARD = $10 ZP_JOY0_DIR = $11 ZP_JOY1_DIR = $13 ZP_JOY0_BUTTONS = $16 ZP_JOY1_BUTTONS = $17 ;** Joystick direction values (ZP_JOY0_DIR/ZP_JOY1_DIR) JOY_N = $49 JOY_NNE = $48 JOY_NE = $47 JOY_ENE = $46 JOY_E = $45 JOY_ESE = $44 JOY_SE = $43 JOY_SSE = $42 JOY_S = $41 JOY_SSW = $40 JOY_SW = $4F JOY_WSW = $4E JOY_W = $4D JOY_WNW = $4C JOY_NW = $4B JOY_NNW = $4A ;** BIOS BIOS_IRQ1_ADDR = $FF3F BIOS_IRQ2_ADDR = $FF52 BIOS_NMI_RESET_ADDR = $F808 BIOS_WRITE_VDP_REG = $FE1F cc65-2.18/asminc/ctype.inc000066400000000000000000000017441347360151100153040ustar00rootroot00000000000000; ; Definitions for the character type tables ; ; Ullrich von Bassewitz, 08.09.2001 ; ; Make the __ctype table an exported/imported symbol .global __ctype ; Define bitmapped constants for the table entries CT_NONE = $00 ; Nothing special CT_LOWER = $01 ; 0 - Lower case char CT_UPPER = $02 ; 1 - Upper case char CT_DIGIT = $04 ; 2 - Numeric digit CT_XDIGIT = $08 ; 3 - Hex digit (both, lower and upper) CT_CTRL = $10 ; 4 - Control character CT_SPACE = $20 ; 5 - The space character itself CT_OTHER_WS = $40 ; 6 - Other whitespace ('\f', '\n', '\r', '\t' and '\v') CT_SPACE_TAB = $80 ; 7 - Space or tab character ; Combined stuff CT_ALNUM = (CT_LOWER | CT_UPPER | CT_DIGIT) CT_ALPHA = (CT_LOWER | CT_UPPER) CT_CTRL_SPACE = (CT_CTRL | CT_SPACE) CT_NOT_PUNCT = (CT_SPACE | CT_CTRL | CT_DIGIT | CT_UPPER | CT_LOWER) cc65-2.18/asminc/em-error.inc000066400000000000000000000060131347360151100157020ustar00rootroot00000000000000;/*****************************************************************************/ ;/* */ ;/* em-error.inc */ ;/* */ ;/* EM error codes */ ;/* */ ;/* */ ;/* */ ;/* (C) 2002-2012, Ullrich von Bassewitz */ ;/* Roemerstrasse 52 */ ;/* D-70794 Filderstadt */ ;/* EMail: uz@cc65.org */ ;/* */ ;/* */ ;/* This software is provided 'as-is', without any expressed or implied */ ;/* warranty. In no event will the authors be held liable for any damages */ ;/* arising from the use of this software. */ ;/* */ ;/* Permission is granted to anyone to use this software for any purpose, */ ;/* including commercial applications, and to alter it and redistribute it */ ;/* freely, subject to the following restrictions: */ ;/* */ ;/* 1. The origin of this software must not be misrepresented; you must not */ ;/* claim that you wrote the original software. If you use this software */ ;/* in a product, an acknowledgment in the product documentation would be */ ;/* appreciated but is not required. */ ;/* 2. Altered source versions must be plainly marked as such, and must not */ ;/* be misrepresented as being the original software. */ ;/* 3. This notice may not be removed or altered from any source */ ;/* distribution. */ ;/* */ ;/*****************************************************************************/ ; Error constants .enum EM_ERR_OK ; No error EM_ERR_NO_DRIVER ; No driver available EM_ERR_CANNOT_LOAD ; Error loading driver EM_ERR_INV_DRIVER ; Invalid driver EM_ERR_NO_DEVICE ; Device (hardware) not found EM_ERR_INSTALLED ; A driver is already installed EM_ERR_COUNT ; Special: Number of error messages .endenum cc65-2.18/asminc/em-kernel.inc000066400000000000000000000115421347360151100160340ustar00rootroot00000000000000;/*****************************************************************************/ ;/* */ ;/* em-kernel.inc */ ;/* */ ;/* EM kernel interface */ ;/* */ ;/* */ ;/* */ ;/* (C) 2002-2003 Ullrich von Bassewitz */ ;/* Römerstrasse 52 */ ;/* D-70794 Filderstadt */ ;/* EMail: uz@cc65.org */ ;/* */ ;/* */ ;/* This software is provided 'as-is', without any expressed or implied */ ;/* warranty. In no event will the authors be held liable for any damages */ ;/* arising from the use of this software. */ ;/* */ ;/* Permission is granted to anyone to use this software for any purpose, */ ;/* including commercial applications, and to alter it and redistribute it */ ;/* freely, subject to the following restrictions: */ ;/* */ ;/* 1. The origin of this software must not be misrepresented; you must not */ ;/* claim that you wrote the original software. If you use this software */ ;/* in a product, an acknowledgment in the product documentation would be */ ;/* appreciated but is not required. */ ;/* 2. Altered source versions must be plainly marked as such, and must not */ ;/* be misrepresented as being the original software. */ ;/* 3. This notice may not be removed or altered from any source */ ;/* distribution. */ ;/* */ ;/*****************************************************************************/ ;------------------------------------------------------------------------------ ; The driver header .struct EMD_HDR ID .byte 3 ; Contains 0x65, 0x6d, 0x64 ("emd") VERSION .byte 1 ; Interface version LIBREF .addr ; Library reference JUMPTAB .struct INSTALL .addr ; INSTALL routine UNINSTALL .addr ; UNINSTALL routine PAGECOUNT .addr ; PAGECOUNT routine MAP .addr ; MAP routine USE .addr ; USE routine MAPCLEAN .addr ; MAPCLEAN routine COPYFROM .addr ; COPYFROM routine COPYTO .addr ; COPYTO routine .endstruct .endstruct ;------------------------------------------------------------------------------ ; The EMD API version, stored in EMD_HDR::VERSION EMD_API_VERSION = $02 ;------------------------------------------------------------------------------ ; The asm equivalent to the C em_copy structure .struct EM_COPY BUF .addr ; Memory buffer to copy from or to OFFS .byte ; Offset into page PAGE .word ; Starting page to copy from or to COUNT .word ; Number of bytes to copy UNUSED .byte ; Make the size 8 bytes .endstruct ;------------------------------------------------------------------------------ ; Variables .global _em_drv ; Pointer to driver ;------------------------------------------------------------------------------ ; Driver entry points .global emd_install .global emd_uninstall .global emd_pagecount .global emd_map .global emd_use .global emd_commit .global emd_copyfrom .global emd_copyto ;------------------------------------------------------------------------------ ; ASM functions .global em_clear_ptr ;------------------------------------------------------------------------------ ; C callable functions .global _em_load_driver .global _em_unload .global _em_install .global _em_uninstall .global _em_pagecount .global _em_map .global _em_use .global _em_commit .global _em_copyfrom .global _em_copyto cc65-2.18/asminc/errno.inc000066400000000000000000000026001347360151100152750ustar00rootroot00000000000000; ; Ullrich von Bassewitz, 16.05.2000 ; ; Variables and functions .global __errno, __oserror .global __osmaperrno .global __seterrno .global __directerrno, __mappederrno ; Error codes, must match the values in the C headers .enum EOK ; No error ENOENT ; No such file or directory ENOMEM ; Out of memory EACCES ; Permission denied ENODEV ; No such device EMFILE ; Too many open files EBUSY ; Device or resource busy EINVAL ; Invalid argument ENOSPC ; No space left on device EEXIST ; File exists EAGAIN ; Try again EIO ; I/O error EINTR ; Interrupted system call ENOSYS ; Function not implemented ESPIPE ; Illegal seek ERANGE ; Range error EBADF ; Bad file number ENOEXEC ; Exec format error EUNKNOWN ; Unknown OS specific error - must be last! EMAX = EUNKNOWN ; Highest error code .endenum cc65-2.18/asminc/fcntl.inc000066400000000000000000000005341347360151100152620ustar00rootroot00000000000000; ; Ullrich von Bassewitz, 05.06.1999 ; ; Predefined file handles STDIN_FILENO = 0 STDOUT_FILENO = 1 STDERR_FILENO = 2 ; File mode constants, must match the values in the C headers O_RDONLY = $01 O_WRONLY = $02 O_RDWR = $03 O_CREAT = $10 O_TRUNC = $20 O_APPEND = $40 O_EXCL = $80 cc65-2.18/asminc/gamate.inc000066400000000000000000000026061347360151100154140ustar00rootroot00000000000000;------------------------------------------------------------------------------- ; gamate.inc ; ; Gamate system specific definitions ; ; (w) 2015 Groepaz/Hitmen (groepaz@gmx.net) ; based on technical reference by PeT (mess@utanet.at) ;------------------------------------------------------------------------------- ; look at gamate.h for comments, they are not duplicated here AUDIO_BASE = $4000 JOY_DATA = $4400 JOY_DATA_UP = $01 JOY_DATA_DOWN = $02 JOY_DATA_LEFT = $04 JOY_DATA_RIGHT = $08 JOY_DATA_FIRE_A = $10 JOY_DATA_FIRE_B = $20 JOY_DATA_START = $40 JOY_DATA_SELECT = $80 LCD_WIDTH = 160 LCD_HEIGHT = 152 LCD_BASE = $5000 LCD_MODE = $5001 LCD_XPOS = $5002 LCD_YPOS = $5003 LCD_X = $5004 LCD_Y = $5005 LCD_READ = $5006 LCD_DATA = $5007 LCD_MODE_INC_X = $00 LCD_MODE_INC_Y = $40 LCD_XPOS_PLANE1 = $00 LCD_XPOS_PLANE2 = $80 ; constants for the conio implementation charsperline = (LCD_WIDTH / 8) screenrows = (LCD_HEIGHT / 8) CH_HLINE = 1 CH_VLINE = 2 COLOR_WHITE = 0 COLOR_GREY2 = 1 COLOR_GREY1 = 2 COLOR_BLACK = 3 ; bios zp usage: ZP_NMI_4800 = $0a ZP_IRQ_COUNT = $0b ZP_IRQ_CTRL = $0c ZP_IRQ_CNT1 = $0e ZP_IRQ_CNT2 = $0f ZP_IRQ_CNT3 = $10 ZP_IRQ_CNT4 = $11 ZP_NMI_FLAG = $e8 cc65-2.18/asminc/generic.mac000066400000000000000000000016741347360151100155650ustar00rootroot00000000000000 ; add - Add without carry .macro add Arg1, Arg2 clc .if .paramcount = 2 adc Arg1, Arg2 .else adc Arg1 .endif .endmacro ; sub - subtract without borrow .macro sub Arg1, Arg2 sec .if .paramcount = 2 sbc Arg1, Arg2 .else sbc Arg1 .endif .endmacro ; bge - jump if unsigned greater or equal .macro bge Arg bcs Arg .endmacro ; blt - Jump if unsigned less .macro blt Arg bcc Arg .endmacro ; bgt - jump if unsigned greater .macro bgt Arg .local L beq L bcs Arg L: .endmacro ; ble - jump if unsigned less or equal .macro ble Arg beq Arg bcc Arg .endmacro ; bnz - jump if not zero .macro bnz Arg bne Arg .endmacro ; bze - jump if zero .macro bze Arg beq Arg .endmacro cc65-2.18/asminc/get_tv.inc000066400000000000000000000003411347360151100154400ustar00rootroot00000000000000; ; get_tv.inc ; ; Ullrich von Bassewitz, 2004-10-15 ; ; Defines for the get_tv function. ; Error codes returned by all functions .enum TV NTSC PAL OTHER .endenum ; get_tv function .global _get_tv cc65-2.18/asminc/joy-error.inc000066400000000000000000000055051347360151100161070ustar00rootroot00000000000000;/*****************************************************************************/ ;/* */ ;/* joy-error.inc */ ;/* */ ;/* Joystick error codes */ ;/* */ ;/* */ ;/* */ ;/* (C) 2002 Ullrich von Bassewitz */ ;/* Wacholderweg 14 */ ;/* D-70597 Stuttgart */ ;/* EMail: uz@musoftware.de */ ;/* */ ;/* */ ;/* 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. */ ;/* */ ;/*****************************************************************************/ ; Error codes JOY_ERR_OK = 0 ; No error JOY_ERR_NO_DRIVER = 1 ; No driver available JOY_ERR_CANNOT_LOAD = 2 ; Error loading driver JOY_ERR_INV_DRIVER = 3 ; Invalid driver JOY_ERR_NO_DEVICE = 4 ; Device (hardware) not found cc65-2.18/asminc/joy-kernel.inc000066400000000000000000000076431347360151100162430ustar00rootroot00000000000000;/*****************************************************************************/ ;/* */ ;/* joy-kernel.inc */ ;/* */ ;/* Internally used joystick functions */ ;/* */ ;/* */ ;/* */ ;/* (C) 2002-2006, Ullrich von Bassewitz */ ;/* Römerstraße 52 */ ;/* D-70794 Filderstadt */ ;/* EMail: uz@cc65.org */ ;/* */ ;/* */ ;/* This software is provided 'as-is', without any expressed or implied */ ;/* warranty. In no event will the authors be held liable for any damages */ ;/* arising from the use of this software. */ ;/* */ ;/* Permission is granted to anyone to use this software for any purpose, */ ;/* including commercial applications, and to alter it and redistribute it */ ;/* freely, subject to the following restrictions: */ ;/* */ ;/* 1. The origin of this software must not be misrepresented; you must not */ ;/* claim that you wrote the original software. If you use this software */ ;/* in a product, an acknowledgment in the product documentation would be */ ;/* appreciated but is not required. */ ;/* 2. Altered source versions must be plainly marked as such, and must not */ ;/* be misrepresented as being the original software. */ ;/* 3. This notice may not be removed or altered from any source */ ;/* distribution. */ ;/* */ ;/*****************************************************************************/ ;------------------------------------------------------------------------------ ; Driver header stuff .struct JOY_HDR ID .byte 3 ; $6A, $6F, $79 ("joy") VERSION .byte 1 ; Interface version LIBREF .addr ; Library reference JUMPTAB .struct INSTALL .addr ; INSTALL routine UNINSTALL .addr ; UNINSTALL routine COUNT .addr ; COUNT routine READ .addr ; READ routine .endstruct .endstruct ;------------------------------------------------------------------------------ ; The JOY API version, stored in JOY_HDR::VERSION JOY_API_VERSION = $05 ;------------------------------------------------------------------------------ ; Variables .global _joy_drv ; Pointer to driver .global _joy_masks ;------------------------------------------------------------------------------ ; Driver entry points .global joy_install .global joy_uninstall .global joy_count .global joy_read ;------------------------------------------------------------------------------ ; C callable functions .global _joy_load_driver .global _joy_unload .global _joy_install .global _joy_uninstall .global _joy_count .global _joy_read .global _joy_clear_ptr cc65-2.18/asminc/longbranch.mac000066400000000000000000000051101347360151100162530ustar00rootroot00000000000000.macro jeq Target .if .match(Target, 0) bne *+5 jmp Target .elseif .def(Target) .and .const((*-2)-(Target)) .and ((*+2)-(Target) <= 127) beq Target .else bne *+5 jmp Target .endif .endmacro .macro jne Target .if .match(Target, 0) beq *+5 jmp Target .elseif .def(Target) .and .const((*-2)-(Target)) .and ((*+2)-(Target) <= 127) bne Target .else beq *+5 jmp Target .endif .endmacro .macro jmi Target .if .match(Target, 0) bpl *+5 jmp Target .elseif .def(Target) .and .const((*-2)-(Target)) .and ((*+2)-(Target) <= 127) bmi Target .else bpl *+5 jmp Target .endif .endmacro .macro jpl Target .if .match(Target, 0) bmi *+5 jmp Target .elseif .def(Target) .and .const((*-2)-(Target)) .and ((*+2)-(Target) <= 127) bpl Target .else bmi *+5 jmp Target .endif .endmacro .macro jcs Target .if .match(Target, 0) bcc *+5 jmp Target .elseif .def(Target) .and .const((*-2)-(Target)) .and ((*+2)-(Target) <= 127) bcs Target .else bcc *+5 jmp Target .endif .endmacro .macro jcc Target .if .match(Target, 0) bcs *+5 jmp Target .elseif .def(Target) .and .const((*-2)-(Target)) .and ((*+2)-(Target) <= 127) bcc Target .else bcs *+5 jmp Target .endif .endmacro .macro jvs Target .if .match(Target, 0) bvc *+5 jmp Target .elseif .def(Target) .and .const((*-2)-(Target)) .and ((*+2)-(Target) <= 127) bvs Target .else bvc *+5 jmp Target .endif .endmacro .macro jvc Target .if .match(Target, 0) bvs *+5 jmp Target .elseif .def(Target) .and .const((*-2)-(Target)) .and ((*+2)-(Target) <= 127) bvc Target .else bvs *+5 jmp Target .endif .endmacro cc65-2.18/asminc/lynx.inc000066400000000000000000000132001347360151100151400ustar00rootroot00000000000000; Lynx system hardware includes ; Shawn Jefferson ; June 18th, 2004 ; ; Reference: ; Bastian Schick's Lynx Documentation ; http://www.geocities.ws/SiliconValley/Byte/4242/lynx/ ; ; *** ; *** Suzy Addresses ; *** ; Sprite Control Block TMPADRL = $FC00 TMPADRH = $FC01 TILTACUML = $FC02 TILTACUMH = $FC03 HOFFL = $FC04 HOFFH = $FC05 VOFFL = $FC06 VOFFH = $FC07 VIDBASL = $FC08 VIDBASH = $FC09 COLLBASL = $FC0A COLLBASH = $FC0B VIDADRL = $FC0C VIDADRH = $FC0D COLLADRL = $FC0E COLLADRH = $FC0F SCBNEXTL = $FC10 SCBNEXTH = $FC11 SPRDLINEL = $FC12 SPRDLINEH = $FC13 HPOSSTRTL = $FC14 HPOSSTRTH = $FC15 VPOSSTRTL = $FC16 VPOSSTRTH = $FC17 SPRHSIZL = $FC18 SPRHSIZH = $FC19 SPRVSIZL = $FC1A SPRVSIZH = $FC1B STRETCHL = $FC1C STRETCHH = $FC1D TILTL = $FC1E TILTH = $FC1F SPRDOFFL = $FC20 SPRDOFFH = $FC21 SPRVPOSL = $FC22 SPRVPOSH = $FC23 COLLOFFL = $FC24 COLLOFFH = $FC25 VSIZACUML = $FC26 VSIZACUMH = $FC27 HSIZOFFL = $FC28 HSIZOFFH = $FC29 VSIZOFFL = $FC2A VSIZOFFH = $FC2B SCBADRL = $FC2C SCBADRH = $FC2D PROCADRL = $FC2E PROCADRH = $FC2F ; Suzy Math MATHD = $FC52 MATHC = $FC53 MATHB = $FC54 MATHA = $FC55 MATHP = $FC56 MATHN = $FC57 MATHH = $FC60 MATHG = $FC61 MATHF = $FC62 MATHE = $FC63 MATHM = $FC6C MATHL = $FC6D MATHK = $FC6E MATHJ = $FC6F ; Suzy Misc SPRCTL0 = $FC80 SPRCTL1 = $FC81 SPRCOLL = $FC82 SPRINIT = $FC83 SUZYHREV = $FC88 SUZYSREV = $FC89 SUZYBUSEN = $FC90 SPRGO = $FC91 SPRSYS = $FC92 JOYSTICK = $FCB0 SWITCHES = $FCB1 RCART0 = $FCB2 RCART1 = $FCB3 LEDS = $FCC0 PARSTATUS = $FCC2 PARDATA = $FCC3 HOWIE = $FCC4 ; *** ; *** Mikey Addresses ; *** ; Mikey Timers TIMER0 = $FD00 TIMER1 = $FD04 TIMER2 = $FD08 TIMER3 = $FD0C TIMER4 = $FD10 TIMER5 = $FD14 TIMER6 = $FD18 TIMER7 = $FD1C HTIMER = $FD00 ; horizontal line timer (timer 0) VTIMER = $FD08 ; vertical blank timer (timer 2) STIMER = $FD1C ; sound timer (timer 7) HTIMBKUP = $FD00 ; horizontal line timer (timer 0) HTIMCTLA = $FD01 HTIMCNT = $FD02 HTIMCTLB = $FD03 VTIMBKUP = $FD08 ; vertical blank timer (timer 2) VTIMCTLA = $FD09 VTIMCNT = $FD0A VTIMCTLB = $FD0B BAUDBKUP = $FD10 ; serial timer (timer 4) STIMBKUP = $FD1C ; sound timer (timer 7) STIMCTLA = $FD1D STIMCNT = $FD1E STIMCTLB = $FD1F TIM0BKUP = $FD00 TIM0CTLA = $FD01 TIM0CNT = $FD02 TIM0CTLB = $FD03 TIM1BKUP = $FD04 TIM1CTLA = $FD05 TIM1CNT = $FD06 TIM1CTLB = $FD07 TIM2BKUP = $FD08 TIM2CTLA = $FD09 TIM2CNT = $FD0A TIM2CTLB = $FD0B TIM3BKUP = $FD0C TIM3CTLA = $FD0D TIM3CNT = $FD0E TIM3CTLB = $FD0F TIM4BKUP = $FD10 TIM4CTLA = $FD11 TIM4CNT = $FD12 TIM4CTLB = $FD13 TIM5BKUP = $FD14 TIM5CTLA = $FD15 TIM5CNT = $FD16 TIM5CTLB = $FD17 TIM6BKUP = $FD18 TIM6CTLA = $FD19 TIM6CNT = $FD1A TIM6CTLB = $FD1B TIM7BKUP = $FD1C TIM7CTLA = $FD1D TIM7CNT = $FD1E TIM7CTLB = $FD1F ; Mikey Audio AUDIO0 = $FD20 ; audio channel 0 AUDIO1 = $FD28 ; audio channel 1 AUDIO2 = $FD30 ; audio channel 2 AUDIO3 = $FD38 ; audio channel 3 AUD0VOL = $FD20 AUD0FEED = $FD21 AUD0OUT = $FD22 AUD0SHIFT = $FD23 AUD0BKUP = $FD24 AUD0CTLA = $FD25 AUD0CNT = $FD26 AUD0CTLB = $FD27 AUD1VOL = $FD28 AUD1FEED = $FD29 AUD1OUT = $FD2A AUD1SHIFT = $FD2B AUD1BKUP = $FD2C AUD1CTLA = $FD2D AUD1CNT = $FD2E AUD1CTLB = $FD2F AUD2VOL = $FD30 AUD2FEED = $FD31 AUD2OUT = $FD32 AUD2SHIFT = $FD33 AUD2BKUP = $FD34 AUD2CTLA = $FD35 AUD2CNT = $FD36 AUD2CTLB = $FD37 AUD3VOL = $FD38 AUD3FEED = $FD39 AUD3OUT = $FD3A AUD3SHIFT = $FD3B AUD3BKUP = $FD3C AUD3CTLA = $FD3D AUD3CNT = $FD3E AUD3CTLB = $FD3F MSTEREO = $FD50 ; Mikey Misc ; Interrupt bits in INTRST and INTSET TIMER0_INTERRUPT = $01 TIMER1_INTERRUPT = $02 TIMER2_INTERRUPT = $04 TIMER3_INTERRUPT = $08 TIMER4_INTERRUPT = $10 TIMER5_INTERRUPT = $20 TIMER6_INTERRUPT = $40 TIMER7_INTERRUPT = $80 HBL_INTERRUPT = TIMER0_INTERRUPT VBL_INTERRUPT = TIMER2_INTERRUPT SERIAL_INTERRUPT = TIMER4_INTERRUPT SND_INTERRUPT = TIMER7_INTERRUPT INTRST = $FD80 INTSET = $FD81 MAGRDY0 = $FD84 MAGRDY1 = $FD85 AUDIN = $FD86 SYSCTL1 = $FD87 MIKEYHREV = $FD88 MIKEYSREV = $FD89 IODIR = $FD8A IODAT = $FD8B TxIntEnable = %10000000 RxIntEnable = %01000000 TxParEnable = %00010000 ResetErr = %00001000 TxOpenColl = %00000100 TxBreak = %00000010 ParEven = %00000001 TxReady = %10000000 RxReady = %01000000 TxEmpty = %00100000 RxParityErr = %00010000 RxOverrun = %00001000 RxFrameErr = %00000100 RxBreak = %00000010 ParityBit = %00000001 SERCTL = $FD8C SERDAT = $FD8D SDONEACK = $FD90 CPUSLEEP = $FD91 DISPCTL = $FD92 PBKUP = $FD93 DISPADRL = $FD94 DISPADRH = $FD95 MTEST0 = $FD9C MTEST1 = $FD9D MTEST2 = $FD9E PALETTE = $FDA0 ; hardware rgb palette GCOLMAP = $FDA0 ; hardware rgb palette (green) RBCOLMAP = $FDB0 ; hardware rgb palette (red-blue) ; *** ; *** Misc Hardware + 6502 vectors ; *** MAPCTL = $FFF9 VECTORS = $FFFB INTVECTL = $FFFE INTVECTH = $FFFF RSTVECTL = $FFFC RSTVECTH = $FFFD NMIVECTL = $FFFA NMIVECTH = $FFFB cc65-2.18/asminc/modload.inc000066400000000000000000000076641347360151100156060ustar00rootroot00000000000000;*****************************************************************************/ ;* */ ;* modload.inc */ ;* */ ;* o65 module loader interface for cc65 */ ;* */ ;* */ ;* */ ;* (C) 2002 Ullrich von Bassewitz */ ;* Wacholderweg 14 */ ;* D-70597 Stuttgart */ ;* EMail: uz@musoftware.de */ ;* */ ;* */ ;* 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. */ ;* */ ;*****************************************************************************/ ; Exports structures and functions to load relocatable o65 modules at ; runtime. ; Offsets for the mod_ctrl struct. This struct is passed to the module loader. ; It contains stuff, the loader needs to work, and another area where the ; loader will place informational data if it was successful. You will have to ; check the return code of mod_load before accessing any of these additional ; struct members. .struct MOD_CTRL READ .addr CALLERDATA .word MODULE .addr ; Pointer to module data MODULE_SIZE .word ; Total size of loaded module MODULE_ID .word .endstruct ; unsigned char mod_load (struct mod_ctrl* ctrl); ; /* Load a module into memory and relocate it. The function will return an ; * error code (see below). If MLOAD_OK is returned, the outgoing fields in ; * the passed mod_ctrl struct contain information about the module just ; * loaded. ; */ .global _mod_load ; void mod_free (void* module); ; /* Free a loaded module. Note: The given pointer is the pointer to the ; * module memory, not a pointer to a control structure. ; */ .global _mod_free ; Errors .enum MLOAD_OK ; Module load successful MLOAD_ERR_READ ; Read error MLOAD_ERR_HDR ; Header error MLOAD_ERR_OS ; Wrong OS MLOAD_ERR_FMT ; Data format error MLOAD_ERR_MEM ; Not enough memory .endenum cc65-2.18/asminc/module.mac000066400000000000000000000004261347360151100154300ustar00rootroot00000000000000.ifndef DYN_DRV DYN_DRV = 1 .endif .macro module_header module_label .if DYN_DRV .segment "HEADER" .else .data .export module_label module_label: .endif .endmacro cc65-2.18/asminc/mouse-kernel.inc000066400000000000000000000170241347360151100165640ustar00rootroot00000000000000;/*****************************************************************************/ ;/* */ ;/* mouse-kernel.inc */ ;/* */ ;/* Mouse API */ ;/* */ ;/* */ ;/* */ ;/* (C) 2003-2009, Ullrich von Bassewitz */ ;/* Roemerstrasse 52 */ ;/* D-70794 Filderstadt */ ;/* EMail: uz@cc65.org */ ;/* */ ;/* */ ;/* */ ;/* */ ;/* This software is provided 'as-is', without any expressed or implied */ ;/* warranty. In no event will the authors be held liable for any damages */ ;/* arising from the use of this software. */ ;/* */ ;/* Permission is granted to anyone to use this software for any purpose, */ ;/* including commercial applications, and to alter it and redistribute it */ ;/* freely, subject to the following restrictions: */ ;/* */ ;/* 1. The origin of this software must not be misrepresented; you must not */ ;/* claim that you wrote the original software. If you use this software */ ;/* in a product, an acknowledgment in the product documentation would be */ ;/* appreciated but is not required. */ ;/* 2. Altered source versions must be plainly marked as such, and must not */ ;/* be misrepresented as being the original software. */ ;/* 3. This notice may not be removed or altered from any source */ ;/* distribution. */ ;/* */ ;/*****************************************************************************/ ;------------------------------------------------------------------------------ ; Error codes .enum MOUSE_ERR_OK ; No error MOUSE_ERR_NO_DRIVER ; No driver available MOUSE_ERR_CANNOT_LOAD ; Error loading driver MOUSE_ERR_INV_DRIVER ; Invalid driver MOUSE_ERR_NO_DEVICE ; Mouse hardware not found MOUSE_ERR_INV_IOCTL ; Invalid ioctl code MOUSE_ERR_COUNT ; Special: Number of error codes .endenum ;------------------------------------------------------------------------------ ; The driver header .struct MOUSE_HDR ID .byte 3 ; Contains 0x6D, 0x6F, 0x75 ("mou") VERSION .byte 1 ; Interface version LIBREF .addr ; Library reference JUMPTAB .struct INSTALL .addr UNINSTALL .addr HIDE .addr SHOW .addr SETBOX .addr GETBOX .addr MOVE .addr BUTTONS .addr POS .addr INFO .addr IOCTL .addr IRQ .addr .endstruct FLAGS .byte ; Mouse driver flags CALLBACKS .struct ; Jump instructions .byte ; JMP opcode CHIDE .addr ; Jump address .byte CSHOW .addr .byte CPREP .addr .byte CDRAW .addr .byte CMOVEX .addr .byte CMOVEY .addr .endstruct .endstruct ;------------------------------------------------------------------------------ ; The mouse callback structure .struct MOUSE_CALLBACKS HIDE .addr ; Hide the mouse cursor SHOW .addr ; Show the mouse cursor PREP .addr ; Prepare to move the mouse cursor DRAW .addr ; Draw the mouse cursor MOVEX .addr ; Move the mouse cursor to X coord MOVEY .addr ; Move the mouse cursor to Y coord .endstruct ;------------------------------------------------------------------------------ ; The mouse API version, stored in MOUSE_HDR::VERSION MOUSE_API_VERSION = $06 ;------------------------------------------------------------------------------ ; Bitmapped mouse driver flags, stored in MOUSE_HDR::FLAGS. ; Note: If neither of MOUSE_FLAG_XXX_IRQ is set, no interrupts are supplied ; to the driver. If one of the bits is set, the interrupt vector MUST be ; valid. ; Beware: Some of the bits are tested using the BIT instruction, so do not ; change the values without checking the code! MOUSE_FLAG_EARLY_IRQ = $40 ; Enable IRQ *before* calling INSTALL MOUSE_FLAG_LATE_IRQ = $80 ; Enable IRQ *after* calling INSTALL ;------------------------------------------------------------------------------ ; Mouse button definitions MOUSE_BTN_LEFT = $10 MOUSE_BTN_RIGHT = $01 ;------------------------------------------------------------------------------ ; Structures used to return data from the mouse driver .struct MOUSE_POS XCOORD .word YCOORD .word .endstruct .struct MOUSE_INFO POS .tag MOUSE_POS BUTTONS .byte .endstruct .struct MOUSE_BOX MINX .word MINY .word MAXX .word MAXY .word .endstruct ;------------------------------------------------------------------------------ ; Variables .global _mouse_drv ; Pointer to driver .global _mouse_hidden ; Counter, 0 = mouse is visible ;------------------------------------------------------------------------------ ; C callable functions .global _mouse_load_driver .global _mouse_unload .global _mouse_install .global _mouse_uninstall .global _mouse_geterrormsg .global _mouse_hide .global _mouse_show .global _mouse_setbox .global _mouse_getbox .global _mouse_move .global _mouse_buttons .global _mouse_pos .global _mouse_info .global _mouse_ioctl .global _mouse_clear_ptr ;------------------------------------------------------------------------------ ; Driver entry points (asm callable) .global mouse_install .global mouse_uninstall .global mouse_hide .global mouse_show .global mouse_setbox .global mouse_getbox .global mouse_move .global mouse_buttons .global mouse_pos .global mouse_info .global mouse_ioctl cc65-2.18/asminc/nes.inc000066400000000000000000000053661347360151100147510ustar00rootroot00000000000000; ; NES definitions. By Groepaz/Hitmem. ; ;; FIXME: optimize zeropage usage SCREEN_PTR = $62 ;2 CRAM_PTR = $64 ;2 CHARCOLOR = $66 BGCOLOR = $67 RVS = $68 CURS_X = $69 CURS_Y = $6a tickcount = $6b ;2 VBLANK_FLAG = $70 ringbuff = $0200 ringwrite = $71 ringread = $72 ringcount = $73 ppuhi = $74 ppulo = $75 ppuval = $76 screenrows = (30-1) charsperline = 32 xsize = charsperline ;; PPU defines PPU_CTRL1 = $2000 PPU_CTRL2 = $2001 PPU_STATUS = $2002 PPU_SPR_ADDR = $2003 PPU_SPR_IO = $2004 PPU_VRAM_ADDR1 = $2005 PPU_VRAM_ADDR2 = $2006 PPU_VRAM_IO = $2007 ;; APU defines APU_PULSE1CTRL = $4000 ; Pulse #1 Control Register (W) APU_PULSE1RAMP = $4001 ; Pulse #1 Ramp Control Register (W) APU_PULSE1FTUNE = $4002 ; Pulse #1 Fine Tune (FT) Register (W) APU_PULSE1CTUNE = $4003 ; Pulse #1 Coarse Tune (CT) Register (W) APU_PULSE2CTRL = $4004 ; Pulse #2 Control Register (W) APU_PULSE2RAMP = $4005 ; Pulse #2 Ramp Control Register (W) APU_PULSE2FTUNE = $4006 ; Pulse #2 Fine Tune Register (W) APU_PULSE2STUNE = $4007 ; Pulse #2 Coarse Tune Register (W) APU_TRICTRL1 = $4008 ; Triangle Control Register #1 (W) APU_TRICTRL2 = $4009 ; Triangle Control Register #2 (?) APU_TRIFREQ1 = $400A ; Triangle Frequency Register #1 (W) APU_TRIFREQ2 = $400B ; Triangle Frequency Register #2 (W) APU_NOISECTRL = $400C ; Noise Control Register #1 (W) ;;APU_ = $400D ; Unused (???) APU_NOISEFREQ1 = $400E ; Noise Frequency Register #1 (W) APU_NOISEFREQ2 = $400F ; Noise Frequency Register #2 (W) APU_MODCTRL = $4010 ; Delta Modulation Control Register (W) APU_MODDA = $4011 ; Delta Modulation D/A Register (W) APU_MODADDR = $4012 ; Delta Modulation Address Register (W) APU_MODLEN = $4013 ; Delta Modulation Data Length Register (W) APU_SPR_DMA = $4014 ; Sprite DMA Register (W) APU_CHANCTRL = $4015 ; Sound/Vertical Clock Signal Register (R) APU_PAD1 = $4016 ; Joypad #1 (RW) APU_PAD2 = $4017 ; Joypad #2/SOFTCLK (RW) CH_HLINE = 11 CH_VLINE = 14 CH_ULCORNER = 176 CH_URCORNER = 174 CH_LLCORNER = 173 CH_LRCORNER = 189 CH_TTEE = 178 CH_RTEE = 179 CH_BTEE = 177 CH_LTEE = 171 CH_CROSS = 123 CH_CURS_UP = 145 CH_CURS_DOWN = 17 CH_CURS_LEFT = 157 CH_CURS_RIGHT = 29 CH_PI = 126 CH_DEL = 20 CH_INS = 148 CH_ENTER = 10 CH_STOP = 3 CH_ESC = 27 cc65-2.18/asminc/o65.inc000066400000000000000000000163451347360151100145740ustar00rootroot00000000000000;*****************************************************************************/ ;* */ ;* o65.inc */ ;* */ ;* Definitions for the o65 file format */ ;* */ ;* */ ;* */ ;* (C) 2002-2009, Ullrich von Bassewitz */ ;* Roemerstrasse 52 */ ;* D-70794 Filderstadt */ ;* EMail: uz@cc65.org */ ;* */ ;* */ ;* This software is provided 'as-is', without any expressed or implied */ ;* warranty. In no event will the authors be held liable for any damages */ ;* arising from the use of this software. */ ;* */ ;* Permission is granted to anyone to use this software for any purpose, */ ;* including commercial applications, and to alter it and redistribute it */ ;* freely, subject to the following restrictions: */ ;* */ ;* 1. The origin of this software must not be misrepresented; you must not */ ;* claim that you wrote the original software. If you use this software */ ;* in a product, an acknowledgment in the product documentation would be */ ;* appreciated but is not required. */ ;* 2. Altered source versions must be plainly marked as such, and must not */ ;* be misrepresented as being the original software. */ ;* 3. This notice may not be removed or altered from any source */ ;* distribution. */ ;* */ ;*****************************************************************************/ ; This files exports structures and constants to handle the o65 relocatable ; file format as defined by Andre Fachat. ; The o65 header structure (6502 format) .struct O65_HDR MARKER .byte 2 ; Non-C64 marker: $01 $00 MAGIC .byte 3 ; o65 magic: "o65" VERSION .byte 1 ; Version number MODE .word ; Mode word TBASE .word ; Original text (code) segment address TLEN .word ; Size of text (code) segment DBASE .word ; Original data segment address DLEN .word ; Size of data segment BBASE .word ; Original bss segment address BLEN .word ; Size of bss segment ZBASE .word ; Original zp segment address ZLEN .word ; Size of zp segment STACK .word ; Stacksize needed .endstruct ; Marker, magic and version number O65_MARKER_0 = $01 O65_MARKER_1 = $00 O65_MAGIC_0 = $6F ; 'o' O65_MAGIC_1 = $36 ; '6' O65_MAGIC_2 = $35 ; '5' O65_VERSION = $00 ; Defines for the mode word O65_CPU_65816 = $8000 ; Executable is for 65816 O65_CPU_6502 = $0000 ; Executable is for the 6502 O65_CPU_MASK = $8000 ; Mask to extract CPU type O65_RELOC_PAGE = $4000 ; Page wise relocation O65_RELOC_BYTE = $0000 ; Byte wise relocation O65_RELOC_MASK = $4000 ; Mask to extract relocation type O65_SIZE_32BIT = $2000 ; All size words are 32bit O65_SIZE_16BIT = $0000 ; All size words are 16bit O65_SIZE_MASK = $2000 ; Mask to extract size O65_FTYPE_OBJ = $1000 ; Object file O65_FTYPE_EXE = $0000 ; Executable file O65_FTYPE_MASK = $1000 ; Mask to extract type O65_ADDR_SIMPLE = $0800 ; Simple addressing O65_ADDR_DEFAULT = $0000 ; Default addressing O65_ADDR_MASK = $0800 ; Mask to extract addressing O65_CHAIN = $0400 ; Chained file, another one follows O65_CHAIN_MASK = $0400 ; Mask to extract chain flag O65_BSSZERO = $0200 ; BSS segment must be zeroed O65_BSSZERO_MASK = $0200 ; Mask to extract bss zero flag ; The following is used if O65_CPU == 6502 O65_CPU2_6502 = $0000 ; Executable is for 6502 O65_CPU2_65C02 = $0010 ; Executable is for 65C02 O65_CPU2_65SC02 = $0020 ; Executable is for 65SC02 O65_CPU2_65CE02 = $0030 ; Executable is for 65CE02 O65_CPU2_6502X = $0040 ; Executable is for NMOS 6502 O65_CPU2_65816_EMU = $0050 ; Executable is for 65816 in emul mode O65_CPU2_MASK = $00F0 ; Mask to extract CPU2 field O65_ALIGN_1 = $0000 ; Bytewise alignment O65_ALIGN_2 = $0001 ; Align words O65_ALIGN_4 = $0002 ; Align longwords O65_ALIGN_256 = $0003 ; Align pages (256 bytes) O65_ALIGN_MASK = $0003 ; Mask to extract alignment ; The mode word as generated by the ld65 linker O65_MODE_CC65 = O65_CPU_6502 | O65_RELOC_BYTE | O65_SIZE_16BIT | O65_FTYPE_EXE | O65_ADDR_SIMPLE | O65_ALIGN_1 ; Relocation type codes O65_RTYPE_WORD = $80 O65_RTYPE_HIGH = $40 O65_RTYPE_LOW = $20 O65_RTYPE_SEGADDR = $C0 O65_RTYPE_SEG = $A0 O65_RTYPE_MASK = $E0 ; Segment IDs O65_SEGID_UNDEF = $00 O65_SEGID_ABS = $01 O65_SEGID_TEXT = $02 O65_SEGID_DATA = $03 O65_SEGID_BSS = $04 O65_SEGID_ZP = $05 O65_SEGID_MASK = $07 ; Option tags O65_OPT_FILENAME = 0 O65_OPT_OS = 1 O65_OPT_ASM = 2 O65_OPT_AUTHOR = 3 O65_OPT_TIMESTAMP = 4 ; Operating system codes for O65_OPT_OS O65_OS_OSA65 = 1 O65_OS_LUNIX = 2 O65_OS_CC65 = 3 O65_OS_OPENCBM = 4 ; Load errors O65_LOAD_OK = 0 ; Module load successful O65_LOAD_ERR_READ = 1 ; Read error O65_LOAD_ERR_HDR = 2 ; Header error O65_LOAD_ERR_OS = 3 ; Wrong OS O65_LOAD_ERR_FMT = 4 ; Data format error O65_LOAD_ERR_MEM = 5 ; Not enough memory cc65-2.18/asminc/opcodes.inc000066400000000000000000000264461347360151100156220ustar00rootroot00000000000000; opcodes.inc ; ca65 6502 - opcode definitions, mainly for self modifying code ; ; Christian Krüger, latest change: 18-Sep-2010 ; ; This software is provided 'as-is', without any expressed or implied ; warranty. In no event will the authors be held liable for any damages ; arising from the use of this software. ; ; Permission is granted to anyone to use this software for any purpose, ; including commercial applications, and to alter it and redistribute it ; freely, subject to the following restrictions: ; ; 1. The origin of this software must not be misrepresented; you must not ; claim that you wrote the original software. If you use this software ; in a product, an acknowledgment in the product documentation would be ; appreciated but is not required. ; 2. Altered source versions must be plainly marked as such, and must not ; be misrepresented as being the original software. ; 3. This notice may not be removed or altered from any source ; distribution. ; ; Opcode-Table ; ------------ ; Post fix explanation: ; imm = #$00 ; zp = $00 ; zpx = $00,X ; zpy = $00,Y ; izp = ($00) ; izx = ($00,X) ; izy = ($00),Y ; abs = $0000 ; abx = $0000,X ; aby = $0000,Y ; ind = ($0000) ; iax = ($0000,X) ; rel = $0000 (PC-relative) (supressed here) .macpack cpu OPC_BRK = $00 OPC_ORA_izx = $01 OPC_ORA_zp = $05 OPC_ASL_zp = $06 OPC_PHP = $08 OPC_ORA_imm = $09 OPC_ASL = $0A OPC_ORA_abs = $0D OPC_ASL_abs = $0E OPC_BPL = $10 OPC_ORA_izy = $11 OPC_ORA_zpx = $15 OPC_ASL_zpx = $16 OPC_CLC = $18 OPC_ORA_aby = $19 OPC_ORA_abx = $1D OPC_ASL_abx = $1E OPC_JSR_abs = $20 OPC_AND_izx = $21 OPC_BIT_zp = $24 OPC_AND_zp = $25 OPC_ROL_zp = $26 OPC_PLP = $28 OPC_AND_imm = $29 OPC_ROL = $2A OPC_BIT_abs = $2C OPC_AND_abs = $2D OPC_ROL_abs = $2E OPC_BMI = $30 OPC_AND_izy = $31 OPC_AND_zpx = $35 OPC_ROL_zpx = $36 OPC_SEC = $38 OPC_AND_aby = $39 OPC_AND_abx = $3D OPC_ROL_abx = $3E OPC_RTI = $40 OPC_EOR_izx = $41 OPC_EOR_zp = $45 OPC_LSR_zp = $46 OPC_PHA = $48 OPC_EOR_imm = $49 OPC_LSR = $4A OPC_JMP_abs = $4C OPC_EOR_abs = $4D OPC_LSR_abs = $4E OPC_BVC = $50 OPC_EOR_izy = $51 OPC_EOR_zpx = $55 OPC_LSR_zpx = $56 OPC_CLI = $58 OPC_EOR_aby = $59 OPC_EOR_abx = $5D OPC_LSR_abx = $5E OPC_RTS = $60 OPC_ADC_izx = $61 OPC_ADC_zp = $65 OPC_ROR_zp = $66 OPC_PLA = $68 OPC_ADC_imm = $69 OPC_ROR = $6A OPC_JMP_ind = $6C OPC_ADC_abs = $6D OPC_ROR_abs = $6E OPC_BVS = $70 OPC_ADC_izy = $71 OPC_ADC_zpx = $75 OPC_ROR_zpx = $76 OPC_SEI = $78 OPC_ADC_aby = $79 OPC_ADC_abx = $7D OPC_ROR_abx = $7E OPC_STA_izx = $81 OPC_STY_zp = $84 OPC_STA_zp = $85 OPC_STX_zp = $86 OPC_DEY = $88 OPC_TXA = $8A OPC_STY_abs = $8C OPC_STA_abs = $8D OPC_STX_abs = $8E OPC_BCC = $90 OPC_STA_izy = $91 OPC_STY_zpx = $94 OPC_STA_zpx = $95 OPC_STX_zpy = $96 OPC_TYA = $98 OPC_STA_aby = $99 OPC_TXS = $9A OPC_STA_abx = $9D OPC_LDY_imm = $A0 OPC_LDA_izx = $A1 OPC_LDX_imm = $A2 OPC_LDY_zp = $A4 OPC_LDA_zp = $A5 OPC_LDX_zp = $A6 OPC_TAY = $A8 OPC_LDA_imm = $A9 OPC_TAX = $AA OPC_LDY_abs = $AC OPC_LDA_abs = $AD OPC_LDX_abs = $AE OPC_BCS = $B0 OPC_LDA_izy = $B1 OPC_LDY_zpx = $B4 OPC_LDA_zpx = $B5 OPC_LDX_zpy = $B6 OPC_CLV = $B8 OPC_LDA_aby = $B9 OPC_TSX = $BA OPC_LDY_abx = $BC OPC_LDA_abx = $BD OPC_LDX_aby = $BE OPC_CPY_imm = $C0 OPC_CMP_izx = $C1 OPC_CPY_zp = $C4 OPC_CMP_zp = $C5 OPC_DEC_zp = $C6 OPC_INY = $C8 OPC_CMP_imm = $C9 OPC_DEX = $CA OPC_CPY_abs = $CC OPC_CMP_abs = $CD OPC_DEC_abs = $CE OPC_BNE = $D0 OPC_CMP_izy = $D1 OPC_CMP_zpx = $D5 OPC_DEC_zpx = $D6 OPC_CLD = $D8 OPC_CMP_aby = $D9 OPC_CMP_abx = $DD OPC_DEC_abx = $DE OPC_CPX_imm = $E0 OPC_SBC_izx = $E1 OPC_CPX_zp = $E4 OPC_SBC_zp = $E5 OPC_INC_zp = $E6 OPC_INX = $E8 OPC_SBC_imm = $E9 OPC_NOP = $EA OPC_CPX_abs = $EC OPC_SBC_abs = $ED OPC_INC_abs = $EE OPC_BEQ = $F0 OPC_SBC_izy = $F1 OPC_SBC_zpx = $F5 OPC_INC_zpx = $F6 OPC_SED = $F8 OPC_SBC_aby = $F9 OPC_SBC_abx = $FD OPC_INC_abx = $FE .if (.cpu .bitand ::CPU_ISET_65SC02) ; OPC_NOP = $02 ; doublet ; OPC_NOP = $03 ; doublet OPC_TSB_zp = $04 ; OPC_NOP = $0B ; doublet OPC_TSB_abs = $0C OPC_ORA_izp = $12 ; OPC_NOP = $13 ; doublet OPC_TRB_zp = $14 OPC_INC = $1A ; OPC_NOP = $1B ; doublet OPC_TRB_abs = $1C ; OPC_NOP = $22 ; doublet ; OPC_NOP = $23 ; doublet ; OPC_NOP = $2B ; doublet OPC_AND_izp = $32 ; OPC_NOP = $33 ; doublet OPC_BIT_zpx = $34 OPC_DEC = $3A ; OPC_NOP = $3B ; doublet OPC_BIT_abx = $3C ; OPC_NOP = $42 ; doublet ; OPC_NOP = $43 ; doublet ; OPC_NOP = $44 ; doublet ; OPC_NOP = $4B ; doublet OPC_EOR_izp = $52 ; OPC_NOP = $53 ; doublet ; OPC_NOP = $54 ; doublet ; OPC_NOP = $5A ; doublet ; OPC_NOP = $5B ; doublet ; OPC_NOP = $62 ; doublet ; OPC_NOP = $63 ; doublet OPC_STZ_zp = $64 ; OPC_NOP = $6B ; doublet OPC_ADC_izp = $72 ; OPC_NOP = $73 ; doublet OPC_STZ_zpx = $74 OPC_PLY = $7A ; OPC_NOP = $7B ; doublet OPC_JMP_iax = $7C OPC_BRA = $80 ; OPC_NOP = $82 ; doublet ; OPC_NOP = $83 ; doublet OPC_BIT_imm = $89 ; OPC_NOP = $8B ; doublet OPC_STA_izp = $92 ; OPC_NOP = $93 ; doublet ; OPC_NOP = $9B ; doublet OPC_STZ_abs = $9C OPC_STZ_abx = $9E ; OPC_NOP = $A3 ; doublet ; OPC_NOP = $AB ; doublet OPC_LDA_izp = $B2 ; OPC_NOP = $B3 ; doublet ; OPC_NOP = $BB ; doublet ; OPC_NOP = $C2 ; doublet ; OPC_NOP = $C3 ; doublet ; OPC_NOP = $CB ; doublet OPC_CMP_izp = $D2 ; OPC_NOP = $D3 ; doublet ; OPC_NOP = $D4 ; doublet OPC_PHX = $DA ; OPC_NOP = $DB ; doublet ; OPC_NOP = $DC ; doublet ; OPC_NOP = $E2 ; doublet ; OPC_NOP = $E3 ; doublet ; OPC_NOP = $EB ; doublet OPC_SBC_izp = $F2 ; OPC_NOP = $F3 ; doublet ; OPC_NOP = $F4 ; doublet OPC_PLX = $FA ; OPC_NOP = $FB ; doublet ; OPC_NOP = $FC ; doublet .if (.cpu .bitand ::CPU_ISET_65C02) ; bit instructions for 65C02 OPC_RMB0 = $07 OPC_RMB1 = $17 OPC_RMB2 = $27 OPC_RMB3 = $37 OPC_RMB4 = $47 OPC_RMB5 = $57 OPC_RMB6 = $67 OPC_RMB7 = $77 OPC_SMB0 = $87 OPC_SMB1 = $97 OPC_SMB2 = $A7 OPC_SMB3 = $B7 OPC_SMB4 = $C7 OPC_SMB5 = $D7 OPC_SMB6 = $E7 OPC_SMB7 = $F7 OPC_BBR0 = $0F OPC_BBR1 = $1F OPC_BBR2 = $2F OPC_BBR3 = $3F OPC_BBR4 = $4F OPC_BBR5 = $5F OPC_BBR6 = $6F OPC_BBR7 = $7F OPC_BBS0 = $8F OPC_BBS1 = $9F OPC_BBS2 = $AF OPC_BBS3 = $BF OPC_BBS4 = $CF OPC_BBS5 = $DF OPC_BBS6 = $EF OPC_BBS7 = $FF .else ; no bit instructions for 65SC02 ; OPC_NOP = $07 ; doublet ; OPC_NOP = $17 ; doublet ; OPC_NOP = $27 ; doublet ; OPC_NOP = $37 ; doublet ; OPC_NOP = $47 ; doublet ; OPC_NOP = $57 ; doublet ; OPC_NOP = $67 ; doublet ; OPC_NOP = $77 ; doublet ; OPC_NOP = $87 ; doublet ; OPC_NOP = $97 ; doublet ; OPC_NOP = $A7 ; doublet ; OPC_NOP = $B7 ; doublet ; OPC_NOP = $C7 ; doublet ; OPC_NOP = $D7 ; doublet ; OPC_NOP = $E7 ; doublet ; OPC_NOP = $F7 ; doublet ; OPC_NOP = $0F ; doublet ; OPC_NOP = $1F ; doublet ; OPC_NOP = $2F ; doublet ; OPC_NOP = $3F ; doublet ; OPC_NOP = $4F ; doublet ; OPC_NOP = $5F ; doublet ; OPC_NOP = $6F ; doublet ; OPC_NOP = $7F ; doublet ; OPC_NOP = $8F ; doublet ; OPC_NOP = $9F ; doublet ; OPC_NOP = $AF ; doublet ; OPC_NOP = $BF ; doublet ; OPC_NOP = $CF ; doublet ; OPC_NOP = $DF ; doublet ; OPC_NOP = $EF ; doublet ; OPC_NOP = $FF ; doublet .endif .elseif (.cpu .bitand ::CPU_ISET_6502X) ; stable, undocumented opcodes ; OPC_KIL = $02 ; unstable OPC_SLO_izx = $03 OPC_NOP_zp = $04 OPC_SLO_zp = $07 OPC_ANC_imm = $0B OPC_NOP_abs = $0C OPC_SLO_abs = $0F ; OPC_KIL = $12 ; unstable OPC_SLO_izy = $13 OPC_NOP_zpx = $14 OPC_SLO_zpx = $17 ;OPC_NOP = $1A OPC_SLO_aby = $1B OPC_NOP_abx = $1C OPC_SLO_abx = $1F ; OPC_KIL = $22 ; unstable OPC_RLA_izx = $23 OPC_RLA_zp = $27 OPC_ANC_imm = $2B OPC_RLA_abs = $2F ; OPC_KIL = $32 ; unstable OPC_RLA_izy = $33 OPC_NOP_zpx = $34 OPC_RLA_zpx = $37 ; OPC_NOP = $3A ; doublet OPC_RLA_aby = $3B OPC_NOP_abx = $3C OPC_RLA_abx = $3F ; OPC_KIL = $42 ; unstable OPC_SRE_izx = $43 OPC_NOP_zp = $44 OPC_SRE_zp = $47 OPC_ALR_imm = $4B OPC_SRE_abs = $4F ; OPC_KIL = $52 ; unstable OPC_SRE_izy = $53 OPC_NOP_zpx = $54 OPC_SRE_zpx = $57 ; OPC_NOP = $5A ; doublet OPC_SRE_aby = $5B OPC_NOP_abx = $5C OPC_SRE_abx = $5F ; OPC_KIL = $62 OPC_RRA_izx = $63 OPC_NOP_zp = $64 OPC_RRA_zp = $67 OPC_ARR_imm = $6B OPC_RRA_abs = $6F ; OPC_KIL = $72 OPC_RRA_izy = $73 OPC_NOP_zpx = $74 OPC_RRA_zpx = $77 ; OPC_NOP = $7A ; doublet OPC_RRA_aby = $7B OPC_NOP_abx = $7C OPC_RRA_abx = $7F OPC_NOP_imm = $80 ; OPC_NOP_imm = $82 ; doublet OPC_SAX_izx = $83 OPC_SAX_zp = $87 ; OPC_NOP_imm = $89 ; doublet ; OPC_XAA = $8B ; unstable OPC_SAX_abs = $8F ; OPC_KIL = $92 ; unstable ; OPC_AHX_izy = $93 ; unstable OPC_SAX_zpy = $97 ; OPC_TAS_aby = $9B ; unstable ; OPC_SHY_abx = $9C ; unstable ; OPC_SHX_aby = $9E ; unstable ; OPC_AHX_aby = $9F ; unstable OPC_LAX_izx = $A3 OPC_LAX_zp = $A7 ; OPC_LAX_imm = $AB ; unstable OPC_LAX_abs = $AF ; OPC_KIL = $B2 ; unstable OPC_LAX_izy = $B3 OPC_LAX_zpy = $B7 OPC_LAS_aby = $BB OPC_LAX_aby = $BF ; OPC_NOP_imm = $C2 ; doublet OPC_DCP_izx = $C3 OPC_DCP_zp = $C7 OPC_AXS_imm = $CB OPC_DCP_abs = $CF ; OPC_KIL = $D2 ; unstable OPC_DCP_izy = $D3 OPC_NOP_zpx = $D4 OPC_DCP_zpx = $D7 OPC_NOP_DA = $DA OPC_DCP_aby = $DB OPC_NOP_abx = $DC OPC_DCP_abx = $DF ; OPC_NOP_imm = $E2 ; doublet OPC_ISC_izx = $E3 OPC_ISC_zp = $E7 ; OPC_SBC_imm = $EB ; doublet OPC_ISC_abs = $EF ; OPC_KIL = $F2 ; unstable OPC_ISC_izy = $F3 OPC_NOP_zpx = $F4 OPC_ISC_zpx = $F7 OPC_NOP_FA = $FA OPC_ISC_aby = $FB OPC_NOP_abx = $FC OPC_ISC_abx = $FF .endif cc65-2.18/asminc/pce.inc000066400000000000000000000055651347360151100147340ustar00rootroot00000000000000; ; PCE definitions. By Groepaz/Hitmen. ; ; FIXME: Screen dimensions can change according to the 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 VDC_VRR = 2 ; VRAM Read Register 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_VSR = 12 ; Vertical sync Register VDC_VDR = 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: The zero-page addressing mode is redirected to page $20. ; We avoid it by using mirror locations that are outside of the zero page. VDC_CTRL := $0200 VDC_DATA_LO := $0202 VDC_DATA_HI := $0203 ; HuC6260 -- Video Color Encoder (VCE) ; The DAC has a palette of 512 colours. ; The bitmap of that data is 0000000gggrrrbbb (Green, Red, Blue). ; 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 to a VDC register. .macro VREG arg1, arg2 st0 #arg1 st1 #<(arg2) st2 #>(arg2) .endmacro cc65-2.18/asminc/pet.inc000066400000000000000000000060461347360151100147500ustar00rootroot00000000000000; ; PET generic definitions. ; ; --------------------------------------------------------------------------- ; 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 KEY_COUNT := $9E ; Number of keys in input buffer RVS := $9F ; Reverse flag CURS_FLAG := $A7 ; 1 = cursor off CURS_BLINK := $A8 ; Blink counter CURS_CHAR := $A9 ; Character under the cursor CURS_STATE := $AA ; Cursor blink state SCREEN_PTR := $C4 ; Pointer to current char in text screen CURS_X := $C6 ; Cursor column FNLEN := $D1 ; Length of filename LFN := $D2 ; Current Logical File Number SECADR := $D3 ; Secondary address DEVNUM := $D4 ; Device number SCR_LINELEN := $D5 ; Screen line length CURS_Y := $D8 ; Cursor row FNADR := $DA ; Pointer to file name ; 80-Column CBMs KBDREPEAT80 := $E4 KBDRPTRATE80 := $E5 KBDRPTDELAY80 := $E6 BASIC_BUF := $200 ; Location of command-line BASIC_BUF_LEN = 81 ; Maximum length of command-line KEY_BUF := $26F ; Keyboard buffer ; 40-Column PETs/CBMs KBDRPTDELAY40 := $3E9 KBDRPTRATE40 := $3EA KBDREPEAT40 := $3EE KBDREPEAT40B := $3F8 ;---------------------------------------------------------------------------- ; PET ROM type detection PET_DETECT := $FFFB PET_2000 = $CA PET_3000 = $FC PET_4000 = $FD ;---------------------------------------------------------------------------- ; Vector and other locations IRQVec := $0090 BRKVec := $0092 NMIVec := $0094 ; --------------------------------------------------------------------------- ; I/O: 6522 VIA2 VIA := $E840 ; VIA base address VIA_PB := VIA+$0 ; Port register B VIA_PA1 := VIA+$1 ; Port register A VIA_PRB := VIA+$0 ; *** Deprecated *** VIA_PRA := VIA+$1 ; *** Deprecated *** VIA_DDRB := VIA+$2 ; Data direction register B VIA_DDRA := VIA+$3 ; Data direction register A VIA_T1CL := VIA+$4 ; Timer 1, low byte VIA_T1CH := VIA+$5 ; Timer 1, high byte VIA_T1LL := VIA+$6 ; Timer 1 latch, low byte VIA_T1LH := VIA+$7 ; Timer 1 latch, high byte VIA_T2CL := VIA+$8 ; Timer 2, low byte VIA_T2CH := VIA+$9 ; Timer 2, high byte VIA_SR := VIA+$A ; Shift register VIA_CR := VIA+$B ; Auxiliary control register VIA_PCR := VIA+$C ; Peripheral control register VIA_IFR := VIA+$D ; Interrupt flag register VIA_IER := VIA+$E ; Interrupt enable register VIA_PA2 := VIA+$F ; Port register A w/o handshake cc65-2.18/asminc/plus4.inc000066400000000000000000000053151347360151100152250ustar00rootroot00000000000000; ; Plus/4 generic definitions. ; ; --------------------------------------------------------------------------- ; 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 LFN := $AC ; Logical file number SECADR := $AD ; Secondary address DEVNUM := $AE ; Device number FNAM := $AF ; Pointer to filename for OPEN KEY_COUNT := $EF ; Number of keys in input buffer RVS := $C2 ; Reverse flag CURS_X := $CA ; Cursor column CURS_Y := $CD ; Cursor row SCREEN_PTR := $C8 ; Pointer to current char in text screen CRAM_PTR := $EA ; Pointer to current char in color RAM BASIC_BUF := $200 ; Location of command-line BASIC_BUF_LEN = 89 ; Maximum length of command-line FNBUF := $25E ; Buffer for filename FETCH := $494 ; lda (zp),y from RAM CHARCOLOR := $53B FKEY_COUNT := $55D ; Characters for function key FKEY_SPACE := $55F ; Function key definitions FKEY_ORIG := $F3D2 ; Original definitions KBDREPEAT := $540 KBDREPEATRATE := $541 KBDREPEATDELAY := $542 ; --------------------------------------------------------------------------- ; Vector and other locations IRQVec := $0314 BRKVec := $0316 NMIVec := $0318 ; --------------------------------------------------------------------------- ; Screen size XSIZE = 40 YSIZE = 25 ; --------------------------------------------------------------------------- ; I/O TED_T1LO := $FF00 TED_T1HI := $FF01 TED_T2LO := $FF02 TED_T2HI := $FF03 TED_T3LO := $FF04 TED_T4HI := $FF05 TED_MULTI1 := $FF07 TED_KBD := $FF08 TED_CURSHI := $FF0C TED_CURSLO := $FF0D TED_V1FRQLO := $FF0E TED_V2FRQLO := $FF0F TED_V2FRQHI := $FF10 TED_CLK := $FF13 TED_BGCOLOR := $FF15 TED_COLOR1 := $FF16 TED_COLOR2 := $FF17 TED_COLOR3 := $FF18 TED_BORDERCOLOR := $FF19 TED_VLINEHI := $FF1C TED_VLINELO := $FF1D TED_HPOS := $FF1E TED_ROMSEL := $FF3E TED_RAMSEL := $FF3F ; --------------------------------------------------------------------------- ; RAM/ROM selection addresses ENABLE_ROM := TED_ROMSEL ENABLE_RAM := TED_RAMSEL cc65-2.18/asminc/ser-error.inc000066400000000000000000000065641347360151100161050ustar00rootroot00000000000000;**************************************************************************** ;* * ;* ser-error.inc * ;* * ;* Serial communication API * ;* * ;* * ;* * ;* (C) 2003-2012, Ullrich von Bassewitz * ;* Roemerstrasse 52 * ;* D-70794 Filderstadt * ;* EMail: uz@cc65.org * ;* * ;* * ;*This software is provided 'as-is', without any expressed or implied * ;*warranty. In no event will the authors be held liable for any damages * ;*arising from the use of this software. * ;* * ;*Permission is granted to anyone to use this software for any purpose, * ;*including commercial applications, and to alter it and redistribute it * ;*freely, subject to the following restrictions: * ;* * ;*1. The origin of this software must not be misrepresented; you must not * ;* claim that you wrote the original software. If you use this software * ;* in a product, an acknowledgment in the product documentation would be * ;* appreciated but is not required. * ;*2. Altered source versions must be plainly marked as such, and must not * ;* be misrepresented as being the original software. * ;*3. This notice may not be removed or altered from any source * ;* distribution. * ;* * ;**************************************************************************** ;------------------------------------------------------------------------------ ; Error codes .enum SER_ERR_OK ; Not an error - relax SER_ERR_NO_DRIVER ; No driver available SER_ERR_CANNOT_LOAD ; Error loading driver SER_ERR_INV_DRIVER ; Invalid driver SER_ERR_NO_DEVICE ; Device (hardware) not found SER_ERR_BAUD_UNAVAIL ; Baud rate not available SER_ERR_NO_DATA ; Nothing to read SER_ERR_OVERFLOW ; No room in send buffer SER_ERR_INIT_FAILED ; Initialization failed SER_ERR_INV_IOCTL ; IOCTL not supported SER_ERR_INSTALLED ; A driver is already installed SER_ERR_NOT_OPEN ; Driver not open SER_ERR_COUNT ; Special: Number of error codes .endenum cc65-2.18/asminc/ser-kernel.inc000066400000000000000000000151741347360151100162310ustar00rootroot00000000000000;**************************************************************************** ;* * ;* ser-kernel.inc * ;* * ;* Serial communication API * ;* * ;* * ;* * ;*(C) 2003-2006, Ullrich von Bassewitz * ;* Römerstrasse 52 * ;* D-70794 Filderstadt * ;*EMail: uz@cc65.org * ;* * ;* * ;*This software is provided 'as-is', without any expressed or implied * ;*warranty. In no event will the authors be held liable for any damages * ;*arising from the use of this software. * ;* * ;*Permission is granted to anyone to use this software for any purpose, * ;*including commercial applications, and to alter it and redistribute it * ;*freely, subject to the following restrictions: * ;* * ;*1. The origin of this software must not be misrepresented; you must not * ;* claim that you wrote the original software. If you use this software * ;* in a product, an acknowledgment in the product documentation would be * ;* appreciated but is not required. * ;*2. Altered source versions must be plainly marked as such, and must not * ;* be misrepresented as being the original software. * ;*3. This notice may not be removed or altered from any source * ;* distribution. * ;* * ;**************************************************************************** ;------------------------------------------------------------------------------ ; The driver header .struct SER_HDR ID .byte 3 ; Contains 0x73, 0x65, 0x72 ("ser") VERSION .byte 1 ; Interface version LIBREF .addr ; Library reference JUMPTAB .struct SER_INSTALL .addr ; SER_INSTALL routine SER_UNINSTALL .addr ; SER_UNINSTALL routine SER_OPEN .addr ; SER_OPEN routine SER_CLOSE .addr ; SER_CLOSE routine SER_GET .addr ; SER_GET routine SER_PUT .addr ; SER_PUT routine SER_STATUS .addr ; SER_STATUS routine SER_IOCTL .addr ; SER_IOCTL routine SER_IRQ .addr ; SER_IRQ routine .endstruct .endstruct ;------------------------------------------------------------------------------ ; The SER API version, stored SER_HDR::VERSION SER_API_VERSION = $02 ;------------------------------------------------------------------------------ ; ser_params .struct SER_PARAMS BAUDRATE .byte ; Baudrate DATABITS .byte ; Number of data bits STOPBITS .byte ; Number of stop bits PARITY .byte ; Parity setting HANDSHAKE .byte ; Type of handshake to use .endstruct ;------------------------------------------------------------------------------ ; Serial parameters ; Baudrate SER_BAUD_45_5 = $00 SER_BAUD_50 = $01 SER_BAUD_75 = $02 SER_BAUD_110 = $03 SER_BAUD_134_5 = $04 SER_BAUD_150 = $05 SER_BAUD_300 = $06 SER_BAUD_600 = $07 SER_BAUD_1200 = $08 SER_BAUD_1800 = $09 SER_BAUD_2400 = $0A SER_BAUD_3600 = $0B SER_BAUD_4800 = $0C SER_BAUD_7200 = $0D SER_BAUD_9600 = $0E SER_BAUD_19200 = $0F SER_BAUD_38400 = $10 SER_BAUD_57600 = $11 SER_BAUD_115200 = $12 SER_BAUD_230400 = $13 SER_BAUD_31250 = $14 SER_BAUD_62500 = $15 SER_BAUD_56_875 = $16 ; Data bit settings SER_BITS_5 = $00 SER_BITS_6 = $01 SER_BITS_7 = $02 SER_BITS_8 = $03 ; Stop bit settings SER_STOP_1 = $00 SER_STOP_2 = $01 ; Parity SER_PAR_NONE = $00 SER_PAR_ODD = $01 SER_PAR_EVEN = $02 SER_PAR_MARK = $03 SER_PAR_SPACE = $04 ; Handshake SER_HS_NONE = $00 ; No handshake SER_HS_HW = $01 ; Hardware (RTS/CTS) handshake SER_HS_SW = $02 ; Software handshake ; Bit masks to mask out things from the status returned by ser_status SER_STATUS_PE = $01 ; Parity error SER_STATUS_FE = $02 ; Framing error SER_STATUS_OE = $04 ; Overrun error SER_STATUS_DCD = $20 ; NOT data carrier detect SER_STATUS_DSR = $40 ; NOT data set ready ;------------------------------------------------------------------------------ ; Variables .global _ser_drv ; Pointer to driver ;------------------------------------------------------------------------------ ; Driver entry points .global ser_install .global ser_uninstall .global ser_open .global ser_close .global ser_get .global ser_put .global ser_status .global ser_ioctl .global ser_irq ;------------------------------------------------------------------------------ ; C callable functions .global _ser_load_driver .global _ser_unload .global _ser_install .global _ser_uninstall .global _ser_open .global _ser_close .global _ser_get .global _ser_put .global _ser_status .global _ser_ioctl .global _ser_clear_ptr cc65-2.18/asminc/signal.inc000066400000000000000000000057431347360151100154400ustar00rootroot00000000000000;/*****************************************************************************/ ;/* */ ;/* signal.inc */ ;/* */ ;/* Signal handling definitions */ ;/* */ ;/* */ ;/* */ ;/* (C) 2002 Ullrich von Bassewitz */ ;/* Wacholderweg 14 */ ;/* D-70597 Stuttgart */ ;/* EMail: uz@musoftware.de */ ;/* */ ;/* */ ;/* 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. */ ;/* */ ;/*****************************************************************************/ ; Standard signal handling functions SIG_ERR = $0000 ; Signal numbers SIGABRT = 0 SIGFPE = 1 SIGILL = 2 SIGINT = 3 SIGSEGV = 4 SIGTERM = 5 SIGCOUNT = 6 ; Number of signals ; Table with signal handlers (asm code only) .global sigtable ; Function declarations .global __sig_ign .global __sig_dfl .global _signal .global _raise cc65-2.18/asminc/smc.inc000066400000000000000000000200111347360151100147260ustar00rootroot00000000000000; smc.mac ; ca65 Macro-Pack for Self Modifying Code (SMC) ; ; (c) Christian Krüger, latest change: 17-Jul-2016 ; ; This software is provided 'as-is', without any expressed or implied ; warranty. In no event will the authors be held liable for any damages ; arising from the use of this software. ; ; Permission is granted to anyone to use this software for any purpose, ; including commercial applications, and to alter it and redistribute it ; freely, subject to the following restrictions: ; ; 1. The origin of this software must not be misrepresented; you must not ; claim that you wrote the original software. If you use this software ; in a product, an acknowledgment in the product documentation would be ; appreciated but is not required. ; 2. Altered source versions must be plainly marked as such, and must not ; be misrepresented as being the original software. ; 3. This notice may not be removed or altered from any source ; distribution. ; .define _SMCDesignator .mid(0, .tcount(label) - 1, label) .ident(.concat(.string(.right(1, label)), "_SMC")) .define _SMCAlias .mid(0, .tcount(alias) - 1, alias) .ident(.concat(.string(.right(1, alias)), "_SMC")) .define SMC_AbsAdr $FADE .define SMC_ZpAdr $00 .define SMC_Opcode nop .define SMC_Value $42 .macro SMC_OperateOnValue opcode, label opcode _SMCDesignator+1 .endmacro .macro SMC_OperateOnLowByte opcode, label SMC_OperateOnValue opcode, label .endmacro .macro SMC_OperateOnHighByte opcode, label opcode _SMCDesignator + 2 .endmacro .macro SMC_Import alias .import _SMCAlias .endmacro .macro SMC_Export alias, label .export _SMCAlias := _SMCDesignator .endmacro .macro SMC label, statement _SMCDesignator: statement .endmacro .macro SMC_TransferOpcode label, opcode, register .if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, ) lda #opcode sta _SMCDesignator .elseif .match ({register}, x) ldx #opcode stx _SMCDesignator .elseif .match ({register}, y) ldy #opcode sty _SMCDesignator .else .error "Invalid usage of macro 'SMC_TransferOpcode'" .endif .endmacro .macro SMC_LoadOpcode label, register .if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, ) lda _SMCDesignator .elseif .match ({register}, x) ldx _SMCDesignator .elseif .match ({register}, y) ldy _SMCDesignator .else .error "Invalid usage of macro 'SMC_LoadOpcode'" .endif .endmacro .macro SMC_StoreOpcode label, register .if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, ) sta _SMCDesignator .elseif .match ({register}, x) stx _SMCDesignator .elseif .match ({register}, y) sty _SMCDesignator .else .error "Invalid usage of macro 'SMC_StoreOpcode'" .endif .endmacro .macro SMC_ChangeBranch label, destination, register .if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, ) lda #(<(destination - _SMCDesignator -2)) sta _SMCDesignator+1 .elseif .match ({register}, x) ldx #(<(destination - _SMCDesignator - 2)) stx _SMCDesignator+1 .elseif .match ({register}, y) ldy #(<(destination - _SMCDesignator - 2)) sty _SMCDesignator+1 .else .error "Invalid usage of macro 'SMC_ChangeBranch'" .endif .endmacro .macro SMC_TransferValue label, value, register .if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, ) lda value sta _SMCDesignator+1 .elseif .match ({register}, x) ldx value stx _SMCDesignator+1 .elseif .match ({register}, y) ldy value sty _SMCDesignator+1 .else .error "Invalid usage of macro 'SMC_TransferValue'" .endif .endmacro .macro SMC_LoadValue label, register .if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, ) lda _SMCDesignator+1 .elseif .match ({register}, x) ldx _SMCDesignator+1 .elseif .match ({register}, y) ldy _SMCDesignator+1 .else .error "Invalid usage of macro 'SMC_LoadValue'" .endif .endmacro .macro SMC_StoreValue label, register .if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, ) sta _SMCDesignator+1 .elseif .match ({register}, x) stx _SMCDesignator+1 .elseif .match ({register}, y) sty _SMCDesignator+1 .else .error "Invalid usage of macro 'SMC_StoreValue'" .endif .endmacro .macro SMC_TransferLowByte label, value, register SMC_TransferValue label, value, register .endmacro .macro SMC_LoadLowByte label, register SMC_LoadValue label, register .endmacro .macro SMC_StoreLowByte label, register SMC_StoreValue label, register .endmacro .macro SMC_TransferHighByte label, value, register .if .paramcount = 2 .or .match ({register}, a) .or .match ({register}, ) lda value sta _SMCDesignator+2 .elseif .match ({register}, x) ldx value stx _SMCDesignator+2 .elseif .match ({register}, y) ldy value sty _SMCDesignator+2 .else .error "Invalid usage of macro 'SMC_TransferHighByte'" .endif .endmacro .macro SMC_LoadHighByte label, register .if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, ) lda _SMCDesignator+2 .elseif .match ({register}, x) ldx _SMCDesignator+2 .elseif .match ({register}, y) ldy _SMCDesignator+2 .else .error "Invalid usage of macro 'SMC_LoadHighByte'" .endif .endmacro .macro SMC_StoreHighByte label, register .if .paramcount = 1 .or .match ({register}, a) .or .match ({register}, ) sta _SMCDesignator+2 .elseif .match ({register}, x) stx _SMCDesignator+2 .elseif .match ({register}, y) sty _SMCDesignator+2 .else .error "Invalid usage of macro 'SMC_StoreHighByte'" .endif .endmacro .macro SMC_TransferAddressSingle label, address, register .if .paramcount = 2 .or .match ((register), a) .or .match ({register}, ) .if (.match (.left (1, {address}), #)) ; immediate mode lda #<(.right (.tcount ({address})-1, {address})) sta _SMCDesignator+1 lda #>(.right (.tcount ({address})-1, {address})) sta _SMCDesignator+2 .else ; assume absolute or zero page lda address sta _SMCDesignator+1 lda 1+(address) sta _SMCDesignator+2 .endif .elseif .match ((register), x) .if (.match (.left (1, {address}), #)) ; immediate mode ldx #<(.right (.tcount ({address})-1, {address})) stx _SMCDesignator+1 ldx #>(.right (.tcount ({address})-1, {address})) stx _SMCDesignator+2 .else ; assume absolute or zero page ldx address stx _SMCDesignator+1 ldx 1+(address) stx _SMCDesignator+2 .endif .elseif .match ((register), y) .if (.match (.left (1, {address}), #)) ; immediate mode ldy #<(.right (.tcount ({address})-1, {address})) sty _SMCDesignator+1 ldy #>(.right (.tcount ({address})-1, {address})) sty _SMCDesignator+2 .else ; assume absolute or zero page ldy address sty _SMCDesignator+1 ldy 1+(address) sty _SMCDesignator+2 .endif .else .error "Invalid usage of macro 'SMC_TransferAddressSingle'" .endif .endmacro .macro SMC_TransferAddress label, address .if (.match (.left (1, {address}), #)) ; immediate mode lda #<(.right (.tcount ({address})-1, {address})) sta _SMCDesignator+1 ldx #>(.right (.tcount ({address})-1, {address})) stx _SMCDesignator+2 .else ; assume absolute or zero page lda {address} sta _SMCDesignator+1 ldx 1+{address} stx _SMCDesignator)+2 .endif .endmacro .macro SMC_StoreAddress label sta _SMCDesignator+1 stx _SMCDesignator+2 .endmacro cc65-2.18/asminc/stdio.inc000066400000000000000000000064431347360151100153030ustar00rootroot00000000000000;*****************************************************************************/ ;* */ ;* stdio.inc */ ;* */ ;* Mirror definitions for stdio.h */ ;* */ ;* */ ;* */ ;* (C) 2003-2005, Ullrich von Bassewitz */ ;* Römerstrasse 52 */ ;* D-70794 Filderstadt */ ;* EMail: uz@cc65.org */ ;* */ ;* */ ;* This software is provided 'as-is', without any expressed or implied */ ;* warranty. In no event will the authors be held liable for any damages */ ;* arising from the use of this software. */ ;* */ ;* Permission is granted to anyone to use this software for any purpose, */ ;* including commercial applications, and to alter it and redistribute it */ ;* freely, subject to the following restrictions: */ ;* */ ;* 1. The origin of this software must not be misrepresented; you must not */ ;* claim that you wrote the original software. If you use this software */ ;* in a product, an acknowledgment in the product documentation would be */ ;* appreciated but is not required. */ ;* 2. Altered source versions must be plainly marked as such, and must not */ ;* be misrepresented as being the original software. */ ;* 3. This notice may not be removed or altered from any source */ ;* distribution. */ ;* */ ;*****************************************************************************/ ;---------------------------------------------------------------------------- ; Constants _IOFBF = 0 _IOLBF = 1 _IONBF = 2 BUFSIZ = 256 EOF = -1 .if .defined(__APPLE2__) FILENAME_MAX = 64+1 .elseif .defined(__ATARI__) FILENAME_MAX = 12+1 .elseif .defined(__LUNIX__) FILENAME_MAX = 80+1 .elseif .defined(__TELESTRAT__) FILENAME_MAX = 50+1 .else FILENAME_MAX = 16+1 .endif L_tmpnam = FILENAME_MAX SEEK_CUR = 0 SEEK_END = 1 SEEK_SET = 2 TMP_MAX = 256 ; Maximum number of open files (size of the file table) FOPEN_MAX = 8 ;---------------------------------------------------------------------------- ; External variables .global _stdin .global _stdout .global _stderr cc65-2.18/asminc/supervision.inc000066400000000000000000000027001347360151100165370ustar00rootroot00000000000000; supervision symbols ; supervision 65c02s ; in cc65 up to 2.9.1 65c02 means 65sc02 lcd_addr = $4000 LCD_LINESIZE = $30 LCD_WIDTH = 160 LCD_HEIGHT = 160 ; 2 bit per pixel, packed lcd_width = $2000 lcd_height = $2001 lcd_xpos = $2002 ; in pixel, bit 0+1 not used lcd_ypos = $2003 ; weird sv_port_r = $2021 sv_port_w = $2022 sv_timer_count = $2023 ; read for quitting sv_timer_quit = $2024 ; bit 0 timer, bit 1 dma sv_irq_source = $2027 SV_IRQ_REQUEST_TIMER = 1 SV_IRQ_REQUEST_DMA = 2 ; bit 5,6,7 select bank at 0x8000 sv_bank = $2026 SV_NMI_ENABLE_ON = 1 SV_IRQ_ENABLE_TIMER = 2 SV_IRQ_ENABLE_DMA = 4 SV_LCD_ON = 8 SV_TIMER_MODE_240Hz = $10 ; else 15360 ; low activ/pressed sv_control = $2020 SV_RIGHT = 1 SV_LEFT = 2 SV_DOWN = 4 SV_UP = 8 SV_BUTTONB = $10 SV_BUTTONA = $20 SV_SELECT = $40 SV_START = $80 ; frequency=125000/counter sv_audio_right_counter = $2010 ;word sv_audio_left_counter = $2014 SV_AUDIO_ON =$40 ;bits 0..3 volume ; bit 4 ? ; bit 5 ? sv_audio_right_control = $2012 sv_audio_left_control = $2016 ; write activates tone for x/60 sec (0 means 256) sv_audio_right_timer = $2013 sv_audio_left_timer = $2017 ;read for irq quitting sv_dma_quit = $2025 sv_dma_on = $201c ; bit 7 true start, false stop sv_dma_start = $2018 ; word sv_dma_size = $201a ; *32 samples sv_dma_control = $201b ; bit 0,1 speed: 0 15360, 11 15360/4 ; bit 2,3 volume: 0 silent, 11 loud sv_noise_volume = $2028 ; and frequency sv_noise_timer = $2029 sv_noise_control = $202a cc65-2.18/asminc/telestrat.inc000066400000000000000000000353721347360151100161730ustar00rootroot00000000000000; ; Oric TELEMON definition ; TELEMON 2.4 & TELEMON 3.x ; For TELEMON 3.x check http://orix.oric.org ; ; --------------------------------------------------------------------------- ; Constants SCREEN_XSIZE = 40 ; Screen columns SCREEN_YSIZE = 28 ; Screen rows FUNCTKEY = $A5 FNAME_LEN = 11 ; Maximum length of file-name ; --------------------------------------------------------------------------- ; I/O Identifier ; Theses identifers are used for channel management ; XKBD = $80 ; Keyboard XRSE = $83 ; RS232 in XSCR = $88 ; Screen XRSS = $90 ; RS232 out ; --------------------------------------------------------------------------- ; Zero page ; --------------------------------------------------------------------------- ; Page 00 RES := $00 RESB := $02 DECDEB := $04 DECFIN := $06 DECCIB := $08 DECTRV := $0A TR0 := $0C TR1 := $0D TR2 := $0E TR3 := $0F TR4 := $10 TR5 := $11 TR6 := $12 TR7 := $13 DEFAFF := $14 IRQSVA := $21 ; Used to save A when a BRK call occurs IRQSVX := $22 ; Used to save X when a BRK call occurs IRQSVY := $23 ; Used to save Y when a BRK call occurs IRQSVP := $24 ; Used to save P when a BRK call occurs ADSCR := $26 SCRNB := $28 ; Id of the current window ADKBD := $2A ; Address ASCII conversion table PTR_READ_DEST := $2C ; Used for XFREAD and XWRITE only in TELEMON 3.x ADCLK := $40 ; Address for clock display TIMEUS := $42 TIMEUD := $44 HRSX := $46 HRSY := $47 XLPRBI := $48 ; Printer flag (b7) HRSX40 := $49 HRSX6 := $4A ADHRS := $4B ; Hires screen address (word) HRS1 := $4D HRS2 := $4F HRS3 := $51 HRS4 := $53 HRS5 := $55 HRSFB := $57 VABKP1 := $58 ; RS232T ; b0-b3 : speed ; 1111 => 19200 bps (please note that telestrat can't handle this speed without stopping all IRQ except ACIA's one) ; 1100 => 9600 bps (default from TELEMON) ; 1110 => 4800 bps ; 1010 => 2400 bps ; 1000 => 1200 bps ; 0111 => 600 bps ; 0110 => 300 bps ; 0101 => 150 bps ; 0010 => 75 bps ; b4 : 0 external clock, 1 internal clock ; b6-b5 : 00 8 bits ; 01 7 bits ; 10 6 bits ; 11 5 bits ; b7 : 0 a stop RS232T := $59 ; RS232C ; b0-b3 : 0 ; b4 : 1 if echo ; b5 : 1 if parity ; b7-b6 : 00 in/out parity odd ; : 01 on/out parity even ; : 10 parity sent, answer not tested ; : 11 SPACE SENT, reception not tested RS232C := $5A INDRS := $5B ACC1E := $60 ACC1M := $61 ACC1S := $65 FLGMEN := $68 ADMEN := $69 FLSVS := $89 FLERR := $8B VARLNG := $8C VARAPL := $D0 ; --------------------------------------------------------------------------- ; Low memory IRQVec := $02FB ; "fast" interrupt vector ; --------------------------------------------------------------------------- ; I/O locations ; 6522 .struct VIA ; Versatile Interface Adapter .res $0300 PRB .byte ; Port Register B PRA .byte ; Port Register A DDRB .byte ; Data Direction Register B DDRA .byte ; Data Direction Register A T1 .word ; Timer 1 T1L .word ; Timer 1 Latch T2 .word ; Timer 2 SR .byte ; Shift Register ACR .byte ; Auxiliary Control Register PCR .byte ; Peripheral Control Register IFR .byte ; Interrupt Flags Register IER .byte ; Interrupt Enable Register PRA2 .byte ; Port Register A without handshaking .endstruct .struct VIA2 ; Versatile Interface Adapter .res $0320 PRB .byte ; Port Register B PRA .byte ; Port Register A DDRB .byte ; Data Direction Register B DDRA .byte ; Data Direction Register A T1 .word ; Timer 1 T1L .word ; Timer 1 Latch T2 .word ; Timer 2 SR .byte ; Shift Register ACR .byte ; Auxiliary Control Register PCR .byte ; Peripheral Control Register IFR .byte ; Interrupt Flags Register IER .byte ; Interrupt Enable Register PRA2 .byte ; Port Register A without handshaking .endstruct ; 6551 .struct ACIA ; Asynchronous Communications Interface Adapter .res $031C DATA .byte STATUS .byte CMD .byte ; Command register CTRL .byte ; Control register .endstruct SCREEN := $BB80 ; --------------------------------------------------------------------------- ; ROM entries ; TELEMON primitives (2.4 & 3.x) ; all values are used to call bank 7 of telestrat cardridge. It works with 'brk value' XOP0 = $00 ; Open device on channel 0 XOP1 = $01 ; Open device on channel 1 XOP2 = $02 ; Open device on channel 2 XOP3 = $03 ; Open device on channel 3 XCL0 = $04 ; Close channel 0 XCL1 = $05 ; Close channel 1 XCL2 = $06 ; Close channel 2 XCL3 = $07 ; Close channel 3 XRD0 = $08 XRDW0 = $0C XWR0 = $10 ; Write a char in channel 0 XWR1 = $11 ; Write a char in channel 1 XWR2 = $12 ; Write a char in channel 2 XWR3 = $13 ; Write a char in channel 3 XWSTR0 = $14 ; Write a string in text mode channel 0 XWSTR1 = $15 ; Write a string in text mode channel 1 XWSTR2 = $16 ; Write a string in text mode channel 2 XWSTR3 = $17 ; Write a string in text mode channel 3 XDECAL = $18 XTEXT = $19 XHIRES = $1A XEFFHI = $1B ; Clear hires screen XFILLM = $1C XMINMA = $1F XVARS = $24 ; Only in TELEMON 3.x, in TELEMON 2.4, it's XNOMFI ($24) XCRLF = $25 ; Jump a line and return to the beginning of the line XDECAY = $26 XFREAD = $27 ; Only in TELEMON 3.x (bank 7 of Orix) XBINDX = $28 ; Convert a number into hex and displays on channel 0 XDECIM = $29 XHEXA = $2A ; Convert a number into hex XEDT = $2D ; Launch editor XINSER = $2E XSCELG = $2F ; Search a line in editor mode XOPEN = $30 ; Only in TELEMON 3.x (bank 7 of Orix) XECRPR = $33 ; Displays prompt XCOSCR = $34 ; Switch off cursor XCSSCR = $35 ; Switch on cursor XSCRSE = $36 XSCRNE = $39 ; Load charset from rom to ram XCLOSE = $3A ; Only in TELEMON 3.x close file (bank 7 of Orix) XFWRITE = $3B ; Only in TELEMON 3.x write file (bank 7 of Orix) ; Clock primitive XRECLK = $3C ; Reset clock XCLCL = $3D ; Close clock XWRCLK = $3E ; Displays clock in the adress in A & Y registers XSONPS = $40 ; Send data to PSG register (14 values) XOUPS = $42 ; Send Oups sound into PSG XPLAY = $43 ; Play a sound XSOUND = $44 XMUSIC = $45 XZAP = $46 ; Send Zap sound to PSG XSHOOT = $47 XMKDIR = $4B ; Create a folder. Only available in TELEMON 3.x (bank 7 of Orix) XRM = $4D ; Remove a folder or a file. Only available in TELEMON 3.x (bank 7 of Orix) XGOKBD = $52 ; Buffer management XECRBU = $54 ; Write A or AY in the buffer XLISBU = $55 ; Read A or AY in the buffer XTSTBU = $56 XVIDBU = $57 ; Flush the buffer XINIBU = $58 ; Initialize the buffer X XDEFBU = $59 ; Reset all value of the buffer XBUSY = $5A ; Test if the buffer is empty XMALLOC = $5B ; Only in TELEMON 3.x (bank 7 of Orix) XFREE = $62 ; Only in TELEMON 3.x (bank 7 of Orix) XSOUT = $67 ; Send accumulator value (A) to RS232, available in TELEMON 2.4 & 3.x : if RS232 buffer is full, the Oric Telestrat freezes XHRSSE = $8C ; Set hires position cursor XDRAWA = $8D ; Draw a line absolute XDRAWR = $8E ; Draw a line (relative) XCIRCL = $8F ; Draw a circle XCURSE = $90 ; Plot a pixel XCURMO = $91 ; Move to x,y pos in Hires XPAPER = $92 XINK = $93 XBOX = $94 ; Draw a box XABOX = $95 XFILL = $96 XCHAR = $97 ; Display a char on the screen in Hires XSCHAR = $98 ; Draw a string in hires XEXPLO = $9C ; Send Explode sound to PSG XPING = $9D ; Send Ping sound to PSG ; --------------------------------------------------------------------------- ; ROM entries variables PWD_PTR = $00 ; --------------------------------------------------------------------------- ; BUFTRV := $100 ; --------------------------------------------------------------------------- ; Page $200 BNKST := $200 ; Used to store signature of 8 bank (length : 8 bytes) TABDRV := $208 DRVDEF := $20C FLGTEL := $20D KOROM := $20E ; Used to compute the size of all rom bank. The result is store here. The value is in KB KORAM := $20F ; Used to compute the size of all ram bank. The result is store here. The value is in KB ; Time management TIMED := $210 TIMES := $211 TIMEM := $212 TIMEH := $213 FLGCLK := $214 FLGCLK_FLAG := $215 FLGCUR := $216 ; Cursor management flag ; screens position managements FLGCUR_STATE := $217 ; Cursor state flag ADSCRL := $218 ADSCRH := $21C SCRX := $220 SCRY := $224 SCRDX := $228 SCRFX := $22C SCRDY := $230 SCRFY := $234 SCRBAL := $238 SCRBAH := $23C SCRCT := $240 SCRCF := $244 FLGSCR := $248 CURSCR := $24C HARD_COPY_HIRES := $250 ; Hard copy vector SCRTXT := $256 SCRHIR := $25C SCRTRA := $262 ; 6 bytes lenfth ; Keyboard management KBDCOL := $268 ; 8 bytes length KBDFLG_KEY := $270 ; 0 if no key pressed KBDVRR := $272 KBDVRL := $273 FLGKBD := $275 KBDFCT := $276 KBDSHT := $278 KBDKEY := $279 KBDCTC := $27E LPRX := $286 LPRY := $287 LPRFX := $288 LPRFY := $289 FLGLPR := $28A ; Joysticks management FLGJCK := $28C JCGVAL := $28D JCDVAL := $28E JCKTAB := $29D HRSPAT := $2AA ; Hires pattern : it's used to draw pattern for a line or a circle HRSERR := $2AB IOTAB0 := $2AE IOTAB1 := $2B2 IOTAB2 := $2B6 IOTAB3 := $2BA ADIOB := $2BE ; 48 bytes length FLGRST := $2EE CSRND := $2EF VNMI := $2F4 ADIODB_VECTOR := $2f7 ; 3 bytes length IRQVECTOR := $2FA VAPLIC := $2FD ; --------------------------------------------------------------------------- ; Page $400 EXBNK := $40C VEXBNK := $414 BNKCIB := $417 ; --------------------------------------------------------------------------- ; Page $500 DRIVE := $500 ERRNB := $512 SAVES := $513 BUFNOM := $517 VSALO0 := $528 VSALO1 := $529 FTYPE := $52C ; File type DESALO := $52D FISALO := $52F EXSALO := $531 EXTDEF := $55D ; Default extension. At the start of telemon, it's set to ".COM" BUFEDT := $590 ; Buffer edition MAX_BUFEDT_LENGTH=110 ; --------------------------------------------------------------------------- ; Hardware CH376_DATA := $340 CH376_COMMAND := $341 ; RAM overlays buffer BUFBUF := $c080 ; --------------------------------------------------------------------------- ; Stratsed vectors ; Stratsed is the main OS for Telestrat XMERGE := $FF0E XFST := $FF11 XSPUT := $FF14 XSTAKE := $FF17 XTAKE := $FF20 XOPENS := $FF1A ; XOPEN from Stratsed XCLOSES := $FF1D ; XCLOSE from Stratsed XPUT := $FF23 XREWIN := $FF29 XJUMP := $FF2C XLGBUF := $FF2F XERVEC := $FF32 XESAVE := $FF35 XCOPY := $FF38 XDNAME := $FF3B XSTATU := $FF3E XUPDAT := $FF41 XFORMA := $FF44 XDELBK := $FF4A XDELN := $FF4D XPROT := $FF50 XUNPRO := $FF53 XDIRN := $FF56 XBKP := $FF59 XINITI := $FF5C XERREU := $FF5F XLOAD := $FF62 XDEFSA := $FF65 XDEFLO := $FF68 XSAVE := $FF6B XNOMDE := $FF6E XCREAY := $FF71 XDETSE := $FF74 XLIBSE := $FF77 XTRVCA := $FF7A XTRVNM := $FF7D XTRVNX := $FF80 XBUCA := $FF86 XVBUF1 := $FF89 XSVSEC := $FF8C XSAY := $FF8F XSBUF1 := $FF92 XSBUF2 := $FF95 XSBUF3 := $FF98 XSCAT := $FF9B XPRSEC := $FFA1 XPBUF1 := $FFA4 XPMAP := $FFA7 XRWTS := $FFAA ; --------------------------------------------------------------------------- ; MACRO .macro BRK_TELEMON value .byte $00,value .endmacro cc65-2.18/asminc/tgi-error.inc000066400000000000000000000063401347360151100160670ustar00rootroot00000000000000;*****************************************************************************/ ;* */ ;* tgi-error.inc */ ;* */ ;* TGI error codes */ ;* */ ;* */ ;* */ ;* (C) 2002-2012, Ullrich von Bassewitz */ ;* Roemerstrasse 52 */ ;* D-70794 Filderstadt */ ;* EMail: uz@cc65.org */ ;* */ ;* */ ;* This software is provided 'as-is', without any expressed or implied */ ;* warranty. In no event will the authors be held liable for any damages */ ;* arising from the use of this software. */ ;* */ ;* Permission is granted to anyone to use this software for any purpose, */ ;* including commercial applications, and to alter it and redistribute it */ ;* freely, subject to the following restrictions: */ ;* */ ;* 1. The origin of this software must not be misrepresented; you must not */ ;* claim that you wrote the original software. If you use this software */ ;* in a product, an acknowledgment in the product documentation would be */ ;* appreciated but is not required. */ ;* 2. Altered source versions must be plainly marked as such, and must not */ ;* be misrepresented as being the original software. */ ;* 3. This notice may not be removed or altered from any source */ ;* distribution. */ ;* */ ;*****************************************************************************/ ; Error constants .enum TGI_ERR_OK ; No error TGI_ERR_NO_DRIVER ; No driver available TGI_ERR_CANNOT_LOAD ; Error loading driver or font TGI_ERR_INV_DRIVER ; Invalid driver TGI_ERR_INV_MODE ; Mode not supported by driver TGI_ERR_INV_ARG ; Invalid function argument TGI_ERR_INV_FUNC ; Function not supported TGI_ERR_INV_FONT ; Font file is invalid TGI_ERR_NO_RES ; Out of resources (memory, handles, ...) TGI_ERR_UNKNOWN ; Unknown error TGI_ERR_INSTALLED ; A driver is already installed TGI_ERR_COUNT ; Special: Number of error messages .endenum cc65-2.18/asminc/tgi-kernel.inc000066400000000000000000000243631347360151100162230ustar00rootroot00000000000000;*****************************************************************************/ ;* */ ;* tgi-kernel.inc */ ;* */ ;* TGI kernel interface */ ;* */ ;* */ ;* */ ;* (C) 2002-2012, Ullrich von Bassewitz */ ;* Roemerstrasse 52 */ ;* D-70794 Filderstadt */ ;* EMail: uz@cc65.org */ ;* */ ;* */ ;* This software is provided 'as-is', without any expressed or implied */ ;* warranty. In no event will the authors be held liable for any damages */ ;* arising from the use of this software. */ ;* */ ;* Permission is granted to anyone to use this software for any purpose, */ ;* including commercial applications, and to alter it and redistribute it */ ;* freely, subject to the following restrictions: */ ;* */ ;* 1. The origin of this software must not be misrepresented; you must not */ ;* claim that you wrote the original software. If you use this software */ ;* in a product, an acknowledgment in the product documentation would be */ ;* appreciated but is not required. */ ;* 2. Altered source versions must be plainly marked as such, and must not */ ;* be misrepresented as being the original software. */ ;* 3. This notice may not be removed or altered from any source */ ;* distribution. */ ;* */ ;*****************************************************************************/ ;------------------------------------------------------------------------------ ; The driver header .struct TGI_HDR ID .byte 3 ; Contains 0x74, 0x67, 0x69 ("tgi") VERSION .byte 1 ; Interface version LIBREF .addr ; Library reference VARS .struct XRES .word 1 ; X resolution YRES .word 1 ; Y resolution COLORCOUNT .byte 1 ; Number of available colors PAGECOUNT .byte 1 ; Number of screens available FONTWIDTH .byte 1 ; System font width in pixel FONTHEIGHT .byte 1 ; System font height in pixel ASPECTRATIO .word 1 ; Fixed point 8.8 format FLAGS .byte 1 ; TGI driver flags .endstruct JUMPTAB .struct INSTALL .addr ; INSTALL routine UNINSTALL .addr ; UNINSTALL routine INIT .addr ; INIT routine DONE .addr ; DONE routine GETERROR .addr ; GETERROR routine CONTROL .addr ; CONTROL routine CLEAR .addr ; CLEAR routine SETVIEWPAGE .addr ; SETVIEWPAGE routine SETDRAWPAGE .addr ; SETDRAWPAGE routine SETCOLOR .addr ; SETCOLOR routine SETPALETTE .addr ; SETPALETTE routine GETPALETTE .addr ; GETPALETTE routine GETDEFPALETTE .addr ; GETDEFPALETTE routine SETPIXEL .addr ; SETPIXEL routine GETPIXEL .addr ; GETPIXEL routine LINE .addr ; LINE routine BAR .addr ; BAR routine TEXTSTYLE .addr ; TEXTSTYLE routine OUTTEXT .addr ; OUTTEXT routine .endstruct .endstruct ;------------------------------------------------------------------------------ ; The TGI API version, stored at TGI_HDR_VERSION TGI_API_VERSION = $06 ;------------------------------------------------------------------------------ ; Bitmapped tgi driver flags, stored in TGI_HDR::VARS::FLAGS. ; Beware: Some of the bits are tested using the BIT instruction, so do not ; change the values without checking the code! TGI_BM_FONT_FINESCALE = $80 ; Bitmap fonts are fine grained scalable ;------------------------------------------------------------------------------ ; Text constants TGI_FONT_BITMAP = 0 TGI_FONT_VECTOR = 1 TGI_TEXT_HORIZONTAL = 0 TGI_TEXT_VERTICAL = 1 ;---------------------------------------------------------------------------- ; Results of tgi_outcode TGI_CLIP_NONE = $00 TGI_CLIP_LEFT = $01 TGI_CLIP_RIGHT = $02 TGI_CLIP_BOTTOM = $04 TGI_CLIP_TOP = $08 ;------------------------------------------------------------------------------ ; ASM accessible color constants .global tgi_color_black:zp ; Target-specific value for black .global tgi_color_white:zp ; Target-specific value for white ;------------------------------------------------------------------------------ ; C accessible variables .global _tgi_drv ; Pointer to driver .global _tgi_error ; Last error code .global _tgi_gmode ; Flag: graphics mode active .global _tgi_curx ; Current drawing cursor X .global _tgi_cury ; Current drawing cursor Y .global _tgi_color ; Current drawing color .global _tgi_font ; Which font to use .global _tgi_textdir ; Current text direction .global _tgi_vectorfont ; Pointer to vector font .global _tgi_textscalew ; Text magnification for the width .global _tgi_textscaleh ; Text magnification for the height .global _tgi_charwidth ; Width of scaled system font char .global _tgi_charheight ; Height of scaled system font char .global _tgi_xres ; X resolution of the current mode .global _tgi_yres ; Y resolution of the current mode .global _tgi_xmax ; Maximum X coordinate .global _tgi_ymax ; Maximum Y coordinate .global _tgi_colorcount ; Number of available colors .global _tgi_pagecount ; Number of available screen pages .global _tgi_fontwidth ; System font width .global _tgi_fontheight ; System font height .global _tgi_aspectratio ; Aspect ratio, fixed point 8.8 .global _tgi_flags ; TGI driver flags ;------------------------------------------------------------------------------ ; ASM accessible variables .global tgi_clip_x1 ; Coordinate for line clipper .global tgi_clip_y1 ; Coordinate for line clipper .global tgi_clip_x2 ; Coordinate for line clipper .global tgi_clip_y2 ; Coordinate for line clipper ;------------------------------------------------------------------------------ ; Driver entry points .global tgi_install .global tgi_uninstall .global tgi_init .global tgi_done .global tgi_geterror .global tgi_control .global tgi_clear .global tgi_setviewpage .global tgi_setdrawpage .global tgi_setcolor .global tgi_setpalette .global tgi_getpalette .global tgi_getdefpalette .global tgi_setpixel .global tgi_getpixel .global tgi_line .global tgi_bar .global tgi_textstyle .global tgi_outtext ;------------------------------------------------------------------------------ ; ASM functions .global tgi_clear_ptr .global tgi_clippedline .global tgi_curtoxy .global tgi_getset .global tgi_imulround .global tgi_inv_arg .global tgi_inv_drv .global tgi_linepop .global tgi_outcode .global tgi_popxy .global tgi_popxy2 .global tgi_set_ptr ;------------------------------------------------------------------------------ ; C callable functions .global _tgi_arc .global _tgi_bar .global _tgi_circle .global _tgi_clear .global _tgi_done .global _tgi_ellipse .global _tgi_getaspectratio .global _tgi_getcolor .global _tgi_getcolorcount .global _tgi_getdefpalette .global _tgi_geterror .global _tgi_geterrormsg .global _tgi_getmaxcolor .global _tgi_getmaxx .global _tgi_getmaxy .global _tgi_getpagecount .global _tgi_getpalette .global _tgi_getpixel .global _tgi_gettextheight .global _tgi_gettextwidth .global _tgi_getxres .global _tgi_getyres .global _tgi_gotoxy .global _tgi_imulround .global _tgi_init .global _tgi_install .global _tgi_install_vectorfont .global _tgi_ioctl .global _tgi_line .global _tgi_lineto .global _tgi_load_driver .global _tgi_outtext .global _tgi_outtextxy .global _tgi_pieslice .global _tgi_setaspectratio .global _tgi_setcolor .global _tgi_setdrawpage .global _tgi_setpalette .global _tgi_setpixel .global _tgi_settextdir .global _tgi_settextscale .global _tgi_settextstyle .global _tgi_setviewpage .global _tgi_uninstall .global _tgi_unload cc65-2.18/asminc/tgi-vectorfont.inc000066400000000000000000000075231347360151100171330ustar00rootroot00000000000000;*****************************************************************************/ ;* */ ;* tgi-vectorfont.inc */ ;* */ ;* TGI vector font definitions */ ;* */ ;* */ ;* */ ;* (C) 2009, Ullrich von Bassewitz */ ;* Roemerstrasse 52 */ ;* D-70794 Filderstadt */ ;* EMail: uz@cc65.org */ ;* */ ;* */ ;* This software is provided 'as-is', without any expressed or implied */ ;* warranty. In no event will the authors be held liable for any damages */ ;* arising from the use of this software. */ ;* */ ;* Permission is granted to anyone to use this software for any purpose, */ ;* including commercial applications, and to alter it and redistribute it */ ;* freely, subject to the following restrictions: */ ;* */ ;* 1. The origin of this software must not be misrepresented; you must not */ ;* claim that you wrote the original software. If you use this software */ ;* in a product, an acknowledgment in the product documentation would be */ ;* appreciated but is not required. */ ;* 2. Altered source versions must be plainly marked as such, and must not */ ;* be misrepresented as being the original software. */ ;* 3. This notice may not be removed or altered from any source */ ;* distribution. */ ;* */ ;*****************************************************************************/ ;------------------------------------------------------------------------------ ; Vectorfont constants TGI_VF_VERSION = $00 ; File version number TGI_VF_FIRSTCHAR = $20 ; First char in file TGI_VF_LASTCHAR = $7E ; Last char in file TGI_VF_CCOUNT = (TGI_VF_LASTCHAR - TGI_VF_FIRSTCHAR + 1) ;------------------------------------------------------------------------------ ; TCH file header and font data structures ; TCH file header .struct TGI_VF_HDR MAGIC .byte 3 ; "TCH" VERSION .byte 1 ; Version number SIZE .word 1 ; Font data size .endstruct ; Font data loaded directly from file .struct TGI_VECTORFONT TOP .byte ; Height of char BOTTOM .byte ; Descender HEIGHT .byte ; Maximum char height WIDTHS .byte ::TGI_VF_CCOUNT ; Char widths CHARS .word ::TGI_VF_CCOUNT ; Pointer to character defs OPS .byte ; Actually dynamic .endstruct ;------------------------------------------------------------------------------ ; C callable functions .global _tgi_vectorchar cc65-2.18/asminc/time.inc000066400000000000000000000066021347360151100151140ustar00rootroot00000000000000;/*****************************************************************************/ ;/* */ ;/* time.inc */ ;/* */ ;/* Date and time */ ;/* */ ;/* */ ;/* */ ;/* (C) 2009 Ullrich von Bassewitz */ ;/* Roemerstrasse 52 */ ;/* D-70794 Filderstadt */ ;/* EMail: uz@cc65.org */ ;/* */ ;/* */ ;/* This software is provided 'as-is', without any expressed or implied */ ;/* warranty. In no event will the authors be held liable for any damages */ ;/* arising from the use of this software. */ ;/* */ ;/* Permission is granted to anyone to use this software for any purpose, */ ;/* including commercial applications, and to alter it and redistribute it */ ;/* freely, subject to the following restrictions: */ ;/* */ ;/* 1. The origin of this software must not be misrepresented; you must not */ ;/* claim that you wrote the original software. If you use this software */ ;/* in a product, an acknowledgment in the product documentation would be */ ;/* appreciated but is not required. */ ;/* 2. Altered source versions must be plainly marked as such, and must not */ ;/* be misrepresented as being the original software. */ ;/* 3. This notice may not be removed or altered from any source */ ;/* distribution. */ ;/* */ ;/*****************************************************************************/ ;------------------------------------------------------------------------------ ; Struct tm - must match the struct defined in time.h .struct tm tm_sec .word tm_min .word tm_hour .word tm_mday .word tm_mon .word tm_year .word tm_wday .word tm_yday .word tm_isdst .word .endstruct ;------------------------------------------------------------------------------ ; Struct timespec - must match the struct defined in time.h .struct timespec tv_sec .dword tv_nsec .dword .endstruct ;------------------------------------------------------------------------------ ; Exported functions .global _clock_getres .global _clock_gettime .global _clock_settime .global _localtime .global _mktime cc65-2.18/asminc/utsname.inc000066400000000000000000000053771347360151100156420ustar00rootroot00000000000000;/*****************************************************************************/ ;/* */ ;/* utsname.inc */ ;/* */ ;/* Return system information */ ;/* */ ;/* */ ;/* */ ;/* (C) 2003 Ullrich von Bassewitz */ ;/* Römerstrasse 52 */ ;/* D-70794 Filderstadt */ ;/* EMail: uz@cc65.org */ ;/* */ ;/* */ ;/* This software is provided 'as-is', without any expressed or implied */ ;/* warranty. In no event will the authors be held liable for any damages */ ;/* arising from the use of this software. */ ;/* */ ;/* Permission is granted to anyone to use this software for any purpose, */ ;/* including commercial applications, and to alter it and redistribute it */ ;/* freely, subject to the following restrictions: */ ;/* */ ;/* 1. The origin of this software must not be misrepresented; you must not */ ;/* claim that you wrote the original software. If you use this software */ ;/* in a product, an acknowledgment in the product documentation would be */ ;/* appreciated but is not required. */ ;/* 2. Altered source versions must be plainly marked as such, and must not */ ;/* be misrepresented as being the original software. */ ;/* 3. This notice may not be removed or altered from any source */ ;/* distribution. */ ;/* */ ;/*****************************************************************************/ ; Struct utsname .struct utsname sysname .byte 17 nodename .byte 9 release .byte 9 version .byte 9 machine .byte 25 .endstruct cc65-2.18/asminc/vic20.inc000066400000000000000000000112161347360151100150760ustar00rootroot00000000000000; ; Vic20 generic definitions. Stolen mostly from c64.inc - Steve Schmidtke ; ; --------------------------------------------------------------------------- ; 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 SECADR := $B9 ; Secondary address DEVNUM := $BA ; Device number FNAM := $BB ; Pointer to filename KEY_COUNT := $C6 ; Number of keys in input buffer RVS := $C7 ; Reverse flag CURS_FLAG := $CC ; 1 = cursor off CURS_BLINK := $CD ; Blink counter CURS_CHAR := $CE ; Character under the cursor CURS_STATE := $CF ; Cursor blink state 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 BASIC_BUF := $200 ; Location of command-line BASIC_BUF_LEN = 89 ; Maximum length of command-line CHARCOLOR := $286 CURS_COLOR := $287 ; Color under the cursor KBDREPEAT := $28a KBDREPEATRATE := $28b KBDREPEATDELAY := $28c ; --------------------------------------------------------------------------- ; Screen size XSIZE = 22 YSIZE = 23 ; --------------------------------------------------------------------------- ; Vector and other locations IRQVec := $0314 BRKVec := $0316 NMIVec := $0318 ; --------------------------------------------------------------------------- ; I/O: 6560 VIC VIC := $9000 VIC_CR0 := VIC+$0 VIC_CR1 := VIC+$1 VIC_CR2 := VIC+$2 VIC_CR3 := VIC+$3 VIC_LINES := VIC+$3 ; Screen lines, bit 7 is bit 0 from VIC_HLINE VIC_CR4 := VIC+$4 VIC_HLINE := VIC+$4 ; Rasterline, bits 1-8 VIC_CR5 := VIC+$5 VIC_CR6 := VIC+$6 VIC_CR7 := VIC+$7 VIC_CR8 := VIC+$8 VIC_CR9 := VIC+$9 VIC_CRA := VIC+$A VIC_CRB := VIC+$B VIC_CRC := VIC+$C VIC_CRD := VIC+$D VIC_CRE := VIC+$E VIC_CRF := VIC+$F VIC_COLOR := VIC+$F ; Border and background color ; --------------------------------------------------------------------------- ; I/O: 6522 VIA1 VIA1 := $9110 ; VIA1 base address VIA1_JOY := VIA1+$0 ; *** Deprecated *** VIA1_PB := VIA1+$0 ; Port register B VIA1_PA1 := VIA1+$1 ; Port register A VIA1_DDRB := VIA1+$2 ; Data direction register B VIA1_DDRA := VIA1+$3 ; Data direction register A VIA1_T1CL := VIA1+$4 ; Timer 1, low byte VIA1_T1CH := VIA1+$5 ; Timer 1, high byte VIA1_T1LL := VIA1+$6 ; Timer 1 latch, low byte VIA1_T1LH := VIA1+$7 ; Timer 1 latch, high byte VIA1_T2CL := VIA1+$8 ; Timer 2, low byte VIA1_T2CH := VIA1+$9 ; Timer 2, high byte VIA1_SR := VIA1+$A ; Shift register VIA1_CR := VIA1+$B ; Auxiliary control register VIA1_PCR := VIA1+$C ; Peripheral control register VIA1_IFR := VIA1+$D ; Interrupt flag register VIA1_IER := VIA1+$E ; Interrupt enable register VIA1_PA2 := VIA1+$F ; Port register A w/o handshake ; --------------------------------------------------------------------------- ; I/O: 6522 VIA2 VIA2 := $9120 ; VIA2 base address VIA2_JOY := VIA2+$0 ; *** Deprecated *** VIA2_PB := VIA2+$0 ; Port register B VIA2_PA1 := VIA2+$1 ; Port register A VIA2_DDRB := VIA2+$2 ; Data direction register B VIA2_DDRA := VIA2+$3 ; Data direction register A VIA2_T1CL := VIA2+$4 ; Timer 1, low byte VIA2_T1CH := VIA2+$5 ; Timer 1, high byte VIA2_T1LL := VIA2+$6 ; Timer 1 latch, low byte VIA2_T1LH := VIA2+$7 ; Timer 1 latch, high byte VIA2_T2CL := VIA2+$8 ; Timer 2, low byte VIA2_T2CH := VIA2+$9 ; Timer 2, high byte VIA2_SR := VIA2+$A ; Shift register VIA2_CR := VIA2+$B ; Auxiliary control register VIA2_PCR := VIA2+$C ; Peripheral control register VIA2_IFR := VIA2+$D ; Interrupt flag register VIA2_IER := VIA2+$E ; Interrupt enable register VIA2_PA2 := VIA2+$F ; Port register A w/o handshake cc65-2.18/asminc/zeropage.inc000066400000000000000000000013211347360151100157630ustar00rootroot00000000000000; ; zeropage.inc ; ; (C) Copyright 2002-2012, Ullrich von Bassewitz (uz@cc65.org) ; ; Assembler include file that imports the runtime zero page locations used ; by the compiler, ready for usage in asm code. .globalzp sp, sreg, regsave .globalzp ptr1, ptr2, ptr3, ptr4 .globalzp tmp1, tmp2, tmp3, tmp4 .globalzp regbank ; The size of the register bank regbanksize = 6 ; The total amount of zero page space used zpspace = 26 ; The amount of space that needs to be saved by an interrupt handler that ; calls C code (does not include the register bank, which is saved by the ; generated C code if required). zpsavespace = zpspace - regbanksize cc65-2.18/cfg/000077500000000000000000000000001347360151100127445ustar00rootroot00000000000000cc65-2.18/cfg/apple2-asm.cfg000066400000000000000000000015561347360151100153750ustar00rootroot00000000000000# Configuration for assembler programs which don't need a special setup FEATURES { STARTADDRESS: default = $0803; } SYMBOLS { __FILETYPE__: type = weak, value = $0006; # ProDOS file type } MEMORY { ZP: file = "", start = $0000, size = $00FF; HEADER: file = %O, start = %S - $003A, size = $003A; MAIN: file = %O, define = yes, start = %S, size = $C000 - %S; BSS: file = "", start = __MAIN_LAST__, size = $C000 - __MAIN_LAST__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp, optional = yes; EXEHDR: load = HEADER, type = ro, optional = yes; CODE: load = MAIN, type = rw; RODATA: load = MAIN, type = ro, optional = yes; DATA: load = MAIN, type = rw, optional = yes; BSS: load = BSS, type = bss, optional = yes, define = yes; } cc65-2.18/cfg/apple2-hgr.cfg000066400000000000000000000041611347360151100153700ustar00rootroot00000000000000# Configuration for programs including a hires screen (with 6KB LOWCODE) FEATURES { STARTADDRESS: default = $0803; } SYMBOLS { __EXEHDR__: type = import; __FILETYPE__: type = weak, value = $0006; # ProDOS file type __STACKSIZE__: type = weak, value = $0800; # 2k stack __HIMEM__: type = weak, value = $9600; # Presumed RAM end __LCADDR__: type = weak, value = $D400; # Behind quit code __LCSIZE__: type = weak, value = $0C00; # Rest of bank two } MEMORY { ZP: file = "", define = yes, start = $0080, size = $001A; HEADER: file = %O, start = %S - $003A, size = $003A; MAIN: file = %O, define = yes, start = %S, size = __HIMEM__ - %S; BSS: file = "", start = __ONCE_RUN__, size = __HIMEM__ - __STACKSIZE__ - __ONCE_RUN__; LC: file = "", define = yes, start = __LCADDR__, size = __LCSIZE__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXEHDR: load = HEADER, type = ro, optional = yes; STARTUP: load = MAIN, type = ro; LOWCODE: load = MAIN, type = ro, optional = yes; HGR: load = MAIN, type = rw, optional = yes, start = $2000; CODE: load = MAIN, type = ro start = $4000; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; INIT: load = MAIN, type = rw; ONCE: load = MAIN, type = ro, define = yes; LC: load = MAIN, run = LC, type = ro, optional = yes; BSS: load = BSS, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/apple2-overlay.cfg000066400000000000000000000077551347360151100163050ustar00rootroot00000000000000# Configuration for overlay programs (overlays located below main program) # The overlay files are raw binary files so use AppleCommander like this: # java -jar ac.jar -as mydisk.dsk myprog < myprog # java -jar ac.jar -p mydisk.dsk myprog.1 bin < myprog.1 # java -jar ac.jar -p mydisk.dsk myprog.2 bin < myprog.2 # java -jar ac.jar -p mydisk.dsk myprog.3 bin < myprog.3 # ... FEATURES { STARTADDRESS: default = $0803; } SYMBOLS { __EXEHDR__: type = import; __FILETYPE__: type = weak, value = $0006; # ProDOS file type __STACKSIZE__: type = weak, value = $0800; # 2k stack __HIMEM__: type = weak, value = $9600; # Presumed RAM end __LCADDR__: type = weak, value = $D400; # Behind quit code __LCSIZE__: type = weak, value = $0C00; # Rest of bank two __OVERLAYSIZE__: type = weak, value = $1000; # 4k overlay } MEMORY { ZP: file = "", define = yes, start = $0080, size = $001A; HEADER: file = %O, start = %S - $003A, size = $003A; MAIN: file = %O, define = yes, start = %S + __OVERLAYSIZE__, size = __HIMEM__ - __OVERLAYSIZE__ - %S; BSS: file = "", start = __ONCE_RUN__, size = __HIMEM__ - __STACKSIZE__ - __ONCE_RUN__; LC: file = "", define = yes, start = __LCADDR__, size = __LCSIZE__; OVL1: file = "%O.1", start = %S, size = __OVERLAYSIZE__; OVL2: file = "%O.2", start = %S, size = __OVERLAYSIZE__; OVL3: file = "%O.3", start = %S, size = __OVERLAYSIZE__; OVL4: file = "%O.4", start = %S, size = __OVERLAYSIZE__; OVL5: file = "%O.5", start = %S, size = __OVERLAYSIZE__; OVL6: file = "%O.6", start = %S, size = __OVERLAYSIZE__; OVL7: file = "%O.7", start = %S, size = __OVERLAYSIZE__; OVL8: file = "%O.8", start = %S, size = __OVERLAYSIZE__; OVL9: file = "%O.9", start = %S, size = __OVERLAYSIZE__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXEHDR: load = HEADER, type = ro, optional = yes; STARTUP: load = MAIN, type = ro, define = yes; LOWCODE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; INIT: load = MAIN, type = rw; ONCE: load = MAIN, type = ro, define = yes; LC: load = MAIN, run = LC, type = ro, optional = yes; BSS: load = BSS, type = bss, define = yes; OVERLAY1: load = OVL1, type = ro, define = yes, optional = yes; OVERLAY2: load = OVL2, type = ro, define = yes, optional = yes; OVERLAY3: load = OVL3, type = ro, define = yes, optional = yes; OVERLAY4: load = OVL4, type = ro, define = yes, optional = yes; OVERLAY5: load = OVL5, type = ro, define = yes, optional = yes; OVERLAY6: load = OVL6, type = ro, define = yes, optional = yes; OVERLAY7: load = OVL7, type = ro, define = yes, optional = yes; OVERLAY8: load = OVL8, type = ro, define = yes, optional = yes; OVERLAY9: load = OVL9, type = ro, define = yes, optional = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/apple2-system.cfg000066400000000000000000000036141347360151100161360ustar00rootroot00000000000000# Configuration for ProDOS 8 system programs (allowing for 3KB in LC) SYMBOLS { __EXEHDR__: type = import; __FILETYPE__: type = weak, value = $00FF; # ProDOS file type __STACKSIZE__: type = weak, value = $0800; # 2k stack __LCADDR__: type = weak, value = $D400; # Behind quit code __LCSIZE__: type = weak, value = $0C00; # Rest of bank two } MEMORY { ZP: file = "", define = yes, start = $0080, size = $001A; HEADER: file = %O, start = $2000 - $003A, size = $003A; MAIN: file = %O, define = yes, start = $2000, size = $BF00 - $2000; BSS: file = "", start = __ONCE_RUN__, size = $BF00 - __STACKSIZE__ - __ONCE_RUN__; LC: file = "", define = yes, start = __LCADDR__, size = __LCSIZE__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXEHDR: load = HEADER, type = ro, optional = yes; STARTUP: load = MAIN, type = ro; LOWCODE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; INIT: load = MAIN, type = rw; ONCE: load = MAIN, type = ro, define = yes; LC: load = MAIN, run = LC, type = ro, optional = yes; BSS: load = BSS, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/apple2.cfg000066400000000000000000000037511347360151100146160ustar00rootroot00000000000000# Default configuration (allowing for 3KB in LC) FEATURES { STARTADDRESS: default = $0803; } SYMBOLS { __EXEHDR__: type = import; __FILETYPE__: type = weak, value = $0006; # ProDOS file type __STACKSIZE__: type = weak, value = $0800; # 2k stack __HIMEM__: type = weak, value = $9600; # Presumed RAM end __LCADDR__: type = weak, value = $D400; # Behind quit code __LCSIZE__: type = weak, value = $0C00; # Rest of bank two } MEMORY { ZP: file = "", define = yes, start = $0080, size = $001A; HEADER: file = %O, start = %S - $003A, size = $003A; MAIN: file = %O, define = yes, start = %S, size = __HIMEM__ - %S; BSS: file = "", start = __ONCE_RUN__, size = __HIMEM__ - __STACKSIZE__ - __ONCE_RUN__; LC: file = "", define = yes, start = __LCADDR__, size = __LCSIZE__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXEHDR: load = HEADER, type = ro, optional = yes; STARTUP: load = MAIN, type = ro; LOWCODE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; INIT: load = MAIN, type = rw; ONCE: load = MAIN, type = ro, define = yes; LC: load = MAIN, run = LC, type = ro, optional = yes; BSS: load = BSS, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/apple2enh-asm.cfg000066400000000000000000000015561347360151100160700ustar00rootroot00000000000000# Configuration for assembler programs which don't need a special setup FEATURES { STARTADDRESS: default = $0803; } SYMBOLS { __FILETYPE__: type = weak, value = $0006; # ProDOS file type } MEMORY { ZP: file = "", start = $0000, size = $00FF; HEADER: file = %O, start = %S - $003A, size = $003A; MAIN: file = %O, define = yes, start = %S, size = $C000 - %S; BSS: file = "", start = __MAIN_LAST__, size = $C000 - __MAIN_LAST__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp, optional = yes; EXEHDR: load = HEADER, type = ro, optional = yes; CODE: load = MAIN, type = rw; RODATA: load = MAIN, type = ro, optional = yes; DATA: load = MAIN, type = rw, optional = yes; BSS: load = BSS, type = bss, optional = yes, define = yes; } cc65-2.18/cfg/apple2enh-hgr.cfg000066400000000000000000000041611347360151100160630ustar00rootroot00000000000000# Configuration for programs including a hires screen (with 6KB LOWCODE) FEATURES { STARTADDRESS: default = $0803; } SYMBOLS { __EXEHDR__: type = import; __FILETYPE__: type = weak, value = $0006; # ProDOS file type __STACKSIZE__: type = weak, value = $0800; # 2k stack __HIMEM__: type = weak, value = $9600; # Presumed RAM end __LCADDR__: type = weak, value = $D400; # Behind quit code __LCSIZE__: type = weak, value = $0C00; # Rest of bank two } MEMORY { ZP: file = "", define = yes, start = $0080, size = $001A; HEADER: file = %O, start = %S - $003A, size = $003A; MAIN: file = %O, define = yes, start = %S, size = __HIMEM__ - %S; BSS: file = "", start = __ONCE_RUN__, size = __HIMEM__ - __STACKSIZE__ - __ONCE_RUN__; LC: file = "", define = yes, start = __LCADDR__, size = __LCSIZE__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXEHDR: load = HEADER, type = ro, optional = yes; STARTUP: load = MAIN, type = ro; LOWCODE: load = MAIN, type = ro, optional = yes; HGR: load = MAIN, type = rw, optional = yes, start = $2000; CODE: load = MAIN, type = ro start = $4000; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; INIT: load = MAIN, type = rw; ONCE: load = MAIN, type = ro, define = yes; LC: load = MAIN, run = LC, type = ro, optional = yes; BSS: load = BSS, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/apple2enh-overlay.cfg000066400000000000000000000077551347360151100170000ustar00rootroot00000000000000# Configuration for overlay programs (overlays located below main program) # The overlay files are raw binary files so use AppleCommander like this: # java -jar ac.jar -as mydisk.dsk myprog < myprog # java -jar ac.jar -p mydisk.dsk myprog.1 bin < myprog.1 # java -jar ac.jar -p mydisk.dsk myprog.2 bin < myprog.2 # java -jar ac.jar -p mydisk.dsk myprog.3 bin < myprog.3 # ... FEATURES { STARTADDRESS: default = $0803; } SYMBOLS { __EXEHDR__: type = import; __FILETYPE__: type = weak, value = $0006; # ProDOS file type __STACKSIZE__: type = weak, value = $0800; # 2k stack __HIMEM__: type = weak, value = $9600; # Presumed RAM end __LCADDR__: type = weak, value = $D400; # Behind quit code __LCSIZE__: type = weak, value = $0C00; # Rest of bank two __OVERLAYSIZE__: type = weak, value = $1000; # 4k overlay } MEMORY { ZP: file = "", define = yes, start = $0080, size = $001A; HEADER: file = %O, start = %S - $003A, size = $003A; MAIN: file = %O, define = yes, start = %S + __OVERLAYSIZE__, size = __HIMEM__ - __OVERLAYSIZE__ - %S; BSS: file = "", start = __ONCE_RUN__, size = __HIMEM__ - __STACKSIZE__ - __ONCE_RUN__; LC: file = "", define = yes, start = __LCADDR__, size = __LCSIZE__; OVL1: file = "%O.1", start = %S, size = __OVERLAYSIZE__; OVL2: file = "%O.2", start = %S, size = __OVERLAYSIZE__; OVL3: file = "%O.3", start = %S, size = __OVERLAYSIZE__; OVL4: file = "%O.4", start = %S, size = __OVERLAYSIZE__; OVL5: file = "%O.5", start = %S, size = __OVERLAYSIZE__; OVL6: file = "%O.6", start = %S, size = __OVERLAYSIZE__; OVL7: file = "%O.7", start = %S, size = __OVERLAYSIZE__; OVL8: file = "%O.8", start = %S, size = __OVERLAYSIZE__; OVL9: file = "%O.9", start = %S, size = __OVERLAYSIZE__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXEHDR: load = HEADER, type = ro, optional = yes; STARTUP: load = MAIN, type = ro, define = yes; LOWCODE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; INIT: load = MAIN, type = rw; ONCE: load = MAIN, type = ro, define = yes; LC: load = MAIN, run = LC, type = ro, optional = yes; BSS: load = BSS, type = bss, define = yes; OVERLAY1: load = OVL1, type = ro, define = yes, optional = yes; OVERLAY2: load = OVL2, type = ro, define = yes, optional = yes; OVERLAY3: load = OVL3, type = ro, define = yes, optional = yes; OVERLAY4: load = OVL4, type = ro, define = yes, optional = yes; OVERLAY5: load = OVL5, type = ro, define = yes, optional = yes; OVERLAY6: load = OVL6, type = ro, define = yes, optional = yes; OVERLAY7: load = OVL7, type = ro, define = yes, optional = yes; OVERLAY8: load = OVL8, type = ro, define = yes, optional = yes; OVERLAY9: load = OVL9, type = ro, define = yes, optional = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/apple2enh-system.cfg000066400000000000000000000036141347360151100166310ustar00rootroot00000000000000# Configuration for ProDOS 8 system programs (allowing for 3KB in LC) SYMBOLS { __EXEHDR__: type = import; __FILETYPE__: type = weak, value = $00FF; # ProDOS file type __STACKSIZE__: type = weak, value = $0800; # 2k stack __LCADDR__: type = weak, value = $D400; # Behind quit code __LCSIZE__: type = weak, value = $0C00; # Rest of bank two } MEMORY { ZP: file = "", define = yes, start = $0080, size = $001A; HEADER: file = %O, start = $2000 - $003A, size = $003A; MAIN: file = %O, define = yes, start = $2000, size = $BF00 - $2000; BSS: file = "", start = __ONCE_RUN__, size = $BF00 - __STACKSIZE__ - __ONCE_RUN__; LC: file = "", define = yes, start = __LCADDR__, size = __LCSIZE__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXEHDR: load = HEADER, type = ro, optional = yes; STARTUP: load = MAIN, type = ro; LOWCODE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; INIT: load = MAIN, type = rw; ONCE: load = MAIN, type = ro, define = yes; LC: load = MAIN, run = LC, type = ro, optional = yes; BSS: load = BSS, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/apple2enh.cfg000066400000000000000000000037511347360151100153110ustar00rootroot00000000000000# Default configuration (allowing for 3KB in LC) FEATURES { STARTADDRESS: default = $0803; } SYMBOLS { __EXEHDR__: type = import; __FILETYPE__: type = weak, value = $0006; # ProDOS file type __STACKSIZE__: type = weak, value = $0800; # 2k stack __HIMEM__: type = weak, value = $9600; # Presumed RAM end __LCADDR__: type = weak, value = $D400; # Behind quit code __LCSIZE__: type = weak, value = $0C00; # Rest of bank two } MEMORY { ZP: file = "", define = yes, start = $0080, size = $001A; HEADER: file = %O, start = %S - $003A, size = $003A; MAIN: file = %O, define = yes, start = %S, size = __HIMEM__ - %S; BSS: file = "", start = __ONCE_RUN__, size = __HIMEM__ - __STACKSIZE__ - __ONCE_RUN__; LC: file = "", define = yes, start = __LCADDR__, size = __LCSIZE__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXEHDR: load = HEADER, type = ro, optional = yes; STARTUP: load = MAIN, type = ro; LOWCODE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; INIT: load = MAIN, type = rw; ONCE: load = MAIN, type = ro, define = yes; LC: load = MAIN, run = LC, type = ro, optional = yes; BSS: load = BSS, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/atari-asm-xex.cfg000066400000000000000000000014231347360151100161050ustar00rootroot00000000000000FEATURES { STARTADDRESS: default = $2E00; } SYMBOLS { __STARTADDRESS__: type = export, value = %S; } MEMORY { ZP: file = "", define = yes, start = $0082, size = $007E; MAIN: file = %O, define = yes, start = %S, size = $BC20 - %S; } FILES { %O: format = atari; } FORMATS { atari: runad = start; } SEGMENTS { ZEROPAGE: load = ZP, type = zp, optional = yes; EXTZP: load = ZP, type = zp, optional = yes; # to enable modules to be able to link to C and assembler programs CODE: load = MAIN, type = rw, define = yes; RODATA: load = MAIN, type = ro optional = yes; DATA: load = MAIN, type = rw optional = yes; BSS: load = MAIN, type = bss, optional = yes, define = yes; } cc65-2.18/cfg/atari-asm.cfg000066400000000000000000000023551347360151100153100ustar00rootroot00000000000000FEATURES { STARTADDRESS: default = $2E00; } SYMBOLS { __EXEHDR__: type = import; __AUTOSTART__: type = import; # force inclusion of autostart "trailer" __STARTADDRESS__: type = export, value = %S; } MEMORY { ZP: file = "", define = yes, start = $0082, size = $007E; # file header, just $FFFF HEADER: file = %O, start = $0000, size = $0002; # "main program" load chunk MAINHDR: file = %O, start = $0000, size = $0004; MAIN: file = %O, define = yes, start = %S, size = $BC20 - %S; TRAILER: file = %O, start = $0000, size = $0006; } SEGMENTS { ZEROPAGE: load = ZP, type = zp, optional = yes; EXTZP: load = ZP, type = zp, optional = yes; # to enable modules to be able to link to C and assembler programs EXEHDR: load = HEADER, type = ro, optional = yes; MAINHDR: load = MAINHDR, type = ro, optional = yes; CODE: load = MAIN, type = rw, define = yes; RODATA: load = MAIN, type = ro optional = yes; DATA: load = MAIN, type = rw optional = yes; BSS: load = MAIN, type = bss, optional = yes, define = yes; AUTOSTRT: load = TRAILER, type = ro, optional = yes; } cc65-2.18/cfg/atari-cart.cfg000066400000000000000000000043761347360151100154660ustar00rootroot00000000000000FEATURES { STARTADDRESS: default = $2000; } SYMBOLS { __CARTSIZE__: type = weak, value = $2000; # possible values: $2000 and $4000 __CART_HEADER__: type = import; __STACKSIZE__: type = weak, value = $0800; # 2k stack __STARTADDRESS__: type = export, value = %S; __RESERVED_MEMORY__: type = export, value = $0000; __CARTFLAGS__: type = weak, value = $01; # see documentation for other possible values } MEMORY { ZP: file = "", define = yes, start = $0082, size = $007E; MAIN: file = "", define = yes, start = %S, size = __CARTSIZE__; ROM: file = %O, define = yes, start = $C000 - __CARTSIZE__, size = __CARTSIZE__ - 6, fill = yes, fillval = $FF; CARTID: file = %O, start = $BFFA, size = $0006; } SEGMENTS { ZEROPAGE: load = ZP, type = zp, optional = yes; EXTZP: load = ZP, type = zp, optional = yes; STARTUP: load = ROM, type = ro, define = yes, optional = yes; LOWBSS: load = MAIN, type = bss, optional = yes; # not zero initialized LOWCODE: load = ROM, type = ro, define = yes, optional = yes; ONCE: load = ROM, type = ro, optional = yes; CODE: load = ROM, type = ro, define = yes; RODATA: load = ROM, type = ro, optional = yes; DATA: load = ROM, run = MAIN, type = rw, define = yes, optional = yes; INIT: load = MAIN, type = bss, optional = yes; BSS: load = MAIN, type = bss, define = yes, optional = yes; CARTHDR: load = CARTID, type = ro; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/atari-cassette.cfg000066400000000000000000000033651347360151100163450ustar00rootroot00000000000000FEATURES { STARTADDRESS: default = $0900; } SYMBOLS { __STACKSIZE__: type = weak, value = $0800; # 2k stack __RESERVED_MEMORY__: type = weak, value = $0000; __STARTADDRESS__: type = export, value = %S; _cas_hdr: type = import; } MEMORY { ZP: file = "", define = yes, start = $0082, size = $007E; MAIN: file = %O, define = yes, start = %S, size = $BC20 - __STACKSIZE__ - __RESERVED_MEMORY__ - %S; } SEGMENTS { ZEROPAGE: load = ZP, type = zp, optional = yes; EXTZP: load = ZP, type = zp, optional = yes; CASHDR: load = MAIN, type = ro; STARTUP: load = MAIN, type = ro, define = yes, optional = yes; LOWBSS: load = MAIN, type = rw, optional = yes; # not zero initialized LOWCODE: load = MAIN, type = ro, define = yes, optional = yes; ONCE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro, define = yes; RODATA: load = MAIN, type = ro, optional = yes; DATA: load = MAIN, type = rw, optional = yes; BSS: load = MAIN, type = bss, define = yes, optional = yes; INIT: load = MAIN, type = bss, optional = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/atari-overlay.cfg000066400000000000000000000106201347360151100162030ustar00rootroot00000000000000FEATURES { STARTADDRESS: default = $2000; } SYMBOLS { __EXEHDR__: type = import; __SYSTEM_CHECK__: type = import; # force inclusion of "system check" load chunk __AUTOSTART__: type = import; # force inclusion of autostart "trailer" __STACKSIZE__: type = weak, value = $0800; # 2k stack __OVERLAYSIZE__: type = weak, value = $1000; # 4k overlay __STARTADDRESS__: type = export, value = %S; __RESERVED_MEMORY__: type = weak, value = $0000; } MEMORY { ZP: file = "", define = yes, start = $0082, size = $007E; # file header, just $FFFF HEADER: file = %O, start = $0000, size = $0002; # "system check" load chunk SYSCHKHDR: file = %O, start = $0000, size = $0004; SYSCHKCHNK: file = %O, start = $2E00, size = $0300; SYSCHKTRL: file = %O, start = $0000, size = $0006; # "main program" load chunk MAINHDR: file = %O, start = $0000, size = $0004; MAIN: file = %O, define = yes, start = %S + __OVERLAYSIZE__, size = $BC20 - __OVERLAYSIZE__ - __STACKSIZE__ - __RESERVED_MEMORY__ - %S; TRAILER: file = %O, start = $0000, size = $0006; # overlays OVL1: file = "%O.1", start = %S, size = __OVERLAYSIZE__; OVL2: file = "%O.2", start = %S, size = __OVERLAYSIZE__; OVL3: file = "%O.3", start = %S, size = __OVERLAYSIZE__; OVL4: file = "%O.4", start = %S, size = __OVERLAYSIZE__; OVL5: file = "%O.5", start = %S, size = __OVERLAYSIZE__; OVL6: file = "%O.6", start = %S, size = __OVERLAYSIZE__; OVL7: file = "%O.7", start = %S, size = __OVERLAYSIZE__; OVL8: file = "%O.8", start = %S, size = __OVERLAYSIZE__; OVL9: file = "%O.9", start = %S, size = __OVERLAYSIZE__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXTZP: load = ZP, type = zp, optional = yes; EXEHDR: load = HEADER, type = ro; SYSCHKHDR: load = SYSCHKHDR, type = ro, optional = yes; SYSCHK: load = SYSCHKCHNK, type = rw, define = yes, optional = yes; SYSCHKTRL: load = SYSCHKTRL, type = ro, optional = yes; MAINHDR: load = MAINHDR, type = ro; STARTUP: load = MAIN, type = ro, define = yes; LOWBSS: load = MAIN, type = rw, optional = yes; # not zero initialized LOWCODE: load = MAIN, type = ro, define = yes, optional = yes; ONCE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro, define = yes; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; INIT: load = MAIN, type = rw, optional = yes; BSS: load = MAIN, type = bss, define = yes; AUTOSTRT: load = TRAILER, type = ro; OVERLAY1: load = OVL1, type = ro, define = yes, optional = yes; OVERLAY2: load = OVL2, type = ro, define = yes, optional = yes; OVERLAY3: load = OVL3, type = ro, define = yes, optional = yes; OVERLAY4: load = OVL4, type = ro, define = yes, optional = yes; OVERLAY5: load = OVL5, type = ro, define = yes, optional = yes; OVERLAY6: load = OVL6, type = ro, define = yes, optional = yes; OVERLAY7: load = OVL7, type = ro, define = yes, optional = yes; OVERLAY8: load = OVL8, type = ro, define = yes, optional = yes; OVERLAY9: load = OVL9, type = ro, define = yes, optional = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/atari-xex.cfg000066400000000000000000000045141347360151100153330ustar00rootroot00000000000000# Sample linker configuration for C programs using the Atari binary file support. # Use with: cl65 -tatari -Catari-xex.cfg prog.c -o prog.xex FEATURES { STARTADDRESS: default = $2000; } SYMBOLS { __SYSTEM_CHECK__: type = import; # force inclusion of "system check" load chunk __STACKSIZE__: type = weak, value = $0800; # 2k stack __STARTADDRESS__: type = export, value = %S; __RESERVED_MEMORY__: type = weak, value = $0000; __SYSCHKHDR__: type = export, value = 0; # Disable system check header __SYSCHKTRL__: type = export, value = 0; # Disable system check trailer } MEMORY { ZP: file = "", define = yes, start = $0082, size = $007E; # "system check" load chunk SYSCHKCHNK: file = %O, start = $2E00, size = $0300; # "main program" load chunk MAIN: file = %O, define = yes, start = %S, size = $BC20 - __STACKSIZE__ - __RESERVED_MEMORY__ - %S; } FILES { %O: format = atari; } FORMATS { atari: runad = start, initad = SYSCHKCHNK: __SYSTEM_CHECK__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXTZP: load = ZP, type = zp, optional = yes; SYSCHK: load = SYSCHKCHNK, type = rw, define = yes, optional = yes; STARTUP: load = MAIN, type = ro, define = yes; LOWBSS: load = MAIN, type = rw, optional = yes; # not zero initialized LOWCODE: load = MAIN, type = ro, define = yes, optional = yes; ONCE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro, define = yes; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; INIT: load = MAIN, type = rw, optional = yes; BSS: load = MAIN, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/atari.cfg000066400000000000000000000052651347360151100145350ustar00rootroot00000000000000FEATURES { STARTADDRESS: default = $2000; } SYMBOLS { __EXEHDR__: type = import; __SYSTEM_CHECK__: type = import; # force inclusion of "system check" load chunk __AUTOSTART__: type = import; # force inclusion of autostart "trailer" __STACKSIZE__: type = weak, value = $0800; # 2k stack __STARTADDRESS__: type = export, value = %S; __RESERVED_MEMORY__: type = weak, value = $0000; } MEMORY { ZP: file = "", define = yes, start = $0082, size = $007E; # file header, just $FFFF HEADER: file = %O, start = $0000, size = $0002; # "system check" load chunk SYSCHKHDR: file = %O, start = $0000, size = $0004; SYSCHKCHNK: file = %O, start = $2E00, size = $0300; SYSCHKTRL: file = %O, start = $0000, size = $0006; # "main program" load chunk MAINHDR: file = %O, start = $0000, size = $0004; MAIN: file = %O, define = yes, start = %S, size = $BC20 - __STACKSIZE__ - __RESERVED_MEMORY__ - %S; TRAILER: file = %O, start = $0000, size = $0006; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXTZP: load = ZP, type = zp, optional = yes; EXEHDR: load = HEADER, type = ro; SYSCHKHDR: load = SYSCHKHDR, type = ro, optional = yes; SYSCHK: load = SYSCHKCHNK, type = rw, define = yes, optional = yes; SYSCHKTRL: load = SYSCHKTRL, type = ro, optional = yes; MAINHDR: load = MAINHDR, type = ro; STARTUP: load = MAIN, type = ro, define = yes; LOWBSS: load = MAIN, type = rw, optional = yes; # not zero initialized LOWCODE: load = MAIN, type = ro, define = yes, optional = yes; ONCE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro, define = yes; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; INIT: load = MAIN, type = rw, optional = yes; BSS: load = MAIN, type = bss, define = yes; AUTOSTRT: load = TRAILER, type = ro; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/atari2600.cfg000066400000000000000000000014651347360151100150430ustar00rootroot00000000000000# Atari VCS 2600 linker configuration file for cc65 # # Florent Flament (contact@florentflament.com), 2017 SYMBOLS { __STACKSIZE__: type = weak, value = $0010; # 16 Bytes system stack } MEMORY { RAM: file = "", start = $0080, size = $0080 - __STACKSIZE__, define = yes; ROM: file = %O, start = $F000, size = $1000, fill = yes, fillval = $FF; } SEGMENTS { ZEROPAGE: load = RAM, type = zp; STARTUP: load = ROM, type = ro; CODE: load = ROM, type = ro; RODATA: load = ROM, type = ro, optional = yes; DATA: load = ROM, run = RAM, type = rw, optional = yes, define = yes; BSS: load = RAM, type = bss, optional = yes; VECTORS: load = ROM, type = ro, start = $FFFA; } cc65-2.18/cfg/atari5200.cfg000066400000000000000000000050531347360151100150370ustar00rootroot00000000000000SYMBOLS { __CARTSIZE__: type = weak, value = $4000; # possible values: $4000 and $8000 __CART_ENTRY__: type = import; __STACKSIZE__: type = weak, value = $0400; # 4 pages stack __RESERVED_MEMORY__: type = export, value = $01E0; # space for 20x24 screen buffer (default display list is in ROM) } MEMORY { ZP: file = "", start = $001D, size = $00E3, define = yes; RAM: file = "", start = $021C, size = $4000 - __STACKSIZE__ - __RESERVED_MEMORY__ - $021C, define = yes; ROM: file = %O, start = $C000 - __CARTSIZE__, size = __CARTSIZE__ - $18, define = yes, fill = yes, fillval = $FF; CARTNAME: file = %O, start = $BFE8, size = $0014 fill = yes, fillval = $40; CARTYEAR: file = %O, start = $BFFC, size = $0002 fill = yes, fillval = $59; CARTENTRY: file = %O, start = $BFFE, size = $0002; } SEGMENTS { ZEROPAGE: load = ZP, type = zp, optional = yes; EXTZP: load = ZP, type = zp, optional = yes; DLIST: load = ROM , type = ro, define = yes, optional = yes; STARTUP: load = ROM, type = ro, define = yes, optional = yes; LOWCODE: load = ROM, type = ro, define = yes, optional = yes; ONCE: load = ROM, type = ro, optional = yes; CODE: load = ROM, type = ro, define = yes; RODATA: load = ROM, type = ro, optional = yes; DATA: load = ROM, run = RAM, type = rw, define = yes, optional = yes; BSS: load = RAM, type = bss, define = yes, optional = yes; CARTNAME: load = CARTNAME, type = ro; CARTYEAR: load = CARTYEAR, type = ro; CARTENTRY: load = CARTENTRY, type = ro; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/atarixl-largehimem.cfg000066400000000000000000000105511347360151100172030ustar00rootroot00000000000000# This config file provides a single big upper memory block (HIDDEN_RAM). # To achieve this, it relocates the character generator from $E000 to CHARGEN. # The runtime library must be compiled with CHARGEN_RELOC for this config # file to work. See libsrc/atari/Makefile.inc. FEATURES { STARTADDRESS: default = $2400; } SYMBOLS { __EXEHDR__: type = import; __SYSTEM_CHECK__: type = import; # force inclusion of "system check" load chunk __AUTOSTART__: type = import; # force inclusion of autostart "trailer" __STACKSIZE__: type = weak, value = $0800; # 2k stack __STARTADDRESS__: type = export, value = %S; } MEMORY { ZP: file = "", define = yes, start = $0082, size = $007E; # just $FFFF HEADER: file = %O, start = $0000, size = $0002; # "system check" load chunk SYSCHKHDR: file = %O, start = $0000, size = $0004; SYSCHKCHNK: file = %O, start = $2E00, size = $0300; SYSCHKTRL: file = %O, start = $0000, size = $0006; # "shadow RAM preparation" load chunk SRPREPHDR: file = %O, start = $0000, size = $0004; SRPREPCHNK: file = %O, define = yes, start = %S, size = $7C20 - %S - $07FF; # $07FF: space for temp. chargen buffer, 1K aligned SRPREPTRL: file = %O, start = $0000, size = $0006; # "main program" load chunk MAINHDR: file = %O, start = $0000, size = $0004; MAIN: file = %O, define = yes, start = %S + __LOWBSS_SIZE__, size = $D000 - __STACKSIZE__ - %S - __LOWBSS_SIZE__; # defines entry point into program TRAILER: file = %O, start = $0000, size = $0006; # address of relocated character generator CHARGEN: file = "", define = yes, start = $D800, size = $0400; # memory beneath the ROM HIDDEN_RAM: file = "", define = yes, start = $DC00, size = $FFFA - $DC00; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXTZP: load = ZP, type = zp, optional = yes; EXEHDR: load = HEADER, type = ro; SYSCHKHDR: load = SYSCHKHDR, type = ro, optional = yes; SYSCHK: load = SYSCHKCHNK, type = rw, define = yes, optional = yes; SYSCHKTRL: load = SYSCHKTRL, type = ro, optional = yes; SRPREPHDR: load = SRPREPHDR, type = ro; LOWBSS: load = SRPREPCHNK, type = bss, define = yes; # shared btw. SRPREPCHNK and RAM, not zero initialized SRPREP: load = SRPREPCHNK, type = rw, define = yes; SHADOW_RAM: load = SRPREPCHNK, run = HIDDEN_RAM, type = rw, define = yes, optional = yes; SHADOW_RAM2: load = SRPREPCHNK, run = HIDDEN_RAM, type = rw, define = yes, optional = yes; SRPREPTRL: load = SRPREPTRL, type = ro; MAINHDR: load = MAINHDR, type = ro; STARTUP: load = MAIN, type = ro, define = yes; LOWCODE: load = MAIN, type = ro, define = yes, optional = yes; ONCE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro, define = yes; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; INIT: load = MAIN, type = rw, optional = yes; BSS: load = MAIN, type = bss, define = yes; AUTOSTRT: load = TRAILER, type = ro; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/atarixl-overlay.cfg000066400000000000000000000142531347360151100165550ustar00rootroot00000000000000FEATURES { STARTADDRESS: default = $2400; } SYMBOLS { __EXEHDR__: type = import; __SYSTEM_CHECK__: type = import; # force inclusion of "system check" load chunk __AUTOSTART__: type = import; # force inclusion of autostart "trailer" __STACKSIZE__: type = weak, value = $0800; # 2k stack __OVERLAYSIZE__: type = weak, value = $1000; # 4k overlay __STARTADDRESS__: type = export, value = %S; } MEMORY { ZP: file = "", define = yes, start = $0082, size = $007E; # just $FFFF HEADER: file = %O, start = $0000, size = $0002; # "system check" load chunk SYSCHKHDR: file = %O, start = $0000, size = $0004; SYSCHKCHNK: file = %O, start = $2E00, size = $0300; SYSCHKTRL: file = %O, start = $0000, size = $0006; # "shadow RAM preparation" load chunk SRPREPHDR: file = %O, start = $0000, size = $0004; SRPREPCHNK: file = %O, define = yes, start = %S + __OVERLAYSIZE__, size = $7C20 - %S - __OVERLAYSIZE__ - $07FF; # $07FF: space for temp. chargen buffer, 1K aligned SRPREPTRL: file = %O, start = $0000, size = $0006; # "main program" load chunk MAINHDR: file = %O, start = $0000, size = $0004; MAIN: file = %O, define = yes, start = %S + __OVERLAYSIZE__ + __LOWBSS_SIZE__, size = $D000 - __STACKSIZE__ - %S - __OVERLAYSIZE__ - __LOWBSS_SIZE__; # defines entry point into program TRAILER: file = %O, start = $0000, size = $0006; # memory beneath the ROM preceeding the character generator HIDDEN_RAM2: file = "", define = yes, start = $D800, size = $0800; # address of relocated character generator (same addess as ROM version) CHARGEN: file = "", define = yes, start = $E000, size = $0400; # memory beneath the ROM HIDDEN_RAM: file = "", define = yes, start = $E400, size = $FFFA - $E400; # overlays OVL1: file = "%O.1", start = %S, size = __OVERLAYSIZE__; OVL2: file = "%O.2", start = %S, size = __OVERLAYSIZE__; OVL3: file = "%O.3", start = %S, size = __OVERLAYSIZE__; OVL4: file = "%O.4", start = %S, size = __OVERLAYSIZE__; OVL5: file = "%O.5", start = %S, size = __OVERLAYSIZE__; OVL6: file = "%O.6", start = %S, size = __OVERLAYSIZE__; OVL7: file = "%O.7", start = %S, size = __OVERLAYSIZE__; OVL8: file = "%O.8", start = %S, size = __OVERLAYSIZE__; OVL9: file = "%O.9", start = %S, size = __OVERLAYSIZE__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXTZP: load = ZP, type = zp, optional = yes; EXEHDR: load = HEADER, type = ro; SYSCHKHDR: load = SYSCHKHDR, type = ro, optional = yes; SYSCHK: load = SYSCHKCHNK, type = rw, define = yes, optional = yes; SYSCHKTRL: load = SYSCHKTRL, type = ro, optional = yes; SRPREPHDR: load = SRPREPHDR, type = ro; LOWBSS: load = SRPREPCHNK, type = bss, define = yes; # shared btw. SRPREPCHNK and RAM, not zero initialized SRPREP: load = SRPREPCHNK, type = rw, define = yes; SHADOW_RAM: load = SRPREPCHNK, run = HIDDEN_RAM, type = rw, define = yes, optional = yes; SHADOW_RAM2: load = SRPREPCHNK, run = HIDDEN_RAM2, type = rw, define = yes, optional = yes; SRPREPTRL: load = SRPREPTRL, type = ro; MAINHDR: load = MAINHDR, type = ro; STARTUP: load = MAIN, type = ro, define = yes; LOWCODE: load = MAIN, type = ro, define = yes, optional = yes; ONCE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro, define = yes; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; INIT: load = MAIN, type = rw, optional = yes; BSS: load = MAIN, type = bss, define = yes; AUTOSTRT: load = TRAILER, type = ro; OVERLAY1: load = OVL1, type = ro, define = yes, optional = yes; OVERLAY2: load = OVL2, type = ro, define = yes, optional = yes; OVERLAY3: load = OVL3, type = ro, define = yes, optional = yes; OVERLAY4: load = OVL4, type = ro, define = yes, optional = yes; OVERLAY5: load = OVL5, type = ro, define = yes, optional = yes; OVERLAY6: load = OVL6, type = ro, define = yes, optional = yes; OVERLAY7: load = OVL7, type = ro, define = yes, optional = yes; OVERLAY8: load = OVL8, type = ro, define = yes, optional = yes; OVERLAY9: load = OVL9, type = ro, define = yes, optional = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/atarixl-xex.cfg000066400000000000000000000072651347360151100157050ustar00rootroot00000000000000# Sample linker configuration for C programs using the Atari binary file support. # Use with: cl65 -tatarixl -Catarixl-c-xex.cfg prog.c -o prog.xex FEATURES { STARTADDRESS: default = $2400; } SYMBOLS { __SYSTEM_CHECK__: type = import; # force inclusion of "system check" load chunk __STACKSIZE__: type = weak, value = $0800; # 2k stack __STARTADDRESS__: type = export, value = %S; __SYSCHKHDR__: type = export, value = 0; # Disable system check header __SYSCHKTRL__: type = export, value = 0; # Disable system check trailer } MEMORY { ZP: file = "", define = yes, start = $0082, size = $007E; # "system check" load chunk SYSCHKCHNK: file = %O, start = $2E00, size = $0300; # "shadow RAM preparation" load chunk SRPREPCHNK: file = %O, define = yes, start = %S, size = $7C20 - %S - $07FF; # $07FF: space for temp. chargen buffer, 1K aligned # "main program" load chunk MAIN: file = %O, define = yes, start = %S + __LOWBSS_SIZE__, size = $D000 - __STACKSIZE__ - %S - __LOWBSS_SIZE__; # memory beneath the ROM preceeding the character generator HIDDEN_RAM2: file = "", define = yes, start = $D800, size = $0800; # address of relocated character generator (same addess as ROM version) CHARGEN: file = "", define = yes, start = $E000, size = $0400; # memory beneath the ROM HIDDEN_RAM: file = "", define = yes, start = $E400, size = $FFFA - $E400; # UNUSED - hide UNUSED: file = "", start = $0, size = $10; } FILES { %O: format = atari; } FORMATS { atari: runad = start, initad = SYSCHKCHNK: __SYSTEM_CHECK__, initad = SRPREPCHNK: sramprep; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXTZP: load = ZP, type = zp, optional = yes; SYSCHK: load = SYSCHKCHNK, type = rw, define = yes, optional = yes; LOWBSS: load = SRPREPCHNK, type = bss, define = yes; # shared btw. SRPREPCHNK and RAM, not zero initialized SRPREP: load = SRPREPCHNK, type = rw, define = yes; SHADOW_RAM: load = SRPREPCHNK, run = HIDDEN_RAM, type = rw, define = yes, optional = yes; SHADOW_RAM2: load = SRPREPCHNK, run = HIDDEN_RAM2, type = rw, define = yes, optional = yes; STARTUP: load = MAIN, type = ro, define = yes; LOWCODE: load = MAIN, type = ro, define = yes, optional = yes; ONCE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro, define = yes; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; INIT: load = MAIN, type = rw, optional = yes; BSS: load = MAIN, type = bss, define = yes; SRPREPHDR: load = UNUSED, type = ro; SRPREPTRL: load = UNUSED, type = ro; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/atarixl.cfg000066400000000000000000000104511347360151100150720ustar00rootroot00000000000000FEATURES { STARTADDRESS: default = $2400; } SYMBOLS { __EXEHDR__: type = import; __SYSTEM_CHECK__: type = import; # force inclusion of "system check" load chunk __AUTOSTART__: type = import; # force inclusion of autostart "trailer" __STACKSIZE__: type = weak, value = $0800; # 2k stack __STARTADDRESS__: type = export, value = %S; } MEMORY { ZP: file = "", define = yes, start = $0082, size = $007E; # just $FFFF HEADER: file = %O, start = $0000, size = $0002; # "system check" load chunk SYSCHKHDR: file = %O, start = $0000, size = $0004; SYSCHKCHNK: file = %O, start = $2E00, size = $0300; SYSCHKTRL: file = %O, start = $0000, size = $0006; # "shadow RAM preparation" load chunk SRPREPHDR: file = %O, start = $0000, size = $0004; SRPREPCHNK: file = %O, define = yes, start = %S, size = $7C20 - %S - $07FF; # $07FF: space for temp. chargen buffer, 1K aligned SRPREPTRL: file = %O, start = $0000, size = $0006; # "main program" load chunk MAINHDR: file = %O, start = $0000, size = $0004; MAIN: file = %O, define = yes, start = %S + __LOWBSS_SIZE__, size = $D000 - __STACKSIZE__ - %S - __LOWBSS_SIZE__; # defines entry point into program TRAILER: file = %O, start = $0000, size = $0006; # memory beneath the ROM preceeding the character generator HIDDEN_RAM2: file = "", define = yes, start = $D800, size = $0800; # address of relocated character generator (same addess as ROM version) CHARGEN: file = "", define = yes, start = $E000, size = $0400; # memory beneath the ROM HIDDEN_RAM: file = "", define = yes, start = $E400, size = $FFFA - $E400; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXTZP: load = ZP, type = zp, optional = yes; EXEHDR: load = HEADER, type = ro; SYSCHKHDR: load = SYSCHKHDR, type = ro, optional = yes; SYSCHK: load = SYSCHKCHNK, type = rw, define = yes, optional = yes; SYSCHKTRL: load = SYSCHKTRL, type = ro, optional = yes; SRPREPHDR: load = SRPREPHDR, type = ro; LOWBSS: load = SRPREPCHNK, type = bss, define = yes; # shared btw. SRPREPCHNK and RAM, not zero initialized SRPREP: load = SRPREPCHNK, type = rw, define = yes; SHADOW_RAM: load = SRPREPCHNK, run = HIDDEN_RAM, type = rw, define = yes, optional = yes; SHADOW_RAM2: load = SRPREPCHNK, run = HIDDEN_RAM2, type = rw, define = yes, optional = yes; SRPREPTRL: load = SRPREPTRL, type = ro; MAINHDR: load = MAINHDR, type = ro; STARTUP: load = MAIN, type = ro, define = yes; LOWCODE: load = MAIN, type = ro, define = yes, optional = yes; ONCE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro, define = yes; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; INIT: load = MAIN, type = rw, optional = yes; BSS: load = MAIN, type = bss, define = yes; AUTOSTRT: load = TRAILER, type = ro; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/atmos.cfg000066400000000000000000000037161347360151100145570ustar00rootroot00000000000000SYMBOLS { __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 = $001F; BASHEAD: file = %O, define = yes, start = $0501, size = $000D; MAIN: file = %O, define = yes, start = __BASHEAD_LAST__, size = __RAMEND__ - __MAIN_START__; BSS: file = "", start = __ONCE_RUN__, size = __RAMEND__ - __STACKSIZE__ - __ONCE_RUN__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; TAPEHDR: load = TAPEHDR, type = ro; BASHDR: load = BASHEAD, type = ro, optional = yes; STARTUP: load = MAIN, type = ro; LOWCODE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; INIT: load = MAIN, type = rw; ONCE: load = MAIN, type = ro, define = yes; BASTAIL: load = MAIN, type = ro, optional = yes; BSS: load = BSS, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/bbc.cfg000066400000000000000000000021361347360151100141550ustar00rootroot00000000000000SYMBOLS { __STACKSIZE__: type = weak, value = $0800; # 2k stack } MEMORY { ZP: file = "", define = yes, start = $0070, size = $0020; MAIN: file = %O, start = $0E00, size = $7200 - __STACKSIZE__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; STARTUP: load = MAIN, type = ro, define = yes; LOWCODE: load = MAIN, type = ro, optional = yes; ONCE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; BSS: load = MAIN, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/c128-overlay.cfg000066400000000000000000000104151347360151100155620ustar00rootroot00000000000000SYMBOLS { __LOADADDR__: type = import; __EXEHDR__: type = import; __OVERLAYADDR__: type = import; __STACKSIZE__: type = weak, value = $0800; # 2k stack __OVERLAYSIZE__: type = weak, value = $1000; # 4k overlay } MEMORY { ZP: file = "", define = yes, start = $0002, size = $001A; LOADADDR: file = %O, start = $1BFF, size = $0002; HEADER: file = %O, start = $1C01, size = $000C; MAIN: file = %O, define = yes, start = $1C0D, size = $A3F3 - __OVERLAYSIZE__ - __STACKSIZE__; OVL1ADDR: file = "%O.1", start = $BFFE - __OVERLAYSIZE__, size = $0002; OVL1: file = "%O.1", start = $C000 - __OVERLAYSIZE__, size = __OVERLAYSIZE__; OVL2ADDR: file = "%O.2", start = $BFFE - __OVERLAYSIZE__, size = $0002; OVL2: file = "%O.2", start = $C000 - __OVERLAYSIZE__, size = __OVERLAYSIZE__; OVL3ADDR: file = "%O.3", start = $BFFE - __OVERLAYSIZE__, size = $0002; OVL3: file = "%O.3", start = $C000 - __OVERLAYSIZE__, size = __OVERLAYSIZE__; OVL4ADDR: file = "%O.4", start = $BFFE - __OVERLAYSIZE__, size = $0002; OVL4: file = "%O.4", start = $C000 - __OVERLAYSIZE__, size = __OVERLAYSIZE__; OVL5ADDR: file = "%O.5", start = $BFFE - __OVERLAYSIZE__, size = $0002; OVL5: file = "%O.5", start = $C000 - __OVERLAYSIZE__, size = __OVERLAYSIZE__; OVL6ADDR: file = "%O.6", start = $BFFE - __OVERLAYSIZE__, size = $0002; OVL6: file = "%O.6", start = $C000 - __OVERLAYSIZE__, size = __OVERLAYSIZE__; OVL7ADDR: file = "%O.7", start = $BFFE - __OVERLAYSIZE__, size = $0002; OVL7: file = "%O.7", start = $C000 - __OVERLAYSIZE__, size = __OVERLAYSIZE__; OVL8ADDR: file = "%O.8", start = $BFFE - __OVERLAYSIZE__, size = $0002; OVL8: file = "%O.8", start = $C000 - __OVERLAYSIZE__, size = __OVERLAYSIZE__; OVL9ADDR: file = "%O.9", start = $BFFE - __OVERLAYSIZE__, size = $0002; OVL9: file = "%O.9", start = $C000 - __OVERLAYSIZE__, size = __OVERLAYSIZE__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; LOADADDR: load = LOADADDR, type = ro; EXEHDR: load = HEADER, type = ro; STARTUP: load = MAIN, type = ro; LOWCODE: load = MAIN, type = ro, optional = yes; ONCE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; INIT: load = MAIN, type = bss; BSS: load = MAIN, type = bss, define = yes; OVL1ADDR: load = OVL1ADDR, type = ro; OVERLAY1: load = OVL1, type = ro, define = yes, optional = yes; OVL2ADDR: load = OVL2ADDR, type = ro; OVERLAY2: load = OVL2, type = ro, define = yes, optional = yes; OVL3ADDR: load = OVL3ADDR, type = ro; OVERLAY3: load = OVL3, type = ro, define = yes, optional = yes; OVL4ADDR: load = OVL4ADDR, type = ro; OVERLAY4: load = OVL4, type = ro, define = yes, optional = yes; OVL5ADDR: load = OVL5ADDR, type = ro; OVERLAY5: load = OVL5, type = ro, define = yes, optional = yes; OVL6ADDR: load = OVL6ADDR, type = ro; OVERLAY6: load = OVL6, type = ro, define = yes, optional = yes; OVL7ADDR: load = OVL7ADDR, type = ro; OVERLAY7: load = OVL7, type = ro, define = yes, optional = yes; OVL8ADDR: load = OVL8ADDR, type = ro; OVERLAY8: load = OVL8, type = ro, define = yes, optional = yes; OVL9ADDR: load = OVL9ADDR, type = ro; OVERLAY9: load = OVL9, type = ro, define = yes, optional = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/c128.cfg000066400000000000000000000027001347360151100141010ustar00rootroot00000000000000SYMBOLS { __LOADADDR__: type = import; __EXEHDR__: type = import; __STACKSIZE__: type = weak, value = $0800; # 2k stack } MEMORY { ZP: file = "", define = yes, start = $0002, size = $001A; LOADADDR: file = %O, start = $1BFF, size = $0002; HEADER: file = %O, start = $1C01, size = $000C; MAIN: file = %O, define = yes, start = $1C0D, size = $A3F3 - __STACKSIZE__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; LOADADDR: load = LOADADDR, type = ro; EXEHDR: load = HEADER, type = ro; STARTUP: load = MAIN, type = ro; LOWCODE: load = MAIN, type = ro, optional = yes; ONCE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; INIT: load = MAIN, type = bss; BSS: load = MAIN, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/c16-32k.cfg000066400000000000000000000027001347360151100144120ustar00rootroot00000000000000SYMBOLS { __LOADADDR__: type = import; __EXEHDR__: type = import; __STACKSIZE__: type = weak, value = $0800; # 2k stack } MEMORY { ZP: file = "", define = yes, start = $0002, size = $001A; LOADADDR: file = %O, start = $0FFF, size = $0002; HEADER: file = %O, start = $1001, size = $000C; MAIN: file = %O, start = $100D, size = $6FF3 - __STACKSIZE__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; LOADADDR: load = LOADADDR, type = ro; EXEHDR: load = HEADER, type = ro; STARTUP: load = MAIN, type = ro; LOWCODE: load = MAIN, type = ro, optional = yes; ONCE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; INIT: load = MAIN, type = bss; BSS: load = MAIN, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/c16.cfg000066400000000000000000000027001347360151100140150ustar00rootroot00000000000000SYMBOLS { __LOADADDR__: type = import; __EXEHDR__: type = import; __STACKSIZE__: type = weak, value = $0400; # 1k stack } MEMORY { ZP: file = "", define = yes, start = $0002, size = $001A; LOADADDR: file = %O, start = $0FFF, size = $0002; HEADER: file = %O, start = $1001, size = $000C; MAIN: file = %O, start = $100D, size = $2FF3 - __STACKSIZE__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; LOADADDR: load = LOADADDR, type = ro; EXEHDR: load = HEADER, type = ro; STARTUP: load = MAIN, type = ro; LOWCODE: load = MAIN, type = ro, optional = yes; ONCE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; INIT: load = MAIN, type = bss; BSS: load = MAIN, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/c64-asm.cfg000066400000000000000000000012731347360151100146020ustar00rootroot00000000000000FEATURES { STARTADDRESS: default = $0801; } SYMBOLS { __LOADADDR__: type = import; } MEMORY { ZP: file = "", start = $0002, size = $00FE, define = yes; LOADADDR: file = %O, start = %S - 2, size = $0002; MAIN: file = %O, start = %S, size = $D000 - %S; } SEGMENTS { ZEROPAGE: load = ZP, type = zp, optional = yes; LOADADDR: load = LOADADDR, type = ro; EXEHDR: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = rw; RODATA: load = MAIN, type = ro, optional = yes; DATA: load = MAIN, type = rw, optional = yes; BSS: load = MAIN, type = bss, optional = yes, define = yes; } cc65-2.18/cfg/c64-overlay.cfg000066400000000000000000000107421347360151100155040ustar00rootroot00000000000000FEATURES { 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 __HIMEM__: type = weak, value = $D000; __OVERLAYSTART__: type = export, value = __HIMEM__ - __OVERLAYSIZE__; } MEMORY { ZP: file = "", define = yes, start = $0002, size = $001A; LOADADDR: file = %O, start = %S - 2, size = $0002; HEADER: file = %O, define = yes, start = %S, size = $000D; MAIN: file = %O, define = yes, start = __HEADER_LAST__, size = __HIMEM__ - __HEADER_LAST__; BSS: file = "", start = __ONCE_RUN__, size = __OVERLAYSTART__ - __STACKSIZE__ - __ONCE_RUN__; OVL1ADDR: file = "%O.1", start = __OVERLAYSTART__ - 2, size = $0002; OVL1: file = "%O.1", start = __OVERLAYSTART__, size = __OVERLAYSIZE__; OVL2ADDR: file = "%O.2", start = __OVERLAYSTART__ - 2, size = $0002; 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 { ZEROPAGE: load = ZP, type = zp; LOADADDR: load = LOADADDR, type = ro; EXEHDR: load = HEADER, type = ro; STARTUP: load = MAIN, type = ro; LOWCODE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; INIT: load = MAIN, type = rw; ONCE: load = MAIN, type = ro, define = yes; BSS: load = BSS, type = bss, define = yes; OVL1ADDR: load = OVL1ADDR, type = ro; OVERLAY1: load = OVL1, type = ro, define = yes, optional = yes; OVL2ADDR: load = OVL2ADDR, type = ro; OVERLAY2: load = OVL2, type = ro, define = yes, optional = yes; OVL3ADDR: load = OVL3ADDR, type = ro; OVERLAY3: load = OVL3, type = ro, define = yes, optional = yes; OVL4ADDR: load = OVL4ADDR, type = ro; OVERLAY4: load = OVL4, type = ro, define = yes, optional = yes; OVL5ADDR: load = OVL5ADDR, type = ro; OVERLAY5: load = OVL5, type = ro, define = yes, optional = yes; OVL6ADDR: load = OVL6ADDR, type = ro; OVERLAY6: load = OVL6, type = ro, define = yes, optional = yes; OVL7ADDR: load = OVL7ADDR, type = ro; OVERLAY7: load = OVL7, type = ro, define = yes, optional = yes; OVL8ADDR: load = OVL8ADDR, type = ro; OVERLAY8: load = OVL8, type = ro, define = yes, optional = yes; OVL9ADDR: load = OVL9ADDR, type = ro; OVERLAY9: load = OVL9, type = ro, define = yes, optional = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/c64.cfg000066400000000000000000000032751347360151100140300ustar00rootroot00000000000000FEATURES { 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 = %S - 2, size = $0002; HEADER: file = %O, define = yes, start = %S, size = $000D; MAIN: file = %O, define = yes, start = __HEADER_LAST__, size = __HIMEM__ - __HEADER_LAST__; BSS: file = "", start = __ONCE_RUN__, size = __HIMEM__ - __STACKSIZE__ - __ONCE_RUN__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; LOADADDR: load = LOADADDR, type = ro; EXEHDR: load = HEADER, type = ro; STARTUP: load = MAIN, type = ro; LOWCODE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; INIT: load = MAIN, type = rw; ONCE: load = MAIN, type = ro, define = yes; BSS: load = BSS, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/cbm510.cfg000066400000000000000000000035351347360151100144220ustar00rootroot00000000000000SYMBOLS { # The stack starts from $FEC3 and grows towards the video ram __STACKSIZE__: type = weak, value = $06C3; # ~1.5k stack } MEMORY { HEADER: file = %O, start = $0001, size = $0050, fill = yes; ZP: file = %O, define = yes, start = $0051, size = $00AD, fill = yes; STARTUP: file = %O, start = $00FE, size = $0102, fill = yes; PAGE2: file = %O, start = $0200, size = $0100, fill = yes; PAGE3: file = %O, start = $0300, size = $0100, fill = yes; MAIN: file = %O, start = $0400, size = $DC00; CHARRAM: file = "", define = yes, start = $E000, size = $1000; VIDRAM: file = "", define = yes, start = $F000, size = $0400; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXTZP: load = ZP, type = rw, define = yes; EXEHDR: load = HEADER, type = rw; STARTUP: load = STARTUP, type = rw; PAGE2: load = PAGE2, type = rw; PAGE3: load = PAGE3, type = rw; LOWCODE: load = MAIN, type = ro, optional = yes; ONCE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; INIT: load = MAIN, type = bss, optional = yes; BSS: load = MAIN, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/cbm610.cfg000066400000000000000000000032421347360151100144160ustar00rootroot00000000000000SYMBOLS { __STACKSIZE__: type = weak, value = $0800; # 2k stack } MEMORY { HEADER: file = %O, start = $0001, size = $0050, fill = yes; ZP: file = %O, define = yes, start = $0051, size = $00AD, fill = yes; STARTUP: file = %O, start = $00FE, size = $0102, fill = yes; PAGE2: file = %O, start = $0200, size = $0100, fill = yes; PAGE3: file = %O, start = $0300, size = $0100, fill = yes; MAIN: file = %O, start = $0400, size = $FECB - __STACKSIZE__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXTZP: load = ZP, type = rw, define = yes; EXEHDR: load = HEADER, type = rw; STARTUP: load = STARTUP, type = rw; PAGE2: load = PAGE2, type = rw; PAGE3: load = PAGE3, type = rw; LOWCODE: load = MAIN, type = ro, optional = yes; ONCE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; INIT: load = MAIN, type = bss, optional = yes; BSS: load = MAIN, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/creativision.cfg000066400000000000000000000030551347360151100161270ustar00rootroot00000000000000SYMBOLS { __STACKSIZE__: type = weak, value = $0040; } MEMORY { ZP: file = "", define = yes, start = $0020, size = $00E0; RAM: file = "", define = yes, start = $01FA, size = $0206 - __STACKSIZE__; ROM: file = %O, define = yes, start = $B000, size = $1000, fill = yes, fillval = $FF; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; ZP: load = ZP, type = zp, optional = yes; VECTORS: load = ROM, run = RAM, type = rw, define = yes; DATA: load = ROM, run = RAM, type = rw, define = yes, start = $0204; BSS: load = RAM, type = bss, define = yes; ONCE: load = ROM, type = ro, optional = yes; CODE: load = ROM, type = ro; INIT: load = ROM, type = ro; RODATA: load = ROM, type = ro; AUDIO: load = ROM, type = ro, optional = yes, start = $BF00; SETUP: load = ROM, type = ro, start = $BFE8; } 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__; } cc65-2.18/cfg/gamate.cfg000066400000000000000000000042371347360151100146710ustar00rootroot00000000000000# linker config to produce simple Gamate cartridge (.bin) SYMBOLS { __STARTUP__: type = import; __STACKSIZE__: type = weak, value = $0080; # 1 page stack } MEMORY { # 0000-03ff is RAM # FIXME: what zp range can we actually use? # $0a-$11 is used by IRQ/NMI, $e8 is used by NMI ZP: start = $0012, size = $00E8 - $0012; CPUSTACK: start = $0100, size = $0100; RAM: start = $0200, size = $0200 - __STACKSIZE__, define = yes; CARTHEADER: file = %O, define = yes, start = %S, size = $0029; # 6000-e000 can be (Cartridge) ROM # WARNING: fill value must be $00 else it will no more work #ROM: start = $6000, size = $1000, fill = yes, fillval = $00, file = %O, define = yes; #ROMFILL: start = $7000, size = $7000, fill = yes, fillval = $00, file = %O, define = yes; # for images that have code >$6fff we must calculate the checksum! ROM: start = $6000 + $0029, size = $8000 - $0029, fill = yes, fillval = $00, file = %O, define = yes; } SEGMENTS { ZEROPAGE: load = ZP, type = zp, define = yes; EXTZP: load = ZP, type = zp, define = yes, optional = yes; APPZP: load = ZP, type = zp, define = yes, optional = yes; STARTUP: load = CARTHEADER, type = ro, define = yes; ONCE: load = ROM, type = ro, optional = yes; CODE: load = ROM, type = ro, define = yes; RODATA: load = ROM, type = ro, define = yes; DATA: load = ROM, run = RAM, type = rw, define = yes; BSS: load = RAM, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/geos-apple.cfg000066400000000000000000000160531347360151100154660ustar00rootroot00000000000000FEATURES { STARTADDRESS: default = $4000; } SYMBOLS { __BACKBUFSIZE__: type = weak, value = $2000; __HIMEM__: type = weak, value = $C000 - __BACKBUFSIZE__; __OVERLAYSIZE__: type = weak, value = $0000; __OVERLAYADDR__: type = weak, value = __HIMEM__ - __OVERLAYSIZE__; __STACKSIZE__: type = weak, value = $0400; # 1k stack __STACKADDR__: type = weak, value = $2000 - __STACKSIZE__; } MEMORY { CVT: file = %O, start = $0, size = $20000; ZP: define = yes, start = $80, size = $1A + $06; EXT: define = yes, start = $0C00, size = __STACKADDR__ - __EXT_START__; VLIR0: define = yes, start = %S, size = __OVERLAYADDR__ - %S; VLIR1: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR2: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR3: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR4: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR5: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR6: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR7: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR8: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR9: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR10: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR11: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR12: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR13: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR14: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR15: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR16: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR17: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR18: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR19: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; } SEGMENTS { ZEROPAGE: type = zp, load = ZP; EXTZP: type = zp, load = ZP, optional = yes; EXTBSS: type = bss, load = EXT, define = yes, optional = yes; FILEINFO: type = ro, load = CVT, offset = $002; RECORDS: type = ro, load = CVT, offset = $100, optional = yes; DIRENTRY: type = ro, load = CVT, offset = $180; VLIRIDX0: type = ro, load = CVT, align = $200, optional = yes; STARTUP: type = ro, run = VLIR0, load = CVT, align_load = $200, define = yes; LOWCODE: type = ro, run = VLIR0, load = CVT, optional = yes; ONCE: type = ro, run = VLIR0, load = CVT, optional = yes; CODE: type = ro, run = VLIR0, load = CVT; RODATA: type = ro, run = VLIR0, load = CVT; DATA: type = rw, run = VLIR0, load = CVT; INIT: type = bss, load = VLIR0, optional = yes; BSS: type = bss, load = VLIR0, define = yes; VLIRIDX1: type = ro, load = CVT, align = $200, optional = yes; OVERLAY1: type = ro, run = VLIR1, load = CVT, align_load = $200, optional = yes; VLIRIDX2: type = ro, load = CVT, align = $200, optional = yes; OVERLAY2: type = ro, run = VLIR2, load = CVT, align_load = $200, optional = yes; VLIRIDX3: type = ro, load = CVT, align = $200, optional = yes; OVERLAY3: type = ro, run = VLIR3, load = CVT, align_load = $200, optional = yes; VLIRIDX4: type = ro, load = CVT, align = $200, optional = yes; OVERLAY4: type = ro, run = VLIR4, load = CVT, align_load = $200, optional = yes; VLIRIDX5: type = ro, load = CVT, align = $200, optional = yes; OVERLAY5: type = ro, run = VLIR5, load = CVT, align_load = $200, optional = yes; VLIRIDX6: type = ro, load = CVT, align = $200, optional = yes; OVERLAY6: type = ro, run = VLIR6, load = CVT, align_load = $200, optional = yes; VLIRIDX7: type = ro, load = CVT, align = $200, optional = yes; OVERLAY7: type = ro, run = VLIR7, load = CVT, align_load = $200, optional = yes; VLIRIDX8: type = ro, load = CVT, align = $200, optional = yes; OVERLAY8: type = ro, run = VLIR8, load = CVT, align_load = $200, optional = yes; VLIRIDX9: type = ro, load = CVT, align = $200, optional = yes; OVERLAY9: type = ro, run = VLIR9, load = CVT, align_load = $200, optional = yes; VLIRIDX10: type = ro, load = CVT, align = $200, optional = yes; OVERLAY10: type = ro, run = VLIR10, load = CVT, align_load = $200, optional = yes; VLIRIDX11: type = ro, load = CVT, align = $200, optional = yes; OVERLAY11: type = ro, run = VLIR11, load = CVT, align_load = $200, optional = yes; VLIRIDX12: type = ro, load = CVT, align = $200, optional = yes; OVERLAY12: type = ro, run = VLIR12, load = CVT, align_load = $200, optional = yes; VLIRIDX13: type = ro, load = CVT, align = $200, optional = yes; OVERLAY13: type = ro, run = VLIR13, load = CVT, align_load = $200, optional = yes; VLIRIDX14: type = ro, load = CVT, align = $200, optional = yes; OVERLAY14: type = ro, run = VLIR14, load = CVT, align_load = $200, optional = yes; VLIRIDX15: type = ro, load = CVT, align = $200, optional = yes; OVERLAY15: type = ro, run = VLIR15, load = CVT, align_load = $200, optional = yes; VLIRIDX16: type = ro, load = CVT, align = $200, optional = yes; OVERLAY16: type = ro, run = VLIR16, load = CVT, align_load = $200, optional = yes; VLIRIDX17: type = ro, load = CVT, align = $200, optional = yes; OVERLAY17: type = ro, run = VLIR17, load = CVT, align_load = $200, optional = yes; VLIRIDX18: type = ro, load = CVT, align = $200, optional = yes; OVERLAY18: type = ro, run = VLIR18, load = CVT, align_load = $200, optional = yes; VLIRIDX19: type = ro, load = CVT, align = $200, optional = yes; OVERLAY19: type = ro, run = VLIR19, load = CVT, align_load = $200, optional = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/geos-cbm.cfg000066400000000000000000000121611347360151100151220ustar00rootroot00000000000000FEATURES { STARTADDRESS: default = $0400; } SYMBOLS { __BACKBUFSIZE__: type = weak, value = $2000; __HIMEM__: type = weak, value = $8000 - __BACKBUFSIZE__; __OVERLAYSIZE__: type = weak, value = $0000; __OVERLAYADDR__: type = weak, value = __HIMEM__ - __OVERLAYSIZE__; __STACKSIZE__: type = weak, value = $0400; # 1k stack __STACKADDR__: type = weak, value = __OVERLAYADDR__ - __STACKSIZE__; } MEMORY { CVT: file = %O, start = $0, size = $40000; ZP: define = yes, start = $58, size = $1A + $06; VLIR0: define = yes, start = %S, size = __STACKADDR__ - %S; VLIR1: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR2: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR3: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR4: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR5: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR6: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR7: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR8: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR9: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR10: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR11: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR12: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR13: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR14: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR15: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR16: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR17: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR18: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; VLIR19: define = yes, start = __OVERLAYADDR__, size = __OVERLAYSIZE__; } SEGMENTS { ZEROPAGE: type = zp, load = ZP; EXTZP: type = zp, load = ZP, optional = yes; DIRENTRY: type = ro, load = CVT, align = $FE; FILEINFO: type = ro, load = CVT, align = $FE; RECORDS: type = ro, load = CVT, align = $FE, optional = yes; STARTUP: type = ro, run = VLIR0, load = CVT, align_load = $FE, define = yes; LOWCODE: type = ro, run = VLIR0, load = CVT, optional = yes; ONCE: type = ro, run = VLIR0, load = CVT, optional = yes; CODE: type = ro, run = VLIR0, load = CVT; RODATA: type = ro, run = VLIR0, load = CVT; DATA: type = rw, run = VLIR0, load = CVT; INIT: type = bss, load = VLIR0, optional = yes; BSS: type = bss, load = VLIR0, define = yes; OVERLAY1: type = ro, run = VLIR1, load = CVT, align_load = $FE, optional = yes; OVERLAY2: type = ro, run = VLIR2, load = CVT, align_load = $FE, optional = yes; OVERLAY3: type = ro, run = VLIR3, load = CVT, align_load = $FE, optional = yes; OVERLAY4: type = ro, run = VLIR4, load = CVT, align_load = $FE, optional = yes; OVERLAY5: type = ro, run = VLIR5, load = CVT, align_load = $FE, optional = yes; OVERLAY6: type = ro, run = VLIR6, load = CVT, align_load = $FE, optional = yes; OVERLAY7: type = ro, run = VLIR7, load = CVT, align_load = $FE, optional = yes; OVERLAY8: type = ro, run = VLIR8, load = CVT, align_load = $FE, optional = yes; OVERLAY9: type = ro, run = VLIR9, load = CVT, align_load = $FE, optional = yes; OVERLAY10: type = ro, run = VLIR10, load = CVT, align_load = $FE, optional = yes; OVERLAY11: type = ro, run = VLIR11, load = CVT, align_load = $FE, optional = yes; OVERLAY12: type = ro, run = VLIR12, load = CVT, align_load = $FE, optional = yes; OVERLAY13: type = ro, run = VLIR13, load = CVT, align_load = $FE, optional = yes; OVERLAY14: type = ro, run = VLIR14, load = CVT, align_load = $FE, optional = yes; OVERLAY15: type = ro, run = VLIR15, load = CVT, align_load = $FE, optional = yes; OVERLAY16: type = ro, run = VLIR16, load = CVT, align_load = $FE, optional = yes; OVERLAY17: type = ro, run = VLIR17, load = CVT, align_load = $FE, optional = yes; OVERLAY18: type = ro, run = VLIR18, load = CVT, align_load = $FE, optional = yes; OVERLAY19: type = ro, run = VLIR19, load = CVT, align_load = $FE, optional = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/lunix.cfg000066400000000000000000000032641347360151100145710ustar00rootroot00000000000000# ld65 Linker-configuration for LUnix, Next Generation. SYMBOLS { __HEAPSIZE__: type = weak, value = $2000; # 8k heap [temporary, until LUnix malloc() exists] __STACKSIZE__: type = weak, value = $0400; # 1k stack (do typical LUnix apps. need 2k?) } MEMORY { ZP: start = $0080, size = $0040; MAIN: start = %S, size = $7600 - __STACKSIZE__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp, define = yes; # Pseudo-registers STARTUP: load = MAIN, type = ro; # First initialization code LOWCODE: load = MAIN, type = ro, optional = yes; # Legacy from other platforms ONCE: load = MAIN, type = ro, optional = yes; # Library initialization code CODE: load = MAIN, type = ro; # Program RODATA: load = MAIN, type = ro; # Literals, constants DATA: load = MAIN, type = rw; # Initialized variables BSS: load = MAIN, type = bss, define = yes; # Uninitialized variables } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } FILES { %O: format = o65; } FORMATS { o65: os = lunix, type = small, export = main, # Program entry-point import = LUNIXKERNEL; # Kernel entry-points } cc65-2.18/cfg/lynx-bll.cfg000066400000000000000000000033101347360151100151630ustar00rootroot00000000000000SYMBOLS { __STACKSIZE__: type = weak, value = $0800; # 2k stack __STARTOFDIRECTORY__: type = weak, value = $00CB; # start just after loader __BANK0BLOCKSIZE__: type = weak, value = $0400; # bank 0 cart block size __BANK1BLOCKSIZE__: type = weak, value = $0000; # bank 1 block size __BLLHDR__: type = import; } MEMORY { ZP: file = "", define = yes, start = $0000, size = $0100; HEADER: file = %O, start = $0000, size = $000a; MAIN: file = %O, define = yes, start = $0400, size = $BC38 - __STACKSIZE__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXTZP: load = ZP, type = zp, optional = yes; APPZP: load = ZP, type = zp, optional = yes; BLLHDR: load = HEADER, type = ro; STARTUP: load = MAIN, type = ro, define = yes; LOWCODE: load = MAIN, type = ro, define = yes, optional = yes; ONCE: load = MAIN, type = ro, define = yes, optional = yes; CODE: load = MAIN, type = ro, define = yes; RODATA: load = MAIN, type = ro, define = yes; DATA: load = MAIN, type = rw, define = yes; BSS: load = MAIN, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/lynx-coll.cfg000066400000000000000000000040061347360151100153460ustar00rootroot00000000000000SYMBOLS { __STACKSIZE__: type = weak, value = $0800; # 2k stack __STARTOFDIRECTORY__: type = weak, value = $00CB; # start just after loader __BANK0BLOCKSIZE__: type = weak, value = $0400; # bank 0 cart block size __BANK1BLOCKSIZE__: type = weak, value = $0000; # bank 1 block size __EXEHDR__: type = import; __BOOTLDR__: type = import; __DEFDIR__: type = import; } MEMORY { ZP: file = "", define = yes, start = $0000, size = $0100; HEADER: file = %O, start = $0000, size = $0040; BOOT: file = %O, start = $0200, size = __STARTOFDIRECTORY__; DIR: file = %O, start = $0000, size = 8; MAIN: file = %O, define = yes, start = $0200, size = $9E58 - __STACKSIZE__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXTZP: load = ZP, type = zp, optional = yes; APPZP: load = ZP, type = zp, optional = yes; EXEHDR: load = HEADER, type = ro; BOOTLDR: load = BOOT, type = ro; DIRECTORY: load = DIR, type = ro; STARTUP: load = MAIN, type = ro, define = yes; LOWCODE: load = MAIN, type = ro, define = yes, optional = yes; ONCE: load = MAIN, type = ro, define = yes, optional = yes; CODE: load = MAIN, type = ro, define = yes; RODATA: load = MAIN, type = ro, define = yes; DATA: load = MAIN, type = rw, define = yes; BSS: load = MAIN, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/lynx-uploader.cfg000066400000000000000000000043221347360151100162310ustar00rootroot00000000000000SYMBOLS { __STACKSIZE__: type = weak, value = $0800; # 2k stack __STARTOFDIRECTORY__: type = weak, value = $00CB; # start just after loader __BANK0BLOCKSIZE__: type = weak, value = $0400; # bank 0 cart block size __BANK1BLOCKSIZE__: type = weak, value = $0000; # bank 1 block size __EXEHDR__: type = import; __BOOTLDR__: type = import; __DEFDIR__: type = import; __UPLOADER__: type = import; } MEMORY { ZP: file = "", define = yes, start = $0000, size = $0100; HEADER: file = %O, start = $0000, size = $0040; BOOT: file = %O, start = $0200, size = __STARTOFDIRECTORY__; DIR: file = %O, start = $0000, size = 8; MAIN: file = %O, define = yes, start = $0200, size = $BD38 - __STACKSIZE__; UPLDR: file = %O, define = yes, start = $BFDC, size = $005C; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXTZP: load = ZP, type = zp, optional = yes; APPZP: load = ZP, type = zp, optional = yes; EXEHDR: load = HEADER, type = ro; BOOTLDR: load = BOOT, type = ro; DIRECTORY:load = DIR, type = ro; STARTUP: load = MAIN, type = ro, define = yes; LOWCODE: load = MAIN, type = ro, define = yes, optional = yes; ONCE: load = MAIN, type = ro, define = yes, optional = yes; CODE: load = MAIN, type = ro, define = yes; RODATA: load = MAIN, type = ro, define = yes; DATA: load = MAIN, type = rw, define = yes; BSS: load = MAIN, type = bss, define = yes; UPCODE: load = UPLDR, type = ro, define = yes; UPDATA: load = UPLDR, type = rw, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/lynx.cfg000066400000000000000000000040061347360151100144170ustar00rootroot00000000000000SYMBOLS { __STACKSIZE__: type = weak, value = $0800; # 2k stack __STARTOFDIRECTORY__: type = weak, value = $00CB; # start just after loader __BANK0BLOCKSIZE__: type = weak, value = $0400; # bank 0 cart block size __BANK1BLOCKSIZE__: type = weak, value = $0000; # bank 1 block size __EXEHDR__: type = import; __BOOTLDR__: type = import; __DEFDIR__: type = import; } MEMORY { ZP: file = "", define = yes, start = $0000, size = $0100; HEADER: file = %O, start = $0000, size = $0040; BOOT: file = %O, start = $0200, size = __STARTOFDIRECTORY__; DIR: file = %O, start = $0000, size = 8; MAIN: file = %O, define = yes, start = $0200, size = $BE38 - __STACKSIZE__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXTZP: load = ZP, type = zp, optional = yes; APPZP: load = ZP, type = zp, optional = yes; EXEHDR: load = HEADER, type = ro; BOOTLDR: load = BOOT, type = ro; DIRECTORY: load = DIR, type = ro; STARTUP: load = MAIN, type = ro, define = yes; LOWCODE: load = MAIN, type = ro, define = yes, optional = yes; ONCE: load = MAIN, type = ro, define = yes, optional = yes; CODE: load = MAIN, type = ro, define = yes; RODATA: load = MAIN, type = ro, define = yes; DATA: load = MAIN, type = rw, define = yes; BSS: load = MAIN, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/module.cfg000066400000000000000000000011161347360151100147110ustar00rootroot00000000000000MEMORY { ZP: start = $0000, size = $0100; COMBINED: file = %O, start = $0000, size = $FFFF; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXTZP: load = ZP, type = zp, optional = yes; HEADER: load = COMBINED, type = ro; ONCE: load = COMBINED, type = ro, optional = yes; CODE: load = COMBINED, type = ro; RODATA: load = COMBINED, type = ro; DATA: load = COMBINED, type = rw; BSS: load = COMBINED, type = bss; } FILES { %O: format = o65; } FORMATS { o65: os = cc65, type = small; } cc65-2.18/cfg/nes.cfg000066400000000000000000000042021347360151100142100ustar00rootroot00000000000000SYMBOLS { __STACKSIZE__: type = weak, value = $0300; # 3 pages stack } MEMORY { ZP: file = "", start = $0002, size = $001A, type = rw, define = yes; # INES Cartridge Header HEADER: file = %O, start = $0000, size = $0010, fill = yes; # 2 16K ROM Banks # - startup # - code # - rodata # - data (load) ROM0: file = %O, start = $8000, size = $7FFA, fill = yes, define = yes; # Hardware Vectors at End of 2nd 8K ROM ROMV: file = %O, start = $FFFA, size = $0006, fill = yes; # 1 8k CHR Bank ROM2: file = %O, start = $0000, size = $2000, fill = yes; # standard 2k SRAM (-zeropage) # $0100-$0200 cpu stack # $0200-$0500 3 pages for ppu memory write buffer # $0500-$0800 3 pages for cc65 parameter stack SRAM: file = "", start = $0500, size = __STACKSIZE__, define = yes; # additional 8K SRAM Bank # - data (run) # - bss # - heap RAM: file = "", start = $6000, size = $2000, define = yes; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; HEADER: load = HEADER, type = ro; STARTUP: load = ROM0, type = ro, define = yes; LOWCODE: load = ROM0, type = ro, optional = yes; ONCE: load = ROM0, type = ro, optional = yes; CODE: load = ROM0, type = ro, define = yes; RODATA: load = ROM0, type = ro, define = yes; DATA: load = ROM0, run = RAM, type = rw, define = yes; VECTORS: load = ROMV, type = rw; CHARS: load = ROM2, type = rw; BSS: load = RAM, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/none.cfg000066400000000000000000000024111347360151100143620ustar00rootroot00000000000000FEATURES { STARTADDRESS: default = $1000; } SYMBOLS { __STACKSIZE__: type = weak, value = $0800; # 2k stack __STACKSTART__: type = weak, value = $8000; __ZPSTART__: type = weak, value = $0080; } MEMORY { ZP: file = "", define = yes, start = __ZPSTART__, size = $001F; MAIN: file = %O, start = %S, size = __STACKSTART__ - __STACKSIZE__ - %S; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; STARTUP: load = MAIN, type = ro, optional = yes; LOWCODE: load = MAIN, type = ro, optional = yes; ONCE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = rw; RODATA: load = MAIN, type = rw; DATA: load = MAIN, type = rw; BSS: load = MAIN, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/osic1p-asm.cfg000066400000000000000000000017531347360151100154070ustar00rootroot00000000000000FEATURES { 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 = $00FE; HEAD: file = %O, start = $0000, size = $00B6; MAIN: file = %O, define = yes, start = %S, size = __HIMEM__ - __STACKSIZE__ - %S; } SEGMENTS { ZEROPAGE: load = ZP, type = zp, optional = yes; BOOT: load = HEAD, type = ro, optional = yes; CODE: load = MAIN, type = rw; RODATA: load = MAIN, type = ro, optional = yes; DATA: load = MAIN, type = rw, optional = yes; BSS: load = MAIN, type = bss, optional = yes, define = yes; } cc65-2.18/cfg/osic1p.cfg000066400000000000000000000027541347360151100146330ustar00rootroot00000000000000FEATURES { 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; MAIN: file = %O, define = yes, start = %S, size = __HIMEM__ - __STACKSIZE__ - %S; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXTZP: load = ZP, type = zp, define = yes, optional = yes; BOOT: load = HEAD, type = ro, optional = yes; STARTUP: load = MAIN, type = ro; LOWCODE: load = MAIN, type = ro, optional = yes; ONCE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = rw; RODATA: load = MAIN, type = rw; DATA: load = MAIN, type = rw; BSS: load = MAIN, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; } cc65-2.18/cfg/pce.cfg000066400000000000000000000034621347360151100142010ustar00rootroot00000000000000# Linker config. to produce a NEC PC-Engine 8K, 16K, or 32K image (.bin) SYMBOLS { __CARTSIZE__: type = weak, value = $2000; # $2000, $4000, or $8000 __STACKSIZE__: type = weak, value = $0300; # 3 pages stack } MEMORY { ZP: file = "", start = $0000, define = yes, size = $0100; # RAM bank MAIN: file = "", start = $2200, define = yes, size = $1E00 - __STACKSIZE__; # ROM banks, before swapping, and after mapping ROM: file = %O, start = $10000 - __CARTSIZE__, size = __CARTSIZE__, fill = yes, fillval = $FF; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXTZP: load = ZP, type = zp, optional = yes; APPZP: load = ZP, type = zp, optional = yes; DATA: load = ROM, run = MAIN, type = rw, define = yes; INIT: load = MAIN, type = bss, optional = yes; BSS: load = MAIN, type = bss, define = yes; RODATA: load = ROM, type = ro; CODE: load = ROM, type = ro; LOWCODE: load = ROM, type = ro, optional = yes; ONCE: load = ROM, type = ro, optional = yes; STARTUP: load = ROM, type = ro, start = $FFF6 - $0066; VECTORS: load = ROM, type = ro, start = $FFF6; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/pet.cfg000066400000000000000000000027001347360151100142140ustar00rootroot00000000000000SYMBOLS { __LOADADDR__: type = import; __EXEHDR__: type = import; __STACKSIZE__: type = weak, value = $0800; # 2k stack } MEMORY { ZP: file = "", define = yes, start = $0055, size = $001A; LOADADDR: file = %O, start = $03FF, size = $0002; HEADER: file = %O, start = $0401, size = $000C; RAM: file = %O, start = $040D, size = $7BF3 - __STACKSIZE__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; LOADADDR: load = LOADADDR, type = ro; EXEHDR: load = HEADER, type = ro; STARTUP: load = RAM, type = ro; LOWCODE: load = RAM, type = ro, optional = yes; ONCE: load = RAM, type = ro, optional = yes; CODE: load = RAM, type = ro; RODATA: load = RAM, type = ro; DATA: load = RAM, type = rw; INIT: load = RAM, type = bss; BSS: load = RAM, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/plus4.cfg000066400000000000000000000031341347360151100144750ustar00rootroot00000000000000FEATURES { STARTADDRESS: default = $1001; } SYMBOLS { __LOADADDR__: type = import; __EXEHDR__: type = import; __STACKSIZE__: type = weak, value = $0800; # 2k stack __HIMEM__: type = weak, value = $FD00; } MEMORY { ZP: file = "", define = yes, start = $0002, size = $001A; LOADADDR: file = %O, start = %S - 2, size = $0002; HEADER: file = %O, define = yes, start = %S, size = $000D; MAIN: file = %O, define = yes, start = __HEADER_LAST__, size = __HIMEM__ - __MAIN_START__ - __STACKSIZE__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; LOADADDR: load = LOADADDR, type = ro; EXEHDR: load = HEADER, type = ro; STARTUP: load = MAIN, type = ro; LOWCODE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro; ONCE: load = MAIN, type = ro, optional = yes; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; INIT: load = MAIN, type = bss; BSS: load = MAIN, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/sim6502.cfg000066400000000000000000000023551347360151100145370ustar00rootroot00000000000000SYMBOLS { __EXEHDR__: type = import; __STACKSIZE__: type = weak, value = $0800; # 2k stack } MEMORY { ZP: file = "", start = $0000, size = $001B; HEADER: file = %O, start = $0000, size = $000C; MAIN: file = %O, define = yes, start = $0200, size = $FDF0 - __STACKSIZE__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXEHDR: load = HEADER, type = ro; STARTUP: load = MAIN, type = ro; LOWCODE: load = MAIN, type = ro, optional = yes; ONCE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; BSS: load = MAIN, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/sim65c02.cfg000066400000000000000000000023551347360151100147020ustar00rootroot00000000000000SYMBOLS { __EXEHDR__: type = import; __STACKSIZE__: type = weak, value = $0800; # 2k stack } MEMORY { ZP: file = "", start = $0000, size = $001B; HEADER: file = %O, start = $0000, size = $000C; MAIN: file = %O, define = yes, start = $0200, size = $FDF0 - __STACKSIZE__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; EXEHDR: load = HEADER, type = ro; STARTUP: load = MAIN, type = ro; LOWCODE: load = MAIN, type = ro, optional = yes; ONCE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; BSS: load = MAIN, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/supervision-128k.cfg000066400000000000000000000033341347360151100165010ustar00rootroot00000000000000# supervision 1284kbyte cartridge with bankswitching # for assembler # ld65 config file # ld65 --config supervision-128k.cfg -o .bin .o SYMBOLS { __STACKSIZE__: type = weak, value = $0100; # 1 page stack } MEMORY { RAM: file = "", start = $0000, size = $2000 - __STACKSIZE__, define = yes; VRAM: file = "", start = $4000, size = $2000; BANKROM1: file = %O, start = $8000, size = $4000, fill = yes, fillval = $FF; BANKROM2: file = %O, start = $8000, size = $4000, fill = yes, fillval = $FF; BANKROM3: file = %O, start = $8000, size = $4000, fill = yes, fillval = $FF; BANKROM4: file = %O, start = $8000, size = $4000, fill = yes, fillval = $FF; BANKROM5: file = %O, start = $8000, size = $4000, fill = yes, fillval = $FF; BANKROM6: file = %O, start = $8000, size = $4000, fill = yes, fillval = $FF; BANKROM7: file = %O, start = $8000, size = $4000, fill = yes, fillval = $FF; ROM: file = %O, start = $c000, size = $4000, fill = yes, fillval = $FF; } SEGMENTS { LOWCODE: load = ROM, type = ro, optional = yes; ONCE: load = ROM, type = ro, optional = yes; CODE: load = ROM, type = ro; BANK1: load = BANKROM1, type = ro; BANK2: load = BANKROM2, type = ro; BANK3: load = BANKROM3, type = ro; BANK4: load = BANKROM4, type = ro; BANK5: load = BANKROM5, type = ro; BANK6: load = BANKROM6, type = ro; BANK7: load = BANKROM7, type = ro; ZEROPAGE: load = RAM, type = bss, define = yes; DATA: load = RAM, type = bss, define = yes, offset = $0200; BSS: load = RAM, type = bss, define = yes; VECTOR: load = ROM, type = ro, offset = $3FFA; } cc65-2.18/cfg/supervision-16k.cfg000066400000000000000000000031731347360151100164160ustar00rootroot00000000000000# supervision 16kbyte cartridge # ld65 config file # ld65 --config supervision-16k.cfg -o .bin .o SYMBOLS { __STACKSIZE__: type = weak, value = $0100; # 1 page stack } MEMORY { ZP: file = "", start = $0000, size = $0100; CPUSTACK: file = "", start = $0100, size = $0100; RAM: file = "", start = $0200, size = $1E00 - __STACKSIZE__, define = yes; VRAM: file = "", start = $4000, size = $2000; ROM: file = %O, start = $C000, size = $4000, fill = yes, fillval = $FF, define = yes; } SEGMENTS { ZEROPAGE: load = ZP, type = zp, define = yes; LOWCODE: load = ROM, type = ro, optional = yes; ONCE: load = ROM, type = ro, optional = yes; CODE: load = ROM, type = ro, define = yes; RODATA: load = ROM, type = ro, define = yes; DATA: load = ROM, run = RAM, type = rw, define = yes; FFF0: load = ROM, type = ro, offset = $3FF0; VECTOR: load = ROM, type = ro, offset = $3FFA; BSS: load = RAM, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/supervision-64k.cfg000066400000000000000000000024271347360151100164220ustar00rootroot00000000000000# supervision 64kbyte cartridge with bankswitching # for assembler # ld65 config file # ld65 --config supervision-64k.cfg -o .bin .o SYMBOLS { __STACKSIZE__: type = weak, value = $0100; # 1 page stack } MEMORY { RAM: file = "", start = $0000, size = $2000 - __STACKSIZE__, define = yes; VRAM: file = "", start = $4000, size = $2000; BANKROM1: file = %O, start = $8000, size = $4000, fill = yes, fillval = $FF; BANKROM2: file = %O, start = $8000, size = $4000, fill = yes, fillval = $FF; BANKROM3: file = %O, start = $8000, size = $4000, fill = yes, fillval = $FF; ROM: file = %O, start = $C000, size = $4000, fill = yes, fillval = $FF; } SEGMENTS { LOWCODE: load = ROM, type = ro, optional = yes; ONCE: load = ROM, type = ro, optional = yes; CODE: load = ROM, type = ro; RODATA: load = ROM, type = ro; BANK1: load = BANKROM1, type = ro; BANK2: load = BANKROM2, type = ro; BANK3: load = BANKROM3, type = ro; ZEROPAGE: load = RAM, type = bss, define = yes; DATA: load = RAM, type = bss, define = yes, offset = $0200; BSS: load = RAM, type = bss, define = yes; VECTOR: load = ROM, type = ro, offset = $3FFA; } cc65-2.18/cfg/supervision.cfg000066400000000000000000000032711347360151100160160ustar00rootroot00000000000000# if you want to combine the 2 16 kbyte roms # make sure the halves are mirrored in the 64kbyte cartridge image # or reset from code >0xc000 and switch bank to the 3rd bank SYMBOLS { __STACKSIZE__: type = weak, value = $0100; # 1 page stack } MEMORY { ZP: file = "", start = $0000, size = $0100; CPUSTACK: file = "", start = $0100, size = $0100; RAM: file = "", start = $0200, size = $1E00 - __STACKSIZE__, define = yes; VRAM: file = "", start = $4000, size = $2000; ROM: file = %O, start = $8000, size = $8000, fill = yes, fillval = $FF, define = yes; } SEGMENTS { ZEROPAGE: load = ZP, type = zp, define = yes; LOWCODE: load = ROM, type = ro, optional = yes; ONCE: load = ROM, type = ro, optional = yes; CODE: load = ROM, type = ro, define = yes; RODATA: load = ROM, type = ro, define = yes; DATA: load = ROM, run = RAM, type = rw, define = yes; FFF0: load = ROM, type = ro, offset = $7FF0; VECTOR: load = ROM, type = ro, offset = $7FFA; BSS: load = RAM, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/telestrat.cfg000066400000000000000000000032271347360151100154400ustar00rootroot00000000000000SYMBOLS { __ORIXHDR__: type = import; __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 = $00B0, size = $003A; ORIXHDR: file = %O, type = ro, start = $0000, size = $001F; MAIN: file = %O, define = yes, start = $0800, size = __RAMEND__ - __MAIN_START__; BSS: file = "", start = __ONCE_RUN__, size = __RAMEND__ - __STACKSIZE__ - __ONCE_RUN__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; ORIXHDR: load = ORIXHDR, type = ro; STARTUP: load = MAIN, type = ro; LOWCODE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; INIT: load = MAIN, type = rw; ONCE: load = MAIN, type = ro, define = yes; BASTAIL: load = MAIN, type = ro, optional = yes; BSS: load = BSS, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/vic20-32k.cfg000066400000000000000000000030401347360151100147420ustar00rootroot00000000000000# Memory configuration for the VIC-20 with 32K RAM Cartridge # Contributed by Stefan Haubenthal SYMBOLS { __LOADADDR__: type = import; __EXEHDR__: type = import; __STACKSIZE__: type = weak, value = $0800; # 2k stack } MEMORY { ZP: file = "", define = yes, start = $0002, size = $001A; LOADADDR: file = %O, start = $11FF, size = $0002; HEADER: file = %O, start = $1201, size = $000C; MAIN: file = %O, define = yes, start = $120D, size = $6DF3 - __STACKSIZE__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; LOADADDR: load = LOADADDR, type = ro; EXEHDR: load = HEADER, type = ro; STARTUP: load = MAIN, type = ro; LOWCODE: load = MAIN, type = ro, optional = yes; ONCE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; INIT: load = MAIN, type = bss; BSS: load = MAIN, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/cfg/vic20.cfg000066400000000000000000000027001347360151100143470ustar00rootroot00000000000000SYMBOLS { __LOADADDR__: type = import; __EXEHDR__: type = import; __STACKSIZE__: type = weak, value = $0400; # 1k stack } MEMORY { ZP: file = "", define = yes, start = $0002, size = $001A; LOADADDR: file = %O, start = $0FFF, size = $0002; HEADER: file = %O, start = $1001, size = $000C; MAIN: file = %O, define = yes, start = $100D, size = $0DF3 - __STACKSIZE__; } SEGMENTS { ZEROPAGE: load = ZP, type = zp; LOADADDR: load = LOADADDR, type = ro; EXEHDR: load = HEADER, type = ro; STARTUP: load = MAIN, type = ro; LOWCODE: load = MAIN, type = ro, optional = yes; ONCE: load = MAIN, type = ro, optional = yes; CODE: load = MAIN, type = ro; RODATA: load = MAIN, type = ro; DATA: load = MAIN, type = rw; INIT: load = MAIN, type = bss; BSS: load = MAIN, type = bss, define = yes; } FEATURES { CONDES: type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__, segment = ONCE; CONDES: type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__, segment = RODATA; CONDES: type = interruptor, label = __INTERRUPTOR_TABLE__, count = __INTERRUPTOR_COUNT__, segment = RODATA, import = __CALLIRQ__; } cc65-2.18/doc/000077500000000000000000000000001347360151100127525ustar00rootroot00000000000000cc65-2.18/doc/Makefile000066400000000000000000000023571347360151100144210ustar00rootroot00000000000000ifneq ($(shell echo),) CMD_EXE = 1 endif .PHONY: all mostlyclean clean install zip doc html info .SUFFIXES: htmldir = $(PREFIX)/share/doc/cc65$(DESTPACKAGE_SUFFIX)/html infodir = $(PREFIX)/share/info ifdef CMD_EXE doc clean install zip: else # CMD_EXE SGMLS := $(wildcard *.sgml) ../html/coding.html ../html/index.html: \ TOC_LEVEL = 0 TOC_LEVEL = 2 INSTALL = install doc: html info html: $(addprefix ../html/,$(SGMLS:.sgml=.html) doc.css doc.png) info: $(addprefix ../info/,$(SGMLS:.sgml=.info)) ../html ../info: @mkdir $@ ../html/%.html: %.sgml header.html | ../html @cd ../html && linuxdoc -B html -s 0 -T $(TOC_LEVEL) -H ../doc/header.html ../doc/$< ../html/doc.%: doc.% | ../html cp $< ../html ../info/%.info: %.sgml | ../info @cd ../info && linuxdoc -B info ../doc/$< clean: $(RM) -r ../html ../info install: $(if $(PREFIX),,$(error variable "PREFIX" must be set)) ifeq ($(wildcard ../html),../html) $(INSTALL) -d $(DESTDIR)$(htmldir) $(INSTALL) -m0644 ../html/*.* $(DESTDIR)$(htmldir) endif ifeq ($(wildcard ../info),../info) $(INSTALL) -d $(DESTDIR)$(infodir) $(INSTALL) -m0644 ../info/*.* $(DESTDIR)$(infodir) endif zip: ifneq "$(wildcard ../html)" "" @cd .. && zip cc65 html/*.* endif endif # CMD_EXE all mostlyclean: cc65-2.18/doc/apple2.sgml000066400000000000000000000577771347360151100150500ustar00rootroot00000000000000
Apple ][ specific information for cc65 <author><url url="mailto:ol.sc@web.de" name="Oliver Schmidt"> <abstract> An overview over the Apple ][ 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 Apple ][ runtime system as it comes with the cc65 C compiler. It describes the memory layout, Apple ][ specific header files, available drivers, and any pitfalls specific to that platform. Please note that Apple ][ 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 file format generated by the linker for the Apple ][ target is an <url name="AppleSingle" url="http://kaiser-edv.de/documents/AppleSingle_AppleDouble.pdf"> file. The default load address is $803. <bf/AppleCommander 1.4.0/ or later (available at <url url="https://applecommander.github.io/">) includes the option <tt/-as/ that allows to put AppleSingle files onto disk images containing DOS 3.3 as well as ProDOS 8. <sect>Memory layout<p> In the standard setup, cc65 generated programs use the memory from $803 to $95FF, so 35.5 KB of RAM are available. Special locations: <descrip> <tag/Stack/ The C runtime stack is located at HIMEM and grows downwards, regardless of how your linker config file is setup. <tag/Heap/ The C heap is located at the end of the program and grows towards the C runtime stack. </descrip><p> While running <tt/main()/ the Language Card bank 2 is enabled for read access. However while running module constructors/destructors the Language Card is disabled. Enabling the Language Card allows to use it as additional memory for cc65 generated code. However code is never automatically placed there. Rather code needs to be explicitly placed in the Language Card either per file by compiling with <tt/--code-name LC/ or per function by enclosing in <tt/#pragma code-name (push, "LC")/ and <tt/#pragma code-name (pop)/. In either case the cc65 runtime system takes care of actually moving the code into the Language Card. The amount of memory available in the Language Card for generated code depends on the <ref id="link-configs" name="linker configuration"> parameters. There are several usefull settings: <descrip> <tag>LC address: $D400, LC size: $C00</tag> For plain vanilla ProDOS 8 which doesn't actually use the Language Card bank 2 memory from $D400 to $DFFF. This is the default setting. <tag>LC address: $D000, LC size: $1000</tag> For ProDOS 8 together with the function <tt/rebootafterexit()/. If a program doesn't quit to the ProDOS 8 dispatcher but rather reboots the machine after exit then a plain vanilla ProDOS 8 doesn't make use of the Language Card bank 2 at all. <tag>LC address: $D000, LC size: $3000</tag> For plain vanilla DOS 3.3 which doesn't make use of the Language Card at all. </descrip><p> <sect>Linker configurations<label id="link-configs"><p> The ld65 linker comes with a default config file for the Apple ][, which is used via <tt/-t apple2/. The apple2 package comes with additional secondary linker config files, which are used via <tt/-t apple2 -C <configfile>/. <sect1>default config file (<tt/apple2.cfg/)<label id="apple-def-cfg"><p> Default configuration for a binary program. Parameters: <descrip> <tag><tt/STARTADDRESS:/ Program start address</tag> Default: $803. Use <tt/-S <addr>/ to set a different start address. <tag><tt/__EXEHDR__:/ AppleSingle executable file header</tag> Default: Yes. Use <tt/-D __EXEHDR__=0/ to omit the AppleSingle header. <tag><tt/__STACKSIZE__:/ C runtime stack size</tag> Default: $800. Use <tt/-D __STACKSIZE__=<size>/ to set a different stack size. <tag><tt/__HIMEM__:/ Highest usable memory address presumed at link time</tag> Default: $9600. Use <tt/-D __HIMEM__=<addr>/ to set a different highest usable address. <tag><tt/__LCADDR__:/ Address of code in the Language Card</tag> Default: $D400. Use <tt/-D __LCADDR__=<addr>/ to set a different code address. <tag><tt/__LCSIZE__:/ Size of code in the Language Card</tag> Default: $C00. Use <tt/-D __LCSIZE__=<size>/ to set a different code size. </descrip><p> <sect1><tt/apple2-system.cfg/<label id="apple-sys-cfg"><p> Configuration for a system program running on ProDOS 8 and using the memory from $2000 to $BEFF. Parameters: <descrip> <tag><tt/__EXEHDR__:/ AppleSingle executable file header</tag> Default: Yes. Use <tt/-D __EXEHDR__=0/ to omit the AppleSingle header. <tag><tt/__STACKSIZE__:/ C runtime stack size</tag> Default: $800. Use <tt/-D __STACKSIZE__=<size>/ to set a different stack size. <tag><tt/__LCADDR__:/ Address of code in the Language Card</tag> Default: $D400. Use <tt/-D __LCADDR__=<addr>/ to set a different code address. <tag><tt/__LCSIZE__:/ Size of code in the Language Card</tag> Default: $C00. Use <tt/-D __LCSIZE__=<size>/ to set a different code size. </descrip><p> <sect1><tt/apple2-hgr.cfg/<p> Configuration for a program including a hires page. See <tt>testcode/lib/apple/hgrtest.c</tt> for an example of such a program. Parameters: <descrip> <tag><tt/STARTADDRESS:/ Program start address</tag> Default: $803. Use <tt/-S <addr>/ to set a different start address. <tag><tt/__EXEHDR__:/ AppleSingle executable file header</tag> Default: Yes. Use <tt/-D __EXEHDR__=0/ to omit the AppleSingle header. <tag><tt/__STACKSIZE__:/ C runtime stack size</tag> Default: $800. Use <tt/-D __STACKSIZE__=<size>/ to set a different stack size. <tag><tt/__HIMEM__:/ Highest usable memory address presumed at link time</tag> Default: $9600. Use <tt/-D __HIMEM__=<addr>/ to set a different highest usable address. <tag><tt/__LCADDR__:/ Address of code in the Language Card</tag> Default: $D400. Use <tt/-D __LCADDR__=<addr>/ to set a different code address. <tag><tt/__LCSIZE__:/ Size of code in the Language Card</tag> Default: $C00. Use <tt/-D __LCSIZE__=<size>/ to set a different code size. </descrip><p> <sect1><tt/apple2-overlay.cfg/<p> Configuration for an overlay program with up to nine overlays. The overlay files don't include the AppleSingle header. See <tt>samples/overlaydemo.c</tt> for more information on overlays. Parameters: <descrip> <tag><tt/STARTADDRESS:/ Program start address</tag> Default: $803. Use <tt/-S <addr>/ to set a different start address. <tag><tt/__EXEHDR__:/ AppleSingle executable file header</tag> Default: Yes. Use <tt/-D __EXEHDR__=0/ to omit the AppleSingle header. <tag><tt/__STACKSIZE__:/ C runtime stack size</tag> Default: $800. Use <tt/-D __STACKSIZE__=<size>/ to set a different stack size. <tag><tt/__HIMEM__:/ Highest usable memory address presumed at link time</tag> Default: $9600. Use <tt/-D __HIMEM__=<addr>/ to set a different highest usable address. <tag><tt/__LCADDR__:/ Address of code in the Language Card</tag> Default: $D400. Use <tt/-D __LCADDR__=<addr>/ to set a different code address. <tag><tt/__LCSIZE__:/ Size of code in the Language Card</tag> Default: $C00. Use <tt/-D __LCSIZE__=<size>/ to set a different code size. <tag><tt/__OVERLAYSIZE__:/ Size of code in the overlays</tag> Default: $1000. Use <tt/-D __OVERLAYSIZE__=<size>/ to set a different code size. </descrip><p> <sect1><tt/apple2-asm.cfg/<p> Configuration for an assembler program that doesn't need a special setup. Parameters: <descrip> <tag><tt/STARTADDRESS:/ Program start address</tag> Default: $803. Use <tt/-S <addr>/ to set a different start address. <tag><tt/__EXEHDR__:/ AppleSingle executable file header</tag> Default: No. Use <tt/-u __EXEHDR__ apple2.lib/ to add the AppleSingle header. </descrip><p> <sect>ProDOS 8 system programs<p> ProDOS 8 system programs are always loaded to the start address $2000. For cc65 programs this means that the 6 KB from $800 to $2000 are by default unused. There are however several options to make use of that memory range. <sect1>LOADER.SYSTEM<p> The easiest (and for really large programs in fact the only) way to have a cc65 program use the memory from $800 to $2000 is to link it as binary (as opposed to system) program using the default linker configuration <ref id="apple-def-cfg" name="apple2.cfg"> with <tt/__HIMEM__/ set to $BF00 and load it with the LOADER.SYSTEM utility. The program then works like a system program (i.e. quits to the ProDOS dispatcher). Using LOADER.SYSTEM is as simple as copying it to the ProDOS 8 directory of the program to load under name <program>.SYSTEM as a system program. For example the program <tt/MYPROG/ is loaded by <tt/MYPROG.SYSTEM/. The right AppleCommander option to put LOADER.SYSTEM on a ProDOS 8 disk image is <tt/-p/. <sect1>Heap<p> If the cc65 program can be successfully linked as system program using the linker configuration <ref id="apple-sys-cfg" name="apple2-system.cfg">, but uses the heap either explicitly or implicitly (i.e. by loading a driver) then the memory from $800 to $2000 can be added to the heap by calling <tt/_heapadd ((void *) 0x0800, 0x1800);/ at the beginning of <tt/main()/. <sect1>ProDOS 8 I/O buffers<p> ProDOS 8 requires for every open file a page-aligned 1 KB I/O buffer. By default these buffers are allocated by the cc65 runtime system on the heap using <tt/posix_memalign()/. While this is generally the best solution it means quite some overhead for (especially rather small) cc65 programs which do open files but don't make use of the heap otherwise. The apple2 package comes with the alternative ProDOS 8 I/O buffer allocation module <tt/apple2-iobuf-0800.o/ which uses the memory between $800 and the program start address for the 1 KB I/O buffers. For system programs (with start address $2000) this results in up to 6 I/O buffers and thus up to 6 concurrently open files. While using <tt/_heapadd()/ as described in the section above together with the default I/O buffer allocation basically yields the same placement of I/O buffers in memory the primary benefit of <tt/apple2-iobuf-0800.o/ is a reduction in code size - and thus program file size - of more than 1400 bytes. Using <tt/apple2-iobuf-0800.o/ is as simple as placing it on the linker command line like this: <tscreen><verb> cl65 -t apple2 -C apple2-system.cfg myprog.c apple2-iobuf-0800.o </verb></tscreen> <sect>Platform specific header files<p> Programs containing Apple ][ specific code may use the <tt/apple2.h/ header file. <sect1>Apple ][ specific functions<p> The functions listed below are special for the Apple ][. See the <url url="funcref.html" name="function reference"> for declaration and usage. <itemize> <item>_auxtype <item>_dos_type <item>_filetype <item>get_ostype <item>rebootafterexit <item>ser_apple2_slot <item>tgi_apple2_mix </itemize> <sect1>Hardware access<p> There's currently no support for direct hardware access. This does not mean you cannot do it, it just means that there's no help. <sect>Loadable drivers<p> The names in the parentheses denote the symbols to be used for static linking of the drivers. <sect1>Graphics drivers<p> <descrip> <tag><tt/a2.lo.tgi (a2_lo_tgi)/</tag> This driver features a resolution of 40×48 with 16 colors. The function <tt/tgi_apple2_mix()/ allows to activate 4 lines of text. The function clears the corresponding area at the bottom of the screen. <tag><tt/a2.hi.tgi (a2_hi_tgi)/</tag> This driver features a resolution of 280×192 with 8 colors and two hires pages. Note that programs using this driver will have to be linked with <tt/-S $4000/ to reserve the first hires page or with <tt/-S $6000/ to reserve both hires pages. The function <tt/tgi_apple2_mix()/ allows to activate 4 lines of text. The function doesn't clear the corresponding area at the bottom of the screen. In memory constrained situations the memory from $803 to $1FFF can be made available to a program by calling <tt/_heapadd ((void *) 0x0803, 0x17FD);/ at the beginning of <tt/main()/. Doing so is beneficial even if the program doesn't use the the heap explicitly because loading the driver (and in fact already opening the driver file) uses the heap implicitly. </descrip><p> <sect1>Extended memory drivers<p> <descrip> <tag><tt/a2.auxmem.emd (a2_auxmem_emd)/</tag> Gives access to 47.5 KB RAM (190 pages of 256 bytes each) on an Extended 80-Column Text Card. Note that this driver doesn't check for the actual existence of the memory and that it doesn't check for ProDOS 8 RAM disk content! </descrip><p> <sect1>Joystick drivers<p> <descrip> <tag><tt/a2.stdjoy.joy (a2_stdjoy_joy)/</tag> Supports up to two standard analog joysticks connected to the game port of the Apple ][. </descrip><p> <sect1>Mouse drivers<p> <descrip> <tag><tt/a2.stdmou.mou (a2_stdmou_mou)/</tag> Driver for the AppleMouse II Card. Searches all Apple II slots for an AppleMouse II Card compatible firmware. The default bounding box is [0..279,0..191]. Programs using this driver will have to be linked with <tt/-S $4000/ to reserve the first hires page if they are intended to run on an Apple ][ (in contrast to an Apple //e) because the AppleMouse II Card firmware writes to the hires page when initializing on that machine. Note that the Apple ][ default mouse callbacks support text mode only. </descrip><p> <sect1>RS232 device drivers<p> <descrip> <tag><tt/a2.ssc.ser (a2_ssc_ser)/</tag> Driver for the Apple II Super Serial Card. Supports up to 19200 baud, hardware flow control (RTS/CTS) and interrupt driven receives. Note that because of the peculiarities of the 6551 chip transmits are not interrupt driven, and the transceiver blocks if the receiver asserts flow control because of a full buffer. The driver defaults to slot 2. Call <tt/ser_apple2_slot()/ prior to <tt/ser_open()/ in order to select a different slot. <tt/ser_apple2_slot()/ succeeds for all Apple II slots, but <tt/ser_open()/ fails with <tt/SER_ERR_NO_DEVICE/ if there's no SSC firmware found in the selected slot. </descrip><p> <sect>Limitations<p> <sect1>DOS 3.3<p> Although the standard binaries generated by the linker for the Apple ][ generally run both on DOS 3.3 (with Applesoft BASIC) and on ProDOS 8 (with BASIC.SYSTEM) there are some limitations for DOS 3.3: <descrip> <tag>Disk file I/O</tag> There's no disk file I/O support. Any attempt to use it yields an error with <tt/errno/ set to <tt/ENOSYS/. This implicitly means that loadable drivers are in general not functional as they depend on disk file I/O. Therefore the statically linked drivers have to be used instead. <tag/Interrupts/ There's no <tt/interruptor/ support. Any attempt to use it yields the message 'FAILED TO ALLOC INTERRUPT' on program startup. This implicitly means that mouse and RS232 device drivers are not functional as they depend on interrupts. </descrip><p> <sect1>Direct console I/O<p> The Apple ][ has no color text mode. Therefore the functions <tt/textcolor()/, <tt/bgcolor()/ and <tt/bordercolor()/ have no effect. <sect1>Random number generator<p> The random number seed is generated from the time the program waits for user input. Therefore it is necessary to wait for at least one user keypress either via Standard I/O or via Direct console I/O before initializing the pseudo random number generator. <sect1>Realtime clock<p> There are several types of realtime clocks. It's not desirable to have specific code for all of them. As ProDOS 8 supports file timestamps, realtime clock owners usually use ProDOS 8 drivers for their realtime clock. Those drivers read the realtime clock and write the result to the date/time location in RAM ($BF90 to $BF93). ProDOS 8 reads the date/time from that RAM location. If there's no realtime clock the RAM location keeps containing zeros. ProDOS 8 uses those zeros as timestamps and the files show up in a directory as <tt/<NO DATE>/. There's no common interface to set realtime clocks so if a realtme clock <bf/IS/ present there's just nothing to do. However, if there's <bf/NO/ realtime clock present, the user might very well be interested to "manually" set the RAM location in order to have timestamps. But he surely doesn't want to manually set the RAM location over and over again. Rather he wants to set it just once after booting ProDOS 8. From that perspective it makes most sense to not set both the date and the time but rather only set the date and have the time just stay zero. Then files show up in a directory as <tt/DD-MON-YY 0:00/. So <tt/clock_settime()/ checks if the current time equals 0:00. If it does <bf/NOT/ then a realtime clock is supposed to be active and <tt/clock_settime()/ fails with <tt/ERANGE/. Otherwise <tt/clock_settime()/ sets the date - and completely ignores the time provided as parameter. <tt/clock_getres()/ too checks if the current time equals 0:00. If it does <bf/NOT/ then a realtime clock is supposed to be active and <tt/clock_getres()/ returns a time resolution of one minute. Otherwise <tt/clock_getres()/ presumes that the only one who sets the RAM location is <tt/clock_settime()/ and therefore returns a time resolution of one day. <sect>Other hints<p> <sect1>Passing arguments to the program<p> Command line arguments can be passed to <tt/main()/ after BLOAD. Since this is not supported by BASIC, the following syntax was chosen: <tscreen><verb> ]CALL2051:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5 </verb></tscreen> <enum> <item>Arguments are separated by spaces. <item>Arguments may be quoted. <item>Leading and trailing spaces around an argument are ignored. Spaces within a quoted argument are allowed. <item>The first argument passed to <tt/main/ is the program name. <item>A maximum number of 10 arguments (including the program name) are supported. </enum> <sect1>Interrupts<p> The runtime for the Apple ][ uses routines marked as <tt/.INTERRUPTOR/ for ProDOS 8 interrupt handlers. Such routines must be written as simple machine language subroutines and will be called automatically by the interrupt handler code when they are linked into a program. See the discussion of the <tt/.CONDES/ feature in the <url url="ca65.html" name="assembler manual">. <sect1>DIO<p> <descrip> <tag/Drive ID/ The function <url url="dio.html#s1" name="dio_open()"> has the single parameter <tt/device/ to identify the device to be opened. Therefore an Apple II slot and drive pair is mapped to that <tt/device/ according to the formula <tscreen> device = slot + (drive - 1) * 8 </tscreen> so that for example slot 6 drive 2 is mapped to <tt/device/ 14. <tag/Sector count/ The function <url url="dio.html#s3" name="dio_query_sectcount()"> returns the correct sector count for all ProDOS 8 disks. However for any non-ProDOS 8 disk it simply always returns 280 (which is only correct for a 140 KB disk). This condition is indicated by the <tt/_oserror/ value 82. </descrip><p> <sect1>Specifying file types for fopen<p> <descrip> <tag>Explanation of File Types</tag> ProDOS associates a file type and an auxiliary type with each file. These type specifications are separate from the file's name, unlike Windows which uses the file name's suffix (a.k.a. extension) to specify the file type. For example, <tt/.exe/, <tt/.doc/, or <tt/.bat/. The ProDOS low-level Machine-Language Interface (MLI) functions for creating and opening files require these types to be specified. And if they don't match with the file being opened, the operation may fail. In contrast, the ISO C function <tt/fopen()/ and the POSIX function <tt/open()/ have no parameter to specify either a file type or an auxiliary type. Therefore, some additional mechanism for specifying the file types is needed. <tag>Specifying the File Type and Auxiliary Type</tag> There are two global variables provided that allow the file type and auxiliary type to be specified before a call to <tt/fopen()/ or <tt/open()/. They are defined in <tt/apple2_filetype.h/: <tscreen> <verb> extern unsigned char _filetype; /* Default: PRODOS_T_BIN */ extern unsigned int _auxtype; /* Default: 0 */ </verb> </tscreen> The header file <tt/apple2_filetype.h/ also defines many values that can be used to set these variables. It is included in <tt/apple2.h/, which is in turn included in <tt/apple2enh.h/. So it isn't necessary to include it directly. Just include one of <tt/apple2.h/ or <tt/apple2enh.h/. <tag>Example</tag> A text file cannot be created with just the standard C functions because they default to the binary type <tt/PRODOS_T_BIN/. The <tt/_filetype/ variable must be set to <tt/PRODOS_T_TXT/ to create a text file. For a text file, <tt/_auxtype/ specifies the record length. A zero record length text file is referred to as a sequential text file. This is equivalent to text files on other operating systems, except that the line terminator is a carriage return instead of a line-feed (Linux/BSD/MacOS) or carriage return, line-feed pair (Windows). The "sequential" text file terminology is in contrast to a "random-access" text file which would have a fixed-length, non-zero record length, so that the file position of any individual record can be calculated. For this example, the <tt/_auxtype/ does not need to be set because it defaults to the desired value, which is zero. To be more explicit, <tt/_auxtype/ can also be set to <tt/PRODOS_AUX_T_TXT_SEQ/ which is defined as zero. <tscreen> <verb> #include <stdio.h> #include <string.h> #include <errno.h> #include <apple2.h> void main(void) { FILE *out; char *name = "MY.FAVS"; /*-----------------------------*/ _filetype = PRODOS_T_TXT; _auxtype = PRODOS_AUX_T_TXT_SEQ; /*-----------------------------*/ if ((out = fopen(name, "w")) != NULL) { fputs("Jorah Mormont\r", out); fputs("Brienne of Tarth\r", out); fputs("Daenerys Targaryen\r", out); fputs("Sandor Clegane\r", out); if (fclose(out) == EOF) { fprintf(stderr, "fclose failed for %s: %s", name, strerror(errno)); } } else { fprintf(stderr, "fopen failed for %s: %s", name, strerror(errno)); } } </verb> </tscreen> </descrip><p> <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> �cc65-2.18/doc/apple2enh.sgml������������������������������������������������������������������������0000664�0000000�0000000�00000060234�13473601511�0015521�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>Enhanced Apple //e specific information for cc65 <author><url url="mailto:ol.sc@web.de" name="Oliver Schmidt"> <abstract> An overview over the enhanced Apple //e 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 enhanced Apple //e runtime system as it comes with the cc65 C compiler. It describes the memory layout, enhanced Apple //e specific header files, available drivers, and any pitfalls specific to that platform. Please note that enhanced Apple //e 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 file format generated by the linker for the enhanced Apple //e target is an <url name="AppleSingle" url="http://kaiser-edv.de/documents/AppleSingle_AppleDouble.pdf"> file. The default load address is $803. <bf/AppleCommander 1.4.0/ or later (available at <url url="https://applecommander.github.io/">) includes the option <tt/-as/ that allows to put AppleSingle files onto disk images containing DOS 3.3 as well as ProDOS 8. <sect>Memory layout<p> In the standard setup, cc65 generated programs use the memory from $803 to $95FF, so 35.5 KB of RAM are available. Special locations: <descrip> <tag/Stack/ The C runtime stack is located at HIMEM and grows downwards, regardless of how your linker config file is setup. <tag/Heap/ The C heap is located at the end of the program and grows towards the C runtime stack. </descrip><p> While running <tt/main()/ the Language Card bank 2 is enabled for read access. However while running module constructors/destructors the Language Card is disabled. Enabling the Language Card allows to use it as additional memory for cc65 generated code. However code is never automatically placed there. Rather code needs to be explicitly placed in the Language Card either per file by compiling with <tt/--code-name LC/ or per function by enclosing in <tt/#pragma code-name (push, "LC")/ and <tt/#pragma code-name (pop)/. In either case the cc65 runtime system takes care of actually moving the code into the Language Card. The amount of memory available in the Language Card for generated code depends on the <ref id="link-configs" name="linker configuration"> parameters. There are several usefull settings: <descrip> <tag>LC address: $D400, LC size: $C00</tag> For plain vanilla ProDOS 8 which doesn't actually use the Language Card bank 2 memory from $D400 to $DFFF. This is the default setting. <tag>LC address: $D000, LC size: $1000</tag> For ProDOS 8 together with the function <tt/rebootafterexit()/. If a program doesn't quit to the ProDOS 8 dispatcher but rather reboots the machine after exit then a plain vanilla ProDOS 8 doesn't make use of the Language Card bank 2 at all. <tag>LC address: $D000, LC size: $3000</tag> For plain vanilla DOS 3.3 which doesn't make use of the Language Card at all. </descrip><p> <sect>Linker configurations<label id="link-configs"><p> The ld65 linker comes with a default config file for the enhanced Apple //e, which is used via <tt/-t apple2enh/. The apple2enh package comes with additional secondary linker config files, which are used via <tt/-t apple2enh -C <configfile>/. <sect1>default config file (<tt/apple2enh.cfg/)<label id="apple-def-cfg"><p> Default configuration for a binary program. Parameters: <descrip> <tag><tt/STARTADDRESS:/ Program start address</tag> Default: $803. Use <tt/-S <addr>/ to set a different start address. <tag><tt/__EXEHDR__:/ AppleSingle executable file header</tag> Default: Yes. Use <tt/-D __EXEHDR__=0/ to omit the AppleSingle header. <tag><tt/__STACKSIZE__:/ C runtime stack size</tag> Default: $800. Use <tt/-D __STACKSIZE__=<size>/ to set a different stack size. <tag><tt/__HIMEM__:/ Highest usable memory address presumed at link time</tag> Default: $9600. Use <tt/-D __HIMEM__=<addr>/ to set a different highest usable address. <tag><tt/__LCADDR__:/ Address of code in the Language Card</tag> Default: $D400. Use <tt/-D __LCADDR__=<addr>/ to set a different code address. <tag><tt/__LCSIZE__:/ Size of code in the Language Card</tag> Default: $C00. Use <tt/-D __LCSIZE__=<size>/ to set a different code size. </descrip><p> <sect1><tt/apple2enh-system.cfg/<label id="apple-sys-cfg"><p> Configuration for a system program running on ProDOS 8 and using the memory from $2000 to $BEFF. Parameters: <descrip> <tag><tt/__EXEHDR__:/ AppleSingle executable file header</tag> Default: Yes. Use <tt/-D __EXEHDR__=0/ to omit the AppleSingle header. <tag><tt/__STACKSIZE__:/ C runtime stack size</tag> Default: $800. Use <tt/-D __STACKSIZE__=<size>/ to set a different stack size. <tag><tt/__LCADDR__:/ Address of code in the Language Card</tag> Default: $D400. Use <tt/-D __LCADDR__=<addr>/ to set a different code address. <tag><tt/__LCSIZE__:/ Size of code in the Language Card</tag> Default: $C00. Use <tt/-D __LCSIZE__=<size>/ to set a different code size. </descrip><p> <sect1><tt/apple2enh-hgr.cfg/<p> Configuration for a program including a hires page. See <tt>testcode/lib/apple/hgrtest.c</tt> for an example of such a program. Parameters: <descrip> <tag><tt/STARTADDRESS:/ Program start address</tag> Default: $803. Use <tt/-S <addr>/ to set a different start address. <tag><tt/__EXEHDR__:/ AppleSingle executable file header</tag> Default: Yes. Use <tt/-D __EXEHDR__=0/ to omit the AppleSingle header. <tag><tt/__STACKSIZE__:/ C runtime stack size</tag> Default: $800. Use <tt/-D __STACKSIZE__=<size>/ to set a different stack size. <tag><tt/__HIMEM__:/ Highest usable memory address presumed at link time</tag> Default: $9600. Use <tt/-D __HIMEM__=<addr>/ to set a different highest usable address. <tag><tt/__LCADDR__:/ Address of code in the Language Card</tag> Default: $D400. Use <tt/-D __LCADDR__=<addr>/ to set a different code address. <tag><tt/__LCSIZE__:/ Size of code in the Language Card</tag> Default: $C00. Use <tt/-D __LCSIZE__=<size>/ to set a different code size. </descrip><p> <sect1><tt/apple2enh-overlay.cfg/<p> Configuration for an overlay program with up to nine overlays. The overlay files don't include the AppleSingle header. See <tt>samples/overlaydemo.c</tt> for more information on overlays. Parameters: <descrip> <tag><tt/STARTADDRESS:/ Program start address</tag> Default: $803. Use <tt/-S <addr>/ to set a different start address. <tag><tt/__EXEHDR__:/ AppleSingle executable file header</tag> Default: Yes. Use <tt/-D __EXEHDR__=0/ to omit the AppleSingle header. <tag><tt/__STACKSIZE__:/ C runtime stack size</tag> Default: $800. Use <tt/-D __STACKSIZE__=<size>/ to set a different stack size. <tag><tt/__HIMEM__:/ Highest usable memory address presumed at link time</tag> Default: $9600. Use <tt/-D __HIMEM__=<addr>/ to set a different highest usable address. <tag><tt/__LCADDR__:/ Address of code in the Language Card</tag> Default: $D400. Use <tt/-D __LCADDR__=<addr>/ to set a different code address. <tag><tt/__LCSIZE__:/ Size of code in the Language Card</tag> Default: $C00. Use <tt/-D __LCSIZE__=<size>/ to set a different code size. <tag><tt/__OVERLAYSIZE__:/ Size of code in the overlays</tag> Default: $1000. Use <tt/-D __OVERLAYSIZE__=<size>/ to set a different code size. </descrip><p> <sect1><tt/apple2enh-asm.cfg/<p> Configuration for an assembler program that doesn't need a special setup. Parameters: <descrip> <tag><tt/STARTADDRESS:/ Program start address</tag> Default: $803. Use <tt/-S <addr>/ to set a different start address. <tag><tt/__EXEHDR__:/ AppleSingle executable file header</tag> Default: No. Use <tt/-u __EXEHDR__ apple2enh.lib/ to add the AppleSingle header. </descrip><p> <sect>ProDOS 8 system programs<p> ProDOS 8 system programs are always loaded to the start address $2000. For cc65 programs this means that the 6 KB from $800 to $2000 are by default unused. There are however several options to make use of that memory range. <sect1>LOADER.SYSTEM<p> The easiest (and for really large programs in fact the only) way to have a cc65 program use the memory from $800 to $2000 is to link it as binary (as opposed to system) program using the default linker configuration <ref id="apple-def-cfg" name="apple2enh.cfg"> with <tt/__HIMEM__/set to $BF00 and load it with the LOADER.SYSTEM utility. The program then works like a system program (i.e. quits to the ProDOS dispatcher). Using LOADER.SYSTEM is as simple as copying it to the ProDOS 8 directory of the program to load under name <program>.SYSTEM as a system program. For example the program <tt/MYPROG/ is loaded by <tt/MYPROG.SYSTEM/. The right AppleCommander option to put LOADER.SYSTEM on a ProDOS 8 disk image is <tt/-p/. <sect1>Heap<p> If the cc65 program can be successfully linked as system program using the linker configuration <ref id="apple-sys-cfg" name="apple2enh-system.cfg">, but uses the heap either explicitly or implicitly (i.e. by loading a driver) then the memory from $800 to $2000 can be added to the heap by calling <tt/_heapadd ((void *) 0x0800, 0x1800);/ at the beginning of <tt/main()/. <sect1>ProDOS 8 I/O buffers<p> ProDOS 8 requires for every open file a page-aligned 1 KB I/O buffer. By default these buffers are allocated by the cc65 runtime system on the heap using <tt/posix_memalign()/. While this is generally the best solution it means quite some overhead for (especially rather small) cc65 programs which do open files but don't make use of the heap otherwise. The apple2enh package comes with the alternative ProDOS 8 I/O buffer allocation module <tt/apple2enh-iobuf-0800.o/ which uses the memory between $800 and the program start address for the 1 KB I/O buffers. For system programs (with start address $2000) this results in up to 6 I/O buffers and thus up to 6 concurrently open files. While using <tt/_heapadd()/ as described in the section above together with the default I/O buffer allocation basically yields the same placement of I/O buffers in memory the primary benefit of <tt/apple2enh-iobuf-0800.o/ is a reduction in code size - and thus program file size - of more than 1400 bytes. Using <tt/apple2enh-iobuf-0800.o/ is as simple as placing it on the linker command line like this: <tscreen><verb> cl65 -t apple2enh -C apple2enh-system.cfg myprog.c apple2enh-iobuf-0800.o </verb></tscreen> <sect>Platform specific header files<p> Programs containing enhanced Apple //e specific code may use the <tt/apple2enh.h/ header file. <sect1>Enhanced Apple //e specific functions<p> The functions listed below are special for the enhanced Apple //e. See the <url url="funcref.html" name="function reference"> for declaration and usage. <itemize> <item>_auxtype <item>_dos_type <item>_filetype <item>get_ostype <item>rebootafterexit <item>ser_apple2_slot <item>textframe <item>textframexy <item>tgi_apple2_mix <item>videomode </itemize> <sect1>Hardware access<p> There's currently no support for direct hardware access. This does not mean you cannot do it, it just means that there's no help. <sect>Loadable drivers<p> The names in the parentheses denote the symbols to be used for static linking of the drivers. <sect1>Graphics drivers<p> <descrip> <tag><tt/a2e.lo.tgi (a2e_lo_tgi)/</tag> This driver features a resolution of 40×48 with 16 colors. The function <tt/tgi_apple2_mix()/ allows to activate 4 lines of text. The function clears the corresponding area at the bottom of the screen. <tag><tt/a2e.hi.tgi (a2e_hi_tgi)/</tag> This driver features a resolution of 280×192 with 8 colors and two hires pages. Note that programs using this driver will have to be linked with <tt/-S $4000/ to reserve the first hires page or with <tt/-S $6000/ to reserve both hires pages. Note that the second hires page is only available if the text display is not in 80 column mode. This can be asserted by calling <tt/videomode (VIDEOMODE_40COL);/ before installing the driver. The function <tt/tgi_apple2_mix()/ allows to activate 4 lines of text. The function doesn't clear the corresponding area at the bottom of the screen. In memory constrained situations the memory from $803 to $1FFF can be made available to a program by calling <tt/_heapadd ((void *) 0x0803, 0x17FD);/ at the beginning of <tt/main()/. Doing so is beneficial even if the program doesn't use the the heap explicitly because loading the driver (and in fact already opening the driver file) uses the heap implicitly. </descrip><p> <sect1>Extended memory drivers<p> <descrip> <tag><tt/a2e.auxmem.emd (a2e_auxmem_emd)/</tag> Gives access to 47.5 KB RAM (190 pages of 256 bytes each) on an Extended 80-Column Text Card. Note that this driver doesn't check for the actual existence of the memory and that it doesn't check for ProDOS 8 RAM disk content! </descrip><p> <sect1>Joystick drivers<p> <descrip> <tag><tt/a2e.stdjoy.joy (a2e_stdjoy_joy)/</tag> Supports up to two standard analog joysticks connected to the game port of the enhanced Apple //e. </descrip><p> <sect1>Mouse drivers<p> <descrip> <tag><tt/a2e.stdmou.mou (a2e_stdmou_mou)/</tag> Driver for the AppleMouse II Card. Searches all Apple II slots for an AppleMouse II Card compatible firmware. The default bounding box is [0..279,0..191]. Note that the enhanced Apple //e default mouse callbacks support text mode only. </descrip><p> <sect1>RS232 device drivers<p> <descrip> <tag><tt/a2e.ssc.ser (a2e_ssc_ser)/</tag> Driver for the Apple II Super Serial Card. Supports up to 19200 baud, hardware flow control (RTS/CTS) and interrupt driven receives. Note that because of the peculiarities of the 6551 chip transmits are not interrupt driven, and the transceiver blocks if the receiver asserts flow control because of a full buffer. The driver defaults to slot 2. Call <tt/ser_apple2_slot()/ prior to <tt/ser_open()/ in order to select a different slot. <tt/ser_apple2_slot()/ succeeds for all Apple II slots, but <tt/ser_open()/ fails with <tt/SER_ERR_NO_DEVICE/ if there's no SSC firmware found in the selected slot. </descrip><p> <sect>Limitations<p> <sect1>DOS 3.3<p> Although the standard binaries generated by the linker for the enhanced Apple //e generally run both on DOS 3.3 (with Applesoft BASIC) and on ProDOS 8 (with BASIC.SYSTEM) there are some limitations for DOS 3.3: <descrip> <tag>Disk file I/O</tag> There's no disk file I/O support. Any attempt to use it yields an error with <tt/errno/ set to <tt/ENOSYS/. This implicitly means that loadable drivers are in general not functional as they depend on disk file I/O. Therefore the statically linked drivers have to be used instead. <tag/Interrupts/ There's no <tt/interruptor/ support. Any attempt to use it yields the message 'Failed to alloc interrupt' on program startup. This implicitly means that mouse and RS232 device drivers are not functional as they depend on interrupts. </descrip><p> <sect1>Direct console I/O<p> The enhanced Apple //e has no color text mode. Therefore the functions <tt/textcolor()/, <tt/bgcolor()/ and <tt/bordercolor()/ have no effect. <sect1>Random number generator<p> The random number seed is generated from the time the program waits for user input. Therefore it is necessary to wait for at least one user keypress either via Standard I/O or via Direct console I/O before initializing the pseudo random number generator. <sect1>Realtime clock<p> There are several types of realtime clocks. It's not desirable to have specific code for all of them. As ProDOS 8 supports file timestamps, realtime clock owners usually use ProDOS 8 drivers for their realtime clock. Those drivers read the realtime clock and write the result to the date/time location in RAM ($BF90 to $BF93). ProDOS 8 reads the date/time from that RAM location. If there's no realtime clock the RAM location keeps containing zeros. ProDOS 8 uses those zeros as timestamps and the files show up in a directory as <tt/<NO DATE>/. There's no common interface to set realtime clocks so if a realtme clock <bf/IS/ present there's just nothing to do. However, if there's <bf/NO/ realtime clock present, the user might very well be interested to "manually" set the RAM location in order to have timestamps. But he surely doesn't want to manually set the RAM location over and over again. Rather he wants to set it just once after booting ProDOS 8. From that perspective it makes most sense to not set both the date and the time but rather only set the date and have the time just stay zero. Then files show up in a directory as <tt/DD-MON-YY 0:00/. So <tt/clock_settime()/ checks if the current time equals 0:00. If it does <bf/NOT/ then a realtime clock is supposed to be active and <tt/clock_settime()/ fails with <tt/ERANGE/. Otherwise <tt/clock_settime()/ sets the date - and completely ignores the time provided as parameter. <tt/clock_getres()/ too checks if the current time equals 0:00. If it does <bf/NOT/ then a realtime clock is supposed to be active and <tt/clock_getres()/ returns a time resolution of one minute. Otherwise <tt/clock_getres()/ presumes that the only one who sets the RAM location is <tt/clock_settime()/ and therefore returns a time resolution of one day. <sect>Other hints<p> <sect1>Passing arguments to the program<p> Command line arguments can be passed to <tt/main()/ after BLOAD. Since this is not supported by BASIC, the following syntax was chosen: <tscreen><verb> ]CALL2051:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5 </verb></tscreen> <enum> <item>Arguments are separated by spaces. <item>Arguments may be quoted. <item>Leading and trailing spaces around an argument are ignored. Spaces within a quoted argument are allowed. <item>The first argument passed to <tt/main/ is the program name. <item>A maximum number of 10 arguments (including the program name) are supported. </enum> <sect1>Function keys<p> These are defined to be OpenApple + number key. <sect1>Interrupts<p> The runtime for the enhanced Apple //e uses routines marked as <tt/.INTERRUPTOR/ for ProDOS 8 interrupt handlers. Such routines must be written as simple machine language subroutines and will be called automatically by the interrupt handler code when they are linked into a program. See the discussion of the <tt/.CONDES/ feature in the <url url="ca65.html" name="assembler manual">. <sect1>DIO<p> <descrip> <tag/Drive ID/ The function <url url="dio.html#s1" name="dio_open()"> has the single parameter <tt/device/ to identify the device to be opened. Therefore an Apple II slot and drive pair is mapped to that <tt/device/ according to the formula <tscreen> device = slot + (drive - 1) * 8 </tscreen> so that for example slot 6 drive 2 is mapped to <tt/device/ 14. <tag/Sector count/ The function <url url="dio.html#s3" name="dio_query_sectcount()"> returns the correct sector count for all ProDOS 8 disks. However for any non-ProDOS 8 disk it simply always returns 280 (which is only correct for a 140 KB disk). This condition is indicated by the <tt/_oserror/ value 82. </descrip><p> <sect1>Specifying file types for fopen<p> <descrip> <tag>Explanation of File Types</tag> ProDOS associates a file type and an auxiliary type with each file. These type specifications are separate from the file's name, unlike Windows which uses the file name's suffix (a.k.a. extension) to specify the file type. For example, <tt/.exe/, <tt/.doc/, or <tt/.bat/. The ProDOS low-level Machine-Language Interface (MLI) functions for creating and opening files require these types to be specified. And if they don't match with the file being opened, the operation may fail. In contrast, the ISO C function <tt/fopen()/ and the POSIX function <tt/open()/ have no parameter to specify either a file type or an auxiliary type. Therefore, some additional mechanism for specifying the file types is needed. <tag>Specifying the File Type and Auxiliary Type</tag> There are two global variables provided that allow the file type and auxiliary type to be specified before a call to <tt/fopen()/ or <tt/open()/. They are defined in <tt/apple2_filetype.h/: <tscreen> <verb> extern unsigned char _filetype; /* Default: PRODOS_T_BIN */ extern unsigned int _auxtype; /* Default: 0 */ </verb> </tscreen> The header file <tt/apple2_filetype.h/ also defines many values that can be used to set these variables. It is included in <tt/apple2.h/, which is in turn included in <tt/apple2enh.h/. So it isn't necessary to include it directly. Just include one of <tt/apple2.h/ or <tt/apple2enh.h/. <tag>Example</tag> A text file cannot be created with just the standard C functions because they default to the binary type <tt/PRODOS_T_BIN/. The <tt/_filetype/ variable must be set to <tt/PRODOS_T_TXT/ to create a text file. For a text file, <tt/_auxtype/ specifies the record length. A zero record length text file is referred to as a sequential text file. This is equivalent to text files on other operating systems, except that the line terminator is a carriage return instead of a line-feed (Linux/BSD/MacOS) or carriage return, line-feed pair (Windows). The "sequential" text file terminology is in contrast to a "random-access" text file which would have a fixed-length, non-zero record length, so that the file position of any individual record can be calculated. For this example, the <tt/_auxtype/ does not need to be set because it defaults to the desired value, which is zero. To be more explicit, <tt/_auxtype/ can also be set to <tt/PRODOS_AUX_T_TXT_SEQ/ which is defined as zero. <tscreen> <verb> #include <stdio.h> #include <string.h> #include <errno.h> #include <apple2.h> void main(void) { FILE *out; char *name = "MY.FAVS"; /*-----------------------------*/ _filetype = PRODOS_T_TXT; _auxtype = PRODOS_AUX_T_TXT_SEQ; /*-----------------------------*/ if ((out = fopen(name, "w")) != NULL) { fputs("Jorah Mormont\r", out); fputs("Brienne of Tarth\r", out); fputs("Daenerys Targaryen\r", out); fputs("Sandor Clegane\r", out); if (fclose(out) == EOF) { fprintf(stderr, "fclose failed for %s: %s", name, strerror(errno)); } } else { fprintf(stderr, "fopen failed for %s: %s", name, strerror(errno)); } } </verb> </tscreen> </descrip><p> <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> ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/ar65.sgml�����������������������������������������������������������������������������0000664�0000000�0000000�00000011355�13473601511�0014420�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>ar65 Users Guide <author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> <abstract> ar65 is an archiver for object files generated by ca65. It allows to create archives, add or remove modules from archives, and to extract modules from existing archives. </abstract> <!-- Table of contents --> <toc> <!-- Begin the document --> <sect>Overview<p> ar65 is a replacement for the libr65 archiver that was part of the cc65 C compiler suite developed by John R. Dunning. libr65 had some problems and the copyright does not permit some things which I wanted to be possible, so I decided to write a completely new assembler/linker/archiver suite for the cc65 compiler. ar65 is part of this suite. <sect>Usage<p> The archiver is called as follows: <tscreen><verb> Usage: ar65 <operation ...> lib file|module ... Operations are some of: r Add modules d Delete modules t List library table v Increase verbosity (put before other operation) x Extract modules V Print the archiver version </verb></tscreen> You may add modules to a library using the <tt/'r'/ command ('a' is deprecated). If the library does not exist, it is created (and a warning message is printed which you may ignore if creation of the library was your intention). You may specify any number of modules on the command line following the library. If a module with the same name exists in the library, it is replaced by the new one. The archiver prints a warning, if the module in the library has a newer timestamp than the one to add. Here's an example: <tscreen><verb> ar65 r mysubs.lib sub1.o sub2.o </verb></tscreen> This will add two modules to the library 'mysubs.lib' creating the library if necessary. If the library contains modules named sub1.o or sub2.o, they are replaced by the new ones. Modules names in the library are stored without the path, so, using <tscreen><verb> ar65 v v r mysubs.lib ofiles/sub1.o ofiles/sub2.o </verb></tscreen> will verbose add two modules named 'sub1.o' and 'sub2.o' to the library. Deleting modules from a library is done with the <tt/'d'/ command. You may not give a path when naming the modules. Example: <tscreen><verb> ar65 d mysubs.lib sub1.o </verb></tscreen> This will delete the module named 'sub1.o' from the library, printing an error if the library does not contain that module. The <tt/'t'/ command prints a table of all modules in the library ('l' is deprecated). Any module names on the command line are ignored. Example: <tscreen><verb> ar65 tv mysubs.lib </verb></tscreen> Using the <tt/'x'/ command, you may extract modules from the library. The modules named on the command line are extracted from the library and put into the current directory. Note: Because of the indexing done by the archiver, the modules may have a changed binary layout, that is, a binary compare with the old module (before importing it into the library) may yield differences. The extracted modules are accepted by the linker and archiver, however, so this is not a problem. Example for extracting a module from the library: <tscreen><verb> ar65 x mysubs.lib sub1.o </verb></tscreen> The <tt/'V'/ command prints the version number of the assembler. If you send any suggestions or bugfixes, please include your version number. In addition to these operations, the archiver will check for, and warn about duplicate external symbols in the library, every time when an operation does update the library. This is only a warning, the linker will ignore one of the duplicate symbols (which one is unspecified). <sect>Copyright<p> ar65 (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> �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/atari.sgml����������������������������������������������������������������������������0000664�0000000�0000000�00000135000�13473601511�0014735�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>Atari specific information for cc65 <author> <url url="mailto:shawnjefferson@24fightingchickens.com" name="Shawn Jefferson"> and<newline> <url url="mailto:chris@groessler.org" name="Christian Groessler"> <abstract> An overview over the Atari runtime system as it is implemented for the cc65 C compiler. </abstract> <!-- Table of contents --> <toc> <!-- Begin the document --> <sect>Overview<p> This file contains an overview of the Atari runtime system as it comes with the cc65 C compiler. It describes the memory layout, Atari specific header files, available drivers, and any pitfalls specific to that platform. The Atari runtime support comes in two flavors: <tt/atari/ and <tt/atarixl/. The <tt/atari/ target supports all Atari 8-bit computers, the <tt/atarixl/ only supports XL type or newer machines (excluding the 600XL). The <tt/atarixl/ runtime makes the whole 64K of memory available, with the exception of the I/O area at $D000 - $D7FF. Since the <tt/atarixl/ runtime has some <ref name="limitations" id="xllimitations">, it is recommended to use the <tt/atari/ target unless lack of memory dictates the use of the <tt/atarixl/ target. Please note that Atari 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 Atari DOS executable file format supports more than one load block (<it/chunk/). The default binary output format generated by the linker for the Atari target is a machine language program with a standard executable header (FF FF <load chunk #1> ... <load chunk #n>). A load chunk has the format [<2 byte start address> <2 bytes end address> <chunk data>]. A run vector is added to the end of the file ($02E0 $02E1 <run vector>) and is calculated using the <tt/start/ label in crt0.s. (Technically the run vector is also a load chunk, but is not regarded as such here.) An <tt/atari/ program has two load chunks, an <tt/atarixl/ program has three load chunks. The load chunks are defined in the linker configuration files. For more detailed information about the load chunks see the chapter <ref name="Technical details" id="techdetail">. For the discussion here it's sufficient to know that the first load chunk(s) do preparation work and the main part of the program is in the last load chunk. The values determining the size of the main part of the program (the second load chunk for <tt/atari/, the third load chunk for <tt/atarixl/) are calculated in the crt0.s file from the __STARTUP_LOAD__ and __BSS_LOAD__ values. Be aware of that if you create a custom linker config file and start moving segments around (see section <ref name="Reserving a memory area inside the program" id="memhole">). <sect>Memory layout<p> <sect1><tt/atari/ target<p> The default linker config file assumes that the BASIC ROM is disabled (or the BASIC cartridge unplugged). This gives a usable memory range of [$2000-$BC1F]. The library startup code examines the current memory configuration, which depends on the size of the installed memory and cartridges. It does so by using the value in the MEMTOP ($2E5) variable as highest memory address the program can use. The initial stack pointer, which is the upper bound of memory used by the program, is set to this value, minus an optionally defined __RESERVED_MEMORY__ value. The default load address of $2000 can be changed by creating a custom linker config file or by using the "--start-addr" cl65 command line argument or the "--start-addr" or "-S" ld65 command line arguments. Please note that the first load chunk (which checks the available memory) will always be loaded at $2E00, regardless of the specified start address. This address can only be changed by a custom linker config file. Special locations: <descrip> <tag/Text screen/ The text screen depends on the installed memory size and cartridges and can be obtained from the SAVMSC variable ($58). <tag/Stack/ The C runtime stack is located at MEMTOP and grows downwards, regardless of how your linker config file is setup. This accommodates the different memory configurations of the Atari machines, as well as having a cartridge installed. You can override this behaviour by writing your own crt0.s file and linking it to your program (see also <ref name="Final note" id="memhole_final_note">). <tag/Heap/ The C heap is located at the end of the program and grows towards the C runtime stack. </descrip><p> <sect1><tt/atarixl/ target<p> The startup code rearranges the memory as follows: <enum> <item>Sceen memory and display list are moved below the program start address. <item>The ROM is disabled, making the memory in the areas [$C000-$CFFF] and [$D800-$FFF9] available. <item>Character generator data is copied from ROM to the CHARGEN location specified in the linker config file. This is (in the default <tt/atarixl.cfg/ file) at the same address as where it is in ROM ($E000, it can be changed, see <ref name="atarixl chargen location" id="chargenloc">). With the character generator at $E000, there are two upper memory areas available, [$D800-$DFFF] and [$E400-$FFF9]. </enum> With the default load address of $2400 this gives a usable memory range of [$2400-$CFFF]. Please note that the first load chunk (which checks the system compatibilty and available memory) will always be loaded at $2E00, regardless of the specified start address. This address can only be changed by a custom linker config file. Special locations: <descrip> <tag/Text screen/ The text screen depends on the selected load address ($2400 by default), and resides directly before that address, rounded to the next lower page boundary. The screen memory's start address can be obtained from the SAVMSC variable ($58). <tag/Stack/ The C runtime stack is located at end of the MAIN memory area ($CFFF) and grows downwards. <tag/Heap/ The C heap is located at the end of the program (end of BSS segment) and grows towards the C runtime stack. </descrip><p> <sect>Linker configurations<p> The ld65 linker comes with default config files for the Atari. There are two targets for the Atari, <tt/atari/ and <tt/atarixl/. The default config file for <tt/atari/ is selected with <tt/-t atari/, and the default config file for <tt/atarixl/ is selected with <tt/-t atarixl/. The Atari package comes with additional secondary linker config files which can be used via <tt/-t atari -C <configfile>/ (for <tt/atari/ target) or <tt/-t atarixl -C <configfile>/ (for <tt/atarixl/ target). <sect1><tt/atari/ config files<p> <sect2>default config file (<tt/atari.cfg/)<p> The default configuration is tailored to C programs. It creates files which have a default load address of $2000. The files generated by this config file include the <ref name="&dquot;system check&dquot;" id="syschk"> load chunk. It can optionally be left out, see <ref name="Getting rid of the &dquot;system check&dquot; load chunk" id="nosyschk">. <sect2><tt/atari-asm.cfg/<p> This config file aims to give the assembler programmer maximum flexibility. All program segments (<tt/CODE/, <tt/DATA/, etc.) are optional. By default it creates regular DOS executable files, which have a default load address of $2E00. It's also possible to generate an image of just the program data without EXE header, load address, or (auto-)start address. To you so, you have to define the symbols <tt/__AUTOSTART__/ and <tt/__EXEHDR__/ when linking the program. Therefore, to generate a "plain" binary file, pass the options "<tt/-D__AUTOSTART__=1 -D__EXEHDR__=1/" to the linker. It's also possible to create a non auto-starting program file, by defining only the <tt/__AUTOSTART__/ symbol. Such a program has to be run manually after being loaded by DOS (for example by using the "M" option of DOS 2.5). Defining only the <tt/__EXEHDR__/ symbol will create a (useless) file which doesn't conform to the DOS executable file format (like a "plain" binary file) but still has the "autostart" load chunk appended. The sections of the file which the defines refer to (<tt/__AUTOSTART__/ for the autostart trailer, <tt/__EXEHDR__/ for the EXE header and load address) is <it/left out/, keep this in mind. The values you assign to the two symbols <tt/__AUTOSTART__/ and <tt/__EXEHDR__/ don't matter. <sect2><tt/atari-asm-xex.cfg/<p> This config file allows writing multi segment binaries easily, without having to write the header explicitly on each segment. It is similar to the <tt/atari-asm.cfg/ above, but uses the ATARI (xex) file format support on LD65 instead of the standard binary output, so it does not have the <tt/__AUTOSTART/ nor the <tt/__EXEHDR__/ symbols. Note that each <tt/MEMORY/ area in the configuration file will have it's own segment in the output file with the correct headers, and you can specify and init address INITAD) for each memory area. <sect2><tt/atari-cart.cfg/<p> This config file can be used to create 8K or 16K cartridges. It's suited both for C and assembly language programs. By default, an 8K cartridge is generated. To create a 16K cartridge, pass the size of the cartridge to the linker, like "<tt/-D__CARTSIZE__=0x4000/". The only valid values for <tt/__CARTSIZE__/ are 0x2000 and 0x4000. The option byte of the cartridge can be set with the <tt/__CARTFLAGS__/ value, passed to the linker. The default value is $01, which means that the cartridge doesn't prevent the booting of DOS. The option byte will be located at address $BFFD. For more information about its use, see e.g. "Mapping the Atari". <sect2><tt/atari-cassette.cfg/<p> This config file can be used to create cassette boot files. It's suited both for C and assembly language programs. The size of a cassette boot file is restricted to 32K. Larger programs would need to be split in more parts and the parts to be loaded manually. To write the generated file to a cassette, a utility (<tt/w2cas.com/) to run on an Atari is provided in the <tt/util/ directory of <tt/atari/ target dir. <sect2><tt/atari-xex.cfg/<p> This config file shows how to write a binary using the ATARI (xex) file format support on LD65, this simplifies the memory areas and allows to add new memory areas easily without writing new headers and trailers. Note that the default C library includes the system-check chunk, so in this linker configuration we suppress the importing of the header and trailer for this chunk by defining the standard import symbols to a 0 value. For the initialization address of the system-check chunk, the INITAD is set directly in the configuration. <sect1><tt/atarixl/ config files<p> <sect2>default config file (<tt/atarixl.cfg/)<p> The default configuration is tailored to C programs. It creates files which have a default load address of $2400. The files generated by this config file include the <ref name="&dquot;system check&dquot;" id="syschkxl"> load chunk. It can optionally be left out, see <ref name="Getting rid of the &dquot;system check&dquot; load chunk" id="nosyschk">. <sect2><tt/atarixl-largehimem.cfg/<p> This is the same as the default config file, but it rearranges the high memory beneath the ROM into one large block. In order for this config file to work, the runtime library has to be recompiled with a special define. See the file <tt/libsrc/atari/Makefile.inc/ in the source distribution. The files generated by this config file include the <ref name="&dquot;system check&dquot;" id="syschkxl"> load chunk. It can optionally be left out, see <ref name="Getting rid of the &dquot;system check&dquot; load chunk" id="nosyschk">. <sect2><tt/atarixl-xex.cfg/<p> Similar to the <tt/atari-xex.cfg/ above, this config file shows how to write a binary using the ATARI (xex) file format support on LD65. In addition to the suppressing of the system-check headers and trailers, this also suppresses the shadow-ram-preparation headers and trailers, but does this by defining an "UNUSED" memory area that is not written to the output file. <sect>Platform specific header files<p> Programs containing Atari specific code may use the <tt/atari.h/ header file. This also includes access to operating system locations (e.g. hardware shadow registers) by a structure called "<tt/OS/". The names are the usual ones you can find in system reference manuals. Example: <tscreen><verb> ... OS.savmsc = ScreenMemory; OS.color4 = 14; // white frame if (OS.stick0 != 15 || OS.ch != 255) // key or stick input? ... </verb></tscreen> Please note that memory location 762/$2FA is called "<tt/char_/" while the orignal name "<tt/char/" conflicts with the C keyword. If you like to use the OS names and locations for the original Atari 800 operating system, please "<tt/#define OSA/" before including the <tt/atari.h/ header file. If you like to target the floating point register model of revision 2 machines, put a "<tt/#define OS_REV2/" before including <tt/atari.h/. Access to the Basic programming language zero page variables is established by the structure "<tt/BASIC/". <sect1>Atari specific functions<p> The functions and global variable listed below are special for the Atari. See the <url url="funcref.html" name="function reference"> for declaration and usage. <itemize> <item>get_ostype <item>get_tv <item>_dos_type <item>_gtia_mkcolor <item>_getcolor <item>_getdefdev <item>_graphics <item>_is_cmdline_dos <item>_rest_vecs <item>_save_vecs <item>_scroll <item>_setcolor <item>_setcolor_low </itemize> <sect1>Hardware access<p> The following pseudo variables declared in the <tt/atari.h/ header file do allow access to hardware located in the address space. Some variables are structures, accessing the struct fields will access the chip registers. <descrip> <tag><tt/GTIA_READ/ and <tt/GTIA_WRITE/</tag> The <tt/GTIA_READ/ structure allows read access to the GTIA. The <tt/GTIA_WRITE/ structure allows write access to the GTIA. See the <tt/_gtia.h/ header file located in the include directory for the declaration of the structure. <tag><tt/POKEY_READ/ and <tt/POKEY_WRITE/</tag> The <tt/POKEY_READ/ structure allows read access to the POKEY. The <tt/POKEY_WRITE/ structure allows write access to the POKEY. See the <tt/_pokey.h/ header file located in the include directory for the declaration of the structure. <tag><tt/ANTIC/</tag> The <tt/ANTIC/ structure allows read access to the ANTIC. See the <tt/_antic.h/ header file located in the include directory for the declaration of the structure. <tag><tt/PIA/</tag> The <tt/PIA/ structure allows read access to the PIA 6520. See the <tt/_pia.h/ header file located in the include directory for the declaration of the structure. </descrip><p> <sect1>Display lists<p> A major feature of the Atari graphics chip "ANTIC" is to process instructions for the display generation. cc65 supports constructing these display lists by offering defines for the instructions. In conjunction with the "void"-variable extension of cc65, display lists can be created quite comfortable: <tscreen><verb> ... unsigned char ScreenMemory[100]; void DisplayList = { DL_BLK8, DL_BLK8, DL_BLK8, DL_LMS(DL_CHR20x8x2), ScreenMemory, DL_CHR20x8x2, DL_CHR20x8x2, DL_CHR20x8x2, DL_BLK4, DL_CHR20x8x2, DL_JVB, &DisplayList }; ... OS.sdlst = &DisplayList; ... </verb></tscreen> Please inspect the <tt/_antic.h/ header file to detemine the supported instruction names. Modifiers on instructions can be nested without need for an order: <tt/DL_LMS(DL_HSCROL(DL_VSCROL(DL_DLI(DL_MAP80x4x2))))/ Please mind that ANTIC has memory alignment requirements for "player missile graphics"-data, font data, display lists and screen memory. Creation of a special linker configuration with appropriate aligned segments and switching to that segment in the c-code is usually neccessary. A more memory hungry solution consists in using the "<tt/posix_memalign()/" function in conjunction with copying your data to the allocated memory. <sect1>Character mapping<p> The Atari has two representations for characters: <enum> <item> ATASCII is character mapping which is similar to ASCII and used by the CIO system of the OS. This is the default mapping of cc65 when producing code for the atari target. <item> The internal/screen mapping represents the real value of the screen ram when showing a character. </enum> For direct memory access (simplicity and speed) enabling the internal mapping can be useful. This can be achieved by including the "<tt/atari_screen_charmap.h/" header. A word of caution: Since the <tt/0x00/ character has to be mapped in an incompatible way to the C-standard, the usage of string functions in conjunction with internal character mapped strings delivers unexpected results regarding the string length. The end of strings are detected where you may not expect them (too early or (much) too late). Internal mapped strings typically support the "<tt/mem...()/" functions. <em>For assembler sources the macro "<tt/scrcode/" from the "<tt/atari.mac/" package delivers the same feature.</em> You can switch back to the ATASCII mapping by including "<tt/atari_atascii_charmap.h/". A final note: Since cc65 has currently some difficulties with string merging under different mappings, defining remapped strings works only flawlessly with static array initialization: <tscreen><verb> #include <atari_screen_charmap.h> char pcScreenMappingString[] = "Hello Atari!"; #include <atari_atascii_charmap.h> char pcAtasciiMappingString[] = "Hello Atari!"; </verb></tscreen> delivers correct results, while <tscreen><verb> #include <atari_screen_charmap.h> char* pcScreenMappingString = "Hello Atari!"; #include <atari_atascii_charmap.h> char* pcAtasciiMappingString = "Hello Atari!"; </verb></tscreen> does not. <sect1>Keyboard codes<p> For direct keyboard scanning in conjunction with e.g. the OS location "CH" (764/$2FC), all keyboard codes are available as defined values on C and assembler side. Example: <tscreen><verb> ... while (!kbhit()); switch (OS.ch) { case KEY_RETURN: ... case KEY_SPACE: ... case KEY_1: ... } ... </verb></tscreen> You can find the C defines in the file "<tt/atari.h/" or "<tt/atari.inc/" for the assembler variant. <sect>Loadable drivers<p> The names in the parentheses denote the symbols to be used for static linking of the drivers. <sect1>Graphics drivers<p> <table><tabular ca="rrrr"> <tt/atari/|<tt/atarixl/|screen resolution|display pages@<hline> <tt/atr3.tgi (atr3_tgi)/|<tt/atrx3.tgi (atrx3_tgi)/|40x24x4 (CIO mode 3, ANTIC mode 8)|1@ <tt/atr4.tgi (atr4_tgi)/|<tt/atrx4.tgi (atrx4_tgi)/|80x48x2 (CIO mode 4, ANTIC mode 9)|1@ <tt/atr5.tgi (atr5_tgi)/|<tt/atrx5.tgi (atrx5_tgi)/|80x48x4 (CIO mode 5, ANTIC mode A)|1@ <tt/atr6.tgi (atr6_tgi)/|<tt/atrx6.tgi (atrx6_tgi)/|160x96x2 (CIO mode 6, ANTIC mode B)|1@ <tt/atr7.tgi (atr7_tgi)/|<tt/atrx7.tgi (atrx7_tgi)/|160x96x4 (CIO mode 7, ANTIC mode D)|1@ <tt/atr8.tgi (atr8_tgi)/|<tt/atrx8.tgi (atrx8_tgi)/|320x192x2 (CIO mode 8, ANTIC mode F)|1@ <tt/atr8p2.tgi (atr8p2_tgi)/|<tt/atrx8p2.tgi (atrx8p2_tgi)/|320x192x2 (CIO mode 8, ANTIC mode F)|2@ <tt/atr9.tgi (atr9_tgi)/|<tt/atrx9.tgi (atrx9_tgi)/|80x192x16b (CIO mode 9, ANTIC mode F, GTIA mode $40)|1@ <tt/atr9p2.tgi (atr9p2_tgi)/|<tt/atrx9p2.tgi (atrx9p2_tgi)/|80x192x16b (CIO mode 9, ANTIC mode F, GTIA mode $40)|2@ <tt/atr10.tgi (atr10_tgi)/|<tt/atrx10.tgi (atrx10_tgi)/|80x192x9 (CIO mode 10, ANTIC mode F, GTIA mode $80)|1@ <tt/atr10p2.tgi (atr10p2_tgi)/|<tt/atrx10p2.tgi (atrx10p2_tgi)/|80x192x9 (CIO mode 10, ANTIC mode F, GTIA mode $80)|2@ <tt/atr11.tgi (atr11_tgi)/|<tt/atrx11.tgi (atrx11_tgi)/|80x192x16h (CIO mode 11, ANTIC mode F, GTIA mode $C0)|1@ <tt/atr14.tgi (atr14_tgi)/|<tt/atrx14.tgi (atrx14_tgi)/|160x192x2 (CIO mode 14, ANTIC mode C)|1@ <tt/atr15.tgi (atr15_tgi)/|<tt/atrx15.tgi (atrx15_tgi)/|160x192x4 (CIO mode 15, ANTIC mode E)|1@ <tt/atr15p2.tgi (atr15p2_tgi)/|<tt/atrx15p2.tgi (atrx15p2_tgi)/|160x192x4 (CIO mode 15, ANTIC mode E)|2 </tabular> <!-- <caption>bla bla --> </table> Many graphics modes require more memory than the text screen which is in effect when the program starts up. Therefore the programmer has to tell the program beforehand the memory requirements of the graphics modes the program intends to use. On the <tt/atari/ target his can be done by using the __RESERVED_MEMORY__ linker config variable. The number specified there describes the number of bytes to subtract from the top of available memory as seen from the runtime library. This memory is then used by the screen buffer. On the <tt/atarixl/ target the screen memory resides below the program load address. In order to reserve memory for a graphics mode, one simply uses a higher program load address. There are restrictions on selectable load addresses, see <ref name="Selecting a good program load address" id="loadaddr">. The numbers for the different graphics modes presented below should only be seen as a rule of thumb. Since the screen buffer memory needs to start at specific boundaries, the numbers depend on the current top of available memory. The following numbers were determined by a BASIC program. <table> <tabular ca="rr"> graphics mode|reserved memory@<hline> 0|1@ 1|1@ 2|1@ 3|1@ 4|1@ 5|182@ 6|1182@ 7|3198@ 8|7120@ 9|7146@ 10|7146@ 11|7146@ 12|162@ 13|1@ 14|3278@ 15|7120@ 16|1@ 17|1@ 18|1@ 19|1@ 20|1@ 21|184@ 22|1192@ 23|3208@ 24|7146@ 25|7146@ 26|7146@ 27|7146@ 28|162@ 29|1@ 30|3304@ 31|7146 </tabular> <caption>reserved memory required for different graphics modes </table> The values of "1" are needed because the graphics command crashes if it doesn't have at least one byte available. This seems to be a bug of the Atari ROM code. Default drivers: <tt/atr8.tgi (atr8_tgi)/ and <tt/atrx8.tgi (atrx8_tgi)/. <sect1>Extended memory drivers<p> Currently there is only one extended memory driver. It manages the second 64K of a 130XE. <table> <tabular ca="rr"> <tt/atari/|<tt/atarixl/@<hline> <tt/atr130.emd (atr130_emd)/|<tt/atrx130.emd (atrx130_emd)/ </tabular> </table> <sect1>Joystick drivers<p> Currently there are two joystick drivers available: <table> <tabular ca="rrr"> <tt/atari/|<tt/atarixl/|description@<hline> <tt/atrstd.joy (atrstd_joy)/|<tt/atrxstd.joy (atrxstd_joy)/|Supports up to two/four standard joysticks connected to the joystick ports of the Atari. (Four on the pre-XL systems, two on XL or newer.)@ <tt/atrmj8.joy (atrmj8_joy)/|<tt/atrxmj8.joy (atrxmj8_joy)/|Supports up to eight standard joysticks connected to a MultiJoy adapter. </tabular> </table> Default drivers: <tt/atrstd.joy (atrstd_joy)/ and <tt/atrxstd.joy (atrxstd_joy)/. <sect1>Mouse drivers<p> Currently there are five mouse drivers available: <table> <tabular ca="rrr"> <tt/atari/|<tt/atarixl/|description@<hline> <tt/atrjoy.mou (atrjoy_mou)/|<tt/atrxjoy.mou (atrxjoy_mou)/|Supports a mouse emulated by a standard joystick.@ <tt/atrst.mou (atrst_mou)/|<tt/atrxst.mou (atrxst_mou)/|Supports an Atari ST mouse.@ <tt/atrami.mou (atrami_mou)/|<tt/atrxami.mou (atrxami_mou)/|Supports an Amiga mouse.@ <tt/atrtrk.mou (atrtrk_mou)/|<tt/atrxtrk.mou (atrxtrk_mou)/|Supports an Atari trakball.@ <tt/atrtt.mou (atrtt_mou)/|<tt/atrxtt.mou (atrxtt_mou)/|Supports an Atari touch tablet. </tabular> </table> All mouse devices connect to joystick port #0. Default drivers: <tt/atrst.mou (atrst_mou)/ and <tt/atrxst.mou (atrxst_mou)/. <sect2>Mouse callbacks<p> There are two mouse callbacks available. <p> The "text mode" callbacks (<tt/mouse_txt_callbacks/) display the mouse cursor as a "diamond" character on the standard "GRAPHICS 0" text mode screen. The mouse cursor character can be changed by an assembly file defining the character by exporting the zeropage symbol <tt/mouse_txt_char/. The default file looks like this: <tscreen><verb> .export mouse_txt_char : zp = 96 ; 'diamond' screen code </verb></tscreen> <p> The "P/M" callbacks (<tt/mouse_pm_callbacks/) use Player-Missile graphics for the mouse cursor. The cursor shape can be changed, too, by an assembly file. Here's the default shape definition: <tscreen><verb> .export mouse_pm_bits .export mouse_pm_height : zeropage .export mouse_pm_hotspot_x : zeropage .export mouse_pm_hotspot_y : zeropage .rodata mouse_pm_bits: .byte %11110000 .byte %11000000 .byte %10100000 .byte %10010000 .byte %10001000 .byte %00000100 .byte %00000010 mouse_pm_height = * - mouse_pm_bits ; hot spot is upper left corner mouse_pm_hotspot_x = 0 mouse_pm_hotspot_y = 0 </verb></tscreen> <p> <tt/mouse_pm_bits/ defines the shape of the cursor, <tt/mouse_pm_height/ defines the number of bytes in <tt/mouse_pm_bits/. <tt/mouse_pm_hotspot_x/ and <tt/mouse_pm_hotspot_y/ define the position in the shape where "the mouse points to". When using this callback page #6 ($600 - $6FF) is used for the P/M graphics data and no P/M graphics can otherwise be used by the program. The height of the shape (<tt/mouse_pm_height/) must not exceed 32 lines since the callback routines cannot handle more than 32 lines. <p> The default callbacks definition (<tt/mouse_def_callbacks/) is an alias for the "P/M" callbacks. <sect1>RS232 device drivers<p> Currently there is one RS232 driver. It uses the R: device (therefore an R: driver needs to be installed) and was tested with the 850 interface module. <table> <tabular ca="rr"> <tt/atari/|<tt/atarixl/@<hline> <tt/atrrdev.ser (atrrdev_ser)/|<tt/atrxrdev.ser (atrxrdev_ser)/ </tabular> </table> <sect>Limitations<p> <sect1><tt/Realtime clock/<label id="realtimeclock"<p> Access to the realtime clock is supported only when running on SpartaDOS-X. There needs to be a realtime clock driver installed. This is normally the case in the default installation (CONFIG.SYS) of SpartaDOS-X. A missing realtime clock driver in SpartaDOS-X is not supported, and the program may crash when calling the <tt/clock_settime()/ or <tt/clock_gettime()/ functions. The resolution of the realtime clock driver is 1 second. <sect1><tt/atarixl target/<#if output="info|latex2e"> limitations</#if><label id="xllimitations"<p> <itemize> <item>The display is cleared at program start and at program termination. This is a side effect of relocating the display memory below the program start address. <item>Not all possible CIO and SIO functions are handled by the runtime stub code which banks the ROM in and out. All functions used by the runtime library are handled, though. <item>The <tt/_sys()/ function is not supported. <item>It is not compatible with DOSes or other programs using the memory below the ROM. </itemize> <sect>DIO implementation<label id="dio"><p> The Atari supports disk drives with either 128 or 256 byte sectors. The first three sectors of any disk are always 128 bytes long though. This is because the system can only boot from 128 bytes sectors. Therefore the DIO read and write functions transfer only 128 bytes for sectors 1 to 3, regardless of the type of diskette. <sect>CONIO implementation<label id="conio"><p> The console I/O is speed optimized therefore support for XEP80 hardware or f80.com software is missing. Of course you may use stdio.h functions. <sect>Technical details<label id="techdetail"><p> <sect1><tt/atari/<#if output="info|latex2e"> details</#if><p> <sect2><#if output="info|latex2e"><tt/atari/ </#if>Load chunks<p> An <tt/atari/ program contains two load chunks. <enum> <item>"system check"<label id="syschk">&nl; This load chunk is always loaded at address $2E00, and checks if the system has enough memory to run the program. It also checks if the program start address is not below MEMLO. If any of the checks return false, the loading of the program is aborted.&nl; The contents of this chunk come from the SYSCHKCHNK memory area of the linker config file. <item>main program&nl; This load chunk is loaded at the selected program start address (default $2000) and contains all of the code and data of the program.&nl; The contents of this chunk come from the MAIN memory area of the linker config file. </enum> <sect1><tt/atarixl/<#if output="info|latex2e"> details</#if><p> <sect2>General operation<p> The <tt/atarixl/ target banks out the ROM while the program is running in order to make more memory available to the program. The screen memory is by default located at the top of available memory, $BFFF if BASIC is not enabled, $9FFF if BASIC is enabled. Therefore, in order to create a largest possible continuous memory area, the screen memory is moved below the program load address. This gives a memory area from <program load addr> to $CFFF. The startup code installs wrappers for interrupt handlers and ROM routines. When an interrupt or call to a ROM routine happens, the wrappers enable the ROM, call the handler or routine, and disable the ROM again. The "wrapping" of the ROM routines is done by changing the ROM entry point symbols in <tt/atari.inc/ to point to the wrapper functions. For ROM functions which require input or output buffers, the wrappers copy the data as required to buffers in low memory. <sect2><#if output="info|latex2e"><tt/atarixl/ </#if>Load chunks<label id="xlchunks"><p> An <tt/atarixl/ program contains three load chunks. <enum> <item>"system check"<label id="syschkxl">&nl; This load chunk is always loaded at address $2E00, and checks if the system is suitable for running the program. It also checks if there is enough room between MEMLO and the program start address to move the text mode screen buffer there. If any of the checks return false, the loading of the program is aborted.&nl; The contents of this chunk come from the SYSCHKCHNK memory area of the linker config file. <item>"shadow RAM prepare"&nl; The second load chunk gets loaded to the selected program load address (default $2400). It moves the screen memory below the program load address, copies the character generator from ROM to its new place in RAM, and copies the parts of the program which reside in high memory below the ROM to their place. The high memory parts are included in this load chunk.&nl; At the beginning of this load chunk there is a .bss area, which is not part of the EXE file. Therefore the on-disk start address of this load chunk will be higher than the selected start address. This .bss area (segment LOWBSS) contains the buffers for the double buffering of ROM input and output data. If you add contents to this segment be aware that the contents won't be zero initialized by the startup code.&nl; The contents of this chunk come from the SRPREPCHNK memory area of the linker config file. <item>main program&nl; This load chunk is loaded just above the LOWBSS segment, replacing the code of the previous load chunk. It contains all remaining code and data sections of the program, including the startup code.&nl; The contents of this chunk come from the RAM memory area of the linker config file. </enum> <sect2>Moving screen memory below the program start address<p> When setting a graphics mode, the ROM looks at the RAMTOP location. RAMTOP describes the amount of installed memory in pages (RAMTOP is only one byte). The screen memory and display list are placed immediately below RAMTOP. Now in order to relocate the screen memory to lower memory, the startup code puts a value into RAMTOP which causes the ROM routines to allocate the display memory below the program start address and then it issues a ROM call to setup the regular text mode. <sect2>Selecting a good program load address<label id="loadaddr"><p> Due to the movement of the screen memory below the program start, there are some load addresses which are sub-optimal because they waste memory or prevent a higher resolution graphics mode from being enabled. There are restrictions at which addresses screen memory (display buffer and display list) can be placed. The display buffer cannot cross a 4K boundary and a display list cannot cross a 1K boundary. The startup code takes this into account when moving the screen memory down. If the program start address (aligned to the next lower page boundary) minus the screen buffer size would result in a screen buffer which spans a 4K boundary, the startup code lowers RAMTOP to this 4K boundary.&nl; The size of the screen buffer in text mode is 960 ($3C0) bytes. So, for example, a selected start address of $2300 would span the 4K boundary at $2000. The startup code would adjust the RAMTOP value in such way that the screen memory would be located just below this boundary (at $1C40). This results in the area [$2000-$22FF] being wasted. Additionally, the program might fail to load since the lowest address used by the screen memory could be below MEMLO. (The lowest address used in this example would be at $1C20, where the display list would allocated.) These calculations are performed by the startup code (in the first two load chunks), but the startup code only takes the default 40x24 text mode into account. If the program later wants to load TGI drivers which set a more memory consuming graphics mode, the user has to pick a higher load address. Using higher resolution modes there is a restriction in the ROM that it doesn't expect RAMTOP to be at arbitrary values. The Atari memory modules came only in 8K or 16K sizes, so the ROM expects RAMTOP to only have values in 8K steps. Therefore, when using the highest resolution modes the program start address must be at an 8K boundary. <sect2>Character generator location<label id="chargenloc"><p> The default <tt/atarixl/ linker config file (<tt/atarixl.cfg/) leaves the character generator location at the same address where it is in ROM ($E000). This has the disadvatage to split the upper memory into two parts ([$D800-$DFFF] and [$E400-$FFF9]). For applications which require a large continuous upper memory area, an alternative linker config file (<tt/atarixl-largehimem.cfg/) is provided. It relocates the character generator to $D800, providing a single big upper memory area at [$DC00-$FFF9]. With the character generator at a different address than in ROM, the routines which enable and disable the ROM also have to update the chargen pointer. This code is not enabled by default. In order to enable it, uncomment the line which sets CHARGEN_RELOC in <tt/libsrc/atari/Makefile.inc/ and recompile the <tt/atarixl/ runtime library. <sect>Other hints<p> <sect1>Function keys<p> Function keys are mapped to Atari + number key. <sect1>Passing arguments to the program<p> Command line arguments can be passed to <tt/main()/ when the used DOS supports it. <enum> <item>Arguments are separated by spaces. <item>Leading and trailing spaces around an argument are ignored. <item>The first argument passed to <tt/main/ is the program name. <item>A maximum number of 16 arguments (including the program name) are supported. </enum> <sect1>Interrupts<p> The runtime for the Atari uses routines marked as <tt/.INTERRUPTOR/ for interrupt handlers. Such routines must be written as simple machine language subroutines and will be called automatically by the VBI handler code when they are linked into a program. See the discussion of the <tt/.CONDES/ feature in the <url url="ca65.html" name="assembler manual">. Please note that on the Atari targets the <tt/.INTERRUPTOR/s are being run in NMI context. The other targets run them in IRQ context. <sect1>Reserving a memory area inside a program<label id="memhole"><p> (This section is primarily applicable to the <tt/atari/ target, but the principles apply to <tt/atatixl/ as well.) The Atari 130XE maps its additional memory into CPU memory in 16K chunks at address $4000 to $7FFF. One might want to prevent this memory area from being used by cc65. Other reasons to prevent the use of some memory area could be to reserve space for the buffers for display lists and screen memory. <p> The Atari executable format allows holes inside a program, e.g. one part loads into $2E00 to $3FFF, going below the reserved memory area (assuming a reserved area from $4000 to $7FFF), and another part loads into $8000 to $BC1F. <p> Each load chunk of the executable starts with a 4 byte header which defines its load address and size. In the following linker config files these headers are named HEADER and SECHDR (for the MEMORY layout), and accordingly NEXEHDR and CHKHDR (for the SEGMENTS layout). <p> <sect2>Low code and high data example<p> Goal: Create an executable with 2 load chunks which doesn't use the memory area from $4000 to $7FFF. The CODE segment of the program should go below $4000 and the DATA and RODATA segments should go above $7FFF. <p> The main problem is that the EXE header generated by the cc65 runtime lib is wrong. It defines a single load chunk with the sizes/addresses of the STARTUP, LOWCODE, ONCE, CODE, RODATA, and DATA segments, in fact, the whole user program (we're disregarding the "system check" load chunk here). <p> The contents of the EXE header come from the EXEHDR and MAINHDR segments. The EXEHDR segment just contains the $FFFF value which is required to be the first bytes of the EXE file.&nl; The MAINHDR are defined in in crt0.s. This cannot be changed without modifying and recompiling the cc65 atari runtime library. Therefore the original contents of this segment must be discarded and be replaced by a user created one. This discarding is done by assigning the MAINHDR segment to the (new introduced) DISCARD memory area. The DISCARD memory area is thrown away in the new linker config file (written to file ""). We add a new FSTHDR segment for the chunk header of the first chunk. <p> The user needs to create a customized linker config file which adds new memory areas and segments to hold the new header data for the first load chunk and the header data for the second load chunk. Also an assembly source file needs to be created which defines the contents of the new header data for the two load chunks. <p> <p> This is an example of a modified cc65 Atari linker configuration file (split.cfg): <tscreen><verb> SYMBOLS { __STACKSIZE__: value = $800 type = weak; # 2K stack __RESERVED_MEMORY__: value = $0000, type = weak; } FEATURES { STARTADDRESS: default = $2E00; } MEMORY { ZP: start = $82, size = $7E, type = rw, define = yes; HEADER: start = $0000, size = $2, file = %O; # first load chunk FSTHDR: start = $0000, size = $4, file = %O; # second load chunk RAMLO: start = %S, size = $4000 - %S, file = %O; DISCARD: start = $4000, size = $4000, file = ""; SECHDR: start = $0000, size = $4, file = %O; # second load chunk RAM: start = $8000, size = $3C20, file = %O; # $3C20: matches upper bound $BC1F } SEGMENTS { EXEHDR: load = HEADER, type = ro; MAINHDR: load = DISCARD, type = ro; NEXEHDR: load = FSTHDR, type = ro; # first load chunk STARTUP: load = RAMLO, type = ro, define = yes; LOWCODE: load = RAMLO, type = ro, define = yes, optional = yes; ONCE: load = RAMLO, type = ro, optional = yes; CODE: load = RAMLO, type = ro, define = yes; CHKHDR: load = SECHDR, type = ro; # second load chunk RODATA: load = RAM, type = ro, define = yes; DATA: load = RAM, type = rw, define = yes; BSS: load = RAM, type = bss, define = yes; ZEROPAGE: load = ZP, type = zp; AUTOSTRT: load = RAM, type = ro; # defines program entry point } FEATURES { CONDES: segment = ONCE, type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__; CONDES: segment = RODATA, type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__; } </verb></tscreen> <p> A new memory area DISCARD was added. It gets loaded with the contents of the (now unused) MAINHDR segment. But the memory area isn't written to the output file. This way the contents of the MAINHDR segment get discarded. <p> The newly added NEXEHDR segment defines the correct chunk header for the first intended load chunk. It puts the STARTUP, LOWCODE, ONCE, and CODE segments, which are the segments containing only code, into load chunk #1 (RAMLO memory area). <p> The header for the second load chunk comes from the new CHKHDR segment. It puts the RODATA, DATA, BSS, and ZPSAVE segments into load chunk #2 (RAM memory area). <p> <p> The contents of the new NEXEHDR and CHKHDR segments come from this file (split.s): <tscreen><verb> .import __CODE_LOAD__, __BSS_LOAD__, __CODE_SIZE__ .import __DATA_LOAD__, __RODATA_LOAD__, __STARTUP_LOAD__ .segment "NEXEHDR" .word __STARTUP_LOAD__ .word __CODE_LOAD__ + __CODE_SIZE__ - 1 .segment "CHKHDR" .word __RODATA_LOAD__ .word __BSS_LOAD__ - 1 </verb></tscreen> <p> Compile with <tscreen><verb> cl65 -t atari -C split.cfg -o prog.com prog.c split.s </verb></tscreen> <sect2>Low data and high code example<p> Goal: Put RODATA and DATA into low memory and STARTUP, LOWCODE, ONCE, CODE, BSS, ZPSAVE into high memory (split2.cfg): <tscreen><verb> SYMBOLS { __STACKSIZE__: value = $800 type = weak; # 2K stack __RESERVED_MEMORY__: value = $0000, type = weak; } FEATURES { STARTADDRESS: default = $2E00; } MEMORY { ZP: start = $82, size = $7E, type = rw, define = yes; HEADER: start = $0000, size = $2, file = %O; # first load chunk FSTHDR: start = $0000, size = $4, file = %O; # second load chunk RAMLO: start = %S, size = $4000 - %S, file = %O; DISCARD: start = $4000, size = $4000, file = ""; SECHDR: start = $0000, size = $4, file = %O; # second load chunk RAM: start = $8000, size = $3C20, file = %O; # $3C20: matches upper bound $BC1F } SEGMENTS { EXEHDR: load = HEADER, type = ro; # discarded old EXE header MAINHDR: load = DISCARD, type = ro; NEXEHDR: load = FSTHDR, type = ro; # first load chunk RODATA: load = RAMLO, type = ro, define = yes; DATA: load = RAMLO, type = rw, define = yes; CHKHDR: load = SECHDR, type = ro; # second load chunk STARTUP: load = RAM, type = ro, define = yes; ONCE: load = RAM, type = ro, optional = yes; CODE: load = RAM, type = ro, define = yes; BSS: load = RAM, type = bss, define = yes; ZEROPAGE: load = ZP, type = zp; AUTOSTRT: load = RAM, type = ro; # defines program entry point } FEATURES { CONDES: segment = ONCE, type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__; CONDES: segment = RODATA, type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__; } </verb></tscreen> New contents for NEXEHDR and CHKHDR are needed (split2.s): <tscreen><verb> .import __STARTUP_LOAD__, __BSS_LOAD__, __DATA_SIZE__ .import __DATA_LOAD__, __RODATA_LOAD__ .segment "NEXEHDR" .word __RODATA_LOAD__ .word __DATA_LOAD__ + __DATA_SIZE__ - 1 .segment "CHKHDR" .word __STARTUP_LOAD__ .word __BSS_LOAD__ - 1 </verb></tscreen> Compile with <tscreen><verb> cl65 -t atari -C split2.cfg -o prog.com prog.c split2.s </verb></tscreen> <sect2>Final note<label id="memhole_final_note"><p> There are two other memory areas which don't appear directly in the linker config file. They are the stack and the heap. The cc65 runtime lib places the stack location at the end of available memory. This is dynamically set from the MEMTOP system variable at startup. The heap is located in the area between the end of the BSS segment and the top of the stack as defined by __STACKSIZE__. If BSS and/or the stack shouldn't stay at the end of the program, some parts of the cc65 runtime lib need to be replaced/modified. common/_heap.s defines the location of the heap and atari/crt0.s defines the location of the stack by initializing sp. <sect1>Upgrading from an older cc65 version<p> If you are using a customized linker config file you might get some errors regarding the MAINHDR segment. Like this: <tscreen><verb> ld65: Error: Missing memory area assignment for segment 'MAINHDR' </verb></tscreen> The old "HEADER" memory description contained six bytes: $FFFF and the first and last memory addess of the program. For the "system check" load chunk this had to be split into two memory assigments. The "HEADER" now only contains the $FFFF. The main program's first and last memory address were moved to a new segment, called "MAINHDR", which in the new linker config file goes into its own memory area (also called "MAINHDR").&nl;&nl; A simple way to adapt your old linker config file is to add the following line to the "SEGMENTS" section: <tscreen><verb> MAINHDR: load = HEADER, type = ro; </verb></tscreen> <sect1>Getting rid of the "system check" load chunk<label id="nosyschk"><p> If, for some reason, you don't want to include the "system check" load chunk, you can do so by defining the symbol <tt/__SYSTEM_CHECK__/ when linking the program. The "system check" chunk doesn't include vital parts of the program. So if you don't want the system checks, it is save to leave them out. This is probably mostly interesting for debugging. When using cl65, you can leave it out with this command line: <tscreen><verb> cl65 -Wl -D__SYSTEM_CHECK__=1 <arguments> </verb></tscreen> The value you assign to <tt/__SYSTEM_CHECK_/ doesn't matter. If the <tt/__SYSTEM_CHECK__/ symbol is defined, the load chunk won't be included. <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> cc65-2.18/doc/atari2600.sgml������������������������������������������������������������������������0000664�0000000�0000000�00000007472�13473601511�0015260�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>Atari 2600 specific information for cc65 <author> <url url="mailto:contact@florentflament.com" name="Florent Flament"><newline> <abstract> An overview over the Atari 2600 runtime system as it is implemented for the cc65 C compiler. </abstract> <!-- Table of contents --> <toc> <!-- Begin the document --> <sect>Overview<p> This file contains an overview of the Atari 2600 runtime system as it comes with the cc65 C compiler. It describes the memory layout, Atari 2600 specific header files and any pitfalls specific to that platform. <sect>Binary format<p> The default binary output format generated by the linker for the Atari 2600 target is a 4K cartridge image. <sect>Memory layout<p> cc65 generated programs with the default setup can use RAM from $0080 to $00FF - __STACKSIZE__, where __STACKSIZE__ is the size of the system stack with a default value of 16 bytes. The size of the system stack can be customized by defining the __STACKSIZE__ linker variable. Special locations: <descrip> <tag/Stack/ The C runtime stack is located at $00FF - __STACKSIZE__ and growing downwards. <tag/Heap/ The C heap is located at $0080 and grows upwards. </descrip><p> <sect>Start-up condition<p> When powered-up, the Atari 2600 TIA registers contain random values. During the initialization phase, the start-up code needs to initialize the TIA registers to sound values (or else the console has an unpredictable behavior). In this implementation, zeros are written to all of TIA registers during the start-up phase. Note that RIOT registers (mostly timers) are left uninitialized, as they don't have any consequence on the console behavior. <sect>Platform specific header files<p> Programs containing Atari 2600 specific code may use the <tt/atari2600.h/ header file. The following pseudo variables declared in the <tt/atari2600.h/ header file allow access to the Atari 2600 TIA & RIOT chips registers. <descrip> <tag><tt/TIA/</tag> The <tt/TIA/ structure allows read/write access to the Atari 2600 TIA chip registers. See the <tt/_tia.h/ header file located in the include directory for the declaration of the structure. Also refer to the Stella Programmer's Guide by Steve Wright for a detailed description of the chip and its registers. <tag><tt/RIOT/</tag> The <tt/RIOT/ structure allows read/write access to the Atari 2600 RIOT chip registers. See the <tt/_riot.h/ header file located in the include directory for the declaration of the structure. Also refer to the Stella Programmer's Guide by Steve Wright for a detailed description of the chip and its registers. </descrip><p> <sect>Loadable drivers<p> There are no drivers for the Atari 2600. <sect>Limitations<p> TBD <sect>Other hints<p> One may write a custom linker configuration file to tune the memory layout of a program. See the <tt/atari2600.cfg/ file in the cfg directory as a starting point. <sect>License<p> This software is provided 'as-is', without any expressed or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: <enum> <item> The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. <item> Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. <item> This notice may not be removed or altered from any source distribution. </enum> </article> ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/atari5200.sgml������������������������������������������������������������������������0000664�0000000�0000000�00000016035�13473601511�0015252�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>Atari 5200 specific information for cc65 <author> <url url="mailto:chris@groessler.org" name="Christian Groessler"><newline> <abstract> An overview over the Atari 5200 runtime system as it is implemented for the cc65 C compiler. </abstract> <!-- Table of contents --> <toc> <!-- Begin the document --> <sect>Overview<p> This file contains an overview of the Atari 5200 runtime system as it comes with the cc65 C compiler. It describes the memory layout, Atari 5200 specific header files, available drivers, and any pitfalls specific to that platform. Please note that Atari 5200 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 Atari 5200 target is a cartridge image. 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 use the RAM space from $021C to $3FFF. If you want to reserve memory for the display list and screen buffer you should define the __RESERVED_MEMORY__ linker variable. The number of bytes specified by __RESERVED_MEMORY__ are lowering the top of memory, therefore the available RAM memory for the program is $021C to $3FFF-__RESERVED_MEMORY__. The default linker config file sets __RESERVED_MEMORY__ to $1E0 to reserve space for an optional CONIO text screen. Special locations: <descrip> <tag/Text screen/ The text screen is only enabled if any of the CONIO output functions is used in the program. Its size is 20x24 characters (Antic mode 6, BASIC mode 1) by default. The text screen is located at $3E00. The address of the screen memory is available at runtime in the variable SAVMSC ($001B).<p> If the program doesn't use any CONIO output functions it needs to setup its own display list. <tag/Stack/ The C runtime stack is located at $3FFF-__RESERVED_MEMORY__ and growing downwards. <tag/Heap/ The C heap is located at the end of the program and grows towards the C runtime stack. </descrip><p> <sect>Platform specific header files<p> Programs containing Atari 5200 specific code may use the <tt/atari5200.h/ header file. <sect1>Atari 5200 specific functions<p> <itemize> <item>TBD. </itemize> <sect1>Hardware access<p> The following pseudo variables declared in the <tt/atari5200.h/ header file do allow access to hardware located in the address space. Some variables are structures, accessing the struct fields will access the chip registers. <descrip> <tag><tt/GTIA_READ/ and <tt/GTIA_WRITE/</tag> The <tt/GTIA_READ/ structure allows read access to the GTIA. The <tt/GTIA_WRITE/ structure allows write access to the GTIA. See the <tt/_gtia.h/ header file located in the include directory for the declaration of the structure. <tag><tt/POKEY_READ/ and <tt/POKEY_WRITE/</tag> The <tt/POKEY_READ/ structure allows read access to the POKEY. The <tt/POKEY_WRITE/ structure allows write access to the POKEY. See the <tt/_pokey.h/ header file located in the include directory for the declaration of the structure. <tag><tt/ANTIC/</tag> The <tt/ANTIC/ structure allows read access to the ANTIC. See the <tt/_antic.h/ header file located in the include directory for the declaration of the structure. </descrip><p> <sect>Loadable drivers<p> All drivers must be statically linked because no disk 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 graphics drivers are currently available for the Atari 5200. <sect1>Extended memory drivers<p> No extended memory drivers are available for the Atari 5200. <sect1>Joystick drivers<p> <descrip> <tag><tt/atr5200std.joy (atr5200std_joy)/</tag> A joystick driver for the standard Atari 5200 joystick is available. Depending on the version of the 5200 console, two or four joysticks can be attached. </descrip><p> <sect1>Mouse drivers<p> No mouse drivers are available for the Atari 5200. <sect1>RS232 device drivers<p> No serial drivers are available for the Atari 5200. <sect>Limitations<p> <sect1>Direct console I/O<p> The <tt/atari5200/ target uses Antic mode 6 (BASIC mode 1) for the console screen by default. There are four colors available: <itemize> <item><tt/COLOR_WHITE/ <item><tt/COLOR_RED/ <item><tt/COLOR_GREEN/ <item><tt/COLOR_BLACK/ </itemize> Note that the <tt/COLOR_GREEN/ and <tt/COLOR_RED/ colors aren't exactly the same colors as the ones with the same name on the <tt/atari/ target. They are the colors which are available as <tt/COLOR_LIGHTGREEN/ and <tt/COLOR_LIGHTRED/ there. One can set the color shadow registers directly with other colors. Then the color defines from above will just become placeholders. In this scenario it might be more convenient to use index values (0..3) instead of the color defines. The index values specify which of the system shadow color registers (<tt/COLOR0/ .. <tt/COLOR3/) to use. The default console screen has a layout of 20x24 characters. An alternative layout, 20x12, Antic mode 7, BASIC mode 2, is provided in the file <tt/atari5200-conioscreen-20x12.o/. Using <tt/atari5200-conioscreen-20x12.o/ is as simple as placing it on the linker command line like this: <tscreen><verb> cl65 -t atari5200 myprog.c atari5200-conioscreen-20x12.o </verb></tscreen> <sect1>Disk I/O<p> Disk I/O is not supported by the <tt/atari5200/ target. This means that you cannot use any of the following functions (and a few others): <itemize> <item>fclose <item>fopen <item>fread <item>fprintf <item>fputc <item>fscanf <item>fwrite <item>... </itemize> <sect>Other hints<p> AtariROMMaker (<url url="https://www.wudsn.com/index.php/productions-atari800/tools/atarirommaker"> ) can be used to create a <tt/.CAR/ file from the binary ROM image cc65 generates. This might be more convenient when working with emulators. <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> ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/atmos.sgml����������������������������������������������������������������������������0000664�0000000�0000000�00000021715�13473601511�0014767�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>Oric Atmos-specific information for cc65 <author> <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"> <abstract> An overview over the Atmos 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 Atmos runtime system as it comes with the cc65 C compiler. It describes the memory layout, Atmos-specific header files, available drivers, and any pitfalls specific to that platform. Please note that Atmos-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 Atmos target 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 $501. <sect>Memory layout<p> In the standard setup, cc65-generated programs use the memory from $0501 to $9800; so, nearly 37K of memory (including the stack) is available. ROM calls are possible without further precautions. If your program needs more memory, and it won't use TGI graphics, then you can use the ld65 command-line option, <tt/-D __GRAB__=1/, when building the program, to include the graphics screen RAM. Then, nearly 44K of memory ($0501 to $B400) is available. Special locations: <descrip> <tag/Stack/ The C runtime stack is located at $97FF (or $B3FF), and grows downwards. <tag/Heap/ The C heap is located at the end of the program, and grows towards the C runtime stack. </descrip><p> <sect>Platform-specific header files<p> Programs containing Atmos-specific code may use the <tt/atmos.h/ header file. <sect1>Atmos-specific functions<p> The functions listed below are special for the Atmos. See the <url url="funcref.html" name="function reference"> for declaration and usage. <itemize> <item>atmos_load <item>atmos_save <item>atmos_explode <item>atmos_ping <item>atmos_shoot <item>atmos_tick <item>atmos_tock <item>atmos_zap </itemize> <sect1>Hardware access<p> The following pseudo variables declared in the <tt/atmos.h/ header file do allow access to hardware located in the address space. Some variables are 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 <tt/VIA/ variable. The structure behind this variable is explained in <tt/_6522.h/. </descrip><p> <sect>Loadable drivers<p> <em>Note:</em> Since the Atmos doesn't have working disk I/O (see <ref id="limitations" name="section "Limitations"">), the available drivers cannot be loaded at runtime (so the term "loadable drivers" is somewhat misleading). Instead, the drivers have to be statically linked. While this may seem overhead, it has two advantages: <enum> <item>The interface is identical to the one used for other platforms and to the one for the Atmos once it has disk I/O. <item>Once disk I/O is available, existing code can be changed to load drivers at runtime with almost no effort. </enum> The names in the parentheses denote the symbols to be used for static linking of the drivers. <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)/. <descrip> <tag><tt/atmos-228-200-3.tgi (atmos_228_200_3_tgi)/</tag> This driver was written by Greg King and Stefan Haubenthal. It features a resolution of 228×200 with a palette of two colors that can be chosen from the Atmos's eight colors. The driver supports a third palette-"color" that actually "flips" the pixel (it becomes the other color) that is on the screen under the graphics cursor. <tag><tt/atmos-240-200-2.tgi (atmos_240_200_2_tgi)/</tag> This driver was written by Stefan Haubenthal and Greg King. It features a resolution of 240×200 with black and white colors. It is the default graphics driver for the Atmos. </descrip><p> <sect1>Extended memory drivers<p> No extended memory drivers are currently available for the Atmos. <sect1>Joystick drivers<p> <descrip> <tag><tt/atmos-pase.joy (atmos_pase_joy)/</tag> Supports two standard joysticks connected to a P.A.S.E. / Altai interface of the Atmos. <tag><tt/atmos-ijk.joy (atmos_ijk_joy)/</tag> Supports two standard joysticks connected to an IJK interface of the Atmos. </descrip><p> <sect1>Mouse drivers<p> No mouse drivers are currently available for the Atmos. <sect1>RS232 device drivers<p> <descrip> <tag><tt/atmos-acia.ser (atmos_acia_ser)/</tag> Driver for the Telestrat integrated serial controller and the Atmos with a serial add-on. Note that, because of the peculiarities of the 6551 chip, together with the use of the NMI, transmits are not interrupt driven; and, the transceiver blocks if the receiver asserts flow control because of a full buffer. </descrip><p> <sect>Limitations<label id="limitations"><p> <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 <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, that limitation means that you cannot use any of the following functions (and a few others): <itemize> <item>fclose <item>fopen <item>fread <item>fprintf <item>fputc <item>fscanf <item>fwrite <item>... </itemize> <sect>Other hints<p> <sect1>Function keys<p> 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> Command-line arguments can be passed to <tt/main()/. Since that is not supported directly by BASIC, the following syntax was chosen: <tscreen><verb> 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 a quoted argument are allowed. <item>The first argument passed to <tt/main()/ is the program name. <item>A maximum number of 10 arguments (including the program name) are supported. </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 interrupt handlers. Such routines must be written as simple machine language subroutines and will be called automatically by the interrupt handler code when they are linked into a program. See the discussion of the <tt/.CONDES/ feature in the <url url="ca65.html" name="assembler manual">. <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> ���������������������������������������������������cc65-2.18/doc/c128.sgml�����������������������������������������������������������������������������0000664�0000000�0000000�00000032324�13473601511�0014317�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>Commodore 128-specific information for cc65 <author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline> <url url="mailto:polluks@sdf.lonestar.org" name="Stefan A. Haubenthal"> <abstract> An overview over the C128 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 C128 runtime system as it comes with the cc65 C compiler. It describes the memory layout, C128-specific header files, available drivers, and any pitfalls specific to that platform. Please note that C128-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 C128 target is a machine language program with a one line BASIC stub, which calls the machine language part via SYS. This means that a program can be loaded as BASIC program and started with RUN. 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 the kernal ROM enabled. Note that this is a non standard memory layout, and that there is no "memory configuration index" for this layout. This means that special care has to be taken when changing the configuration, or calling any code that does this. The memory configuration register at $FF00 should be saved and restored instead of relying on the memory configuration index stored in the zero page. The setup gives a usable memory range of $1C00 - $BFFF. Having just the kernal ROM mapped in means, that kernal entry points may be called directly, but using the BASIC ROM is not possible without additional code. Special locations: <descrip> <tag/Text screen/ The text screen is located at $400 (as in the standard setup). <tag/Stack/ The C runtime stack is located at $BFFF, and growing downwards. <tag/Heap/ The C heap is located at the end of the program, and grows towards the C runtime stack. </descrip><p> <sect>Platform-specific header files<p> Programs containing C128-specific code may use the <tt/c128.h/ or <tt/cbm.h/ header files. Using the later may be an option when writing code for more than one CBM platform, since it includes <tt/c128.h/ and declares several functions common to all CBM platforms. <sect1>C128-specific functions<p> The functions listed below are special for the C128. See the <url url="funcref.html" name="function reference"> for declaration and usage. <itemize> <item>videomode <item>c64mode </itemize> <sect1>C128-specific accelerator functions<p> The functions listed below are accelerator functions for the C128. See the <url url="funcref.html" name="function reference"> for declaration and usage. <itemize> <item>detect_c128 <item>detect_scpu <item>get_c128_speed <item>get_scpu_speed <item>set_c128_speed <item>set_scpu_speed </itemize> <sect1>CBM-specific functions<p> Some functions are available for all (or at least most) of the Commodore machines. See the <url url="funcref.html" name="function reference"> for declaration and usage. <itemize> <item>cbm_close <item>cbm_closedir <item>cbm_k_setlfs <item>cbm_k_setnam <item>cbm_k_load <item>cbm_k_save <item>cbm_k_open <item>cbm_k_close <item>cbm_k_readst <item>cbm_k_chkin <item>cbm_k_ckout <item>cbm_k_basin <item>cbm_k_bsout <item>cbm_k_clrch <item>cbm_k_tksa <item>cbm_k_second <item>cbm_load <item>cbm_open <item>cbm_opendir <item>cbm_read <item>cbm_readdir <item>cbm_save <item>cbm_write <item>get_tv </itemize> <sect1>CBM specific CPU functions<p> Some CPU related functions are available for some of the Commodore machines. See the <url url="funcref.html" name="function reference"> for declaration and usage. <itemize> <item>fast <item>slow <item>isfast </itemize> <sect1>Hardware access<p> The following pseudo variables declared in the <tt/c128.h/ header file do allow access to hardware located in the address space. Some variables are structures, accessing the struct fields will access the chip registers. <descrip> <tag><tt/VIC/</tag> The <tt/VIC/ structure allows access to the VIC II (the graphics controller). See the <tt/_vic2.h/ header file located in the include directory for the declaration of the structure. <tag><tt/SID/</tag> The <tt/SID/ structure allows access to the SID (the sound interface device). See the <tt/_sid.h/ header file located in the include directory for the declaration of the structure. <tag><tt/VDC/</tag> The <tt/VDC/ structure allows access to the VDC (the video display controller). See the <tt/_vdc.h/ header file located in the include directory for the declaration of the structure. <tag><tt/CIA1, CIA2/</tag> Access to the two CIA (complex interface adapter) chips is available via the <tt/CIA1/ and <tt/CIA2/ variables. The structure behind these variables is explained in <tt/_6526.h/. <tag><tt/COLOR_RAM/</tag> A character array that mirrors the color RAM of the C128 at $D800. </descrip><p> <sect>Loadable drivers<p> The names in the parentheses denote the symbols to be used for static linking of the drivers. <sect1>Graphics drivers<p> The default drivers, <tt/tgi_stddrv (tgi_static_stddrv)/, point to <tt/c128-vdc.tgi (c128_vdc_tgi)/. Note: The graphics drivers for the VDC are incompatible with the extended memory drivers using the VDC memory! <descrip> <tag><tt/c128-hi.tgi (c128_hi_tgi)/</tag> This driver features a resolution of 320×200 with two colors and an adjustable palette (that means that the two colors can be chosen out of a palette of the 16 VIC colors). Unlike BASIC 7.0, this driver puts its graphics data into the RAM behind the ROMs. <tag><tt/c128-vdc.tgi (c128_vdc_tgi)/</tag> This driver was written by Maciej Witkowiak. It uses the 80-column display, and features a resolution of 640×200 with two colors and an adjustable palette (that means that the two colors can be chosen out of the 16 VDC colors). <tag><tt/c128-vdc2.tgi (c128_vdc2_tgi)/</tag> This driver was written by Maciej Witkowiak. This driver uses the 80-column display, and features a resolution of 640×480 with two colors and an adjustable palette (that means that the two colors can be chosen out of the 16 VDC colors). The driver requires 64KB VDC RAM. </descrip><p> Note: The colors are translated from the definitions in the headers to correct VDC values; so, please use definitions or VIC color numbers only. Colors <tt/GRAY3/ and <tt/BROWN/ are missing on the VDC; and, are translated to the two colors missing from the VIC palette. <sect1>Extended memory drivers<p> <descrip> <tag><tt/c128-efnram.emd (c128_efnram_emd)/</tag> Extended memory driver for the C128 External Function RAM. Written and contributed by Marco van den Heuvel. <tag><tt/c128-georam.emd (c128_georam_emd)/</tag> A driver for the GeoRam cartridge. The driver will always assume 2048 pages of 256 bytes each. There are no checks, so if your program knows better, just go ahead. <tag><tt/c128-ifnram.emd (c128_ifnram_emd)/</tag> Extended memory driver for the C128 Internal Function RAM. Written and contributed by Marco van den Heuvel. <tag><tt/c128-ram.emd (c128_ram_emd)/</tag> An extended memory driver for the RAM in page 1. The common memory area is excluded, so this driver supports 251 pages of 256 bytes each. <tag><tt/c128-ram2.emd (c128_ram2_emd)/</tag> An extended memory driver for the RAM in pages 1-3. The common memory area is excluded, so this driver supports up to 731 pages of 256 bytes each. The driver can be used as a full replacement for <tt/c128-ram.emd/, because RAM in pages 2+3 is autodetected, but it's larger and there are not many machines with RAM in banks 2+3, so it has been made a separate driver. The additional code was contributed by Marco van den Heuvel. <tag><tt/c128-ramcart.emd (c128_ramcart_emd)/</tag> A driver for the RamCart 64/128 written and contributed by Maciej Witkowiak. Will test the hardware for the available RAM. <tag><tt/c128-reu.emd (c128_reu_emd)/</tag> A driver for the CBM REUs. The driver will test the connected REU to find out how much RAM is present. <tag><tt/c128-vdc.emd (c128_vdc_emd)/</tag> A driver for the VDC memory of the C128, written and contributed by Maciej Witkowiak. Autodetects the amount of memory available (16 or 64K), and offers 64 or 256 pages of 256 bytes each. Note: This driver is incompatible with any of the graphics drivers using the VDC! </descrip><p> <sect1>Joystick drivers<p> The default drivers, <tt/joy_stddrv (joy_static_stddrv)/, point to <tt/c128-stdjoy.joy (c128_stdjoy_joy)/. <descrip> <tag><tt/c128-ptvjoy.joy (c128_ptvjoy_joy)/</tag> Driver for the Protovision 4-player adapter originally written by Groepaz for the C64, and converted for the C128 by Uz. See <url url="http://www.protovision-online.de/hardw/4_player.php?language=en" name="Protovision shop"> for prices and building instructions. Up to four joysticks are supported. <tag><tt/c128-stdjoy.joy (c128_stdjoy_joy)/</tag> Supports up to two joysticks connected to the standard joysticks ports of the C128. </descrip><p> <sect1>Mouse drivers<p> The default drivers, <tt/mouse_stddrv (mouse_static_stddrv)/, point to <tt/c128-1351.mou (c128_1351_mou)/. <descrip> <tag><tt/c128-1351.mou (c128_1351_mou)/</tag> Supports a standard mouse connected to port #0 of the C128. <tag><tt/c128-inkwell.mou (c128_inkwell_mou)/</tag> Supports the Inkwell Systems lightpens, connected to port #0 of the C128. It can read both the one-button 170-C and the two-button 184-C pens. (It can read other lightpens and light-guns that send their button signal to the joystick left-button pin or the paddle Y [up/down] pin.) It works on only the 40-column screen. <tag><tt/c128-joy.mou (c128_joy_mou)/</tag> Supports a mouse emulated by a standard joystick, e.g. 1350 mouse, in port #1 of the C128. <tag><tt/c128-pot.mou (c128_pot_mou)/</tag> Supports a potentiometer device, e.g. Koala Pad, connected to port #1 of the C128. </descrip><p> <sect1>RS232 device drivers<p> <descrip> <tag><tt/c128-swlink.ser (c128_swlink_ser)/</tag> Driver for the SwiftLink cartridge. Supports up to 38400 BPS, hardware flow control (RTS/CTS), and interrupt-driven receives. Note that, because of the peculiarities of the 6551 chip, together with the use of the NMI, transmits are not interrupt driven; and, the transceiver blocks if the receiver asserts flow control because of a full buffer. The driver uses the RS232 variables and buffers of the kernal (buffers at $C00 and $D00). </descrip><p> <sect>Limitations<p> <sect1>Realtime clock<p> The realtime clock functions use the CIA1 TOD clock. As that clock only stores the time but not the date, the date set by <tt/clock_settime()/ is simply stored inside the C library for retrieval in the same program via <tt/clock_gettime()/. <sect>Other hints<p> <sect1>Passing arguments to the program<p> Command-line arguments can be passed to <tt/main()/. Since this is not supported directly by BASIC, the following syntax was chosen: <tscreen><verb> RUN:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5 </verb></tscreen> <enum> <item>Arguments are separated by spaces. <item>Arguments may be quoted. <item>Leading and trailing spaces around an argument are ignored. Spaces within a quoted argument are allowed. <item>The first argument passed to <tt/main()/ is the program name. <item>A maximum number of 10 arguments (including the program name) are supported. </enum> <sect1>Program return code<p> The program return code (low byte) is passed back to BASIC by use of the <tt/ST/ variable. <sect1>Interrupts<p> The runtime for the C128 uses routines marked as <tt/.INTERRUPTOR/ for interrupt handlers. Such routines must be written as simple machine language subroutines and will be called automatically by the interrupt handler code when they are linked into a program. See the discussion of the <tt/.CONDES/ feature in the <url url="ca65.html" name="assembler manual">. <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> ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/c16.sgml������������������������������������������������������������������������������0000664�0000000�0000000�00000017516�13473601511�0014241�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>Commodore 16/116 specific information for cc65 <author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> <abstract> An overview over the C16 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 C16 runtime system as it comes with the cc65 C compiler. It describes the memory layout, C16/116 specific header files, available drivers, and any pitfalls specific to that platform. Please note that C16 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. Since the C16/C116 and the Commodore Plus/4 are almost identical (the former don't have the 6551 ACIA and only 16KB of memory), the <url url="plus4.html" name="Plus/4 documentation"> is also worth a look. The difference between both cc65 targets is that the Plus/4 runtime uses banking to support full 64K RAM, while the C16 does not use banking and supports up to 32K RAM. Because banking is not needed, most C16 programs will be somewhat smaller than the same program compiled for the Plus/4. However, programs C16 will always run on the Plus/4, while the reverse is not necessarily true. <sect>Binary format<p> The standard binary output format generated by the linker for the C16/116 target is a machine language program with a one line BASIC stub which, calls the machine language part via SYS. This means that a program can be loaded as BASIC program and started with RUN. 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 kernal and basic banked in. This gives a usable memory range of $1000 - $4000 (or $8000 if the machine is equipped with 32K RAM or more). Having the kernal and basic ROMs banked in means, that ROM entry points may be called directly from user code. Special locations: <descrip> <tag/Text screen/ The text screen is located at $C00 (as in the standard setup). <tag/Color RAM/ The color RAM is located at $800 (standard location). <tag/Stack/ The C runtime stack is located at $3FFF ($7FFF in case of a machine with 32K of memory or more) and growing downwards. <tag/Heap/ The C heap is located at the end of the program and grows towards the C runtime stack. </descrip><p> <sect>Platform specific header files<p> Programs containing C16 specific code may use the <tt/c16.h/ or <tt/cbm.h/ header files. Using the later may be an option when writing code for more than one CBM platform, since it includes <tt/c16.h/ and declares several functions common to all CBM platforms. Please note that most of the header file declarations from the <tt/c16.h/ header file are shared between the C16 and Plus/4 configurations. For this reason, most of it is located in a common header file named <tt/cbm264.h/. <sect1>C16/C116 specific functions<p> There are currently no special C16/C116 functions. <sect1>CBM specific functions<p> Some functions are available for all (or at least most) of the Commodore machines. See the <url url="funcref.html" name="function reference"> for declaration and usage. <itemize> <item>cbm_close <item>cbm_closedir <item>cbm_k_setlfs <item>cbm_k_setnam <item>cbm_k_load <item>cbm_k_save <item>cbm_k_open <item>cbm_k_close <item>cbm_k_readst <item>cbm_k_chkin <item>cbm_k_ckout <item>cbm_k_basin <item>cbm_k_bsout <item>cbm_k_clrch <item>cbm_k_tksa <item>cbm_k_second <item>cbm_load <item>cbm_open <item>cbm_opendir <item>cbm_read <item>cbm_readdir <item>cbm_save <item>cbm_write <item>get_tv </itemize> <sect1>CBM specific CPU functions<p> Some CPU related functions are available for some of the Commodore machines. See the <url url="funcref.html" name="function reference"> for declaration and usage. <itemize> <item>fast <item>slow <item>isfast </itemize> <sect1>Hardware access<p> The following pseudo variables declared in the <tt/c16.h/ header file do allow access to hardware located in the address space. Some variables are structures, accessing the struct fields will access the chip registers. <descrip> <tag><tt/TED/</tag> The <tt/TED/ structure allows access to the TED chip. See the <tt/_ted.h/ header file located in the include directory for the declaration of the structure. <tag><tt/COLOR_RAM/</tag> A character array that mirrors the color RAM of the C16 at $0800. </descrip><p> <sect>Loadable drivers<p> The names in the parentheses denote the symbols to be used for static linking of the drivers. <sect1>Graphics drivers<p> No graphics drivers are currently available for the C16/C116. <sect1>Extended memory drivers<p> <descrip> <tag><tt/c16-ram.emd (c16_ram_emd)/</tag> A driver for the hidden RAM below the BASIC and KERNAL ROMs. Supports 125 pages with 256 bytes each if the machine is equipped with 64K of memory (a Plus/4 or a memory extended C16/116). </descrip><p> <sect1>Joystick drivers<p> <descrip> <tag><tt/c16-stdjoy.joy (c16_stdjoy_joy)/</tag> Supports up to two joysticks connected to the standard joysticks port of the Commodore 16/116. </descrip><p> <sect1>Mouse drivers<p> No mouse drivers are currently available for the C16/C116. <sect1>RS232 device drivers<p> The Commodore 16 does not have a builtin ACIA and no RS232 extensions are known. For this reason, there are no RS232 drivers available. Please note that the standard Plus/4 driver will <em>not</em> run together with the C16 library, because the latter does not support interrupts needed by the driver. <sect>Limitations<p> <sect>Other hints<p> <sect1>Passing arguments to the program<p> Command line arguments can be passed to <tt/main()/. Since this is not supported by BASIC, the following syntax was chosen: <tscreen><verb> RUN:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5 </verb></tscreen> <enum> <item>Arguments are separated by spaces. <item>Arguments may be quoted. <item>Leading and trailing spaces around an argument are ignored. Spaces within a quoted argument are allowed. <item>The first argument passed to <tt/main/ is the program name. <item>A maximum number of 10 arguments (including the program name) are supported. </enum> <sect1>Program return code<p> The program return code (low byte) is passed back to BASIC by use of the <tt/ST/ variable. <sect1>Interrupts<p> The runtime for the C16 uses routines marked as <tt/.INTERRUPTOR/ for interrupt handlers. Such routines must be written as simple machine language subroutines and will be called automatically by the interrupt handler code when they are linked into a program. See the discussion of the <tt/.CONDES/ feature in the <url url="ca65.html" name="assembler manual">. <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> ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/c64.sgml������������������������������������������������������������������������������0000664�0000000�0000000�00000037704�13473601511�0014245�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>Commodore 64-specific information for cc65 <author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"><newline> <url url="mailto:greg.king5@verizon.net" name="Greg King"> <abstract> An overview over the C64 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 C64 runtime system as it comes with the cc65 C compiler. It describes the memory layout, C64-specific header files, available drivers, and any pitfalls specific to that platform. Please note that C64-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 C64 target is a machine language program with a one line BASIC stub, which calls the machine language part via SYS. This means that a program can be loaded as BASIC program and started with RUN. 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 the kernal ROM enabled (memory under the kernal may be used for graphics or as extended memory - see the sections about graphics and extended memory drivers). The BASIC ROM is disabled, which gives a usable memory range of $0800 - $CFFF. This means that kernal entry points may be called directly, but using the BASIC ROM is not possible without additional code. Special locations: <descrip> <tag/Text screen/ The text screen is located at $400 (as in the standard setup). <tag/Stack/ The C runtime stack is located at $CFFF and growing downwards. <tag/Heap/ The C heap is located at the end of the program and grows towards the C runtime stack. </descrip><p> <sect>Linker configurations<p> The ld65 linker comes with a default config file for the Commodore 64, which is used via <tt/-t c64/. The c64 package comes with additional secondary linker config files, which are used via <tt/-t c64 -C <configfile>/. <sect1>default config file (<tt/c64.cfg/)<p> The default configuration is tailored to C programs. It supplies the load address and a small BASIC stub that starts the compiled program using a SYS command. <sect1><tt/c64-asm.cfg/<p> This configuration is made for assembler programmers who don't need a special setup. The default start address is $801. It can be changed with the linker command line option <tt/--start-addr/. All standard segments with the exception of <tt/zeropage/ are written to the output file and a two byte load address is prepended. To use this config file, assemble with <tt/-t c64/ and link with <tt/-C c64-asm.cfg/. The former will make sure that correct character translation is in effect, while the latter supplies the actual config. When using <tt/cl65/, use both command line options. Sample command line for <tt/cl65/: <tscreen><verb> cl65 -o file.prg -t c64 -C c64-asm.cfg source.s </verb></tscreen> To generate code that loads to $C000: <tscreen><verb> cl65 -o file.prg --start-addr $C000 -t c64 -C c64-asm.cfg source.s </verb></tscreen> It is also possible to add a small BASIC header to the program, that uses SYS to jump to the program entry point (which is the start of the code segment). The advantage is that the program can be started using RUN. To generate a program with a BASIC SYS header, use <tscreen><verb> cl65 -o file.prg -u __EXEHDR__ -t c64 -C c64-asm.cfg source.s </verb></tscreen> 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 $D000 and $FF3F. In memory constrained situations the memory from $400 to $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> Programs containing C64-specific code may use the <tt/c64.h/ or <tt/cbm.h/ header files. Using the later may be an option when writing code for more than one CBM platform, since it includes <tt/c64.h/ and declares several functions common to all CBM platforms. <sect1>C64-specific functions<p> The functions listed below are special for the C64. See the <url url="funcref.html" name="function reference"> for declaration and usage. <itemize> <item>get_ostype </itemize> <sect1>C64-specific accelerator functions<p> The functions listed below are accelerator functions for the C64. See the <url url="funcref.html" name="function reference"> for declaration and usage. <itemize> <item>detect_c128 <item>detect_c64dtv <item>detect_c65 <item>detect_chameleon <item>detect_scpu <item>detect_turbomaster <item>get_c128_speed <item>get_c64dtv_speed <item>get_c65_speed <item>get_chameleon_speed <item>get_scpu_speed <item>get_turbomaster_speed <item>set_c128_speed <item>set_c64dtv_speed <item>set_c65_speed <item>set_chameleon_speed <item>set_scpu_speed <item>set_turbomaster_speed </itemize> <sect1>CBM-specific functions<p> Some functions are available for all (or at least most) of the Commodore machines. See the <url url="funcref.html" name="function reference"> for declaration and usage. <itemize> <item>cbm_close <item>cbm_closedir <item>cbm_k_setlfs <item>cbm_k_setnam <item>cbm_k_load <item>cbm_k_save <item>cbm_k_open <item>cbm_k_close <item>cbm_k_readst <item>cbm_k_chkin <item>cbm_k_ckout <item>cbm_k_basin <item>cbm_k_bsout <item>cbm_k_clrch <item>cbm_k_tksa <item>cbm_k_second <item>cbm_load <item>cbm_open <item>cbm_opendir <item>cbm_read <item>cbm_readdir <item>cbm_save <item>cbm_write <item>get_tv </itemize> <sect1>Hardware access<p> The following pseudo variables declared in the <tt/c64.h/ header file do allow access to hardware located in the address space. Some variables are structures, accessing the struct fields will access the chip registers. <descrip> <tag><tt/VIC/</tag> The <tt/VIC/ structure allows access to the VIC II (the graphics controller). See the <tt/_vic2.h/ header file located in the include directory for the declaration of the structure. <tag><tt/SID/</tag> The <tt/SID/ structure allows access to the SID (the sound interface device). See the <tt/_sid.h/ header file located in the include directory for the declaration of the structure. <tag><tt/CIA1, CIA2/</tag> Access to the two CIA (complex interface adapter) chips is available via the <tt/CIA1/ and <tt/CIA2/ variables. The structure behind these variables is explained in <tt/_6526.h/. <tag><tt/COLOR_RAM/</tag> A character array that mirrors the color RAM of the C64 at $D800. </descrip><p> <sect>Loadable drivers<p> The names in the parentheses denote the symbols to be used for static linking of the drivers. <label id="graphics-drivers"> <sect1>Graphics drivers<p> <em>Note:</em> All available graphics drivers for the TGI interface will use the space below the I/O area and Kernal ROM; so, you can have hires graphics in the standard setup without any memory loss or need for a changed configuration. You can use a mouse driver at the same time that you use a TGI driver. But, if you want to see the default mouse pointer on the graphics screen, then you explicitly must link a special object file into your program. It will put the arrow into the "high RAM" area where the bitmaps are put. Its name is "<tt/c64-tgimousedata.o/". Example: <tscreen><verb> cl65 -t c64 -o program-file main-code.c subroutines.s c64-tgimousedata.o </verb></tscreen> <descrip> <tag><tt/c64-hi.tgi (c64_hi_tgi)/</tag> This driver features a resolution of 320*200 with two colors and an adjustable palette (that means that the two colors can be chosen out of a 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> <descrip> <tag><tt/c64-65816.emd (c64_65816_emd)/</tag> Extended memory driver for 65816 (eg SCPU) based extra RAM. Written and contributed by Marco van den Heuvel. <tag><tt/c64-c256k.emd (c64_c256k_emd)/</tag> A driver for the C64 256K memory expansion. This driver offers 768 pages of 256 bytes each. Written and contributed by Marco van den Heuvel. <tag><tt/c64-dqbb.emd (c64_dqbb_emd)/</tag> A driver for the Double Quick Brown Box cartridge. This driver offers 64 pages of 256 bytes each. Written and contributed by Marco van den Heuvel. <tag><tt/c64-georam.emd (c64_georam_emd)/</tag> A driver for the Berkeley Softworks GeoRam cartridge. The driver will determine the available RAM from the connected cartridge. It supports 64KB up to 2048KB of RAM. <tag><tt/c64-isepic.emd (c64_isepic_emd)/</tag> A driver for the ISEPIC cartridge. This driver offers just 8 pages of 256 bytes each. Written and contributed by Marco van den Heuvel. <tag><tt/c64-ram.emd (c64_ram_emd)/</tag> A driver for the hidden RAM below the I/O area and kernal ROM. Supports 47 256 byte pages. Please note that this driver is incompatible with any of the 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. Will test the hardware for the available RAM. <tag><tt/c64-reu.emd (c64_reu_emd)/</tag> A driver for the CBM REUs. The driver will test the connected REU to find out how much RAM is present. <tag><tt/c64-vdc.emd (c64_vdc_emd)/</tag> A driver for the VDC memory of the C128. Written and contributed by Maciej Witkowiak. Can be used if the program is running in C64 mode of the C128. Autodetects the amount of memory available (16 or 64K) and offers 64 or 256 pages of 256 bytes each. <tag><tt/dtv-himem.emd (dtv_himem_emd)/</tag> A driver for the C64 D2TV (the second or PAL version). This driver offers indeed 7680 pages of 256 bytes each. </descrip><p> <sect1>Joystick drivers<p> The default drivers, <tt/joy_stddrv (joy_static_stddrv)/, point to <tt/c64-stdjoy.joy (c64_stdjoy_joy)/. <descrip> <tag><tt/c64-hitjoy.joy (c64_hitjoy_joy)/</tag> Driver for the Digital Excess & Hitmen adapter contributed by Groepaz. See <url url="http://www.digitalexcess.de/downloads/productions.php"> on instructions how to build one. Up to four joysticks are supported. <tag><tt/c64-ptvjoy.joy (c64_ptvjoy_joy)/</tag> Driver for the Protovision 4-player adapter contributed by Groepaz. See <url url="http://www.protovision-online.de/hardw/4_player.php?language=en" name="Protovision shop"> for prices and building instructions. Up to four joysticks are supported. <tag><tt/c64-stdjoy.joy (c64_stdjoy_joy)/</tag> Supports up to two standard joysticks connected to the joysticks port of the C64. <tag><tt/c64-numpad.joy (c64_numpad_joy)/</tag> Supports one joystick emulated by the numberpad of the C128 in C64 mode, the firebutton is labeled &dquot;5&dquot; and ENTER. </descrip><p> <sect1>Mouse drivers<p> You can use these drivers in text-mode or graphics-mode (TGI) programs. See the description of <ref id="graphics-drivers" name="the graphics drivers">. The default drivers, <tt/mouse_stddrv (mouse_static_stddrv)/, point to <tt/c64-1351.mou (c64_1351_mou)/. <descrip> <tag><tt/c64-1351.mou (c64_1351_mou)/</tag> Supports a standard mouse connected to port #0 of the C64. <tag><tt/c64-inkwell.mou (c64_inkwell_mou)/</tag> Supports the Inkwell Systems lightpens, connected to port #0 of the C64. It can read both the one-button 170-C and the two-button 184-C pens. (It can read other lightpens and light-guns that send their button signal to the joystick left-button pin or the paddle Y [up/down] pin.) <tag><tt/c64-joy.mou (c64_joy_mou)/</tag> Supports a mouse emulated by a standard joystick, e.g. 1350 mouse, in port #1 of the C64. <tag><tt/c64-pot.mou (c64_pot_mou)/</tag> Supports a potentiometer device, e.g. Koala Pad, connected to port #1 of the C64. </descrip><p> <sect1>RS232 device drivers<p> <descrip> <tag><tt/c64-swlink.ser (c64_swlink_ser)/</tag> Driver for the SwiftLink cartridge. Supports up to 38400 BPS, hardware flow control (RTS/CTS), and interrupt-driven receives. Note that, because of the peculiarities of the 6551 chip, together with the use of the NMI, transmits are not interrupt driven; and, the transceiver blocks if the receiver asserts flow control because of a full buffer. </descrip><p> <sect>Limitations<p> <sect1>Realtime clock<p> The realtime clock functions use the CIA1 TOD clock. As that clock only stores the time but not the date, the date set by <tt/clock_settime()/ is simply stored inside the C library for retrieval in the same program via <tt/clock_gettime()/. <sect>Other hints<p> <sect1>Escape code<p> For an Esc, press CTRL and the <tt/[/ key. <sect1>Passing arguments to the program<p> Command-line arguments can be passed to <tt/main()/. Since this is not supported directly by BASIC, the following syntax was chosen: <tscreen><verb> RUN:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5 </verb></tscreen> <enum> <item>Arguments are separated by spaces. <item>Arguments may be quoted. <item>Leading and trailing spaces around an argument are ignored. Spaces within a quoted argument are allowed. <item>The first argument passed to <tt/main()/ is the program name. <item>A maximum number of 10 arguments (including the program name) are supported. </enum> <sect1>Program return code<p> The program return code (low byte) is passed back to BASIC by use of the <tt/ST/ variable. <sect1>Interrupts<p> The runtime for the C64 uses routines marked as <tt/.INTERRUPTOR/ for interrupt handlers. Such routines must be written as simple machine language subroutines and will be called automatically by the interrupt handler code when they are linked into a program. See the discussion of the <tt/.CONDES/ feature in the <url url="ca65.html" name="assembler manual">. <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> ������������������������������������������������������������cc65-2.18/doc/ca65.sgml�����������������������������������������������������������������������������0000664�0000000�0000000�00000517000�13473601511�0014377�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <!-- -*- text-mode -*- --> <article> <title>ca65 Users Guide <author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline> <url url="mailto:greg.king5@verizon.net" name="Greg King"> <abstract> 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> <!-- Table of contents --> <toc> <!-- Begin the document --> <sect>Overview<p> ca65 is a replacement for the ra65 assembler that was part of the cc65 C compiler, originally developed by John R. Dunning. I had some problems with ra65 and the copyright does not permit some things which I wanted to be possible, so I decided to write a completely new assembler/linker/archiver suite for the cc65 compiler. ca65 is part of this suite. Some parts of the assembler (code generation and some routines for symbol table handling) are taken from an older crossassembler named a816 written by me a long time ago. <sect1>Design criteria<p> Here's a list of the design criteria, that I considered important for the development: <itemize> <item> The assembler must support macros. Macros are not essential, but they make some things easier, especially when you use the assembler in the backend of a compiler. <item> The assembler must support the newer 65C02 and 65816 CPUs. I have been thinking about a 65816 backend for the C compiler, and even my old a816 assembler had support for these CPUs, so this wasn't really a problem. <item> The assembler must produce relocatable code. This is necessary for the compiler support, and it is more convenient. <item> Conditional assembly must be supported. This is a must for bigger projects written in assembler (like Elite128). <item> The assembler must support segments, and it must support more than three segments (this is the count, most other assemblers support). Having more than one code segments helps developing code for systems with a divided ROM area (like the C64). <item> The linker must be able to resolve arbitrary expressions. It should be able to get things like <tscreen><verb> .import S1, S2 .export Special Special = 2*S1 + S2/7 </verb></tscreen> right. <item> True lexical nesting for symbols. This is very convenient for larger assembly projects. <item> "Cheap" local symbols without lexical nesting for those quick, late night hacks. <item> I liked the idea of "options" as Anre Fachats .o65 format has it, so I introduced the concept into the object file format use by the new cc65 binutils. <item> The assembler will be a one pass assembler. There was no real need for this decision, but I've written several multipass assemblers, and it started to get boring. A one pass assembler needs much more elaborated data structures, and because of that it's much more fun:-) <item> Non-GPLed code that may be used in any project without restrictions or fear of "GPL infecting" other code. </itemize> <p> <sect>Usage<p> <sect1>Command line option overview<p> The assembler accepts the following options: <tscreen><verb> --------------------------------------------------------------------------- Usage: ca65 [options] file Short options: -D name[=value] Define a symbol -I dir Set an include directory search path -U Mark unresolved symbols as import -V Print the assembler version -W n Set warning level n -d Debug mode -g Add debug info to object file -h Help (this text) -i Ignore case of symbols -l name Create a listing file if assembly was ok -mm model Set the memory model -o name Name the output file -s Enable smart mode -t sys Set the target system -v Increase verbosity Long options: --auto-import Mark unresolved symbols as import --bin-include-dir dir Set a search path for binary includes --cpu type Set cpu type --create-dep name Create a make dependency file --create-full-dep name Create a full make dependency file --debug Debug mode --debug-info Add debug info to object file --feature name Set an emulation feature --help Help (this text) --ignore-case Ignore case of symbols --include-dir dir Set an include directory search path --large-alignment Don't warn about large alignments --listing name Create a listing file if assembly was ok --list-bytes n Maximum number of bytes per listing line --memory-model model Set the memory model --pagelength n Set the page length for the listing --relax-checks Relax some checks (see docs) --smart Enable smart mode --target sys Set the target system --verbose Increase verbosity --version Print the assembler version --------------------------------------------------------------------------- </verb></tscreen> <sect1>Command line options in detail<p> Here is a description of all the command line options: <descrip> <label id="option--bin-include-dir"> <tag><tt>--bin-include-dir dir</tt></tag> Name a directory which is searched for binary include files. The option may be used more than once to specify more than one directory to search. The current directory is always searched first before considering any additional directories. See also the section about <ref id="search-paths" name="search paths">. <label id="option--cpu"> <tag><tt>--cpu type</tt></tag> Set the default for the CPU type. The option takes a parameter, which may be one of 6502, 6502X, 65SC02, 65C02, 65816, sweet16, HuC6280, 4510 <label id="option-create-dep"> <tag><tt>--create-dep name</tt></tag> Tells the assembler to generate a file containing the dependency list for the assembled module in makefile syntax. The output is written to a file with the given name. The output does not include files passed via debug information to the assembler. <label id="option-create-full-dep"> <tag><tt>--create-full-dep name</tt></tag> Tells the assembler to generate a file containing the dependency list for the assembled module in makefile syntax. The output is written to a file with the given name. The output does include files passed via debug information to the assembler. <tag><tt>-d, --debug</tt></tag> Enables debug mode, something that should not be needed for mere mortals:-) <label id="option--feature"> <tag><tt>--feature name</tt></tag> Enable an emulation feature. This is identical as using <tt/.FEATURE/ in the source with two exceptions: Feature names must be lower case, and each feature must be specified by using an extra <tt/--feature/ option, comma separated lists are not allowed. See the discussion of the <tt><ref id=".FEATURE" name=".FEATURE"></tt> command for a list of emulation features. <label id="option-g"> <tag><tt>-g, --debug-info</tt></tag> When this option (or the equivalent control command <tt/.DEBUGINFO/) is used, the assembler will add a section to the object file that contains all symbols (including local ones) together with the symbol values and source file positions. The linker will put these additional symbols into the VICE label file, so even local symbols can be seen in the VICE monitor. <label id="option-h"> <tag><tt>-h, --help</tt></tag> Print the short option summary shown above. <label id="option-i"> <tag><tt>-i, --ignore-case</tt></tag> This option makes the assembler case insensitive on identifiers and labels. This option will override the default, but may itself be overridden by the <tt><ref id=".CASE" name=".CASE"></tt> control command. <label id="option-l"> <tag><tt>-l name, --listing name</tt></tag> Generate an assembler listing with the given name. A listing file will never be generated in case of assembly errors. <label id="option--large-alignment"> <tag><tt>--large-alignment</tt></tag> Disable warnings about a large combined alignment. See the discussion of the <tt><ref id=".ALIGN" name=".ALIGN"></tt> directive for futher information. <label id="option--list-bytes"> <tag><tt>--list-bytes n</tt></tag> Set the maximum number of bytes printed in the listing for one line of input. See the <tt><ref id=".LISTBYTES" name=".LISTBYTES"></tt> directive for more information. The value zero can be used to encode an unlimited number of printed bytes. <label id="option-mm"> <tag><tt>-mm model, --memory-model model</tt></tag> Define the default memory model. Possible model specifiers are near, far and huge. <label id="option-o"> <tag><tt>-o name</tt></tag> The default output name is the name of the input file with the extension replaced by ".o". If you don't like that, you may give another name with the -o option. The output file will be placed in the same directory as the source file, or, if -o is given, the full path in this name is used. <label id="option--pagelength"> <tag><tt>--pagelength n</tt></tag> sets the length of a listing page in lines. See the <tt><ref id=".PAGELENGTH" name=".PAGELENGTH"></tt> directive for more information. <label id="option--relax-checks"> <tag><tt>--relax-checks</tt></tag> Relax some checks done by the assembler. This will allow code that is an error in most cases and flagged as such by the assembler, but can be valid in special situations. Examples are: <itemize> <item>Short branches between two different segments. <item>Byte sized address loads where the address is not a zeropage address. </itemize> <label id="option-s"> <tag><tt>-s, --smart-mode</tt></tag> In smart mode (enabled by -s or the <tt><ref id=".SMART" name=".SMART"></tt> pseudo instruction) the assembler will track usage of the <tt/REP/ and <tt/SEP/ instructions in 65816 mode and update the operand sizes accordingly. If the operand of such an instruction cannot be evaluated by the assembler (for example, because the operand is an imported symbol), a warning is issued. Beware: Since the assembler cannot trace the execution flow this may lead to false results in some cases. If in doubt, use the .ixx and .axx instructions to tell the assembler about the current settings. Smart mode is off by default. <label id="option-t"> <tag><tt>-t sys, --target sys</tt></tag> Set the target system. This will enable translation of character strings and character constants into the character set of the target platform. The default for the target system is "none", which means that no translation will take place. The assembler supports the same target systems as the compiler, see there for a list. Depending on the target, the default CPU type is also set. This can be overriden by using the <tt/<ref id="option--cpu" name="--cpu">/ option. <label id="option-v"> <tag><tt>-v, --verbose</tt></tag> Increase the assembler verbosity. Usually only needed for debugging purposes. You may use this option more than one time for even more verbose output. <label id="option-D"> <tag><tt>-D</tt></tag> This option allows you to define symbols on the command line. Without a value, the symbol is defined with the value zero. When giving a value, you may use the '$' prefix for hexadecimal symbols. Please note that for some operating systems, '$' has a special meaning, so you may have to quote the expression. <label id="option-I"> <tag><tt>-I dir, --include-dir dir</tt></tag> Name a directory which is searched for include files. The option may be used more than once to specify more than one directory to search. The current directory is always searched first before considering any additional directories. See also the section about <ref id="search-paths" name="search paths">. <label id="option-U"> <tag><tt>-U, --auto-import</tt></tag> Mark symbols that are not defined in the sources as imported symbols. This should be used with care since it delays error messages about typos and such until the linker is run. The compiler uses the equivalent of this switch (<tt><ref id=".AUTOIMPORT" name=".AUTOIMPORT"></tt>) to enable auto imported symbols for the runtime library. However, the compiler is supposed to generate code that runs through the assembler without problems, something which is not always true for assembler programmers. <label id="option-V"> <tag><tt>-V, --version</tt></tag> Print the version number of the assembler. If you send any suggestions or bugfixes, please include the version number. <label id="option-W"> <tag><tt>-Wn</tt></tag> Set the warning level for the assembler. Using -W2 the assembler will even warn about such things like unused imported symbols. The default warning level is 1, and it would probably be silly to set it to something lower. </descrip> <p> <sect>Search paths<label id="search-paths"><p> Normal include files are searched in the following places: <enum> <item>The current file's directory. <item>Any directory added with the <tt/<ref id="option-I" name="-I">/ option on the command line. <item>The value of the environment variable <tt/CA65_INC/ if it is defined. <item>A subdirectory named <tt/asminc/ of the directory defined in the environment variable <tt/CC65_HOME/, if it is defined. <item>An optionally compiled-in directory. </enum> Binary include files are searched in the following places: <enum> <item>The current file's directory. <item>Any directory added with the <tt/<ref id="option--bin-include-dir" name="--bin-include-dir">/ option on the command line. </enum> <sect>Input format<p> <sect1>Assembler syntax<p> The assembler accepts the standard 6502/65816 assembler syntax. One line may contain a label (which is identified by a colon), and, in addition to the label, an assembler mnemonic, a macro, or a control command (see section <ref id="control-commands" name="Control Commands"> for supported control commands). Alternatively, the line may contain a symbol definition using the '=' token. Everything after a semicolon is handled as a comment (that is, it is ignored). Here are some examples for valid input lines: <tscreen><verb> Label: ; A label and a comment lda #$20 ; A 6502 instruction plus comment L1: ldx #$20 ; Same with label L2: .byte "Hello world" ; Label plus control command mymac $20 ; Macro expansion MySym = 3*L1 ; Symbol definition MaSym = Label ; Another symbol </verb></tscreen> The assembler accepts <itemize> <item>all valid 6502 mnemonics when in 6502 mode (the default or after the <tt><ref id=".P02" name=".P02"></tt> command was given). <item>all valid 6502 mnemonics plus a set of illegal instructions when in <ref id="6502X-mode" name="6502X mode">. <item>all valid 65SC02 mnemonics when in 65SC02 mode (after the <tt><ref id=".PSC02" name=".PSC02"></tt> command was given). <item>all valid 65C02 mnemonics when in 65C02 mode (after the <tt><ref id=".PC02" name=".PC02"></tt> command was given). <item>all valid 65816 mnemonics when in 65816 mode (after the <tt><ref id=".P816" name=".P816"></tt> command was given). <item>all valid 4510 mnemonics when in 4510 mode (after the <tt><ref id=".P4510" name=".P4510"></tt> command was given). </itemize> <sect1>65816 mode<p> In 65816 mode, several aliases are accepted, in addition to the official mnemonics: <itemize> <item><tt>CPA</tt> is an alias for <tt>CMP</tt> <item><tt>DEA</tt> is an alias for <tt>DEC A</tt> <item><tt>INA</tt> is an alias for <tt>INC A</tt> <item><tt>SWA</tt> is an alias for <tt>XBA</tt> <item><tt>TAD</tt> is an alias for <tt>TCD</tt> <item><tt>TAS</tt> is an alias for <tt>TCS</tt> <item><tt>TDA</tt> is an alias for <tt>TDC</tt> <item><tt>TSA</tt> is an alias for <tt>TSC</tt> </itemize> <sect1>6502X mode<label id="6502X-mode"><p> 6502X mode is an extension to the normal 6502 mode. In this mode, several mnemonics for illegal instructions of the NMOS 6502 CPUs are accepted. Since these instructions are illegal, there are no official mnemonics for them. The unofficial ones are taken from <url url="http://www.oxyron.de/html/opcodes02.html">. Please note that only the ones marked as "stable" are supported. The following table uses information from the mentioned web page, for more information, see there. <itemize> <item><tt>ALR: A:=(A and #{imm})/2;</tt> <item><tt>ANC: A:=A and #{imm};</tt> Generates opcode $0B. <item><tt>ARR: A:=(A and #{imm})/2;</tt> <item><tt>AXS: X:=A and X-#{imm};</tt> <item><tt>DCP: {adr}:={adr}-1; A-{adr};</tt> <item><tt>ISC: {adr}:={adr}+1; A:=A-{adr};</tt> <item><tt>LAS: A,X,S:={adr} and S;</tt> <item><tt>LAX: A,X:={adr};</tt> <item><tt>RLA: {adr}:={adr}rol; A:=A and {adr};</tt> <item><tt>RRA: {adr}:={adr}ror; A:=A adc {adr};</tt> <item><tt>SAX: {adr}:=A and X;</tt> <item><tt>SLO: {adr}:={adr}*2; A:=A or {adr};</tt> <item><tt>SRE: {adr}:={adr}/2; A:=A xor {adr};</tt> </itemize> <sect1>4510 mode<p> The 4510 is a microcontroller that is the core of the Commodore C65 aka C64DX. It contains among other functions a slightly modified 65CE02/4502 CPU, to allow address mapping for 20 bits of address space (1 megabyte addressable area). As compared to the description of the CPU in the <url url="http://www.zimmers.net/anonftp/pub/cbm/c65/c65manualupdated.txt.gz" name="C65 System Specification"> <url url="https://raw.githubusercontent.com/MEGA65/c65-specifications/master/c65manualupdated.txt" name="(updated version)"> uses these changes: <itemize> <item><tt>LDA (d,SP),Y</tt> may also be written as <tt>LDA (d,S),Y</tt> (matching the 65816 notataion). <item>All branch instruction allow now 16 bit offsets. To use a 16 bit branch you have to prefix these with an "L" (e.g. "<tt>LBNE</tt>" instead of "<tt>BNE</tt>"). This might change at a later implementation of the assembler. </itemize> For more information about the Commodore C65/C64DX and the 4510 CPU, see <url url="http://www.zimmers.net/anonftp/pub/cbm/c65/"> and <url url="https://en.wikipedia.org/wiki/Commodore_65" name="Wikipedia">. <sect1>sweet16 mode<label id="sweet16-mode"><p> SWEET 16 is an interpreter for a pseudo 16 bit CPU written by Steve Wozniak for the Apple ][ machines. It is available in the Apple ][ ROM. ca65 can generate code for this pseudo CPU when switched into sweet16 mode. The following is special in sweet16 mode: <itemize> <item>The '@' character denotes indirect addressing and is no longer available for cheap local labels. If you need cheap local labels, you will have to switch to another lead character using the <tt/<ref id=".LOCALCHAR" name=".LOCALCHAR">/ command. <item>Registers are specified using <tt/R0/ .. <tt/R15/. In sweet16 mode, these identifiers are reserved words. </itemize> Please note that the assembler does neither supply the interpreter needed for SWEET 16 code, nor the zero page locations needed for the SWEET 16 registers, nor does it call the interpreter. All this must be done by your program. Apple ][ programmers do probably know how to use sweet16 mode. For more information about SWEET 16, see <url url="http://www.6502.org/source/interpreters/sweet16.htm">. <sect1>Number format<p> For literal values, the assembler accepts the widely used number formats: A preceding '$' or a trailing 'h' denotes a hex value, a preceding '%' denotes a binary value, and a bare number is interpreted as a decimal. There are currently no octal values and no floats. <sect1>Conditional assembly<p> Please note that when using the conditional directives (<tt/.IF/ and friends), the input must consist of valid assembler tokens, even in <tt/.IF/ branches that are not assembled. The reason for this behaviour is that the assembler must still be able to detect the ending tokens (like <tt/.ENDIF/), so conversion of the input stream into tokens still takes place. As a consequence conditional assembly directives may <bf/not/ be used to prevent normal text (used as a comment or similar) from being assembled. <p> <sect>Expressions<p> <sect1>Expression evaluation<p> All expressions are evaluated with (at least) 32 bit precision. An expression may contain constant values and any combination of internal and external symbols. Expressions that cannot be evaluated at assembly time are stored inside the object file for evaluation by the linker. Expressions referencing imported symbols must always be evaluated by the linker. <sect1>Size of an expression result<p> Sometimes, the assembler must know about the size of the value that is the result of an expression. This is usually the case, if a decision has to be made, to generate a zero page or an absolute memory references. In this case, the assembler has to make some assumptions about the result of an expression: <itemize> <item> If the result of an expression is constant, the actual value is checked to see if it's a byte sized expression or not. <item> If the expression is explicitly casted to a byte sized expression by one of the '>', '<' or '^' operators, it is a byte expression. <item> If this is not the case, and the expression contains a symbol, explicitly declared as zero page symbol (by one of the .importzp or .exportzp instructions), then the whole expression is assumed to be byte sized. <item> If the expression contains symbols that are not defined, and these symbols are local symbols, the enclosing scopes are searched for a symbol with the same name. If one exists and this symbol is defined, its attributes are used to determine the result size. <item> In all other cases the expression is assumed to be word sized. </itemize> Note: If the assembler is not able to evaluate the expression at assembly time, the linker will evaluate it and check for range errors as soon as the result is known. <sect1>Boolean expressions<p> In the context of a boolean expression, any non zero value is evaluated as true, any other value to false. The result of a boolean expression is 1 if it's true, and zero if it's false. There are boolean operators with extreme low precedence with version 2.x (where x > 0). The <tt/.AND/ and <tt/.OR/ operators are shortcut operators. That is, if the result of the expression is already known, after evaluating the left hand side, the right hand side is not evaluated. <sect1>Constant expressions<p> Sometimes an expression must evaluate to a constant without looking at any further input. One such example is the <tt/<ref id=".IF" name=".IF">/ command that decides if parts of the code are assembled or not. An expression used in the <tt/.IF/ command cannot reference a symbol defined later, because the decision about the <tt/.IF/ must be made at the point when it is read. If the expression used in such a context contains only constant numerical values, there is no problem. When unresolvable symbols are involved it may get harder for the assembler to determine if the expression is actually constant, and it is even possible to create expressions that aren't recognized as constant. Simplifying the expressions will often help. In cases where the result of the expression is not needed immediately, the assembler will delay evaluation until all input is read, at which point all symbols are known. So using arbitrary complex constant expressions is no problem in most cases. <sect1>Available operators<label id="operators"><p> <table> <tabular ca="clc"> <bf/Operator/| <bf/Description/| <bf/Precedence/@<hline> | Built-in string functions| 0@ ||~@ | Built-in pseudo-variables| 1@ | Built-in pseudo-functions| 1@ +| Unary positive| 1@ -| Unary negative| 1@ ˜<newline> .BITNOT| Unary bitwise not| 1@ <<newline> .LOBYTE| Unary low-byte operator| 1@ ><newline> .HIBYTE| Unary high-byte operator| 1@ ^<newline> .BANKBYTE| Unary bank-byte operator| 1@ ||~@ *| Multiplication| 2@ /| Division| 2@ .MOD| Modulo operator| 2@ &<newline> .BITAND| Bitwise and| 2@ ^<newline> .BITXOR| Binary bitwise xor| 2@ <<<newline> .SHL| Shift-left operator| 2@ >><newline> .SHR| Shift-right operator| 2@ ||~@ +| Binary addition| 3@ -| Binary subtraction| 3@ |<newline> .BITOR| Bitwise or| 3@ ||~@ = | Compare operator (equal)| 4@ <>| Compare operator (not equal)| 4@ <| Compare operator (less)| 4@ >| Compare operator (greater)| 4@ <=| Compare operator (less or equal)| 4@ >=| Compare operator (greater or equal)| 4@ ||~@ &&<newline> .AND| Boolean and| 5@ .XOR| Boolean xor| 5@ ||~@ ||<newline> .OR| Boolean or| 6@ ||~@ !<newline> .NOT| Boolean not| 7@<hline> </tabular> <caption>Available operators, sorted by precedence </table> To force a specific order of evaluation, parentheses may be used, as usual. <sect>Symbols and labels<p> A symbol or label is an identifier that starts with a letter and is followed by letters and digits. Depending on some features enabled (see <tt><ref id="at_in_identifiers" name="at_in_identifiers"></tt>, <tt><ref id="dollar_in_identifiers" name="dollar_in_identifiers"></tt> and <tt><ref id="leading_dot_in_identifiers" name="leading_dot_in_identifiers"></tt>) other characters may be present. Use of identifiers consisting of a single character will not work in all cases, because some of these identifiers are reserved keywords (for example "A" is not a valid identifier for a label, because it is the keyword for the accumulator). The assembler allows you to use symbols instead of naked values to make the source more readable. There are a lot of different ways to define and use symbols and labels, giving a lot of flexibility. <sect1>Numeric constants<p> Numeric constants are defined using the equal sign or the label assignment operator. After doing <tscreen><verb> two = 2 </verb></tscreen> may use the symbol "two" in every place where a number is expected, and it is evaluated to the value 2 in this context. The label assignment operator is almost identical, but causes the symbol to be marked as a label, so it may be handled differently in a debugger: <tscreen><verb> io := $d000 </verb></tscreen> The right side can of course be an expression: <tscreen><verb> four = two * two </verb></tscreen> <label id="variables"> <sect1>Numeric variables<p> Within macros and other control structures (<tt><ref id=".REPEAT" name=".REPEAT"></tt>, ...) it is sometimes useful to have some sort of variable. This can be achieved by the <tt>.SET</tt> operator. It creates a symbol that may get assigned a different value later: <tscreen><verb> four .set 4 lda #four ; Loads 4 into A four .set 3 lda #four ; Loads 3 into A </verb></tscreen> Since the value of the symbol can change later, it must be possible to evaluate it when used (no delayed evaluation as with normal symbols). So the expression used as the value must be constant. Following is an example for a macro that generates a different label each time it is used. It uses the <tt><ref id=".SPRINTF" name=".SPRINTF"></tt> function and a numeric variable named <tt>lcount</tt>. <tscreen><verb> .lcount .set 0 ; Initialize the counter .macro genlab .ident (.sprintf ("L%04X", lcount)): lcount .set lcount + 1 .endmacro </verb></tscreen> <sect1>Standard labels<p> A label is defined by writing the name of the label at the start of the line (before any instruction mnemonic, macro or pseudo directive), followed by a colon. This will declare a symbol with the given name and the value of the current program counter. <sect1>Local labels and symbols<p> Using the <tt><ref id=".PROC" name=".PROC"></tt> directive, it is possible to create regions of code where the names of labels and symbols are local to this region. They are not known outside of this region and cannot be accessed from there. Such regions may be nested like PROCEDUREs in Pascal. See the description of the <tt><ref id=".PROC" name=".PROC"></tt> directive for more information. <sect1>Cheap local labels<p> Cheap local labels are defined like standard labels, but the name of the label must begin with a special symbol (usually '@', but this can be changed by the <tt><ref id=".LOCALCHAR" name=".LOCALCHAR"></tt> directive). Cheap local labels are visible only between two non cheap labels. As soon as a standard symbol is encountered (this may also be a local symbol if inside a region defined with the <tt><ref id=".PROC" name=".PROC"></tt> directive), the cheap local symbol goes out of scope. You may use cheap local labels as an easy way to reuse common label names like "Loop". Here is an example: <tscreen><verb> Clear: lda #$00 ; Global label ldy #$20 @Loop: sta Mem,y ; Local label dey bne @Loop ; Ok rts Sub: ... ; New global label bne @Loop ; ERROR: Unknown identifier! </verb></tscreen> <sect1>Unnamed labels<p> If you really want to write messy code, there are also unnamed labels. These labels do not have a name (you guessed that already, didn't you?). A colon is used to mark the absence of the name. Unnamed labels may be accessed by using the colon plus several minus or plus characters as a label designator. Using the '-' characters will create a back reference (use the n'th label backwards), using '+' will create a forward reference (use the n'th label in forward direction). An example will help to understand this: <tscreen><verb> : lda (ptr1),y ; #1 cmp (ptr2),y bne :+ ; -> #2 tax beq :+++ ; -> #4 iny bne :- ; -> #1 inc ptr1+1 inc ptr2+1 bne :- ; -> #1 : bcs :+ ; #2 -> #3 ldx #$FF rts : ldx #$01 ; #3 : rts ; #4 </verb></tscreen> As you can see from the example, unnamed labels will make even short sections of code hard to understand, because you have to count labels to find branch targets (this is the reason why I for my part do prefer the "cheap" local labels). Nevertheless, unnamed labels are convenient in some situations, so it's your decision. <em/Note:/ <ref id="scopes" name="Scopes"> organize named symbols, not unnamed ones, so scopes don't have an effect on unnamed labels. <sect1>Using macros to define labels and constants<p> While there are drawbacks with this approach, it may be handy in a few rare situations. Using <tt><ref id=".DEFINE" name=".DEFINE"></tt>, it is possible to define symbols or constants that may be used elsewhere. One of the advantages is that you can use it to define string constants (this is not possible with the other symbol types). Please note: <tt/.DEFINE/ style macros do token replacements on a low level, so the names do not adhere to scoping, diagnostics may be misleading, there are no symbols to look up in the map file, and there is no debug info. Especially the first problem in the list can lead to very nasty programming errors. Because of these problems, the general advice is, <bf/NOT/ do use <tt/.DEFINE/ if you don't have to. Example: <tscreen><verb> .DEFINE two 2 .DEFINE version "SOS V2.3" four = two * two ; Ok .byte version ; Ok .PROC ; Start local scope two = 3 ; Will give "2 = 3" - invalid! .ENDPROC </verb></tscreen> <sect1>Symbols and <tt>.DEBUGINFO</tt><p> If <tt><ref id=".DEBUGINFO" name=".DEBUGINFO"></tt> is enabled (or <ref id="option-g" name="-g"> is given on the command line), global, local and cheap local labels are written to the object file and will be available in the symbol file via the linker. Unnamed labels are not written to the object file, because they don't have a name which would allow to access them. <sect>Scopes<label id="scopes"><p> ca65 implements several sorts of scopes for symbols. <sect1>Global scope<p> All (non cheap local) symbols that are declared outside of any nested scopes are in global scope. <sect1>Cheap locals<p> A special scope is the scope for cheap local symbols. It lasts from one non local symbol to the next one, without any provisions made by the programmer. All other scopes differ in usage but use the same concept internally. <sect1>Generic nested scopes<p> A nested scoped for generic use is started with <tt/<ref id=".SCOPE" name=".SCOPE">/ and closed with <tt/<ref id=".ENDSCOPE" name=".ENDSCOPE">/. The scope can have a name, in which case it is accessible from the outside by using <ref id="scopesyntax" name="explicit scopes">. If the scope does not have a name, all symbols created within the scope are local to the scope, and aren't accessible from the outside. A nested scope can access symbols from the local or from enclosing scopes by name without using explicit scope names. In some cases there may be ambiguities, for example if there is a reference to a local symbol that is not yet defined, but a symbol with the same name exists in outer scopes: <tscreen><verb> .scope outer foo = 2 .scope inner lda #foo foo = 3 .endscope .endscope </verb></tscreen> In the example above, the <tt/lda/ instruction will load the value 3 into the accumulator, because <tt/foo/ is redefined in the scope. However: <tscreen><verb> .scope outer foo = $1234 .scope inner lda foo,x foo = $12 .endscope .endscope </verb></tscreen> Here, <tt/lda/ will still load from <tt/$12,x/, but since it is unknown to the assembler that <tt/foo/ is a zeropage symbol when translating the instruction, absolute mode is used instead. In fact, the assembler will not use absolute mode by default, but it will search through the enclosing scopes for a symbol with the given name. If one is found, the address size of this symbol is used. This may lead to errors: <tscreen><verb> .scope outer foo = $12 .scope inner lda foo,x foo = $1234 .endscope .endscope </verb></tscreen> In this case, when the assembler sees the symbol <tt/foo/ in the <tt/lda/ instruction, it will search for an already defined symbol <tt/foo/. It will find <tt/foo/ in scope <tt/outer/, and a close look reveals that it is a zeropage symbol. So the assembler will use zeropage addressing mode. If <tt/foo/ is redefined later in scope <tt/inner/, the assembler tries to change the address in the <tt/lda/ instruction already translated, but since the new value needs absolute addressing mode, this fails, and an error message "Range error" is output. Of course the most simple solution for the problem is to move the definition of <tt/foo/ in scope <tt/inner/ upwards, so it precedes its use. There may be rare cases when this cannot be done. In these cases, you can use one of the address size override operators: <tscreen><verb> .scope outer foo = $12 .scope inner lda a:foo,x foo = $1234 .endscope .endscope </verb></tscreen> This will cause the <tt/lda/ instruction to be translated using absolute addressing mode, which means changing the symbol reference later does not cause any errors. <sect1>Nested procedures<p> A nested procedure is created by use of <tt/<ref id=".PROC" name=".PROC">/. It differs from a <tt/<ref id=".SCOPE" name=".SCOPE">/ in that it must have a name, and a it will introduce a symbol with this name in the enclosing scope. So <tscreen><verb> .proc foo ... .endproc </verb></tscreen> is actually the same as <tscreen><verb> foo: .scope foo ... .endscope </verb></tscreen> This is the reason why a procedure must have a name. If you want a scope without a name, use <tt/<ref id=".SCOPE" name=".SCOPE">/. <em/Note:/ As you can see from the example above, scopes and symbols live in different namespaces. There can be a symbol named <tt/foo/ and a scope named <tt/foo/ without any conflicts (but see the section titled <ref id="scopesearch" name=""Scope search order"">). <sect1>Structs, unions and enums<p> Structs, unions and enums are explained in a <ref id="structs" name="separate section">, I do only cover them here, because if they are declared with a name, they open a nested scope, similar to <tt/<ref id=".SCOPE" name=".SCOPE">/. However, when no name is specified, the behaviour is different: In this case, no new scope will be opened, symbols declared within a struct, union, or enum declaration will then be added to the enclosing scope instead. <sect1>Explicit scope specification<label id="scopesyntax"><p> Accessing symbols from other scopes is possible by using an explicit scope specification, provided that the scope where the symbol lives in has a name. The namespace token (<tt/::/) is used to access other scopes: <tscreen><verb> .scope foo bar: .word 0 .endscope ... lda foo::bar ; Access foo in scope bar </verb></tscreen> The only way to deny access to a scope from the outside is to declare a scope without a name (using the <tt/<ref id=".SCOPE" name=".SCOPE">/ command). A special syntax is used to specify the global scope: If a symbol or scope is preceded by the namespace token, the global scope is searched: <tscreen><verb> bar = 3 .scope foo bar = 2 lda #::bar ; Access the global bar (which is 3) .endscope </verb></tscreen> <sect1>Scope search order<label id="scopesearch"><p> The assembler searches for a scope in a similar way as for a symbol. First, it looks in the current scope, and then it walks up the enclosing scopes until the scope is found. However, one important thing to note when using explicit scope syntax is, that a symbol may be accessed before it is defined, but a scope may <bf/not/ be used without a preceding definition. This means that in the following example: <tscreen><verb> .scope foo bar = 3 .endscope .scope outer lda #foo::bar ; Will load 3, not 2! .scope foo bar = 2 .endscope .endscope </verb></tscreen> the reference to the scope <tt/foo/ will use the global scope, and not the local one, because the local one is not visible at the point where it is referenced. Things get more complex if a complete chain of scopes is specified: <tscreen><verb> .scope foo .scope outer .scope inner bar = 1 .endscope .endscope .scope another .scope nested lda #outer::inner::bar ; 1 .endscope .endscope .endscope .scope outer .scope inner bar = 2 .endscope .endscope </verb></tscreen> When <tt/outer::inner::bar/ is referenced in the <tt/lda/ instruction, the assembler will first search in the local scope for a scope named <tt/outer/. Since none is found, the enclosing scope (<tt/another/) is checked. There is still no scope named <tt/outer/, so scope <tt/foo/ is checked, and finally scope <tt/outer/ is found. Within this scope, <tt/inner/ is searched, and in this scope, the assembler looks for a symbol named <tt/bar/. Please note that once the anchor scope is found, all following scopes (<tt/inner/ in this case) are expected to be found exactly in this scope. The assembler will search the scope tree only for the first scope (if it is not anchored in the root scope). Starting from there on, there is no flexibility, so if the scope named <tt/outer/ found by the assembler does not contain a scope named <tt/inner/, this would be an error, even if such a pair does exist (one level up in global scope). Ambiguities that may be introduced by this search algorithm may be removed by anchoring the scope specification in the global scope. In the example above, if you want to access the "other" symbol <tt/bar/, you would have to write: <tscreen><verb> .scope foo .scope outer .scope inner bar = 1 .endscope .endscope .scope another .scope nested lda #::outer::inner::bar ; 2 .endscope .endscope .endscope .scope outer .scope inner bar = 2 .endscope .endscope </verb></tscreen> <sect>Address sizes and memory models<label id="address-sizes"><p> <sect1>Address sizes<p> ca65 assigns each segment and each symbol an address size. This is true, even if the symbol is not used as an address. You may also think of a value range of the symbol instead of an address size. Possible address sizes are: <itemize> <item>Zeropage or direct (8 bits) <item>Absolute (16 bits) <item>Far (24 bits) <item>Long (32 bits) </itemize> Since the assembler uses default address sizes for the segments and symbols, it is usually not necessary to override the default behaviour. In cases, where it is necessary, the following keywords may be used to specify address sizes: <itemize> <item>DIRECT, ZEROPAGE or ZP for zeropage addressing (8 bits). <item>ABSOLUTE, ABS or NEAR for absolute addressing (16 bits). <item>FAR for far addressing (24 bits). <item>LONG or DWORD for long addressing (32 bits). </itemize> <sect1>Address sizes of segments<p> The assembler assigns an address size to each segment. Since the representation of a label within this segment is "segment start + offset", labels will inherit the address size of the segment they are declared in. The address size of a segment may be changed, by using an optional address size modifier. See the <tt/<ref id=".SEGMENT" name="segment directive">/ for an explanation on how this is done. <sect1>Address sizes of symbols<p> The address size of a symbol can be specified with a prefix: <itemize> <item>z: zeropage addressing (8 bits). <item>a: absolute addressing (16 bits). <item>f: far addressing (24 bits). </itemize> The zeropage addressing override can be used to ensure the use of optimal zeropage instructions, or correct cases where the size isn't yet known due to the single-pass assembly model. The larger addressing overrides can be used to promote a smaller address to absolute or far addressing, instead of being automatically fit into a smaller addressing type. <sect1>Memory models<p> The default address size of a segment depends on the memory model used. Since labels inherit the address size from the segment they are declared in, changing the memory model is an easy way to change the address size of many symbols at once. <sect>Pseudo variables<label id="pseudo-variables"><p> Pseudo variables are readable in all cases, and in some special cases also writable. <sect1><tt>*</tt><p> Reading this pseudo variable will return the program counter at the start of the current input line. Assignment to this variable is possible when <tt/<ref id=".FEATURE" name=".FEATURE pc_assignment">/ is used. Note: You should not use 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 tells which CPU is currently enabled. It can also tell which instruction set the CPU is able to translate. The value read from the pseudo variable should be further examined by using one of the constants defined by the "cpu" macro package (see <tt/<ref id=".MACPACK" name=".MACPACK">/). It may be used to replace the .IFPxx pseudo instructions or to construct even more complex expressions. Example: <tscreen><verb> .macpack cpu .if (.cpu .bitand CPU_ISET_65816) phx phy .else txa pha tya pha .endif </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 the actual number of parameters that were given in the macro invocation. Example: <tscreen><verb> .macro foo arg1, arg2, arg3 .if .paramcount <> 3 .error "Too few parameters for macro foo" .endif ... .endmacro </verb></tscreen> See section <ref id="macros" name="Macros">. <sect1><tt>.TIME</tt><label id=".TIME"><p> Reading this pseudo variable will give a constant integer value that represents the current time in POSIX standard (as seconds since the Epoch). It may be used to encode the time of translation somewhere in the created code. Example: <tscreen><verb> .dword .time ; Place time here </verb></tscreen> <sect1><tt>.VERSION</tt><label id=".VERSION"><p> Reading this pseudo variable will give the assembler version according to the following formula: VER_MAJOR*$100 + VER_MINOR*$10 It may be used to encode the assembler version or check the assembler for special features not available with older versions. Example: Version 2.14 of the assembler will return $2E0 as numerical constant when reading the pseudo variable <tt/.VERSION/. <sect>Pseudo functions<label id="pseudo-functions"><p> 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 argument is an expression with exactly one segment reference - usually a label. The function result is the value of the <tt/bank/ attribute assigned to the run memory area of the segment. Please see the linker documentation for more information about memory areas and their attributes. The value of <tt/.BANK/ can be used to switch memory so that a memory bank containing specific data is available. The <tt/bank/ attribute is a 32 bit integer and so is the result of the <tt/.BANK/ function. You will have to use <tt><ref id=".LOBYTE" name=".LOBYTE"></tt> or similar functions to address just part of it. Please note that <tt/.BANK/ will always get evaluated in the link stage, so an expression containing <tt/.BANK/ can never be used where a constant known result is expected (for example with <tt/.RES/). Example: <tscreen><verb> .segment "BANK1" .proc banked_func_1 ... .endproc .segment "BANK2" .proc banked_func_2 ... .endproc .proc bank_table .addr banked_func_1 .byte <.BANK (banked_func_1) .addr banked_func_2 .byte <.BANK (banked_func_2) .endproc </verb></tscreen> <sect1><tt>.BANKBYTE</tt><label id=".BANKBYTE"><p> The function returns the bank byte (that is, bits 16-23) of its argument. It works identical to the '^' operator. See: <tt><ref id=".HIBYTE" name=".HIBYTE"></tt>, <tt><ref id=".LOBYTE" name=".LOBYTE"></tt> <sect1><tt>.BLANK</tt><label id=".BLANK"><p> Builtin function. The function evaluates its argument in braces and yields "false" if the argument is non blank (there is an argument), and "true" if there is no argument. The token list that makes up the function argument may optionally be enclosed in curly braces. This allows the inclusion of tokens that would otherwise terminate the list (the closing right parenthesis). The curly braces are not considered part of the list, a list just consisting of curly braces is considered to be empty. As an example, the <tt/.IFBLANK/ statement may be replaced by <tscreen><verb> .if .blank({arg}) </verb></tscreen> <sect1><tt>.CONCAT</tt><label id=".CONCAT"><p> Builtin string function. The function allows to concatenate a list of string constants separated by commas. The result is a string constant that is the concatenation of all arguments. This function is most useful in macros and when used together with the <tt/.STRING/ builtin function. The function may be used in any case where a string constant is expected. Example: <tscreen><verb> .include .concat ("myheader", ".", "inc") </verb></tscreen> This is the same as the command <tscreen><verb> .include "myheader.inc" </verb></tscreen> <sect1><tt>.CONST</tt><label id=".CONST"><p> Builtin function. The function evaluates its argument in braces and yields "true" if the argument is a constant expression (that is, an expression that yields a constant value at assembly time) and "false" otherwise. As an example, the .IFCONST statement may be replaced by <tscreen><verb> .if .const(a + 3) </verb></tscreen> <sect1><tt>.HIBYTE</tt><label id=".HIBYTE"><p> The function returns the high byte (that is, bits 8-15) of its argument. It works identical to the '>' operator. See: <tt><ref id=".LOBYTE" name=".LOBYTE"></tt>, <tt><ref id=".BANKBYTE" name=".BANKBYTE"></tt> <sect1><tt>.HIWORD</tt><label id=".HIWORD"><p> The function returns the high word (that is, bits 16-31) of its argument. See: <tt><ref id=".LOWORD" name=".LOWORD"></tt> <sect1><tt>.IDENT</tt><label id=".IDENT"><p> The function expects a string as its argument, and converts this argument into an identifier. If the string starts with the current <tt/<ref id=".LOCALCHAR" name=".LOCALCHAR">/, it will be converted into a cheap local identifier, otherwise it will be converted into a normal identifier. Example: <tscreen><verb> .macro makelabel arg1, arg2 .ident (.concat (arg1, arg2)): .endmacro makelabel "foo", "bar" .word foobar ; Valid label </verb></tscreen> <sect1><tt>.LEFT</tt><label id=".LEFT"><p> Builtin function. Extracts the left part of a given token list. Syntax: <tscreen><verb> .LEFT (<int expr>, <token list>) </verb></tscreen> The first integer expression gives the number of tokens to extract from the token list. The second argument is the token list itself. The token list may optionally be enclosed into curly braces. This allows the inclusion of tokens that would otherwise terminate the list (the closing right paren in the given case). Example: To check in a macro if the given argument has a '#' as first token (immediate addressing mode), use something like this: <tscreen><verb> .macro ldax arg ... .if (.match (.left (1, {arg}), #)) ; ldax called with immediate operand ... .endif ... .endmacro </verb></tscreen> See also the <tt><ref id=".MID" name=".MID"></tt> and <tt><ref id=".RIGHT" name=".RIGHT"></tt> builtin functions. <sect1><tt>.LOBYTE</tt><label id=".LOBYTE"><p> The function returns the low byte (that is, bits 0-7) of its argument. It works identical to the '<' operator. See: <tt><ref id=".HIBYTE" name=".HIBYTE"></tt>, <tt><ref id=".BANKBYTE" name=".BANKBYTE"></tt> <sect1><tt>.LOWORD</tt><label id=".LOWORD"><p> The function returns the low word (that is, bits 0-15) of its argument. See: <tt><ref id=".HIWORD" name=".HIWORD"></tt> <sect1><tt>.MATCH</tt><label id=".MATCH"><p> Builtin function. Matches two token lists against each other. This is most useful within macros, since macros are not stored as strings, but as lists of tokens. The syntax is <tscreen><verb> .MATCH(<token list #1>, <token list #2>) </verb></tscreen> Both token list may contain arbitrary tokens with the exception of the terminator token (comma resp. right parenthesis) and <itemize> <item>end-of-line <item>end-of-file </itemize> The token lists may optionally be enclosed into curly braces. This allows the inclusion of tokens that would otherwise terminate the list (the closing right paren in the given case). Often a macro parameter is used for any of the token lists. Please note that the function does only compare tokens, not token attributes. So any number is equal to any other number, regardless of the actual value. The same is true for strings. If you need to compare tokens <em/and/ token attributes, use the <tt><ref id=".XMATCH" name=".XMATCH"></tt> function. Example: Assume the macro <tt/ASR/, that will shift right the accumulator by one, while honoring the sign bit. The builtin processor instructions will allow an optional "A" for accu addressing for instructions like <tt/ROL/ and <tt/ROR/. We will use the <tt><ref id=".MATCH" name=".MATCH"></tt> function to check for this and print and error for invalid calls. <tscreen><verb> .macro asr arg .if (.not .blank(arg)) .and (.not .match ({arg}, a)) .error "Syntax error" .endif cmp #$80 ; Bit 7 into carry lsr a ; Shift carry into bit 7 .endmacro </verb></tscreen> The macro will only accept no arguments, or one argument that must be the reserved keyword "A". See: <tt><ref id=".XMATCH" name=".XMATCH"></tt> <sect1><tt>.MAX</tt><label id=".MAX"><p> Builtin function. The result is the larger of two values. The syntax is <tscreen><verb> .MAX (<value #1>, <value #2>) </verb></tscreen> Example: <tscreen><verb> ; Reserve space for the larger of two data blocks savearea: .res .max (.sizeof (foo), .sizeof (bar)) </verb></tscreen> See: <tt><ref id=".MIN" name=".MIN"></tt> <sect1><tt>.MID</tt><label id=".MID"><p> Builtin function. Takes a starting index, a count and a token list as arguments. Will return part of the token list. Syntax: <tscreen><verb> .MID (<int expr>, <int expr>, <token list>) </verb></tscreen> The first integer expression gives the starting token in the list (the first token has index 0). The second integer expression gives the number of tokens to extract from the token list. The third argument is the token list itself. The token list may optionally be enclosed into curly braces. This allows the inclusion of tokens that would otherwise terminate the list (the closing right paren in the given case). Example: To check in a macro if the given argument has a '<tt/#/' as first token (immediate addressing mode), use something like this: <tscreen><verb> .macro ldax arg ... .if (.match (.mid (0, 1, {arg}), #)) ; ldax called with immediate operand ... .endif ... .endmacro </verb></tscreen> See also the <tt><ref id=".LEFT" name=".LEFT"></tt> and <tt><ref id=".RIGHT" name=".RIGHT"></tt> builtin functions. <sect1><tt>.MIN</tt><label id=".MIN"><p> Builtin function. The result is the smaller of two values. The syntax is <tscreen><verb> .MIN (<value #1>, <value #2>) </verb></tscreen> Example: <tscreen><verb> ; Reserve space for some data, but 256 bytes maximum savearea: .res .min (.sizeof (foo), 256) </verb></tscreen> See: <tt><ref id=".MAX" name=".MAX"></tt> <sect1><tt>.REF, .REFERENCED</tt><label id=".REFERENCED"><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 a symbol that has already been referenced somewhere in the source file up to the current position. Otherwise the function yields false. As an example, the <tt><ref id=".IFREF" name=".IFREF"></tt> statement may be replaced by <tscreen><verb> .if .referenced(a) </verb></tscreen> See: <tt><ref id=".DEFINED" name=".DEFINED"></tt> <sect1><tt>.RIGHT</tt><label id=".RIGHT"><p> Builtin function. Extracts the right part of a given token list. Syntax: <tscreen><verb> .RIGHT (<int expr>, <token list>) </verb></tscreen> The first integer expression gives the number of tokens to extract from the token list. The second argument is the token list itself. The token list may optionally be enclosed into curly braces. This allows the inclusion of tokens that would otherwise terminate the list (the closing right paren in the given case). See also the <tt><ref id=".LEFT" name=".LEFT"></tt> and <tt><ref id=".MID" name=".MID"></tt> builtin functions. <sect1><tt>.SIZEOF</tt><label id=".SIZEOF"><p> <tt/.SIZEOF/ is a pseudo function that returns the size of its argument. The argument can be a struct/union, a struct member, a procedure, or a label. In case of a procedure or label, its size is defined by the amount of data placed in the segment where the label is relative to. If a line of code switches segments (for example in a macro) data placed in other segments does not count for the size. Please note that a symbol or scope must exist, before it is used together with <tt/.SIZEOF/ (this may get relaxed later, but will always be true for scopes). A scope has preference over a symbol with the same name, so if the last part of a name represents both, a scope and a symbol, the scope is chosen over the symbol. After the following code: <tscreen><verb> .struct Point ; Struct size = 4 xcoord .word ycoord .word .endstruct P: .tag Point ; Declare a point @P: .tag Point ; Declare another point .code .proc Code nop .proc Inner nop .endproc nop .endproc .proc Data .data ; Segment switch!!! .res 4 .endproc </verb></tscreen> <descrip> <tag><tt/.sizeof(Point)/</tag> will have the value 4, because this is the size of struct <tt/Point/. <tag><tt/.sizeof(Point::xcoord)/</tag> will have the value 2, because this is the size of the member <tt/xcoord/ in struct <tt/Point/. <tag><tt/.sizeof(P)/</tag> will have the value 4, this is the size of the data declared on the same source line as the label <tt/P/, which is in the same segment that <tt/P/ is relative to. <tag><tt/.sizeof(@P)/</tag> will have the value 4, see above. The example demonstrates that <tt/.SIZEOF/ does also work for cheap local symbols. <tag><tt/.sizeof(Code)/</tag> will have the value 3, since this is amount of data emitted into the code segment, the segment that was active when <tt/Code/ was entered. Note that this value includes the amount of data emitted in child scopes (in this case <tt/Code::Inner/). <tag><tt/.sizeof(Code::Inner)/</tag> will have the value 1 as expected. <tag><tt/.sizeof(Data)/</tag> will have the value 0. Data is emitted within the scope <tt/Data/, but since the segment is switched after entry, this data is emitted into another segment. </descrip> <sect1><tt>.STRAT</tt><label id=".STRAT"><p> Builtin function. The function accepts a string and an index as arguments and returns the value of the character at the given position as an integer value. The index is zero based. Example: <tscreen><verb> .macro M Arg ; Check if the argument string starts with '#' .if (.strat (Arg, 0) = '#') ... .endif .endmacro </verb></tscreen> <sect1><tt>.SPRINTF</tt><label id=".SPRINTF"><p> Builtin function. It expects a format string as first argument. The number and type of the following arguments depend on the format string. The format string is similar to the one of the C <tt/printf/ function. Missing things are: Length modifiers, variable width. The result of the function is a string. Example: <tscreen><verb> num = 3 ; Generate an identifier: .ident (.sprintf ("%s%03d", "label", num)): </verb></tscreen> <sect1><tt>.STRING</tt><label id=".STRING"><p> Builtin function. The function accepts an argument in braces and converts this argument into a string constant. The argument may be an identifier, or a constant numeric value. Since you can use a string in the first place, the use of the function may not be obvious. However, it is useful in macros, or more complex setups. Example: <tscreen><verb> ; Emulate other assemblers: .macro section name .segment .string(name) .endmacro </verb></tscreen> <sect1><tt>.STRLEN</tt><label id=".STRLEN"><p> Builtin function. The function accepts a string argument in braces and evaluates to the length of the string. Example: The following macro encodes a string as a pascal style string with a leading length byte. <tscreen><verb> .macro PString Arg .byte .strlen(Arg), Arg .endmacro </verb></tscreen> <sect1><tt>.TCOUNT</tt><label id=".TCOUNT"><p> Builtin function. The function accepts a token list in braces. The function result is the number of tokens given as argument. The token list may optionally be enclosed into curly braces which are not considered part of the list and not counted. Enclosement in curly braces allows the inclusion of tokens that would otherwise terminate the list (the closing right paren in the given case). Example: The <tt/ldax/ macro accepts the '#' token to denote immediate addressing (as with the normal 6502 instructions). To translate it into two separate 8 bit load instructions, the '#' token has to get stripped from the argument: <tscreen><verb> .macro ldax arg .if (.match (.mid (0, 1, {arg}), #)) ; ldax called with immediate operand lda #<(.right (.tcount ({arg})-1, {arg})) ldx #>(.right (.tcount ({arg})-1, {arg})) .else ... .endif .endmacro </verb></tscreen> <sect1><tt>.XMATCH</tt><label id=".XMATCH"><p> Builtin function. Matches two token lists against each other. This is most useful within macros, since macros are not stored as strings, but as lists of tokens. The syntax is <tscreen><verb> .XMATCH(<token list #1>, <token list #2>) </verb></tscreen> Both token list may contain arbitrary tokens with the exception of the terminator token (comma resp. right parenthesis) and <itemize> <item>end-of-line <item>end-of-file </itemize> The token lists may optionally be enclosed into curly braces. This allows the inclusion of tokens that would otherwise terminate the list (the closing right paren in the given case). Often a macro parameter is used for any of the token lists. The function compares tokens <em/and/ token values. If you need a function that just compares the type of tokens, have a look at the <tt><ref id=".MATCH" name=".MATCH"></tt> function. See: <tt><ref id=".MATCH" name=".MATCH"></tt> <sect>Control commands<label id="control-commands"><p> Here's a list of all control commands and a description, what they do: <sect1><tt>.A16</tt><label id=".A16"><p> Valid only in 65816 mode. Switch the accumulator to 16 bit. Note: This command will not emit any code, it will tell the assembler to create 16 bit operands for immediate accumulator addressing mode. See also: <tt><ref id=".SMART" name=".SMART"></tt> <sect1><tt>.A8</tt><label id=".A8"><p> Valid only in 65816 mode. Switch the accumulator to 8 bit. Note: This command will not emit any code, it will tell the assembler to create 8 bit operands for immediate accu addressing mode. See also: <tt><ref id=".SMART" name=".SMART"></tt> <sect1><tt>.ADDR</tt><label id=".ADDR"><p> Define word sized data. In 6502 mode, this is an alias for <tt/.WORD/ and may be used for better readability if the data words are address values. In 65816 mode, the address is forced to be 16 bit wide to fit into the current segment. See also <tt><ref id=".FARADDR" name=".FARADDR"></tt>. The command must be followed by a sequence of (not necessarily constant) expressions. Example: <tscreen><verb> .addr $0D00, $AF13, _Clear </verb></tscreen> See: <tt><ref id=".FARADDR" name=".FARADDR"></tt>, <tt><ref id=".WORD" name=".WORD"></tt> <sect1><tt>.ALIGN</tt><label id=".ALIGN"><p> Align data to a given boundary. The command expects a constant integer argument in the range 1 ... 65536, plus an optional second argument in byte range. If there is a second argument, it is used as fill value, otherwise the value defined in the linker configuration file is used (the default for this value is zero). <tt/.ALIGN/ will insert fill bytes, and the number of fill bytes depend of the final address of the segment. <tt/.ALIGN/ cannot insert a variable number of bytes, since that would break address calculations within the module. So each <tt/.ALIGN/ expects the segment to be aligned to a multiple of the alignment, because that allows the number of fill bytes to be calculated in advance by the assembler. You are therefore required to specify a matching alignment for the segment in the linker config. The linker will output a warning if the alignment of the segment is less than what is necessary to have a correct alignment in the object file. Example: <tscreen><verb> .align 256 </verb></tscreen> Some unexpected behaviour might occur if there are multiple <tt/.ALIGN/ commands with different arguments. To allow the assembler to calculate the number of fill bytes in advance, the alignment of the segment must be a multiple of each of the alignment factors. This may result in unexpectedly large alignments for the segment within the module. Example: <tscreen><verb> .align 15 .byte 15 .align 18 .byte 18 </verb></tscreen> For the assembler to be able to align correctly, the segment must be aligned to the least common multiple of 15 and 18 which is 90. The assembler will calculate this automatically and will mark the segment with this value. Unfortunately, the combined alignment may get rather large without the user knowing about it, wasting space in the final executable. If we add another alignment to the example above <tscreen><verb> .align 15 .byte 15 .align 18 .byte 18 .align 251 .byte 0 </verb></tscreen> the assembler will force a segment alignment to the least common multiple of 15, 18 and 251 - which is 22590. To protect the user against errors, the assembler will issue a warning when the combined alignment exceeds 256. The command line option <tt><ref id="option--large-alignment" name="--large-alignment"></tt> will disable this warning. Please note that with alignments that are a power of two (which were the only alignments possible in older versions of the assembler), the problem is less severe, because the least common multiple of powers to the same base is always the larger one. <sect1><tt>.ASCIIZ</tt><label id=".ASCIIZ"><p> Define a string with a trailing zero. Example: <tscreen><verb> Msg: .asciiz "Hello world" </verb></tscreen> This will put the string "Hello world" followed by a binary zero into the current segment. There may be more strings separated by commas, but the binary zero is only appended once (after the last one). <sect1><tt>.ASSERT</tt><label id=".ASSERT"><p> Add an assertion. The command is followed by an expression, an action specifier, and an optional message that is output in case the assertion fails. If no message was given, the string "Assertion failed" is used. The action specifier may be one of <tt/warning/, <tt/error/, <tt/ldwarning/ or <tt/lderror/. In the former two cases, the assertion is evaluated by the assembler if possible, and in any case, it's also passed to the linker in the object file (if one is generated). The linker will then evaluate the expression when segment placement has been done. Example: <tscreen><verb> .assert * = $8000, error, "Code not at $8000" </verb></tscreen> The example assertion will check that the current location is at $8000, when the output file is written, and abort with an error if this is not the case. More complex expressions are possible. The action specifier <tt/warning/ outputs a warning, while the <tt/error/ specifier outputs an error message. In the latter case, generation of the output file is suppressed in both the assembler and linker. <sect1><tt>.AUTOIMPORT</tt><label id=".AUTOIMPORT"><p> Is followed by a plus or a minus character. When switched on (using a +), undefined symbols are automatically marked as import instead of giving errors. When switched off (which is the default so this does not make much sense), this does not happen and an error message is displayed. The state of the autoimport flag is evaluated when the complete source was translated, before outputting actual code, so it is <em/not/ possible to switch this feature on or off for separate sections of code. The last setting is used for all symbols. You should probably not use this switch because it delays error messages about undefined symbols until the link stage. The cc65 compiler (which is supposed to produce correct assembler code in all circumstances, something which is not true for most assembler programmers) will insert this command to avoid importing each and every routine from the runtime library. Example: <tscreen><verb> .autoimport + ; Switch on auto import </verb></tscreen> <sect1><tt>.BANKBYTES</tt><label id=".BANKBYTES"><p> Define byte sized data by extracting only the bank byte (that is, bits 16-23) from each expression. This is equivalent to <tt><ref id=".BYTE" name=".BYTE"></tt> with the operator '^' prepended to each expression in its list. Example: <tscreen><verb> .define MyTable TableItem0, TableItem1, TableItem2, TableItem3 TableLookupLo: .lobytes MyTable TableLookupHi: .hibytes MyTable TableLookupBank: .bankbytes MyTable </verb></tscreen> which is equivalent to <tscreen><verb> TableLookupLo: .byte <TableItem0, <TableItem1, <TableItem2, <TableItem3 TableLookupHi: .byte >TableItem0, >TableItem1, >TableItem2, >TableItem3 TableLookupBank: .byte ^TableItem0, ^TableItem1, ^TableItem2, ^TableItem3 </verb></tscreen> See also: <tt><ref id=".BYTE" name=".BYTE"></tt>, <tt><ref id=".HIBYTES" name=".HIBYTES"></tt>, <tt><ref id=".LOBYTES" name=".LOBYTES"></tt> <sect1><tt>.BSS</tt><label id=".BSS"><p> Switch to the BSS segment. The name of the BSS segment is always "BSS", so this is a shortcut for <tscreen><verb> .segment "BSS" </verb></tscreen> See also the <tt><ref id=".SEGMENT" name=".SEGMENT"></tt> command. <sect1><tt>.BYT, .BYTE</tt><label id=".BYTE"><p> Define byte sized data. Must be followed by a sequence of (byte ranged) expressions or strings. Example: <tscreen><verb> .byte "Hello " .byt "world", $0D, $00 </verb></tscreen> <sect1><tt>.CASE</tt><label id=".CASE"><p> Switch on or off case sensitivity on identifiers. The default is off (that is, identifiers are case sensitive), but may be changed by the -i switch on the command line. The command must be followed by a '+' or '-' character to switch the option on or off respectively. Example: <tscreen><verb> .case - ; Identifiers are not case sensitive </verb></tscreen> <sect1><tt>.CHARMAP</tt><label id=".CHARMAP"><p> Apply a custom mapping for characters. The command is followed by two numbers. The first one is the index of the source character (range 0..255); the second one is the mapping (range 0..255). The mapping applies to all character and string constants <em/when/ they generate output; and, overrides a mapping table specified with the <tt><ref id="option-t" name="-t"></tt> command line switch. Example: <tscreen><verb> .charmap $41, $61 ; Map 'A' to 'a' </verb></tscreen> <sect1><tt>.CODE</tt><label id=".CODE"><p> Switch to the CODE segment. The name of the CODE segment is always "CODE", so this is a shortcut for <tscreen><verb> .segment "CODE" </verb></tscreen> See also the <tt><ref id=".SEGMENT" name=".SEGMENT"></tt> command. <sect1><tt>.CONDES</tt><label id=".CONDES"><p> Export a symbol and mark it in a special way. The linker is able to build tables of all such symbols. This may be used to automatically create a list of functions needed to initialize linked library modules. Note: The linker has a feature to build a table of marked routines, but it is your code that must call these routines, so just declaring a symbol with <tt/.CONDES/ does nothing by itself. All symbols are exported as an absolute (16 bit) symbol. You don't need to use an additional <tt><ref id=".EXPORT" name=".EXPORT"></tt> statement, this is implied by <tt/.CONDES/. <tt/.CONDES/ is followed by the type, which may be <tt/constructor/, <tt/destructor/ or a numeric value between 0 and 6 (where 0 is the same as specifying <tt/constructor/ and 1 is equal to specifying <tt/destructor/). The <tt><ref id=".CONSTRUCTOR" name=".CONSTRUCTOR"></tt>, <tt><ref id=".DESTRUCTOR" name=".DESTRUCTOR"></tt> and <tt><ref id=".INTERRUPTOR" name=".INTERRUPTOR"></tt> commands are actually shortcuts for <tt/.CONDES/ with a type of <tt/constructor/ resp. <tt/destructor/ or <tt/interruptor/. After the type, an optional priority may be specified. Higher numeric values mean higher priority. If no priority is given, the default priority of 7 is used. Be careful when assigning priorities to your own module constructors so they won't interfere with the ones in the cc65 library. Example: <tscreen><verb> .condes ModuleInit, constructor .condes ModInit, 0, 16 </verb></tscreen> See the <tt><ref id=".CONSTRUCTOR" name=".CONSTRUCTOR"></tt>, <tt><ref id=".DESTRUCTOR" name=".DESTRUCTOR"></tt> and <tt><ref id=".INTERRUPTOR" name=".INTERRUPTOR"></tt> commands and the separate section <ref id="condes" name="Module constructors/destructors"> explaining the feature in more detail. <sect1><tt>.CONSTRUCTOR</tt><label id=".CONSTRUCTOR"><p> Export a symbol and mark it as a module constructor. This may be used together with the linker to build a table of constructor subroutines that are called by the startup code. Note: The linker has a feature to build a table of marked routines, but it is your code that must call these routines, so just declaring a symbol as constructor does nothing by itself. A constructor is always exported as an absolute (16 bit) symbol. You don't need to use an additional <tt/.export/ statement, this is implied by <tt/.constructor/. It may have an optional priority that is separated by a comma. Higher numeric values mean a higher priority. If no priority is given, the default priority of 7 is used. Be careful when assigning priorities to your own module constructors so they won't interfere with the ones in the cc65 library. Example: <tscreen><verb> .constructor ModuleInit .constructor ModInit, 16 </verb></tscreen> See the <tt><ref id=".CONDES" name=".CONDES"></tt> and <tt><ref id=".DESTRUCTOR" name=".DESTRUCTOR"></tt> commands and the separate section <ref id="condes" name="Module constructors/destructors"> explaining the feature in more detail. <sect1><tt>.DATA</tt><label id=".DATA"><p> Switch to the DATA segment. The name of the DATA segment is always "DATA", so this is a shortcut for <tscreen><verb> .segment "DATA" </verb></tscreen> See also the <tt><ref id=".SEGMENT" name=".SEGMENT"></tt> command. <sect1><tt>.DBYT</tt><label id=".DBYT"><p> Define word sized data with the hi and lo bytes swapped (use <tt/.WORD/ to create word sized data in native 65XX format). Must be followed by a sequence of (word ranged) expressions. Example: <tscreen><verb> .dbyt $1234, $4512 </verb></tscreen> This will emit the bytes <tscreen><verb> $12 $34 $45 $12 </verb></tscreen> into the current segment in that order. <sect1><tt>.DEBUGINFO</tt><label id=".DEBUGINFO"><p> Switch on or off debug info generation. The default is off (that is, the object file will not contain debug infos), but may be changed by the -g switch on the command line. The command must be followed by a '+' or '-' character to switch the option on or off respectively. Example: <tscreen><verb> .debuginfo + ; Generate debug info </verb></tscreen> <sect1><tt>.DEFINE</tt><label id=".DEFINE"><p> Start a define style macro definition. The command is followed by an identifier (the macro name) and optionally by a list of formal arguments in braces. Please note that <tt/.DEFINE/ shares most disadvantages with its C counterpart, so the general advice is, <bf/NOT/ do use <tt/.DEFINE/ if you don't have to. See also the <tt><ref id=".UNDEFINE" name=".UNDEFINE"></tt> command and section <ref id="macros" name="Macros">. <sect1><tt>.DELMAC, .DELMACRO</tt><label id=".DELMACRO"><p> Delete a classic macro (defined with <tt><ref id=".MACRO" name=".MACRO"></tt>) . The command is followed by the name of an existing macro. Its definition will be deleted together with the name. If necessary, another macro with this name may be defined later. See: <tt><ref id=".ENDMACRO" name=".ENDMACRO"></tt>, <tt><ref id=".EXITMACRO" name=".EXITMACRO"></tt>, <tt><ref id=".MACRO" name=".MACRO"></tt> See also section <ref id="macros" name="Macros">. <sect1><tt>.DEF, .DEFINED</tt><label id=".DEFINED"><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 a symbol that is already defined somewhere in the source file up to the current position. Otherwise the function yields false. As an example, the <tt><ref id=".IFDEF" name=".IFDEF"></tt> statement may be replaced by <tscreen><verb> .if .defined(a) </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 together with the linker to build a table of destructor subroutines that are called by the startup code. Note: The linker has a feature to build a table of marked routines, but it is your code that must call these routines, so just declaring a symbol as constructor does nothing by itself. A destructor is always exported as an absolute (16 bit) symbol. You don't need to use an additional <tt/.export/ statement, this is implied by <tt/.destructor/. It may have an optional priority that is separated by a comma. Higher numerical values mean a higher priority. If no priority is given, the default priority of 7 is used. Be careful when assigning priorities to your own module destructors so they won't interfere with the ones in the cc65 library. Example: <tscreen><verb> .destructor ModuleDone .destructor ModDone, 16 </verb></tscreen> See the <tt><ref id=".CONDES" name=".CONDES"></tt> and <tt><ref id=".CONSTRUCTOR" name=".CONSTRUCTOR"></tt> commands and the separate section <ref id="condes" name="Module constructors/destructors"> explaining the feature in more detail. <sect1><tt>.DWORD</tt><label id=".DWORD"><p> Define dword sized data (4 bytes) Must be followed by a sequence of expressions. Example: <tscreen><verb> .dword $12344512, $12FA489 </verb></tscreen> <sect1><tt>.ELSE</tt><label id=".ELSE"><p> Conditional assembly: Reverse the current condition. <sect1><tt>.ELSEIF</tt><label id=".ELSEIF"><p> Conditional assembly: Reverse current condition and test a new one. <sect1><tt>.END</tt><label id=".END"><p> Forced end of assembly. Assembly stops at this point, even if the command is read from an include file. <sect1><tt>.ENDENUM</tt><label id=".ENDENUM"><p> End a <tt><ref id=".ENUM" name=".ENUM"></tt> declaration. <sect1><tt>.ENDIF</tt><label id=".ENDIF"><p> Conditional assembly: Close a <tt><ref id=".IF" name=".IF..."></tt> or <tt><ref id=".ELSE" name=".ELSE"></tt> branch. <sect1><tt>.ENDMAC, .ENDMACRO</tt><label id=".ENDMACRO"><p> Marks the end of a macro definition. See: <tt><ref id=".DELMACRO" name=".DELMACRO"></tt>, <tt><ref id=".EXITMACRO" name=".EXITMACRO"></tt>, <tt><ref id=".MACRO" name=".MACRO"></tt> See also section <ref id="macros" name="Macros">. <sect1><tt>.ENDPROC</tt><label id=".ENDPROC"><p> End of local lexical level (see <tt><ref id=".PROC" name=".PROC"></tt>). <sect1><tt>.ENDREP, .ENDREPEAT</tt><label id=".ENDREPEAT"><p> End a <tt><ref id=".REPEAT" name=".REPEAT"></tt> block. <sect1><tt>.ENDSCOPE</tt><label id=".ENDSCOPE"><p> End of local lexical level (see <tt/<ref id=".SCOPE" name=".SCOPE">/). <sect1><tt>.ENDSTRUCT</tt><label id=".ENDSTRUCT"><p> Ends a struct definition. See the <tt/<ref id=".STRUCT" name=".STRUCT">/ command and the separate section named <ref id="structs" name=""Structs and unions"">. <sect1><tt>.ENDUNION</tt><label id=".ENDUNION"><p> Ends a union definition. See the <tt/<ref id=".UNION" name=".UNION">/ command and the separate section named <ref id="structs" name=""Structs and unions"">. <sect1><tt>.ENUM</tt><label id=".ENUM"><p> Start an enumeration. This directive is very similar to the C <tt/enum/ keyword. If a name is given, a new scope is created for the enumeration, otherwise the enumeration members are placed in the enclosing scope. In the enumeration body, symbols are declared. The first symbol has a value of zero, and each following symbol will get the value of the preceding plus one. This behaviour may be overridden by an explicit assignment. Two symbols may have the same value. Example: <tscreen><verb> .enum errorcodes no_error file_error parse_error .endenum </verb></tscreen> Above example will create a new scope named <tt/errorcodes/ with three symbols in it that get the values 0, 1 and 2 respectively. Another way to write this would have been: <tscreen><verb> .scope errorcodes no_error = 0 file_error = 1 parse_error = 2 .endscope </verb></tscreen> Please note that explicit scoping must be used to access the identifiers: <tscreen><verb> .word errorcodes::no_error </verb></tscreen> A more complex example: <tscreen><verb> .enum EUNKNOWN = -1 EOK EFILE EBUSY EAGAIN EWOULDBLOCK = EAGAIN .endenum </verb></tscreen> In this example, the enumeration does not have a name, which means that the members will be visible in the enclosing scope and can be used in this scope without explicit scoping. The first member (<tt/EUNKNOWN/) has the value -1. The value for the following members is incremented by one, so <tt/EOK/ would be zero and so on. <tt/EWOULDBLOCK/ is an alias for <tt/EGAIN/, so it has an override for the value using an already defined symbol. <sect1><tt>.ERROR</tt><label id=".ERROR"><p> Force an assembly error. The assembler will output an error message preceded by "User error". Assembly is continued but no object file will generated. This command may be used to check for initial conditions that must be set before assembling a source file. Example: <tscreen><verb> .if foo = 1 ... .elseif bar = 1 ... .else .error "Must define foo or bar!" .endif </verb></tscreen> See also: <tt><ref id=".FATAL" name=".FATAL"></tt>, <tt><ref id=".OUT" name=".OUT"></tt>, <tt><ref id=".WARNING" name=".WARNING"></tt> <sect1><tt>.EXITMAC, .EXITMACRO</tt><label id=".EXITMACRO"><p> Abort a macro expansion immediately. This command is often useful in recursive macros. See: <tt><ref id=".DELMACRO" name=".DELMACRO"></tt>, <tt><ref id=".ENDMACRO" name=".ENDMACRO"></tt>, <tt><ref id=".MACRO" name=".MACRO"></tt> See also section <ref id="macros" name="Macros">. <sect1><tt>.EXPORT</tt><label id=".EXPORT"><p> Make symbols accessible from other modules. Must be followed by a comma separated list of symbols to export, with each one optionally followed by an address specification and (also optional) an assignment. Using an additional assignment in the export statement allows to define and export a symbol in one statement. The default is to export the symbol with the address size it actually has. The assembler will issue a warning, if the symbol is exported with an address size smaller than the actual address size. Examples: <tscreen><verb> .export foo .export bar: far .export foobar: far = foo * bar .export baz := foobar, zap: far = baz - bar </verb></tscreen> As with constant definitions, using <tt/:=/ instead of <tt/=/ marks the symbols as a label. See: <tt><ref id=".EXPORTZP" name=".EXPORTZP"></tt> <sect1><tt>.EXPORTZP</tt><label id=".EXPORTZP"><p> Make symbols accessible from other modules. Must be followed by a comma separated list of symbols to export. The exported symbols are explicitly marked as zero page symbols. An assignment may be included in the <tt/.EXPORTZP/ statement. This allows to define and export a symbol in one statement. Examples: <tscreen><verb> .exportzp foo, bar .exportzp baz := $02 </verb></tscreen> See: <tt><ref id=".EXPORT" name=".EXPORT"></tt> <sect1><tt>.FARADDR</tt><label id=".FARADDR"><p> Define far (24 bit) address data. The command must be followed by a sequence of (not necessarily constant) expressions. Example: <tscreen><verb> .faraddr DrawCircle, DrawRectangle, DrawHexagon </verb></tscreen> See: <tt><ref id=".ADDR" name=".ADDR"></tt> <sect1><tt>.FATAL</tt><label id=".FATAL"><p> Force an assembly error and terminate assembly. The assembler will output an error message preceded by "User error" and will terminate assembly immediately. This command may be used to check for initial conditions that must be set before assembling a source file. Example: <tscreen><verb> .if foo = 1 ... .elseif bar = 1 ... .else .fatal "Must define foo or bar!" .endif </verb></tscreen> See also: <tt><ref id=".ERROR" name=".ERROR"></tt>, <tt><ref id=".OUT" name=".OUT"></tt>, <tt><ref id=".WARNING" name=".WARNING"></tt> <sect1><tt>.FEATURE</tt><label id=".FEATURE"><p> This directive may be used to enable one or more compatibility features of the assembler. While the use of <tt/.FEATURE/ should be avoided when possible, it may be useful when porting sources written for other assemblers. There is no way to switch a feature off, once you have enabled it, so using <tscreen><verb> .FEATURE xxx </verb></tscreen> will enable the feature until end of assembly is reached. The following features are available: <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 at character is not allowed to start an identifier, even with this feature enabled. <tag><tt>bracket_as_indirect</tt><label id="bracket_as_indirect"></tag> Use <tt>[]</tt> instead of <tt>()</tt> for the indirect addressing modes. Example: <tscreen><verb> lda [$82] lda [$82,x] lda [$82],y jmp [$fffe] jmp [table,x] </verb></tscreen> <em/Note:/ This should not be used in 65186 mode because it conflicts with the 65816 instruction syntax for far addressing. See the section covering <tt/<ref id="address-sizes" name="address sizes">/ for more information. <tag><tt>c_comments</tt><label id="c_comments"></tag> Allow C like comments using <tt>/*</tt> and <tt>*/</tt> as left and right comment terminators. Note that C comments may not be nested. There's also a pitfall when using C like comments: All statements must be terminated by "end-of-line". Using C like comments, it is possible to hide the newline, which results in error messages. See the following non working example: <tscreen><verb> lda #$00 /* This comment hides the newline */ sta $82 </verb></tscreen> <tag><tt>dollar_in_identifiers</tt><label id="dollar_in_identifiers"></tag> Accept the dollar sign ('$') as a valid character in identifiers. The dollar character is not allowed to start an identifier, even with this feature enabled. <tag><tt>dollar_is_pc</tt><label id="dollar_is_pc"></tag> The dollar sign may be used as an alias for the star ('*'), which gives the value of the current PC in expressions. Note: Assignment to the pseudo variable is not allowed. <tag><tt>force_range</tt><label id="force_range"></tag> Force expressions into their valid range for immediate addressing and storage operators like <tt><ref id=".BYTE" name=".BYTE"></tt> and <tt><ref id=".WORD" name=".WORD"></tt>. Be very careful with this one, since it will completely disable error checks. <tag><tt>labels_without_colons</tt><label id="labels_without_colons"></tag> Allow labels without a trailing colon. These labels are only accepted, if they start at the beginning of a line (no leading white space). <tag><tt>leading_dot_in_identifiers</tt><label id="leading_dot_in_identifiers"></tag> Accept the dot ('.') as the first character of an identifier. This may be used for example to create macro names that start with a dot emulating control directives of other assemblers. Note however, that none of the reserved keywords built into the assembler, that starts with a dot, may be overridden. When using this feature, you may also get into trouble if later versions of the assembler define new keywords starting with a dot. <tag><tt>loose_char_term</tt><label id="loose_char_term"></tag> Accept single quotes as well as double quotes as terminators for char constants. <tag><tt>loose_string_term</tt><label id="loose_string_term"></tag> Accept single quotes as well as double quotes as terminators for string constants. <tag><tt>missing_char_term</tt><label id="missing_char_term"></tag> Accept single quoted character constants where the terminating quote is missing. <tscreen><verb> lda #'a </verb></tscreen> <em/Note:/ This does not work in conjunction with <tt/.FEATURE loose_string_term/, since in this case the input would be ambiguous. <tag><tt>org_per_seg</tt><label id="org_per_seg"></tag> This feature makes relocatable/absolute mode local to the current segment. Using <tt><ref id=".ORG" name=".ORG"></tt> when <tt/org_per_seg/ is in effect will only enable absolute mode for the current segment. Dito for <tt><ref id=".RELOC" name=".RELOC"></tt>. <tag><tt>pc_assignment</tt><label id="pc_assignment"></tag> Allow assignments to the PC symbol ('*' or '$' if <tt/dollar_is_pc/ is enabled). Such an assignment is handled identical to the <tt><ref id=".ORG" name=".ORG"></tt> command (which is usually not needed, so just removing the lines with the assignments may also be an option when porting code written for older assemblers). <tag><tt>string_escapes</tt><label id="string_escapes"></tag> Allow C-style backslash escapes within string constants to embed special characters. The following escapes are accepted: <itemize> <item><tt>\\</tt> backslash (<tt>$5C</tt>) <item><tt>\'</tt> single quote (<tt>$27</tt>) <item><tt>\"</tt> double quote (<tt>$22</tt>) <item><tt>\t</tt> tab (<tt>$09</tt>) <item><tt>\r</tt> carriage return (<tt>$0D</tt>) <item><tt>\n</tt> newline (<tt>$0A</tt>) <item><tt>\xNN</tt> (<tt>$NN</tt>) </itemize> Note that string escapes are converted to platform-specific characters in the same way that other characters are converted. <tag><tt>ubiquitous_idents</tt><label id="ubiquitous_idents"></tag> Allow the use of instructions names as names for macros and symbols. This makes it possible to "overload" instructions by defining a macro with the same name. This does also make it possible to introduce hard to find errors in your code, so be careful! <tag><tt>underline_in_numbers</tt><label id="underline_in_numbers"></tag> Allow underlines within numeric constants. These may be used for grouping the digits of numbers for easier reading. Example: <tscreen><verb> .feature underline_in_numbers .word %1100001110100101 .word %1100_0011_1010_0101 ; Identical but easier to read </verb></tscreen> </descrip> It is also possible to specify features on the command line using the <tt><ref id="option--feature" name="--feature"></tt> command line option. This is useful when translating sources written for older assemblers, when you don't want to change the source code. As an example, to translate sources written for Andre Fachats xa65 assembler, the features <verb> labels_without_colons, pc_assignment, loose_char_term </verb> may be helpful. They do not make ca65 completely compatible, so you may not be able to translate the sources without changes, even when enabling these features. However, I have found several sources that translate without problems when enabling these features on the command line. <sect1><tt>.FILEOPT, .FOPT</tt><label id=".FOPT"><p> Insert an option string into the object file. There are two forms of this command, one specifies the option by a keyword, the second specifies it as a number. Since usage of the second one needs knowledge of the internal encoding, its use is not recommended and I will only describe the first form here. The command is followed by one of the keywords <tscreen><verb> author comment compiler </verb></tscreen> a comma and a string. The option is written into the object file together with the string value. This is currently unidirectional and there is no way to actually use these options once they are in the object file. Examples: <tscreen><verb> .fileopt comment, "Code stolen from my brother" .fileopt compiler, "BASIC 2.0" .fopt author, "J. R. User" </verb></tscreen> <sect1><tt>.FORCEIMPORT</tt><label id=".FORCEIMPORT"><p> Import an absolute symbol from another module. The command is followed by a comma separated list of symbols to import. The command is similar to <tt> <ref id=".IMPORT" name=".IMPORT"></tt>, but the import reference is always written to the generated object file, even if the symbol is never referenced (<tt><ref id=".IMPORT" name=".IMPORT"></tt> will not generate import references for unused symbols). Example: <tscreen><verb> .forceimport needthisone, needthistoo </verb></tscreen> See: <tt><ref id=".IMPORT" name=".IMPORT"></tt> <sect1><tt>.GLOBAL</tt><label id=".GLOBAL"><p> Declare symbols as global. Must be followed by a comma separated list of symbols to declare. Symbols from the list, that are defined somewhere in the source, are exported, all others are imported. Additional <tt><ref id=".IMPORT" name=".IMPORT"></tt> or <tt><ref id=".EXPORT" name=".EXPORT"></tt> commands for the same symbol are allowed. Example: <tscreen><verb> .global foo, bar </verb></tscreen> <sect1><tt>.GLOBALZP</tt><label id=".GLOBALZP"><p> Declare symbols as global. Must be followed by a comma separated list of symbols to declare. Symbols from the list, that are defined somewhere in the source, are exported, all others are imported. Additional <tt><ref id=".IMPORTZP" name=".IMPORTZP"></tt> or <tt><ref id=".EXPORTZP" name=".EXPORTZP"></tt> commands for the same symbol are allowed. The symbols in the list are explicitly marked as zero page symbols. Example: <tscreen><verb> .globalzp foo, bar </verb></tscreen> <sect1><tt>.HIBYTES</tt><label id=".HIBYTES"><p> Define byte sized data by extracting only the high byte (that is, bits 8-15) from each expression. This is equivalent to <tt><ref id=".BYTE" name=".BYTE"></tt> with the operator '>' prepended to each expression in its list. Example: <tscreen><verb> .lobytes $1234, $2345, $3456, $4567 .hibytes $fedc, $edcb, $dcba, $cba9 </verb></tscreen> which is equivalent to <tscreen><verb> .byte $34, $45, $56, $67 .byte $fe, $ed, $dc, $cb </verb></tscreen> Example: <tscreen><verb> .define MyTable TableItem0, TableItem1, TableItem2, TableItem3 TableLookupLo: .lobytes MyTable TableLookupHi: .hibytes MyTable </verb></tscreen> which is equivalent to <tscreen><verb> TableLookupLo: .byte <TableItem0, <TableItem1, <TableItem2, <TableItem3 TableLookupHi: .byte >TableItem0, >TableItem1, >TableItem2, >TableItem3 </verb></tscreen> See also: <tt><ref id=".BYTE" name=".BYTE"></tt>, <tt><ref id=".LOBYTES" name=".LOBYTES"></tt>, <tt><ref id=".BANKBYTES" name=".BANKBYTES"></tt> <sect1><tt>.I16</tt><label id=".I16"><p> Valid only in 65816 mode. Switch the index registers to 16 bit. Note: This command will not emit any code, it will tell the assembler to create 16 bit operands for immediate operands. See also the <tt><ref id=".I8" name=".I8"></tt> and <tt><ref id=".SMART" name=".SMART"></tt> commands. <sect1><tt>.I8</tt><label id=".I8"><p> Valid only in 65816 mode. Switch the index registers to 8 bit. Note: This command will not emit any code, it will tell the assembler to create 8 bit operands for immediate operands. See also the <tt><ref id=".I16" name=".I16"></tt> and <tt><ref id=".SMART" name=".SMART"></tt> commands. <sect1><tt>.IF</tt><label id=".IF"><p> Conditional assembly: Evaluate an expression and switch assembler output on or off depending on the expression. The expression must be a constant expression, that is, all operands must be defined. A expression value of zero evaluates to FALSE, any other value evaluates to TRUE. <sect1><tt>.IFBLANK</tt><label id=".IFBLANK"><p> Conditional assembly: Check if there are any remaining tokens in this line, and evaluate to FALSE if this is the case, and to TRUE otherwise. If the condition is not true, further lines are not assembled until an <tt><ref id=".ELSE" name=".ELSE"></tt>, <tt><ref id=".ELSEIF" name=".ELSEIF"></tt> or <tt><ref id=".ENDIF" name=".ENDIF"></tt> directive. This command is often used to check if a macro parameter was given. Since an empty macro parameter will evaluate to nothing, the condition will evaluate to TRUE if an empty parameter was given. Example: <tscreen><verb> .macro arg1, arg2 .ifblank arg2 lda #arg1 .else lda #arg2 .endif .endmacro </verb></tscreen> See also: <tt><ref id=".BLANK" name=".BLANK"></tt> <sect1><tt>.IFCONST</tt><label id=".IFCONST"><p> Conditional assembly: Evaluate an expression and switch assembler output on or off depending on the constness of the expression. A const expression evaluates to to TRUE, a non const expression (one containing an imported or currently undefined symbol) evaluates to FALSE. See also: <tt><ref id=".CONST" name=".CONST"></tt> <sect1><tt>.IFDEF</tt><label id=".IFDEF"><p> Conditional assembly: Check if a symbol is defined. Must be followed by a symbol name. The condition is true if the the given symbol is already defined, and false otherwise. See also: <tt><ref id=".DEFINED" name=".DEFINED"></tt> <sect1><tt>.IFNBLANK</tt><label id=".IFNBLANK"><p> Conditional assembly: Check if there are any remaining tokens in this line, and evaluate to TRUE if this is the case, and to FALSE otherwise. If the condition is not true, further lines are not assembled until an <tt><ref id=".ELSE" name=".ELSE"></tt>, <tt><ref id=".ELSEIF" name=".ELSEIF"></tt> or <tt><ref id=".ENDIF" name=".ENDIF"></tt> directive. This command is often used to check if a macro parameter was given. Since an empty macro parameter will evaluate to nothing, the condition will evaluate to FALSE if an empty parameter was given. Example: <tscreen><verb> .macro arg1, arg2 lda #arg1 .ifnblank arg2 lda #arg2 .endif .endmacro </verb></tscreen> See also: <tt><ref id=".BLANK" name=".BLANK"></tt> <sect1><tt>.IFNDEF</tt><label id=".IFNDEF"><p> Conditional assembly: Check if a symbol is defined. Must be followed by a symbol name. The condition is true if the the given symbol is not defined, and false otherwise. See also: <tt><ref id=".DEFINED" name=".DEFINED"></tt> <sect1><tt>.IFNREF</tt><label id=".IFNREF"><p> Conditional assembly: Check if a symbol is referenced. Must be followed by a symbol name. The condition is true if if the the given symbol was not referenced before, and false otherwise. See also: <tt><ref id=".REFERENCED" name=".REFERENCED"></tt> <sect1><tt>.IFP02</tt><label id=".IFP02"><p> Conditional assembly: Check if the assembler is currently in 6502 mode (see <tt><ref id=".P02" name=".P02"></tt> command). <sect1><tt>.IFP4510</tt><label id=".IFP4510"><p> Conditional assembly: Check if the assembler is currently in 4510 mode (see <tt><ref id=".P4510" name=".P4510"></tt> command). <sect1><tt>.IFP816</tt><label id=".IFP816"><p> Conditional assembly: Check if the assembler is currently in 65816 mode (see <tt><ref id=".P816" name=".P816"></tt> command). <sect1><tt>.IFPC02</tt><label id=".IFPC02"><p> Conditional assembly: Check if the assembler is currently in 65C02 mode (see <tt><ref id=".PC02" name=".PC02"></tt> command). <sect1><tt>.IFPSC02</tt><label id=".IFPSC02"><p> Conditional assembly: Check if the assembler is currently in 65SC02 mode (see <tt><ref id=".PSC02" name=".PSC02"></tt> command). <sect1><tt>.IFREF</tt><label id=".IFREF"><p> Conditional assembly: Check if a symbol is referenced. Must be followed by a symbol name. The condition is true if if the the given symbol was referenced before, and false otherwise. This command may be used to build subroutine libraries in include files (you may use separate object modules for this purpose too). Example: <tscreen><verb> .ifref ToHex ; If someone used this subroutine ToHex: tay ; Define subroutine lda HexTab,y rts .endif </verb></tscreen> See also: <tt><ref id=".REFERENCED" name=".REFERENCED"></tt> <sect1><tt>.IMPORT</tt><label id=".IMPORT"><p> Import a symbol from another module. The command is followed by a comma separated list of symbols to import, with each one optionally followed by an address specification. Example: <tscreen><verb> .import foo .import bar: zeropage </verb></tscreen> See: <tt><ref id=".IMPORTZP" name=".IMPORTZP"></tt> <sect1><tt>.IMPORTZP</tt><label id=".IMPORTZP"><p> Import a symbol from another module. The command is followed by a comma separated list of symbols to import. The symbols are explicitly imported as zero page symbols (that is, symbols with values in byte range). Example: <tscreen><verb> .importzp foo, bar </verb></tscreen> See: <tt><ref id=".IMPORT" name=".IMPORT"></tt> <sect1><tt>.INCBIN</tt><label id=".INCBIN"><p> Include a file as binary data. The command expects a string argument that is the name of a file to include literally in the current segment. In addition to that, a start offset and a size value may be specified, separated by commas. If no size is specified, all of the file from the start offset to end-of-file is used. If no start position is specified either, zero is assumed (which means that the whole file is inserted). Example: <tscreen><verb> ; Include whole file .incbin "sprites.dat" ; Include file starting at offset 256 .incbin "music.dat", $100 ; Read 100 bytes starting at offset 200 .incbin "graphics.dat", 200, 100 </verb></tscreen> <sect1><tt>.INCLUDE</tt><label id=".INCLUDE"><p> Include another file. Include files may be nested up to a depth of 16. Example: <tscreen><verb> .include "subs.inc" </verb></tscreen> <sect1><tt>.INTERRUPTOR</tt><label id=".INTERRUPTOR"><p> Export a symbol and mark it as an interruptor. This may be used together with the linker to build a table of interruptor subroutines that are called in an interrupt. Note: The linker has a feature to build a table of marked routines, but it is your code that must call these routines, so just declaring a symbol as interruptor does nothing by itself. An interruptor is always exported as an absolute (16 bit) symbol. You don't need to use an additional <tt/.export/ statement, this is implied by <tt/.interruptor/. It may have an optional priority that is separated by a comma. Higher numeric values mean a higher priority. If no priority is given, the default priority of 7 is used. Be careful when assigning priorities to your own module constructors so they won't interfere with the ones in the cc65 library. Example: <tscreen><verb> .interruptor IrqHandler .interruptor Handler, 16 </verb></tscreen> See the <tt><ref id=".CONDES" name=".CONDES"></tt> command and the separate section <ref id="condes" name="Module constructors/destructors"> explaining 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 before a newline. The option is off by default. Note: Line continuations do not work in a comment. A backslash at the end of a comment is treated as part of the comment and does not trigger line continuation. The command must be followed by a '+' or '-' character to switch the option on or off respectively. Example: <tscreen><verb> .linecont + ; Allow line continuations lda \ #$20 ; This is legal now </verb></tscreen> <sect1><tt>.LIST</tt><label id=".LIST"><p> Enable output to the listing. The command must be followed by a boolean switch ("on", "off", "+" or "-") and will enable or disable listing output. The option has no effect if the listing is not enabled by the command line switch -l. If -l is used, an internal counter is set to 1. Lines are output to the listing file, if the counter is greater than zero, and suppressed if the counter is zero. Each use of <tt/.LIST/ will increment or decrement the counter. Example: <tscreen><verb> .list on ; Enable listing output </verb></tscreen> <sect1><tt>.LISTBYTES</tt><label id=".LISTBYTES"><p> Set, how many bytes are shown in the listing for one source line. The default is 12, so the listing will show only the first 12 bytes for any source line that generates more than 12 bytes of code or data. The directive needs an argument, which is either "unlimited", or an integer constant in the range 4..255. Examples: <tscreen><verb> .listbytes unlimited ; List all bytes .listbytes 12 ; List the first 12 bytes .incbin "data.bin" ; Include large binary file </verb></tscreen> <sect1><tt>.LOBYTES</tt><label id=".LOBYTES"><p> Define byte sized data by extracting only the low byte (that is, bits 0-7) from each expression. This is equivalent to <tt><ref id=".BYTE" name=".BYTE"></tt> with the operator '<' prepended to each expression in its list. Example: <tscreen><verb> .lobytes $1234, $2345, $3456, $4567 .hibytes $fedc, $edcb, $dcba, $cba9 </verb></tscreen> which is equivalent to <tscreen><verb> .byte $34, $45, $56, $67 .byte $fe, $ed, $dc, $cb </verb></tscreen> Example: <tscreen><verb> .define MyTable TableItem0, TableItem1, TableItem2, TableItem3 TableLookupLo: .lobytes MyTable TableLookupHi: .hibytes MyTable </verb></tscreen> which is equivalent to <tscreen><verb> TableLookupLo: .byte <TableItem0, <TableItem1, <TableItem2, <TableItem3 TableLookupHi: .byte >TableItem0, >TableItem1, >TableItem2, >TableItem3 </verb></tscreen> See also: <tt><ref id=".BYTE" name=".BYTE"></tt>, <tt><ref id=".HIBYTES" name=".HIBYTES"></tt>, <tt><ref id=".BANKBYTES" name=".BANKBYTES"></tt> <sect1><tt>.LOCAL</tt><label id=".LOCAL"><p> This command may only be used inside a macro definition. It declares a list of identifiers as local to the macro expansion. A problem when using macros are labels: Since they don't change their name, you get a "duplicate symbol" error if the macro is expanded the second time. Labels declared with <tt><ref id=".LOCAL" name=".LOCAL"></tt> have their name mapped to an internal unique name (<tt/___ABCD__/) with each macro invocation. Some other assemblers start a new lexical block inside a macro expansion. This has some drawbacks however, since that will not allow <em/any/ symbol to be visible outside a macro, a feature that is sometimes useful. The <tt><ref id=".LOCAL" name=".LOCAL"></tt> command is in my eyes a better way to address the problem. You get an error when using <tt><ref id=".LOCAL" name=".LOCAL"></tt> outside a macro. <sect1><tt>.LOCALCHAR</tt><label id=".LOCALCHAR"><p> Defines the character that start "cheap" local labels. You may use one of '@' and '?' as start character. The default is '@'. Cheap local labels are labels that are visible only between two non cheap labels. This way you can reuse identifiers like "<tt/loop/" without using explicit lexical nesting. Example: <tscreen><verb> .localchar '?' Clear: lda #$00 ; Global label ?Loop: sta Mem,y ; Local label dey bne ?Loop ; Ok rts Sub: ... ; New global label bne ?Loop ; ERROR: Unknown identifier! </verb></tscreen> <sect1><tt>.MACPACK</tt><label id=".MACPACK"><p> Insert a predefined macro package. The command is followed by an identifier specifying the macro package to insert. Available macro packages are: <tscreen><verb> atari Defines the scrcode macro. cbm Defines the scrcode macro. cpu Defines constants for the .CPU variable. 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 redefines already existing macros will lead to an error. Example: <tscreen><verb> .macpack longbranch ; Include macro package cmp #$20 ; Set condition codes jne Label ; Jump long on condition </verb></tscreen> Macro packages are explained in more detail in section <ref id="macropackages" name="Macro packages">. <sect1><tt>.MAC, .MACRO</tt><label id=".MACRO"><p> Start a classic macro definition. The command is followed by an identifier (the macro name) and optionally by a comma separated list of identifiers that are macro parameters. A macro definition is terminated by <tt><ref id=".ENDMACRO" name=".ENDMACRO"></tt>. Example: <tscreen><verb> .macro ldax arg ; Define macro ldax lda arg ldx arg+1 </verb></tscreen> See: <tt><ref id=".DELMACRO" name=".DELMACRO"></tt>, <tt><ref id=".ENDMACRO" name=".ENDMACRO"></tt>, <tt><ref id=".EXITMACRO" name=".EXITMACRO"></tt> See also section <ref id="macros" name="Macros">. <sect1><tt>.ORG</tt><label id=".ORG"><p> Start a section of absolute code. The command is followed by a constant expression that gives the new PC counter location for which the code is assembled. Use <tt><ref id=".RELOC" name=".RELOC"></tt> to switch back to relocatable code. By default, absolute/relocatable mode is global (valid even when switching segments). Using <tt>.FEATURE <ref id="org_per_seg" name="org_per_seg"></tt> it can be made segment local. Please note that you <em/do not need/ <tt/.ORG/ in most cases. Placing code at a specific address is the job of the linker, not the assembler, so there is usually no reason to assemble code to a specific address. Example: <tscreen><verb> .org $7FF ; Emit code starting at $7FF </verb></tscreen> <sect1><tt>.OUT</tt><label id=".OUT"><p> Output a string to the console without producing an error. This command is similar to <tt/.ERROR/, however, it does not force an assembler error that prevents the creation of an object file. Example: <tscreen><verb> .out "This code was written by the codebuster(tm)" </verb></tscreen> See also: <tt><ref id=".ERROR" name=".ERROR"></tt>, <tt><ref id=".FATAL" name=".FATAL"></tt>, <tt><ref id=".WARNING" name=".WARNING"></tt> <sect1><tt>.P02</tt><label id=".P02"><p> Enable the 6502 instruction set, disable 65SC02, 65C02 and 65816 instructions. This is the default if not overridden by the <tt><ref id="option--cpu" name="--cpu"></tt> command line option. See: <tt><ref id=".PC02" name=".PC02"></tt>, <tt><ref id=".PSC02" name=".PSC02"></tt>, <tt><ref id=".P816" name=".P816"></tt> and <tt><ref id=".P4510" name=".P4510"></tt> <sect1><tt>.P4510</tt><label id=".P4510"><p> Enable the 4510 instruction set. This is a superset of the 65C02 and 6502 instruction sets. See: <tt><ref id=".P02" name=".P02"></tt>, <tt><ref id=".PSC02" name=".PSC02"></tt>, <tt><ref id=".PC02" name=".PC02"></tt> and <tt><ref id=".P816" name=".P816"></tt> <sect1><tt>.P816</tt><label id=".P816"><p> Enable the 65816 instruction set. This is a superset of the 65SC02 and 6502 instruction sets. See: <tt><ref id=".P02" name=".P02"></tt>, <tt><ref id=".PSC02" name=".PSC02"></tt>, <tt><ref id=".PC02" name=".PC02"></tt> and <tt><ref id=".P4510" name=".P4510"></tt> <sect1><tt>.PAGELEN, .PAGELENGTH</tt><label id=".PAGELENGTH"><p> Set the page length for the listing. Must be followed by an integer constant. The value may be "unlimited", or in the range 32 to 127. The statement has no effect if no listing is generated. The default value is -1 (unlimited) but may be overridden by the <tt/--pagelength/ command line option. Beware: Since ca65 is a one pass assembler, the listing is generated after assembly is complete, you cannot use multiple line lengths with one source. Instead, the value set with the last <tt/.PAGELENGTH/ is used. Examples: <tscreen><verb> .pagelength 66 ; Use 66 lines per listing page .pagelength unlimited ; Unlimited page length </verb></tscreen> <sect1><tt>.PC02</tt><label id=".PC02"><p> Enable the 65C02 instructions set. This instruction set includes all 6502 and 65SC02 instructions. See: <tt><ref id=".P02" name=".P02"></tt>, <tt><ref id=".PSC02" name=".PSC02"></tt>, <tt><ref id=".P816" name=".P816"></tt> and <tt><ref id=".P4510" name=".P4510"></tt> <sect1><tt>.POPCPU</tt><label id=".POPCPU"><p> Pop the last CPU setting from the stack, and activate it. This command will switch back to the CPU that was last pushed onto the CPU stack using the <tt><ref id=".PUSHCPU" name=".PUSHCPU"></tt> command, and remove this entry from the stack. The assembler will print an error message if the CPU stack is empty when this command is issued. See: <tt><ref id=".CPU" name=".CPU"></tt>, <tt><ref id=".PUSHCPU" name=".PUSHCPU"></tt>, <tt><ref id=".SETCPU" name=".SETCPU"></tt> <sect1><tt>.POPSEG</tt><label id=".POPSEG"><p> Pop the last pushed segment from the stack, and set it. This command will switch back to the segment that was last pushed onto the segment stack using the <tt><ref id=".PUSHSEG" name=".PUSHSEG"></tt> command, and remove this entry from the stack. The assembler will print an error message if the segment stack is empty when this command is issued. See: <tt><ref id=".PUSHSEG" name=".PUSHSEG"></tt> <sect1><tt>.PROC</tt><label id=".PROC"><p> Start a nested lexical level with the given name and adds a symbol with this name to the enclosing scope. All new symbols from now on are in the local lexical level and are accessible from outside only via <ref id="scopesyntax" name="explicit scope specification">. Symbols defined outside this local level may be accessed as long as their names are not used for new symbols inside the level. Symbols names in other lexical levels do not clash, so you may use the same names for identifiers. The lexical level ends when the <tt><ref id=".ENDPROC" name=".ENDPROC"></tt> command is read. Lexical levels may be nested up to a depth of 16 (this is an artificial limit to protect against errors in the source). Note: Macro names are always in the global level and in a separate name space. There is no special reason for this, it's just that I've never had any need for local macro definitions. Example: <tscreen><verb> .proc Clear ; Define Clear subroutine, start new level lda #$00 L1: sta Mem,y ; L1 is local and does not cause a ; duplicate symbol error if used in other ; places dey bne L1 ; Reference local symbol rts .endproc ; Leave lexical level </verb></tscreen> See: <tt/<ref id=".ENDPROC" name=".ENDPROC">/ and <tt/<ref id=".SCOPE" name=".SCOPE">/ <sect1><tt>.PSC02</tt><label id=".PSC02"><p> Enable the 65SC02 instructions set. This instruction set includes all 6502 instructions. See: <tt><ref id=".P02" name=".P02"></tt>, <tt><ref id=".PC02" name=".PC02"></tt>, <tt><ref id=".P816" name=".P816"></tt> and <tt><ref id=".P4510" name=".P4510"></tt> <sect1><tt>.PUSHCPU</tt><label id=".PUSHCPU"><p> Push the currently active CPU onto a stack. The stack has a size of 8 entries. <tt/.PUSHCPU/ allows together with <tt><ref id=".POPCPU" name=".POPCPU"></tt> to switch to another CPU and to restore the old CPU later, without knowledge of the current CPU setting. The assembler will print an error message if the CPU stack is already full, when this command is issued. See: <tt><ref id=".CPU" name=".CPU"></tt>, <tt><ref id=".POPCPU" name=".POPCPU"></tt>, <tt><ref id=".SETCPU" name=".SETCPU"></tt> <sect1><tt>.PUSHSEG</tt><label id=".PUSHSEG"><p> Push the currently active segment onto a stack. The entries on the stack include the name of the segment and the segment type. The stack has a size of 16 entries. <tt/.PUSHSEG/ allows together with <tt><ref id=".POPSEG" name=".POPSEG"></tt> to switch to another segment and to restore the old segment later, without even knowing the name and type of the current segment. The assembler will print an error message if the segment stack is already full, when this command is issued. See: <tt><ref id=".POPSEG" name=".POPSEG"></tt> <sect1><tt>.RELOC</tt><label id=".RELOC"><p> Switch back to relocatable mode. See the <tt><ref id=".ORG" name=".ORG"></tt> command. <sect1><tt>.REPEAT</tt><label id=".REPEAT"><p> Repeat all commands between <tt/.REPEAT/ and <tt><ref id=".ENDREPEAT" name=".ENDREPEAT"></tt> constant number of times. The command is followed by a constant expression that tells how many times the commands in the body should get repeated. Optionally, a comma and an identifier may be specified. If this identifier is found in the body of the repeat statement, it is replaced by the current repeat count (starting with zero for the first time the body is repeated). <tt/.REPEAT/ statements may be nested. If you use the same repeat count identifier for a nested <tt/.REPEAT/ statement, the one from the inner level will be used, not the one from the outer level. Example: The following macro will emit a string that is "encrypted" in that all characters of the string are XORed by the value $55. <tscreen><verb> .macro Crypt Arg .repeat .strlen(Arg), I .byte .strat(Arg, I) ^ $55 .endrep .endmacro </verb></tscreen> See: <tt><ref id=".ENDREPEAT" name=".ENDREPEAT"></tt> <sect1><tt>.RES</tt><label id=".RES"><p> Reserve storage. The command is followed by one or two constant expressions. The first one is mandatory and defines, how many bytes of storage should be defined. The second, optional expression must by a constant byte value that will be used as value of the data. If there is no fill value given, the linker will use the value defined in the linker configuration file (default: zero). Example: <tscreen><verb> ; Reserve 12 bytes of memory with value $AA .res 12, $AA </verb></tscreen> <sect1><tt>.RODATA</tt><label id=".RODATA"><p> Switch to the RODATA segment. The name of the RODATA segment is always "RODATA", so this is a shortcut for <tscreen><verb> .segment "RODATA" </verb></tscreen> The RODATA segment is a segment that is used by the compiler for readonly data like string constants. See also the <tt><ref id=".SEGMENT" name=".SEGMENT"></tt> command. <sect1><tt>.SCOPE</tt><label id=".SCOPE"><p> Start a nested lexical level with the given name. All new symbols from now on are in the local lexical level and are accessible from outside only via <ref id="scopesyntax" name="explicit scope specification">. Symbols defined outside this local level may be accessed as long as their names are not used for new symbols inside the level. Symbols names in other lexical levels do not clash, so you may use the same names for identifiers. The lexical level ends when the <tt><ref id=".ENDSCOPE" name=".ENDSCOPE"></tt> command is read. Lexical levels may be nested up to a depth of 16 (this is an artificial limit to protect against errors in the source). Note: Macro names are always in the global level and in a separate name space. There is no special reason for this, it's just that I've never had any need for local macro definitions. Example: <tscreen><verb> .scope Error ; Start new scope named Error None = 0 ; No error File = 1 ; File error Parse = 2 ; Parse error .endscope ; Close lexical level ... lda #Error::File ; Use symbol from scope Error </verb></tscreen> See: <tt/<ref id=".ENDSCOPE" name=".ENDSCOPE">/ and <tt/<ref id=".PROC" name=".PROC">/ <sect1><tt>.SEGMENT</tt><label id=".SEGMENT"><p> Switch to another segment. Code and data is always emitted into a 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 ("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 names that would also be valid identifiers). There may also be an optional address size separated by a colon. See the section covering <tt/<ref id="address-sizes" name="address sizes">/ for more information. The default address size for a segment depends on the memory model specified on the command line. The default is "absolute", which means that you don't have to use an address size modifier in most cases. "absolute" means that the is a segment with 16 bit (absolute) addressing. That is, the segment will reside somewhere in core memory outside the zero page. "zeropage" (8 bit) means that the segment will be placed in the zero page and direct (short) addressing is possible for data in this segment. Beware: Only labels in a segment with the zeropage attribute are marked as reachable by short addressing. The '*' (PC counter) operator will work as in other segments and will create absolute variable values. Please note that a segment cannot have two different address sizes. A segment specified as zeropage cannot be declared as being absolute later. Examples: <tscreen><verb> .segment "ROM2" ; Switch to ROM2 segment .segment "ZP2": zeropage ; New direct segment .segment "ZP2" ; Ok, will use last attribute .segment "ZP2": absolute ; Error, redecl mismatch </verb></tscreen> See: <tt><ref id=".BSS" name=".BSS"></tt>, <tt><ref id=".CODE" 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> <tt/.SET/ is used to assign a value to a variable. See <ref id="variables" name="Numeric variables"> for a full description. <sect1><tt>.SETCPU</tt><label id=".SETCPU"><p> Switch the CPU instruction set. The command is followed by a string that specifies the CPU. Possible values are those that can also be supplied to the <tt><ref id="option--cpu" name="--cpu"></tt> command line option, namely: 6502, 6502X, 65SC02, 65C02, 65816, 4510 and HuC6280. See: <tt><ref id=".CPU" name=".CPU"></tt>, <tt><ref id=".IFP02" name=".IFP02"></tt>, <tt><ref id=".IFP816" name=".IFP816"></tt>, <tt><ref id=".IFPC02" name=".IFPC02"></tt>, <tt><ref id=".IFPSC02" name=".IFPSC02"></tt>, <tt><ref id=".P02" name=".P02"></tt>, <tt><ref id=".P816" name=".P816"></tt>, <tt><ref id=".P4510" name=".P4510"></tt>, <tt><ref id=".PC02" name=".PC02"></tt>, <tt><ref id=".PSC02" name=".PSC02"></tt> <sect1><tt>.SMART</tt><label id=".SMART"><p> Switch on or off smart mode. The command must be followed by a '+' or '-' character to switch the option on or off respectively. The default is off (that is, the assembler doesn't try to be smart), but this default may be changed by the -s switch on the command line. In smart mode the assembler will do the following: <itemize> <item>Track usage of the <tt/REP/ and <tt/SEP/ instructions in 65816 mode and update the operand sizes accordingly. If the operand of such an instruction cannot be evaluated by the assembler (for example, because the operand is an imported symbol), a warning is issued. Beware: Since the assembler cannot trace the execution flow this may lead to false results in some cases. If in doubt, use the <tt/.Inn/ and <tt/.Ann/ instructions to tell the assembler about the current settings. <item>In 65816 mode, replace a <tt/RTS/ instruction by <tt/RTL/ if it is used within a procedure declared as <tt/far/, or if the procedure has no explicit address specification, but it is <tt/far/ because of the memory model used. </itemize> Example: <tscreen><verb> .smart ; Be smart .smart - ; Stop being smart </verb></tscreen> See: <tt><ref id=".A16" name=".A16"></tt>, <tt><ref id=".A8" name=".A8"></tt>, <tt><ref id=".I16" name=".I16"></tt>, <tt><ref id=".I8" name=".I8"></tt> <sect1><tt>.STRUCT</tt><label id=".STRUCT"><p> Starts a struct definition. Structs are covered in a separate section named <ref id="structs" name=""Structs and unions"">. See also: <tt><ref id=".ENDSTRUCT" name=".ENDSTRUCT"></tt>, <tt><ref id=".ENDUNION" name=".ENDUNION"></tt>, <tt><ref id=".UNION" name=".UNION"></tt> <sect1><tt>.TAG</tt><label id=".TAG"><p> Allocate space for a struct or union. Example: <tscreen><verb> .struct Point xcoord .word ycoord .word .endstruct .bss .tag Point ; Allocate 4 bytes </verb></tscreen> <sect1><tt>.UNDEF, .UNDEFINE</tt><label id=".UNDEFINE"><p> Delete a define style macro definition. The command is followed by an identifier which specifies the name of the macro to delete. Macro replacement is switched of when reading the token following the command (otherwise the macro name would be replaced by its replacement list). See also the <tt><ref id=".DEFINE" name=".DEFINE"></tt> command and section <ref id="macros" name="Macros">. <sect1><tt>.UNION</tt><label id=".UNION"><p> Starts a union definition. Unions are covered in a separate section named <ref id="structs" name=""Structs and unions"">. See also: <tt><ref id=".ENDSTRUCT" name=".ENDSTRUCT"></tt>, <tt><ref id=".ENDUNION" name=".ENDUNION"></tt>, <tt><ref id=".STRUCT" name=".STRUCT"></tt> <sect1><tt>.WARNING</tt><label id=".WARNING"><p> Force an assembly warning. The assembler will output a warning message preceded by "User warning". This warning will always be output, even if other warnings are disabled with the <tt><ref id="option-W" name="-W0"></tt> command line option. This command may be used to output possible problems when assembling the source file. Example: <tscreen><verb> .macro jne target .local L1 .ifndef target .warning "Forward jump in jne, cannot optimize!" beq L1 jmp target L1: .else ... .endif .endmacro </verb></tscreen> See also: <tt><ref id=".ERROR" name=".ERROR"></tt>, <tt><ref id=".FATAL" name=".FATAL"></tt>, <tt><ref id=".OUT" name=".OUT"></tt> <sect1><tt>.WORD</tt><label id=".WORD"><p> Define word sized data. Must be followed by a sequence of (word ranged, but not necessarily constant) expressions. Example: <tscreen><verb> .word $0D00, $AF13, _Clear </verb></tscreen> <sect1><tt>.ZEROPAGE</tt><label id=".ZEROPAGE"><p> Switch to the ZEROPAGE segment and mark it as direct (zeropage) segment. The name of the ZEROPAGE segment is always "ZEROPAGE", so this is a shortcut for <tscreen><verb> .segment "ZEROPAGE": zeropage </verb></tscreen> Because of the "zeropage" attribute, labels declared in this segment are addressed using direct addressing mode if possible. You <em/must/ instruct the linker to place this segment somewhere in the address range 0..$FF otherwise you will get errors. See: <tt><ref id=".SEGMENT" name=".SEGMENT"></tt> <sect>Macros<label id="macros"><p> <sect1>Introduction<p> Macros may be thought of as "parametrized super instructions". Macros are sequences of tokens that have a name. If that name is used in the source file, the macro is "expanded", that is, it is replaced by the tokens that were specified when the macro was defined. <sect1>Macros without parameters<p> 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 </verb></tscreen> The macro above consists of two real instructions, that are inserted into 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 </verb></tscreen> <sect1>Parametrized macros<p> When using macro parameters, macros can be even more useful: <tscreen><verb> .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 the name "addr" in the macro definition will be replaced by the given parameter. So <tscreen><verb> inc16 $1000 </verb></tscreen> will be expanded to <tscreen><verb> 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 are separated by commas. You are free to give less parameters than the macro actually takes in the definition. You may also leave intermediate parameters empty. Empty parameters are replaced by empty space (that is, they are removed when the macro is expanded). If you have a look at our macro definition above, you will see, that replacing the "addr" parameter by nothing will lead to wrong code in most lines. To help you, writing macros with a variable parameter list, there are some control commands: <tt><ref id=".IFBLANK" name=".IFBLANK"></tt> tests the rest of the line and returns true, if there are any tokens on the remainder of the line. Since empty parameters are replaced by nothing, this may be used to test if a given parameter is empty. <tt><ref id=".IFNBLANK" name=".IFNBLANK"></tt> tests the 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 </verb></tscreen> That macro may be called as follows: <tscreen><verb> ldaxy 1, 2, 3 ; Load all three registers ldaxy 1, , 3 ; Load only a and y 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>. 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 </verb></tscreen> Macro parameters may optionally be enclosed into curly braces. This allows the inclusion of tokens that would otherwise terminate the parameter (the comma in case of a macro parameter). <tscreen><verb> .macro foo arg1, arg2 ... .endmacro foo ($00,x) ; Two parameters passed foo {($00,x)} ; One parameter passed </verb></tscreen> In the first case, the macro is called with two parameters: '<tt/($00/' and '<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, '<tt/($00,x)/' is passed to the macro; this time, including the comma. <sect1>Detecting parameter types<p> Sometimes it is nice to write a macro that acts differently depending on the type of the argument supplied. An example would be a macro that loads a 16 bit value from either an immediate operand, or from memory. The <tt/<ref 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 </verb></tscreen> Using the <tt/<ref id=".MATCH" name=".MATCH">/ function, the macro is able to check if its argument begins with a hash mark. If so, two immediate loads are emitted, Otherwise a load from an absolute zero page memory location is assumed. Please note how the curly braces are used to enclose parameters to pseudo functions handling token lists. This is necessary, because the token lists may include commas or parens, which would be treated by the assembler 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 </verb></tscreen> <sect1>Recursive macros<p> Macros may be used recursively: <tscreen><verb> .macro push r1, r2, r3 lda r1 pha .ifnblank r2 push r2, r3 .endif .endmacro </verb></tscreen> 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 </verb></tscreen> 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 </verb></tscreen> <sect1>Local symbols inside macros<p> Now, with recursive macros, <tt><ref id=".IFBLANK" name=".IFBLANK"></tt> and <tt><ref id=".PARAMCOUNT" name=".PARAMCOUNT"></tt>, what else do you need? Have a look at the inc16 macro above. Here is it again: <tscreen><verb> .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 </verb></tscreen> But imagine what happens, if you use this macro twice? Since the label "Skip" has the same name both times, you get a "duplicate symbol" error. Without a way to circumvent this problem, macros are not as useful, as they could be. One possible solution is the command <tt><ref id=".LOCAL" name=".LOCAL"></tt>. It declares one or more symbols as local to the macro expansion. The names of 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 </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 </verb></tscreen> <sect1>C style macros<p> Starting with version 2.5 of the assembler, there is a second macro type available: C style macros using the <tt/.DEFINE/ directive. These macros are similar to the classic macro type described above, but behaviour is sometimes different: <itemize> <item> Macros defined with <tt><ref id=".DEFINE" name=".DEFINE"></tt> may not span more than a line. You may use line continuation (see <tt><ref id=".LINECONT" name=".LINECONT"></tt>) to spread the definition over more than one line for increased readability, but the macro itself may not contain an end-of-line token. <item> Macros defined with <tt><ref id=".DEFINE" name=".DEFINE"></tt> share the name space with classic macros, but they are detected and replaced at the scanner level. While classic macros may be used in every place, where a mnemonic or other directive is allowed, <tt><ref id=".DEFINE" name=".DEFINE"></tt> style macros are allowed anywhere in a line. So they are more versatile in some situations. <item> <tt><ref id=".DEFINE" name=".DEFINE"></tt> style macros may take parameters. While classic macros may have empty parameters, this is not true for <tt><ref id=".DEFINE" name=".DEFINE"></tt> style macros. For this macro type, the number of actual parameters must match exactly the number of formal parameters. To make this possible, formal parameters are enclosed in braces when defining the macro. If there are no parameters, the empty braces may 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 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. <item> Parentheses work differently from C macros. The common practice of wrapping C macros in parentheses may cause unintended problems here, such as accidentally implying an indirect addressing mode. While the definition of a macro requires parentheses around its argument list, when invoked they should not be included. </itemize> Let's look at a few examples to make the advantages and disadvantages clear. To emulate assemblers that use "<tt/EQU/" instead of "<tt/=/" you may use the following <tt/.DEFINE/: <tscreen><verb> .define EQU = 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" ; ... and use it .asciiz VERSION </verb></tscreen> Macros with parameters may also be useful: <tscreen><verb> .define DEBUG(message) .out message DEBUG "Assembling include file #3" </verb></tscreen> Note that, while formal parameters have to be placed in parentheses, the actual argument used when invoking the macro should not be. The invoked arguments are separated by commas only, if parentheses are used by accident they will become part of the replaced token. If you wish to have an expression follow the macro invocation, the last parameter can be enclosed in curly braces {} to indicate the end of that argument. Examples: <tscreen><verb> .define COMBINE(ta,tb,tc) ta+tb*10+tc*100 .word COMBINE 5,6,7 ; 5+6*10+7*100 = 765 .word COMBINE(5,6,7) ; (5+6*10+7)*100 = 7200 ; incorrect use of parentheses .word COMBINE 5,6,7+1 ; 5+6*10+7+1*100 = 172 .word COMBINE 5,6,{7}+1 ; 5+6*10+7*100+1 = 766 ; {} encloses the argument .word COMBINE 5,6-2,7 ; 5+6-2*10+7*100 = 691 .word COMBINE 5,(6-2),7 ; 5+(6-2)*10+7*100 = 745 .word COMBINE 5,6,7+COMBINE 0,1,2 ; 5+6*10+7+0+1*10+2*100*100 = 20082 .word COMBINE 5,6,{7}+COMBINE 0,1,2 ; 5+6*10+7*100+0+1*10+2*100 = 975 </verb></tscreen> With C macros it is common to enclose the results in parentheses to prevent unintended interactions with the text of the arguments, but additional care must be taken in this assembly context where parentheses may alter the meaning of a statement. In particular, indirect addressing modes may be accidentally implied: <tscreen><verb> .define DUO(ta,tb) (ta+(tb*10)) lda DUO(5,4), Y ; LDA (indirect), Y lda 0+DUO(5,4), Y ; LDA absolute indexed, Y </verb></tscreen> <sect1>Characters in macros<p> When using the <ref id="option-t" name="-t"> option, characters are translated into the target character set of the specific machine. However, this happens as late as possible. This means that strings are translated if they are part of a <tt><ref id=".BYTE" name=".BYTE"></tt> or <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt> command. Characters are translated as soon as they are used as part of an expression. This behaviour is very intuitive outside of macros but may be confusing when doing more complex macros. If you compare characters against numeric values, 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: <tscreen><verb> .macro notworking .delmacro notworking .endmacro notworking ; Will not work </verb></tscreen> The commands to delete classic and define style macros differ. Classic macros can be deleted by use of <tt><ref id=".DELMACRO" name=".DELMACRO"></tt>, while 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 .byte value ; Emit one byte with value 1 mac ; Emit another byte with value 2 .undefine value .delmacro mac .byte value ; Error: Unknown identifier mac ; Error: Missing ":" </verb></tscreen> A separate command for <tt>.DEFINE</tt> style macros was necessary, because the name of such a macro is replaced by its replacement list on a very low level. To get the actual name, macro replacement has to be switched off when reading the argument to <tt>.UNDEFINE</tt>. This does also mean that the argument to <tt>.UNDEFINE</tt> is not allowed to come from another <tt>.DEFINE</tt>. All this is not necessary for classic macros, so having two different commands increases flexibility. <sect>Macro packages<label id="macropackages"><p> Using the <tt><ref id=".MACPACK" name=".MACPACK"></tt> directive, predefined macro packages may be included with just one command. Available macro packages are: <sect1><tt>.MACPACK generic</tt><p> This macro package defines macroes that are useful in almost any program. Currently defined macroes are: <tscreen><verb> .macro add Arg ; add without carry clc adc Arg .endmacro .macro sub Arg ; subtract without borrow sec sbc Arg .endmacro .macro bge Arg ; branch on greater-than or equal bcs Arg .endmacro .macro blt Arg ; branch on less-than bcc Arg .endmacro .macro bgt Arg ; branch on greater-than .local L beq L bcs Arg L: .endmacro .macro ble Arg ; branch on less-than or equal beq Arg bcc Arg .endmacro .macro bnz Arg ; branch on not zero bne Arg .endmacro .macro bze Arg ; branch on zero beq Arg .endmacro </verb></tscreen> <sect1><tt>.MACPACK longbranch</tt><p> This macro package defines long conditional jumps. They are named like the short counterpart but with the 'b' replaced by a 'j'. Here is a sample definition for the "<tt/jeq/" macro, the other macros are built using the same scheme: <tscreen><verb> .macro jeq Target .if .def(Target) .and ((*+2)-(Target) <= 127) beq Target .else bne *+5 jmp Target .endif .endmacro </verb></tscreen> All macros expand to a short branch, if the label is already defined (back jump) and is reachable with a short jump. Otherwise the macro expands to a conditional branch with the branch condition inverted, followed by an absolute jump to the actual branch target. The package defines the following macros: <tscreen><verb> jeq, jne, jmi, jpl, jcs, jcc, jvs, jvc </verb></tscreen> <sect1><tt>.MACPACK apple2</tt><p> This macro package defines a macro named <tt/scrcode/. It takes a string as argument and places this string into memory translated into screen codes. <sect1><tt>.MACPACK atari</tt><p> This macro package defines a macro named <tt/scrcode/. It takes a string as argument and places this string into memory translated into screen codes. <sect1><tt>.MACPACK cbm</tt><p> This macro package defines a macro named <tt/scrcode/. It takes a string as argument and places this string into memory translated into screen codes. <sect1><tt>.MACPACK cpu</tt><p> This macro package does not define any macros but constants used to examine the value read from the <tt/<ref id=".CPU" name=".CPU">/ pseudo variable. For each supported CPU a constant similar to <tscreen><verb> CPU_6502 CPU_65SC02 CPU_65C02 CPU_65816 CPU_SWEET16 CPU_HUC6280 CPU_4510 </verb></tscreen> is defined. These constants may be used to determine the exact type of the currently enabled CPU. In addition to that, for each CPU instruction set, another constant is defined: <tscreen><verb> CPU_ISET_6502 CPU_ISET_65SC02 CPU_ISET_65C02 CPU_ISET_65816 CPU_ISET_SWEET16 CPU_ISET_HUC6280 CPU_ISET_4510 </verb></tscreen> The value read from the <tt/<ref id=".CPU" name=".CPU">/ pseudo variable may be checked with <tt/<ref id="operators" name=".BITAND">/ to determine if the currently enabled CPU supports a specific instruction set. For example the 65C02 supports all instructions of the 65SC02 CPU, so it has the <tt/CPU_ISET_65SC02/ bit set in addition to its native <tt/CPU_ISET_65C02/ bit. Using <tscreen><verb> .if (.cpu .bitand CPU_ISET_65SC02) lda (sp) .else ldy #$00 lda (sp),y .endif </verb></tscreen> it is possible to determine if the <tscreen><verb> lda (sp) </verb></tscreen> 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 identifier as argument and is used to define the header of a module both in the dynamic and static variant. <sect>Predefined constants<label id="predefined-constants"><p> For better orthogonality, the assembler defines similar symbols as the compiler, depending on the target system selected: <itemize> <item><tt/__APPLE2__/ - Target system is <tt/apple2/ or <tt/apple2enh/ <item><tt/__APPLE2ENH__/ - Target system is <tt/apple2enh/ <item><tt/__ATARI2600__/ - Target system is <tt/atari2600/ <item><tt/__ATARI5200__/ - Target system is <tt/atari5200/ <item><tt/__ATARI__/ - Target system is <tt/atari/ or <tt/atarixl/ <item><tt/__ATARIXL__/ - Target system is <tt/atarixl/ <item><tt/__ATMOS__/ - Target system is <tt/atmos/ <item><tt/__BBC__/ - Target system is <tt/bbc/ <item><tt/__C128__/ - Target system is <tt/c128/ <item><tt/__C16__/ - Target system is <tt/c16/ or <tt/plus4/ <item><tt/__C64__/ - Target system is <tt/c64/ <item><tt/__CBM__/ - Target is a Commodore system <item><tt/__CBM510__/ - Target system is <tt/cbm510/ <item><tt/__CBM610__/ - Target system is <tt/cbm610/ <item><tt/__GEOS__/ - Target is a GEOS system <item><tt/__GEOS_APPLE__/ - Target system is <tt/geos-apple/ <item><tt/__GEOS_CBM__/ - Target system is <tt/geos-cbm/ <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/ <item><tt/__SIM65C02__/ - Target system is <tt/sim65c02/ <item><tt/__SUPERVISION__/ - Target system is <tt/supervision/ <item><tt/__VIC20__/ - Target system is <tt/vic20/ </itemize> <sect>Structs and unions<label id="structs"><p> <sect1>Structs and unions Overview<p> Structs and unions are special forms of <ref id="scopes" name="scopes">. They are to some degree comparable to their C counterparts. Both have a list of members. Each member allocates storage and may optionally have a name, which, in case of a struct, is the offset from the beginning and, in case of a union, is always zero. <sect1>Declaration<p> Here is an example for a very simple struct with two members and a total size of 4 bytes: <tscreen><verb> .struct Point xcoord .word ycoord .word .endstruct </verb></tscreen> A union shares the total space between all its members, its size is the same as that of the largest member. The offset of all members relative to the union is zero. <tscreen><verb> .union Entry index .word ptr .addr .endunion </verb></tscreen> A struct or union must not necessarily have a name. If it is anonymous, no local scope is opened, the identifiers used to name the members are placed into the current scope instead. A struct may contain unnamed members and definitions of local structs. The storage allocators may contain a multiplier, as in the example below: <tscreen><verb> .struct Circle .struct Point .word 2 ; Allocate two words .endstruct Radius .word .endstruct </verb></tscreen> <sect1>The <tt/.TAG/ keyword<p> Using the <ref id=".TAG" name=".TAG"> keyword, it is possible to reserve space for an already defined struct or unions within another struct: <tscreen><verb> .struct Point xcoord .word ycoord .word .endstruct .struct Circle Origin .tag Point Radius .byte .endstruct </verb></tscreen> Space for a struct or union may be allocated using the <ref id=".TAG" name=".TAG"> directive. <tscreen><verb> C: .tag Circle </verb></tscreen> Currently, members are just offsets from the start of the struct or union. To access a field of a struct, the member offset has to be added to the address of the struct itself: <tscreen><verb> lda C+Circle::Radius ; Load circle radius into A </verb></tscreen> This may change in a future version of the assembler. <sect1>Limitations<p> Structs and unions are currently implemented as nested symbol tables (in fact, they were a by-product of the improved scoping rules). Currently, the assembler has no idea of types. This means that the <ref id=".TAG" name=".TAG"> keyword will only allocate space. You won't be able to initialize variables declared with <ref id=".TAG" name=".TAG">, and adding an embedded structure to another structure with <ref id=".TAG" name=".TAG"> will not make this structure accessible by using the '::' operator. <sect>Module constructors/destructors<label id="condes"><p> <em>Note:</em> This section applies mostly to C programs, so the explanation below uses examples from the C libraries. However, the feature may also be useful for assembler programs. <sect1>Module constructors/destructors Overview<p> Using the <tt><ref id=".CONSTRUCTOR" name=".CONSTRUCTOR"></tt>, <tt><ref id=".DESTRUCTOR" name=".DESTRUCTOR"></tt> and <tt><ref id=".INTERRUPTOR" name=".INTERRUPTOR"></tt> keywords it is possible to export functions in a special way. The linker is able to generate tables with all functions of a specific type. Such a table will <em>only</em> include symbols from object files that are linked into a specific executable. This may be used to add initialization and cleanup code for library modules, or a table of interrupt handler functions. The C heap functions are an example where module initialization code is used. All heap functions (<tt>malloc</tt>, <tt>free</tt>, ...) work with a few variables that contain the start and the end of the heap, pointers to the free list and so on. Since the end of the heap depends on the size and start of the stack, it must be initialized at runtime. However, initializing these variables for programs that do not use the heap are a waste of time and memory. So the central module defines a function that contains initialization code and exports this function using the <tt/.CONSTRUCTOR/ statement. If (and only if) this module is added to an executable by the linker, the initialization function will be placed into the table of constructors by the linker. The C startup code will call all constructors before <tt/main/ and all destructors after <tt/main/, so without any further work, the heap initialization code is called once the module is linked in. While it would be possible to add explicit calls to initialization functions in the startup code, the new approach has several advantages: <enum> <item> If a module is not included, the initialization code is not linked in and not called. So you don't pay for things you don't need. <item> Adding another library that needs initialization does not mean that the startup code has to be changed. Before we had module constructors and destructors, the startup code for all systems had to be adjusted to call the new initialization code. <item> The feature saves memory: Each additional initialization function needs just two bytes in the table (a pointer to the function). </enum> <sect1>Calling order<p> The symbols are sorted in increasing priority order by the linker when using one of the builtin linker configurations, so the functions with lower priorities come first and are followed by those with higher priorities. The C library runtime subroutine that walks over the function tables calls the functions starting from the top of the table - which means that functions with a high priority are called first. So when using the C runtime, functions are called with high priority functions first, followed by low priority functions. <sect1>Pitfalls<p> When using these special symbols, please take care of the following: <itemize> <item> The linker will only generate function tables, it will not generate code to call these functions. If you're using the feature in some other than the existing C environments, you have to write code to call all functions in a linker generated table yourself. See the <tt/condes/ and <tt/callirq/ modules in the C runtime for an example on how to do this. <item> The linker will only add addresses of functions that are in modules linked to the executable. This means that you have to be careful where to place the condes functions. If initialization or an irq handler is needed for a group of functions, be sure to place the function into a module that is linked in regardless of which function is called by the user. <item> The linker will generate the tables only when requested to do so by the <tt/FEATURE CONDES/ statement in the linker config file. Each table has to be requested separately. <item> Constructors and destructors may have priorities. These priorities determine the order of the functions in the table. If your initialization or cleanup code does depend on other initialization or cleanup code, you have to choose the priority for the functions accordingly. <item> Besides the <tt><ref id=".CONSTRUCTOR" name=".CONSTRUCTOR"></tt>, <tt><ref id=".DESTRUCTOR" name=".DESTRUCTOR"></tt> and <tt><ref id=".INTERRUPTOR" name=".INTERRUPTOR"></tt> statements, there is also a more generic command: <tt><ref id=".CONDES" name=".CONDES"></tt>. This allows to specify an additional type. Predefined types are 0 (constructor), 1 (destructor) and 2 (interruptor). The linker generates a separate table for each type on request. </itemize> <sect>Porting sources from other assemblers<p> Sometimes it is necessary to port code written for older assemblers to ca65. In some cases, this can be done without any changes to the source code by using the emulation features of ca65 (see <tt><ref id=".FEATURE" name=".FEATURE"></tt>). In other cases, it is necessary to make changes to the source code. Probably the biggest difference is the handling of the <tt><ref id=".ORG" name=".ORG"></tt> directive. ca65 generates relocatable code, and placement is done by the linker. Most other assemblers generate absolute code, placement is done within the assembler and there is no external linker. In general it is not a good idea to write new code using the emulation features of the assembler, but there may be situations where even this rule is not valid. <sect1>TASS<p> You need to use some of the ca65 emulation features to simulate the behaviour of such simple assemblers. <enum> <item>Prepare your sourcecode like this: <tscreen><verb> ; if you want TASS style labels without colons .feature labels_without_colons ; if you want TASS style character constants ; ("a" instead of the default 'a') .feature loose_char_term .word *+2 ; the cbm load address [yourcode here] </verb></tscreen> notice that the two emulation features are mostly useful for porting sources originally written in/for TASS, they are not needed for the actual "simple assembler operation" and are not recommended if you are writing new code from scratch. <item>Replace all program counter assignments (which are not possible in ca65 by default, and the respective emulation feature works different from what you'd expect) by another way to skip to memory locations, for example the <tt><ref id=".RES" name=".RES"></tt> directive. <tscreen><verb> ; *=$2000 .res $2000-* ; reserve memory up to $2000 </verb></tscreen> Please note that other than the original TASS, ca65 can never move the program counter backwards - think of it as if you are assembling to disk with TASS. <item>Conditional assembly (<tt/.ifeq//<tt/.endif//<tt/.goto/ etc.) must be rewritten to match ca65 syntax. Most importantly notice that due to the lack of <tt/.goto/, everything involving loops must be replaced by <tt><ref id=".REPEAT" name=".REPEAT"></tt>. <item>To assemble code to a different address than it is executed at, use the <tt><ref id=".ORG" name=".ORG"></tt> directive instead of <tt/.offs/-constructs. <tscreen><verb> .org $1800 [floppy code here] .reloc ; back to normal </verb></tscreen> <item>Then assemble like this: <tscreen><verb> cl65 --start-addr 0x0ffe -t none myprog.s -o myprog.prg </verb></tscreen> Note that you need to use the actual start address minus two, since two bytes are used for the cbm load address. </enum> <sect>Copyright<p> ca65 (and all cc65 binutils) are (C) Copyright 1998-2003 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> cc65-2.18/doc/cbm510.sgml���������������������������������������������������������������������������0000664�0000000�0000000�00000025142�13473601511�0014631�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>Commodore 510 (aka P500) specific information for cc65 <author> <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"> <abstract> An overview over the Commodore 510 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 CBM 510 runtime system as it comes with the cc65 C compiler. It describes the memory layout, CBM 510-specific header files, available drivers, and any pitfalls specific to that platform. Please note that CBM 510-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. In addition to the Commodore 510 (named P128 in the U.S.), no other machines are supported by this cc65 target. <sect>Binary format<p> The standard binary output format generated by the linker for the Commodore 510 target is a machine language program with a one-line BASIC stub, which transfers control to the machine language running in bank 0. That means that a program can be loaded as a BASIC program, and started with RUN. It is, of course, possible to change that behaviour by using a modified startup file and linker config. <sect>Memory layout<p> cc65 generated programs for the Commodore 510 run in bank 0, the memory bank reserved for BASIC programs. Since there are no ROMs in this memory bank, kernal subroutines are either emulated or called by bank switching, which has the disadvantage of being slow compared to a direct call. The default memory configuration for the CBM 510 allocates all memory between $0002 and $FFF0 in bank 0 for the compiled program. Some space in low memory is lost, because a separate hardware stack is set up in page 1, and the kernal replacement functions need some more memory locations. A few more pages are lost in high memory, because the runtime sets up a copy of the character ROM, a text screen, and a CBM-compatible jump table at $FF81. The main startup code is located at $0400, so about 54K of the complete bank are actually usable for applications. Special locations: <descrip> <tag/Stack/ The C runtime stack is located at $FEC2, and grows downwards. <tag/Heap/ The C heap is located at the end of the program, and grows towards the C runtime stack. </descrip><p> <sect>Platform-specific header files<p> Programs containing CBM 510-specific code may use the <tt/cbm510.h/ or <tt/cbm.h/ header files. Using the later may be an option when writing code for more than one CBM platform, since it includes <tt/cbm510.h/, and declares several functions common to all CBM platforms. <sect1>CBM 510-specific functions<p> The functions listed below are special for the CBM 510. See the <url url="funcref.html" name="function reference"> for declaration and usage. <itemize> <item>peekbsys <item>peekwsys <item>pokebsys <item>pokewsys </itemize> <sect1>CBM-specific functions<p> Some functions are available for all (or at least most) of the Commodore machines. See the <url url="funcref.html" name="function reference"> for declaration and usage. <itemize> <item>cbm_close <item>cbm_closedir <item>cbm_k_setlfs <item>cbm_k_setnam <item>cbm_k_load <item>cbm_k_save <item>cbm_k_open <item>cbm_k_close <item>cbm_k_readst <item>cbm_k_chkin <item>cbm_k_ckout <item>cbm_k_basin <item>cbm_k_bsout <item>cbm_k_clrch <item>cbm_k_tksa <item>cbm_k_second <item>cbm_load <item>cbm_open <item>cbm_opendir <item>cbm_read <item>cbm_readdir <item>cbm_save <item>cbm_write <item>get_tv </itemize> <sect1>Hardware access<p> The following pseudo variables declared in the <tt/cbm510.h/ header file do allow access to hardware located in the address space. Some variables are structures; accessing the struct fields will access the chip registers. <em/Note:/ All I/O chips are located in the system bank (bank 15); and can therefore not be accessed like on other platforms. Please use one of the <tt/peekbsys/, <tt/peekwsys/, <tt/pokebsys/, and <tt/pokewsys/ functions to access the I/O chips. Direct reads and writes to the structures named below will <em>not</em> work! <descrip> <tag><tt/VIC/</tag> The <tt/VIC/ structure allows access to the VIC II (the graphics controller). See the <tt/_vic2.h/ header file located in the include directory for the declaration of the structure. <tag><tt/SID/</tag> The <tt/SID/ structure allows access to the SID (the sound interface device). See the <tt/_sid.h/ header file located in the include directory for the declaration of the structure. <tag><tt/ACIA/</tag> Access to the ACIA (the RS232 chip) is available via the <tt/ACIA/ variable. See the <tt/_6551.h/ header file located in the include directory for the declaration of the structure. <tag><tt/CIA/</tag> Access to the CIA chip is available via the <tt/CIA/ variable. See the <tt/_6526.h/ header file located in the include directory for the declaration of the structure. <tag><tt/TPI1, TPI2/</tag> The two 6525 triport chips may be accessed by using these variables. See the <tt/_6525.h/ header file located in the include directory for the declaration of the structure. </descrip><p> <sect>Loadable drivers<p> The names in the parentheses denote the symbols to be used for static linking of the drivers. <sect1>Graphics drivers<p> No graphics drivers are currently available for the Commodore 510. <sect1>Extended memory drivers<p> <descrip> <tag><tt/cbm510-ram.emd (cbm510_ram_emd)/</tag> A driver for the RAM in bank 1. Supports up to 255 pages with 256 bytes each. </descrip><p> <sect1>Joystick drivers<p> <descrip> <tag><tt/cbm510-std.joy (cbm510_std_joy)/</tag> Supports up to two standard joysticks connected to the joysticks ports of the Commodore 510. </descrip><p> <sect1>Mouse drivers<p> The default drivers, <tt/mouse_stddrv (mouse_static_stddrv)/, point to <tt/cbm510-joy.mou (cbm510_joy_mou)/. <descrip> <tag><tt/cbm510-joy.mou (cbm510_joy_mou)/</tag> Supports a mouse that is emulated by a standard joystick, e.g. 1350 mouse, in joystick port #2 of the CBM510. That stick's fire button acts as the left mouse button. The fire button of a stick in joystick port #1 can act as the right mouse button. <tag><tt/cbm510-inkwl.mou (cbm510_inkwl_mou)/</tag> Supports the Inkwell Systems lightpens, connected to port #1 of the CBM510. It can read both the 170-C and one button of the 184-C pens. (It can read other lightpens and light-guns that send their button signal to the joystick left-button pin.) </descrip><p> <sect1>RS232 device drivers<p> <descrip> <tag><tt/cbm510-std.ser (cbm510_std_ser)/</tag> Driver for the 6551 ACIA chip built into the Commodore 510. Supports up to 19200 BPS, hardware flow control (RTS/CTS), and interrupt-driven receives. Note that, because of the peculiarities of the 6551 chip, transmits are not interrupt driven; and, the transceiver blocks if the receiver asserts flow control because of a full buffer. </descrip><p> <sect>Limitations<label id="limitations"><p> <sect1>Realtime clock<p> The realtime clock functions use the CIA2 TOD clock. As that clock only stores the time but not the date, the date set by <tt/clock_settime()/ is simply stored inside the C library for retrieval in the same program via <tt/clock_gettime()/. <sect1>Kernal and hardware access<p> Since the program runs in bank 0, and the kernal and all I/O chips are located in bank 15, calling ROM routines or accessing hardware needs special code. The cc65 runtime implements wrappers for all functions in the kernal jump table. While this simplifies things, it should be noted that the wrappers do have quite an impact on performance: A cross-bank call has an extra 300µs penalty added by the wrapper. <sect1>Interrupts<p> Compiled programs contain an interrupt handler that runs in the program bank. This has several advantages, one of them being performance (see cross-bank call overhead mentioned above). However, this introduces one problem: Interrupts are lost while the CPU executes code in the kernal bank. As a result, the clock may go wrong; and (worse), serial interrupts may get lost. Since the cc65 runtime does only call the kernal for disk I/O, this means that a program should not do file I/O while it depends on interrupts. <sect>Other hints<p> <sect1>Passing arguments to the program<p> Command-line arguments can be passed to <tt/main()/. Since that is not supported directly by BASIC, the following syntax was chosen: <tscreen><verb> RUN:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5 </verb></tscreen> <enum> <item>Arguments are separated by spaces. <item>Arguments may be quoted. <item>Leading and trailing spaces around an argument are ignored. Spaces within a quoted argument are allowed. <item>The first argument passed to <tt/main()/ is the program name. <item>A maximum number of 10 arguments (including the program name) are supported. </enum> <sect1>Program return code<p> The program return code (signed char) is passed back to BASIC by use of the <tt/ST/ variable. <sect1>Interrupt handlers<p> The runtime for the Commodore 510 uses routines marked as <tt/.INTERRUPTOR/ for interrupt handlers. Such routines must be written as simple machine language subroutines and will be called automatically by the interrupt handler code when they are linked into a program. See the discussion of the <tt/.CONDES/ feature in the <url url="ca65.html" name="assembler manual">. <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> ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/cbm610.sgml���������������������������������������������������������������������������0000664�0000000�0000000�00000024053�13473601511�0014632�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>Commodore 610-specific information for cc65 <author> <url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline> <url url="mailto:greg.king5@verizon.net" name="Greg King"> <abstract> An overview over the Commodore 610 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 CBM 610 runtime system as it comes with the cc65 C compiler. It describes the memory layout, CBM 610-specific header files, available drivers, and any pitfalls specific to that platform. Please note that CBM 610-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. In addition to the Commodore 610 (named B40 in the U.S.), several other machines are supported by this cc65 target, since they have identical hardware: The Commodore 620 and 630 (more memory, additional coprocessor card), and the Commodore 710, 720, and 730 (same hardware in another case with a built-in monitor). <sect>Binary format<p> The standard binary output format generated by the linker for the Commodore 610 target is a machine language program with a one-line BASIC stub, which transfers control to the machine language running in bank 1. That means that a program can be loaded as a BASIC program, and started with RUN. It is, of course, possible to change that behaviour by using a modified startup file and linker config. <sect>Memory layout<p> cc65 generated programs for the Commodore 610 run in bank 1, the memory bank reserved for BASIC programs. Since there are no ROMs in this memory bank, kernal subroutines are either emulated or called by bank switching, which has the disadvantage of being slow compared to a direct call. The default memory configuration for the CBM 610 allocates all memory between $0002 and $FFF0 in bank 1 for the compiled program. Some space in low memory is lost, because a separate hardware stack is set up in page 1, and the kernal replacement functions need some more memory locations. A few more bytes are lost in high memory, because the runtime sets up a CBM-compatible jump table at $FF81. The main startup code is located at $0400, so about 63K of the complete bank are actually usable for applications. Special locations: <descrip> <tag/Stack/ The C runtime stack is located at $FF81, and grows downwards. <tag/Heap/ The C heap is located at the end of the program, and grows towards the C runtime stack. </descrip><p> <sect>Platform-specific header files<p> Programs containing CBM 610-specific code may use the <tt/cbm610.h/ or <tt/cbm.h/ header files. Using the later may be an option when writing code for more than one CBM platform, since it includes <tt/cbm610.h/, and declares several functions common to all CBM platforms. <sect1>CBM 610-specific functions<p> The functions listed below are special for the CBM 610. See the <url url="funcref.html" name="function reference"> for declaration and usage. <itemize> <item>peekbsys <item>peekwsys <item>pokebsys <item>pokewsys </itemize> <sect1>CBM-specific functions<p> Some functions are available for all (or at least most) of the Commodore machines. See the <url url="funcref.html" name="function reference"> for declaration and usage. <itemize> <item>cbm_close <item>cbm_closedir <item>cbm_k_setlfs <item>cbm_k_setnam <item>cbm_k_load <item>cbm_k_save <item>cbm_k_open <item>cbm_k_close <item>cbm_k_readst <item>cbm_k_chkin <item>cbm_k_ckout <item>cbm_k_basin <item>cbm_k_bsout <item>cbm_k_clrch <item>cbm_k_tksa <item>cbm_k_second <item>cbm_load <item>cbm_open <item>cbm_opendir <item>cbm_read <item>cbm_readdir <item>cbm_save <item>cbm_write <item>get_tv </itemize> <sect1>Hardware access<p> The following pseudo variables declared in the <tt/cbm610.h/ header file do allow access to hardware located in the address space. Some variables are structures; accessing the struct fields will access the chip registers. <em/Note:/ All I/O chips are located in the system bank (bank 15); and can therefore not be accessed like on other platforms. Please use one of the <tt/peekbsys/, <tt/peekwsys/, <tt/pokebsys/, and <tt/pokewsys/ functions to access the I/O chips. Direct reads and writes to the structures named below will <em>not</em> work! <descrip> <tag><tt/CRTC/</tag> The <tt/CRTC/ structure allows access to the CRTC (the video controller). See the <tt/_6545.h/ header file located in the include directory for the declaration of the structure. <tag><tt/SID/</tag> The <tt/SID/ structure allows access to the SID (the sound interface device). See the <tt/_sid.h/ header file located in the include directory for the declaration of the structure. <tag><tt/ACIA/</tag> Access to the ACIA (the RS232 chip) is available via the <tt/ACIA/ variable. See the <tt/_6551.h/ header file located in the include directory for the declaration of the structure. <tag><tt/CIA/</tag> Access to the CIA chip is available via the <tt/CIA/ variable. See the <tt/_6526.h/ header file located in the include directory for the declaration of the structure. <tag><tt/TPI1, TPI2/</tag> The two 6525 triport chips may be accessed by using these variables. See the <tt/_6525.h/ header file located in the include directory for the declaration of the structure. </descrip><p> <sect>Loadable drivers<p> The names in the parentheses denote the symbols to be used for static linking of the drivers. <sect1>Graphics drivers<p> No graphics drivers are currently available for the Commodore 610 (and since the machine has no graphics capabilities, chances for a graphics driver aren't really good :-). <sect1>Extended memory drivers<p> <descrip> <tag><tt/cbm610-ram.emd (cbm610_ram_emd)/</tag> A driver for the RAM in bank 2. Supports up to 255 pages with 256 bytes each. </descrip><p> <sect1>Joystick drivers<p> The Commodore 610 is a business machine, and doesn't have joystick ports. There are no drivers for the non-existing ports available. <sect1>Mouse drivers<p> No mouse drivers are currently available for the Commodore 610. <sect1>RS232 device drivers<p> <descrip> <tag><tt/cbm610-std.ser (cbm610_std_ser)/</tag> Driver for the 6551 ACIA chip built into the Commodore 610. Supports up to 19200 BPS, hardware flow control (RTS/CTS), and interrupt-driven receives. Note that, because of the peculiarities of the 6551 chip, transmits are not interrupt driven; and, the transceiver blocks if the receiver asserts flow control because of a full buffer. </descrip><p> <sect>Limitations<label id="limitations"><p> <sect1>Realtime clock<p> The realtime clock functions use the CIA1 TOD clock. As that clock only stores the time but not the date, the date set by <tt/clock_settime()/ is simply stored inside the C library for retrieval in the same program via <tt/clock_gettime()/. <sect1>Kernal and hardware access<p> Since the program runs in bank 1, and the kernal and all I/O chips are located in bank 15, calling ROM routines or accessing hardware needs special code. The cc65 runtime implements wrappers for all functions in the kernal jump table. While this simplifies things, it should be noted that the wrappers do have quite an impact on performance: A cross-bank call has an extra 300µs penalty added by the wrapper. <sect1>Interrupts<p> Compiled programs contain an interrupt handler that runs in the program bank. This has several advantages, one of them being performance (see cross-bank call overhead mentioned above). However, this introduces one problem: Interrupts are lost while the CPU executes code in the kernal bank. As a result, the clock may go wrong; and (worse), serial interrupts may get lost. Since the cc65 runtime does only call the kernal for disk I/O, this means that a program should not do file I/O while it depends on interrupts. <sect>Other hints<p> <sect1>Passing arguments to the program<p> Command-line arguments can be passed to <tt/main()/. Since that is not supported directly by BASIC, the following syntax was chosen: <tscreen><verb> RUN:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5 </verb></tscreen> <enum> <item>Arguments are separated by spaces. <item>Arguments may be quoted. <item>Leading and trailing spaces around an argument are ignored. Spaces within a quoted argument are allowed. <item>The first argument passed to <tt/main()/ is the program name. <item>A maximum number of 10 arguments (including the program name) are supported. </enum> <sect1>Program return code<p> The program return code (low byte) is passed back to BASIC by use of the <tt/ST/ variable. <sect1>Interrupt handlers<p> The runtime for the Commodore 610 uses routines marked as <tt/.INTERRUPTOR/ for interrupt handlers. Such routines must be written as simple machine language subroutines and will be called automatically by the interrupt handler code when they are linked into a program. See the discussion of the <tt/.CONDES/ feature in the <url url="ca65.html" name="assembler manual">. <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> �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/cc65-intern.sgml����������������������������������������������������������������������0000664�0000000�0000000�00000011713�13473601511�0015676�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>cc65 internals <author><url url="mailto:bbbradsmith@users.noreply.github.com" name="Brad Smith"> <abstract> Internal details of cc65 code generation, such as calling assembly functions from C. </abstract> <!-- Table of contents --> <toc> <!-- Begin the document --> <sect>Calling assembly functions from C<p> <sect1>Calling conventions<p> There are two calling conventions used in cc65: <itemize> <item><tt/cdecl/ - passes all parameters on the C-stack. <p> <item><tt/fastcall/ - passes the rightmost parameter in registers <tt>A/X/sreg</tt> and all others on the C-stack. <p> </itemize> The default convention is <tt/fastcall/, but this can be changed with the <tt/--all-cdecl/ command line option. If a convention is specified in the function's declaration, that convention will be used instead. Variadic functions will always use <tt/cdecl/ convention. If the <tt/--standard/ command line option is used, the <tt/cdecl/ and <tt/fastcall/ keywords will not be available. The standard compliant variations <tt/__cdecl__/ and <tt/__fastcall__/ are always available. If a function has a prototype, parameters are pushed to the C-stack as their respective types (i.e. a <tt/char/ parameter will push 1 byte), but if a function has no prototype, default promotions will apply. This means that with no prototype, <tt/char/ will be promoted to <tt/int/ and be pushed as 2 bytes. K & R style function prototypes may be used, but they will function the same as if no prototype was used. <sect1>Prologue, before the function call<p> If the function is declared as fastcall, the rightmost argument will be loaded into the <tt>A/X/sreg</tt> registers: <itemize> <item><tt/A/ - 8-bit parameter, or low byte of larger types<p> <item><tt/X/ - 16-bit high byte, or second byte of 32-bits<p> <item><tt/sreg/ - Zeropage pseudo-register including high 2 bytes of 32-bit parameter<p> </itemize> All other parameters will be pushed to the C-stack from left to right. The rightmost parameter will have the lowest address on the stack, and multi-byte parameters will have their least significant byte at the lower address. The <tt/sp/ pseudo-register is a zeropage pointer to the base of the C-stack. If the function has no prototype or is variadic the <tt/Y/ register will contain the number of bytes pushed to the stack for this function. Example: <tscreen><verb> // C prototype void cdecl foo(unsigned bar, unsigned char baz); ; C-stack layout within the function: ; ; +------------------+ ; | High byte of bar | ; Offset 2 ->+------------------+ ; | Low byte of bar | ; Offset 1 ->+------------------+ ; | baz | ; Offset 0 ->+------------------+ ; Example code for accessing bar. The variable is in A/X after this code snippet: ; ldy #2 ; Offset of high byte of bar lda (sp),y ; High byte now in A tax ; High byte now in X dey ; Offset of low byte of bar lda (sp),y ; Low byte now in A </verb></tscreen> <sect1>Epilogue, after the function call<p> <sect2>Return requirements<p> If the function has a return value, it will appear in the <tt>A/X/sreg</tt> registers. Functions with an 8-bit return value (<tt/char/ or <tt/unsigned char/) are expected to promote this value to a 16-bit integer on return, and store the high byte in <tt/X/. The compiler will depend on the promoted value in some cases (e.g. implicit conversion to <tt/int/), and failure to return the high byte in <tt/X/ will cause unexpected errors. This problem does not apply to the <tt/sreg/ pseudo-register, which is only used if the return type is 32-bit. If the function has a void return type, the compiler will not depend on the result of <tt>A/X/sreg</tt>, so these may be clobbered by the function. The C-stack pointer <tt/sp/ must be restored by the function to its value before the function call prologue. It may pop all of its parameters from the C-stack (e.g. using the <tt/runtime/ function <tt/popa/), or it could adjust <tt/sp/ directly. If the function has no prototype, or is variadic the <tt/Y/ register contains the number of bytes pushed to the stack on entry, which may be added to <tt/sp/ to restore its original state. The internal pseudo-register <tt/regbank/ must not be changed by the function. <sect2>Clobbered state<p> The <tt/Y/ register may be clobbered by the function. The compiler will not depend on its state after a function call. The <tt>A/X/sreg</tt> registers may be clobbered if any of them are not used by the return value (see above). Many of the internal pseudo-registers used by cc65 are available for free use by any function called by C, and do not need to be preserved. Note that if another C function is called from your assembly function, it may clobber any of these itself: <itemize> <item><tt>tmp1 .. tmp4</tt><p> <item><tt>ptr1 .. ptr4</tt><p> <item><tt>regsave</tt><p> <item><tt>sreg</tt> (if unused by return)<p> </itemize> </article> �����������������������������������������������������cc65-2.18/doc/cc65.sgml�����������������������������������������������������������������������������0000664�0000000�0000000�00000170277�13473601511�0014414�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>cc65 Users Guide <author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline> <url url="mailto:gregdk@users.sf.net" name="Greg King"> <abstract> cc65 is a C compiler for 6502 targets. It supports several 6502 based home computers like the Commodore and Atari machines, but it is easily retargetable. </abstract> <!-- Table of contents --> <toc> <!-- Begin the document --> <sect>Overview<p> cc65 was originally a C compiler for the Atari 8-bit machines written by John R. Dunning. In prior releases I've described the compiler by listing up the changes made by me. I have made many more changes in the meantime (and rewritten major parts of the compiler), so I will no longer do that, since the list would be too large and of no use to anyone. Instead I will describe the compiler in respect to the ANSI/ISO C standard. There are separate documents named <url url="library.html"> and <url url="funcref.html"> that cover the library that is available for the compiler. If you know C, and are interested in doing actual programming, the library documentation is probably of much more use than this document. If you need some hints for getting the best code out of the compiler, you may have a look at <url url="coding.html"> which covers some code generation issues. <sect>Usage<p> The compiler translates C files into files containing assembly code that may be translated by the ca65 macroassembler (for more information about the assembler, have a look at <url url="ca65.html">). <sect1>Command line option overview<p> The compiler may be called as follows: <tscreen><verb> --------------------------------------------------------------------------- Usage: cc65 [options] file Short options: -Cl Make local variables static -Dsym[=defn] Define a symbol -E Stop after the preprocessing stage -I dir Set an include directory search path -O Optimize code -Oi Optimize code, inline more code -Or Enable register variables -Os Inline some standard functions -T Include source as comment -V Print the compiler version number -W warning[,...] Suppress warnings -d Debug mode -g Add debug info to object file -h Help (this text) -j Default characters are signed -mm model Set the memory model -o name Name the output file -r Enable register variables -t sys Set the target system -v Increase verbosity 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 --codesize x Accept larger code by factor x --cpu type Set cpu type (6502, 65c02) --create-dep name Create a make dependency file --create-full-dep name Create a full make dependency file --data-name seg Set the name of the DATA segment --debug Debug mode --debug-info Add debug info to object file --debug-opt name Configure optimizations with a file --debug-opt-output Debug output of each optimization step --dep-target target Use this dependency target --disable-opt name Disable an optimization step --eagerly-inline-funcs Eagerly inline some known functions --enable-opt name Enable an optimization step --help Help (this text) --include-dir dir Set an include directory search path --inline-stdfuncs Inline some standard functions --list-opt-steps List all optimizer steps and exit --list-warnings List available warning types for -W --local-strings Emit string literals immediately --memory-model model Set the memory model --register-space b Set space available for register variables --register-vars Enable register variables --rodata-name seg Set the name of the RODATA segment --signed-chars Default characters are signed --standard std Language standard (c89, c99, cc65) --static-locals Make local variables static --target sys Set the target system --verbose Increase verbosity --version Print the compiler version number --writable-strings Make string literals writable --------------------------------------------------------------------------- </verb></tscreen> <sect1>Command line options in detail<p> 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> Set the name of the bss segment. See also <tt/<ref id="pragma-bss-name" name="#pragma bss-name">/. <label id="option-check-stack"> <tag><tt>--check-stack</tt></tag> Tells the compiler to generate code that checks for stack overflows. See <tt/<ref id="pragma-check-stack" name="#pragma check-stack">/ for an explanation of this feature. <label id="option-code-name"> <tag><tt>--code-name seg</tt></tag> Set the name of the code segment. See also <tt/<ref id="pragma-code-name" name="#pragma code-name">/ <label id="option-codesize"> <tag><tt>--codesize x</tt></tag> This options allows finer control about speed vs. size decisions in the code generation and optimization phases. It gives the allowed size increase factor (in percent). The default is 100 when not using <tt/-Oi/ and 200 when using <tt/-Oi/ (<tt/-Oi/ is the same as <tt/-O --codesize 200/). <label id="option--cpu"> <tag><tt>--cpu CPU</tt></tag> Set the CPU, the compiler generates code for. You may specify "6502" or "65C02" as the CPU. The default depends on the selected target (see option <tt/<ref id="option-t" name="-t">/). It is the 6502 CPU for most targets or if no target has been set. Specifying 65C02 will use a few 65C02 instructions when generating code. Don't expect too much from this option: In most cases the difference in size and speed is just 1-2%. <label id="option-create-dep"> <tag><tt>--create-dep name</tt></tag> Tells the compiler to generate a file containing the dependency list for the compiled module in makefile syntax. The output is written to a file with the given name. The output does not include system include files (in angle brackets). <label id="option-create-full-dep"> <tag><tt>--create-full-dep name</tt></tag> Tells the compiler to generate a file containing the dependency list for the compiled module in makefile syntax. The output is written to a file with the given name. The output does include system include files (in angle brackets). <label id="option-data-name"> <tag><tt>--data-name seg</tt></tag> Set the name of the data segment. See also <tt/<ref id="pragma-data-name" name="#pragma data-name">/ <tag><tt>-d, --debug</tt></tag> Enables debug mode, for debugging the behavior of cc65. <tag><tt>--debug-opt name</tt></tag> The named file contains a list of specific optimization steps to enable or disable. Each line contains the name of an optimization step with either a <tt>+</tt> (enable) or <tt>-</tt> (disable) prefix. The name <tt>all</tt> can be used to enable or disable all optimizations. Comment lines may begin with <tt>#</tt> or <tt>;</tt>. Use <tt>--list-opt-steps</tt> to generate a complete list of available optimization steps. Use <tt>--debug</tt> to see a list of optimizations applied during compilation. <tag><tt>--debug-opt-output</tt></tag> For debugging the output of each optimization pass, step by step. Generates a <tt>name.opt</tt> output listing for each optimized function <tt>name</tt>. <label id="option-dep-target"> <tag><tt>--dep-target target</tt></tag> When generating a dependency file, don't use the actual output file as the target of the dependency, but the file specified with this option. The option has no effect if neither <tt/<ref id="option-create-dep" name="--create-dep">/ nor <tt/<ref id="option-create-full-dep" name="--create-full-dep">/ is specified. <tag><tt>-D sym[=definition]</tt></tag> Define a macro on the command line. If no definition is given, the macro is defined to the value "1". <tag><tt>-g, --debug-info</tt></tag> This will cause the compiler to insert a <tt/.DEBUGINFO/ command into the generated assembler code. This will cause the assembler to include all symbols in a special section in the object file. <label id="option-eagerly-inline-funcs"> <tag><tt>--eagerly-inline-funcs</tt></tag> Have the compiler eagerly inline these functions from the C library: <itemize> <item><tt/memcpy()/ <item><tt/memset()/ <item><tt/strcmp()/ <item><tt/strcpy()/ <item><tt/strlen()/ <item>most of the functions declared in <tt/<ctype.h>/ </itemize> Note: This has two consequences: <itemize> <item>You may not use names of standard C functions for your own functions. If you do that, your program is not standard-compliant anyway; but, using <tt/--eagerly-inline-funcs/ actually will break things. <p> <item>The inlined string and memory functions will not handle strings or memory areas larger than 255 bytes. Similarly, the inlined <tt/is..()/ functions will not work with values outside the char. range (such as <tt/EOF/). <p> </itemize> <tt/--eagerly-inline-funcs/ implies the <tt><ref id="option-inline-stdfuncs" name="--inline-stdfuncs"></tt> command line option. See also <tt><ref id="pragma-allow-eager-inline" name="#pragma allow-eager-inline"></tt>. <tag><tt>-h, --help</tt></tag> Print the short option summary shown above. <label id="option-inline-stdfuncs"> <tag><tt>--inline-stdfuncs</tt></tag> Allow the compiler to inline some standard functions from the C library like strlen. This will not only remove the overhead for a function call, but will make the code visible for the optimizer. See also the <tt><ref id="option-O" name="-Os"></tt> command line option and <tt><ref id="pragma-inline-stdfuncs" name="#pragma inline-stdfuncs"></tt>. <label id="option-list-warnings"> <tag><tt>--list-warnings</tt></tag> List the names of warning types available for use with <tt><ref id="option-W" name="-W"></tt>. <label id="option-local-strings"> <tag><tt>--local-strings</tt></tag> Emit string literals into the rodata segment as soon as they're encountered in the source (even if you do nothing but get the sizeof those strings). The default is to keep string literals until end of assembly, merge read only literals if possible, and then output the literals into the data or rodata segment that is active at that point. Use of this option prevents merging of duplicate strings, but the options that change the name of one of the data segments will work. You can also use <tt><ref id="pragma-local-strings" name="#pragma local-strings"></tt> for fine grained control. <tag><tt>-o name</tt></tag> Specify the name of the output file. If you don't specify a name, the name of the C input file is used, with the extension replaced by ".s". <label id="option-register-vars"> <tag><tt>-r, --register-vars</tt></tag> <tt/-r/ will make the compiler honor the <tt/register/ keyword. Local variables may be placed in registers (which are actually zero page locations). There is some overhead involved with register variables, since the old contents of the registers must be saved and restored. Since register variables are of limited use without the optimizer, there is also a combined switch: <tt/-Or/ will enable both, the optimizer and register variables. For more information about register variables see <ref id="register-vars" name="register variables">. The compiler setting can also be changed within the source file by using <tt/<ref id="pragma-register-vars" name="#pragma register-vars">/. <label id="option-register-space"> <tag><tt>--register-space</tt></tag> This option takes a numeric parameter and is used to specify, how much zero page register space is available. Please note that just giving this option will not increase or decrease by itself, it will just tell the compiler about the available space. You will have to allocate that space yourself using an assembler module with the necessary allocations, and a linker configuration that matches the assembler module. The default value for this option is 6 (bytes). If you don't know what all this means, please don't use this option. <label id="option-rodata-name"> <tag><tt>--rodata-name seg</tt></tag> Set the name of the rodata segment (the segment used for readonly data). See also <tt/<ref id="pragma-rodata-name" name="#pragma rodata-name">/ <label id="option-signed-chars"> <tag><tt>-j, --signed-chars</tt></tag> Using this option, you can make the default characters signed. Since the 6502 has no provisions for sign extending characters (which is needed on almost any load operation), this will make the code larger and slower. A better way is to declare characters explicitly as "signed" if needed. You can also use <tt><ref id="pragma-signed-chars" name="#pragma signed-chars"></tt> for better control of this option. <label id="option--standard"> <tag><tt>--standard std</tt></tag> This option allows to set the language standard supported. The argument is one of <descrip> <tag/c89/ This disables anything that is illegal in C89/C90. Among those things are <tt>//</tt> comments and the non-standard keywords without underscores. Please note that cc65 is not a fully C89 compliant compiler despite this option. A few more things (like floats) are missing. <tag/c99/ This enables a few features from the C99 standard. With this option, <tt>//</tt> comments are allowed. It will also cause warnings and even errors in a few situations that are allowed with <tt/--standard c89/. For example, a call to a function without a prototype is an error in this mode. <tag/cc65/ This is the default mode. It is like c99 mode, but additional features are enabled. Among these are "void data", non-standard keywords without the underlines, unnamed function parameters and the requirement for main() to return an int. </descrip> Please note that the compiler does not support the C99 standard and never will. c99 mode is actually c89 mode with a few selected C99 extensions. <label id="option-t"> <tag><tt>-t target, --target target</tt></tag> This option is used to set the target system. The target system determines the character set that is used for strings and character constants and the default CPU. The CPU setting can be overriden by use of the <tt/<ref id="option--cpu" name="--cpu">/ option. The following target systems are supported: <itemize> <item>none <item>apple2 <item>apple2enh <item>atari <item>atarixl <item>atmos <item>c16 (works also for the c116 with memory up to 32K) <item>c64 <item>c128 <item>cbm510 (CBM-II series with 40 column video) <item>cbm610 (all CBM-II II computers with 80 column video) <item>geos-apple <item>geos-cbm <item>lunix <item>lynx <item>nes <item>osic1p <item>pet (all CBM PET systems except the 2001) <item>plus4 <item>sim6502 <item>sim65c02 <item>supervision <item>telestrat <item>vic20 </itemize> <tag><tt>-v, --verbose</tt></tag> Using this option, the compiler will be somewhat more verbose if errors or warnings are encountered. <label id="option-writable-strings"> <tag><tt>--writable-strings</tt></tag> Make string literals writable by placing them into the data segment instead of the rodata segment. You can also use <tt><ref id="pragma-writable-strings" name="#pragma writable-strings"></tt> to control this option from within the source file. <label id="option-static-locals"> <tag><tt>-Cl, --static-locals</tt></tag> Use static storage for local variables instead of storage on the stack. Since the stack is emulated in software, this gives shorter and usually faster code, but the code is no longer reentrant. The difference between <tt/-Cl/ and declaring local variables as static yourself is, that initializer code is executed each time, the function is entered. So when using <tscreen><verb> void f (void) { unsigned a = 1; ... } </verb></tscreen> the variable <tt/a/ will always have the value <tt/1/ when entering the function and using <tt/-Cl/, while in <tscreen><verb> void f (void) { static unsigned a = 1; .... } </verb></tscreen> the variable <tt/a/ will have the value <tt/1/ only the first time that the function is entered, and will keep the old value from one call of the function to the next. You may also use <tt><ref id="pragma-static-locals" name="#pragma static-locals"></tt> to change this setting in your sources. <label id="option-include-dir"> <tag><tt>-I dir, --include-dir dir</tt></tag> Set a directory where the compiler searches for include files. You may use this option multiple times to add more than one directory to the search list. <label id="option-O"> <tag><tt>-O, -Oi, -Or, -Os</tt></tag> Enable an optimizer run over the produced code. Using <tt/-Oi/, the code generator will inline some code where otherwise a runtime functions would have been called, even if the generated code is larger. This will not only remove the overhead for a function call, but will make the code visible for the optimizer. <tt/-Oi/ is an alias for <tt/-O --codesize 200/. <tt/-Or/ will make the compiler honor the <tt/register/ keyword. Local variables may be placed in registers (which are actually zero page locations). See also the <tt/<ref id="option-register-vars" name="--register-vars">/ command line option, and the <ref id="register-vars" name="discussion of register variables"> below. Using <tt/-Os/ will allow the compiler to inline some standard functions from the C library like strlen. This will not only remove the overhead for a function call, but will make the code visible for the optimizer. See also the <tt/<ref id="option-inline-stdfuncs" name="--inline-stdfuncs">/ command line option. It is possible to concatenate the modifiers for <tt/-O/. For example, to enable register variables and inlining of standard functions, you may use <tt/-Ors/. <tag><tt>-T, --add-source</tt></tag> This include the source code as comments in the generated code. This is normally not needed. <tag><tt>-V, --version</tt></tag> Print the version number of the compiler. When submitting a bug report, please include the operating system you're using, and the compiler version. <label id="option-W"> <tag><tt>-W name[,name,...]</tt></tag> This option allows to control warnings generated by the compiler. It is followed by a comma-separated list of warnings that should be enabled or disabled. To disable a warning, its name is prefixed by a minus sign. If no such prefix exists, or the name is prefixed by a plus sign, the warning is enabled. The following warning names currently are recognized: <descrip> <tag><tt/const-comparison/</tag> Warn if the result of a comparison is constant. <tag><tt/error/</tag> Treat all warnings as errors. <tag><tt/no-effect/</tag> Warn about statements that don't have an effect. <tag><tt/remap-zero/</tag> Warn about a <tt/<ref id="pragma-charmap" name="#pragma charmap()">/ that changes a character's code number from/to 0x00. <tag><tt/struct-param/</tag> Warn when passing structs by value. <tag><tt/unknown-pragma/</tag> Warn about #pragmas that aren't recognized by cc65. <tag><tt/unused-label/</tag> Warn about unused labels. <tag><tt/unused-param/</tag> Warn about unused function parameters. <tag><tt/unused-var/</tag> Warn about unused variables. </descrip> The full list of available warning names can be retrieved by using the option <tt><ref id="option-list-warnings" name="--list-warnings"></tt>. You may use also <tt><ref id="pragma-warn" name="#pragma warn"></tt> to control this setting, for smaller pieces of code, from within your sources. </descrip><p> <sect>Input and output<p> The compiler will accept one C file per invocation and create a file with the same base name, but with the extension replaced by ".s". The output file contains assembler code suitable for use with the ca65 macro assembler. Include files in quotes are searched in the following places: <enum> <item>The current file's directory. <item>Any directory added with the <tt/-I/ option on the command line. <item>The value of the environment variable <tt/CC65_INC/ if it is defined. </enum> Include files in angle brackets are searched in the following places: <enum> <item>Any directory added with the <tt/-I/ option on the command line. <item>The value of the environment variable <tt/CC65_INC/ if it is defined. <item>A subdirectory named <tt/include/ of the directory defined in the environment variable <tt/CC65_HOME/, if it is defined. <item>An optionally compiled-in directory. </enum> <sect>Differences to the ISO standard<p> Apart from the things listed below, the compiler does support additional keywords, has several functions in the standard headers with names outside the reserved namespace and a few syntax extensions. All these can be disabled with the <tt><ref id="option--standard" name="--standard"></tt> command line option. Its use for maximum standards compatibility is advised. Here is a list of differences between the language, the compiler accepts, and the one defined by the ISO standard: <itemize> <item> The datatypes "float" and "double" are not available. <p> <item> C Functions may not return structs (or unions), and structs may not be passed as parameters by value. However, struct assignment *is* possible. <p> <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 has almost no effect. That is not as bad as it sounds, since the 6502 has so few registers that it isn't possible to keep values in registers anyway. <p> </itemize> There may be some more minor differences I'm currently not aware of. The biggest problem is the missing float data type. With this limitation in mind, you should be able to write fairly portable code. <sect>Extensions<p> This cc65 version has some extensions to the ISO C standard. <itemize> <item> The compiler allows to insert assembler statements into the output file. The syntax is <tscreen><verb> asm [optional volatile] (<string literal>[, optional parameters]) ; </verb></tscreen> or <tscreen><verb> __asm__ [optional volatile] (<string literal>[, optional parameters]) ; </verb></tscreen> The first form is in the user namespace; and, is disabled if the <tt/-A/ switch is given. There is a whole section covering inline assembler statements, <ref id="inline-asm" name="see there">. <p> <label id="extension-fastcall"> <item> The normal calling convention -- for non-variadic functions -- is named "fastcall". The syntax for a function declaration that <em/explicitly/ uses fastcall is <tscreen><verb> <return type> fastcall <function name> (<parameter list>) </verb></tscreen> or <tscreen><verb> <return type> __fastcall__ <function name> (<parameter list>) </verb></tscreen> An example is <tscreen><verb> 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 that are <tt/fastcall/, the rightmost parameter is not pushed on the stack but left in the primary register when the function is called. That significantly reduces the cost of calling those functions. <p> <item> There is another calling convention named "cdecl". Variadic functions (their prototypes have an ellipsis [<tt/.../]) always use that convention. The syntax for a function declaration using cdecl is <tscreen><verb> <return type> cdecl <function name> (<parameter list>) </verb></tscreen> or <tscreen><verb> <return type> __cdecl__ <function name> (<parameter list>) </verb></tscreen> An example is <tscreen><verb> int* __cdecl__ f (unsigned char c) </verb></tscreen> The first form of the cdecl keyword is in the user namespace; and therefore, can be disabled with the <tt/<ref id="option--standard" name="--standard">/ command-line option. For functions that are <tt/cdecl/, the rightmost parameter is pushed onto the stack before the function is called. That increases the cost of calling those functions, especially when they are called from many places. <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 type <tt/unsigned int/ and <tt/__EAX__/ of type <tt/long unsigned int/ respectively. The pseudo variables may be used as lvalue and rvalue as every other variable. They are most useful together with short sequences of assembler code. For example, the macro <tscreen><verb> #define hi(x) \ (__AX__ = (x), \ asm ("txa"), \ asm ("ldx #$00"), \ __AX__) </verb></tscreen> will give the high byte of any unsigned value. <p> <item> Inside a function, the identifier <tt/__func__/ gives the name of the current function as a string. Outside of functions, <tt/__func__/ is undefined. Example: <tscreen><verb> #define PRINT_DEBUG(s) printf ("%s: %s\n", __func__, s); </verb></tscreen> The macro will print the name of the current function plus a given string. <p> <item> cc65 allows the initialization of <tt/void/ variables. This may be used to create arbitrary structures that are more compatible with interfaces written for assembler languages. Here is an example: <tscreen><verb> void GCmd = { (char)3, (unsigned)0x2000, (unsigned)0x3000 }; </verb></tscreen> That will be translated as follows: <tscreen><verb> _GCmd: .byte 3 .word $2000 .word $3000 </verb></tscreen> Since the variable is of type <tt/void/, you may not use it as-is. However, taking the address of the variable results in a <tt/void*/ which may be passed to any function expecting a pointer. Also, the <tt/sizeof/ operator will give the length of the initializer: <tscreen><verb> GLen = sizeof GCmd; </verb></tscreen> will assign the value 5 to <tt/GLen/. See the <url url="geos.html" name="GEOS library document"> for examples on how to use that feature. <p> <item> cc65 implements flexible array struct members as defined in the C99 ISO standard. As an extension, these fields may be initialized. There are several exceptions, however (which is probably the reason why the standard does not define this feature, because it is highly unorthogonal). Flexible array members cannot be initialized ... <itemize> <item>... when defining an array of structs with flexible members. <item>... if such a struct is a member field of another struct which is not the last field. <item>... if the struct which contains a flexible array member is declared as <tt/register/, and the size and compiler settings do allow the compiler actually to place the struct into the register bank in the zero page. </itemize> Please note that -- as defined in the ISO C standard -- the <tt/sizeof/ operator returns the struct size with the flexible array member having size zero, even if it is initialized. <p> <item> Computed gotos, a GCC extension, has limited support. With it you can use fast jump tables from C. You can take the address of a label with a double ampersand, putting them in a static const array of type void *. Then you can jump to one of these labels as follows: <tscreen><verb> static const void * const jumptable[] = { &&add, &&sub }; goto *jumptable[somevar]; add: ...code... </verb></tscreen> In the jump table, no expressions are supported. The array index used in the goto must be a simple variable or a constant. </itemize> <p> <sect>Predefined macros<p> The compiler defines several macros at startup: <descrip> <tag><tt>__APPLE2__</tt></tag> This macro is defined if the target is the Apple ][ (-t apple2) or the enhanced Apple //e (-t apple2enh). <tag><tt>__APPLE2ENH__</tt></tag> This macro is defined if the target is the enhanced Apple //e (-t apple2enh). <tag><tt>__ATARI2600__</tt></tag> This macro is defined if the target is the Atari 2600 game console. <tag><tt>__ATARI5200__</tt></tag> This macro is defined if the target is the Atari 5200 game console. <tag><tt>__ATARI__</tt></tag> This macro is defined if the target is the Atari 400/800 (-t atari) or the Atari 800XL/130XE (-t atarixl). <tag><tt>__ATARIXL__</tt></tag> This macro is defined if the target is the Atari 800XL/130XE (-t atarixl). <tag><tt>__ATMOS__</tt></tag> This macro is defined if the target is the Oric Atmos (-t atmos). <tag><tt>__C128__</tt></tag> This macro is defined if the target is the Commodore 128 (-t c128). <tag><tt>__C16__</tt></tag> This macro is defined if the target is the Commodore 16/116 (-t c16) or the Commodore Plus/4 (-t plus4). <tag><tt>__C64__</tt></tag> This macro is defined if the target is the Commodore 64 (-t c64). <tag><tt>__CBM__</tt></tag> This macro is defined if the target system is one of the CBM targets. <tag><tt>__CBM510__</tt></tag> This macro is defined if the target is the CBM 500 series of computers. <tag><tt>__CBM610__</tt></tag> This macro is defined if the target is one of the CBM 600/700 family of computers (called B series in the US). <tag><tt>__CC65__</tt></tag> This macro is always defined. Its value is the version number of the compiler in hex. For example, version 2.14 of the compiler has this macro defined as <tt/0x02E0/. <tag><tt>__CC65_STD__</tt></tag> This macro is defined to one of the following depending on the <tt><ref id="option--standard" name="--standard"></tt> command line option: <itemize> <item><tt/__CC65_STD_C89__/ <item><tt/__CC65_STD_C99__/ <item><tt/__CC65_STD_CC65__/ </itemize> <tag><tt>__DATE__</tt></tag> This macro expands to the date of translation of the preprocessing translation unit in the form "Mmm dd yyyy". <tag><tt>__EAGERLY_INLINE_FUNCS__</tt></tag> Is defined if the compiler was called with the <tt><ref id="option-eagerly-inline-funcs" name="--eagerly-inline-funcs"></tt> command line option. <tag><tt>__FILE__</tt></tag> This macro expands to a string containing the name of the C source file. <tag><tt>__GEOS__</tt></tag> This macro is defined if you are compiling for one of the GEOS systems. <tag><tt>__GEOS_APPLE__</tt></tag> This macro is defined if you are compiling for the Apple GEOS system (-t geos-apple). <tag><tt>__GEOS_CBM__</tt></tag> This macro is defined if you are compiling for the GEOS 64/128 system (-t geos-cbm). <tag><tt>__LINE__</tt></tag> This macro expands to the current line number. <tag><tt>__LUNIX__</tt></tag> This macro is defined if you are compiling for the LUnix system (-t lunix). <tag><tt>__LYNX__</tt></tag> This macro is defined if the target is the Atari Lynx (-t lynx). <tag><tt>__NES__</tt></tag> This macro is defined if the target is the Nintendo Entertainment System (-t nes). <tag><tt>__OPT__</tt></tag> Is defined if the compiler was called with the <tt/-O/ command line option. <tag><tt>__OPT_i__</tt></tag> Is defined if the compiler was called with the <tt/-Oi/ command line option. <tag><tt>__OPT_r__</tt></tag> Is defined if the compiler was called with the <tt/-Or/ command line option. <tag><tt>__OPT_s__</tt></tag> 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). <tag><tt>__PLUS4__</tt></tag> This macro is defined if the target is the Commodore Plus/4 (-t plus4). <tag><tt>__STDC_HOSTED__</tt></tag> This macro is expands to the integer constant 1. <tag><tt>__SIM6502__</tt></tag> This macro is defined if the target is sim65 in 6502 mode (-t sim6502). <tag><tt>__SIM65C02__</tt></tag> This macro is defined if the target is sim65 in 65C02 mode (-t sim65c02). <tag><tt>__SUPERVISION__</tt></tag> This macro is defined if the target is the Supervision (-t supervision). <tag><tt>__TELESTRAT__</tt></tag> This macro is defined if the target is the Telestrat (-t telestrat). <tag><tt>__TIME__</tt></tag> This macro expands to the time of translation of the preprocessing translation unit in the form "hh:mm:ss". <tag><tt>__VIC20__</tt></tag> This macro is defined if the target is the Commodore VIC20 (-t vic20). </descrip> <sect>#pragmas<label id="pragmas"><p> The compiler understands some pragmas that may be used to change code generation and other stuff. Some of these pragmas understand a special form: If the first parameter is <tt/push/, the old value is saved onto a stack before changing it. The value may later be restored by using the <tt/pop/ parameter with the <tt/#pragma/. <sect1><tt>#pragma allow-eager-inline ([push,] on|off)</tt><label id="pragma-allow-eager-inline"><p> Allow eager inlining of known functions. If the argument is "off", eager inlining is disabled, otherwise it is enabled. Please note that (in contrast to the <tt><ref id="option-eagerly-inline-funcs" name="--eagerly-inline-funcs"></tt> command line option) this pragma does not imply the <tt><ref id="option-inline-stdfuncs" name="--inline-stdfuncs"></tt> command line option. Rather it marks code to be safe for eager inlining of known functions if inlining of standard functions is enabled. The <tt/#pragma/ understands the push and pop parameters as explained above. <sect1><tt>#pragma bss-name ([push,] <name>)</tt><label id="pragma-bss-name"><p> This pragma changes the name used for the BSS segment (the BSS segment is used to store uninitialized data). The argument is a string enclosed in double quotes. Note: The default linker configuration file does only map the standard segments. If you use other segments, you have to create a new linker configuration file. Beware: The startup code will zero only the default BSS segment. If you use another BSS segment, you have to do that yourself, otherwise uninitialized variables do not have the value zero. The <tt/#pragma/ understands the push and pop parameters as explained above. Example: <tscreen><verb> #pragma bss-name ("MyBSS") </verb></tscreen> <sect1><tt>#pragma charmap (<index>, <code>)</tt><label id="pragma-charmap"><p> Each literal string and each literal character in the source is translated by use of a translation table. That translation table is preset when the compiler is started, depending on the target system; for example, to map ISO-8859-1 characters into PETSCII if the target is a Commodore machine. This pragma allows to change entries in the translation table, so the translation for individual characters, or even the complete table may be adjusted. Both arguments are assumed to be unsigned characters with a valid range of 0-255. Beware of some pitfalls: <itemize> <item>The character index is actually the code of the character in the C source; so, character mappings do always depend on the source character set. That means that <tt/#pragma charmap()/ is not portable -- it depends on the build environment. <item>While it is possible to use character literals as indices, the result may be somewhat unexpected, since character literals are themselves translated. For that reason, I would suggest to avoid character literals, and use numeric character codes instead. <item>It is risky to change index <tt/0x00/, because string functions depend on it. If it is changed, then the <tt/'\0'/ at the end of string literals will become non-zero. Functions that are used on those literals won't stop at the end of them. cc65 will warn you if you do change that code number. You can turn off that <tt/remap-zero/ warning if you are certain that you know what you are doing (see <tt/<ref id="pragma-warn" name="#pragma warn()">/). </itemize> Example: <tscreen><verb> /* Use a space wherever an 'a' occurs in ISO-8859-1 source */ #pragma charmap (0x61, 0x20); </verb></tscreen> <sect1><tt>#pragma check-stack ([push,] on|off)</tt><label id="pragma-check-stack"><p> Tells the compiler to insert calls to a stack checking subroutine to detect stack overflows. The stack checking code will lead to somewhat larger and slower programs, so you may want to use this pragma when debugging your program and switch it off for the release version. If a stack overflow is detected, the program is aborted. If the argument is "off", stack checks are disabled (the default), otherwise they're enabled. The <tt/#pragma/ understands the push and pop parameters as explained above. <sect1><tt>#pragma code-name ([push,] <name>)</tt><label id="pragma-code-name"><p> This pragma changes the name used for the CODE segment (the CODE segment is used to store executable code). The argument is a string enclosed in double quotes. Note: The default linker configuration file does only map the standard segments. If you use other segments, you have to create a new linker configuration file. The <tt/#pragma/ understands the push and pop parameters as explained above. Example: <tscreen><verb> #pragma code-name ("MyCODE") </verb></tscreen> <sect1><tt>#pragma codesize ([push,] <int>)</tt><label id="pragma-codesize"><p> This pragma allows finer control about speed vs. size decisions in the code generation and optimization phase. It gives the allowed size increase factor (in percent). The default is can be changed by use of the <tt/<ref id="option-codesize" name="--codesize">/ compiler option. The <tt/#pragma/ understands the push and pop parameters as explained above. <sect1><tt>#pragma data-name ([push,] <name>)</tt><label id="pragma-data-name"><p> This pragma changes the name used for the DATA segment (the DATA segment is used to store initialized data). The argument is a string enclosed in double quotes. Note: The default linker configuration file does only map the standard segments. If you use other segments, you have to create a new linker configuration file. The <tt/#pragma/ understands the push and pop parameters as explained above. Example: <tscreen><verb> #pragma data-name ("MyDATA") </verb></tscreen> <sect1><tt>#pragma inline-stdfuncs ([push,] on|off)</tt><label id="pragma-inline-stdfuncs"><p> Allow the compiler to inline some standard functions from the C library like strlen. If the argument is "off", inlining is disabled, otherwise it is enabled. See also the <tt/<ref id="option-inline-stdfuncs" name="--inline-stdfuncs">/ command line option. The <tt/#pragma/ understands the push and pop parameters as explained above. <sect1><tt>#pragma local-strings ([push,] on|off)</tt><label id="pragma-local-strings"><p> When "on", emit string literals to the data segment when they're encountered in the source. The default ("off") is to keep string literals until end of assembly, merge read only literals if possible, and then output the literals into the data or rodata segment that is active at that point. Using this <tt/#pragma/ it is possible to control the behaviour from within the source. When <tt/#pragma local-strings/ is active, string literals are output immediately, which means that they go into the currently active data or rodata segment, but cannot be merged. When inactive, string literals are remembered and output as a whole when translation is finished. <sect1><tt>#pragma message (<message>)</tt><label id="pragma-message"><p> This pragma is used to display informational messages at compile-time. The message intented to be displayed must be a string literal. Example: <tscreen><verb> #pragma message ("in a bottle") </verb></tscreen> Results in the compiler outputting the following to stderr: <tscreen><verb> example.c(42): Note: in a bottle </verb></tscreen> <sect1><tt>#pragma optimize ([push,] on|off)</tt><label id="pragma-optimize"><p> Switch optimization on or off. If the argument is "off", optimization is disabled, otherwise it is enabled. Please note that this pragma only effects whole functions. The setting in effect when the function is encountered will determine if the generated code is optimized or not. Optimization and code generation is also controlled by the <ref id="pragma-codesize" name="codesize pragma">. The default is "off", but may be changed with the <tt/<ref name="-O" id="option-O">/ compiler option. The <tt/#pragma/ understands the push and pop parameters as explained above. <sect1><tt>#pragma rodata-name ([push,] <name>)</tt><label id="pragma-rodata-name"><p> This pragma changes the name used for the RODATA segment (the RODATA segment is used to store readonly data). The argument is a string enclosed in double quotes. Note: The default linker configuration file does only map the standard segments. If you use other segments, you have to create a new linker configuration file. The <tt/#pragma/ understands the push and pop parameters as explained above. Example: <tscreen><verb> #pragma rodata-name ("MyRODATA") </verb></tscreen> <sect1><tt>#pragma regvaraddr ([push,] on|off)</tt><label id="pragma-regvaraddr"><p> The compiler does not allow to take the address of register variables. The regvaraddr pragma changes this. Taking the address of a register variable is allowed after using this pragma with "on" as argument. Using "off" as an argument switches back to the default behaviour. Beware: The C standard does not allow taking the address of a variable declared as register. So your programs become non-portable if you use this pragma. In addition, your program may not work. This is usually the case if a subroutine is called with the address of a register variable, and this subroutine (or a subroutine called from there) uses register variables. So be careful with this #pragma. The <tt/#pragma/ understands the push and pop parameters as explained above. Example: <tscreen><verb> #pragma regvaraddr(on) /* Allow taking the address * of register variables */ </verb></tscreen> <sect1><tt>#pragma register-vars ([push,] on|off)</tt><label id="pragma-register-vars"><p> Enables or disables use of register variables. If register variables are disabled (the default), the <tt/register/ keyword is ignored. Register variables are explained in more detail in <ref id="register-vars" name="a separate chapter">. The <tt/#pragma/ understands the push and pop parameters as explained above. <sect1><tt>#pragma signed-chars ([push,] on|off)</tt><label id="pragma-signed-chars"><p> Changes the signedness of the default character type. If the argument is "on", default characters are signed, otherwise characters are unsigned. The compiler default is to make characters unsigned since this creates a lot better code. This default may be overridden by the <tt/<ref name="--signed-chars" id="option-signed-chars">/ command line option. The <tt/#pragma/ understands the push and pop parameters as explained above. <sect1><tt>#pragma static-locals ([push,] on|off)</tt><label id="pragma-static-locals"<p> Use variables in the bss segment instead of variables on the stack. This pragma changes the default set by the compiler option <tt/<ref name="--static-locals" id="option-static-locals">/. If the argument is "on", local variables are allocated in the BSS segment, leading to shorter and in most cases faster, but non-reentrant code. The <tt/#pragma/ understands the push and pop parameters as explained above. <sect1><tt>#pragma warn (name, [push,] on|off)</tt><label id="pragma-warn"><p> Switch compiler warnings on or off. "name" is the name of a warning (see the <tt/<ref name="-W" id="option-W">/ compiler option for a list). The name is followed either by "pop", which restores the last pushed state, or by "on" or "off", optionally preceeded by "push" to push the current state before changing it. Example: <tscreen><verb> /* Don't warn about the unused parameter in function func */ #pragma warn (unused-param, push, off) static int func (int unused) { return 0; } #pragma warn (unused-param, pop) </verb></tscreen> <sect1><tt>#pragma wrapped-call (push, <name>, <identifier>)</tt><label id="pragma-wrapped-call"><p> This pragma sets a wrapper for functions, often used for trampolines. The name is a function returning <tt/void/, and taking no parameters. It must preserve the CPU's <tt/A/ and <tt/X/ registers if it wraps any <tt/__fastcall__/ functions that have parameters. It must preserve the <tt/Y/ register if it wraps any variadic functions (they have "<tt/.../" in their prototypes). The identifier is an 8-bit number that's set into <tt/tmp4/. The address of a wrapped function is passed in <tt/ptr4/. The wrapper can call that function by using "<tt/jsr callptr4/". This feature is useful, for example, with banked memory, to switch banks automatically to where a wrapped function resides, and then to restore the previous bank when it returns. The <tt/#pragma/ requires the push or pop argument as explained above. Example: <tscreen><verb> /* Note that this code can be in a header. */ void mytrampoline(void); /* Doesn't corrupt __AX__ */ #pragma wrapped-call (push, mytrampoline, 5) void somefunc1(void); void somefunc2(int, char *); #pragma wrapped-call (pop) </verb></tscreen> <sect1><tt>#pragma writable-strings ([push,] on|off)</tt><label id="pragma-writable-strings"><p> Changes the storage location of string literals. For historical reasons, the C standard defines that string literals are of type "char[]", but writing to such a literal causes undefined behaviour. Most compilers (including cc65) place string literals in the read-only data segment, which may cause problems with old C code that writes to string literals. Using this pragma (or the corresponding command line option <tt/<ref name="--writable-strings" id="option-writable-strings">/) causes the literals to be placed in the data segment so they can be written to without worry. The <tt/#pragma/ understands the push and pop parameters as explained above. <sect1><tt>#pragma zpsym (<name>)</tt><p> Tell the compiler that the -- previously as external declared -- symbol with the given name is a zero page symbol (usually from an assembler file). The compiler will create a matching import declaration for the assembler. Example: <tscreen><verb> extern int foo; #pragma zpsym ("foo"); /* foo is in the zeropage */ </verb></tscreen> <sect>Register variables<label id="register-vars"><p> The runtime for all supported platforms has 6 bytes of zero page space available for register variables (this could be increased, but I think it's a good value). So you can declare register variables up to a total size of 6 per function. The compiler will allocate register space on a "first come, first served" base and convert any <tt/register/ declarations that exceed the available register space silently to <tt/auto/. Parameters can also be declared as <tt/register/, this will in fact give slightly shorter code than using a register variable. Since a function must save the current values of the registers on entry and restore them on exit, there is an overhead associated with register variables, and this overhead is quite high (about 20 bytes per variable). This means that just declaring anything as <tt/register/ is not a good idea. The best use for register variables are pointers, especially those that point to structures. The magic number here is about 3 uses of a struct field: If the function contains this number or even more, the generated code will be usually shorter and faster when using a register variable for the struct pointer. The reason for this is that the register variable can in many cases be used as a pointer directly. Having a pointer in an auto variable means that this pointer must first be copied into a zero page location, before it can be dereferenced. Second best use for register variables are counters. However, there is not much difference in the code generated for counters, so you will need at least 100 operations on this variable (for example in a loop) to make it worth the trouble. The only savings you get here are by the use of a zero page variable instead of one on the stack or in the data segment. Register variables must be explicitly enabled, either by using <tt/<ref name="-Or" id="option-O">/ or <tt/<ref name="--register-vars" id="option-register-vars">/ on the command line or by use of <tt/<ref name="#pragma register-vars" id="pragma-register-vars">/. Register variables are only accepted on function top level, register variables declared in interior blocks are silently converted to <tt/auto/. With register variables disabled, all variables declared as <tt/register/ are actually auto variables. Please take care when using register variables: While they are helpful and can lead to a tremendous speedup when used correctly, improper usage will cause bloated code and a slowdown. <sect>Inline assembler<label id="inline-asm"><p> The compiler allows to insert assembler statements into the output file. The syntax is <tscreen><verb> asm [optional volatile] (<string literal>[, optional parameters]) ; </verb></tscreen> or <tscreen><verb> __asm__ [optional volatile] (<string literal>[, optional parameters]) ; </verb></tscreen> <p> The first form is in the user namespace; and, is disabled by <tt><ref id="option--standard" name="--standard"></tt> if the argument is not <tt/cc65/. The <tt/asm/ statement can be used only inside a function. Please note that the result of an inline assembler expression is always of type <tt/void/. The contents of the string literal are preparsed by the compiler; and, inserted into the generated assembly output, so that it can be processed further by the backend -- and, especially the optimizer. For that reason, the compiler does allow only regular 6502 opcodes to be used with the inline assembler. Pseudo instructions (like <tt/.import/, <tt/.byte/, and so on) are <em/not/ allowed, even if the ca65 assembler (which is used to translate the generated assembler code) would accept them. The built-in inline assembler is not a replacement for the full-blown macro assembler which comes with the compiler. Note: Inline assembler statements are subject to all optimizations done by the compiler. There currently is no way to protect an inline assembler statement -- alone -- from being moved or removed completely by the optimizer. If in doubt, check the generated assembler output; or, disable optimizations (for that function). As a shortcut, you can put the <tt/volatile/ qualifier in your <tt/asm/ statements. It will disable optimization for the functions in which those <tt/asm volatile/ statements sit. The effect is the same as though you put <tt/#pragma optimize(push, off)/ above those functions, and <tt/#pragma optimize(pop)/ below those functions. The string literal may contain format specifiers from the following list. For each format specifier, an argument is expected which is inserted instead of the format specifier, before passing the assembly code line to the backend. <itemize> <item><tt/%b/ - Numerical 8-bit value <item><tt/%w/ - Numerical 16-bit value <item><tt/%l/ - Numerical 32-bit value <item><tt/%v/ - Assembler name of a global variable or function <item><tt/%o/ - Stack offset of a local variable <item><tt/%g/ - Assembler name of a C label <item><tt/%s/ - The argument is converted to a string <item><tt/%%/ - The % sign itself </itemize><p> Using those format specifiers, you can access C <tt/#defines/, variables, or similar stuff from the inline assembler. For example, to load the value of a C <tt/#define/ into the Y index register, one would use <tscreen><verb> #define OFFS 23 __asm__ ("ldy #%b", OFFS); </verb></tscreen> Or, to access a struct member of a static variable: <tscreen><verb> typedef struct { unsigned char x; unsigned char y; unsigned char color; unsigned char data[32]; } pixel_t; static pixel_t pixel; __asm__ ("ldy #%b", offsetof(pixel_t, color)); __asm__ ("lda %v,y", pixel); /* or to access an array member */ static unsigned char i; __asm__ ("ldy %v", i); __asm__ ("lda %v+%b,y", pixel, offsetof(pixel_t, data)); </verb></tscreen> <p> The next example shows how to use global variables to exchange data between C and assembler; and, how to handle assembler jumps: <tscreen><verb> static unsigned char globalSubA, globalSubB, globalSubResult; /* return a-b, return 255 if b>a */ unsigned char sub (unsigned char a, unsigned char b) { globalSubA = a; globalSubB = b; __asm__ ("sec"); __asm__ ("lda %v", globalSubA); __asm__ ("sbc %v", globalSubB); __asm__ ("bcs %g", jumpSubNoError); __asm__ ("lda #$FF"); jumpSubNoError: __asm__ ("sta %v", globalSubResult); return globalSubResult; } </verb></tscreen> <p> Arrays also can be accessed: <tscreen><verb> static const unsigned char globalSquareTable[] = { 0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225 }; static unsigned char globalSquareA, globalSquareResult; /* return a*a for a<16, else 255 */ unsigned char square (unsigned char a) { if (a > 15) { return 255; } globalSquareA = a; __asm__ ("ldx %v", globalSquareA); __asm__ ("lda %v,x", globalSquareTable); __asm__ ("sta %v", globalSquareResult); return globalSquareResult; } </verb></tscreen> <p> Note: Do not embed the assembler labels that are used as names of global variables or functions into your <tt/asm/ statements. Code such as this: <tscreen><verb> int foo; int bar (void) { return 1; } ... __asm__ ("lda _foo"); /* DON'T DO THAT! */ ... __asm__ ("jsr _bar"); /* DON'T DO THAT EITHER! */ </verb></tscreen> <p> might stop working if the way that the compiler generates those names is changed in a future version. Instead, use the format specifiers from the table above: <tscreen><verb> __asm__ ("lda %v", foo); /* OK */ ... __asm__ ("jsr %v", bar); /* OK */ </verb></tscreen> <p> <sect>Implementation-defined behavior<p> This section describes the behavior of cc65 when the standard describes the behavior as implementation-defined. (to be done) <sect>Copyright<p> This is the original compiler copyright: <tscreen><verb> -------------------------------------------------------------------------- -*- 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. -------------------------------------------------------------------------- </verb></tscreen> Small parts of the compiler (parts of the preprocessor and main parser) are still covered by this copyright. The main portion is covered by the usual cc65 license, which reads: 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> ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/chrcvt65.sgml�������������������������������������������������������������������������0000664�0000000�0000000�00000006154�13473601511�0015310�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <!-- -*- text-mode -*- --> <article> <title>chrcvt65 Users Guide <author><url url="mailto:polluks@sdf.lonestar.org" name="Stefan A. Haubenthal"> <abstract> chrcvt65 is the vector font converter. It is able to convert a foreign font into the native format. </abstract> <!-- Table of contents --> <toc> <!-- Begin the document --> <sect>Overview<p> chrcvt65 is a vector font converter. It is able to convert a "BGI Stroked Font" to a compact TGI native vector font. See the function <url url="funcref.html#tgi_load_vectorfont" name="tgi_load_vectorfont"> for usage. <sect>Usage<p> The chrcvt65 utility converts the font of one Borland file to its cc65 equivalent. <sect1>Command line option overview<p> The program may be called as follows: <tscreen><verb> --------------------------------------------------------------------------- Usage: chrcvt65 [options] file [options] [file] Short options: -h Help (this text) -v Be more verbose -V Print the version number and exit Long options: --help Help (this text) --verbose Be more verbose --version Print the version number and exit --------------------------------------------------------------------------- </verb></tscreen> <sect1>Command line options in detail<p> Here is a description of all the command line options: <descrip> <tag><tt>-v, --verbose</tt></tag> Increase the converter verbosity. <tag><tt>-h, --help</tt></tag> Print the short option summary shown above. <tag><tt>-V, --version</tt></tag> Print the version number of the utility. When submitting a bug report, please include the operating system you're using, and the compiler version. </descrip> <sect>Input and output<p> The converter will read one CHR file per invocation and write the font in TCH format to a new file. Example output for the command <tscreen><verb> chrcvt65 --verbose LITT.CHR </verb></tscreen> <tscreen><verb> BGI Stroked Font V1.1 - Aug 12, 1991 Copyright (c) 1987,1988 Borland International </verb></tscreen> <sect>Copyright<p> chrcvt65 is (C) Copyright 2009, Ullrich von Bassewitz. For usage of the binaries and/or sources the following conditions apply: This software is provided 'as-is', without any expressed or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: <enum> <item> The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. <item> Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. <item> This notice may not be removed or altered from any source distribution. </enum> </article> ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/cl65.sgml�����������������������������������������������������������������������������0000664�0000000�0000000�00000033662�13473601511�0014421�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>cl65 Users Guide <author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline> <url url="mailto:greg.king5@verizon.net" name="Greg King"> <abstract> cl65 is the compile & link utility for cc65, the 6502 C compiler. It was designed as a smart frontend for the C compiler (cc65), the assembler (ca65), the object file converter (co65), and the linker (ld65). </abstract> <!-- Table of contents --> <toc> <!-- Begin the document --> <sect>Overview<p> cl65 is a frontend for cc65, ca65, co65 and ld65. While you may not use the full power of the tools when calling them through cl65, most features are available, and the use of cl65 is much simpler. <sect>Basic Usage<p> The cl65 compile and link utility may be used to convert, compile, assemble and link files. While the separate tools do just one step, cl65 knows how to build object files from C files (by calling the compiler, then the assembler) and other things. <tscreen><verb> --------------------------------------------------------------------------- Usage: cl65 [options] file [...] Short options: -c Compile and assemble but don't link -d Debug mode -g Add debug info -h Help (this text) -l name Create an assembler listing file -m name Create a map file -mm model Set the memory model -o name Name the output file -r Enable register variables -t sys Set the target system -u sym Force an import of symbol 'sym' -v Verbose mode -vm Verbose map file -C name Use linker config file -Cl Make local variables static -D sym[=defn] Define a preprocessor symbol -E Stop after the preprocessing stage -I dir Set a compiler include directory path -L path Specify a library search path -Ln name Create a VICE label file -O Optimize code -Oi Optimize code, inline more code -Or Optimize code, honour the register keyword -Os Optimize code, inline standard funtions -S Compile but don't assemble and link -T Include source as comment -V Print the version number -W name[,...] Supress compiler warnings -Wa options Pass options to the assembler -Wc options Pass options to the compiler -Wl options Pass options to the linker Long options: --add-source Include source as comment --all-cdecl Make functions default to __cdecl__ --asm-args options Pass options to the assembler --asm-define sym[=v] Define an assembler symbol --asm-include-dir dir Set an assembler include directory --bin-include-dir dir Set an assembler binary include directory --bss-label name Define and export a BSS segment label --bss-name seg Set the name of the BSS segment --cc-args options Pass options to the compiler --cfg-path path Specify a config file search path --check-stack Generate stack overflow checks --code-label name Define and export a CODE segment label --code-name seg Set the name of the CODE segment --codesize x Accept larger code by factor x --config name Use linker config file --cpu type Set cpu type --create-dep name Create a make dependency file --create-full-dep name Create a full make dependency file --data-label name Define and export a DATA segment label --data-name seg Set the name of the DATA segment --debug Debug mode --debug-info Add debug info --feature name Set an emulation feature --force-import sym Force an import of symbol 'sym' --help Help (this text) --include-dir dir Set a compiler include directory path --ld-args options Pass options to the linker --lib file Link this library --lib-path path Specify a library search path --list-targets List all available targets --listing name Create an assembler listing file --list-bytes n Number of bytes per assembler listing line --mapfile name Create a map file --memory-model model Set the memory model --module Link as a module --module-id id Specify a module id for the linker --no-target-lib Don't link the target library --o65-model model Override the o65 model --obj file Link this object file --obj-path path Specify an object file search path --print-target-path Print the target file path --register-space b Set space available for register variables --register-vars Enable register variables --rodata-name seg Set the name of the RODATA segment --signed-chars Default characters are signed --standard std Language standard (c89, c99, cc65) --start-addr addr Set the default start address --static-locals Make local variables static --target sys Set the target system --version Print the version number --verbose Verbose mode --zeropage-label name Define and export a ZEROPAGE segment label --zeropage-name seg Set the name of the ZEROPAGE segment --------------------------------------------------------------------------- </verb></tscreen> Most of the options have the same meanings as the corresponding compiler, assembler, and linker options. See the documentation for those tools for an explanation. If an option is available for more than one of the tools, it is set for all tools where it is available. One example for that is <tt/-v/: The compiler, the assembler, and the linker are all called with the <tt/-v/ switch. There are a few remaining options that control the behaviour of cl65: <descrip> <tag><tt>-E</tt></tag> This option is passed to the cc65 compiler; and, it forces cl65 to stop before the assembly step. That means that C-level preprocessor directives are obeyed; and, macroes are expanded. But, the C source isn't compiled. If the <tt/-o/ option isn't used, then the C code results are written into files with a ".i" suffix on their base names. Assembler files, object files, and libraries given on the command line are ignored. <tag><tt>-S</tt></tag> This option forces cl65 to stop before the assembly step. That means that C files are translated into assembler files; but, nothing more is done. Assembler files, object files, and libraries given on the command line are ignored. <tag><tt>-c</tt></tag> This option forces cl65 to stop after the assembly step. That means that C and assembler files given on the command line are translated into object files; but, there is no link step. Object files and libraries given on the command line are ignored. <tag><tt>-o name</tt></tag> The -o option is used for the target name in the final step. That causes problems if the linker will not be called, and there are several input files on the command line. In that case, the name given with -o will be used for all of them, which makes the option pretty useless. You shouldn't use <tt/-o/ when more than one output file is created. <tag><tt>--print-target-path</tt></tag> This option prints the absolute path of the target file directory, and exits then. It is supposed to be used with shell backquotes or the GNU make shell function. That way, you can write build scripts or Makefiles accessing target files without any assumption about the cc65 installation path. <tag><tt>-t sys, --target sys</tt></tag> The default for this option is different from the compiler and linker, in the case that the option is missing: While the other tools (compiler, assembler, and linker) will use the "none" system settings by default, cl65 will use "c64" as a target system by default. That was chosen because most people seem to use cc65 to develop for the C64. <tag><tt>--no-target-lib</tt></tag> This option tells the cl65 to not include the target library into the list of libraries. <tag><tt>-Wa options, --asm-args options</tt></tag> Pass options directly to the assembler. This may be used to pass options that aren't directly supported by cl65. Several options may be separated by commas; the commas are replaced by spaces when passing them to the assembler. Beware: Passing arguments directly to the assembler might interfere with some of the defaults because cl65 doesn't parse the options passed. So, if cl65 supports an option by itself, do not pass that option to the assembler by means of the <tt/-Wa/ switch. <tag><tt>-Wc options, --cc-args options</tt></tag> Pass options directly to the compiler. This may be used to pass options that aren't directly supported by cl65. Several options may be separated by commas; the commas are replaced by spaces when passing them to the compiler. Beware: Passing arguments directly to the compiler might interfere with some of the defaults because cl65 doesn't parse the options passed. So, if cl65 supports an option by itself, do not pass that option to the compiler by means of the <tt/-Wc/ switch. <tag><tt>-Wl options, --ld-args options</tt></tag> Pass options directly to the linker. This may be used to pass options that aren't directly supported by cl65. Several options may be separated by commas; the commas are replaced by spaces when passing them to the linker. Beware: Passing arguments directly to the linker might interfere with some of the defaults because cl65 doesn't parse the options passed. So, if cl65 supports an option by itself, do not pass that option to the linker by means of the <tt/-Wl/ switch. </descrip> <sect>More usage<p> Because cl65 was created to simplify the use of the cc65 development package, it tries to be smart about several things. <itemize> <item> If you don't give a target system on the command line, cl65 defaults to the C64. <item> When linking, cl65 will supply the name of the library file for the target system to the linker; so, you don't have to do that. <item> If the final step is the linker, and the name of the output file was not explicitly given, cl65 will use the name of the first input file without the extension, provided that the name of that file has an extension. So, you don't need to give the executable name in most cases; just give the name of your "main" file as the first input file. </itemize> The command line is parsed from left to right, and the actual processing tool (compiler, assembler, ...) is invoked whenever a file name is encountered. This means that only the options to the left of a file name are in effect when this file is processed. It does also mean that you're able to specify different options for different files on the command line. As an example. <tscreen><verb> cl65 -Oirs main.c -O -g module.c </verb></tscreen> translates main.c with full optimization and module.c with less optimization and debug info enabled. The type of an input file is derived from its extension: <itemize> <item>C files: <tt/.c/ <item>Assembler files: <tt/.s/, <tt/.asm/, <tt/.a65/ <item>Object files: <tt/.o/, <tt/.obj/ <item>Libraries: <tt/.a/, <tt/.lib/ <item>GEOS resource files: <tt/.grc/ <item>o65 files: <tt/.o65/, <tt/.emd/, <tt/.joy/, <tt/.tgi/ </itemize> Please note that the program cannot handle input files with unknown file extensions. <sect>Examples<p> The morse trainer software, which consists of one C file (morse.c) and one assembler file (irq.s) will need the following separate steps to compile into an executable named morse: <tscreen><verb> cc65 -g -Oi -t c64 morse.c ca65 -g morse.s ca65 -g irq.s ld65 -o morse -t c64 c64.o morse.o irq.o c64.lib </verb></tscreen> When using cl65, this is simplified to <tscreen><verb> cl65 -g -Oi morse.c irq.s </verb></tscreen> As a general rule, you may use cl65 instead of cc65 at most times, especially in makefiles to build object files directly from C files. Use <tscreen><verb> .c.o: cl65 -g -Oi $< </verb></tscreen> to do this. <sect>Copyright<p> cl65 (and all cc65 binutils) are (C) Copyright 1998-2004 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> ������������������������������������������������������������������������������cc65-2.18/doc/co65.sgml�����������������������������������������������������������������������������0000664�0000000�0000000�00000030137�13473601511�0014416�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>co65 Users Guide <author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> <abstract> co65 is an object file conversion utility. It converts o65 object files into the native object file format used by the cc65 tool chain. Since o65 is the file format used by cc65 for loadable drivers, the co65 utility allows (among other things) to link drivers statically to the generated executables instead of loading them from disk. </abstract> <!-- Table of contents --> <toc> <!-- Begin the document --> <sect>Overview<p> co65 is an object file conversion utility. It converts o65 object files into assembler files, which may be translated by ca65 to generate object files in the native object file format used by the cc65 tool chain. Since loadable drivers used by the library that comes with cc65 use the o65 relocatable object code format, using the co65 utility allows to link these drivers statically. This enables the use of these drivers without loading additional files from a disk or other secondary storage. Another use would be to link object files generated by other development tools to projects using the cc65 tool chain, but this has not been tested until now, since such tools are currently rare. <sect>Usage<p> The co65 utility converts one o65 file per run into one assembler files in ca65 format. The utility tries to autodetect the type of the o65 input file using the operating system identifier contained in the o65 option list. <sect1>Command line option overview<p> The converter may be called as follows: <tscreen><verb> --------------------------------------------------------------------------- Usage: co65 [options] file Short options: -V Print the version number -g Add debug info to object file -h Help (this text) -m model Override the o65 model -n Don't generate an output file -o name Name the output file -v Increase verbosity Long options: --bss-label name Define and export a BSS segment label --bss-name seg Set the name of the BSS segment --code-label name Define and export a CODE segment label --code-name seg Set the name of the CODE segment --data-label name Define and export a DATA segment label --data-name seg Set the name of the DATA segment --debug-info Add debug info to object file --help Help (this text) --no-output Don't generate an output file --o65-model model Override the o65 model --verbose Increase verbosity --version Print the version number --zeropage-label name Define and export a ZEROPAGE segment label --zeropage-name seg Set the name of the ZEROPAGE segment --------------------------------------------------------------------------- </verb></tscreen> <sect1>Command line options in detail<p> Here is a description of all the command line options: <descrip> <tag><tt>--bss-label name</tt></tag> Set the label used to mark the start of the bss segment. When this option is given, the label is also exported and may be accessed from other code. When accessing such a label from C code, be sure to include the leading underscore. If you don't need to access the bss segment, there's no need to use this option. <tag><tt>--bss-name seg</tt></tag> Set the name of the bss segment. The default name is "BSS" which is compatible with the standard ld65 linker configurations. <tag><tt>--code-label name</tt></tag> Set the label used to mark the start of the code segment. When this option is given, the label is also exported and may be accessed from other code. When accessing such a label from C code, be sure to include the leading underscore. If you don't need to access the code segment, there's no need to use this option. <tag><tt>--code-name seg</tt></tag> Set the name of the code segment. The default name is "CODE" which is compatible with the standard ld65 linker configurations. <tag><tt>--data-label name</tt></tag> Set the label used to mark the start of the data segment. When this option is given, the label is also exported and may be accessed from other code. When accessing such a label from C code, be sure to include the leading underscore. If you don't need to access the data segment, there's no need to use this option. <tag><tt>--data-name seg</tt></tag> Set the name of the data segment. The default name is "DATA" which is compatible with the standard ld65 linker configurations. <tag><tt>-d, --debug</tt></tag> Enables debug mode, something that should not be needed for mere mortals. Currently the converter does only accept cc65 loadable modules generated by ld65 when not in debug mode. Please note that correct conversion has never been tested for o65 files from other sources, so be careful when using <tt/-d/. <tag><tt>-g, --debug-info</tt></tag> This will cause the converter to insert a <tt/.DEBUGINFO/ command into the generated assembler code. This will cause the assembler to include all symbols in a special section in the object file. <tag><tt>-h, --help</tt></tag> Print the short option summary shown above. <tag><tt>-m model, --o65-model model</tt></tag> Set an o65 model. This option changes the way, output is generated for the given o65 file. For example, cc65 loadable drivers have a zero page segment, but this segment must not be defined in the file itself, because the standard module loader will overlay it with the zeropage space used by the application that loads this module. So instead of allocating space in the zero page segment, the converter will reference the start of the zero page area used by the application. Currently, the following models are defined: <itemize> <item>lunix <item>os/a65 <item>cc65-module </itemize> The default is to autodetect the model to use from the input file, so there's rarely a need to use this option. <tag><tt>-n, --no-output</tt></tag> Don't do the actual conversion, just read in the o65 file checking for problems. This option may be used in conjunction with <tt/--verbose/ to view some information about the input file. <tag><tt>-o name</tt></tag> Specify the name of the output file. If you don't specify a name, the name of the o65 input file is used, with the extension replaced by ".s". <tag><tt>-v, --verbose</tt></tag> Using this option, the converter will be somewhat more verbose and print some information about the o65 input file (among other things). You may use this option together with <tt/--no-output/ to just get the o65 info. <tag><tt>-V, --version</tt></tag> Print the version number of the compiler. When submitting a bug report, please include the operating system you're using, and the compiler version. <tag><tt>--zeropage-label name</tt></tag> Set the label used to mark the start of the zeropage segment. When this option is given, the label is also exported and may be accessed from other code. When accessing such a label from C code, be sure to include the leading underscore. If you don't need to access the zeropage segment, there's no need to use this option. <tag><tt>--zeropage-name seg</tt></tag> Set the name of the zeropage segment. The default name is "ZEROPAGE" which is compatible with the standard ld65 linker configurations. </descrip> <sect>Input and output<p> The converter will accept one o65 file per invocation and create a file with the same base name, but with the extension replaced by ".s". The output file contains assembler code suitable for the use with the ca65 macro assembler. <sect>Converting loadable drivers<p> <sect1>Differences between static linking and runtime loading<p> One main use of the utility is conversion of loadable drivers, so they may be linked statically to an application. Statically linking will cause a few things to be different from runtime loading: <itemize> <item> Without changing the segment names, all segments take the default names used by the standard linker configurations. This means that the driver code is no longer contingous in memory, instead the code segment is placed somewhere in between all other code segments, the data segment is placed with all other data segments and so on. If the driver doesn't do strange things this shouldn't be a problem. <item> With statically linked code, data and bss segments will get intialized once (when the application is loaded), while a loadable driver will get its initialization each time the driver is loaded into memory (which may be more than once in the lifetime of a program). It depends on the driver if this is a problem. Currently, most drivers supplied with cc65 behave correctly when linked statically. </itemize> <sect1>Additional requirements<p> All loadable drivers used by cc65 have a header and a jump table at the start of the code segment. The header is needed to detect the driver (it may also contain some data that is necessary to access the driver). The jump table is used to access the functions in the driver code. When loading a driver at runtime, the load address of the driver is also the address of the code segment, so the locations of the header and jump table are known. However, when linking the driver statically, it is up to the programmer to provide this information to the driver API. For this purpose, it is necessary to define a code segment label that can be accessed from the outside later. Please note that the converter does currently <em/not/ create such a label without being ordered to do so, even if the input file is a cc65 module. To create such a label, use the <tt/--code-label/ option when calling the converter. Be sure to begin the label with a leading underscore when accessing it from C code. In your code, define an arbitrary variable with this name. Use the address of this variable as the address of the code segment of the driver. Be sure to never modify the variable which is in reality the start of your driver! <sect1>Example - Convert and link a graphics driver<p> As an example, here are some instructions to convert and use the c64-hi.tgi graphics driver: First, convert the driver, generating a label named "_c64_hi" for the code segment. Use the assembler to generate an object file from the assembler output. <tscreen><verb> co65 --code-label _c64_hi c64-hi.tgi ca65 c64-hi.s </verb></tscreen> Next, change your C code to declare a variable that is actually the address of the driver: <tscreen><verb> extern void c64_hi[]; </verb></tscreen> Instead of loading and unloading the driver, change the code to install and uninstall the driver, which will be already in memory after linking: <tscreen><verb> /* Install the driver */ tgi_install (c64_hi); ... /* Uninstall the driver */ tgi_uninstall (); </verb></tscreen> Don't forget to link the driver object file to your application, otherwise you will get an "undefined external" error for the _c64_hi symbol. <sect>Copyright<p> co65 is (C) Copyright 2003 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> ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/coding.sgml���������������������������������������������������������������������������0000664�0000000�0000000�00000023524�13473601511�0015107�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>cc65 coding hints <author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> <abstract> How to generate the most effective code with cc65. </abstract> <sect>Use prototypes<p> This will not only help to find errors between separate modules, it will also generate better code, since the compiler must not assume that a variable sized parameter list is in place and must not pass the argument count to the called function. This will lead to shorter and faster code. <sect>Don't declare auto variables in nested function blocks<p> Variable declarations in nested blocks are usually a good thing. But with cc65, there is a drawback: Since the compiler generates code in one pass, it must create the variables on the stack each time the block is entered and destroy them when the block is left. This causes a speed penalty and larger code. <sect>Remember that the compiler does no high level optimizations<p> The compiler needs hints from you about the code to generate. It will try to optimize the generated code, but follow the outline you gave in your C program. So for example, when accessing indexed data structures, get a pointer to the element and use this pointer instead of calculating the index again and again. If you want to have your loops unrolled, or loop invariant code moved outside the loop, you have to do that yourself. <sect>Longs are slow!<p> While long support is necessary for some things, it's really, really slow on the 6502. Remember that any long variable will use 4 bytes of memory, and any operation works on double the data compared to an int. <sect>Use unsigned types wherever possible<p> The 6502 CPU has no opcodes to handle signed values greater than 8 bit. So sign extension, test of signedness etc. has to be done with extra code. As a consequence, the code to handle signed operations is usually a bit larger and slower than the same code for unsigned types. <sect>Use chars instead of ints if possible<p> While in arithmetic operations, chars are immidiately promoted to ints, they are passed as chars in parameter lists and are accessed as chars in variables. The code generated is usually not much smaller, but it is faster, since accessing chars is faster. For several operations, the generated code may be better if intermediate results that are known not to be larger than 8 bit are casted to chars. You should especially use unsigned chars for loop control variables if the loop is known not to execute more than 255 times. <sect>Make the size of your array elements one of 1, 2, 4, 8<p> When indexing into an array, the compiler has to calculate the byte offset into the array, which is the index multiplied by the size of one element. When doing the multiplication, the compiler will do a strength reduction, that is, replace the multiplication by a shift if possible. For the values 2, 4 and 8, there are even more specialized subroutines available. So, array access is fastest when using one of these sizes. <sect>Expressions are evaluated from left to right<p> Since cc65 is not building an explicit expression tree when parsing an expression, constant subexpressions may not be detected and optimized properly if you don't help. Look at this example: <tscreen><verb> #define OFFS 4 int i; i = i + OFFS + 3; </verb></tscreen> The expression is parsed from left to right, that means, the compiler sees 'i', and puts it contents into the secondary register. Next is OFFS, which is constant. The compiler emits code to add a constant to the secondary register. Same thing again for the constant 3. So the code produced contains a fetch of 'i', two additions of constants, and a store (into 'i'). Unfortunately, the compiler does not see, that "OFFS + 3" is a constant for itself, since it does its evaluation from left to right. There are some ways to help the compiler to recognize expression like this: <enum> <item>Write "i = OFFS + 3 + i;". Since the first and second operand are constant, the compiler will evaluate them at compile time reducing the code to a fetch, one addition (secondary + constant) and one store. <item>Write "i = i + (OFFS + 3)". When seeing the opening parenthesis, the compiler will start a new expression evaluation for the stuff in the braces, and since all operands in the subexpression are constant, it will detect this and reduce the code to one fetch, one addition and one store. </enum> <sect>Use the preincrement and predecrement operators<p> The compiler is not always smart enough to figure out, if the rvalue of an increment is used or not. So it has to save and restore that value when producing code for the postincrement and postdecrement operators, even if this value is never used. To avoid the additional overhead, use the preincrement and predecrement operators if you don't need the resulting value. That means, use <tscreen><verb> ... ++i; ... </verb></tscreen> instead of <tscreen><verb> ... i++; ... </verb></tscreen> <sect>Use constants to access absolute memory locations<p> The compiler produces optimized code, if the value of a pointer is a constant. So, to access direct memory locations, use <tscreen><verb> #define VDC_STATUS 0xD601 *(char*)VDC_STATUS = 0x01; </verb></tscreen> That will be translated to <tscreen><verb> lda #$01 sta $D601 </verb></tscreen> The constant value detection works also for struct pointers and arrays, if the subscript is a constant. So <tscreen><verb> #define VDC ((unsigned char*)0xD600) #define STATUS 0x01 VDC[STATUS] = 0x01; </verb></tscreen> will also work. If you first load the constant into a variable and use that variable to access an absolute memory location, the generated code will be much slower, since the compiler does not know anything about the contents of the variable. <sect>Use initialized local variables<p> Initialization of local variables when declaring them gives shorter and faster code. So, use <tscreen><verb> int i = 1; </verb></tscreen> instead of <tscreen><verb> int i; i = 1; </verb></tscreen> But beware: To maximize your savings, don't mix uninitialized and initialized variables. Create one block of initialized variables and one of uniniitalized ones. The reason for this is, that the compiler will sum up the space needed for uninitialized variables as long as possible, and then allocate the space once for all these variables. If you mix uninitialized and initialized variables, you force the compiler to allocate space for the uninitialized variables each time, it parses an initialized one. So do this: <tscreen><verb> int i, j; int a = 3; int b = 0; </verb></tscreen> instead of <tscreen><verb> int i; int a = 3; int j; int b = 0; </verb></tscreen> The latter will work, but will create larger and slower code. <sect>Use the array operator [] even for pointers<p> When addressing an array via a pointer, don't use the plus and dereference operators, but the array operator. This will generate better code in some common cases. Don't use <tscreen><verb> char* a; char b, c; char b = *(a + c); </verb></tscreen> Use <tscreen><verb> char* a; char b, c; char b = a[c]; </verb></tscreen> instead. <sect>Use register variables with care<p> Register variables may give faster and shorter code, but they do also have an overhead. Register variables are actually zero page locations, so using them saves roughly one cycle per access. The calling routine may also use register variables, so the old values have to be saved on function entry and restored on exit. Saving an d restoring has an overhead of about 70 cycles per 2 byte variable. It is easy to see, that - apart from the additional code that is needed to save and restore the values - you need to make heavy use of a variable to justify the overhead. As a general rule: Use register variables only for pointers that are dereferenced several times in your function, or for heavily used induction variables in a loop (with several 100 accesses). When declaring register variables, try to keep them together, because this will allow the compiler to save and restore the old values in one chunk, and not in several. And remember: Register variables must be enabled with <tt/-r/ or <tt/-Or/. <sect>Decimal constants greater than 0x7FFF are actually long ints<p> The language rules for constant numeric values specify that decimal constants without a type suffix that are not in integer range must be of type long int or unsigned long int. So a simple constant like 40000 is of type long int! This is often unexpected and may cause an expression to be evaluated with 32 bits. While in many cases the compiler takes care about it, in some places it can't. So be careful when you get a warning like <tscreen><verb> test.c(7): Warning: Constant is long </verb></tscreen> Use the <tt/U/, <tt/L/ or <tt/UL/ suffixes to tell the compiler the desired type of a numeric constant. <sect>Access to parameters in variadic functions is expensive<p> Since cc65 has the "wrong" calling order, the location of the fixed parameters in a variadic function (a function with a variable parameter list) depends on the number and size of variable arguments passed. Since this number and size is unknown at compile time, the compiler will generate code to calculate the location on the stack when needed. Because of this additional code, accessing the fixed parameters in a variadic function is much more expensive than access to parameters in a "normal" function. Unfortunately, this additional code is also invisible to the programmer, so it is easy to forget. As a rule of thumb, if you access such a parameter more than once, you should think about copying it into a normal variable and using this variable instead. </article> ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/creativision.sgml���������������������������������������������������������������������0000664�0000000�0000000�00000010644�13473601511�0016342�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>VTech Creativision (aka Funvision) specific information for cc65 <author><url url="mailto:polluks+cc65@sdf.lonestar.org" name="Stefan A. Haubenthal"> <abstract> An overview over the Creativision 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 Creativision runtime system as it comes with the cc65 C compiler. It describes the memory layout, Creativision specific header files, available drivers, and any pitfalls specific to that platform. Please note that Creativision 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 Creativision target is a 4 KB ROM image. To create an 8 KB ROM a custom linker script has to be used. <sect>Memory layout<p> cc65 generated programs with the default setup are 4 KB in size, occupying $B000 - $BFFF. Usable memory space for the user program is $B000 - $BEFF. $BF00 - $BFFF is reserved for the runtime and cartridge configuration area. Special locations: <descrip> <tag/Text screen/ The text screen is located at VRAM $1000. <tag/Stack/ The C runtime stack is located at $03FF and growing downwards. <tag/RAM/ The available RAM for cc65 programs of an unexpanded Creativision starts at $01FA and ends at $03FF. <tag/Heap/ The C heap is located at the end of the program's data area and grows towards the C runtime stack. </descrip><p> <sect>Platform specific header files<p> Programs containing Creativision specific code may use the <tt/creativision.h/ header file. <sect1>Creativision specific functions<p> <itemize> <item>bios_playsound <item>psg_delay <item>psg_outb <item>psg_silence </itemize> <!--<sect1>Hardware access<p> The following pseudo variables declared in the <tt/creativision.inc/ include file do allow access to hardware located in the address space. <descrip> <tag><tt/VDP/</tag> The <tt/VDP/ defines allow access to the video chip. </descrip><p> <descrip> <tag><tt/PIA/</tag> The <tt/PIA/ defines allow access to the I/O chip. </descrip><p>--> <sect>Loadable drivers<p> <sect1>Graphics drivers<p> No graphics drivers are currently available for the Creativision. <sect1>Extended memory drivers<p> No extended memory drivers are currently available for the Creativision. <sect1>Joystick drivers<p> <descrip> <tag><tt/creativision-stdjoy.joy (creativisionstd_joy)/</tag> A joystick driver for the standard joystick is available. </descrip><p> <sect1>Mouse drivers<p> No mouse drivers are currently available for the Creativision. <sect1>RS232 device drivers<p> No communication port drivers are currently available for the Creativision. <sect>Limitations<p> <sect1>Disk I/O<p> The existing library for the Creativision doesn't implement C file I/O. There are even 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>fclose <item>fopen <item>fread <item>fprintf <item>fputc <item>fscanf <item>fwrite <item>... </itemize> <sect>Other hints<p> <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> ��������������������������������������������������������������������������������������������cc65-2.18/doc/customizing.sgml����������������������������������������������������������������������0000664�0000000�0000000�00000073262�13473601511�0016223�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>Defining a Custom cc65 Target <author>Bruce Reidenbach <abstract> This section provides step-by-step instructions on how to use the cc65 toolset for a custom hardware platform (a target system not currently supported by the cc65 library set). </abstract> <!-- Table of contents --> <toc> <!-- Begin the document --> <sect>Overview<p> The cc65 toolset provides a set of pre-defined libraries that allow the user to target the executable image to a variety of hardware platforms. In addition, the user can create a customized environment so that the executable can be targeted to a custom platform. The following instructions provide step-by-step instructions on how to customize the toolset for a target that is not supported by the standard cc65 installation. The platform used in this example is a Xilinx Field Programmable Gate Array (FPGA) with an embedded 65C02 core. The processor core supports the additional opcodes/addressing modes of the 65SC02, along with the STP and WAI instructions. These instructions will create a set of files to create a custom target, named SBC, for <bf>S</bf>ingle <bf>B</bf>oard <bf>C</bf>omputer. <sect>System Memory Map Definition<p> The targeted system uses block RAM contained on the XILINX FPGA for the system memory (both RAM and ROM). The block RAMs are available in various aspect ratios, and they will be used in this system as 2K*8 devices. There will be two RAMs used for data storage, starting at location $0000 and growing upwards. There will be one ROM (realized as initialized RAM) used code storage, starting at location $FFFF and growing downwards. The cc65 toolset requires a memory configuration file to define the memory that is available to the cc65 run-time environment, which is defined as follows: <tscreen><code> MEMORY { ZP: start = $0, size = $100, type = rw, define = yes; RAM: start = $200, size = $0E00, define = yes; ROM: start = $F800, size = $0800, file = %O; } </code></tscreen> ZP defines the available zero page locations, which in this case starts at $0 and has a length of $100. Keep in mind that certain systems may require access to some zero page locations, so the starting address may need to be adjusted accordingly to prevent cc65 from attempting to reuse those locations. Also, at a minimum, the cc65 run-time environment uses 26 zero page locations, so the smallest zero page size that can be specified is $1A. The usable RAM memory area begins after the 6502 stack storage in page 1, so it is defined as starting at location $200 and filling the remaining 4K of space (4096 - 2 * 256 = 3584 = $0E00). The 2K of ROM space begins at address $F800 and goes to $FFFF (size = $0800). Next, the memory segments within the memory devices need to be defined. A standard segment definition is used, with one notable exception. The interrupt and reset vector locations need to be defined at locations $FFFA through $FFFF. A special segment named VECTORS is defined that resides at these locations. Later, the interrupt vector map will be created and placed in the VECTORS segment, and the linker will put these vectors at the proper memory locations. The segment definition is: <tscreen><code> SEGMENTS { ZEROPAGE: load = ZP, type = zp, define = yes; DATA: load = ROM, type = rw, define = yes, run = RAM; BSS: load = RAM, type = bss, define = yes; HEAP: load = RAM, type = bss, optional = yes; STARTUP: load = ROM, type = ro; ONCE: load = ROM, type = ro, optional = yes; CODE: load = ROM, type = ro; RODATA: load = ROM, type = ro; VECTORS: load = ROM, type = ro, start = $FFFA; } </code></tscreen> The meaning of each of these segments is as follows. <p><tt> ZEROPAGE: </tt>Data in page 0, defined by ZP as starting at $0 with length $100 <p><tt> DATA: </tt>Initialized data that can be modified by the program, stored in RAM <p><tt> BSS: </tt>Uninitialized data stored in RAM (used for variable storage) <p><tt> HEAP: </tt>Uninitialized C-level heap storage in RAM, optional <p><tt> STARTUP: </tt>The program initialization code, stored in ROM <p><tt> ONCE: </tt>The code run once to initialize the system, stored in ROM <p><tt> CODE: </tt>The program code, stored in ROM <p><tt> RODATA: </tt>Initialized data that cannot be modified by the program, stored in ROM <p><tt> VECTORS: </tt>The interrupt vector table, stored in ROM at location $FFFA A note about initialized data: any variables that require an initial value, such as external (global) variables, require that the initial values be stored in the ROM code image. However, variables stored in ROM cannot change; therefore the data must be moved into variables that are located in RAM. Specifying <tt>run = RAM</tt> as part of the DATA segment definition will indicate that those variables will require their initialization value to be copied via a call to the <tt>copydata</tt> routine in the startup assembly code. In addition, there are system level variables that will need to be initialized as well, especially if the heap segment is used via a C-level call to <tt>malloc ()</tt>. The final section of the definition file contains the data constructors and destructors used for system startup. In addition, if the heap is used, the maximum C-level stack size needs to be defined in order for the system to be able to reliably allocate blocks of memory. The stack size selection must be greater than the maximum amount of storage required to run the program, keeping in mind that the C-level subroutine call stack and all local variables are stored in this stack. The <tt>FEATURES</tt> section defines the required constructor/destructor attributes and the <tt>SYMBOLS</tt> section defines the stack size. The constructors will be run via a call to <tt>initlib</tt> in the startup assembly code and the destructors will be run via an assembly language call to <tt>donelib</tt> during program termination. <tscreen><code> FEATURES { CONDES: segment = STARTUP, type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__; CONDES: segment = STARTUP, type = destructor, label = __DESTRUCTOR_TABLE__, count = __DESTRUCTOR_COUNT__; } SYMBOLS { # Define the stack size for the application __STACKSIZE__: value = $0200, weak = yes; } </code></tscreen> These definitions are placed in a file named "sbc.cfg" and are referred to during the ld65 linker stage. <sect>Startup Code Definition<p> In the cc65 toolset, a startup routine must be defined that is executed when the CPU is reset. This startup code is marked with the STARTUP segment name, which was defined in the system configuration file as being in read only memory. The standard convention used in the predefined libraries is that this code is resident in the crt0 module. For this custom system, all that needs to be done is to perform a little bit of 6502 housekeeping, set up the C-level stack pointer, initialize the memory storage, and call the C-level routine <tt>main ()</tt>. The following code was used for the crt0 module, defined in the file "crt0.s": <tscreen><code> ; --------------------------------------------------------------------------- ; crt0.s ; --------------------------------------------------------------------------- ; ; Startup code for cc65 (Single Board Computer version) .export _init, _exit .import _main .export __STARTUP__ : absolute = 1 ; Mark as startup .import __RAM_START__, __RAM_SIZE__ ; Linker generated .import copydata, zerobss, initlib, donelib .include "zeropage.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__) STA sp LDA #>(__RAM_START__ + __RAM_SIZE__) STA sp+1 ; --------------------------------------------------------------------------- ; Initialize memory storage JSR zerobss ; Clear BSS segment JSR copydata ; Initialize DATA segment JSR initlib ; Run constructors ; --------------------------------------------------------------------------- ; Call main() JSR _main ; --------------------------------------------------------------------------- ; Back from main (this is also the _exit entry): force a software break _exit: JSR donelib ; Run destructors BRK </code></tscreen> The following discussion explains the purpose of several important assembler level directives in this file. <tscreen><verb> .export _init, _exit </verb></tscreen> This line instructs the assembler that the symbols <tt>_init</tt> and <tt>_exit</tt> are to be accessible from other modules. In this example, <tt>_init</tt> is the location that the CPU should jump to when reset, and <tt>_exit</tt> is the location that will be called when the program is finished. <tscreen><verb> .import _main </verb></tscreen> This line instructs the assembler to import the symbol <tt>_main</tt> from another module. cc65 names all C-level routines as {underscore}{name} in assembler, thus the <tt>main ()</tt> routine in C is named <tt>_main</tt> in the assembler. This is how the startup code will link to the C-level code. <tscreen><verb> .export __STARTUP__ : absolute = 1 ; Mark as startup </verb></tscreen> This line marks this code as startup code (code that is executed when the processor is reset), which will then be automatically linked into the executable code. <tscreen><verb> .import __RAM_START__, __RAM_SIZE__ ; Linker generated </verb></tscreen> This line imports the RAM starting address and RAM size constants, which are used to initialize the cc65 C-level argument stack pointer. <tscreen><verb> .segment "STARTUP" </verb></tscreen> This line instructs the assembler that the code is to be placed in the STARTUP segment of memory. <tscreen><verb> JSR zerobss ; Clear BSS segment JSR copydata ; Initialize DATA segment JSR initlib ; Run constructors </verb></tscreen> These three lines initialize the external (global) and system variables. The first line sets the BSS segment -- the memory locations used for external variables -- to 0. The second line copies the initialization value stored in ROM to the RAM locations used for initialized external variables. The last line runs the constructors that are used to initialize the system run-time variables. <tscreen><verb> JSR _main </verb></tscreen> This is the actual call to the C-level <tt>main ()</tt> routine, which is called after the startup code completes. <tscreen><verb> _exit: JSR donelib ; Run destructors BRK </verb></tscreen> This is the code that will be executed when <tt>main ()</tt> terminates. The first thing that must be done is run the destructors via a call to <tt>donelib</tt>. Then the program can terminate. In this example, the program is expected to run forever. Therefore, there needs to be a way of indicating when something has gone wrong and the system needs to be shut down, requiring a restart only by a hard reset. The BRK instruction will be used to indicate a software fault. This is advantageous because cc65 uses the BRK instruction as the fill byte in the final binary code. In addition, the hardware has been designed to force the data lines to $00 for all illegal memory accesses, thereby also forcing a BRK instruction into the CPU. <sect>Custom Run-Time Library Creation<p> The next step in customizing the cc65 toolset is creating a run-time library for the targeted hardware. The easiest way to do this is to modify a standard library from the cc65 distribution. In this example, there is no console I/O, mouse, joystick, etc. in the system, so it is most appropriate to use the simplest library as the base, which is for the Watara Supervision and is named "supervision.lib" in the lib directory of the distribution. The only modification required is to replace the <tt>crt0</tt> module in the supervision.lib library with custom startup code. This is simply done by first copying the library and giving it a new name, compiling the startup code with ca65, and finally using the ar65 archiver to replace the module in the new library. The steps are shown below: <tscreen><verb> $ copy "C:\Program Files\cc65\lib\supervision.lib" sbc.lib $ ca65 crt0.s $ ar65 a sbc.lib crt0.o </verb></tscreen> <sect>Interrupt Service Routine Definition<p> For this system, the CPU is put into a wait condition prior to allowing interrupt processing. Therefore, the interrupt service routine is very simple: return from all valid interrupts. However, as mentioned before, the BRK instruction is used to indicate a software fault, which will call the same interrupt service routine as the maskable interrupt signal IRQ. The interrupt service routine must be able to tell the difference between the two, and act appropriately. The interrupt service routine shown below includes code to detect when a BRK instruction has occurred and stops the CPU from further processing. The interrupt service routine is in a file named "interrupt.s". <tscreen><code> ; --------------------------------------------------------------------------- ; interrupt.s ; --------------------------------------------------------------------------- ; ; Interrupt handler. ; ; Checks for a BRK instruction and returns from all valid interrupts. .import _stop .export _irq_int, _nmi_int .segment "CODE" .PC02 ; Force 65C02 assembly mode ; --------------------------------------------------------------------------- ; Non-maskable interrupt (NMI) service routine _nmi_int: RTI ; Return from all NMI interrupts ; --------------------------------------------------------------------------- ; Maskable interrupt (IRQ) service routine _irq_int: PHX ; Save X register contents to stack TSX ; Transfer stack pointer to X PHA ; Save accumulator contents to stack INX ; Increment X so it points to the status INX ; register value saved on the stack LDA $100,X ; Load status register contents AND #$10 ; Isolate B status bit BNE break ; If B = 1, BRK detected ; --------------------------------------------------------------------------- ; IRQ detected, return irq: PLA ; Restore accumulator contents PLX ; Restore X register contents RTI ; Return from all IRQ interrupts ; --------------------------------------------------------------------------- ; BRK detected, stop break: JMP _stop ; If BRK is detected, something very bad ; has happened, so stop running </code></tscreen> The following discussion explains the purpose of several important assembler level directives in this file. <tscreen><verb> .import _stop </verb></tscreen> This line instructs the assembler to import the symbol <tt>_stop</tt> from another module. This routine will be called if a BRK instruction is encountered, signaling a software fault. <tscreen><verb> .export _irq_int, _nmi_int </verb></tscreen> This line instructs the assembler that the symbols <tt>_irq_int</tt> and <tt>_nmi_int</tt> are to be accessible from other modules. In this example, the address of these symbols will be placed in the interrupt vector table. <tscreen><verb> .segment "CODE" </verb></tscreen> This line instructs the assembler that the code is to be placed in the CODE segment of memory. Note that because there are 65C02 mnemonics in the assembly code, the assembler is forced to use the 65C02 instruction set with the <tt>.PC02</tt> directive. The final step is to define the interrupt vector memory locations. Recall that a segment named VECTORS was defined in the memory configuration file, which started at location $FFFA. The addresses of the interrupt service routines from "interrupt.s" along with the address for the initialization code in crt0 are defined in a file named "vectors.s". Note that these vectors will be placed in memory in their proper little-endian format as: <p><tt> $FFFA - $FFFB:</tt> NMI interrupt vector (low byte, high byte) <p><tt> $FFFC - $FFFD:</tt> Reset vector (low byte, high byte) <p><tt> $FFFE - $FFFF:</tt> IRQ/BRK interrupt vector (low byte, high byte) using the <tt>.addr</tt> assembler directive. The contents of the file are: <tscreen><code> ; --------------------------------------------------------------------------- ; vectors.s ; --------------------------------------------------------------------------- ; ; Defines the interrupt vector table. .import _init .import _nmi_int, _irq_int .segment "VECTORS" .addr _nmi_int ; NMI vector .addr _init ; Reset vector .addr _irq_int ; IRQ/BRK vector </code></tscreen> The cc65 toolset will replace the address symbols defined here with the actual addresses of the routines during the link process. <sect>Adding Custom Instructions<p> The cc65 instruction set only supports the WAI (Wait for Interrupt) and STP (Stop) instructions when used with the 65816 CPU (accessed via the --cpu command line option of the ca65 macro assembler). The 65C02 core used in this example supports these two instructions, and in fact the system benefits from the use of both the WAI and STP instructions. In order to use the WAI instruction in this case, a C routine named "wait" was created that consists of the WAI opcode followed by a subroutine return. It was convenient in this example to put the IRQ interrupt enable in this subroutine as well, since interrupts should only be enabled when the code is in this wait condition. For both the WAI and STP instructions, the assembler is "fooled" into placing those opcodes into memory by inserting a single byte of data that just happens to be the opcode for those instructions. The assembly code routines are placed in a file, named "wait.s", which is shown below: <tscreen><code> ; --------------------------------------------------------------------------- ; wait.s ; --------------------------------------------------------------------------- ; ; Wait for interrupt and return .export _wait, _stop ; --------------------------------------------------------------------------- ; Wait for interrupt: Forces the assembler to emit a WAI opcode ($CB) ; --------------------------------------------------------------------------- .segment "CODE" .proc _wait: near CLI ; Enable interrupts .byte $CB ; Inserts a WAI opcode RTS ; Return to caller .endproc ; --------------------------------------------------------------------------- ; Stop: Forces the assembler to emit a STP opcode ($DB) ; --------------------------------------------------------------------------- .proc _stop: near .byte $DB ; Inserts a STP opcode .endproc </code></tscreen> The label <tt>_wait</tt>, when exported, can be called by using the <tt>wait ()</tt> subroutine call in C. The section is marked as code so that it will be stored in read-only memory, and the procedure is tagged for 16-bit absolute addressing via the "near" modifier. Similarly, the <tt>_stop</tt> routine can be called from within the C-level code via a call to <tt>stop ()</tt>. In addition, the routine can be called from assembly code by calling <tt>_stop</tt> (as was done in the interrupt service routine). <sect>Hardware Drivers<p> Oftentimes, it can be advantageous to create small application helpers in assembly language to decrease codespace and increase execution speed of the overall program. An example of this would be the transfer of characters to a FIFO (<bf>F</bf>irst-<bf>I</bf>n, <bf>F</bf>irst-<bf>O</bf>ut) storage buffer for transmission over a serial port. This simple action could be performed by an assembly language driver which would execute much quicker than coding it in C. The following discussion outlines a method of interfacing a C program with an assembly language subroutine. 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__/ 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. 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 and X. When the subroutine is finished, the values on the stack must be popped off and discarded via a jump to <tt>incsp2</tt>, which includes the RTS subroutine return command. This is shown in the following code sample. Calling sequence: <tscreen><verb> lda #<(L0001) ; Load A with the high order byte ldx #>(L0001) ; Load X with the low order byte jsr pushax ; Push A and X onto the stack jsr _foo ; Call foo, i.e., foo (arg) </verb></tscreen> Subroutine code: <tscreen><verb> _foo: jsr ldax0sp ; Retrieve A and X from the stack sta ptr ; Store A in ptr stx ptr+1 ; Store X in ptr+1 ... ; (more subroutine code goes here) jmp incsp2 ; Pop A and X from the stack (includes return) </verb></tscreen> 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. Furthermore, the subroutine can be terminated with an RTS statement since there is no stack cleanup which needs to be performed. This is shown in the following code sample. Calling sequence: <tscreen><verb> lda #<(L0001) ; Load A with the high order byte ldx #>(L0001) ; Load X with the low order byte jsr _foo ; Call foo, i.e., foo (arg) </verb></tscreen> Subroutine code: <tscreen><verb> _foo: sta ptr ; Store A in ptr stx ptr+1 ; Store X in ptr+1 ... ; (more subroutine code goes here) rts ; Return from subroutine </verb></tscreen> The hardware driver in this example writes a string of character data to a hardware FIFO located at memory location $1000. Each character is read and is compared to the C string termination value ($00), which will terminate the loop. All other character data is written to the FIFO. For convenience, a carriage return/line feed sequence is automatically appended to the serial stream. The driver defines a local pointer variable which is stored in the zero page memory space in order to allow for retrieval of each character in the string via the indirect indexed addressing mode. The assembly language routine is stored in a file names "rs232_tx.s" and is shown below: <tscreen><code> ; --------------------------------------------------------------------------- ; rs232_tx.s ; --------------------------------------------------------------------------- ; ; Write a string to the transmit UART FIFO .export _rs232_tx .exportzp _rs232_data: near .define TX_FIFO $1000 ; Transmit FIFO memory location .zeropage _rs232_data: .res 2, $00 ; Reserve a local zero page pointer .segment "CODE" .proc _rs232_tx: near ; --------------------------------------------------------------------------- ; Store pointer to zero page memory and load first character sta _rs232_data ; Set zero page pointer to string address stx _rs232_data+1 ; (pointer passed in via the A/X registers) ldy #00 ; Initialize Y to 0 lda (_rs232_data) ; Load first character ; --------------------------------------------------------------------------- ; Main loop: read data and store to FIFO until \0 is encountered loop: sta TX_FIFO ; Loop: Store character in FIFO iny ; Increment Y index lda (_rs232_data),y ; Get next character bne loop ; If character == 0, exit loop ; --------------------------------------------------------------------------- ; Append CR/LF to output stream and return lda #$0D ; Store CR sta TX_FIFO lda #$0A ; Store LF sta TX_FIFO rts ; Return .endproc </code></tscreen> <sect>Hello World! Example<p> The following short example demonstrates programming in C using the cc65 toolset with a custom run-time environment. In this example, a Xilinx FPGA contains a UART which is connected to a 65c02 processor with FIFO (<bf>F</bf>irst-<bf>I</bf>n, <bf>F</bf>irst-<bf>O</bf>ut) storage to buffer the data. The C program will wait for an interrupt generated by the receive UART and then respond by transmitting the string "Hello World! " every time a question mark character is received via a call to the hardware driver <tt>rs232_tx ()</tt>. The driver prototype uses the <tt>__fastcall__</tt> extension to indicate that the driver does not use the stack. The FIFO data interface is at address $1000 and is defined as the symbolic constant <tt>FIFO_DATA</tt>. Writing to <tt>FIFO_DATA</tt> transfers a byte of data into the transmit FIFO for subsequent transmission over the serial interface. Reading from <tt>FIFO_DATA</tt> transfers a byte of previously received data out of the receive FIFO. The FIFO status data is at address $1001 and is defined as the symbolic constant <tt>FIFO_STATUS</tt>. For convenience, the symbolic constants <tt>TX_FIFO_FULL</tt> (which isolates bit 0 of the register) and <tt>RX_FIFO_EMPTY</tt> (which isolates bit 1 of the register) have been defined to read the FIFO status. The following C code is saved in the file "main.c". As this example demonstrates, the run-time environment has been set up such that all of the behind-the-scene work is transparent to the user. <tscreen><code> #define FIFO_DATA (*(unsigned char *) 0x1000) #define FIFO_STATUS (*(unsigned char *) 0x1001) #define TX_FIFO_FULL (FIFO_STATUS & 0x01) #define RX_FIFO_EMPTY (FIFO_STATUS & 0x02) extern void wait (); extern void __fastcall__ rs232_tx (char *str); int main () { while (1) { // Run forever wait (); // Wait for an RX FIFO interrupt while (RX_FIFO_EMPTY == 0) { // While the RX FIFO is not empty if (FIFO_DATA == '?') { // Does the RX character = '?' rs232_tx ("Hello World!"); // Transmit "Hello World!" } // Discard any other RX characters } } return (0); // We should never get here! } </code></tscreen> <sect>Putting It All Together<p> The following commands will create a ROM image named "a.out" that can be used as the initialization data for the Xilinx Block RAM used for code storage: <tscreen><verb> $ cc65 -t none -O --cpu 65sc02 main.c $ ca65 --cpu 65sc02 main.s $ ca65 --cpu 65sc02 rs232_tx.s $ ca65 --cpu 65sc02 interrupt.s $ ca65 --cpu 65sc02 vectors.s $ ca65 --cpu 65sc02 wait.s $ ld65 -C sbc.cfg -m main.map interrupt.o vectors.o wait.o rs232_tx.o main.o sbc.lib </verb></tscreen> During the C-level code compilation phase (<tt>cc65</tt>), assumptions about the target system are disabled via the <tt>-t none</tt> command line option. During the object module linker phase (<tt>ld65</tt>), the target customization is enabled via inclusion of the <tt>sbc.lib</tt> file and the selection of the configuration file via the <tt>-C sbc.cfg</tt> command line option. The 65C02 core used most closely matches the cc65 toolset processor named 65SC02 (the 65C02 extensions without the bit manipulation instructions), so all the commands specify the use of that processor via the <tt>--cpu 65sc02</tt> option. </article> ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/da65.sgml�����������������������������������������������������������������������������0000664�0000000�0000000�00000062111�13473601511�0014376�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>da65 Users Guide <author> <url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline> <url url="mailto:greg.king5@verizon.net" name="Greg King"> <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 feeding into ca65, the macro assembler supplied with the cc65 C compiler. </abstract> <!-- Table of contents --> <toc> <!-- Begin the document --> <sect>Overview<p> da65 is a disassembler for 6502/65C02 code. It is supplied as a utility with 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, for improved results. This information may include the location and size of tables, and their format. One nice advantage of this concept is that disassembly of copyrighted binaries may be handled without problems: One can just pass the information file for disassembling the binary, so everyone with a legal copy of the binary can generate a nicely formatted disassembly with readable labels and other information. <sect>Usage<p> <sect1>Command line option overview<p> The assembler accepts the following options: <tscreen><verb> --------------------------------------------------------------------------- Usage: da65 [options] [inputfile] Short options: -g Add debug info to object file -h Help (this text) -i name Specify an info file -o name Name the output file -v Increase verbosity -F Add formfeeds to the output -s Accept line markers in the info file -S addr Set the start/load address -V Print the disassembler version Long options: --argument-column n Specify argument start column --comment-column n Specify comment start column --comments n Set the comment level for the output --cpu type Set cpu type --debug-info Add debug info to object file --formfeeds Add formfeeds to the output --help Help (this text) --hexoffs Use hexadecimal label offsets --info name Specify an info file --label-break n Add newline if label exceeds length n --mnemonic-column n Specify mnemonic start column --pagelength n Set the page length for the listing --start-addr addr Set the start/load address --sync-lines Accept line markers in the info file --text-column n Specify text start column --verbose Increase verbosity --version Print the disassembler version --------------------------------------------------------------------------- </verb></tscreen> <sect1>Command line options in detail<p> Here is a description of all the command line options: <descrip> <label id="option--argument-column"> <tag><tt>--argument-column n</tt></tag> Specifies the column where the argument for a mnemonic or pseudo instruction starts. <label id="option--comment-column"> <tag><tt>--comment-column n</tt></tag> Specifies the column where the comment for an instruction starts. <label id="option--comments"> <tag><tt>--comments n</tt></tag> Set the comment level for the output. Valid arguments are 0..4. Greater values will increase the level of additional information written to the output file in form of comments. <label id="option--cpu"> <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 <item>4510 </itemize> 6502x is for the NMOS 6502 with unofficial opcodes. huc6280 is the CPU of the PC engine. 4510 is the CPU of the Commodore C65. Support for the 65816 currently is not available. <label id="option--formfeeds"> <tag><tt>-F, --formfeeds</tt></tag> Add formfeeds to the generated output. This feature is useful together with the <tt><ref id="option--pagelength" name="--pagelength"></tt> option. If <tt/--formfeeds/ is given, a formfeed is added to the output after each page. <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 re-assembling the generated output. <tag><tt>-h, --help</tt></tag> Print the short option summary shown above. <label id="option--hexoffs"> <tag><tt>--hexoffs</tt></tag> Output label offsets in hexadecimal instead of decimal notation. <label id="option--info"> <tag><tt>-i name, --info name</tt></tag> Specify an info file. The info file contains global options that may override or replace command line options plus informations about the code that has to be disassembled. See the separate section <ref id="infofile" name="Info File Format">. <label id="option-o"> <tag><tt>-o name</tt></tag> Specify a name for an output file. The default is to use <tt/stdout/, so without this switch or the corresponding <ref id="global-options" name="global option"> <tt><ref id="OUTPUTNAME" name="OUTPUTNAME"></tt>, the output will go to the terminal. <label id="option--label-break"> <tag><tt>--label-break n</tt></tag> Adds a newline if the length of a label exceeds the given length. Note: If the label would run into the code in the mid column, a linefeed is always inserted regardless of this setting. This option overrides the <ref id="global-options" name="global option"> <tt><ref id="LABELBREAK" name="LABELBREAK"></tt>. <label id="option--mnemonic-column"> <tag><tt>--mnemonic-column n</tt></tag> Specifies the column where a mnemonic or pseudo instrcuction is output. <label id="option--pagelength"> <tag><tt>--pagelength n</tt></tag> Sets the length of a listing page in lines. After this number of lines, a new page header is generated. If the <tt><ref id="option--formfeeds" name="--formfeeds"></tt> is also given, a formfeed is inserted before generating the page header. A value of zero for the page length will disable paging of the output. <label id="option--start-addr"> <tag><tt>-S addr, --start-addr addr</tt></tag> Specify the start/load address of the binary code that is going to be disassembled. The given address is interpreted as an octal value if preceded with a '0' digit, as a hexadecimal value if preceded with '0x', '0X', or '$', and as a decimal value in all other cases. If no start address is specified, $10000 minus the size of the input file is used. <label id="option--sync-lines"> <tag><tt>-s, --sync-lines</tt></tag> Accept line markers in the info file in the following syntax: <tscreen><verb> #line <lineno> ["<filename>"] # <lineno> "<filename>" [<flag>] ... </verb></tscreen> This option is intended for preprocessing info files with "cpp" or "m4". <label id="option--text-column"> <tag><tt>--text-column n</tt></tag> Specifies the column where additional text is output. This additional text consists of the bytes encoded in this line in text representation. <tag><tt>-v, --verbose</tt></tag> Increase the disassembler verbosity. Usually only needed for debugging purposes. You may use this option more than one time for even more verbose output. <tag><tt>-V, --version</tt></tag> Print the version number of the assembler. If you send any suggestions or bugfixes, please include the version number. </descrip> <p> <sect>Detailed workings<p> <sect1>Supported CPUs<p> The default (no CPU given on the command line or in the <tt/GLOBAL/ section of the info file) is the 6502 CPU. The disassembler knows all "official" opcodes for this CPU. Invalid opcodes are translated into <tt/.byte/ commands. With the command line option <tt><ref id="option--cpu" name="--cpu"></tt>, the disassembler may be told to recognize either the 65SC02 or 65C02 CPUs. The latter understands the same opcodes as the former, plus 16 additional bit manipulation and bit test-and-branch commands. When disassembling 4510 code, due to handling of 16-bit wide branches, da65 can produce output that can not be re-assembled, when one or more of those branches point outside of the disassembled memory. This can happen when text or binary data is processed. While there is some code for the 65816 in the sources, it is currently unsupported. <sect1>Attribute map<p> 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 disassembled code is gathered and added to the symbol and attribute maps. The last pass generates output using the information from the maps. <sect1>Labels<p> Some instructions may generate labels in the first pass, while most other instructions do not generate labels, but use them if they are available. Among others, the branch and jump instructions will generate labels for the target of the branch in the first pass. External labels (taken from the info file) have precedence over internally generated ones, They must be valid identifiers as specified for the ca65 assembler. Internal labels (generated by the disassembler) have the form <tt/Labcd/, where <tt/abcd/ is the hexadecimal address of the label in upper case letters. You should probably avoid using such label names for external labels. <sect1>Info File<p> The info file is used to pass additional information about the input code to the disassembler. This includes label names, data areas or tables, and global options like input and output file names. See the <ref id="infofile" name="next section"> for more information. <sect>Info File Format<label id="infofile"><p> The info file contains lists of specifications grouped together. Each group directive has an identifying token and an attribute list enclosed in curly 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 anything). Each attribute is terminated by a semicolon. <tscreen><verb> group-name { attribute1 attribute-value; attribute2 attribute-value; } </verb></tscreen> <sect1>Comments<p> Comments start with a hash mark (<tt/#/) or a double slash (<tt>//</tt>); and, extend from the position of the mark to the end of the current line. Hash marks or double slashes inside of strings will <em/not/ start a comment, of course. <sect1>Specifying global options<label id="global-options"><p> Global options may be specified in a group with the name <tt/GLOBAL/. The following attributes are recognized: <descrip> <tag><tt/ARGUMENTCOLUMN/</tag> This attribute specifies the column in the output, where the argument for an opcode or pseudo instruction starts. The corresponding command line option is <tt><ref id="option--argument-column" name="--argument-column"></tt>. <tag><tt/COMMENTCOLUMN/</tag> This attribute specifies the column in the output, where the comment starts in a line. It is only used for in-line comments. The corresponding command line option is <tt><ref id="option--comment-column" name="--comment-column"></tt>. <label id="COMMENTS"> <tag><tt/COMMENTS/</tag> This attribute may be used instead of the <tt><ref id="option--comments" name="--comments"></tt> option on the command line. It takes a numerical parameter between 0 and 4. Higher values increase the amount of information written to the output file in form of comments. <tag><tt/CPU/</tag> This attribute may be used instead of the <tt><ref id="option--cpu" name="--cpu"></tt> option on the command line. For possible values see there. The value is a string and must be enclosed in quotes. <tag><tt/HEXOFFS/</tag> The attribute is followed by a boolean value. If true, offsets to labels are output in hex, otherwise they're output in decimal notation. The default is false. The attribute may be changed on the command line using the <tt><ref id="option--hexoffs" name="--hexoffs"></tt> option. <tag><tt/INPUTNAME/</tag> The attribute is followed by a string value, which gives the name of the input file to read. If it is present, the disassembler does not accept an input file name on the command line. <tag><tt/INPUTOFFS/</tag> The attribute is followed by a numerical value that gives an offset into the input file which is skipped before reading data. The attribute may be used to skip headers or unwanted code sections in the input file. <tag><tt/INPUTSIZE/</tag> <tt/INPUTSIZE/ is followed by a numerical value that gives the amount of data to read from the input file. Data beyond <tt/INPUTOFFS + INPUTSIZE/ is ignored. <label id="LABELBREAK"> <tag><tt/LABELBREAK/</tag> <tt/LABELBREAK/ is followed by a numerical value that specifies the label length that will force a newline. To have all labels on their own lines, you may set this value to zero. See also the <tt><ref id="option--label-break" name="--label-break"></tt> command line option. A <tt/LABELBREAK/ statement in the info file will override any value given on the command line. <tag><tt/MNEMONICCOLUMN/</tag> This attribute specifies the column in the output, where the mnemonic or pseudo instruction is placed. The corresponding command line option is <tt><ref id="option--mnemonic-column" name="--mnemonic-column"></tt>. <tag><tt/NEWLINEAFTERJMP/</tag> This attribute is followed by a boolean value. When true, a newline is inserted after each <tt/JMP/ instruction. The default is false. <tag><tt/NEWLINEAFTERRTS/</tag> This attribute is followed by a boolean value. When true, a newline is inserted after each <tt/RTS/ instruction. The default is false. <label id="OUTPUTNAME"> <tag><tt/OUTPUTNAME/</tag> The attribute is followed by string value, which gives the name of the output file to write. If it is present, specification of an output file on the command line using the <tt><ref id="option-o" name="-o"></tt> option is not allowed. The default is to use <tt/stdout/ for output, so without this attribute or the corresponding command line option <tt/<ref id="option-o" name="-o">/ the output will go to the terminal. <tag><tt/PAGELENGTH/</tag> This attribute may be used instead of the <tt><ref id="option--pagelength" name="--pagelength"></tt> option on the command line. It takes a numerical parameter. Using zero as page length (which is the default) means that no pages are generated. <tag><tt/STARTADDR/</tag> This attribute may be used instead of the <tt><ref id="option--start-addr" name="--start-addr"></tt> option on the command line. It takes a numerical parameter. The default for the start address is $10000 minus the size of the input file (this assumes that the input file is a ROM that contains the reset and irq vectors). <tag><tt/TEXTCOLUMN/</tag> This attribute specifies the column, where the data bytes are output translated into ASCII text. It is only used if <tt><ref id="COMMENTS" name="COMMENTS"></tt> is set to at least 4. The corresponding command line option is <tt><ref id="option--text-column" name="--text-column"></tt>. </descrip> <sect1>Specifying Ranges<p> The <tt/RANGE/ directive is used to give information about address ranges. The following attributes are recognized: <descrip> <tag><tt>COMMENT</tt></tag> This attribute is only allowed if a label is also given. It takes a string as argument. See the description of the <tt><ref id="infofile-label" name="LABEL"></tt> directive for an explanation. <tag><tt>END</tt></tag> This gives the end address of the range. The end address is inclusive, that means, it is part of the range. Of course, it may not be smaller than the start address. <tag><tt>NAME</tt></tag> This is a convenience attribute. It takes a string argument and will cause the disassembler to define a label for the start of the range with the given name. So a separate <tt><ref id="infofile-label" name="LABEL"></tt> directive is not needed. <tag><tt>START</tt></tag> This gives the start address of the range. <tag><tt>TYPE</tt></tag> This attribute specifies the type of data within the range. The attribute value is one of the following keywords: <descrip> <tag><tt>ADDRTABLE</tt></tag> The range consists of data and is disassembled as a table of words (16 bit values). The difference to the <tt/WORDTABLE/ type is that a label is defined for each entry in the table. <tag><tt>BYTETABLE</tt></tag> The range consists of data and is disassembled as a byte table. <tag><tt>CODE</tt></tag> The range consists of code. <tag><tt>DBYTETABLE</tt></tag> The range consists of data and is disassembled as a table of dbytes (double byte values, 16 bit values with the low byte containing the most significant byte of the 16 bit value). <tag><tt>DWORDTABLE</tt></tag> The range consists of data and is disassembled as a table of double words (32 bit values). <tag><tt>RTSTABLE</tt></tag> The range consists of data and is disassembled as a table of words (16 bit values). The values are interpreted as words that are pushed onto the stack and jump to it via <tt/RTS/. This means that they contain <tt/address-1/ of a function, for which a label will get defined by the disassembler. <tag><tt>SKIP</tt></tag> The range is simply ignored when generating the output file. Please note that this means that reassembling the output file will <em/not/ generate the original file, not only because the missing piece in between, but also because the following code will be located on wrong addresses. Output generated with <tt/SKIP/ ranges will need manual rework. <tag><tt>TEXTTABLE</tt></tag> The range consists of readable text. <tag><tt>WORDTABLE</tt></tag> The range consists of data and is disassembled as a table of words (16 bit values). </descrip> </descrip> <sect1>Specifying Labels<label id="infofile-label"><p> The <tt/LABEL/ directive is used to give names for labels in the disassembled code. The following attributes are recognized: <descrip> <tag><tt>ADDR</tt></tag> Followed by a numerical value. Specifies the value of the label. <tag><tt>COMMENT</tt></tag> Attribute argument is a string. The comment will show up in a separate line before the label, if the label is within code or data range, or after the label if it is outside. Example output: <tscreen><verb> foo := $0001 ; Comment for label named "foo" ; Comment for label named "bar" bar: </verb></tscreen> <tag><tt>NAME</tt></tag> The attribute is followed by a string value which gives the name of the label. Empty names are allowed, in this case the disassembler will create an unnamed label (see the assembler docs for more information about unnamed labels). <tag><tt>SIZE</tt></tag> This attribute is optional and may be used to specify the size of the data that follows. If a size greater than 1 is specified, the disassembler will create labels in the form <tt/label+offs/ for all bytes within the given range, where <tt/label/ is the label name given with the <tt/NAME/ attribute, and <tt/offs/ is the offset within the data. <tag><tt>PARAMSIZE</tt></tag> This optional attribute is followed by a numerical value. It tells the assembler that subroutine calls to this label are followed by "inline parameters" with the given number of bytes, like this: <tscreen><verb> JSR LabelWithParamSize2 .byte $00, $10 (return here) code... </verb></tscreen> </descrip> <sect1>Specifying Segments<label id="infofile-segment"><p> The <tt/SEGMENT/ directive is used to specify a segment within the disassembled code. The following attributes are recognized: <descrip> <tag><tt>START</tt></tag> Followed by a numerical value. Specifies the start address of the segment. <tag><tt>END</tt></tag> Followed by a numerical value. Specifies the end address of the segment. The 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 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> 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 </verb></tscreen> The usual conventions apply for symbol names. Values may be specified as hex (leading $), binary (leading %) or decimal. The values may optionally be signed. NOTE: The include file parser is very simple. Expressions are not allowed, and anything but symbol assignments is flagged as an error (but see the <tt/IGNOREUNKNOWN/ directive below). The following attributes are recognized: <descrip> <tag><tt>FILE</tt></tag> Followed by a string value. Specifies the name of the file to read. <tag><tt>COMMENTSTART</tt></tag> The optional attribute is followed by a character constant. It specifies the character that starts a comment. The default value is a semicolon. This value is ignored if <tt/IGNOREUNKNOWN/ is true. <tag><tt>IGNOREUNKNOWN</tt></tag> This attribute is optional and is followed by a boolean value. It allows to ignore input lines that don't have a valid syntax. This allows to read in assembler include files that contain more than just symbol assignments. Note: When this attribute is used, the disassembler will ignore any errors in the given include file. This may have undesired side effects. </descrip> <sect1>An Info File Example<p> The following is a short example for an info file that contains most of the directives explained above: <tscreen><verb> # This is a comment. It extends to the end of the line GLOBAL { OUTPUTNAME "kernal.s"; INPUTNAME "kernal.bin"; STARTADDR $E000; PAGELENGTH 0; # No paging CPU "6502"; }; # One segment for the whole stuff 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; }; # 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; }; # 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 # 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; }; # Hardware vectors 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) 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 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> �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/debugging.sgml������������������������������������������������������������������������0000664�0000000�0000000�00000011032�13473601511�0015566�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>Using emulators with cc65 <author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> <abstract> How to debug your code using the VICE and Oricutron emulators. </abstract> <!-- Table of contents --> <toc> <!-- Begin the document --> <sect>Overview<p> This document describes how to debug your programs using the cc65 development tools and the VICE CBM emulator. <sect>What is VICE?<p> VICE is an emulator for many of the CBM machines. It runs on Unix, MS-DOS, Win32, OS/2, Acorn RISC OS, BeOS, QNX 6.x, Amiga, GP2X and Mac OS X. It emulates the Commodore 64, 128, VIC20, PET and the 600/700 machines. For more information see the VICE home page: <url url="http://vice-emu.sourceforge.net/">. VICE has a builtin machine language monitor that may be used for debugging your programs. Using an emulator for debugging has some advantages: <itemize> <item>Since you're using a crossassembler/-compiler anyway, you don't need to transfer the program to the real machine until it is done. <item>An emulator allows many things that are almost impossible one of the original machines. You may set watchpoints (detect read or write access to arbitary addresses), debug interrupt handlers and even debug routines that run inside the 1541 floppy. <item>You may use the label file generated by the linker to make much more use from the monitor. </itemize> <sect>How to prepare your programs<p> VICE support is mostly done via a label file that is generated by the linker and that may be read by the VICE monitor, so it knows about your program. Source level debugging is <tt/not/ available, you have to debug your programs in the assembler view. The first step is to generate object files that contain information about <em/all/ labels in your sources, not just the exported ones. This can be done by several means: <itemize> <item>Use the -g switch on the assembler command line. <item>Use the <tscreen><verb> .debuginfo + </verb></tscreen> command in your source. <item>Use the <tt/-g/ switch when invoking the compiler. The compiler will then place a <tt/.debuginfo/ command into the generated assembler source. </itemize> So, if you have just C code, all you need is to invoke the compiler with <tt/-g/. If you're using assembler code, you have to use <tt/-g/ for the assembler, or add "<tt/.debuginfo on/" to your source files. Since the generated debug info is not appended to the generated executables, it is a good idea to always use <tt/-g/. It makes the object files and libraries slightly larger (˜30%), but this is usually not a problem. The second step is to tell the linker that it should generate a VICE label file. This is done by the <tt/-Ln/ switch followed by the name of the label file (I'm usually using a <tt/.lbl/ extension for these files). An example for a linker command line would be: <tscreen><verb> ld65 -o hello -t c64 -Ln hello.lbl -m hello.map hello.o c64.lib </verb></tscreen> or <tscreen><verb> ld65 -o hello.tap -t atmos -Ln hello.sym -m hello.map hello.o atmos.lib </verb></tscreen> This will generate a file named hello.lbl that contains all symbols used in your program. <bf>Note</bf>: The runtime libraries and startup files were generated with debug info, so you don't have to care about this. <sect>How to use the label file with VICE<p> Load your program, then enter the monitor and use the "<tt/ll/" command to load your label file like this: <tscreen><verb> ll "hello.lbl" </verb></tscreen> You will get lots of warnings and even a few errors. You may ignore safely all these warnings and errors as long as they reference any problems VICE thinks it has with the labels. After loading the labels, they are used by VICE in the disassembler listing, and you may use them whereever you need to specify an address. Try <tscreen><verb> d ._main </verb></tscreen> as an example (note that VICE needs a leading dot before all labels, and that the compiler prepends an underline under most named labels). <sect>How to use the label file with Oricutron<p> Load your program, then enter the monitor and use the "<tt/sl/" command to load your label file like this: <tscreen><verb> sl hello.sym </verb></tscreen> After loading the labels, they are used by Oricutron in the disassembler listing, and you may use them whereever you need to specify an address. Try <tscreen><verb> d ._main </verb></tscreen> as an example (note that VICE needs a leading dot before all labels, and that the compiler prepends an underline under most named labels). </article> ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/dio.sgml������������������������������������������������������������������������������0000664�0000000�0000000�00000010465�13473601511�0014417�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>Diskette Sector I/O Routines <author><url url="mailto:chris@groessler.org" name="Christian Groessler"> <abstract> The cc65 library provides functions to read and write raw disk sectors. Include the dio.h header file to get the necessary definitions. </abstract> <!-- Table of contents --> <toc> <!-- Begin the document --> <sect>Opening the disk for low level I/O<p> Prior to using these functions a handle to the device has to be obtained. This is done with the <tt>dio_open</tt> function. After use, the handle should be released with the <tt>dio_close</tt> function. <tscreen><verb> dhandle_t __fastcall__ dio_open (unsigned char device); </verb></tscreen> The <tt>device</tt> specifies the device to access. <tscreen><verb> unsigned char __fastcall__ dio_close (dhandle_t handle); </verb></tscreen> Closes a handle obtained by <tt>dio_open</tt>. Returns status code. <p> <sect>Reading and writing sectors<p> The read and write functions are: <tscreen><verb> unsigned char __fastcall__ dio_read (dhandle_t handle, unsigned sect_num, void *buffer); </verb></tscreen> This function will read the sector specified by <tt>sect_num</tt> into the memory location at buffer. <tscreen><verb> unsigned char __fastcall__ dio_write (dhandle_t handle, unsigned sect_num, const void *buffer); </verb></tscreen> This function will write the memory contents at buffer to the sector specified by <tt>sect_num</tt>. No verify is performed. <tscreen><verb> unsigned char __fastcall__ dio_write_verify (dhandle_t handle, unsigned sect_num, const void *buffer); </verb></tscreen> This function will write the memory contents at buffer to the sector specified by <tt>sect_num</tt>. A verification is performed. <p> Use the <tt><ref name="dio_query_sectsize" id="sectsizecount"></tt> function to query the size of a sector and the <tt><ref name="dio_query_sectcount" id="sectsizecount"></tt> function to query the number of available sectors. <p> All these functions will return 0 for success and an OS specific error code in case of failure. <p> <sect>Querying sector size and count<label id="sectsizecount"><p> Some systems support multiple diskette formats which have different sector sizes and/or different sector counts. <p> The following function returns the sector size of the currently inserted disk: <tscreen><verb> unsigned __fastcall__ dio_query_sectsize (dhandle_t handle); </verb></tscreen> On the Atari platform, the sector size is handled specially. Please refer to the DIO section in the <url url="atari.html" name="Atari-specific platform documentation">. <p> The following function returns the sector count of the currently inserted disk: <tscreen><verb> unsigned __fastcall__ dio_query_sectcount (dhandle_t handle); </verb></tscreen> <sect>Converting sector numbers<p> Since the read and write functions expect a sector number, for systems where the sectors aren't addressed by a logical sector number (e.g. CBM devices), there are 2 conversion functions. One of them converts a logical sector number to a head/track/sector triple. The other conversion function works the other way round. <tscreen><verb> unsigned char __fastcall__ dio_phys_to_log (dhandle_t handle, const dio_phys_pos *physpos, unsigned *sectnum); </verb></tscreen> This function converts track/head/sector to logical sector number. <tscreen><verb> unsigned char __fastcall__ dio_log_to_phys (dhandle_t handle, const unsigned *sectnum, dio_phys_pos *physpos); </verb></tscreen> This function converts a logical sector number to track/head/sector notation. <p> Note, that on systems which natively use logical sector numbers (e.g. Atari), the conversion functions are dummies. They ignore head/track (<tt>dio_phys_to_log</tt>) or return them as zero (<tt>dio_log_to_phys</tt>). The logical sector number is returned as physical sector and vice versa. <p> </article> �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/doc.css�������������������������������������������������������������������������������0000664�0000000�0000000�00000001446�13473601511�0014236�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������body { font-family: arial, helvetica, sans-serif; font-size: 100%; text-align: justify; margin-left: 110px; margin-top: 10px; margin-right: 30px; margin-bottom: 10px; background-image: url(doc.png); background-repeat: repeat-y; } h1, h2, h2 a:link, h2 a:active, h2 a:visited { font-weight: bold; font-style: italic; text-align: left; color: #DB3232; } h1 { font-size: 250%; text-shadow: 2px 2px 6px #505050; letter-spacing: 2px; padding-top: 40px; } h2 { font-size: 160%; text-shadow: 2px 2px 6px #303030; letter-spacing: 1px; margin-top: 2em; margin-bottom: 1em; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/doc.png�������������������������������������������������������������������������������0000664�0000000�0000000�00000002433�13473601511�0014227�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������‰PNG  ��� IHDR�� ���#���Ub]+���gAMA��± üa���ØPLTEf’’”NNL¢&$Ò.,ê64rò><Šº*,ö64ÒÒÔÞ24~–"$Æ.,>><®&$ò64ú><rrtÚ24îîìn²²´Ò24ê:<z’"$Â*,þ:<æ64úBDjbbdª&$Š"$ö:<ÞÞÜâ64†ž&$Î.,¶*,j¢¢¤VVT¦&$Ö.,î64vö><¾*,â24‚š"$Ê.,FFD²*,ò:<þ><‚‚„þþüÂÂÄÖ24ææäzÂ.,î:<þBDŽ"$ú:<‹äfw��îIDATxÚíÝmWGÆq[Y³[-Ø UØ%–l! ­Cʪà´Ýžýþߨ3ËÃ>4}‘œ1õÅÿ§÷ÂëëÜçbÀ#åÙ«ïûùÇ?¾ûõ§¿^ÿò÷›?�_çHüR«j@¿! à«ú97è×lÐ�ðRZ¨8�à…nÐB@€§€öÛ@76h:h�x1t½ƒ& àe´Ø¿�üÝ<‡ÇçÛáãìà¾Lh:h�ðÐ_Ð0÷OÂq·ÝͲb< Ô¾æ�|û zy4Xç‹§N¦L1§ý\2G¤g>Šƒ�¾A@w¯ï$6æ¡—<mŠ ë©î˜ß÷ 44�<[@¯g³ög¦ûùXÅWîádR\™+óÊe²Tß#$ ÀW@×Zæå‡ù ßM»ª9Ý/;›É.‹‹×Î#g»`>4Ð|P�žcƒ¾¿í¿—äɦn4¦¨©DÒñcx³;±!ý–µ–íæ9;�¼t:¦±Iz™2YcžÙý8†ãv÷n¹-?Jé¥;‘JÙ@³AÀ3ômØŠßN\§œmšÓ|¦³8Ž{Ûv¿wÝ^²˜(-i;/h6h�ðÐeÿÜ?_l&Eúʤ1I¿%OÁ(k¥6’;î}Ávœ<$½Ì†³Êš �üoÐÓ;?üÇÔ=UÚ\¹\ç*÷³ý]¶D'£ò �¾ZN"mF²«*ê“j‡J܇¢ÎÎUfÔv_v¯[Δ;Ì!‡Ä& À÷}«x´OÚÚ$. Ýh…m•\HÙ9¯‡J™Ñ¡fƒ�o½ÿ&gu¢u³Ê“ÌE/;¦×‘2ŸìJ½ÜmуÕÙ” 44�øß ‡—"©vÇíÎòÚÔr‹³ÒréNz Ull O߷ŵ›¦âûpÎŽ �ü´;ÅÑÕyº~žöÓEm²ù+ÝsÑi7üFsesø:JǧýùàÆæó…” ´Û W4�xÝ å^«\§í(ØŒª“ ì“ú£ÊUE™Ù¸1 í%-¢³Ø¼äeMÅ�Þz×@;Y¯c.>Õ¦WŤ³NlÇM2ÙVÍû¤»\=õ¾¦â��ßô6c³Àþ4§â­B{“A å×%£‘÷Ëóþ¼Ç„€�½Û¡÷GìêÓn–JQ»\ùÔ 4�<ǽÏY©NªZ/ÿû®ÍÅ=4�ø èC-•ù0‰4ò¸xB¤šÐ•š/K�Ï´¨j‹Q›¤ÖR_œ¥Ù@  �>ºÒ@«Z­¾¸¶·+:h�ðºAûi 9 �þÚoÍõ�Ÿ´ÇšS�àË?À ÃUŠÈ-±����IEND®B`‚�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/funcref.sgml��������������������������������������������������������������������������0000664�0000000�0000000�00000770730�13473601511�0015304�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <!-- -*- text-mode -*- --> <article> <title>cc65 function reference <author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline> <url url="mailto:greg.king5@verizon.net" name="Greg King"> <abstract> cc65 is a C compiler for 6502 based systems. This function reference describes the C functions available in the standard library. </abstract> <!-- Table of contents --> <toc> <!-- Begin the document --> <sect>Introduction<p> cc65 is a C compiler for 6502 based systems. It implements a subset of the ISO C standard plus additional functions specially crafted for 6502 systems or just some of the supported machines. This function refrence describes the available functions together with any limitations. For an overview about the available libraries, their purpose, and any differences to the ISO standard, please have a look at the <url url="library.html" name="cc65 Library Overview">. <em/Note:/ Standard C functions are listed here, but not described in detail. Since these functions behave identical on all standard compliant systems, they are described in any book covering standard C. Each entry for a function contains a detailed description <quote> <descrip> <tag/Function/Summary of what <bf/function/ does. <tag/Header/The header file that contains the declaration. <tag/Declaration/Describes the needed header files and declaration of the function. <tag/Description/Description of the function. <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. </descrip> </quote> <sect>Functions by header file<p> <sect1><tt/6502.h/<label id="6502.h"><p> <itemize> <item><ref id="BRK" name="BRK"> <item><ref id="CLI" name="CLI"> <item><ref id="SEI" name="SEI"> <item><ref id="_sys" name="_sys"> <item><ref id="getcpu" name="getcpu"> <item><ref id="reset_brk" name="reset_brk"> <item><ref id="reset_irq" name="reset_irq"> <item><ref id="set_brk" name="set_brk"> <item><ref id="set_irq" name="set_irq"> </itemize> <sect1><tt/accelerator.h/<label id="accelerator.h"><p> <itemize> <item><ref id="detect_c128" name="detect_c128"> <item><ref id="detect_c64dtv" name="detect_c64dtv"> <item><ref id="detect_c65" name="detect_c65"> <item><ref id="detect_chameleon" name="detect_chameleon"> <item><ref id="detect_scpu" name="detect_scpu"> <item><ref id="detect_turbomaster" name="detect_turbomaster"> <item><ref id="get_c128_speed" name="get_c128_speed"> <item><ref id="get_c64dtv_speed" name="get_c64dtv_speed"> <item><ref id="get_c65_speed" name="get_c65_speed"> <item><ref id="get_chameleon_speed" name="get_chameleon_speed"> <item><ref id="get_scpu_speed" name="get_scpu_speed"> <item><ref id="get_turbomaster_speed" name="get_turbomaster_speed"> <item><ref id="set_c128_speed" name="set_c128_speed"> <item><ref id="set_c64dtv_speed" name="set_c64dtv_speed"> <item><ref id="set_c65_speed" name="set_c65_speed"> <item><ref id="set_chameleon_speed" name="set_chameleon_speed"> <item><ref id="set_scpu_speed" name="set_scpu_speed"> <item><ref id="set_turbomaster_speed" name="set_turbomaster_speed"> </itemize> <sect1><tt/apple2.h/<label id="apple2.h"><p> <itemize> <item>_dos_type <item><ref id="get_ostype" name="get_ostype"> <item>rebootafterexit </itemize> <sect1><tt/apple2enh.h/<label id="apple2enh.h"><p> <itemize> <item>_dos_type <item><ref id="get_ostype" name="get_ostype"> <item>rebootafterexit <item><ref id="videomode" name="videomode"> </itemize> <sect1><tt/assert.h/<label id="assert.h"><p> <itemize> <item><ref id="assert" name="assert"> </itemize> <sect1><tt/atari.h/<label id="atari.h"><p> <itemize> <!-- <item><ref id="_getcolor" name="_getcolor"> --> <!-- <item><ref id="_getdefdev" name="_getdefdev"> --> <!-- <item><ref id="_graphics" name="_graphics"> --> <item><ref id="_is_cmdline_dos" name="_is_cmdline_dos"> <!-- <item><ref id="_rest_vecs" name="_rest_vecs"> --> <!-- <item><ref id="_save_vecs" name="_save_vecs"> --> <!-- <item><ref id="_scroll" name="_scroll"> --> <!-- <item><ref id="_setcolor" name="_setcolor"> --> <!-- <item><ref id="_setcolor_low" name="_setcolor_low"> --> <item><ref id="get_ostype" name="get_ostype"> <!-- <item><ref id="get_tv" name="get_tv"> --> </itemize> (incomplete) <sect1><tt/atmos.h/<label id="atmos.h"><p> <itemize> <item><ref id="atmos_explode" name="atmos_explode"> <item><ref id="atmos_load" name="atmos_load"> <item><ref id="atmos_ping" name="atmos_ping"> <item><ref id="atmos_save" name="atmos_save"> <item><ref id="atmos_shoot" name="atmos_shoot"> <item><ref id="atmos_tick" name="atmos_tick"> <item><ref id="atmos_tock" name="atmos_tock"> <item><ref id="atmos_zap" name="atmos_zap"> </itemize> <sect1><tt/c128.h/<label id="c128.h"><p> <itemize> <item><ref id="c64mode" name="c64mode"> <item><ref id="fast" name="fast"> <item><ref id="isfast" name="isfast"> <item><ref id="slow" name="slow"> <item><ref id="toggle_videomode" name="toggle_videomode"> <item><ref id="videomode" name="videomode"> </itemize> <sect1><tt/c16.h/<label id="c16.h"><p> <itemize> <item><ref id="fast" name="fast"> <item><ref id="isfast" name="isfast"> <item><ref id="slow" name="slow"> </itemize> (incomplete) <sect1><tt/c64.h/<label id="c64.h"><p> <itemize> <item><ref id="get_ostype" name="get_ostype"> </itemize> <sect1><tt/cbm.h/<label id="cbm.h"><p> <itemize> <item><ref id="cbm_k_acptr" name="cbm_k_acptr"> <item><ref id="cbm_k_basin" name="cbm_k_basin"> <item><ref id="cbm_k_bsout" name="cbm_k_bsout"> <item><ref id="cbm_k_chkin" name="cbm_k_chkin"> <item><ref id="cbm_k_ciout" name="cbm_k_ciout"> <item><ref id="cbm_k_ckout" name="cbm_k_ckout"> <item><ref id="cbm_k_clall" name="cbm_k_clall"> <item><ref id="cbm_k_close" name="cbm_k_close"> <item><ref id="cbm_k_clrch" name="cbm_k_clrch"> <item><ref id="cbm_k_getin" name="cbm_k_getin"> <item><ref id="cbm_k_iobase" name="cbm_k_iobase"> <item><ref id="cbm_k_listen" name="cbm_k_listen"> <item><ref id="cbm_k_load" name="cbm_k_load"> <item><ref id="cbm_k_open" name="cbm_k_open"> <item><ref id="cbm_k_readst" name="cbm_k_readst"> <item><ref id="cbm_k_save" name="cbm_k_save"> <item><ref id="cbm_k_scnkey" name="cbm_k_scnkey"> <item><ref id="cbm_k_second" name="cbm_k_second"> <item><ref id="cbm_k_setlfs" name="cbm_k_setlfs"> <item><ref id="cbm_k_setnam" name="cbm_k_setnam"> <item><ref id="cbm_k_talk" name="cbm_k_talk"> <item><ref id="cbm_k_tksa" name="cbm_k_tksa"> <item><ref id="cbm_k_udtim" name="cbm_k_udtim"> <item><ref id="cbm_k_unlsn" name="cbm_k_unlsn"> <item><ref id="cbm_k_untlk" name="cbm_k_untlk"> <!-- <item><ref id="cbm_load" name="cbm_load"> --> <!-- <item><ref id="cbm_open" name="cbm_open"> --> <!-- <item><ref id="cbm_opendir" name="cbm_opendir"> --> <!-- <item><ref id="cbm_read" name="cbm_read"> --> <!-- <item><ref id="cbm_readdir" name="cbm_readdir"> --> <!-- <item><ref id="cbm_save" name="cbm_save"> --> <!-- <item><ref id="cbm_write" name="cbm_write"> --> <!-- <item><ref id="get_tv" name="get_tv"> --> <item><ref id="waitvsync" name="waitvsync"> <item><ref id="kbrepeat" name="kbrepeat"> </itemize> (incomplete) <sect1><tt/cbm510.h/<label id="cbm510.h"><p> <itemize> <item><ref id="peekbsys" name="peekbsys"> <item><ref id="peekwsys" name="peekwsys"> <item><ref id="pokebsys" name="pokebsys"> <item><ref id="pokewsys" name="pokewsys"> </itemize> <sect1><tt/cbm610.h/<label id="cbm610.h"><p> <itemize> <item><ref id="peekbsys" name="peekbsys"> <item><ref id="peekwsys" name="peekwsys"> <item><ref id="pokebsys" name="pokebsys"> <item><ref id="pokewsys" name="pokewsys"> </itemize> <sect1><tt/cc65.h/<label id="cc65.h"><p> <itemize> <!-- <item><ref id="_cos" name="_cos"> --> <!-- <item><ref id="idiv32by16r16" name="idiv32by16r16"> --> <!-- <item><ref id="imul16x16r32" name="imul16x16r32"> --> <!-- <item><ref id="imul8x8r16" name="imul8x8r16"> --> <!-- <item><ref id="_sin" name="_sin"> --> <!-- <item><ref id="udiv32by16r16" name="udiv32by16r16"> --> <!-- <item><ref id="umul16x16r32" name="umul16x16r32"> --> <!-- <item><ref id="umul16x8r32" name="umul16x8r32"> --> <!-- <item><ref id="umul8x8r16" name="umul8x8r16"> --> <item><ref id="doesclrscrafterexit" name="doesclrscrafterexit"> <item><ref id="mul20" name="mul20"> <item><ref id="mul40" name="mul40"> </itemize> (incomplete) <sect1><tt/conio.h/<label id="conio.h"><p> <itemize> <item><ref id="bgcolor" name="bgcolor"> <item><ref id="bordercolor" name="bordercolor"> <item><ref id="cclear" name="cclear"> <item><ref id="cclearxy" name="cclearxy"> <item><ref id="cgetc" name="cgetc"> <item><ref id="chline" name="chline"> <item><ref id="chlinexy" name="chlinexy"> <item><ref id="clrscr" name="clrscr"> <item><ref id="cpeekc" name="cpeekc"> <item><ref id="cpeekcolor" name="cpeekcolor"> <item><ref id="cpeekrevers" name="cpeekrevers"> <item><ref id="cpeeks" name="cpeeks"> <item><ref id="cprintf" name="cprintf"> <item><ref id="cputc" name="cputc"> <item><ref id="cputcxy" name="cputcxy"> <item><ref id="cputs" name="cputs"> <item><ref id="cputsxy" name="cputsxy"> <item><ref id="cursor" name="cursor"> <item><ref id="cvline" name="cvline"> <item><ref id="cvlinexy" name="cvlinexy"> <item><ref id="gotox" name="gotox"> <item><ref id="gotoxy" name="gotoxy"> <item><ref id="gotoy" name="gotoy"> <item><ref id="kbhit" name="kbhit"> <item><ref id="revers" name="revers"> <item><ref id="screensize" name="screensize"> <item><ref id="textcolor" name="textcolor"> <item><ref id="vcprintf" name="vcprintf"> <item><ref id="wherex" name="wherex"> <item><ref id="wherey" name="wherey"> </itemize> <sect1><tt/ctype.h/<label id="ctype.h"><p> <itemize> <item><ref id="isalnum" name="isalnum"> <item><ref id="isalpha" name="isalpha"> <item><ref id="isascii" name="isascii"> <item><ref id="isblank" name="isblank"> <item><ref id="iscntrl" name="iscntrl"> <item><ref id="isdigit" name="isdigit"> <item><ref id="isgraph" name="isgraph"> <item><ref id="islower" name="islower"> <item><ref id="isprint" name="isprint"> <item><ref id="ispunct" name="ispunct"> <item><ref id="isspace" name="isspace"> <item><ref id="isupper" name="isupper"> <item><ref id="isxdigit" name="isxdigit"> <item><ref id="tolower" name="tolower"> <item><ref id="toupper" name="toupper"> </itemize> <sect1><tt/dbg.h/<label id="dbg.h"><p> <!-- <itemize> --> <!-- <item><ref id="DbgInit" name="DbgInit"> --> <!-- </itemize> --> (incomplete) <sect1><tt/device.h/<label id="device.h"><p> <itemize> <item><ref id="getcurrentdevice" name="getcurrentdevice"> <item><ref id="getdevicedir" name="getdevicedir"> <item><ref id="getfirstdevice" name="getfirstdevice"> <item><ref id="getnextdevice" name="getnextdevice"> </itemize> <sect1><tt/dio.h/<label id="dio.h"><p> <url url="dio.html" name="Low-level disk I/O API">. <sect1><tt/dirent.h/<label id="dirent.h"><p> <itemize> <item><ref id="_DE_ISDIR" name="_DE_ISDIR"> <item><ref id="_DE_ISLBL" name="_DE_ISLBL"> <item><ref id="_DE_ISLNK" name="_DE_ISLNK"> <item><ref id="_DE_ISREG" name="_DE_ISREG"> <item><ref id="closedir" name="closedir"> <item><ref id="opendir" name="opendir"> <item><ref id="readdir" name="readdir"> <item><ref id="rewinddir" name="rewinddir"> <item><ref id="seekdir" name="seekdir"> <item><ref id="telldir" name="telldir"> </itemize> <sect1><tt/em.h/<label id="em.h"><p> This header file contains definitions for extended memory access, see also <tt>testcode/lib/em-test.c</tt> and <tt>samples/multidemo.c</tt>. <itemize> <item><ref id="em_commit" name="em_commit"> <item><ref id="em_copyfrom" name="em_copyfrom"> <item><ref id="em_copyto" name="em_copyto"> <item><ref id="em_install" name="em_install"> <item><ref id="em_load_driver" name="em_load_driver"> <item><ref id="em_map" name="em_map"> <item><ref id="em_pagecount" name="em_pagecount"> <item><ref id="em_uninstall" name="em_uninstall"> <item><ref id="em_unload" name="em_unload"> <item><ref id="em_use" name="em_use"> </itemize> <sect1><tt/errno.h/<label id="errno.h"><p> <!-- <itemize> --> <!-- <item><ref id="_directerrno" name="_directerrno"> --> <!-- <item><ref id="_mappederrno" name="_mappederrno"> --> <!-- <item><ref id="_osmaperrno" name="_osmaperrno"> --> <!-- <item><ref id="_seterrno" name="_seterrno"> --> <!-- </itemize> --> (incomplete) <sect1><tt/fcntl.h/<label id="fcntl.h"><p> <itemize> <item><ref id="close" name="close"> <item><ref id="creat" name="creat"> <item><ref id="open" name="open"> </itemize> <sect1><tt/gamate.h/<label id="gamate.h"><p> <itemize> <!-- <item><ref id="get_tv" name="get_tv"> --> <item><ref id="waitvsync" name="waitvsync"> </itemize> (incomplete) <sect1><tt/geos.h/<label id="geos.h"><p> <url url="geos.html" name="GEOS API">. <sect1><tt/joystick.h/<label id="joystick.h"><p> <itemize> <item><ref id="joy_count" name="joy_count"> <item><ref id="joy_install" name="joy_install"> <item><ref id="joy_load_driver" name="joy_load_driver"> <item><ref id="joy_read" name="joy_read"> <item><ref id="joy_uninstall" name="joy_uninstall"> <item><ref id="joy_unload" name="joy_unload"> </itemize> <sect1><tt/locale.h/<label id="locale.h"><p> <itemize> <item><ref id="localeconv" name="localeconv"> <item><ref id="setlocale" name="setlocale"> </itemize> <sect1><tt/lynx.h/<label id="lynx.h"><p> <!-- <itemize> --> <!-- <item><ref id="lynx_eeprom_erase" name="lynx_eeprom_erase"> --> <!-- <item><ref id="lynx_eeprom_read" name="lynx_eeprom_read"> --> <!-- <item><ref id="lynx_eeprom_write" name="lynx_eeprom_write"> --> <!-- <item><ref id="lynx_eeread" name="lynx_eeread"> --> <!-- <item><ref id="lynx_eewrite" name="lynx_eewrite"> --> <!-- <item><ref id="lynx_exec" name="lynx_exec"> --> <!-- <item><ref id="lynx_load" name="lynx_load"> --> <!-- </itemize> --> (incomplete) <sect1><tt/lz4.h/<label id="lz4.h"><p> <itemize> <item><ref id="decompress_lz4" name="decompress_lz4"> </itemize> <sect1><tt/modload.h/<label id="modload.h"><p> <itemize> <item><ref id="mod_load" name="mod_load"> <item><ref id="mod_free" name="mod_free"> </itemize> <sect1><tt/mouse.h/<label id="mouse.h"><p> <itemize> <item><ref id="mouse_buttons" name="mouse_buttons"> <item><ref id="mouse_getbox" name="mouse_getbox"> <item><ref id="mouse_geterrormsg" name="mouse_geterrormsg"> <item><ref id="mouse_hide" name="mouse_hide"> <item><ref id="mouse_info" name="mouse_info"> <item><ref id="mouse_install" name="mouse_install"> <item><ref id="mouse_ioctl" name="mouse_ioctl"> <item><ref id="mouse_load_driver" name="mouse_load_driver"> <item><ref id="mouse_move" name="mouse_move"> <item><ref id="mouse_pos" name="mouse_pos"> <item><ref id="mouse_setbox" name="mouse_setbox"> <item><ref id="mouse_show" name="mouse_show"> <item><ref id="mouse_uninstall" name="mouse_uninstall"> <item><ref id="mouse_unload" name="mouse_unload"> </itemize> <sect1><tt/nes.h/<label id="nes.h"><p> <itemize> <!-- <item><ref id="get_tv" name="get_tv"> --> <item><ref id="waitvsync" name="waitvsync"> </itemize> (incomplete) <sect1><tt/o65.h/<label id="o65.h"><p> The <tt/o65.h/ header file contains structure and constant definitions that may be used when dealing with files in <url url="http://www.6502.org/users/andre/o65/fileformat.html" name="the o65 format">. It does not declare any functions. <sect1><tt/pce.h/<label id="pce.h"><p> <itemize> <!-- <item><ref id="get_tv" name="get_tv"> --> <item><ref id="waitvsync" name="waitvsync"> </itemize> (incomplete) <sect1><tt/peekpoke.h/<label id="peekpoke.h"><p> <itemize> <item><ref id="PEEK" name="PEEK"> <item><ref id="PEEKW" name="PEEKW"> <item><ref id="POKE" name="POKE"> <item><ref id="POKEW" name="POKEW"> </itemize> <sect1><tt/pen.h/<label id="pen.h"><p> <!-- <itemize> --> <!-- <item><ref id="pen_adjust" name="pen_adjust"> --> <!-- <item><ref id="pen_calibrate" name="pen_calibrate"> --> <!-- </itemize> --> (incomplete) <sect1><tt/pet.h/<label id="pet.h"><p> (incomplete) <sect1><tt/plus4.h/<label id="plus4.h"><p> <itemize> <item><ref id="fast" name="fast"> <item><ref id="isfast" name="isfast"> <item><ref id="slow" name="slow"> </itemize> (incomplete) <sect1><tt/serial.h/<label id="serial.h"><p> This header file contains definitions for initializing serial communication, see also <tt>testcode/lib/ser-test.c</tt>. <itemize> <item><ref id="ser_close" name="ser_close"> <item><ref id="ser_get" name="ser_get"> <item><ref id="ser_install" name="ser_install"> <item><ref id="ser_ioctl" name="ser_ioctl"> <item><ref id="ser_load_driver" name="ser_load_driver"> <item><ref id="ser_open" name="ser_open"> <item><ref id="ser_put" name="ser_put"> <item><ref id="ser_status" name="ser_status"> <item><ref id="ser_uninstall" name="ser_uninstall"> <item><ref id="ser_unload" name="ser_unload"> </itemize> <sect1><tt/setjmp.h/<label id="setjmp.h"><p> <itemize> <item><ref id="setjmp" name="setjmp"> <item><ref id="longjmp" name="longjmp"> </itemize> <sect1><tt/signal.h/<label id="signal.h"><p> <itemize> <item><ref id="raise" name="raise"> <item><ref id="signal" name="signal"> </itemize> <sect1><tt/stdarg.h/<label id="stdarg.h"><p> (incomplete) <sect1><tt/stdbool.h/<label id="stdbool.h"><p> (incomplete) <sect1><tt/stddef.h/<label id="stddef.h"><p> <itemize> <item><ref id="offsetof" name="offsetof"> </itemize> <sect1><tt/stdio.h/<label id="stdio.h"><p> <itemize> <item><ref id="_poserror" name="_poserror"> <item><ref id="clearerr" name="clearerr"> <!-- <item><ref id="fclose" name="fclose"> --> <!-- <item><ref id="fdopen" name="fdopen"> --> <item><ref id="feof" name="feof"> <item><ref id="ferror" name="ferror"> <!-- <item><ref id="fflush" name="fflush"> --> <!-- <item><ref id="fgetc" name="fgetc"> --> <!-- <item><ref id="fgetpos" name="fgetpos"> --> <!-- <item><ref id="fgets" name="fgets"> --> <item><ref id="fileno" name="fileno"> <!-- <item><ref id="fopen" name="fopen"> --> <!-- <item><ref id="fprintf" name="fprintf"> --> <!-- <item><ref id="fputc" name="fputc"> --> <!-- <item><ref id="fputs" name="fputs"> --> <!-- <item><ref id="fread" name="fread"> --> <!-- <item><ref id="freopen" name="freopen"> --> <!-- <item><ref id="fscanf" name="fscanf"> --> <!-- <item><ref id="fseek" name="fseek"> --> <!-- <item><ref id="fsetpos" name="fsetpos"> --> <!-- <item><ref id="ftell" name="ftell"> --> <!-- <item><ref id="fwrite" name="fwrite"> --> <!-- <item><ref id="getc" name="getc"> --> <!-- <item><ref id="getchar" name="getchar"> --> <!-- <item><ref id="gets" name="gets"> --> <!-- <item><ref id="printf" name="printf"> --> <!-- <item><ref id="putc" name="putc"> --> <!-- <item><ref id="putchar" name="putchar"> --> <!-- <item><ref id="puts" name="puts"> --> <item><ref id="rename" name="rename"> <item><ref id="remove" name="remove"> <!-- <item><ref id="rewind" name="rewind"> --> <!-- <item><ref id="scanf" name="scanf"> --> <!-- <item><ref id="snprintf" name="snprintf"> --> <!-- <item><ref id="sprintf" name="sprintf"> --> <!-- <item><ref id="sscanf" name="sscanf"> --> <!-- <item><ref id="vfprintf" name="vfprintf"> --> <!-- <item><ref id="vfscanf" name="vfscanf"> --> <!-- <item><ref id="vprintf" name="vprintf"> --> <!-- <item><ref id="vscanf" name="vscanf"> --> <!-- <item><ref id="vsnprintf" name="vsnprintf"> --> <!-- <item><ref id="vsprintf" name="vsprintf"> --> <!-- <item><ref id="vsscanf" name="vsscanf"> --> </itemize> (incomplete) <sect1><tt/stdlib.h/<label id="stdlib.h"><p> <itemize> <item><ref id="_heapadd" name="_heapadd"> <item><ref id="_heapblocksize" name="_heapblocksize"> <item><ref id="_heapmaxavail" name="_heapmaxavail"> <item><ref id="_heapmemavail" name="_heapmemavail"> <item><ref id="_randomize" name="_randomize"> <item><ref id="_swap" name="_swap"> <item><ref id="abort" name="abort"> <item><ref id="abs" name="abs"> <item><ref id="atexit" name="atexit"> <item><ref id="atoi" name="atoi"> <item><ref id="atol" name="atol"> <item><ref id="bsearch" name="bsearch"> <item><ref id="calloc" name="calloc"> <item><ref id="div" name="div"> <item><ref id="exit" name="exit"> <item><ref id="free" name="free"> <item><ref id="getenv" name="getenv"> <item><ref id="itoa" name="itoa"> <item><ref id="labs" name="labs"> <item><ref id="ltoa" name="ltoa"> <item><ref id="malloc" name="malloc"> <item><ref id="perror" name="perror"> <!-- <item><ref id="posix_memalign" name="posix_memalign"> --> <!-- <item><ref id="putenv" name="putenv"> --> <item><ref id="qsort" name="qsort"> <item><ref id="rand" name="rand"> <item><ref id="realloc" name="realloc"> <item><ref id="srand" name="srand"> <!-- <item><ref id="system" name="system"> --> <item><ref id="ultoa" name="ultoa"> <item><ref id="utoa" name="utoa"> </itemize> (incomplete) <sect1><tt/string.h/<label id="string.h"><p> <itemize> <item><ref id="_stroserror" name="_stroserror"> <item><ref id="bzero" name="bzero"> <item><ref id="memchr" name="memchr"> <item><ref id="memcmp" name="memcmp"> <item><ref id="memcpy" name="memcpy"> <item><ref id="memmove" name="memmove"> <item><ref id="memset" name="memset"> <item><ref id="strcasecmp" name="strcasecmp"> <item><ref id="strcat" name="strcat"> <item><ref id="strchr" name="strchr"> <item><ref id="strcmp" name="strcmp"> <item><ref id="strcoll" name="strcoll"> <item><ref id="strcpy" name="strcpy"> <item><ref id="strcspn" name="strcspn"> <item><ref id="strdup" name="strdup"> <item><ref id="strerror" name="strerror"> <item><ref id="stricmp" name="stricmp"> <item><ref id="strlen" name="strlen"> <item><ref id="strlower" name="strlower"> <item><ref id="strlwr" name="strlwr"> <item><ref id="strncasecmp" name="strncasecmp"> <item><ref id="strncat" name="strncat"> <item><ref id="strncmp" name="strncmp"> <item><ref id="strncpy" name="strncpy"> <item><ref id="strnicmp" name="strnicmp"> <item><ref id="strpbrk" name="strpbrk"> <item><ref id="strqtok" name="strqtok"> <item><ref id="strrchr" name="strrchr"> <item><ref id="strspn" name="strspn"> <item><ref id="strstr" name="strstr"> <item><ref id="strtok" name="strtok"> <item><ref id="strxfrm" name="strxfrm"> <item><ref id="strupper" name="strupper"> <item><ref id="strupr" name="strupr"> </itemize> <sect1><tt/telestrat.h/<label id="telestrat.h"><p> <itemize> <item><ref id="atmos_explode" name="explode"> <item><ref id="atmos_ping" name="ping"> <item><ref id="atmos_shoot" name="shoot"> <item><ref id="atmos_zap" name="zap"> <!-- <item><ref id="kbdclick1" name="kbdclick1"> --> <!-- <item><ref id="oups" name="oups"> --> </itemize> (incomplete) <sect1><tt/tgi.h/<label id="tgi.h"><p> <url url="tgi.html" name="Tiny Graphics Interface">. <sect1><tt/time.h/<label id="time.h"><p> <itemize> <!-- <item><ref id="asctime" name="asctime"> --> <item><ref id="clock" name="clock"> <item><ref id="clock_getres" name="clock_getres"> <item><ref id="clock_gettime" name="clock_gettime"> <item><ref id="clock_settime" name="clock_settime"> <!-- <item><ref id="ctime" name="ctime"> --> <!-- <item><ref id="gmtime" name="gmtime"> --> <!-- <item><ref id="localtime" name="localtime"> --> <!-- <item><ref id="mktime" name="mktime"> --> <!-- <item><ref id="strftime" name="strftime"> --> <item><ref id="time" name="time"> </itemize> (incomplete) <sect1><tt/unistd.h/<label id="unistd.h"><p> <itemize> <!-- <item><ref id="chdir" name="chdir"> --> <item><ref id="exec" name="exec"> <item><ref id="getcwd" name="getcwd"> <item><ref id="getopt" name="getopt"> <!-- <item><ref id="lseek" name="lseek"> --> <!-- <item><ref id="mkdir" name="mkdir"> --> <!-- <item><ref id="read" name="read"> --> <!-- <item><ref id="rmdir" name="rmdir"> --> <item><ref id="sleep" name="sleep"> <item><ref id="unlink" name="unlink"> <!-- <item><ref id="write" name="write"> --> </itemize> (incomplete) <sect1><tt/vic20.h/<label id="vic20.h"><p> (incomplete) <sect1><tt/zlib.h/<label id="zlib.h"><p> <!-- <itemize> --> <!-- <item><ref id="adler32" name="adler32"> --> <!-- <item><ref id="crc32" name="crc32"> --> <!-- <item><ref id="inflatemem" name="inflatemem"> --> <!-- <item><ref id="uncompress" name="uncompress"> --> <!-- </itemize> --> (incomplete) <sect>Alphabetical function reference<p> <sect1>_DE_ISDIR<label id="_DE_ISDIR"><p> <quote> <descrip> <tag/Function/Determine if a directory entry specifies a directory. <tag/Header/<tt/<ref id="dirent.h" name="dirent.h">/ <tag/Declaration/<tt/int _DE_ISDIR(unsigned char type);/ <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/Notes/<itemize> <item>The function is actually a macro. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="_DE_ISLBL" name="_DE_ISLBL">, <ref id="_DE_ISLNK" name="_DE_ISLNK">, <ref id="_DE_ISREG" name="_DE_ISREG"> <tag/Example/None. </descrip> </quote> <sect1>_DE_ISLBL<label id="_DE_ISLBL"><p> <quote> <descrip> <tag/Function/Determine if a directory entry specifies a disk label. <tag/Header/<tt/<ref id="dirent.h" name="dirent.h">/ <tag/Declaration/<tt/int _DE_ISLBL(unsigned char type);/ <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/Notes/<itemize> <item>The function is actually a macro. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="_DE_ISDIR" name="_DE_ISDIR">, <ref id="_DE_ISLNK" name="_DE_ISLNK">, <ref id="_DE_ISREG" name="_DE_ISREG"> <tag/Example/None. </descrip> </quote> <sect1>_DE_ISLNK<label id="_DE_ISLNK"><p> <quote> <descrip> <tag/Function/Determine if a directory entry specifies a link. <tag/Header/<tt/<ref id="dirent.h" name="dirent.h">/ <tag/Declaration/<tt/int _DE_ISLNK(unsigned char type);/ <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/Notes/<itemize> <item>The function is actually a macro. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="_DE_ISDIR" name="_DE_ISDIR">, <ref id="_DE_ISLBL" name="_DE_ISLBL">, <ref id="_DE_ISREG" name="_DE_ISREG"> <tag/Example/None. </descrip> </quote> <sect1>_DE_ISREG<label id="_DE_ISREG"><p> <quote> <descrip> <tag/Function/Determine if a directory entry specifies a regular file. <tag/Header/<tt/<ref id="dirent.h" name="dirent.h">/ <tag/Declaration/<tt/int _DE_ISREG(unsigned char type);/ <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/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 the CBM systems are classified as being "regular" files, for example. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="_DE_ISDIR" name="_DE_ISDIR">, <ref id="_DE_ISLBL" name="_DE_ISLBL">, <ref id="_DE_ISLNK" name="_DE_ISLNK"> <tag/Example/None. </descrip> </quote> <sect1>_heapadd<label id="_heapadd"><p> <quote> <descrip> <tag/Function/Add a block to the heap. <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/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/ <ref id="_heapblocksize" name="_heapblocksize">, <ref id="_heapmaxavail" name="_heapmaxavail">, <ref id="_heapmemavail" name="_heapmemavail">, <ref id="calloc" name="calloc">, <ref id="free" name="free">, <ref id="malloc" name="malloc">, <ref id="realloc" name="realloc"> <tag/Example/None. </descrip> </quote> <sect1>_heapblocksize<label id="_heapblocksize"><p> <quote> <descrip> <tag/Function/Return the size of an allocated block. <tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ <tag/Declaration/<tt/size_t __fastcall__ _heapblocksize (const void* block);/ <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/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/ <ref id="_heapadd" name="_heapadd">, <ref id="_heapmaxavail" name="_heapmaxavail">, <ref id="_heapmemavail" name="_heapmemavail">, <ref id="calloc" name="calloc">, <ref id="free" name="free">, <ref id="malloc" name="malloc">, <ref id="realloc" name="realloc"> <tag/Example/None. </descrip> </quote> <sect1>_heapmaxavail<label id="_heapmaxavail"><p> <quote> <descrip> <tag/Function/Return the largest block that is available on the heap. <tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ <tag/Declaration/<tt/size_t _heapmaxavail (void);/ <tag/Description/The function returns the size of the largest block that may be allocated from the heap using <tt/<ref id="malloc" name="malloc">/. <tag/Availability/cc65 <tag/See also/ <ref id="_heapadd" name="_heapadd">, <ref id="_heapblocksize" name="_heapblocksize">, <ref id="_heapmemavail" name="_heapmemavail">, <ref id="calloc" name="calloc">, <ref id="free" name="free">, <ref id="malloc" name="malloc">, <ref id="realloc" name="realloc"> <tag/Example/None. </descrip> </quote> <sect1>_heapmemavail<label id="_heapmemavail"><p> <quote> <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 _heapmemavail (void);/ <tag/Description/The function returns the total number of bytes available on the heap. <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 id="malloc" name="malloc"> may still return <tt/NULL/. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="_heapadd" name="_heapadd">, <ref id="_heapblocksize" name="_heapblocksize">, <ref id="_heapmaxavail" name="_heapmaxavail">, <ref id="calloc" name="calloc">, <ref id="free" name="free">, <ref id="malloc" name="malloc">, <ref id="realloc" name="realloc"> <tag/Example/None. </descrip> </quote> <sect1>_is_cmdline_dos<label id="_is_cmdline_dos"><p> <quote> <descrip> <tag/Function/Determines whether the underlying DOS supports command line arguments. <tag/Header/<tt/<ref id="atari.h" name="atari.h">/ <tag/Declaration/<tt/unsigned char _is_cmdline_dos (void);/ <tag/Description/The function returns 0 if the DOS doesn't support command line arguments. It returns 1 if it does. <tag/Availability/cc65 (<tt/atari/ and <tt/atarixl/ platforms) </descrip> </quote> <sect1>_poserror<label id="_poserror"><p> <quote> <descrip> <tag/Function/Print an error message for the error in <tt/_oserror/. <tag/Header/<tt/<ref id="stdio.h" name="stdio.h">/ <tag/Declaration/<tt/void __fastcall__ _poserror (const char* msg);/ <tag/Description/<tt/_poserror/ prints an error message to <tt/stderr/. If <tt/msg/ 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/_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/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. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="_stroserror" name="_stroserror">, <ref id="perror" name="perror"> <tag/Example/None. </descrip> </quote> <sect1>_randomize<label id="_randomize"><p> <quote> <descrip> <tag/Function/Initialize the pseudo random number generator. <tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ <tag/Declaration/<tt/void _randomize (void);/ <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/Notes/<itemize> <item>The randomness of the seed depends on the machine hardware. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="rand" name="rand">, <ref id="srand" name="srand"> <tag/Example/None. </descrip> </quote> <sect1>_stroserror<label id="_stroserror"><p> <quote> <descrip> <tag/Function/Return a string describing an OS specific error code. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <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/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. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="strerror" name="strerror"> <tag/Example/None. </descrip> </quote> <sect1>_swap<label id="_swap"><p> <quote> <descrip> <tag/Function/Swap the contents of memory areas. <tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ <tag/Declaration/<tt/void __fastcall__ _swap (void* p, void* q, size_t size);/ <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/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. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="memcpy" name="memcpy">, <ref id="memmove" name="memmove"> <tag/Example/None. </descrip> </quote> <sect1>_sys<label id="_sys"><p> <quote> <descrip> <tag/Function/Call a subroutine passing register values. <tag/Header/<tt/<ref id="6502.h" name="6502.h">/ <tag/Declaration/<tt/void __fastcall__ _sys (struct regs* r);/ <tag/Description/The function will call the subroutine at the address 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/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 used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/Example/None. </descrip> </quote> <sect1>BRK<label id="BRK"><p> <quote> <descrip> <tag/Function/Insert a 6502 BRK instrunction into the code. <tag/Header/<tt/<ref id="6502.h" name="6502.h">/ <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/Notes/<itemize> <item>The function is actually a macro. <item>The inserted instruction may lead to unexpected results if no debugger is present. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="CLI" name="CLI">, <ref id="SEI" name="SEI"> <tag/Example/None. </descrip> </quote> <sect1>CLI<label id="CLI"><p> <quote> <descrip> <tag/Function/Insert a 6502 CLI instrunction into the code. <tag/Header/<tt/<ref id="6502.h" name="6502.h">/ <tag/Declaration/<tt/void CLI (void);/ <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/Notes/<itemize> <item>The function is actually a macro. <item>Disabling interrupts may lead to unexpected results. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="BRK" name="BRK">, <ref id="SEI" name="SEI"> <tag/Example/None. </descrip> </quote> <sect1>PEEK<label id="PEEK"><p> <quote> <descrip> <tag/Function/Read a byte from memory. <tag/Header/<tt/<ref id="peekpoke.h" name="peekpoke.h">/ <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/Notes/<itemize> <item>The function is actually a macro. <item>This function depends highly on the platform and environment. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="PEEKW" name="PEEKW">, <ref id="POKE" name="POKE"> <tag/Example/None. </descrip> </quote> <sect1>PEEKW<label id="PEEKW"><p> <quote> <descrip> <tag/Function/Read a word (two bytes) from memory. <tag/Header/<tt/<ref id="peekpoke.h" name="peekpoke.h">/ <tag/Declaration/<tt/unsigned PEEKW (unsigned addr);/ <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/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 depend of the address expression used. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="PEEK" name="PEEK">, <ref id="POKE" name="POKE"> <tag/Example/None. </descrip> </quote> <sect1>POKE<label id="POKE"><p> <quote> <descrip> <tag/Function/Write a byte to memory. <tag/Header/<tt/<ref id="peekpoke.h" name="peekpoke.h">/ <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/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 machine. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="PEEK" name="PEEK">, <ref id="POKEW" name="POKEW"> <tag/Example/None. </descrip> </quote> <sect1>POKEW<label id="POKEW"><p> <quote> <descrip> <tag/Function/Write a word (two bytes) to memory. <tag/Header/<tt/<ref id="peekpoke.h" name="peekpoke.h">/ <tag/Declaration/<tt/void POKEW (unsigned addr, unsigned val);/ <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/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 machine. <item>The order in which the two bytes are written is unspecified and may depend of the address expression used. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="PEEK" name="PEEK">, <ref id="POKE" name="POKE"> <tag/Example/None. </descrip> </quote> <sect1>SEI<label id="SEI"><p> <quote> <descrip> <tag/Function/Insert a 6502 SEI instrunction into the code. <tag/Header/<tt/<ref id="6502.h" name="6502.h">/ <tag/Declaration/<tt/void SEI (void);/ <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/Notes/<itemize> <item>The function is actually a macro. <item>Disabling interrupts may lead to unexpected results. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="BRK" name="BRK">, <ref id="CLI" name="CLI"> <tag/Example/None. </descrip> </quote> <sect1>abort<label id="abort"><p> <quote> <descrip> <tag/Function/Terminates a program abnormally. <tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ <tag/Declaration/<tt/void abort (void);/ <tag/Description/<tt/abort/ raises <tt/SIGABRT/, writes a termination message on stderr, then terminates the program with an exit code of 3. <tag/Availability/ISO 9899 <tag/See also/ <ref id="assert" name="assert">, <ref id="exit" name="exit">, <ref id="raise" name="raise"> <tag/Example/None. </descrip> </quote> <sect1>abs<label id="abs"><p> <quote> <descrip> <tag/Function/Returns the absolute value of an integer. <tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ <tag/Declaration/<tt/int __fastcall__ abs (int v);/ <tag/Description/<tt/abs/ returns the absolute value of the argument passed to the function. <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. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="labs" name="labs"> <tag/Example/None. </descrip> </quote> <sect1>assert<label id="assert"><p> <quote> <descrip> <tag/Function/Test a condition and possibly abort. <tag/Header/<tt/<ref id="assert.h" name="assert.h">/ <tag/Declaration/<tt/void assert (int cond);/ <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/Notes/<itemize> <item>The function is actually a macro. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="abort" name="abort">, <ref id="exit" name="exit"> <tag/Example/None. </descrip> </quote> <sect1>atexit<label id="atexit"><p> <quote> <descrip> <tag/Function/Register an exit function. <tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ <tag/Declaration/<tt/int __fastcall__ atexit (void (*exitfunc) (void));/ <tag/Description/<tt/atexit/ registers the function pointed to by <tt/exitfunc/ as an exit function. Exit functions are called when 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/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 used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="abort" name="abort">, <ref id="exit" name="exit"> <tag/Example/None. </descrip> </quote> <sect1>atmos_explode<label id="atmos_explode"><p> <quote> <descrip> <tag/Function/Bomb sound effect. <tag/Header/<tt/<ref id="atmos.h" name="atmos.h">/ <tag/Declaration/<tt/void __fastcall__ atmos_explode(void);/ <tag/Description/<tt/atmos_explode/ plays the BASIC sound. <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_ping" name="atmos_ping">, <ref id="atmos_shoot" name="atmos_shoot">, <ref id="atmos_tick" name="atmos_tick">, <ref id="atmos_tock" name="atmos_tock">, <ref id="atmos_zap" name="atmos_zap"> <tag/Example/None. </descrip> </quote> <sect1>atmos_load<label id="atmos_load"><p> <quote> <descrip> <tag/Function/Load Atmos tape. <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"> <tag/Example/None. </descrip> </quote> <sect1>atmos_ping<label id="atmos_ping"><p> <quote> <descrip> <tag/Function/Bell or ricochet sound effect. <tag/Header/<tt/<ref id="atmos.h" name="atmos.h">/ <tag/Declaration/<tt/void __fastcall__ atmos_ping(void);/ <tag/Description/<tt/atmos_ping/ plays the BASIC sound. <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_explode" name="atmos_explode">, <ref id="atmos_shoot" name="atmos_shoot">, <ref id="atmos_tick" name="atmos_tick">, <ref id="atmos_tock" name="atmos_tock">, <ref id="atmos_zap" name="atmos_zap"> <tag/Example/None. </descrip> </quote> <sect1>atmos_save<label id="atmos_save"><p> <quote> <descrip> <tag/Function/Save Atmos tape. <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"> <tag/Example/<verb> atmos_save("hires", 0xa000, 0xc000); </verb> </descrip> </quote> <sect1>atmos_shoot<label id="atmos_shoot"><p> <quote> <descrip> <tag/Function/Pistol sound effect. <tag/Header/<tt/<ref id="atmos.h" name="atmos.h">/ <tag/Declaration/<tt/void __fastcall__ atmos_shoot(void);/ <tag/Description/<tt/atmos_shoot/ plays the BASIC sound. <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_explode" name="atmos_explode">, <ref id="atmos_ping" name="atmos_ping">, <ref id="atmos_tick" name="atmos_tick">, <ref id="atmos_tock" name="atmos_tock">, <ref id="atmos_zap" name="atmos_zap"> <tag/Example/None. </descrip> </quote> <sect1>atmos_tick<label id="atmos_tick"><p> <quote> <descrip> <tag/Function/High-pitch click. <tag/Header/<tt/<ref id="atmos.h" name="atmos.h">/ <tag/Declaration/<tt/void __fastcall__ atmos_tick(void);/ <tag/Description/<tt/atmos_tick/ plays the system sound. <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_explode" name="atmos_explode">, <ref id="atmos_ping" name="atmos_ping">, <ref id="atmos_shoot" name="atmos_shoot">, <ref id="atmos_tock" name="atmos_tock">, <ref id="atmos_zap" name="atmos_zap"> <tag/Example/None. </descrip> </quote> <sect1>atmos_tock<label id="atmos_tock"><p> <quote> <descrip> <tag/Function/Low-pitch click. <tag/Header/<tt/<ref id="atmos.h" name="atmos.h">/ <tag/Declaration/<tt/void __fastcall__ atmos_tock(void);/ <tag/Description/<tt/atmos_tock/ plays the system sound. <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_explode" name="atmos_explode">, <ref id="atmos_ping" name="atmos_ping">, <ref id="atmos_shoot" name="atmos_shoot">, <ref id="atmos_tick" name="atmos_tick">, <ref id="atmos_zap" name="atmos_zap"> <tag/Example/None. </descrip> </quote> <sect1>atmos_zap<label id="atmos_zap"><p> <quote> <descrip> <tag/Function/Raygun sound effect. <tag/Header/<tt/<ref id="atmos.h" name="atmos.h">/ <tag/Declaration/<tt/void __fastcall__ atmos_zap(void);/ <tag/Description/<tt/atmos_zap/ plays the BASIC sound. <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_explode" name="atmos_explode">, <ref id="atmos_ping" name="atmos_ping">, <ref id="atmos_shoot" name="atmos_shoot">, <ref id="atmos_tick" name="atmos_tick">, <ref id="atmos_tock" name="atmos_tock"> <tag/Example/None. </descrip> </quote> <sect1>atoi<label id="atoi"><p> <quote> <descrip> <tag/Function/Convert a string to an integer. <tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ <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/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 used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="atol" name="atol">, <ref id="itoa" name="itoa">, <ref id="ltoa" name="ltoa">, <ref id="ultoa" name="ultoa">, <ref id="utoa" name="utoa"> <tag/Example/None. </descrip> </quote> <sect1>atol<label id="atol"><p> <quote> <descrip> <tag/Function/Convert a string to a long integer. <tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ <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/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 used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="atoi" name="atoi">, <ref id="itoa" name="itoa">, <ref id="ltoa" name="ltoa">, <ref id="ultoa" name="ultoa">, <ref id="utoa" name="utoa"> <tag/Example/None. </descrip> </quote> <sect1>bgcolor<label id="bgcolor"><p> <quote> <descrip> <tag/Function/Set the background text color. <tag/Header/<tt/<ref id="conio.h" name="conio.h">/ <tag/Declaration/<tt/unsigned char __fastcall__ bgcolor (unsigned char color);/ <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/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 used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="bordercolor" name="bordercolor">, <ref id="textcolor" name="textcolor"> <tag/Example/None. </descrip> </quote> <sect1>bordercolor<label id="bordercolor"><p> <quote> <descrip> <tag/Function/Set the border (frame) color. <tag/Header/<tt/<ref id="conio.h" name="conio.h">/ <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/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 be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="bgcolor" name="bgcolor">, <ref id="textcolor" name="textcolor"> <tag/Example/None. </descrip> </quote> <sect1>bsearch<label id="bsearch"><p> <quote> <descrip> <tag/Function/Do a binary search in a sorted array. <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 __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/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/ <ref id="qsort" name="qsort"> <tag/Example/None. </descrip> </quote> <sect1>bzero<label id="bzero"><p> <quote> <descrip> <tag/Function/Fill a memory area with zeroes. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <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/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 be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="_swap" name="_swap">, <ref id="memcpy" name="memcpy">, <ref id="memmove" name="memmove">, <ref id="memset" name="memset">, <tag/Example/None. </descrip> </quote> <sect1>c64mode<label id="c64mode"><p> <quote> <descrip> <tag/Function/Switch the C128 into C64 compatible mode. <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/Notes/<itemize> <item>The function is specific to the C128. <item>The function will not return to the caller. </itemize> <tag/Availability/C128 <tag/Example/None. </descrip> </quote> <sect1>calloc<label id="calloc"><p> <quote> <descrip> <tag/Function/Allocate and clear memory. <tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ <tag/Declaration/<tt/void* __fastcall__ calloc (size_t n, size_t size);/ <tag/Description/<tt/calloc/ allocates memory for an array of <tt/n/ elements 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/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 should be used with care for portable programs. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="_heapadd" name="_heapadd">, <ref id="_heapblocksize" name="_heapblocksize">, <ref id="_heapmaxavail" name="_heapmaxavail">, <ref id="_heapmemavail" name="_heapmemavail">, <ref id="free" name="free">, <ref id="malloc" name="malloc">, <ref id="realloc" name="realloc"> <tag/Example/None. </descrip> </quote> <sect1>cbm_k_acptr<label id="cbm_k_acptr"><p> <quote> <descrip> <tag/Function/Input byte from serial bus <tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ <tag/Declaration/<tt/unsigned char cbm_k_acptr (void);/ <tag/Description/The function returns a byte of data, which it 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/Notes/<itemize> <item> </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cbm_k_talk" name="cbm_k_talk">, <tag/Example/None. </descrip> </quote> <sect1>cbm_k_basin<label id="cbm_k_basin"><p> <quote> <descrip> <tag/Function/Input a Character from the Current Device <tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ <tag/Declaration/<tt/unsigned char cbm_k_basin (void);/ <tag/Description/The function returns a character from the current input device. 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/Notes/<itemize> <item> </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cbm_k_open" name="cbm_k_open">, <ref id="cbm_k_chkin" name="cbm_k_chkin"> <tag/Example/None. </descrip> </quote> <sect1>cbm_k_bsout<label id="cbm_k_bsout"><p> <quote> <descrip> <tag/Function/Output a byte <tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ <tag/Declaration/<tt/void __fastcall__ cbm_k_bsout (unsigned char C);/ <tag/Description/Function sends the character to the current output device. Unless a device has been OPENed and designated as the current output channel using the CHKOUT routine, the character is 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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cbm_k_open" name="cbm_k_open">, <ref id="cbm_k_chkin" name="cbm_k_chkout"> <tag/Example/None. </descrip> </quote> <sect1>cbm_k_chkin<label id="cbm_k_chkin"><p> <quote> <descrip> <tag/Function/Designate a Logical File As the Current Input Channel <tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ <tag/Declaration/<tt/unsigned char __fastcall__ cbm_k_chkin (unsigned char FN);/ <tag/Description/If you wish to get data from any device other than the keyboard, this function must be called after OPENing the device, before you can get a data byte with the cbm_k_basin or cbm_k_getin routine. When called, the routine will designate the logical file whose file number was supplied as the current file, its device as the current device, and its secondary 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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cbm_k_open" name="cbm_k_open">, <ref id="cbm_k_basin" name="cbm_k_basin">, <ref id="cbm_k_getin" name="cbm_k_getin"> <tag/Example/None. </descrip> </quote> <sect1>cbm_k_ciout<label id="cbm_k_ciout"><p> <quote> <descrip> <tag/Function/Transmit a byte over the serial bus <tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ <tag/Declaration/<tt/void __fastcall__ cbm_k_ciout (unsigned char C);/ <tag/Description/Purpose of this function is to send a byte of data over the serial bus. In order for the data to be received, the serial device must have first been commanded to LISTEN and been given a 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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cbm_k_listen" name="cbm_k_listen">, <ref id="cbm_k_unlsn" name="cbm_k_unlsn"> <tag/Example/None. </descrip> </quote> <sect1>cbm_k_ckout<label id="cbm_k_ckout"><p> <quote> <descrip> <tag/Function/Designate a Logical File As the Current Output Channel <tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ <tag/Declaration/<tt/unsigned char __fastcall__ cbm_k_ckout (unsigned char FN);/ <tag/Description/If you wish to output data to any device other than the screen, this routine must be called after OPENing the device, and before you output a data byte with the cbm_k_bsout() function. When called, the function will designate the logical file whose file number was supplied as the current 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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cbm_k_bsout" name="cbm_k_bsout">, <ref id="cbm_k_listen" name="cbm_k_listen"> <tag/Example/None. </descrip> </quote> <sect1>cbm_k_clall<label id="cbm_k_clall"><p> <quote> <descrip> <tag/Function/Close All Logical I/O Files <tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ <tag/Declaration/<tt/void cbm_k_clall (void);/ <tag/Description/It closes all open files, by resetting the index into open files to zero and restores the default I/O devices. <tag/Notes/<itemize> <item> </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cbm_k_open" name="cbm_k_open">, <ref id="cbm_k_close" name="cbm_k_close"> <tag/Example/None. </descrip> </quote> <sect1>cbm_k_close<label id="cbm_k_close"><p> <quote> <descrip> <tag/Function/Close a Logical I/O File <tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ <tag/Declaration/<tt/void __fastcall__ cbm_k_close (unsigned char FN);/ <tag/Description/It is used to close a logical file after all I/O operations involving that file have been completed. <tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cbm_k_open" name="cbm_k_open">, <ref id="cbm_k_clall" name="cbm_k_clall"> <tag/Example/None. </descrip> </quote> <sect1>cbm_k_clrch<label id="cbm_k_clrch"><p> <quote> <descrip> <tag/Function/Restore Current Input and Output Devices to the Default Devices <tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ <tag/Declaration/<tt/void cbm_k_clrch (void);/ <tag/Description/It sets the current input device to the keyboard, and the current output device to 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/Notes/<itemize> <item> </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cbm_k_chkin" name="cbm_k_chkin">, <ref id="cbm_k_ckout" name="cbm_k_ckout"> <tag/Example/None. </descrip> </quote> <sect1>cbm_k_getin<label id="cbm_k_getin"><p> <quote> <descrip> <tag/Function/Get One Byte from the Input Device <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/Notes/<itemize> <item> </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cbm_k_basin" name="cbm_k_basin"> <tag/Example/None. </descrip> </quote> <sect1>cbm_k_iobase<label id="cbm_k_iobase"><p> <quote> <descrip> <tag/Function/Return Base Address of Memory-Mapped I/O Devices <tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ <tag/Declaration/<tt/unsigned cbm_k_iobase (void);/ <tag/Description/This function returns the address of the memory section where the memory mapped I/O devices are located. This address can then be used with an offset to access the memory mapped I/O devices in the Commodore 64. The offset is the number of locations from the beginning of the page on which the I/O register you want is located. This function exists to provide compatibility between the Commodore 64, 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/Notes/<itemize> <item> </itemize> <tag/Availability/cc65 <tag/See also/ <tag/Example/None. </descrip> </quote> <sect1>cbm_k_listen<label id="cbm_k_listen"><p> <quote> <descrip> <tag/Function/Command a device on the serial bus to LISTEN <tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ <tag/Declaration/<tt/void __fastcall__ cbm_k_listen (unsigned char dev);/ <tag/Description/This function will command a device on the serial bus to 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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cbm_k_unlsn" name="cbm_k_unlsn"> <tag/Example/None. </descrip> </quote> <sect1>cbm_k_load<label id="cbm_k_load"><p> <quote> <descrip> <tag/Function/Load RAM from a Device <tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ <tag/Declaration/<tt/unsigned int __fastcall__ cbm_k_load(unsigned char flag, unsigned addr);/ <tag/Description/This function LOADs data bytes from any input device directly into the memory. It can also be used for a verify operation, comparing data from a device with the data already in memory, while leaving the data stored in RAM unchanged. The flag must be set to 0 for a LOAD operation, or 1 for a verify, If the input device is OPENed with a secondary address (SA) of 0 the header information from the device is ignored. In this case, the starting address for the load must be supplied. If the device is addressed with a secondary address of 1, then the data is 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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cbm_k_save" name="cbm_k_save">, <ref id="cbm_k_setlfs" name="cbm_k_setlfs">, <ref id="cbm_k_setnam" name="cbm_k_setnam"> <tag/Example/None. </descrip> </quote> <sect1>cbm_k_open<label id="cbm_k_open"><p> <quote> <descrip> <tag/Function/Open a Logical I/O File <tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ <tag/Declaration/<tt/unsigned char cbm_k_open (void);/ <tag/Description/This function assigns a logical file to a device, so that it can be used for 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/Notes/<itemize> <item> </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cbm_k_close" name="cbm_k_close">, <ref id="cbm_k_setlfs" name="cbm_k_setlfs">, <ref id="cbm_k_setnam" name="cbm_k_setnam"> <tag/Example/None. </descrip> </quote> <sect1>cbm_k_readst<label id="cbm_k_readst"><p> <quote> <descrip> <tag/Function/Read status word <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/Notes/<itemize> <item> </itemize> <tag/Availability/cc65 <tag/See also/ <tag/Example/None. </descrip> </quote> <sect1>cbm_k_save<label id="cbm_k_save"><p> <quote> <descrip> <tag/Function/Save RAM to a Device <tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ <tag/Declaration/<tt/unsigned char __fastcall__ cbm_k_save(unsigned int start, unsigned int end)/ <tag/Description/This function saves a section of memory. The cbm_k_setlfs() and cbm_k_setnam() functions must be 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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cbm_k_load" name="cbm_k_load">, <ref id="cbm_k_setlfs" name="cbm_k_setlfs">, <ref id="cbm_k_setnam" name="cbm_k_setnam"> <tag/Example/None. </descrip> </quote> <sect1>cbm_k_scnkey<label id="cbm_k_scnkey"><p> <quote> <descrip> <tag/Function/Scan the keyboard matrix. <tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ <tag/Declaration/<tt/void cbm_k_scnkey (void);/ <tag/Description/This function looks at the switches in the keyboard, to see if any of them are being pressed. If they are, then code numbers for them are stored in RAM. Other functions use those numbers to input text. Normally, the keyboard is scanned by the Kernal's Interrupt Service Routine. But, if you divert the "Jiffy interrupt" to a C-code ISR, then that ISR must call this function, in order to provide input from the keyboard. <tag/Availability/cc65 <tag/See also/ <ref id="cbm_k_getin" name="cbm_k_getin">, <ref id="cbm_k_udtim" name="cbm_k_udtim">, <ref id="cgetc" name="cgetc">, <!-- <ref id="getc" name="getc"> --> <!-- <ref id="getchar" name="getchar"> --> <tag/Example/None. </descrip> </quote> <sect1>cmb_k_second<label id="cbm_k_second"><p> <quote> <descrip> <tag/Function/Send secondary address for LISTEN. <tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ <tag/Declaration/<tt/void __fastcall__ cbm_k_second (unsigned char addr);/ <tag/Description/This function is used to send a secondary address to an I/O device after a call to LISTEN is made, and the device is commanded to LISTEN. <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 can only be called after a call to LISTEN. <item>The function will not work after a TALK. <item>When a secondary address is to be sent to a device on the serial bus, the address must first be ORed with $60. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cbm_k_listen" name="cbm_k_listen"> <tag/Exampe/None. </descrip> </quote> <sect1>cbm_k_setlfs<label id="cbm_k_setlfs"><p> <quote> <descrip> <tag/Function/Set up a logical file <tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cbm_k_setnam" name="cbm_k_setnam"> <tag/Example/None. </descrip> </quote> <sect1>cbm_k_setnam<label id="cbm_k_setnam"><p> <quote> <descrip> <tag/Function/Set Filename Parameters <tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cbm_k_open" name="cbm_k_open">, <ref id="cbm_k_load" name="cbm_k_load">, <ref id="cbm_k_save" name="cbm_k_save"> <tag/Example/None. </descrip> </quote> <sect1>cbm_k_talk<label id="cbm_k_talk"><p> <quote> <descrip> <tag/Function/Commands device to TALK <tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cbm_k_acptr" name="cbm_k_acptr"> <tag/Example/None. </descrip> </quote> <sect1>cbm_k_tksa<label id="cbm_k_tksa"><p> <quote> <descrip> <tag/Function/Send TALK secondary address to serial bus <tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ <tag/Declaration/<tt/void __fastcall__ cbm_k_tksa (unsigned char addr);/ <tag/Description/This function transmits a secondary address on the serial bus for a TALK device. <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 can only be called after a call to TALK. <item>The function will not work after a LISTEN. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cbm_k_talk" name="cbm_k_talk"> <tag/Example/None. </descrip> </quote> <sect1>cbm_k_udtim<label id="cbm_k_udtim"><p> <quote> <descrip> <tag/Function/Update the Jiffy clock. <tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ <tag/Declaration/<tt/void cbm_k_udtim (void);/ <tag/Description/This function adds one count to the Jiffy clock. That clock counts sixtieths of a second. It is used by the library's <tt/clock()/ function. Normally, the Jiffy clock is updated by the Kernal's Interrupt Service Routine. But, if you divert the "Jiffy interrupt" to a C-code ISR, then that ISR must call this function, in order to keep the clock valid. <tag/Availability/cc65 <tag/See also/ <ref id="cbm_k_scnkey" name="cbm_k_scnkey">, <ref id="clock" name="clock"> <tag/Example/None. </descrip> </quote> <sect1>cbm_k_unlsn<label id="cbm_k_unlsn"><p> <quote> <descrip> <tag/Function/Send an UNLISTEN command <tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ <tag/Declaration/<tt/void cbm_k_unlsn (void);/ <tag/Description/This function commands all devices on the serial bus to stop receiving data from the host computer (i.e., UNLISTEN). Calling this function results in an UNLISTEN command being transmitted on the serial 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/Availability/cc65 <tag/See also/ <ref id="cbm_k_listen" name="cbm_k_listen"> <tag/Example/None. </descrip> </quote> <sect1>cbm_k_untlk<label id="cbm_k_untlk"><p> <quote> <descrip> <tag/Function/Send an UNTALK command <tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ <tag/Declaration/<tt/void cbm_k_untlk (void);/ <tag/Description/This function commands all devices on the serial bus to stop sending data to the host computer (i.e., UNTALK). Calling this function results in an UNTALK command being transmitted on the serial bus. Only devices previously commanded to TALK are affected. This function is normally used after the host computer is finished listening to data from an external device. Sending the UNTALK commands the sending devices to get off the serial bus so it can be used for other purposes. <tag/Availability/cc65 <tag/See also/ <ref id="cbm_k_talk" name="cbm_k_talk"> <tag/Example/None. </descrip> </quote> <sect1>cclear<label id="cclear"><p> <quote> <descrip> <tag/Function/Clear part of a line (write a given number of spaces). <tag/Header/<tt/<ref id="conio.h" name="conio.h">/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cclearxy" name="cclearxy">, <ref id="clrscr" name="clrscr"> <tag/Example/None. </descrip> </quote> <sect1>cclearxy<label id="cclearxy"><p> <quote> <descrip> <tag/Function/Clear part of a line (write a given number of spaces) starting at a specific screen position. <tag/Header/<tt/<ref id="conio.h" name="conio.h">/ <tag/Declaration/<tt/void __fastcall__ cclearxy (unsigned char x, unsigned char y, unsigned char length);/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cclear" name="cclear">, <ref id="clrscr" name="clrscr"> <tag/Example/None. </descrip> </quote> <sect1>cgetc<label id="cgetc"><p> <quote> <descrip> <tag/Function/Read a character from the keyboard. <tag/Header/<tt/<ref id="conio.h" name="conio.h">/ <tag/Declaration/<tt/char cgetc (void);/ <tag/Description/The function reads a character from the keyboard. If there is no character available, <tt/cgetc()/ waits until the user presses a key. If the cursor is enabled by use of the <tt/cursor/ function, a blinking cursor is displayed while waiting. <tag/Notes/<itemize> <item>If the system supports a keyboard buffer, <tt/cgetc()/ will fetch a key from that buffer; and, wait only if the buffer is empty. <item>The keyboard must be scanned periodically, in order for this function to see anything that you type. (See the description of <tt/cbm_k_scnkey()/.) </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cbm_k_scnkey" name="cbm_k_scnkey">, <ref id="cursor" name="cursor">, <ref id="kbhit" name="kbhit"> <tag/Example/None. </descrip> </quote> <sect1>chline<label id="chline"><p> <quote> <descrip> <tag/Function/Output a horizontal line in text mode. <tag/Header/<tt/<ref id="conio.h" name="conio.h">/ <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/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. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="chlinexy" name="chlinexy">, <ref id="cvline" name="cvline">, <ref id="cvlinexy" name="cvlinexy"> <tag/Example/None. </descrip> </quote> <sect1>chlinexy<label id="chlinexy"><p> <quote> <descrip> <tag/Function/Output a horizontal line at a given position in text mode. <tag/Header/<tt/<ref id="conio.h" name="conio.h">/ <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/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. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="chline" name="chline">, <ref id="cvline" name="cvline">, <ref id="cvlinexy" name="cvlinexy"> <tag/Example/None. </descrip> </quote> <sect1>clearerr<label id="clearerr"><p> <quote> <descrip> <tag/Function/Clear error and end-of-file status of a stream. <tag/Header/<tt/<ref id="stdio.h" name="stdio.h">/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="feof" name="feof">, <ref id="ferror" name="ferror"> <tag/Example/None. </descrip> </quote> <sect1>clock<label id="clock"><p> <quote> <descrip> <tag/Function/Determine the processor time used. <tag/Header/<tt/<ref id="time.h" name="time.h">/ <tag/Declaration/<tt/clock_t clock (void);/ <tag/Description/The <tt/clock/ function returns an approximaton of processor time used by the program. The time is returned in implementation-defined units. It can be converted to seconds by dividing by the value of the macro <tt/CLOCKS_PER_SEC/. <tag/Notes/<itemize> <item>Since the machines that cc65-generated programs run on cannot run multiple processes, the function actually will return the time since some implementation-defined point in the past. <item>The Jiffy clock must be "running", in order for this function to return changing values. (See the description of <tt/cbm_k_udtim()/.) </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="cbm_k_udtim" name="cbm_k_udtim">, <ref id="time" name="time"> <tag/Example/None. </descrip> </quote> <sect1>clock_getres<label id="clock_getres"><p> <quote> <descrip> <tag/Function/Determine the realtime clock resolution. <tag/Header/<tt/<ref id="time.h" name="time.h">/ <tag/Declaration/<tt/int __fastcall__ clock_getres (clockid_t clock_id, struct timespec *res);/ <tag/Description/The <tt/clock_getres/ function finds the resolution (precision) of the realtime clock. <tt/clock_id/ has to be <tt/CLOCK_REALTIME/. If <tt/res/ is not <tt/NULL/, the resolution of the realtime clock is stored in the location pointed to by <tt/res/. If <tt/res/ is <tt/NULL/, the clock resolution is not returned. If the <tt/tp/ argument of <tt/<ref id="clock_settime" name="clock_settime">/ is not a multiple of <tt/res/, then the value is truncated to a multiple of <tt/res/. 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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>Depending on the target either the <tt/tv_sec/ or the <tt/tv_nsec/ field of the <tt/struct timespec/ returned is zero. </itemize> <tag/Availability/POSIX 1003.1 <tag/See also/ <ref id="clock_gettime" name="clock_gettime">, <ref id="clock_settime" name="clock_settime"> <tag/Example/None. </descrip> </quote> <sect1>clock_gettime<label id="clock_gettime"><p> <quote> <descrip> <tag/Function/Get the time from the realtime clock. <tag/Header/<tt/<ref id="time.h" name="time.h">/ <tag/Declaration/<tt/int __fastcall__ clock_gettime (clockid_t clock_id, struct timespec *tp);/ <tag/Description/The <tt/clock_gettime/ function retrieves the time since the 1970-01-01 00:00:00 measured in nanoseconds. <tt/clock_id/ has to be <tt/CLOCK_REALTIME/. 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/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 retrieved value may not be valid. See also the platform-specific information. </itemize> <tag/Availability/POSIX 1003.1 <tag/See also/ <ref id="clock_getres" name="clock_getres">, <ref id="clock_settime" name="clock_settime">, <ref id="time" name="time"> <tag/Example/None. </descrip> </quote> <sect1>clock_settime<label id="clock_settime"><p> <quote> <descrip> <tag/Function/Set the time on the realtime clock. <tag/Header/<tt/<ref id="time.h" name="time.h">/ <tag/Declaration/<tt/int __fastcall__ clock_settime (clockid_t clock_id, const struct timespec *tp);/ <tag/Description/The <tt/clock_settime/ function sets the time since the 1970-01-01 00:00:00 measured in nanoseconds. <tt/clock_id/ has to be <tt/CLOCK_REALTIME/. 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/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 setting the time may not work. See also the platform-specific information. </itemize> <tag/Availability/POSIX 1003.1 <tag/See also/ <ref id="clock_getres" name="clock_getres">, <ref id="clock_gettime" name="clock_gettime"> <tag/Example/None. </descrip> </quote> <sect1>clrscr<label id="clrscr"><p> <quote> <descrip> <tag/Function/Clear the text screen. <tag/Header/<tt/<ref id="conio.h" name="conio.h">/ <tag/Declaration/<tt/void clrscr (void);/ <tag/Description/The function clears the text screen and moves the cursor to the upper left corner. <tag/Availability/cc65 <tag/See also/ <ref id="cclear" name="cclear">, <ref id="cclearxy" name="cclearxy"> <tag/Example/None. </descrip> </quote> <sect1>close<label id="close"><p> <quote> <descrip> <tag/Function/Close a file descriptor. <tag/Header/<tt/<ref id="fcntl.h" name="fcntl.h">/ <tag/Declaration/<tt/int __fastcall__ close (int fd);/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/POSIX 1003.1 <tag/See also/ <ref id="creat" name="creat">, <ref id="open" name="open"> <tag/Example/None. </descrip> </quote> <sect1>closedir<label id="closedir"><p> <quote> <descrip> <tag/Function/Close a directory. <tag/Header/<tt/<ref id="dirent.h" name="dirent.h">/ <tag/Declaration/<tt/int __fastcall__ closedir (DIR* dir);/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/POSIX 1003.1 <tag/See also/ <ref id="opendir" name="opendir">, <ref id="readdir" name="readdir"> <tag/Example/None. </descrip> </quote> <sect1>cpeekc<label id="cpeekc"><p> <quote> <descrip> <tag/Function/Get a character from the display memory. <tag/Header/<tt/<ref id="conio.h" name="conio.h">/ <tag/Declaration/<tt/char cpeekc (void);/ <tag/Description/The function gets the character that's at the current location of the cursor in the display screen RAM. That character is converted, if needed, into the encoding that can be passed to <tt/cputc()/. <tag/Notes/<itemize> <item>Conio peek functions don't have <tt/cpeek...xy()/ versions. That was done to make it obvious that peeking doesn't move the cursor in any way. Your program must place the cursor where it wants to peek before it calls any of those functions. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cpeekcolor" name="cpeekcolor">, <ref id="cpeekrevers" name="cpeekrevers">, <ref id="cpeeks" name="cpeeks">, <ref id="cputc" name="cputc"> <tag/Example/None. </descrip> </quote> <sect1>cpeekcolor<label id="cpeekcolor"><p> <quote> <descrip> <tag/Function/Get a color from the display memory. <tag/Header/<tt/<ref id="conio.h" name="conio.h">/ <tag/Declaration/<tt/unsigned char cpeekcolor (void);/ <tag/Description/The function gets the color number that's at the current location of the cursor in the display screen RAM. That number can be passed to <tt/textcolor()/. <tag/Notes/<itemize> <item>Conio peek functions don't have <tt/cpeek...xy()/ versions. That was done to make it obvious that peeking doesn't move the cursor in any way. Your program must place the cursor where it wants to peek before it calls any of those functions. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cpeekc" name="cpeekc">, <ref id="cpeekrevers" name="cpeekrevers">, <ref id="cpeeks" name="cpeeks">, <ref id="cputc" name="cputc">, <ref id="textcolor" name="textcolor"> <tag/Example/None. </descrip> </quote> <sect1>cpeekrevers<label id="cpeekrevers"><p> <quote> <descrip> <tag/Function/Get a reverse-character attribute from the display memory. <tag/Header/<tt/<ref id="conio.h" name="conio.h">/ <tag/Declaration/<tt/unsigned char cpeekrevers (void);/ <tag/Description/The function gets the "reverse-mode" attribute of the character that's at the current location of the cursor in the display screen RAM. It returns a boolean value (0/1) that can be passed to <tt/revers()/. <tag/Notes/<itemize> <item>Conio peek functions don't have <tt/cpeek...xy()/ versions. That was done to make it obvious that peeking doesn't move the cursor in any way. Your program must place the cursor where it wants to peek before it calls any of those functions. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cpeekc" name="cpeekc">, <ref id="cpeekcolor" name="cpeekcolor">, <ref id="cpeeks" name="cpeeks">, <ref id="cputc" name="cputc">, <ref id="revers" name="revers"> <tag/Example/None. </descrip> </quote> <sect1>cpeeks<label id="cpeeks"><p> <quote> <descrip> <tag/Function/Get a string from the display memory. <tag/Header/<tt/<ref id="conio.h" name="conio.h">/ <tag/Declaration/<tt/void __fastcall__ cpeeks (char* s, unsigned length);/ <tag/Description/The function gets a fixed-length string ('\0'-terminated) of characters that start at the current location of the cursor in the display screen RAM. Those characters are converted, if needed, into the encoding that can be passed to <tt/cputs()/. The first argument must point to a RAM area that's large enough to hold "length + 1" bytes. <tag/Notes/<itemize> <item>Conio peek functions don't have <tt/cpeek...xy()/ versions. That was done to make it obvious that peeking doesn't move the cursor in any way. Your program must place the cursor where it wants to peek before it calls any of those functions. <item>The function is available as only a fastcall function; so, it may be used only in the presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cpeekc" name="cpeekc">, <ref id="cpeekcolor" name="cpeekcolor">, <ref id="cpeekrevers" name="cpeekrevers">, <ref id="cputc" name="cputc">, <ref id="cputs" name="cputs"> <tag/Example/None. </descrip> </quote> <sect1>creat<label id="creat"><p> <quote> <descrip> <tag/Function/Create a file. <tag/Header/<tt/<ref id="fcntl.h" name="fcntl.h">/ <tag/Declaration/<tt/int __fastcall__ creat (const char* name, unsigned mode);/ <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/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 be used in presence of a prototype. </itemize> <tag/Availability/POSIX 1003.1 <tag/See also/ <ref id="close" name="close">, <ref id="open" name="open"> <tag/Example/None. </descrip> </quote> <sect1>cprintf<label id="cprintf"><p> <quote> <descrip> <tag/Function/Formatted output to the console. <tag/Header/<tt/<ref id="conio.h" name="conio.h">/ <tag/Declaration/<tt/int cprintf (const char* format, ...);/ <tag/Description/The arguments are converted to text where necessary and 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/Notes/<itemize> <item>Like all other <tt/conio/ output functions, <tt/cprintf/ distinguishes between <tt/\r/ and <tt/\n/. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cputc" name="cputc">, <ref id="cputcxy" name="cputcxy">, <ref id="cputs" name="cputs">, <ref id="cputsxy" name="cputsxy">, <ref id="vcprintf" name="vcprintf"> <tag/Example/None. </descrip> </quote> <sect1>cputc<label id="cputc"><p> <quote> <descrip> <tag/Function/Output a character directly to the console. <tag/Header/<tt/<ref id="conio.h" name="conio.h">/ <tag/Declaration/<tt/void __fastcall__ cputc (char c);/ <tag/Description/Output one character to the console at the current cursor position. <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 be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cprintf" name="cprintf">, <ref id="cputcxy" name="cputcxy">, <ref id="cputs" name="cputs">, <ref id="cputsxy" name="cputsxy">, <ref id="vcprintf" name="vcprintf"> <tag/Example/None. </descrip> </quote> <sect1>cputcxy<label id="cputcxy"><p> <quote> <descrip> <tag/Function/Output a character at a specific screen position. <tag/Header/<tt/<ref id="conio.h" name="conio.h">/ <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/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 be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cprintf" name="cprintf">, <ref id="cputc" name="cputc">, <ref id="cputs" name="cputs">, <ref id="cputsxy" name="cputsxy">, <ref id="vcprintf" name="vcprintf"> <tag/Example/None. </descrip> </quote> <sect1>cputs<label id="cputs"><p> <quote> <descrip> <tag/Function/Output a string directly to the console. <tag/Header/<tt/<ref id="conio.h" name="conio.h">/ <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/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 be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cprintf" name="cprintf">, <ref id="cputc" name="cputc">, <ref id="cputcxy" name="cputcxy">, <ref id="cputsxy" name="cputsxy">, <ref id="vcprintf" name="vcprintf"> <tag/Example/None. </descrip> </quote> <sect1>cputsxy<label id="cputsxy"><p> <quote> <descrip> <tag/Function/Output a string to the console at a given position. <tag/Header/<tt/<ref id="conio.h" name="conio.h">/ <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/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 be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cprintf" name="cprintf">, <ref id="cputc" name="cputc">, <ref id="cputcxy" name="cputcxy">, <ref id="cputs" name="cputs">, <ref id="vcprintf" name="vcprintf"> <tag/Example/None. </descrip> </quote> <sect1>cursor<label id="cursor"><p> <quote> <descrip> <tag/Function/Enable/disable a blinking cursor when waiting for keyboard input. <tag/Header/<tt/<ref id="conio.h" name="conio.h">/ <tag/Declaration/<tt/unsigned char __fastcall__ cursor (unsigned char onoff);/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cgetc" name="cgetc">, <ref id="kbhit" name="kbhit"> <tag/Example/None. </descrip> </quote> <sect1>cvline<label id="cvline"><p> <quote> <descrip> <tag/Function/Output a vertical line in text mode. <tag/Header/<tt/<ref id="conio.h" name="conio.h">/ <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/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. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="chline" name="chline">, <ref id="chlinexy" name="chlinexy">, <ref id="cvlinexy" name="cvlinexy"> <tag/Example/None. </descrip> </quote> <sect1>cvlinexy<label id="cvlinexy"><p> <quote> <descrip> <tag/Function/Output a vertical line at a given position in text mode. <tag/Header/<tt/<ref id="conio.h" name="conio.h">/ <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/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. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="chline" name="chline">, <ref id="chlinexy" name="chlinexy">, <ref id="cvline" name="cvline"> <tag/Example/None. </descrip> </quote> <sect1>decompress_lz4<label id="decompress_lz4"><p> <quote> <descrip> <tag/Function/Uncompress a LZ4-compressed buffer. <tag/Header/<tt/<ref id="lz4.h" name="lz4.h">/ <tag/Declaration/<tt/void decompress_lz4 (const unsigned char* src, unsigned char* const dst, const unsigned short uncompressed_size);/ <tag/Description/<tt/decompress_lz4/ uncompresses a LZ4-compressed buffer. <tag/Notes/<itemize> <item>Use LZ4_compress_HC with compression level 16 for best compression. </itemize> <tag/Availability/cc65 <tag/Example/None. </descrip> </quote> <sect1>detect_c128<label id="detect_c128"><p> <quote> <descrip> <tag/Function/Check if a C128 CPU is the current CPU. <tag/Header/<tt/<ref id="accelerator.h" name="accelerator.h">/ <tag/Declaration/<tt/unsigned char detect_c128 (void);/ <tag/Description/The function returns a 1 if a C128 CPU is the current CPU. <tag/Notes/<itemize> <item>The function is specific to the C64 and C128. </itemize> <tag/Availability/cc65 (not all platforms) <tag/See also/ <ref id="get_c128_speed" name="get_c128_speed">, <ref id="set_c128_speed" name="set_c128_speed">, <tag/Example/None. </descrip> </quote> <sect1>detect_c64dtv<label id="detect_c64dtv"><p> <quote> <descrip> <tag/Function/Check for the presence of the C64DTV. <tag/Header/<tt/<ref id="accelerator.h" name="accelerator.h">/ <tag/Declaration/<tt/unsigned char detect_c64dtv (void);/ <tag/Description/The function returns a 1 if a C64DTV has been detected. <tag/Notes/<itemize> <item>The function is specific to the C64. </itemize> <tag/Availability/cc65 (not all platforms) <tag/See also/ <ref id="get_c64dtv_speed" name="get_c64dtv_speed">, <ref id="set_c64dtv_speed" name="set_c64dtv_speed">, <tag/Example/None. </descrip> </quote> <sect1>detect_c65<label id="detect_c65"><p> <quote> <descrip> <tag/Function/Check for the presence of a C65/C64DX in C64 mode. <tag/Header/<tt/<ref id="accelerator.h" name="accelerator.h">/ <tag/Declaration/<tt/unsigned char detect_c65 (void);/ <tag/Description/The function returns a 1 if a C65/C64DX in C64 mode has been detected. <tag/Notes/<itemize> <item>The function is specific to the C64. </itemize> <tag/Availability/cc65 (not all platforms) <tag/See also/ <ref id="get_c65_speed" name="get_c65_speed">, <ref id="set_c65_speed" name="set_c65_speed">, <tag/Example/None. </descrip> </quote> <sect1>detect_chameleon<label id="detect_chameleon"><p> <quote> <descrip> <tag/Function/Check for the presence of the C64 Chameleon cartridge. <tag/Header/<tt/<ref id="accelerator.h" name="accelerator.h">/ <tag/Declaration/<tt/unsigned char detect_chameleon (void);/ <tag/Description/The function returns a 1 if a C64 Chameleon cartridge has been detected. <tag/Notes/<itemize> <item>The function is specific to the C64. </itemize> <tag/Availability/cc65 (not all platforms) <tag/See also/ <ref id="get_chameleon_speed" name="get_chameleon_speed">, <ref id="set_chameleon_speed" name="set_chameleon_speed">, <tag/Example/None. </descrip> </quote> <sect1>detect_scpu<label id="detect_scpu"><p> <quote> <descrip> <tag/Function/Check for the presence of the C64/C128 SuperCPU cartridge. <tag/Header/<tt/<ref id="accelerator.h" name="accelerator.h">/ <tag/Declaration/<tt/unsigned char detect_scpu (void);/ <tag/Description/The function returns a 1 if a SuperCPU cartridge has been detected. <tag/Notes/<itemize> <item>The function is specific to the C128 and C64. </itemize> <tag/Availability/cc65 (not all platforms) <tag/See also/ <ref id="get_scpu_speed" name="get_scpu_speed">, <ref id="set_scpu_speed" name="set_scpu_speed">, <tag/Example/None. </descrip> </quote> <sect1>detect_turbomaster<label id="detect_turbomaster"><p> <quote> <descrip> <tag/Function/Check for the presence of the C64 Turbo Master cartridge. <tag/Header/<tt/<ref id="accelerator.h" name="accelerator.h">/ <tag/Declaration/<tt/unsigned char detect_turbomaster (void);/ <tag/Description/The function returns a 1 if a C64 Turbo Master cartridge has been detected. <tag/Notes/<itemize> <item>The function is specific to the C64. </itemize> <tag/Availability/cc65 (not all platforms) <tag/See also/ <ref id="get_turbomaster_speed" name="get_turbomaster_speed">, <ref id="set_turbomaster_speed" name="set_turbomaster_speed">, <tag/Example/None. </descrip> </quote> <sect1>div<label id="div"><p> <quote> <descrip> <tag/Function/Divide two ints and return quotient and remainder. <tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ ldiv <tag/Example/None. </descrip> </quote> <sect1>doesclrscrafterexit<label id="doesclrscrafterexit"><p> <quote> <descrip> <tag/Function/Determines whether the screen is going to be cleared after program exit. <tag/Header/<tt/<ref id="cc65.h" name="cc65.h">/ <tag/Declaration/<tt/unsigned char doesclrscrafterexit (void);/ <tag/Description/The function returns zero if the screen won't be cleared immediately after program termination. It returns a non-zero value if it will. <tag/Notes/<itemize> <item>Some systems, maybe depending on configuration, immediately clear the screen after a program exits. Therefore it might be difficult to read the last messages printed by the program prior to its exit. This function can be used to decide if a delay or wait for a key press should be executed when then program exits. </itemize> <tag/Availability/cc65 <tag/Example/<verb> /* Hello World */ #include <stdio.h> #include <unistd.h> #include <cc65.h> int main(void) { printf("Hello World\n"); if (doesclrscrafterexit()) sleep(5); return 0; } </verb> </descrip> </quote> <sect1>em_commit<label id="em_commit"><p> <quote> <descrip> <tag/Function/Commit changes into extended memory. <tag/Header/<tt/<ref id="em.h" name="em.h">/ <tag/Declaration/<tt/void em_commit (void);/ <tag/Description/Commit changes in the memory window to extended storage. If 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/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. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>The function produces undefined results if no extended memory driver is loaded. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="em_load_driver" name="em_load_driver">, <ref id="em_map" name="em_map">, <ref id="em_use" name="em_use"> <tag/Example/None. </descrip> </quote> <sect1>em_copyfrom<label id="em_copyfrom"><p> <quote> <descrip> <tag/Function/Copy from extended into normal memory. <tag/Header/<tt/<ref id="em.h" name="em.h">/ <tag/Declaration/<tt/void __fastcall__ em_copyfrom (const struct em_copy* copy_data);/ <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/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. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>The function produces undefined results if no extended memory driver is loaded. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="em_commit" name="em_commit">, <ref id="em_copyto" name="em_copyto">, <ref id="em_load_driver" name="em_load_driver"> <tag/Example/None. </descrip> </quote> <sect1>em_copyto<label id="em_copyto"><p> <quote> <descrip> <tag/Function/Copy from normal into extended memory. <tag/Header/<tt/<ref id="em.h" name="em.h">/ <tag/Declaration/<tt/void __fastcall__ em_copyto (const struct em_copy* copy_data);/ <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/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. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>The function produces undefined results if no extended memory driver is loaded. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="em_commit" name="em_commit">, <ref id="em_copyfrom" name="em_copyfrom">, <ref id="em_load_driver" name="em_load_driver"> <tag/Example/None. </descrip> </quote> <sect1>em_install<label id="em_install"><p> <quote> <descrip> <tag/Function/Install an already loaded extended memory driver. <tag/Header/<tt/<ref id="em.h" name="em.h">/ <tag/Declaration/<tt/unsigned char _fastcall__ em_install (void* driver);/ <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/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 used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="em_load_driver" name="em_load_driver">, <ref id="em_uninstall" name="em_uninstall">, <ref id="em_unload" name="em_unload"> <tag/Example/None. </descrip> </quote> <sect1>em_load_driver<label id="em_load_driver"><p> <quote> <descrip> <tag/Function/Load and initialize an extended memory driver. <tag/Header/<tt/<ref id="em.h" name="em.h">/ <tag/Declaration/<tt/unsigned char __fastcall__ em_load_driver (const char* name);/ <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/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 used in presence of a prototype. <item>The driver is loaded by name, so currently you must know the type of extended memory that should be supported. There is no autodetect capability. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="em_unload" name="em_unload"> <tag/Example/None. </descrip> </quote> <sect1>em_map<label id="em_map"><p> <quote> <descrip> <tag/Function/Make a page of extended memory accessible. <tag/Header/<tt/<ref id="em.h" name="em.h">/ <tag/Declaration/<tt/void* __fastcall__ em_map (unsigned page);/ <tag/Description/The function maps one page of extended memory into linear memory and returns a pointer to the page frame. Depending on the hardware and driver, the data is either mapped into the address space or transfered 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/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. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>The function produces undefined results if no extended memory driver is loaded. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="em_commit" name="em_commit">, <ref id="em_load_driver" name="em_load_driver">, <ref id="em_use" name="em_use"> <tag/Example/None. </descrip> </quote> <sect1>em_pagecount<label id="em_pagecount"><p> <quote> <descrip> <tag/Function/Return the number of available extended memory pages. <tag/Header/<tt/<ref id="em.h" name="em.h">/ <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/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> <tag/Availability/cc65 <tag/See also/ <ref id="em_load_driver" name="em_load_driver"> <tag/Example/None. </descrip> </quote> <sect1>em_uninstall<label id="em_uninstall"><p> <quote> <descrip> <tag/Function/Uninstall an already loaded extended memory driver. <tag/Header/<tt/<ref id="em.h" name="em.h">/ <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/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 from memory. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="em_install" name="em_install">, <ref id="em_load_driver" name="em_load_driver">, <ref id="em_unload" name="em_unload"> <tag/Example/None. </descrip> </quote> <sect1>em_unload<label id="em_unload"><p> <quote> <descrip> <tag/Function/Unload an extended memory driver. <tag/Header/<tt/<ref id="em.h" name="em.h">/ <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/Notes/<itemize> <item>The function does nothing if no driver is loaded. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="em_load_driver" name="em_load_driver"> <tag/Example/None. </descrip> </quote> <sect1>em_use<label id="em_use"><p> <quote> <descrip> <tag/Function/Prepare an extended memory page for use. <tag/Header/<tt/<ref id="em.h" name="em.h">/ <tag/Declaration/<tt/void* __fastcall__ em_use (unsigned page);/ <tag/Description/The function maps one page of extended memory into linear 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/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. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>The function produces undefined results if no extended memory driver is loaded. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="em_commit" name="em_commit">, <ref id="em_load_driver" name="em_load_driver">, <ref id="em_map" name="em_map"> <tag/Example/None. </descrip> </quote> <sect1>exit<label id="exit"><p> <quote> <descrip> <tag/Function/Terminate the program. <tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ <tag/Declaration/<tt/void __fastcall__ exit (int status);/ <tag/Description/<tt/exit/ terminates the program. The argument specifies the return code of the program. Before termination, all files are closed, buffered 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/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 evaluated or is ignored. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="abort" name="abort">, <ref id="exit" name="exit"> <tag/Example/None. </descrip> </quote> <sect1>exec<label id="exec"><p> <quote> <descrip> <tag/Function/Execute a program file. <tag/Header/<tt/<ref id="unistd.h" name="unistd.h">/ <tag/Declaration/<tt/int __fastcall__ exec (const char* progname, const char* cmdline);/ <tag/Description/<tt/exec/ replaces the currently running program by a new one. Calling <tt/exec()/ is identical to calling <tt/<ref id="exit" name="exit()">/, then loading and starting the program named in the first argument, passing 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/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 some memory area outside the program space. This may collide with other programs. See the platform specific docs on this. <item>Because it is necessary to terminate the running program before the memory can be reused to load the new one, there is a high chance that the function may not be able to return on errors. <item>The command line is passed to the new program in the same way as cc65 programs expect the command line. If the new program is not a cc65 generated program, it may not be able to read it. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="exit" name="exit"> <tag/Example/None. </descrip> </quote> <sect1>fast<label id="fast"><p> <quote> <descrip> <tag/Function/Switch the CPU into fast mode (C128: 2MHz mode, C16/Plus4: double clock mode). <tag/Header/<tt/<ref id="c128.h" name="c128.h">, <ref id="c16.h" name="c16.h">, <ref id="plus4.h" name="plus4.h">/ <tag/Declaration/<tt/void fast (void);/ <tag/Description/The function will switch the clock of the CPU to fast mode. For the C128 target it means switching the CPU into 2MHz mode. For the C16/Plus4 target it means switching the CPU into double clock mode. <tag/Notes/<itemize> <item>The function is specific to the C128, C16 and Plus4. <item>On the C128 the 2MHz clock will not work in 40 column mode. </itemize> <tag/Availability/cc65 (not all platforms) <tag/See also/ <ref id="isfast" name="isfast">, <ref id="slow" name="slow">, <tag/Example/None. </descrip> </quote> <sect1>feof<label id="feof"><p> <quote> <descrip> <tag/Function/Return the end-of-file indicator of a stream. <tag/Header/<tt/<ref id="stdio.h" name="stdio.h">/ <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/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 used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="feof" name="clearerr">, <ref id="ferror" name="ferror"> <tag/Example/None. </descrip> </quote> <sect1>ferror<label id="ferror"><p> <quote> <descrip> <tag/Function/Return the error indicator of a stream. <tag/Header/<tt/<ref id="stdio.h" name="stdio.h">/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="feof" name="clearerr">, <ref id="ferror" name="feof"> <tag/Example/None. </descrip> </quote> <sect1>fileno<label id="fileno"><p> <quote> <descrip> <tag/Function/Return the file handle used by a stream. <tag/Header/<tt/<ref id="stdio.h" name="stdio.h">/ <tag/Declaration/<tt/int __fastcall__ fileno (FILE* f);/ <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/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 file may have unpredictable results. </itemize> <tag/Availability/POSIX 1003.1 <tag/See also/ <ref id="creat" name="creat">, <ref id="open" name="open"> <!-- , --> <!-- <ref id="read" name="read">, --> <!-- <ref id="write" name="write"> --> <tag/Example/None. </descrip> </quote> <sect1>free<label id="free"><p> <quote> <descrip> <tag/Function/Free a block of dynamic memory. <tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ <tag/Declaration/<tt/void __fastcall__ free (void* block);/ <tag/Description/Free a block of dynamic memory previously allocated with <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/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 be used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="_heapadd" name="_heapadd">, <ref id="_heapblocksize" name="_heapblocksize">, <ref id="_heapmaxavail" name="_heapmaxavail">, <ref id="_heapmemavail" name="_heapmemavail">, <ref id="calloc" name="calloc">, <ref id="malloc" name="malloc">, <ref id="realloc" name="realloc"> <tag/Example/None. </descrip> </quote> <sect1>get_ostype<label id="get_ostype"><p> <quote> <descrip> <tag/Function/The function returns the operating system, the program runs on. <tag/Header/<tt/<ref id="apple2.h" name="apple2.h">, <ref id="atari.h" name="atari.h">, <ref id="c64.h" name="c64.h">/ <tag/Declaration/<tt/unsigned char get_ostype (void);/ <tag/Description/<tt/get_ostype/ is machine dependent and does not exist for 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/Notes/<itemize> <item>The function does not exist on all platforms. <item>The return codes are platform dependent. </itemize> <tag/Availability/cc65 (not all platforms) <tag/Example/None. </descrip> </quote> <sect1>get_c128_speed<label id="get_c128_speed"><p> <quote> <descrip> <tag/Function/Get the current speed of the C128 CPU. <tag/Header/<tt/<ref id="accelerator.h" name="accelerator.h">/ <tag/Declaration/<tt/unsigned char get_c128_speed (void);/ <tag/Description/The function returns the current speed of the C128 CPU. <tag/Notes/<itemize> <item>The function is specific to the C64 and C128. <item>The function does not check if the C128 CPU is the current CPU. <item>See the accelerator.h header for the speed definitions. </itemize> <tag/Availability/cc65 (not all platforms) <tag/See also/ <ref id="detect_c128" name="detect_c128">, <ref id="set_c128_speed" name="set_c128_speed">, <tag/Example/None. </descrip> </quote> <sect1>get_c64dtv_speed<label id="get_c64dtv_speed"><p> <quote> <descrip> <tag/Function/Get the current speed of the C64DTV. <tag/Header/<tt/<ref id="accelerator.h" name="accelerator.h">/ <tag/Declaration/<tt/unsigned char get_c64dtv_speed (void);/ <tag/Description/The function returns the current speed of the C64DTV. <tag/Notes/<itemize> <item>The function is specific to the C64. <item>The function does not check for the presence of the C64DTV. <item>See the accelerator.h header for the speed definitions. </itemize> <tag/Availability/cc65 (not all platforms) <tag/See also/ <ref id="detect_c64dtv" name="detect_c64dtv">, <ref id="set_c64dtv_speed" name="set_c64dtv_speed">, <tag/Example/None. </descrip> </quote> <sect1>get_c65_speed<label id="get_c65_speed"><p> <quote> <descrip> <tag/Function/Get the current speed of the C65/C64DX in C64 mode. <tag/Header/<tt/<ref id="accelerator.h" name="accelerator.h">/ <tag/Declaration/<tt/unsigned char get_c65_speed (void);/ <tag/Description/The function returns the current speed of the C65/C64DX in C64 mode. <tag/Notes/<itemize> <item>The function is specific to the C64. <item>The function does not check for the presence of a C65/C64DX in C64 mode. <item>See the accelerator.h header for the speed definitions. </itemize> <tag/Availability/cc65 (not all platforms) <tag/See also/ <ref id="detect_c65" name="detect_c65">, <ref id="set_c65_speed" name="set_c65_speed">, <tag/Example/None. </descrip> </quote> <sect1>get_chameleon_speed<label id="get_chameleon_speed"><p> <quote> <descrip> <tag/Function/Get the current speed of the C64 Chameleon cartridge. <tag/Header/<tt/<ref id="accelerator.h" name="accelerator.h">/ <tag/Declaration/<tt/unsigned char get_chameleon_speed (void);/ <tag/Description/The function returns the current speed of the C64 Chameleon cartridge. <tag/Notes/<itemize> <item>The function is specific to the C64. <item>The function does not check for the presence of the C64 Chameleon cartridge. <item>See the accelerator.h header for the speed definitions. </itemize> <tag/Availability/cc65 (not all platforms) <tag/See also/ <ref id="detect_chameleon" name="detect_chameleon">, <ref id="set_chameleon_speed" name="set_chameleon_speed">, <tag/Example/None. </descrip> </quote> <sect1>get_scpu_speed<label id="get_scpu_speed"><p> <quote> <descrip> <tag/Function/Get the current speed of the C64/C128 SuperCPU cartridge. <tag/Header/<tt/<ref id="accelerator.h" name="accelerator.h">/ <tag/Declaration/<tt/unsigned char get_scpu_speed (void);/ <tag/Description/The function returns the current speed of the SuperCPU cartridge. <tag/Notes/<itemize> <item>The function is specific to the C128 and C64. <item>The function does not check for the presence of the cartridge. <item>See the accelerator.h header for the speed definitions. </itemize> <tag/Availability/cc65 (not all platforms) <tag/See also/ <ref id="detect_scpu" name="detect_scpu">, <ref id="set_scpu_speed" name="set_scpu_speed">, <tag/Example/None. </descrip> </quote> <sect1>get_turbomaster_speed<label id="get_turbomaster_speed"><p> <quote> <descrip> <tag/Function/Get the current speed of the C64 Turbo Master cartridge. <tag/Header/<tt/<ref id="accelerator.h" name="accelerator.h">/ <tag/Declaration/<tt/unsigned char get_turbomaster_speed (void);/ <tag/Description/The function returns the current speed of the C64 Turbo Master cartridge. <tag/Notes/<itemize> <item>The function is specific to the C64. <item>The function does not check for the presence of the C64 Turbo Master cartridge. <item>See the accelerator.h header for the speed definitions. </itemize> <tag/Availability/cc65 (not all platforms) <tag/See also/ <ref id="detect_turbomaster" name="detect_turbomaster">, <ref id="set_turbomaster_speed" name="set_turbomaster_speed">, <tag/Example/None. </descrip> </quote> <sect1>getcpu<label id="getcpu"><p> <quote> <descrip> <tag/Function/Determine on which CPU the program is running. <tag/Header/<tt/<ref id="6502.h" name="6502.h">/ <tag/Declaration/<tt/unsigned char getcpu (void);/ <tag/Description/The function checks on which CPU the code is running. It returns one of the constants<itemize> <item><tt/CPU_6502/ <item><tt/CPU_65C02/ <item><tt/CPU_65816/ <item><tt/CPU_4510/ <item><tt/CPU_65SC02/ <item><tt/CPU_65CE02/ <item><tt/CPU_HUC6280/ <item><tt/CPU_2A0x/ </itemize> <tag/Notes/<itemize> <item>Other, more exotic CPU types are not disinguished. </itemize> <tag/Availability/cc65 <tag/Example/None. </descrip> </quote> <sect1>getcurrentdevice<label id="getcurrentdevice"><p> <quote> <descrip> <tag/Function/Get current device. <tag/Header/<tt/<ref id="device.h" name="device.h">/ <tag/Declaration/<tt/unsigned char getcurrentdevice (void);/ <tag/Description/The function returns the current device. It allows to access the current device with the <ref id="dio.h" name="Low-level disk I/O API"> or <ref id="cbm.h" name="cbm_* I/O functions"> requiring a 'device' parameter. <tag/Availability/cc65 <tag/See also/ <ref id="getdevicedir" name="getdevicedir">, <ref id="getfirstdevice" name="getfirstdevice">, <ref id="getnextdevice" name="getnextdevice"> <tag/Example/<verb> dio_open (getcurrentdevice ()); </verb> </descrip> </quote> <sect1>getcwd<label id="getcwd"><p> <quote> <descrip> <tag/Function/Get current working directory. <tag/Header/<tt/<ref id="unistd.h" name="unistd.h">/ <tag/Declaration/<tt/char* __fastcall__ getcwd (char* buf, size_t size);/ <tag/Description/The function will return the current working directory. <tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/POSIX 1003.1 <tag/Example/None. </descrip> </quote> <sect1>getdevicedir<label id="getdevicedir"><p> <quote> <descrip> <tag/Function/Get device directory. <tag/Header/<tt/<ref id="device.h" name="device.h">/ <tag/Declaration/<tt/char* __fastcall__ getdevicedir (unsigned char device, char* buf, size_t size);/ <tag/Description/The function returns the directory representing <tt/device/. It allows to access the device on filesystem level by calling chdir() with the directory returned. <tag/Notes/<itemize> <item>Calling getdevicedir() <em/does/ check for a (formatted) disk in a floppy-disk-type device and returns NULL if that check fails. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="getcwd" name="getcwd">, <ref id="getcurrentdevice" name="getcurrentdevice">, <ref id="getfirstdevice" name="getfirstdevice">, <ref id="getnextdevice" name="getnextdevice"> <tag/Example/<verb> chdir (getdevicedir (device, buf, sizeof buf)); </verb> cf. <tt/samples/enumdevdir.c/ </descrip> </quote> <sect1>getenv<label id="getenv"><p> <quote> <descrip> <tag/Function/Return a value from the environment. <tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ <tag/Declaration/<tt/char* __fastcall__ getenv (const char* name);/ <tag/Description/The function searches the environment for an entry that 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/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 be used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/Example/None. </descrip> </quote> <sect1>getfirstdevice<label id="getfirstdevice"><p> <quote> <descrip> <tag/Function/Get first device. <tag/Header/<tt/<ref id="device.h" name="device.h">/ <tag/Declaration/<tt/unsigned char getfirstdevice (void);/ <tag/Description/The function returns the first device. The constant <tt/INVALID_DEVICE/ indicates no device. <tag/Notes/<itemize> <item>Calling getfirstdevice() does <em/not/ turn on the motor of a drive-type device and does <em/not/ check for a disk in the drive. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="getcurrentdevice" name="getcurrentdevice">, <ref id="getdevicedir" name="getdevicedir">, <ref id="getnextdevice" name="getnextdevice"> <tag/Example/<verb> unsigned char dev = getfirstdevice (); while (dev != INVALID_DEVICE) { printf ("%d\n", dev); dev = getnextdevice (dev); } </verb> </descrip> </quote> <sect1>getnextdevice<label id="getnextdevice"><p> <quote> <descrip> <tag/Function/Get next device. <tag/Header/<tt/<ref id="device.h" name="device.h">/ <tag/Declaration/<tt/unsigned char __fastcall__ getnextdevice (unsigned char device);/ <tag/Description/The function returns the next device after <tt/device/. The constant <tt/INVALID_DEVICE/ indicates no further device. <tag/Notes/<itemize> <item>Calling getnextdevice() does <em/not/ turn on the motor of a drive-type device and does <em/not/ check for a disk in the drive. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="getcurrentdevice" name="getcurrentdevice">, <ref id="getdevicedir" name="getdevicedir">, <ref id="getfirstdevice" name="getfirstdevice"> <tag/Example/<verb> unsigned char dev = getfirstdevice (); while (dev != INVALID_DEVICE) { printf ("%d\n", dev); dev = getnextdevice (dev); } </verb> </descrip> </quote> <sect1>getopt<label id="getopt"><p> <quote> <descrip> <tag/Function/Parse command line options. <tag/Header/<tt/<ref id="unistd.h" name="unistd.h">/ <tag/Declaration/<tt/int __fastcall__ getopt (int argc, char* const* argv, const char* optstring);/ <tag/Description/The function parses command line arguments, <tt/argc/ and <tt/argv/ are the argument count and array passed to <tt/main/. <tt/optstring/ is a string that contains command line option characters. If a character in <tt/optstring/ is followed by a colon, the option requires an argument. An option on the command line is recognized if it is one of the option characters preceeded by a '-'. <tt/getopt/ must be called repeatedly. It will return each option character 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/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. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/POSIX.2 <tag/Example/None. </descrip> </quote> <sect1>gotox<label id="gotox"><p> <quote> <descrip> <tag/Function/Move the text mode cursor to a new X position. <tag/Header/<tt/<ref id="conio.h" name="conio.h">/ <tag/Declaration/<tt/void __fastcall__ gotox (unsigned char x);/ <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/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 lead to undefined behaviour. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="gotoy" name="gotoy">, <ref id="gotoxy" name="gotoxy">, <ref id="wherex" name="wherex">, <ref id="wherey" name="wherey"> <tag/Example/None. </descrip> </quote> <sect1>gotoxy<label id="gotoxy"><p> <quote> <descrip> <tag/Function/Move the text mode cursor to a new position. <tag/Header/<tt/<ref id="conio.h" name="conio.h">/ <tag/Declaration/<tt/void __fastcall__ gotoxy (unsigned char x, unsigned char y);/ <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/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 lead to undefined behaviour. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="gotox" name="gotox">, <ref id="gotoy" name="gotoy">, <ref id="wherex" name="wherex">, <ref id="wherey" name="wherey"> <tag/Example/None. </descrip> </quote> <sect1>gotoy<label id="gotoy"><p> <quote> <descrip> <tag/Function/Move the text mode cursor to a new Y position. <tag/Header/<tt/<ref id="conio.h" name="conio.h">/ <tag/Declaration/<tt/void __fastcall__ gotoy (unsigned char x);/ <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/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 to undefined behaviour. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="gotox" name="gotox">, <ref id="gotoxy" name="gotoxy">, <ref id="wherex" name="wherex">, <ref id="wherey" name="wherey"> <tag/Example/None. </descrip> </quote> <sect1>isalnum<label id="isalnum"><p> <quote> <descrip> <tag/Function/Check if a given character is a letter or digit. <tag/Header/<tt/<ref id="ctype.h" name="ctype.h">/ <tag/Declaration/<tt/int __fastcall__ isalnum (int c);/ <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/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 this range. The non inline function may be accessed by <tt/#undef/'ing the 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/ISO 9899 <tag/See also/ <ref id="isalpha" name="isalpha">, <ref id="isascii" name="isascii">, <ref id="isblank" name="isblank">, <ref id="iscntrl" name="iscntrl">, <ref id="isdigit" name="isdigit">, <ref id="isgraph" name="isgraph">, <ref id="islower" name="islower">, <ref id="isprint" name="isprint">, <ref id="ispunct" name="ispunct">, <ref id="isspace" name="isspace">, <ref id="isupper" name="isupper">, <ref id="isxdigit" name="isxdigit"> <tag/Example/None. </descrip> </quote> <sect1>isalpha<label id="isalpha"><p> <quote> <descrip> <tag/Function/Check if a given character is a letter. <tag/Header/<tt/<ref id="ctype.h" name="ctype.h">/ <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/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 this range. The non inline function may be accessed by <tt/#undef/'ing the 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/ISO 9899 <tag/See also/ <ref id="isalnum" name="isalnum">, <ref id="isascii" name="isascii">, <ref id="isblank" name="isblank">, <ref id="iscntrl" name="iscntrl">, <ref id="isdigit" name="isdigit">, <ref id="isgraph" name="isgraph">, <ref id="islower" name="islower">, <ref id="isprint" name="isprint">, <ref id="ispunct" name="ispunct">, <ref id="isspace" name="isspace">, <ref id="isupper" name="isupper">, <ref id="isxdigit" name="isxdigit"> <tag/Example/None. </descrip> </quote> <sect1>isascii<label id="isascii"><p> <quote> <descrip> <tag/Function/Check if a given character is in the ASCII (0..127) range. <tag/Header/<tt/<ref id="ctype.h" name="ctype.h">/ <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/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 this range. The non inline function may be accessed by <tt/#undef/'ing the 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/ISO 9899 <tag/See also/ <ref id="isalnum" name="isalnum">, <ref id="isalpha" name="isalpha">, <ref id="isblank" name="isblank">, <ref id="iscntrl" name="iscntrl">, <ref id="isdigit" name="isdigit">, <ref id="isgraph" name="isgraph">, <ref id="islower" name="islower">, <ref id="isprint" name="isprint">, <ref id="ispunct" name="ispunct">, <ref id="isspace" name="isspace">, <ref id="isupper" name="isupper">, <ref id="isxdigit" name="isxdigit"> <tag/Example/None. </descrip> </quote> <sect1>isblank<label id="isblank"><p> <quote> <descrip> <tag/Function/Check if a given character is a space or tab. <tag/Header/<tt/<ref id="ctype.h" name="ctype.h">/ <tag/Declaration/<tt/int __fastcall__ isblank (int c);/ <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/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 this range. The non inline function may be accessed by <tt/#undef/'ing the 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/ISO 9899 <tag/See also/ <ref id="isalnum" name="isalnum">, <ref id="isalpha" name="isalpha">, <ref id="isascii" name="isascii">, <ref id="iscntrl" name="iscntrl">, <ref id="isdigit" name="isdigit">, <ref id="isgraph" name="isgraph">, <ref id="islower" name="islower">, <ref id="isprint" name="isprint">, <ref id="ispunct" name="ispunct">, <ref id="isspace" name="isspace">, <ref id="isupper" name="isupper">, <ref id="isxdigit" name="isxdigit"> <tag/Example/None. </descrip> </quote> <sect1>iscntrl<label id="iscntrl"><p> <quote> <descrip> <tag/Function/Check if a given character is a control character. <tag/Header/<tt/<ref id="ctype.h" name="ctype.h">/ <tag/Declaration/<tt/int __fastcall__ iscntrl (int c);/ <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/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 this range. The non inline function may be accessed by <tt/#undef/'ing the 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/ISO 9899 <tag/See also/ <ref id="isalnum" name="isalnum">, <ref id="isalpha" name="isalpha">, <ref id="isascii" name="isascii">, <ref id="isblank" name="isblank">, <ref id="isdigit" name="isdigit">, <ref id="isgraph" name="isgraph">, <ref id="islower" name="islower">, <ref id="isprint" name="isprint">, <ref id="ispunct" name="ispunct">, <ref id="isspace" name="isspace">, <ref id="isupper" name="isupper">, <ref id="isxdigit" name="isxdigit"> <tag/Example/None. </descrip> </quote> <sect1>isdigit<label id="isdigit"><p> <quote> <descrip> <tag/Function/Check if a given character is a digit. <tag/Header/<tt/<ref id="ctype.h" name="ctype.h">/ <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/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 this range. The non inline function may be accessed by <tt/#undef/'ing the 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/ISO 9899 <tag/See also/ <ref id="isalnum" name="isalnum">, <ref id="isalpha" name="isalpha">, <ref id="isascii" name="isascii">, <ref id="isblank" name="isblank">, <ref id="iscntrl" name="iscntrl">, <ref id="isgraph" name="isgraph">, <ref id="islower" name="islower">, <ref id="isprint" name="isprint">, <ref id="ispunct" name="ispunct">, <ref id="isspace" name="isspace">, <ref id="isupper" name="isupper">, <ref id="isxdigit" name="isxdigit"> <tag/Example/None. </descrip> </quote> <sect1>isfast<label id="isfast"><p> <quote> <descrip> <tag/Function/Check if the CPU is in fast mode (C128: 2MHz mode, C16/Plus4: double clock mode). <tag/Header/<tt/<ref id="c128.h" name="c128.h">, <ref id="c16.h" name="c16.h">, <ref id="plus4.h" name="plus4.h">/ <tag/Declaration/<tt/unsigned char isfast (void);/ <tag/Description/The function returns a 1 if the CPU is in fast mode (C128: 2MHz mode, C16/Plus4: double clock mode). <tag/Notes/<itemize> <item>The function is specific to the C128, C16 and Plus4. </itemize> <tag/Availability/cc65 (not all platforms) <tag/See also/ <ref id="fast" name="fast">, <ref id="slow" name="slow">, <tag/Example/None. </descrip> </quote> <sect1>isgraph<label id="isgraph"><p> <quote> <descrip> <tag/Function/Check if a given character is a printable character (except space). <tag/Header/<tt/<ref id="ctype.h" name="ctype.h">/ <tag/Declaration/<tt/int __fastcall__ isgraph (int c);/ <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/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 this range. The non inline function may be accessed by <tt/#undef/'ing the 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/ISO 9899 <tag/See also/ <ref id="isalnum" name="isalnum">, <ref id="isalpha" name="isalpha">, <ref id="isascii" name="isascii">, <ref id="isblank" name="isblank">, <ref id="iscntrl" name="iscntrl">, <ref id="isdigit" name="isdigit">, <ref id="islower" name="islower">, <ref id="isprint" name="isprint">, <ref id="ispunct" name="ispunct">, <ref id="isspace" name="isspace">, <ref id="isupper" name="isupper">, <ref id="isxdigit" name="isxdigit"> <tag/Example/None. </descrip> </quote> <sect1>islower<label id="islower"><p> <quote> <descrip> <tag/Function/Check if a given character is a lower case letter. <tag/Header/<tt/<ref id="ctype.h" name="ctype.h">/ <tag/Declaration/<tt/int __fastcall__ islower (int c);/ <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/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 this range. The non inline function may be accessed by <tt/#undef/'ing the 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/ISO 9899 <tag/See also/ <ref id="isalnum" name="isalnum">, <ref id="isalpha" name="isalpha">, <ref id="isascii" name="isascii">, <ref id="isblank" name="isblank">, <ref id="iscntrl" name="iscntrl">, <ref id="isdigit" name="isdigit">, <ref id="isgraph" name="isgraph">, <ref id="isprint" name="isprint">, <ref id="ispunct" name="ispunct">, <ref id="isspace" name="isspace">, <ref id="isupper" name="isupper">, <ref id="isxdigit" name="isxdigit"> <tag/Example/None. </descrip> </quote> <sect1>isprint<label id="isprint"><p> <quote> <descrip> <tag/Function/Check if a given character is a printable character. <tag/Header/<tt/<ref id="ctype.h" name="ctype.h">/ <tag/Declaration/<tt/int __fastcall__ isprint (int c);/ <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/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 this range. The non inline function may be accessed by <tt/#undef/'ing the 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/ISO 9899 <tag/See also/ <ref id="isalnum" name="isalnum">, <ref id="isalpha" name="isalpha">, <ref id="isascii" name="isascii">, <ref id="isblank" name="isblank">, <ref id="iscntrl" name="iscntrl">, <ref id="isdigit" name="isdigit">, <ref id="isgraph" name="isgraph">, <ref id="islower" name="islower">, <ref id="ispunct" name="ispunct">, <ref id="isspace" name="isspace">, <ref id="isupper" name="isupper">, <ref id="isxdigit" name="isxdigit"> <tag/Example/None. </descrip> </quote> <sect1>ispunct<label id="ispunct"><p> <quote> <descrip> <tag/Function/Check if a given character is a printable character but not a space or an alphanumeric character. <tag/Header/<tt/<ref id="ctype.h" name="ctype.h">/ <tag/Declaration/<tt/int __fastcall__ ispunct (int c);/ <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/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 this range. The non inline function may be accessed by <tt/#undef/'ing the 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/ISO 9899 <tag/See also/ <ref id="isalnum" name="isalnum">, <ref id="isalpha" name="isalpha">, <ref id="isascii" name="isascii">, <ref id="isblank" name="isblank">, <ref id="iscntrl" name="iscntrl">, <ref id="isdigit" name="isdigit">, <ref id="isgraph" name="isgraph">, <ref id="islower" name="islower">, <ref id="isprint" name="isprint">, <ref id="isspace" name="isspace">, <ref id="isupper" name="isupper">, <ref id="isxdigit" name="isxdigit"> <tag/Example/None. </descrip> </quote> <sect1>isspace<label id="isspace"><p> <quote> <descrip> <tag/Function/Check if a given character is a white-space character. <tag/Header/<tt/<ref id="ctype.h" name="ctype.h">/ <tag/Declaration/<tt/int __fastcall__ isspace (int c);/ <tag/Description/The function returns a non zero value if the given argument 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/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 this range. The non inline function may be accessed by <tt/#undef/'ing the 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/ISO 9899 <tag/See also/ <ref id="isalnum" name="isalnum">, <ref id="isalpha" name="isalpha">, <ref id="isascii" name="isascii">, <ref id="isblank" name="isblank">, <ref id="iscntrl" name="iscntrl">, <ref id="isdigit" name="isdigit">, <ref id="isgraph" name="isgraph">, <ref id="islower" name="islower">, <ref id="isprint" name="isprint">, <ref id="ispunct" name="ispunct">, <ref id="isupper" name="isupper">, <ref id="isxdigit" name="isxdigit"> <tag/Example/None. </descrip> </quote> <sect1>isupper<label id="isupper"><p> <quote> <descrip> <tag/Function/Check if a given character is an upper case letter. <tag/Header/<tt/<ref id="ctype.h" name="ctype.h">/ <tag/Declaration/<tt/int __fastcall__ isupper (int c);/ <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/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 this range. The non inline function may be accessed by <tt/#undef/'ing the 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/ISO 9899 <tag/See also/ <ref id="isalnum" name="isalnum">, <ref id="isalpha" name="isalpha">, <ref id="isascii" name="isascii">, <ref id="isblank" name="isblank">, <ref id="iscntrl" name="iscntrl">, <ref id="isdigit" name="isdigit">, <ref id="isgraph" name="isgraph">, <ref id="islower" name="islower">, <ref id="isprint" name="isprint">, <ref id="ispunct" name="ispunct">, <ref id="isspace" name="isspace">, <ref id="isxdigit" name="isxdigit"> <tag/Example/None. </descrip> </quote> <sect1>isxdigit<label id="isxdigit"><p> <quote> <descrip> <tag/Function/Check if a given character is a hexadecimal digit. <tag/Header/<tt/<ref id="ctype.h" name="ctype.h">/ <tag/Declaration/<tt/int __fastcall__ isxdigit (int c);/ <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/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 this range. The non inline function may be accessed by <tt/#undef/'ing the 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/ISO 9899 <tag/See also/ <ref id="isalnum" name="isalnum">, <ref id="isalpha" name="isalpha">, <ref id="isascii" name="isascii">, <ref id="isblank" name="isblank">, <ref id="iscntrl" name="iscntrl">, <ref id="isdigit" name="isdigit">, <ref id="isgraph" name="isgraph">, <ref id="islower" name="islower">, <ref id="isprint" name="isprint">, <ref id="ispunct" name="ispunct">, <ref id="isspace" name="isspace">, <ref id="isupper" name="isupper"> <tag/Example/None. </descrip> </quote> <sect1>itoa<label id="itoa"><p> <quote> <descrip> <tag/Function/Convert an integer into a string. <tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ <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/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. You should probably use <tt/sprintf/ instead. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="atoi" name="atoi">, <ref id="atol" name="atol">, <ref id="ltoa" name="ltoa">, <ref id="ultoa" name="ultoa">, <ref id="utoa" name="utoa"> <tag/Example/None. </descrip> </quote> <sect1>joy_count<label id="joy_count"><p> <quote> <descrip> <tag/Function/Return the number of joysticks supported by the current driver. <tag/Header/<tt/<ref id="joystick.h" name="joystick.h">/ <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/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. There's no way to check for the number of actually connected joysticks. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="joy_load_driver" name="joy_load_driver">, <ref id="joy_read" name="joy_read"> <tag/Example/None. </descrip> </quote> <sect1>joy_install<label id="joy_install"><p> <quote> <descrip> <tag/Function/Install an already loaded driver and return an error code. <tag/Header/<tt/<ref id="joystick.h" name="joystick.h">/ <tag/Declaration/<tt/unsigned char __fastcall__ joy_install (void* driver);/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="joy_load_driver" name="joy_load_driver">, <ref id="joy_uninstall" name="joy_uninstall">, <ref id="joy_unload" name="joy_unload"> <tag/Example/None. </descrip> </quote> <sect1>joy_load_driver<label id="joy_load_driver"><p> <quote> <descrip> <tag/Function/Load a driver from disk and install it. <tag/Header/<tt/<ref id="joystick.h" name="joystick.h">/ <tag/Declaration/<tt/unsigned char __fastcall__ joy_load_driver (const char* driver);/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="joy_install" name="joy_install">, <ref id="joy_uninstall" name="joy_uninstall">, <ref id="joy_unload" name="joy_unload"> <tag/Example/None. </descrip> </quote> <sect1>joy_read<label id="joy_read"><p> <quote> <descrip> <tag/Function/Read the status of a joystick. <tag/Header/<tt/<ref id="joystick.h" name="joystick.h">/ <tag/Declaration/<tt/unsigned char __fastcall__ joy_read (unsigned char joystick);/ <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/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 used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="joy_count" name="joy_count">, <ref id="joy_load_driver" name="joy_load_driver">, <ref id="joy_unload" name="joy_unload"> <tag/Example/None. </descrip> </quote> <sect1>joy_uninstall<label id="joy_uninstall"><p> <quote> <descrip> <tag/Function/Uninstall the current joystick driver. <tag/Header/<tt/<ref id="joystick.h" name="joystick.h">/ <tag/Declaration/<tt/unsigned char joy_uninstall (void);/ <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/Notes/<itemize> <item>A joystick driver must be installed using <ref id="joy_install" name="joy_install"> before calling this function. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="joy_install" name="joy_install">, <ref id="joy_load_driver" name="joy_load_driver">, <ref id="joy_unload" name="joy_unload"> <tag/Example/None. </descrip> </quote> <sect1>joy_unload<label id="joy_unload"><p> <quote> <descrip> <tag/Function/Uninstall, then unload the current joystick driver. <tag/Header/<tt/<ref id="joystick.h" name="joystick.h">/ <tag/Declaration/<tt/unsigned char joy_unload (void);/ <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/Notes/<itemize> <item>A joystick driver must be loaded using <ref id="joy_load_driver" name="joy_load_driver"> before calling this function. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="joy_load_driver" name="joy_load_driver"> <tag/Example/None. </descrip> </quote> <sect1>kbhit<label id="kbhit"><p> <quote> <descrip> <tag/Function/Check if there's a key waiting in the keyboard buffer. <tag/Header/<tt/<ref id="conio.h" name="conio.h">/ <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/Notes/<itemize> <item>If the system does not support a keyboard buffer (most systems do), the function is rather useless. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cgetc" name="cgetc">, <ref id="cursor" name="cursor"> <tag/Example/None. </descrip> </quote> <sect1>kbrepeat<label id="kbrepeat"><p> <quote> <descrip> <tag/Function/Set the keyboard repeat mode. <tag/Header/<tt/<ref id="cbm.h" name="cbm.h">/ <tag/Declaration/<tt/unsigned char __fastcall__ kbrepeat (unsigned char mode);/ <tag/Description/This function changes which keys have automatic repeat when being held down for a certain time. Possible values are <tt/KBREPEAT_CURSOR/ (repeat only cursor-related keys), <tt/KBREPEAT_NONE/ (no repeat for any keys), and <tt/KBREPEAT_ALL/ (repeat all keys). The old mode is returned, so it can be restored later. <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/Example/None. </descrip> </quote> <sect1>labs<label id="labs"><p> <quote> <descrip> <tag/Function/Returns the absolute value of a long integer. <tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ <tag/Declaration/<tt/long __fastcall__ labs (long v);/ <tag/Description/<tt/labs/ returns the absolute value of the argument passed to the function. <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. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="abs" name="abs"> <tag/Example/None. </descrip> </quote> <sect1>ltoa<label id="ltoa"><p> <quote> <descrip> <tag/Function/Convert a long integer into a string. <tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ <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/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. You should probably use <tt/sprintf/ instead. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="atoi" name="atoi">, <ref id="atol" name="atol">, <ref id="itoa" name="itoa">, <ref id="ultoa" name="ultoa">, <ref id="utoa" name="utoa"> <tag/Example/None. </descrip> </quote> <sect1>localeconv<label id="localeconv"><p> <quote> <descrip> <tag/Function/Returns a pointer to the current locale structure. <tag/Header/<tt/<ref id="locale.h" name="locale.h">/ <tag/Declaration/<tt/struct lconv* localeconv (void);/ <tag/Description/<tt/localeconv/ returns a pointer to the current locale structure. <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. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="setlocale" name="setlocale"> <tag/Example/None. </descrip> </quote> <sect1>longjmp<label id="longjmp"><p> <quote> <descrip> <tag/Function/Non local goto. <tag/Header/<tt/<ref id="setjmp.h" name="setjmp.h">/ <tag/Declaration/<tt/void __fastcall__ longjmp (jmp_buf buf, int retval);/ <tag/Description/The <tt/longjmp/ function restores a program context from the 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/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 be used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="setjmp" name="setjmp"> <tag/Example/None. </descrip> </quote> <sect1>malloc<label id="malloc"><p> <quote> <descrip> <tag/Function/Allocate dynamic memory. <tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ <tag/Declaration/<tt/void* __fastcall__ malloc (size_t size);/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="_heapadd" name="_heapadd">, <ref id="_heapblocksize" name="_heapblocksize">, <ref id="_heapmaxavail" name="_heapmaxavail">, <ref id="_heapmemavail" name="_heapmemavail">, <ref id="calloc" name="calloc">, <ref id="free" name="free">, <ref id="realloc" name="realloc">, <ref id="strdup" name="strdup"> <tag/Example/None. </descrip> </quote> <sect1>memchr<label id="memchr"><p> <quote> <descrip> <tag/Function/Search for a character in a block of raw memory. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <tag/Declaration/<tt/void* __fastcall__ strchr (const void* mem, int c, size_t count);/ <tag/Description/The <tt/memchr/ function locates the first occurrence of <tt/c/ (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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="strchr" name="strchr"> <tag/Example/None. </descrip> </quote> <sect1>memcmp<label id="memcmp"><p> <quote> <descrip> <tag/Function/Compare two memory areas. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <tag/Declaration/<tt/int __fastcall__ memcmp (const void* p1, const void* p2, size_t count);/ <tag/Description/<tt/memcmp/ compares <tt/count/ bytes from the memory area 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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="strcmp" name="strcmp">, <ref id="memmove" name="memmove">, <ref id="memset" name="memset"> <tag/Example/None. </descrip> </quote> <sect1>memcpy<label id="memcpy"><p> <quote> <descrip> <tag/Function/Copy a memory area. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <tag/Declaration/<tt/void* __fastcall__ memcpy (void* dest, const void* src, size_t count);/ <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/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 be used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="_swap" name="_swap">, <ref id="memmove" name="memmove">, <ref id="memset" name="memset"> <tag/Example/None. </descrip> </quote> <sect1>memmove<label id="memmove"><p> <quote> <descrip> <tag/Function/Copy a memory area. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <tag/Declaration/<tt/void* __fastcall__ memmove (void* dest, const void* src, size_t count);/ <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/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 be used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="_swap" name="_swap">, <ref id="memcpy" name="memcpy">, <ref id="memset" name="memset"> <tag/Example/None. </descrip> </quote> <sect1>memset<label id="memset"><p> <quote> <descrip> <tag/Function/Fill a memory area. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="_swap" name="_swap">, <ref id="bzero" name="bzero">, <ref id="memcpy" name="memcpy">, <ref id="memmove" name="memmove"> <tag/Example/None. </descrip> </quote> <sect1>mod_free<label id="mod_free"><p> <quote> <descrip> <tag/Function/Free a relocatable module. <tag/Header/<tt/<ref id="modload.h" name="modload.h">/ <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/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/ <ref id="mod_load" name="mod_load"> <tag/Example/None. </descrip> </quote> <sect1>mod_load<label id="mod_load"><p> <quote> <descrip> <tag/Function/Load a relocatable module. <tag/Header/<tt/<ref id="modload.h" name="modload.h">/ <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 the module just loaded. Possible error codes are: <itemize> <item><tt/MLOAD_OK/ - Module load successful <item><tt/MLOAD_ERR_READ/ - Read error <item><tt/MLOAD_ERR_HDR/ - Header error <item><tt/MLOAD_ERR_OS/ - Wrong operating system <item><tt/MLOAD_ERR_FMT/ - Data format error <item><tt/MLOAD_ERR_MEM/ - Not enough memory </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/ <ref id="mod_free" name="mod_free"> <tag/Example/None. </descrip> </quote> <sect1>mouse_setbox<label id="mouse_setbox"><p> <quote> <descrip> <tag/Function/Specify a bounding box for the mouse cursor. <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/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. <item>While the bounding box may be larger than the actual screen size, the standard mouse cursor draw routines may fail to set the cursor to coordinates outside of the screen area. Depending on the platform, you may have to supply your own mouse cursor routines. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="mouse_getbox" name="mouse_getbox">, <ref id="mouse_move" name="mouse_move"> <tag/Example/None. </descrip> </quote> <sect1>mouse_getbox<label id="mouse_getbox"><p> <quote> <descrip> <tag/Function/Return the current bounding box for the mouse cursor. <tag/Header/<tt/<ref id="mouse.h" name="mouse.h">/ <tag/Declaration/<tt/void __fastcall__ mouse_getbox (struct mouse_box* box);/ <tag/Description/The function queries the current bounding box for mouse movement. <tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="mouse_move" name="mouse_move">, <ref id="mouse_setbox" name="mouse_setbox"> <tag/Example/None. </descrip> </quote> <sect1>mouse_buttons<label id="mouse_buttons"><p> <quote> <descrip> <tag/Function/Return a bit mask encoding the state of the mouse buttons. <tag/Header/<tt/<ref id="mouse.h" name="mouse.h">/ <tag/Declaration/<tt/unsigned char mouse_buttons (void);/ <tag/Description/The function returns a bit mask that encodes the state of the mouse buttons. You may use the <tt/MOUSE_BTN_XXX/ flags to decode the function return value. <tag/Availability/cc65 <tag/See also/ <ref id="mouse_info" name="mouse_info">, <ref id="mouse_pos" name="mouse_pos"> <tag/Example/None. </descrip> </quote> <sect1>mouse_geterrormsg<label id="mouse_geterrormsg"><p> <quote> <descrip> <tag/Function/Return a readable error message for an error code. <tag/Header/<tt/<ref id="mouse.h" name="mouse.h">/ <tag/Declaration/<tt/const char* __fastcall__ mouse_geterrormsg (unsigned char code);/ <tag/Description/The function returns an error message (in english) for the error code passed parameter. <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. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="mouse_load_driver" name="mouse_load_driver">, <ref id="mouse_uninstall" name="mouse_uninstall">, <ref id="mouse_unload" name="mouse_unload"> <tag/Example/None. </descrip> </quote> <sect1>mouse_hide<label id="mouse_hide"><p> <quote> <descrip> <tag/Function/Hide the mouse pointer. <tag/Header/<tt/<ref id="mouse.h" name="mouse.h">/ <tag/Declaration/<tt/void mouse_hide (void);/ <tag/Description/The function hides the mouse pointer. It manages a counter that is shared between <tt/<ref id="mouse_show" name="mouse_show">/ and <tt/mouse_hide/ so that every call call to <tt/mouse_hide/ must be followed by a call to <tt/<ref id="mouse_show" name="mouse_show">/ to make the mouse cursor visible. <tag/Availability/cc65 <tag/See also/ <ref id="mouse_show" name="mouse_show"> <tag/Example/None. </descrip> </quote> <sect1>mouse_info<label id="mouse_info"><p> <quote> <descrip> <tag/Function/Return the state of the mouse buttons and the position of the mouse. <tag/Header/<tt/<ref id="mouse.h" name="mouse.h">/ <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/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. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="mouse_buttons" name="mouse_buttons">, <ref id="mouse_pos" name="mouse_pos"> <tag/Example/None. </descrip> </quote> <sect1>mouse_install<label id="mouse_install"><p> <quote> <descrip> <tag/Function/Install an already loaded mouse driver. <tag/Header/<tt/<ref id="mouse.h" name="mouse.h">/ <tag/Declaration/<tt/unsigned char __fastcall__ mouse_install (const struct mouse_callbacks* c, void* driver);/ <tag/Description/The function installs an already loaded mouse driver and returns an error code. The <tt/mouse_callbacks/ structure passed as first parameter contains pointers to 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/. The function may be used to install a driver linked statically to the program. <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. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="mouse_load_driver" name="mouse_load_driver">, <ref id="mouse_uninstall" name="mouse_uninstall">, <ref id="mouse_unload" name="mouse_unload"> <tag/Example/None. </descrip> </quote> <sect1>mouse_ioctl<label id="mouse_ioctl"><p> <quote> <descrip> <tag/Function/Call the driver specific ioctl function. <tag/Header/<tt/<ref id="mouse.h" name="mouse.h">/ <tag/Declaration/<tt/unsigned char __fastcall__ mouse_ioctl (unsigned char code, void* data);/ <tag/Description/The function calls the IOCTL entry in the mouse driver, which is driver specific. The <tt/code/ parameter will choose between 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/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 used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/Example/None. </descrip> </quote> <sect1>mouse_load_driver<label id="mouse_load_driver"><p> <quote> <descrip> <tag/Function/Load and initialize a mouse driver. <tag/Header/<tt/<ref id="mouse.h" name="mouse.h">/ <tag/Declaration/<tt/unsigned char __fastcall__ mouse_load_driver (const struct mouse_callbacks* c, const char* driver);/ <tag/Description/Load a mouse driver into memory and initialize it. The function returns an error code that tells if the call has been successful. The <tt/mouse_callbacks/ structure passed as first parameter contains pointers to 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/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 present. <item>After installing a driver, the mouse cursor is hidden. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="mouse_install" name="mouse_install">, <ref id="mouse_uninstall" name="mouse_uninstall">, <ref id="mouse_unload" name="mouse_unload"> <tag/Example/None. </descrip> </quote> <sect1>mouse_move<label id="mouse_move"><p> <quote> <descrip> <tag/Function/Move the mouse cursor to a specific position. <tag/Header/<tt/<ref id="mouse.h" name="mouse.h">/ <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/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 used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="mouse_getbox" name="mouse_getbox">, <ref id="mouse_setbox" name="mouse_setbox"> <tag/Example/None. </descrip> </quote> <sect1>mouse_pos<label id="mouse_pos"><p> <quote> <descrip> <tag/Function/Return the position of the mouse. <tag/Header/<tt/<ref id="mouse.h" name="mouse.h">/ <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/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. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="mouse_buttons" name="mouse_buttons">, <ref id="mouse_info" name="mouse_info"> <tag/Example/None. </descrip> </quote> <sect1>mouse_show<label id="mouse_show"><p> <quote> <descrip> <tag/Function/Show the mouse pointer. <tag/Header/<tt/<ref id="mouse.h" name="mouse.h">/ <tag/Declaration/<tt/void mouse_show (void);/ <tag/Description/The function shows the mouse pointer. It manages a counter that is shared between <tt/<ref id="mouse_hide" name="mouse_hide">/ and <tt/mouse_show/. The mouse cursor is visible if there was one more call to <tt/mouse_show/ than to <tt/<ref id="mouse_hide" name="mouse_hide">/. <tag/Availability/cc65 <tag/See also/ <ref id="mouse_hide" name="mouse_hide"> <tag/Example/None. </descrip> </quote> <sect1>mouse_uninstall<label id="mouse_uninstall"><p> <quote> <descrip> <tag/Function/Uninstall an already loaded mouse driver. <tag/Header/<tt/<ref id="mouse.h" name="mouse.h">/ <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/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 from memory. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="mouse_install" name="mouse_install">, <ref id="mouse_load_driver" name="mouse_load_driver">, <ref id="mouse_unload" name="mouse_unload"> <tag/Example/None. </descrip> </quote> <sect1>mouse_unload<label id="mouse_unload"><p> <quote> <descrip> <tag/Function/Unload a mouse driver. <tag/Header/<tt/<ref id="mouse.h" name="mouse.h">/ <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/Notes/<itemize> <item>The function does nothing if no driver is loaded. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="mouse_install" name="mouse_install">, <ref id="mouse_load_driver" name="mouse_load_driver">, <ref id="mouse_uninstall" name="mouse_uninstall"> <tag/Example/None. </descrip> </quote> <sect1>mul20<label id="mul20"><p> <quote> <descrip> <tag/Function/Multiplies argument by 20. <tag/Header/<tt/<ref id="cc65.h" name="cc65.h">/ <tag/Declaration/<tt/unsigned int __fastcall__ mul20 (unsigned char value);/ <tag/Description/Speed optimized function to multiply an 8 bit unsigned value by 20 to get a 16 bit result. <tag/Availability/cc65 </descrip> </quote> <sect1>mul40<label id="mul40"><p> <quote> <descrip> <tag/Function/Multiplies argument by 40. <tag/Header/<tt/<ref id="cc65.h" name="cc65.h">/ <tag/Declaration/<tt/unsigned int __fastcall__ mul40 (unsigned char value);/ <tag/Description/Speed optimized function to multiply an 8 bit unsigned value by 40 to get a 16 bit result. <tag/Availability/cc65 </descrip> </quote> <sect1>offsetof<label id="offsetof"><p> <quote> <descrip> <tag/Function/Calculate the offset of a struct or union member. <tag/Header/<tt/<ref id="stddef.h" name="stddef.h">/ <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/Notes/<itemize> <item>The function is actually a macro. </itemize> <tag/Availability/ISO 9899 <tag/Example/None. </descrip> </quote> <sect1>open<label id="open"><p> <quote> <descrip> <tag/Function/Open and possibly create a file. <tag/Header/<tt/<ref id="fcntl.h" name="fcntl.h">/ <tag/Declaration/<tt/int open (const char* name, int flags, ...);/ <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/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. </itemize> <tag/Availability/POSIX 1003.1 <tag/See also/ <ref id="close" name="close">, <ref id="creat" name="creat"> <tag/Example/None. </descrip> </quote> <sect1>opendir<label id="opendir"><p> <quote> <descrip> <tag/Function/Open a directory. <tag/Header/<tt/<ref id="dirent.h" name="dirent.h">/ <tag/Declaration/<tt/DIR* __fastcall__ opendir (const char* name);/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/POSIX 1003.1 <tag/See also/ <ref id="closedir" name="closedir">, <ref id="readdir" name="readdir"> <tag/Example/None. </descrip> </quote> <sect1>peekbsys<label id="peekbsys"><p> <quote> <descrip> <tag/Function/Read one byte from a location in the system bank. <tag/Header/<tt/<ref id="cbm610.h" name="cbm610.h">/, <tt/<ref id="cbm510.h" name="cbm510.h">/ <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/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 actual function is accessible by #undef'ing the macro. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="PEEK" name="PEEK">, <ref id="PEEKW" name="PEEKW">, <ref id="peekwsys" name="peekwsys">, <ref id="pokebsys" name="pokebsys">, <ref id="pokewsys" name="pokewsys"> <tag/Example/None. </descrip> </quote> <sect1>peekwsys<label id="peekwsys"><p> <quote> <descrip> <tag/Function/Read one word from a location in the system bank. <tag/Header/<tt/<ref id="cbm610.h" name="cbm610.h">/, <tt/<ref id="cbm510.h" name="cbm510.h">/ <tag/Declaration/<tt/unsigned __fastcall__ peekwsys (unsigned addr);/ <tag/Description/<tt/peekwsys/ reads one word from the given address in the 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/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. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="PEEK" name="PEEK">, <ref id="PEEKW" name="PEEKW">, <ref id="peekbsys" name="peekbsys">, <ref id="pokebsys" name="pokebsys">, <ref id="pokewsys" name="pokewsys"> <tag/Example/None. </descrip> </quote> <sect1>perror<label id="perror"><p> <quote> <descrip> <tag/Function/Print an error message for the error in <tt/errno/. <tag/Header/<tt/<ref id="stdio.h" name="stdio.h">/ <tag/Declaration/<tt/void __fastcall__ perror (const char* s);/ <tag/Description/<tt/perror/ prints an error message to <tt/stderr/. If <tt/s/ 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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="_poserror" name="_poserror">, <ref id="strerror" name="strerror"> <tag/Example/None. </descrip> </quote> <sect1>pokebsys<label id="pokebsys"><p> <quote> <descrip> <tag/Function/Write one byte to a location in the system bank. <tag/Header/<tt/<ref id="cbm610.h" name="cbm610.h">/, <tt/<ref id="cbm510.h" name="cbm510.h">/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="POKE" name="POKE">, <ref id="POKEW" name="POKEW">, <ref id="peekbsys" name="peekbsys">, <ref id="peekwsys" name="peekwsys">, <ref id="pokewsys" name="pokewsys"> <tag/Example/None. </descrip> </quote> <sect1>pokewsys<label id="pokewsys"><p> <quote> <descrip> <tag/Function/Write one word to a location in the system bank. <tag/Header/<tt/<ref id="cbm610.h" name="cbm610.h">/, <tt/<ref id="cbm510.h" name="cbm510.h">/ <tag/Declaration/<tt/void __fastcall__ pokewsys (unsigned addr, unsigned val);/ <tag/Description/<tt/pokewsys/ writes one word to the given address in the 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/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. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="POKE" name="POKE">, <ref id="POKEW" name="POKEW">, <ref id="peekbsys" name="peekbsys">, <ref id="peekwsys" name="peekwsys">, <ref id="pokebsys" name="pokebsys"> <tag/Example/None. </descrip> </quote> <sect1>qsort<label id="qsort"><p> <quote> <descrip> <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 __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/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/ <ref id="bsearch" name="bsearch"> <tag/Example/None. </descrip> </quote> <sect1>raise<label id="raise"><p> <quote> <descrip> <tag/Function/Send a signal to the executing program. <tag/Header/<tt/<ref id="signal.h" name="signal.h">/ <tag/Declaration/<tt/int __fastcall__ raise (int sig);/ <tag/Description/<tt/raise/ sends the given signal to the program. If the 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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="abort" name="abort">, <ref id="signal" name="signal"> <tag/Example/None. </descrip> </quote> <sect1>rand<label id="rand"><p> <quote> <descrip> <tag/Function/Return a pseudo random number. <tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ <tag/Declaration/<tt/int rand (void);/ <tag/Description/The function returns a pseudo random number between 0 and <tt/RAND_MAX/ (exclusive). <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"> had been used with an argument of 1. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="_randomize" name="_randomize">, <ref id="srand" name="srand"> <tag/Example/None. </descrip> </quote> <sect1>readdir<label id="readdir"><p> <quote> <descrip> <tag/Function/Read a directory. <tag/Header/<tt/<ref id="dirent.h" name="dirent.h">/ <tag/Declaration/<tt/struct dirent* __fastcall__ readdir (DIR* dir);/ <tag/Description/<tt/readdir/ reads the next directory entry from the directory 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/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 <tt/struct dirent/, so it may get overwritten by subsequent calls to <tt/readdir/. <item>On several platforms, namely the CBMs and the Atari, the disk drives get confused when opening/closing files between directory reads. So for example a program that reads the list of files on a disk, and after each call to <tt/readdir/, opens the file to process it, will fail.<newline> Possible solutions are reading the directory into memory before processing the file list, or to reset the directory by seeking to the correct position after opening/closing a file: <verb> seekdir (DIR, telldir (DIR)); </verb> Platforms known to work without problems are: Apple. </itemize> <tag/Availability/POSIX 1003.1 <tag/See also/ <ref id="closedir" name="closedir">, <ref id="opendir" name="opendir"> <tag/Example/None. </descrip> </quote> <sect1>realloc<label id="realloc"><p> <quote> <descrip> <tag/Function/Change the size of an allocated memory block. <tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ <tag/Declaration/<tt/void* __fastcall__ realloc (void* block, size_t size);/ <tag/Description/<tt/realloc/ changes the size of the memory block pointed to 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/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 pointer you're passing somewhere else, otherwise <tscreen><verb> ptr = realloc (ptr, size); </verb></tscreen> will loose your only copy of <tt/ptr/ if <tt/realloc/ returns <tt/NULL/. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="_heapadd" name="_heapadd">, <ref id="_heapblocksize" name="_heapblocksize">, <ref id="_heapmaxavail" name="_heapmaxavail">, <ref id="_heapmemavail" name="_heapmemavail">, <ref id="calloc" name="calloc">, <ref id="free" name="free">, <ref id="realloc" name="realloc"> <tag/Example/None. </descrip> </quote> <sect1>remove<label id="remove"><p> <quote> <descrip> <tag/Function/Delete a file. <tag/Header/<tt/<ref id="stdio.h" name="stdio.h">/ <tag/Declaration/<tt/int __fastcall__ remove (const char* name);/ <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/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 be used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="rename" name="rename">, <ref id="unlink" name="unlink"> <tag/Example/ <verb> #include <stdio.h> #define FILENAME "helloworld" if (remove (FILENAME) == 0) { printf ("We deleted %s successfully\n", FILENAME); } else { printf ("There was a problem deleting %s\n", FILENAME); } </verb> </descrip> </quote> <sect1>rename<label id="rename"><p> <quote> <descrip> <tag/Function/Rename a file. <tag/Header/<tt/<ref id="stdio.h" name="stdio.h">/ <tag/Declaration/<tt/int __fastcall__ rename (const char* oldname, const char* newname);/ <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/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 be used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="remove" name="remove"> <tag/Example/ <verb> #include <stdio.h> #define OLDNAME "textfile.txt" #define NEWNAME "textfile.bak" if (rename (OLDNAME, NEWNAME) == 0) { printf ("Renamed %s to %s\n", OLDNAME, NEWNAME); } else { printf ("Error renaming %s to %s\n", OLDNAME, NEWNAME); } </verb> </descrip> </quote> <sect1>reset_brk<label id="reset_brk"><p> <quote> <descrip> <tag/Function/Resets the break vector to its original value. <tag/Header/<tt/<ref id="6502.h" name="6502.h">/ <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/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 exiting the program. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="reset_irq" name="reset_irq">, <ref id="set_brk" name="set_brk">, <ref id="set_irq" name="set_irq"> <tag/Example/None. </descrip> </quote> <sect1>reset_irq<label id="reset_irq"><p> <quote> <descrip> <tag/Function/Resets the C level interrupt request vector. <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/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 exiting the program. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="reset_brk" name="reset_brk">, <ref id="set_brk" name="set_brk">, <ref id="set_irq" name="set_irq"> <tag/Example/None. </descrip> </quote> <sect1>revers<label id="revers"><p> <quote> <descrip> <tag/Function/Control revers character display. <tag/Header/<tt/<ref id="conio.h" name="conio.h">/ <tag/Declaration/<tt/unsigned char __fastcall__ revers (unsigned char onoff);/ <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/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 be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="textcolor" name="textcolor"> <tag/Example/None. </descrip> </quote> <sect1>rewinddir<label id="rewinddir"><p> <quote> <descrip> <tag/Function/Reset a directory stream. <tag/Header/<tt/<ref id="dirent.h" name="dirent.h">/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/POSIX 1003.1 <tag/See also/ <ref id="seekdir" name="seekdir">, <ref id="telldir" name="telldir"> <tag/Example/None. </descrip> </quote> <sect1>screensize<label id="screensize"><p> <quote> <descrip> <tag/Function/Return the dimensions of the text mode screen. <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="gotox" name="gotox">, <ref id="gotoxy" name="gotoxy">, <ref id="gotoy" name="gotoy">, <ref id="wherex" name="wherex">, <ref id="wherey" name="wherey"> <tag/Example/None. </descrip> </quote> <sect1>seekdir<label id="seekdir"><p> <quote> <descrip> <tag/Function/Set the position of a directory stream. <tag/Header/<tt/<ref id="dirent.h" name="dirent.h">/ <tag/Declaration/<tt/void __fastcall__ seekdir (DIR* dir, long offset);/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/POSIX 1003.1 <tag/See also/ <ref id="rewinddir" name="rewinddir">, <ref id="telldir" name="telldir"> <tag/Example/None. </descrip> </quote> <sect1>ser_close<label id="ser_close"><p> <quote> <descrip> <tag/Function/Close the port and disable interrupts <tag/Header/<tt/<ref id="serial.h" name="serial.h">/ <tag/Declaration/<tt/unsigned char ser_close (void);/ <tag/Description/Close the port by clearing buffers and disable interrupts. <tag/Availability/cc65 <tag/See also/Other serial functions. <tag/Example/ <verb> #include <serial.h> static void initialize(){ struct ser_params params = { SER_BAUD_9600, SER_BITS_8, SER_STOP_1, SER_PAR_MARK, SER_HS_NONE }; ser_install(lynx_comlynx); // This will activate the ComLynx CLI(); ser_open(&params); } </verb> </descrip> </quote> <sect1>ser_get<label id="ser_get"><p> <quote> <descrip> <tag/Function/Read a character from serial port. <tag/Header/<tt/<ref id="serial.h" name="serial.h">/ <tag/Declaration/<tt/unsigned char __fastcall__ ser_get (char* b);/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/Other serial functions. <tag/Example/ Wait for a character to be available from a serial port. <verb> char ch; while (ser_get(&ch) == SER_ERR_NO_DATA) ; </verb> </descrip> </quote> <sect1>ser_install<label id="ser_install"><p> <quote> <descrip> <tag/Function/Install an already loaded driver and return an error code. <tag/Header/<tt/<ref id="serial.h" name="serial.h">/ <tag/Declaration/<tt/unsigned char __fastcall__ ser_install (void* driver);/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="ser_load_driver" name="ser_load_driver">, <ref id="ser_uninstall" name="ser_uninstall">, <ref id="ser_unload" name="ser_unload"> <tag/Example/<verb> ser_install(lynx_comlynx); //Include the driver statically instead of loading it. </verb> </descrip> </quote> <sect1>ser_ioctl<label id="ser_ioctl"><p> <quote> <descrip> <tag/Function/Platform dependent code extensions. <tag/Header/<tt/<ref id="serial.h" name="serial.h">/ <tag/Declaration/<tt/unsigned __fastcall__ ser_ioctl (unsigned char code, void* data);/ <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/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. </itemize> <tag/Availability/cc65 <tag/See also/Other serial functions. <tag/Example/None </descrip> </quote> <sect1>ser_load_driver<label id="ser_load_driver"><p> <quote> <descrip> <tag/Function/Load and install a serial driver. <tag/Header/<tt/<ref id="serial.h" name="serial.h">/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/Other serial functions. <tag/Example/None. </descrip> </quote> <sect1>ser_open<label id="ser_open"><p> <quote> <descrip> <tag/Function/Open the port by setting the port parameters and enable interrupts <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/Other serial functions. <tag/Example/ <verb> #include <serial.h> static void initialize(){ struct ser_params params = { SER_BAUD_9600, SER_BITS_8, SER_STOP_1, SER_PAR_MARK, SER_HS_NONE }; ser_install(lynx_comlynx); // This will activate the ComLynx CLI(); ser_open(&params); } </verb> </descrip> </quote> <sect1>ser_put<label id="ser_put"><p> <quote> <descrip> <tag/Function/Write a character to a serial port. <tag/Header/<tt/<ref id="serial.h" name="serial.h">/ <tag/Declaration/<tt/unsigned char __fastcall__ ser_put (char b);/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/Other serial functions. <tag/Example/ <verb> ser_put('A'); </verb> </descrip> </quote> <sect1>ser_status<label id="ser_status"><p> <quote> <descrip> <tag/Function/Return the serial port status. <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/Other serial functions. <tag/Example/None </descrip> </quote> <sect1>ser_uninstall<label id="ser_uninstall"><p> <quote> <descrip> <tag/Function/Uninstall the currently loaded driver but do not unload it. <tag/Header/<tt/<ref id="serial.h" name="serial.h">/ <tag/Declaration/<tt/unsigned char ser_uninstall (void);/ <tag/Description/Uninstall the currently loaded driver but do not unload it. <tag/Availability/cc65 <tag/See also/Other serial functions. <tag/Example/None. </descrip> </quote> <sect1>ser_unload<label id="ser_unload"><p> <quote> <descrip> <tag/Function/Uninstall, then unload the currently loaded driver. <tag/Header/<tt/<ref id="serial.h" name="serial.h">/ <tag/Declaration/<tt/unsigned char ser_unload (void);/ <tag/Description/Uninstall, then unload the currently loaded driver. <tag/Availability/cc65 <tag/See also/Other serial functions. <tag/Example/None. </descrip> </quote> <sect1>set_brk<label id="set_brk"><p> <quote> <descrip> <tag/Function/Set the break vector to a user function. <tag/Header/<tt/<ref id="6502.h" name="6502.h">/ <tag/Declaration/<tt/void __fastcall__ set_brk (brk_handler func);/ <tag/Description/<tt/set_brk/ allows a user program to handle breaks within the 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/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 to a small break handler stack. This means that it is safe to execute C code, even if C code was interrupted. Be careful however not to use too many local variables, and do not enable stack checks for the handler function or any other 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>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 exiting the program. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="reset_brk" name="reset_brk"> <tag/Example/None. </descrip> </quote> <sect1>set_irq<label id="set_irq"><p> <quote> <descrip> <tag/Function/Set the C level interrupt request vector to the given address. <tag/Header/<tt/<ref id="6502.h" name="6502.h">/ <tag/Declaration/<tt/void __fastcall__ set_irq (irq_handler f, void *stack_addr, size_t stack_size);/ <tag/Description/<tt/set_irq/ allows a user program to handle interrupt requests (IRQs) within the program code by letting the vector point to a user written C function. The runtime library installs a small stub that saves the zero page registers used by the C runtime before calling the handler function and restores them after the handler function returns. Additionally the stub temporarily switches the C runtime stack to the stack area provided as parameter. If the handler function 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/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 and switches to the provided stack area. As a consequence, there is some 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 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 exiting the program. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="reset_brk" name="reset_brk">, <ref id="reset_irq" name="reset_irq">, <ref id="set_brk" name="set_brk"> <tag/Example/None. </descrip> </quote> <sect1>set_c128_speed<label id="set_c128_speed"><p> <quote> <descrip> <tag/Function/Set the current speed of a C128 CPU. <tag/Header/<tt/<ref id="accelerator.h" name="accelerator.h">/ <tag/Declaration/<tt/unsigned char __fastcall__ set_c128_speed (unsigned char speed);/ <tag/Description/The function returns the speed after trying to set the speed of the C128 CPU. <tag/Notes/<itemize> <item>The function is specific to the C64 and C128. <item>The function does not check if the C128 CPU is the current CPU. <item>See the accelerator.h header for the speed definitions. </itemize> <tag/Availability/cc65 (not all platforms) <tag/See also/ <ref id="detect_c128" name="detect_c128">, <ref id="get_c128_speed" name="get_c128_speed">, <tag/Example/None. </descrip> </quote> <sect1>set_c64dtv_speed<label id="set_c64dtv_speed"><p> <quote> <descrip> <tag/Function/Set the current speed of the C64DTV. <tag/Header/<tt/<ref id="accelerator.h" name="accelerator.h">/ <tag/Declaration/<tt/unsigned char __fastcall__ set_c64dtv_speed (unsigned char speed);/ <tag/Description/The function returns the speed after trying to set the speed of the C64DTV. <tag/Notes/<itemize> <item>The function is specific to the C64. <item>The function does not check for the presence of the C64DTV. <item>See the accelerator.h header for the speed definitions. </itemize> <tag/Availability/cc65 (not all platforms) <tag/See also/ <ref id="detect_c64dtv" name="detect_c64dtv">, <ref id="get_c64dtv_speed" name="get_c64dtv_speed">, <tag/Example/None. </descrip> </quote> <sect1>set_c65_speed<label id="set_c65_speed"><p> <quote> <descrip> <tag/Function/Set the current speed of the C65/C64DX in C64 mode. <tag/Header/<tt/<ref id="accelerator.h" name="accelerator.h">/ <tag/Declaration/<tt/unsigned char __fastcall__ set_c65_speed (unsigned char speed);/ <tag/Description/The function returns the speed after trying to set the speed of the C65/C64DX in C64 mode. <tag/Notes/<itemize> <item>The function is specific to the C64. <item>The function does not check for the presence of a C65/C64DX in C64 mode. <item>See the accelerator.h header for the speed definitions. </itemize> <tag/Availability/cc65 (not all platforms) <tag/See also/ <ref id="detect_c65" name="detect_c65">, <ref id="get_c65_speed" name="get_c65_speed">, <tag/Example/None. </descrip> </quote> <sect1>set_chameleon_speed<label id="set_chameleon_speed"><p> <quote> <descrip> <tag/Function/Set the current speed of the C64 Chameleon cartridge. <tag/Header/<tt/<ref id="accelerator.h" name="accelerator.h">/ <tag/Declaration/<tt/unsigned char __fastcall__ set_chameleon_speed (unsigned char speed);/ <tag/Description/The function returns the speed after trying to set the speed of the C64 Chameleon cartridge. <tag/Notes/<itemize> <item>The function is specific to the C64. <item>The function does not check for the presence of the C64 Chameleon cartridge. <item>See the accelerator.h header for the speed definitions. </itemize> <tag/Availability/cc65 (not all platforms) <tag/See also/ <ref id="detect_chameleon" name="detect_chameleon">, <ref id="get_chameleon_speed" name="get_chameleon_speed">, <tag/Example/None. </descrip> </quote> <sect1>set_scpu_speed<label id="set_scpu_speed"><p> <quote> <descrip> <tag/Function/Set the current speed of the C64/C128 SuperCPU cartridge. <tag/Header/<tt/<ref id="accelerator.h" name="accelerator.h">/ <tag/Declaration/<tt/unsigned char __fastcall__ set_scpu_speed (unsigned char speed);/ <tag/Description/The function returns the speed after trying to set the speed of the SuperCPU cartridge. <tag/Notes/<itemize> <item>The function is specific to the C128 and C64. <item>The function does not check for the presence of the cartridge. <item>See the accelerator.h header for the speed definitions. </itemize> <tag/Availability/cc65 (not all platforms) <tag/See also/ <ref id="detect_scpu" name="detect_scpu">, <ref id="get_scpu_speed" name="get_scpu_speed">, <tag/Example/None. </descrip> </quote> <sect1>set_turbomaster_speed<label id="set_turbomaster_speed"><p> <quote> <descrip> <tag/Function/Set the current speed of the C64 Turbo Master cartridge. <tag/Header/<tt/<ref id="accelerator.h" name="accelerator.h">/ <tag/Declaration/<tt/unsigned char __fastcall__ set_turbomaster_speed (unsigned char speed);/ <tag/Description/The function returns the speed after trying to set the speed of the C64 Turbo Master cartridge. <tag/Notes/<itemize> <item>The function is specific to the C64. <item>The function does not check for the presence of the C64 Turbo Master cartridge. <item>See the accelerator.h header for the speed definitions. </itemize> <tag/Availability/cc65 (not all platforms) <tag/See also/ <ref id="detect_turbomaster" name="detect_turbomaster">, <ref id="get_turbomaster_speed" name="get_turbomaster_speed">, <tag/Example/None. </descrip> </quote> <sect1>setjmp<label id="setjmp"><p> <quote> <descrip> <tag/Function/Save the context for use with <tt/longjmp/. <tag/Header/<tt/<ref id="setjmp.h" name="setjmp.h">/ <tag/Declaration/<tt/int __fastcall__ setjmp (jmp_buf buf);/ <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/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. <item><tt/setjmp/ will not save the signal context. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="longjmp" name="longjmp"> <tag/Example/None. </descrip> </quote> <sect1>setlocale<label id="setlocale"><p> <quote> <descrip> <tag/Function/Selects a locale. <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/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 different locale has no effect. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="localeconv" name="localeconv">, <ref id="strcoll" name="strcoll"> <ref id="strxfrm" name="strxfrm"> <tag/Example/None. </descrip> </quote> <sect1>signal<label id="signal"><p> <quote> <descrip> <tag/Function/Install a signal handler. <tag/Header/<tt/<ref id="signal.h" name="signal.h">/ <tag/Declaration/<tt/__sigfunc __fastcall__ signal (int sig, __sigfunc func);/ <tag/Description/<tt/signal/ installs a handler for the given signal. The 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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="abort" name="abort">, <ref id="raise" name="raise"> <tag/Example/None. </descrip> </quote> <sect1>sleep<label id="sleep"><p> <quote> <descrip> <tag/Function/Sleep for a specified amount of time. <tag/Header/<tt/<ref id="unistd.h" name="unistd.h">/ <tag/Declaration/<tt/void __fastcall__ sleep (unsigned seconds);/ <tag/Description/The function will return after the specified number of seconds have elapsed. <tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/POSIX 1003.1 <tag/Example/None. </descrip> </quote> <sect1>slow<label id="slow"><p> <quote> <descrip> <tag/Function/Switch the CPU into slow mode (C128: 1MHz mode, C16/Plus4: single clock mode). <tag/Header/<tt/<ref id="c128.h" name="c128.h">, <ref id="c16.h" name="c16.h">, <ref id="plus4.h" name="plus4.h">/ <tag/Declaration/<tt/void slow (void);/ <tag/Description/The function will switch the clock of the CPU to slow mode. for the C128 target it means switching the CPU into 1MHz mode. for the C16/Plus4 target it means switching the CPU into single clock mode. <tag/Notes/<itemize> <item>The function is specific to the C128, C16 and Plus4. </itemize> <tag/Availability/cc65 (not all platforms) <tag/See also/ <ref id="fast" name="fast">, <ref id="isfast" name="isfast">, <tag/Example/None. </descrip> </quote> <sect1>srand<label id="srand"><p> <quote> <descrip> <tag/Function/Initialize the pseudo random number generator. <tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ <tag/Declaration/<tt/void __fastcall__ srand (unsigned seed);/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="_randomize" name="_randomize">, <ref id="rand" name="rand"> <tag/Example/None. </descrip> </quote> <sect1>strcasecmp<label id="strcasecmp"><p> <quote> <descrip> <tag/Function/Compare two strings case insensitive. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <tag/Declaration/<tt/int __fastcall__ strcasecmp (const char* s1, const char* s2);/ <tag/Description/The <tt/strcasecmp/ function compares the two strings passed 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/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. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="strcmp" name="strcmp">, <ref id="strcoll" name="strcoll">, <ref id="stricmp" name="stricmp">, <ref id="strncmp" name="strncmp">, <ref id="strxfrm" name="strxfrm"> <tag/Example/None. </descrip> </quote> <sect1>strcat<label id="strcat"><p> <quote> <descrip> <tag/Function/Concatentate two strings. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <tag/Declaration/<tt/char* __fastcall__ strcat (char* s1, const char* s2);/ <tag/Description/The <tt/strcat/ function appends a copy of the string 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/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 is undefined. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="strcpy" name="strcpy">, <ref id="strncat" name="strncat">, <ref id="strncpy" name="strncpy"> <tag/Example/None. </descrip> </quote> <sect1>strchr<label id="strchr"><p> <quote> <descrip> <tag/Function/Search for a character in a string. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <tag/Declaration/<tt/char* __fastcall__ strchr (const char* s, int c);/ <tag/Description/The <tt/strchr/ function locates the first occurrence of <tt/c/ (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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="memchr" name="memchr">, <ref id="strrchr" name="strrchr"> <tag/Example/None. </descrip> </quote> <sect1>strcmp<label id="strcmp"><p> <quote> <descrip> <tag/Function/Compare two strings. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <tag/Declaration/<tt/int __fastcall__ strcmp (const char* s1, const char* s2);/ <tag/Description/The <tt/strcmp/ function compares the two strings passed as 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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="strcasecmp" name="strcasecmp">, <ref id="strcoll" name="strcoll">, <ref id="stricmp" name="stricmp">, <ref id="strncmp" name="strncmp"> <ref id="strxfrm" name="strxfrm"> <tag/Example/None. </descrip> </quote> <sect1>strcoll<label id="strcoll"><p> <quote> <descrip> <tag/Function/Compare two strings. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <tag/Declaration/<tt/int __fastcall__ strcoll (const char* s1, const char* s2);/ <tag/Description/The <tt/strcoll/ function compares the two strings passed as 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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="setlocale" name="setlocale">, <ref id="strcasecmp" name="strcasecmp">, <ref id="strcmp" name="strcmp">, <ref id="stricmp" name="stricmp">, <ref id="strncmp" name="strncmp">, <ref id="strxfrm" name="strxfrm"> <tag/Example/None. </descrip> </quote> <sect1>strcpy<label id="strcpy"><p> <quote> <descrip> <tag/Function/Copy a string. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <tag/Declaration/<tt/char* __fastcall__ strcpy (char* s1, const char* s2);/ <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/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 is undefined. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="strcat" name="strcat">, <ref id="strncat" name="strncat">, <ref id="strncpy" name="strncpy"> <tag/Example/ <verb> #include <string.h> static char hello[14]; strcpy (hello, "Hello world!\n"); </verb> </descrip> </quote> <sect1>strcspn<label id="strcspn"><p> <quote> <descrip> <tag/Function/Compute the length of a substring. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <tag/Declaration/<tt/size_t __fastcall__ strcspn (const char* s, const char* set);/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="strpbrk" name="strpbrk">, <ref id="strqtok" name="strqtok">, <ref id="strspn" name="strspn">, <ref id="strstr" name="strstr">, <ref id="strtok" name="strtok"> <tag/Example/None. </descrip> </quote> <sect1>strdup<label id="strdup"><p> <quote> <descrip> <tag/Function/Allocate a copy of a string on the heap. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <tag/Declaration/<tt/char* __fastcall__ strdup (const char* s);/ <tag/Description/<tt/strdup/ allocates a memory block on the heap, big enough 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/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. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="free" name="free">, <ref id="malloc" name="malloc"> <tag/Example/None. </descrip> </quote> <sect1>strerror<label id="strerror"><p> <quote> <descrip> <tag/Function/Return a string describing an error code. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <tag/Declaration/<tt/char* __fastcall__ strerror (int errcode);/ <tag/Description/The <tt/strerror/ function returns a string describing the 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/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 string must not be modified by the caller! </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="_stroserror" name="_stroserror"> <tag/Example/None. </descrip> </quote> <sect1>stricmp<label id="stricmp"><p> <quote> <descrip> <tag/Function/Compare two strings case insensitive. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <tag/Declaration/<tt/int __fastcall__ stricmp (const char* s1, const char* s2);/ <tag/Description/The <tt/stricmp/ function compares the two strings passed 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/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. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="strcasecmp" name="strcasecmp">, <ref id="strcmp" name="strcmp">, <ref id="strcoll" name="strcoll">, <ref id="strncmp" name="strncmp">, <ref id="strxfrm" name="strxfrm"> <tag/Example/None. </descrip> </quote> <sect1>strlen<label id="strlen"><p> <quote> <descrip> <tag/Function/Return the length of a string. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <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/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 function does not work correctly for strings with more than 255 characters. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="strcpy" name="strcpy"> <tag/Example/None. </descrip> </quote> <sect1>strlower<label id="strlower"><p> <quote> <descrip> <tag/Function/Make a string lower case. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <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/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. <item>An alias name for this function is <tt/strlwr/. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="strupper" name="strupper">, <ref id="tolower" name="tolower"> <tag/Example/None. </descrip> </quote> <sect1>strlwr<label id="strlwr"><p> <quote> See <tt/strlower/. </quote> <sect1>strncasecmp<label id="strncasecmp"><p> <quote> <descrip> <tag/Function/Compare two strings case insensitive. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <tag/Declaration/<tt/int __fastcall__ strncasecmp (const char* s1, const char* s2, size_t count);/ <tag/Description/The <tt/strncasecmp/ function compares the two strings passed 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/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. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="strcmp" name="strcmp">, <ref id="strcoll" name="strcoll">, <ref id="stricmp" name="stricmp">, <ref id="strncmp" name="strncmp">, <ref id="strxfrm" name="strxfrm"> <tag/Example/None. </descrip> </quote> <sect1>strncat<label id="strncat"><p> <quote> <descrip> <tag/Function/Concatentate two strings. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <tag/Declaration/<tt/char* __fastcall__ strncat (char* s1, const char* s2, size_t n);/ <tag/Description/The <tt/strncat/ function appends not more than n characters 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/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 is undefined. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="strcpy" name="strcpy">, <ref id="strncat" name="strncat">, <ref id="strncpy" name="strncpy"> <tag/Example/None. </descrip> </quote> <sect1>strncmp<label id="strncmp"><p> <quote> <descrip> <tag/Function/Compare two strings. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <tag/Declaration/<tt/int __fastcall__ strncmp (const char* s1, const char* s2, size_t count);/ <tag/Description/The <tt/strncmp/ function compares not more than <tt/count/ 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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="strcasecmp" name="strcasecmp">, <ref id="strcmp" name="strcmp">, <ref id="strcoll" name="strcoll">, <ref id="stricmp" name="stricmp">, <ref id="strxfrm" name="strxfrm"> <tag/Example/None. </descrip> </quote> <sect1>strncpy<label id="strncpy"><p> <quote> <descrip> <tag/Function/Copy part of a string. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <tag/Declaration/<tt/char* __fastcall__ strncpy (char* s1, const char* s2, size_t n);/ <tag/Description/The <tt/strncpy/ function copies not more than <tt/n/ bytes from 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/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 to by <tt/s2/, the result is <em/not/ null-terminated! <item>If copying takes place between objects that overlap, the behaviour is undefined. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="memcpy" name="memcpy">, <ref id="strcat" name="strcat">, <ref id="strcpy" name="strcpy">, <ref id="strncat" name="strncat"> <tag/Example/ <verb> #include <string.h> static char hello[6]; strncpy (hello, "Hello world!\n", sizeof hello - 1)[5] = '\0'; </verb> </descrip> </quote> <sect1>strnicmp<label id="strnicmp"><p> <quote> <descrip> <tag/Function/Compare two strings case insensitive. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <tag/Declaration/<tt/int __fastcall__ strnicmp (const char* s1, const char* s2, size_t count);/ <tag/Description/The <tt/strnicmp/ function compares the two strings passed 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/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. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="strcasecmp" name="strcasecmp">, <ref id="strcmp" name="strcmp">, <ref id="strcoll" name="strcoll">, <ref id="strncmp" name="strncmp">, <ref id="strxfrm" name="strxfrm"> <tag/Example/None. </descrip> </quote> <sect1>strpbrk<label id="strpbrk"><p> <quote> <descrip> <tag/Function/Find a character in a string, from a set of characters. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <tag/Declaration/<tt/char* __fastcall__ strpbrk (const char* str, const char* set);/ <tag/Description/<tt/strpbrk()/ searches within <tt/str/ for the first occurance of any character from <tt/set/. It returns a pointer to that character if found; otherwise, it returns <tt/NULL/. <tag/Notes/<itemize> <item>The function is available only as a fastcall function; so, it should be used only in the presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="strchr" name="strchr">, <ref id="strcspn" name="strcspn">, <ref id="strqtok" name="strqtok">, <ref id="strspn" name="strspn">, <ref id="strtok" name="strtok"> <tag/Example/None. </descrip> </quote> <sect1>strqtok<label id="strqtok"><p> <quote> <descrip> <tag/Function/Break a string into tokens. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <tag/Declaration/<tt/char* __fastcall__ strqtok (char* s1, const char* s2);/ <tag/Description/<tt/strqtok()/ will break the string <tt/s1/ into a sequence of tokens, which are delimited by either quotation marks or characters from the string <tt/s2/. Tokens inside quotation marks may contain characters from <tt/s2/ (they aren't delimiters there). The first call to <tt/strqtok()/ 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/strqtok()/. <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/. <item>The function will forget where it is in the <tt/s1/ string if it is given a second <tt/s1/ string before it finishes the first one. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="strcspn" name="strcspn">, <ref id="strpbrk" name="strpbrk">, <ref id="strspn" name="strspn">, <ref id="strtok" name="strtok"> <tag/Example/None. </descrip> </quote> <sect1>strrchr<label id="strrchr"><p> <quote> <descrip> <tag/Function/Search for a character in a string. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <tag/Declaration/<tt/char* __fastcall__ strrchr (const char* s, int c);/ <tag/Description/The <tt/strrchr/ function locates the last occurrence of <tt/c/ (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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="strchr" name="strchr"> <tag/Example/None. </descrip> </quote> <sect1>strspn<label id="strspn"><p> <quote> <descrip> <tag/Function/Compute the length of a substring. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <tag/Declaration/<tt/size_t __fastcall__ strspn (const char* s, const char* set);/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="strcspn" name="strcspn">, <ref id="strpbrk" name="strpbrk">, <ref id="strstr" name="strstr"> <tag/Example/None. </descrip> </quote> <sect1>strstr<label id="strstr"><p> <quote> <descrip> <tag/Function/Find a substring. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <tag/Declaration/<tt/char* __fastcall__ strstr (const char* str, const char* substr);/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="strcspn" name="strcspn">, <ref id="strspn" name="strspn"> <tag/Example/None. </descrip> </quote> <sect1>strtok<label id="strtok"><p> <quote> <descrip> <tag/Function/Break a string into tokens. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <tag/Declaration/<tt/char* __fastcall__ strtok (char* s1, const char* s2);/ <tag/Description/<tt/strtok()/ will break the string <tt/s1/ into a sequence of tokens, which are delimited by characters from the string <tt/s2/. The first call 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/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/. <item>The function will forget where it is in the <tt/s1/ string if it is given a second <tt/s1/ string before it finishes the first one. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="strcspn" name="strcspn">, <ref id="strpbrk" name="strpbrk">, <ref id="strqtok" name="strqtok">, <ref id="strspn" name="strspn"> <tag/Example/None. </descrip> </quote> <sect1>strxfrm<label id="strxfrm"><p> <quote> <descrip> <tag/Function/Transform a string. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <tag/Declaration/<tt/size_t __fastcall__ strxfrm (char* s1, const char* s2, size_t n);/ <tag/Description/The <tt/strxfrm/ function transforms the string pointed to by s2 and places the resulting string into the string pointed to by s1. The transformation is such that if the <tt/strcmp/ function is applied to two 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/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. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>Since cc65 doesn't support different charcter sets, <tt/strxfrm/ will just copy s2 to s1 using <tt><ref id="strncpy" name="strncpy"></tt>. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="strcmp" name="strcmp">, <ref id="strcoll" name="strcoll">, <ref id="strncpy" name="strncpy"> <tag/Example/None. </descrip> </quote> <sect1>strupper<label id="strupper"><p> <quote> <descrip> <tag/Function/Make a string upper case. <tag/Header/<tt/<ref id="string.h" name="string.h">/ <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/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. <item>An alias name for this function is <tt/strupr/. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="strlower" name="strlower"> <ref id="toupper" name="toupper"> <tag/Example/None. </descrip> </quote> <sect1>strupr<label id="strupr"><p> <quote> See <tt/strupper/. </quote> <sect1>telldir<label id="telldir"><p> <quote> <descrip> <tag/Function/Return the current position of a directory stream. <tag/Header/<tt/<ref id="dirent.h" name="dirent.h">/ <tag/Declaration/<tt/long __fastcall__ telldir (DIR* dir);/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/POSIX 1003.1 <tag/See also/ <ref id="seekdir" name="seekdir">, <ref id="telldir" name="telldir"> <tag/Example/None. </descrip> </quote> <sect1>textcolor<label id="textcolor"><p> <quote> <descrip> <tag/Function/Set the text color. <tag/Header/<tt/<ref id="conio.h" name="conio.h">/ <tag/Declaration/<tt/unsigned char __fastcall__ textcolor (unsigned char color);/ <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/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 be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="bgcolor" name="bgcolor">, <ref id="bordercolor" name="bordercolor"> <tag/Example/None. </descrip> </quote> <sect1>time<label id="time"><p> <quote> <descrip> <tag/Function/Get the time. <tag/Header/<tt/<ref id="time.h" name="time.h">/ <tag/Declaration/<tt/time_t __fastcall__ time (time_t* t);/ <tag/Description/The function returns the time since the 1970-01-01 00:00:00 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 an error code is stored in <tt/errno/. <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 returned value may not be valid. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="clock" name="clock">, <ref id="clock_gettime" name="clock_gettime"> <tag/Example/None. </descrip> </quote> <sect1>toggle_videomode<label id="toggle_videomode"><p> <quote> <descrip> <tag/Function/Toggle between 40 and 80 column mode. <tag/Header/<tt/<ref id="c128.h" name="c128.h">/ <tag/Declaration/<tt/void toggle_videomode (void);/ <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/Notes/<itemize> <item>The function is specific to the C128. <item>This function is deprecated. Please use <ref id="videomode" name="videomode"> instead! </itemize> <tag/Availability/C128 <tag/See also/ <ref id="fast" name="fast">, <ref id="isfast" name="isfast">, <ref id="slow" name="slow">, <ref id="videomode" name="videomode"> <tag/Example/None. </descrip> </quote> <sect1>tolower<label id="tolower"><p> <quote> <descrip> <tag/Function/Convert a character into its lower case representation. <tag/Header/<tt/<ref id="ctype.h" name="ctype.h">/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="islower" name="islower">, <ref id="isupper" name="isupper">, <ref id="toupper" name="toupper"> <tag/Example/None. </descrip> </quote> <sect1>toupper<label id="toupper"><p> <quote> <descrip> <tag/Function/Convert a character into its upper case representation. <tag/Header/<tt/<ref id="ctype.h" name="ctype.h">/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/ISO 9899 <tag/See also/ <ref id="islower" name="islower">, <ref id="isupper" name="isupper">, <ref id="tolower" name="tolower"> <tag/Example/None. </descrip> </quote> <sect1>ultoa<label id="ultoa"><p> <quote> <descrip> <tag/Function/Convert an unsigned long integer into a string. <tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ <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/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. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="atoi" name="atoi">, <ref id="atol" name="atol">, <ref id="itoa" name="itoa">, <ref id="ltoa" name="ltoa">, <ref id="utoa" name="utoa"> <tag/Example/None. </descrip> </quote> <sect1>unlink<label id="unlink"><p> <quote> <descrip> <tag/Function/Delete a file. <tag/Header/<tt/<ref id="unistd.h" name="unistd.h">/ <tag/Declaration/<tt/int __fastcall__ unlink (const char* name);/ <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/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 availability of file I/O). <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. <item>Instead of <tt/unlink/, <tt/<ref id="remove" name="remove">/ should be used, which has the same semantics, but is more portable, because it conforms to the ISO C standard. </itemize> <tag/Availability/POSIX 1003.1 <tag/See also/ <ref id="remove" name="remove"> <tag/Example/ <verb> #include <stdio.h> #include <unistd.h> #define FILENAME "helloworld" if (unlink (FILENAME) == 0) { printf ("We deleted %s successfully\n", FILENAME); } else { printf ("There was a problem deleting %s\n", FILENAME); } </verb> </descrip> </quote> <sect1>utoa<label id="utoa"><p> <quote> <descrip> <tag/Function/Convert an unsigned integer into a string. <tag/Header/<tt/<ref id="stdlib.h" name="stdlib.h">/ <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/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. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="atoi" name="atoi">, <ref id="atol" name="atol">, <ref id="itoa" name="itoa">, <ref id="ltoa" name="ltoa">, <ref id="ultoa" name="ultoa"> <tag/Example/None. </descrip> </quote> <sect1>vcprintf<label id="vcprintf"><p> <quote> <descrip> <tag/Function/Formatted output to the console. <tag/Header/<tt/<ref id="conio.h" name="conio.h">/ <tag/Declaration/<tt/int __fastcall__ vcprintf (const char* format, va_list ap);/ <tag/Description/The arguments specified as a <tt/va_list/ are converted to 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/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 used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="cprintf" name="cprintf">, <ref id="cputc" name="cputc">, <ref id="cputcxy" name="cputcxy">, <ref id="cputs" name="cputs">, <ref id="cputsxy" name="cputsxy"> <tag/Example/None. </descrip> </quote> <sect1>videomode<label id="videomode"><p> <quote> <descrip> <tag/Function/Switch to either 40 or 80 column mode. <tag/Header/<tt/<ref id="apple2enh.h" name="apple2enh.h">, <ref id="c128.h" name="c128.h">/ <tag/Declaration/<tt/unsigned __fastcall__ videomode (unsigned Mode);/ <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/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">. <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/C128 and enhanced Apple //e <tag/See also/ <ref id="fast" name="fast">, <ref id="isfast" name="isfast">, <ref id="slow" name="slow">, <ref id="toggle_videomode" name="toggle_videomode"> <tag/Example/None. </descrip> </quote> <sect1>waitvsync<label id="waitvsync"><p> <quote> <descrip> <tag/Function/Wait until the start of the next frame. <tag/Header/ <tt/<ref id="cbm.h" name="cbm.h">/, <tt/<ref id="gamate.h" name="gamate.h">/, <tt/<ref id="nes.h" name="nes.h">/, <tt/<ref id="pce.h" name="pce.h">/ <tag/Declaration/<tt/void waitvsync (void);/ <tag/Description/Wait for vertical sync to reduce flickering. <tag/Availability/Platforms above <tag/Example/None. </descrip> </quote> <sect1>wherex<label id="wherex"><p> <quote> <descrip> <tag/Function/Return the current X position of the text mode cursor. <tag/Header/<tt/<ref id="conio.h" name="conio.h">/ <tag/Declaration/<tt/unsigned char wherex (void);/ <tag/Description/The function returns the current X position of the text mode cursor. Zero is returned for the leftmost screen position. <tag/Availability/cc65 <tag/See also/ <ref id="gotox" name="gotox">, <ref id="gotoy" name="gotoy">, <ref id="gotoxy" name="gotoxy">, <ref id="wherey" name="wherey"> <tag/Example/None. </descrip> </quote> <sect1>wherey<label id="wherey"><p> <quote> <descrip> <tag/Function/Return the current Y position of the text mode cursor. <tag/Header/<tt/<ref id="conio.h" name="conio.h">/ <tag/Declaration/<tt/unsigned char wherey (void);/ <tag/Description/The function returns the current Y position of the text mode cursor. Zero is returned for the uppermost screen position. <tag/Availability/cc65 <tag/See also/ <ref id="gotox" name="gotox">, <ref id="gotoy" name="gotoy">, <ref id="gotoxy" name="gotoxy">, <ref id="wherex" name="wherex"> <tag/Example/None. </descrip> </quote> </article> ����������������������������������������cc65-2.18/doc/gamate.sgml���������������������������������������������������������������������������0000664�0000000�0000000�00000007710�13473601511�0015101�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>Gamate System specific information for cc65 <author> <url url="mailto:groepaz@gmx.net" name="Groepaz/Hitmen"> <abstract> An overview over the Gamate 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 Gamate runtime system as it comes with the cc65 C compiler. It describes the memory layout, Gamate specific header files, available drivers, and any pitfalls specific to that platform. Please note that Gamate 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 Gamate target is a cartridge image with header. It is of course possible to change this behaviour by using a modified startup file and linker config. Note: the first two bytes of the header contain a checksum that must be inserted by an external program. Such an utility is provided in util/gamate/gamate-fixcart.c <sect>Platform specific header files<p> Programs containing Gamate specific code may use the <tt/gamate.h/ header file. <sect1>Gamate specific functions<p> <itemize> <item>waitvsync</item> </itemize> <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 Gamate. <sect1>Extended memory drivers<p> No extended memory drivers are currently available for the Gamate. <sect1>Joystick drivers<p> <descrip> <tag><tt/gamate-stdjoy.joy (gamate_stdjoy)/</tag> A joystick driver for the standard two buttons joypad is available. </descrip><p> <sect1>Mouse drivers<p> No mouse drivers are currently available for the Gamate. <sect1>RS232 device drivers<p> No serial drivers are currently available for the Gamate. <sect>Limitations<p> <itemize> <item>When using the C-compiler, keep in mind that only 0x200 bytes RAM in total can be used for variables and the runtime stack. </itemize> <sect1>Disk I/O<p> The existing library for the Gamate 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>The Gamate is emulated by MESS (<url url="http://www.mess.org/">), run like this: <tt>mess gamate -debug -window -skip_gameinfo -cart test.bin</tt> </itemize> some resources on the Gamate: <itemize> <item><url url="http://en.wikipedia.org/wiki/Gamate"> </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> ��������������������������������������������������������cc65-2.18/doc/geos.sgml�����������������������������������������������������������������������������0000664�0000000�0000000�00000211455�13473601511�0014603�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>GEOSLib docs <author><url url="mailto:ytm@elysium.pl" name="Maciej Witkowiak"> <abstract> This is the documentation of cc65's GEOSLib, but information contained here may be also useful for writing GEOS applications in general. </abstract> <!-- Table of contents --> <toc> <!-- Begin the document --> <sect>Introduction <p> As we all know that the best computers in the world are the C64 and C128. They have their GUI too - the excellent GEOS. GEOS seems very difficult and cryptic for many people, from programmer's point of view. That's not true. The designers of GEOS created a flexible and powerful system, which is easy to use and program. <p> Coding GEOS in C? That's something new. It is possible now - with Ulrich von Bassewitz's cc65 package and my GEOSLib you are able to create GEOS applications in no time. <p> GEOSLib supports a subset of the standard cc65 libraries. Whenever possible native Kernal functions are used (e.g. <tt/memset/ is an alias for <tt/FillRam/), however not all are supported. E.g. string functions like <tt/strcmp/, <tt/strcpy/ are doubled with native <tt/CmpString/, <tt/CopyString/ because the latter can handle only 256 byte strings. Keep this in mind when you write your program. If you don't need long strings simply use functions from the Kernal, the resulting code will be smaller. <p> <tt/dio/ - direct disk access is available, but you might have problems with devices other than 1541, 1571 or 1581. RAM drives emulating these should work. <p> <tt/conio/ - simple console input-output is available for command line applications. This implementation assumes that one character does fit in 8x8 cell, so output with default BSW font, which is has 9 points, might be a bit messy. There is no color support in GEOS 2.0 so color functions are disabled. Both 40 and 80 column modes are supported and automatically detected. <p> <tt/tgi/ - TGI driver for GEOS that supports both 40 and 80 column modes but mode can not be changed between <tt/tgi_init/ and <tt/tgi_done/. <p> <tt/joy/ - JOY driver for GEOS that supports only joystick, not current pointing device. <p> It is safe to use these standard includes and their contents: <tt/assert.h, conio.h, dio.h, errno.h, em.h, geos.h, joystick.h, modload.h, mouse.h, stdlib.h, string.h, tgi.h, time.h/ <p> For <tt/time.h/ functions <tt/clock()/ and <tt/clock_gettime()/ note that the resolution is one second. <p> Functions from the headers above are either standard C library functions or cc65-specific, in either case they are not GEOS specific and so they are not described here. <p> I am an assembler programmer and GEOSLib was designed in such way that cc65 could emit the best available code (well, the best as for machine :-). Many of the <tt/void foo (void)/ functions are just raw calls to the Kernal (assembled just as <tt/jsr _foo/), look in <tt/gsym.h/, where you can find many definitions of standard GEOS locations. Access to these addresses is optimized by cc65 to simple <tt/lda/ and <tt/sta/. Don't be afraid to use C syntax. <sect1>Requirements <p> You don't need a C64 or C128 for development. The only hardware requirement is a PC capable of running cc65. You do however need C64 or C128 emulator and GEOS disk images (.d64) to test your programs. The software needed: <itemize> <item><em/cc65/ Excellent package containing a C crosscompiler, a crossassembler and a linker, you can get it from: <url url="https://cc65.github.io/">. <item><em/VICE/ This is a portable C64, C128 and few other Commodore computers emulator, you can obtain it from: <url url="http://vice-emu.sourceforge.net/">. The VICE package contains the <em/c1541/ program that is able to convert/unconvert GEOS files to disk images. <item><em/The Star Commander/ This tool is only for DOS. You will need it for transferring object files from a PC to a 1541. There's also one important ability of this tool - it automatically un-converts .cvt files into GEOS native format on disk image files. Check out: <url url="http://sta.c64.org/sc.html">. <item><em/opencbm/ A package that allows for communication directly with a 1541 and other Commodore IEC bus drives. It can be a replacement for Star Commander if you only want to transfer files to a disk and unconvert using GEOS program for this purpose. Check out: <url url="https://spiro.trikaliotis.net/opencbm">. </itemize> <p> VICE and cc65 are portable - they run on variety of platforms - DOS, Win32 and UNIX. GEOSLib only needs cc65. <p> <em/Update:/ starting from v2.5.0 GEOSLib is a part of the cc65 package as its GEOS support library. <sect1>Legal <p> I want to thank Uz for his cc65 package, Alexander Boyce for his excellent GEOS Programmer's Reference Guide and BSW for GEOS. <p> GEOSLib is covered by the same license as cc65. You can find the whole text among documentation. I would really appreciate if you would like to send me your comments, suggestions, questions, changes, bug reports etc. I will also appreciate if you will just give me a sign that you are using GEOSLib - not especially something big and important, mail me even if you are just playing with it. <p> You can send postcards with hellos to: <p> Maciej Witkowiak, ul. Slowackiego 6/57, 77-400 ZLOTOW <p> POLAND <p> e-mail: <tt/ytm@elysium.pl/ <sect>What do you have and what to do with it? <p> This chapter describes some rules you ought to obey, and how to use GEOSLib. <sect1>Usage <p> Apart from this file, which merely describes only standard GEOS library functions, you should read the <tt/grc65/ (GEOS resource compiler) documentation. There is information about necessary resource files (each GEOS application needs at least one) and the build process - what should be done and in what order. Please also read the cc65 documentation on how to compile C, assembler and link everything together. <p> All in all, you just need to place <tscreen><verb> #include <geos.h> </verb></tscreen> at the top of your source. <p> As a general rule read the sources of the example programs and read the headers. These are the most reliable sources of knowledge ;-). You will also find there many C macros representing various arguments passed to the functions. Please use them. You will find your sources easier to understand, and it will be easier to find bugs. <p> All types used in GEOSLib are <tt/unsigned/. <p> Screen coordinates are given in pixels unless stated differently. <sect1>Notes on style <p> Contrary to a typical GEOS assembly program which has a main function called after loading that setups the screen, menus, icons etc. exiting from the <tt/main/ function in C is equivalent to calling <tt/exit()/. These two are the only safe methods of terminating applications. DO NOT USE <tt/EnterDeskTop/! Your data may be lost as library destructors and functions registered with <tt/atexit/ are not called. <p> For GEOS GUI applications the recommended program structure is to have everything initialized in the <tt/main/ function and at the end of it a call to the <tt/MainLoop()/ function. WARNING! This function never returns, any code between <tt/MainLoop();/ and the end of <tt/main/ will not be executed. You have to call <tt/exit()/ explicitly somewhere in your code (e.g. in a menu handler or via DialogBox action). <p> Whenever possible use definitions from <tt/gsym.h/. The resulting code is translated by cc65 into series of <tt/lda/ and <tt/sta/, so you can't do it better :-). <p> Don't hesitate to use library functions. Everything was written with size and speed in mind. In fact many calls are just redirections to the GEOS Kernal which results in a simple <tt/jsr/. <p> The <tt/main/ function receives the standard <tt/argc/ and <tt/argv/ parameters. There are always either 1 or 3 parameters. The DOS application name is always set as <tt/argv[0]/. If present, <tt/argv[1]/ and <tt/argv[2]/ will be set to the data filename and data diskname (it only works if the user double-clicks on a data file associated with your application). Note that it is up to your application to determine which of the available (up to four) disk drives has the disk with given diskname inside. If this fails your program should ask to insert the proper disk into one of available drives. <p> You might wonder why I have chosen a sometimes weird order of arguments in functions. I just wanted to avoid unnecessary pushing and popping of arguments from the stack because cc65 can pass a single <tt/unsigned int/ through CPU registers. <p> Do not try to compile in strict ANSI mode. The library uses cc65 extensions which are not available in ANSI. <p> It is possible to use dynamically loaded modules, three such modules are provided: A GEOS TGI driver, a GEOS EMD driver (for VDC extended memory) and a GEOS JOY driver. Just make sure that their filenames appear UPPERCASE in DeskTop. There are no more special recommendations, read the cc65 documentation about modules and the demo programs source code. <sect>Library Functions <p> Functions here are sorted more or less in the way they appear in the header files. This way I am able to keep functions covering similar tasks near each other. All function names are identical to those from the <tt/geosSym/ file provided with the GeoProgrammer package. Only my extensions to <tt/geosSym/ are covered by new names, but I tried to keep them in the naming convention. <sect1>Graphics <p> This section covers the drawing package of GEOS along with text output routines. <sect2>SetNewMode <p> <tt/void SetNewMode (void)/ <p> This function is intended for use by GEOS 128 only, and will exhibit undefined behavior on the C64. It will toggle between the 40 column screen mode and the 80 column screen mode. Many C128 GEOS programs implement a "Switch 40/80" submenu option under the <tt/geos/ menu. <sect2>SetPattern <p> <tt/void SetPattern (char pattern)/ <p> This function sets the current pattern to the given. There are 32 different patterns in GEOS. You can see them together in the filling box in GeoPaint. <sect2>GraphicsString <p> <tt/void GraphicsString (char *myGString)/ <p> One of the more powerfull routines of GEOS. This function calls other graphic functions depending on the given command string. See the structures chapter for a more detailed description. <sect2>Rectangle functions <p> Parameters to those functions are grouped in the <tt/struct window drawWindow/. To speed up things and reduce overhead this structure is bound to zero page locations, where all rectangle functions expect their parameters. You can modify the data directly (e.g. <tt/drawWindow.top=10/) or via the <tt/InitDrawWindow/ function. Contents of <tt/drawWindow/ are guaranteed not to change when only using graphics functions. In other cases you should keep your data in separate <tt/struct window/ and use <tt/InitDrawWindow/ before the first call to one of the rectangle functions. <sect3>InitDrawWindow <p> <tt/void InitDrawWindow (struct window *myWindow)/ <p> This function only copies the contents of <tt/myWindow/ into the system area of <tt/drawWindow/. Use it if for some reason you have to keep your window data out of the zero page space. <sect3>Rectangle <p> <tt/void Rectangle (void)/ <p> This draws on screen a rectangle filled with the current pattern. <sect3>FrameRectangle <p> <tt/void FrameRectangle (char pattern)/ <p> This one draws a frame with the given bit pattern (not a pattern from the GEOS palette). <sect3>InvertRectangle <p> <tt/void InvertRectangle (void)/ <p> Just as the name says... <sect3>ImprintRectangle and RecoverRectangle <p> <tt/void ImprintRectangle (void)/ <p> <tt/void RecoverRectangle (void)/ <p> These two functions are for copying parts of the screen to (<tt/Imprint/) and from (<tt/Recover/) the backbuffer of the screen. For example when drawing a new menu box GEOS first uses <tt/ImprintRectangle/ to save the area under the box, and restores it by <tt/RecoverRectangle/ upon destroying the menu. <sect2>Line Functions <p> The GEOS drawing package is optimized so there are different functions for drawing vertical and horizontal lines. <sect3>HorizontalLine <p> <tt/void HorizontalLine (char pattern, char y, unsigned xStart, unsigned xEnd)/ <p> This function draws a horizontal line using the given pattern. Note that <tt/pattern/ is not a pattern number as set in <tt/SetPattern/ but a true bit pattern. <sect3>InvertLine <p> <tt/void InvertLine (char y, unsigned xStart, unsigned xEnd)/ <p> There is only a horizontal version. <sect3>RecoverLine <p> <tt/void RecoverLine (char y, unsigned xStart, unsigned xEnd)/ <p> This function recovers a single line. It is utilized by <tt/RecoverRectangle/. See its description for more details. <sect3>VerticalLine <p> <tt/void VerticalLine (char pattern, char yStart, char yEnd, unsigned x)/ <p> This function draws a vertical line using the given pattern. Note that <tt/pattern/ is not a pattern number as set in <tt/SetPattern/ but a true bit pattern. <sect3>DrawLine <p> <tt/void DrawLine (char mode, struct window *myWindow)/ <p> The <tt/top/ parameters of <tt/struct window/ describe the starting point of the line, while <tt/bottom/ ones are for the ending point. If <tt/mode/ is <tt/DRAW_DRAW/ then the current pattern from <tt/SetPattern/ is used for drawing. If <tt/mode/ is <tt/DRAW_ERASE/ then the line is erased from the screen. If <tt/mode/ is <tt/DRAW_COPY/ then the line is copied from/to back/frontbuffer, according to the <tt/dispBufferOn/ setting. <sect2>Point Functions <p> The parameters to these two functions are passed by a pointer to an own <tt/struct pixel/ filled with proper values. <sect3>DrawPoint <p> <tt/void DrawPoint (char mode, struct pixel *myPixel)/ <p> Depending on <tt/mode/ (see <tt/DrawLine/) draws/erases/copies a single point on the screen. <sect3>TestPoint <p> <tt/char TestPoint (struct pixel *myPixel)/ <p> This function tests if the given pixel is set and returns <tt/true/ (non-zero) or <tt/false/ (zero). <sect2>Character and string output <sect3>PutChar <p> <tt/void PutChar (char character, char y, unsigned x)/ <p> This function outputs a single character using the current style and font to the screen. <sect3>PutString <p> <tt/void PutString (char *myString, char y, unsigned x)/ <p> Same as <tt/PutChar/ except the fact that you can output a whole <tt/NULL/-terminated string. See <tt/ggraph.h/ for the list of tokens that you can also place in the string - like <tt/CBOLDON/ or <tt/COUTLINEON/. <sect3>PutDecimal <p> <tt/void PutDecimal (char parameter, unsigned value, char y, unsigned x)/ <p> This function converts <tt/value/ to its decimal representation and outputs it to the screen. The <tt/parameter/ is the field width in pixels (range 1-31) and the mode bits. Depending on them the string can be filled with zeroes (the string is always 5 characters long) or not and left or right justified to the given pixel. See <tt/ggraph.h/ for predefined values for <tt/parameter/. <sect2>Font Handling <sect3>GetCharWidth <p> <tt/char GetCharWidth (char character)/ <p> This function returns the real width (in pixels) of the given character with the current font. It can be used for counting the length of a string on the screen, allowing for indentation or justification. <sect3>LoadCharSet <p> <tt/void LoadCharSet (struct fontdesc *myFont)/ <p> This function forces GEOS to use the given font. <tt/myFont/ should be casted from a pointer to the start of the area where a record from a font file (VLIR structure) was loaded. <sect3>UseSystemFont <p> <tt/void UseSystemFont (void)/ <p> This function forces GEOS to use the built-in BSW font. <sect2>Bitmap handling <p> I'm not quite sure how these functions are working (except <tt/BitmapUp/) so you should probably look into the library sources and compare it with your knowledge. Please let me know if something is wrong or broken. <sect3>BitmapUp <p> <tt/void BitmapUp (struct iconpic *myPic)/ <p> This function unpacks the bitmap and places it on the screen - just as you set it in the <tt/struct iconpic/ pointer which you pass. See <tt/gstruct.h/ for a description of this structure. Note that you can only use packed GEOS bitmaps - a simple Photo Scrap is in this format. <sect3>BitmapClip <p> <tt/void BitmapClip (char skipLeft, char skipRight, unsigned skipTop, struct iconpic *myPic)/ <p> This function acts similar to <tt/BitmapUp/ but you can also define which parts of the bitmap are to be drawn - you give the number of columns (8-pixel) to skip on the right and left of the bitmap, and the number of rows to skip from the top if it. <sect3>BitOtherClip <p> <tt/void BitOtherClip (void *proc1, void *proc2, char skipLeft, char skip Right, unsigned skipTop, struct iconpic *myPic)/ <p> Similar to the previous one with some extension. <tt/proc1/ is called before reading a byte (it returns in .A the next value), and <tt/proc2/ is called every time the parser reads a byte which is not a piece of a pattern (byte of code greater than 219). Both procedures should be written separately in assembler and declared as <tt/__fastcall__/ returning char. <sect1>Menus and Icons <p> Here you will find information about functions related with menus and icons. <sect2>Menus <p> Menus are essential for a GUI. GEOS can handle only one menu at a time, but each menu can call another one, which results in a submenu tree. There can be up to 8 menu levels, each one with up to 32 items. <p> Menus are initialized with <tt/DoMenu/ and then the Kernal takes care of everything. Your code (called from an event handler) should be a function without parameters, returning void. You should use <tt/DoPreviousMenu/ or <tt/GotoFirstMenu/ at least once in its code to have the screen clean. <sect3>DoMenu <p> <tt/void DoMenu (struct menu *myMenu)/ <p> This function initializes the GEOS menu processor and exits. See <tt/DoMenu structure/ for more information about it. Know that many GEOS applications just initialize the screen, menu and exit to the main Kernal loop, this proves the power of <tt/DoMenu/. <sect3>ReDoMenu <p> <tt/void ReDoMenu (void)/ <p> This simply redraws the menu at the lowest level. It works like calling <tt/DoMenu/ again with the same parameters. <sect3>RecoverMenu <p> <tt/void RecoverMenu (void)/ <p> This function erases the current menu from the screen. It doesn't change the menu level. <sect3>RecoverAllMenus <p> <tt/void RecoverAllMenus (void)/ <p> This calls <tt/RecoverMenu/ and erases all menus from the screen. Then the menu level is set to 0 (topmost). <sect3>DoPreviousMenu <p> <tt/void DoPreviousMenu (void)/ <p> This functions causes the menu processor to go back one menu level. You should use it in menu handler code to have the screen clean. <sect3>GotoFirstMenu <p> <tt/void GotoFirstMenu (void)/ <p> This one jumps back to the topmost menu. If there is only a menu and one submenu it works the same as <tt/DoPreviousMenu/. <sect2>Icon Functions <p> Icons are working similar to menus except the fact that there is only one level. Icons are defined as a screen area filled with a bitmap, but if you would setup icons and erase the screen they would still be active and clicking in the place where formerly an icon was would cause an effect. Similarly if you would setup icons and then turn them off with <tt/ClearMouseMode/ the bitmap would still be on the screen but clicking on it would not cause any action. There is only one, but powerful icon function. <sect3>DoIcons <p> <tt/void DoIcons (struct icontab *myIconTab)/ <p> This function initializes all icons that are present on the screen at once. For more information look at the <tt/Icons/ chapter in this manual. <sect1>DialogBoxes <p> This chapter covers the most powerful GEOS user interface function - <tt/DoDlgBox/. <sect2>GEOS standard <sect3>DoDlgBox <p> <tt/char DoDlgBox (char *dialogString)/ <p> This function returns one byte. It can be the value of one of six standard icons (see <tt/gdlgbox.h/) or whatever the closing routine passes. Register <tt/r0L/ also contains this value. <p> Read the structures chapter for the specs of the <tt/dialogString/. <sect3>RstrFrmDialogue <p> <tt/char RstrFrmDialogue/ <p> This function is called from within DoDlgBox event. It immediately closes the DialogBox and returns the owner ID (or whatever caller has in the .A register). <sect2>GEOSLib extensions <p> To simplify the usage of DoDlgBox from C I wrote some helper functions - wrappers for DoDlgBox, with predefined data. In one word - these are standard DialogBoxes you can see in almost every GEOS application. <sect3>DlgBoxYesNo, DlgBoxOkCancel, DlgBoxOk <p> <tt/char DlgBoxYesNo (char *line1, char *line2)/ <p> <tt/char DlgBoxOkCancel (char *line1, char *line2)/ <p> <tt/void DlgBoxOk (char *line1, char *line2)/ <p> These function show two lines of text in a standard-sized DialogBox. You can read the code of the pressed icon from the return value. E.g. for <tt/DlgBoxYesNo/ it can only be <tt/YES/ or <tt/NO/. You can pass an empty string or NULL to get a blank line. <sect3>DlgBoxGetString <p> <tt/char DlgBoxGetString (char *string, char strlen, char *line1, char *line2)/ <p> This function prompts the user to enter a string of at most <tt/strlen/ characters. It is returned in <tt/string/. The two given lines of text are shown above the input line. Please remember that there is also a <tt/CANCEL/ icon in the DialogBox and you should test if user confirmed his input or gave up. The <tt/string/ is also shown so you can place a default input there or remember to place <tt/NULL/ at start. <sect3>DlgBoxFileSelect <p> <tt/char DlgBoxFileSelect (char *class, char filetype, char *filename)/ <p> This routine is the standard file selector. It can return <tt/OPEN/, <tt/CANCEL/ or disk error on reading the directory or opening the disk. There is also a <tt/DISK/ icon shown, but it is handled internally. You pass as input parameters <tt/filetype/ and a pointer to a string containing the first part of a file's class. If this string is empty (<tt/NULL/ at the start), then all files with given filetype will be shown. <p> At present this file selector handles only first 16 files of given type and supports only one (current) drive. <sect3>MessageBox <p> <tt/char MessageBox (char mode, const char *format, ...)/ <p> This function is a more general one. It works very much like <tt/printf/ in a box. The only difference is the <tt/mode/ parameter which allows for placing default icons (see <tt/gdlgbox.h/ for list of possible <tt/MB_/ values). Any too wide text will be clipped to the size of the default window. If <tt/mode/ is invalid or equal to <tt/MB_EMPTY/ then the window will be closed after a click. Otherwise the user must choose an icon. <p> Note: Use it if you really need (or if you use it in many places) as it adds quite amount of code to your program. <p> Note: the formatted text <em/cannot exceed/ 255 bytes in length, there is no check for that. <sect1>Mouse, Sprites and Cursors <p> You will find here functions related to sprite and mouse drawing and handling. <sect2>Mouse related functions <p> These cover the mouse - as a general pointing device, but expect users to utilize as different devices as a digital or analog joystick, a mouse, a lightpen or a koalapad (whatever it is). <sect3>StartMouseMode <p> <tt/void StartMouseMode (void)/ <p> This function initializes the mouse vectors - <tt/mouseVector/ and <tt/mouseFaultVec/, and then calls <tt/MouseUp/. <sect3>ClearMouseMode <p> <tt/void ClearMouseMode (void)/ <p> This function disables all mouse activities - icons and menus stop to respond to mouse events, but they are not cleared from the screen. <sect3>MouseUp and MouseOff <p> <tt/void MouseUp (void)/ <p> <tt/void MouseOff (void)/ <p> The first function turns the mouse pointer on. It appears on the next IRQ. The second one does the opposite - it turns off the pointer, but its position is still updated by the input driver. <sect3>IsMseInRegion <p> <tt/char IsMseInRegion (struct window *myWindow)/ <p> This function tests if the mouse pointer is actually in the given range of the screen. See <tt/gsprite.h/ for a description of the bits in the return values - they describe the position in detail. <sect2>Sprites <p> You are free to use any of the eight sprites, but keep in mind that sprite 0 is actually the mouse pointer and sprite 1 can be overwritten when using a text prompt. You don't have to worry about 40/80 column issues because GEOS128 has a pretty good sprite emulator for the VDC. <sect3>DrawSprite <p> <tt/void DrawSprite (char sprite, char *mySprite)/ <p> This function initializes the sprite data. <tt/mySprite/ is a 63-byte table with bitmap data, which is copied to the system sprite area (at <tt/sprpic/ - see <tt/gsym.h/). Hardware sprite registers are not initialized and the sprite is not yet visible. <sect3>PosSprite <p> <tt/void PosSprite (char sprite, struct pixel *myPixel)/ <p> This function positions the sprite on the screen. The given coordinates are screen ones - they are converted to sprite coordinates by GEOS. Due to this you cannot use this function to position your sprite off the left or top to the screen. <sect3>EnablSprite and DisablSprite <p> <tt/void EnablSprite (char sprite)/ <p> <tt/void DisablSprite (char sprite)/ <p> These two functions are responsible for making the sprite visible or not. <sect2>Cursors and Console <sect3>InitTextPrompt <p> <tt/void InitTextPrompt (char height)/ <p> This function initializes sprite 1 for a text prompt with given <tt/height/. This parameter can be in range 1-48. <sect3>PromptOn and PromptOff <p> <tt/void PromptOn (struct pixel *myPixel)/ <p> <tt/void PromptOff (void)/ <p> The first function places a text prompt in given place and enables blinking. The second one is pretty self-explanatory. <sect3>GetNextChar <p> <tt/char GetNextChar (void)/ <p> This function gets the next character from the keyboard queue. If the queue is empty it returns <tt/NULL/, otherwise you receive the true ASCII code of a character or the value of a special (function) key. See <tt/gsprite.h/ for the list of them. <sect1>Disk <p> This chapter covers rather low-level disk routines. You should use them with care, because you may easily corrupt data on disks. Also remember that contemporary GEOS supports many various devices and sticking to 1541 track layout (e.g. expecting the directory on track 18) might be dangerous. <p> For some purposes you might consider using the <tt/dio.h/ interface to disk access. It is native. <p> All GEOS disk functions return an error code in the X register. In some cases this is returned by the GEOSLib function (if its type is <tt/char/), but in all cases the last error is saved in the <tt/__oserror/ location. If it is nonzero - an error occured. See <tt/gdisk.h/ for the list of possible errorcodes. You need to include <tt/errno.h/ to get <tt/__oserror/, together with the standard <tt/errno/. The latter gives less verbose, but still usable information and can be used with <tt/strerror/. Probably you will get more information using <tt/_stroserror/ in a similar way. <p> For passing parameters use almost always a pointer to your data e.g. <tt/ReadBuff (&myTrSe)/. <sect2>Buffer functions <p> These functions take a single data sector (256 bytes) to read or write on the disk. <sect3>ReadBuff and Writebuff <p> <tt/char ReadBuff (struct tr_se *myTrSe)/ <p> <tt/char WriteBuff (struct tr_se *myTrSe)/ <p> These functions read and write a sector placed at <tt/diskBlkBuf/. <sect3>GetBlock and ReadBlock <p> <tt/char GetBlock (struct tr_se *myTrSe, char *buffer)/ <p> <tt/char ReadBlock (struct tr_se *myTrSe, char *buffer)/ <p> These two functions read a single block directly to the 256 byte array placed at <tt/buffer/. The difference between them is that <tt/GetBlock/ initializes TurboDos in the drive if it was not enabled. <tt/ReadBlock/ assumes that it is already enabled thus being slightly faster. <sect3>PutBlock, WriteBlock, VerWriteBlock <p> <tt/char PutBlock (struct tr_se *myTrSe, char *buffer)/ <p> <tt/char WriteBlock (struct tr_se *myTrSe, char *buffer)/ <p> <tt/char VerWriteBlock (struct tr_se *myTrSe, char *buffer)/ <p> Similar to previous but needed for writing the disk. <tt/VerWriteBlock/ verifies the data after writing. In case of an error five tries are attempted before an error code is returned. <sect2>Directory header <p> The functions described here operate on <tt/curDirHeader/ where the current disk header is stored. On larger (than 1541) capacity drives the second part of the directory header is in <tt/dir2Head/. <sect3>GetPtrCurDkNm <p> <tt/void GetPtrCurDkNm (char *diskName)/ <p> This function fills the given character string with the name of current disk. It is converted to C standard - the string is terminated with <tt/NULL/ character instead of code 160 as in Commodore DOS. Note that the passed pointer must point to an array of at least 17 bytes. <sect3>GetDirHead and PutDirHead <p> <tt/char GetDirHead (void)/ <p> <tt/char PutDirHead (void)/ <p> These functions read and write the directory header. You should use <tt/GetDirHead/ before using any functions described below, and you should use <tt/PutDirHead/ to save the changes on the disk. Otherwise they will be lost. Operating area is the <tt/curDirHead/. <sect3>CalcBlksFree <p> <tt/unsigned CalcBlksFree (void)/ <p> This function returns the number of free blocks on the current disk. It is counted using data in <tt/curDirHead/ so you must initialize the disk before calling it. <sect3>ChkDskGEOS <p> <tt/char ChkDskGEOS (void)/ <p> This functions checks <tt/curDirHead/ for the GEOS Format identifier. It returns either true or false, and also sets <tt/isGEOS/ properly. You must initialize the disk before using this. <sect3>SetGEOSDisk <p> <tt/char SetGEOSDisk (void)/ <p> This function initializes disk for use with GEOS. It sets the indicator in directory header and allocates a sector for the directory of border files. You don't need to initialize the disk before using. <sect3>FindBAMBit <p> <tt/char FindBAMBit (struct tr_se *myTrSe)/ <p> This function returns the bit value from the BAM (Block Allocation Map) for the given sector. The bit is set if the sector is free to use. The returned value is always zero if the sector is already allocated. In fact, this function could be used in a following way: <tscreen><verb> #define BlockInUse FindBAMBit ... if (!BlockInUse(&myTrSe)) { ... block not allocated ... } </verb></tscreen> <p> Anyway, I feel that this function is too low-level. <sect3>BlkAlloc and NxtBlkAlloc <p> <tt/char BlkAlloc (struct tr_se output[&rsqb, unsigned length)/ <p> <tt/char NxtBlkAlloc (struct tr_se *myTrSe, struct tr_se output[&rsqb, unsigned length)/ <p> Both functions allocate enough disk sectors to fit <tt/length/ bytes in them. You find the output in <tt/output/ which is a table of <tt/struct tr_se/. The last entry will have the track equal to 0 and sector equal to 255. The simplest way of using them is to use predefined space in the GEOS data space and pass <tt/fileTrScTab/, which is a predefined table. <p> The difference between those two is that <tt/NextBlkAlloc/ starts allocating from the given sector, and <tt/BlkAlloc/ starts from the first nonused sector. <p> You need to use <tt/PutDirHead/ later to save any changes in BAM. <sect3>FreeBlock <p> <tt/char FreeBlock (struct tr_se *myTrSe)/ <p> Simply deallocates a block in the BAM. You need to update the BAM with <tt/PutDirHead/. <sect3>SetNextFree <p> <tt/struct tr_se SetNextFree (struct tr_se *myTrSe)/ <p> This function finds the first free sector starting from given track and sector and allocates it. It might return the same argument if the given block is not allocated. I wanted it to be type clean, but this made the usage a bit tricky. To assign a value to your own <tt/struct tr_se/ you have to cast both variables to <tt/unsigned/. E.g. <tscreen><verb> struct tr_se myTrSe; ... (unsigned)myTrSe=(unsigned)SetNextFree(&otherTrSe); </verb></tscreen> <p> In this example <tt/otherTrSe/ can be replaced by <tt/myTrSe/. <p> Note: you <em/must/ use casting to have the correct values. <sect2>Low-level disk IO <p> Functions described here are more usable in Kernal or drivers code, less common in applications, but who knows, maybe someone will need them. <sect3>EnterTurbo, ExitTurbo, PurgeTurbo <p> <tt/void EnterTurbo (void)/ <p> <tt/void ExitTurbo (void)/ <p> <tt/void PurgeTurbo (void)/ <p> These functions are the interface to the GEOS TurboDos feature which makes slow Commodore drives a bit more usable. <tt/EnterTurbo/ enables TurboDos unless it is already enabled. If not, then you will have to wait a bit to transfer the TurboDos code into disk drive RAM. <tt/ExitTurbo/ disables TurboDos. This is useful for sending some DOS commands to a drive e.g. for formatting. Note that before any interaction with the Kernal in ROM you have to call <tt/InitForIO/. You don't have to worry about speed. <tt/EnterTurbo/ will only enable TurboDos (no code transfer) if TurboDos was disabled with <tt/ExitTurbo/. <tt/PurgeTurbo/ acts differently from <tt/ExitTurbo/ - it not only disables TurboDos, but also removes it from drive RAM (not quite true, but it works like that). After using <tt/PurgeTurbo/ the next call to <tt/EnterTurbo/ will reload drive RAM. <sect3>ChangeDiskDevice <p> <tt/char ChangeDiskDevice (char newDevice)/ <p> This function changes the device number of the current device (in fact drives only) to the given one. It is usable for swapping drives. There's no check if the given <tt/newDevice/ already exist, so if you want to change the logical number of drive 8 to 9 and you already have a drive number 9 then GEOS will probably hang on disk access. Use safe, large numbers. Note that the safe IEC range is 8-30. <sect2>Disk Initialization <p> GEOS has two functions for initialization ('logging in' as they say on CP/M) of a disk. <sect3>OpenDisk <p> <tt/char OpenDisk (void)/ <p> This function initializes everything for a new disk. It loads and enables TurboDos if needed. Then the disk is initialized with <tt/NewDisk/. Next, <tt/GetDirHead/ initializes <tt/curDirHead/. Disk names are compared and if they differ then the disk cache on REU is cleared. Finally the format is checked with <tt/ChkDkGEOS/ and the disk name is updated in the internal tables. <sect3>NewDisk <p> <tt/char NewDisk (void)/ <p> This function is similar to the DOS command I. It clears the REU cache and enables TurboDos if needed. <sect1>Files <p> This section covers the GEOS file interface. <sect2>Directory handling <p> The functions described here are common for SEQ and VLIR structures. <sect3>Get1stDirEntry and GetNxtDirEntry <p> <tt/struct filehandle *Get1stDirEntry (void)/ <p> <tt/struct filehandle *GetNxtDirEntry (void)/ <p> These two functions are best suited for scanning the whole directory for particular files. Note that the returned filehandles describe all file slots in the directory - even those with deleted files. The return value can be obtained by casting both sides to <tt/unsigned/ - as in the <tt/SetNextFree/ function or read directly after a call to those two functions from <tt/r5/. The current sector number is in <tt/r1/ and the sector data itself is in <tt/diskBlkBuf/. <sect3>FindFile <p> <tt/char FindFile (char *fName)/ <p> This function scans the whole directory for the given filename. It returns either 0 (success) or 5 (FILE_NOT_FOUND, defined in <tt/gdisk.h/) or any other fatal disk read error. After a successful <tt/FindFile/ you will have <tt/struct filehandle/ at <tt/dirEntryBuf/ filled with the file's data and other registers set as described in <tt/GetNxtDirEntry/. <sect3>FindFTypes <p> <tt/char FindFTypes (char *buffer, char fType, char fMaxNum, char *classTxt)/ <p> This function scans the directory and fills a table at <tt/buffer/ with <tt/char [17]/ entries. <tt/fType/ is the GEOS type of the searched files and <tt/classTxt/ is a string for the Class field in the file header. Class matches if the given string is equal or shorter than that found in the file's header block. If you want just to find all files with the given GEOS type you should pass an empty string or <tt/NULL/ as <tt/classTxt/. Be warned that for searching <tt/NON_GEOS/ files you must pass <tt/NULL/ as <tt/classTxt/. <tt/fMaxNum/ is the maximal number of files to find, thus the <tt/buffer/ must provide an area of size equal to <tt/17 * fMaxNum/. This function returns the number of found files, ranging from 0 to number passed as <tt/fMaxNum/. The return value can be also restored from <tt/r7H/. <sect3>DeleteFile <p> <tt/char DeleteFile (char *fName)/ <p> This function deletes a file by its name. It works for SEQ and VLIR files. <sect3>RenameFile <p> <tt/char RenameFile (char *oldName, char *newName)/ <p> I think it is obvious... <sect3>GetFHdrInfo <p> <tt/char GetFHdrInfo (struct filehandle *myFile)/ <p> This function loads the file header into the <tt/fileHeader/ buffer. Using after e.g. <tt/FindFile/ you can pass the address of <tt/dirEntryBuf/. <sect2>Common and SEQ structure <p> Functions described here are common for SEQ and VLIR structures because the arguments passed are the starting track and sector which may point either to the start of a chain for VLIR or the data for SEQ. <sect3>GetFile <p> <tt/char __fastcall__ GetFile(char flag, const char *fname, const char *loadaddr, const char *datadname, const char *datafname)/ <p> This routine loads and runs a given file <tt/fname/. The file must be one of following types: <tt/SYSTEM, DESK_ACC, APPLICATION, APPL_DATA, PRINTER,/ or <tt/INPUT_DEVICE/. The execution address is taken from the file header. If it is zero, then the file is only loaded. Only the first chain from VLIR files is loaded. If <tt/flag/ has bit 0 set then the load address is taken from <tt/loadaddr/ and not from the file header. In this case <tt/APPLICATION/ files will be only loaded, not executed. This does not apply to <tt/DESK_ACC/. If either bit 6 or 7 of <tt/flag/ are set, then 16 bytes from <tt/datadname/ are copied to <tt/dataDiskName/ and 16 bytes from <tt/datafname/ go to <tt/dataFileName/ thus becoming parameters for the new application. Pass <tt/NULL/ for any unused parameter. <sect3>ReadFile <p> <tt/char ReadFile (struct tr_se *myTrSe, char *buffer, unsigned fLength)/ <p> This function reads at most <tt/fLength/ bytes into <tt/buffer/ from chained sectors starting at <tt/myTrSe/. <sect3>ReadByte <p> <tt/char ReadByte (void)/ <p> This function returns the next byte from a file. Before the first call to it you must load <tt/r5/ with <tt/NULL/, <tt/r4/ with the sector buffer address and <tt/r1/ with the track and sector of the first block of a file. Remember to not modify <tt/r1/, <tt/r4/ and <tt/r5/. These registers must be preserved between calls to <tt/ReadByte/. <p> The returned value is valid only if there was no error. The end of file is marked as <tt/BFR_OVERFLOW/ in <tt/__oserror/, this is set when trying to read one byte after the end of file, in this case the returned value is invalid. <sect3>SaveFile <p> <tt/char SaveFile (char skip, struct fileheader *myHeader)/ <p> <tt/SaveFile/ will take care of everything needed to create a GEOS file, no matter if VLIR of SEQ structure. All you need to do is to place the data in the proper place and prepare a header which will contain all information about a file. The <tt/skip/ parameter says how many directory pages you want to skip before searching for a free slot for the directory entry. In most cases you will put <tt/0/ there. <p> You have to declare a <tt/struct fileheader/ and fill it with proper values. There is only one difference - the first two bytes which are a link to a nonexistent next sector are replaced by a pointer to the DOS filename of the file. <p> When saving sequential files the two most important fields in <tt/struct fileheader/ are <tt/fileheader.load_address/ and <tt/fileheader.end_address/. <sect3>FreeFile <p> <tt/char FreeFile (struct tr_se myTable[])/ <p> This function deallocates all sectors contained in the passed table. <sect3>FollowChain <p> <tt/char FollowChain(struct tr_se *myTrSe, char *buffer)/ <p> This function fills a <tt/struct tr_se/ table at <tt/buffer/ with the sector numbers for a chain of sectors starting with <tt/myTrSe/. You can pass such data (<tt/buffer/) to e.g. <tt/FreeFile/. <sect2>VLIR structure <p> Here is information about VLIR files (later called RecordFiles) and functions. <p> A VLIR structure file consists of up to 127 SEQ-like files called records. Each record is like one SEQ structure file. Records are grouped together, described by a common name - the VLIR file name and an own number. Each record pointed to by its number is described by the starting track and sector numbers. VLIR structures allow records to be empty (<tt/tr_se/ of such record is equal to <tt/{NULL,$ff}/), or even non-exist (<tt/{NULL,NULL}/). Any other numbers represent the starting track and sector of a particular file. <p> In GEOS there can be only one file opened at a time. Upon opening a VLIR file some information about it is copied into memory. You can retrieve the records table at <tt/fileTrScTab/ (table of 128 <tt/struct tr_se/) and from <tt/VLIRInfo/ (<tt/struct VLIR_info/. E.g. the size of whole VLIR file can be retrieved by reading <tt/VLIRInfo.fileSize/. <sect3>OpenRecordFile <p> <tt/char OpenRecordFile (char *fName)/ <p> This function finds and opens a given file. An error is returned if the file is not found or if it is not in VLIR format. Information in <tt/VLIRInfo/ is initialized. VLIR track and sector table is loaded at <tt/fileTrScTab/ and will be valid until a call to <tt/CloseRecordFile/ so don't modify it. You should call <tt/PointRecord/ before trying to do something with the file. <sect3>CloseRecordFile <p> <tt/char CloseRecordFile (void)/ <p> This function calls <tt/UpdateRecordFile/ and clears internal GEOS variables. <sect3>UpdateRecordFile <p> <tt/char UpdateRecordFile (void)/ <p> This function will check the <tt/VLIRInfo.fileWritten/ flag and if it is set, then <tt/curDirHead/ is updated along with size and date stamps in the directory entry. <sect3>PointRecord <p> <tt/char PointRecord (char recordNumber)/ <p> This function will setup internal variables (and <tt/VLIRInfo.curRecord/) and return the track and sector of the given record in <tt/r1/. Note that the data may not be valid (if the record is non-existing you will get 0,0 and if it is empty - 255,0). <sect3>NextRecord and PreviousRecord <p> <tt/char NextRecord (void)/ <p> <tt/char PreviousRecord (void)/ <p> These two work like <tt/PointRecord/. Names are self-explanatory. <sect3>AppendRecord <p> <tt/char AppendRecord (void)/ <p> This function will append an empty record (pair of 255,0) to the current VLIR track and sector table. It will also set <tt/VLIRInfo.curRecord/ to its number. <sect3>DeleteRecord <p> <tt/char DeleteRecord (void)/ <p> This function will remove the current record from the table, and move all current+1 records one place back (in the table). Note that there's no BAM update and you must call <tt/UpdateRecordFile/ to commit changes. <sect3>InsertRecord <p> <tt/char InsertRecord (void)/ <p> This function will insert an empty record in place of <tt/VLIRInfo.curRecord/ and move all following records in the table one place forward (contents of <tt/VLIRInfo.curRecord/ after a call to <tt/InsertRecord/ can be found in <tt/VLIRInfo.curRecord + 1/). <sect3>ReadRecord and WriteRecord <p> <tt/char ReadRecord (char *buffer, unsigned fLength)/ <p> <tt/char WriteRecord (char *buffer, unsigned fLength)/ <p> This function will load or save at most <tt/fLength/ bytes from the currently pointed record into or from <tt/buffer/. <sect1>Memory and Strings <p> The functions covered in this section are common for the whole C world - copying memory parts and strings is one of the main computer tasks. GEOS also has an interface to do this. These functions are replacements for those like <tt/memset, memcpy, strcpy/ etc. from standard libraries. If you are dealing with short strings (up to 255 characters) you should use these functions instead of standard ones, e.g. <tt/CopyString/ instead of <tt/strcpy/. It will work faster. <p> However some of them have slightly different calling conventions (order of arguments to be specific), so please check their syntax here before a direct replacement. <p> Please note that the memory areas described here as <em/strings/ are up to 255 characters (without counting the terminating <tt/NULL/), and <em/regions/ can cover the whole 64K of memory. <sect2>CopyString <p> <tt/void CopyString (char *dest, char *src)/ <p> This function copies the string from <tt/src/ to <tt/dest/, until it reaches <tt/NULL/. The <tt/NULL/ is also copied. <sect2>CmpString <p> <tt/char CmpString (char *s1, char *s2)/ <p> This function compares the strings <tt/s1/ to <tt/s2/ for equality - this is case sensitive, and both strings have to have the same length. It returns either <tt/true/ (non-zero) or <tt/false/ (zero). <sect2>CopyFString and CmpFString <p> <tt/void CopyFString (char length, char *dest, char *src)/ <p> <tt/char CmpFString (char length, char *s1, char *s2)/ <p> These two are similar to <tt/CopyString/ and <tt/CmpString/ except the fact, that you provide the length of the copied or compared strings. The strings can also contain several <tt/NULL/ characters - they are not treated as delimiters. <sect2>CRC <p> <tt/unsigned CRC (char *src, unsigned length)/ <p> This function calculates the CRC checksum for the given memory range. I don't know if it is compatible with standard CRC routines. <sect2>FillRam and ClearRam <p> <tt/void *FillRam (char *dest, char value, unsigned length)/ <p> <tt/void *ClearRam (char *dest, unsigned length)/ <p> Both functions are filling the given memory range. <tt/ClearRam/ fills with <tt/0s/, while <tt/FillRam/ uses the given <tt/value/. Be warned that these functions destroy <tt/r0, r1 and r2L/ registers. The functions are aliases for <tt/memset/ and <tt/bzero/, respectively. <sect2>MoveData <p> <tt/void *MoveData (char *dest, char *src, unsigned length)/ <p> This functions copies one memory region to another. There are checks for an overlap and the non-destructive method is chosen. Be warned that this function destroys contents of the <tt/r0, r1 and r2/ registers. This function is an alias for <tt/memcpy/. <sect2>InitRam <p> <tt/void InitRam (char *table)/ <p> This function allows to initialize multiple memory locations with single bytes or strings. This is done with a <tt/table/ where everything is defined. See the structures chapter for a description of <tt/InitRam's/ command string. <sect2>StashRAM, FetchRAM, SwapRAM, and VerifyRAM <p> <tt/void StashRAM (char bank, unsigned length, char *reuAddress, char *cpuAddress)/ <p> <tt/void FetchRAM (char bank, unsigned length, char *reuAddress, char *cpuAddress)/ <p> <tt/void SwapRAM (char bank, unsigned length, char *reuAddress, char *cpuAddress)/ <p> <tt/ char VerifyRAM (char bank, unsigned length, char *reuAddress, char *cpuAddress)/ <p> These functions are the interface to a REU - Ram Expansion Unit. I think that they are self-explanatory. You can check for REU presence by taking the value of <tt/ramExpSize/. You have to do it before using any of these functions. <sect1>Processes and Multitasking <p> Weird? Not at all. GEOS has some limited multitasking ability. You can set up a chain of functions called in specified intervals and you can put the main program to sleep without disturbing other tasks and making the user interface unresponsive. <sect2>InitProcesses <p> <tt/void InitProcesses (char number, struct process *processTab)/ <p> This is the main initialization routine. After calling it processes are set up, but not enabled. The parameters for <tt/InitProcesses/ are: <itemize> <item><tt/number/ - number of processes <item><tt/processTab/ - a table of <tt/struct process/, with size equal to <tt/number/ </itemize> <p> A single task is described by an entry in <tt/processTab/, it contains two values - a <tt/pointer/ to the task function and a number of <tt/jiffies/ which describe the delay between calls to task. On PAL systems there are 50 jiffies per second, while on NTSC there are 60. <p> The maximum number of tasks is 20. Be warned that GEOS doesn't check if parameters are valid and if <tt/processTab/ would be too large it would overwrite existing data in GEOS space. <p> There's one important thing - the last entry in <tt/processTab/ has to be <tt/NULL,NULL/, so the maximum size of <tt/processTab/ is equal to 21. <p> See the description of <tt/process/ structure for a more detailed discussion on this. <sect2>RestartProcess and EnableProcess <p> <tt/void RestartProcess (char processNumber)/ <p> <tt/void EnableProcess (char processNumber)/ <p> These two functions start the task counter. <tt/RestartProcess/ should be called for each process after <tt/InitProcesses/, because it resets all flags and counters and it starts the counters. <p> <tt/RestartProcess/ enables the counters and sets their initial value to that given in <tt/processTab/. <p> <tt/EnableProcess/ forces the given process to execute by simulating the timer expiring. <sect2>BlockProcess and UnblockProcess <p> <tt/void BlockProcess (char processNumber)/ <p> <tt/void UnblockProcess (char processNumber)/ <p> <tt/BlockProcess/ disables the execution of the given process, but this does not disable the timers. It means that if you call <tt/UnblockProcess/ before the timer runs out, the process will be executed. <p> <tt/UnblockProcess/ does the opposite. <sect2>FreezeProcess and UnfreezeProcess <p> <tt/void FreezeProcess (char processNumber)/ <p> <tt/void UnfreezeProcess (char processNumber)/ <p> <tt/FreezeProcess/ disables timer for given process. <tt/UnfreezeProcess/ does the opposite. This is not equal to <tt/RestartProcess/ as timers are not reloaded with initial value. <sect2>Sleep <p> <tt/void Sleep (unsigned jiffies)/ <p> This function is a multitasking sleep - the program is halted, but it doesn't block other functions e.g. callbacks from menus and icons. The only argument here is the number of jiffies to wait until the app will wake up. It depends on the video mode (PAL or NTSC) how many jiffies there are per second (50 or 60, respectively). If you don't want to worry about it and need only full second resolution, call the standard <tt/sleep/ function from <tt/unistd.h/. <sect1>System Functions <sect2>FirstInit <p> <tt/void FirstInit (void)/ <p> This function initializes some GEOS variables and mouse parameters. This is called on GEOS boot up. You shouldn't use this unless you know what you are doing. <sect2>InitForIO and DoneWithIO <p> <tt/void InitForIO (void)/ <p> <tt/void DoneWithIO (void)/ <p> These functions are called by some disk routines. You should call them only if you want to do something with IO registers or call one of the Kernal ROM routines. Note that this is rather an expensive way of turning off IRQs and enabling IO. <sect2>MainLoop <p> <tt/void MainLoop (void)/ <p> Returns control to the system. Any code between call to <tt/MainLoop/ and the end of current function will never be executed. When in <tt/MainLoop/ the system waits for your action - using icons, keyboard or menus to force some specific action from the program. You have to define proper handlers before that. <sect2>EnterDeskTop <p> <tt/void EnterDeskTop (void)/ <p> This is an alias for <tt/exit(0)/ so you will never burn yourself. Anyway, you should not use it. Always use <tt/exit()/ instead. Library destructors and functions registered with <tt/atexit()/ are called. <sect2>ToBASIC <p> <tt/void ToBASIC (void)/ <p> This one is another way of terminating an application - forcing GEOS to shutdown and exit to BASIC. I was considering whether to include it or not, but maybe someone will need it - which I doubt. <p> <em/WARNING:/ library destructors and functions registered with <tt/atexit()/ will not be called so it is quite unsafe way to terminate your program. <sect2>Panic <p> <tt/void Panic (void)/ <p> This calls system's <tt/Panic/ handler - it shows a dialog box with the message <tscreen><verb> System error at:xxxx </verb></tscreen> where <tt/xxxx/ is last known execution address (caller). By default this is bound to the <tt/BRK/ instruction, but it might be usable in debugging as kind of <tt/assert/. (Note that <tt/assert/ is available as a separate function and will give you more information than that). <p> The system is halted after a call to <tt/Panic/ which means that library destructors will not be called and some data may be lost (no wonder you're panicking). <sect2>CallRoutine <p> <tt/void CallRoutine (void *myFunct)/ <p> This is a system caller routine. You need to provide a pointer to a function and it will be immediately called, unless the pointer is equal to <tt/NULL/. This is the main functionality of this function - you don't need to check if the pointer is valid. <sect2>GetSerialNumber <p> <tt/unsigned GetSerialNumber (void)/ <p> This function returns the serial number of the system. It might be used for copy-protection. However, please remember that Free Software is a true power and you are using it right now. <sect2>GetRandom <p> <tt/char GetRandom (void)/ <p> This function returns a random number. It can be also read from <tt/random/ e.g. <tscreen><verb> a=random; </verb></tscreen> but by calling this function you are sure that the results will be always different. <tt/random/ is updated once a frame (50Hz PAL) and on every call to <tt/GetRandom/. <p> Note that this is not the same as the <tt/rand/ function from the standard library. <tt/GetRandom/ will give you unpredictable results (if IRQs occur between calls to it) while <tt/rand/ conforms to the standard and for a given seed (<tt/srand/) always returns with the same sequence of values. <sect2>SetDevice <p> <tt/void SetDevice (char device)/ <p> This function sets the current device to the given. It might be used together with <tt/InitForIO/, <tt/DoneWithIO/ and some Kernal routines. Unless the new device is a disk drive this only sets new value in <tt/curDevice/, in the other case new disk driver is loaded from REU or internal RAM. <sect2>get_ostype <p> <tt/char get_ostype (void)/ <p> This function returns the GEOS Kernal version combined (by logical OR) with the machine type. Read <tt/gsys.h/ for definitions of the returned values. <sect2>get_tv <p> <tt/char get_tv (void)/ <p> This function returns the PAL/NTSC flag combined (by logical OR) with the 40/80 columns flag. This is not the best way to check if the screen has 40 or 80 columns since a PAL/NTSC check is always performed and it can take as long as a full raster frame. If you just want to know if the screen has 40 or 80 columns use the expression <tt/graphMode & 0x80/ which returns <tt/0/ for 40 columns and <tt/0x80/ for 80 columns. Remember that this value can be changed during runtime. It is unclear if this will work for GEOS 64 so you probably do not want to test anything if not running under GEOS128. Use <tt/get_ostype/ to check it. Read <tt/gsys.h/ for definitions of the returned values. <sect>Library Structures <p> To simplify usage and optimize passing parameters to functions I have declared several structures which describe the most common objects. Some of these structures are bound to static addresses in the GEOS data space (<tt/$8000-$8fff/), so you can use their fields directly in an optimized way. Please see <tt/gsym.h/ to find them. All structures are defined in <tt/gstruct.h/ and you may find also some comments there. <sect1>Graphics Structures <sect2>pixel <p> A simple structure describing a point on the screen. <sect2>fontdesc <p> This structure describes a font in one pointsize. There is the current font - <tt/struct fontdesc/ bound to <tt/curFontDesc/. You can also force GEOS to use your own fonts by calling <tt/LoadCharSet/. You just need to open a VLIR font file and load one record - one pointsize - somewhere. At the start of this area you already have all data for <tt/fontdesc/ so you can pass a pointer to the load address of that pointsize to <tt/LoadCharSet/. (Note that although it has 'Load' in the name, that function loads only GEOS internal data structures, not data from disk). <sect2>window <p> This widely used structure holds the description of a region of the screen. It describes the top-left and bottom-right corners of a window. <sect2>iconpic <p> Maybe the name isn't the best - it has nothing with <tt/DoIcons/ but with bitmap functions - <tt/BitmapUp/ for example. This structure holds the parameters needed to properly decode and show a bitmap on the screen. The bitmap has to be encoded - if you have some non-GEOS bitmaps simply convert them to Photo Scraps - this is the format used by all GEOS bitmap functions - <tt/DoIcons/ too. <sect1>Icons <p> These structures describe click boxes (icons) that can be placed on screen or in a dialog box. <sect2>icondef <p> This is the definition of a single click box. Please see <tt/gstruct.h/ for a description of its fields. <sect2>icontab <p> This is the toplevel description of icons to be placed and enabled on the screen. This structure has the following fields: <itemize> <item><tt/char number/ - total number of icons declared here <item><tt/struct pixel mousepos/ - after finishing <tt/DoIcons/ the mouse pointer will be placed in this point allowing you to have a hint for the user what the default action is <item><tt/struct icondef tab[&rsqb/ - this table of size equal to <tt/icontab.number/ contains descriptions for all icons </itemize> <sect1>File and Disk <sect2>tr_se <p> This simple structure holds the track and sector number of something. Do not expect the track to be in range 1-35, as GEOS can support many various and weird devices. For example my C128 256K expansion is utilized as RAMDisk with a layout of 4 tracks of 128 sectors each. However assuming that a track number equal to 0 is illegal might be wise. <sect2>f_date <p> This is a placeholder for a file datestamp. This structure is also present in <tt/struct filehandle/. GEOS is not Y2K compliant, so if the current file has in <tt/filehandle.date.year/ a value less than 86 you can safely assume that it is e.g. 2004 and not 1904. <sect2>filehandle <p> This is the main file descriptor. It is either an entry in the directory (returned from file functions) or its copy in <tt/dirEntryBuf/. This is optimized so you can safely get to the file's year e.g. by testing <tt/dirEntryBuf.date.year/ - it will be compiled to simple <tt/LDA, STA/. <sect2>fileheader <p> This structure holds the fileheader description. You can load a file's header into the <tt/fileHeader/ fixed area using <tt/GetFHdrInfo/. (note that <tt/fileHeader/ is a place in memory while <tt/fileheader/ is a structure). You will also need your own fileheader for <tt/SaveFile/. <sect1>System Structures <sect2>s_date <p> This structure is defined only for <tt/system_date/. It is slightly different from <tt/f_date/ so I prepared this one. You can e.g. get or set the current time using <tt/system_date.s_hour/ and <tt/system_date.s_minute/. Accesses to these will be optimized to simple <tt/LDA/ and <tt/STA/ pair. <sect2>process <p> You should declare a table of that type to prepare data for <tt/InitProcesses/. The maximum number of processes is 20, and the last entry has to be equal to <tt/{NULL,NULL}/, so this table may hold only 21 entries. The first member of this structure (<tt/pointer/) holds the pointer to the called function (void returning void), you will probably have to cast that pointer into <tt/unsigned int/. The second field <tt/jiffies/ holds the amount of time between calls to that function. On PAL systems there are 50 jiffies per second, while NTSC have 60 of them. <sect1>A few things in detail... <p> GEOSLib uses cc65 non-ANSI extensions to easily initialize data in memory. This is done with a kind of array of unspecified length and unspecified type. Here is how it works: <tscreen><verb> void example = { (char)3, (unsigned)3, (char)0 }; </verb></tscreen> Which will be compiled to following string of bytes: <tscreen><verb> _example: .byte 3 .word 3 .byte 0 </verb></tscreen> As you see this way it is possible to define data of any type in any order. You must remember to cast each member to proper type. <sect2>DoMenu structure <p> <tt/DoMenu/ is responsible for everything concerned with menu processing. Many, many GEOS programs are just initializing the screen and menu and returning to <tt/MainLoop/. In GEOSLib it is the same as returning from <tt/main/ function without using <tt/exit(0)/. <p> A menu is described by two types of data - menu descriptors and menu items. A descriptor contains information about the following menu items, and items contain names of entries and either pointers to functions to execute or, in case of nested menus, pointers to submenu descriptors. Note that submenu descriptor can be top-level descriptor, there's no difference in structure, just in the content. <p> Here is how a single descriptor looks like: <tscreen><verb> void myMenu = { (char)top, (char)bottom, // this is the size of the menubox (unsigned)left, (unsigned)right, // counting all items in the current descriptor (char)number_of_items | type_of_menu, // number of following items ORed with // type of this menu, it can be either // HORIZONTAL or VERTICAL if you will have also bit 6 set then menu won't be closed // after moving mouse pointer outside the menubox. You can have at most 31 items. </verb></tscreen> This is followed by <tt/number_of_items/ of following item description. <tscreen><verb> ... "menuitemname", (char)item_type, (unsigned)pointer, "nextitemname", (char)item_type, (unsigned)pointer, ... "lastitemname", (char)item_type, (unsigned)pointer }; // Note that there isn't ending <tt/NULL/ or something like that. </verb></tscreen> <tt/pointer/ is a pointer to something, what it points for depends from <tt/item_type/. This one can have following values: <p> <tt/MENU_ACTION/ - a function pointed by <tt/pointer/ will be called after clicking on the menu item <p> <tt/SUB_MENU/ - <tt/pointer/ points to next menu descriptor - a submenu <p> Both of them can be ORed with <tt/DYN_SUB_MENU/ and then the <tt/pointer/ points to a function which will return in <tt/r0/ the needed pointer (to function to execute or a submenu). <p> For creating nested menus (you can have at most 8 levels of submenus) you need to declare such a structure for each submenu and top level menu. <sect2>DoDlgBox command string <p> <tt/DoDlgBox/ is together with <tt/DoMenu/ one of the most powerful routines in GEOS. It is responsible for creating dialog boxes, that is windows which task is to interact with the user. The format of the command string is following: <tscreen><verb> (window size and position) (commands and parameters) NULL </verb></tscreen> There is a custom type defined for the command string: <tt/dlgBoxStr/. <sect3>Size and position <p> The first element can be specified in two ways - by using the default size and position or specifying your own. The first case results in <tscreen><verb> const dlgBoxStr example = { DB_DEFPOS (pattern_of_shadow), ... // commands DB_END }; </verb></tscreen> And the own size and position would be: <tscreen><verb> const dlgBoxStr example = { DB_SETPOS (pattern, top, bottom, left, right) ... // commands DB_END }; </verb></tscreen> <sect3>Commands <p> The next element of the <tt/DoDlgBox/ command string are the commands themselves. The first six commands are default icons and the number of the selected icon will be returned from window processor. The icons are <tt/OK, CANCEL, YES, NO, OPEN/, and <tt/DISK/. You can use predefined macros for using them, e.g.: <tscreen><verb> ... DB_ICON(OK, DBI_X_0, DBI_Y_0), ... </verb></tscreen> Note that the position is counted from top left corner of window, not entire screen and that the 'x' position is counted in cards (8-pixel) and not in pixels. This is also true for all following commands. <tt/DBI_X_0/ and <tt/DBI_Y_0/ are predefined (see <tt/gdlgbox.h/ for more), the default positions which will cause icons to appear on a default window exactly where you would expect them. <p> <tt/DB_TXTSTR (x, y, text)/ will cause to show the given text in the window. <p> <tt/DB_VARSTR (x, y, ptr)/ works as above, but here you are passing a pointer to a zero page location where the address of the text is stored. This is useful for information windows where only the text content is variable. Consider following: <tscreen><verb> char text = "foo"; ... r15=(unsigned)text; // in code just before call to DoDlgBox ... DB_VARSTR (TXT_LN_X, TXT_LN_1_Y, &r15), ... </verb></tscreen> will cause the word ''foo'' to appear in the window, but you may store the pointer to any text in <tt/r15/ (in this case) before the call to DoDlgBox. <p> <tt/DB_GETSTR(x, y, ptr, length)/ - will add a input-from-keyboard feature. <tt/ptr/ works as in the previous example and points to the location where the text is to be stored. Note that the contents of this location will be shown upon creating the window. <tt/length/ is the maximum number of characters to input. <p> <tt/DB_SYSOPV(ptr)/ - this sets <tt/otherPressVec/ to the given pointer. It is called on every keypress. <p> <tt/DB_GRPHSTR(ptr)/ - the data for this command is a pointer for <tt/GraphicsString/ commands. <p> <tt/DB_GETFILES(x, y)/ - for a standard window you should pass 4 for both x and y. This function draws a file selection box and searches the current drive for files. Before the call to <tt/DoDlgBox/ you must load <tt/r7L/ with the GEOS filetype of searched files and <tt/r10/ with the class text. In <tt/r5/ you have to load a pointer to a <tt/char[17]/ where the selected filename will be copied. It works like <tt/FindFTypes/ but is limited to first 16 files. <p> <tt/DB_OPVEC(ptr)/ - this sets a new pointer for the button press function, if you pass <tt/RstrFrmDialogue/ here you will cause the window to close after pressing mouse button. <p> <tt/DB_USRICON(x, y, ptr)/ - places a single user icon (click box) on the window, <tt/ptr/ points at a <tt/struct icondef/ but fields <tt/x/ and <tt/y/ are not used here. You can have at most 8 click boxes in a window, this is an internal limit of the GEOS Kernal. <p> <tt/DB_USRROUT(ptr)/ - this command causes to immediately call the user routine pointed by <tt/ptr/. <sect2>GraphicsString command string <p> <tt/GraphicsString/ is a very powerful routine to initialize the whole screen at once. There are predefined macros for all commands, names are self-explanatory, see them in <tt/ggraph.h/. The last command has to be <tt/GSTR_END/. There is a custom type defined for the command string: <tt/graphicStr/. <p> Here is an example for clearing the screen: <tscreen><verb> const graphicStr example = { MOVEPENTO(0,0), NEWPATTERN(0), RECTANGLETO(319,199) GSTR_END }; </verb></tscreen> <sect2>InitRam table <p> This type of data is used to initialize one or more bytes in different locations at once. The format is the following: <tscreen><verb> void example = { (unsigned)address_to_store_values_at, (char)number_of_bytes_that_follow, (char)data,(char)data (...) // more such definitions (unsigned)NULL // address of 0 ends the table }; </verb></tscreen> <sect2>Intercepting system vectors <p> It is possible to intercept events and hook into the GEOS Kernal using vectors. Here is a little example: <tscreen><verb> void_func oldVector; void NewVectorHandler(void) { // do something and at the end call the old vector routine oldVector(); } void hook_into_system(void) { oldVector = mouseVector; mouseVector = NewVectorHandler; } void remove_hook(void) { mouseVector = oldVector; } </verb></tscreen> <p> In your <tt/main/ function you should call <tt/hook_into_system()/ but <em/after/ all calls to the GEOS Kernal (like <tt/DoMenu/, <tt/DoIcons/, etc.) - right before passing control to the <tt/MainLoop()/. Be warned that vectors are most likely to be changed by the GEOS Kernal also via other functions (like <tt/GotoFirstMenu/, <tt/DoDlgBox/ and its derivatives etc.). It depends on what Kernal functions you use and which vectors you altered. Unfortunately there is no exact list for GEOS 2.0, a complete list for GEOS 1.x can be found in A. Boyce's Programmers' Reference Guide mentioned before. Most of the information contained there should be still valid for GEOS 2.0. When calling a function that restores the vector you should add a <tt/hook_into_system()/ call right after it. <p> It is critical to restore old vector values before exiting the program. If you have more than one place where you call <tt/exit()/ then it might be worth to register <tt/remove_hook/ function to be called upon exiting with <tt/atexit(&remove_hook);/ call. This way you will ensure that such destructor will be always called. <p> That little example above intercepts <tt/mouseVector/. The <tt/NewVectorHandler/ function will be called every time the mouse button changes status. Other important vectors you should know about are: <itemize> <item><tt/appMain/ - this is called from within the <tt/MainLoop/ system loop <item><tt/keyVector/ - called whenever a keypress occurs <item><tt/intTopVector/ - called at the start of the IRQ routine <item><tt/intBotVector/ - called at the end of the IRQ routine </itemize> </article> �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/grc65.sgml����������������������������������������������������������������������������0000664�0000000�0000000�00000041263�13473601511�0014572�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>grc65 -- GEOS Resource Compiler <author> <url url="mailto:ytm@elysium.pl" name="Maciej 'YTM/Elysium' Witkowiak">,<newline> <url url="mailto:greg.king5@verizon.net" name="Greg King"> <abstract> This document describes a compiler that can create GEOS headers and menues for cc65-compiled programs. </abstract> <!-- Table of contents --> <toc> <!-- Begin the document --> <sect>Overview <p><bf/grc65/ is a part of cc65's GEOS support. The tool is necessary to generate required and optional resources. A required resource for every GEOS application is the header, that is: an icon, some strings, and some addresses. Optional resources might be menu definitions, other headers (e.g., for data files of an app.), dialog definitions, etc. Without an application's header, GEOS is unable to load and start it. Currently, <bf/grc65/ supports only menues and the required header definition, along with support for building applications with VLIR-structured overlays. <bf/grc65/ generates output in two formats: C header and <bf/ca65/ source (.s). That is because the application header data must be in assembly format, while the menu definitions can be translated easily into C. The purpose of the C file is to include it as a header in only one project file. The assembly source should be processed by <bf/ca65/ and linked to the application (read about <ref name="the building process" id="building-seq">). <sect>Usage <p>grc65 accepts the following options: <tscreen><verb> --------------------------------------------------------------------------- Usage: grc65 [options] file Short options: -V Print the version number -h Help (this text) -o name Name the C output file -s name Name the asm output file -t sys Set the target system Long options: --help Help (this text) --target sys Set the target system --version Print the version number --------------------------------------------------------------------------- </verb></tscreen> Default output names are made from input names with extensions replaced by <tt/.h/ and <tt/.s/. <sect>Resource file format <p>A resource file has the name extension <tt/.grc/. That is not required, but it will make for an easier recognition of the file's purpose. Also, <bf/cl65/ recognizes those files. <bf/grc65/'s parser is very weak at the moment; so, read the comments carefully, and write resources exactly as they are written here. Look out for CAPS and small letters. Everything after a '<tt/;/' until the end of the line is considered as a comment and ignored. See the included <ref name="commented example .grc file" id="example-grc"> for a better view of the situation. <sect1>Menu definition <p><tscreen><verb> MENU menuName leftx,topy <ORIENTATION> { "item name 1" <MENU_TYPE> pointer ... "item name x" <MENU_TYPE> pointer }</verb></tscreen> The definition starts with the keyword <tt/MENU/, then comes the menu's name, which will be represented in C as <tt/const void/. Then are the co-ordinates of the top left corner of the menu box. The position of the bottom right corner is estimated, based on the length of item names and the menu's orientation. It means that the menu box always will be as large as it should be. Then, there's the orientation keyword; it can be either <tt/HORIZONTAL/ or <tt/VERTICAL/. Between <tt/{/ and <tt/}/, there's the menu's content. It consists of item definitions. First is an item name -- it has to be in quotes. Next is a menu-type bit. It can be <tt/MENU_ACTION/ or <tt/SUB_MENU/; either of them can be combined with the <tt/DYN_SUB_MENU/ bit (see <url name="the GEOSLib documentation" url="geos.html"> for descriptions of them). You can use C logical operators in expressions, but you have to do it without spaces. So a dynamically created submenu will be something like: <tscreen><verb> "dynamic" SUB_MENU|DYN_SUB_MENU create_dynamic</verb></tscreen> The last part of the item definition is a pointer which can be any name that is present in the C source code that includes the generated header. It can point to a function or to another menu definition. If you are doing sub(sub)menu definitions, remember to place the lowest level definition first, and the top-level menu as the last one. That way the C compiler won't complain about unknown names. <sect1>Header definition <p><tscreen><verb> HEADER <GEOS_TYPE> "dosname" "classname" "version" { author "Joe Schmoe" info "This is my killer-app!" date yy mm dd hh ss dostype SEQ mode any structure SEQ icon "sprite.raw" }</verb></tscreen> The header definition describes the GEOS header sector which is unique to each file. The definition starts with the keyword <tt/HEADER/, then goes the GEOS file-type. You can use only <tt/APPLICATION/ here at the moment. Then, there are (each one in quotes) the DOS file-name (up to 16 characters), the GEOS Class name (up to 12 characters), and the version info (up to 4 characters). The version should be written as &dquot;<tt/V/x.y&dquot;, where <em/x/ is the major, and <em/y/ is the minor, version number. Those fields, along with both braces, are required. The lines between braces are optional, and will be replaced by default and current values. The keyword <tt/author/ and its value in quotes name the programmer, and can be up to 63 bytes long. <tt/info/ (in the same format) can have up to 95 characters. If the <tt/date/ field is omitted, then the time of that compilation will be placed into the header. Note that, if you do specify the date, you have to write all 5 numbers. The <tt/dostype/ can be <tt/SEQ/, <tt/PRG/, or <tt/USR/. <tt/USR/ is used by default; GEOS usually doesn't care. The <tt/mode/ can be <tt/any/, <tt/40only/, <tt/80only/, or <tt/c64only/; and, it describes system requirements. <tt/any/ will work on both 64-GEOS and 128-GEOS, in 40- and 80-column modes. <tt/40only/ will work on 128-GEOS in 40-column mode only. <tt/80only/ will work on only 128-GEOS in 80-column mode, and <tt/c64only/ will work on only 64-GEOS. The default value for <tt/structure/ is <tt/SEQ/ (sequential). You can put <tt/VLIR/ there, too; but then, you also have to put in a third type of resource -- a memory definition. The value of <tt/icon/ is a quoted file-name. The first 63 bytes of this file are expected to represent a standard monochrome VIC sprite. The file gets accessed when the generated assembly source is being processed by <bf/ca65/. Examples for programs generating such files are <em/Sprite Painter/, <em/SpritePad/ and the <url name="sp65 sprite and bitmap utility" url="sp65.html">. The default <tt/icon/ is an empty frame internally represented in the generated assembly file. <sect1>Memory definition <p><tscreen><verb> MEMORY { stacksize 0x0800 overlaysize 0x2000 overlaynums 0 1 2 4 5 }</verb></tscreen> The memory definition is unique to each file and describes several attributes related to the memory layout. It consists of the keyword <tt/MEMORY/ followed by braces which contain optional lines. The value of <tt/stacksize/ can be either decimal (e.g. <tt/4096/) or hexadecimal with a <tt/0x/ prefix (e.g. <tt/0x1000/). The default value of 0x400 comes from the linker configuration file. The value of <tt/backbuffer/ can be either <tt/yes/ or <tt/no/. The further means that the application uses the system-supplied background screen buffer while the latter means that the program uses the memory of the background screen buffer for own purposes. The default value of <tt/yes/ comes from the linker configuration file. If the <tt/structure/ in the header definition is set to the value <tt/VLIR/ then it is possible and necessary to provide here the attributes of the VLIR overlays. <tt/overlaysize/ defines the maximal size for all VLIR records but number 0. It can be either decimal (e.g. <tt/4096/) or hexadecimal with a <tt/0x/ prefix (e.g. <tt/0x1000/). <tt/overlaynums/ defines the VLIR record numbers used by the application. Skipped numbers denote empty records. In the example, record number 3 is missing. Read <ref name="this description" id="building-vlir"> for details. <sect>Building a GEOS sequential application<label id="building-seq"> <p>Before proceeding, please read the <url name="compiler" url="cc65.html">, <url name="assembler" url="ca65.html">, and <url name="linker" url="ld65.html"> documentation, and find the appropriate sections about building programs, in general. GEOS support in cc65 is based on the <em/Convert v2.5/ format, well-known in the GEOS world. It means that each file built with the cc65 package has to be deconverted in GEOS, before it can be run. You can read a step-by-step description of that in the <url name="GEOS section of the cc65 Compiler Intro" url="intro.html#ss6.5">. Each project consists of four parts, two are provided by cc65. Those parts are:<enum> <item>application header <item>start-up object <item>application objects <item>system library </enum> <bf/2./ and <bf/4./ come with cc65; however you have to write the application yourself ;-) The application header is defined in the <tt/HEADER/ section of the <tt/.grc/ file and is processed into an assembly <tt/.s/ file. You must assemble it, with <bf/ca65/, into the object <tt/.o/ format. Assume that there are three input files: &dquot;<tt/test.c/&dquot; (a C source), &dquot;<tt/test.h/&dquot; (a header file), and &dquot;<tt/testres.grc/&dquot; (with menu and header definitions). Note the fact that I <em/don't recommend/ naming that file &dquot;<tt/test.grc/&dquot; because you will have to be very careful with names (<bf/grc65/ will make &dquot;<tt/test.s/&dquot; and &dquot;<tt/test.h/&dquot; out of &dquot;<tt/test.grc/&dquot; by default; and you don't want that because &dquot;<tt/test.s/&dquot; is compiled from &dquot;<tt/test.c/&dquot;, and &dquot;<tt/test.h/&dquot; is something completely different)! <bf/One important thing/ -- the top of &dquot;<tt/test.c/&dquot; looks like: <tscreen><verb> #include <geos.h> #include "testres.h" </verb></tscreen> There are no other includes. <sect1>Building the GEOS application using cl65 <p>This is a simple one step process: <tscreen><verb> cl65 -t geos-cbm -O -o test.cvt testres.grc test.c </verb></tscreen> Always place the <tt/.grc/ file as first input file on the command-line in order to make sure that the generated <tt/.h/ file is available when it is needed for inclusion by a <tt/.c/ file. <sect1>Building the GEOS application without cl65 <sect2>First step -- compiling the resources <p> <tscreen><verb> grc65 -t geos-cbm testres.grc </verb></tscreen> will produce two output files: &dquot;<tt/testres.h/&dquot; and &dquot;<tt/testres.s/&dquot;. Note that &dquot;<tt/testres.h/&dquot; is included at the top of &dquot;<tt/test.c/&dquot;. So, resource compiling <em/must be/ the first step. <sect2>Second step -- assembling the application header <p> <tscreen><verb> ca65 -t geos-cbm testres.s </verb></tscreen> And, voilá -- &dquot;<tt/testres.o/&dquot; is ready. <sect2>Third step -- compiling the code <p> <tscreen><verb> cc65 -t geos-cbm -O test.c ca65 -t geos-cbm test.s </verb></tscreen> That way, you have a &dquot;<tt/test.o/&dquot; object file which contains all of the executable code. <sect2>Fourth and last step -- linking the application <p> <tscreen><verb> ld65 -t geos-cbm -o test.cvt testres.o test.o geos-cbm.lib </verb></tscreen> The last file is the GEOS system library. The resulting file &dquot;<tt/test.cvt/&dquot; is an executable that's contained in the well-known GEOS <em/Convert/ format. Note that its name (<tt/test.cvt/) isn't important; the real name, after deconverting, is the DOS name that was given in the header definition. At each step, a <tt/-t geos-cbm/ was present on the command-line. That switch is required for the correct process of GEOS sequential application building. <sect>Building a GEOS VLIR overlay application<label id="building-vlir"> <p>Large GEOS applications typically don't fit in one piece in their designated memory area. They are therefore split into overlays which are loaded into memory on demand. The individual overlays are stored as records of a VLIR (Variable Length Index Record) file. When GEOS starts a VLIR overlay appliation it loads record number 0 which is supposed to contain the main program. The record numbers starting with 1 are to be used for the actual overlays. In "<tt>cc65/samples/geos</tt>" there's a VLIR overlay demo application consisting of the files "<tt/overlay-demo.c/" and "<tt/overlay-demores.grc/". <sect1>Building the GEOS overlay application using cl65 <p>This is a simple one step process: <tscreen><verb> cl65 -t geos-cbm -O -o overlay-demo.cvt -m overlay-demo.map overlay-demores.grc overlay-demo.c </verb></tscreen> Always place the <tt/.grc/ file as first input file on the command-line in order to make sure that the generated <tt/.h/ file is available when it is needed for inclusion by a <tt/.c/ file. You will almost certainly want to generate a map file that shows (beside a lot of other infos) how large your individual overlays are. This info is necessary to tune the distribution of code into the overlays and to optimize the memory area reserved for the overlays. <sect1>Building the GEOS overlay application without cl65 <sect2>First step -- compiling the overlay resources <p> <tscreen><verb> grc65 -t geos-cbm overlay-demores.grc </verb></tscreen> <sect2>Second step -- assembling the overlay application header <p> <tscreen><verb> ca65 -t geos-cbm overlay-demores.s </verb></tscreen> <sect2>Third step -- compiling the overlay code <p> <tscreen><verb> cc65 -t geos-cbm -O overlay-demo.c ca65 -t geos-cbm overlay-demo.s </verb></tscreen> <sect2>Fourth and last step -- linking the overlay application <p> <tscreen><verb> ld65 -t geos-cbm -o overlay-demo.cvt -m overlay-demo.map overlay-demores.o overlay-demo.o geos-cbm.lib </verb></tscreen> <sect>Bugs and feedback <p>This is the first release of <bf/grc65/, and it contains bugs, for sure! I am aware of them; I know that the parser is weak, and if you don't follow the grammar rules strictly, then everything will crash. However, if you find an interesting bug, mail me. :-) Mail me also for help with writing your <tt/.grc/ file correctly if you have problems with it. I would appreciate comments also, and help on this file because I am sure that it can be written better. <sect>Legal stuff <p><bf/grc65/ is covered by the same license as the whole cc65 package, so you should see its documentation for more info. Anyway, if you like it, and want to encourage me to work more on it, send me a postcard with a sight of your neighbourhood, city, region, etc. Or, just e-mail me with info that you actually used it. See <url name="the GEOSLib documentation" url="geos.html"> for addresses. <!-- <appendix> --> <sect>Appendix A -- example.grc<label id="example-grc"> <p><tscreen><verb> ; Note that MENU can define both menues and submenues. ; If you want to use any C operators (such as "|", "&", etc.), do it WITHOUT ; any spaces between the arguments (the parser is simple and weak). MENU subMenu1 15,0 VERTICAL ; This is a vertical menu, placed at (15,0). { ; There are three items, all of them will call functions. ; The first and third ones are normal functions, see GEOSLib documentation for ; information about what the second function should return (it's a dynamic one). "subitem1" MENU_ACTION smenu1 "subitem2" MENU_ACTION|DYN_SUB_MENU smenu2 "subitem3" MENU_ACTION smenu3 } ;; Format: MENU "name" left,top ALIGN { "itemname" TYPE pointer ... } MENU mainMenu 0,0 HORIZONTAL ; Here, we have our main menu, placed at (0,0), and it is a horizontal menu. ; Because it is a top-level menu, you would register it in your C source by ; using: DoMenu(&ero;mainMenu); { ; There are two items -- a submenu and an action. ; This calls a submenu named subMenu1 (see previous definition). "first sub-menu" SUB_MENU subMenu1 ; This will work the same as an EnterDeskTop() call in C source code. "quit" MENU_ACTION EnterDeskTop } ;; Format: HEADER <GEOS_TYPE> "dosname" "classname" "version" HEADER APPLICATION "MyFirstApp" "Class Name" "V1.0" ; This is a header for an APPLICATION which will be seen in the directory as a ; file named MyFirstApp with the Class-string "Class Name V1.0" { ; Not all fields are required, default and current values will be used. author "Maciej Witkowiak" ; always in quotes! info "Information text" ; always in quotes! ; date yy mm dd hh ss ; always 5 fields! ; dostype seq ; can be: PRG, SEQ, USR (only all UPPER- or lower-case) ; structure seq ; can be: SEQ, VLIR (only UPPER- or lower-case) mode c64only ; can be: any, 40only, 80only, c64only }</verb></tscreen> </article> ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/header.html���������������������������������������������������������������������������0000664�0000000�0000000�00000000176�13473601511�0015074�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> <HTML> <HEAD> <LINK REL="stylesheet" TYPE="text/css" HREF="doc.css"> ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/index.sgml����������������������������������������������������������������������������0000664�0000000�0000000�00000012751�13473601511�0014753�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>cc65 Documentation Overview <author><url url="https://cc65.github.io/doc"> <sect>Program documentation<p> <descrip> <tag><htmlurl url="ar65.html" name="ar65.html"></tag> Describes the ar65 archiver. <tag><htmlurl url="ca65.html" name="ca65.html"></tag> Describes the ca65 macro assembler. <tag><htmlurl url="cc65.html" name="cc65.html"></tag> Describes the cc65 C compiler. <tag><htmlurl url="chrcvt65.html" name="chrcvt65.html"></tag> Describes the vector font converter. <tag><htmlurl url="cl65.html" name="cl65.html"></tag> Describes the cl65 compile & link utility. <tag><htmlurl url="co65.html" name="co65.html"></tag> Describes the co65 object-file converter. <tag><htmlurl url="da65.html" name="da65.html"></tag> Describes the da65 6502/65C02 disassembler. <tag><htmlurl url="grc65.html" name="grc65.html"></tag> Describes the GEOS resource compiler. <tag><htmlurl url="ld65.html" name="ld65.html"></tag> Describes the ld65 linker. <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. </descrip> <sect>Usage<p> <descrip> <tag><htmlurl url="intro.html" name="intro.html"></tag> Describes the use of the tools, by building a short &dquot;hello world&dquot; example. <tag><htmlurl url="coding.html" name="coding.html"></tag> Contains hints on creating the most effective code with cc65. <tag><htmlurl url="cc65-intern.html" name="cc65-intern.html"></tag> Describes internal details of cc65, such as calling conventions. <tag><htmlurl url="using-make.html" name="using-make.html"></tag> Build programs, using the GNU Make utility. <tag><htmlurl url="customizing.html" name="customizing.html"></tag> How to use the cc65 toolset for a custom hardware platform (a target system not currently supported by the cc65 library set). <tag><htmlurl url="debugging.html" name="debugging.html"></tag> Debug programs, using the VICE emulator. </descrip> <sect>Library information and other references<p> <descrip> <tag><htmlurl url="funcref.html" name="funcref.html"></tag> A (currently incomplete) function reference. <tag><htmlurl url="dio.html" name="dio.html"></tag> Low-level disk I/O API. <tag><htmlurl url="tgi.html" name="tgi.html"></tag> Tiny Graphics Interface. <tag><htmlurl url="geos.html" name="geos.html"></tag> The GEOSLib manual. <tag><htmlurl url="library.html" name="library.html"></tag> An overview over the cc65 runtime and C libraries. <tag><htmlurl url="smc.html" name="smc.html"></tag> Describes Christian Krüger's macro package for writing self modifying assembler code. <tag><url name="6502 Binary Relocation Format document" url="http://www.6502.org/users/andre/o65/fileformat.html"></tag> Describes the o65 file format that is used for dynamically loadable modules and LUnix programs. </descrip> <sect>Platform-specific information<p> <descrip> <tag><htmlurl url="apple2.html" name="apple2.html"></tag> Topics specific to the Apple ][. <tag><htmlurl url="apple2enh.html" name="apple2enh.html"></tag> Topics specific to the enhanced Apple //e. <tag><htmlurl url="atari.html" name="atari.html"></tag> Topics specific to the Atari 8-bit machines. <tag><htmlurl url="atari2600.html" name="atari2600.html"></tag> Topics specific to the Atari 2600 Game Console. <tag><htmlurl url="atari5200.html" name="atari5200.html"></tag> Topics specific to the Atari 5200 Game Console. <tag><htmlurl url="atmos.html" name="atmos.html"></tag> Topics specific to the Oric Atmos. <tag><htmlurl url="c128.html" name="c128.html"></tag> Topics specific to the Commodore 128. <tag><htmlurl url="c16.html" name="c16.html"></tag> Topics specific to the Commodore 16/116. <tag><htmlurl url="c64.html" name="c64.html"></tag> Topics specific to the Commodore 64. <tag><htmlurl url="cbm510.html" name="cbm510.html"></tag> Topics specific to the Commodore 510. <tag><htmlurl url="cbm610.html" name="cbm610.html"></tag> Topics specific to the Commodore 610. <tag><htmlurl url="creativision.html" name="creativision.html"></tag> Topics specific to the Creativision Console. <tag><htmlurl url="gamate.html" name="gamate.html"></tag> Topics specific to the Bit Corporation Gamate Console. <tag><htmlurl url="lynx.html" name="lynx.html"></tag> Topics specific to the Atari Lynx Game Console. <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 the NEC PC-Engine (TurboGrafx-16) Console. <tag><htmlurl url="pet.html" name="pet.html"></tag> Topics specific to the Commodore PET machines. <tag><htmlurl url="plus4.html" name="plus4.html"></tag> Topics specific to the Commodore Plus/4. <tag><htmlurl url="supervision.html" name="supervision.html"></tag> Topics specific to the Watara Supervision Console. <tag><htmlurl url="telestrat.html" name="telestrat.html"></tag> Topics specific to the Oric Telestrat. <tag><htmlurl url="vic20.html" name="vic20.html"></tag> Topics specific to the Commodore VIC20. </descrip> </article> �����������������������cc65-2.18/doc/intro.sgml����������������������������������������������������������������������������0000664�0000000�0000000�00000055527�13473601511�0015007�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>cc65 Compiler Intro <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">,<newline> <url url="mailto:stephan.muehlstrasser@web.de" name="Stephan Mühlstrasser"> <abstract> How to use the cc65 C language system -- an introduction. </abstract> <!-- Table of contents --> <toc> <!-- Begin the document --> <sect>Overview<p> This is a short intro of how to use the compiler and the bin-utils. It contains a step-by-step example of how to build a complete application from one C and one assembly modules. This file does <em/not/ contain a complete reference for the tools used in the process. There are separate files describing those tools, in detail (see <url url="index.html">). I do assume that you have downloaded and installed the compiler and target-specific files. Windows users should use the friendly .exe installer (named cc65-2.13.0-1.exe for version 2.13.0 of the package - adjust the version number if necessary). It does not only install the target files, but will also set up necessary environment variables for you. If you're going for the .ZIP archives, please note that there is one file for the host platform (Windows, DOS or OS/2), one file for each target platform (C64 or whatever) and a separate file containing the docs (which include the file you're currently reading). So for most uses, you will need at least 3 files and unpack all three into one directory. In case of the .ZIP archives, you will also need to set the environment variables <tt/CC65_INC/, <tt/LD65_LIB/ and <tt/LD65_CFG/ as described below. <em/Note:/ There is a much simpler way to compile this example, by using the <bf/cl65/ compile-and-link utility. However, it makes sense to understand how the separate steps work. How to do the example with the <bf/cl65/ utility is described <ref id="using-cl65" name="later">. <sect1>Before we start<p> You will find a copy of the sample modules, used in the next section, in the "<tt>cc65/samples/tutorial</tt>" directory. If you encounter problems with missing include files and/or libraries, please check the environment variables <tt/CC65_INC/, <tt/LD65_LIB/ and <tt/LD65_CFG/. They should point to the <tt/include/, <tt/lib/ and <tt/cfg/ subdirectories of the directory, where you installed cc65. <sect1>The sample modules<p> To explain the development flow, I will use the following example modules: hello.c: <tscreen><code> #include <stdio.h> #include <stdlib.h> extern const char text[]; /* In text.s */ int main (void) { printf ("%s\n", text); return EXIT_SUCCESS; } </code></tscreen> text.s: <tscreen><code> .export _text _text: .asciiz "Hello world!" </code></tscreen> <sect1>Translation phases<p> We assume that the target file should be named "hello", and the target system is the C64. <tscreen><verb> +---------+ | hello.c | +---------+ | cc65 \/ +---------+ +---------+ +---------+ | hello.s | | text.s | | crt0.o | +---------+ +---------+ +---------+ | | | ca65 ca65 ar65 \/ \/ \/ +---------+ +---------+ +---------+ | hello.o | | text.o | | c64.lib | +---------+ +---------+ +---------+ | \ / | \ / | \ / +----------------------->ld65< \/ hello </verb></tscreen> <tt/crt0.o/ (the startup code) and <tt/c64.lib/ (the C64 version of the runtime and C library) are provided in binary form in the cc65 package. Actually, the startup code is contained in the library, so you won't need to care about it. <sect>The compiler<p> The compiler translates one C source into one assembly source, for each invocation. It does <em/not/ create object files directly, and it is <em/not/ able to translate more than one file per run. In the example above, we would use the following command line, to translate <tt/hello.c/ into <tt/hello.s/: <tscreen><verb> cc65 -O -t c64 hello.c </verb></tscreen> The <tt/-O/ switch tells the compiler to do an additional optimizer run, which is usually a good idea, since it makes the code smaller. If you don't care about the size, but want to have slightly faster code, use <tt/-Oi/ to inline some runtime functions. The <tt/-t/ switch is followed by the target system name. If the compiler does not complain about errors in our "hello world" program, we will have a file named "<tt/hello.s/", in our directory, that contains the assembly source for the <bf/hello/ module. For more information about the compiler, see <url url="cc65.html">. <sect>The assembler<p> The assembler translates one assembly source into an object file, for each invocation. The assembler is <em/not/ able to translate more than one source file per run. Let's translate the "hello.s" and "text.s" files from our example: <tscreen><verb> ca65 hello.s ca65 -t c64 text.s </verb></tscreen> The <tt/-t/ switch is needed when translating the <tt/text.s/ file, so the text is converted from the input character-set (usually ISO-8859-1) into the target character-set (PETSCII, in this example) by the assembler. The compiler-generated file <tt/hello.s/ does not contain any character constants, so specification of a target is not necessary (it wouldn't do any harm, however). If the assembler does not complain, we should now have two object files (named <tt/hello.o/ and <tt/text.o/) in the current directory. For more information about the assembler, see <url url="ca65.html">. <sect>The linker<p> The linker combines several object and library files into one output file. <bf/ld65/ is very configurable, but fortunately has built-in configurations, so we don't need to mess with configuration files, here. The compiler uses small functions to do things that cannot be done inline without a big impact on code size. Those runtime functions, together with the C library, are in an object-file archive named after the system, in this case, "<tt/c64.lib/". We have to specify that file on the command line, so that the linker can resolve those functions. Let's link our files to get the final executable: <tscreen><verb> ld65 -o hello -t c64 hello.o text.o c64.lib </verb></tscreen> The argument after <tt/-o/ specifies the name of the output file, the argument after <tt/-t/ gives the target system. The following arguments are object files or libraries. Since the target library resolves imports in <tt/hello.o/ and <tt/text.o/, it must be specified <em/after/ those files. After a successful linker run, we have a file named "<tt/hello/", ready for our C64! For more information about the linker, see <url url="ld65.html">. <sect>The easy way (using the cl65 utility)<label id="using-cl65"><p> The <bf/cl65/ utility is able to do all of the steps described above, in just one command line, and it has defaults for some options that are very well-suited for our example. To compile both files into one executable, enter: <tscreen><verb> cl65 -O hello.c text.s </verb></tscreen> The <bf/cl65/ utility knows how to translate C files into object files (it will call the compiler, and then the assembler). It does know also how to create object files from assembly files (it will call only the assembler, for that). It knows how to build an executable (it will pass all object files to the linker). And finally, it has the C64 as a default target, and will supply the correct startup file and runtime library names to the linker, so you don't have to care about that. The one-liner above should give you a C64 executable named "<tt/hello/" in the current directory. For more information about the compile & link utility, see <url url="cl65.html">. <sect>Running The Executable<p> <em/Note: this section is incomplete!/ Depending on the target, cc65 chooses several methods of making a program available for execution. Here, we list sample emulators and instructions for running the program. Unless noted, similar instructions would also apply to a real machine. One word of advice: we suggest you clear the screen at the start, and wait for a keypress at the end of your program, as each target varies in its start and exit conditions. <sect1>Apple <sect2>AppleWin<p> Available at <url url="https://github.com/AppleWin/AppleWin">: Emulates Apple ][/enhanced Apple //e computers, with sound, video, joysticks, serial port, and disk images. Includes monitor. Only for Windows. The package comes with a DOS 3.3 disk (called "master.dsk") image; however, you will need <bf/AppleCommander 1.4.0/ or later (available at <url url="https://applecommander.github.io/">). Compile the tutorial with <tscreen><verb> cl65 -O -t apple2 hello.c text.s </verb></tscreen> for the Apple ][, or: <tscreen><verb> cl65 -O -t apple2enh hello.c text.s </verb></tscreen> for the enhanced Apple //e. Then, put the file onto an Apple disk image, for use with an emulator. Copy the <tt/master.dsk/ which comes with <bf/AppleWin/, and rename it to <tt/cc65.dsk/, then use <bf/AppleCommander/: <tscreen><verb> java -jar ac.jar -as cc65.dsk test < hello </verb></tscreen> Note that a convention in the Apple world is that "hello" is the file which is run automatically upon booting a DOS disk, sort of like the "autoexec.bat" of the MSDOS/Windows world. We've avoided that in the example, however by using "test" as the name of the program as it will appear on the Apple disk. Start the emulator, click on the <bf/Disk 1/ icon, and point to <bf/cc65.dsk/; then, click the big Apple logo, to boot the system. Then, type this on the Apple: <tscreen><verb> BRUN TEST </verb></tscreen> You will see "Hello, World!" appear on the same line. Thanks to <url url="mailto:ol.sc@web.de" name="Oliver Schmidt"> for his help in completing this section. <sect1>Atari <sect2>Atari800Win PLus<p> Available at <url url="http://www.atari.org.pl/PLus/index_us.htm">: Emulates Atari 400/800/65XE/130XE/800XL/1200XL/5200, with stereo sound, disk images, scanline-exact NTSC/PAL video, joysticks, mouse, cartridges, and RAM expansions. Includes monitor. Unfortunately, only for Windows. You will need the emulator, "atarixl.rom" or "atariosb.rom"/"ataribas.rom", and "dos25.xfd" files (not supplied). Compile the tutorial with <tscreen><verb> cl65 -O -t atari hello.c text.s </verb></tscreen> Start the emulator, choose <bf/File>Autoboot image/ or <bf/File>Load executable/, and point to the "<bf/hello/" executable. It is customary to rename executables of that type to "<bf/hello.xex/". The file has a 7-byte header meant to be loaded directly from Atari DOS 2/2.5 or compatibles. On a real Atari, you would need a disk drive, and Atari DOS 2.5 or compatible. Turn on the computer, type <tscreen><verb> DOS </verb></tscreen> at the BASIC prompt, then choose <bf/N. CREATE MEM.SAV/, then choose <bf/L. BINARY LOAD/, and enter <tt/HELLO/. The emulation, also, supports that method. Look at <bf/Atari>Settings/, and check <bf/Enable H: Patch for Hard Disk Devices/, then <bf/Atari>Hard disks/, and set the path of <bf/H1:/ to your executables directory, then use "<bf/H0:HELLO.XEX/" in the above procedure (after pressing <tt/L/), to access your harddrive directly. <em/Note:/ There is no delay after the program exits, as you are returned to the DOS menu. Your C program should wait for a keypress if you want to see any output. <sect2>Stella<p> Available at <url url="http://stella.sourceforge.net">: Stella is a multi-platform Atari 2600 VCS emulator. The latest version is available on the emulator's website. It is also available through the package manager of most Linux distributions (Fedora, Ubuntu, ..). Compile the Atari 2600 sample with <tscreen><verb> make SYS=atari2600 samples </verb></tscreen> Then execute it with <tscreen><verb> stella samples/atari2600hello </verb></tscreen> <sect2>Harmony Cartridge<p> Available at <url url="http://harmony.atariage.com/Site/Harmony.html">: The Harmony Cartridge allows running any Atari 2600 binary on real hardware. The binary must be copied on an SD card, to be inserted in the Harmony Cartridge. It can then be inserted on an Atari 2600 console, and run any binary on the SD card. <sect1>Atmos <sect2>Oricutron<p> 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 a monitor. Fortunately, for all SDL platforms. You will need just the emulator; all ROMs are supplied. Compile the tutorial with <tscreen><verb> 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. 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 <tscreen><verb> CLOAD"" </verb></tscreen> at the BASIC prompt. After it has finished loading, type <tscreen><verb> RUN </verb></tscreen> The emulation, also, supports that method. <sect1>Commodore <sect2>VICE<p> Available at <url url="http://vice-emu.sourceforge.net/">: Emulates Commodore 64/128/VIC-20/PET/CBM II/Plus 4 computers. Supports printers, serial port and adapters, stereo sound, disk drives and images, RAM expansions, cartridges, ethernet connection, cycle-exact NTSC/PAL video, mice, graphics tablet, lightpens, and joysticks. Includes monitor. Runs on MSDOS/PCDOS, Win9x/ME/NT/2000/XP, OS2, BeOS x86, Acorn RISC OS, and most Unixes. Compile the tutorial with <tscreen><verb> cl65 -O -t <sys> hello.c text.s </verb></tscreen> Substitute the name of a Commodore computer for that <tt/<sys>/: <itemize> <item><tt/c128/ <item><tt/c16/ <item><tt/c64/ <item><tt/cbm510/ <item><tt/cbm610/ <item><tt/pet/ <item><tt/plus4/ <item><tt/vic20/ </itemize> Start the desired version of the emulator (CBM610 programs run on the CBM II [<tt/xcbm2/] emulator). In the Windows versions of VICE, choose <bf>File>Autoboot disk/tape image...</bf>, choose your executable, and click <bf/OK/. In the Unix versions, hold down the mouse's first button. Move the pointer to <bf>Smart-attach disk/tape...</bf>, and release the button. Choose your executable, and click <bf/Autostart/. The file has a 14-byte header which corresponds to a PRG-format BASIC program, consisting of a single line, similar to this: <tscreen><code> 1000 sys2061 </code></tscreen> On a real Commodore with attached disk drive, you would type: <tscreen><verb> LOAD "0:HELLO",8 </verb></tscreen> for VIC-20/C64, or: <tscreen><verb> DLOAD "HELLO" </verb></tscreen> on PET/CBM II/C128/C16/Plus 4; then, type <tscreen><verb> RUN </verb></tscreen> On a Commodore 128, you can combine those two commands: <tscreen><verb> RUN "HELLO" </verb></tscreen> The output will appear on a separate line, and you will be returned to a BASIC prompt. <sect1>GEOS<p> Available at <it/Click Here Software's/ <url url="http://cbmfiles.com/geos/index.html" name="GEOS download section">: <it><bf/G/raphics <bf/E/nvironment <bf/O/perating <bf/S/ystem.</it> It provides a WIMP GUI (Windows, Icons, and Mouse-Pointer Graphical User Interface) for Commodore's computer models <bf/64/ and <bf/128/. It can be controlled by many different types of input devices: <itemize> <item>keyboard <item>joysticks <item>mice <item>trackballs <item>graphics drawing tablets <item>light-pens </itemize> The tutorial files are different for GEOS. You will find them "next door," in "<tt>cc65/samples/geos</tt>"; they are called "<tt/hello1.c/" and "<tt/hello1res.grc/". Compile the tutorial with <tscreen><verb> cl65 -t geos-cbm -O -o hello1 hello1res.grc hello1.c </verb></tscreen> Copy the resulting file "<tt/hello1/" onto a (GEOS-format) disk. Boot the GEOS master disk/image. <quote> When you want to run GEOS in an emulator, you must adjust that emulator so that it does a "true drive" emulation. Each emulator has its own way of turning that feature on. </quote> <quote> VICE even has different ways that depend on which operating system is running the emulator. <itemize> <item>In Windows, you must click on <bf/Options/ (in an always visible menu). Then, you must click on <bf/True drive emulation/. <item>In Unix, you must <em/hold down/ the second button on your mouse. Move the pointer down to <bf/Drive settings/. Then, move the pointer over to <bf/Enable true drive emulation/. (If there is a check-mark in front of those words, that feature already is turned on -- then, move the pointer off of that menu.) Release the mouse button. </itemize> </quote> Find the <bf/CONVERT/ program on the boot disk [tap the 6-key; then, you should see its icon in the fourth position on the <bf/deskTop/'s directory notePad]. Move GEOS's pointer over to <bf/CONVERT/'s icon; double-click it to run that program. Click on the <bf/Disk/ icon; put the disk with "<tt/hello1/" into the drive; and, click the <bf/OK/ icon. Use the little icons under the list of file-names to move through that list until you find "<tt/hello1/". Click on it; and then, click on the <bf/Convrt/ icon. <bf/CONVERT/ will ask you to confirm that you choose the correct file; click <bf/YES/ if you did (or, click <bf/NO/ if you made a mistake). After the program has converted "<tt/hello1/" from a CBM file into a GEOS file, it will announce what it did -- click on <bf/OK/. <bf/CONVERT/ will show the file list again. This time, click on <bf/Quit/. (You might need to put the boot disk back into the drive, in order to reload <bf/deskTop/. Then, you must swap back to the disk with the tutorial program on it, and click on its disk icon [on the right side of the screen].) Now, you must find <bf/hello1/. Click on the lower left-hand corner of the directory notePad. Look at the eight file-positions on each page until you see <bf/hello1/. Double-click on its icon. 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 are missing. We suggest that you choose emulators with good compatibility. Also, being able to run all computers in the target series is good for target compatibility testing. A machine-language monitor is almost essential for debugging, but a native debugger could be used, as well. Finally, emulators which run on Unix or Windows would help to reach a wider audience. </article> �������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/ld65.sgml�����������������������������������������������������������������������������0000664�0000000�0000000�00000133200�13473601511�0014407�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <!-- -*- text-mode -*- --> <article> <title>ld65 Users Guide <author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> <abstract> The ld65 linker combines object files into an executable file. ld65 is highly configurable and uses configuration files for high flexibility. </abstract> <!-- Table of contents --> <toc> <!-- Begin the document --> <sect>Overview<p> The ld65 linker combines several object modules created by the ca65 assembler, producing an executable file. The object modules may be read from a library created by the ar65 archiver (this is somewhat faster and more convenient). The linker was designed to be as flexible as possible. It complements the features that are built into the ca65 macroassembler: <itemize> <item> Accept any number of segments to form an executable module. <item> Resolve arbitrary expressions stored in the object files. <item> In case of errors, use the meta information stored in the object files to produce helpful error messages. In case of undefined symbols, expression range errors, or symbol type mismatches, ld65 is able to tell you the exact location in the original assembler source, where the symbol was referenced. <item> Flexible output. The output of ld65 is highly configurable by a config file. Some more-common platforms are supported by default configurations that may be activated by naming the target system. The output generation was designed with different output formats in mind, so adding other formats shouldn't be a great problem. </itemize> <sect>Usage<p> <sect1>Command-line option overview<p> The linker is called as follows: <tscreen><verb> --------------------------------------------------------------------------- Usage: ld65 [options] module ... Short options: -( Start a library group -) End a library group -C name Use linker config file -D sym=val Define a symbol -L path Specify a library search path -Ln name Create a VICE label file -S addr Set the default start address -V Print the linker version -h Help (this text) -m name Create a map file -o name Name the default output file -t sys Set the target system -u sym Force an import of symbol 'sym' -v Verbose mode -vm Verbose map file Long options: --allow-multiple-definition Allow multiple definitions --cfg-path path Specify a config file search path --config name Use linker config file --dbgfile name Generate debug information --define sym=val Define a symbol --end-group End a library group --force-import sym Force an import of symbol 'sym' --help Help (this text) --lib file Link this library --lib-path path Specify a library search path --mapfile name Create a map file --module-id id Specify a module id --obj file Link this object file --obj-path path Specify an object file search path --start-addr addr Set the default start address --start-group Start a library group --target sys Set the target system --version Print the linker version --------------------------------------------------------------------------- </verb></tscreen> <sect1>Command-line options in detail<p> Here is a description of all of the command-line options: <descrip> <tag><tt>--allow-multiple-definition</tt></tag> Normally when a global symbol is defined multiple times, ld65 will issue an error and not create the output file. This option lets it silently ignore this fact and continue. The first definition of a symbol will be used. <label id="option--start-group"> <tag><tt>-(, --start-group</tt></tag> Start a library group. The libraries specified within a group are searched multiple times to resolve crossreferences within the libraries. Normally, crossreferences are resolved only within a library, that is the library is searched multiple times. Libraries specified later on the command line cannot reference otherwise unreferenced symbols in libraries specified earlier, because the linker has already handled them. Library groups are a solution for this problem, because the linker will search repeatedly through all libraries specified in the group, until all possible open symbol references have been satisfied. <tag><tt>-), --end-group</tt></tag> End a library group. See the explanation of the <tt><ref id="option--start-group" name="--start-group"></tt> option. <tag><tt>-h, --help</tt></tag> Print the short option summary shown above. <label id="option-m"> <tag><tt>-m name, --mapfile name</tt></tag> This option (which needs an argument that will used as a filename for the generated map file) will cause the linker to generate a map file. The map file does contain a detailed overview over the modules used, the sizes for the different segments, and a table containing exported symbols. <label id="option-o"> <tag><tt>-o name</tt></tag> The -o switch is used to give the name of the default output file. Depending on your output configuration, this name <em/might not/ be used as the name for the output file. However, for the default configurations, this name is used for the output file name. <label id="option-t"> <tag><tt>-t sys, --target sys</tt></tag> The argument for the -t switch is the name of the target system. Since this switch will activate a default configuration, it may not be used together with the <tt><ref id="option-C" name="-C"></tt> option. The following target systems are currently supported: <itemize> <item>none <item>module <item>apple2 <item>apple2enh <item>atari2600 <item>atari <item>atarixl <item>atmos <item>c16 (works also for the c116 with memory up to 32K) <item>c64 <item>c128 <item>cbm510 (CBM-II series with 40-column video) <item>cbm610 (all CBM series-II computers with 80-column video) <item>geos-apple <item>geos-cbm <item>lunix <item>lynx <item>nes <item>pet (all CBM PET systems except the 2001) <item>plus4 <item>sim6502 <item>sim65c02 <item>supervision <item>telestrat <item>vic20 </itemize> There are a few more targets defined but neither of them is actually supported. <tag><tt>-u sym[:addrsize], --force-import sym[:addrsize]</tt></tag> Force an import of a symbol. While object files are always linked to the output file, regardless if there are any references, object modules from libraries get only linked in if an import can be satisfied by this module. The <tt/--force-import/ option may be used to add a reference to a symbol and as a result force linkage of the module that exports the identifier. The name of the symbol may optionally be followed by a colon and an address-size specifier. If no address size is specified, the default address size for the target machine is used. Please note that the symbol name needs to have the internal representation, meaning you have to prepend an underscore for C identifiers. <label id="option-v"> <tag><tt>-v, --verbose</tt></tag> Using the -v option, you may enable more output that may help you to locate problems. If an undefined symbol is encountered, -v causes the linker to print a detailed list of the references (that is, source file and line) for this symbol. <tag><tt>-vm</tt></tag> Must be used in conjunction with <tt><ref id="option-m" name="-m"></tt> (generate map file). Normally the map file will not include empty segments and sections, or unreferenced symbols. Using this option, you can force the linker to include all that information into the map file. Also, it will include a second <tt/Exports/ list. The first list is sorted by name; the second one is sorted by value. <label id="option-C"> <tag><tt>-C</tt></tag> This gives the name of an output config file to use. See section 4 for more information about config files. -C may not be used together with <tt><ref id="option-t" name="-t"></tt>. <label id="option-D"> <tag><tt>-D sym=value, --define sym=value</tt></tag> This option allows to define an external symbol on the command line. Value may start with a '$' sign or with <tt/0x/ for hexadecimal values, otherwise a leading zero denotes octal values. See also <ref id="SYMBOLS" name="the SYMBOLS section"> in the configuration file. <label id="option--lib-path"> <tag><tt>-L path, --lib-path path</tt></tag> Specify a library search path. This option may be used more than once. It adds a directory to the search path for library files. Libraries specified without a path are searched in the current directory, in the list of directories specified using <tt/--lib-path/, in directories given by environment variables, and in a built-in default directory. <tag><tt>-Ln</tt></tag> This option allows you to create a file that contains all global labels and may be loaded into the VICE emulator using the <tt/ll/ (load label) command or into the Oricutron emulator using the <tt/sl/ (symbols load) command. You may use this to debug your code with VICE. Note: Older versions had some bugs in the label code. If you have problems, please get the latest <url url="http://vice-emu.sourceforge.net" name="VICE"> version. <label id="option-S"> <tag><tt>-S addr, --start-addr addr</tt></tag> Using -S you may define the default starting address. If and how this address is used depends on the config file in use. For the default configurations, only the "none", "apple2" and "apple2enh" systems honor an explicit start address, all other default configs provide their own. <tag><tt>-V, --version</tt></tag> This option prints the version number of the linker. If you send any suggestions or bugfixes, please include this number. <label id="option--cfg-path"> <tag><tt>--cfg-path path</tt></tag> Specify a config file search path. This option may be used more than once. It adds a directory to the search path for config files. A config file given with the <tt><ref id="option-C" name="-C"></tt> option that has no path in its name is searched in the current directory, in the list of directories specified using <tt/--cfg-path/, in directories given by environment variables, and in a built-in default directory. <label id="option--dbgfile"> <tag><tt>--dbgfile name</tt></tag> Specify an output file for debug information. Available information will be written to this file. Using the <tt/-g/ option for the compiler and assembler will increase the amount of information available. Please note that debug information generation is currently being developed, so the format of the file and its contents are subject to change without further notice. <tag><tt>--lib file</tt></tag> Links a library to the output. Use this command-line option instead of just naming the library file, if the linker is not able to determine the file type because of an unusual extension. <tag><tt>--obj file</tt></tag> Links an object file to the output. Use this command-line option instead of just naming the object file, if the linker is not able to determine the file type because of an unusual extension. <label id="option--obj-path"> <tag><tt>--obj-path path</tt></tag> Specify an object file search path. This option may be used more than once. It adds a directory to the search path for object files. An object file passed to the linker that has no path in its name is searched in the current directory, in the list of directories specified using <tt/--obj-path/, in directories given by environment variables, and in a built-in default directory. </descrip> <sect>Search paths<p> Starting with version 2.10, there are now several search-path lists for files needed by the linker: one for libraries, one for object files, and one for config files. <sect1>Library search path<p> The library search-path list contains in this order: <enum> <item>The current directory. <item>Any directory added with the <tt><ref id="option--lib-path" name="--lib-path"></tt> option on the command line. <item>The value of the environment variable <tt/LD65_LIB/ if it is defined. <item>A subdirectory named <tt/lib/ of the directory defined in the environment variable <tt/CC65_HOME/, if it is defined. <item>An optionally compiled-in library path. </enum> <sect1>Object file search path<p> The object file search-path list contains in this order: <enum> <item>The current directory. <item>Any directory added with the <tt><ref id="option--obj-path" name="--obj-path"></tt> option on the command line. <item>The value of the environment variable <tt/LD65_OBJ/ if it is defined. <item>A subdirectory named <tt/obj/ of the directory defined in the environment variable <tt/CC65_HOME/, if it is defined. <item>An optionally compiled-in directory. </enum> <sect1>Config file search path<p> The config file search-path list contains in this order: <enum> <item>The current directory. <item>Any directory added with the <tt><ref id="option--cfg-path" name="--cfg-path"></tt> option on the command line. <item>The value of the environment variable <tt/LD65_CFG/ if it is defined. <item>A subdirectory named <tt/cfg/ of the directory defined in the environment variable <tt/CC65_HOME/, if it is defined. <item>An optionally compiled-in directory. </enum> <sect>Detailed workings<p> The linker does several things when combining object modules: First, the command line is parsed from left to right. For each object file encountered (object files are recognized by a magic word in the header, so the linker does not care about the name), imported and exported identifiers are read from the file and inserted in a table. If a library name is given (libraries are also recognized by a magic word, there are no special naming conventions), all modules in the library are checked if an export from this module would satisfy an import from other modules. All modules where this is the case are marked. If duplicate identifiers are found, the linker issues warnings. That procedure (parsing and reading from left to right) does mean that a library may only satisfy references for object modules (given directly or from a library) named <em/before/ that library. With the command line <tscreen><verb> ld65 crt0.o clib.lib test.o </verb></tscreen> the module <tt/test.o/ must not contain references to modules in the library <tt/clib.lib/. But, if it does, you have to change the order of the modules on the command line: <tscreen><verb> ld65 crt0.o test.o clib.lib </verb></tscreen> Step two is, to read the configuration file, and assign start addresses for the segments and define any linker symbols (see <ref id="config-files" name="Configuration files">). After that, the linker is ready to produce an output file. Before doing that, it checks its data for consistency. That is, it checks for unresolved externals (if the output format is not relocatable) and for symbol type mismatches (for example a zero-page symbol is imported by a module as an absolute symbol). Step four is, to write the actual target files. In this step, the linker will resolve any expressions contained in the segment data. Circular references are also detected in this step (a symbol may have a circular reference that goes unnoticed if the symbol is not used). Step five is to output a map file with a detailed list of all modules, segments and symbols encountered. And, last step, if you give the <tt><ref id="option-v" name="-v"></tt> switch twice, you get a dump of the segment data. However, this may be quite unreadable if you're not a developer. :-) <sect>Configuration files<label id="config-files"><p> Configuration files are used to describe the layout of the output file(s). Two major topics are covered in a config file: The memory layout of the target architecture, and the assignment of segments to memory areas. In addition, several other attributes may be specified. Case is ignored for keywords, that is, section or attribute names, but it is <em/not/ ignored for names and strings. <sect1>Memory areas<p> Memory areas are specified in a <tt/MEMORY/ section. Let's have a look at an example (this one describes the usable memory layout of the C64): <tscreen><verb> MEMORY { RAM1: start = $0800, size = $9800; ROM1: start = $A000, size = $2000; RAM2: start = $C000, size = $1000; ROM2: start = $E000, size = $2000; } </verb></tscreen> As you can see, there are two RAM areas and two ROM areas. The names (before the colon) are arbitrary names that must start with a letter, with the remaining characters being letters or digits. The names of the memory areas are used when assigning segments. As mentioned above, case is significant for those names. The syntax above is used in all sections of the config file. The name (<tt/ROM1/ etc.) is said to be an identifier, the remaining tokens up to the semicolon specify attributes for this identifier. You may use the equal sign to assign values to attributes, and you may use a comma to separate attributes, you may also leave both out. But you <em/must/ use a semicolon to mark the end of the attributes for one identifier. The section above may also have looked like this: <tscreen><verb> # Start of memory section MEMORY { RAM1: start $0800 size $9800; ROM1: start $A000 size $2000; RAM2: start $C000 size $1000; ROM2: start $E000 size $2000; } </verb></tscreen> There are of course more attributes for a memory section than just start and size. Start and size are mandatory attributes, that means, each memory area defined <em/must/ have these attributes given (the linker will check that). I will cover other attributes later. As you may have noticed, I've used a comment in the example above. Comments start with a hash mark ('#'), the remainder of the line is ignored if this character is found. <sect1>Segments<p> Let's assume you have written a program for your trusty old C64, and you would like to run it. For testing purposes, it should run in the <tt/RAM/ area. So we will start to assign segments to memory sections in the <tt/SEGMENTS/ section: <tscreen><verb> SEGMENTS { CODE: load = RAM1, type = ro; RODATA: load = RAM1, type = ro; DATA: load = RAM1, type = rw; BSS: load = RAM1, type = bss, define = yes; } </verb></tscreen> What we are doing here is telling the linker, that all segments go into the <tt/RAM1/ memory area in the order specified in the <tt/SEGMENTS/ section. So the linker will first write the <tt/CODE/ segment, then the <tt/RODATA/ segment, then the <tt/DATA/ segment - but it will not write the <tt/BSS/ segment. Why? Here enters the segment type: For each segment specified, you may also specify a segment attribute. There are five possible segment attributes: <tscreen><verb> ro means readonly rw means read/write bss means that this is an uninitialized segment zp a zeropage segment overwrite a segment that overwrites (parts of) another one </verb></tscreen> So, because we specified that the segment with the name BSS is of type bss, the linker knows that this is uninitialized data, and will not write it to an output file. This is an important point: For the assembler, the <tt/BSS/ segment has no special meaning. You specify, which segments have the bss attribute when linking. This approach is much more flexible than having one fixed bss segment, and is a result of the design decision to supporting an arbitrary segment count. If you specify "<tt/type = bss/" for a segment, the linker will make sure that this segment does only contain uninitialized data (that is, zeroes), and issue a warning if this is not the case. For a <tt/bss/ type segment to be useful, it must be cleared somehow by your program (this happens usually in the startup code - for example the startup code for cc65-generated programs takes care about that). But how does your code know, where the segment starts, and how big it is? The linker is able to give that information, but you must request it. This is, what we're doing with the "<tt/define = yes/" attribute in the <tt/BSS/ definitions. For each segment, where this attribute is true, the linker will export three symbols. <tscreen><verb> __NAME_LOAD__ This is set to the address where the segment is loaded. __NAME_RUN__ This is set to the run address of the segment. We will cover run addresses later. __NAME_SIZE__ This is set to the segment size. </verb></tscreen> Replace <tt/NAME/ by the name of the segment, in the example above, this would be <tt/BSS/. These symbols may be accessed by your code. Now, as we've configured the linker to write the first three segments and create symbols for the last one, there's only one question left: Where does the linker put the data? It would be very convenient to have the data in a file, wouldn't it? <sect1>Output files<p> We don't have any files specified above, and indeed, this is not needed in a simple configuration like the one above. There is an additional attribute "file" that may be specified for a memory area, that gives a file name to write the area data into. If there is no file name given, the linker will assign the default file name. This is "a.out" or the one given with the <tt><ref id="option-o" name="-o"></tt> option on the command line. Since the default behaviour is OK for our purposes, I did not use the attribute in the example above. Let's have a look at it now. The "file" attribute (the keyword may also be written as "FILE" if you like that better) takes a string enclosed in double quotes ('&dquot;') that specifies the file, where the data is written. You may specify the same file several times, in that case the data for all memory areas having this file name is written into this file, in the order of the memory areas defined in the <tt/MEMORY/ section. Let's specify some file names in the <tt/MEMORY/ section used above: <tscreen><verb> MEMORY { RAM1: start = $0800, size = $9800, file = %O; ROM1: start = $A000, size = $2000, file = "rom1.bin"; RAM2: start = $C000, size = $1000, file = %O; ROM2: start = $E000, size = $2000, file = "rom2.bin"; } </verb></tscreen> The <tt/%O/ used here is a way to specify the default behaviour explicitly: <tt/%O/ is replaced by a string (including the quotes) that contains the default output name, that is, "a.out" or the name specified with the <tt><ref id="option-o" name="-o"></tt> option on the command line. Into this file, the linker will first write any segments that go into <tt/RAM1/, and will append then the segments for <tt/RAM2/, because the memory areas are given in this order. So, for the RAM areas, nothing has really changed. We've not used the ROM areas, but we will do that below, so we give the file names here. Segments that go into <tt/ROM1/ will be written to a file named "rom1.bin", and segments that go into <tt/ROM2/ will be written to a file named "rom2.bin". The name given on the command line is ignored in both cases. Assigning an empty file name for a memory area will discard the data written to it. This is useful, if the memory area has segments assigned that are empty (for example because they are of type bss). In that case, the linker will create an empty output file. This may be suppressed by assigning an empty file name to that memory area. The <tt/%O/ sequence is also allowed inside a string. So using <tscreen><verb> MEMORY { ROM1: start = $A000, size = $2000, file = "%O-1.bin"; ROM2: start = $E000, size = $2000, file = "%O-2.bin"; } </verb></tscreen> would write two files that start with the name of the output file specified on the command line, with "-1.bin" and "-2.bin" appended respectively. Because '%' is used as an escape char, the sequence "%%" has to be used if a single percent sign is required. <sect1>OVERWRITE segments<p> There are situations when you may wish to overwrite some part (or parts) of a segment with another one. Perhaps you are modifying an OS ROM that has its public subroutines at fixed, well-known addresses, and you want to prevent them from shifting to other locations in memory if your changed code takes less space. Or you are updating a block of code available in binary-only form with fixes that are scattered in various places. Generally, whenever you want to minimize disturbance to an existing code brought on by your updates, OVERWRITE segments are worth considering. Here is an example: <tscreen><verb> MEMORY { RAM: file = "", start = $6000, size = $2000, type=rw; ROM: file = %O, start = $8000, size = $8000, type=ro; } </verb></tscreen> Nothing unusual so far, just two memory blocks - one RAM, one ROM. Now let's look at the segment configuration: <tscreen><verb> SEGMENTS { RAM: load = RAM, type = bss; ORIGINAL: load = ROM, type = ro; FASTCOPY: load = ROM, start=$9000, type = overwrite; JMPPATCH1: load = ROM, start=$f7e8, type = overwrite; DEBUG: load = ROM, start=$8000, type = overwrite; VERSION: load = ROM, start=$e5b7, type = overwrite; } </verb></tscreen> Segment named ORIGINAL contains the original code, disassembled or provided in a binary form (i.e. using <tt/.INCBIN/ directive; see the <tt/ca65/ assembler document). Subsequent four segments will be relocated to addresses specified by their "start" attributes ("offset" can also be used) and then will overwrite whatever was at these locations in the ORIGINAL segment. In the end, resulting binary output file will thus contain original data with the exception of four sequences starting at $9000, $f7e8, $8000 and $e5b7, which will sport code from their respective segments. How long these sequences will be depends on the lengths of corresponding segments - they can even overlap, so think what you're doing. Finally, note that OVERWRITE segments should be the final segments loaded to a particular memory area, and that they need at least one of "start" or "offset" attributes specified. <sect1>LOAD and RUN addresses (ROMable code)<p> Let us look now at a more complex example. Say, you've successfully tested your new "Super Operating System" (SOS for short) for the C64, and you will now go and replace the ROMs by your own code. When doing that, you face a new problem: If the code runs in RAM, we need not to care about read/write data. But now, if the code is in ROM, we must care about it. Remember the default segments (you may of course specify your own): <tscreen><verb> CODE read-only code RODATA read-only data DATA read/write data BSS uninitialized data, read/write </verb></tscreen> Since <tt/BSS/ is not initialized, we must not care about it now, but what about <tt/DATA/? <tt/DATA/ contains initialized data, that is, data that was explicitly assigned a value. And your program will rely on these values on startup. Since there's no way to remember the contents of the data segment, other than storing it into one of the ROMs, we have to put it there. But unfortunately, ROM is not writable, so we have to copy it into RAM before running the actual code. The linker won't copy the data from ROM into RAM for you (this must be done by the startup code of your program), but it has some features that will help you in this process. First, you may not only specify a "<tt/load/" attribute for a segment, but also a "<tt/run/" attribute. The "<tt/load/" attribute is mandatory, and, if you don't specify a "<tt/run/" attribute, the linker assumes that load area and run area are the same. We will use this feature for our data area: <tscreen><verb> SEGMENTS { CODE: load = ROM1, type = ro; RODATA: load = ROM2, type = ro; DATA: load = ROM2, run = RAM2, type = rw, define = yes; BSS: load = RAM2, type = bss, define = yes; } </verb></tscreen> Let's have a closer look at this <tt/SEGMENTS/ section. We specify that the <tt/CODE/ segment goes into <tt/ROM1/ (the one at $A000). The readonly data goes into <tt/ROM2/. Read/write data will be loaded into <tt/ROM2/ but is run in <tt/RAM2/. That means that all references to labels in the <tt/DATA/ segment are relocated to be in <tt/RAM2/, but the segment is written to <tt/ROM2/. All your startup code has to do is, to copy the data from its location in <tt/ROM2/ to the final location in <tt/RAM2/. So, how do you know, where the data is located? This is the second point, where you get help from the linker. Remember the "<tt/define/" attribute? Since we have set this attribute to true, the linker will define three external symbols for the data segment that may be accessed from your code: <tscreen><verb> __DATA_LOAD__ This is set to the address where the segment is loaded, in this case, it is an address in ROM2. __DATA_RUN__ This is set to the run address of the segment, in this case, it is an address in RAM2. __DATA_SIZE__ This is set to the segment size. </verb></tscreen> So, what your startup code must do, is to copy <tt/__DATA_SIZE__/ bytes from <tt/__DATA_LOAD__/ to <tt/__DATA_RUN__/ before any other routines are called. All references to labels in the <tt/DATA/ segment are relocated to <tt/RAM2/ by the linker, so things will work properly. There's a library subroutine called <tt/copydata/ (in a module named <tt/copydata.s/) that might be used to do actual copying. Be sure to have a look at it's inner workings before using it! <sect1>Other MEMORY area attributes<p> There are some other attributes not covered above. Before starting the reference section, I will discuss the remaining things here. You may request symbols definitions also for memory areas. This may be useful for things like a software stack, or an I/O area. <tscreen><verb> MEMORY { STACK: start = $C000, size = $1000, define = yes; } </verb></tscreen> This will define some external symbols that may be used in your code: <tscreen><verb> __STACK_START__ This is set to the start of the memory area, $C000 in this example. __STACK_SIZE__ The size of the area, here $1000. __STACK_LAST__ This is NOT the same as START+SIZE. Instead, it is defined as the first address that is not used by data. If we don't define any segments for this area, the value will be the same as START. __STACK_FILEOFFS__ The binary offset in the output file. This is not defined for relocatable output file formats (o65). </verb></tscreen> A memory section may also have a type. Valid types are <tscreen><verb> ro for readonly memory rw for read/write memory. </verb></tscreen> The linker will assure, that no segment marked as read/write or bss is put into a memory area that is marked as readonly. Unused memory in a memory area may be filled. Use the "<tt/fill = yes/" attribute to request this. The default value to fill unused space is zero. If you don't like this, you may specify a byte value that is used to fill these areas with the "<tt/fillval/" attribute. If there is no "<tt/fillval/" attribute for the segment, the "<tt/fillval/" attribute of the memory area (or its default) is used instead. This means that the value may also be used to fill unfilled areas generated by the assembler's <tt/.ALIGN/ and <tt/.RES/ directives. The symbol <tt/%S/ may be used to access the default start address (that is, the one defined in <ref id="FEATURES" name="the FEATURES section">, or the value given on the command line with the <tt><ref id="option-S" name="-S"></tt> option). To support systems with banked memory, a special attribute named <tt/bank/ is available. The attribute value is an arbitrary 32-bit integer. The assembler has a builtin function named <tt/.BANK/ which may be used with an argument that has a segment reference (for example a symbol). The result of this function is the value of the bank attribute for the run memory area of the segment. <sect1>Other SEGMENT attributes<p> Segments may be aligned to some memory boundary. Specify "<tt/align = num/" to request this feature. To align all segments on a page boundary, use <tscreen><verb> SEGMENTS { CODE: load = ROM1, type = ro, align = $100; RODATA: load = ROM2, type = ro, align = $100; DATA: load = ROM2, run = RAM2, type = rw, define = yes, align = $100; BSS: load = RAM2, type = bss, define = yes, align = $100; } </verb></tscreen> If an alignment is requested, the linker will add enough space to the output file, so that the new segment starts at an address that is dividable by the given number without a remainder. All addresses are adjusted accordingly. To fill the unused space, bytes of zero are used, or, if the memory area has a "<tt/fillval/" attribute, that value. Alignment is always needed, if you have used the <tt/.ALIGN/ command in the assembler. The alignment of a segment must be equal or greater than the alignment used in the <tt/.ALIGN/ command. The linker will check that, and issue a warning, if the alignment of a segment is lower than the alignment requested in an <tt/.ALIGN/ command of one of the modules making up this segment. For a given segment you may also specify a fixed offset into a memory area or a fixed start address. Use this if you want the code to run at a specific address (a prominent case is the interrupt vector table which must go at address $FFFA). Only one of <tt/ALIGN/ or <tt/OFFSET/ or <tt/START/ may be specified. If the directive creates empty space, it will be filled with zero, of with the value specified with the "<tt/fillval/" attribute if one is given. The linker will warn you if it is not possible to put the code at the specified offset (this may happen if other segments in this area are too large). Here's an example: <tscreen><verb> SEGMENTS { VECTORS: load = ROM2, type = ro, start = $FFFA; } </verb></tscreen> or (for the segment definitions from above) <tscreen><verb> SEGMENTS { VECTORS: load = ROM2, type = ro, offset = $1FFA; } </verb></tscreen> The "<tt/align/", "<tt/start/" and "<tt/offset/" attributes change placement of the segment in the run memory area, because this is what is usually desired. If load and run memory areas are equal (which is the case if only the load memory area has been specified), the attributes will also work. There is also an "<tt/align_load/" attribute that may be used to align the start of the segment in the load memory area, in case different load and run areas have been specified. There are no special attributes to set start or offset for just the load memory area. A "<tt/fillval/" attribute may not only be specified for a memory area, but also for a segment. The value must be an integer between 0 and 255. It is used as the fill value for space reserved by the assembler's <tt/.ALIGN/ and <tt/.RES/ commands. It is also used as the fill value for space between sections (part of a segment that comes from one object file) caused by alignment, but not for space that preceeds the first section. To suppress the warning, the linker issues if it encounters a segment that is not found in any of the input files, use "<tt/optional=yes/" as an additional segment attribute. Be careful when using this attribute, because a missing segment may be a sign of a problem, and if you're suppressing the warning, there is no one left to tell you about it. <sect1>The FILES section<p> The <tt/FILES/ section is used to support other formats than straight binary (which is the default, so binary output files do not need an explicit entry in the <tt/FILES/ section). The <tt/FILES/ section lists output files and as only attribute the format of each output file. Assigning binary format to the default output file would look like this: <tscreen><verb> FILES { %O: format = bin; } </verb></tscreen> There are two other available formats, one is the o65 format specified by Andre Fachat (see the <url url="http://www.6502.org/users/andre/o65/fileformat.html" name="6502 binary relocation format specification">). It is defined like this: <tscreen><verb> FILES { %O: format = o65; } </verb></tscreen> The other format available is the Atari (xex) segmented file format, this is the standard format used by Atari DOS 2.0 and upward file managers in the Atari 8-bit computers, and it is defined like this: <tscreen><verb> FILES { %O: format = atari; } </verb></tscreen> In the Atari segmented file format, the linker will write each <tt/MEMORY/ area as a new segment, including a header with the start and end address. The necessary o65 or Atari attributes are defined in a special section labeled <ref id="FORMAT" name="FORMAT">. <sect1>The FORMAT section<label id="FORMAT"><p> The <tt/FORMAT/ section is used to describe file formats. The default (binary) format has currently no attributes, so, while it may be listed in this section, the attribute list is empty. The second supported format, <url url="http://www.6502.org/users/andre/o65/fileformat.html" name="o65">, has several attributes that may be defined here. <tscreen><verb> FORMATS { o65: os = lunix, version = 0, type = small, import = LUNIXKERNEL, export = _main; } </verb></tscreen> The Atari file format has two attributes: <descrip> <tag><tt>RUNAD = symbol</tt></tag> Specify a symbol as the run address of the binary, the loader will call this address after all the file is loaded in memory. If the attribute is omitted, no run address is included in the file. <tag><tt>INITAD = memory_area : symbol</tt></tag> Specify a symbol as the initialization address for the given memory area. The binary loader will call this address just after the memory area is loaded into memory, before continuing loading the rest of the file. </descrip> <tscreen><verb> FORMATS { atari: runad = _start; } </verb></tscreen> <sect1>The FEATURES section<label id="FEATURES"><p> In addition to the <tt/MEMORY/ and <tt/SEGMENTS/ sections described above, the linker has features that may be enabled by an additional section labeled <tt/FEATURES/. <sect2>The CONDES feature<p> <tt/CONDES/ is used to tell the linker to emit module constructor/destructor tables. <tscreen><verb> FEATURES { CONDES: segment = RODATA, type = constructor, label = __CONSTRUCTOR_TABLE__, count = __CONSTRUCTOR_COUNT__; } </verb></tscreen> The <tt/CONDES/ feature has several attributes: <descrip> <tag><tt>segment</tt></tag> This attribute tells the linker into which segment the table should be placed. If the segment does not exist, it is created. <tag><tt>type</tt></tag> Describes the type of the routines to place in the table. Type may be one of the predefined types <tt/constructor/, <tt/destructor/, <tt/interruptor/, or a numeric value between 0 and 6. <tag><tt>label</tt></tag> This specifies the label to use for the table. The label points to the start of the table in memory and may be used from within user-written code. <tag><tt>count</tt></tag> This is an optional attribute. If specified, an additional symbol is defined by the linker using the given name. The value of this symbol is the number of entries (<em/not/ bytes) in the table. While this attribute is optional, it is often useful to define it. <tag><tt>order</tt></tag> An optional attribute that takes one of the keywords <tt/increasing/ or <tt/decreasing/ as an argument. Specifies the sorting order of the entries within the table. The default is <tt/increasing/, which means that the entries are sorted with increasing priority (the first entry has the lowest priority). "Priority" is the priority specified when declaring a symbol as <tt/.CONDES/ with the assembler, higher values mean higher priority. You may change this behaviour by specifying <tt/decreasing/ as the argument, the order of entries is reversed in this case. Please note that the order of entries with equal priority is undefined. <tag><tt>import</tt></tag> This attribute defines a valid symbol name, that is added as an import to the modules defining a constructor/destructor of the given type. This can be used to force linkage of a module if this module exports the requested symbol. </descrip> Without specifying the <tt/CONDES/ feature, the linker will not create any tables, even if there are <tt/condes/ entries in the object files. For more information see the <tt/.CONDES/ command in the <url url="ca65.html" name="ca65 manual">. <sect2>The STARTADDRESS feature<p> <tt/STARTADDRESS/ is used to set the default value for the start address, which can be referenced by the <tt/%S/ symbol. The builtin default for the linker is $200. <tscreen><verb> FEATURES { # Default start address is $1000 STARTADDRESS: default = $1000; } </verb></tscreen> Please note that order is important: The default start address must be defined <em/before/ the <tt/%S/ symbol is used in the config file. This does usually mean, that the <tt/FEATURES/ section has to go to the top of the config file. <sect1>The SYMBOLS section<label id="SYMBOLS"><p> The configuration file may also be used to define symbols used in the link stage or to force symbols imports. This is done in the SYMBOLS section. The symbol name is followed by a colon and symbol attributes. The following symbol attributes are supported: <descrip> <tag><tt>addrsize</tt></tag> The <tt/addrsize/ attribute specifies the address size of the symbol and may be one of <itemize> <item><tt/zp/, <tt/zeropage/ or <tt/direct/ <item><tt/abs/, <tt/absolute/ or <tt/near/ <item><tt/far/ <item><tt/long/ or <tt/dword/. </itemize> Without this attribute, the default address size is <tt/abs/. <tag><tt>type</tt></tag> This attribute is mandatory. Its value is one of <tt/export/, <tt/import/ or <tt/weak/. <tt/export/ means that the symbol is defined and exported from the linker config. <tt/import/ means that an import is generated for this symbol, eventually forcing a module that exports this symbol to be included in the output. <tt/weak/ is similar as <tt/export/. However, the symbol is only defined if it is not defined elsewhere. <tag><tt>value</tt></tag> This must only be given for symbols of type <tt/export/ or <tt/weak/. It defines the value of the symbol and may be an expression. </descrip> The following example defines the stack size for an application, but allows the programmer to override the value by specifying <tt/--define __STACKSIZE__=xxx/ on the command line. <tscreen><verb> SYMBOLS { # Define the stack size for the application __STACKSIZE__: type = weak, value = $800; } </verb></tscreen> <sect>Special segments<p> The builtin config files do contain segments that have a special meaning for the compiler and the libraries that come with it. If you replace the builtin config files, you will need the following information. <sect1>ONCE<p> The ONCE segment is used for initialization code run only once before execution reaches main() - provided that the program runs in RAM. You may for example add the ONCE segment to the heap in really memory constrained systems. <sect1>LOWCODE<p> For the LOWCODE segment, it is guaranteed that it won't be banked out, so it is reachable at any time by interrupt handlers or similar. <sect1>STARTUP<p> This segment contains the startup code which initializes the C software stack and the libraries. It is placed in its own segment because it needs to be loaded at the lowest possible program address on several platforms. <sect1>ZPSAVE<p> The ZPSAVE segment contains the original values of the zeropage locations used by the ZEROPAGE segment. It is placed in its own segment because it must not be initialized. <sect>Copyright<p> ld65 (and all cc65 binutils) are (C) Copyright 1998-2005 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> ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/library.sgml��������������������������������������������������������������������������0000664�0000000�0000000�00000017605�13473601511�0015313�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>cc65 Library Overview <author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> <abstract> An overview over the runtime and C libraries that come with the cc65 compiler, including a discussion of the differences to the ISO standard. </abstract> <!-- Table of contents --> <toc> <!-- Begin the document --> <sect>Overview<p> This file contains a short overview of the libraries available for the cc65 C compiler. Please have a look at the <url url="funcref.html" name="function reference"> for a list function by function. Since the function reference is not complete (I'm working on that) it may happen that you don't find a specific function. In this case, have a look into the header files. All functions, that are not defined by the ISO C standard have a short comment in the headers, explaining their use. <sect>ISO C compatible library<p> The C library contains a large subset of the ISO C library. Functions are usually missing in areas, where there is no support on typical 6502 systems. Wide character sets are an example for this. I will not go into detail about the ISO functions. If a function is not mentioned here explicitly, expect it to be available and to behave as defined in the C standard. Functions that are <em/not/ available: <itemize> <item><tt>tmpfile/tmpnam</tt> <p> <item><tt>system</tt> (cc65 alternative <tt>exec</tt>) <p> <item>All functions that handle floating point numbers in some manner. <p> <item>The <tt/ldiv/ function (cc65 is currently not able to return structs with a size not equal to 1, 2 or 4 bytes by value). <p> <item>All functions handling wide character strings. <p> <item>Signals and all related functions (having <tt/SIGSEGV/ would be cool:-) <p> <item><tt>setbuf/setvbuf</tt> </itemize> Functions not available on all supported systems: <itemize> <item><tt>fopen/fread/fwrite/fclose/fputs/fgets/fscanf</tt>: The functions are built on open/read/write/close. These latter functions are not available on all systems. <p> <item><tt>ftell/fseek/fgetpos/fsetpos</tt>: Support depends on the capabilities of the target machine. <p> <item><tt>rename/remove/rewind</tt>: Support depends on the capabilities of the target machine. <p> <item><tt>time</tt>: Since many of the supported systems do not have a real time clock, which means that the <tt/time/ function is not available. Please note that the other functions from <tt/time.h/ <em/are/ available. </itemize> Functions that are limited in any way: <itemize> <item><tt>strcspn/strpbrk/strspn</tt>: These functions have a length limitation of 256 for the second string argument. Since this string gives a character set, and there are only 256 distinct characters, this shouldn't be a problem. <p> <item><tt>getenv</tt>: Since there is no such thing as an environment on all supported systems, the <tt/getenv/ function will always return a <tt/NULL/ pointer. <p> <item><tt>locale</tt>: There is no other locale than the "C" locale. The native locale is identical to the "C" locale. </itemize> In addition to these limitations, some more functions are limited if inlined versions are requested by using -Os: <itemize> <item>The <tt/strlen/ function only works for strings with a maximum length of 255 characters. <p> <item>The <tt/isxxx/ character classification functions from <tt/<ctype.h>/ will give unpredictable results if the argument is not in character range (0..255). This limitation may be removed by #undef'ing the function name (when using <tt/-Os/, the functions are actually macros that expand to inline assembler code, but the real functions are still available if the macro definition is removed). </itemize> <sect>CPU specific stuff - 6502.h<p> The header file 6502.h contains some functions that make only sense with the 6502 CPU. Examples are macros to insert more or less useful instructions into your C code, or a function to call arbitrary machine language subroutines, passing registers in and out. <sect>Target specific stuff<p> For each supported system there's a header file that contains calls or defines specific for this system. So, when programming for the C64, include c64.h, for the C128, include c128.h and so on. To make the task for the Commodore systems easier, there is also a header file named cbm.h that will define stuff common for all CBM systems, and include the header file for the specific target system. The header files contain <itemize> <item>Defines for special keys (like function keys) <item>Defines for special characters (like the graphics characters) <item>Variables with a fixed address in memory that may be used to access special hardware. For the C64 and C128 there is a variable struct named <tt/SID/. Writing to the fields of this struct will write to the SID device instead. Using these variables will make your program more readable and more portable. Don't fear ineffective code when using these variables, the compiler will translate reads and writes to these structs into direct memory accesses. <item>Other routines that make only sense for a specific system. One example are routines to write memory locations in the system bank for the CBM PET-II family. </itemize> <sect>Direct console I/O - <tt/conio.h/<p> The <tt/conio.h/ header file contains a large set of functions that do screen and keyboard I/O. The functions will write directly to the screen or poll the keyboard directly with no more help from the operating system than needed. This has some disadvantages, but on the other side it's fast and reasonably portable. conio implementations exist for the following targets: <itemize> <item>apple2 <item>apple2enh <item>atari <item>atari5200 <item>atarixl <item>atmos <item>c16 (works also for the c116 with up to 32K memory) <item>c64 <item>c128 <item>plus4 (or expanded c16/c116) <item>cbm510 (40 column video) <item>cbm610 (all CBM series-II computers with 80 column video) <item>creativision <item>gamate <item>geos-apple <item>geos-cbm <item>nes <item>osic1p <item>pce <item>pet (all CBM PET systems except the 2001) <item>telestrat <item>vic20 </itemize> The conio.h header file does also include the system specific header files which define constants for special characters and keys. <sect>Using the joystick - <tt/joystick.h/<p> For systems that have a joystick, <tt/joystick.h/ will define a subroutine to read the current value, including constants to evaluate the result of this function. <sect>Using a mouse - <tt/mouse.h/<p> Some target machines support a mouse. Mouse support is currently available for the following targets: <itemize> <item>apple2 <item>apple2enh <item>atari <item>atarixl <item>c64 <item>c128 <item>cbm510 </itemize> The available functions are declared in <tt/mouse.h/. <sect>Copyright<p> This C runtime library implementation for the cc65 compiler is (C) Copyright 1998-2002 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> ���������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/lynx.sgml�����������������������������������������������������������������������������0000664�0000000�0000000�00000024546�13473601511�0014643�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>Atari Lynx specific information for cc65 <author> <url url="mailto:karri@sipo.fi" name="Karri Kaksonen">,<newline> <url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> <abstract> An overview over the Atari Lynx runtime system as it is implemented for the cc65 C compiler. </abstract> <!-- Table of contents --> <toc> <!-- Begin the document --> <sect>Overview<p> This file contains an overview of the Atari Lynx runtime system as it comes with the cc65 C compiler. It describes the memory layout, Lynx specific header files, available drivers, and any pitfalls specific to that platform. Please note that Lynx 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>Building your first Hello World application<p> Here is a small traditional Hello World program for the Atari Lynx. <tscreen><verb> #include <lynx.h> #include <tgi.h> #include <6502.h> void main(void) { tgi_install(tgi_static_stddrv); tgi_init(); CLI(); while (tgi_busy()) ; tgi_clear(); tgi_setcolor(COLOR_GREEN); tgi_outtextxy(0, 0, "Hello World"); tgi_updatedisplay(); while (1) ; } </verb></tscreen> The lynx.h contains all kind of system dependent things. The tgi.h contains the graphics driver functions. The 6502.h is needed for executing the CLI() command. As the Atari Lynx does not have ASCII characters available you need to use the Tiny Graphics Interface library for producing letters on the screen. The cc65 compiler suite has a graphics library called "Tiny Graphics Interface". This interface has some relocatable code. In order to use this in your own program you need to load it at run time. Unfortunately the Lynx does not have a disk drive from where to load it. Therefore you must already load it at compile time. The easiest way is to automatically link it in statically from the Lynx C library. <tscreen><verb> cl65 -t lynx -o game.lnx main.c </verb></tscreen> This will create a bootable cart image called game.lnx <sect>Binary format<p> The standard binary output format generated by the linker for the Lynx target is a cart image. By specifying the config file lynx-bll.cfg the linker will generate BLL download compatible binary files. It is of course possible to change this behaviour by using a modified startup file and linker config. The bootloader used in the cc65 lynx library uses a very minimal bootloader that does not check the cart or show a title screen. The advantage of this bootloader is that it allows creation of cart images to many common formats. Cart sizes <tscreen><verb> Block size Rom size Description 512 bytes 128k Standard old games like Warbirds 1024 bytes 256k Most common format for homebrew. Also newer games like Lemmings 2048 bytes 512k Largest games like EOTB </verb></tscreen> <sect>Memory layout<p> cc65 generated programs with the default setup run with the I/O area and the kernal enabled, which gives a usable memory range of $200 - $C037. Special locations: <tscreen><verb> 0000 - 00FF Zero page 0100 - 01FF Machine stack A058 - C037 Collision buffer C038 - E017 Screen buffer 1 E018 - FFF7 Screen buffer 0 FFF8 - FFFF Hardware vectors </verb></tscreen> <descrip> <tag/Text screen/ No conio support is currently available for the Lynx. <tag/Keyboard/ The Lynx "flabode" keys, Opt 1, Pause and Opt 2 are implemented using the conio interface. The only characters the keyboard is able to produce are 'R' for Restart (Opt 1 + Pause), 'F' for flip (Opt 2 + Pause), 'P' for pause, '1' for Opt 1, '2' for Opt 2, '3' for Opt 1 + Opt 2 and '?' for all keys down at the same time. <tag/Stack/ The C runtime stack is located at $C037 (or $A057 if collision detection is enabled) and growing downwards. <tag/Heap/ The C heap is located at the end of the program and grows towards the C runtime stack. <tag/Screen/ The collision detection screen is at $A058 if it is enabled. The double buffered screens are at $C038 and $E018. </descrip><p> <sect>Platform specific header files<p> Programs containing Lynx specific code may use the <tt/lynx.h/ header file. <sect1>Lynx specific functions<p> <itemize> <item>lynx_eeprom_erase <item>lynx_eeprom_read <item>lynx_eeprom_write <item>lynx_eeread <item>lynx_eewrite <item>lynx_exec <item>lynx_load </itemize> <sect1>Hardware access<p> The following pseudo variables declared in the <tt/lynx.h/ header file do allow access to hardware located in the address space. Some variables are structures, accessing the struct fields will access the chip registers. <descrip> <tag><tt/MIKEY/</tag> The <tt/MIKEY/ structure allows access to MIKEY chip. See the <tt/_mikey.h/ header file located in the include directory for the declaration of the structure. <tag><tt/SUZY/</tag> The <tt/SUZY/ structure allows access to SUZY chip. See the <tt/_suzy.h/ header file located in the include directory for the declaration of the structure. </descrip><p> <sect>Loadable drivers<p> The names in the parentheses denote the symbols to be used for static linking of the drivers. <sect1>Graphics drivers<p> <descrip> <tag><tt/lynx-160-102-16.tgi (lynx_160_102_16_tgi)/</tag> A TGI driver for the standard graphics mode (160×102 in 16 colors). The TGI driver is implemented as an interrupt driven dual buffering device. To use it as a single-buffer device set draw page and view page to the same value 0 or 1; The TGI driver has a few Lynx-specific extensions. Calling tgi_sprite(spr) or tgi_ioctl(0, spr) will display a standard Lynx sprite on screen. Calling tgi_flip() or tgi_ioctl(1, 0) will do a flip screen. Calling tgi_setbgcolor(bgcolor) or tgi_ioctl(2, bgindex) will set the text background color to the index defined by bgindex. If bgindex is 0 then the background color is transparent. To set the framerate of the display hardware call tgi_setframerate(rate) or tgi_ioctl(3, rate). The supported framerates are 50, 60 and 75 frames per second. Actually there is no real reason to use anything else than 75 frames per second. To check if the drawing engine is busy with the previous swap you can call tgi_busy or tgi_ioctl(4, 0). It returns 0 if idle and 1 if busy To update displays you can call tgi_updatedisplay() or tgi_ioctl(4, 1) it will wait for the next VBL interrupt and set the draw buffer to the view buffer. The draw buffer is also changed to (drawbuffer xor 1). You can also enable or disable collision detection by a call to tgi_setcollisiondetection(active) or tgi_ioctl(5, active). The collision result is located before the sprite structure by default in this driver. In order to reserve memory for the collision detection buffer you need to specify lynx-coll.cfg as the configuration file to the linker. </descrip><p> <sect1>Extended memory drivers<p> No extended memory drivers are currently available for the Lynx. <sect1>Joystick drivers<p> <descrip> <tag><tt/lynx-stdjoy.joy (lynx_stdjoy_joy)/</tag> A joystick driver for the standard buttons. </descrip><p> <sect1>Mouse drivers<p> No mouse drivers are currently available for the Lynx. <sect1>RS232 device drivers<p> <descrip> <tag><tt/lynx-comlynx.ser (lynx_comlynx_ser)/</tag> A serial driver for the ComLynx port. The ComLynx port has Tx and Rx wired together. Every byte is sent to all connected Lynxes. Only one Lynx can send at a time. There is no protocol created for communication. You are on your own. If the Lynx returns framing error then it is likely that another Lynx is sending data at the same time. The Lynx can also send a break and receive a break. The Lynx break is recognized if the bit is down for 24 bit cycles or more. To send a break you just set the break bit. The length of the break depends on how long this bit is down. The driver supports the baudrates: <itemize> <item>62500 <item>31250 <item>9600 <item>7200 <item>4800 <item>3600 <item>2400 <item>1800 <item>1200 <item>600 <item>300 <item>150 <item>134.5 <item>110 <item>75 </itemize> The parity bit supports MARK and SPACE. It also supports EVEN and ODD parity but the parity bit is included in the calculation. Most of us don't want it this way. But there is nothing we can do about it. The Lynx hardware will always check parity on incoming traffic. Currently the driver cannot receive data from standard PC's due to this parity bug. For working with Lynx to Lynx communication use EVEN parity. To send data to standard PC's use MARK or SPACE as parity setting. There is always only one stop bit. And the data length is always 8 bits. We have no handshaking available. Even software handshake is impossible as ComLynx has only one wire for the data. Both transmit and receive are interrupt driven. </descrip><p> <sect>Limitations<p> <sect>Cart access<p> At this point in time there is no support for the cart filesystem yet. I have a <tt/lynx-cart-demo/ example project that uses an interrupt driven display, has support for the cart filesystem and an abcmusic sound module. At some point in time we may find a way to rewrite these to fit the way the cc65 drivers require. But for the time being you can create less portable applications using these Lynx specific modules in <tt/lynx-cart-demo/. <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> ����������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/nes.sgml������������������������������������������������������������������������������0000664�0000000�0000000�00000011272�13473601511�0014426�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>Nintendo Entertainment System specific information for cc65 <author> <url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline> <url url="mailto:polluks@sdf.lonestar.org" name="Stefan A. Haubenthal"> <abstract> An overview over the NES 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 NES runtime system as it comes with the cc65 C compiler. It describes the memory layout, NES specific header files, available drivers, and any pitfalls specific to that platform. Please note that NES 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 NES target is a machine language program with an INES cartridge header. It is of course possible to change this behaviour by using a modified startup file and linker config. <sect>Memory layout<p> cc65 generated programs with the default setup run with the I/O area and a CHR bank enabled, which gives a usable memory range of $8000 - $FFF3. All boot ROM entry points may be called directly without additional code. Special locations: <descrip> <tag/Text screen/ The text screen is located at VRAM $2000. <tag/Stack/ The C runtime stack is located at $7FFF and growing downwards. <tag/Heap/ The C heap is located at the end of the program and grows towards the C runtime stack. </descrip><p> <sect>Platform specific header files<p> Programs containing NES specific code may use the <tt/nes.h/ header file. <sect1>NES specific functions<p> <itemize> <item>waitvsync - wait until the start of the next frame</item> <item>get_tv</item> </itemize> <sect1>Hardware access<p> The following pseudo variables declared in the <tt/nes.inc/ include file do allow access to hardware located in the address space. <descrip> <tag><tt/PPU/</tag> The <tt/PPU/ defines allow access to the PPU chip. <tag><tt/APU/</tag> The <tt/APU/ defines allow access to the APU chip. </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> <descrip> <tag><tt/nes-64-56-2.tgi (nes_64_56_2)/</tag> This driver features a resolution of 64×56 with 2 colors using the CHR bank. </descrip><p> <sect1>Extended memory drivers<p> No extended memory drivers are currently available for the NES. <sect1>Joystick drivers<p> <descrip> <tag><tt/nes-stdjoy.joy (nes_stdjoy)/</tag> A joystick driver for the standard four buttons joypad is available. </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> No mouse drivers are currently available for the NES. <sect1>RS232 device drivers<p> No serial drivers are currently available for the NES. <sect>Limitations<p> <sect1>Disk I/O<p> The existing library for the NES 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>fclose <item>fopen <item>fread <item>fprintf <item>fputc <item>fscanf <item>fwrite <item>... </itemize> <sect>Other hints<p> <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> ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/od65.sgml�����������������������������������������������������������������������������0000664�0000000�0000000�00000014246�13473601511�0014422�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>od65 Users Guide <author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> <abstract> od65 is the object file dump utility. It is able to output most parts of <htmlurl url="ca65.html" name="ca65-generated"> object files in readable form. </abstract> <!-- Table of contents --> <toc> <!-- Begin the document --> <sect>Overview<p> od65 is an object file dump utility. It is able to output most parts of <htmlurl url="ca65.html" name="ca65-generated"> object files in readable form. Since the contents and format of the object files are not documented elsewhere and may change at any time, this tool is a portable way to look at the contents. Apart from curiosity, most people don't need to use this tool. <sect>Usage<p> The od65 utility dumps contents of one or more ca65 generated object file to standard output. It has no cross-version compatibility, so you have to use a version that matches the version of ca65 used to create the object files. <sect1>Command line option overview<p> The program may be called as follows: <tscreen><verb> --------------------------------------------------------------------------- Usage: od65 [options] file [options] [file] Short options: -h Help (this text) -H Dump the object file header -S Dump segments sizes -V Print the version number and exit Long options: --dump-all Dump all object file information --dump-dbgsyms Dump debug symbols --dump-exports Dump exported symbols --dump-files Dump the source files --dump-header Dump the object file header --dump-imports Dump imported symbols --dump-lineinfo Dump line information --dump-options Dump object file options --dump-segments Dump the segments in the file --dump-segsize Dump segments sizes --help Help (this text) --version Print the version number and exit --------------------------------------------------------------------------- </verb></tscreen> <sect1>Command line options in detail<label id="cmdline-opt-detail"><p> Here is a description of all the command line options: <descrip> <tag><tt>--dump-all</tt></tag> This will output all information, od65 is able to process. The option is a shortcut for specifying all the other <tt/--dump/ options. <tag><tt>--dump-dbgsyms</tt></tag> Dump all debug symbols contained in the object file. <tag><tt>--dump-exports</tt></tag> Dump all exported symbols contained in the object file. <tag><tt>--dump-files</tt></tag> Dump the file table contained in the object file. <tag><tt>-H, --dump-header</tt></tag> Dump the object file header. <tag><tt>--dump-imports</tt></tag> Dump the list of imported symbols contained in the object file. <tag><tt>--dump-lineinfo</tt></tag> Dump the line info contained in the object file. <tag><tt>--dump-segments</tt></tag> Dump the list of segments contained in the object file. <tag><tt>--dump-scopes</tt></tag> Dump the scope (lexical level) information contained in the object file. <tag><tt>-S, --dump-segsize</tt></tag> Dump the sizes of all segments contained in the object file. This option is quite useful to determine the effect of measures that increase or decrease code size. <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 compiler. 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 or more object files per invocation and write the contents in readable format to standard output. Please note that you need to specify any of the <tt/--dump/ options listed <ref id="cmdline-opt-detail" name="above">, otherwise no useful output will be generated. Example output for the command <tscreen><verb> od65 --dump-header --dump-files t.o </verb></tscreen> <tscreen><verb> t.o: Header: Magic: 0x616E7A55 Version: 12 Flags: 0x0001 (OBJ_FLAGS_DBGINFO) Options: Offset: 88 Size: 9 Files: Offset: 97 Size: 10 Segments: Offset: 107 Size: 101 Imports: Offset: 208 Size: 1 Exports: Offset: 209 Size: 1 Debug symbols: Offset: 210 Size: 55 Line infos: Offset: 265 Size: 1 String pool: Offset: 266 Size: 80 Files: Count: 1 Index: 0 Name: "t.s" Size: 402 Modification time: 1280498435 (Fri Jul 30 16:00:35 2010) </verb></tscreen> <sect>Copyright<p> od65 is (C) Copyright 2000-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> ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/osi.sgml������������������������������������������������������������������������������0000664�0000000�0000000�00000017447�13473601511�0014445�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>Ohio Scientific-specific information for cc65 <author> <url url="mailto:stephan.muehlstrasser@web.de" name="Stephan Mühlstrasser">,<newline> <url url="mailto:greg.king5@verizon.net" name="Greg King"> <abstract> An overview over the Ohio Scientific runtime system as it is implemented for the cc65 C compiler. </abstract> <!-- Table of contents --> <toc> <!-- Begin the document --> <sect>Overview<p> This file contains an overview of the Ohio Scientific runtime system as it comes with the cc65 C compiler. It describes the memory layout, Ohio Scientific-specific header files, and any pitfalls specific to that platform. Please note that Ohio Scientific-specific functions are just mentioned here, they are described in detail in the separate <url url="funcref.html" name="function reference">. Even functions marked as "platform dependent" may be available on more than one platform. Please see the function reference for more information. <sect>Targets<p> Currently the target "osic1p" is implemented. This works for the Ohio Scientific Challenger 1P machine and for the Briel Superboard /// replica. <sect>Program file formats<p> <descrip> <tag/Binary, then text/ The standard binary output format generated by the linker for the osic1p target is a pure machine language program. For uploading into a real machine over its serial port or into an emulator, that program must be converted into a text file that can be understood by the 65V PROM monitor. For that purpose, the <bf/srec_cat/ program from <url url="http://srecord.sourceforge.net/" name="the SRecord tool collection"> can be used. Care must be taken that the <tt/-offset/ and <tt/-execution-start-address/ options for the <bf/srec_cat/ program correspond to the start address of the executable. Example for converting an executable "hello" file that was built for the default start address $0200 to an uploadable file "hello.c1p": <tscreen><verb> srec_cat hello -bin -of 0x200 -o hello.c1p -os -esa=0x200 </verb></tscreen> <tag/Hybrid/ The linker can create an alternate format that contains two parts: <enum> <item>A text header that is understood by the 65V PROM monitor. It is a boot loader that reads the second part. <item>The default binary code that is described above. </enum> You can make the alternate format by adding the option <tt/-u __BOOT__/ to <tt/cl65/'s or <tt/ld65/'s command lines. This format doesn't need to be converted. It is smaller than the text-only format. But, it cannot be loaded by <url url="http://www.pcjs.org/docs/c1pjs/" name="C1Pjs">; you must use the SRecord-produced text-only format with that emulator. (However, if you know that you never will use C1Pjs, then you can edit the <tt>cfg/osic1p*.cfg</tt> files; uncomment the lines that import <tt/__BOOT__/. Then, you won't need to use <tt/-u __BOOT__/ on your command lines.) </descrip> <sect>Memory layout<p> By default programs compiled for the osic1p target are configured for 32 kB RAM. The RAM size can be configured via the symbol <tt/__HIMEM__/. Special locations: <descrip> <tag/Program start address/ The default start address is $0200. The start address is configurable via the linker option <tt/--start-addr/. <tag/Stack/ The C runtime stack is located at the top of RAM and growing downwards. The size is configurable via the symbol <tt/__STACKSIZE__/. The default stack size is $0400. <tag/Heap/ The C heap is located at the end of the program and grows towards the C runtime stack. <tag/Video RAM/ The 1 kB video RAM is located at $D000. On the monitor, only a subset of the available video RAM is visible. The address of the upper left corner of the visible area is $D085 and corresponds to conio cursor position (0, 0). </descrip><p> Example for building a program with start address $0300, stack size $0200 and RAM size $2000: <tscreen><verb> cl65 --start-addr 0x300 -Wl -D,__HIMEM__=$2000,-D,__STACKSIZE__=$0200 -t osic1p hello.c </verb></tscreen> <sect>Linker configurations<p> The ld65 linker comes with a default config file "osic1p.cfg" for the Ohio Scientific Challenger 1P, which is implicitly used via <tt/-t osic1p/. The osic1p package comes with additional secondary linker config files, which are used via <tt/-t osic1p -C <configfile>/. <sect1>Default config file (<tt/osic1p.cfg/)<p> The default configuration is tailored to C programs. <sect1><tt/osic1p-asm.cfg/<p> This configuration is made for assembler programmers who don't need a special setup. To use this config file, assemble with <tt/-t osic1p/ and link with <tt/-C osic1p-asm.cfg/. The former will make sure that correct runtime library is used, while the latter supplies the actual config. When using <tt/cl65/, use both command line options. Sample command lines for <tt/cl65/: <tscreen><verb> cl65 -t osic1p -C osic1p-asm.cfg -o program source.s cl65 -t osic1p -C osic1p-asm.cfg -u __BOOT__ -o program.lod source.s </verb></tscreen> <sect>Platform-specific header files<p> Programs containing Ohio Scientific-specific code may use the <tt/osic1p.h/ header file. <sect1>Ohio Scientific-specific functions<p> There are currently no special Ohio Scientific functions. <sect1>Hardware access<p> There is no specific support for direct hardware access. <sect>Loadable drivers<p> There are no loadable drivers available. <sect>Support for different screen layouts<p> By default the conio library uses a 24 columns by 24 lines screen layout for the Challenger 1P, like under BASIC. In addition to that there is support for other screen layouts with extra modules. There is a module <tt/screen-c1p-24x24.o/ in the OSI-specific cc65 runtime library that contains all conio functions that depend on the screen layout. No further configuration is needed for using the default screen layout of the Challenger 1P. For other screen layouts additional versions of the screen module are available. The linker finds these modules without further configuration if they are specified on the compiler or linker command line. The extra module then overrides the default module. Sample <tt/cl65/ command line to override the default screen module with the module <tt/osic1p-screen-s3-32x28.o/: <tscreen><verb> cl65 -o hello -t osic1p osic1p-screen-s3-32x28.o hello.c </verb></tscreen> Currently the following extra screen configuration modules are implemented: <itemize> <item><tt>osic1p-screen-s3-32x28.o</tt>: 32 columns by 28 lines mode for Briel Superboard ///</item> </itemize> <sect>Limitations<p> <sect1>stdio implementation<p> There is no support for stdio at the moment. <sect>Other hints<p> <sect1>Passing arguments to the program<p> There is currently no support for passing arguments to a program. <sect1>Program return code<p> The program return code currently has no effect. When the main() function finishes, the boot prompt is shown again. <sect>License<p> This software is provided 'as-is', without any expressed or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: <enum> <item> The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. <item> Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. <item> This notice may not be removed or altered from any source distribution. </enum> </article> �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/pce.sgml������������������������������������������������������������������������������0000664�0000000�0000000�00000016001�13473601511�0014403�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>PC-Engine (TurboGrafx 16) System-specific information for cc65 <author><url url="mailto:groepaz@gmx.net" name="Groepaz/Hitmen">,<newline> <url url="mailto:greg.king5@verizon.net" name="Greg King"> <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" might be available on more than one platform. Please see the function reference for more information. <sect>Binary format<p> The binary output file generated by the linker, for the PCE target, is an image, with no header, that has 8K bytes in the wrong place. That file must be post-processed; the 8K at the end must be moved to the front of the image. On POSIX systems, the <tt/dd/ command and the shell give a convenient way to do it. Here is an example of their use: <tscreen><verb> dd if=conio.bin bs=8K skip=3 > conio.pce dd if=conio.bin bs=8K count=3 >> conio.pce </verb></tscreen> The first command grabs the last 8K of a 32K file, and writes it as the first part of a new file. The second command reads all but the last part of the old file, and appends it to the new file. <tscreen><verb> +--------+--------+--------+--------+ | Bank 1 | Bank 2 | Bank 3 | Bank 0 | <-- "conio.bin" +--------+--------+--------+--------+ +--------+--------+--------+--------+ | Bank 0 | Bank 1 | Bank 2 | Bank 3 | <-- "conio.pce" +--------+--------+--------+--------+ </verb></tscreen> <em/Note/: That <tt/.pce/ file shows the format of the ROM cartridge that is plugged into a PC-Engine. But, that <tt/.bin/ file shows what programs actually see when they execute the code in that cartridge. <sect>Memory layout<p> cc65-generated programs with the default setup run with the memory map that was used by many PC-Engine games: <itemize> <item>The first 8K bytes is the I/O area. <item>The second 8K bytes is RAM, which holds <itemize> <item>the redirected zero-page and the redirected hardware stack page, <item>and 7680 bytes of general memory ($2200 - $3FFF). </itemize> <item>The last 8K bytes in the usual 64K-byte range is the ROM that holds the program. </itemize> Special locations: <descrip> <tag/Text screen and Font/ The text screen is located at Video RAM (VRAM) address $0000; the Font is located at VRAM address $2000. <tag/Stack/ The C run-time stack is located in system RAM at $3FFF; and, grows downwards. <tag/Data and BSS/ The Data (initialized variables) and BSS (uninitialized variables) sections are placed one after the other into system RAM at $2200. <tag/Heap/ The C heap is located after the end of the BSS section; and, extends up to the C run-time stack. <tag/Code/ In an 8K ROM cartridge, code and read-only data are located between $E000 and $FFF5 in the System bank. In a 16K cartridge, code and read-only data are located between $C000 and $FFF5. In a 32K cartridge, code and read-only data are located between $8000 and $FFF5. </descrip> <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>waitvsync</item> <item>get_tv (since all PCE systems are NTSC, this always returns TV_NTSC)</item> </itemize> <sect1>Hardware access<p> The following constants, defined in the <tt/pce.inc/ include file, do allow access to hardware that is located in the address space. <descrip> <tag><tt/PSG/</tag> The <tt/PSG/ defines allow access to the PSG (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).<newline> 32K of 16-bit words of Video RAM can be accessed only through this chip. </descrip> <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-button joypad is available. Note that the Japanese 6-button pad currently is not supported. </descrip> <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> <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, that 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><url url="https://mednafen.github.io/" name= "Mednafen"> is a good emulator to use for the PC-Engine. </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&platform=4"> <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 marked plainly 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> �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/pet.sgml������������������������������������������������������������������������������0000664�0000000�0000000�00000015715�13473601511�0014437�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>Commodore PET-specific information for cc65 <author> <url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline> <url url="mailto:polluks@sdf.lonestar.org" name="Stefan A. Haubenthal"> <abstract> An overview over the PET 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 PET runtime system as it comes with the cc65 C compiler. It describes the memory layout, PET-specific header files, available drivers, and any pitfalls specific to that platform. Please note that PET-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 PET target is a machine language program with a one line BASIC stub, which calls the machine language part via SYS. This means that a program can be loaded as BASIC program and started with RUN. 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 the kernal and BASIC ROM enabled, which gives a usable memory range of $0400 - $7FFF (32KB machine). All ROM entry points may be called directly without additional code. Special locations: <descrip> <tag/Text screen/ The text screen is located at $8000. <tag/Stack/ The C runtime stack is located at $7FFF and growing downwards. <tag/Heap/ The C heap is located at the end of the program and grows towards the C runtime stack. </descrip><p> <sect>Platform-specific header files<p> Programs containing PET-specific code may use the <tt/pet.h/ or <tt/cbm.h/ header files. Using the later may be an option when writing code for more than one CBM platform, since it includes <tt/pet.h/ and declares several functions common to all CBM platforms. <sect1>PET-specific functions<p> There are currently no special PET functions. <sect1>CBM-specific functions<p> Some functions are available for all (or at least most) of the Commodore machines. See the <url url="funcref.html" name="function reference"> for declaration and usage. <itemize> <item>cbm_close <item>cbm_closedir <item>cbm_k_setlfs <item>cbm_k_setnam <item>cbm_k_load <item>cbm_k_save <item>cbm_k_open <item>cbm_k_close <item>cbm_k_readst <item>cbm_k_chkin <item>cbm_k_ckout <item>cbm_k_basin <item>cbm_k_bsout <item>cbm_k_clrch <item>cbm_load <item>cbm_open <item>cbm_opendir <item>cbm_read <item>cbm_readdir <item>cbm_save <item>cbm_write <item>get_tv </itemize> <sect1>Hardware access<p> The following pseudo variables declared in the <tt/pet.h/ header file do allow access to hardware located in the address space. Some variables are structures, accessing the struct fields will access the chip registers. <descrip> <tag><tt/PIA1, PIA2/</tag> Access to the two PIA (peripheral interface adapter) chips is available via the <tt/PIA1/ and <tt/PIA2/ variables. The structure behind these variables is explained in <tt/_pia.h/. <tag><tt/VIA/</tag> The <tt/VIA/ structure allows access to the VIA (versatile interface adapter). See the <tt/_6522.h/ header file located in the include directory for the declaration of the structure. </descrip><p> <sect>Loadable drivers<p> The names in the parentheses denote the symbols to be used for static linking of the drivers. <sect1>Graphics drivers<p> No graphics drivers are currently available for the PET. <sect1>Extended memory drivers<p> No extended memory drivers are currently available for the PET. <sect1>Joystick drivers<p> The default drivers, <tt/joy_stddrv (joy_static_stddrv)/, point to <tt/pet-stdjoy.joy (pet_stdjoy_joy)/. <descrip> <tag><tt/pet-ptvjoy.joy (pet_ptvjoy_joy)/</tag> Driver for the Protovision 4-player adapter contributed by Groepaz. See <url url="http://www.protovision-online.de/hardw/4_player.php?language=en" name="Protovision shop"> for prices and building instructions. Up to two joysticks are supported. <tag><tt/pet-stdjoy.joy (pet_stdjoy_joy)/</tag> Driver for the standard PET userport joystick. </descrip><p> <sect1>Mouse drivers<p> No mouse drivers are currently available for the PET. <sect1>RS232 device drivers<p> No serial drivers are currently available for the PET. <sect>Limitations<p> <sect>Other hints<p> <sect1>Passing arguments to the program<p> Command-line arguments can be passed to <tt/main()/. Since that is not supported directly by BASIC, the following syntax was chosen: <tscreen><verb> RUN:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5 </verb></tscreen> <enum> <item>Arguments are separated by spaces. <item>Arguments may be quoted. <item>Leading and trailing spaces around an argument are ignored. Spaces within a quoted argument are allowed. <item>The first argument passed to <tt/main()/ is the program name. <item>A maximum number of 10 arguments (including the program name) are supported. </enum> <sect1>Program return code<p> The program return code (low byte) is passed back to BASIC by use of the <tt/ST/ variable. <sect1>Interrupts<p> The runtime for the PET uses routines marked as <tt/.INTERRUPTOR/ for interrupt handlers. Such routines must be written as simple machine language subroutines and will be called automatically by the interrupt handler code when they are linked into a program. See the discussion of the <tt/.CONDES/ feature in the <url url="ca65.html" name="assembler manual">. <sect1>Using extended memory<p> The extended memory at $9000 of the CBM 8x96 may be added to the heap by using the following code: <tscreen><verb> /* Check for the existence of RAM */ if (PEEK(0x9000) == POKE(0x9000, PEEK(0x9000)+1)) { /* Add it to the heap */ _heapadd ((void *) 0x9000, 0x2000); } </verb></tscreen> <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> ���������������������������������������������������cc65-2.18/doc/plus4.sgml����������������������������������������������������������������������������0000664�0000000�0000000�00000017435�13473601511�0014717�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>Commodore Plus/4 specific information for cc65 <author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> <abstract> An overview over the Plus/4 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 Plus/4 runtime system as it comes with the cc65 C compiler. It describes the memory layout, Plus/4 specific header files, available drivers, and any pitfalls specific to that platform. Please note that Plus/4 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. Since the Plus/4 and the Commodore 16/116 are almost identical (the latter are missing the 6551 ACIA and do only have 16KB of memory), the <url url="c16.html" name="C16 documentation"> is also worth a look. The difference between both cc65 targets is that the Plus/4 runtime uses banking to support full 64K RAM, while the C16 does not use banking and supports up to 32K RAM. Because banking is not needed, most C16 programs will be somewhat smaller than the same program compiled for the Plus/4. However, programs compiled for the C16 will always run on the Plus/4, while the reverse is not necessarily true. <sect>Binary format<p> The standard binary output format generated by the linker for the Plus/4 target is a machine language program with a one line BASIC stub, which calls the machine language part via SYS. This means that a program can be loaded as BASIC program and started with RUN. 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 kernal and basic banked out. This gives a usable memory range of $1000 - $FD00. Having the kernal and basic ROMs banked out means, that no ROM entry points may be called directly from user code. Special locations: <descrip> <tag/Text screen/ The text screen is located at $C00 (as in the standard setup). <tag/Color RAM/ The color RAM is located at $800 (standard location). <tag/Stack/ The C runtime stack is located at $FCFF and growing downwards. <tag/Heap/ The C heap is located at the end of the program and grows towards the C runtime stack. </descrip><p> <sect>Platform specific header files<p> Programs containing Plus/4 specific code may use the <tt/plus4.h/ or <tt/cbm.h/ header files. Using the later may be an option when writing code for more than one CBM platform, since it includes <tt/plus4.h/ and declares several functions common to all CBM platforms. Please note that most of the header file declarations from the <tt/plus4.h/ header file are shared between the C16 and Plus/4 configurations. For this reason, most of it is located in a common header file named <tt/cbm264.h/. <sect1>Plus/4 specific functions<p> There are currently no special Plus/4 functions. <sect1>CBM specific functions<p> Some functions are available for all (or at least most) of the Commodore machines. See the <url url="funcref.html" name="function reference"> for declaration and usage. <itemize> <item>cbm_close <item>cbm_closedir <item>cbm_k_setlfs <item>cbm_k_setnam <item>cbm_k_load <item>cbm_k_save <item>cbm_k_open <item>cbm_k_close <item>cbm_k_readst <item>cbm_k_chkin <item>cbm_k_ckout <item>cbm_k_basin <item>cbm_k_bsout <item>cbm_k_clrch <item>cbm_k_tksa <item>cbm_k_second <item>cbm_load <item>cbm_open <item>cbm_opendir <item>cbm_read <item>cbm_readdir <item>cbm_save <item>cbm_write <item>get_tv </itemize> <sect1>CBM specific CPU functions<p> Some CPU related functions are available for some of the Commodore machines. See the <url url="funcref.html" name="function reference"> for declaration and usage. <itemize> <item>fast <item>slow <item>isfast </itemize> <sect1>Hardware access<p> The following pseudo variables declared in the <tt/plus4.h/ header file do allow access to hardware located in the address space. Some variables are structures, accessing the struct fields will access the chip registers. <descrip> <tag><tt/TED/</tag> The <tt/TED/ structure allows access to the TED chip. See the <tt/_ted.h/ header file located in the include directory for the declaration of the structure. <tag><tt/COLOR_RAM/</tag> A character array that mirrors the color RAM of the Plus/4 at $0800. </descrip><p> <sect>Loadable drivers<p> The names in the parentheses denote the symbols to be used for static linking of the drivers. <sect1>Graphics drivers<p> No graphics drivers are currently available for the Plus/4. <sect1>Extended memory drivers<p> No extended memory drivers are currently available for the Plus/4. <sect1>Joystick drivers<p> <descrip> <tag><tt/plus4-stdjoy.joy (plus4_stdjoy_joy)/</tag> Supports up to two joysticks connected to the standard joysticks port of the Plus/4. </descrip><p> <sect1>Mouse drivers<p> No mouse drivers are currently available for the Plus/4. <sect1>RS232 device drivers<p> <descrip> <tag><tt/plus4-stdser.ser (plus4_stdser_ser)/</tag> Driver for the 6551 ACIA chip built into the Plus/4. Supports up to 19200 baud, hardware flow control (RTS/CTS) and interrupt driven receives. Note that because of the peculiarities of the 6551 chip transmits are not interrupt driven, and the transceiver blocks if the receiver asserts flow control because of a full buffer. You need an adapter to use the builtin port, since the output levels available at the user port don't follow the RS232 standard. </descrip><p> <sect>Limitations<p> <sect>Other hints<p> <sect1>Passing arguments to the program<p> Command line arguments can be passed to <tt/main()/. Since this is not supported by BASIC, the following syntax was chosen: <tscreen><verb> RUN:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5 </verb></tscreen> <enum> <item>Arguments are separated by spaces. <item>Arguments may be quoted. <item>Leading and trailing spaces around an argument are ignored. Spaces within a quoted argument are allowed. <item>The first argument passed to <tt/main/ is the program name. <item>A maximum number of 10 arguments (including the program name) are supported. </enum> <sect1>Program return code<p> The program return code (low byte) is passed back to BASIC by use of the <tt/ST/ variable. <sect1>Interrupts<p> The runtime for the Plus/4 uses routines marked as <tt/.INTERRUPTOR/ for interrupt handlers. Such routines must be written as simple machine language subroutines and will be called automatically by the interrupt handler code when they are linked into a program. See the discussion of the <tt/.CONDES/ feature in the <url url="ca65.html" name="assembler manual">. <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> �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/sim65.sgml����������������������������������������������������������������������������0000664�0000000�0000000�00000013715�13473601511�0014610�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <!-- -*- text-mode -*- --> <article> <title>sim65 Users Guide <author><url url="mailto:polluks@sdf.lonestar.org" name="Stefan A. Haubenthal">,<newline> <url url="mailto:bbbradsmith@users.noreply.github.com" name="Brad Smith"> <abstract> sim65 is a simulator for 6502 and 65C02 CPUs. It allows to test target independent code. </abstract> <!-- Table of contents --> <toc> <!-- Begin the document --> <sect>Overview<p> sim65 is used as part of the toolchain to test 6502 or 65C02 code. The binary to test should 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) -c Print amount of executed CPU cycles -v Increase verbosity -V Print the simulator version number -x <num> Exit simulator after <num> cycles Long options: --help Help (this text) --cycles Print amount of executed CPU cycles --verbose Increase verbosity --version Print the simulator version number </verb></tscreen> <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>-c, --cycles</tt></tag> Print the number of executed CPU cycles when the program terminates. The cycles for the final "<tt>jmp exit</tt>" are not included in this count. <tag><tt>-v, --verbose</tt></tag> Increase the simulator verbosity. <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>Creating a Test in C<p> For a C test compiled and linked with <tt/--target sim6502/ the command line arguments to <tt/sim65/ will be passed to <tt/main/, and the return value from <tt/main/ will become sim65's exit code. The <tt/exit/ function may also be used to terminate with an exit code. Exit codes are limited to 8 bits. The standard C library high level file input and output is functional, and can be used like a command line application in sim65. Lower level file input and output is provided by a set of built-in paravirtualization functions: <tscreen><verb> int open (const char* name, int flags, ...); int __fastcall__ close (int fd); int __fastcall__ read (int fd, void* buf, unsigned count); int __fastcall__ write (int fd, const void* buf, unsigned count); </verb></tscreen> These built-in functions can be used with <tt/STDIN_FILENO/, <tt/STDOUT_FILENO/ and <tt/STDERR_FILENO/ which are mapped to sim65's corresponding file descriptors. <sect>Creating a Test in Assembly<p> Assembly tests may similarly be assembled and linked with <tt/--target sim6502/ or <tt/--target sim65c02/, and the sim65 library provides an <tt/exit/ symbol that the program may <tt/JMP/ to terminate with the current A register value as an exit code. The binary file has a 12 byte header: <itemize> <item>5 byte <bf/signature/: <tt/$73, $69, $6D, $36, $35/ or <tt/'sim65'/ <item>1 byte <bf/version/: <tt/2/ <item>1 byte <bf/CPU type/: <tt/0/ = 6502, <tt/1/ = 65C02 <item>1 byte <bf/sp address/: the zero page address of the C parameter stack pointer <tt/sp/ used by the paravirtualization functions <item>1 word <bf/load address/: where to load the data from the file into memory (default: <tt/$0200/) <item>1 word <bf/reset address/: specifies where to begin execution after loading (default: <tt/$0200/) </itemize> Other internal details: <itemize> <item>The entire 64 kilobyte address space is writeable RAM. Aside from the loaded binary, the reset vector at <tt/$FFFC/ will be pre-loaded with the given <bf/reset address/. <item>The <tt/exit/ address is <tt/$FFF9/. Jumping to this address will terminate execution with the A register value as an exit code. <item><tt/IRQ/ and <tt/NMI/ events will not be generated, though <tt/BRK/ can be used if the IRQ vector at <tt/$FFFE/ is manually prepared by the test code. </itemize> <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> ���������������������������������������������������cc65-2.18/doc/smc.sgml������������������������������������������������������������������������������0000664�0000000�0000000�00000037324�13473601511�0014431�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>ca65 Macros for Self Modifying Code <author>Christian Krüger <abstract> The 'smc.inc' macro package for ca65 eases the use, increases the safeness and self-explanation of 'self-modifying-code' (SMC). </abstract> <!-- Table of contents --> <toc> <!-- Begin the document --> <sect>Overview<p> When reading assembler sources, self modifying code is often hard to identify and applying it needs a lot of discipline. Since the cacheless 6502 is a thankful target of such kind of code, the macro package will not only reduce this complexness, but also document the use. The resulting source is more self-explanatory and so easier to maintain. While for general purposes SMC is not a desired form for implementations, it can be quite useful for a small range of scenarios. Normally SMC will be introduced when optimizing code in respect to: <itemize> <item>speed and/or <item>size. </itemize> Please mind that SMC can only be applied for code in RAM, which means that a general purpose library with SMC excludes ROM targets! The ca65 SMC macro package consists of two files: <itemize> <item><tt>smc.inc</tt> <item><tt>opcodes.inc</tt> </itemize> The latter is only needed if you also plan to modify opcodes and not only data within your code. <sect>Usage<p> The use of the macros is quite simple: Original: <tscreen><verb> PHA JSR SUBROUTINE PLA </verb></tscreen> By applying SMC, the speed will now be increased by once cycle: SMC: <tscreen><verb> SMC_StoreValue RestoreAccu JSR SUBROUTINE SMC RestoreAccu, { LDA #SMC_Value } </verb></tscreen> The first line stores the value of the accu into the '<tt>RestoreAccu</tt>' labeled SMC target. Please note: <enum> <item> for all SMC store or transfer operations, a second argument can be given. This determines the register for the operation: '<tt>SMC_StoreValue Label, y</tt>' will store the value of the Y-register. If the second argument is missing, the accu will be used automatically. <item> The label targets a 'special SMC namespace'. It fits only to destinations which are introduced with the macro '<tt>SMC</tt>'. A normal label '<tt>RestoreAccu</tt>' wouldn't match and could even coexist (even if you should abstain from doing so). <item> The macro '<tt>SMC_StoreValue</tt>' takes care, that the store operation will occur on the value-position of a SMC-instruction. As you will see, other macros influence other instruction part positions. There is no consistency check, if the targeted SMC instruction acually contains a value. Storing a 'value' on an immplied SMC instruction would corrupt the following memory cell! </enum> The second line needs no further explanation, this is just a placeholder for some code in the example. The third line is the code line which is about to be modified. It has to start with the '<tt>SMC</tt>' macro and must be labeled, so that the modification can be designated. Then the unmodified code is given in curly braces. Please note the usage of the value placeholder 'SMC_Value'. Using such a placeholder has two advantages: <enum> <item> The code is better documented. It is clearly visible that the given value is about to be changed. <item> When examining an (initial) disassembly (e.g. in a debugger), these placegolders can be better identified: They are fixed and, you may notice that below, quite eye catching defined. </enum> <sect1>Argument placeholders<p> There are four kinds of placeholders: <descrip> <label id="Address placeholder"> <tag><tt>SMC_AbsAdr</tt></tag> Used to indicate an address. The value is '<tt>$FADE</tt>'. Example: <tt>STA SMC_AbsAdr</tt> <label id="Zero-Page-Address placeholder"> <tag><tt>SMC_ZpAdr</tt></tag> Used to indicate a zero-page-address. The value is '<tt>$00</tt>'. Example: <tt>LDA SMC_ZpAdr</tt> <label id="Opcode placeholder"> <tag><tt>SMC_Opcode</tt></tag> Used to indicate an instruction. The value is '<tt>NOP</tt>'. Example: <tt>SMC_Opcode</tt> <label id="Immediate value placeholder"> <tag><tt>SMC_Value</tt></tag> Used to indicate a value. The value is '<tt>$42</tt>'. Example: <tt>LDX #SMC_Value</tt> </descrip> Attention: Often code is modified after the initial use - where using the placeholders does not makes sense. Please mind also, that in very variable expressions (e.g. opcode and argument is about to be changed), placeholders can lead to unidentifyable code for a debugger/disassembler: <tt>SMC Example, { SMC_Opcode SMC_AbsAdr } </tt> Since the opcode is '<tt/NOP/', the value '<tt/$DE/' from '<tt/$FADE/' will interpreted as opcode in a disassembler too. This breaks the correct disassembly, because '<tt/$DE/' is interpreted as '<tt/DEC abx/'. Establishing a valid placeholder instruction may be better: <tt>SMC Example, { sta SMC_AbsAdr } ; Note: Opcode will be modified too!</tt> <sect1>Accessing opcodes<p> Some macros are designed to access the instruction of a code line. To increase readability, please use the opcodes as defined in the '<tt>opcodes.inc</tt>' file. <descrip> <label id="Transfer opcode"> <tag><tt>SMC_TransferOpcode label, opcode (, register)</tt></tag> Loads and store an opcode to given SMC instruction. Example: <tscreen><verb> SMC SumRegister, { LDA #10 } JSR OUTPUT SMC_TransferOpcode SumRegister, OPC_ADC_imm, x </verb></tscreen> The macro above will load the opcode '<tt>ADC #</tt>' into the x - register and stores it at the place of the '<tt>LDA #</tt>'. <label id="Load opcode"> <tag><tt>SMC_LoadOpcode label (, register)</tt></tag> Loads the opcode of a SMC line to the given register. Example: <tscreen><verb> SMC ShiftOrNothing, { LSL } SMC_LoadOpcode ShiftOrNothing, y CPY #OPC_NOP BEQ Exit </verb></tscreen> <label id="Store opcode"> <tag><tt>SMC_StoreOpcode label (, register)</tt></tag> Stores the value of the given register at the opcode place of a SMC line. Example: <tscreen><verb> SetBoldMode: LDA #OPC_INX SMC_StoreOpcode AdaptCharWidth SMC_StoreOpcode AdaptUnderlineWidth RTS ... SMC AdaptCharWidth, { NOP } ... SMC AdaptUnderlineWidth, { NOP } </verb></tscreen> </descrip> <sect1>Accessing arguments<p> These marcos are determined to get, set and change arguments of instructions: <descrip> <label id="Change branch"> <tag><tt>SMC_ChangeBranch label, destination (, register)</tt></tag> 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: <tscreen><verb> Disable Handler: SMC_ChangeBranch BranchToHandler, Exit RTS ... LDA warning SMC BranchToHandler, { BNE Handler } Exit: RTS </verb></tscreen> <label id="Transfer value"> <tag><tt>SMC_TransferValue label, value (, register)</tt></tag> Changes the value of a SMC line. Example: <tscreen><verb> ClearDefault: SMC_TransferValue LoadDefault, 0 RTS ... SMC LoadDefault, { LDX #25 } </verb></tscreen> <label id="Load value"> <tag><tt>SMC_LoadValue label (, register)</tt></tag> Retreives the value of a SMC line. Example: <tscreen><verb> ShowDefault: SMC_LoadValue LoadDefault JSR PrintValue RTS ... SMC LoadDefault, { LDX #25 } </verb></tscreen> <label id="Store value"> <tag><tt>SMC_StoreValue label (, register)</tt></tag> Stores the value in the register to given SMC line. Example: <tscreen><verb> InitCounters: LDY #0 SMC_StoreValue GetI, y SMC_StoreValue GetJ, y SMC_StoreValue GetK, y ... SMC GetI, { LDX #SMC_Value } ... SMC GetJ, { LDX #SMC_Value } ... SMC GetK, { LDX #SMC_Value } </verb></tscreen> <label id="Transfer low-byte"> <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 addresses for better readability. Example: <tscreen><verb> ActivateSecondDataSet: SMC_TransferLowByte LoadData, $40 RTS ... SMC LoadData, { LDA $2000 } </verb></tscreen> <label id="Load low-byte"> <tag><tt>SMC_LoadLowByte label (, register)</tt></tag> Does the same as '<tt>SMC_LoadValue</tt>' but should be used for low-bytes of addresses for better readability. Example: <tscreen><verb> IsSecondDataSetActive: SMC_LoadLowByte LoadData, y CPY #$40 BNE NotActive ... SMC LoadData, { LDA $2000 } </verb></tscreen> <label id="Store low-byte"> <tag><tt>SMC_StoreLowByte label (, register)</tt></tag> Does the same as '<tt>SMC_StoreValue</tt>' but should be used for low-bytes of addresses for better readability. Example: <tscreen><verb> InitStructureBaseAddresses: LDX #0 SMC_StoreLowByte GetPlayerGraphic, x SMC_StoreLowByte GetObjectGraphic, x SMC_StoreLowByte StoreCollisionData, x RTS ... SMC GetPlayerGraphic, { LDX $2000 } ... SMC GetObjectGraphic, { LDA $2100,x } ... SMC StoreCollisionData, { STY $2200 } </verb></tscreen> <label id="Transfer high-byte"> <tag><tt>SMC_TransferHighByte label, value (, register)</tt></tag> Loads and stores the given value via the named register to the high-byte address portion of an SMC-instruction. Example: <tscreen><verb> PlaySFX: SMC GetVolume { LDA $3200,x } STA SoundOut INX BNE PlaySFX ... PlayOtherSound: SMC_TransferHighByte GetVolume, $34 </verb></tscreen> <label id="Load high-byte"> <tag><tt>SMC_LoadHighByte label (, register)</tt></tag> Loads the high-byte part of an SMC-instruction address to the given register. Example: <tscreen><verb> PlaySFX: SMC GetVolume { LDA $3200,x } ... SMC_LoadHighByte GetVolume cmp #$34 beq OtherSoundPlaying ... </verb></tscreen> <label id="Store high-byte"> <tag><tt>SMC_StoreHighByte label (, register)</tt></tag> Stores the high-byte address part of an SMC-instruction from the given register. Example: <tscreen><verb> SetupLevel2: LDX #(>Level2Base) SMC_StoreHighByte GetLevelData, x SMC_StoreHighByte GetScreenData, x SMC_StoreHighByte GetSoundData, x RTS ... SMC GetLevelData, { LDA Level1Base+Data } ... SMC GetScreenData, { LDA Level1Base+Screen, x } ... SMC GetSoundData, { LDA Level1Base+Sound, y } </verb></tscreen> <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 designated SMC instruction. Example: <tscreen><verb> PrintHello: SMC_TransferAddressSingle GetChar, #HelloMsg ... LDX #0 NextChar: SMC GetChar, { LDA SMC_AbsAdr, x } BEQ leave JSR CharOut INX BNE NextChar </verb></tscreen> <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 instruction. Allows reuse of register contents by using '<tt>SMC_StoreAddress</tt>' for multiple SMC instruction modifications. Example: <tscreen><verb> SMC_TransferAddress JumpTo, #CloseChannel ... SMC JumpTo, { JMP OpenChannel } </verb></tscreen> <label id="Store address"> <tag><tt>SMC_StoreAddress label</tt></tag> Stores the address value in a/x to a SMC instruction address position. Example: <tscreen><verb> SMC_StoreAddress GetData ... SMC GetData, { LDA SMC_AbsAdr } </verb></tscreen> </descrip> <sect1>Operational macros<p> These marcos are determined to let read/modify/write opcodes work on parts of SMC instructions. <descrip> <label id="Operate on value"> <tag><tt>SMC_OperateOnValue opcode, label</tt></tag> Let given opcode work on the value part of a SMC instruction. Example: <tscreen><verb> SMC_OperateOnValue ASL, LoadMask ; shift mask to left ... SMC LoadMask, { LDA #$20 } </verb></tscreen> <label id="Operate on low-byte"> <tag><tt>SMC_OperateOnLowByte opcode, label</tt></tag> Same as '<tt/SMC_OperateOnValue/' but renamed for better readability when accessing low-bytes of address. Example: <tscreen><verb> SMC_OperateOnLowByte DEC, AccessData ... SMC AccessData, { LDX Data } </verb></tscreen> <label id="Operate on high-byte"> <tag><tt>SMC_OperateOnHighByte opcode, label</tt></tag> Let the given opcode work on the high-byte part on a SMC-instruction. Example: <tscreen><verb> NextPage: SMC_OperateOnHighByte INC, GetPageData ... SMC GetPageData, { LDA SourceData, X } </verb></tscreen> </descrip> <sect1>Scope macros<p> These marcos are determined to export and import SMC labels out of the current file scope. Please handle with care! If you cannot abstain from leaving the file scope, you should at least document the exported SMC lines very well. On import side no checking is available if the SMC line is correct accessed (e.g. invalid access to the value of an implied instruction)! <descrip> <label id="Export SMC line under given name"> <tag><tt>SMC_Export alias, label</tt></tag> SMC label will be exported under given alias. Example: <tscreen><verb> .proc GetValue SMC LoadValue, { LDA #12 } rts .endproc SMC_Export GetValueLoader, GetValue::LoadValue </verb></tscreen> <label id="Import SMC alias"> <tag><tt>SMC_Import alias</tt></tag> SMC line is made accessible under given alias. Example: <tscreen><verb> SMC_Import GetValueLoader ... SMC_TransferValue GetValueLoader, #47 ... </verb></tscreen> </descrip> <sect>A complex example<p> Let's have a look on a quite sophisticated example for the usage of SMC. It not only modifies code, but also the modification of the code is modified - allowing reuse of some instructions. <descrip> <tag/The code is from my 'memset()'implementation:/ <tscreen><verb> 1: ... 2: SMC_StoreAddress StoreAccuFirstSection 3: 4: StoreToFirstSection: 5: SMC StoreAccuFirstSection, { sta SMC_AbsAdr, Y } 6: ... 7: RestoreCodeBranchBaseAdr: 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 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 address) 16: ... </verb></tscreen> <tag/Some explanation:/ Line 2: The register pair A/X contains an address, which is stored on the address location of a SMC line called 'StoreAccuFirstSection'. According to cc65's calling convention, the low-byte is in accu while the high-byte is in the X-register. Line 5: The (modified) address is accessed. Line 8: We have a line here, which is about to be modified (it begins with SMC), but itself modifies code. Please note: Contrary to the rest of SMC-line modifying macros, the 'OperateOn'-macros just expand their given arguments into a single instruction line. These can be changed of course too. Line 10,11: These lines construct a branch operation for line 8: The X-register will be used to change it from 'inc StoreAccuFirstSection+2' (high-byte operation) to 'beq restoreCode'. Please note: To calculate the relaive branch offset, we introduced a second label ('RestoreCodeBranchBaseAdr') for to calculate it. Some could also use the internal name of the SMC label, but you should abstain to do so - it may be changed in the future... Line 14,15: The original code from line 8 is reestablished. </descrip> </article> ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/sp65.sgml�����������������������������������������������������������������������������0000664�0000000�0000000�00000033414�13473601511�0014440�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <!-- -*- text-mode -*- --> <article> <title>sp65 Users Guide <author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> <abstract> sp65 is a sprite and bitmap utility that is part of the cc65 development suite. It is used to convert graphics and bitmaps into the target formats of the supported machines. </abstract> <!-- Table of contents --> <toc> <!-- Begin the document --> <sect>Overview<p> sp65 is a tool that converts images from common formats into formats used on the 6502 platforms that are the targets of the cc65 compiler suite. In addition, it allows some very simple operation with loaded graphics data, like using part of an image for further processing. The utility has been designed in a way that adding additional source or target formats is easy. The final output is either binary, or C/assembler source. <sect>Usage<p> <sect1>Command line option overview<p> The sp65 utility accepts the following options: <tscreen><verb> --------------------------------------------------------------------------- Usage: sp65 [options] file [options] [file] Short options: -V Print the version number and exit -c fmt[,attrlist] Convert into target format -h Help (this text) -lc List all possible conversions -r file[,attrlist] Read an input file -v Increase verbosity -w file[,attrlist] Write the output to a file Long options: --convert-to fmt[,attrlist] Convert into target format --dump-palette Dump palette as table --help Help (this text) --list-conversions List all possible conversions --pop Restore the original loaded image --read file[,attrlist] Read an input file --slice x,y,w,h Generate a slice from the loaded bitmap --verbose Increase verbosity --version Print the version number and exit --write file[,attrlist] Write the output to a file --------------------------------------------------------------------------- </verb></tscreen> <sect1>Command line options in detail<p> Below is a description of all the command line options. For the concept of attribute lists see <ref id="attr-lists" name="below">. <descrip> <label id="option--convert-to"> <tag><tt>-c, --convert-to format[,attrlist]</tt></tag> Convert a bitmap into one of the supported target formats. The option argument must at least contain the "format" attribute. For more attributes, see section <ref id="conversions" name="Conversions">. <label id="option--dump-palette"> <tag><tt>--dump-palette</tt></tag> Dump palette as table. <label id="option--help"> <tag><tt>-h, --help</tt></tag> Print the short option summary shown above. <label id="option--list-conversions"> <tag><tt>-lc, --list-conversions</tt></tag> Print a list of possible conversions. <label id="option--pop"> <tag><tt>--pop</tt></tag> Restore the working copy of the bitmap from the one originally loaded from the file. This may for example be used when creating several output files from one input file. <label id="option--read"> <tag><tt>-r, --read filename[,attrlist]</tt></tag> Read an input file. The option argument must at least contain the "name" attribute. See <ref id="input-formats" name="input formats"> for more information. <label id="option-v"> <tag><tt>-v, --verbose</tt></tag> Increase verbosity. Usually only needed for debugging purposes. You may use this option more than one time for even more verbose output. <label id="option-V"> <tag><tt>-V, --version</tt></tag> Print the version number of the assembler. If you send any suggestions or bugfixes, please include the version number. <label id="option--write"> <tag><tt>-w, --write filename[,attrlist]</tt></tag> Write an output file. The option argument must at least contain the "name" attribute. See <ref id="output-formats" name="output formats"> for more information. </descrip> <p> <sect>Processing pipeline<label id="processing-pipeline"><p> sp65 consists of <itemize> <item>Front ends that read graphics data, <item>processors for graphics data, <item>converters <item>and output modules for several formats. </itemize> These modules can be combined to a pipeline that reads data, does some optional bitmap processing, converts the bitmap into a target format, and writes this binary data to disk in one of several forms. <sect>Attribute lists<label id="attr-lists"><p> As described in <ref id="processing-pipeline" name="Processing pipeline">, sp65 consists of lots of different modules that may be combined in different ways, to convert an input bitmap to some output. Many of the processors and converters have options to change the way, they're working. To avoid having lots of command line options that must be parsed on high level and passed down to the relevant parts of the program, sp65 features something called "attribute lists". Attribute lists are lists of attribute/value pairs. These lists are parsed by the main program module without any knowledge about their meaning. Lower level parts just grab the attributes they need. In general, attribute lists look like this: <tscreen><verb> attr1=val1[,attr2=val2[,...]] </verb></tscreen> Instead of the comma, colons may also be used (even mixed). To simplify things and to make the most common options look "normal", some mandatory attributes may be given without an attribute name. If the attribute name is missing, the default name is determined by the position. For example, the option <tt/<ref id="option--read" name="--read">/ does always need a file name. The attribute name for the file name is "name". To avoid having to type <tscreen><verb> sp65 --read name=ball.pcx ... </verb></tscreen> the first attribute gets the default name "name" assigned. So if the first attribute doesn't have a name, it is assumed that it is the file name. This means that instead of the line above, one can also use <tscreen><verb> sp65 --read ball.pcx ... </verb></tscreen> The second attribute for <tt/--read/ is the format of the input file. So when using <tscreen><verb> sp65 --read ball.pic:pcx ... </verb></tscreen> a PCX file named "ball.pic" is read. The long form would be <tscreen><verb> sp65 --read name=ball.pic:format=pcx ... </verb></tscreen> Changing the order of the attributes is possible only when explicitly specifying the names of the attributes. Using <tscreen><verb> sp65 --read pcx:ball.pic ... </verb></tscreen> will make sp65 complain, because it tries to read a file named "pcx" with an (unknown) format of "ball.pic". The following however will work: <tscreen><verb> sp65 --read format=pcx:name=ball.pic ... </verb></tscreen> The attributes that are valid for each processor or converter are listed below. <sect>Input formats<label id="input-formats"><p> Input formats are either specified explicitly when using <tt/<ref id="option--read" name="--read">/, or are determined by looking at the extension of the file name given. <sect1>PCX<p> While sp65 is prepared for more, this is currently the only possible input format. There are no additional attributes for this format. <sect>Conversions<label id="conversions"><p> <sect1>GEOS bitmap<p> The current bitmap working copy is converted to a GEOS compacted bitmap. This format is used by several GEOS functions (i.e. 'BitmapUp') and is described in 'The Official GEOS Programmers Reference Guide', chapter 4, section 'Bit-Mapped Graphics'. <sect1>GEOS icon<p> The current bitmap working copy is converted to GEOS icon format. A GEOS icon has the same format as a C64 high resolution sprite (24x21, monochrome, 63 bytes). There are no additional attributes for this conversion. <sect1>Koala image<p> <sect1>Lynx sprite<p> Lynx can handle 1, 2, 3 and 4 bits per pixel indexed sprites. The maximum size of a sprite is roughly 508 pixels but in reality the Lynx screen is only 160 by 102 pixels which makes very large sprites useless. The number per pixels is taken from the number of colors of the input bitmap. There are a few attributes that you can give to the conversion software. <descrip> <tag/mode/ The first is what kind of encoding to use for the sprite. The attribute for this is called "mode" and the possible values are "literal", "packed" or "transparent". The default is "packed" if no mode is specified. The "literal" is a totally literal mode with no packing. In this mode the number of pixels per scanline will be a multiple of 8 both right and left from the action point. If the source bitmap edge ends with a color where the least significant bit is one then there will be an extra 8 zero bits on that scan line. So if you are using totally literal sprites and intend to change them at runtime then please add a single pixel border far left and far right with zeros in order to prevent graphical glitches in the game. The standard encoding is called "packed". In this mode the sprite is packed using run-length encoding and literal coding mixed for optimisation to produce a small sprite. The last encoding mode "transparent" is like packed. But here we know that the index 0 will be transparent so we can clip off all 0 pixels from the left and right edge of the sprite. This will produce the smallest sprite possible on the Lynx. The sprite is not rectangular anymore. <tag/ax/ The sprite is painted around the Anchor point. The anchor point x can be between 0 and the width of the sprite - 1. If anchor point x is zero then painting the sprite in location 10,20 will set the left edge of the sprite 10 pixels from the left of the Lynx screen. When the sprite is scaled by hardware the anchor point stays in place and the sprite grows or shrinks around the anchor point. The default value is 0 (left). <tag/ay/ The sprite is painted around the Anchor point. The anchor point y can be between 0 and the height of the sprite - 1. If anchor point y is zero then painting the sprite in location 10,20 will set the top of the sprite 20 pixels from the top of the Lynx screen. When the sprite is scaled by hardware the anchor point stays in place and the sprite grows or shrinks around the anchor point. The default value is 0 (top). </descrip> <sect1>VIC2 sprite<p> <sect>Output formats<label id="output-formats"><p> Using <tt/<ref id="option--write" name="--write">/ it is possible to write processed data to an output file. An attribute "name" is mandatory, it is used as the file name for the output. The output format can be specified using an attribute named "format". If this attribute doesn't exist, the output format is determined by looking at the file name extension. <sect1>Binary<p> For this format, the processed data is written to the output file in raw binary format. There are no additional attributes (besides "name" and "format") for this output format. <sect1>Assembler code<p> For this format, the processed data is written to the output file in ca65 assembler format. There are several attributes for this output format: <descrip> <tag/base/ The value for this attribute specifies the numeric base for the data values. It may be either 2, 10 or 16. The default is 16. If the base is 2, the numbers are prefixed by '%', if the base is 16, the numbers are prefixed by '$'. For base 10, there is no prefix. <tag/bytesperline/ The value for this attribute specifies the number of bytes output in one line of the assembler file. The default is 16. <tag/ident/ This is an optional attribute. When given, the output processor will wrap the data into a <tt/.PROC/ with the given name. In addition, three constants are added as local symbols within the <tt/.PROC/: <tt/COLORS/, <tt/WIDTH/ and <tt/HEIGHT/. </descrip> <sect1>C code<p> When using C output format, a small piece of C source code is generated that defines the data containing the output in an array of <tt/unsigned char/. Possible attributes for this format are: <descrip> <tag/base/ The value for this attribute specifies the numeric base for the data values. It may be either 10 or 16. The default is 16. If the base is 16, the numbers are prefixed by 0x. For base 10, there is no prefix. <tag/bytesperline/ The value for this attribute specifies the number of bytes output in one line of the C source code. The default is 16. <tag/ident/ This is an optional attribute. When given, the output processor will wrap the data into an array of unsigned char with the given name. In addition, three <tt/#define/s are added for <tt/<ident>_COLORS/, <tt/<ident>_WIDTH/ and <tt/<ident>_HEIGHT/. </descrip> <sect>Copyright<p> sp65 (and all cc65 binutils) are (C) Copyright 1998-2012 Ullrich von Bassewitz and others. 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> ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/supervision.sgml����������������������������������������������������������������������0000664�0000000�0000000�00000010506�13473601511�0016226�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>Watara Supervision specific information for cc65 <author><url url="mailto:polluks@sdf.lonestar.org" name="Stefan A. Haubenthal"> <abstract> An overview over the Supervision 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 Supervision runtime system as it comes with the cc65 C compiler. It describes the memory layout, Supervision specific header files, available drivers, and any pitfalls specific to that platform. Please note that Supervision 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 Supervision target is a 2×16 kbyte machine language program. It is of course possible to change this behaviour by using one of the different linker configs. <sect>Memory layout<p> cc65 generated programs with the default setup run with the I/O area enabled, which gives a usable memory range of $8000 - $FFF9. More ROM may need additional bankswitching code. Special locations: <descrip> <tag/Text screen/ <!-- The text screen is located at VRAM $4000.--> No conio support is currently available for the Supervision. <tag/Stack/ The C runtime stack is located at $1FFF and growing downwards. <tag/Heap/ The C heap is located at the end of the program and grows towards the C runtime stack. </descrip><p> <sect>Platform specific header files<p> Programs containing Supervision specific code may use the <tt/supervision.h/ header file. <sect1>Hardware access<p> The following pseudo variables declared in the <tt/supervision.inc/ include file do allow access to hardware located in the address space. <descrip> <tag><tt/IO/</tag> The <tt/IO/ defines allow access to the IO chip. </descrip><p> <sect>Loadable drivers<p> <sect1>Graphics drivers<p> No graphics drivers are currently available for the Supervision. <!--A TGI driver for the standard graphics mode (160×160 in 4 colors) is available, but must be statically linked, because no file I/O is available. See the documentation for the <url url="co65.html" name="co65 utility"> for information on how to do that.--> <sect1>Extended memory drivers<p> No extended memory drivers are currently available for the Supervision. <sect1>Joystick drivers<p> <descrip> <tag><tt/supervision-stdjoy.joy (supervision_stdjoy_joy)/</tag> A joystick driver for the standard two buttons joypad is available. </descrip><p> <sect1>Mouse drivers<p> No mouse drivers are currently available for the Supervision. <sect1>RS232 device drivers<p> No communication port drivers are currently available for the Supervision. <sect>Limitations<p> <sect1>Disk I/O<p> The existing library for the Supervision doesn't implement C file I/O. There are even 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>fclose <item>fopen <item>fread <item>fprintf <item>fputc <item>fscanf <item>fwrite <item>... </itemize> <sect>Other hints<p> <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> ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/telestrat.sgml������������������������������������������������������������������������0000664�0000000�0000000�00000020426�13473601511�0015651�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>Oric Telestrat-specific information for cc65 <author> <url url="mailto:jede@oric.org" name="Jede"> <abstract> An overview over the Telestrat (Telemon 2.4 & Telemon 3.x : http://orix.oric.org) 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 Telestrat runtime system as it comes with the cc65 C compiler. It describes the memory layout, Telestrat-specific header files, available drivers, and any pitfalls specific to that platform. Please note that Telestrat-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. Oric Telestrat is the last Oric computer (Released in 1986, mainly in France). This computer is an Atmos with extra hardware: RS232, cardridge(banking system), joysticks (2 ports) or mouse (on joystick port), FDC. Video chip, CPU, keyboard management, tape hardware are the same than Atmos. Telestrat can start in Atmos mode with Atmos Cardridge (which is only the atmos Basic 1.1 ROM). Telestrat can start in Sedoric (Atmos OS) and Atmos mode with Stratoric Cardridge. This Cardridge has 3 banks of 16KB of rom with: <itemize> <item>a Sedoric ROM. <item>a Basic 1.1 ROM (Atmos). <item>a Basic 1.0 ROM (Oric-1). </itemize> The main Telestrat's configuration is the Telemon/Hyperbasic Cardridge inserted with Stratsed in floppy drive. Anyway, there is no way to load a tape file in Telemon/Hyperbasic mode without alternative program. There is also no software to write a Stratsed dsk file on PC. This Telestrat target build an Orix binary file. But, in the future, it will be possible to build a Stratsed disk. Orix uses the same systems calls than Telemon mode. That is why if you need to do software for telestrat target, you have the choice to: <itemize> <item>use cc65 Atmos target and start Telestrat in Atmos mode: A tape file is required. <item>use cc65 Atmos target and start Telestrat in Stratoric mode: A dsk file or tape file is required. <item>use cc65 Telestrat target and start Telestrat in Orix mode (see <url name="here" url="http://orix.oric.org/download/">). <item>use cc65 Telestrat target, remove Orix header from binary, code a dsk tool for Stratsed, add Stratsed header on your binary,insert your binary on floppy disk (this solution will be possible is the future). </itemize> Telestrat (from cardridge) can handle 8 banks (from $C000 to $FFFF): Bank 0 is the overlay ram. Others banks can be ROM or RAM. <sect>Binary format<p> The standard binary output format generated the linker for the Telestrat target is a machine language program with a 20 bytes header described <url name="here" url="http://orix.oric.org/orix-header/"> This header is used for Telemon 3.0. Anyway, for Telemon 2.4, there is no file management, there is no TAPE routine in Telemon, there is no way to load a binary easily. Stratsed (the Telestrat operating system) handles files management. Stratsed is loaded to memory from floppy disk. Stratsed vector are declared in asminc/telestrat.inc. But, reverse engineering is required to find how theses vectors works. Please, note that Stratsed is located in overlay memory (bank 0) There is no tool to insert a binary in a Stratsed floppy disk. The only way to load a binary (for Telemon 2.4) is to: <itemize> <item>remove the 20 bytes header <item>download <url name="osdk" url="http://osdk.defence-force.org/index?page=download"> <item>use Floppybuilder in OSDK to insert the binary with the tool (please read FloppyBuilder manual to learn how to insert your binary and how to start Microdisc boot sector when Telestrat starts) </itemize> Please note also, that the binary converted into TAP file, will not produce a right stratsed file when tap2dsk and old2mfm are used. You will be in the case that Telestrat/Stratsed crashed when you do "DIR" command. If you know the Stratsed disk format, please contact the author of this doc. <sect>Memory layout<p> In the standard setup, cc65-generated programs use the memory from $0801 to $9800; so, nearly 37K of memory (including the stack) is available. ROM calls are possible with BRK feature. Special locations: <descrip> <tag/Stack/ The C runtime stack is located at $97FF (or $B3FF), and grows downwards. <tag/Heap/ The C heap is located at the end of the program, and grows towards the C runtime stack. </descrip><p> <sect>Platform-specific header files<p> Programs containing Telestrat-specific code may use the <tt/telestrat.h/ header file. <sect1>Telestrat-specific functions<p> The functions listed below are special for the Telestrat. See the <url url="funcref.html" name="function reference"> for declaration and usage. <itemize> <item>explode <item>ping <item>shoot <item>zap <item>oups </itemize> <sect1>Hardware access<p> The following pseudo variables declared in the <tt/telestrat.h/ header file do allow access to hardware located in the address space. Some variables are 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 <tt/VIA/ variable. The structure behind this variable is explained in <tt/_6522.h/. <tag><tt/VIA2/</tag> Access to the VIA2 (Versatile Interface Adapter) chip is available via the <tt/VIA2/ variable. The structure behind this variable is explained in <tt/_6522.h/. <tag><tt/ACIA/</tag> Access to the 6551 ACIA chip is available via the <tt/ACIA/ variable. The structure behind this variable is explained in <tt/_6551.h/. </descrip><p> <sect>Loadable drivers<p> <sect1>TGI<p> TGI drivers is available on Oric Telestrat with some functions: <itemize> <item>tgi_clear <item>tgi_done <item>tgi_init <item>tgi_install <item>tgi_line <item>tgi_outtext <item>tgi_setpixel </itemize> <sect1>Extended memory drivers<p> No extended memory drivers are currently available for the Telestrat. This feature could be done because telestrat can manage RAM inserted in his port cardridge. <sect1>Joystick drivers<p> Telemon 2.4 & 3.0 manages joysticks but it had been handled yet. This means that joysticks driver could be written easily. Telemon 2.4 returns in keyboard buffer the direction of the joysticks. This means that if you get input from keyboard by conio cgetc function, you will get direction from joysticks. <sect1>Mouse drivers<p> Telestrat manages also mouse, but it had been no handled yet in this version. Telestrat mouse is really difficult to find. <sect1>RS232 device drivers<p> Telestrat has a RS232 port, but it's not usable in cc65. It is possible to use RS232 port with Telemon calls (see XSOUT primitive for example) <sect>Limitations<label id="limitations"><p> <sect1>Disk I/O<p> Telemon 3.0 handles fopen, fread, fclose primitives. It means that this function will crash the Telestrat because Telemon 2.4 does not have these primitives. By the way, Telemon 3.0 uses an extension "ch376 card" which handles sdcard and FAT 32 usb key. In the next version of Telemon, FT DOS, Sedoric, Stratsed will be handled in these 3 primitives (fopen, fread, fclose). <itemize> <item>fclose <item>fopen <item>fread </itemize> <sect>Other hints<p> <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> ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/tgi.sgml������������������������������������������������������������������������������0000664�0000000�0000000�00000076331�13473601511�0014433�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>Tiny Graphics Interface <author><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"> <abstract> The cc65 library provides functions for platform independent graphics. Include the tgi.h header file to get the necessary definitions, see also <tt>samples/tgidemo.c</tt> and <tt>samples/mandelbrot.c</tt>. </abstract> <!-- Begin the document --> <sect>tgi.h<label id="tgi.h"> <sect1>tgi_arc<label id="tgi_arc"><p> <quote> <descrip> <tag/Function/Draw an elliptic arc in the current color. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/void __fastcall__ tgi_arc (int x, int y, unsigned char rx, unsigned char ry, unsigned sa, unsigned ea);/ <tag/Description/The function draws an elliptic arc with center at x/y and 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/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 of range. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="tgi_bar" name="tgi_bar">, <ref id="tgi_circle" name="tgi_circle">, <ref id="tgi_ellipse" name="tgi_ellipse">, <ref id="tgi_pieslice" name="tgi_pieslice">, <ref id="tgi_setcolor" name="tgi_setcolor"> <tag/Example/<verb> /* Draw the upper half of an ellipse */ tgi_setcolor(TGI_COLOR_BLUE); tgi_arc (50, 50, 40, 20, 0, 180); </verb> </descrip> </quote> <sect1>tgi_bar<label id="tgi_bar"><p> <quote> <descrip> <tag/Function/The function fills a rectangle on the drawpage with the current color. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/Other tgi function <tag/Example/<verb> tgi_setcolor(TGI_COLOR_GREEN); tgi_bar(10, 10, 100, 60); </verb> </descrip> </quote> <sect1>tgi_circle<label id="tgi_circle"><p> <quote> <descrip> <tag/Function/The function draws a circle in the current color. <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="tgi_arc" name="tgi_arc">, <ref id="tgi_bar" name="tgi_bar">, <ref id="tgi_ellipse" name="tgi_ellipse">, <ref id="tgi_pieslice" name="tgi_pieslice">, <ref id="tgi_setcolor" name="tgi_setcolor"> <tag/Example/<verb> tgi_setcolor(TGI_COLOR_BLACK); tgi_circle(50, 40, 40); </verb> </descrip> </quote> <sect1>tgi_clear<label id="tgi_clear"><p> <quote> <descrip> <tag/Function/Clear the drawpage <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/void tgi_clear (void);/ <tag/Description/Clear the drawpage <tag/Availability/cc65 <tag/See also/Other tgi functions <tag/Example/None. </descrip> </quote> <sect1>tgi_done<label id="tgi_done"><p> <quote> <descrip> <tag/Function/End graphics mode, switch back to text mode. Will NOT uninstall or unload the driver! <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/void tgi_done (void);/ <tag/Description/End graphics mode, switch back to text mode. Will NOT uninstall or unload the driver! <tag/Availability/cc65 <tag/See also/Other tgi functions <tag/Example/None. </descrip> </quote> <sect1>tgi_ellipse<label id="tgi_ellipse"><p> <quote> <descrip> <tag/Function/The function draws an ellipse in the current color. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="tgi_arc" name="tgi_arc">, <ref id="tgi_bar" name="tgi_bar">, <ref id="tgi_circle" name="tgi_circle">, <ref id="tgi_pieslice" name="tgi_pieslice">, <ref id="tgi_setcolor" name="tgi_setcolor"> <tag/Example/<verb> tgi_setcolor(TGI_COLOR_RED); tgi_ellipse (50, 40, 40, 20); </verb> </descrip> </quote> <sect1>tgi_free_vectorfont<label id="tgi_free_vectorfont"><p> <quote> <descrip> <tag/Function/Free a vector font that was previously loaded into memory. <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="tgi_load_vectorfont" name="tgi_load_vectorfont">, <ref id="tgi_install_vectorfont" name="tgi_install_vectorfont"> <tag/Example/None. </descrip> </quote> <sect1>tgi_getaspectratio<label id="tgi_getaspectratio"><p> <quote> <descrip> <tag/Function/Return the pixel aspect ratio. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/unsigned tgi_getaspectratio (void);/ <tag/Description/The function returns the pixel aspect ratio for the current 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/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. <item>No TGI function will use the aspect ratio. It is up to the programmer to make use of it. <item>The <ref id="tgi_setaspectratio" name="tgi_setaspectratio"> function can be used to change the aspect 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. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="tgi_setaspectratio" name="tgi_setaspectratio"> <tag/Example/None. </descrip> </quote> <sect1>tgi_getcolor<label id="tgi_getcolor"><p> <quote> <descrip> <tag/Function/Return the current drawing color. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/unsigned char tgi_getcolor (void);/ <tag/Description/The actual color is an index to a palette. During tgi_init you will get a default palette. The number of colors depend on the platform. All platforms recognize at least TGI_COLOR_BLACK and TGI_COLOR_WHITE. But some platforms have many more predefined colors. If you paint using TGI_COLOR_GREEN and then you change the green of the palette to blue using tgi_setpalette then after this painting in TGI_COLOR_GREEN will actually be blue. <tag/Availability/cc65 <tag/See also/Other tgi functions <tag/Example/<verb> color = tgi_getcolor(); </verb> </descrip> </quote> <sect1>tgi_getcolorcount<label id="tgi_getcolorcount"><p> <quote> <descrip> <tag/Function/Get the number of available colors. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/unsigned char tgi_getcolorcount (void);/ <tag/Description/Tgi platforms use indexed color palettes. This function returns the number of entries we can use in the palette. <tag/Availability/cc65 <tag/See also/Other tgi functions <tag/Example/<verb> if (tgi_getcolorcount() == 2) { printf("Only monochrome graphics is supported\n"); } </verb> </descrip> </quote> <sect1>tgi_getdefpalette<label id="tgi_getdefpalette"><p> <quote> <descrip> <tag/Function/Get the palette installed by default. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/const unsigned char* tgi_getdefpalette (void);/ <tag/Description/The tgi driver has a default palette that is active at startup. The named colors TGI_COLOR_BLACK, TGI_COLOR_WHITE, TGI_COLOR_RED... need this palette to work correctly. <tag/Availability/cc65 <tag/See also/Other tgi functions <tag/Example/None. </descrip> </quote> <sect1>tgi_geterror<label id="tgi_geterror"><p> <quote> <descrip> <tag/Function/Return the error code for the last operation. This will also clear the error. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/unsigned char tgi_geterror (void);/ <tag/Description/Return the error code for the last operation. This will also clear the error. <tag/Availability/cc65 <tag/See also/Other tgi functions <tag/Example/None. </descrip> </quote> <sect1>tgi_geterrormsg<label id="tgi_geterrormsg"><p> <quote> <descrip> <tag/Function/Get an error message describing 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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/Other tgi functions <tag/Example/None. </descrip> </quote> <sect1>tgi_getmaxcolor<label id="tgi_getmaxcolor"><p> <quote> <descrip> <tag/Function/Get the highest index of the palette. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/unsigned char tgi_getmaxcolor (void);/ <tag/Description/Get the highest index of the palette. <tag/Availability/cc65 <tag/See also/Other tgi functions <tag/Example/None. </descrip> </quote> <sect1>tgi_getmaxx<label id="tgi_getmaxx"><p> <quote> <descrip> <tag/Function/Get the maximum x coordinate that can be used on this screen. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/unsigned tgi_getmaxx (void);/ <tag/Description/Get the maximum x coordinate that can be used on this screen. <tag/Availability/cc65 <tag/See also/Other tgi functions <tag/Example/None. </descrip> </quote> <sect1>tgi_getmaxy<label id="tgi_getmaxy"><p> <quote> <descrip> <tag/Function/Get the maximum y coordinate that can be used on this screen. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/unsigned tgi_getmaxy (void);/ <tag/Description/Get the maximum y coordinate that can be used on this screen. <tag/Availability/cc65 <tag/See also/Other tgi functions <tag/Example/None. </descrip> </quote> <sect1>tgi_getpagecount<label id="tgi_getpagecount"><p> <quote> <descrip> <tag/Function/Return the number of screen pages available. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/unsigned tgi_getpagecount (void);/ <tag/Description/Return the number of screen pages available. <tag/Availability/cc65 <tag/See also/ <ref id="tgi_setdrawpage" name="tgi_setdrawpage">, <ref id="tgi_setviewpage" name="tgi_setviewpage"> <tag/Example/None. </descrip> </quote> <sect1>tgi_getpalette<label id="tgi_getpalette"><p> <quote> <descrip> <tag/Function/Get the palette installed. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/const unsigned char* tgi_getpalette (void);/ <tag/Description/Get the palette installed. <tag/Availability/cc65 <tag/See also/Other tgi functions <tag/Example/None. </descrip> </quote> <sect1>tgi_getpixel<label id="tgi_getpixel"><p> <quote> <descrip> <tag/Function/Get the color of a pixel from the viewpage. <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/Other tgi functions. <tag/Example/None. </descrip> </quote> <sect1>tgi_gettextheight<label id="tgi_gettextheight"><p> <quote> <descrip> <tag/Function/Calculate the height of the text in pixels according to the current text style. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/Other tgi functions. <tag/Example/None. </descrip> </quote> <sect1>tgi_gettextwidth<label id="tgi_gettextwidth"><p> <quote> <descrip> <tag/Function/Calculate the width of the text in pixels according to the current text style. <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/Other tgi functions. <tag/Example/None. </descrip> </quote> <sect1>tgi_getxres<label id="tgi_getxres"><p> <quote> <descrip> <tag/Function/Get number of horisontal pixels on the screen. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/unsigned tgi_getxres (void);/ <tag/Description/Get number of horisontal pixels on the screen. This is same as tgi_maxx()+1. <tag/Availability/cc65 <tag/See also/Other tgi functions. <tag/Example/None. </descrip> </quote> <sect1>tgi_getyres<label id="tgi_getyres"><p> <quote> <descrip> <tag/Function/Get number of vertical pixels on the screen. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/unsigned tgi_getyres (void);/ <tag/Description/Get number of vertical pixels on the screen. This is same as tgi_maxy()+1. <tag/Availability/cc65 <tag/See also/Other tgi functions. <tag/Example/None. </descrip> </quote> <sect1>tgi_gotoxy<label id="tgi_gotoxy"><p> <quote> <descrip> <tag/Function/Set graphics cursor at x, y. <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/Other tgi functions. <tag/Example/None. </descrip> </quote> <sect1>tgi_init<label id="tgi_init"><p> <quote> <descrip> <tag/Function/Initialize the already loaded graphics driver. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/void tgi_init (void);/ <tag/Description/The tgi_init function will set the default palette to the hardware. <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" name="tgi_clear">/ after <tt/tgi_init/. </itemize> <tag/Availability/cc65 <tag/See also/Other tgi functions. <tag/Example/<verb> tgi_install(tgi_static_stddrv); //Include the driver statically instead of loading it. tgi_init(); //Set up the default palette and clear the screen. </verb> </descrip> </quote> <sect1>tgi_install<label id="tgi_install"><p> <quote> <descrip> <tag/Function/Install an already loaded driver and return an error code. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/unsigned char __fastcall__ tgi_install (void* driver);/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="tgi_load_driver" name="tgi_load_driver">, <ref id="tgi_uninstall" name="tgi_uninstall">, <ref id="tgi_unload" name="tgi_unload"> <tag/Example/<verb> tgi_install(tgi_static_stddrv); //Include the driver statically instead of loading it. tgi_init(); //Set up the default palette and clear the screen. </verb> </descrip> </quote> <sect1>tgi_install_vectorfont<label id="tgi_install_vectorfont"><p> <quote> <descrip> <tag/Function/Install an already loaded driver and return an error code. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/void __fastcall__ tgi_install_vectorfont (const tgi_vectorfont* font);/ <tag/Description/ 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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="tgi_load_vectorfont" name="tgi_load_vectorfont">, <ref id="tgi_free_vectorfont" name="tgi_free_vectorfont"> <tag/Example/None. </descrip> </quote> <sect1>tgi_ioctl<label id="tgi_ioctl"><p> <quote> <descrip> <tag/Function/Platform dependent code extensions. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/unsigned __fastcall__ tgi_ioctl (unsigned char code, void* data);/ <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/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. </itemize> <tag/Availability/cc65 <tag/See also/Other tgi functions. <tag/Example/<verb> #define tgi_sprite(spr) tgi_ioctl(0, (void*)(spr)) #define tgi_flip() tgi_ioctl(1, (void*)0) #define tgi_setbgcolor(bgcol) tgi_ioctl(2, (void*)(bgcol)) #define tgi_setframerate(rate) tgi_ioctl(3, (void*)(rate)) #define tgi_busy() tgi_ioctl(4, (void*)0) #define tgi_updatedisplay() tgi_ioctl(4, (void*)1) if (!tgi_busy()) { tgi_sprite(&background); tgi_setcolor(TGI_COLOR_BLUE); tgi_outttextxy(20,40,"Hello World"); tgi_updatedisplay(); } </verb> </descrip> </quote> <sect1>tgi_line<label id="tgi_line"><p> <quote> <descrip> <tag/Function/Draw a line in the current drawing color. The graphics cursor will be set to x2/y2 by this call. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/Other tgi functions. <tag/Example/None. </descrip> </quote> <sect1>tgi_lineto<label id="tgi_lineto"><p> <quote> <descrip> <tag/Function/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/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/Other tgi functions. <tag/Example/None. </descrip> </quote> <sect1>tgi_load_driver<label id="tgi_load_driver"><p> <quote> <descrip> <tag/Function/Load and install the given driver. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/void __fastcall__ tgi_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. Will not switch to graphics mode. <tag/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/Other tgi functions. <tag/Example/None. </descrip> </quote> <sect1>tgi_load_vectorfont<label id="tgi_load_vectorfont"><p> <quote> <descrip> <tag/Function/Load the given vector font. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/const tgi_vectorfont* __fastcall__ tgi_load_vectorfont (const char* name);/ <tag/Description/ 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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="tgi_install_vectorfont" name="tgi_install_vectorfont">, <ref id="tgi_free_vectorfont" name="tgi_free_vectorfont"> <tag/Example/None. </descrip> </quote> <sect1>tgi_outtext<label id="tgi_outtext"><p> <quote> <descrip> <tag/Function/Output text at the current graphics cursor position. The graphics cursor is moved to the end of the text. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/Other tgi functions. <tag/Example/None. </descrip> </quote> <sect1>tgi_outtextxy<label id="tgi_outtextxy"><p> <quote> <descrip> <tag/Function/Output text at the given cursor position. The graphics cursor is moved to the end of the text. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/Other tgi functions. <tag/Example/None. </descrip> </quote> <sect1>tgi_pieslice<label id="tgi_pieslice"><p> <quote> <descrip> <tag/Function/Draw an elliptic pie slice in the current color. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/void __fastcall__ tgi_pie slice (int x, int y, unsigned char rx, unsigned char ry, unsigned sa, unsigned ea);/ <tag/Description/The function draws an elliptic pie slice with center at x/y 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/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 of range. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="tgi_bar" name="tgi_arc">, <ref id="tgi_bar" name="tgi_bar">, <ref id="tgi_circle" name="tgi_circle">, <ref id="tgi_ellipse" name="tgi_ellipse">, <ref id="tgi_setcolor" name="tgi_setcolor"> <tag/Example/<verb> /* Draw the closed upper half of an ellipse */ tgi_setcolor(TGI_COLOR_BLUE); tgi_pieslice (50, 50, 40, 20, 0, 180); </verb> </descrip> </quote> <sect1>tgi_setaspectratio<label id="tgi_setaspectratio"><p> <quote> <descrip> <tag/Function/Set the pixel aspect ratio. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/void __fastcall__ tgi_setaspectratio (unsigned ratio);/ <tag/Description/The function sets the pixel aspect ratio for the current 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/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. <item>No TGI function will use the aspect ratio. It is up to the programmer to make use of it. <item>The <tt/tgi_setaspectratio/ function can be used to change the aspect 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/ <ref id="tgi_getaspectratio" name="tgi_getaspectratio"> <tag/Example/None. </descrip> </quote> <sect1>tgi_setcolor<label id="tgi_setcolor"><p> <quote> <descrip> <tag/Function/Set color to be used in future draw operations. <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/Other tgi functions. <tag/Example/<verb> tgi_setcolor(TGI_COLOR_BLACK); tgi_bar(0,0,30,30); tgi_setcolor(TGI_COLOR_WHITE); tgi_bar(10,10,20,20); </verb> </descrip> </quote> <sect1>tgi_setdrawpage<label id="tgi_setdrawpage"><p> <quote> <descrip> <tag/Function/Set the page for drawing. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/void __fastcall__ tgi_setdrawpage (unsigned char page);/ <tag/Description/If the drawpage and the viewpage are the same then all drawing 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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/Other tgi functions. <tag/Example/<verb> tgi_setdrawpage(1); tgi_outtextxy(10, 10, "Hello World"); tgi_setviewpage(1); // Show page 1 tgi_setdrawpage(0); tgi_outtextxy(10, 10, "Creating next frame"); ... tgi_setviewpage(0); // Show page 0 </verb> </descrip> </quote> <sect1>tgi_setpalette<label id="tgi_setpalette"><p> <quote> <descrip> <tag/Function/Set the palette (not available with all drivers/hardware). Palette is a pointer to as many entries as there are colors. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/Other tgi functions. <tag/Example/None. </descrip> </quote> <sect1>tgi_setpixel<label id="tgi_setpixel"><p> <quote> <descrip> <tag/Function/Plot a pixel on the drawpage with the current color. <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/Other tgi functions. <tag/Example/None. </descrip> </quote> <sect1>tgi_settextscale<label id="tgi_settextscale"><p> <quote> <descrip> <tag/Function/Set the scaling for text output. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/void __fastcall__ tgi_settextscale (unsigned width, unsigned height);/ <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="tgi_settextstyle" name="tgi_settextstyle"> <tag/Example/None. </descrip> </quote> <sect1>tgi_settextstyle<label id="tgi_settextstyle"><p> <quote> <descrip> <tag/Function/Set the style for text output. <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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/ <ref id="tgi_settextscale" name="tgi_settextscale"> <tag/Example/None. </descrip> </quote> <sect1>tgi_setviewpage<label id="tgi_setviewpage"><p> <quote> <descrip> <tag/Function/Set page to be visible on screen. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/void __fastcall__ tgi_setviewpage (unsigned char page);/ <tag/Description/If the drawpage and the viewpage are the same then all drawing 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/Notes/<itemize> <item>The function is only available as fastcall function, so it may only be used in presence of a prototype. </itemize> <tag/Availability/cc65 <tag/See also/Other tgi functions. <tag/Example/<verb> tgi_setdrawpage(1); tgi_outtextxy(10, 10, "Hello World"); tgi_setviewpage(1); // Show page 1 tgi_setdrawpage(0); tgi_outtextxy(10, 10, "Creating next frame"); ... tgi_setviewpage(0); // Show page 0 </verb> </descrip> </quote> <sect1>tgi_uninstall<label id="tgi_uninstall"><p> <quote> <descrip> <tag/Function/Uninstall the currently loaded driver but do not unload it. Will call tgi_done if necessary. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/void tgi_uninstall (void);/ <tag/Description/Uninstall the currently loaded driver but do not unload it. Will call tgi_done if necessary. <tag/Availability/cc65 <tag/See also/Other tgi functions. <tag/Example/None. </descrip> </quote> <sect1>tgi_unload<label id="tgi_unload"><p> <quote> <descrip> <tag/Function/Uninstall, then unload the currently loaded driver. Will call tgi_done if necessary. <tag/Header/<tt/<ref id="tgi.h" name="tgi.h">/ <tag/Declaration/<tt/void tgi_unload (void);/ <tag/Description/Uninstall, then unload the currently loaded driver. Will call tgi_done if necessary. <tag/Availability/cc65 <tag/See also/Other tgi functions. <tag/Example/None. </descrip> </quote> </article> �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/using-make.sgml�����������������������������������������������������������������������0000664�0000000�0000000�00000011251�13473601511�0015676�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>Using GNU Make with cc65 <author><url url="mailto:ol.sc@web.de" name="Oliver Schmidt"> <abstract> How to build your program using the GNU Make utility. </abstract> <!-- Table of contents --> <toc> <!-- Begin the document --> <sect>Overview<p> This document describes how to build your programs using the cc65 development tools and the GNU Make utility. The cc65 development package doesn't come with a make utility. However this is no issue because GNU Make works very nicely with cc65. <sect>What is GNU Make?<p> GNU Make is a both very powerful and very popular make utility. It might even be called the de facto standard for make utilities. For more information see the GNU Make home page: <url url="http://www.gnu.org/software/make/"> The cc65 development package is available as binaries for several host systems and can easily built for quite some additional systems. The very same is true for GNU Make so a cc65-based project coming with a GNU Make Makefile can easily be built by any cc65 developer no matter what host system is used. Because of the strong alignment of the cc65 compiler with the ISO C standard it is very well feasible to compile a single C code base both with the cc65 compiler and other C compilers like for example GCC. GNU Make turns out to be very well suited to build projects for several target systems using multiple compilers as it isn't tied to any C compiler. <sect>A sample Makefile<p> This Makefile is a fully functional sample for compiling several C sources (here <tt/foo.c/ and <tt/bar.c/) and link the resulting object files into an executable program (here <tt/foobar/): <tscreen><verb> SOURCES = foo.c bar.c PROGRAM = foobar ifdef CC65_TARGET CC = cl65 CFLAGS = -t $(CC65_TARGET) --create-dep $(<:.c=.d) -O LDFLAGS = -t $(CC65_TARGET) -m $(PROGRAM).map else CC = gcc CFLAGS = -MMD -MP -O LDFLAGS = -Wl,-Map,$(PROGRAM).map endif ######################################## .SUFFIXES: .PHONY: all clean all: $(PROGRAM) ifneq ($(MAKECMDGOALS),clean) -include $(SOURCES:.c=.d) endif %.o: %.c $(CC) -c $(CFLAGS) -o $@ $< $(PROGRAM): $(SOURCES:.c=.o) $(CC) $(LDFLAGS) -o $@ $^ clean: $(RM) $(SOURCES:.c=.o) $(SOURCES:.c=.d) $(PROGRAM) $(PROGRAM).map </verb></tscreen> <bf/Important:/ When using the sample Makefile above via copy & paste it is important to make sure that command lines (lines 26, 29 and 32) start with a tab character (ASCII code 9). <sect1>Invoking the sample Makefile<p> Without any specific configuration the sample Makefile will compile and link using GCC. In order to rather use cc65 the variable <tt/CC65_TARGET/ needs to be defined. This may by done as an environment variable or simply as part of the Makefile. However to quickly switch between compilers and/or cc65 targets it is best done on the GNU Make command line like this: <tscreen><verb> make CC65_TARGET=c64 </verb></tscreen> <sect1>Understanding the sample Makefile<p> Most parts of the sample Makefile follow the guidelines in the <url url="http://www.gnu.org/software/make/manual/make.html" name="GNU Make Manual"> that can be searched online for background information. The automatic generation of dependency however rather works as described by the GNU Make maintainer Paul D. Smith in <url url="http://make.paulandlesley.org/autodep.html#advanced" name="&dquot;Advanced Auto-Dependencies&dquot;">. Fortunately both GCC and cc65 directly support this method in the meantime. <sect1>Invoking the sample Makefile on Windows<p> The recommended way to use GNU Make on Windows is to install it as part of a Cygwin environment. For more information see the Cygwin home page: <url url="http://www.cygwin.com/"> If however installing Cygwin shouldn't be an option for one or the other reason then the sample Makefile may be invoked from the Windows Command Prompt (cmd.exe) by downloading the following programs: <itemize> <item><url name="make.exe" url="http://gnuwin32.sourceforge.net/packages/make.htm"> <item><url name="rm.exe" url="http://gnuwin32.sourceforge.net/packages/coreutils.htm"> </itemize> <sect>Target-specific Variable Values<p> The very limited resources of the cc65 target machines now and then require manual optimization of the build process by compiling individual source files with different compiler options. GNU Make offers <url url="http://www.gnu.org/software/make/manual/html_node/Target_002dspecific.html" name="Target-specific Variable Values"> perfectly suited for doing so. For example placing the code of the two modules <tt/foo/ and <tt/bar/ in the segment <tt/FOOBAR/ can be achieved with this target-specific variable definition: <tscreen><verb> foo.o bar.o: CFLAGS += --code-name FOOBAR </verb></tscreen> </article> �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/doc/vic20.sgml����������������������������������������������������������������������������0000664�0000000�0000000�00000017321�13473601511�0014565�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!doctype linuxdoc system> <article> <title>Commodore VIC20 (aka VC20 aka VIC1001) specific information for cc65 <author> <url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline> <url url="mailto:polluks@sdf.lonestar.org" name="Stefan A. Haubenthal"> <abstract> An overview over the VIC20 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 VIC20 runtime system as it comes with the cc65 C compiler. It describes the memory layout, VIC20-specific header files, available drivers, and any pitfalls specific to that platform. Please note that VIC20-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 VIC20 target is a machine language program with a one line BASIC stub, which calls the machine language part via SYS. This means that a program can be loaded as BASIC program and started with RUN. 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 unexpanded memory (RAM at $A000 - $BFFF may be used for the heap), which gives a usable memory range of $1000 - $1DFF. All ROM entry points may be called directly without additional code. Special locations: <descrip> <tag/Text screen/ The text screen is located at $1E00 (as in the standard setup). <tag/Stack/ The C runtime stack is located at $1DFF and growing downwards. <tag/Heap/ The C heap is located at the end of the program and grows towards the C runtime stack. </descrip><p> <sect>Platform-specific header files<p> Programs containing VIC20-specific code may use the <tt/vic20.h/ or <tt/cbm.h/ header files. Using the later may be an option when writing code for more than one CBM platform, since it includes <tt/vic20.h/ and declares several functions common to all CBM platforms. <sect1>VIC20-specific functions<p> There are currently no special VIC20 functions. <sect1>CBM-specific functions<p> Some functions are available for all (or at least most) of the Commodore machines. See the <url url="funcref.html" name="function reference"> for declaration and usage. <itemize> <item>cbm_close <item>cbm_closedir <item>cbm_k_setlfs <item>cbm_k_setnam <item>cbm_k_load <item>cbm_k_save <item>cbm_k_open <item>cbm_k_close <item>cbm_k_readst <item>cbm_k_chkin <item>cbm_k_ckout <item>cbm_k_basin <item>cbm_k_bsout <item>cbm_k_clrch <item>cbm_k_tksa <item>cbm_k_second <item>cbm_load <item>cbm_open <item>cbm_opendir <item>cbm_read <item>cbm_readdir <item>cbm_save <item>cbm_write <item>get_tv </itemize> <sect1>Hardware access<p> The following pseudo variables declared in the <tt/vic20.h/ header file do allow access to hardware located in the address space. Some variables are structures, accessing the struct fields will access the chip registers. <descrip> <tag><tt/VIC/</tag> The <tt/VIC/ structure allows access to the VIC (the graphics controller). See the <tt/_vic.h/ header file located in the include directory for the declaration of the structure. <tag><tt/VIA1, VIA2/</tag> Access to the two VIA (versatile interface adapter) chips is available via the <tt/VIA1/ and <tt/VIA2/ variables. The structure behind these variables is explained in <tt/_6522.h/. <tag><tt/COLOR_RAM/</tag> A character array that mirrors the color RAM of the VIC20 at $9600. </descrip><p> <sect>Loadable drivers<p> The names in the parentheses denote the symbols to be used for static linking of the drivers. <sect1>Graphics drivers<p> No graphics drivers are currently available for the VIC20. <sect1>Extended memory drivers<p> <descrip> <tag><tt/vic20-rama.emd (vic20_rama_emd)/</tag> A driver for any RAM at $A000-$BFFF. Supports 32 256 byte pages. Written and contributed by Marco van den Heuvel. <tag><tt/vic20-georam.emd (vic20_georam_emd)/</tag> A driver for the Berkeley Softworks GeoRam cartridge connected by means of the MasC=erade c64 cartridge adapter. The driver will determine the available RAM from the connected cartridge. It supports 64KB up to 2048KB of RAM. </descrip><p> <sect1>Joystick drivers<p> The default drivers, <tt/joy_stddrv (joy_static_stddrv)/, point to <tt/vic20-stdjoy.joy (vic20_stdjoy_joy)/. <descrip> <tag><tt/vic20-stdjoy.joy (vic20_stdjoy_joy)/</tag> Supports one standard joystick connected to the joysticks port of the VIC20. <tag><tt/vic20-ptvjoy.joy (vic20_ptvjoy_joy)/</tag> Driver for the Protovision 4-player adapter contributed by Groepaz. See <url url="https://www.protovision.games/hardw/4_player.php" name="the Protovision shop"> for prices and building instructions. Up to three joysticks are supported. </descrip><p> <sect1>Mouse drivers<p> No mouse drivers are currently available for the VIC20. <sect1>RS232 device drivers<p> No VIC1011 drivers are currently available for the VIC20. <sect>Limitations<p> <sect1>Escape code<p> The CTRL key cannot be used to type most control characters, entering an Esc is not possible. <sect>Other hints<p> <sect1>Passing arguments to the program<p> Command-line arguments can be passed to <tt/main()/. Since that is not supported directly by BASIC, the following syntax was chosen: <tscreen><verb> RUN:REM ARG1 " ARG2 IS QUOTED" ARG3 "" ARG5 </verb></tscreen> <enum> <item>Arguments are separated by spaces. <item>Arguments may be quoted. <item>Leading and trailing spaces around an argument are ignored. Spaces within a quoted argument are allowed. <item>The first argument passed to <tt/main()/ is the program name. <item>A maximum number of 10 arguments (including the program name) are supported. </enum> <sect1>Program return code<p> The program return code (low byte) is passed back to BASIC by use of the <tt/ST/ variable. <sect1>Using extended memory<p> BLK5 memory may be added to the heap by using the following code: <tscreen><verb> /* Check for the existence of RAM */ if (PEEK(0xA000) == POKE(0xA000, PEEK(0xA000)+1)) { /* Add it to the heap */ _heapadd ((void *) 0xA000, 0x2000); } </verb></tscreen> <sect1>Interrupts<p> The runtime for the VIC20 uses routines marked as <tt/.INTERRUPTOR/ for interrupt handlers. Such routines must be written as simple machine language subroutines and will be called automatically by the interrupt handler code when they are linked into a program. See the discussion of the <tt/.CONDES/ feature in the <url url="ca65.html" name="assembler manual">. <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> ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/����������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0013630�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/6502.h����������������������������������������������������������������������������0000664�0000000�0000000�00000012536�13473601511�0014404�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* 6502.h */ /* */ /* 6502 specific declarations */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _6502_H #define _6502_H /* We need size_t */ #ifndef _HAVE_size_t #define _HAVE_size_t typedef unsigned size_t; #endif /* Possible returns of getcpu() */ #define CPU_6502 0 #define CPU_65C02 1 #define CPU_65816 2 #define CPU_4510 3 #define CPU_65SC02 4 #define CPU_65CE02 5 #define CPU_HUC6280 6 #define CPU_2A0x 7 #define CPU_45GS02 8 unsigned char getcpu (void); /* Detect the CPU the program is running on */ /* Macros for CPU instructions */ #define BRK() __asm__ ("brk") #define CLI() __asm__ ("cli") #define SEI() __asm__ ("sei") /* Struct that holds the registers for the sys function */ struct regs { unsigned char a; /* A register value */ unsigned char x; /* X register value */ unsigned char y; /* Y register value */ unsigned char flags; /* Flags value */ unsigned pc; /* Program counter */ }; /* Defines for the flags in the regs structure */ #define F6502_N 0x80 /* N flag */ #define F6502_V 0x40 /* V flag */ #define F6502_B 0x10 /* B flag */ #define F6502_D 0x08 /* D flag */ #define F6502_I 0x04 /* I flag */ #define F6502_Z 0x02 /* Z flag */ #define F6502_C 0x01 /* C flag */ /* Function to call any machine language subroutine. All registers in the ** regs structure are passed into the routine and the results are passed ** out. The B flag is ignored on input. The called routine must end with ** an RTS. */ void __fastcall__ _sys (struct regs* r); /* Set and reset the break vector. The given user function is called if ** a break occurs. The values of the registers may be read from the brk_... ** variables. The value in brk_pc will point to the address that contains ** the brk instruction. ** The set_brk function will install an exit handler that will reset the ** vector if the program ends. */ extern unsigned char brk_a; /* A register value */ extern unsigned char brk_x; /* X register value */ extern unsigned char brk_y; /* Y register value */ extern unsigned char brk_sr; /* Status register */ extern unsigned brk_pc; /* PC value */ typedef void (*brk_handler) (void); /* Type of the break handler */ void __fastcall__ set_brk (brk_handler f); /* Set the break vector to the given address */ void reset_brk (void); /* Reset the break vector to the original value */ /* Possible returns for irq_handler() */ #define IRQ_NOT_HANDLED 0 #define IRQ_HANDLED 1 typedef unsigned char (*irq_handler) (void); /* Type of the C level interrupt request handler */ void __fastcall__ set_irq (irq_handler f, void *stack_addr, size_t stack_size); /* Set the C level interrupt request vector to the given address */ void reset_irq (void); /* Reset the C level interrupt request vector */ /* End of 6502.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/_6522.h���������������������������������������������������������������������������0000664�0000000�0000000�00000007305�13473601511�0014543�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* _6522.h */ /* */ /* Internal include file, do not use directly */ /* */ /* */ /* */ /* (C) 2004 Stefan Haubenthal <polluks@sdf.lonestar.org> */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef __VIA_H #define __VIA_H /* Define a structure with the 6522 register offsets. ** NOTE: The timer registers are not declared as 16 bit registers, because ** the order in which the two 8 bit halves are written is important, and ** the compiler doesn't guarantee any order when writing 16 bit values. */ struct __6522 { unsigned char prb; /* Port register B */ unsigned char pra; /* Port register A */ unsigned char ddrb; /* Data direction register B */ unsigned char ddra; /* Data direction register A */ unsigned char t1_lo; /* Timer 1, low byte */ unsigned char t1_hi; /* Timer 1, high byte */ unsigned char t1l_lo; /* Timer 1 latch, low byte */ unsigned char t1l_hi; /* Timer 1 latch, high byte */ unsigned char t2_lo; /* Timer 2, low byte */ unsigned char t2_hi; /* Timer 2, high byte */ unsigned char sr; /* Shift register */ unsigned char acr; /* Auxiliary control register */ unsigned char pcr; /* Peripheral control register */ unsigned char ifr; /* Interrupt flag register */ unsigned char ier; /* Interrupt enable register */ unsigned char pra2; /* Port register A w/o handshake */ }; /* End of _6522.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/_6525.h���������������������������������������������������������������������������0000664�0000000�0000000�00000006522�13473601511�0014546�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* _6525.h */ /* */ /* Internal include file, do not use directly */ /* */ /* */ /* */ /* (C) 1998-2000 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 __6525_H #define __6525_H /* Define a structure with the 6525 register offsets. The shadow registers ** (if port C is unused) are currently not implemented, we would need a ** union to do that, however that would introduce an additional name. */ struct __6525 { unsigned char pra; /* Port register A */ unsigned char prb; /* Port register B */ unsigned char prc; /* Port register C */ unsigned char ddra; /* Data direction register A */ unsigned char ddrb; /* Data direction register B */ unsigned char ddrc; /* Data direction register C */ unsigned char cr; /* Control register */ unsigned char air; /* Active interrupt register */ }; /* End of _6525.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/_6526.h���������������������������������������������������������������������������0000664�0000000�0000000�00000007572�13473601511�0014555�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* _6526.h */ /* */ /* Internal include file, do not use directly */ /* */ /* */ /* */ /* (C) 1998-2000 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 __6526_H #define __6526_H /* Define a structure with the 6526 register offsets. ** NOTE: The timer registers are not declared as 16 bit registers, because ** the order in which the two 8 bit halves are written is important, and ** the compiler doesn't guarantee any order when writing 16 bit values. */ struct __6526 { unsigned char pra; /* Port register A */ unsigned char prb; /* Port register B */ unsigned char ddra; /* Data direction register A */ unsigned char ddrb; /* Data direction register B */ unsigned char ta_lo; /* Timer A, low byte */ unsigned char ta_hi; /* Timer A, high byte */ unsigned char tb_lo; /* Timer B, low byte */ unsigned char tb_hi; /* Timer B, high byte */ unsigned char tod_10; /* TOD, 1/10 sec. */ unsigned char tod_sec; /* TOD, seconds */ unsigned char tod_min; /* TOD, minutes */ unsigned char tod_hour; /* TOD, hours */ unsigned char sdr; /* Serial data register */ unsigned char icr; /* Interrupt control register */ unsigned char cra; /* Control register A */ unsigned char crb; /* Control register B */ }; /* End of _6526.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/_6545.h���������������������������������������������������������������������������0000664�0000000�0000000�00000005420�13473601511�0014544�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* _6545.h */ /* */ /* Internal include file, do not use directly */ /* */ /* */ /* */ /* (C) 1998-2000 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 __6545_H #define __6545_H /* Define a structure with the 6545 register offsets */ struct __6545 { unsigned char ctrl; /* Control register */ unsigned char data; /* Data register */ }; /* End of _6545.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/_6551.h���������������������������������������������������������������������������0000664�0000000�0000000�00000005615�13473601511�0014547�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* _6551.h */ /* */ /* Internal include file, do not use directly */ /* */ /* */ /* */ /* (C) 1998-2000 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 __6551_H #define __6551_H /* Define a structure with the 6551 register offsets */ struct __6551 { unsigned char data; /* Data register */ unsigned char status; /* Status register */ unsigned char cmd; /* Command register */ unsigned char ctrl; /* Control register */ }; /* End of _6551.h */ #endif �������������������������������������������������������������������������������������������������������������������cc65-2.18/include/_antic.h��������������������������������������������������������������������������0000664�0000000�0000000�00000027064�13473601511�0015247�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* _antic.h */ /* */ /* Internal include file, do not use directly */ /* */ /* */ /* "ANTIC, Alphanumeric Television Interface Controller, is responsible for */ /* the generation of playfield graphics which is delivered as a datastream */ /* to the related CTIA/GTIA chip. The CTIA/GTIA provides the coloring of the */ /* playfield graphics, and is responsible for adding overlaid sprite */ /* (referred to as "Player/Missile graphics" by Atari). Atari advertised it */ /* as a true microprocessor, in that it has an instruction set to run */ /* programs (called display lists) to process data. ANTIC has no capacity */ /* for writing back computed values to memory, it merely reads data from */ /* memory and processes it for output to the screen, therefore it is not */ /* Turing complete." - Wikipedia article on "ANTIC" (with edits) */ /* */ /* (C) 2000 Freddy Offenga <taf_offenga@yahoo.com> */ /* 24-Jan-2011: Christian Krueger: Added defines for Antic instruction set */ /* 2019-01-16: Bill Kendrick <nbs@sonic.net>: More defines for registers */ /* */ /* */ /* 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 __ANTIC_H #define __ANTIC_H /*****************************************************************************/ /* Define a structure with the ANTIC coprocessor's register offsets */ /*****************************************************************************/ struct __antic { unsigned char dmactl; /* (W) direct memory access control */ unsigned char chactl; /* (W) character mode control */ unsigned char dlistl; /* display list pointer low-byte */ unsigned char dlisth; /* display list pointer high-byte */ unsigned char hscrol; /* (W) horizontal scroll enable */ unsigned char vscrol; /* (W) vertical scroll enable */ unsigned char unuse0; /* unused */ unsigned char pmbase; /* (W) msb of p/m base address (for when DMACTL has player and/or missile DMA enabled) */ unsigned char unuse1; /* unused */ unsigned char chbase; /* (W) msb of character set base address */ unsigned char wsync; /* (W) wait for horizontal synchronization */ unsigned char vcount; /* (R) vertical line counter */ unsigned char penh; /* (R) light pen horizontal position */ unsigned char penv; /* (R) light pen vertical position */ unsigned char nmien; /* (W) non-maskable interrupt enable */ union { /* (W) ("NMIRES") nmi reset -- clears the interrupt request register; ** resets all of the NMI status together */ unsigned char nmires; /* (R) ("NMIST") nmi status -- holds cause for the NMI interrupt */ unsigned char nmist; }; }; /*****************************************************************************/ /* DMACTL register options */ /*****************************************************************************/ /* Initialized to 0x22: DMA fetch, normal playfield, no PMG DMA, double-line PMGs */ /* Playfield modes: */ #define DMACTL_PLAYFIELD_NONE 0x00 #define DMACTL_PLAYFIELD_NARROW 0x01 /* e.g., 32 bytes per scanline with thick borders */ #define DMACTL_PLAYFIELD_NORMAL 0x02 /* e.g., 40 bytes per scanline with normal borders */ #define DMACTL_PLAYFIELD_WIDE 0x03 /* e.g., 48 bytes per scanline with no borders (overscan) */ /* Other options: */ /* If not set, GTIA's GRAFP0 thru GRAFP3, and/or GRAFM registers are used for ** player & missile shapes, respectively. (Modify the registers during the horizontal blank ** (Display List Interrupt), a la "racing the beam" on an Atari VCS/2600, ) ** if set, ANTIC's PMBASE will be used to fetch shapes from memory via DMA. */ #define DMACTL_DMA_MISSILES 0x04 #define DMACTL_DMA_PLAYERS 0x08 /* Unless set, PMGs (as fetched via DMA) will be double-scanline resolution */ #define DMACTL_PMG_SINGLELINE 0x10 /* Unless set, ANTIC operation is disabled, since it cannot fetch ** Display List instructions */ #define DMACTL_DMA_FETCH 0x20 /*****************************************************************************/ /* CHACTL register options */ /*****************************************************************************/ /* Initialized to 2 (CHACTL_CHAR_NORMAL | CHACTL_INV_PRESENT) */ /* Inverted (upside-down) characters */ #define CHACTL_CHAR_NORMAL 0x00 #define CHACTL_CHAR_INVERTED 0x04 /* Inverse (reverse-video) characters */ #define CHACTL_INV_TRANS 0x00 /* chars with high-bit shown */ #define CHACTL_INV_OPAQUE 0x01 /* chars with high-bit appear as space */ #define CHACTL_INV_PRESENT 0x02 /* chars with high-bit are reverse-video */ /*****************************************************************************/ /* Values for NMIEN (enabling interrupts) & NMIST (cause for the interrupt) */ /*****************************************************************************/ /* Display List Interrupts ** Called on a modeline when "DL_DLI" bit is set the ANTIC instruction, ** and jumps through VDSLST vector. */ #define NMIEN_DLI 0x80 /* Vertical Blank Interrupt ** Called during every vertical blank; see SYSVBV, VVBLKI, CRITIC, and VVBLKD, ** as well as the SETVBV routine. */ #define NMIEN_VBI 0x40 /* [Reset] key pressed */ #define NMIEN_RESET 0x20 /*****************************************************************************/ /* ANTIC instruction set */ /*****************************************************************************/ /* Absolute instructions (non mode lines) */ #define DL_JMP ((unsigned char) 1) #define DL_JVB ((unsigned char) 65) #define DL_BLK1 ((unsigned char) 0) /* 1 blank scanline */ #define DL_BLK2 ((unsigned char) 16) /* 2 blank scanlines */ #define DL_BLK3 ((unsigned char) 32) /* ...etc. */ #define DL_BLK4 ((unsigned char) 48) #define DL_BLK5 ((unsigned char) 64) #define DL_BLK6 ((unsigned char) 80) #define DL_BLK7 ((unsigned char) 96) #define DL_BLK8 ((unsigned char) 112) /* Absolute instructions (mode lines) */ /* Note: Actual width varies (e.g., 40 vs 32 vs 48) depending on ** normal vs narrow vs wide (overscan) playfield setting; see DMACTL */ /* Character modes (text, tile graphics, etc.) */ /* monochrome, 40 character & 8 scanlines per mode line (aka Atari BASIC GRAPHICS 0 via OS's CIO routines) */ #define DL_CHR40x8x1 ((unsigned char) 2) /* monochrome, 40 character & 10 scanlines per mode line (like GR. 0, with descenders) */ #define DL_CHR40x10x1 ((unsigned char) 3) /* colour, 40 character & 8 scanlines per mode line (GR. 12) */ #define DL_CHR40x8x4 ((unsigned char) 4) /* colour, 40 character & 16 scanlines per mode line (GR. 13) */ #define DL_CHR40x16x4 ((unsigned char) 5) /* colour (duochrome per character), 20 character & 8 scanlines per mode line (GR. 1) */ #define DL_CHR20x8x2 ((unsigned char) 6) /* colour (duochrome per character), 20 character & 16 scanlines per mode line (GR. 2) */ #define DL_CHR20x16x2 ((unsigned char) 7) /* Bitmap modes */ /* colour, 40 pixel & 8 scanlines per mode line (GR. 3) */ #define DL_MAP40x8x4 ((unsigned char) 8) /* 'duochrome', 80 pixel & 4 scanlines per mode line (GR.4) */ #define DL_MAP80x4x2 ((unsigned char) 9) /* colour, 80 pixel & 4 scanlines per mode line (GR.5) */ #define DL_MAP80x4x4 ((unsigned char) 10) /* 'duochrome', 160 pixel & 2 scanlines per mode line (GR.6) */ #define DL_MAP160x2x2 ((unsigned char) 11) /* 'duochrome', 160 pixel & 1 scanline per mode line (GR.14) */ #define DL_MAP160x1x2 ((unsigned char) 12) /* 4 colours, 160 pixel & 2 scanlines per mode line (GR.7) */ #define DL_MAP160x2x4 ((unsigned char) 13) /* 4 colours, 160 pixel & 1 scanline per mode line (GR.15) */ #define DL_MAP160x1x4 ((unsigned char) 14) /* monochrome, 320 pixel & 1 scanline per mode line (GR.8) */ #define DL_MAP320x1x1 ((unsigned char) 15) /* Equivalents, for people familiar with Atari 8-bit OS */ #define DL_GRAPHICS0 DL_CHR40x8x1 #define DL_GRAPHICS1 DL_CHR20x8x2 #define DL_GRAPHICS2 DL_CHR20x16x2 #define DL_GRAPHICS3 DL_MAP40x8x4 #define DL_GRAPHICS4 DL_MAP80x4x2 #define DL_GRAPHICS5 DL_MAP80x4x4 #define DL_GRAPHICS6 DL_MAP160x2x2 #define DL_GRAPHICS7 DL_MAP160x2x4 #define DL_GRAPHICS8 DL_MAP320x1x1 #define DL_GRAPHICS9 DL_MAP320x1x1 /* N.B.: GRAPHICS 9, 10, and 11 also involve GTIA's PRIOR register */ #define DL_GRAPHICS10 DL_MAP320x1x1 #define DL_GRAPHICS11 DL_MAP320x1x1 #define DL_GRAPHICS12 DL_CHR40x8x4 /* N.B.: Atari 400/800 OS didn't have GRAPHICS 12 or 13 */ #define DL_GRAPHICS13 DL_CHR40x16x4 #define DL_GRAPHICS14 DL_MAP160x1x2 #define DL_GRAPHICS15 DL_MAP160x1x4 /* Atari 400/800 OS didn't have GRAPHICS 14 or 15, so they were known by "6+" and "7+" */ #define DL_GRAPHICS6PLUS DL_GRAPHICS14 #define DL_GRAPHICS7PLUS DL_GRAPHICS15 /* Neither Atari 400/800 nor XL OS supported 10-scanline (descenders) text mode via CIO */ #define DL_GRAPHICS0_DESCENDERS DL_CHR40x10x1 /* Modifiers to mode lines */ #define DL_HSCROL(x) ((unsigned char)((x) | 16)) /* enable smooth horizontal scrolling on this line; see HSCROL */ #define DL_VSCROL(x) ((unsigned char)((x) | 32)) /* enable smooth vertical scrolling on this line; see VSCROL */ #define DL_LMS(x) ((unsigned char)((x) | 64)) /* Load Memory Scan (next two bytes must be the LSB/MSB of the data to load) */ /* General modifier */ #define DL_DLI(x) ((unsigned char)((x) | 128)) /* enable Display List Interrupt on this mode line */ /* End of _antic.h */ #endif /* #ifndef __ANTIC_H */ ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/_atarios.h������������������������������������������������������������������������0000664�0000000�0000000�00000120240�13473601511�0015601�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* _atarios.h */ /* */ /* Internal include file, do not use directly */ /* */ /* */ /* 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 __ATARIOS_H #define __ATARIOS_H /* IOCB Command Codes */ #define IOCB_OPEN 0x03 /* open */ #define IOCB_GETREC 0x05 /* get record */ #define IOCB_GETCHR 0x07 /* get character(s) */ #define IOCB_PUTREC 0x09 /* put record */ #define IOCB_PUTCHR 0x0B /* put character(s) */ #define IOCB_CLOSE 0x0C /* close */ #define IOCB_STATIS 0x0D /* status */ #define IOCB_SPECIL 0x0E /* special */ #define IOCB_DRAWLN 0x11 /* draw line */ #define IOCB_FILLIN 0x12 /* draw line with right fill */ #define IOCB_RENAME 0x20 /* rename disk file */ #define IOCB_DELETE 0x21 /* delete disk file */ #define IOCB_LOCKFL 0x23 /* lock file (set to read-only) */ #define IOCB_UNLOCK 0x24 /* unlock file */ #define IOCB_POINT 0x25 /* point sector */ #define IOCB_NOTE 0x26 /* note sector */ #define IOCB_GETFL 0x27 /* get file length */ #define IOCB_CHDIR_MYDOS 0x29 /* change directory (MyDOS) */ #define IOCB_MKDIR 0x2A /* make directory (MyDOS/SpartaDOS) */ #define IOCB_RMDIR 0x2B /* remove directory (SpartaDOS) */ #define IOCB_CHDIR_SPDOS 0x2C /* change directory (SpartaDOS) */ #define IOCB_GETCWD 0x30 /* get current directory (MyDOS/SpartaDOS) */ #define IOCB_FORMAT 0xFE /* format */ /* Device control block */ struct __dcb { unsigned char ddevic; /* device id */ unsigned char dunit; /* unit number */ unsigned char dcomnd; /* command */ unsigned char dstats; /* command type / status return */ void *dbuf; /* pointer to buffer */ unsigned char dtimlo; /* device timeout in seconds */ unsigned char dunuse; /* - unused - */ unsigned int dbyt; /* # of bytes to transfer */ union { struct { unsigned char daux1; /* 1st command auxiliary byte */ unsigned char daux2; /* 2nd command auxiliary byte */ }; unsigned int daux; /* auxiliary as word */ }; }; typedef struct __dcb dcb_t; /* I/O control block */ struct __iocb { unsigned char handler; /* handler index number (0xff free) */ unsigned char drive; /* device number (drive) */ unsigned char command; /* command */ unsigned char status; /* status of last operation */ void* buffer; /* pointer to buffer */ void* put_byte; /* pointer to device's PUT BYTE routine */ unsigned int buflen; /* length of buffer */ unsigned char aux1; /* 1st auxiliary byte */ unsigned char aux2; /* 2nd auxiliary byte */ unsigned char aux3; /* 3rd auxiliary byte */ unsigned char aux4; /* 4th auxiliary byte */ unsigned char aux5; /* 5th auxiliary byte */ unsigned char spare; /* spare byte */ }; typedef struct __iocb iocb_t; /* DOS 2.x zeropage variables */ struct __dos2x { unsigned char* zbufp; /* points to user filename */ unsigned char* zdrva; /* points to serveral buffers (mostly VTOC) */ unsigned char* zsba; /* points to sector buffer */ unsigned char errno; /* number of occured error */ }; typedef struct __dos2x dos2x_t; /* A single device handler formed by it's routines */ struct __devhdl { void *open; /* address of OPEN routine -1 */ void *close; /* address of CLOSE routine -1 */ void *get; /* address of GET BYTE routine -1 */ void *put; /* address of PUT BYTE routine -1 */ void *status; /* address of GET STATUS routine -1 */ void *special; /* address od SPECIAL routine -1 */ void (*init)(void); /* init routine (JMP INIT) */ void *reserved; /* unused */ }; typedef struct __devhdl devhdl_t; /* List of device handlers, as managed in HATABS */ struct __hatabs { unsigned char id; /* ATASCII code of handler e.g. 'C','D','E','K','P','S','R' */ devhdl_t* devhdl; /* Pointer to routines of device */ }; typedef struct __hatabs hatabs_t; /* Floating point register */ struct __fpreg { #ifdef OS_REV2 unsigned char fr; unsigned char frm[5]; /* 5-byte register mantissa */ #else unsigned char fr[6]; /* 6 bytes for single register */ #endif }; typedef struct __fpreg fpreg_t; enum { /* enum for access of floating point registers */ FPIDX_R0 = 0, /* (to use as index) */ FPIDX_RE = 1, FPIDX_R1 = 2, FPIDX_R2 = 3 }; /* Define a structure with atari os register offsets */ struct __os { // --- Zero-Page --- #ifdef OSA unsigned char* linzbs; // = $00/$01 LINBUG RAM (WILL BE REPLACED BY MONITOR RAM) #else unsigned char linflg; // = $00 LNBUG FLAG (0 = NOT LNBUG) unsigned char ngflag; // = $01 MEMORY STATUS (0 = FAILURE) #endif unsigned char* casini; // = $02/$03 CASSETTE INIT LOCATION unsigned char* ramlo; // = $04/$05 RAM POINTER FOR MEMORY TEST #ifdef OSA unsigned char tramsz; // = $06 FLAG FOR LEFT CARTRIDGE unsigned char tstdat; // = $07 FLAG FOR RIGHT CARTRIDGE #else unsigned char trnsmz; // = $06 TEMPORARY REGISTER FOR RAM SIZE unsigned char tstdat; // = $07 UNUSED (NOT TOUCHED DURING RESET/COLD START) #endif // Cleared upon Coldstart only unsigned char warmst; // = $08 WARM START FLAG unsigned char bootq; // = $09 SUCCESSFUL BOOT FLAG void (*dosvec)(void); // = $0A/$0B DISK SOFTWARE START VECTOR void (*dosini)(void); // = $0C/$0D DISK SOFTWARE INIT ADDRESS unsigned char* appmhi; // = $0E/$0F APPLICATIONS MEMORY HI LIMIT // Cleared upon Coldstart or Warmstart unsigned char pokmsk; // = $10 SYSTEM MASK FOR POKEY IRQ ENABLE unsigned char brkkey; // = $11 BREAK KEY FLAG unsigned char rtclok[3]; // = $12-$14 REAL TIME CLOCK (IN 16 MSEC UNITS) unsigned char* bufadr; // = $15/$16 INDIRECT BUFFER ADDRESS REGISTER unsigned char iccomt; // = $17 COMMAND FOR VECTOR unsigned char* dskfms; // = $18/$19 DISK FILE MANAGER POINTER unsigned char* dskutl; // = $1A/$1B DISK UTILITIES POINTER #ifdef OSA unsigned char ptimot; // = $1C PRINTER TIME OUT REGISTER unsigned char pbpnt; // = $1D PRINT BUFFER POINTER unsigned char pbufsz; // = $1E PRINT BUFFER SIZE unsigned char ptemp; // = $1F TEMPORARY REGISTER #else unsigned char abufpt[4]; // = $1C-$1F ACMI BUFFER POINTER AREA #endif iocb_t ziocb; // = $20-$2F ZERO PAGE I/O CONTROL BLOCK unsigned char status; // = $30 INTERNAL STATUS STORAGE unsigned char chksum; // = $31 CHECKSUM (SINGLE BYTE SUM WITH CARRY) unsigned char* bufr; // = $32/$33 POINTER TO DATA BUFFER unsigned char* bfen; // = $34/$35 NEXT BYTE PAST END OF THE DATA BUFFER LO #ifdef OSA unsigned char cretry; // = $36 NUMBER OF COMMAND FRAME RETRIES unsigned char dretry; // = $37 NUMBER OF DEVICE RETRIES #else unsigned int ltemp; // = $36/$37 LOADER TEMPORARY #endif unsigned char bufrfl; // = $38 DATA BUFFER FULL FLAG unsigned char recvdn; // = $39 RECEIVE DONE FLAG unsigned char xmtdon; // = $3A TRANSMISSION DONE FLAG unsigned char chksnt; // = $3B CHECKSUM SENT FLAG unsigned char nocksm; // = $3C NO CHECKSUM FOLLOWS DATA FLAG unsigned char bptr; // = $3D CASSETTE BUFFER POINTER unsigned char ftype; // = $3E CASSETTE IRG TYPE unsigned char feof; // = $3F CASSETTE EOF FLAG (0 // = QUIET) unsigned char freq; // = $40 CASSETTE BEEP COUNTER unsigned char soundr; // = $41 NOISY I/0 FLAG. (ZERO IS QUIET) unsigned char critic; // = $42 DEFINES CRITICAL SECTION (CRITICAL IF NON-Z) dos2x_t fmszpg; // = $43-$49 DISK FILE MANAGER SYSTEM ZERO PAGE #ifdef OSA unsigned char ckey; // = $4A FLAG SET WHEN GAME START PRESSED unsigned char cassbt; // = $4B CASSETTE BOOT FLAG #else void* zchain; // = $4A/$4B HANDLER LINKAGE CHAIN POINTER #endif unsigned char dstat; // = $4C DISPLAY STATUS unsigned char atract; // = $4D ATRACT FLAG unsigned char drkmsk; // = $4E DARK ATRACT MASK unsigned char colrsh; // = $4F ATRACT COLOR SHIFTER (EOR'ED WITH PLAYFIELD unsigned char tmpchr; // = $50 TEMPORARY CHARACTER unsigned char hold1; // = $51 TEMPORARY unsigned char lmargn; // = $52 LEFT MARGIN (NORMALLY 2, CC65 C STARTUP CODE SETS IT TO 0) unsigned char rmargn; // = $53 RIGHT MARGIN (NORMALLY 39 IF NO XEP80 IS USED) unsigned char rowcrs; // = $54 1CURSOR ROW unsigned int colcrs; // = $55/$56 CURSOR COLUMN unsigned char dindex; // = $57 DISPLAY MODE unsigned char* savmsc; // = $58/$59 SAVED MEMORY SCAN COUNTER unsigned char oldrow; // = $5A PRIOR ROW unsigned int oldcol; // = $5B/$5C PRIOR COLUMN unsigned char oldchr; // = $5D DATA UNDER CURSOR unsigned char* oldadr; // = $5E/$5F SAVED CURSOR MEMORY ADDRESS #ifdef OSA unsigned char newrow; // = $60 POINT DRAW GOES TO unsigned int newcol; // = $61/$62 COLUMN DRAW GOES TO #else unsigned char* fkdef; // = $60/$61 FUNCTION KEY DEFINITION TABLE unsigned char palnts; // = $62 PAL/NTSC INDICATOR (0 // = NTSC) #endif unsigned char logcol; // = $63 POINTS AT COLUMN IN LOGICAL LINE unsigned char* adress; // = $64/$65 TEMPORARY ADDRESS unsigned int mlttmp; // = $66/$67 TEMPORARY / FIRST BYTE IS USED IN OPEN AS TEMP unsigned int savadr; // = $68/$69 SAVED ADDRESS unsigned char ramtop; // = $6A RAM SIZE DEFINED BY POWER ON LOGIC unsigned char bufcnt; // = $6B BUFFER COUNT unsigned char* bufstr; // = $6C/$6D EDITOR GETCH POINTER unsigned char bitmsk; // = $6E BIT MASK unsigned char shfamt; // = $6F SHIFT AMOUNT FOR PIXEL JUSTIFUCATION unsigned int rowac; // = $70/$71 DRAW WORKING ROW unsigned int colac; // = $72/$73 DRAW WORKING COLUMN unsigned char* endpt; // = $74/$75 END POINT unsigned char deltar; // = $76 ROW DIFFERENCE unsigned int deltac; // = $77/$78 COLUMN DIFFERENCE #ifdef OSA unsigned char rowinc; // = $79 ROWINC unsigned char colinc; // = $7A COLINC #else unsigned char* keydef; // = $79/$7A 2-BYTE KEY DEFINITION TABLE ADDRESS #endif unsigned char swpflg; // = $7B NON-0 1F TXT AND REGULAR RAM IS SWAPPED unsigned char holdch; // = $7C CH IS MOVED HERE IN KGETCH BEFORE CNTL & SH unsigned char insdat; // = $7D 1-BYTE TEMPORARY unsigned int countr; // = $7E/$7F 2-BYTE DRAW ITERATION COUNT unsigned char _free_1[0xD4-0x7F-1]; // USER SPACE // Floating Point Package Page Zero Address Equates fpreg_t fpreg[4]; // = $D4-$EB 4 REGSITERS, ACCCESS LIKE "fpreg[FPIDX_R0].fr" unsigned char frx; // = $EC 1-BYTE TEMPORARY unsigned char eexp; // = $ED VALUE OF EXP #ifdef OS_REV2 unsigned char frsign; // = $EE ##REV2## 1-BYTE FLOATING POINT SIGN unsigned char plycnt; // = $EF ##REV2## 1-BYTE POLYNOMIAL DEGREE unsigned char sgnflg; // = $F0 ##REV2## 1-BYTE SIGN FLAG unsigned char xfmflg; // = $F1 ##REV2## 1-BYTE TRANSFORM FLAG #else unsigned char nsign; // = $EE SIGN OF # unsigned char esign; // = $EF SIGN OF EXPONENT unsigned char fchrflg; // = $F0 1ST CHAR FLAG unsigned char digrt; // = $F1 # OF DIGITS RIGHT OF DECIMAL #endif unsigned char cix; // = $F2 CURRENT INPUT INDEX unsigned char* inbuff; // = $F3/$F4 POINTS TO USER'S LINE INPUT BUFFER unsigned int ztemp1; // = $F5/$F6 2-BYTE TEMPORARY unsigned int ztemp4; // = $F7/$F8 2-BYTE TEMPORARY unsigned int ztemp3; // = $F9/$FA 2-BYTE TEMPORARY union { unsigned char degflg; // = $FB ##OLD## SAME AS RADFLG unsigned char radflg; // = $FB ##OLD## 0=RADIANS, 6=DEGREES }; fpreg_t* flptr; // = $FC/$FD 2-BYTE FLOATING POINT NUMBER POINTER fpreg_t* fptr2; // = $FE/$FF 2-BYTE FLOATING POINT NUMBER POINTER // --- Page 1 --- unsigned char stack[0x100]; // STACK // --- Page 2 --- void (*vdslst)(void); // = $0200/$0201 DISPLAY LIST NMI VECTOR void (*vprced)(void); // = $0202/$0203 PROCEED LINE IRQ VECTOR void (*vinter)(void); // = $0204/$0205 INTERRUPT LINE IRQ VECTOR void (*vbreak)(void); // = $0206/$0207 SOFTWARE BREAK (00) INSTRUCTION IRQ VECTOR void (*vkeybd)(void); // = $0208/$0209 POKEY KEYBOARD IRQ VECTOR void (*vserin)(void); // = $020A/$020B POKEY SERIAL INPUT READY IRQ void (*vseror)(void); // = $020C/$020D POKEY SERIAL OUTPUT READY IRQ void (*vseroc)(void); // = $020E/$020F POKEY SERIAL OUTPUT COMPLETE IRQ void (*vtimr1)(void); // = $0210/$0201 POKEY TIMER 1 IRQ void (*vtimr2)(void); // = $0212/$0203 POKEY TIMER 2 IRQ void (*vtimr4)(void); // = $0214/$0205 POKEY TIMER 4 IRQ void (*vimirq)(void); // = $0216/$0207 IMMEDIATE IRQ VECTOR unsigned int cdtmv1; // = $0218/$0210 COUNT DOWN TIMER 1 unsigned int cdtmv2; // = $021A/$021B COUNT DOWN TIMER 2 unsigned int cdtmv3; // = $021C/$021D COUNT DOWN TIMER 3 unsigned int cdtmv4; // = $021E/$021F COUNT DOWN TIMER 4 unsigned int cdtmv5; // = $0220/$0221 COUNT DOWN TIMER 5 void (*vvblki)(void); // = $0222/$0223 IMMEDIATE VERTICAL BLANK NMI VECTOR void (*vvblkd)(void); // = $0224/$0224 DEFERRED VERTICAL BLANK NMI VECTOR void (*cdtma1)(void); // = $0226/$0227 COUNT DOWN TIMER 1 JSR ADDRESS void (*cdtma2)(void); // = $0228/$0229 COUNT DOWN TIMER 2 JSR ADDRESS unsigned char cdtmf3; // = $022A COUNT DOWN TIMER 3 FLAG unsigned char srtimr; // = $022B SOFTWARE REPEAT TIMER unsigned char cdtmf4; // = $022C COUNT DOWN TIMER 4 FLAG unsigned char intemp; // = $022D IAN'S TEMP unsigned char cdtmf5; // = $022E COUNT DOWN TIMER FLAG 5 unsigned char sdmctl; // = $022F SAVE DMACTL REGISTER union { struct { unsigned char sdlstl; // = $0230 SAVE DISPLAY LIST LOW BYTE unsigned char sdlsth; // = $0231 SAVE DISPLAY LIST HI BYTE }; void* sdlst; // = $0230/$0231 (same as above as pointer) }; unsigned char sskctl; // = $0232 SKCTL REGISTER RAM #ifdef OSA unsigned char _spare_1; // = $0233 No OS use. #else unsigned char lcount; // = $0233 ##1200xl## 1-byte relocating loader record #endif unsigned char lpenh; // = $0234 LIGHT PEN HORIZONTAL VALUE unsigned char lpenv; // = $0235 LIGHT PEN VERTICAL VALUE void (*brkky)(void); // = $0236/$0237 BREAK KEY VECTOR #ifdef OSA unsigned char spare2[2]; // = $0238/$0239 No OS use. #else void (*vpirq)(void); // = $0238/$0239 ##rev2## 2-byte parallel device IRQ vector #endif unsigned char cdevic; // = $023A COMMAND FRAME BUFFER - DEVICE unsigned char ccomnd; // = $023B COMMAND union { struct { unsigned char caux1; // = $023C COMMAND AUX BYTE 1 unsigned char caux2; // = $023D COMMAND AUX BYTE 2 }; unsigned int caux; // = $023C/$023D (same as above as word) }; unsigned char temp; // = $023E TEMPORARY RAM CELL unsigned char errflg; // = $023F ERROR FLAG - ANY DEVICE ERROR EXCEPT TIME OUT unsigned char dflags; // = $0240 DISK FLAGS FROM SECTOR ONE unsigned char dbsect; // = $0241 NUMBER OF DISK BOOT SECTORS unsigned char* bootad; // = $0242/$0243 ADDRESS WHERE DISK BOOT LOADER WILL BE PUT unsigned char coldst; // = $0244 COLDSTART FLAG (1=IN MIDDLE OF COLDSTART> #ifdef OSA unsigned char spare3; // = $0245 No OS use. #else unsigned char reclen; // = $0245 ##1200xl## 1-byte relocating loader record length #endif unsigned char dsktim; // = $0246 DISK TIME OUT REGISTER #ifdef OSA unsigned char linbuf[40]; // = $0247-$026E ##old## CHAR LINE BUFFER #else unsigned char pdvmsk; // = $0247 ##rev2## 1-byte parallel device selection mask unsigned char shpdvs; // = $0248 ##rev2## 1-byte PDVS (parallel device select) unsigned char pdimsk; // = $0249 ##rev2## 1-byte parallel device IRQ selection unsigned int reladr; // = $024A/$024B ##rev2## 2-byte relocating loader relative adr. unsigned char pptmpa; // = $024C ##rev2## 1-byte parallel device handler temporary unsigned char pptmpx; // = $024D ##rev2## 1-byte parallel device handler temporary unsigned char _reserved_1[29]; // = $024E-$026A RESERVED unsigned char chsalt; // = $026B ##1200xl## 1-byte character set alternate unsigned char vsflag; // = $026C ##1200xl## 1-byte fine vertical scroll count unsigned char keydis; // = $026D ##1200xl## 1-byte keyboard disable unsigned char fine; // = $026E ##1200xl## 1-byte fine scrolling mode #endif unsigned char gprior; // = $026F GLOBAL PRIORITY CELL unsigned char paddl0; // = $0270 1-BYTE POTENTIOMETER 0 unsigned char paddl1; // = $0271 1-BYTE POTENTIOMETER 1 unsigned char paddl2; // = $0272 1-BYTE POTENTIOMETER 2 unsigned char paddl3; // = $0273 1-BYTE POTENTIOMETER 3 unsigned char paddl4; // = $0274 1-BYTE POTENTIOMETER 4 unsigned char paddl5; // = $0275 1-BYTE POTENTIOMETER 5 unsigned char paddl6; // = $0276 1-BYTE POTENTIOMETER 6 unsigned char paddl7; // = $0277 1-BYTE POTENTIOMETER 7 unsigned char stick0; // = $0278 1-byte joystick 0 unsigned char stick1; // = $0279 1-byte joystick 1 unsigned char stick2; // = $027A 1-byte joystick 2 unsigned char stick3; // = $027B 1-byte joystick 3 unsigned char ptrig0; // = $027C 1-BYTE PADDLE TRIGGER 0 unsigned char ptrig1; // = $027D 1-BYTE PADDLE TRIGGER 1 unsigned char ptrig2; // = $027E 1-BYTE PADDLE TRIGGER 2 unsigned char ptrig3; // = $027F 1-BYTE PADDLE TRIGGER 3 unsigned char ptrig4; // = $0280 1-BYTE PADDLE TRIGGER 4 unsigned char ptrig5; // = $0281 1-BYTE PADDLE TRIGGER 5 unsigned char ptrig6; // = $0281 1-BYTE PADDLE TRIGGER 6 unsigned char ptrig7; // = $0283 1-BYTE PADDLE TRIGGER 7 unsigned char strig0; // = $0284 1-BYTE JOYSTICK TRIGGER 0 unsigned char strig1; // = $0285 1-BYTE JOYSTICK TRIGGER 1 unsigned char strig2; // = $0286 1-BYTE JOYSTICK TRIGGER 2 unsigned char strig3; // = $0287 1-BYTE JOYSTICK TRIGGER 3 #ifdef OSA unsigned char cstat; // = $0288 ##old## cassette status register #else unsigned char hibyte; // = $0288 ##1200xl## 1-byte relocating loader high byte #endif unsigned char wmode; // = $0289 1-byte cassette WRITE mode unsigned char blim; // = $028A 1-byte cassette buffer limit #ifdef OSA unsigned char _reserved_2[5]; // = $028B-$028F RESERVED #else unsigned char imask; // = $028B ##rev2## (not used) void (*jveck)(void); // = $028C/$028D 2-byte jump vector unsigned newadr; // = $028E/028F ##1200xl## 2-byte relocating address #endif unsigned char txtrow; // = $0290 TEXT ROWCRS unsigned txtcol; // = $0291/$0292 TEXT COLCRS unsigned char tindex; // = $0293 TEXT INDEX unsigned char* txtmsc; // = $0294/$0295 FOOLS CONVRT INTO NEW MSC unsigned char txtold[6]; // = $0296-$029B OLDROW & OLDCOL FOR TEXT (AND THEN SOME) #ifdef OSA unsigned char tmpx1; // = $029C ##old## 1--byte temporary register #else unsigned char cretry; // = $029C ##1200xl## 1-byte number of command frame retries #endif unsigned char hold3; // = $029D 1-byte temporary unsigned char subtmp; // = $029E 1-byte temporary unsigned char hold2; // = $029F 1-byte (not used) unsigned char dmask; // = $02A0 1-byte display (pixel location) mask unsigned char tmplbt; // = $02A1 1-byte (not used) unsigned char escflg; // = $02A2 ESCAPE FLAG unsigned char tabmap[15]; // = $02A3-$02B1 15-byte (120 bit) tab stop bit map unsigned char logmap[4]; // = $02B2-$02B5 LOGICAL LINE START BIT MAP unsigned char invflg; // = $02B6 INVERSE VIDEO FLAG (TOGGLED BY ATARI KEY) unsigned char filflg; // = $02B7 RIGHT FILL FLAG FOR DRAW unsigned char tmprow; // = $02B8 1-byte temporary row unsigned tmpcol; // = $02B9/$02BA 2-byte temporary column unsigned char scrflg; // = $02BB SET IF SCROLL OCCURS unsigned char hold4; // = $02BC TEMP CELL USED IN DRAW ONLY #ifdef OSA unsigned char hold5; // = $02BD ##old## DITTO #else unsigned char dretry; // = $02BD ##1200xl## 1-byte number of device retries #endif unsigned char shflok; // = $02BE 1-byte shift/control lock flags unsigned char botscr; // = $02BF BOTTOM OF SCREEN 24 NORM 4 SPLIT unsigned char pcolr0; // = $02C0 1-byte player-missile 0 color/luminance unsigned char pcolr1; // = $02C1 1-byte player-missile 1 color/luminance unsigned char pcolr2; // = $02C2 1-byte player-missile 2 color/luminance unsigned char pcolr3; // = $02C3 1-byte player-missile 3 color/luminance unsigned char color0; // = $02C4 1-byte playfield 0 color/luminance unsigned char color1; // = $02C5 1-byte playfield 1 color/luminance unsigned char color2; // = $02C6 1-byte playfield 2 color/luminance unsigned char color3; // = $02C7 1-byte playfield 3 color/luminance unsigned char color4; // = $02C8 1-byte background color/luminance #ifdef OSA unsigned char _spare_2[23]; // = $02C9-$02DF No OS use. #else union { unsigned char parmbl[6]; // = $02C9 ##rev2## 6-byte relocating loader parameter struct { void (*runadr)(void); // = $02C9 ##1200xl## 2-byte run address unsigned int hiused; // = $02CB ##1200xl## 2-byte highest non-zero page address unsigned int zhiuse; // = $02CD ##1200xl## 2-byte highest zero page address }; }; union { unsigned char oldpar[6]; // = $02CF ##rev2## 6-byte relocating loader parameter struct { void (*gbytea)(void); // = $02CF ##1200xl## 2-byte GET-BYTE routine address unsigned int loadad; // = $02D1 ##1200xl## 2-byte non-zero page load address unsigned int zloada; // = $02D3 ##1200xl## 2-byte zero page load address }; }; unsigned int dsctln; // = $02D5 ##1200xl## 2-byte disk sector length unsigned int acmisr; // = $02D7 ##1200xl## 2-byte ACMI interrupt service routine unsigned char krpdel; // = $02D9 ##1200xl## 1-byte auto-repeat delay unsigned char keyrep; // = $02DA ##1200xl## 1-byte auto-repeat rate unsigned char noclik; // = $02DB ##1200xl## 1-byte key click disable unsigned char helpfg; // = $02DC ##1200xl## 1-byte HELP key flag (0 = no HELP) unsigned char dmasav; // = $02DD ##1200xl## 1-byte SDMCTL save/restore unsigned char pbpnt; // = $02DE ##1200xl## 1-byte printer buffer pointer unsigned char pbufsz; // = $02DF ##1200xl## 1-byte printer buffer size #endif union { unsigned char glbabs[4]; // = $02E0-$02E3 byte global variables for non-DOS users struct { void (*runad)(void); // = $02E0 ##map## 2-byte binary file run address void (*initad)(void); // = $02E2 ##map## 2-byte binary file initialization address }; }; unsigned char ramsiz; // = $02E4 RAM SIZE (HI BYTE ONLY) void* memtop; // = $02E5 TOP OF AVAILABLE USER MEMORY void* memlo; // = $02E7 BOTTOM OF AVAILABLE USER MEMORY #ifdef OSA unsigned char _spare_3; // = $02E9 No OS use. #else unsigned char hndlod; // = $02E9 ##1200xl## 1-byte user load flag #endif unsigned char dvstat[4]; // = $02EA-$02ED STATUS BUFFER union { unsigned int cbaud; // = $02EE/$02EF 2-byte cassette baud rate struct { unsigned char cbaudl; // = $02EE 1-byte low cassette baud rate unsigned char cbaudh; // = $02EF 1-byte high cassette baud rate }; }; unsigned char crsinh; // = $02F0 CURSOR INHIBIT (00 = CURSOR ON) unsigned char keydel; // = $02F1 KEY DELAY unsigned char ch1; // = $02F2 1-byte prior keyboard character unsigned char chact; // = $02F3 CHACTL REGISTER RAM unsigned char chbas; // = $02F4 CHBAS REGISTER RAM #ifdef OSA unsigned char _spare_4[5]; // = $02F5-$02F9 No OS use. #else unsigned char newrow; // = $02F5 ##1200xl## 1-byte draw destination row unsigned int newcol; // = $02F6/$02F7 ##1200xl## 2-byte draw destination column unsigned char rowinc; // = $02F8 ##1200xl## 1-byte draw row increment unsigned char colinc; // = $02F9 ##1200xl## 1-byte draw column increment #endif unsigned char char_; // = $02FA 1-byte internal character (naming changed due to do keyword conflict) unsigned char atachr; // = $02FB ATASCII CHARACTER unsigned char ch; // = $02FC GLOBAL VARIABLE FOR KEYBOARD unsigned char fildat; // = $02FD RIGHT FILL DATA <DRAW> unsigned char dspflg; // = $02FE DISPLAY FLAG DISPLAY CNTLS IF NON-ZERO unsigned char ssflag; // = $02FF START/STOP FLAG FOR PAGING (CNTL 1). CLEARE // --- Page 3 --- dcb_t dcb; // = $0300-$030B DEVICE CONTROL BLOCK unsigned int timer1; // = $030C/$030D INITIAL TIMER VALUE #ifdef OSA unsigned char addcor; // = $030E ##old## ADDITION CORRECTION #else unsigned char jmpers; // = $030E ##1200xl## 1-byte jumper options #endif unsigned char casflg; // = $030F CASSETTE MODE WHEN SET unsigned int timer2; // = $0310/$0311 2-byte final baud rate timer value unsigned char temp1; // = $0312 TEMPORARY STORAGE REGISTER #ifdef OSA unsigned char _spare_5; // = $0313 unused unsigned char temp2; // = $0314 ##old## TEMPORARY STORAGE REGISTER #else unsigned char temp2; // = $0313 ##1200xl## 1-byte temporary unsigned char ptimot; // = $0314 ##1200xl## 1-byte printer timeout #endif unsigned char temp3; // = $0315 TEMPORARY STORAGE REGISTER unsigned char savio; // = $0316 SAVE SERIAL IN DATA PORT unsigned char timflg; // = $0317 TIME OUT FLAG FOR BAUD RATE CORRECTION unsigned char stackp; // = $0318 SIO STACK POINTER SAVE CELL unsigned char tstat; // = $0319 TEMPORARY STATUS HOLDER #ifdef OSA hatabs_t hatabs[12]; // = $031A-$033D handler address table unsigned int zeropad; // = $033E/$033F zero padding #else hatabs_t hatabs[11]; // = $031A-$033A handler address table unsigned int zeropad; // = $033B/$033C zero padding unsigned char pupbt1; // = $033D ##1200xl## 1-byte power-up validation byte 1 unsigned char pupbt2; // = $033E ##1200xl## 1-byte power-up validation byte 2 unsigned char pupbt3; // = $033F ##1200xl## 1-byte power-up validation byte 3 #endif iocb_t iocb[8]; // = $0340-$03BF 8 I/O Control Blocks unsigned char prnbuf[40]; // = $03C0-$3E7 PRINTER BUFFER #ifdef OSA unsigned char _spare_6[151]; // = $03E8-$047F unused #else unsigned char superf; // = $03E8 ##1200xl## 1-byte editor super function flag unsigned char ckey; // = $03E9 ##1200xl## 1-byte cassette boot request flag unsigned char cassbt; // = $03EA ##1200xl## 1-byte cassette boot flag unsigned char cartck; // = $03EB ##1200xl## 1-byte cartridge equivalence check unsigned char derrf; // = $03EC ##rev2## 1-byte screen OPEN error flag unsigned char acmvar[11]; // = $03ED-$03F7 ##1200xl## reserved for ACMI, not cleared upon reset unsigned char basicf; // = $03F8 ##rev2## 1-byte BASIC switch flag unsigned char mintlk; // = $03F9 ##1200xl## 1-byte ACMI module interlock unsigned char gintlk; // = $03FA ##1200xl## 1-byte cartridge interlock void* chlink; // = $03FB/$03FC ##1200xl## 2-byte loaded handler chain link unsigned char casbuf[131]; // = $03FD-$047F CASSETTE BUFFER #endif // --- Page 4 --- unsigned char usarea[128]; // = $0480 128 bytes reserved for application // --- Page 5 --- unsigned char _spare_7[126]; // = $0500-$057D reserved for FP package / unused unsigned char lbpr1; // = $057E LBUFF PREFIX 1 unsigned char lbpr2; // = $057F LBUFF PREFIX 2 unsigned char lbuff[128]; // = $0580-$05FF 128-byte line buffer }; /* Define a structure with the zero page atari basic register offsets */ struct __basic { void* lowmem; // = $80/$81 POINTER TO BASIC'S LOW MEMORY void* vntp; // = $82/$83 BEGINNING ADDRESS OF THE VARIABLE NAME TABLE void* vntd; // = $84/$85 POINTER TO THE ENDING ADDRESS OF THE VARIABLE NAME TABLE PLUS ONE void* vvtp; // = $86/$87 ADDRESS FOR THE VARIABLE VALUE TABLE void* stmtab; // = $88/$89 ADDRESS OF THE STATEMENT TABLE void* stmcur; // = $8A/$8B CURRENT BASIC STATEMENT POINTER void* starp; // = $8C/$8D ADDRESS FOR THE STRING AND ARRAY TABLE void* runstk; // = $8E/$8F ADDRESS OF THE RUNTIME STACK void* memtop; // = $90/$91 POINTER TO THE TOP OF BASIC MEMORY unsigned char _internal_1[0xBA-0x91-1]; // INTERNAL DATA unsigned int stopln; // = $BA/$BB LINE WHERE A PROGRAM WAS STOPPED unsigned char _internal_2[0xC3-0xBB-1]; // INTERNAL DATA unsigned char errsav; // = $C3 NUMBER OF THE ERROR CODE unsigned char _internal_3[0xC9-0xC3-1]; // INTERNAL DATA unsigned char ptabw; // = $C9 NUMBER OF COLUMNS BETWEEN TAB STOPS unsigned char loadflg; // = $CA LIST PROTECTION unsigned char _internal_4[0xD4-0xCA-1]; // INTERNAL DATA unsigned int binint; // = $D4/$D5 USR-CALL RETURN VALUE }; #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/_gtia.h���������������������������������������������������������������������������0000664�0000000�0000000�00000033017�13473601511�0015070�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* _gtia.h */ /* */ /* Internal include file, do not use directly */ /* */ /* "GTIA, Graphic Television Interface Adaptor, is a custom chip used in the */ /* Atari 8-bit family of computers and in the Atari 5200 console. In these */ /* systems, GTIA chip works together with ANTIC to produce video display. */ /* ANTIC generates the playfield graphics (text and bitmap) while GTIA */ /* provides the color for the playfield and adds overlay objects known as */ /* player/missile graphics (sprites)" - Wikipedia article on "GTIA" */ /* */ /* */ /* (C) 2000 Freddy Offenga <taf_offenga@yahoo.com> */ /* 2019-01-16: Bill Kendrick <nbs@sonic.net>: More defines for registers */ /* */ /* */ /* 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 __GTIA_H #define __GTIA_H /*****************************************************************************/ /* Define a structure with the GTIA register offsets for write (W) */ /*****************************************************************************/ struct __gtia_write { unsigned char hposp0; /* 0x00: horizontal position of player 0 */ unsigned char hposp1; /* 0x01: horizontal position of player 1 */ unsigned char hposp2; /* 0x02: horizontal position of player 2 */ unsigned char hposp3; /* 0x03: horizontal position of player 3 */ unsigned char hposm0; /* 0x04: horizontal position of missile 0 */ unsigned char hposm1; /* 0x05: horizontal position of missile 1 */ unsigned char hposm2; /* 0x06: horizontal position of missile 2 */ unsigned char hposm3; /* 0x07: horizontal position of missile 3 */ unsigned char sizep0; /* 0x08: size of player 0 */ unsigned char sizep1; /* 0x09: size of player 1 */ unsigned char sizep2; /* 0x0A: size of player 2 */ unsigned char sizep3; /* 0x0B: size of player 3 */ unsigned char sizem; /* 0x0C: size of missiles */ unsigned char grafp0; /* 0x0D: graphics shape player 0 (used when ANTIC is not instructed to use DMA; see DMACTL) */ unsigned char grafp1; /* 0x0E: graphics shape player 1 */ unsigned char grafp2; /* 0x0F: graphics shape player 2 */ unsigned char grafp3; /* 0x10: graphics shape player 3 */ unsigned char grafm; /* 0x11: graphics shape missiles */ unsigned char colpm0; /* 0x12: color player and missile 0 */ unsigned char colpm1; /* 0x13: color player and missile 1 */ unsigned char colpm2; /* 0x14: color player and missile 2 */ unsigned char colpm3; /* 0x15: color player and missile 3 */ unsigned char colpf0; /* 0x16: color playfield 0 */ unsigned char colpf1; /* 0x17: color playfield 1 */ unsigned char colpf2; /* 0x18: color playfield 2 */ unsigned char colpf3; /* 0x19: color playfield 3 */ unsigned char colbk; /* 0x1A: color background */ unsigned char prior; /* 0x1B: priority selection */ unsigned char vdelay; /* 0x1C: vertical delay -- one-line resolution movement of ** vertical position of an object when two line resolution display is enabled */ unsigned char gractl; /* 0x1D: stick/paddle latch, p/m control */ unsigned char hitclr; /* 0x1E: clear p/m collision */ unsigned char consol; /* 0x1F: builtin speaker */ }; /*****************************************************************************/ /* (W) Values for SIZEP0-SIZEP3 and SIZEM registers: */ /*****************************************************************************/ #define PMG_SIZE_NORMAL 0x0 /* one color clock per pixel */ #define PMG_SIZE_DOUBLE 0x1 /* two color clocks per pixel */ #define PMG_SIZE_QUAD 0x2 /* four color clocks per pixel */ /* COLPM0-COLPM3, COLPF0-COLPF3, COLBK color registers */ /*****************************************************************************/ /* Color definitions */ /*****************************************************************************/ /* Make a GTIA color value */ #define _gtia_mkcolor(hue,lum) (((hue) << 4) | ((lum) << 1)) /* Luminance values go from 0 (black) to 7 (white) */ /* Hue values */ /* (These can vary depending on TV standard (NTSC vs PAL), ** tint potentiometer settings, TV tint settings, emulator palette, etc.) */ #define HUE_GREY 0 #define HUE_GOLD 1 #define HUE_GOLDORANGE 2 #define HUE_REDORANGE 3 #define HUE_ORANGE 4 #define HUE_MAGENTA 5 #define HUE_PURPLE 6 #define HUE_BLUE 7 #define HUE_BLUE2 8 #define HUE_CYAN 9 #define HUE_BLUEGREEN 10 #define HUE_BLUEGREEN2 11 #define HUE_GREEN 12 #define HUE_YELLOWGREEN 13 #define HUE_YELLOW 14 #define HUE_YELLOWRED 15 /* Color defines, similar to c64 colors (untested) */ /* Hardware palette values (for GTIA colxxx registers) */ #define GTIA_COLOR_BLACK _gtia_mkcolor(HUE_GREY,0) #define GTIA_COLOR_WHITE _gtia_mkcolor(HUE_GREY,7) #define GTIA_COLOR_RED _gtia_mkcolor(HUE_REDORANGE,1) #define GTIA_COLOR_CYAN _gtia_mkcolor(HUE_CYAN,3) #define GTIA_COLOR_VIOLET _gtia_mkcolor(HUE_PURPLE,4) #define GTIA_COLOR_GREEN _gtia_mkcolor(HUE_GREEN,2) #define GTIA_COLOR_BLUE _gtia_mkcolor(HUE_BLUE,2) #define GTIA_COLOR_YELLOW _gtia_mkcolor(HUE_YELLOW,7) #define GTIA_COLOR_ORANGE _gtia_mkcolor(HUE_ORANGE,5) #define GTIA_COLOR_BROWN _gtia_mkcolor(HUE_YELLOW,2) #define GTIA_COLOR_LIGHTRED _gtia_mkcolor(HUE_REDORANGE,6) #define GTIA_COLOR_GRAY1 _gtia_mkcolor(HUE_GREY,2) #define GTIA_COLOR_GRAY2 _gtia_mkcolor(HUE_GREY,3) #define GTIA_COLOR_LIGHTGREEN _gtia_mkcolor(HUE_GREEN,6) #define GTIA_COLOR_LIGHTBLUE _gtia_mkcolor(HUE_BLUE,6) #define GTIA_COLOR_GRAY3 _gtia_mkcolor(HUE_GREY,5) /*****************************************************************************/ /* (W) PRIOR register values */ /*****************************************************************************/ #define PRIOR_P03_PF03 0x01 /* Players 0-3, then Playfields 0-3, then background */ #define PRIOR_P01_PF03_P23 0x02 /* Players 0-1, then Playfields 0-3, then Players 2-3, then background */ #define PRIOR_PF03_P03 0x04 /* Playfields 0-3, then Players 0-3, then background */ #define PRIOR_PF01_P03_PF23 0x08 /* Playfields 0-1, then Players 0-3, then Playfields 2-3, then background */ #define PRIOR_5TH_PLAYER 0x10 /* Four missiles combine to be a 5th player (uses COLPF3) */ /* Causes overlap of players 0 & 1 and of players 2 & 3 to result in a third color, ** the logical OR of the two players' colors, and other overlaps (e.g., players 0 and 2) ** to result in black (0x00). */ #define PRIOR_OVERLAP_3RD_COLOR 0x20 /*****************************************************************************/ /* (W) GTIA special graphics mode options for GPRIOR */ /*****************************************************************************/ /* Pixels are 2 color clocks wide, and one scanline tall ** (so 80x192 in normal playfield width). ** May be used with both bitmap and character modelines. */ /* 16 shade shades of the background (COLBK) hue; ** Note: brightnesses other than 0 (darkest) in COLBK cause additional effects */ #define PRIOR_GFX_MODE_9 0x40 /* 9 color palette mode; ** COLPM0 (acts as background) thru COLPM3, followed by COLPF0 thru COLPF3, and COLBK */ #define PRIOR_GFX_MODE_10 0x80 /* 16 hues of the background (COLBK) brightness; ** Note: hues other than 0 (greys) in COLBK caus additional effects */ #define PRIOR_GFX_MODE_11 0xC0 /*****************************************************************************/ /* (W) VDELAY register values */ /*****************************************************************************/ #define VDELAY_MISSILE0 0x01 #define VDELAY_MISSILE1 0x02 #define VDELAY_MISSILE2 0x04 #define VDELAY_MISSILE3 0x08 #define VDELAY_PLAYER0 0x10 #define VDELAY_PLAYER1 0x20 #define VDELAY_PLAYER2 0x40 #define VDELAY_PLAYER3 0x80 /*****************************************************************************/ /* (W) GRACTL register values */ /*****************************************************************************/ #define GRACTL_MISSLES 0x01 /* enable missiles */ #define GRACTL_PLAYERS 0x02 /* enable players */ /* "Latch" triggers; once pressed, will give a continuous ** pressed input until this bit is cleared */ #define GRACTL_LATCH_TRIGGER_INPUTS 0x04 /*****************************************************************************/ /* Define a structure with the GTIA register offsets for read (R) */ /*****************************************************************************/ struct __gtia_read { unsigned char m0pf; /* 0x00: missile 0 to playfield collision */ unsigned char m1pf; /* 0x01: missile 1 to playfield collision */ unsigned char m2pf; /* 0x02: missile 2 to playfield collision */ unsigned char m3pf; /* 0x03: missile 3 to playfield collision */ unsigned char p0pf; /* 0x04: player 0 to playfield collision */ unsigned char p1pf; /* 0x05: player 1 to playfield collision */ unsigned char p2pf; /* 0x06: player 2 to playfield collision */ unsigned char p3pf; /* 0x07: player 3 to playfield collision */ unsigned char m0pl; /* 0x08: missile 0 to player collision */ unsigned char m1pl; /* 0x09: missile 1 to player collision */ unsigned char m2pl; /* 0x0A: missile 2 to player collision */ unsigned char m3pl; /* 0x0B: missile 3 to player collision */ unsigned char p0pl; /* 0x0C: player 0 to player collision */ unsigned char p1pl; /* 0x0D: player 1 to player collision */ unsigned char p2pl; /* 0x0E: player 2 to player collision */ unsigned char p3pl; /* 0x0F: player 3 to player collision */ unsigned char trig0; /* 0x10: joystick trigger 0 (0=pressed, 1=released) */ unsigned char trig1; /* 0x11: joystick trigger 1 */ unsigned char trig2; /* 0x12: joystick trigger 2 */ unsigned char trig3; /* 0x13: joystick trigger 3 */ unsigned char pal; /* 0x14: pal/ntsc flag */ unsigned char unused[10]; unsigned char consol; /* 0x1F: console buttons */ }; /*****************************************************************************/ /* (R) PAL register possible values */ /*****************************************************************************/ /* Note: This only tells you whether the GTIA is PAL or NTSC; some NTSC ** systems are modded with PAL ANTIC chips; testing VCOUNT limits can be ** done to check for that. Seems like it's not possible to test for SECAM */ #define TV_STD_PAL 0x1 #define TV_STD_NTSC 0xE /*****************************************************************************/ /* Macros for reading console keys (Start/Select/Option) via CONSOL register */ /*****************************************************************************/ #define CONSOL_START(x) !((unsigned char)((x) & 1)) /* true if Start pressed */ #define CONSOL_SELECT(x) !((unsigned char)((x) & 2)) /* true if Select pressed */ #define CONSOL_OPTION(x) !((unsigned char)((x) & 4)) /* true if Option pressed */ /* End of _gtia.h */ #endif /* #ifndef __GTIA_H */ �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/_heap.h���������������������������������������������������������������������������0000664�0000000�0000000�00000002136�13473601511�0015057�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** _heap.h ** ** Ullrich von Bassewitz, 1998-06-03, 2004-12-19 ** */ #ifndef __HEAP_H #define __HEAP_H /* Structure that preceeds a user block in most cases. ** The aligned_malloc function may generate blocks where the start pointer ** and size are splitted to handle a memory hole that is needed for ** alignment. */ struct usedblock { unsigned size; struct usedblock* start; }; /* Space needed for administering used blocks */ #define HEAP_ADMIN_SPACE sizeof (struct usedblock) /* The data type used to implement the free list. ** Beware: Field order is significant! */ struct freeblock { unsigned size; struct freeblock* next; struct freeblock* prev; }; /* Variables that describe the heap */ extern unsigned* _heaporg; /* Bottom of heap */ extern unsigned* _heapptr; /* Current top */ extern unsigned* _heapend; /* Upper limit */ extern struct freeblock* _heapfirst; /* First free block in list */ extern struct freeblock* _heaplast; /* Last free block in list */ /* End of _heap.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/_mikey.h��������������������������������������������������������������������������0000664�0000000�0000000�00000012351�13473601511�0015260�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* _mikey.h */ /* */ /* Atari Lynx, Mikey chip register hardware structures */ /* */ /* */ /* 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 __MIKEY_H #define __MIKEY_H /* timer structure */ typedef struct _mikey_timer { unsigned char reload; unsigned char control; unsigned char count; unsigned char control2; } _mikey_timer; typedef struct _mikey_all_timers { struct _mikey_timer timer[8]; } _mikey_all_timers; /* audio channel structure */ typedef struct _mikey_audio { unsigned char volume; unsigned char feedback; unsigned char dac; unsigned char shiftlo; unsigned char reload; unsigned char control; unsigned char count; unsigned char other; } _mikey_audio; /* Define a structure with the mikey register offsets */ struct __mikey { struct _mikey_timer timer0; // 0xFD00 struct _mikey_timer timer1; // 0xFD04 struct _mikey_timer timer2; // 0xFD08 struct _mikey_timer timer3; // 0xFD0C struct _mikey_timer timer4; // 0xFD10 struct _mikey_timer timer5; // 0xFD14 struct _mikey_timer timer6; // 0xFD18 struct _mikey_timer timer7; // 0xFD1C struct _mikey_audio channel_a; // 0xFD20 struct _mikey_audio channel_b; // 0xFD28 struct _mikey_audio channel_c; // 0xFD30 struct _mikey_audio channel_d; // 0xFD38 unsigned char attena; // 0xFD40 ?? not yet allocated? unsigned char attenb; // 0xFD41 | unsigned char attenc; // 0xFD42 | unsigned char attend; // 0xFD43 | unsigned char panning; // 0xFD44 | unsigned char unused0[11]; // 0xFD45 - 0xFD4F not used unsigned char mstereo; // 0xFD50 stereo control bits unsigned char unused1[47]; // 0xFD51 - 0xFD7F not used unsigned char intrst; // 0xFD80 interrupt poll 0 unsigned char intset; // 0xFD81 interrupt poll 1 unsigned char unused2[2]; // 0xFD82 - 0xFD83 not used unsigned char magrdy0; // 0xFD84 mag tape channel0 ready bit unsigned char magrdy1; // 0xFD85 mag tape channel1 ready bit unsigned char audin; // 0xFD86 audio in unsigned char sysctl1; // 0xFD87 control bits unsigned char mikeyrev; // 0xFD88 mikey hardware rev unsigned char mikeysrev; // 0xFD89 mikey software rev unsigned char iodir; // 0xFD8A parallel i/o data dir unsigned char iodat; // 0xFD8B parallel data unsigned char serctl; // 0xFD8C serial control register unsigned char serdat; // 0xFD8D serial data unsigned char unused3[2]; // 0xFD8E - 0xFD8F not used unsigned char sdoneack; // 0xFD90 suzy done acknowledge unsigned char cpusleep; // 0xFD91 cpu bus request disable unsigned char dispctl; // 0xFD92 video bus request enable, viddma unsigned char pkbkup; // 0xFD93 magic 'P' count unsigned char *scrbase; // 0xFD94 start address of video display unsigned char unused4[6]; // 0xFD96 - 0xFD9B not used unsigned char mtest0; // 0xFD9C unsigned char mtest1; // 0xFD9D unsigned char mtest2; // 0xFD9E unsigned char unused5; // 0xFD9F not used unsigned char palette[32]; // 0xFDA0 - 0xFDBF palette 32 bytes // 0xFDC0 - 0xFDFF not used }; #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/_pbi.h����������������������������������������������������������������������������0000664�0000000�0000000�00000006107�13473601511�0014716�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* _pbi.h */ /* */ /* Internal include file, do not use directly */ /* */ /* */ /* */ /* (C) 2000 Freddy Offenga <taf_offenga@yahoo.com> */ /* */ /* */ /* 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 __PBI_H #define __PBI_H /* parallel bus interface area */ #define PBI ((unsigned char*)0xD100) /* parallel device IRQ status */ #define PDVI ((unsigned char*)0xD1FF) /* parallel device select */ #define PDVS ((unsigned char*)0xD1FF) /* parallel bus interface RAM area */ #define PBIRAM ((unsigned char*)0xD600) /* parallel device ID 1 */ #define PDID1 ((unsigned char*)0xD803) /* parallel device I/O vector */ #define PDIDV ((unsigned char*)0xD805) /* parallel device IRQ vector */ #define PDIRQV ((unsigned char*)0xD808) /* parallel device ID 2 */ #define PDID2 ((unsigned char*)0xD80B) /* parallel device vector table */ #define PDVV ((unsigned char*)0xD80D) /* End of _pbi.h */ #endif /* #ifndef __PBI_H */ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/_pia.h����������������������������������������������������������������������������0000664�0000000�0000000�00000005744�13473601511�0014723�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* _pia.h */ /* */ /* Internal include file, do not use directly */ /* */ /* The Peripheral Interface Adapter (PIA) chip (a 6520 or 6820) provides */ /* parallel I/O interfacing; it was used in Atari 400/800 and Commodore PET */ /* family of computers, for joystick and some interrupts. */ /* Sources; various + Wikpedia article on "Peripheral Interface Adapter". */ /* */ /* */ /* (C) 2000 Freddy Offenga <taf_offenga@yahoo.com> */ /* */ /* */ /* 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 __PIA_H #define __PIA_H /* Define a structure with the PIA register offsets */ struct __pia { unsigned char porta; /* port A data r/w */ unsigned char portb; /* port B data r/w */ unsigned char pactl; /* port A control */ unsigned char pbctl; /* port B control */ }; /* (Some specific register values for Atari defined in atari.h) */ /* End of _pia.h */ #endif ����������������������������cc65-2.18/include/_pokey.h��������������������������������������������������������������������������0000664�0000000�0000000�00000026173�13473601511�0015300�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* _pokey.h */ /* */ /* Internal include file, do not use directly */ /* */ /* POKEY, Pot Keyboard Integrated Circuit, is a digital I/O chip designed */ /* for the Atari 8-bit family of home computers; it combines functions for */ /* sampling (ADC) potentiometers (such as game paddles) and scan matrices of */ /* switches (such as a computer keyboard) as well as sound generation. */ /* It produces four voices of distinctive square wave sound, either as clear */ /* tones or modified with a number of distortion settings. - Wikipedia */ /* "POKEY" article. */ /* */ /* */ /* (C) 2000 Freddy Offenga <taf_offenga@yahoo.com> */ /* 2019-01-16: Bill Kendrick <nbs@sonic.net>: More defines for registers */ /* */ /* */ /* 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 __POKEY_H #define __POKEY_H /*****************************************************************************/ /* Define a structure with the POKEY register offsets for write (W) */ /*****************************************************************************/ struct __pokey_write { unsigned char audf1; /* audio channel #1 frequency */ unsigned char audc1; /* audio channel #1 control */ unsigned char audf2; /* audio channel #2 frequency */ unsigned char audc2; /* audio channel #2 control */ unsigned char audf3; /* audio channel #3 frequency */ unsigned char audc3; /* audio channel #3 control */ unsigned char audf4; /* audio channel #4 frequency */ unsigned char audc4; /* audio channel #4 control */ unsigned char audctl; /* audio control */ unsigned char stimer; /* start pokey timers */ unsigned char skrest; /* reset serial port status reg.; ** Reset BITs 5 - 7 of the serial port status register (SKCTL) to "1" */ unsigned char potgo; /* start paddle scan sequence (see "ALLPOT") */ unsigned char unuse1; /* unused */ unsigned char serout; /* serial port data output */ unsigned char irqen; /* interrupt request enable */ unsigned char skctl; /* serial port control */ }; /*****************************************************************************/ /* (W) AUDC1-4 register values */ /*****************************************************************************/ /* Meaningful values for the distortion bits. ** The first process is to divide the clock value by the frequency, ** then mask the output using the polys in the order below; ** finally, the result is divided by two. */ #define AUDC_POLYS_5_17 0x00 #define AUDC_POLYS_5 0x20 /* Same as 0x60 */ #define AUDC_POLYS_5_4 0x40 #define AUDC_POLYS_17 0x80 #define AUDC_POLYS_NONE 0xA0 /* Same as 0xE0 */ #define AUDC_POLYS_4 0xC0 /* When set, the volume value in AUDC1-4 bits 0-3 is sent directly to the speaker; ** it is not modulated with the frequency specified in the AUDF1-4 registers. ** (See "De Re Atari" Chapter 7: Sound) */ #define AUDC_VOLUME_ONLY 0x10 /*****************************************************************************/ /* (W) AUDCTL register values */ /*****************************************************************************/ #define AUDCTL_CLOCKBASE_15HZ 0x01 /* Switch main clock base from 64 KHz to 15 KHz */ #define AUDCTL_HIGHPASS_CHAN2 0x02 /* Insert high pass filter into channel two, clocked by channel four */ #define AUDCTL_HIGHPASS_CHAN1 0x04 /* Insert high pass filter into channel one, clocked by channel two */ #define AUDCTL_JOIN_CHAN34 0x08 /* Join channels four and three (16 bit) */ #define AUDCTL_JOIN_CHAN12 0x10 /* Join channels two and one (16 bit) */ #define AUDCTL_CLOCK_CHAN3_179MHZ 0x20 /* Clock channel three with 1.79 MHz */ #define AUDCTL_CLOCK_CHAN1_179MHZ 0x40 /* Clock channel one with 1.79 MHz */ #define AUDCTL_9BIT_POLY 0x80 /* Makes the 17 bit poly counter into nine bit poly (see also: RANDOM) */ /*****************************************************************************/ /* (W) IRQEN register values */ /*****************************************************************************/ #define IRQEN_TIMER_1 0x01 /* The POKEY timer one interrupt is enabled */ #define IRQEN_TIMER_2 0x02 /* The POKEY timer two interrupt is enabled */ #define IRQEN_TIMER_4 0x04 /* The POKEY timer four interrupt is enabled */ #define IRQEN_SERIAL_TRANS_FINISHED 0x08 /* The serial out transmission finished interrupt is enabled */ #define IRQEN_SERIAL_OUT_DATA_REQUIRED 0x10 /* The serial output data required interrupt is enabled */ #define IRQEN_SERIAL_IN_DATA_READY 0x20 /* The serial input data ready interrupt is enabled. */ #define IRQEN_OTHER_KEY 0x40 /* The "other key" interrupt is enabled */ #define IRQEN_BREAK_KEY 0x80 /* The BREAK key is enabled */ /*****************************************************************************/ /* (W) SKCTL register values */ /*****************************************************************************/ #define SKCTL_KEYBOARD_DEBOUNCE 0x01 /* Enable keyboard debounce circuits */ #define SKCTL_KEYBOARD_SCANNING 0x02 /* Enable keyboard scanning circuit */ /* Fast pot scan ** The pot scan counter completes its sequence in two TV line times instead of ** one frame time (228 scan lines). Not as accurate as the normal pot scan */ #define SKCTL_FAST_POT_SCAN 0x04 /* POKEY two-tone mode ** Serial output is transmitted as a two-tone signal rather than a logic true/false. */ #define SKCTL_TWO_TONE_MODE 0x08 /* Force break (serial output to zero) */ #define SKCTL_FORCE_BREAK 0x80 /* Bits 4, 5, and 6 of SKCTL set Serial Mode Control: */ /* Trans. & Receive rates set by external clock; Also internal clock phase reset to zero. */ #define SKCTL_SER_MODE_TX_EXT_RX_EXT 0x00 /* Trans. rate set by external clock; Receive asynch. (ch. 4) (CH3 and CH4). */ #define SKCTL_SER_MODE_TX_EXT_RX_ASYNC 0x10 /* Trans. & Receive rates set by Chan. 4; Chan. 4 output on Bi-Direct. clock line. */ #define SKCTL_SER_MODE_TX_CH4_RX_CH4_BIDIR 0x20 /* N.B.: Bit combination 0,1,1 not useful */ /* Trans. rate set by Chan. 4; Receive rate set by external clock. */ #define SKCTL_SER_MODE_TX_CH4_RX_EXT 0x40 /* N.B.: Bit combination 1,0,1 not useful */ /* Trans. rate set by Chan. 2; Receive rate set by Chan. 4; Chan. 4 out on Bi-Direct. clock line. */ #define SKCTL_SER_MODE_TX_CH2_RX_CH4_BIDIR 0x60 /* Trans. rate set by Chan. 2; Receive asynch. (chan 3 & 4); Bi-Direct. clock not used (tri-state condition). */ #define SKCTL_SER_MODE_TX_CH4_RX_ASYNC 0x70 /*****************************************************************************/ /* Define a structure with the POKEY register offsets for read (R) */ /*****************************************************************************/ struct __pokey_read { unsigned char pot0; /* paddle 0 value */ unsigned char pot1; /* paddle 1 value */ unsigned char pot2; /* paddle 2 value */ unsigned char pot3; /* paddle 3 value */ unsigned char pot4; /* paddle 4 value */ unsigned char pot5; /* paddle 5 value */ unsigned char pot6; /* paddle 6 value */ unsigned char pot7; /* paddle 7 value */ unsigned char allpot; /* eight paddle port status (see "POTGO") */ unsigned char kbcode; /* keyboard code */ unsigned char random; /* random number generator */ unsigned char unuse2; /* unused */ unsigned char unuse3; /* unused */ unsigned char serin; /* serial port input */ unsigned char irqst; /* interrupt request status */ unsigned char skstat; /* serial port status */ }; /*****************************************************************************/ /* (R) SKSTAT register values */ /*****************************************************************************/ #define SKSTAT_SERIN_SHIFTREG_BUSY 0x02 /* Serial input shift register busy */ #define SKSTAT_LASTKEY_PRESSED 0x04 /* the last key is still pressed */ #define SKSTAT_SHIFTKEY_PRESSED 0x08 /* the [Shift] key is pressed */ #define SKSTAT_DATA_READ_INGORING_SHIFTREG 0x10 /* Data can be read directly from the serial input port, ignoring the shift register. */ #define SKSTAT_KEYBOARD_OVERRUN 0x20 /* Keyboard over-run; Reset BITs 7, 6 and 5 (latches) to 1, using SKREST */ #define SKSTAT_INPUT_OVERRUN 0x40 /* Serial data input over-run. Reset latches as above. */ #define SKSTAT_INPUT_FRAMEERROR 0x80 /* Serial data input frame error caused by missing or extra bits. Reset latches as above. */ /* KBCODE, internal keyboard codes for Atari 8-bit computers, ** are #defined as "KEY_..." in "atari.h". ** Note some keys are not read via KBCODE: ** - Reset ** - Start, Select, and Option; see CONSOL in "gtia.h" ** - Break */ /* End of _pokey.h */ #endif /* #ifndef __POKEY_H */ �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/_riot.h���������������������������������������������������������������������������0000664�0000000�0000000�00000002030�13473601511�0015110�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* Atari VCS 2600 RIOT registers addresses */ /* */ /* Source: DASM - vcs.h */ /* */ /* Florent Flament (contact@florentflament.com), 2017 */ /* */ /*****************************************************************************/ /* RIOT registers */ struct __riot { unsigned char swcha; unsigned char swacnt; unsigned char swchb; unsigned char swbcnt; unsigned char intim; unsigned char timint; unsigned char unused[14]; unsigned char tim1t; unsigned char tim8t; unsigned char tim64t; unsigned char t1024t; }; ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/_sid.h����������������������������������������������������������������������������0000664�0000000�0000000�00000007052�13473601511�0014723�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* _sid.h */ /* */ /* Internal include file, do not use directly */ /* */ /* */ /* */ /* (C) 1998-2000 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 __SID_H #define __SID_H /* Define a structure with the sid register offsets */ struct __sid_voice { unsigned freq; /* Frequency */ unsigned pw; /* Pulse width */ unsigned char ctrl; /* Control register */ unsigned char ad; /* Attack/decay */ unsigned char sr; /* Sustain/release */ }; struct __sid { struct __sid_voice v1; /* Voice 1 */ struct __sid_voice v2; /* Voice 2 */ struct __sid_voice v3; /* Voice 3 */ unsigned flt_freq; /* Filter frequency */ unsigned char flt_ctrl; /* Filter control register */ unsigned char amp; /* Amplitude */ unsigned char ad1; /* A/D converter 1 */ unsigned char ad2; /* A/D converter 2 */ unsigned char noise; /* Noise generator */ unsigned char read3; /* Value of voice 3 */ }; /* End of _sid.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/_suzy.h���������������������������������������������������������������������������0000664�0000000�0000000�00000025626�13473601511�0015165�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* _suzy.h */ /* */ /* Atari Lynx, Suzy chip register hardware structures */ /* */ /* */ /* 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 __SUZY_H #define __SUZY_H /* Joypad $FCB0 */ #define JOYPAD_RIGHT 0x10 #define JOYPAD_LEFT 0x20 #define JOYPAD_DOWN 0x40 #define JOYPAD_UP 0x80 #define BUTTON_OPTION1 0x08 #define BUTTON_OPTION2 0x04 #define BUTTON_INNER 0x02 #define BUTTON_OUTER 0x01 /* Switches $FCB1 */ #define BUTTON_PAUSE 0x01 /* Hardware Math */ #define FACTOR_A *(unsigned int *) 0xFC54 #define FACTOR_B *(unsigned int *) 0xFC52 #define PRODUCT0 *(unsigned int *) 0xFC60 #define PRODUCT1 *(unsigned int *) 0xFC62 #define PRODUCT *(long *) 0xFC60 #define DIVIDEND0 *(unsigned int *) 0xFC60 #define DIVIDEND1 *(unsigned int *) 0xFC62 #define DIVIDEND *(long *) 0xFC60 #define DIVISOR *(unsigned int *) 0xFC56 #define QUOTIENT0 *(unsigned int *) 0xFC52 #define QUOTIENT1 *(unsigned int *) 0xFC54 #define QUOTIENT *(long *) 0xFC52 #define REMAINDER0 *(unsigned int *) 0xFC6C #define REMAINDER1 *(unsigned int *) 0xFC6E #define REMAINDER *(long *) 0xFC6C /* Sprite control block (SCB) defines */ /* SPRCTL0 $FC80 */ #define BPP_4 0xC0 #define BPP_3 0x80 #define BPP_2 0x40 #define BPP_1 0x00 #define HFLIP 0x20 #define VFLIP 0x10 #define TYPE_SHADOW 0x07 #define TYPE_XOR 0x06 #define TYPE_NONCOLL 0x05 #define TYPE_NORMAL 0x04 #define TYPE_BOUNDARY 0x03 #define TYPE_BSHADOW 0x02 #define TYPE_BACKNONCOLL 0x01 #define TYPE_BACKGROUND 0x00 /* SPRCTL1 $FC81 */ #define LITERAL 0x80 #define PACKED 0x00 #define ALGO3 0x40 #define RENONE 0x00 #define REHV 0x10 #define REHVS 0x20 #define REHVST 0x30 #define REUSEPAL 0x08 #define SKIP 0x04 #define DRAWUP 0x02 #define DRAWLEFT 0x01 typedef struct SCB_REHVST_PAL { // SCB with all attributes unsigned char sprctl0; unsigned char sprctl1; unsigned char sprcoll; char *next; unsigned char *data; signed int hpos; signed int vpos; unsigned int hsize; unsigned int vsize; unsigned int stretch; unsigned int tilt; unsigned char penpal[8]; } SCB_REHVST_PAL; typedef struct SCB_REHVST { // SCB without pallette unsigned char sprctl0; unsigned char sprctl1; unsigned char sprcoll; char *next; unsigned char *data; signed int hpos; signed int vpos; unsigned int hsize; unsigned int vsize; unsigned int stretch; unsigned int tilt; } SCB_REHVST; typedef struct SCB_REHV { // SCB without stretch/tilt unsigned char sprctl0; unsigned char sprctl1; unsigned char sprcoll; char *next; unsigned char *data; signed int hpos; signed int vpos; unsigned int hsize; unsigned int vsize; } SCB_REHV; typedef struct SCB_REHV_PAL { // SCB without str/tilt, w/ penpal unsigned char sprctl0; unsigned char sprctl1; unsigned char sprcoll; char *next; unsigned char *data; signed int hpos; signed int vpos; unsigned int hsize; unsigned int vsize; unsigned char penpal[8]; } SCB_REHV_PAL; typedef struct SCB_REHVS { // SCB w/o tilt & penpal unsigned char sprctl0; unsigned char sprctl1; unsigned char sprcoll; char *next; unsigned char *data; signed int hpos; signed int vpos; unsigned int hsize; unsigned int vsize; unsigned int stretch; } SCB_REHVS; typedef struct SCB_REHVS_PAL { // SCB w/o tilt w/penpal unsigned char sprctl0; unsigned char sprctl1; unsigned char sprcoll; char *next; unsigned char *data; signed int hpos; signed int vpos; unsigned int hsize; unsigned int vsize; unsigned int stretch; unsigned char penpal[8]; } SCB_REHVS_PAL; typedef struct SCB_RENONE { // SCB w/o size/stretch/tilt/pal unsigned char sprctl0; unsigned char sprctl1; unsigned char sprcoll; char *next; unsigned char *data; signed int hpos; signed int vpos; } SCB_RENONE; typedef struct SCB_RENONE_PAL { // SCB w/o size/str/tilt w/penpal unsigned char sprctl0; unsigned char sprctl1; unsigned char sprcoll; char *next; unsigned char *data; signed int hpos; signed int vpos; unsigned char penpal[8]; } SCB_RENONE_PAL; typedef struct PENPAL_4 { unsigned char penpal[8]; } PENPAL_4; typedef struct PENPAL_3 { unsigned char penpal[4]; } PENPAL_3; typedef struct PENPAL_2 { unsigned char penpal[2]; } PENPAL_2; typedef struct PENPAL_1 { unsigned char penpal[1]; } PENPAL_1; /* Misc system defines */ /* SPRGO $FC91 */ #define EVER_ON 0x04 #define SPRITE_GO 0x01 /* SPRSYS (write) $FC92 */ #define SIGNMATH 0x80 #define ACCUMULATE 0x40 #define NO_COLLIDE 0x20 #define VSTRETCH 0x10 #define LEFTHAND 0x08 #define CLR_UNSAFE 0x04 #define SPRITESTOP 0x02 /* SPRSYS (read) $FC92 */ #define MATHWORKING 0x80 #define MATHWARNING 0x40 #define MATHCARRY 0x20 #define VSTRETCHING 0x10 #define LEFTHANDED 0x08 #define UNSAFE_ACCESS 0x04 #define SPRITETOSTOP 0x02 #define SPRITEWORKING 0x01 /* MAPCTL $FFF9 */ #define HIGHSPEED 0x80 #define VECTORSPACE 0x08 #define ROMSPACE 0x04 #define MIKEYSPACE 0x02 #define SUZYSPACE 0x01 /* Suzy Hardware Registers */ struct __suzy { unsigned int tmpadr; // 0xFC00 Temporary address unsigned int tiltacc; // 0xFC02 Tilt accumulator unsigned int hoff; // 0xFC04 Offset to H edge of screen unsigned int voff; // 0xFC06 Offset to V edge of screen unsigned char *sprbase; // 0xFC08 Base address of sprite unsigned char *colbase; // 0xFC0A Base address of collision buffer unsigned char *vidadr; // 0xFC0C Current vid buffer address unsigned char *coladr; // 0xFC0E Current col buffer address unsigned char *scbnext; // 0xFC10 Address of next SCB unsigned char *sprdline; // 0xFC12 start of sprite data line address unsigned char *hposstrt; // 0xFC14 start hpos unsigned char *vposstrt; // 0xFC16 start vpos unsigned char *sprhsize; // 0xFC18 sprite h size unsigned char *sprvsize; // 0xFC1A sprite v size unsigned int stretchl; // 0xFC1C H size adder unsigned int tilt; // 0xFC1E H pos adder unsigned int sprdoff; // 0xFC20 offset to next sprite data line unsigned int sprvpos; // 0xFC22 current vpos unsigned int colloff; // 0xFC24 offset to collision depository unsigned int vsizeacc; // 0xFC26 vertical size accumulator unsigned int hsizeoff; // 0xFC28 horizontal size offset unsigned int vsizeoff; // 0xFC2A vertical size offset unsigned char *scbaddr; // 0xFC2C address of current SCB unsigned char *procaddr; // 0xFC2E address of current spr data proc unsigned char unused0[32]; // 0xFC30 - 0xFC4F reserved/unused unsigned char unused1[2]; // 0xFC50 - 0xFC51 do not use unsigned char mathd; // 0xFC52 unsigned char mathc; // 0xFC53 unsigned char mathb; // 0xFC54 unsigned char matha; // 0xFC55 unsigned char mathp; // 0xFC56 unsigned char mathn; // 0xFC57 unsigned char unused2[8]; // 0xFC58 - 0xFC5F do not use unsigned char mathh; // 0xFC60 unsigned char mathg; // 0xFC61 unsigned char mathf; // 0xFC62 unsigned char mathe; // 0xFC63 unsigned char unused3[8]; // 0xFC64 - 0xFC6B do not use unsigned char mathm; // 0xFC6C unsigned char mathl; // 0xFC6D unsigned char mathk; // 0xFC6E unsigned char mathj; // 0xFC6F unsigned char unused4[16]; // 0xFC70 - 0xFC7F do not use unsigned char sprctl0; // 0xFC80 sprite control bits 0 unsigned char sprctl1; // 0xFC81 sprite control bits 1 unsigned char sprcoll; // 0xFC82 sprite collision number unsigned char sprinit; // 0xFC83 sprite initialization bits unsigned char unused5[4]; // 0xFC84 - 0xFC87 unused unsigned char suzyhrev; // 0xFC88 suzy hardware rev unsigned char suzysrev; // 0xFC89 suzy software rev unsigned char unused6[6]; // 0xFC8A - 0xFC8F unused unsigned char suzybusen; // 0xFC90 suzy bus enable unsigned char sprgo; // 0xFC91 sprite process start bit unsigned char sprsys; // 0xFC92 sprite system control bits unsigned char unused7[29]; // 0xFC93 - 0xFCAF unused unsigned char joystick; // 0xFCB0 joystick and buttons unsigned char switches; // 0xFCB1 other switches unsigned char cart0; // 0xFCB2 cart0 r/w unsigned char cart1; // 0xFCB3 cart1 r/w unsigned char unused8[8]; // 0xFCB4 - 0xFCBF unused unsigned char leds; // 0xFCC0 leds unsigned char unused9; // 0xFCC1 unused unsigned char parstat; // 0xFCC2 parallel port status unsigned char pardata; // 0xFCC3 parallel port data unsigned char howie; // 0xFCC4 howie (?) // 0xFCC5 - 0xFCFF unused }; #endif ����������������������������������������������������������������������������������������������������������cc65-2.18/include/_ted.h����������������������������������������������������������������������������0000664�0000000�0000000�00000011632�13473601511�0014717�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* _ted.h */ /* */ /* Internal include file, do not use directly */ /* */ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef __TED_H #define __TED_H /* Define a structure with the ted register offsets */ struct __ted { unsigned char t1_lo; /* Timer #1 low */ unsigned char t1_hi; /* Timer #1 high */ unsigned char t2_lo; /* Timer #2 low */ unsigned char t2_hi; /* Timer #2 high */ unsigned char t3_lo; /* Timer #3 low */ unsigned char t3_hi; /* Timer #3 high */ unsigned char vscroll; /* Vertical scroll control */ unsigned char hscroll; /* Horizontal scroll control */ unsigned char kbdlatch; /* Keyboard latch */ unsigned char irr; /* Interrupt request register */ unsigned char imr; /* Interrupt mask register */ unsigned char irq_rasterline; /* Interrupt rasterline */ unsigned char cursor_hi; /* Cursor position high */ unsigned char cursor_lo; /* Cursor position low */ unsigned char snd1_freq_lo; /* Channel #1 frequency */ unsigned char snd2_freq_lo; /* Channel #2 frequency low */ unsigned char snd2_freq_hi; /* Channel #2 frequency high */ unsigned char snd_ctrl; /* Sound control */ unsigned char misc; /* Channel #1 frequency high and more */ unsigned char char_addr; /* Character data base address */ unsigned char video_addr; /* Video memory base address */ unsigned char bgcolor; /* Background color */ unsigned char color1; /* Color register #1 */ unsigned char color2; /* Color register #2 */ unsigned char color3; /* Color register #3 */ unsigned char bordercolor; /* Border color */ unsigned char bmap_reload_hi; /* Bitmap reload bits 8+9 */ unsigned char bmap_reload_lo; /* Bitmap reload bits 0-7 */ unsigned char rasterline_hi; /* Current rasterline bit 8 */ unsigned char rasterline_lo; /* Current rasterline bits 0-7 */ unsigned char rastercolumn; /* Current rastercolumn */ unsigned char cursor_blink; /* Cursor blink attribute */ unsigned char unused[30]; /* Unused */ unsigned char enable_rom; /* Write enables ROM */ unsigned char enable_ram; /* Write enables RAM */ }; /* End of _ted.h */ #endif ������������������������������������������������������������������������������������������������������cc65-2.18/include/_tia.h����������������������������������������������������������������������������0000664�0000000�0000000�00000005107�13473601511�0014720�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* Atari VCS 2600 TIA registers addresses */ /* */ /* Source: DASM - vcs.h */ /* */ /* Florent Flament (contact@florentflament.com), 2017 */ /* */ /*****************************************************************************/ /* TIA write / read registers */ struct __tia { union { unsigned char vsync; unsigned char cxm0p; }; union { unsigned char vblank; unsigned char cxm1p; }; union { unsigned char wsync; unsigned char cxp0fb; }; union { unsigned char rsync; unsigned char cxp1fb; }; union { unsigned char nusiz0; unsigned char cxm0fb; }; union { unsigned char nusiz1; unsigned char cxm1fb; }; union { unsigned char colup0; unsigned char cxblpf; }; union { unsigned char colup1; unsigned char cxppmm; }; union { unsigned char colupf; unsigned char inpt0; }; union { unsigned char colubk; unsigned char inpt1; }; union { unsigned char ctrlpf; unsigned char inpt2; }; union { unsigned char refp0; unsigned char inpt3; }; union { unsigned char refp1; unsigned char inpt4; }; union { unsigned char pf0; unsigned char inpt5; }; unsigned char pf1; unsigned char pf2; unsigned char resp0; unsigned char resp1; unsigned char resm0; unsigned char resm1; unsigned char resbl; unsigned char audc0; unsigned char audc1; unsigned char audf0; unsigned char audf1; unsigned char audv0; unsigned char audv1; unsigned char grp0; unsigned char grp1; unsigned char enam0; unsigned char enam1; unsigned char enabl; unsigned char hmp0; unsigned char hmp1; unsigned char hmm0; unsigned char hmm1; unsigned char hmbl; unsigned char vdelp0; unsigned char vdelp1; unsigned char vdelbl; unsigned char resmp0; unsigned char resmp1; unsigned char hmove; unsigned char hmclr; unsigned char cxclr; }; ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/_vdc.h����������������������������������������������������������������������������0000664�0000000�0000000�00000005413�13473601511�0014717�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* _vdc.h */ /* */ /* Internal include file, do not use directly */ /* */ /* */ /* */ /* (C) 1998-2000 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 __VDC_H #define __VDC_H /* Define a structure with the vdc register offsets */ struct __vdc { unsigned char ctrl; /* Control register */ unsigned char data; /* Data register */ }; /* End of _vdc.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/_vic.h����������������������������������������������������������������������������0000664�0000000�0000000�00000007204�13473601511�0014724�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* _vic.h */ /* */ /* Internal include file, do not use directly */ /* */ /* */ /* */ /* (C) 2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 __VIC_H #define __VIC_H /* Define a structure with the vic register offsets */ struct __vic { unsigned char leftborder; unsigned char upperborder; unsigned char charsperline; /* Characters per line */ unsigned char linecount; /* Number of lines */ unsigned char rasterline; /* Current raster line */ unsigned char addr; /* Address of chargen and video ram */ unsigned char strobe_x; /* Light pen, X position */ unsigned char strobe_y; /* Light pen, Y position */ unsigned char analog_x; /* Analog input X */ unsigned char analog_y; /* Analog input Y */ unsigned char voice1; /* Sound generator #1 */ unsigned char voice2; /* Sound generator #2 */ unsigned char voice3; /* Sound generator #3 */ unsigned char noise; /* Noise generator */ unsigned char volume_color; /* Bits 0..3: volume, 4..7: color */ unsigned char bg_border_color;/* Background and border color */ }; /* End of _vic.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/_vic2.h���������������������������������������������������������������������������0000664�0000000�0000000�00000025123�13473601511�0015006�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* _vic2.h */ /* */ /* Internal include file, do not use directly */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef __VIC2_H #define __VIC2_H /* Define a structure with the vic register offsets. In cc65 mode, there ** are aliases for the field accessible as arrays. */ #if __CC65_STD__ == __CC65_STD_CC65__ struct __vic2 { union { struct { unsigned char spr0_x; /* Sprite 0, X coordinate */ unsigned char spr0_y; /* Sprite 0, Y coordinate */ unsigned char spr1_x; /* Sprite 1, X coordinate */ unsigned char spr1_y; /* Sprite 1, Y coordinate */ unsigned char spr2_x; /* Sprite 2, X coordinate */ unsigned char spr2_y; /* Sprite 2, Y coordinate */ unsigned char spr3_x; /* Sprite 3, X coordinate */ unsigned char spr3_y; /* Sprite 3, Y coordinate */ unsigned char spr4_x; /* Sprite 4, X coordinate */ unsigned char spr4_y; /* Sprite 4, Y coordinate */ unsigned char spr5_x; /* Sprite 5, X coordinate */ unsigned char spr5_y; /* Sprite 5, Y coordinate */ unsigned char spr6_x; /* Sprite 6, X coordinate */ unsigned char spr6_y; /* Sprite 6, Y coordinate */ unsigned char spr7_x; /* Sprite 7, X coordinate */ unsigned char spr7_y; /* Sprite 7, Y coordinate */ }; struct { unsigned char x; /* X coordinate */ unsigned char y; /* Y coordinate */ } spr_pos[8]; }; unsigned char spr_hi_x; /* High bits of X coordinate */ unsigned char ctrl1; /* Control register 1 */ unsigned char rasterline; /* Current raster line */ union { struct { unsigned char strobe_x; /* Light pen, X position */ unsigned char strobe_y; /* Light pen, Y position */ }; struct { unsigned char x; /* Light pen, X position */ unsigned char y; /* Light pen, Y position */ } strobe; }; unsigned char spr_ena; /* Enable sprites */ unsigned char ctrl2; /* Control register 2 */ unsigned char spr_exp_y; /* Expand sprites in Y dir */ unsigned char addr; /* Address of chargen and video ram */ unsigned char irr; /* Interrupt request register */ unsigned char imr; /* Interrupt mask register */ unsigned char spr_bg_prio; /* Priority to background */ unsigned char spr_mcolor; /* Sprite multicolor bits */ unsigned char spr_exp_x; /* Expand sprites in X dir */ unsigned char spr_coll; /* Sprite/sprite collision reg */ unsigned char spr_bg_coll; /* Sprite/background collision reg */ unsigned char bordercolor; /* Border color */ union { struct { unsigned char bgcolor0; /* Background color 0 */ unsigned char bgcolor1; /* Background color 1 */ unsigned char bgcolor2; /* Background color 2 */ unsigned char bgcolor3; /* Background color 3 */ }; unsigned char bgcolor[4]; /* Background colors */ }; union { struct { unsigned char spr_mcolor0; /* Color 0 for multicolor sprites */ unsigned char spr_mcolor1; /* Color 1 for multicolor sprites */ }; /* spr_color is already used ... */ unsigned char spr_mcolors[2]; /* Color for multicolor sprites */ }; union { struct { unsigned char spr0_color; /* Color sprite 0 */ unsigned char spr1_color; /* Color sprite 1 */ unsigned char spr2_color; /* Color sprite 2 */ unsigned char spr3_color; /* Color sprite 3 */ unsigned char spr4_color; /* Color sprite 4 */ unsigned char spr5_color; /* Color sprite 5 */ unsigned char spr6_color; /* Color sprite 6 */ unsigned char spr7_color; /* Color sprite 7 */ }; unsigned char spr_color[8]; /* Colors for the sprites */ }; /* The following ones are only valid in the C128: */ unsigned char x_kbd; /* Additional keyboard lines */ unsigned char clock; /* Clock switch bit */ }; #else struct __vic2 { unsigned char spr0_x; /* Sprite 0, X coordinate */ unsigned char spr0_y; /* Sprite 0, Y coordinate */ unsigned char spr1_x; /* Sprite 1, X coordinate */ unsigned char spr1_y; /* Sprite 1, Y coordinate */ unsigned char spr2_x; /* Sprite 2, X coordinate */ unsigned char spr2_y; /* Sprite 2, Y coordinate */ unsigned char spr3_x; /* Sprite 3, X coordinate */ unsigned char spr3_y; /* Sprite 3, Y coordinate */ unsigned char spr4_x; /* Sprite 4, X coordinate */ unsigned char spr4_y; /* Sprite 4, Y coordinate */ unsigned char spr5_x; /* Sprite 5, X coordinate */ unsigned char spr5_y; /* Sprite 5, Y coordinate */ unsigned char spr6_x; /* Sprite 6, X coordinate */ unsigned char spr6_y; /* Sprite 6, Y coordinate */ unsigned char spr7_x; /* Sprite 7, X coordinate */ unsigned char spr7_y; /* Sprite 7, Y coordinate */ unsigned char spr_hi_x; /* High bits of X coordinate */ unsigned char ctrl1; /* Control register 1 */ unsigned char rasterline; /* Current raster line */ unsigned char strobe_x; /* Light pen, X position */ unsigned char strobe_y; /* Light pen, Y position */ unsigned char spr_ena; /* Enable sprites */ unsigned char ctrl2; /* Control register 2 */ unsigned char spr_exp_y; /* Expand sprites in Y dir */ unsigned char addr; /* Address of chargen and video ram */ unsigned char irr; /* Interrupt request register */ unsigned char imr; /* Interrupt mask register */ unsigned char spr_bg_prio; /* Priority to background */ unsigned char spr_mcolor; /* Sprite multicolor bits */ unsigned char spr_exp_x; /* Expand sprites in X dir */ unsigned char spr_coll; /* Sprite/sprite collision reg */ unsigned char spr_bg_coll; /* Sprite/background collision reg */ unsigned char bordercolor; /* Border color */ unsigned char bgcolor0; /* Background color 0 */ unsigned char bgcolor1; /* Background color 1 */ unsigned char bgcolor2; /* Background color 2 */ unsigned char bgcolor3; /* Background color 3 */ unsigned char spr_mcolor0; /* Color 0 for multicolor sprites */ unsigned char spr_mcolor1; /* Color 1 for multicolor sprites */ unsigned char spr0_color; /* Color sprite 0 */ unsigned char spr1_color; /* Color sprite 1 */ unsigned char spr2_color; /* Color sprite 2 */ unsigned char spr3_color; /* Color sprite 3 */ unsigned char spr4_color; /* Color sprite 4 */ unsigned char spr5_color; /* Color sprite 5 */ unsigned char spr6_color; /* Color sprite 6 */ unsigned char spr7_color; /* Color sprite 7 */ /* The following ones are only valid in the C128: */ unsigned char x_kbd; /* Additional keyboard lines */ unsigned char clock; /* Clock switch bit */ }; #endif /* End of _vic2.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/accelerator.h���������������������������������������������������������������������0000664�0000000�0000000�00000025400�13473601511�0016266�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* accelerator.h */ /* */ /* Accelerator specific definitions */ /* */ /* */ /* */ /* (C) 2018 Marco van den Heuvel */ /* EMail: blackystardust68@yahoo.com */ /* */ /* */ /* 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 _ACCELERATOR_H #define _ACCELERATOR_H /*****************/ /* Speed defines */ /*****************/ #define SPEED_SLOW 0x00 #define SPEED_FAST 0xFF #define SPEED_1X SPEED_SLOW #define SPEED_2X 2 - 1 /* C64 Chameleon, C64DTV, C128, PET 65816, Apple2 Fast Chip, Apple2 TransWarp, Apple2 Zip Chip */ #define SPEED_3X 3 - 1 /* C64 Chameleon, C65, PET 65816, Apple2 Booster, Apple 2 Fast Chip, Apple2 Titan, Apple2 TransWarp, Apple2 Zip Chip */ #define SPEED_4X 4 - 1 /* C64 Chameleon, C64 TurboMaster, C64 TurboProcess, PET 65816, Apple2 Fast Chip, Apple2 Zip Chip */ #define SPEED_5X 5 - 1 /* C64 Chameleon, PET 65816, Apple2 Fast Chip */ #define SPEED_6X 6 - 1 /* C64 Chameleon, PET 65816, Apple2 Fast Chip */ #define SPEED_7X 7 - 1 /* PET 65816, Apple2 Fast Chip */ #define SPEED_8X 8 - 1 /* C64 Flash8, PET 65816, Apple 2 Fast Chip */ #define SPEED_10X 10 - 1 /* PET 65816, Apple2 Fast Chip */ #define SPEED_12X 12 - 1 /* Apple2 Fast Chip */ #define SPEED_16X 16 - 1 /* Apple2 Fast Chip */ #define SPEED_20X 20 - 1 /* C64/C128 SuperCPU */ /***********************************/ /* Accelerator function prototypes */ /***********************************/ /* C64/C128 SuperCPU cartridge */ unsigned char __fastcall__ set_scpu_speed (unsigned char speed); /* Set the speed of the SuperCPU cartridge, using SPEED_SLOW will switch to * 1 Mhz mode, SPEED_20X or SPEED_FAST will switch to 20 Mhz mode. * * Note that any value lower than SPEED_20X will switch to 1 Mhz mode, and * any value higher or equal to SPEED_20X will switch to 20 Mhz mode. * * This function will return the actual speed the CPU is at after trying * to set the requested speed, if this is not the speed that was requested * then possibly the hardware speed switch prevented any software speed * switching. * * This function does not check for the presence of the SuperCPU cartridge, * make sure you use 'detect_scpu();' before using. */ unsigned char get_scpu_speed (void); /* Get the speed of the SuperCPU cartridge. * * Possible return values: * SPEED_1X : 1 Mhz mode * SPEED_20X : 20 Mhz mode * * This function does not check for the presence of the SuperCPU cartridge, * make sure you use 'detect_scpu();' before using. */ unsigned char detect_scpu (void); /* Check for the presence of the SuperCPU cartridge. * * Possible return values: * 0x00 : SuperCPU cartridge not present * 0x01 : SuperCPU cartridge present */ /* C64DTV */ unsigned char __fastcall__ set_c64dtv_speed (unsigned char speed); /* Set the speed of the C64DTV, using SPEED_SLOW will switch to * slow mode, SPEED_2X or SPEED_FAST will switch to fast mode. * * Note that any value higher or equal to SPEED_2X will switch to fast mode. * * This function will return the actual speed the CPU is at after trying * to set the requested speed, to my knowledge the switch should not fail. * * This function does not check for the presence of the C64DTV, * make sure you use 'detect_c64dtv();' before using. */ unsigned char get_c64dtv_speed (void); /* Get the speed of the C64DTV. * * Possible return values: * SPEED_1X : slow mode * SPEED_2X : fast mode * * This function does not check for the presence of the C64DTV, * make sure you use 'detect_c64dtv();' before using. */ unsigned char detect_c64dtv (void); /* Check for the presence of the C64DTV. * * Possible return values: * 0x00 : C64DTV not present * 0x01 : C64DTV present */ /* C128 8502 CPU */ unsigned char __fastcall__ set_c128_speed (unsigned char speed); /* Set the speed of the C128 8502 CPU, using SPEED_SLOW will switch to * 1 Mhz (slow) mode, SPEED_2X or SPEED_FAST will switch to 2Mhz (fast) mode. * * Note that any value higher or equal to SPEED_2X will switch to fast mode. * * This function will return the actual speed the CPU is at after trying * to set the requested speed, to my knowledge the switching should not fail. * * This function does not check if the C128 CPU is the current CPU, make sure * you use 'detect_c128();' before using. */ unsigned char get_c128_speed (void); /* Get the speed of the C128 8502 CPU. * * Possible return values: * SPEED_SLOW : Slow mode * SPEED_2X : Fast mode * * This function does not check if the C128 CPU is the current CPU, make sure * you use 'detect_c128();' before using. */ unsigned char detect_c128 (void); /* Check if the C128 CPU is the current CPU. * * Possible return values: * 0x00 : C128 CPU is not the current CPU * 0x01 : C128 CPU is the current CPU */ /* C64 Chameleon cartridge */ unsigned char __fastcall__ set_chameleon_speed (unsigned char speed); /* Set the speed of the C64 Chameleon cartridge, the following inputs * are accepted: * SPEED_SLOW : 1 Mhz mode * SPEED_1X : 1 Mhz mode * SPEED_2X : 2 Mhz mode * SPEED_3X : 3 Mhz mode * SPEED_4X : 4 Mhz mode * SPEED_5X : 5 Mhz mode * SPEED_6X : 6 Mhz mode * SPEED_FAST : Maximum speed mode * * Note that any value higher or equal to SPEED_7X will switch to maximum * speed mode. * * This function will return the actual speed the CPU is at after trying * to set the requested speed, to my knowledge the switching should not fail. * * This function does not check for the presence of the C64 Chameleon cartridge, * make sure you use 'detect_chameleon();' before using. */ unsigned char get_chameleon_speed (void); ;/* Get the speed of the C64 Chameleon cartridge. ; * ; * Possible return values: ; * SPEED_SLOW : Slow mode ; * SPEED_2X : 2Mhz mode ; * SPEED_3X : 3Mhz mode ; * SPEED_4X : 4Mhz mode ; * SPEED_5X : 5Mhz mode ; * SPEED_6X : 6Mhz mode ; * SPEED_FAST : Maximum speed mode ; * ; * This function does not check for the presence of the C64 Chameleon cartridge, ; * make sure you use 'detect_chameleon();' before using. ; */ unsigned char detect_chameleon (void); /* Check for the presence of the C64 Chameleon cartridge. * * Possible return values: * 0x00 : C64 Chameleon cartridge not present * 0x01 : C64 Chameleon cartridge present */ /* C65/C64DX in C64 mode */ unsigned char __fastcall__ set_c65_speed (unsigned char speed); /* Set the speed of the C65/C64DX CPU, using SPEED_SLOW will switch to * 1 Mhz mode, SPEED_3X or SPEED_FAST will switch to 3.5 Mhz (fast) mode. * * Note that any value higher or equal to SPEED_3X will switch to fast mode. * * This function will return the actual speed the CPU is at after trying * to set the requested speed, to my knowledge the switching should not fail. * * This function does not check for the presence of a C65/C64DX in C64 mode, * make sure you use 'detect_c65();' before using. */ unsigned char get_c65_speed (void); /* Get the speed of the C65/C64DX CPU. * * Possible return values: * SPEED_SLOW : Slow mode * SPEED_3X : Fast mode * * This function does not check for the presence of a C65/C64DX in C64 mode, * make sure you use 'detect_c65();' before using. */ unsigned char detect_c65 (void); /* Check for the presence of a C65/C64DX in C64 mode. * * Possible return values: * 0x00 : C65/C64DX in C64 mode not present * 0x01 : C65/C64DX in C64 mode present */ /* C64 Turbo Master cartridge */ unsigned char __fastcall__ set_turbomaster_speed (unsigned char speed); /* Set the speed of the Turbo Master cartridge, using SPEED_SLOW will switch to * 1 Mhz mode, SPEED_4X or SPEED_FAST will switch to 4 Mhz mode. * * Note that any value higher or equal to SPEED_4X will switch to 4 Mhz mode, * any value lower than SPEED_4X will switch to 1 Mhz mode. * * This function will return the actual speed the CPU is at after trying * to set the requested speed, if the speed is different it might indicate * that the hardware switch has locked the speed. * * This function does not check for the presence of a Turbo Master cartridge, * make sure you use 'detect_turbomaster();' before using. */ unsigned char get_turbomaster_speed (void); /* Get the speed of the Turbo Master cartridge. * * Possible return values: * SPEED_SLOW : 1 Mhz mode * SPEED_4X : 4 Mhz mode * * This function does not check for the presence of a Turbo Master cartridge, * make sure you use 'detect_turbomaster();' before using. */ unsigned char detect_turbomaster (void); /* Check for the presence of a C64 Turbo Master cartridge. * * Possible return values: * 0x00 : C64 Turbo Master cartridge not present * 0x01 : C64 Turbo Master cartridge present */ /* End of accelerator.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/apple2.h��������������������������������������������������������������������������0000664�0000000�0000000�00000017455�13473601511�0015200�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* apple2.h */ /* */ /* Apple ][ system specific definitions */ /* */ /* */ /* */ /* (C) 2000 Kevin Ruland, <kevin@rodin.wustl.edu> */ /* (C) 2003 Ullrich von Bassewitz, <uz@cc65.org> */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _APPLE2_H #define _APPLE2_H /* Check for errors */ #if !defined(__APPLE2__) # error This module may only be used when compiling for the Apple ][! #endif #include <apple2_filetype.h> /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Color defines */ #define COLOR_BLACK 0x00 #define COLOR_WHITE 0x01 /* TGI color defines */ #define TGI_COLOR_BLACK 0x00 #define TGI_COLOR_GREEN 0x01 #define TGI_COLOR_VIOLET 0x02 #define TGI_COLOR_WHITE 0x03 #define TGI_COLOR_BLACK2 0x04 #define TGI_COLOR_ORANGE 0x05 #define TGI_COLOR_BLUE 0x06 #define TGI_COLOR_WHITE2 0x07 #define TGI_COLOR_MAGENTA TGI_COLOR_BLACK2 #define TGI_COLOR_DARKBLUE TGI_COLOR_WHITE2 #define TGI_COLOR_DARKGREEN 0x08 #define TGI_COLOR_GRAY 0x09 #define TGI_COLOR_CYAN 0x0A #define TGI_COLOR_BROWN 0x0B #define TGI_COLOR_GRAY2 0x0C #define TGI_COLOR_PINK 0x0D #define TGI_COLOR_YELLOW 0x0E #define TGI_COLOR_AQUA 0x0F /* Characters codes */ #define CH_ENTER 0x0D #define CH_ESC 0x1B #define CH_CURS_LEFT 0x08 #define CH_CURS_RIGHT 0x15 #if !defined(__APPLE2ENH__) #define CH_HLINE '-' #define CH_VLINE '!' #define CH_ULCORNER '+' #define CH_URCORNER '+' #define CH_LLCORNER '+' #define CH_LRCORNER '+' #define CH_TTEE '+' #define CH_BTEE '+' #define CH_LTEE '+' #define CH_RTEE '+' #define CH_CROSS '+' #endif /* Masks for joy_read */ #define JOY_UP_MASK 0x10 #define JOY_DOWN_MASK 0x20 #define JOY_LEFT_MASK 0x04 #define JOY_RIGHT_MASK 0x08 #define JOY_BTN_1_MASK 0x40 #define JOY_BTN_2_MASK 0x80 /* Return codes for get_ostype */ #define APPLE_UNKNOWN 0x00 #define APPLE_II 0x10 /* Apple ][ */ #define APPLE_IIPLUS 0x11 /* Apple ][+ */ #define APPLE_IIIEM 0x20 /* Apple /// (emulation) */ #define APPLE_IIE 0x30 /* Apple //e */ #define APPLE_IIEENH 0x31 /* Apple //e (enhanced) */ #define APPLE_IIECARD 0x40 /* Apple //e Option Card */ #define APPLE_IIC 0x50 /* Apple //c */ #define APPLE_IIC35 0x51 /* Apple //c (3.5 ROM) */ #define APPLE_IICEXP 0x53 /* Apple //c (Mem. Exp.) */ #define APPLE_IICREV 0x54 /* Apple //c (Rev. Mem. Exp.) */ #define APPLE_IICPLUS 0x55 /* Apple //c Plus */ #define APPLE_IIGS 0x80 /* Apple IIgs */ #define APPLE_IIGS1 0x81 /* Apple IIgs (ROM 1) */ #define APPLE_IIGS3 0x83 /* Apple IIgs (ROM 3) */ extern unsigned char _dos_type; /* Valid _dos_type values: ** ** AppleDOS 3.3 - 0x00 ** ProDOS 8 1.0.1 - 0x10 ** ProDOS 8 1.0.2 - 0x10 ** ProDOS 8 1.1.1 - 0x11 ** ProDOS 8 1.2 - 0x12 ** ProDOS 8 1.3 - 0x13 ** ProDOS 8 1.4 - 0x14 ** ProDOS 8 1.5 - 0x15 ** ProDOS 8 1.6 - 0x16 ** ProDOS 8 1.7 - 0x17 ** ProDOS 8 1.8 - 0x18 ** ProDOS 8 1.9 - 0x18 (!) ** ProDOS 8 2.0.1 - 0x21 ** ProDOS 8 2.0.2 - 0x22 ** ProDOS 8 2.0.3 - 0x23 ** ProDOS 8 2.4.x - 0x24 */ /*****************************************************************************/ /* Variables */ /*****************************************************************************/ /* The file stream implementation and the POSIX I/O functions will use the ** following struct to set the date and time stamp on files. This specificially ** applies to the open and fopen functions. */ extern struct { struct { unsigned day :5; unsigned mon :4; unsigned year :7; } createdate; /* Current date: 0 */ struct { unsigned char min; unsigned char hour; } createtime; /* Current time: 0 */ } _datetime; /* The addresses of the static drivers */ #if !defined(__APPLE2ENH__) extern void a2_auxmem_emd[]; extern void a2_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */ extern void a2_stdmou_mou[]; /* Referred to by mouse_static_stddrv[] */ extern void a2_ssc_ser[]; extern void a2_hi_tgi[]; /* Referred to by tgi_static_stddrv[] */ extern void a2_lo_tgi[]; #endif /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned char get_ostype (void); /* Get the machine type. Returns one of the APPLE_xxx codes. */ void rebootafterexit (void); /* Reboot machine after program termination has completed. */ #define ser_apple2_slot(num) ser_ioctl (0, (void*) (num)) /* Select a slot number from 1 to 7 prior to ser_open. ** The default slot number is 2. */ #define tgi_apple2_mix(onoff) tgi_ioctl (0, (void*) (onoff)) /* If onoff is 1, graphics/text mixed mode is enabled. ** If onoff is 0, graphics/text mixed mode is disabled. */ /* The following #defines will cause the matching functions calls in conio.h ** to be overlaid by macros with the same names, saving the function call ** overhead. */ #define _textcolor(color) COLOR_WHITE #define _bgcolor(color) COLOR_BLACK #define _bordercolor(color) COLOR_BLACK /* End of apple2.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/apple2_filetype.h�����������������������������������������������������������������0000664�0000000�0000000�00000041312�13473601511�0017066�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* apple2_filetype.h */ /* */ /* Apple ][ file type definitions */ /* */ /* */ /* */ /* (C) 2017 Bill Chatfield, <bill_chatfield@yahoo.com> */ /* */ /* */ /* 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 _APPLE2_FILETYPE_H #define _APPLE2_FILETYPE_H /* Check for errors */ #if !defined(__APPLE2__) # error This module may only be used when compiling for the Apple ][! #endif /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* ProDOS general file types */ #define PRODOS_T_UNK 0x00 /* Unknown */ #define PRODOS_T_BAD 0x01 /* Bad blocks */ #define PRODOS_T_PCD 0x02 /* Pascal code */ #define PRODOS_T_PTX 0x03 /* Pascal text */ #define PRODOS_T_TXT 0x04 /* ASCII text */ #define PRODOS_T_PDA 0x05 /* Pascal data */ #define PRODOS_T_BIN 0x06 /* Binary */ #define PRODOS_T_FNT 0x07 /* Apple III font */ #define PRODOS_T_FOT 0x08 /* Hi-res, dbl hi-res graphics */ #define PRODOS_T_BA3 0x09 /* Apple III BASIC program */ #define PRODOS_T_DA3 0x09 /* Apple III BASIC data */ #define PRODOS_T_WPF 0x0A /* Generic word processing */ #define PRODOS_T_SOS 0x0B /* SOS system */ #define PRODOS_T_DIR 0x0F /* ProDOS directory */ /* ProDOS productivity file types */ #define PRODOS_T_RPD 0x10 /* RPS data */ #define PRODOS_T_RPI 0x11 /* RPS index */ #define PRODOS_T_AFD 0x12 /* AppleFile discard */ #define PRODOS_T_AFM 0x13 /* AppleFile model */ #define PRODOS_T_AFR 0x14 /* AppleFile report */ #define PRODOS_T_SCL 0x15 /* Screen library */ #define PRODOS_T_PFS 0x16 /* PFS document */ #define PRODOS_T_ADB 0x19 /* AppleWorks database */ #define PRODOS_T_AWP 0x1A /* AppleWorks word processing */ #define PRODOS_T_ASP 0x1B /* AppleWorks spreadsheet */ /* ProDOS code file types */ #define PRODOS_T_TDM 0x20 /* Desktop Manager */ #define PRODOS_T_IPS 0x21 /* Instant Pascal source */ #define PRODOS_T_UPV 0x22 /* USCD Pascal volume */ #define PRODOS_T_3SD 0x29 /* SOS directory */ #define PRODOS_T_8SC 0x2A /* Source code */ #define PRODOS_T_8OB 0x2B /* Object code */ #define PRODOS_T_8IC 0x2C /* Interpreted code */ #define PRODOS_T_8LD 0x2D /* Language data */ #define PRODOS_T_P8C 0x2E /* ProDOS 8 code module */ /* ProDOS miscellaneous file types */ #define PRODOS_T_OCR 0x41 /* Optical char recognition */ #define PRODOS_T_FTD 0x42 /* File type definitions */ /* ProDOS Apple IIgs general file types */ #define PRODOS_T_GWP 0x50 /* Apple IIgs word processing */ #define PRODOS_T_GSS 0x51 /* Apple IIgs spreadsheet */ #define PRODOS_T_GDB 0x52 /* Apple IIgs database */ #define PRODOS_T_DRW 0x53 /* Object oriented graphics */ #define PRODOS_T_GDP 0x54 /* Apple IIgs desktop publish */ #define PRODOS_T_HMD 0x55 /* HyperMedia */ #define PRODOS_T_EDU 0x56 /* Educational program data */ #define PRODOS_T_STN 0x57 /* Stationary */ #define PRODOS_T_HLP 0x58 /* Help */ #define PRODOS_T_COM 0x59 /* Communications */ #define PRODOS_T_CFG 0x5A /* Configuration */ #define PRODOS_T_ANM 0x5B /* Animation */ #define PRODOS_T_MUM 0x5C /* Multimedia */ #define PRODOS_T_ENT 0x5D /* Entertainment */ #define PRODOS_T_DVU 0x5E /* Development utility */ /* ProDOS PC Transporter file types */ #define PRODOS_T_PRE 0x60 /* PC pre-boot */ #define PRODOS_T_BIO 0x6B /* PC BIOS */ #define PRODOS_T_NCF 0x66 /* ProDOS File Nav command file */ #define PRODOS_T_DVR 0x6D /* PC driver */ #define PRODOS_T_PRE2 0x6E /* PC pre-boot */ #define PRODOS_T_HDV 0x6F /* PC hard disk image */ /* ProDOS Kreative Software file types */ #define PRODOS_T_SN2 0x70 /* Sabine's Notebook 2.0 */ #define PRODOS_T_KMT 0x71 #define PRODOS_T_DSR 0x72 #define PRODOS_T_BAN 0x73 #define PRODOS_T_CG7 0x74 #define PRODOS_T_TNJ 0x75 #define PRODOS_T_SA7 0x76 #define PRODOS_T_KES 0x77 #define PRODOS_T_JAP 0x78 #define PRODOS_T_CSL 0x79 #define PRODOS_T_TME 0x7A #define PRODOS_T_TLB 0x7B #define PRODOS_T_MR7 0x7C #define PRODOS_T_MLR 0x7D /* Mika City */ #define PRODOS_T_MMM 0x7E #define PRODOS_T_JCP 0x7F /* ProDOS GEOS file types */ #define PRODOS_T_GES 0x80 /* GEOS system file */ #define PRODOS_T_GEA 0x81 /* GEOS desk accessory */ #define PRODOS_T_GEO 0x82 /* GEOS application */ #define PRODOS_T_GED 0x83 /* GEOS document */ #define PRODOS_T_GEF 0x84 /* GEOS font */ #define PRODOS_T_GEP 0x85 /* GEOS printer driver */ #define PRODOS_T_GEI 0x86 /* GEOS input driver */ #define PRODOS_T_GEX 0x87 /* GEOS auxiliary driver */ #define PRODOS_T_GEV 0x89 /* GEOS swap file */ #define PRODOS_T_GEC 0x8B /* GEOS clock driver */ #define PRODOS_T_GEK 0x8C /* GEOS interface card driver */ #define PRODOS_T_GEW 0x8D /* GEOS formatting data */ /* ProDOS Apple IIgs BASIC file types */ #define PRODOS_T_WP 0xA0 /* WordPerfect */ #define PRODOS_T_GSB 0xAB /* Apple IIgs BASIC program */ #define PRODOS_T_TDF 0xAB /* Apple IIgs BASIC TDF */ #define PRODOS_T_BDF 0xAB /* Apple IIgs BASIC data */ /* ProDOS Apple IIgs system file types */ #define PRODOS_T_SRC 0xB0 /* Apple IIgs source code */ #define PRODOS_T_OBJ 0xB1 /* Apple IIgs object code */ #define PRODOS_T_LIB 0xB2 /* Apple IIgs library */ #define PRODOS_T_S16 0xB3 /* Apple IIgs application pgm */ #define PRODOS_T_RTL 0xB4 /* Apple IIgs runtime library */ #define PRODOS_T_EXE 0xB5 /* Apple IIgs shell script */ #define PRODOS_T_PIF 0xB6 /* Apple IIgs permanent init */ #define PRODOS_T_TIF 0xB7 /* Apple IIgs temporary init */ #define PRODOS_T_NDA 0xB8 /* Apple IIgs new desk accesry */ #define PRODOS_T_CDA 0xB9 /* Apple IIgs classic desk aces */ #define PRODOS_T_TOL 0xBA /* Apple IIgs tool */ #define PRODOS_T_DRV 0xBB /* Apple IIgs device driver */ #define PRODOS_T_LDF 0xBC /* Apple IIgs generic load file */ #define PRODOS_T_FST 0xBD /* Apple IIgs file sys translat */ #define PRODOS_T_DOC 0xBF /* Apple IIgs document */ /* ProDOS graphics file types */ #define PRODOS_T_PNT 0xC0 /* Apple IIgs packed sup hi-res */ #define PRODOS_T_PIC 0xC1 /* Apple IIgs super hi-res */ #define PRODOS_T_ANI 0xC2 /* PaintWorks animation */ #define PRODOS_T_PAL 0xC3 /* PaintWorks palette */ #define PRODOS_T_OOG 0xC5 /* Object-oriented graphics */ #define PRODOS_T_SCR 0xC6 /* Script */ #define PRODOS_T_CDV 0xC7 /* Apple IIgs control panel */ #define PRODOS_T_FON 0xC8 /* Apple IIgs font */ #define PRODOS_T_FND 0xC9 /* Apple IIgs Finder data */ #define PRODOS_T_ICN 0xCA /* Apple IIgs icon */ /* ProDOS audio file types */ #define PRODOS_T_MUS 0xD5 /* Music */ #define PRODOS_T_INS 0xD6 /* Instrument */ #define PRODOS_T_MID 0xD7 /* MIDI */ #define PRODOS_T_SND 0xD8 /* Apple IIgs audio */ #define PRODOS_T_DBM 0xDB /* DB master document */ /* ProDOS miscellaneous file types */ #define PRODOS_T_LBR 0xE0 /* Archive */ #define PRODOS_T_ATK 0xE2 /* AppleTalk data */ #define PRODOS_T_R16 0xEE /* EDASM 816 relocatable code */ #define PRODOS_T_PAR 0xEF /* Pascal area */ /* ProDOS system file types */ #define PRODOS_T_CMD 0xF0 /* ProDOS command file */ #define PRODOS_T_OVL 0xF1 /* User defined 1 */ #define PRODOS_T_UD2 0xF2 /* User defined 2 */ #define PRODOS_T_UD3 0xF3 /* User defined 3 */ #define PRODOS_T_UD4 0xF4 /* User defined 4 */ #define PRODOS_T_BAT 0xF5 /* User defined 5 */ #define PRODOS_T_UD6 0xF6 /* User defined 6 */ #define PRODOS_T_UD7 0xF7 /* User defined 7 */ #define PRODOS_T_PRG 0xF8 /* User defined 8 */ #define PRODOS_T_P16 0xF9 /* ProDOS-16 system file */ #define PRODOS_T_INT 0xFA /* Integer BASIC program */ #define PRODOS_T_IVR 0xFB /* Integer BASIC variables */ #define PRODOS_T_BAS 0xFC /* Applesoft BASIC program */ #define PRODOS_T_VAR 0xFD /* Applesoft BASIC variables */ #define PRODOS_T_REL 0xFE /* EDASM relocatable code */ #define PRODOS_T_SYS 0xFF /* ProDOS-8 system file */ /* The auxiliary type of a text file specifies its record length. ** A record length of 0 indicates a sequential text file, which is ** equivalent to text files of other operating systems like MacOS ** or Windows, except that lines are delimited by carriage returns ** only. An auxiliary type value greater than 0 for a text file, ** which is the record length, indicates a random access text file ** with fixed-length lines. */ #define PRODOS_AUX_T_TXT_SEQ 0x0000 /* Sequential text */ /* 8IC auxiliary types */ #define PRODOS_AUX_T_8IC_APEX_PGM 0x8003 /* Apex program */ /* GWP auxiliary types */ #define PRODOS_AUX_T_GWP_TEACH 0x5445 /* Teach */ #define PRODOS_AUX_T_GWP_DELUXEWRITE 0x8001 /* DeluxeWrite */ #define PRODOS_AUX_T_GWP_APPLEWORKS_GS 0x8010 /* AppleWorks GS */ /* GSS auxiliary types */ #define PRODOS_AUX_T_GSS_APPLEWORKS_GS 0x8010 /* AppleWorks GS */ /* GDB auxiliary types */ #define PRODOS_AUX_T_GDB_APPLEWORKS_GS 0x8010 /* AppleWorks GS DB */ #define PRODOS_AUX_T_GDB_AWGS_TMPL 0x8011 /* AWGS template */ #define PRODOS_AUX_T_GDB_GSAS 0x8013 /* DRW auxiliary types */ #define PRODOS_AUX_T_DRW_OO_GRAPHICS 0x8013 /* AWGS O-O graphics */ /* GDP auxiliary types */ #define PRODOS_AUX_T_GDP_GRAPHICWRITER 0x8002 /* A2gs GraphicWriter */ #define PRODOS_AUX_T_GDP_APPLEWORKS_GS 0x8010 /* A2gs AWGS */ /* HMD auxiliary types */ #define PRODOS_AUX_T_HMD_HYPERCARD_GS 0x0001 /* HyperCard GS */ #define PRODOS_AUX_T_HMD_TUTOR_TECH 0x8001 /* Tutor-Tech */ #define PRODOS_AUX_T_HMD_HYPERSTUDIO 0x8002 /* HyperStudio */ #define PRODOS_AUX_T_HMD_NEXUS 0x8003 /* Nexus */ /* COM auxiliary types */ #define PRODOS_AUX_T_COM_APPLEWORKS_GS 0x8003 /* AppleWorks GS */ /* MLR auxiliary types */ #define PRODOS_AUX_T_MLR_SCRIPT 0x005C /* Mika City script */ #define PRODOS_AUX_T_MLR_COLOR_TABLE 0xC7AB /* Mika City color table */ #define PRODOS_AUX_T_MLR_CHARACTER_DEF 0xCDEF /* Mika City character def */ /* LDF auxiliary types */ #define PRODOS_AUX_T_LDF_NIFTY_LIST_MOD 0x4001 /* Nifty list module */ #define PRODOS_AUX_T_LDF_SUPER_INFO_MOD 0x4002 /* Super info module */ #define PRODOS_AUX_T_LDF_TWILIGHT_MOD 0x4004 /* Twilight module */ #define PRODOS_AUX_T_LDF_MARINETTI_LLM 0x4004 /* Marinetti link layer mod */ /* PNT auxiliary types */ #define PRODOS_AUX_T_PNT_PK_SUPER_HIRES 0x0001 /* Packed super hi-res */ #define PRODOS_AUX_T_PNT_APPLE_PREF 0x0002 /* Apple preferred format */ #define PRODOS_AUX_T_PNT_PK_QUICKDRAWII 0x0003 /* Packed QuickDraw II */ /* PIC auxiliary types */ #define PRODOS_AUX_T_PIC_QUICKDRAW 0x0001 /* QuickDraw image */ #define PRODOS_AUX_T_PIC_SHIRES_3200 0x0002 /* Super hi-res 3200 */ /* FON auxiliary types */ #define PRODOS_AUX_T_FON_QUICKDRAW_BIT 0x0000 /* QuickDraw bitmap font */ #define PRODOS_AUX_T_FON_POINTLESS_TT 0x0001 /* Pointless TrueType font */ /* SND auxiliary types */ #define PRODOS_AUX_T_SND_AIFF 0x0000 /* AIFF */ #define PRODOS_AUX_T_SND_AIFF_C 0x0001 /* AIFF-C */ #define PRODOS_AUX_T_SND_ASIF_INSTR 0x0002 /* ASIF instrument */ #define PRODOS_AUX_T_SND_SOUND_RSRC 0x0003 /* Sound resource */ #define PRODOS_AUX_T_SND_MIDI_SYNTH_WAV 0x0004 /* MIDI synth wave */ #define PRODOS_AUX_T_SND_HYPERSTUDIO 0x8001 /* HyperStudio sound */ /* LBR auxiliary types */ #define PRODOS_AUX_T_LBR_ALU 0x0000 /* ALU */ #define PRODOS_AUX_T_LBR_APPLE_SINGLE 0x0001 /* AppleSingle */ #define PRODOS_AUX_T_LBR_APPLEDBL_HDR 0x0002 /* AppleDouble header */ #define PRODOS_AUX_T_LBR_APPLEDBL_DATA 0x0003 /* AppleDouble data */ #define PRODOS_AUX_T_LBR_BINARY_II 0x8000 /* Binary II */ #define PRODOS_AUX_T_LBR_APPLELINK_ACU 0x8001 /* AppleLink ACU */ #define PRODOS_AUX_T_LBR_SHRINKIT 0x8002 /* ShrinkIt */ /* LBR auxiliary types */ #define PRODOS_AUX_T_ATK_EASYMNT_ALIAS 0x0000 /* EasyMount alias */ /* BAS auxiliary types */ #define PRODOS_AUX_T_BAS_PGM_LOAD_ADDR 0x0801 /* Applesoft pgm load addr */ /*****************************************************************************/ /* Variables */ /*****************************************************************************/ /* The file stream implementation and the POSIX I/O functions will use the ** following variables to determine the file type and auxiliary type to use. ** This applies specifically to the fopen and open functions. */ extern unsigned char _filetype; /* Default: PRODOS_T_BIN */ extern unsigned int _auxtype; /* Default: 0 */ /* End of apple2_filetype.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/apple2enh.h�����������������������������������������������������������������������0000664�0000000�0000000�00000011101�13473601511�0015651�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* apple2enh.h */ /* */ /* enhanced Apple //e system specific definitions */ /* */ /* */ /* */ /* (C) 2004 Oliver Schmidt, <ol.sc@web.de> */ /* */ /* */ /* 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 _APPLE2ENH_H #define _APPLE2ENH_H /* Check for errors */ #if !defined(__APPLE2ENH__) # error This module may only be used when compiling for the enhanced Apple //e! #endif #include <apple2.h> /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Characters codes */ #define CH_DEL 0x7F #define CH_CURS_UP 0x0B #define CH_CURS_DOWN 0x0A #define CH_HLINE 0x5F #define CH_VLINE 0xDF #define CH_ULCORNER 0x5F #define CH_URCORNER 0x20 #define CH_LLCORNER 0xD4 #define CH_LRCORNER 0xDF #define CH_TTEE 0x5F #define CH_BTEE 0xD4 #define CH_LTEE 0xD4 #define CH_RTEE 0xDF #define CH_CROSS 0xD4 /* These are defined to be OpenApple + NumberKey */ #define CH_F1 0xB1 #define CH_F2 0xB2 #define CH_F3 0xB3 #define CH_F4 0xB4 #define CH_F5 0xB5 #define CH_F6 0xB6 #define CH_F7 0xB7 #define CH_F8 0xB8 #define CH_F9 0xB9 #define CH_F10 0xB0 /* Video modes */ #define VIDEOMODE_40x24 0x0011 #define VIDEOMODE_80x24 0x0012 #define VIDEOMODE_40COL VIDEOMODE_40x24 #define VIDEOMODE_80COL VIDEOMODE_80x24 /*****************************************************************************/ /* Variables */ /*****************************************************************************/ /* The addresses of the static drivers */ extern void a2e_auxmem_emd[]; extern void a2e_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */ extern void a2e_stdmou_mou[]; /* Referred to by mouse_static_stddrv[] */ extern void a2e_ssc_ser[]; extern void a2e_hi_tgi[]; /* Referred to by tgi_static_stddrv[] */ extern void a2e_lo_tgi[]; /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned __fastcall__ videomode (unsigned mode); /* Set the video mode, return the old mode. Call with one of the VIDEOMODE_xx ** constants. */ /* End of apple2enh.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/assert.h��������������������������������������������������������������������������0000664�0000000�0000000�00000005421�13473601511�0015304�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* assert.h */ /* */ /* Diagnostics */ /* */ /* */ /* */ /* (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 */ /* 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 _ASSERT_H #define _ASSERT_H #undef assert #ifdef NDEBUG # define assert(expr) #else extern void __fastcall__ _afailed (const char*, unsigned); # define assert(expr) ((expr)? (void)0 : _afailed(__FILE__, __LINE__)) #endif /* End of assert.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/atari.h���������������������������������������������������������������������������0000664�0000000�0000000�00000052135�13473601511�0015107�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* atari.h */ /* */ /* Atari system specific definitions */ /* */ /* */ /* */ /* (C) 2000-2019 Mark Keates <markk@dendrite.co.uk> */ /* Freddy Offenga <taf_offenga@yahoo.com> */ /* Christian Groessler <chris@groessler.org> */ /* Bill Kendrick <nbs@sonic.net> */ /* */ /* */ /* 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 _ATARI_H #define _ATARI_H /* Check for errors */ #if !defined(__ATARI__) # error This module may only be used when compiling for the Atari! #endif /*****************************************************************************/ /* Character codes */ /*****************************************************************************/ #define CH_DELCHR 0xFE /* delete char under the cursor */ #define CH_ENTER 0x9B #define CH_ESC 0x1B #define CH_CURS_UP 28 #define CH_CURS_DOWN 29 #define CH_CURS_LEFT 30 #define CH_CURS_RIGHT 31 #define CH_TAB 0x7F /* tabulator */ #define CH_EOL 0x9B /* end-of-line marker */ #define CH_CLR 0x7D /* clear screen */ #define CH_BEL 0xFD /* bell */ #define CH_DEL 0x7E /* back space (delete char to the left) */ #define CH_RUBOUT 0x7E /* back space (old, deprecated) */ #define CH_DELLINE 0x9C /* delete line */ #define CH_INSLINE 0x9D /* insert line */ /* These are defined to be Atari + NumberKey */ #define CH_F1 177 #define CH_F2 178 #define CH_F3 179 #define CH_F4 180 #define CH_F5 181 #define CH_F6 182 #define CH_F7 183 #define CH_F8 184 #define CH_F9 185 #define CH_F10 176 #define CH_ULCORNER 0x11 #define CH_URCORNER 0x05 #define CH_LLCORNER 0x1A #define CH_LRCORNER 0x03 #define CH_TTEE 0x17 #define CH_BTEE 0x18 #define CH_LTEE 0x01 #define CH_RTEE 0x04 #define CH_CROSS 0x13 #define CH_HLINE 0x12 #define CH_VLINE 0x7C /*****************************************************************************/ /* Masks for joy_read */ /*****************************************************************************/ #define JOY_UP_MASK 0x01 #define JOY_DOWN_MASK 0x02 #define JOY_LEFT_MASK 0x04 #define JOY_RIGHT_MASK 0x08 #define JOY_BTN_1_MASK 0x10 #define JOY_FIRE_MASK JOY_BTN_1_MASK #define JOY_FIRE(v) ((v) & JOY_FIRE_MASK) /*****************************************************************************/ /* Keyboard values returned by kbcode / CH */ /*****************************************************************************/ #define KEY_NONE ((unsigned char) 0xFF) #define KEY_0 ((unsigned char) 0x32) #define KEY_1 ((unsigned char) 0x1F) #define KEY_2 ((unsigned char) 0x1E) #define KEY_3 ((unsigned char) 0x1A) #define KEY_4 ((unsigned char) 0x18) #define KEY_5 ((unsigned char) 0x1D) #define KEY_6 ((unsigned char) 0x1B) #define KEY_7 ((unsigned char) 0x33) #define KEY_8 ((unsigned char) 0x35) #define KEY_9 ((unsigned char) 0x30) #define KEY_A ((unsigned char) 0x3F) #define KEY_B ((unsigned char) 0x15) #define KEY_C ((unsigned char) 0x12) #define KEY_D ((unsigned char) 0x3A) #define KEY_E ((unsigned char) 0x2A) #define KEY_F ((unsigned char) 0x38) #define KEY_G ((unsigned char) 0x3D) #define KEY_H ((unsigned char) 0x39) #define KEY_I ((unsigned char) 0x0D) #define KEY_J ((unsigned char) 0x01) #define KEY_K ((unsigned char) 0x05) #define KEY_L ((unsigned char) 0x00) #define KEY_M ((unsigned char) 0x25) #define KEY_N ((unsigned char) 0x23) #define KEY_O ((unsigned char) 0x08) #define KEY_P ((unsigned char) 0x0A) #define KEY_Q ((unsigned char) 0x2F) #define KEY_R ((unsigned char) 0x28) #define KEY_S ((unsigned char) 0x3E) #define KEY_T ((unsigned char) 0x2D) #define KEY_U ((unsigned char) 0x0B) #define KEY_V ((unsigned char) 0x10) #define KEY_W ((unsigned char) 0x2E) #define KEY_X ((unsigned char) 0x16) #define KEY_Y ((unsigned char) 0x2B) #define KEY_Z ((unsigned char) 0x17) #define KEY_COMMA ((unsigned char) 0x20) #define KEY_PERIOD ((unsigned char) 0x22) #define KEY_SLASH ((unsigned char) 0x26) #define KEY_SEMICOLON ((unsigned char) 0x02) #define KEY_PLUS ((unsigned char) 0x06) #define KEY_ASTERISK ((unsigned char) 0x07) #define KEY_DASH ((unsigned char) 0x0E) #define KEY_EQUALS ((unsigned char) 0x0F) #define KEY_LESSTHAN ((unsigned char) 0x36) #define KEY_GREATERTHAN ((unsigned char) 0x37) #define KEY_ESC ((unsigned char) 0x1C) #define KEY_TAB ((unsigned char) 0x2C) #define KEY_SPACE ((unsigned char) 0x21) #define KEY_RETURN ((unsigned char) 0x0C) #define KEY_DELETE ((unsigned char) 0x34) #define KEY_CAPS ((unsigned char) 0x3C) #define KEY_INVERSE ((unsigned char) 0x27) #define KEY_HELP ((unsigned char) 0x11) /* Function keys only exist on the 1200XL model. */ #define KEY_F1 ((unsigned char) 0x03) #define KEY_F2 ((unsigned char) 0x04) #define KEY_F3 ((unsigned char) 0x13) #define KEY_F4 ((unsigned char) 0x14) /* N.B. Cannot read Ctrl key alone */ #define KEY_CTRL ((unsigned char) 0x80) /* N.B. Cannot read Shift key alone via KBCODE; ** instead, check "Shfit key press" bit of SKSTAT register. ** Also, no way to tell left Shift from right Shift. */ #define KEY_SHIFT ((unsigned char) 0x40) /* Composed keys ** (Other combinations are possible, including Shift+Ctrl+key, ** though not all such combinations are available.) */ #define KEY_EXCLAMATIONMARK (KEY_1 | KEY_SHIFT) #define KEY_QUOTE (KEY_2 | KEY_SHIFT) #define KEY_HASH (KEY_3 | KEY_SHIFT) #define KEY_DOLLAR (KEY_4 | KEY_SHIFT) #define KEY_PERCENT (KEY_5 | KEY_SHIFT) #define KEY_AMPERSAND (KEY_6 | KEY_SHIFT) #define KEY_APOSTROPHE (KEY_7 | KEY_SHIFT) #define KEY_AT (KEY_8 | KEY_SHIFT) #define KEY_OPENINGPARAN (KEY_9 | KEY_SHIFT) #define KEY_CLOSINGPARAN (KEY_0 | KEY_SHIFT) #define KEY_UNDERLINE (KEY_DASH | KEY_SHIFT) #define KEY_BAR (KEY_EQUALS | KEY_SHIFT) #define KEY_COLON (KEY_SEMICOLON | KEY_SHIFT) #define KEY_BACKSLASH (KEY_PLUS | KEY_SHIFT) #define KEY_CIRCUMFLEX (KEY_ASTERISK | KEY_SHIFT) #define KEY_OPENINGBRACKET (KEY_COMMA | KEY_SHIFT) #define KEY_CLOSINGBRACKET (KEY_PERIOD | KEY_SHIFT) #define KEY_QUESTIONMARK (KEY_SLASH | KEY_SHIFT) #define KEY_CLEAR (KEY_LESSTHAN | KEY_SHIFT) #define KEY_INSERT (KEY_GREATERTHAN | KEY_SHIFT) #define KEY_UP (KEY_UNDERLINE | KEY_CTRL) #define KEY_DOWN (KEY_EQUALS | KEY_CTRL) #define KEY_LEFT (KEY_PLUS | KEY_CTRL) #define KEY_RIGHT (KEY_ASTERISK | KEY_CTRL) /*****************************************************************************/ /* Color register functions */ /*****************************************************************************/ extern void __fastcall__ _setcolor (unsigned char color_reg, unsigned char hue, unsigned char luminace); extern void __fastcall__ _setcolor_low (unsigned char color_reg, unsigned char color_value); extern unsigned char __fastcall__ _getcolor (unsigned char color_reg); /*****************************************************************************/ /* Other screen functions */ /*****************************************************************************/ extern int __fastcall__ _graphics (unsigned char mode); /* mode value same as in BASIC */ extern void __fastcall__ _scroll (signed char numlines); /* numlines > 0 scrolls up */ /* numlines < 0 scrolls down */ /*****************************************************************************/ /* Misc. functions */ /*****************************************************************************/ extern unsigned char get_ostype(void); /* get ROM version */ extern unsigned char get_tv(void); /* get TV system */ extern void _save_vecs(void); /* save system vectors */ extern void _rest_vecs(void); /* restore system vectors */ extern char *_getdefdev(void); /* get default floppy device */ extern unsigned char _is_cmdline_dos(void); /* does DOS support command lines */ /*****************************************************************************/ /* Global variables */ /*****************************************************************************/ extern unsigned char _dos_type; /* the DOS flavour */ #ifndef __ATARIXL__ extern void atr130_emd[]; extern void atrstd_joy[]; /* referred to by joy_static_stddrv[] */ extern void atrmj8_joy[]; extern void atrjoy_mou[]; extern void atrst_mou[]; /* referred to by mouse_static_stddrv[] */ extern void atrami_mou[]; extern void atrtrk_mou[]; extern void atrtt_mou[]; extern void atrrdev_ser[]; extern void atr3_tgi[]; extern void atr4_tgi[]; extern void atr5_tgi[]; extern void atr6_tgi[]; extern void atr7_tgi[]; extern void atr8_tgi[]; /* referred to by tgi_static_stddrv[] */ extern void atr8p2_tgi[]; extern void atr9_tgi[]; extern void atr9p2_tgi[]; extern void atr10_tgi[]; extern void atr10p2_tgi[]; extern void atr11_tgi[]; extern void atr14_tgi[]; extern void atr15_tgi[]; extern void atr15p2_tgi[]; #else extern void atrx130_emd[]; extern void atrxstd_joy[]; /* referred to by joy_static_stddrv[] */ extern void atrxmj8_joy[]; extern void atrxjoy_mou[]; extern void atrxst_mou[]; /* referred to by mouse_static_stddrv[] */ extern void atrxami_mou[]; extern void atrxtrk_mou[]; extern void atrxtt_mou[]; extern void atrxrdev_ser[]; extern void atrx3_tgi[]; extern void atrx4_tgi[]; extern void atrx5_tgi[]; extern void atrx6_tgi[]; extern void atrx7_tgi[]; extern void atrx8_tgi[]; /* referred to by tgi_static_stddrv[] */ extern void atrx8p2_tgi[]; extern void atrx9_tgi[]; extern void atrx9p2_tgi[]; extern void atrx10_tgi[]; extern void atrx10p2_tgi[]; extern void atrx11_tgi[]; extern void atrx14_tgi[]; extern void atrx15_tgi[]; extern void atrx15p2_tgi[]; #endif /*****************************************************************************/ /* get_ostype return value defines (for explanation, see ostype.s) */ /*****************************************************************************/ /* masks */ #define AT_OS_TYPE_MAIN 7 #define AT_OS_TYPE_MINOR (7 << 3) /* AT_OS_TYPE_MAIN values */ #define AT_OS_UNKNOWN 0 #define AT_OS_400800 1 #define AT_OS_1200XL 2 #define AT_OS_XLXE 3 /* AS_OS_TYPE_MINOR values */ /* for 400/800 remember this are the ROM versions */ /* to check whether the hw is PAL or NTSC, use get_tv() */ #define AT_OS_400800PAL_A 1 #define AT_OS_400800PAL_B 2 #define AT_OS_400800NTSC_A 1 #define AT_OS_400800NTSC_B 2 #define AT_OS_1200_10 1 #define AT_OS_1200_11 2 #define AT_OS_XLXE_1 1 #define AT_OS_XLXE_2 2 #define AT_OS_XLXE_3 3 #define AT_OS_XLXE_4 4 /*****************************************************************************/ /* get_tv return values */ /*****************************************************************************/ #define AT_NTSC 0 #define AT_PAL 1 /*****************************************************************************/ /* valid _dos_type values */ /*****************************************************************************/ #define SPARTADOS 0 #define REALDOS 1 #define BWDOS 2 #define OSADOS 3 #define XDOS 4 #define ATARIDOS 5 #define MYDOS 6 #define NODOS 255 /*****************************************************************************/ /* Define hardware and where they're mapped in memory */ /*****************************************************************************/ #include <_atarios.h> #define OS (*(struct __os*)0x0000) #define BASIC (*(struct __basic*)0x0080) #include <_gtia.h> #define GTIA_READ (*(struct __gtia_read*)0xD000) #define GTIA_WRITE (*(struct __gtia_write*)0xD000) #include <_pbi.h> #include <_pokey.h> #define POKEY_READ (*(struct __pokey_read*)0xD200) #define POKEY_WRITE (*(struct __pokey_write*)0xD200) #include <_pia.h> #define PIA (*(struct __pia*)0xD300) #include <_antic.h> #define ANTIC (*(struct __antic*)0xD400) /*****************************************************************************/ /* conio and TGI color defines */ /*****************************************************************************/ /* Note that the conio color implementation is monochrome ** (textcolor just sets text brightness low or high, depending on background ** color) ** These values can be used with bordercolor(), bgcolor(), and _setcolor_low() */ #define COLOR_BLACK GTIA_COLOR_BLACK #define COLOR_WHITE GTIA_COLOR_WHITE #define COLOR_RED GTIA_COLOR_RED #define COLOR_CYAN GTIA_COLOR_CYAN #define COLOR_VIOLET GTIA_COLOR_VIOLET #define COLOR_GREEN GTIA_COLOR_GREEN #define COLOR_BLUE GTIA_COLOR_BLUE #define COLOR_YELLOW GTIA_COLOR_YELLOW #define COLOR_ORANGE GTIA_COLOR_ORANGE #define COLOR_BROWN GTIA_COLOR_BROWN #define COLOR_LIGHTRED GTIA_COLOR_LIGHTRED #define COLOR_GRAY1 GTIA_COLOR_GRAY1 #define COLOR_GRAY2 GTIA_COLOR_GRAY2 #define COLOR_LIGHTGREEN GTIA_COLOR_LIGHTGREEN #define COLOR_LIGHTBLUE GTIA_COLOR_LIGHTBLUE #define COLOR_GRAY3 GTIA_COLOR_GRAY3 /* TGI color defines */ #define TGI_COLOR_BLACK COLOR_BLACK #define TGI_COLOR_WHITE COLOR_WHITE #define TGI_COLOR_RED COLOR_RED #define TGI_COLOR_CYAN COLOR_CYAN #define TGI_COLOR_VIOLET COLOR_VIOLET #define TGI_COLOR_GREEN COLOR_GREEN #define TGI_COLOR_BLUE COLOR_BLUE #define TGI_COLOR_YELLOW COLOR_YELLOW #define TGI_COLOR_ORANGE COLOR_ORANGE #define TGI_COLOR_BROWN COLOR_BROWN #define TGI_COLOR_LIGHTRED COLOR_LIGHTRED #define TGI_COLOR_GRAY1 COLOR_GRAY1 #define TGI_COLOR_GRAY2 COLOR_GRAY2 #define TGI_COLOR_LIGHTGREEN COLOR_LIGHTGREEN #define TGI_COLOR_LIGHTBLUE COLOR_LIGHTBLUE #define TGI_COLOR_GRAY3 COLOR_GRAY3 /*****************************************************************************/ /* PIA PORTA and PORTB register bits */ /*****************************************************************************/ /* See also: "JOY_xxx_MASK" in "atari.h" */ /* Paddle 0-3 triggers (per PORTA bits) */ #define PORTA_PTRIG3 0x80 #define PORTA_PTRIG2 0x40 #define PORTA_PTRIG1 0x08 #define PORTA_PTRIG0 0x04 /* On the Atari 400/800, PORTB is the same as PORTA, but for controller ports 3 & 4. */ /* Paddle 4-7 triggers (per PORTB bits); only 400/800 had four controller ports */ #define PORTB_PTRIG7 0x80 #define PORTB_PTRIG6 0x40 #define PORTB_PTRIG5 0x08 #define PORTB_PTRIG4 0x04 /* On the XL series of computers, PORTB has been changed to a memory and ** LED control (1200XL model only) register (read/write): */ /* If set, the built-in OS is enabled, and occupies the address range $C000-$FFFF ** (except that the area $D000-$D7FF will only access the hardware registers.) ** If clear, RAM is enabled in this area (again, save for the hole.) */ #define PORTB_OSROM 0x01 /* If set, RAM is enabled for the address range $A000-$BFFF. ** If clear, the built-in BASIC ROM is enabled at this address. ** And if there is a cartridge installed in the computer, it makes no difference. */ #define PORTB_BASICROM 0x02 /* If set, the corresponding LED is turned off. If clear, the LED will be on. ** (1200XL only) */ #define PORTB_LED1 0x04 #define PORTB_LED2 0x08 /* On the XE series of computers, PORTB is a bank-selected memory control register (read/write): */ /* These bits determine which memory bank is visible to the CPU and/or ANTIC chip ** when their Bank Switch bit is set. There are four possible banks of 16KB each. */ #define PORTB_BANKSELECT1 0x00 #define PORTB_BANKSELECT2 0x04 #define PORTB_BANKSELECT3 0x08 #define PORTB_BANKSELECT4 0x0C /* If set, the CPU and/or ANTIC chip will access bank-switched memory mapped to the ** address range $4000-$7FFF. ** If clear, the CPU and/or ANTIC will see normal memory in this region. */ #define PORTB_BANKSWITCH_CPU 0x10 #define PORTB_BANKSWITCH_ANTIC 0x20 /* If set, RAM is enabled for the address range $5000-$57FF. ** If clear, the self-test ROM (physically located at $D000-$D7FF, under the hardware registers) ** is remapped to this memory area. */ #define PORTB_SELFTEST 0x80 /*****************************************************************************/ /* PACTL and PBCTL register bits */ /*****************************************************************************/ /* (W) Peripheral PA1/PB1 interrupt (IRQ) ("peripheral proceed line available") enable. ** One equals enable. Set by the OS but available to the user; reset on powerup. ** (PxCTL_IRQ_STATUS (R) bit will get set upon interrupt occurance) */ #define PxCTL_IRQ_ENABLE 0x01 /* bit 0 */ /* Note: Bit 1 is always set to */ /* (W) Controls PORTA/PORTB addressing ** 1 = PORTA/PORTB register; read/write to controller port ** 0 = direction control register; write to direction controls ** (allows setting data flow; write 0s & 1s to PORTA/PORTB bits ** to set which port's pins are read (input), or write (output), ** respectively) */ #define PxCTL_ADDRESSING 0x04 /* bit 2 */ /* (W) Peripheral motor control line; Turn the cassette on or off ** (PACTL-specific register bit) ** 0 = on ** 1 = off */ #define PACTL_MOTOR_CONTROL 0x08 /* bit 3 */ /* Peripheral command identification (serial bus command line) ** (PBCTL-specific register bit) */ #define PBCTL_PERIPH_CMD_IDENT 0x08 /* bit 3 */ /* Note: Bits 4 & 5 are always set to 1 */ /* Note: Bit 6 is always set to 0 */ /* (R) Peripheral interrupt (IRQ) status bit. ** Set by Peripherals (PORTA / PORTB). Reset by reading from PORTA / PORTB. ** PACTL's is interrupt status of PROCEED ** PBCTL's is interrupt status of SIO */ #define PxCTL_IRQ_STATUS 0x80 /* The following #define will cause the matching function calls in conio.h ** to be overlaid by macros with the same names, saving the function call ** overhead. */ #define _textcolor(color) COLOR_WHITE /* End of atari.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/atari2600.h�����������������������������������������������������������������������0000664�0000000�0000000�00000002031�13473601511�0015405�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* Atari VCS 2600 TIA & RIOT registers addresses */ /* */ /* Source: DASM Version 1.05 - vcs.h */ /* */ /* Florent Flament (contact@florentflament.com), 2017 */ /* */ /*****************************************************************************/ #ifndef _ATARI2600_H #define _ATARI2600_H /* Check for errors */ #if !defined(__ATARI2600__) # error This module may only be used when compiling for the Atari 2600! #endif #include <_tia.h> #define TIA (*(struct __tia*)0x0000) #include <_riot.h> #define RIOT (*(struct __riot*)0x0280) /* End of atari2600.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/atari5200.h�����������������������������������������������������������������������0000664�0000000�0000000�00000007461�13473601511�0015420�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* atari5200.h */ /* */ /* Atari 5200 system specific definitions */ /* */ /* */ /* */ /* (C) 2014 Christian Groessler <chris@groessler.org> */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _ATARI5200_H #define _ATARI5200_H /* Check for errors */ #if !defined(__ATARI5200__) # error This module may only be used when compiling for the Atari 5200! #endif /* no support for dynamically loadable drivers */ #define DYN_DRV 0 /* the addresses of the static drivers */ extern void atr5200std_joy[]; /* referred to by joy_static_stddrv[] */ /* Masks for joy_read */ #define JOY_UP_MASK 0x01 #define JOY_DOWN_MASK 0x02 #define JOY_LEFT_MASK 0x04 #define JOY_RIGHT_MASK 0x08 #define JOY_BTN_1_MASK 0x10 /* Character codes */ #define CH_ULCORNER 0x0B /* '+' sign */ #define CH_URCORNER 0x0B #define CH_LLCORNER 0x0B #define CH_LRCORNER 0x0B #define CH_HLINE 0x0D /* dash */ #define CH_VLINE 0x01 /* exclamation mark */ /* get_tv return values */ #define AT_NTSC 0 #define AT_PAL 1 /* Define hardware */ #include <_gtia.h> #define GTIA_READ (*(struct __gtia_read*)0xC000) #define GTIA_WRITE (*(struct __gtia_write*)0xC000) #include <_pokey.h> #define POKEY_READ (*(struct __pokey_read*)0xE800) #define POKEY_WRITE (*(struct __pokey_write*)0xE800) #include <_antic.h> #define ANTIC (*(struct __antic*)0xD400) /* conio color defines */ #define COLOR_WHITE 0x00 #define COLOR_RED 0x01 #define COLOR_GREEN 0x02 #define COLOR_BLACK 0x03 /* The following #define will cause the matching function calls in conio.h ** to be overlaid by macros with the same names, saving the function call ** overhead. */ #define _bordercolor(color) 0 /* End of atari5200.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/atari_atascii_charmap.h�����������������������������������������������������������0000664�0000000�0000000�00000023154�13473601511�0020276�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* atari_atascii_charmap.h */ /* */ /* Atari system standard string mapping (ISO-8859-1 -> AtASCII) */ /* */ /* */ /* */ /* (C) 2016 Christian Krueger */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* No include guard here! Multiple use in one file may be intentional. */ #pragma charmap (0x00, 0x00) #pragma charmap (0x01, 0x01) #pragma charmap (0x02, 0x02) #pragma charmap (0x03, 0x03) #pragma charmap (0x04, 0x04) #pragma charmap (0x05, 0x05) #pragma charmap (0x06, 0x06) #pragma charmap (0x07, 0xFD) #pragma charmap (0x08, 0x08) #pragma charmap (0x09, 0x7F) #pragma charmap (0x0A, 0x9B) #pragma charmap (0x0B, 0x0B) #pragma charmap (0x0C, 0x7D) #pragma charmap (0x0D, 0x0D) #pragma charmap (0x0E, 0x0E) #pragma charmap (0x0F, 0x0F) #pragma charmap (0x10, 0x10) #pragma charmap (0x11, 0x11) #pragma charmap (0x12, 0x12) #pragma charmap (0x13, 0x13) #pragma charmap (0x14, 0x14) #pragma charmap (0x15, 0x15) #pragma charmap (0x16, 0x16) #pragma charmap (0x17, 0x17) #pragma charmap (0x18, 0x18) #pragma charmap (0x19, 0x19) #pragma charmap (0x1A, 0x1A) #pragma charmap (0x1B, 0x1B) #pragma charmap (0x1C, 0x1C) #pragma charmap (0x1D, 0x1D) #pragma charmap (0x1E, 0x1E) #pragma charmap (0x1F, 0x1F) #pragma charmap (0x20, 0x20) #pragma charmap (0x21, 0x21) #pragma charmap (0x22, 0x22) #pragma charmap (0x23, 0x23) #pragma charmap (0x24, 0x24) #pragma charmap (0x25, 0x25) #pragma charmap (0x26, 0x26) #pragma charmap (0x27, 0x27) #pragma charmap (0x28, 0x28) #pragma charmap (0x29, 0x29) #pragma charmap (0x2A, 0x2A) #pragma charmap (0x2B, 0x2B) #pragma charmap (0x2C, 0x2C) #pragma charmap (0x2D, 0x2D) #pragma charmap (0x2E, 0x2E) #pragma charmap (0x2F, 0x2F) #pragma charmap (0x30, 0x30) #pragma charmap (0x31, 0x31) #pragma charmap (0x32, 0x32) #pragma charmap (0x33, 0x33) #pragma charmap (0x34, 0x34) #pragma charmap (0x35, 0x35) #pragma charmap (0x36, 0x36) #pragma charmap (0x37, 0x37) #pragma charmap (0x38, 0x38) #pragma charmap (0x39, 0x39) #pragma charmap (0x3A, 0x3A) #pragma charmap (0x3B, 0x3B) #pragma charmap (0x3C, 0x3C) #pragma charmap (0x3D, 0x3D) #pragma charmap (0x3E, 0x3E) #pragma charmap (0x3F, 0x3F) #pragma charmap (0x40, 0x40) #pragma charmap (0x41, 0x41) #pragma charmap (0x42, 0x42) #pragma charmap (0x43, 0x43) #pragma charmap (0x44, 0x44) #pragma charmap (0x45, 0x45) #pragma charmap (0x46, 0x46) #pragma charmap (0x47, 0x47) #pragma charmap (0x48, 0x48) #pragma charmap (0x49, 0x49) #pragma charmap (0x4A, 0x4A) #pragma charmap (0x4B, 0x4B) #pragma charmap (0x4C, 0x4C) #pragma charmap (0x4D, 0x4D) #pragma charmap (0x4E, 0x4E) #pragma charmap (0x4F, 0x4F) #pragma charmap (0x50, 0x50) #pragma charmap (0x51, 0x51) #pragma charmap (0x52, 0x52) #pragma charmap (0x53, 0x53) #pragma charmap (0x54, 0x54) #pragma charmap (0x55, 0x55) #pragma charmap (0x56, 0x56) #pragma charmap (0x57, 0x57) #pragma charmap (0x58, 0x58) #pragma charmap (0x59, 0x59) #pragma charmap (0x5A, 0x5A) #pragma charmap (0x5B, 0x5B) #pragma charmap (0x5C, 0x5C) #pragma charmap (0x5D, 0x5D) #pragma charmap (0x5E, 0x5E) #pragma charmap (0x5F, 0x5F) #pragma charmap (0x60, 0x60) #pragma charmap (0x61, 0x61) #pragma charmap (0x62, 0x62) #pragma charmap (0x63, 0x63) #pragma charmap (0x64, 0x64) #pragma charmap (0x65, 0x65) #pragma charmap (0x66, 0x66) #pragma charmap (0x67, 0x67) #pragma charmap (0x68, 0x68) #pragma charmap (0x69, 0x69) #pragma charmap (0x6A, 0x6A) #pragma charmap (0x6B, 0x6B) #pragma charmap (0x6C, 0x6C) #pragma charmap (0x6D, 0x6D) #pragma charmap (0x6E, 0x6E) #pragma charmap (0x6F, 0x6F) #pragma charmap (0x70, 0x70) #pragma charmap (0x71, 0x71) #pragma charmap (0x72, 0x72) #pragma charmap (0x73, 0x73) #pragma charmap (0x74, 0x74) #pragma charmap (0x75, 0x75) #pragma charmap (0x76, 0x76) #pragma charmap (0x77, 0x77) #pragma charmap (0x78, 0x78) #pragma charmap (0x79, 0x79) #pragma charmap (0x7A, 0x7A) #pragma charmap (0x7B, 0x7B) #pragma charmap (0x7C, 0x7C) #pragma charmap (0x7D, 0x7D) #pragma charmap (0x7E, 0x7E) #pragma charmap (0x7F, 0x7F) #pragma charmap (0x80, 0x80) #pragma charmap (0x81, 0x81) #pragma charmap (0x82, 0x82) #pragma charmap (0x83, 0x83) #pragma charmap (0x84, 0x84) #pragma charmap (0x85, 0x85) #pragma charmap (0x86, 0x86) #pragma charmap (0x87, 0x87) #pragma charmap (0x88, 0x88) #pragma charmap (0x89, 0x89) #pragma charmap (0x8A, 0x8A) #pragma charmap (0x8B, 0x8B) #pragma charmap (0x8C, 0x8C) #pragma charmap (0x8D, 0x8D) #pragma charmap (0x8E, 0x8E) #pragma charmap (0x8F, 0x8F) #pragma charmap (0x90, 0x90) #pragma charmap (0x91, 0x91) #pragma charmap (0x92, 0x92) #pragma charmap (0x93, 0x93) #pragma charmap (0x94, 0x94) #pragma charmap (0x95, 0x95) #pragma charmap (0x96, 0x96) #pragma charmap (0x97, 0x97) #pragma charmap (0x98, 0x98) #pragma charmap (0x99, 0x99) #pragma charmap (0x9A, 0x9A) #pragma charmap (0x9B, 0x9B) #pragma charmap (0x9C, 0x9C) #pragma charmap (0x9D, 0x9D) #pragma charmap (0x9E, 0x9E) #pragma charmap (0x9F, 0x9F) #pragma charmap (0xA0, 0xA0) #pragma charmap (0xA1, 0xA1) #pragma charmap (0xA2, 0xA2) #pragma charmap (0xA3, 0xA3) #pragma charmap (0xA4, 0xA4) #pragma charmap (0xA5, 0xA5) #pragma charmap (0xA6, 0xA6) #pragma charmap (0xA7, 0xA7) #pragma charmap (0xA8, 0xA8) #pragma charmap (0xA9, 0xA9) #pragma charmap (0xAA, 0xAA) #pragma charmap (0xAB, 0xAB) #pragma charmap (0xAC, 0xAC) #pragma charmap (0xAD, 0xAD) #pragma charmap (0xAE, 0xAE) #pragma charmap (0xAF, 0xAF) #pragma charmap (0xB0, 0xB0) #pragma charmap (0xB1, 0xB1) #pragma charmap (0xB2, 0xB2) #pragma charmap (0xB3, 0xB3) #pragma charmap (0xB4, 0xB4) #pragma charmap (0xB5, 0xB5) #pragma charmap (0xB6, 0xB6) #pragma charmap (0xB7, 0xB7) #pragma charmap (0xB8, 0xB8) #pragma charmap (0xB9, 0xB9) #pragma charmap (0xBA, 0xBA) #pragma charmap (0xBB, 0xBB) #pragma charmap (0xBC, 0xBC) #pragma charmap (0xBD, 0xBD) #pragma charmap (0xBE, 0xBE) #pragma charmap (0xBF, 0xBF) #pragma charmap (0xC0, 0xC0) #pragma charmap (0xC1, 0xC1) #pragma charmap (0xC2, 0xC2) #pragma charmap (0xC3, 0xC3) #pragma charmap (0xC4, 0xC4) #pragma charmap (0xC5, 0xC5) #pragma charmap (0xC6, 0xC6) #pragma charmap (0xC7, 0xC7) #pragma charmap (0xC8, 0xC8) #pragma charmap (0xC9, 0xC9) #pragma charmap (0xCA, 0xCA) #pragma charmap (0xCB, 0xCB) #pragma charmap (0xCC, 0xCC) #pragma charmap (0xCD, 0xCD) #pragma charmap (0xCE, 0xCE) #pragma charmap (0xCF, 0xCF) #pragma charmap (0xD0, 0xD0) #pragma charmap (0xD1, 0xD1) #pragma charmap (0xD2, 0xD2) #pragma charmap (0xD3, 0xD3) #pragma charmap (0xD4, 0xD4) #pragma charmap (0xD5, 0xD5) #pragma charmap (0xD6, 0xD6) #pragma charmap (0xD7, 0xD7) #pragma charmap (0xD8, 0xD8) #pragma charmap (0xD9, 0xD9) #pragma charmap (0xDA, 0xDA) #pragma charmap (0xDB, 0xDB) #pragma charmap (0xDC, 0xDC) #pragma charmap (0xDD, 0xDD) #pragma charmap (0xDE, 0xDE) #pragma charmap (0xDF, 0xDF) #pragma charmap (0xE0, 0xE0) #pragma charmap (0xE1, 0xE1) #pragma charmap (0xE2, 0xE2) #pragma charmap (0xE3, 0xE3) #pragma charmap (0xE4, 0xE4) #pragma charmap (0xE5, 0xE5) #pragma charmap (0xE6, 0xE6) #pragma charmap (0xE7, 0xE7) #pragma charmap (0xE8, 0xE8) #pragma charmap (0xE9, 0xE9) #pragma charmap (0xEA, 0xEA) #pragma charmap (0xEB, 0xEB) #pragma charmap (0xEC, 0xEC) #pragma charmap (0xED, 0xED) #pragma charmap (0xEE, 0xEE) #pragma charmap (0xEF, 0xEF) #pragma charmap (0xF0, 0xF0) #pragma charmap (0xF1, 0xF1) #pragma charmap (0xF2, 0xF2) #pragma charmap (0xF3, 0xF3) #pragma charmap (0xF4, 0xF4) #pragma charmap (0xF5, 0xF5) #pragma charmap (0xF6, 0xF6) #pragma charmap (0xF7, 0xF7) #pragma charmap (0xF8, 0xF8) #pragma charmap (0xF9, 0xF9) #pragma charmap (0xFA, 0xFA) #pragma charmap (0xFB, 0xFB) #pragma charmap (0xFC, 0xFC) #pragma charmap (0xFD, 0xFD) #pragma charmap (0xFE, 0xFE) #pragma charmap (0xFF, 0xFF) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/atari_screen_charmap.h������������������������������������������������������������0000664�0000000�0000000�00000023366�13473601511�0020145�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* atari_screen_charmap.h */ /* */ /* Atari system internal string mapping (ISO-8859-1 -> Internal/Screen-Code) */ /* */ /* */ /* */ /* (C) 2016 Christian Krueger */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* No include guard here! Multiple use in one file may be intentional. */ #pragma warn (remap-zero, push, off) #pragma charmap (0x00, 0x40) #pragma warn (remap-zero, pop) #pragma charmap (0x01, 0x41) #pragma charmap (0x02, 0x42) #pragma charmap (0x03, 0x43) #pragma charmap (0x04, 0x44) #pragma charmap (0x05, 0x45) #pragma charmap (0x06, 0x46) #pragma charmap (0x07, 0xFD) #pragma charmap (0x08, 0x48) #pragma charmap (0x09, 0x7F) #pragma charmap (0x0A, 0xDB) #pragma charmap (0x0B, 0x4B) #pragma charmap (0x0C, 0x7D) #pragma charmap (0x0D, 0x4D) #pragma charmap (0x0E, 0x4E) #pragma charmap (0x0F, 0x4F) #pragma charmap (0x10, 0x50) #pragma charmap (0x11, 0x51) #pragma charmap (0x12, 0x52) #pragma charmap (0x13, 0x53) #pragma charmap (0x14, 0x54) #pragma charmap (0x15, 0x55) #pragma charmap (0x16, 0x56) #pragma charmap (0x17, 0x57) #pragma charmap (0x18, 0x58) #pragma charmap (0x19, 0x59) #pragma charmap (0x1A, 0x5A) #pragma charmap (0x1B, 0x5B) #pragma charmap (0x1C, 0x5C) #pragma charmap (0x1D, 0x5D) #pragma charmap (0x1E, 0x5E) #pragma charmap (0x1F, 0x5F) #pragma warn (remap-zero, push, off) #pragma charmap (0x20, 0x00) #pragma warn (remap-zero, pop) #pragma charmap (0x21, 0x01) #pragma charmap (0x22, 0x02) #pragma charmap (0x23, 0x03) #pragma charmap (0x24, 0x04) #pragma charmap (0x25, 0x05) #pragma charmap (0x26, 0x06) #pragma charmap (0x27, 0x07) #pragma charmap (0x28, 0x08) #pragma charmap (0x29, 0x09) #pragma charmap (0x2A, 0x0A) #pragma charmap (0x2B, 0x0B) #pragma charmap (0x2C, 0x0C) #pragma charmap (0x2D, 0x0D) #pragma charmap (0x2E, 0x0E) #pragma charmap (0x2F, 0x0F) #pragma charmap (0x30, 0x10) #pragma charmap (0x31, 0x11) #pragma charmap (0x32, 0x12) #pragma charmap (0x33, 0x13) #pragma charmap (0x34, 0x14) #pragma charmap (0x35, 0x15) #pragma charmap (0x36, 0x16) #pragma charmap (0x37, 0x17) #pragma charmap (0x38, 0x18) #pragma charmap (0x39, 0x19) #pragma charmap (0x3A, 0x1A) #pragma charmap (0x3B, 0x1B) #pragma charmap (0x3C, 0x1C) #pragma charmap (0x3D, 0x1D) #pragma charmap (0x3E, 0x1E) #pragma charmap (0x3F, 0x1F) #pragma charmap (0x40, 0x20) #pragma charmap (0x41, 0x21) #pragma charmap (0x42, 0x22) #pragma charmap (0x43, 0x23) #pragma charmap (0x44, 0x24) #pragma charmap (0x45, 0x25) #pragma charmap (0x46, 0x26) #pragma charmap (0x47, 0x27) #pragma charmap (0x48, 0x28) #pragma charmap (0x49, 0x29) #pragma charmap (0x4A, 0x2A) #pragma charmap (0x4B, 0x2B) #pragma charmap (0x4C, 0x2C) #pragma charmap (0x4D, 0x2D) #pragma charmap (0x4E, 0x2E) #pragma charmap (0x4F, 0x2F) #pragma charmap (0x50, 0x30) #pragma charmap (0x51, 0x31) #pragma charmap (0x52, 0x32) #pragma charmap (0x53, 0x33) #pragma charmap (0x54, 0x34) #pragma charmap (0x55, 0x35) #pragma charmap (0x56, 0x36) #pragma charmap (0x57, 0x37) #pragma charmap (0x58, 0x38) #pragma charmap (0x59, 0x39) #pragma charmap (0x5A, 0x3A) #pragma charmap (0x5B, 0x3B) #pragma charmap (0x5C, 0x3C) #pragma charmap (0x5D, 0x3D) #pragma charmap (0x5E, 0x3E) #pragma charmap (0x5F, 0x3F) #pragma charmap (0x60, 0x60) #pragma charmap (0x61, 0x61) #pragma charmap (0x62, 0x62) #pragma charmap (0x63, 0x63) #pragma charmap (0x64, 0x64) #pragma charmap (0x65, 0x65) #pragma charmap (0x66, 0x66) #pragma charmap (0x67, 0x67) #pragma charmap (0x68, 0x68) #pragma charmap (0x69, 0x69) #pragma charmap (0x6A, 0x6A) #pragma charmap (0x6B, 0x6B) #pragma charmap (0x6C, 0x6C) #pragma charmap (0x6D, 0x6D) #pragma charmap (0x6E, 0x6E) #pragma charmap (0x6F, 0x6F) #pragma charmap (0x70, 0x70) #pragma charmap (0x71, 0x71) #pragma charmap (0x72, 0x72) #pragma charmap (0x73, 0x73) #pragma charmap (0x74, 0x74) #pragma charmap (0x75, 0x75) #pragma charmap (0x76, 0x76) #pragma charmap (0x77, 0x77) #pragma charmap (0x78, 0x78) #pragma charmap (0x79, 0x79) #pragma charmap (0x7A, 0x7A) #pragma charmap (0x7B, 0x7B) #pragma charmap (0x7C, 0x7C) #pragma charmap (0x7D, 0x7D) #pragma charmap (0x7E, 0x7E) #pragma charmap (0x7F, 0x7F) #pragma charmap (0x80, 0xC0) #pragma charmap (0x81, 0xC1) #pragma charmap (0x82, 0xC2) #pragma charmap (0x83, 0xC3) #pragma charmap (0x84, 0xC4) #pragma charmap (0x85, 0xC5) #pragma charmap (0x86, 0xC6) #pragma charmap (0x87, 0xC7) #pragma charmap (0x88, 0xC8) #pragma charmap (0x89, 0xC9) #pragma charmap (0x8A, 0xCA) #pragma charmap (0x8B, 0xCB) #pragma charmap (0x8C, 0xCC) #pragma charmap (0x8D, 0xCD) #pragma charmap (0x8E, 0xCE) #pragma charmap (0x8F, 0xCF) #pragma charmap (0x90, 0xD0) #pragma charmap (0x91, 0xD1) #pragma charmap (0x92, 0xD2) #pragma charmap (0x93, 0xD3) #pragma charmap (0x94, 0xD4) #pragma charmap (0x95, 0xD5) #pragma charmap (0x96, 0xD6) #pragma charmap (0x97, 0xD7) #pragma charmap (0x98, 0xD8) #pragma charmap (0x99, 0xD9) #pragma charmap (0x9A, 0xDA) #pragma charmap (0x9B, 0xDB) #pragma charmap (0x9C, 0xDC) #pragma charmap (0x9D, 0xDD) #pragma charmap (0x9E, 0xDE) #pragma charmap (0x9F, 0xDF) #pragma charmap (0xA0, 0x80) #pragma charmap (0xA1, 0x81) #pragma charmap (0xA2, 0x82) #pragma charmap (0xA3, 0x83) #pragma charmap (0xA4, 0x84) #pragma charmap (0xA5, 0x85) #pragma charmap (0xA6, 0x86) #pragma charmap (0xA7, 0x87) #pragma charmap (0xA8, 0x88) #pragma charmap (0xA9, 0x89) #pragma charmap (0xAA, 0x8A) #pragma charmap (0xAB, 0x8B) #pragma charmap (0xAC, 0x8C) #pragma charmap (0xAD, 0x8D) #pragma charmap (0xAE, 0x8E) #pragma charmap (0xAF, 0x8F) #pragma charmap (0xB0, 0x90) #pragma charmap (0xB1, 0x91) #pragma charmap (0xB2, 0x92) #pragma charmap (0xB3, 0x93) #pragma charmap (0xB4, 0x94) #pragma charmap (0xB5, 0x95) #pragma charmap (0xB6, 0x96) #pragma charmap (0xB7, 0x97) #pragma charmap (0xB8, 0x98) #pragma charmap (0xB9, 0x99) #pragma charmap (0xBA, 0x9A) #pragma charmap (0xBB, 0x9B) #pragma charmap (0xBC, 0x9C) #pragma charmap (0xBD, 0x9D) #pragma charmap (0xBE, 0x9E) #pragma charmap (0xBF, 0x9F) #pragma charmap (0xC0, 0xA0) #pragma charmap (0xC1, 0xA1) #pragma charmap (0xC2, 0xA2) #pragma charmap (0xC3, 0xA3) #pragma charmap (0xC4, 0xA4) #pragma charmap (0xC5, 0xA5) #pragma charmap (0xC6, 0xA6) #pragma charmap (0xC7, 0xA7) #pragma charmap (0xC8, 0xA8) #pragma charmap (0xC9, 0xA9) #pragma charmap (0xCA, 0xAA) #pragma charmap (0xCB, 0xAB) #pragma charmap (0xCC, 0xAC) #pragma charmap (0xCD, 0xAD) #pragma charmap (0xCE, 0xAE) #pragma charmap (0xCF, 0xAF) #pragma charmap (0xD0, 0xB0) #pragma charmap (0xD1, 0xB1) #pragma charmap (0xD2, 0xB2) #pragma charmap (0xD3, 0xB3) #pragma charmap (0xD4, 0xB4) #pragma charmap (0xD5, 0xB5) #pragma charmap (0xD6, 0xB6) #pragma charmap (0xD7, 0xB7) #pragma charmap (0xD8, 0xB8) #pragma charmap (0xD9, 0xB9) #pragma charmap (0xDA, 0xBA) #pragma charmap (0xDB, 0xBB) #pragma charmap (0xDC, 0xBC) #pragma charmap (0xDD, 0xBD) #pragma charmap (0xDE, 0xBE) #pragma charmap (0xDF, 0xBF) #pragma charmap (0xE0, 0xE0) #pragma charmap (0xE1, 0xE1) #pragma charmap (0xE2, 0xE2) #pragma charmap (0xE3, 0xE3) #pragma charmap (0xE4, 0xE4) #pragma charmap (0xE5, 0xE5) #pragma charmap (0xE6, 0xE6) #pragma charmap (0xE7, 0xE7) #pragma charmap (0xE8, 0xE8) #pragma charmap (0xE9, 0xE9) #pragma charmap (0xEA, 0xEA) #pragma charmap (0xEB, 0xEB) #pragma charmap (0xEC, 0xEC) #pragma charmap (0xED, 0xED) #pragma charmap (0xEE, 0xEE) #pragma charmap (0xEF, 0xEF) #pragma charmap (0xF0, 0xF0) #pragma charmap (0xF1, 0xF1) #pragma charmap (0xF2, 0xF2) #pragma charmap (0xF3, 0xF3) #pragma charmap (0xF4, 0xF4) #pragma charmap (0xF5, 0xF5) #pragma charmap (0xF6, 0xF6) #pragma charmap (0xF7, 0xF7) #pragma charmap (0xF8, 0xF8) #pragma charmap (0xF9, 0xF9) #pragma charmap (0xFA, 0xFA) #pragma charmap (0xFB, 0xFB) #pragma charmap (0xFC, 0xFC) #pragma charmap (0xFD, 0xFD) #pragma charmap (0xFE, 0xFE) #pragma charmap (0xFF, 0xFF) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/atmos.h���������������������������������������������������������������������������0000664�0000000�0000000�00000013252�13473601511�0015127�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* atmos.h */ /* */ /* Oric Atmos system-specific definitions */ /* */ /* */ /* */ /* (C) 2002 Debrune Jérome, <jede@oric.org> */ /* (C) 2003-2013 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _ATMOS_H #define _ATMOS_H /* Check for errors */ #if !defined(__ATMOS__) # error This module may only be used when compiling for the Oric Atmos! #endif /* Color defines */ #define COLOR_BLACK 0x00 #define COLOR_RED 0x01 #define COLOR_GREEN 0x02 #define COLOR_YELLOW 0x03 #define COLOR_BLUE 0x04 #define COLOR_MAGENTA 0x05 #define COLOR_CYAN 0x06 #define COLOR_WHITE 0x07 /* TGI color defines */ /* White and red are swapped, so that the pallete ** driver is compatible with black-and-white drivers. */ #define TGI_COLOR_BLACK COLOR_BLACK #define TGI_COLOR_WHITE 1 #define TGI_COLOR_GREEN COLOR_GREEN #define TGI_COLOR_YELLOW COLOR_YELLOW #define TGI_COLOR_BLUE COLOR_BLUE #define TGI_COLOR_MAGENTA COLOR_MAGENTA #define TGI_COLOR_CYAN COLOR_CYAN #define TGI_COLOR_RED 7 /* Define hardware */ #include <_6522.h> #define VIA (*(struct __6522*)0x300) /* These are defined to be FUNCT + NumberKey */ #define CH_F1 0xB1 #define CH_F2 0xB2 #define CH_F3 0xB3 #define CH_F4 0xB4 #define CH_F5 0xB5 #define CH_F6 0xB6 #define CH_F7 0xB7 #define CH_F8 0xB8 #define CH_F9 0xB9 #define CH_F10 0xB0 /* Character codes */ #define CH_ULCORNER '+' #define CH_URCORNER '+' #define CH_LLCORNER '+' #define CH_LRCORNER '+' #define CH_TTEE '+' #define CH_BTEE '+' #define CH_LTEE '+' #define CH_RTEE '+' #define CH_CROSS '+' #define CH_CURS_UP 11 #define CH_CURS_DOWN 10 #define CH_CURS_LEFT 8 #define CH_CURS_RIGHT 9 #define CH_DEL 127 #define CH_ENTER 13 #define CH_STOP 3 #define CH_LIRA 95 #define CH_ESC 27 /* Masks for joy_read */ #define JOY_UP_MASK 0x10 #define JOY_DOWN_MASK 0x08 #define JOY_LEFT_MASK 0x01 #define JOY_RIGHT_MASK 0x02 #define JOY_BTN_1_MASK 0x20 /* No support for dynamically loadable drivers */ #define DYN_DRV 0 /* The addresses of the static drivers */ extern void atmos_pase_joy[]; /* Referred to by joy_static_stddrv[] */ extern void atmos_ijk_joy[]; extern void atmos_acia_ser[]; extern void atmos_228_200_3_tgi[]; extern void atmos_240_200_2_tgi[]; /* Referred to by tgi_static_stddrv[] */ /*****************************************************************************/ /* Functions */ /*****************************************************************************/ void __fastcall__ atmos_load(const char* name); /* Load Atmos tape. */ void __fastcall__ atmos_save(const char* name, const void* start, const void* end); /* Save Atmos tape. */ void atmos_explode (void); /* Bomb sound effect */ void atmos_ping (void); /* Bell or ricochet sound effect */ void atmos_shoot (void); /* Pistol sound effect */ void atmos_tick (void); /* High-pitch click */ void atmos_tock (void); /* Low-pitch click */ void atmos_zap (void); /* Raygun sound effect */ /* End of atmos.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/c128.h����������������������������������������������������������������������������0000664�0000000�0000000�00000014566�13473601511�0014472�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* c128.h */ /* */ /* C128 system specific definitions */ /* */ /* */ /* */ /* (C) 1998-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _C128_H #define _C128_H /* Check for errors */ #if !defined(__C128__) # error This module may only be used when compiling for the C128! #endif /* Additional key defines */ #define CH_F1 133 #define CH_F2 137 #define CH_F3 134 #define CH_F4 138 #define CH_F5 135 #define CH_F6 139 #define CH_F7 136 #define CH_F8 140 /* Color defines */ #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 /* TGI color defines */ #define TGI_COLOR_BLACK COLOR_BLACK #define TGI_COLOR_WHITE COLOR_WHITE #define TGI_COLOR_RED COLOR_RED #define TGI_COLOR_CYAN COLOR_CYAN #define TGI_COLOR_VIOLET COLOR_VIOLET #define TGI_COLOR_GREEN COLOR_GREEN #define TGI_COLOR_BLUE COLOR_BLUE #define TGI_COLOR_YELLOW COLOR_YELLOW #define TGI_COLOR_ORANGE COLOR_ORANGE #define TGI_COLOR_BROWN COLOR_BROWN #define TGI_COLOR_LIGHTRED COLOR_LIGHTRED #define TGI_COLOR_GRAY1 COLOR_GRAY1 #define TGI_COLOR_GRAY2 COLOR_GRAY2 #define TGI_COLOR_LIGHTGREEN COLOR_LIGHTGREEN #define TGI_COLOR_LIGHTBLUE COLOR_LIGHTBLUE #define TGI_COLOR_GRAY3 COLOR_GRAY3 /* Masks for joy_read */ #define JOY_UP_MASK 0x01 #define JOY_DOWN_MASK 0x02 #define JOY_LEFT_MASK 0x04 #define JOY_RIGHT_MASK 0x08 #define JOY_BTN_1_MASK 0x10 /* Video mode defines */ #define VIDEOMODE_40x25 0x00 #define VIDEOMODE_80x25 0x80 #define VIDEOMODE_40COL VIDEOMODE_40x25 #define VIDEOMODE_80COL VIDEOMODE_80x25 /* Define hardware */ #include <_vic2.h> #define VIC (*(struct __vic2*)0xD000) #include <_sid.h> #define SID (*(struct __sid*)0xD400) #include <_vdc.h> #define VDC (*(struct __vdc*)0xD600) #include <_6526.h> #define CIA1 (*(struct __6526*)0xDC00) #define CIA2 (*(struct __6526*)0xDD00) /* Define special memory areas */ #define COLOR_RAM ((unsigned char*)0xD800) /* The addresses of the static drivers */ extern void c128_georam_emd[]; extern void c128_ram_emd[]; extern void c128_ram2_emd[]; extern void c128_ramcart_emd[]; extern void c128_reu_emd[]; extern void c128_vdc_emd[]; extern void c128_ptvjoy_joy[]; extern void c128_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */ extern void c128_1351_mou[]; /* Referred to by mouse_static_stddrv[] */ extern void c128_joy_mou[]; extern void c128_inkwell_mou[]; extern void c128_pot_mou[]; extern void c128_swlink_ser[]; extern void c128_hi_tgi[]; extern void c128_vdc_tgi[]; /* Referred to by tgi_static_stddrv[] */ extern void c128_vdc2_tgi[]; unsigned __fastcall__ videomode (unsigned Mode); /* Set the video mode, return the old mode. Call with one of the VIDEOMODE_xx ** constants. */ void toggle_videomode (void); /* Toggle the video mode between 40 and 80 chars (calls SWAPPER). ** THIS FUNCTION IS DEPRECATED, please use videomode instead! */ void c64mode (void); /* Switch the C128 into C64 mode. Note: This function will not return! */ void fast (void); /* Switch the CPU into 2MHz mode. Note: This will disable video when in ** 40 column mode. */ void slow (void); /* Switch the CPU into 1MHz mode. */ unsigned char isfast (void); /* Returns 1 if the CPU is in 2MHz mode. */ /* End of c128.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/c16.h�����������������������������������������������������������������������������0000664�0000000�0000000�00000005625�13473601511�0014402�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* c16.h */ /* */ /* C16 system specific definitions */ /* */ /* */ /* */ /* (C) 2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 _C16_H #define _C16_H /* Check for errors */ #if !defined(__C16__) # error This module may only be used when compiling for the C16! #endif /* Include the base header file for the 264 series. */ #include <cbm264.h> /* The addresses of the static drivers */ extern void c16_ram_emd[]; extern void c16_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */ /* End of c16.h */ #endif �����������������������������������������������������������������������������������������������������������cc65-2.18/include/c64.h�����������������������������������������������������������������������������0000664�0000000�0000000�00000015471�13473601511�0014405�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* c64.h */ /* */ /* C64 system-specific definitions */ /* */ /* */ /* */ /* (C) 1998-2013 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _C64_H #define _C64_H /* Check for errors */ #if !defined(__C64__) # error This module may only be used when compiling for the C64! #endif /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Additional key defines */ #define CH_F1 133 #define CH_F2 137 #define CH_F3 134 #define CH_F4 138 #define CH_F5 135 #define CH_F6 139 #define CH_F7 136 #define CH_F8 140 /* Color defines */ #define COLOR_BLACK 0x00 #define COLOR_WHITE 0x01 #define COLOR_RED 0x02 #define COLOR_CYAN 0x03 #define COLOR_VIOLET 0x04 #define COLOR_PURPLE COLOR_VIOLET #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 /* TGI color defines */ #define TGI_COLOR_BLACK COLOR_BLACK #define TGI_COLOR_WHITE COLOR_WHITE #define TGI_COLOR_RED COLOR_RED #define TGI_COLOR_CYAN COLOR_CYAN #define TGI_COLOR_VIOLET COLOR_VIOLET #define TGI_COLOR_PURPLE COLOR_PURPLE #define TGI_COLOR_GREEN COLOR_GREEN #define TGI_COLOR_BLUE COLOR_BLUE #define TGI_COLOR_YELLOW COLOR_YELLOW #define TGI_COLOR_ORANGE COLOR_ORANGE #define TGI_COLOR_BROWN COLOR_BROWN #define TGI_COLOR_LIGHTRED COLOR_LIGHTRED #define TGI_COLOR_GRAY1 COLOR_GRAY1 #define TGI_COLOR_GRAY2 COLOR_GRAY2 #define TGI_COLOR_LIGHTGREEN COLOR_LIGHTGREEN #define TGI_COLOR_LIGHTBLUE COLOR_LIGHTBLUE #define TGI_COLOR_GRAY3 COLOR_GRAY3 /* Masks for joy_read */ #define JOY_UP_MASK 0x01 #define JOY_DOWN_MASK 0x02 #define JOY_LEFT_MASK 0x04 #define JOY_RIGHT_MASK 0x08 #define JOY_BTN_1_MASK 0x10 /* Define hardware */ #include <_vic2.h> #define VIC (*(struct __vic2*)0xD000) #include <_sid.h> #define SID (*(struct __sid*)0xD400) #include <_6526.h> #define CIA1 (*(struct __6526*)0xDC00) #define CIA2 (*(struct __6526*)0xDD00) /* Define special memory areas */ #define COLOR_RAM ((unsigned char*)0xD800) /* Return codes for get_ostype */ #define C64_OS_US 0xAA /* US version */ #define C64_OS_PET64 0x64 /* PET 64 */ #define C64_OS_SX64 0x43 /* SX-64 */ #define C64_EU_NEW 0x03 #define C64_EU_OLD 0x00 #define C64_DTV 0xFF /* C64 DTV */ /*****************************************************************************/ /* Variables */ /*****************************************************************************/ /* The addresses of the static drivers */ extern void c64_65816_emd[]; extern void c64_c256k_emd[]; extern void c64_dqbb_emd[]; extern void c64_georam_emd[]; extern void c64_isepic_emd[]; extern void c64_ram_emd[]; extern void c64_ramcart_emd[]; extern void c64_reu_emd[]; extern void c64_vdc_emd[]; extern void dtv_himem_emd[]; extern void c64_hitjoy_joy[]; extern void c64_numpad_joy[]; extern void c64_ptvjoy_joy[]; extern void c64_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */ extern void c64_1351_mou[]; /* Referred to by mouse_static_stddrv[] */ extern void c64_joy_mou[]; extern void c64_inkwell_mou[]; extern void c64_pot_mou[]; extern void c64_swlink_ser[]; extern void c64_hi_tgi[]; /* Referred to by tgi_static_stddrv[] */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned char get_ostype (void); /* Get the ROM version. Returns one of the C64_OS_xxx codes. */ /* End of c64.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/cbm.h�����������������������������������������������������������������������������0000664�0000000�0000000�00000026132�13473601511�0014546�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* cbm.h */ /* */ /* CBM system-specific definitions */ /* */ /* */ /* */ /* (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 */ /* 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 _CBM_H #define _CBM_H /* Check for errors */ #if !defined(__CBM__) # error This module may be used only when compiling for CBM machines! #endif /* We need NULL. */ #include <stddef.h> /* Load the system-specific files here, if needed. */ #if defined(__C64__) && !defined(_C64_H) # include <c64.h> #elif defined(__VIC20__) && !defined(_VIC20_H) # include <vic20.h> #elif defined(__C128__) && !defined(_C128_H) # include <c128.h> #elif defined(__PLUS4__) && !defined(_PLUS4_H) # include <plus4.h> #elif defined(__C16__) && !defined(_C16_H) # include <c16.h> #elif defined(__CBM510__) && !defined(_CBM510_H) # include <cbm510.h> #elif defined(__CBM610__) && !defined(_CBM610_H) # include <cbm610.h> #elif defined(__PET__) && !defined(_PET_H) # include <pet.h> #endif /* Include definitions for CBM file types */ #include <cbm_filetype.h> #define JOY_FIRE_MASK JOY_BTN_1_MASK #define JOY_FIRE(v) ((v) & JOY_FIRE_MASK) /*****************************************************************************/ /* Variables */ /*****************************************************************************/ /* The file stream implementation and the POSIX I/O functions will ** use the following variable to determine the file type to use. */ extern char _filetype; /* Defaults to 's' */ /*****************************************************************************/ /* Character-codes (CBM charset) */ /*****************************************************************************/ #define CH_HLINE 192 #define CH_VLINE 221 #define CH_ULCORNER 176 #define CH_URCORNER 174 #define CH_LLCORNER 173 #define CH_LRCORNER 189 #define CH_TTEE 178 #define CH_BTEE 177 #define CH_LTEE 171 #define CH_RTEE 179 #define CH_CROSS 219 #define CH_CURS_UP 145 #define CH_CURS_DOWN 17 #define CH_CURS_LEFT 157 #define CH_CURS_RIGHT 29 #define CH_PI 222 #define CH_HOME 19 #define CH_DEL 20 #define CH_INS 148 #define CH_ENTER 13 #define CH_STOP 3 #define CH_LIRA 92 #define CH_ESC 27 /*****************************************************************************/ /* Definitions for directory reading functions */ /*****************************************************************************/ /* CBM FILE ACCESS */ #define CBM_A_RO 1 /* Read only */ #define CBM_A_WO 2 /* Write only */ #define CBM_A_RW 3 /* Read, Write */ struct cbm_dirent { char name[17]; /* File name in PetSCII, limited to 16 chars */ unsigned int size; /* Size, in 254-/256-byte blocks */ unsigned char type; unsigned char access; }; /*****************************************************************************/ /* Machine info */ /*****************************************************************************/ #define TV_NTSC 0 #define TV_PAL 1 #define TV_OTHER 2 unsigned char get_tv (void); /* Return the video mode the machine is using. */ #define KBREPEAT_CURSOR 0x00 #define KBREPEAT_NONE 0x40 #define KBREPEAT_ALL 0x80 unsigned char __fastcall__ kbrepeat (unsigned char mode); /* Changes which keys have automatic repeat. */ #if !defined(__CBM610__) && !defined(__PET__) void waitvsync (void); /* Wait for the start of the next frame */ #endif /*****************************************************************************/ /* CBM kernal functions */ /*****************************************************************************/ /* Constants to use with cbm_open() for openning a file for reading or ** writing without the need to append ",r" or ",w" to the filename. ** ** e.g., cbm_open(2, 8, CBM_READ, "0:data,s"); */ #define CBM_READ 0 /* default is ",p" */ #define CBM_WRITE 1 /* ditto */ #define CBM_SEQ 2 /* default is ",r" -- or ",s" when writing */ /* Kernal-level functions */ unsigned char cbm_k_acptr (void); unsigned char cbm_k_basin (void); void __fastcall__ cbm_k_bsout (unsigned char C); unsigned char __fastcall__ cbm_k_chkin (unsigned char FN); void __fastcall__ cbm_k_ciout (unsigned char C); unsigned char __fastcall__ cbm_k_ckout (unsigned char FN); void cbm_k_clall (void); void __fastcall__ cbm_k_close (unsigned char FN); void cbm_k_clrch (void); unsigned char cbm_k_getin (void); unsigned cbm_k_iobase (void); void __fastcall__ cbm_k_listen (unsigned char dev); unsigned int __fastcall__ cbm_k_load(unsigned char flag, unsigned addr); unsigned char cbm_k_open (void); unsigned char cbm_k_readst (void); unsigned char __fastcall__ cbm_k_save(unsigned int start, unsigned int end); void cbm_k_scnkey (void); void __fastcall__ cbm_k_second (unsigned char addr); void __fastcall__ cbm_k_setlfs (unsigned char LFN, unsigned char DEV, unsigned char SA); void __fastcall__ cbm_k_setnam (const char* Name); void __fastcall__ cbm_k_talk (unsigned char dev); void __fastcall__ cbm_k_tksa (unsigned char addr); void cbm_k_udtim (void); void cbm_k_unlsn (void); void cbm_k_untlk (void); /*****************************************************************************/ /* BASIC-like file I/O functions */ /*****************************************************************************/ /* The cbm_* I/O functions below set _oserror (see errno.h), ** in case of an error. ** ** error-code BASIC error ** ---------- ----------- ** 1 = too many files ** 2 = file open ** 3 = file not open ** 4 = file not found ** 5 = device not present ** 6 = not input-file ** 7 = not output-file ** 8 = missing file-name ** 9 = illegal device-number ** ** 10 = STOP-key pushed ** 11 = general I/O-error */ 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). ** Returns number of bytes that were loaded if loading was successful; ** otherwise 0, "_oserror" contains an error-code, then (see table above). */ unsigned char __fastcall__ cbm_save (const char* name, unsigned char device, const void* addr, unsigned int size); /* Saves "size" bytes, starting at "addr", to a file. ** Returns 0 if saving was successful, otherwise an error-code (see table ** above). */ unsigned char __fastcall__ cbm_open (unsigned char lfn, unsigned char device, unsigned char sec_addr, const char* name); /* Opens a file. Works just like the BASIC command. ** Returns 0 if openning was successful, otherwise an error-code (see table ** above). */ void __fastcall__ cbm_close (unsigned char lfn); /* Closes a file */ int __fastcall__ cbm_read (unsigned char lfn, void* buffer, unsigned int size); /* Reads up to "size" bytes from a file into "buffer". ** Returns the number of actually-read bytes, 0 if there are no bytes left. ** -1 in case of an error; then, _oserror contains an error-code (see table ** above). (Remember: 0 means end-of-file; -1 means error.) */ int __fastcall__ cbm_write (unsigned char lfn, const void* buffer, unsigned int size); /* Writes up to "size" bytes from "buffer" to a file. ** Returns the number of actually-written bytes, or -1 in case of an error; ** _oserror contains an error-code, then (see above table). */ unsigned char cbm_opendir (unsigned char lfn, unsigned char device, ...); /* Opens directory listing. Returns 0 if opening directory was successful; ** otherwise, an error-code corresponding to cbm_open(). As an optional ** argument, the name of the directory may be passed to the function. If ** no explicit name is specified, "$" is used. */ unsigned char __fastcall__ cbm_readdir (unsigned char lfn, struct cbm_dirent* l_dirent); /* Reads one directory line into cbm_dirent structure. ** Returns 0 if reading directory-line was successful. ** Returns non-zero if reading directory failed, or no more file-names to read. ** Returns 2 on last line. Then, l_dirent->size = the number of "blocks free." */ void __fastcall__ cbm_closedir (unsigned char lfn); /* Closes directory by cbm_close(lfn) */ /* End of cbm.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/cbm264.h��������������������������������������������������������������������������0000664�0000000�0000000�00000014207�13473601511�0015002�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* cbm264.h */ /* */ /* System specific definitions for the C16, C116 and Plus/4 */ /* */ /* */ /* */ /* (C) 1998-2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _CBM264_H #define _CBM264_H /* Check for errors */ #if !defined(__C16__) # error This module may only be used when compiling for the Plus/4 or C16! #endif /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Additional key defines */ #define CH_F1 133 #define CH_F2 137 #define CH_F3 134 #define CH_F4 138 #define CH_F5 135 #define CH_F6 139 #define CH_F7 136 #define CH_F8 140 /* Color attributes */ #define CATTR_LUMA0 0x00 #define CATTR_LUMA1 0x10 #define CATTR_LUMA2 0x20 #define CATTR_LUMA3 0x30 #define CATTR_LUMA4 0x40 #define CATTR_LUMA5 0x50 #define CATTR_LUMA6 0x60 #define CATTR_LUMA7 0x70 #define CATTR_BLINK 0x80 /* Base colors */ #define BCOLOR_BLACK 0x00 #define BCOLOR_WHITE 0x01 #define BCOLOR_RED 0x02 #define BCOLOR_CYAN 0x03 #define BCOLOR_VIOLET 0x04 #define BCOLOR_PURPLE BCOLOR_VIOLET #define BCOLOR_GREEN 0x05 #define BCOLOR_BLUE 0x06 #define BCOLOR_YELLOW 0x07 #define BCOLOR_ORANGE 0x08 #define BCOLOR_BROWN 0x09 #define BCOLOR_LEMON 0x0A /* What's that color? */ #define BCOLOR_LIGHTVIOLET 0x0B #define BCOLOR_BLUEGREEN 0x0C #define BCOLOR_LIGHTBLUE 0x0D #define BCOLOR_DARKBLUE 0x0E #define BCOLOR_LIGHTGREEN 0x0F /* Now try to mix up a C64/C128 compatible palette */ #define COLOR_BLACK (BCOLOR_BLACK) #define COLOR_WHITE (BCOLOR_WHITE | CATTR_LUMA7) #define COLOR_RED (BCOLOR_RED | CATTR_LUMA4) #define COLOR_CYAN (BCOLOR_CYAN | CATTR_LUMA7) #define COLOR_VIOLET (BCOLOR_VIOLET | CATTR_LUMA7) #define COLOR_PURPLE COLOR_VIOLET #define COLOR_GREEN (BCOLOR_GREEN | CATTR_LUMA7) #define COLOR_BLUE (BCOLOR_BLUE | CATTR_LUMA7) #define COLOR_YELLOW (BCOLOR_YELLOW | CATTR_LUMA7) #define COLOR_ORANGE (BCOLOR_ORANGE | CATTR_LUMA7) #define COLOR_BROWN (BCOLOR_BROWN | CATTR_LUMA7) #define COLOR_LIGHTRED (BCOLOR_RED | CATTR_LUMA7) #define COLOR_GRAY1 (BCOLOR_WHITE | CATTR_LUMA1) #define COLOR_GRAY2 (BCOLOR_WHITE | CATTR_LUMA3) #define COLOR_LIGHTGREEN (BCOLOR_LIGHTGREEN | CATTR_LUMA7) #define COLOR_LIGHTBLUE (BCOLOR_LIGHTBLUE | CATTR_LUMA7) #define COLOR_GRAY3 (BCOLOR_WHITE | CATTR_LUMA5) /* Masks for joy_read */ #define JOY_UP_MASK 0x01 #define JOY_DOWN_MASK 0x02 #define JOY_LEFT_MASK 0x04 #define JOY_RIGHT_MASK 0x08 #define JOY_BTN_1_MASK 0x80 /* Define hardware */ #include <_ted.h> #define TED (*(struct __ted*)0xFF00) /* Define special memory areas */ #define COLOR_RAM ((unsigned char*)0x0800) /*****************************************************************************/ /* Code */ /*****************************************************************************/ void fast (void); /* Switch the CPU into double-clock mode. */ void slow (void); /* Switch the CPU into single-clock mode. */ unsigned char isfast (void); /* Returns 1 if the CPU is in double-clock mode. */ /* End of cbm264.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/cbm510.h��������������������������������������������������������������������������0000664�0000000�0000000�00000014704�13473601511�0014776�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* cbm510.h */ /* */ /* System-specific definitions for the CBM5x0 / P500 */ /* */ /* */ /* */ /* (C) 2001-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _CBM510_H #define _CBM510_H /* Check for errors */ #if !defined(__CBM510__) # error This module may only be used when compiling for the CBM 510! #endif /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Additional key defines */ #define CH_F1 224 #define CH_F2 225 #define CH_F3 226 #define CH_F4 227 #define CH_F5 228 #define CH_F6 229 #define CH_F7 230 #define CH_F8 231 #define CH_F9 232 #define CH_F10 233 #define CH_F11 234 #define CH_F12 235 #define CH_F13 236 #define CH_F14 237 #define CH_F15 238 #define CH_F16 239 #define CH_F17 240 #define CH_F18 241 #define CH_F19 242 #define CH_F20 243 /* Color defines */ #define COLOR_BLACK 0x00 #define COLOR_WHITE 0x01 #define COLOR_RED 0x02 #define COLOR_CYAN 0x03 #define COLOR_VIOLET 0x04 #define COLOR_PURPLE COLOR_VIOLET #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 /* Masks for joy_read */ #define JOY_UP_MASK 0x01 #define JOY_DOWN_MASK 0x02 #define JOY_LEFT_MASK 0x04 #define JOY_RIGHT_MASK 0x08 #define JOY_BTN_1_MASK 0x10 /* Define hardware */ #include <_vic2.h> #define VIC (*(struct __vic2*)0xD800) #include <_sid.h> #define SID (*(struct __sid*)0xDA00) #include <_6526.h> #define CIA2 (*(struct __6526*)0xDC00) #include <_6551.h> #define ACIA (*(struct __6551*)0xDD00) #include <_6525.h> #define TPI1 (*(struct __6525*)0xDE00) #define TPI2 (*(struct __6525*)0xDF00) /*****************************************************************************/ /* Variables */ /*****************************************************************************/ /* The addresses of the static drivers */ extern void cbm510_inkwl_mou[]; extern void cbm510_joy_mou[]; /* Referred to by mouse_static_stddrv[] */ extern void cbm510_ram_emd[]; extern void cbm510_std_joy[]; /* Referred to by joy_static_stddrv[] */ extern void cbm510_std_ser[]; /*****************************************************************************/ /* Code */ /*****************************************************************************/ /* Special routines to read/write bytes and words in the system bank */ unsigned char __fastcall__ peekbsys (unsigned addr); unsigned __fastcall__ peekwsys (unsigned addr); void __fastcall__ pokebsys (unsigned addr, unsigned char val); void __fastcall__ pokewsys (unsigned addr, unsigned val); #if defined(__OPT_i__) && (__OPT_i__ >= 600) #define peekbsys(addr) \ __AX__ = (addr), \ __asm__ ("sta ptr1"), \ __asm__ ("stx ptr1+1"), \ __asm__ ("ldx $01"), \ __asm__ ("lda #$0F"), \ __asm__ ("sta $01"), \ __asm__ ("ldy #$00"), \ __asm__ ("lda (ptr1),y"), \ __asm__ ("stx $01"), \ __asm__ ("ldx #$00"), \ __AX__ #endif /* End of cbm510.h */ #endif ������������������������������������������������������������cc65-2.18/include/cbm610.h��������������������������������������������������������������������������0000664�0000000�0000000�00000013612�13473601511�0014774�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* cbm610.h */ /* */ /* CBM610 system specific definitions */ /* */ /* */ /* */ /* (C) 1998-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _CBM610_H #define _CBM610_H /* Check for errors */ #if !defined(__CBM610__) # error This module may only be used when compiling for the CBM 610! #endif /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Additional key defines */ #define CH_F1 224 #define CH_F2 225 #define CH_F3 226 #define CH_F4 227 #define CH_F5 228 #define CH_F6 229 #define CH_F7 230 #define CH_F8 231 #define CH_F9 232 #define CH_F10 233 #define CH_F11 234 #define CH_F12 235 #define CH_F13 236 #define CH_F14 237 #define CH_F15 238 #define CH_F16 239 #define CH_F17 240 #define CH_F18 241 #define CH_F19 242 #define CH_F20 243 /* Color defines */ #define COLOR_BLACK 0x00 #define COLOR_WHITE 0x01 /* Define hardware */ #include <_6545.h> #define CRTC (*(struct __6545)0xD800) #include <_sid.h> #define SID (*(struct __sid*)0xDA00) #include <_6526.h> #define CIA1 (*(struct __6526*)0xDB00) #define CIA2 (*(struct __6526*)0xDC00) #include <_6551.h> #define ACIA (*(struct __6551*)0xDD00) #include <_6525.h> #define TPI1 (*(struct __6525*)0xDE00) #define TPI2 (*(struct __6525*)0xDF00) /*****************************************************************************/ /* Variables */ /*****************************************************************************/ /* The addresses of the static drivers */ extern void cbm610_ram_emd[]; extern void cbm610_std_ser[]; /*****************************************************************************/ /* Code */ /*****************************************************************************/ /* Special routines to read/write bytes and words in the system bank */ unsigned char __fastcall__ peekbsys (unsigned addr); unsigned __fastcall__ peekwsys (unsigned addr); void __fastcall__ pokebsys (unsigned addr, unsigned char val); void __fastcall__ pokewsys (unsigned addr, unsigned val); #if defined(__OPT_i__) && (__OPT_i__ >= 600) #define peekbsys(addr) \ __AX__ = (addr), \ __asm__ ("sta ptr1"), \ __asm__ ("stx ptr1+1"), \ __asm__ ("ldx $01"), \ __asm__ ("lda #$0F"), \ __asm__ ("sta $01"), \ __asm__ ("ldy #$00"), \ __asm__ ("lda (ptr1),y"), \ __asm__ ("stx $01"), \ __asm__ ("ldx #$00"), \ __AX__ #endif /* The following #defines will cause the matching functions calls in conio.h ** to be overlaid by macros with the same names, saving the function call ** overhead. */ #define _textcolor(color) COLOR_WHITE #define _bgcolor(color) COLOR_BLACK #define _bordercolor(color) COLOR_BLACK #define _cpeekcolor(color) COLOR_WHITE /* End of cbm610.h */ #endif ����������������������������������������������������������������������������������������������������������������������cc65-2.18/include/cbm_filetype.h��������������������������������������������������������������������0000664�0000000�0000000�00000011525�13473601511�0016447�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* cbm_filetype.h */ /* */ /* Definitions for CBM file types */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _CBM_FILETYPE_H #define _CBM_FILETYPE_H /* Check for errors */ #if !defined(__CBM__) # error This module may be used only when compiling for CBM machines! #endif /*****************************************************************************/ /* Definitions */ /*****************************************************************************/ /* CBM FILE TYPES. The definitions are used within standard headers, so we ** be careful with identifiers in the user name space. ** "Regular" files have a special bit set so it's easier to pick them out. */ #define _CBM_T_REG 0x10U /* Bit set for regular files */ #define _CBM_T_SEQ 0x10U #define _CBM_T_PRG 0x11U #define _CBM_T_USR 0x12U #define _CBM_T_REL 0x13U #define _CBM_T_VRP 0x14U /* Vorpal fast-loadable format */ #define _CBM_T_DEL 0x00U #define _CBM_T_CBM 0x01U /* 1581 sub-partition */ #define _CBM_T_DIR 0x02U /* IDE64 and CMD sub-directory */ #define _CBM_T_LNK 0x03U /* IDE64 soft-link */ #define _CBM_T_OTHER 0x04U /* File-type not recognized */ #define _CBM_T_HEADER 0x05U /* Disk header / title */ #if __CC65_STD__ == __CC65_STD_CC65__ /* Allow for names without leading underscores */ #define CBM_T_DEL _CBM_T_DEL #define CBM_T_SEQ _CBM_T_SEQ #define CBM_T_PRG _CBM_T_PRG #define CBM_T_USR _CBM_T_USR #define CBM_T_REL _CBM_T_REL #define CBM_T_CBM _CBM_T_CBM #define CBM_T_DIR _CBM_T_DIR #define CBM_T_LNK _CBM_T_LNK #define CBM_T_VRP _CBM_T_VRP #define CBM_T_OTHER _CBM_T_OTHER #define CBM_T_HEADER _CBM_T_HEADER #endif /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned char __fastcall__ _cbm_filetype (unsigned char c); /* Map the start character for a file type to one of the file types above. ** Note: 'd' will always mapped to CBM_T_DEL. The calling function has to ** look at the following character to determine if the file type is actually ** CBM_T_DIR. ** This is a function used by the implementation. There is usually no need ** to call it from user code. */ /* End of cbm_filetype.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/cbm_petscii_charmap.h�������������������������������������������������������������0000664�0000000�0000000�00000023014�13473601511�0017755�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* cbm_petscii_charmap.h */ /* */ /* CBM system standard string mapping (ISO-8859-1 -> PetSCII) */ /* */ /* */ /* 2019-03-10, Greg King */ /* */ /* 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 must not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* No include guard here! Multiple use in one file might be intentional. */ #pragma warn (remap-zero, push, off) #pragma charmap (0x00, 0x00) #pragma charmap (0x01, 0x01) #pragma charmap (0x02, 0x02) #pragma charmap (0x03, 0x03) #pragma charmap (0x04, 0x04) #pragma charmap (0x05, 0x05) #pragma charmap (0x06, 0x06) #pragma charmap (0x07, 0x07) #pragma charmap (0x08, 0x14) #pragma charmap (0x09, 0x09) #pragma charmap (0x0A, 0x0D) #pragma charmap (0x0B, 0x11) #pragma charmap (0x0C, 0x93) #pragma charmap (0x0D, 0x0A) #pragma charmap (0x0E, 0x0E) #pragma charmap (0x0F, 0x0F) #pragma charmap (0x10, 0x10) #pragma charmap (0x11, 0x0B) #pragma charmap (0x12, 0x12) #pragma charmap (0x13, 0x13) #pragma charmap (0x14, 0x08) #pragma charmap (0x15, 0x15) #pragma charmap (0x16, 0x16) #pragma charmap (0x17, 0x17) #pragma charmap (0x18, 0x18) #pragma charmap (0x19, 0x19) #pragma charmap (0x1A, 0x1A) #pragma charmap (0x1B, 0x1B) #pragma charmap (0x1C, 0x1C) #pragma charmap (0x1D, 0x1D) #pragma charmap (0x1E, 0x1E) #pragma charmap (0x1F, 0x1F) #pragma charmap (0x20, 0x20) #pragma charmap (0x21, 0x21) #pragma charmap (0x22, 0x22) #pragma charmap (0x23, 0x23) #pragma charmap (0x24, 0x24) #pragma charmap (0x25, 0x25) #pragma charmap (0x26, 0x26) #pragma charmap (0x27, 0x27) #pragma charmap (0x28, 0x28) #pragma charmap (0x29, 0x29) #pragma charmap (0x2A, 0x2A) #pragma charmap (0x2B, 0x2B) #pragma charmap (0x2C, 0x2C) #pragma charmap (0x2D, 0x2D) #pragma charmap (0x2E, 0x2E) #pragma charmap (0x2F, 0x2F) #pragma charmap (0x30, 0x30) #pragma charmap (0x31, 0x31) #pragma charmap (0x32, 0x32) #pragma charmap (0x33, 0x33) #pragma charmap (0x34, 0x34) #pragma charmap (0x35, 0x35) #pragma charmap (0x36, 0x36) #pragma charmap (0x37, 0x37) #pragma charmap (0x38, 0x38) #pragma charmap (0x39, 0x39) #pragma charmap (0x3A, 0x3A) #pragma charmap (0x3B, 0x3B) #pragma charmap (0x3C, 0x3C) #pragma charmap (0x3D, 0x3D) #pragma charmap (0x3E, 0x3E) #pragma charmap (0x3F, 0x3F) #pragma charmap (0x40, 0x40) #pragma charmap (0x41, 0xC1) #pragma charmap (0x42, 0xC2) #pragma charmap (0x43, 0xC3) #pragma charmap (0x44, 0xC4) #pragma charmap (0x45, 0xC5) #pragma charmap (0x46, 0xC6) #pragma charmap (0x47, 0xC7) #pragma charmap (0x48, 0xC8) #pragma charmap (0x49, 0xC9) #pragma charmap (0x4A, 0xCA) #pragma charmap (0x4B, 0xCB) #pragma charmap (0x4C, 0xCC) #pragma charmap (0x4D, 0xCD) #pragma charmap (0x4E, 0xCE) #pragma charmap (0x4F, 0xCF) #pragma charmap (0x50, 0xD0) #pragma charmap (0x51, 0xD1) #pragma charmap (0x52, 0xD2) #pragma charmap (0x53, 0xD3) #pragma charmap (0x54, 0xD4) #pragma charmap (0x55, 0xD5) #pragma charmap (0x56, 0xD6) #pragma charmap (0x57, 0xD7) #pragma charmap (0x58, 0xD8) #pragma charmap (0x59, 0xD9) #pragma charmap (0x5A, 0xDA) #pragma charmap (0x5B, 0x5B) #pragma charmap (0x5C, 0xBF) #pragma charmap (0x5D, 0x5D) #pragma charmap (0x5E, 0x5E) #pragma charmap (0x5F, 0xA4) #pragma charmap (0x60, 0xAD) #pragma charmap (0x61, 0x41) #pragma charmap (0x62, 0x42) #pragma charmap (0x63, 0x43) #pragma charmap (0x64, 0x44) #pragma charmap (0x65, 0x45) #pragma charmap (0x66, 0x46) #pragma charmap (0x67, 0x47) #pragma charmap (0x68, 0x48) #pragma charmap (0x69, 0x49) #pragma charmap (0x6A, 0x4A) #pragma charmap (0x6B, 0x4B) #pragma charmap (0x6C, 0x4C) #pragma charmap (0x6D, 0x4D) #pragma charmap (0x6E, 0x4E) #pragma charmap (0x6F, 0x4F) #pragma charmap (0x70, 0x50) #pragma charmap (0x71, 0x51) #pragma charmap (0x72, 0x52) #pragma charmap (0x73, 0x53) #pragma charmap (0x74, 0x54) #pragma charmap (0x75, 0x55) #pragma charmap (0x76, 0x56) #pragma charmap (0x77, 0x57) #pragma charmap (0x78, 0x58) #pragma charmap (0x79, 0x59) #pragma charmap (0x7A, 0x5A) #pragma charmap (0x7B, 0xB3) #pragma charmap (0x7C, 0xDD) #pragma charmap (0x7D, 0xAB) #pragma charmap (0x7E, 0xB1) #pragma charmap (0x7F, 0xDF) #pragma charmap (0x80, 0x80) #pragma charmap (0x81, 0x81) #pragma charmap (0x82, 0x82) #pragma charmap (0x83, 0x83) #pragma charmap (0x84, 0x84) #pragma charmap (0x85, 0x85) #pragma charmap (0x86, 0x86) #pragma charmap (0x87, 0x87) #pragma charmap (0x88, 0x88) #pragma charmap (0x89, 0x89) #pragma charmap (0x8A, 0x8A) #pragma charmap (0x8B, 0x8B) #pragma charmap (0x8C, 0x8C) #pragma charmap (0x8D, 0x8D) #pragma charmap (0x8E, 0x8E) #pragma charmap (0x8F, 0x8F) #pragma charmap (0x90, 0x90) #pragma charmap (0x91, 0x91) #pragma charmap (0x92, 0x92) #pragma charmap (0x93, 0x0C) #pragma charmap (0x94, 0x94) #pragma charmap (0x95, 0x95) #pragma charmap (0x96, 0x96) #pragma charmap (0x97, 0x97) #pragma charmap (0x98, 0x98) #pragma charmap (0x99, 0x99) #pragma charmap (0x9A, 0x9A) #pragma charmap (0x9B, 0x9B) #pragma charmap (0x9C, 0x9C) #pragma charmap (0x9D, 0x9D) #pragma charmap (0x9E, 0x9E) #pragma charmap (0x9F, 0x9F) #pragma charmap (0xA0, 0xA0) #pragma charmap (0xA1, 0xA1) #pragma charmap (0xA2, 0xA2) #pragma charmap (0xA3, 0xA3) #pragma charmap (0xA4, 0xA4) #pragma charmap (0xA5, 0xA5) #pragma charmap (0xA6, 0xA6) #pragma charmap (0xA7, 0xA7) #pragma charmap (0xA8, 0xA8) #pragma charmap (0xA9, 0xA9) #pragma charmap (0xAA, 0xAA) #pragma charmap (0xAB, 0xAB) #pragma charmap (0xAC, 0xAC) #pragma charmap (0xAD, 0xAD) #pragma charmap (0xAE, 0xAE) #pragma charmap (0xAF, 0xAF) #pragma charmap (0xB0, 0xB0) #pragma charmap (0xB1, 0xB1) #pragma charmap (0xB2, 0xB2) #pragma charmap (0xB3, 0xB3) #pragma charmap (0xB4, 0xB4) #pragma charmap (0xB5, 0xB5) #pragma charmap (0xB6, 0xB6) #pragma charmap (0xB7, 0xB7) #pragma charmap (0xB8, 0xB8) #pragma charmap (0xB9, 0xB9) #pragma charmap (0xBA, 0xBA) #pragma charmap (0xBB, 0xBB) #pragma charmap (0xBC, 0xBC) #pragma charmap (0xBD, 0xBD) #pragma charmap (0xBE, 0xBE) #pragma charmap (0xBF, 0xBF) #pragma charmap (0xC0, 0x60) #pragma charmap (0xC1, 0x61) #pragma charmap (0xC2, 0x62) #pragma charmap (0xC3, 0x63) #pragma charmap (0xC4, 0x64) #pragma charmap (0xC5, 0x65) #pragma charmap (0xC6, 0x66) #pragma charmap (0xC7, 0x67) #pragma charmap (0xC8, 0x68) #pragma charmap (0xC9, 0x69) #pragma charmap (0xCA, 0x6A) #pragma charmap (0xCB, 0x6B) #pragma charmap (0xCC, 0x6C) #pragma charmap (0xCD, 0x6D) #pragma charmap (0xCE, 0x6E) #pragma charmap (0xCF, 0x6F) #pragma charmap (0xD0, 0x70) #pragma charmap (0xD1, 0x71) #pragma charmap (0xD2, 0x72) #pragma charmap (0xD3, 0x73) #pragma charmap (0xD4, 0x74) #pragma charmap (0xD5, 0x75) #pragma charmap (0xD6, 0x76) #pragma charmap (0xD7, 0x77) #pragma charmap (0xD8, 0x78) #pragma charmap (0xD9, 0x79) #pragma charmap (0xDA, 0x7A) #pragma charmap (0xDB, 0x7B) #pragma charmap (0xDC, 0x7C) #pragma charmap (0xDD, 0x7D) #pragma charmap (0xDE, 0x7E) #pragma charmap (0xDF, 0x7F) #pragma charmap (0xE0, 0xE0) #pragma charmap (0xE1, 0xE1) #pragma charmap (0xE2, 0xE2) #pragma charmap (0xE3, 0xE3) #pragma charmap (0xE4, 0xE4) #pragma charmap (0xE5, 0xE5) #pragma charmap (0xE6, 0xE6) #pragma charmap (0xE7, 0xE7) #pragma charmap (0xE8, 0xE8) #pragma charmap (0xE9, 0xE9) #pragma charmap (0xEA, 0xEA) #pragma charmap (0xEB, 0xEB) #pragma charmap (0xEC, 0xEC) #pragma charmap (0xED, 0xED) #pragma charmap (0xEE, 0xEE) #pragma charmap (0xEF, 0xEF) #pragma charmap (0xF0, 0xF0) #pragma charmap (0xF1, 0xF1) #pragma charmap (0xF2, 0xF2) #pragma charmap (0xF3, 0xF3) #pragma charmap (0xF4, 0xF4) #pragma charmap (0xF5, 0xF5) #pragma charmap (0xF6, 0xF6) #pragma charmap (0xF7, 0xF7) #pragma charmap (0xF8, 0xF8) #pragma charmap (0xF9, 0xF9) #pragma charmap (0xFA, 0xFA) #pragma charmap (0xFB, 0xFB) #pragma charmap (0xFC, 0xFC) #pragma charmap (0xFD, 0xFD) #pragma charmap (0xFE, 0xFE) #pragma charmap (0xFF, 0xFF) #pragma warn (remap-zero, pop) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/cbm_screen_charmap.h��������������������������������������������������������������0000664�0000000�0000000�00000022036�13473601511�0017577�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* cbm_screen_charmap.h */ /* */ /* (c) Copyright 2019, Gerhard W. Gruber (sparhawk@gmx.at) */ /* */ /* When using CBM mode, this include converts character literals */ /* from ASCII to screen-code mapping, so you can write directly */ /* to the screen memory. */ /* */ /* If this include is used, no additional macroes are needed. */ /* */ /*****************************************************************************/ /* No include guard here! Multiple use in one file may be intentional. */ #pragma warn (remap-zero, push, off) // Char $00 -> c + 128 #pragma charmap (0x00, 0x80) // Char $01 ... $1A -> c + 128 + 64 (control alphabet) #pragma charmap (0x01, 0xC1) #pragma charmap (0x02, 0xC2) #pragma charmap (0x03, 0xC3) #pragma charmap (0x04, 0xC4) #pragma charmap (0x05, 0xC5) #pragma charmap (0x06, 0xC6) #pragma charmap (0x07, 0xC7) #pragma charmap (0x08, 0xC8) #pragma charmap (0x09, 0xC9) #pragma charmap (0x0A, 0xCA) #pragma charmap (0x0B, 0xCB) #pragma charmap (0x0C, 0xCC) #pragma charmap (0x0D, 0xCD) #pragma charmap (0x0E, 0xCE) #pragma charmap (0x0F, 0xCF) #pragma charmap (0x10, 0xD0) #pragma charmap (0x11, 0xD1) #pragma charmap (0x12, 0xD2) #pragma charmap (0x13, 0xD3) #pragma charmap (0x14, 0xD4) #pragma charmap (0x15, 0xD5) #pragma charmap (0x16, 0xD6) #pragma charmap (0x17, 0xD7) #pragma charmap (0x18, 0xD8) #pragma charmap (0x19, 0xD9) #pragma charmap (0x1A, 0xDA) // Char $1B ... $1F -> c + 128 #pragma charmap (0x1B, 0x9B) #pragma charmap (0x1C, 0x9C) #pragma charmap (0x1D, 0x9D) #pragma charmap (0x1E, 0x9E) #pragma charmap (0x1F, 0x9F) // Char $20 ... $3F -> c #pragma charmap (0x20, 0x20) #pragma charmap (0x21, 0x21) #pragma charmap (0x22, 0x22) #pragma charmap (0x23, 0x23) #pragma charmap (0x24, 0x24) #pragma charmap (0x25, 0x25) #pragma charmap (0x26, 0x26) #pragma charmap (0x27, 0x27) #pragma charmap (0x28, 0x28) #pragma charmap (0x29, 0x29) #pragma charmap (0x2A, 0x2A) #pragma charmap (0x2B, 0x2B) #pragma charmap (0x2C, 0x2C) #pragma charmap (0x2D, 0x2D) #pragma charmap (0x2E, 0x2E) #pragma charmap (0x2F, 0x2F) #pragma charmap (0x30, 0x30) #pragma charmap (0x31, 0x31) #pragma charmap (0x32, 0x32) #pragma charmap (0x33, 0x33) #pragma charmap (0x34, 0x34) #pragma charmap (0x35, 0x35) #pragma charmap (0x36, 0x36) #pragma charmap (0x37, 0x37) #pragma charmap (0x38, 0x38) #pragma charmap (0x39, 0x39) #pragma charmap (0x3A, 0x3A) #pragma charmap (0x3B, 0x3B) #pragma charmap (0x3C, 0x3C) #pragma charmap (0x3D, 0x3D) #pragma charmap (0x3E, 0x3E) #pragma charmap (0x3F, 0x3F) // Char $40 -> c - 64 #pragma charmap (0x40, 0x00) // Char $41 ... $5A -> c (upper-case alphabet) #pragma charmap (0x41, 0x41) #pragma charmap (0x42, 0x42) #pragma charmap (0x43, 0x43) #pragma charmap (0x44, 0x44) #pragma charmap (0x45, 0x45) #pragma charmap (0x46, 0x46) #pragma charmap (0x47, 0x47) #pragma charmap (0x48, 0x48) #pragma charmap (0x49, 0x49) #pragma charmap (0x4A, 0x4A) #pragma charmap (0x4B, 0x4B) #pragma charmap (0x4C, 0x4C) #pragma charmap (0x4D, 0x4D) #pragma charmap (0x4E, 0x4E) #pragma charmap (0x4F, 0x4F) #pragma charmap (0x50, 0x50) #pragma charmap (0x51, 0x51) #pragma charmap (0x52, 0x52) #pragma charmap (0x53, 0x53) #pragma charmap (0x54, 0x54) #pragma charmap (0x55, 0x55) #pragma charmap (0x56, 0x56) #pragma charmap (0x57, 0x57) #pragma charmap (0x58, 0x58) #pragma charmap (0x59, 0x59) #pragma charmap (0x5A, 0x5A) // Char $5B ... $5F -> c - 64 #pragma charmap (0x5B, 0x1B) #pragma charmap (0x5C, 0x1C) #pragma charmap (0x5D, 0x1D) #pragma charmap (0x5E, 0x1E) #pragma charmap (0x5F, 0x1F) // Char $60 -> c - 32 #pragma charmap (0x60, 0x40) // Char $61 ... $7A -> c - 32 - 64 (lower-case alphabet) #pragma charmap (0x61, 0x01) #pragma charmap (0x62, 0x02) #pragma charmap (0x63, 0x03) #pragma charmap (0x64, 0x04) #pragma charmap (0x65, 0x05) #pragma charmap (0x66, 0x06) #pragma charmap (0x67, 0x07) #pragma charmap (0x68, 0x08) #pragma charmap (0x69, 0x09) #pragma charmap (0x6A, 0x0A) #pragma charmap (0x6B, 0x0B) #pragma charmap (0x6C, 0x0C) #pragma charmap (0x6D, 0x0D) #pragma charmap (0x6E, 0x0E) #pragma charmap (0x6F, 0x0F) #pragma charmap (0x70, 0x10) #pragma charmap (0x71, 0x11) #pragma charmap (0x72, 0x12) #pragma charmap (0x73, 0x13) #pragma charmap (0x74, 0x14) #pragma charmap (0x75, 0x15) #pragma charmap (0x76, 0x16) #pragma charmap (0x77, 0x17) #pragma charmap (0x78, 0x18) #pragma charmap (0x79, 0x19) #pragma charmap (0x7A, 0x1A) // Char $7B ... $7F -> c - 32 #pragma charmap (0x7B, 0x5B) #pragma charmap (0x7C, 0x5C) #pragma charmap (0x7D, 0x5D) #pragma charmap (0x7E, 0x5E) #pragma charmap (0x7F, 0x5F) // Char $80 -> c + 64 #pragma charmap (0x80, 0xC0) // Char $81 ... $9A -> c (control alphabet) #pragma charmap (0x81, 0x81) #pragma charmap (0x82, 0x82) #pragma charmap (0x83, 0x83) #pragma charmap (0x84, 0x84) #pragma charmap (0x85, 0x85) #pragma charmap (0x86, 0x86) #pragma charmap (0x87, 0x87) #pragma charmap (0x88, 0x88) #pragma charmap (0x89, 0x89) #pragma charmap (0x8A, 0x8A) #pragma charmap (0x8B, 0x8B) #pragma charmap (0x8C, 0x8C) #pragma charmap (0x8D, 0x8D) #pragma charmap (0x8E, 0x8E) #pragma charmap (0x8F, 0x8F) #pragma charmap (0x90, 0x90) #pragma charmap (0x91, 0x91) #pragma charmap (0x92, 0x92) #pragma charmap (0x93, 0x93) #pragma charmap (0x94, 0x94) #pragma charmap (0x95, 0x95) #pragma charmap (0x96, 0x96) #pragma charmap (0x97, 0x97) #pragma charmap (0x98, 0x98) #pragma charmap (0x99, 0x99) #pragma charmap (0x9A, 0x9A) // Char $9B ... $9F -> c + 64 #pragma charmap (0x9B, 0xDB) #pragma charmap (0x9C, 0xDC) #pragma charmap (0x9D, 0xDD) #pragma charmap (0x9E, 0xDE) #pragma charmap (0x9F, 0xDF) // Char $A0 ... $BF -> c - 64 #pragma charmap (0xA0, 0x60) #pragma charmap (0xA1, 0x61) #pragma charmap (0xA2, 0x62) #pragma charmap (0xA3, 0x63) #pragma charmap (0xA4, 0x64) #pragma charmap (0xA5, 0x65) #pragma charmap (0xA6, 0x66) #pragma charmap (0xA7, 0x67) #pragma charmap (0xA8, 0x68) #pragma charmap (0xA9, 0x69) #pragma charmap (0xAA, 0x6A) #pragma charmap (0xAB, 0x6B) #pragma charmap (0xAC, 0x6C) #pragma charmap (0xAD, 0x6D) #pragma charmap (0xAE, 0x6E) #pragma charmap (0xAF, 0x6F) #pragma charmap (0xB0, 0x70) #pragma charmap (0xB1, 0x71) #pragma charmap (0xB2, 0x72) #pragma charmap (0xB3, 0x73) #pragma charmap (0xB4, 0x74) #pragma charmap (0xB5, 0x75) #pragma charmap (0xB6, 0x76) #pragma charmap (0xB7, 0x77) #pragma charmap (0xB8, 0x78) #pragma charmap (0xB9, 0x79) #pragma charmap (0xBA, 0x7A) #pragma charmap (0xBB, 0x7B) #pragma charmap (0xBC, 0x7C) #pragma charmap (0xBD, 0x7D) #pragma charmap (0xBE, 0x7E) #pragma charmap (0xBF, 0x7F) // Char $C0 ... $DF -> c - 128 #pragma charmap (0xC0, 0x40) // Char $C1 ... $DA -> c - 128 - 64 (lower-case alphabet) #pragma charmap (0xC1, 0x01) #pragma charmap (0xC2, 0x02) #pragma charmap (0xC3, 0x03) #pragma charmap (0xC4, 0x04) #pragma charmap (0xC5, 0x05) #pragma charmap (0xC6, 0x06) #pragma charmap (0xC7, 0x07) #pragma charmap (0xC8, 0x08) #pragma charmap (0xC9, 0x09) #pragma charmap (0xCA, 0x0A) #pragma charmap (0xCB, 0x0B) #pragma charmap (0xCC, 0x0C) #pragma charmap (0xCD, 0x0D) #pragma charmap (0xCE, 0x0E) #pragma charmap (0xCF, 0x0F) #pragma charmap (0xD0, 0x10) #pragma charmap (0xD1, 0x11) #pragma charmap (0xD2, 0x12) #pragma charmap (0xD3, 0x13) #pragma charmap (0xD4, 0x14) #pragma charmap (0xD5, 0x15) #pragma charmap (0xD6, 0x16) #pragma charmap (0xD7, 0x17) #pragma charmap (0xD8, 0x18) #pragma charmap (0xD9, 0x19) #pragma charmap (0xDA, 0x1A) // Char $DB ... $DF -> c - 128 #pragma charmap (0xDB, 0x5B) #pragma charmap (0xDC, 0x5C) #pragma charmap (0xDD, 0x5D) #pragma charmap (0xDE, 0x5E) #pragma charmap (0xDF, 0x5F) // Char $E0 ... $FF -> c - 128 #pragma charmap (0xE0, 0x60) #pragma charmap (0xE1, 0x61) #pragma charmap (0xE2, 0x62) #pragma charmap (0xE3, 0x63) #pragma charmap (0xE4, 0x64) #pragma charmap (0xE5, 0x65) #pragma charmap (0xE6, 0x66) #pragma charmap (0xE7, 0x67) #pragma charmap (0xE8, 0x68) #pragma charmap (0xE9, 0x69) #pragma charmap (0xEA, 0x6A) #pragma charmap (0xEB, 0x6B) #pragma charmap (0xEC, 0x6C) #pragma charmap (0xED, 0x6D) #pragma charmap (0xEE, 0x6E) #pragma charmap (0xEF, 0x6F) #pragma charmap (0xF0, 0x70) #pragma charmap (0xF1, 0x71) #pragma charmap (0xF2, 0x72) #pragma charmap (0xF3, 0x73) #pragma charmap (0xF4, 0x74) #pragma charmap (0xF5, 0x75) #pragma charmap (0xF6, 0x76) #pragma charmap (0xF7, 0x77) #pragma charmap (0xF8, 0x78) #pragma charmap (0xF9, 0x79) #pragma charmap (0xFA, 0x7A) #pragma charmap (0xFB, 0x7B) #pragma charmap (0xFC, 0x7C) #pragma charmap (0xFD, 0x7D) #pragma charmap (0xFE, 0x7E) #pragma charmap (0xFF, 0x7F) #pragma warn (remap-zero, pop) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/cc65.h����������������������������������������������������������������������������0000664�0000000�0000000�00000012025�13473601511�0014541�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* cc65.h */ /* */ /* Target independent but cc65 specific utility functions */ /* */ /* */ /* */ /* (C) 2009-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _CC65_H #define _CC65_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ long __fastcall__ idiv32by16r16 (long rhs, int lhs); /* Divide a 32 bit signed value by a 16 bit signed value yielding a 16 ** bit result and a 16 bit remainder. The former is returned in the lower 16 ** bit of the result, the latter in the upper. If you don't need the ** remainder, just assign (or cast) to an int. */ unsigned long __fastcall__ udiv32by16r16 (unsigned long rhs, unsigned lhs); /* Divide a 32 bit unsigned value by a 16 bit unsigned value yielding a 16 ** bit result and a 16 bit remainder. The former is returned in the lower 16 ** bit of the result, the latter in the upper. If you don't need the ** remainder, just assign (or cast) to an unsigned. */ int __fastcall__ imul8x8r16 (signed char lhs, signed char rhs); /* Multiplicate two signed 8 bit to yield an signed 16 bit result */ long __fastcall__ imul16x16r32 (int lhs, int rhs); /* Multiplicate two signed 16 bit to yield a signed 32 bit result */ unsigned __fastcall__ umul8x8r16 (unsigned char lhs, unsigned char rhs); /* Multiplicate two unsigned 8 bit to yield an unsigned 16 bit result */ unsigned long __fastcall__ umul16x8r32 (unsigned lhs, unsigned char rhs); /* Multiplicate an unsigned 16 bit by an unsigned 8 bit number yielding a 24 ** bit unsigned result that is extended to 32 bits for easier handling from C. */ unsigned long __fastcall__ umul16x16r32 (unsigned lhs, unsigned rhs); /* Multiplicate two unsigned 16 bit to yield an unsigned 32 bit result */ unsigned int __fastcall__ mul20 (unsigned char value); /* Multiply an 8 bit unsigned value by 20 and return the 16 bit unsigned ** result */ unsigned int __fastcall__ mul40 (unsigned char value); /* Multiply an 8 bit unsigned value by 40 and return the 16 bit unsigned ** result */ int __fastcall__ _sin (unsigned x); /* Return the sine of the argument, which must be in range 0..360. The result ** is in 8.8 fixed point format, which means that 1.0 = $100 and -1.0 = $FF00. */ int __fastcall__ _cos (unsigned x); /* Return the cosine of the argument, which must be in range 0..360. The result ** is in 8.8 fixed point format, which means that 1.0 = $100 and -1.0 = $FF00. */ unsigned char doesclrscrafterexit (void); /* Indicates whether the screen automatically be cleared after program ** termination. */ /* End of cc65.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/conio.h���������������������������������������������������������������������������0000664�0000000�0000000�00000021355�13473601511�0015116�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* conio.h */ /* */ /* Direct console I/O */ /* */ /* */ /* */ /* (C) 1998-2007 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* ** This is the direct console interface for cc65. I do not like the function ** names very much, but the first version started as a rewrite of Borland's ** conio, and, even if the interface has changed, the names did not. ** ** The interface does direct screen I/O, so it is fast enough for most ** programs. I did not implement text windows, since many applications do ** not need them and should not pay for the additional overhead. It should ** be easy to add text windows on a higher level if needed, ** ** Most routines do not check the parameters. This may be unfortunate but is ** also related to speed. The coordinates are always 0/0 based. */ #ifndef _CONIO_H #define _CONIO_H #include <stdarg.h> #include <target.h> /*****************************************************************************/ /* Functions */ /*****************************************************************************/ void clrscr (void); /* Clear the whole screen and put the cursor into the top left corner */ unsigned char kbhit (void); /* Return true if there's a key waiting, return false if not */ void __fastcall__ gotox (unsigned char x); /* Set the cursor to the specified X position, leave the Y position untouched */ void __fastcall__ gotoy (unsigned char y); /* Set the cursor to the specified Y position, leave the X position untouched */ void __fastcall__ gotoxy (unsigned char x, unsigned char y); /* Set the cursor to the specified position */ unsigned char wherex (void); /* Return the X position of the cursor */ unsigned char wherey (void); /* Return the Y position of the cursor */ void __fastcall__ cputc (char c); /* Output one character at the current cursor position */ void __fastcall__ cputcxy (unsigned char x, unsigned char y, char c); /* Same as "gotoxy (x, y); cputc (c);" */ void __fastcall__ cputs (const char* s); /* Output a NUL-terminated string at the current cursor position */ void __fastcall__ cputsxy (unsigned char x, unsigned char y, const char* s); /* Same as "gotoxy (x, y); puts (s);" */ int cprintf (const char* format, ...); /* Like printf(), but uses direct screen output */ int __fastcall__ vcprintf (const char* format, va_list ap); /* Like vprintf(), but uses direct screen output */ char cgetc (void); /* Return a character from the keyboard. If there is no character available, ** the function waits until the user does press a key. If cursor is set to ** 1 (see below), a blinking cursor is displayed while waiting. */ int cscanf (const char* format, ...); /* Like scanf(), but uses direct keyboard input */ int __fastcall__ vcscanf (const char* format, va_list ap); /* Like vscanf(), but uses direct keyboard input */ char cpeekc (void); /* Return the character from the current cursor position */ unsigned char cpeekcolor (void); /* Return the color from the current cursor position */ unsigned char cpeekrevers (void); /* Return the reverse attribute from the current cursor position. ** If the character is reversed, then return 1; return 0 otherwise. */ void __fastcall__ cpeeks (char* s, unsigned int length); /* Return a string of the characters that start at the current cursor position. ** Put the string into the buffer to which "s" points. The string will have ** "length" characters, then will be '\0'-terminated. */ unsigned char __fastcall__ cursor (unsigned char onoff); /* If onoff is 1, a cursor is displayed when waiting for keyboard input. If ** onoff is 0, the cursor is hidden when waiting for keyboard input. The ** function returns the old cursor setting. */ unsigned char __fastcall__ revers (unsigned char onoff); /* Enable/disable reverse character display. This may not be supported by ** the output device. Return the old setting. */ unsigned char __fastcall__ textcolor (unsigned char color); /* Set the color for text output. The old color setting is returned. */ unsigned char __fastcall__ bgcolor (unsigned char color); /* Set the color for the background. The old color setting is returned. */ unsigned char __fastcall__ bordercolor (unsigned char color); /* Set the color for the border. The old color setting is returned. */ void __fastcall__ chline (unsigned char length); /* Output a horizontal line with the given length starting at the current ** cursor position. */ void __fastcall__ chlinexy (unsigned char x, unsigned char y, unsigned char length); /* Same as "gotoxy (x, y); chline (length);" */ void __fastcall__ cvline (unsigned char length); /* Output a vertical line with the given length at the current cursor ** position. */ void __fastcall__ cvlinexy (unsigned char x, unsigned char y, unsigned char length); /* Same as "gotoxy (x, y); cvline (length);" */ void __fastcall__ cclear (unsigned char length); /* Clear part of a line (write length spaces). */ void __fastcall__ cclearxy (unsigned char x, unsigned char y, unsigned char length); /* Same as "gotoxy (x, y); cclear (length);" */ void __fastcall__ screensize (unsigned char* x, unsigned char* y); /* Return the current screen size. */ void __fastcall__ cputhex8 (unsigned char val); void __fastcall__ cputhex16 (unsigned val); /* These shouldn't be here... */ /*****************************************************************************/ /* Macros */ /*****************************************************************************/ /* On some platforms, functions are not available or are dummys. To suppress ** the call to these functions completely, the platform header files may ** define macros for these functions that start with an underline. If such a ** macro exists, a new macro is defined here, that expands to the one with the ** underline. The reason for this two stepped approach is that it is sometimes ** necessary to take the address of the function, which is not possible when ** using a macro. Since the function prototype is still present, #undefining ** the macro will give access to the actual function. */ #ifdef _textcolor # define textcolor(x) _textcolor(x) #endif #ifdef _bgcolor # define bgcolor(x) _bgcolor(x) #endif #ifdef _bordercolor # define bordercolor(x) _bordercolor(x) #endif #ifdef _cpeekcolor # define cpeekcolor(x) _cpeekcolor(x) #endif /* End of conio.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/creativision.h��������������������������������������������������������������������0000664�0000000�0000000�00000006722�13473601511�0016507�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* creativision.h */ /* */ /* Creativision system specific definitions */ /* */ /* */ /* */ /* (C) 2013 cvemu */ /* (C) 2017 Christian Groessler <chris@groessler.org> */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _CVISION_H #define _CVISION_H /* Character codes */ #define CH_VLINE 33 #define CH_HLINE 34 #define CH_ULCORNER 35 #define CH_URCORNER 36 #define CH_LLCORNER 37 #define CH_LRCORNER 38 /* Masks for joy_read */ #define JOY_UP_MASK 0x10 #define JOY_DOWN_MASK 0x04 #define JOY_LEFT_MASK 0x20 #define JOY_RIGHT_MASK 0x08 #define JOY_BTN_1_MASK 0x01 #define JOY_BTN_2_MASK 0x02 /* no support for dynamically loadable drivers */ #define DYN_DRV 0 /* Colours - from TMS9918 */ #define C_TRANSPARENT 0 #define C_BLACK 1 #define C_MED_GREEN 2 #define C_LIGHT_GREEN 3 #define C_DARK_BLUE 4 #define C_LIGHT_BLUE 5 #define C_DARK_RED 6 #define C_CYAN 7 #define C_MED_RED 8 #define C_LIGHT_RED 9 #define C_DARK_YELLOW 10 #define C_LIGHT_YELLOW 11 #define C_DARK_GREEN 12 #define C_MAGENTA 13 #define C_GREY 14 #define C_WHITE 15 /* Protos */ void __fastcall__ psg_outb(unsigned char b); void __fastcall__ psg_delay(unsigned char b); void psg_silence(void); void __fastcall__ bios_playsound(void *a, unsigned char b); #endif /* #ifndef _CVISION_H */ ����������������������������������������������cc65-2.18/include/ctype.h���������������������������������������������������������������������������0000664�0000000�0000000�00000020416�13473601511�0015130�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* ctype.h */ /* */ /* Character handling */ /* */ /* */ /* */ /* (C) 1998-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _CTYPE_H #define _CTYPE_H /* The array containing character classification data */ extern unsigned char _ctype[256]; /* Bits used to specify character classes */ #define _CT_LOWER 0x01 /* 0 - Lower case char */ #define _CT_UPPER 0x02 /* 1 - Upper case char */ #define _CT_DIGIT 0x04 /* 2 - Numeric digit */ #define _CT_XDIGIT 0x08 /* 3 - Hex digit (both lower and upper) */ #define _CT_CNTRL 0x10 /* 4 - Control character */ #define _CT_SPACE 0x20 /* 5 - The space character itself */ #define _CT_OTHER_WS 0x40 /* 6 - Other whitespace ('\f', '\n', '\r', '\t', and '\v') */ #define _CT_SPACE_TAB 0x80 /* 7 - Space or tab character */ /* Bit combinations */ #define _CT_ALNUM (_CT_LOWER | _CT_UPPER | _CT_DIGIT) #define _CT_ALPHA (_CT_LOWER | _CT_UPPER) #define _CT_NOT_GRAPH (_CT_CNTRL | _CT_SPACE) #define _CT_NOT_PRINT (_CT_CNTRL) #define _CT_NOT_PUNCT (_CT_SPACE | _CT_CNTRL | _CT_DIGIT | _CT_UPPER | _CT_LOWER) #define _CT_WS (_CT_SPACE | _CT_OTHER_WS) /* Character classification functions */ int __fastcall__ isalnum (int c); int __fastcall__ isalpha (int c); int __fastcall__ iscntrl (int c); int __fastcall__ isdigit (int c); int __fastcall__ isgraph (int c); int __fastcall__ islower (int c); int __fastcall__ isprint (int c); int __fastcall__ ispunct (int c); int __fastcall__ isspace (int c); int __fastcall__ isupper (int c); int __fastcall__ isxdigit (int c); #if __CC65_STD__ >= __CC65_STD_C99__ int __fastcall__ isblank (int c); /* New in C99 */ #endif int __fastcall__ toupper (int c); /* Always external */ int __fastcall__ tolower (int c); /* Always external */ #if __CC65_STD__ >= __CC65_STD_CC65__ unsigned char __fastcall__ toascii (unsigned char c); /* Convert a target-specific character to ASCII. */ #endif /* When --eagerly-inline-funcs is enabled, overload most of the above ** functions by macroes. The function prototypes are available again after ** #undef'ing the macroes. ** Please note that the following macroes do NOT handle EOF correctly, as ** stated in the manual. If you need correct behaviour for EOF, don't ** use --eagerly-inline-funcs, or #undefine the following macroes. */ #ifdef __EAGERLY_INLINE_FUNCS__ #define isalnum(c) (__AX__ = (c), \ __asm__ ("tay"), \ __asm__ ("lda %v,y", _ctype), \ __asm__ ("and #%b", _CT_ALNUM), \ __AX__) #define isalpha(c) (__AX__ = (c), \ __asm__ ("tay"), \ __asm__ ("lda %v,y", _ctype), \ __asm__ ("and #%b", _CT_ALPHA), \ __AX__) #if __CC65_STD__ >= __CC65_STD_C99__ #define isblank(c) (__AX__ = (c), \ __asm__ ("tay"), \ __asm__ ("lda %v,y", _ctype), \ __asm__ ("and #%b", _CT_SPACE_TAB), \ __AX__) #endif #define iscntrl(c) (__AX__ = (c), \ __asm__ ("tay"), \ __asm__ ("lda %v,y", _ctype), \ __asm__ ("and #%b", _CT_CNTRL), \ __AX__) #define isdigit(c) (__AX__ = (c), \ __asm__ ("tay"), \ __asm__ ("lda %v,y", _ctype), \ __asm__ ("and #%b", _CT_DIGIT), \ __AX__) #define isgraph(c) (__AX__ = (c), \ __asm__ ("tay"), \ __asm__ ("lda %v,y", _ctype), \ __asm__ ("and #%b", _CT_NOT_GRAPH), \ __asm__ ("cmp #1"), \ __asm__ ("lda #1"), \ __asm__ ("sbc #1"), \ __AX__) #define islower(c) (__AX__ = (c), \ __asm__ ("tay"), \ __asm__ ("lda %v,y", _ctype), \ __asm__ ("and #%b", _CT_LOWER), \ __AX__) #define isprint(c) (__AX__ = (c), \ __asm__ ("tay"), \ __asm__ ("lda %v,y", _ctype), \ __asm__ ("and #%b", _CT_NOT_PRINT), \ __asm__ ("eor #%b", _CT_NOT_PRINT), \ __AX__) #define ispunct(c) (__AX__ = (c), \ __asm__ ("tay"), \ __asm__ ("lda %v,y", _ctype), \ __asm__ ("and #%b", _CT_NOT_PUNCT), \ __asm__ ("cmp #1"), \ __asm__ ("lda #1"), \ __asm__ ("sbc #1"), \ __AX__) #define isspace(c) (__AX__ = (c), \ __asm__ ("tay"), \ __asm__ ("lda %v,y", _ctype), \ __asm__ ("and #%b", _CT_WS), \ __AX__) #define isupper(c) (__AX__ = (c), \ __asm__ ("tay"), \ __asm__ ("lda %v,y", _ctype), \ __asm__ ("and #%b", _CT_UPPER), \ __AX__) #define isxdigit(c) (__AX__ = (c), \ __asm__ ("tay"), \ __asm__ ("lda %v,y", _ctype), \ __asm__ ("and #%b", _CT_XDIGIT), \ __AX__) #endif /* End of ctype.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/dbg.h�����������������������������������������������������������������������������0000664�0000000�0000000�00000013217�13473601511�0014541�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* dbg.h */ /* */ /* Debugger module interface */ /* */ /* */ /* */ /* (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 */ /* 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. */ /* */ /*****************************************************************************/ /* ** This is the interface to the cc65 debugger. Since many of the functions ** used for the debugger are quite usable even in another context, they ** are declared here. ** ** To use the debugger, just call DbgInit in your application. Once it has ** been called, the debugger will catch any BRK opcode. Use the BREAK macro ** defined below to insert breakpoints into your code. ** ** There are currently a lot of things that cannot be debugged, graphical ** applications are an example. The debugger does not save your screen ** contents, so even your text screen gets destroyed. However, you can ** debug the C and runtime library, even if the debugger is using this ** stuff itself. ** ** Note: When using the debugger, there are some other identifiers with ** external linkage, that start with Dbg. Avoid those names if you use the ** module. */ #ifndef _DBG_H #define _DBG_H /*****************************************************************************/ /* Utility functions */ /*****************************************************************************/ unsigned __fastcall__ DbgDisAsm (unsigned Addr, char* Buf, unsigned char Len); /* Disassemble one instruction at address addr into the given buffer. ** The resulting line has the format, "AAAA__BB_BB_BB___OPC_OPERAND", ** where AAAA is the hexadecimal representation of addr, BB are the ** bytes (in hex) that make the instruction, OPC is the mnemonic, and ** OPERAND is an operand for the instruction. ** The buffer is filled with spaces up to the given length and terminated as ** a usual C string. NOTE: Buf must be able to hold Len+1 characters. ** The function returns the length of the disassembled instruction, so, ** to disassemble the next instruction, add the return value to addr ** and call the function again. */ unsigned __fastcall__ DbgDisAsmLen (unsigned Addr); /* Disassemble one instruction, but do only return the length, do not ** create a visible representation. This function is useful when ** disassembling backwards, it is much faster than DbgDisAsm. */ int __fastcall__ DbgIsRAM (unsigned Addr); /* Return true if we can read and write the given address */ 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 ** plus a terminator byte. ** The function does not work correctly if the created string is longer ** than 255 bytes. ** The return value is Buf. */ /*****************************************************************************/ /* High level user interface */ /*****************************************************************************/ void __fastcall__ DbgInit (unsigned unused); /* Initialize the debugger. Use 0 as parameter. The debugger will popup on ** next brk encountered. */ #define BREAK() __asm__ ("brk") /* Use this to insert breakpoints into your code */ /* End of dbg.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/device.h��������������������������������������������������������������������������0000664�0000000�0000000�00000006214�13473601511�0015243�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* device.h */ /* */ /* Device handling */ /* */ /* */ /* */ /* (C) 2012 Oliver Schmidt, <ol.sc@web.de> */ /* */ /* */ /* 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 _DEVICE_H #define _DEVICE_H #ifndef _HAVE_size_t typedef unsigned size_t; #define _HAVE_size_t #endif /*****************************************************************************/ /* Data */ /*****************************************************************************/ #define INVALID_DEVICE 255 /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned char getfirstdevice (void); unsigned char __fastcall__ getnextdevice (unsigned char device); unsigned char getcurrentdevice (void); char* __fastcall__ getdevicedir (unsigned char device, char* buf, size_t size); /* End of device.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/dio.h�����������������������������������������������������������������������������0000664�0000000�0000000�00000012536�13473601511�0014563�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* dio.h */ /* */ /* Low-Level diskette I/O functions */ /* */ /* */ /* */ /* (C) 2005 Christian Groessler <chris@groessler.org> */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _DIO_H #define _DIO_H /* Please note: All functions in this file will set _oserror *and* return its ** value. The only exception is dio_open, which will return NULL, but _oserror ** will be set. All function will also set _oserror in case of successful ** execution, effectively clearing it. */ /*****************************************************************************/ /* Data */ /*****************************************************************************/ typedef struct __dhandle_t *dhandle_t; typedef struct { unsigned char head; unsigned track; unsigned sector; } dio_phys_pos; /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned __fastcall__ dio_query_sectsize (dhandle_t handle); /* returns sector size */ unsigned __fastcall__ dio_query_sectcount (dhandle_t handle); /* returns sector count */ dhandle_t __fastcall__ dio_open (unsigned char device); /* open device for subsequent dio access */ unsigned char __fastcall__ dio_close (dhandle_t handle); /* close device, returns oserror (0 for success) */ unsigned char __fastcall__ dio_read (dhandle_t handle, unsigned sect_num, void *buffer); /* read sector <sect_num> from device <handle> to memory at <buffer> */ /* the number of bytes transferred depends on the sector size */ /* returns oserror (0 for success) */ unsigned char __fastcall__ dio_write (dhandle_t handle, unsigned sect_num, const void *buffer); /* write memory at <buffer> to sector <sect_num> on device <handle>, no verify */ /* the number of bytes transferred depends on the sector size */ /* returns oserror (0 for success) */ unsigned char __fastcall__ dio_write_verify (dhandle_t handle, unsigned sect_num, const void *buffer); /* write memory at <buffer> to sector <sect_num> on device <handle>, verify after write */ /* the number of bytes transferred depends on the sector size */ /* returns oserror (0 for success) */ unsigned char __fastcall__ dio_phys_to_log (dhandle_t handle, const dio_phys_pos *physpos, /* input */ unsigned *sectnum); /* output */ /* convert physical sector address (head/track/sector) to logical sector number */ /* returns oserror (0 for success) */ unsigned char __fastcall__ dio_log_to_phys (dhandle_t handle, const unsigned *sectnum, /* input */ dio_phys_pos *physpos); /* output */ /* convert logical sector number to physical sector address (head/track/sector) */ /* returns oserror (0 for success) */ #endif /* #ifndef _DIO_H */ ������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/dirent.h��������������������������������������������������������������������������0000664�0000000�0000000�00000012314�13473601511�0015267�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* dirent.h */ /* */ /* Directory entries for cc65 */ /* */ /* */ /* */ /* (C) 2005 Oliver Schmidt, <ol.sc@web.de> */ /* */ /* */ /* 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 _DIRENT_H #define _DIRENT_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ typedef struct DIR DIR; #if defined(__APPLE2__) struct dirent { char d_name[16]; unsigned d_ino; unsigned d_blocks; unsigned long d_size; unsigned char d_type; struct { unsigned day :5; unsigned mon :4; unsigned year :7; } d_cdate; struct { unsigned char min; unsigned char hour; } d_ctime; unsigned char d_access; unsigned d_auxtype; struct { unsigned day :5; unsigned mon :4; unsigned year :7; } d_mdate; struct { unsigned char min; unsigned char hour; } d_mtime; }; #define _DE_ISREG(t) ((t) != 0x0F) #define _DE_ISDIR(t) ((t) == 0x0F) #define _DE_ISLBL(t) (0) #define _DE_ISLNK(t) (0) #elif defined(__ATARI__) struct dirent { char d_name[13]; /* 8.3 + trailing 0 */ unsigned char d_type; }; #define _DE_ISREG(t) ((t) != 0xC4) #define _DE_ISDIR(t) ((t) == 0xC4) #define _DE_ISLBL(t) (0) #define _DE_ISLNK(t) (0) #elif defined(__CBM__) struct dirent { char d_name[16+1]; unsigned int d_off; unsigned int d_blocks; unsigned char d_type; /* See _CBM_T_xxx defines */ /* bsd extensions */ unsigned char d_namlen; }; /* File type specification macros. We need definitions of CBM file types. */ #include <cbm_filetype.h> #define _DE_ISREG(t) (((t) & _CBM_T_REG) != 0) #define _DE_ISDIR(t) ((t) == _CBM_T_DIR) #define _DE_ISLBL(t) ((t) == _CBM_T_HEADER) #define _DE_ISLNK(t) ((t) == _CBM_T_LNK) #elif defined(__LYNX__) struct dirent { unsigned char d_blocks; unsigned int d_offset; char d_type; void *d_address; unsigned int d_size; }; extern struct dirent FileEntry; #pragma zpsym ("FileEntry"); #define _DE_ISREG(t) (1) #define _DE_ISDIR(t) (0) #define _DE_ISLBL(t) (0) #define _DE_ISLNK(t) (0) #else struct dirent { char d_name[1]; }; #define _DE_ISREG(t) (1) #define _DE_ISDIR(t) (0) #define _DE_ISLBL(t) (0) #define _DE_ISLNK(t) (0) #endif /*****************************************************************************/ /* Code */ /*****************************************************************************/ DIR* __fastcall__ opendir (const char* name); struct dirent* __fastcall__ readdir (DIR* dir); int __fastcall__ closedir (DIR* dir); long __fastcall__ telldir (DIR* dir); void __fastcall__ seekdir (DIR* dir, long offs); void __fastcall__ rewinddir (DIR* dir); /* End of dirent.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/em.h������������������������������������������������������������������������������0000664�0000000�0000000�00000014220�13473601511�0014401�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* em.h */ /* */ /* API for extended memory access */ /* */ /* */ /* */ /* (C) 2002-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _EM_H #define _EM_H /*****************************************************************************/ /* Definitions */ /*****************************************************************************/ /* Size of an extended memory page */ #define EM_PAGE_SIZE 256 /* Error codes */ #define EM_ERR_OK 0 /* No error */ #define EM_ERR_NO_DRIVER 1 /* No driver available */ #define EM_ERR_CANNOT_LOAD 2 /* Error loading driver */ #define EM_ERR_INV_DRIVER 3 /* Invalid driver */ #define EM_ERR_NO_DEVICE 4 /* Device (hardware) not found */ #define EM_ERR_INSTALLED 5 /* A driver is already installed */ /* Parameters for the em_copy_... functions. NOTE: The first seven bytes ** have the same order and alignment as needed for the Commodore REU, so ** don't change the order without changing the assembler file that defines ** the struct offsets and the code in the REU driver. */ struct em_copy { void* buf; /* Memory buffer to copy from or to */ unsigned char offs; /* Offset into page */ unsigned page; /* Starting page to copy from or to */ unsigned count; /* Number of bytes to copy */ unsigned char unused; /* Make the size 8 bytes */ }; /*****************************************************************************/ /* Functions */ /*****************************************************************************/ unsigned char __fastcall__ em_load_driver (const char* driver); /* Load and install an extended memory driver. Return an error code. */ unsigned char em_unload (void); /* Uninstall, then unload the currently loaded driver. */ unsigned char __fastcall__ em_install (void* driver); /* Install an already loaded driver. Return an error code. */ unsigned char em_uninstall (void); /* Uninstall the currently loaded driver and return an error code. ** Note: This call does not free allocated memory. */ unsigned em_pagecount (void); /* Return the total number of 256 byte pages available in extended memory. */ void* __fastcall__ em_map (unsigned page); /* Unmap the current page from memory and map a new one. The function returns ** a pointer to the location of the page in memory. Note: Without calling ** em_commit, the old contents of the memory window may be lost! */ void* __fastcall__ em_use (unsigned page); /* Tell the driver that the memory window is associated with a given page. ** This call is very similar to em_map. The difference is that the driver ** does not necessarily transfer the current contents of the extended ** memory into the returned window. If you're going to just write to the ** window and the current contents of the window are invalid or no longer ** use, this call may perform better than em_map. */ void em_commit (void); /* Commit changes in the memory window to extended storage. If the contents ** of the memory window have been changed, these changes may be lost if ** em_map, em_copyfrom or em_copyto are called without calling em_commit ** first. Note: Not calling em_commit does not mean that the changes are ** discarded, it does just mean that some drivers will discard the changes. */ void __fastcall__ em_copyfrom (const struct em_copy* copy_data); /* Copy from extended into linear memory. Note: This may invalidate the ** currently mapped page. */ void __fastcall__ em_copyto (const struct em_copy* copy_data); /* Copy from linear into extended memory. Note: This may invalidate the ** currently mapped page. */ /* End of em.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/em/�������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014231�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/em/em-kernel.h��������������������������������������������������������������������0000664�0000000�0000000�00000007470�13473601511�0016271�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* em-kernel.h */ /* */ /* Internally used EM functions */ /* */ /* */ /* */ /* (C) 2002-2003 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _EM_KERNEL_H #define _EM_KERNEL_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* A structure that describes the header of an extended memory driver loaded ** into memory. */ typedef struct { /* Driver header */ char id[3]; /* Contains 0x65, 0x6d, 0x64 ("emd") */ unsigned char version; /* Interface version */ void* libreference; /* Library reference */ /* Jump vectors. Note that these are not C callable */ void* install; /* INSTALL routine */ void* deinstall; /* DEINSTALL routine */ void* pagecount; /* PAGECOUNT routine */ void* map; /* MAP routine */ void* use; /* USE routine */ void* mapclean; /* MAPCLEAN routine */ void* copyfrom; /* COPYFROM routine */ void* copyto; /* COPYTO routine */ } em_drv_header; /* EM kernel variables */ extern em_drv_header* em_drv; /* Pointer to driver */ /* End of em-kernel.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/errno.h���������������������������������������������������������������������������0000664�0000000�0000000�00000011733�13473601511�0015133�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* errno.h */ /* */ /* Error codes */ /* */ /* */ /* */ /* (C) 1998-2010, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _ERRNO_H #define _ERRNO_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Operating system specific error code */ extern unsigned char _oserror; extern int _errno; /* System errors go here */ #define errno _errno /* errno must be a macro */ /* Possible error codes */ #define ENOENT 1 /* No such file or directory */ #define ENOMEM 2 /* Out of memory */ #define EACCES 3 /* Permission denied */ #define ENODEV 4 /* No such device */ #define EMFILE 5 /* Too many open files */ #define EBUSY 6 /* Device or resource busy */ #define EINVAL 7 /* Invalid argument */ #define ENOSPC 8 /* No space left on device */ #define EEXIST 9 /* File exists */ #define EAGAIN 10 /* Try again */ #define EIO 11 /* I/O error */ #define EINTR 12 /* Interrupted system call */ #define ENOSYS 13 /* Function not implemented */ #define ESPIPE 14 /* Illegal seek */ #define ERANGE 15 /* Range error */ #define EBADF 16 /* Bad file number */ #define ENOEXEC 17 /* Exec format error */ #define EUNKNOWN 18 /* Unknown OS specific error */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ int __fastcall__ _osmaperrno (unsigned char oserror); /* Map an operating system specific error code (for example from _oserror) ** into one of the E... codes above. It is user callable. */ unsigned char __fastcall__ _seterrno (unsigned char code); /* Set errno to a specific error code and return zero. Used by the library */ int __fastcall__ _directerrno (unsigned char code); /* Set errno to a specific error code, clear _oserror and return -1. Used ** by the library. */ 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. */ /* End of errno.h */ #endif �������������������������������������cc65-2.18/include/fcntl.h���������������������������������������������������������������������������0000664�0000000�0000000�00000006736�13473601511�0015123�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* fcntl.h */ /* */ /* File control operations */ /* */ /* */ /* */ /* (C) 1998-2004 Ullrich von Bassewitz */ /* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _FCNTL_H #define _FCNTL_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Flag values for the open() call */ #define O_RDONLY 0x01 #define O_WRONLY 0x02 #define O_RDWR 0x03 #define O_CREAT 0x10 #define O_TRUNC 0x20 #define O_APPEND 0x40 #define O_EXCL 0x80 /*****************************************************************************/ /* Code */ /*****************************************************************************/ /* Functions */ int open (const char* name, int flags, ...); /* May take a mode argument */ int __fastcall__ close (int fd); int __fastcall__ creat (const char* name, unsigned mode); /* End of fcntl.h */ #endif ����������������������������������cc65-2.18/include/gamate.h��������������������������������������������������������������������������0000664�0000000�0000000�00000016746�13473601511�0015255�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* gamate.h */ /* */ /* Gamate system specific definitions */ /* */ /* */ /* */ /* (w) 2015 Groepaz/Hitmen (groepaz@gmx.net) */ /* based on technical reference by PeT (mess@utanet.at) */ /* */ /* 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 _GAMATE_H #define _GAMATE_H /* Check for errors */ #if !defined(__GAMATE__) # error This module may only be used when compiling for the Gamate! #endif #define AUDIO_BASE 0x4000 /* base clock cpu clock/32 ? 0/1: 1. channel(right): 12 bit frequency: right frequency 0 nothing, 1 high; 3 23khz; 4 17,3; 10 6,9; 15 4.6; $60 720hz; $eff 18,0; $fff 16,9 hz) (delay clock/32) 2/3: 2. channel(left): 12 bit frequency 4/5: 3. channel(both): 12 bit frequency 6: 0..5 noise frequency 0 fast 1f slow (about 500us) 15.6ns--> clock/32 counts 7 control (hinibble right) bit 0: right channel high (full cycle, else square pulse/tone) bit 1: left channel high bit 2: both channel high bit 3: set right tone (else noise) bit 4: set left channel normal bit 5: set both normal bits 30: 11 high, 10 square, 01 noise, 00 noise only when square high noise means switches channel to ad converter based noise algorithmen (white noise shift register 17bit wide, repeats after about 130000 cycles) probably out=!bit16, bit0=bit16 xor bit13; runs through, so start value anything than 0 8: 1st volume: 0..3 square volume; bit 4 envelope (higher priority) 9: 2nd volume 10: 3rd volume 11/12: envelope delay time 0 fast, 0xffff slow/nearly no effect (2 22us, 4 56us) frequency $800, envelope $10 2 times in pulse high time (4*16*16) 13: envelope control 0-3 one time falling 4-7 one time rising 8 falling 9 one time falling a starts with down falling, rising; same falling time, but double/longer cycle b one time falling, on c rising d one time rising, on e rising, falling (double cycle before restart) f one time rising bit 0: once only bit 1: full tone bit 2: start rising (else falling) bit 3: */ /* LCD resolution 160x152 in 4 greys/greens 2 256x256 sized bitplanes (2x 8kbyte ram) */ #define LCD_BASE 0x5000 #define LCD_MODE 0x5001 /* bit 3..0 (from zeropage 15) bit 0 set no normal screen display, seldom scrolling effects on screen; bytes written to somewhat actual display refresh position!? bytes read "random" bit 1,2,3 no effect bit 4 swaps plane intensity bit 5 ? display effect bit 6 on y auto increment (else auto x increment), reading bit 7 ? lcd flickering */ #define LCD_MODE_INC_Y 0x40 #define LCD_XPOS 0x5002 /* smooth scrolling X */ #define LCD_YPOS 0x5003 /* smooth scrolling Y */ /* smooth scrolling until $c8 with 200 limit after 200 display if ((value & 0xf) < 8) display of (value & 0xf) - 8 chaos lines from value + current line from plane 2 only then lines starting with zero (problematic 200 limit/overrun implementation!?) */ #define LCD_X 0x5004 /* x-addr */ /* bit 5,6 no effect bit 7 0 1st/1 2nd bitplane */ #define LCD_XPOS_PLANE1 0x00 #define LCD_XPOS_PLANE2 0x80 #define LCD_Y 0x5005 /* y-addr */ #define LCD_READ 0x5006 /* read from RAM (no auto inc?) */ #define LCD_DATA 0x5007 /* write to RAM */ /* BIOS zeropage usage */ /* locations 0x0a-0x0c, 0x0e-0x11 and 0xe8 are in use by the BIOS IRQ/NMI handlers */ #define ZP_NMI_4800 0x0a /* content of I/O reg 4800 gets copied here each NMI */ #define ZP_IRQ_COUNT 0x0b /* increments once per IRQ, used elsewhere in the BIOS for synchronisation purposes */ #define ZP_IRQ_CTRL 0x0c /* if 0 then cartridge irq stubs will not get called */ /* each of the following 4 increments by 1 per IRQ - it is _not_ a 32bit counter (see code at $ffa6 in BIOS) these are not used elsewhere in the bios and can be (re)set as needed by the user. */ #define ZP_IRQ_CNT1 0x0e #define ZP_IRQ_CNT2 0x0f #define ZP_IRQ_CNT3 0x10 #define ZP_IRQ_CNT4 0x11 #define ZP_NMI_FLAG 0xe8 /* set to 0xff each NMI */ /* constants for the conio implementation */ #define COLOR_BLACK 0x03 #define COLOR_WHITE 0x00 #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_RTEE 11 #define CH_LTEE 12 #define CH_ENTER 13 #define CH_PI 18 #define TV_NTSC 0 #define TV_PAL 1 #define TV_OTHER 2 /* No support for dynamically loadable drivers */ #define DYN_DRV 0 /* Masks for joy_read */ #define JOY_UP_MASK 0x01 #define JOY_DOWN_MASK 0x02 #define JOY_LEFT_MASK 0x04 #define JOY_RIGHT_MASK 0x08 #define JOY_BTN_1_MASK 0x10 #define JOY_BTN_2_MASK 0x20 #define JOY_BTN_3_MASK 0x40 #define JOY_BTN_4_MASK 0x80 #define JOY_BTN_A_MASK JOY_BTN_1_MASK #define JOY_BTN_B_MASk JOY_BTN_2_MASK #define JOY_START_MASK JOY_BTN_3_MASK #define JOY_SELECT_MASK JOY_BTN_4_MASK #define JOY_BTN_A(v) ((v) & JOY_BTN_A_MASK) #define JOY_BTN_B(v) ((v) & JOY_BTN_B_MASK) #define JOY_START(v) ((v) & JOY_START_MASK) #define JOY_SELECT(v) ((v) & JOY_SELECT_MASK) /* The addresses of the static drivers */ extern void gamate_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */ void waitvsync (void); /* Wait for start of next frame */ /* NOTE: all Gamate are "NTSC" */ #define get_tv() TV_NTSC /* Return the video mode the machine is using. */ /* End of gamate.h */ #endif ��������������������������cc65-2.18/include/geos.h����������������������������������������������������������������������������0000664�0000000�0000000�00000006213�13473601511�0014740�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Supreme GEOS header file includes all other headers Maciej 'YTM/Elysium' Witkowiak, 27.10.1999 */ #ifndef _GEOS_H #define _GEOS_H /* Check for errors */ #if !defined(__GEOS__) # error This module may only be used when compiling for GEOS! #endif #include <geos/gconst.h> #include <geos/gstruct.h> #include <geos/gsym.h> #include <geos/gdisk.h> #include <geos/gfile.h> #include <geos/gprocess.h> #include <geos/ggraph.h> #include <geos/gmenu.h> #include <geos/gsprite.h> #include <geos/gmemory.h> #include <geos/gsys.h> #include <geos/gdlgbox.h> #define CH_ULCORNER '+' #define CH_URCORNER '+' #define CH_LLCORNER '+' #define CH_LRCORNER '+' #define CH_TTEE '+' #define CH_RTEE '+' #define CH_BTEE '+' #define CH_LTEE '+' #define CH_CROSS '+' #define CH_F1 KEY_F1 #define CH_F2 KEY_F2 #define CH_F3 KEY_F3 #define CH_F4 KEY_F4 #define CH_F5 KEY_F5 #define CH_F6 KEY_F6 #define CH_F7 KEY_F7 #define CH_F8 KEY_F8 #define CH_CURS_UP KEY_UP #define CH_CURS_DOWN KEY_DOWN #define CH_CURS_LEFT KEY_LEFT #define CH_CURS_RIGHT KEY_RIGHT #define CH_DEL KEY_DELETE #define CH_INS KEY_INSERT #define CH_ENTER KEY_ENTER #define CH_STOP KEY_STOP #define CH_ESC KEY_ESC #define COLOR_BLACK BLACK #define COLOR_WHITE WHITE #define COLOR_RED RED #define COLOR_CYAN CYAN #define COLOR_VIOLET PURPLE #define COLOR_PURPLE PURPLE #define COLOR_GREEN GREEN #define COLOR_BLUE BLUE #define COLOR_YELLOW YELLOW #define COLOR_ORANGE ORANGE #define COLOR_BROWN BROWN #define COLOR_LIGHTRED LTRED #define COLOR_GRAY1 DKGREY #define COLOR_GRAY2 MEDGREY #define COLOR_LIGHTGREEN LTGREEN #define COLOR_LIGHTBLUE LTBLUE #define COLOR_GRAY3 LTGREY #define TGI_COLOR_BLACK COLOR_BLACK #define TGI_COLOR_WHITE COLOR_WHITE #define TGI_COLOR_RED COLOR_RED #define TGI_COLOR_CYAN COLOR_CYAN #define TGI_COLOR_VIOLET COLOR_VIOLET #define TGI_COLOR_PURPLE COLOR_PURPLE #define TGI_COLOR_GREEN COLOR_GREEN #define TGI_COLOR_BLUE COLOR_BLUE #define TGI_COLOR_YELLOW COLOR_YELLOW #define TGI_COLOR_ORANGE COLOR_ORANGE #define TGI_COLOR_BROWN COLOR_BROWN #define TGI_COLOR_LIGHTRED COLOR_LIGHTRED #define TGI_COLOR_GRAY1 COLOR_GRAY1 #define TGI_COLOR_GRAY2 COLOR_GRAY2 #define TGI_COLOR_LIGHTGREEN COLOR_LIGHTGREEN #define TGI_COLOR_LIGHTBLUE COLOR_LIGHTBLUE #define TGI_COLOR_GRAY3 COLOR_GRAY3 #define JOY_UP_MASK 0x01 #define JOY_DOWN_MASK 0x02 #define JOY_LEFT_MASK 0x04 #define JOY_RIGHT_MASK 0x08 #define JOY_BTN_1_MASK 0x10 /* End of geos.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/geos/�����������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014565�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/geos/gconst.h���������������������������������������������������������������������0000664�0000000�0000000�00000002672�13473601511�0016242�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* GEOS constants reassembled by Maciej 'YTM/Elysium' Witkowiak */ /* Here are constants which didn't fit into any other cathegory... */ #ifndef _GCONST_H #define _GCONST_H #define NULL 0 #define FALSE NULL #define TRUE 0xff #define MOUSE_SPRNUM 0 #define DISK_DRV_LGH 0x0d80 /* drivetypes */ #define DRV_NULL 0 #define DRV_1541 1 #define DRV_1571 2 #define DRV_1581 3 #define DRV_NETWORK 15 /* various disk constants */ #define REL_FILE_NUM 9 #define CMND_FILE_NUM 15 #define MAX_CMND_STR 32 #define DIR_1581_TRACK 40 #define DIR_ACC_CHAN 13 #define DIR_TRACK 18 #define N_TRACKS 35 #define DK_NM_ID_LEN 18 #define TRACK 9 #define SECTOR 12 #define TOTAL_BLOCKS 664 /* offset to something */ #define OFF_INDEX_PTR 1 /* values for CPU_DATA memory config - C64 */ #define IO_IN 0x35 #define KRNL_IO_IN 0x36 #define KRNL_BAS_IO_IN 0x37 /* values for MMU config - C128 */ #define CIOIN 0x7E #define CRAM64K 0x7F #define CKRNLBASIOIN 0x40 #define CKRNLIOIN 0x4E /* alarmSetFlag */ #define ALARMMASK 4 #define CLR_SAVE 0x40 #define CONSTRAINED 0x40 #define UN_CONSTRAINED 0 #define FG_SAVE 0x80 #define FUTURE1 7 #define FUTURE2 8 #define FUTURE3 9 #define FUTURE4 10 #define USELAST 127 #define SHORTCUT 128 #endif ����������������������������������������������������������������������cc65-2.18/include/geos/gdisk.h����������������������������������������������������������������������0000664�0000000�0000000�00000004357�13473601511�0016050�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* GEOS functions from disk driver by Maciej 'YTM/Elysium' Witkowiak */ #ifndef _GDISK_H #define _GDISK_H #include <geos/gstruct.h> char __fastcall__ ReadBuff(struct tr_se *myTrSe); char __fastcall__ WriteBuff(struct tr_se *myTrSe); char __fastcall__ GetBlock(struct tr_se *myTrSe, char *buffer); char __fastcall__ PutBlock(struct tr_se *myTrSe, const char *buffer); char __fastcall__ ReadBlock(struct tr_se *myTrSe, char *buffer); char __fastcall__ WriteBlock(struct tr_se *myTrSe, const char *buffer); char __fastcall__ VerWriteBlock(struct tr_se *myTrSe, const char *buffer); unsigned CalcBlksFree(void); char ChkDkGEOS(void); char SetGEOSDisk(void); char NewDisk(void); char OpenDisk(void); char __fastcall__ FindBAMBit(struct tr_se *myTrSe); char __fastcall__ BlkAlloc(struct tr_se output[], unsigned length); char __fastcall__ NxtBlkAlloc(struct tr_se *startTrSe, struct tr_se output[], unsigned length); char __fastcall__ FreeBlock(struct tr_se *myTrSe); struct tr_se __fastcall__ SetNextFree(struct tr_se *myTrSe); // above needs (unsigned) casts on both sides of '=' char GetDirHead(void); char PutDirHead(void); void __fastcall__ GetPtrCurDkNm(char *name); void EnterTurbo(void); void ExitTurbo(void); void PurgeTurbo(void); char __fastcall__ ChangeDiskDevice(char newdev); /* disk header offsets i.e. index curDirHead with these */ #define OFF_TO_BAM 4 #define OFF_DISK_NAME 144 #define OFF_GS_DTYPE 189 #define OFF_OP_TR_SC 171 #define OFF_GS_ID 173 /* disk errors reported in _oserror */ #define ANY_FAULT 0xf0 #define G_EOF 0 #define NO_BLOCKS 1 #define INV_TRACK 2 #define INSUFF_SPACE 3 #define FULL_DIRECTORY 4 #define FILE_NOT_FOUND 5 #define BAD_BAM 6 #define UNOPENED_VLIR 7 #define INV_RECORD 8 #define OUT_OF_RECORDS 9 #define STRUCT_MISMAT 10 #define BFR_OVERFLOW 11 #define CANCEL_ERR 12 #define DEV_NOT_FOUND 13 #define INCOMPATIBLE 14 #define HDR_NOT_THERE 0x20 #define NO_SYNC 0x21 #define DBLK_NOT_THERE 0x22 #define DAT_CHKSUM_ERR 0x23 #define WR_VER_ERR 0x25 #define WR_PR_ON 0x26 #define HDR_CHKSUM_ERR 0x27 #define DSK_ID_MISMAT 0x29 #define BYTE_DEC_ERR 0x2e #define DOS_MISMATCH 0x73 #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/geos/gdlgbox.h��������������������������������������������������������������������0000664�0000000�0000000�00000006642�13473601511�0016374�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* GEOS dialog box functions by Maciej 'YTM/Elysium' Witkowiak */ #ifndef _GDLGBOX_H #define _GDLGBOX_H char __fastcall__ DoDlgBox(const char *dboxstring); char RstrFrmDialogue(void); /* These are custom, predefined dialog boxes, I'm sure you'll find them usable Most of them show 2 lines of text */ char __fastcall__ DlgBoxYesNo(const char *line1, const char *line2); char __fastcall__ DlgBoxOkCancel(const char *line1, const char *line2); void __fastcall__ DlgBoxOk(const char *line1, const char *line2); char __fastcall__ DlgBoxGetString(char *myString, char strLength, const char *line1, const char *line2); char __fastcall__ DlgBoxFileSelect(const char *classtxt, char ftype, char *fname); /* This is a more general dialog box, works like printf in a window */ char MessageBox(char mode, const char *format, ...); /* mode argument for MessageBox() */ enum { MB_EMPTY=0, MB_OK, MB_OKCANCEL, MB_YESNO, MB_LAST }; /* Now the command string type */ typedef void dlgBoxStr; /* and command string commands - macros */ #define DB_DEFPOS(pattern) (char)(DEF_DB_POS | (pattern)) #define DB_SETPOS(pattern,top,bot,left,right) \ (char)(SET_DB_POS | (pattern)), (char)(top), (char)(bot), \ (unsigned)(left), (unsigned)(right) #define DB_ICON(i,x,y) (char)(i), (char)(x), (char)(y) #define DB_TXTSTR(x,y,text) (char)DBTXTSTR, (char)(x), (char)(y), (text) #define DB_VARSTR(x,y,ptr) (char)DBVARSTR, (char)(x), (char)(y), (char)(ptr) #define DB_GETSTR(x,y,ptr,length) (char)DBGETSTRING, (char)(x), (char)(y), (char)(ptr), (char)(length) #define DB_SYSOPV(ptr) (char)DBSYSOPV, (unsigned)(ptr) #define DB_GRPHSTR(ptr) (char)DBGRPHSTR, (unsigned)(ptr) #define DB_GETFILES(x,y) (char)DBGETFILES, (char)(x), (char)(y) #define DB_OPVEC(ptr) (char)DBOPVEC, (unsigned)(ptr) #define DB_USRICON(x,y,ptr) (char)DBUSRICON, (char)(x), (char)(y), (unsigned)(ptr) #define DB_USRROUT(ptr) (char)DB_USR_ROUT, (unsigned)(ptr) #define DB_END (char)NULL /* part of constants below is used internally, but some are useful for macros above */ /* icons for DB_ICON */ #define OK 1 #define CANCEL 2 #define YES 3 #define NO 4 #define OPEN 5 #define DISK 6 /* commands - internally used by command macros */ #define DBTXTSTR 11 #define DBVARSTR 12 #define DBGETSTRING 13 #define DBSYSOPV 14 #define DBGRPHSTR 15 #define DBGETFILES 16 #define DBOPVEC 17 #define DBUSRICON 18 #define DB_USR_ROUT 19 /* icons tabulation in standard window */ #define DBI_X_0 1 #define DBI_X_1 9 #define DBI_X_2 17 #define DBI_Y_0 8 #define DBI_Y_1 40 #define DBI_Y_2 72 /* standard window size defaults */ #define SET_DB_POS 0 #define DEF_DB_POS 0x80 #define DEF_DB_TOP 32 #define DEF_DB_BOT 127 #define DEF_DB_LEFT 64 #define DEF_DB_RIGHT 255 /* text tabulation in standard window */ #define TXT_LN_1_Y 16 #define TXT_LN_2_Y 32 #define TXT_LN_3_Y 48 #define TXT_LN_4_Y 64 #define TXT_LN_5_Y 80 #define TXT_LN_X 16 /* system icons size */ #define SYSDBI_HEIGHT 16 #define SYSDBI_WIDTH 6 /* dialogbox string offsets */ #define OFF_DB_FORM 0 #define OFF_DB_TOP 1 #define OFF_DB_BOT 2 #define OFF_DB_LEFT 3 #define OFF_DB_RIGHT 5 #define OFF_DB_1STCMD 7 #endif ����������������������������������������������������������������������������������������������cc65-2.18/include/geos/gfile.h����������������������������������������������������������������������0000664�0000000�0000000�00000004106�13473601511�0016025�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* GEOS filesystem functions by Maciej 'YTM/Elysium' Witkowiak */ #ifndef _GFILE_H #define _GFILE_H #include <geos/gstruct.h> struct filehandle *Get1stDirEntry(void); struct filehandle *GetNxtDirEntry(void); char __fastcall__ FindFTypes(char *buffer, char ftype, char fmaxnum, const char *classtxt); char __fastcall__ GetFile(char flag, const char *fname, const char *loadaddr, const char *datadname, const char *datafname); char __fastcall__ FindFile(const char *fname); char __fastcall__ ReadFile(struct tr_se *myTrSe, char *buffer, unsigned flength); char __fastcall__ SaveFile(char skip, struct fileheader *myHeader); char __fastcall__ FreeFile(struct tr_se myTable[]); char __fastcall__ DeleteFile(const char *fname); char __fastcall__ RenameFile(const char *source, const char *target); char ReadByte(void); char __fastcall__ FollowChain(struct tr_se *startTrSe, char *buffer); char __fastcall__ GetFHdrInfo(struct filehandle *myFile); char __fastcall__ OpenRecordFile(const char *fname); char CloseRecordFile(void); char NextRecord(void); char PreviousRecord(void); char __fastcall__ PointRecord(char); char DeleteRecord(void); char InsertRecord(void); char AppendRecord(void); char __fastcall__ ReadRecord(char *buffer, unsigned flength); char __fastcall__ WriteRecord(const char *buffer, unsigned flength); char UpdateRecordFile(void); /* GEOS filetypes */ #define NOT_GEOS 0 #define BASIC 1 #define ASSEMBLY 2 #define DATA 3 #define SYSTEM 4 #define DESK_ACC 5 #define APPLICATION 6 #define APPL_DATA 7 #define FONT 8 #define PRINTER 9 #define INPUT_DEVICE 10 #define DISK_DEVICE 11 #define SYSTEM_BOOT 12 #define TEMPORARY 13 #define AUTO_EXEC 14 #define INPUT_128 15 #define NUMFILETYPES 16 /* supported structures */ #define SEQUENTIAL 0 #define VLIR 1 /* DOS filetypes */ #define DEL 0 #define SEQ 1 #define PRG 2 #define USR 3 #define REL 4 #define CBM 5 #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/geos/ggraph.h���������������������������������������������������������������������0000664�0000000�0000000�00000012521�13473601511�0016207�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* GEOS graphic (non icon/menu/sprite) functions by Maciej 'YTM/Elysium' Witkowiak */ #ifndef _GGRAPH_H #define _GGRAPH_H #include <geos/gstruct.h> void __fastcall__ SetPattern(char newpattern); void __fastcall__ HorizontalLine(char pattern, char y, unsigned xstart, unsigned xend); void __fastcall__ InvertLine(char y, unsigned xstart, unsigned xend); void __fastcall__ RecoverLine(char y, unsigned xstart, unsigned xend); void __fastcall__ VerticalLine(char pattern, char ystart, char yend, unsigned x); void __fastcall__ InitDrawWindow(struct window *myRectangle); void Rectangle(void); void __fastcall__ FrameRectangle(char pattern); void InvertRectangle(void); void ImprintRectangle(void); void RecoverRectangle(void); void __fastcall__ DrawLine(char mode, struct window *topBotCoords); void __fastcall__ DrawPoint(char mode, struct pixel *myPixel); char __fastcall__ TestPoint(struct pixel *myPixel); void __fastcall__ PutChar(char character, char y, unsigned x); void __fastcall__ PutString(char *myString, char y, unsigned x); void __fastcall__ PutDecimal(char style, unsigned value, char y, unsigned x); char __fastcall__ GetCharWidth(char character); void __fastcall__ LoadCharSet(struct fontdesc *myFont); void UseSystemFont(void); void __fastcall__ BitmapUp(struct iconpic *myIcon); void __fastcall__ BitmapClip(char skipl, char skipr, unsigned skiptop, struct iconpic *myIcon); void __fastcall__ BitOtherClip(void *proc1, void *proc2, char skipl, char skipr, unsigned skiptop, struct iconpic *myIcon); void __fastcall__ GraphicsString(char *myGfxString); #ifdef __GEOS_CBM__ void SetNewMode(void); #endif /* VIC colour constants */ #define BLACK 0 #define WHITE 1 #define RED 2 #define CYAN 3 #define PURPLE 4 #define GREEN 5 #define BLUE 6 #define YELLOW 7 #define ORANGE 8 #define BROWN 9 #define LTRED 10 #define DKGREY 11 #define GREY 12 #define MEDGREY 12 #define LTGREEN 13 #define LTBLUE 14 #define LTGREY 15 /* VIC memory banks - lowest 2 bits of cia2base+0 */ #define GRBANK0 3 #define GRBANK1 2 #define GRBANK2 1 #define GRBANK3 0 /* VIC screen sizes */ #define VIC_X_POS_OFF 24 #define VIC_Y_POS_OFF 50 #ifdef __GEOS_CBM__ #define SC_BYTE_WIDTH 40 #define SC_PIX_HEIGHT 200 #define SC_PIX_WIDTH 320 #define SC_SIZE 8000 #else #define SC_BYTE_WIDTH 70 #define SC_PIX_HEIGHT 192 #define SC_PIX_WIDTH 560 #define SC_SIZE 13440 #endif /* VDC screen constants */ #define SCREENBYTEWIDTH 80 #define SCREENPIXELWIDTH 640 /* control characters for use as numbers, not characters */ #define BACKSPACE 8 #define FORWARDSPACE 9 #define TAB 9 #define LF 10 #define HOME 11 #define PAGE_BREAK 12 #define UPLINE 12 #define CR 13 #define ULINEON 14 #define ULINEOFF 15 #define ESC_GRAPHICS 16 #define ESC_RULER 17 #define REV_ON 18 #define REV_OFF 19 #define GOTOX 20 #define GOTOY 21 #define GOTOXY 22 #define NEWCARDSET 23 #define BOLDON 24 #define ITALICON 25 #define OUTLINEON 26 #define PLAINTEXT 27 /* control characters for use in strings: eg: str[10]=CBOLDON "Hello"; */ #define CCR "\015" #define CULINEON "\016" #define CULINEOFF "\017" #define CREV_ON "\022" #define CREV_OFF "\023" #define CBOLDON "\030" #define CITALICON "\031" #define COUTLINEON "\032" #define CPLAINTEXT "\033" /*values of currentMode */ /* bitNumbers */ #define UNDERLINE_BIT 7 #define BOLD_BIT 6 #define REVERSE_BIT 5 #define ITALIC_BIT 4 #define OUTLINE_BIT 3 #define SUPERSCRIPT_BIT 2 #define SUBSCRIPT_BIT 1 /* bitMasks */ #define SET_UNDERLINE 0x80 #define SET_BOLD 0x40 #define SET_REVERSE 0x20 #define SET_ITALIC 0x10 #define SET_OUTLINE 0x08 #define SET_SUPERSCRIPT 0x04 #define SET_SUBSCRIPT 0x02 #define SET_PLAINTEXT 0 /* values of dispBufferOn */ #define ST_WRGS_FORE 0x20 #define ST_WR_BACK 0x40 #define ST_WR_FORE 0x80 /* PutDecimal parameters */ /* leading zeros? */ #define SET_NOSURPRESS 0 #define SET_SURPRESS 0x40 /* justification */ #define SET_RIGHTJUST 0 #define SET_LEFTJUST 0x80 /* C128 x-extension flags */ #define ADD1_W 0x2000 #define DOUBLE_B 0x80 #define DOUBLE_W 0x8000 /* DrawLine/DrawPoint mode values */ #define DRAW_ERASE 0x00 #define DRAW_DRAW 0x40 #define DRAW_COPY 0x80 typedef void graphicStr; #define MOVEPENTO(x,y) (char)1, (unsigned)(x), (char)(y) #define LINETO(x,y) (char)2, (unsigned)(x), (char)(y) #define RECTANGLETO(x,y) (char)3, (unsigned)(x), (char)(y) #define NEWPATTERN(p) (char)5, (char)(p) #define FRAME_RECTO(x,y) (char)7, (unsigned)(x), (char)(y) #define PEN_X_DELTA(x) (char)8, (unsigned)(x) #define PEN_Y_DELTA(y) (char)9, (char)(y) #define PEN_XY_DELTA(x,y) (char)10, (unsigned)(x), (char)(y) #define GSTR_END (char)NULL /* ESC_PUTSTRING can't be implemented - it needs text, not pointer to it #define ESC_PUTSTRING(x,y,text) (char)6, (unsigned)(x), (char)(y), (text), (char)NULL */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/geos/gmemory.h��������������������������������������������������������������������0000664�0000000�0000000�00000002114�13473601511�0016413�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* GEOS memory and string functions by Maciej 'YTM/Elysium' Witkowiak */ #ifndef _GMEMORY_H #define _GMEMORY_H #include <geos/gstruct.h> void __fastcall__ CopyString(char *dest, const char *source); char __fastcall__ CmpString(const char *dest, const char *source); void __fastcall__ CopyFString(char len, char *dest, const char *source); char __fastcall__ CmpFString(char len, char *dest, const char *source); unsigned __fastcall__ CRC(const char *buffer, unsigned len); void* __fastcall__ ClearRam(char *dest, unsigned len); void* __fastcall__ FillRam(char *dest, char what, unsigned len); void* __fastcall__ MoveData(char *dest, const char *source, unsigned len); void __fastcall__ InitRam(char *myInitTab); void __fastcall__ StashRAM(char REUBank, unsigned len, char *reuaddy, const char *cpuaddy); void __fastcall__ FetchRAM(char REUBank, unsigned len, const char *reuaddy, char *cpuaddy); void __fastcall__ SwapRAM(char REUBank, unsigned len, char *reuaddy, char *cpuaddy); char __fastcall__ VerifyRAM(char REUBank, unsigned len, const char *reuaddy, const char *cpuaddy); #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/geos/gmenu.h����������������������������������������������������������������������0000664�0000000�0000000�00000002305�13473601511�0016051�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* GEOS menu and icon functions by Maciej 'YTM/Elysium' Witkowiak */ #ifndef _GMENU_H #define _GMENU_H #include <geos/gstruct.h> void __fastcall__ DoMenu(struct menu *myMenu); void ReDoMenu(void); void RecoverMenu(void); void RecoverAllMenus(void); void DoPreviousMenu(void); void GotoFirstMenu(void); void __fastcall__ DoIcons(struct icontab *myIconTab); /* DoMenu - menutypes */ #define MENU_ACTION 0x00 #define DYN_SUB_MENU 0x40 #define SUB_MENU 0x80 #define HORIZONTAL 0x00 #define VERTICAL 0x80 /* menu string offsets */ #define OFF_MY_TOP 0 #define OFF_MY_BOT 1 #define OFF_MX_LEFT 2 #define OFF_MX_RIGHT 4 #define OFF_NUM_M_ITEMS 6 #define OFF_1ST_M_ITEM 7 /* icon string offsets */ #define OFF_NM_ICNS 0 #define OFF_IC_XMOUSE 1 #define OFF_IC_YMOUSE 3 #define OFF_PIC_ICON 0 #define OFF_X_ICON_POS 2 #define OFF_Y_ICON_POS 3 #define OFF_WDTH_ICON 4 #define OFF_HEIGHT_ICON 5 #define OFF_SRV_RT_ICON 6 #define OFF_NX_ICON 8 /* icons, menus status flags */ #define ST_FLASH 0x80 #define ST_INVERT 0x40 #define ST_LD_AT_ADDR 0x01 #define ST_LD_DATA 0x80 #define ST_PR_DATA 0x40 #define ST_WR_PR 0x40 #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/geos/gprocess.h�������������������������������������������������������������������0000664�0000000�0000000�00000001055�13473601511�0016564�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* GEOS processes (~multitasking) functions by Maciej 'YTM/Elysium' Witkowiak */ #ifndef _GPROCESS_H #define _GPROCESS_H #include <geos/gstruct.h> void __fastcall__ InitProcesses(char number, struct process *proctab); void __fastcall__ RestartProcess(char number); void __fastcall__ EnableProcess(char number); void __fastcall__ BlockProcess(char number); void __fastcall__ UnblockProcess(char number); void __fastcall__ FreezeProcess(char number); void __fastcall__ UnfreezeProcess(char number); void __fastcall__ Sleep(unsigned jiffies); #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/geos/gsprite.h��������������������������������������������������������������������0000664�0000000�0000000�00000004461�13473601511�0016420�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* GEOS mouse and sprite functions by Maciej 'YTM/Elysium' Witkowiak */ #ifndef _GSPRITE_H #define _GSPRITE_H void StartMouseMode(void); void ClearMouseMode(void); void MouseUp(void); void MouseOff(void); char __fastcall__ IsMseInRegion(struct window *region); void __fastcall__ DrawSprite(char spritenum, const char *spritepic); void __fastcall__ PosSprite(char spritenum, struct pixel *position); void __fastcall__ EnablSprite(char spritenum); void __fastcall__ DisablSprite(char spritenum); void __fastcall__ InitTextPrompt(char height); void __fastcall__ PromptOn(struct pixel *position); void PromptOff(void); char GetNextChar(void); /* keyboard constants */ #define KEY_F1 1 #define KEY_F2 2 #define KEY_F3 3 #define KEY_F4 4 #define KEY_F5 5 #define KEY_F6 6 #define KEY_NOSCRL 7 #define KEY_ENTER 13 #define KEY_F7 14 #define KEY_F8 15 #define KEY_HOME 18 #define KEY_CLEAR 19 #define KEY_LARROW 20 #define KEY_UPARROW 21 #define KEY_STOP 22 #define KEY_RUN 23 #define KEY_BPS 24 #define KEY_HELP 25 #define KEY_ALT 26 #define KEY_ESC 27 #define KEY_INSERT 28 #define KEY_INVALID 31 #define KEY_LEFT BACKSPACE #ifdef __GEOS_CBM__ #define KEY_UP 16 #define KEY_DOWN 17 #define KEY_DELETE 29 #define KEY_RIGHT 30 #else #define KEY_UP 11 #define KEY_DOWN 10 #define KEY_DELETE 127 #define KEY_RIGHT 21 #endif /* values of faultData - pointer position vs. mouseWindow */ /* bit numbers */ #define OFFTOP_BIT 7 #define OFFBOTTOM_BIT 6 #define OFFLEFT_BIT 5 #define OFFRIGHT_BIT 4 #define OFFMENU_BIT 3 /* bit masks */ #define SET_OFFTOP 0x80 #define SET_OFFBOTTOM 0x40 #define SET_OFFLEFT 0x20 #define SET_OFFRIGHT 0x10 #define SET_OFFMENU 0x08 /* mouseOn */ /* bit numbers */ #define MOUSEON_BIT 7 #define MENUON_BIT 6 #define ICONSON_BIT 5 /* bit masks */ #define SET_MSE_ON 0x80 #define SET_MENUON 0x40 #define SET_ICONSON 0x20 /* pressFlag */ /* bit numbers */ #define KEYPRESS_BIT 7 #define INPUT_BIT 6 #define MOUSE_BIT 5 /* bit masks */ #define SET_KEYPRESS 0x80 #define SET_INPUTCHG 0x40 #define SET_MOUSE 0x20 #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/geos/gstruct.h��������������������������������������������������������������������0000664�0000000�0000000�00000012116�13473601511�0016432�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* GEOS structs by Maciej 'YTM/Elysium' Witkowiak */ /* apart from initializing data, structures below can be used to speed up access to data and let cc65 to generate better code e.g. if you have menu defined as TopMenu and you want to change the number of menu items use: ((struct menu*)&TopMenu)->number=newNumber; This will be translated into single lda/sta pair */ #ifndef _GSTRUCT_H #define _GSTRUCT_H typedef void (*void_func) (void); struct s_date { /* system date & time */ char s_year; char s_month; char s_day; char s_hour; char s_minutes; char s_seconds; }; struct tr_se { /* track and sector */ char track; char sector; }; struct fileheader { /* header block (like fileHeader) */ struct tr_se n_block; char icon_desc[3]; char icon_pic[63]; char dostype; char type; char structure; unsigned load_address; unsigned end_address; unsigned exec_address; char class_name[19]; char column_flag; char author[63]; char note[96]; }; #ifdef __GEOS_CBM__ struct f_date { /* date in filedesctiptor */ char f_year; char f_month; char f_day; char f_hour; char f_minute; }; struct filehandle { /* filehandle in directory sectors */ char dostype; /* or in dirEntryBuf */ struct tr_se n_block; char name[16]; struct tr_se header; char structure; char type; struct f_date date; unsigned size; }; #else /* #ifdef __GEOS_CBM__ */ struct f_date { /* date in filedesctiptor */ unsigned f_day:5; unsigned f_month:4; unsigned f_year:7; char f_minute; char f_hour; }; struct filehandle { /* filehandle in directory sectors */ unsigned name_len:4; /* or in dirEntryBuf */ unsigned structure:4; char name[15]; char type; struct tr_se n_block; unsigned size; char byte_size[3]; struct f_date date; char version; char min_version; char access; struct tr_se header; struct f_date mod_date; struct tr_se dir_head; }; #endif /* #ifdef __GEOS_CBM__ */ struct pixel { /* describes point */ unsigned x; char y; }; struct fontdesc { /* describes font */ char baseline; char width; char height; char *index_tbl; char *data_ptr; }; struct window { /* describes screen region */ char top; char bot; unsigned left; unsigned right; }; struct VLIR_info { /* VLIR information */ char curRecord; /* currently only used in VLIR */ char usedRecords; /* as system info (curRecord is mainly of your interest */ char fileWritten; unsigned fileSize; }; struct process { /* process info, declare table of that type */ unsigned pointer; /* (like: struct process proctab[2]=... */ unsigned jiffies; /* last entry HAVE TO BE {0,0} */ }; struct iconpic { /* icon/encoded bitmap description */ char *pic_ptr; /* ptr to a photo scrap (or encoded bitmap) */ char x; /* position in cards (*8 pixels) */ char y; char width; /* in cards */ char heigth; /* in lines (pixels) */ }; struct icondef { /* icon definition for DoIcons */ char *pic_ptr; /* ptr to a photo scrap (or encoded bitmap) */ char x; /* position in cards (*8 pixels) */ char y; char width; /* of icon (in cards) */ char heigth; /* of icon in lines (pixels) */ unsigned proc_ptr; /* pointer to function handling that icon */ }; struct icontab { char number; /* number of declared icons */ struct pixel mousepos; /* position of mouse after DoIcons */ struct icondef tab[]; /* table of size declared by icontab.number */ }; struct menuitem { char *name; char type; void *rest; /* may be ptr to function, or ptr to struct menu (submenu) */ }; struct menu { struct window size; char number; struct menuitem items[]; }; struct inittab { /* use struct inittab mytab[n] for initram */ unsigned ptr; /* ptr to 1st byte */ char number; /* number of following bytes */ char values[]; /* actual string of bytes */ }; #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/geos/gsym.h�����������������������������������������������������������������������0000664�0000000�0000000�00000031004�13473601511�0015713�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* GEOS system addresses and locations reassembled by Maciej 'YTM/Elysium' Witkowiak */ #ifndef _GSYM_H #define _GSYM_H #include <geos/gstruct.h> #define r0 (*(unsigned*)(R_BASE + 0x00)) #define r0L (*(char*)(R_BASE + 0x00)) #define r0H (*(char*)(R_BASE + 0x01)) #define r1 (*(unsigned*)(R_BASE + 0x02)) #define r1L (*(char*)(R_BASE + 0x02)) #define r1H (*(char*)(R_BASE + 0x03)) #define drawWindow (*(struct window*)(R_BASE + 0x04)) #define r2 (*(unsigned*)(R_BASE + 0x04)) #define r2L (*(char*)(R_BASE + 0x04)) #define r2H (*(char*)(R_BASE + 0x05)) #define r3 (*(unsigned*)(R_BASE + 0x06)) #define r3L (*(char*)(R_BASE + 0x06)) #define r3H (*(char*)(R_BASE + 0x07)) #define r4 (*(unsigned*)(R_BASE + 0x08)) #define r4L (*(char*)(R_BASE + 0x08)) #define r4H (*(char*)(R_BASE + 0x09)) #define r5 (*(unsigned*)(R_BASE + 0x0a)) #define r5L (*(char*)(R_BASE + 0x0a)) #define r5H (*(char*)(R_BASE + 0x0b)) #define r6 (*(unsigned*)(R_BASE + 0x0c)) #define r6L (*(char*)(R_BASE + 0x0c)) #define r6H (*(char*)(R_BASE + 0x0d)) #define r7 (*(unsigned*)(R_BASE + 0x0e)) #define r7L (*(char*)(R_BASE + 0x0e)) #define r7H (*(char*)(R_BASE + 0x0f)) #define r8 (*(unsigned*)(R_BASE + 0x10)) #define r8L (*(char*)(R_BASE + 0x10)) #define r8H (*(char*)(R_BASE + 0x11)) #define r9 (*(unsigned*)(R_BASE + 0x12)) #define r9L (*(char*)(R_BASE + 0x12)) #define r9H (*(char*)(R_BASE + 0x13)) #define r10 (*(unsigned*)(R_BASE + 0x14)) #define r10L (*(char*)(R_BASE + 0x14)) #define r10H (*(char*)(R_BASE + 0x15)) #define r11 (*(unsigned*)(R_BASE + 0x16)) #define r11L (*(char*)(R_BASE + 0x16)) #define r11H (*(char*)(R_BASE + 0x17)) #define r12 (*(unsigned*)(R_BASE + 0x18)) #define r12L (*(char*)(R_BASE + 0x18)) #define r12H (*(char*)(R_BASE + 0x19)) #define r13 (*(unsigned*)(R_BASE + 0x1a)) #define r13L (*(char*)(R_BASE + 0x1a)) #define r13H (*(char*)(R_BASE + 0x1b)) #define r14 (*(unsigned*)(R_BASE + 0x1c)) #define r14L (*(char*)(R_BASE + 0x1c)) #define r14H (*(char*)(R_BASE + 0x1d)) #define r15 (*(unsigned*)(R_BASE + 0x1e)) #define r15L (*(char*)(R_BASE + 0x1e)) #define r15H (*(char*)(R_BASE + 0x1f)) #ifdef __GEOS_CBM__ #define nameBuf char[17] #define blockBuf char[256] #define CPU_DDR (*(char*)0x00) #define CPU_DATA (*(char*)0x01) #define R_BASE 0x02 #define curPattern (*(unsigned*)0x22) #define string (*(unsigned*)0x24) #define curFontDesc (*(struct fontdesc*)0x26) #define currentMode (*(char*)0x2e) #define dispBufferOn (*(char*)0x2f) #define mouseOn (*(char*)0x30) #define msePicPtr (*(unsigned*)0x31) #define curWindow (*(struct window*)0x33) #define pressFlag (*(char*)0x39) #define mousePos (*(struct pixel*)0x3a) #define returnAddress (*(unsigned*)0x3d) #define graphMode (*(char*)0x3f) #define STATUS (*(char*)0x90) #define curDevice (*(char*)0xba) #define irqvec (*(void_func*)0x0314) #define bkvec (*(void_func*)0x0316) #define nmivec (*(void_func*)0x0318) #define APP_RAM ((char*)0x0400) #define BACK_SCR_BASE ((char*)0x6000) #define PRINTBASE ((char*)0x7900) #define OS_VARS ((char*)0x8000) #define diskBlkBuf ((blockBuf)0x8000) #define fileHeader (*(struct fileheader*)0x8100) #define curDirHead ((blockBuf)0x8200) #define fileTrScTab ((struct tr_se[128])0x8300) #define dirEntryBuf (*(struct filehandle*)0x8400) #define DrACurDkNm ((nameBuf)0x841e) #define DrBCurDkNm ((nameBuf)0x8430) #define dataFileName ((nameBuf)0x8442) #define dataDiskName ((nameBuf)0x8453) #define PrntFileName ((nameBuf)0x8465) #define PrntDiskName ((nameBuf)0x8476) #define curDrive (*(char*)0x8489) #define diskOpenFlg (*(char*)0x848a) #define isGEOS (*(char*)0x848b) #define interleave (*(char*)0x848c) #define NUMDRV (*(char*)0x848d) #define driveType ((char[4])0x848e) #define turboFlags ((char[4])0x8492) #define VLIRInfo (*(struct VLIR_info*)0x8496) #define appMain (*(void_func*)0x849b) #define intTopVector (*(void_func*)0x849d) #define intBotVector (*(void_func*)0x849f) #define mouseVector (*(void_func*)0x84a1) #define keyVector (*(void_func*)0x84a3) #define inputVector (*(void_func*)0x84a5) #define mouseFaultVec (*(void_func*)0x84a7) #define otherPressVec (*(void_func*)0x84a9) #define StringFaultVec (*(void_func*)0x84ab) #define alarmTmtVector (*(void_func*)0x84ad) #define BRKVector (*(void_func*)0x84af) #define RecoverVector (*(void_func*)0x84b1) #define selectionFlash (*(char*)0x84b3) #define alphaFlag (*(char*)0x84b4) #define iconSelFlg (*(char*)0x84b5) #define faultData (*(char*)0x84b6) #define menuNumber (*(char*)0x84b7) #define mouseWindow (*(struct window*)0x84b8) #define stringXY (*(struct pixel*)0x84be) #define mousePicData (*(char*)0x84c1) #define maxMouseSpeed (*(char*)0x8501) #define minMouseSpeed (*(char*)0x8502) #define mouseAccel (*(char*)0x8503) #define keyData (*(char*)0x8504) #define mouseData (*(char*)0x8505) #define inputData (*(char*)0x8506) #define mouseSpeed (*(char*)0x8507) #define random (*(char*)0x850a) #define saveFontTab (*(struct fontdesc*)0x850c) #define dblClickCount (*(char*)0x8515) #define system_date (*(struct s_date*)0x8516) #define alarmSetFlag (*(char*)0x851c) #define sysDBData (*(char*)0x851d) #define screencolors (*(char*)0x851e) #define dlgBoxRamBuf (*(char*)0x851f) #define savedmoby2 (*(char*)0x88bb) #define scr80polar (*(char*)0x88bc) #define scr80colors (*(char*)0x88bd) #define vdcClrMode (*(char*)0x88be) #define driveData ((char[4])0x88bf) #define ramExpSize (*(char*)0x88c3) #define sysRAMFlg (*(char*)0x88c4) #define firstBoot (*(char*)0x88c5) #define curType (*(char*)0x88c6) #define ramBase (*(char*)0x88c7) #define inputDevName ((nameBuf)0x88cb) #define DrCCurDkNm ((nameBuf)0x88dc) #define DrDCurDkNm ((nameBuf)0x88ee) #define dir2Head ((blockBuf)0x8900) #define SPRITE_PICS ((char*)0x8a00) #define sprpic ((char[8][64])0x8a00) #define COLOR_MATRIX ((char[1000])0x8c00) #define objPointer ((char[8])0x8ff8) #define DISK_BASE ((char*)0x9000) #define SCREEN_BASE ((char*)0xa000) #define OS_ROM ((char*)0xc000) #define OS_JUMPTAB ((char*)0xc100) #define EXP_BASE ((char*)0xdf00) #define MOUSE_BASE_128 ((char*)0xfd00) #define MOUSE_JMP_128 ((char*)0xfd00) #define END_MOUSE_128 ((char*)0xfe80) #define MOUSE_BASE ((char*)0xfe80) #define MOUSE_JMP ((char*)0xfe80) #define config (*(char*)0xff00) #define END_MOUSE ((char*)0xfffa) #define NMI_VECTOR (*(void_func*)0xfffa) #define RESET_VECTOR (*(void_func*)0xfffc) #define IRQ_VECTOR (*(void_func*)0xfffe) #define vicbase ((char*)0xd000) #define sidbase ((char*)0xd400) #define mmu ((char*)0xd500) #define VDC ((char*)0xd600) #define ctab ((char*)0xd800) #define cia1base ((char*)0xdc00) #define cia2base ((char*)0xdd00) #define mob0xpos (*(char*)0xd000) #define mob0ypos (*(char*)0xd001) #define mob1xpos (*(char*)0xd002) #define mob1ypos (*(char*)0xd003) #define mob2xpos (*(char*)0xd004) #define mob2ypos (*(char*)0xd005) #define mob3xpos (*(char*)0xd006) #define mob3ypos (*(char*)0xd007) #define mob4xpos (*(char*)0xd008) #define mob4ypos (*(char*)0xd009) #define mob5xpos (*(char*)0xd00a) #define mob5ypos (*(char*)0xd00b) #define mob6xpos (*(char*)0xd00c) #define mob6ypos (*(char*)0xd00d) #define mob7xpos (*(char*)0xd00e) #define mob7ypos (*(char*)0xd00f) #define msbxpos (*(char*)0xd010) #define grcntrl1 (*(char*)0xd011) #define rasreg (*(char*)0xd012) #define lpxpos (*(char*)0xd013) #define lpypos (*(char*)0xd014) #define mobenble (*(char*)0xd015) #define grcntrl2 (*(char*)0xd016) #define grmemptr (*(char*)0xd018) #define grirq (*(char*)0xd019) #define grirqen (*(char*)0xd01a) #define moby2 (*(char*)0xd017) #define mobprior (*(char*)0xd01b) #define mobmcm (*(char*)0xd01c) #define mobx2 (*(char*)0xd01d) #define mobmobcol (*(char*)0xd01e) #define mobbakcol (*(char*)0xd01f) #define extclr (*(char*)0xd020) #define bakclr0 (*(char*)0xd021) #define bakclr1 (*(char*)0xd022) #define bakclr2 (*(char*)0xd023) #define bakclr3 (*(char*)0xd024) #define mcmclr0 (*(char*)0xd025) #define mcmclr1 (*(char*)0xd026) #define mob0clr (*(char*)0xd027) #define mob1clr (*(char*)0xd028) #define mob2clr (*(char*)0xd029) #define mob3clr (*(char*)0xd02a) #define mob4clr (*(char*)0xd02b) #define mob5clr (*(char*)0xd02c) #define mob6clr (*(char*)0xd02d) #define mob7clr (*(char*)0xd02e) #define keyreg (*(char*)0xd02f) #define clkreg (*(char*)0xd030) #define vdcreg (*(char*)0xd600) #define vdcdata (*(char*)0xd601) #else /* #ifdef __GEOS_CBM__ */ #define nameBuf char[16] #define blockBuf char[512] #define R_BASE 0x00 #define curPattern (*(unsigned*)0x022c) #define string (*(unsigned*)0x53) #define curFontDesc (*(struct fontdesc*)0x0218) #define currentMode (*(char*)0x021c) #define dispBufferOn (*(char*)0x021d) #define mouseOn (*(char*)0x5d) #define curWindow (*(struct window*)0x021e) #define pressFlag (*(char*)0x08fe) #define mousePos (*(struct pixel*)0x0241) #define returnAddress (*(unsigned*)0x64) #define diskBlkBuf ((blockBuf)0xf659) #define fileHeader (*(struct fileheader*)0xf859) #define curDirHead ((char[39])0xfa80) #define dirEntryBuf (*(struct filehandle*)0xfa59) #define DrACurDkNm ((nameBuf)0xfaa7) #define DrBCurDkNm ((nameBuf)0xfab7) #define dataFileName ((nameBuf)0x02a4) #define dataDiskName ((nameBuf)0x02b4) #define PrntFileName ((nameBuf)0x08ac) #define curDrive (*(char*)0xf60d) #define diskOpenFlg (*(char*)0xf617) #define NUMDRV (*(char*)0xf60e) #define driveType ((char[4])0xfaf3) #define VLIRInfo (*(struct VLIR_info*)0xf618) #define appMain (*(void_func*)0x0200) #define intTopVector (*(void_func*)0x0202) #define intBotVector (*(void_func*)0x0204) #define mouseVector (*(void_func*)0x0206) #define keyVector (*(void_func*)0x0208) #define inputVector (*(void_func*)0x020a) #define mouseFaultVec (*(void_func*)0x020c) #define otherPressVec (*(void_func*)0x020e) #define StringFaultVec (*(void_func*)0x0210) #define alarmTmtVector (*(void_func*)0x0212) #define BRKVector (*(void_func*)0x0214) #define RecoverVector (*(void_func*)0x0216) #define selectionFlash (*(char*)0x0224) #define alphaFlag (*(char*)0x0225) #define iconSelFlg (*(char*)0x0226) #define faultData (*(char*)0x0227) #define menuNumber (*(char*)0x0228) #define mouseWindow (*(struct window*)0x57) #define stringXY (*(struct pixel*)0x022e) #define maxMouseSpeed (*(char*)0x027d) #define minMouseSpeed (*(char*)0x027e) #define mouseAccel (*(char*)0x027f) #define keyData (*(char*)0x0245) #define mouseData (*(char*)0x0246) #define inputData (*(char*)0x0247) #define random (*(char*)0x024c) #define saveFontTab (*(struct fontdesc*)0x024e) #define dblClickCount (*(char*)0x0258) #define system_date (*(struct s_date*)0xf200) #define sysDBData (*(char*)0x0259) #define dlgBoxRamBuf (*(char*)0xf381) #define firstBoot (*(char*)0x0281) #define inputDevName ((nameBuf)0x08cc) #define DrCCurDkNm ((nameBuf)0xfac7) #define DrDCurDkNm ((nameBuf)0xfad7) #define mobenble (*(char*)0x0818) #define moby2 (*(char*)0x081a) #define mobx2 (*(char*)0x0819) #endif /* #ifdef __GEOS_CBM__ */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/geos/gsys.h�����������������������������������������������������������������������0000664�0000000�0000000�00000002424�13473601511�0015725�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* GEOS system functions by Maciej 'YTM/Elysium' Witkowiak */ #ifndef _GSYS_H #define _GSYS_H void FirstInit(void); void InitForIO(void); void DoneWithIO(void); void MainLoop(void); void EnterDeskTop(void); void ToBASIC(void); void Panic(void); void __fastcall__ CallRoutine(void *myRoutine); unsigned GetSerialNumber(void); char GetRandom(void); void __fastcall__ SetDevice(char newdev); char get_ostype(void); /* possible return values of get_ostype, machine and version flags will be combined with OR */ /* machine flags */ #define GEOS64 0x00 #define GEOS4 0x04 /* plus4 geos is not or'ed with version */ #define GEOS128 0x80 /* version flags */ #define MEGAPATCH3 0x03 #define GATEWAY 0x08 #define GEOS_V10 0x10 #define GEOS_V11 0x11 #define GEOS_V12 0x12 #define GEOS_V13 0x13 #define GEOS_V15 0x15 #define GEOS_V20 0x20 #define WHEELS 0x40 /* only Wheels? */ char get_tv(void); /* possible return values of get_tv, these flags will be combined note that columns state can be changed during runtime and get_tv always returns the current state */ #define COLUMNS40 0x00 #define COLUMNS80 0x01 #define TV_PAL 0x00 #define TV_NTSC 0x80 #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/inttypes.h������������������������������������������������������������������������0000664�0000000�0000000�00000017202�13473601511�0015662�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* inttypes.h */ /* */ /* Format conversion of integer types */ /* */ /* */ /* */ /* (C) 2002-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* Note: This file is not fully ISO 9899-1999 compliant because cc65 lacks ** a 64 bit data types and is not able to return structs > 4 bytes. The ** declarations have been adjusted accordingly or left out. */ #ifndef _INTTYPES_H #define _INTTYPES_H /* inttypes.h must always include stdint.h */ #ifndef _STDINT_H #include <stdint.h> #endif /* Standard functions */ intmax_t __fastcall__ imaxabs (intmax_t val); intmax_t __fastcall__ strtoimax (const char* nptr, char** endptr, int base); uintmax_t __fastcall__ strtoumax (const char* nptr, char** endptr, int base); /* printf() macros for signed integers */ #define PRId8 "d" #define PRId16 "d" #define PRId32 "ld" #define PRIdLEAST8 "d" #define PRIdLEAST16 "d" #define PRIdLEAST32 "ld" #define PRIdFAST8 "d" #define PRIdFAST16 "d" #define PRIdFAST32 "ld" #define PRIdMAX "ld" #define PRIdPTR "d" #define PRIi8 "i" #define PRIi16 "i" #define PRIi32 "li" #define PRIiLEAST8 "i" #define PRIiLEAST16 "i" #define PRIiLEAST32 "li" #define PRIiFAST8 "i" #define PRIiFAST16 "i" #define PRIiFAST32 "li" #define PRIiMAX "li" #define PRIiPTR "i" /* fprintf() macros for unsigned integers */ #define PRIo8 "o" #define PRIo16 "o" #define PRIo32 "lo" #define PRIoLEAST8 "o" #define PRIoLEAST16 "o" #define PRIoLEAST32 "lo" #define PRIoFAST8 "o" #define PRIoFAST16 "o" #define PRIoFAST32 "lo" #define PRIoMAX "lo" #define PRIoPTR "o" #define PRIu8 "u" #define PRIu16 "u" #define PRIu32 "lu" #define PRIuLEAST8 "u" #define PRIuLEAST16 "u" #define PRIuLEAST32 "lu" #define PRIuFAST8 "u" #define PRIuFAST16 "u" #define PRIuFAST32 "lu" #define PRIuMAX "lu" #define PRIuPTR "u" #define PRIx8 "x" #define PRIx16 "x" #define PRIx32 "lx" #define PRIxLEAST8 "x" #define PRIxLEAST16 "x" #define PRIxLEAST32 "lx" #define PRIxFAST8 "x" #define PRIxFAST16 "x" #define PRIxFAST32 "lx" #define PRIxMAX "lx" #define PRIxPTR "x" #define PRIX8 "X" #define PRIX16 "X" #define PRIX32 "lX" #define PRIXLEAST8 "X" #define PRIXLEAST16 "X" #define PRIXLEAST32 "lX" #define PRIXFAST8 "X" #define PRIXFAST16 "X" #define PRIXFAST32 "lX" #define PRIXMAX "lX" #define PRIXPTR "X" /* fscanf() macros for signed integers */ #define SCNd8 "hd" #define SCNd16 "d" #define SCNd32 "ld" #define SCNdLEAST8 "hd" #define SCNdLEAST16 "d" #define SCNdLEAST32 "ld" #define SCNdFAST8 "hd" #define SCNdFAST16 "d" #define SCNdFAST32 "ld" #define SCNdMAX "ld" #define SCNdPTR "d" #define SCNi8 "hi" #define SCNi16 "i" #define SCNi32 "li" #define SCNiLEAST8 "hi" #define SCNiLEAST16 "i" #define SCNiLEAST32 "li" #define SCNiFAST8 "hi" #define SCNiFAST16 "i" #define SCNiFAST32 "li" #define SCNiMAX "li" #define SCNiPTR "i" /* fscanf() macros for unsigned integers */ #define SCNo8 "ho" #define SCNo16 "o" #define SCNo32 "lo" #define SCNoLEAST8 "ho" #define SCNoLEAST16 "o" #define SCNoLEAST32 "lo" #define SCNoFAST8 "ho" #define SCNoFAST16 "o" #define SCNoFAST32 "lo" #define SCNoMAX "lo" #define SCNoPTR "o" #define SCNu8 "hu" #define SCNu16 "u" #define SCNu32 "lu" #define SCNuLEAST8 "hu" #define SCNuLEAST16 "u" #define SCNuLEAST32 "lu" #define SCNuFAST8 "hu" #define SCNuFAST16 "u" #define SCNuFAST32 "lu" #define SCNuMAX "lu" #define SCNuPTR "u" #define SCNx8 "hx" #define SCNx16 "x" #define SCNx32 "lx" #define SCNxLEAST8 "hx" #define SCNxLEAST16 "x" #define SCNxLEAST32 "lx" #define SCNxFAST8 "hx" #define SCNxFAST16 "x" #define SCNxFAST32 "lx" #define SCNxMAX "lx" #define SCNxPTR "x" /* End of inttypes.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/iso646.h��������������������������������������������������������������������������0000664�0000000�0000000�00000005457�13473601511�0015046�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* iso646.h */ /* */ /* Alternative spellings */ /* */ /* */ /* */ /* (C) 1998-2000 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 _ISO646_H #define _ISO646_H /* Operator tokens */ #define and && #define and_eq &= #define bitand & #define bitor | #define compl ~ #define not ! #define not_eq != #define or || #define or_eq |= #define xor ^ #define xor_eq ^= /* End of iso646.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/joystick.h������������������������������������������������������������������������0000664�0000000�0000000�00000012017�13473601511�0015641�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* joystick.h */ /* */ /* Read the joystick on systems that support it */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _JOYSTICK_H #define _JOYSTICK_H #include <target.h> /*****************************************************************************/ /* Definitions */ /*****************************************************************************/ /* Error codes */ #define JOY_ERR_OK 0 /* No error */ #define JOY_ERR_NO_DRIVER 1 /* No driver available */ #define JOY_ERR_CANNOT_LOAD 2 /* Error loading driver */ #define JOY_ERR_INV_DRIVER 3 /* Invalid driver */ #define JOY_ERR_NO_DEVICE 4 /* Device (hardware) not found */ /* Argument for the joy_read function */ #define JOY_1 0 #define JOY_2 1 /* Macros that evaluate the return code of joy_read */ #define JOY_UP(v) ((v) & JOY_UP_MASK) #define JOY_DOWN(v) ((v) & JOY_DOWN_MASK) #define JOY_LEFT(v) ((v) & JOY_LEFT_MASK) #define JOY_RIGHT(v) ((v) & JOY_RIGHT_MASK) #define JOY_BTN_1(v) ((v) & JOY_BTN_1_MASK) /* Universally available */ #define JOY_BTN_2(v) ((v) & JOY_BTN_2_MASK) /* Second button if available */ #define JOY_BTN_3(v) ((v) & JOY_BTN_3_MASK) /* Third button if available */ #define JOY_BTN_4(v) ((v) & JOY_BTN_4_MASK) /* Fourth button if available */ /* The name of the standard joystick driver for a platform */ extern const char joy_stddrv[]; /* The address of the static standard joystick driver for a platform */ extern const void joy_static_stddrv[]; /*****************************************************************************/ /* Functions */ /*****************************************************************************/ unsigned char __fastcall__ joy_load_driver (const char* driver); /* Load and install a joystick driver. Return an error code. */ unsigned char joy_unload (void); /* Uninstall, then unload the currently loaded driver. */ unsigned char __fastcall__ joy_install (void* driver); /* Install an already loaded driver. Return an error code. */ unsigned char joy_uninstall (void); /* Uninstall the currently loaded driver and return an error code. ** Note: This call does not free allocated memory. */ unsigned char joy_count (void); /* Return the number of joysticks supported by the driver */ unsigned char __fastcall__ joy_read (unsigned char joystick); /* Read a particular joystick */ /* End of joystick.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/joystick/�������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015467�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/joystick/joy-kernel.h�������������������������������������������������������������0000664�0000000�0000000�00000007556�13473601511�0017734�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* joy-kernel.h */ /* */ /* Internally used joystick functions */ /* */ /* */ /* */ /* (C) 2002-2006, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _JOY_KERNEL_H #define _JOY_KERNEL_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* A structure that describes the header of a joystick driver loaded into ** memory. */ typedef struct { /* Driver header */ char id[3]; /* Contains 0x6a, 0x6f, 0x79 ("joy") */ unsigned char version; /* Interface version */ void* libreference; /* Library reference */ /* Jump vectors. Note that these are not C callable */ void* install; /* INSTALL routine */ void* uninstall; /* UNINSTALL routine */ void* count; /* COUNT routine */ void* read; /* READ routine */ } joy_drv_header; /* JOY kernel variables */ extern joy_drv_header* joy_drv; /* Pointer to driver */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ void joy_clear_ptr (void); /* Clear the joy_drv pointer */ /* End of joy-kernel.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/limits.h��������������������������������������������������������������������������0000664�0000000�0000000�00000006112�13473601511�0015302�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* limits.h */ /* */ /* Sizes of integer types */ /* */ /* */ /* */ /* (C) 1998-2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 _LIMITS_H #define _LIMITS_H #define CHAR_BIT 8 #define SCHAR_MIN ((signed char) 0x80) #define SCHAR_MAX 127 #define UCHAR_MAX 255 #define CHAR_MIN 0 #define CHAR_MAX 255 #define SHRT_MIN ((short) 0x8000) #define SHRT_MAX 32767 #define USHRT_MAX 65535U #define INT_MIN ((int) 0x8000) #define INT_MAX 32767 #define UINT_MAX 65535U #define LONG_MAX 2147483647L #define LONG_MIN ((long) 0x80000000) #define ULONG_MAX 4294967295UL /* End of limits.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/locale.h��������������������������������������������������������������������������0000664�0000000�0000000�00000007111�13473601511�0015240�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* locale.h */ /* */ /* Localization <locale.h> */ /* */ /* */ /* */ /* (C) 1998-2005 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _LOCALE_H #define _LOCALE_H /* NULL pointer */ #ifndef _HAVE_NULL #define NULL 0 #define _HAVE_NULL #endif /* Locale information constants */ #define LC_ALL 0 #define LC_COLLATE 1 #define LC_CTYPE 2 #define LC_MONETARY 3 #define LC_NUMERIC 4 #define LC_TIME 5 /* Struct containing locale settings */ struct lconv { char* currency_symbol; char* decimal_point; char* grouping; char* int_curr_symbol; char* mon_decimal_point; char* mon_grouping; char* mon_thousands_sep; char* negative_sign; char* positive_sign; char* thousands_sep; char frac_digits; char int_frac_digits; char n_cs_precedes; char n_sep_by_space; char n_sign_posn; char p_cs_precedes; char p_sep_by_space; char p_sign_posn; }; /* Function prototypes */ struct lconv* localeconv (void); char* __fastcall__ setlocale (int category, const char* locale); /* End of locale.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/lynx.h����������������������������������������������������������������������������0000664�0000000�0000000�00000020561�13473601511�0014777�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* lynx.h */ /* */ /* Lynx system-specific definitions */ /* */ /* */ /* */ /* (C) 2003 Shawn Jefferson */ /* */ /* Adapted with many changes Ullrich von Bassewitz, 2004-10-09 */ /* */ /* */ /* */ /* 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 _LYNX_H #define _LYNX_H /* Check for errors */ #if !defined(__LYNX__) # error This module may only be used when compiling for the Lynx game console! #endif /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Color defines */ #define COLOR_BLACK 0x00 #define COLOR_RED 0x01 #define COLOR_PINK 0x02 #define COLOR_LIGHTGREY 0x03 #define COLOR_GREY 0x04 #define COLOR_DARKGREY 0x05 #define COLOR_BROWN 0x06 #define COLOR_PEACH 0x07 #define COLOR_YELLOW 0x08 #define COLOR_LIGHTGREEN 0x09 #define COLOR_GREEN 0x0A #define COLOR_DARKBROWN 0x0B #define COLOR_VIOLET 0x0C #define COLOR_BLUE 0x0D #define COLOR_LIGHTBLUE 0x0E #define COLOR_WHITE 0x0F /* TGI color defines (default palette) */ #define TGI_COLOR_BLACK COLOR_BLACK #define TGI_COLOR_RED COLOR_RED #define TGI_COLOR_PINK COLOR_PINK #define TGI_COLOR_LIGHTGREY COLOR_LIGHTGREY #define TGI_COLOR_GREY COLOR_GREY #define TGI_COLOR_DARKGREY COLOR_DARKGREY #define TGI_COLOR_BROWN COLOR_BROWN #define TGI_COLOR_PEACH COLOR_PEACH #define TGI_COLOR_YELLOW COLOR_YELLOW #define TGI_COLOR_LIGHTGREEN COLOR_LIGHTGREEN #define TGI_COLOR_GREEN COLOR_GREEN #define TGI_COLOR_DARKBROWN COLOR_DARKBROWN #define TGI_COLOR_VIOLET COLOR_VIOLET #define TGI_COLOR_BLUE COLOR_BLUE #define TGI_COLOR_LIGHTBLUE COLOR_LIGHTBLUE #define TGI_COLOR_WHITE COLOR_WHITE /* Masks for joy_read */ #define JOY_UP_MASK 0x80 #define JOY_DOWN_MASK 0x40 #define JOY_LEFT_MASK 0x20 #define JOY_RIGHT_MASK 0x10 #define JOY_BTN_1_MASK 0x01 #define JOY_BTN_2_MASK 0x02 #define JOY_BTN_A_MASK JOY_BTN_1_MASK #define JOY_BTN_B_MASK JOY_BTN_2_MASK #define JOY_BTN_A(v) ((v) & JOY_BTN_A_MASK) #define JOY_BTN_B(v) ((v) & JOY_BTN_B_MASK) /* No support for dynamically loadable drivers */ #define DYN_DRV 0 /*****************************************************************************/ /* Variables */ /*****************************************************************************/ /* The addresses of the static drivers */ extern void lynx_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */ extern void lynx_comlynx_ser[]; extern void lynx_160_102_16_tgi[]; /* Referred to by tgi_static_stddrv[] */ /*****************************************************************************/ /* Sound support */ /*****************************************************************************/ void lynx_snd_init (void); /* Initialize the sound driver */ void lynx_snd_pause (void); /* Pause sound */ 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); /* Stop sound on all channels */ void __fastcall__ lynx_snd_stop_channel (unsigned char channel); /* Stop sound on all channels */ unsigned char lynx_snd_active(void); /* Show which channels are active */ /*****************************************************************************/ /* Accessing the cart */ /*****************************************************************************/ void __fastcall__ lynx_load (int fileno); /* Load a file into ram. The first entry is fileno=0. */ void __fastcall__ lynx_exec (int fileno); /* Load a file into ram and execute it. */ /*****************************************************************************/ /* Accessing the EEPROM */ /*****************************************************************************/ unsigned __fastcall__ lynx_eeprom_read (unsigned char cell); /* Read a 16 bit word from the given address */ unsigned __fastcall__ lynx_eeprom_write (unsigned char cell, unsigned val); /* Write the word at the given address */ void __fastcall__ lynx_eeprom_erase (unsigned char cell); /* Clear the word at the given address */ unsigned __fastcall__ lynx_eeread (unsigned cell); /* Read a 16 bit word from the given address 93C46 93C66 or 93C86*/ unsigned __fastcall__ lynx_eewrite (unsigned cell, unsigned val); /* Write the word at the given address 93C46 93C66 or 93C86*/ /*****************************************************************************/ /* TGI extras */ /*****************************************************************************/ #define tgi_sprite(spr) tgi_ioctl(0, spr) #define tgi_flip() tgi_ioctl(1, (void*)0) #define tgi_setbgcolor(bgcol) tgi_ioctl(2, (void*)(bgcol)) #define tgi_setframerate(rate) tgi_ioctl(3, (void*)(rate)) #define tgi_busy() tgi_ioctl(4, (void*)0) #define tgi_updatedisplay() tgi_ioctl(4, (void*)1) #define tgi_setcollisiondetection(active) tgi_ioctl(5, (void*)(active)) /* Define Hardware */ #include <_mikey.h> #define MIKEY (*(struct __mikey *)0xFD00) #define _MIKEY_TIMERS (*(struct _mikey_all_timers *) 0xFD00) // mikey_timers[8] #define _HBL_TIMER (*(struct _mikey_timer *) 0xFD00) // timer0 (HBL) #define _VBL_TIMER (*(struct _mikey_timer *) 0xFD08) // timer2 (VBL) #define _UART_TIMER (*(struct _mikey_timer *) 0xFD14) // timer4 (UART) #define _VIDDMA (*(unsigned int *) 0xFD92) // dispctl/viddma #include <_suzy.h> #define SUZY (*(struct __suzy*)0xFC00) /* End of lynx.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/lz4.h�����������������������������������������������������������������������������0000664�0000000�0000000�00000005121�13473601511�0014511�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* lz4.h */ /* */ /* Decompression routine for the 'lz4' format */ /* */ /* */ /* */ /* (C) 2017 Mega Cat Studios */ /* */ /* 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 _LZ4_H #define _LZ4_H void __fastcall__ decompress_lz4 (const unsigned char* src, unsigned char* const dst, const unsigned short uncompressed_size); /* Decompresses the source buffer into the destination buffer. ** The size of the decompressed data must be known in advance, LZ4 ** does not include any terminator in-stream. */ /* end of lz4.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/modload.h�������������������������������������������������������������������������0000664�0000000�0000000�00000011566�13473601511�0015431�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* modload.h */ /* */ /* o65 module loader interface for cc65 */ /* */ /* */ /* */ /* (C) 2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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. */ /* */ /*****************************************************************************/ /* Exports structures and functions to load relocatable o65 modules at ** runtime. */ #ifndef _MODLOAD_H #define _MODLOAD_H /* The following struct is passed to the module loader. It contains stuff, ** the loader needs to work, and another area where the loader will place ** informational data if it was successful. You will have to check the return ** code of mod_load before accessing any of these additional struct members. */ struct mod_ctrl { /* Parameters passed into the loader routine. The member callerdata ** is an opaque 16 bit datatype that may be used by the caller to ** pass data through to the read routine. The read routine is used by the ** loader to load any required data. There are several calls where the ** read routine is passed a count of 1, so you may choose to make this ** a special case when implementing read(). The read() should return the ** number of bytes actually read. If the return value differs from the ** passed count, this is considered an error. ** NOTE: read() is designed so that the POSIX read() routine can be used ** for this vector, if you're loading from disk. */ int __fastcall__ (*read) (int callerdata, void* buffer, unsigned count); int callerdata; /* Parameters set by the loader routine */ void* module; /* Pointer to module data */ unsigned module_size; /* Total size of loaded module */ unsigned module_id; /* Module id */ }; unsigned char __fastcall__ mod_load (struct mod_ctrl* ctrl); /* Load a module into memory and relocate it. The function will return an ** error code (see below). If MLOAD_OK is returned, the outgoing fields in ** the passed mod_ctrl struct contain information about the module just ** loaded. */ void __fastcall__ mod_free (void* module); /* Free a loaded module. Note: The given pointer is the pointer to the ** module memory, not a pointer to a control structure. */ /* Errors */ #define MLOAD_OK 0 /* Module load successful */ #define MLOAD_ERR_READ 1 /* Read error */ #define MLOAD_ERR_HDR 2 /* Header error */ #define MLOAD_ERR_OS 3 /* Wrong OS */ #define MLOAD_ERR_FMT 4 /* Data format error */ #define MLOAD_ERR_MEM 5 /* Not enough memory */ /* End of modload.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/mouse.h���������������������������������������������������������������������������0000664�0000000�0000000�00000021146�13473601511�0015135�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* mouse.h */ /* */ /* Mouse API */ /* */ /* */ /* */ /* (C) 2003-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _MOUSE_H #define _MOUSE_H /*****************************************************************************/ /* Definitions */ /*****************************************************************************/ /* Error codes */ #define MOUSE_ERR_OK 0 /* No error */ #define MOUSE_ERR_NO_DRIVER 1 /* No driver available */ #define MOUSE_ERR_CANNOT_LOAD 2 /* Error loading driver */ #define MOUSE_ERR_INV_DRIVER 3 /* Invalid driver */ #define MOUSE_ERR_NO_DEVICE 4 /* Mouse hardware not found */ #define MOUSE_ERR_INV_IOCTL 5 /* Invalid ioctl code */ /* Mouse button masks */ #define MOUSE_BTN_LEFT 0x10 #define MOUSE_BTN_RIGHT 0x01 /* Structure containing the mouse coordinates */ struct mouse_pos { int x; int y; }; /* Structure containing information about the mouse */ struct mouse_info { struct mouse_pos pos; /* Mouse position */ unsigned char buttons; /* Mouse button mask */ }; /* Structure used for getbox/setbox */ struct mouse_box { int minx; int miny; int maxx; int maxy; }; /* Structure containing mouse callback functions. These functions are declared ** in C notation here, but they cannot be C functions (at least not easily), ** since they may be called from within an interrupt. */ struct mouse_callbacks { void (*hide) (void); /* Hide the mouse cursor. */ void (*show) (void); /* Show the mouse cursor. */ void (*prep) (void); /* Prepare to move the mouse cursor. This function is called, ** even when the cursor is currently invisible. */ void (*draw) (void); /* Draw the mouse cursor. This function is called, ** even when the cursor is currently invisible. */ void __fastcall__ (*movex) (int x); /* Move the mouse cursor to the new X coordinate. This function is called, ** even when the cursor is currently invisible. */ void __fastcall__ (*movey) (int y); /* Move the mouse cursor to the new Y coordinate. This function is called, ** even when the cursor is currently invisible. */ }; /*****************************************************************************/ /* Declarations */ /*****************************************************************************/ /* 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[]; /* The address of the static standard mouse driver for a platform */ extern const void mouse_static_stddrv[]; /*****************************************************************************/ /* Functions */ /*****************************************************************************/ unsigned char __fastcall__ mouse_load_driver (const struct mouse_callbacks* c, const char* driver); /* Load and install a mouse driver, return an error code. */ unsigned char mouse_unload (void); /* Uninstall, then unload the currently loaded driver. */ unsigned char __fastcall__ mouse_install (const struct mouse_callbacks* c, void* driver); /* Install an already loaded driver. Return an error code. */ unsigned char mouse_uninstall (void); /* Uninstall the currently loaded driver. Return an error code. */ const char* __fastcall__ mouse_geterrormsg (unsigned char code); /* Get an error message describing the error in code. */ void mouse_hide (void); /* Hide the mouse. The function manages a counter and may be called more than ** once. For each call to mouse_hide there must be a call to mouse_show to make ** the mouse visible again. */ void mouse_show (void); /* Show the mouse. See mouse_hide() for more information. */ void __fastcall__ mouse_setbox (const struct mouse_box* box); /* Set the bounding box for the mouse pointer movement. The mouse X and Y ** coordinates will never go outside the given box. ** NOTE: The function does *not* check if the mouse is currently inside the ** given margins. The proper way to use this function therefore is: ** ** - Hide the mouse ** - Set the bounding box ** - Place the mouse at the desired position ** - Show the mouse again. ** ** NOTE2: When setting the box to something that is larger than the actual ** screen, the positioning of the mouse cursor can fail. If such margins ** are really what you want, you have to use your own cursor routines. */ void __fastcall__ mouse_getbox (struct mouse_box* box); /* Get the current bounding box for the mouse pointer movement. */ void __fastcall__ mouse_move (int x, int y); /* Set the mouse cursor to the given position. If a mouse cursor is defined ** and currently visible, the mouse cursor is also moved. ** NOTE: This function does not check if the given position is valid and ** inside the bounding box. */ unsigned char mouse_buttons (void); /* Return a bit mask encoding the states of the mouse buttons. Use the ** MOUSE_BTN_XXX flags to decode a specific button. */ void __fastcall__ mouse_pos (struct mouse_pos* pos); /* Return the current mouse position. */ void __fastcall__ mouse_info (struct mouse_info* info); /* Return the state of the mouse buttons and the position of the mouse. */ unsigned char __fastcall__ mouse_ioctl (unsigned char code, void* data); /* Call the driver-specific ioctl function. Return an error code. ** NON-PORTABLE! */ /* End of mouse.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/mouse/����������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014760�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/mouse/mouse-kernel.h��������������������������������������������������������������0000664�0000000�0000000�00000006344�13473601511�0017546�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* mouse-kernel.h */ /* */ /* Internally used mouse functions */ /* */ /* */ /* */ /* (C) 2003-2006, Ullrich von Bassewitz */ /* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _MOUSE_KERNEL_H #define _MOUSE_KERNEL_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Mouse kernel variables */ extern void* mouse_drv; /* Pointer to driver */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ void mouse_clear_ptr (void); /* Clear the mouse_drv pointer */ /* End of mouse-kernel.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/nes.h�����������������������������������������������������������������������������0000664�0000000�0000000�00000015220�13473601511�0014566�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* nes.h */ /* */ /* NES system specific definitions */ /* */ /* */ /* */ /* (C) 2002-2003 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 _NES_H #define _NES_H /* Check for errors */ #if !defined(__NES__) # error This module may only be used when compiling for the NES! #endif /* Key and character defines */ #define CH_ENTER '\n' #define CH_CURS_UP 0x01 #define CH_CURS_DOWN 0x02 #define CH_CURS_LEFT 0x03 #define CH_CURS_RIGHT 0x04 #define CH_ESC 8 #define CH_DEL 20 #define CH_CROSS 0x10 #define CH_RTEE 0x17 #define CH_LTEE 0x0f #define CH_TTEE 0x16 #define CH_BTEE 0x15 #define CH_HLINE 0x0b #define CH_VLINE 0x0e #define CH_ULCORNER 0x14 #define CH_URCORNER 0x12 #define CH_LLCORNER 0x11 #define CH_LRCORNER 0x08 #define CH_PI 0x05 /* Color defines */ #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 /* Masks for joy_read */ #define JOY_UP_MASK 0x10 #define JOY_DOWN_MASK 0x20 #define JOY_LEFT_MASK 0x40 #define JOY_RIGHT_MASK 0x80 #define JOY_BTN_1_MASK 0x01 #define JOY_BTN_2_MASK 0x02 #define JOY_BTN_3_MASK 0x04 #define JOY_BTN_4_MASK 0x08 #define JOY_BTN_A_MASK JOY_BTN_1_MASK #define JOY_BTN_B_MASK JOY_BTN_2_MASK #define JOY_SELECT_MASK JOY_BTN_3_MASK #define JOY_START_MASK JOY_BTN_4_MASK #define JOY_BTN_A(v) ((v) & JOY_BTN_A_MASK) #define JOY_BTN_B(v) ((v) & JOY_BTN_B_MASK) #define JOY_SELECT(v) ((v) & JOY_SELECT_MASK) #define JOY_START(v) ((v) & JOY_START_MASK) /* Return codes of get_tv */ #define TV_NTSC 0 #define TV_PAL 1 #define TV_OTHER 2 /* No support for dynamically loadable drivers */ #define DYN_DRV 0 /* 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[] */ extern void nes_64_56_2_tgi[]; /* Referred to by tgi_static_stddrv[] */ void waitvsync (void); /* Wait for start of the next frame */ unsigned char get_tv (void); /* Return the video mode the machine is using. */ /* End of nes.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/o65.h�����������������������������������������������������������������������������0000664�0000000�0000000�00000017500�13473601511�0014415�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* o65.h */ /* */ /* Definitions for the o65 file format */ /* */ /* */ /* */ /* (C) 2002-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* This files exports structures and constants to handle the o65 relocatable ** file format as defined by Andre Fachat. See the original document under ** ** http://www.6502.org/users/andre/o65/fileformat.html ** ** for more information. */ #ifndef _O65_H #define _O65_H /* o65 size type. It is 2 bytes for the 6502 and 4 bytes for the 65816 */ typedef unsigned o65_size; /* Structure that defines the o65 file header */ typedef struct o65_header o65_header; struct o65_header { char marker[2]; /* Non-C64 marker */ char magic[3]; /* o65 magic */ char version; /* Version number */ unsigned mode; /* Mode word */ o65_size tbase; /* Original text (code) segment address */ o65_size tlen; /* Size of text (code) segment */ o65_size dbase; /* Original data segment address */ o65_size dlen; /* Size of data segment */ o65_size bbase; /* Original bss segment address */ o65_size blen; /* Size of bss segment */ o65_size zbase; /* Original zp segment address */ o65_size zlen; /* Size of zp segment */ o65_size stack; /* Stacksize needed */ }; /* Marker, magic and version number */ #define O65_MARKER_0 0x01 #define O65_MARKER_1 0x00 #define O65_MAGIC_0 0x6F /* 'o' */ #define O65_MAGIC_1 0x36 /* '6' */ #define O65_MAGIC_2 0x35 /* '5' */ #define O65_VERSION 0x00 /* Defines for the mode word */ #define O65_CPU_65816 0x8000 /* Executable is for 65816 */ #define O65_CPU_6502 0x0000 /* Executable is for the 6502 */ #define O65_CPU_MASK 0x8000 /* Mask to extract CPU type */ #define O65_RELOC_PAGE 0x4000 /* Page wise relocation */ #define O65_RELOC_BYTE 0x0000 /* Byte wise relocation */ #define O65_RELOC_MASK 0x4000 /* Mask to extract relocation type */ #define O65_SIZE_32BIT 0x2000 /* All size words are 32bit */ #define O65_SIZE_16BIT 0x0000 /* All size words are 16bit */ #define O65_SIZE_MASK 0x2000 /* Mask to extract size */ #define O65_FTYPE_OBJ 0x1000 /* Object file */ #define O65_FTYPE_EXE 0x0000 /* Executable file */ #define O65_FTYPE_MASK 0x1000 /* Mask to extract type */ #define O65_ADDR_SIMPLE 0x0800 /* Simple addressing */ #define O65_ADDR_DEFAULT 0x0000 /* Default addressing */ #define O65_ADDR_MASK 0x0800 /* Mask to extract addressing */ #define O65_CHAIN 0x0400 /* Chained file, another one follows */ #define O65_CHAIN_MASK 0x0400 /* Mask to extract chain flag */ #define O65_BSSZERO 0x0200 /* BSS segment must be zeroed */ #define O65_BSSZERO_MASK 0x0200 /* Mask to extract bss zero flag */ /* The following is used if O65_CPU == 6502 */ #define O65_CPU2_6502 0x0000 /* Executable is for 6502 */ #define O65_CPU2_65C02 0x0010 /* Executable is for 65C02 */ #define O65_CPU2_65SC02 0x0020 /* Executable is for 65SC02 */ #define O65_CPU2_65CE02 0x0030 /* Executable is for 65CE02 */ #define O65_CPU2_6502X 0x0040 /* Executable is for NMOS 6502 */ #define O65_CPU2_65816_EMU 0x0050 /* Executable is for 65816 in emul mode */ #define O65_CPU2_MASK 0x00F0 /* Mask to extract CPU2 field */ #define O65_ALIGN_1 0x0000 /* Bytewise alignment */ #define O65_ALIGN_2 0x0001 /* Align words */ #define O65_ALIGN_4 0x0002 /* Align longwords */ #define O65_ALIGN_256 0x0003 /* Align pages (256 bytes) */ #define O65_ALIGN_MASK 0x0003 /* Mask to extract alignment */ /* The mode word as generated by the ld65 linker */ #define O65_MODE_CC65 (O65_CPU_6502 | \ O65_RELOC_BYTE | \ O65_SIZE_16BIT | \ O65_FTYPE_EXE | \ O65_ADDR_SIMPLE | \ O65_ALIGN_1) /* The four o65 segment types. */ #define O65_SEGID_UNDEF 0x00 #define O65_SEGID_ABS 0x01 #define O65_SEGID_TEXT 0x02 #define O65_SEGID_DATA 0x03 #define O65_SEGID_BSS 0x04 #define O65_SEGID_ZP 0x05 #define O65_SEGID_MASK 0x07 /* Relocation type codes */ #define O65_RTYPE_WORD 0x80 #define O65_RTYPE_HIGH 0x40 #define O65_RTYPE_LOW 0x20 #define O65_RTYPE_SEGADDR 0xC0 #define O65_RTYPE_SEG 0xA0 #define O65_RTYPE_MASK 0xE0 /* Segment IDs */ #define O65_SEGID_UNDEF 0x00 #define O65_SEGID_ABS 0x01 #define O65_SEGID_TEXT 0x02 #define O65_SEGID_DATA 0x03 #define O65_SEGID_BSS 0x04 #define O65_SEGID_ZP 0x05 #define O65_SEGID_MASK 0x07 /* Option tags */ #define O65_OPT_FILENAME 0 #define O65_OPT_OS 1 #define O65_OPT_ASM 2 #define O65_OPT_AUTHOR 3 #define O65_OPT_TIMESTAMP 4 /* Operating system codes for O65_OPT_OS */ #define O65_OS_OSA65 1 #define O65_OS_LUNIX 2 #define O65_OS_CC65 3 #define O65_OS_OPENCBM 4 /* End of o65.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/osic1p.h��������������������������������������������������������������������������0000664�0000000�0000000�00000005357�13473601511�0015211�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* osic1p.h */ /* */ /* Challenger 1P system specific definitions */ /* */ /* */ /* */ /* (C) 2015 Stephan Muehlstrasser */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _OSIC1P_H #define _OSIC1P_H /* Check for errors */ #if !defined(__OSIC1P__) # error "This module may only be used when compiling for the Challenger 1P!" #endif /* The following #defines will cause the matching functions calls in conio.h ** to be overlaid by macros with the same names, saving the function call ** overhead. */ #define _textcolor(color) COLOR_WHITE #define _bgcolor(color) COLOR_BLACK #define _bordercolor(color) COLOR_BLACK #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/pce.h�����������������������������������������������������������������������������0000664�0000000�0000000�00000011307�13473601511�0014552�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* 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 /* Masks for joy_read */ #define JOY_UP_MASK 0x10 #define JOY_DOWN_MASK 0x40 #define JOY_LEFT_MASK 0x80 #define JOY_RIGHT_MASK 0x20 #define JOY_BTN_1_MASK 0x01 #define JOY_BTN_2_MASK 0x02 #define JOY_BTN_3_MASK 0x04 #define JOY_BTN_4_MASK 0x08 #define JOY_BTN_I_MASK JOY_BTN_1_MASK #define JOY_BTN_II_MASK JOY_BTN_2_MASK #define JOY_SELECT_MASK JOY_BTN_3_MASK #define JOY_RUN_MASK JOY_BTN_4_MASK #define JOY_BTN_I(v) ((v) & JOY_BTN_I_MASK) #define JOY_BTN_II(v) ((v) & JOY_BTN_II_MASK) #define JOY_SELECT(v) ((v) & JOY_SELECT_MASK) #define JOY_RUN(v) ((v) & JOY_RUN_MASK) /* 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[] */ void waitvsync (void); /* Wait for start of the next frame */ /* NOTE: all PCEs are NTSC. */ #define get_tv() TV_NTSC /* Return the video mode the machine is using. */ /* End of pce.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/peekpoke.h������������������������������������������������������������������������0000664�0000000�0000000�00000006044�13473601511�0015610�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* peekpoke.h */ /* */ /* PEEK and POKE macros for those who want to write BASIC code in C */ /* */ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _PEEKPOKE_H #define _PEEKPOKE_H /*****************************************************************************/ /* Macros */ /*****************************************************************************/ #define POKE(addr,val) (*(unsigned char*) (addr) = (val)) #define POKEW(addr,val) (*(unsigned*) (addr) = (val)) #define PEEK(addr) (*(unsigned char*) (addr)) #define PEEKW(addr) (*(unsigned*) (addr)) /* End of peekpoke.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/pen.h�����������������������������������������������������������������������������0000664�0000000�0000000�00000007164�13473601511�0014573�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* pen.h */ /* */ /* Lightpen API */ /* */ /* */ /* 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 marked plainly 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 _PEN_H #define _PEN_H /*****************************************************************************/ /* Declarations */ /*****************************************************************************/ /* A program optionally can set this pointer to a function that gives ** a calibration value to a driver. If this pointer isn't NULL, ** then a driver that wants a value can call that function. ** pen_adjuster must be set before the driver is installed. */ extern void __fastcall__ (*pen_adjuster) (unsigned char *pValue); /*****************************************************************************/ /* Functions */ /*****************************************************************************/ void __fastcall__ pen_calibrate (unsigned char *XOffset); /* Ask the user to help to calibrate a lightpen. Changes the screen! ** A pointer to this function can be put into pen_adjuster. */ void __fastcall__ pen_adjust (const char *filename); /* Get a lightpen calibration value from a file if it exists. Otherwise, call ** pen_calibrate() to create a value; then, write it into a file, so that it ** will be available at the next time that the lightpen is used. ** Might change the screen. ** pen_adjust() is optional; if you want to use its feature, ** then it must be called before a driver is installed. ** Note: This function merely saves the file-name pointer, and sets ** the pen_adjuster pointer. The file will be read only when a driver ** is installed, and only if that driver wants to be calibrated. */ /* End of pen.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/pet.h�����������������������������������������������������������������������������0000664�0000000�0000000�00000011047�13473601511�0014574�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* pet.h */ /* */ /* PET system specific definitions */ /* */ /* */ /* */ /* (C) 1998-2005 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _PET_H #define _PET_H /* Check for errors */ #if !defined(__PET__) # error This module may only be used when compiling for the CBM PET! #endif /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Color defines */ #define COLOR_BLACK 0x00 #define COLOR_WHITE 0x01 /* Masks for joy_read */ #define JOY_UP_MASK 0x01 #define JOY_DOWN_MASK 0x02 #define JOY_LEFT_MASK 0x04 #define JOY_RIGHT_MASK 0x08 #define JOY_BTN_1_MASK 0x10 /* Define hardware */ #include <_pia.h> #define PIA1 (*(struct __pia*)0xE810) #define PIA2 (*(struct __pia*)0xE820) #include <_6522.h> #define VIA (*(struct __6522*)0xE840) /* All models from 40xx and above */ #include <_6545.h> #define CRTC (*(struct __6545)0xE880) /* SuperPET only */ #include <_6551.h> #define ACIA (*(struct __6551*)0xEFF0) /*****************************************************************************/ /* Variables */ /*****************************************************************************/ /* The addresses of the static drivers */ extern void pet_ptvjoy_joy[]; extern void pet_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ /* The following #defines will cause the matching functions calls in conio.h ** to be overlaid by macros with the same names, saving the function call ** overhead. */ #define _textcolor(color) COLOR_WHITE #define _bgcolor(color) COLOR_BLACK #define _bordercolor(color) COLOR_BLACK #define _cpeekcolor(color) COLOR_WHITE /* End of pet.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/plus4.h���������������������������������������������������������������������������0000664�0000000�0000000�00000005774�13473601511�0015065�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* plus4.h */ /* */ /* Plus/4 system specific definitions */ /* */ /* */ /* */ /* (C) 1998-2006, Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _PLUS4_H #define _PLUS4_H /* Check for errors */ #if !defined(__PLUS4__) # error This module may only be used when compiling for the Plus/4! #endif /* Include the base header file for the 264 series. */ #include <cbm264.h> /* Define hardware */ #include <_6551.h> #define ACIA (*(struct __6551*)0xFD00) /* The addresses of the static drivers */ extern void plus4_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */ extern void plus4_stdser_ser[]; /* End of plus4.h */ #endif ����cc65-2.18/include/serial.h��������������������������������������������������������������������������0000664�0000000�0000000�00000017333�13473601511�0015267�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* serial.h */ /* */ /* Serial communication API */ /* */ /* */ /* */ /* (C) 2003-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _SERIAL_H #define _SERIAL_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Baudrate settings */ #define SER_BAUD_45_5 0x00 #define SER_BAUD_50 0x01 #define SER_BAUD_75 0x02 #define SER_BAUD_110 0x03 #define SER_BAUD_134_5 0x04 #define SER_BAUD_150 0x05 #define SER_BAUD_300 0x06 #define SER_BAUD_600 0x07 #define SER_BAUD_1200 0x08 #define SER_BAUD_1800 0x09 #define SER_BAUD_2400 0x0A #define SER_BAUD_3600 0x0B #define SER_BAUD_4800 0x0C #define SER_BAUD_7200 0x0D #define SER_BAUD_9600 0x0E #define SER_BAUD_19200 0x0F #define SER_BAUD_38400 0x10 #define SER_BAUD_57600 0x11 #define SER_BAUD_115200 0x12 #define SER_BAUD_230400 0x13 #define SER_BAUD_31250 0x14 #define SER_BAUD_62500 0x15 #define SER_BAUD_56_875 0x16 /* Data bit settings */ #define SER_BITS_5 0x00 #define SER_BITS_6 0x01 #define SER_BITS_7 0x02 #define SER_BITS_8 0x03 /* Stop bit settings */ #define SER_STOP_1 0x00 /* One stop bit */ #define SER_STOP_2 0x01 /* Two stop bits */ /* Parity settings */ #define SER_PAR_NONE 0x00 #define SER_PAR_ODD 0x01 #define SER_PAR_EVEN 0x02 #define SER_PAR_MARK 0x03 #define SER_PAR_SPACE 0x04 /* Handshake settings. The latter two may be combined. */ #define SER_HS_NONE 0x00 /* No handshake */ #define SER_HS_HW 0x01 /* Hardware (RTS/CTS) handshake */ #define SER_HS_SW 0x02 /* Software handshake */ /* Bit masks to mask out things from the status returned by ser_status. ** These are 6551 specific and must be mapped by drivers for other chips. */ #define SER_STATUS_PE 0x01 /* Parity error */ #define SER_STATUS_FE 0x02 /* Framing error */ #define SER_STATUS_OE 0x04 /* Overrun error */ #define SER_STATUS_DCD 0x20 /* NOT data carrier detect */ #define SER_STATUS_DSR 0x40 /* NOT data set ready */ /* Error codes returned by all functions */ #define SER_ERR_OK 0x00 /* Not an error - relax */ #define SER_ERR_NO_DRIVER 0x01 /* No driver available */ #define SER_ERR_CANNOT_LOAD 0x02 /* Error loading driver */ #define SER_ERR_INV_DRIVER 0x03 /* Invalid driver */ #define SER_ERR_NO_DEVICE 0x04 /* Device (hardware) not found */ #define SER_ERR_BAUD_UNAVAIL 0x05 /* Baud rate not available */ #define SER_ERR_NO_DATA 0x06 /* Nothing to read */ #define SER_ERR_OVERFLOW 0x07 /* No room in send buffer */ #define SER_ERR_INIT_FAILED 0x08 /* Initialization failed */ #define SER_ERR_INV_IOCTL 0x09 /* IOCTL not supported */ #define SER_ERR_INSTALLED 0x0A /* A driver is already installed */ #define SER_ERR_NOT_OPEN 0x0B /* Driver is not open */ /* Struct containing parameters for the serial port */ struct ser_params { unsigned char baudrate; /* Baudrate */ unsigned char databits; /* Number of data bits */ unsigned char stopbits; /* Number of stop bits */ unsigned char parity; /* Parity setting */ unsigned char handshake; /* Type of handshake to use */ }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned char __fastcall__ ser_load_driver (const char* driver); /* Load and install a serial driver. Return an error code. */ unsigned char ser_unload (void); /* Uninstall, then unload the currently loaded driver. */ unsigned char __fastcall__ ser_install (void* driver); /* Install an already loaded driver. Return an error code. */ unsigned char ser_uninstall (void); /* Uninstall the currently loaded driver and return an error code. ** Note: This call does not free allocated memory. */ unsigned char __fastcall__ ser_open (const struct ser_params* params); /* "Open" the port by setting the port parameters and enable interrupts. */ unsigned char ser_close (void); /* "Close" the port. Clear buffers and and disable interrupts. */ unsigned char __fastcall__ ser_get (char* b); /* 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. */ unsigned char __fastcall__ ser_put (char b); /* 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. */ unsigned char __fastcall__ ser_status (unsigned char* status); /* Return the serial port status. */ unsigned char __fastcall__ ser_ioctl (unsigned char code, void* data); /* Driver specific entry. */ /* End of serial.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/setjmp.h��������������������������������������������������������������������������0000664�0000000�0000000�00000005436�13473601511�0015313�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* setjmp.h */ /* */ /* Nonlocal jumps */ /* */ /* */ /* */ /* (C) 1998-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _SETJMP_H #define _SETJMP_H typedef char jmp_buf [5]; int __fastcall__ _setjmp (jmp_buf buf); #define setjmp _setjmp /* ISO insists on a macro */ void __fastcall__ longjmp (jmp_buf buf, int retval) __attribute__((noreturn)); /* End of setjmp.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/signal.h��������������������������������������������������������������������������0000664�0000000�0000000�00000006415�13473601511�0015264�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* signal.h */ /* */ /* Signal handling definitions */ /* */ /* */ /* */ /* (C) 2002-2005, Ullrich von Bassewitz */ /* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _SIGNAL_H #define _SIGNAL_H /* sig_atomic_t */ typedef unsigned char sig_atomic_t; /* Type of a signal handler */ typedef void __fastcall__ (*__sigfunc) (int); /* Functions that implement SIG_IGN and SIG_DFL */ void __fastcall__ _sig_ign (int); void __fastcall__ _sig_dfl (int); /* Standard signal handling functions */ #define SIG_DFL _sig_dfl #define SIG_IGN _sig_ign #define SIG_ERR ((__sigfunc) 0x0000) /* Signal numbers */ #define SIGABRT 0 #define SIGFPE 1 #define SIGILL 2 #define SIGINT 3 #define SIGSEGV 4 #define SIGTERM 5 /* Function declarations */ __sigfunc __fastcall__ signal (int sig, __sigfunc func); int __fastcall__ raise (int sig); /* End of signal.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/stdarg.h��������������������������������������������������������������������������0000664�0000000�0000000�00000005541�13473601511�0015272�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* stdarg.h */ /* */ /* Variable arguments */ /* */ /* */ /* */ /* (C) 1998-2004 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _STDARG_H #define _STDARG_H typedef unsigned char* va_list; #define va_start(ap, fix) ap = ((va_list)&(fix)) #define va_arg(ap,type) (*(type*)(ap -= ((sizeof (type) + 1) & ~1))) #if __CC65_STD__ >= __CC65_STD_C99__ #define va_copy(dest, src) ((dest)=(src)) #endif #define va_end(ap) /* End of stdarg.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/stdbool.h�������������������������������������������������������������������������0000664�0000000�0000000�00000004712�13473601511�0015453�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* stdbool.h */ /* */ /* C99 Boolean definitions */ /* */ /* */ /* */ /* (C) 2002 Greg King */ /* */ /* */ /* 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 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's documentation, */ /* would be appreciated, but is not required. */ /* 2. Alterred source versions must be marked plainly as such, */ /* and must not be misrepresented as being the original software. */ /* 3. This notice may not be removed or alterred */ /* from any source distribution. */ /*****************************************************************************/ #ifndef _STDBOOL_H #define _STDBOOL_H #define bool _Bool typedef unsigned char _Bool; /* Standard test-results. */ #define false 0 #define true 1 /* All three names are macroes. */ #define __bool_true_false_are_defined 1 /* End of stdbool.h */ #endif ������������������������������������������������������cc65-2.18/include/stddef.h��������������������������������������������������������������������������0000664�0000000�0000000�00000005761�13473601511�0015263�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* stddef.h */ /* */ /* Common definitions */ /* */ /* */ /* */ /* (C) 1998-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _STDDEF_H #define _STDDEF_H /* Standard data types */ #ifndef _HAVE_ptrdiff_t #define _HAVE_ptrdiff_t typedef int ptrdiff_t; #endif #ifndef _HAVE_wchar_t #define _HAVE_wchar_t typedef char wchar_t; #endif #ifndef _HAVE_size_t #define _HAVE_size_t typedef unsigned size_t; #endif /* NULL pointer */ #ifndef _HAVE_NULL #define NULL 0 #define _HAVE_NULL #endif /* offsetof macro */ #define offsetof(type, member) (size_t) (&((type*) 0)->member) /* End of stddef.h */ #endif ���������������cc65-2.18/include/stdint.h��������������������������������������������������������������������������0000664�0000000�0000000�00000014064�13473601511�0015313�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* stdint.h */ /* */ /* Standard integer types */ /* */ /* */ /* */ /* (C) 2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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. */ /* */ /*****************************************************************************/ /* Note: This file is not fully ISO 9899-1999 compliant because cc65 lacks ** a 64 bit data types. The declarations have been adjusted accordingly. */ #ifndef _STDINT_H #define _STDINT_H /* Exact-width integer types */ typedef signed char int8_t; typedef int int16_t; typedef long int32_t; typedef unsigned char uint8_t; typedef unsigned uint16_t; typedef unsigned long uint32_t; #define INT8_MIN ((int8_t) 0x80) #define INT8_MAX ((int8_t) 0x7F) #define INT16_MIN ((int16_t) 0x8000) #define INT16_MAX ((int16_t) 0x7FFF) #define INT32_MIN ((int32_t) 0x80000000) #define INT32_MAX ((int32_t) 0x7FFFFFFF) #define UINT8_MAX ((uint8_t) 0xFF) #define UINT16_MAX ((uint16_t) 0xFFFF) #define UINT32_MAX ((uint32_t) 0xFFFFFFFF) /* Minimum-width integer types */ typedef signed char int_least8_t; typedef int int_least16_t; typedef long int_least32_t; typedef unsigned char uint_least8_t; typedef unsigned uint_least16_t; typedef unsigned long uint_least32_t; #define INT_LEAST8_MIN ((int_least8_t) 0x80) #define INT_LEAST8_MAX ((int_least8_t) 0x7F) #define INT_LEAST16_MIN ((int_least16_t) 0x8000) #define INT_LEAST16_MAX ((int_least16_t) 0x7FFF) #define INT_LEAST32_MIN ((int_least32_t) 0x80000000) #define INT_LEAST32_MAX ((int_least32_t) 0x7FFFFFFF) #define UINT_LEAST8_MAX ((uint_least8_t) 0xFF) #define UINT_LEAST16_MAX ((uint_least16_t) 0xFFFF) #define UINT_LEAST32_MAX ((uint_least32_t) 0xFFFFFFFF) /* Fastest minimum-width integer types */ typedef signed char int_fast8_t; typedef int int_fast16_t; typedef long int_fast32_t; typedef unsigned char uint_fast8_t; typedef unsigned uint_fast16_t; typedef unsigned long uint_fast32_t; #define INT_FAST8_MIN ((int_fast8_t) 0x80) #define INT_FAST8_MAX ((int_fast8_t) 0x7F) #define INT_FAST16_MIN ((int_fast16_t) 0x8000) #define INT_FAST16_MAX ((int_fast16_t) 0x7FFF) #define INT_FAST32_MIN ((int_fast32_t) 0x80000000) #define INT_FAST32_MAX ((int_fast32_t) 0x7FFFFFFF) #define UINT_FAST8_MAX ((uint_fast8_t) 0xFF) #define UINT_FAST16_MAX ((uint_fast16_t) 0xFFFF) #define UINT_FAST32_MAX ((uint_fast32_t) 0xFFFFFFFF) /* Integer types capable of holding object pointers */ typedef int intptr_t; typedef unsigned uintptr_t; #define INTPTR_MIN ((intptr_t)0x8000) #define INTPTR_MAX ((intptr_t)0x7FFF) #define UINTPTR_MAX ((uintptr_t) 0xFFFF) /* Greatest width integer types */ typedef long intmax_t; typedef unsigned long uintmax_t; #define INTMAX_MIN ((intmax_t) 0x80000000) #define INTMAX_MAX ((intmax_t) 0x7FFFFFFF) #define UINTMAX_MAX ((uintmax_t) 0xFFFFFFFF) /* Limits of other integer types */ #define PTRDIFF_MIN ((int) 0x8000) #define PTRDIFF_MAX ((int) 0x7FFF) #define SIG_ATOMIC_MIN ((unsigned char) 0x00) #define SIG_ATOMIC_MAX ((unsigned char) 0xFF) #define SIZE_MAX 0xFFFF /* Macros for minimum width integer constants */ #define INT8_C(c) c #define INT16_C(c) c #define INT32_C(c) c##L #define UINT8_C(c) c##U #define UINT16_C(c) c##U #define UINT32_C(c) c##UL /* Macros for greatest width integer constants */ #define INTMAX_C(c) c##L #define UINTMAX_C(c) c##UL /* End of stdint.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/stdio.h���������������������������������������������������������������������������0000664�0000000�0000000�00000014055�13473601511�0015130�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* stdio.h */ /* */ /* Input/output */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _STDIO_H #define _STDIO_H #include <stddef.h> #include <stdarg.h> /* Types */ typedef struct _FILE FILE; typedef unsigned long fpos_t; /* Standard file descriptors */ extern FILE* stdin; extern FILE* stdout; extern FILE* stderr; /* Standard defines */ #define _IOFBF 0 #define _IOLBF 1 #define _IONBF 2 #define BUFSIZ 256 #define EOF -1 #define FOPEN_MAX 8 #define SEEK_CUR 0 #define SEEK_END 1 #define SEEK_SET 2 #define TMP_MAX 256 /* Standard defines that are platform dependent */ #if defined(__APPLE2__) # define FILENAME_MAX (64+1) #elif defined(__ATARI__) # define FILENAME_MAX (12+1) #elif defined(__LUNIX__) # define FILENAME_MAX (80+1) #elif defined(__TELESTRAT__) # define FILENAME_MAX (50+1) #else # define FILENAME_MAX (16+1) #endif #define L_tmpnam FILENAME_MAX /*****************************************************************************/ /* Code */ /*****************************************************************************/ /* Functions */ void __fastcall__ clearerr (FILE* f); int __fastcall__ fclose (FILE* f); int __fastcall__ feof (FILE* f); int __fastcall__ ferror (FILE* f); int __fastcall__ fflush (FILE* f); int __fastcall__ fgetc (FILE* f); char* __fastcall__ fgets (char* buf, size_t size, FILE* f); FILE* __fastcall__ fopen (const char* name, const char* mode); int fprintf (FILE* f, const char* format, ...); int __fastcall__ fputc (int c, FILE* f); int __fastcall__ fputs (const char* s, FILE* f); size_t __fastcall__ fread (void* buf, size_t size, size_t count, FILE* f); FILE* __fastcall__ freopen (const char* name, const char* mode, FILE* f); size_t __fastcall__ fwrite (const void* buf, size_t size, size_t count, FILE* f); int __fastcall__ fgetpos (FILE* f, fpos_t *pos); int __fastcall__ fsetpos (FILE* f, const fpos_t* pos); long __fastcall__ ftell (FILE* f); int __fastcall__ fseek (FILE* f, long offset, int whence); void __fastcall__ rewind (FILE *f); int getchar (void); char* __fastcall__ gets (char* s); void __fastcall__ perror (const char* s); int printf (const char* format, ...); int __fastcall__ putchar (int c); int __fastcall__ puts (const char* s); int __fastcall__ remove (const char* name); int __fastcall__ rename (const char* oldname, const char* newname); int snprintf (char* buf, size_t size, const char* format, ...); int sprintf (char* buf, const char* format, ...); int __fastcall__ ungetc (int c, FILE* f); int __fastcall__ vfprintf (FILE* f, const char* format, va_list ap); int __fastcall__ vprintf (const char* format, va_list ap); int __fastcall__ vsnprintf (char* buf, size_t size, const char* format, va_list ap); int __fastcall__ vsprintf (char* buf, const char* format, va_list ap); int scanf (const char* format, ...); int fscanf (FILE* f, const char* format, ...); int sscanf (const char* s, const char* format, ...); int __fastcall__ vscanf (const char* format, va_list ap); int __fastcall__ vsscanf (const char* s, const char* format, va_list ap); int __fastcall__ vfscanf (FILE* f, const char* format, va_list ap); #if __CC65_STD__ == __CC65_STD_CC65__ FILE* __fastcall__ fdopen (int fd, const char* mode); /* Unix */ int __fastcall__ fileno (FILE* f); /* Unix */ #endif void __fastcall__ _poserror (const char* msg); /* cc65 */ /* Masking macros for some functions */ #define getc(f) fgetc (f) /* ANSI */ #define putc(c, f) fputc (c, f) /* ANSI */ /* End of stdio.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/stdlib.h��������������������������������������������������������������������������0000664�0000000�0000000�00000013164�13473601511�0015267�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* stdlib.h */ /* */ /* General utilities */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _STDLIB_H #define _STDLIB_H /* size_t is needed */ #ifndef _HAVE_size_t typedef unsigned size_t; #define _HAVE_size_t #endif /* Standard exit codes */ #define EXIT_SUCCESS 0 #define EXIT_FAILURE 1 /* Return type of the div function */ typedef struct { int rem; int quot; } div_t; /* Return type of the ldiv function (which currently doesn't exist) */ typedef struct { long rem; long quot; } ldiv_t; /* Memory management */ void* __fastcall__ malloc (size_t size); void* __fastcall__ calloc (size_t count, size_t size); void* __fastcall__ realloc (void* block, size_t size); void __fastcall__ free (void* block); /* Non standard memory management functions */ #if __CC65_STD__ == __CC65_STD_CC65__ int __fastcall__ posix_memalign (void** memptr, size_t alignment, size_t size); /* Allocate a block of memory with the given "size", which is aligned to a ** memory address that is a multiple of "alignment". "alignment" MUST NOT be ** zero, and MUST be a power of two; otherwise, this function will return ** EINVAL. The function returns ENOMEM if not enough memory is available ** to satisfy the request. "memptr" must point to a variable; that variable ** will return the address of the allocated memory. Use free() to release that ** allocated block. */ #endif void __fastcall__ _heapadd (void* mem, size_t size); /* Add a block to the heap */ size_t __fastcall__ _heapblocksize (const void* block); /* Return the size of an allocated block */ size_t _heapmemavail (void); /* Return the total free heap space */ size_t _heapmaxavail (void); /* Return the size of the largest free block on the heap */ /* Random numbers */ #define RAND_MAX 0x7FFF int rand (void); void __fastcall__ srand (unsigned seed); void _randomize (void); /* Non-standard */ /* Other standard stuff */ void abort (void) __attribute__ ((noreturn)); int __fastcall__ abs (int val); long __fastcall__ labs (long val); 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 __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 __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); /* Non-ANSI functions */ void __fastcall__ _swap (void* p, void* q, size_t size); #if __CC65_STD__ == __CC65_STD_CC65__ char* __fastcall__ itoa (int val, char* buf, int radix); char* __fastcall__ utoa (unsigned val, char* buf, int radix); char* __fastcall__ ltoa (long val, char* buf, int radix); char* __fastcall__ ultoa (unsigned long val, char* buf, int radix); int __fastcall__ putenv (char* s); #endif /* End of stdlib.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/string.h��������������������������������������������������������������������������0000664�0000000�0000000�00000011760�13473601511�0015314�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* string.h */ /* */ /* String handling */ /* */ /* */ /* */ /* (C) 1998-2014, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _STRING_H #define _STRING_H #include <stddef.h> char* __fastcall__ strcat (char* dest, const char* src); char* __fastcall__ strchr (const char* s, int c); int __fastcall__ strcmp (const char* s1, const char* s2); int __fastcall__ strcoll (const char* s1, const char* s2); char* __fastcall__ strcpy (char* dest, const char* src); size_t __fastcall__ strcspn (const char* s1, const char* s2); char* __fastcall__ strerror (int errcode); size_t __fastcall__ strlen (const char* s); char* __fastcall__ strncat (char* s1, const char* s2, size_t count); int __fastcall__ strncmp (const char* s1, const char* s2, size_t count); char* __fastcall__ strncpy (char* dest, const char* src, size_t count); char* __fastcall__ strpbrk (const char* str, const char* set); char* __fastcall__ strrchr (const char* s, int c); size_t __fastcall__ strspn (const char* s1, const char* s2); char* __fastcall__ strstr (const char* str, const char* substr); char* __fastcall__ strtok (char* s1, const char* s2); size_t __fastcall__ strxfrm (char* s1, const char* s2, size_t count); void* __fastcall__ memchr (const void* mem, int c, size_t count); int __fastcall__ memcmp (const void* p1, const void* p2, size_t count); void* __fastcall__ memcpy (void* dest, const void* src, size_t count); void* __fastcall__ memmove (void* dest, const void* src, size_t count); void* __fastcall__ memset (void* s, int c, size_t count); /* The following is an internal function, the compiler will replace memset ** with it if the fill value is zero. Never use this one directly! */ void* __fastcall__ _bzero (void* ptr, size_t n); /* Non standard: */ #if __CC65_STD__ == __CC65_STD_CC65__ void __fastcall__ bzero (void* ptr, size_t n); /* BSD */ char* __fastcall__ strdup (const char* s); /* SYSV/BSD */ int __fastcall__ stricmp (const char* s1, const char* s2); /* DOS/Windows */ int __fastcall__ strcasecmp (const char* s1, const char* s2); /* Same for Unix */ int __fastcall__ strnicmp (const char* s1, const char* s2, size_t count); /* DOS/Windows */ int __fastcall__ strncasecmp (const char* s1, const char* s2, size_t count); /* Same for Unix */ char* __fastcall__ strlwr (char* s); char* __fastcall__ strlower (char* s); char* __fastcall__ strupr (char* s); char* __fastcall__ strupper (char* s); char* __fastcall__ strqtok (char* s1, const char* s2); #endif const char* __fastcall__ _stroserror (unsigned char errcode); /* Map an operating system error number to an error message. */ /* End of string.h */ #endif ����������������cc65-2.18/include/supervision.h���������������������������������������������������������������������0000664�0000000�0000000�00000012061�13473601511�0016367�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* supervision.h */ /* */ /* Supervision specific definitions */ /* */ /* */ /* */ /* 2003 Peter Trauner (trap@utanet.at) */ /* */ /* */ /* 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 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's documentation, */ /* would be appreciated, but is not required. */ /* 2. Alterred source versions must be marked plainly as such, */ /* and must not be misrepresented as being the original software. */ /* 3. This notice may not be removed or alterred */ /* from any source distribution. */ /* */ /*****************************************************************************/ #ifndef _SUPERVISION_H #define _SUPERVISION_H /* Check for errors */ #if !defined(__SUPERVISION__) # error This module may only be used when compiling for the Supervision! #endif /*****************************************************************************/ /* Data */ /*****************************************************************************/ struct __sv_lcd { unsigned char width; unsigned char height; unsigned char xpos; unsigned char ypos; }; #define SV_LCD (*(struct __sv_lcd*)0x2000) struct __sv_tone { unsigned delay; unsigned char control; unsigned char timer; }; #define SV_RIGHT (*(struct __sv_tone*)0x2010) #define SV_LEFT (*(struct __sv_tone*)0x2014) struct __sv_noise { unsigned char volume; /* and frequency */ unsigned char timer; unsigned char control; }; #define SV_NOISE (*(struct __sv_noise*)0x2028) struct __io_port { unsigned char in; unsigned char out; }; #define IO_PORT (*(struct __io_port*)0x2021) struct __sv_dma { unsigned start; unsigned char size; unsigned char control; unsigned char on; }; #define SV_DMA (*(struct __sv_dma*)0x2018) #define SV_CONTROL (*(unsigned char*)0x2020) #define SV_BANK (*(unsigned char*)0x2026) #define SV_BANK_COMBINE(nmi,irq_timer,irq_dma,lcd_on, timer_prescale, bank) \ ((nmi)?1:0)|((irq_timer)?2:0)|((irq_dma)?4:0)|((lcd_on)?8:0) \ |((timer_prescale)?0x10:0)|((bank)<<5) #define SV_VIDEO ((unsigned char*)0x4000) #define SV_TIMER_COUNT (*(unsigned char*)0x2023) /* Counters incremented asynchronously! ** If you want more complex, copy the crt0.s file from the libsrc/supervision ** directory and code them yourself (in assembler) */ extern unsigned char sv_nmi_counter; extern unsigned char sv_timer_irq_counter; extern unsigned char sv_timer_dma_counter; /* Masks for joy_read */ #define JOY_UP_MASK 0x08 #define JOY_DOWN_MASK 0x04 #define JOY_LEFT_MASK 0x02 #define JOY_RIGHT_MASK 0x01 #define JOY_BTN_1_MASK 0x20 #define JOY_BTN_2_MASK 0x10 #define JOY_BTN_3_MASK 0x80 #define JOY_BTN_4_MASK 0x40 #define JOY_BTN_A_MASK JOY_BTN_1_MASK #define JOY_BTN_B_MASk JOY_BTN_2_MASK #define JOY_START_MASK JOY_BTN_3_MASK #define JOY_SELECT_MASK JOY_BTN_4_MASK #define JOY_BTN_A(v) ((v) & JOY_BTN_A_MASK) #define JOY_BTN_B(v) ((v) & JOY_BTN_B_MASK) #define JOY_START(v) ((v) & JOY_START_MASK) #define JOY_SELECT(v) ((v) & JOY_SELECT_MASK) /* No support for dynamically loadable drivers */ #define DYN_DRV 0 /* The addresses of the static drivers */ extern void supervision_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */ /* End of supervision.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/sys/������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014446�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/sys/stat.h������������������������������������������������������������������������0000664�0000000�0000000�00000006126�13473601511�0015577�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* stat.h */ /* */ /* Constants for the mode argument of open and creat */ /* */ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _STAT_H #define _STAT_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ #define S_IREAD 0x01 #define S_IWRITE 0x02 /*****************************************************************************/ /* Code */ /*****************************************************************************/ /* End of stat.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/sys/types.h�����������������������������������������������������������������������0000664�0000000�0000000�00000006237�13473601511�0015773�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* types.h */ /* */ /* Primitive system data types for cc65 */ /* */ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _TYPES_H #define _TYPES_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* off_t is also defined in unistd.h */ #ifndef _HAVE_off_t #define _HAVE_off_t typedef long int off_t; #endif /*****************************************************************************/ /* Code */ /*****************************************************************************/ /* End of types.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/sys/utsname.h���������������������������������������������������������������������0000664�0000000�0000000�00000007747�13473601511�0016312�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* utsname.h */ /* */ /* Return system information */ /* */ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _UTSNAME_H #define _UTSNAME_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* ** Suggested field contents: ** ** sysname ** Should contain the name of the underlying operating system, or "cc65" ** if the program runs on the bare machine. ** ** nodename ** Is empty or may be defined by the implementor. ** ** release ** Contains the operating system release or the major/minor cc65 version ** if sysname contains "cc65". ** ** version ** Contains the operating system version or the cc65 patch version if ** sysname contains "cc65". ** ** machine ** Contains the complete name of the machine, like "Commodore 64", ** "Oric Atmos" or similar. ** ** Beware: The library sources written in assembler have knowledge about this ** struct! */ struct utsname { char sysname[17]; char nodename[9]; char release[9]; char version[9]; char machine[25]; }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ int __fastcall__ uname (struct utsname* buf); /* Return system information */ /* End of utsname.h */ #endif �������������������������cc65-2.18/include/target.h��������������������������������������������������������������������������0000664�0000000�0000000�00000005660�13473601511�0015276�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* target.h */ /* */ /* Target specific definitions */ /* */ /* */ /* */ /* 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 _TARGET_H #define _TARGET_H /* Include the correct target specific file */ #if defined(__APPLE2ENH__) # include <apple2enh.h> #elif defined(__APPLE2__) # include <apple2.h> #elif defined(__ATARI__) # include <atari.h> #elif defined(__ATARI2600__) # include <atari2600.h> #elif defined(__ATARI5200__) # include <atari5200.h> #elif defined(__ATMOS__) # include <atmos.h> #elif defined(__CBM__) # include <cbm.h> #elif defined(__CREATIVISION__) # include <creativision.h> #elif defined(__GAMATE__) # include <gamate.h> #elif defined(__GEOS__) # include <geos.h> #elif defined(__LYNX__) # include <lynx.h> #elif defined(__NES__) # include <nes.h> #elif defined(__OSIC1P__) # include <osic1p.h> #elif defined(__PCE__) # include <pce.h> #elif defined(__SUPERVISION__) # include <supervision.h> #elif defined(__TELESTRAT__) # include <telestrat.h> #endif /* End of target.h */ #endif ��������������������������������������������������������������������������������cc65-2.18/include/telestrat.h�����������������������������������������������������������������������0000664�0000000�0000000�00000010167�13473601511�0016015�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* telestrat.h */ /* */ /* Oric Telestrat system-specific definitions */ /* */ /* */ /* */ /* (C) 2017 Debrune Jérome, <jede@oric.org> */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* Color defines */ #define COLOR_BLACK 0x00 #define COLOR_RED 0x01 #define COLOR_GREEN 0x02 #define COLOR_YELLOW 0x03 #define COLOR_BLUE 0x04 #define COLOR_MAGENTA 0x05 #define COLOR_CYAN 0x06 #define COLOR_WHITE 0x07 /* TGI color defines */ /* White and red are swapped, so that the pallete ** driver is compatible with black-and-white drivers. */ #define TGI_COLOR_BLACK COLOR_BLACK #define TGI_COLOR_WHITE 1 #define TGI_COLOR_GREEN COLOR_GREEN #define TGI_COLOR_YELLOW COLOR_YELLOW #define TGI_COLOR_BLUE COLOR_BLUE #define TGI_COLOR_MAGENTA COLOR_MAGENTA #define TGI_COLOR_CYAN COLOR_CYAN #define TGI_COLOR_RED 7 extern void telestrat_228_200_3_tgi[]; extern void telestrat_240_200_2_tgi[]; /* Referred to by tgi_static_stddrv[] */ /* Define hardware */ #include <_6522.h> #define VIA (*(struct __6522*)0x300) /* These are defined to be FUNCT + NumberKey */ #define CH_F1 0xB1 #define CH_F2 0xB2 #define CH_F3 0xB3 #define CH_F4 0xB4 #define CH_F5 0xB5 #define CH_F6 0xB6 #define CH_F7 0xB7 #define CH_F8 0xB8 #define CH_F9 0xB9 #define CH_F10 0xB0 /* Character codes */ #define CH_ULCORNER '+' #define CH_URCORNER '+' #define CH_LLCORNER '+' #define CH_LRCORNER '+' #define CH_TTEE '+' #define CH_BTEE '+' #define CH_LTEE '+' #define CH_RTEE '+' #define CH_CROSS '+' #define CH_CURS_UP 11 #define CH_CURS_DOWN 10 #define CH_CURS_LEFT 8 #define CH_CURS_RIGHT 9 #define CH_DEL 127 #define CH_ENTER 13 #define CH_STOP 3 #define CH_LIRA 95 #define CH_ESC 27 void oups(); void ping(); void zap(); void shoot(); void explode(); void kbdclick1(); ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/tgi.h�����������������������������������������������������������������������������0000664�0000000�0000000�00000025107�13473601511�0014571�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* tgi.h */ /* */ /* Tiny graphics interface */ /* */ /* */ /* */ /* (C) 2002-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _TGI_H #define _TGI_H #include <tgi/tgi-error.h> #include <target.h> /*****************************************************************************/ /* Definitions */ /*****************************************************************************/ /* Font constants for use with tgi_settextstyle */ #define TGI_FONT_BITMAP 0 #define TGI_FONT_VECTOR 1 /* Direction constants for use with tgi_settextstyle */ #define TGI_TEXT_HORIZONTAL 0 #define TGI_TEXT_VERTICAL 1 /* The name of the standard tgi driver for a platform */ extern const char tgi_stddrv[]; /* The address of the static standard tgi driver for a platform */ extern const void tgi_static_stddrv[]; /* A vector font definition */ typedef struct tgi_vectorfont tgi_vectorfont; /*****************************************************************************/ /* Functions */ /*****************************************************************************/ void __fastcall__ tgi_load_driver (const char* name); /* Load and install the given driver. */ void tgi_unload (void); /* Uninstall, then unload the currently loaded driver. Will call tgi_done if ** necessary. */ void __fastcall__ tgi_install (void* driver); /* Install an already loaded driver. */ void tgi_uninstall (void); /* Uninstall the currently loaded driver but do not unload it. Will call ** tgi_done if necessary. */ void tgi_init (void); /* Initialize the already loaded graphics driver. */ void tgi_done (void); /* End graphics mode, switch back to text mode. Will NOT uninstall or unload ** the driver! */ const tgi_vectorfont* __fastcall__ tgi_load_vectorfont (const char* name); /* 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. */ void __fastcall__ tgi_install_vectorfont (const tgi_vectorfont* font); /* 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. */ void __fastcall__ tgi_free_vectorfont (const tgi_vectorfont* font); /* Free a vector font that was previously loaded into memory. */ unsigned char tgi_geterror (void); /* Return the error code for the last operation. This will also clear the ** error. */ const char* __fastcall__ tgi_geterrormsg (unsigned char code); /* Get an error message describing the error in code. */ void tgi_clear (void); /* Clear the drawpage. */ unsigned tgi_getpagecount (void); /* Returns the number of screen pages available. */ void __fastcall__ tgi_setviewpage (unsigned char page); /* Set the visible page. Will set an error if the page is not available. */ void __fastcall__ tgi_setdrawpage (unsigned char page); /* Set the drawable page. Will set an error if the page is not available. */ unsigned char tgi_getcolorcount (void); /* Get the number of available colors. */ unsigned char tgi_getmaxcolor (void); /* Return the maximum supported color number (the number of colors would ** then be getmaxcolor()+1). */ void __fastcall__ tgi_setcolor (unsigned char color); /* Set the current drawing color. */ unsigned char tgi_getcolor (void); /* Return the current drawing color. */ void __fastcall__ tgi_setpalette (const unsigned char* palette); /* Set the palette (not available with all drivers/hardware). palette is ** a pointer to as many entries as there are colors. */ const unsigned char* tgi_getpalette (void); /* Return the current palette. */ const unsigned char* tgi_getdefpalette (void); /* Return the default palette. */ unsigned tgi_getxres (void); /* Return the resolution in X direction. */ unsigned tgi_getmaxx (void); /* Return the maximum x coordinate. The resolution in x direction is ** getmaxx() + 1 */ unsigned tgi_getyres (void); /* Return the resolution in Y direction. */ unsigned tgi_getmaxy (void); /* Return the maximum y coordinate. The resolution in y direction is ** getmaxy() + 1 */ unsigned tgi_getaspectratio (void); /* Returns the aspect ratio for the loaded driver. The aspect ratio is an ** 8.8 fixed point value. */ void __fastcall__ tgi_setaspectratio (unsigned aspectratio); /* Set a new aspect ratio for the loaded driver. The aspect ratio is an ** 8.8 fixed point value. */ unsigned char __fastcall__ tgi_getpixel (int x, int y); /* Get the color value of a pixel. */ void __fastcall__ tgi_setpixel (int x, int y); /* Plot a pixel in the current drawing color. */ void __fastcall__ tgi_gotoxy (int x, int y); /* Set the graphics cursor to the given position. */ void __fastcall__ tgi_line (int x1, int y1, int x2, int y2); /* Draw a line in the current drawing color. The graphics cursor will ** be set to x2/y2 by this call. */ void __fastcall__ tgi_lineto (int x2, int y2); /* 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. */ void __fastcall__ tgi_circle (int x, int y, unsigned char radius); /* Draw a circle in the current drawing color. */ void __fastcall__ tgi_ellipse (int x, int y, unsigned char rx, unsigned char ry); /* Draw a full ellipse with center at x/y and radii rx/ry using the current ** drawing color. */ void __fastcall__ tgi_arc (int x, int y, unsigned char rx, unsigned char ry, unsigned sa, unsigned ea); /* Draw an ellipse arc with center at x/y and 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 (otherwise the function may ** bevave unextectedly). */ void __fastcall__ tgi_pieslice (int x, int y, unsigned char rx, unsigned char ry, unsigned sa, unsigned ea); /* Draw an ellipse pie slice with center at x/y 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 (otherwise the ** function may behave unextectedly). */ void __fastcall__ tgi_bar (int x1, int y1, int x2, int y2); /* Draw a bar (a filled rectangle) using the current color. */ void __fastcall__ tgi_settextdir (unsigned char dir); /* Set the direction for text output. dir is one of the TGI_TEXT_XXX ** constants. */ void __fastcall__ tgi_settextscale (unsigned width, unsigned height); /* 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. */ void __fastcall__ tgi_settextstyle (unsigned width, unsigned height, unsigned char dir, unsigned char font); /* Set the style for text output. The scaling factors for width and height ** are 8.8 fixed point values. This means that $100 = 1 $200 = 2 etc. ** dir is one of the TGI_TEXT_XXX constants. font is one of the TGI_FONT_XXX ** constants. */ unsigned __fastcall__ tgi_gettextwidth (const char* s); /* Calculate the width of the text in pixels according to the current text ** style. */ unsigned __fastcall__ tgi_gettextheight (const char* s); /* Calculate the height of the text in pixels according to the current text ** style. */ void __fastcall__ tgi_outtext (const char* s); /* Output text at the current graphics cursor position. The graphics cursor ** is moved to the end of the text. */ void __fastcall__ tgi_outtextxy (int x, int y, const char* s); /* Output text at the given cursor position. The graphics cursor is moved to ** the end of the text. */ unsigned __fastcall__ tgi_ioctl (unsigned char code, void* data); /* Call the driver specific control function. What this function does for ** a specific code depends on the driver. The driver will set an error ** for unknown codes or values. */ int __fastcall__ tgi_imulround (int rhs, int lhs); /* Helper function for functions using sine/cosine: Multiply two values, one ** being an 8.8 fixed point one, and return the rounded and scaled result. */ /* End of tgi.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/tgi/������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014413�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/tgi/tgi-error.h�������������������������������������������������������������������0000664�0000000�0000000�00000006760�13473601511�0016507�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* tgi-error.h */ /* */ /* TGI error codes */ /* */ /* */ /* */ /* (C) 2002-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _TGI_ERROR_H #define _TGI_ERROR_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ #define TGI_ERR_OK 0 /* No error */ #define TGI_ERR_NO_DRIVER 1 /* No driver available */ #define TGI_ERR_CANNOT_LOAD 2 /* Error loading driver or font */ #define TGI_ERR_INV_DRIVER 3 /* Invalid driver */ #define TGI_ERR_INV_MODE 4 /* Mode not supported by driver */ #define TGI_ERR_INV_ARG 5 /* Invalid function argument */ #define TGI_ERR_INV_FUNC 6 /* Function not supported */ #define TGI_ERR_INV_FONT 7 /* Font file is invalid */ #define TGI_ERR_NO_RES 8 /* Out of resources */ #define TGI_ERR_INSTALLED 9 /* A driver is already installed */ /* End of tgi-error.h */ #endif ����������������cc65-2.18/include/tgi/tgi-kernel.h������������������������������������������������������������������0000664�0000000�0000000�00000010277�13473601511�0016634�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* tgi-kernel.h */ /* */ /* TGI kernel interface */ /* */ /* */ /* */ /* (C) 2002-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _TGI_KERNEL_H #define _TGI_KERNEL_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* TGI kernel variables */ extern void* tgi_drv; /* Pointer to driver */ extern unsigned char tgi_error; /* Last error code */ extern unsigned char tgi_gmode; /* Flag: Graphics mode active */ extern int tgi_curx; /* Current drawing cursor X */ extern int tgi_cury; /* Current drawing cursor Y */ extern unsigned char tgi_color; /* Current drawing color */ extern unsigned char tgi_font; /* Current font type */ extern unsigned tgi_xres; /* X resolution of the current mode */ extern unsigned tgi_yres; /* Y resolution of the current mode */ extern unsigned char tgi_colorcount; /* Number of available colors */ extern unsigned char tgi_pagecount; /* Number of available screens */ extern unsigned char tgi_fontwidth; /* System font width in pixels */ extern unsigned char tgi_fontheight; /* System font height in pixels */ extern unsigned tgi_aspectratio; /* Aspect ratio as fixed point 8.8 */ extern unsigned char tgi_flags; /* TGI driver flags */ extern unsigned tgi_textscalew[2]; /* Vector/bitmap font scale 8.8 */ extern unsigned tgi_textscaleh[2]; /* Vector/bitmap font scale 8.8 */ extern unsigned tgi_charwidth; /* Width of scaled bitmap font */ extern unsigned tgi_charheight; /* Height of scaled bitmap font */ /* End of tgi-kernel.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/tgi/tgi-vectorfont.h��������������������������������������������������������������0000664�0000000�0000000�00000010503�13473601511�0017535�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* tgi-vectorfont.h */ /* */ /* TGI vector font definitions */ /* */ /* */ /* */ /* (C) 2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _TGI_VECTORFONT_H #define _TGI_VECTORFONT_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ #define TGI_VF_FIRSTCHAR 0x20 /* First char in file */ #define TGI_VF_LASTCHAR 0x7E /* Last char in file */ #define TGI_VF_CCOUNT (TGI_VF_LASTCHAR - TGI_VF_FIRSTCHAR + 1) #define TGI_VF_VERSION 0x00 /* File version number */ /* TCH file header */ typedef struct tgi_vectorfont_header tgi_vectorfont_header; struct tgi_vectorfont_header { unsigned char magic[3]; /* "TCH" */ unsigned char version; /* Version number */ unsigned size; /* Font data size */ }; /* Font data loaded directly from file */ struct tgi_vectorfont { unsigned char top; /* Height of char */ unsigned char baseline; /* Character baseline */ unsigned char bottom; /* Descender */ unsigned char widths[TGI_VF_CCOUNT]; /* Char widths */ unsigned char* chars[TGI_VF_CCOUNT]; /* Pointer to character defs */ unsigned char vec_ops[1]; /* Actually dynamic */ }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void __fastcall__ tgi_vectorchar (char C); /* Draw one character of the vector font at the current graphics cursor ** position using the current font magnification. */ /* End of tgi-vectorfont.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/time.h����������������������������������������������������������������������������0000664�0000000�0000000�00000013465�13473601511�0014750�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* time.h */ /* */ /* Date and time */ /* */ /* */ /* */ /* (C) 1998-2012 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _TIME_H #define _TIME_H /* NULL pointer */ #ifndef _HAVE_NULL #define NULL 0 #define _HAVE_NULL #endif /* size_t is needed */ #ifndef _HAVE_size_t #define _HAVE_size_t typedef unsigned size_t; #endif typedef unsigned long time_t; typedef unsigned long clock_t; typedef unsigned char clockid_t; /* Structure for broken down time */ struct tm { int tm_sec; int tm_min; int tm_hour; int tm_mday; int tm_mon; int tm_year; int tm_wday; int tm_yday; int tm_isdst; }; /* Structure for seconds and nanoseconds */ struct timespec { time_t tv_sec; long tv_nsec; }; /* Timezone representation, default is UTC */ extern struct _timezone { char daylight; /* True if daylight savings time active */ long timezone; /* Number of seconds behind UTC */ char tzname[5]; /* Name of timezone, e.g. CET */ char dstname[5]; /* Name when daylight true, e.g. CEST */ } _tz; #if defined(__ATARI__) /* The clock depends on the video standard, so read it at runtime */ unsigned _clocks_per_sec (void); # define CLK_TCK _clocks_per_sec() # define CLOCKS_PER_SEC _clocks_per_sec() #elif defined(__ATARI5200__) # define CLK_TCK 60 /* POSIX */ # define CLOCKS_PER_SEC 60 /* ANSI */ #elif defined(__ATMOS__) # define CLK_TCK 100 /* POSIX */ # define CLOCKS_PER_SEC 100 /* ANSI */ #elif defined(__CBM__) # if defined(__CBM510__) || defined(__CBM610__) /* The 510/610 gets its clock from the AC current */ # define CLK_TCK 50 /* POSIX */ # define CLOCKS_PER_SEC 50 /* ANSI */ # else # define CLK_TCK 60 /* POSIX */ # define CLOCKS_PER_SEC 60 /* ANSI */ # endif #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(__GAMATE__) # define CLK_TCK 135 /* POSIX */ /* FIXME */ # define CLOCKS_PER_SEC 135 /* ANSI */ /* FIXME */ #elif defined(__GEOS__) # define CLK_TCK 1 /* POSIX */ # define CLOCKS_PER_SEC 1 /* ANSI */ #elif defined(__LYNX__) /* The clock-rate depends on the video scan-rate; ** so, read it at run-time. */ extern clock_t _clk_tck (void); # define CLK_TCK _clk_tck() # define CLOCKS_PER_SEC _clk_tck() #endif #define CLOCK_REALTIME 0 /* ISO C function prototypes */ char* __fastcall__ asctime (const struct tm* timep); clock_t clock (void); char* __fastcall__ ctime (const time_t* timep); struct tm* __fastcall__ gmtime (const time_t* timep); struct tm* __fastcall__ localtime (const time_t* timep); time_t __fastcall__ mktime (struct tm* timep); size_t __fastcall__ strftime (char* buf, size_t bufsize, const char* format, const struct tm* tm); time_t __fastcall__ time (time_t* t); /* POSIX function prototypes */ int __fastcall__ clock_getres (clockid_t clock_id, struct timespec *res); int __fastcall__ clock_gettime (clockid_t clock_id, struct timespec *tp); int __fastcall__ clock_settime (clockid_t clock_id, const struct timespec *tp); /* End of time.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/unistd.h��������������������������������������������������������������������������0000664�0000000�0000000�00000010325�13473601511�0015310�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* unistd.h */ /* */ /* Unix compatibility header file for cc65 */ /* */ /* */ /* */ /* (C) 2003-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _UNISTD_H #define _UNISTD_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Predefined file handles */ #define STDIN_FILENO 0 #define STDOUT_FILENO 1 #define STDERR_FILENO 2 /* WE need size_t */ #ifndef _HAVE_size_t #define _HAVE_size_t typedef unsigned size_t; #endif /* We need off_t if sys/types is not included */ #ifndef _HAVE_off_t #define _HAVE_off_t typedef long int off_t; #endif /* Stuff for getopt */ extern char *optarg; extern int optind, opterr, optopt; /*****************************************************************************/ /* Code */ /*****************************************************************************/ /* Files */ int __fastcall__ write (int fd, const void* buf, unsigned count); int __fastcall__ read (int fd, void* buf, unsigned count); off_t __fastcall__ lseek (int fd, off_t offset, int whence); int __fastcall__ unlink (const char* name); /* Same as remove() */ /* Directories */ int __fastcall__ chdir (const char* name); char* __fastcall__ getcwd (char* buf, size_t size); int mkdir (const char* name, ...); /* May take a mode argument */ int __fastcall__ rmdir (const char* name); /* Others */ unsigned __fastcall__ sleep (unsigned seconds); int __fastcall__ getopt (int argc, char* const* argv, const char* optstring); /* Non standard: */ #if __CC65_STD__ == __CC65_STD_CC65__ int __fastcall__ exec (const char* progname, const char* cmdline); #endif /* End of unistd.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/vic20.h���������������������������������������������������������������������������0000664�0000000�0000000�00000010452�13473601511�0014726�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* vic20.h */ /* */ /* vic20 system specific definitions */ /* */ /* */ /* */ /* (C) 1998-2004 Ullrich von Bassewitz */ /* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _VIC20_H #define _VIC20_H /* Check for errors */ #if !defined(__VIC20__) # error This module may only be used when compiling for the Vic20! #endif /* Additional key defines */ #define CH_F1 133 #define CH_F2 137 #define CH_F3 134 #define CH_F4 138 #define CH_F5 135 #define CH_F6 139 #define CH_F7 136 #define CH_F8 140 /* Color defines */ #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 /* Masks for joy_read */ #define JOY_UP_MASK 0x01 #define JOY_DOWN_MASK 0x02 #define JOY_LEFT_MASK 0x04 #define JOY_RIGHT_MASK 0x08 #define JOY_BTN_1_MASK 0x10 /* Define hardware */ #include <_vic.h> #define VIC (*(struct __vic*)0x9000) #include <_6522.h> #define VIA1 (*(struct __6522*)0x9110) #define VIA2 (*(struct __6522*)0x9120) /* Define special memory areas */ #define COLOR_RAM ((unsigned char*)0x9600) /* The addresses of the static drivers */ extern void vic20_ptvjoy_joy[]; extern void vic20_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */ extern void vic20_rama_emd[]; extern void vic20_georam_emd[]; /* End of vic20.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/include/zlib.h����������������������������������������������������������������������������0000664�0000000�0000000�00000015452�13473601511�0014750�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* zlib.h */ /* */ /* Decompression routines for the 'deflate' format */ /* */ /* */ /* */ /* (C) 2000-2015 Piotr Fusik <fox@scene.pl> */ /* */ /* This file is based on the zlib.h from 'zlib' general purpose compression */ /* library, version 1.1.3, (C) 1995-1998 Jean-loup Gailly and Mark Adler. */ /* */ /* Jean-loup Gailly Mark Adler */ /* jloup@gzip.org madler@alumni.caltech.edu */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _ZLIB_H #define _ZLIB_H #define Z_OK 0 #define Z_DATA_ERROR (-3) /* Return codes for uncompress() */ #define Z_DEFLATED 8 /* The deflate compression method (the only one supported) */ #define Z_NULL 0 unsigned __fastcall__ inflatemem (char* dest, const char* source); /* Decompresses the source buffer into the destination buffer. Returns the size of the uncompressed data (number of bytes written starting from dest). This function expects data in the DEFLATE format, described in RFC (Request for Comments) 1951 in the file ftp://ds.internic.net/rfc/rfc1951.txt. This function does not exist in the original zlib. Its implementation using original zlib might be following: unsigned inflatemem (char* dest, const char* source) { z_stream stream; stream.next_in = (Bytef*) source; stream.avail_in = 65535; stream.next_out = dest; stream.avail_out = 65535; stream.zalloc = (alloc_func) 0; stream.zfree = (free_func) 0; inflateInit2(&stream, -MAX_WBITS); inflate(&stream, Z_FINISH); inflateEnd(&stream); return stream.total_out; } */ int __fastcall__ uncompress (char* dest, unsigned* destLen, const char* source, unsigned sourceLen); /* Original zlib description: Decompresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be large enough to hold the entire uncompressed data. (The size of the uncompressed data must have been saved previously by the compressor and transmitted to the decompressor by some mechanism outside the scope of this compression library.) Upon exit, destLen is the actual size of the compressed buffer. This function can be used to decompress a whole file at once if the input file is mmap'ed. uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, or Z_DATA_ERROR if the input data was corrupted. Implementation notes: This function expects data in the ZLIB format, described in RFC 1950 in the file ftp://ds.internic.net/rfc/rfc1950.txt. The ZLIB format is essentially the DEFLATE format plus a very small header and Adler-32 checksum. Z_MEM_ERROR and Z_BUF_ERROR are never returned in this implementation. */ unsigned long __fastcall__ adler32 (unsigned long adler, const char* buf, unsigned len); /* Original zlib description: Update a running Adler-32 checksum with the bytes buf[0..len-1] and return the updated checksum. If buf is NULL, this function returns the required initial value for the checksum. An Adler-32 checksum is almost as reliable as a CRC32 but can be computed much faster. Usage example: unsigned long adler = adler32(0L, Z_NULL, 0); while (read_buffer(buffer, length) != EOF) { adler = adler32(adler, buffer, length); } if (adler != original_adler) error(); Implementation notes: This function isn't actually much faster than crc32(), but it is smaller and does not use any lookup tables. */ unsigned long __fastcall__ crc32 (unsigned long crc, const char* buf, unsigned len); /* Original zlib description: Update a running crc with the bytes buf[0..len-1] and return the updated crc. If buf is NULL, this function returns the required initial value for the crc. Pre- and post-conditioning (one's complement) is performed within this function so it shouldn't be done by the application. Usage example: unsigned long crc = crc32(0L, Z_NULL, 0); while (read_buffer(buffer, length) != EOF) { crc = crc32(crc, buffer, length); } if (crc != original_crc) error(); Implementation notes: This function uses statically allocated 1 KB lookup table. The table is initialised before it is used for the first time (that is, if buffer is NULL or length is zero, then the lookup table isn't initialised). */ /* end of zlib.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/�����������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0013463�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/Makefile���������������������������������������������������������������������������0000664�0000000�0000000�00000015570�13473601511�0015133�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ifneq ($(shell echo),) CMD_EXE = 1 endif CBMS = c128 \ c16 \ c64 \ cbm510 \ cbm610 \ pet \ plus4 \ vic20 GEOS = geos-apple \ geos-cbm TARGETS = apple2 \ apple2enh \ atari \ atarixl \ atari2600 \ atari5200 \ atmos \ creativision \ $(CBMS) \ $(GEOS) \ gamate \ lynx \ nes \ none \ osic1p \ pce \ sim6502 \ sim65c02 \ supervision \ telestrat DRVTYPES = emd \ joy \ mou \ ser \ tgi OUTPUTDIRS := lib \ asminc \ cfg \ include \ $(subst ../,,$(filter-out $(wildcard ../include/*.*),$(wildcard ../include/*))) \ $(subst ../,,$(wildcard ../target/*/drv/*)) \ $(subst ../,,$(wildcard ../target/*/util)) .PHONY: all mostlyclean clean install zip lib $(TARGETS) .SUFFIXES: ifdef CMD_EXE DIRLIST = $(strip $(foreach dir,$1,$(wildcard $(dir)))) MKDIR = mkdir $(subst /,\,$1) RMDIR = $(if $(DIRLIST),rmdir /s /q $(subst /,\,$(DIRLIST))) else MKDIR = mkdir -p $1 RMDIR = $(RM) -r $1 endif # Every target requires its individual vpath setting but the vpath directive # acts globally. Therefore each target is built in a separate make instance. ifeq ($(words $(MAKECMDGOALS)),1) ifeq ($(MAKECMDGOALS),$(filter $(MAKECMDGOALS),$(TARGETS))) TARGET = $(MAKECMDGOALS) endif endif ifndef TARGET datadir = $(PREFIX)/share/cc65 all lib: $(TARGETS) mostlyclean: $(call RMDIR,../libwrk) clean: $(call RMDIR,../libwrk ../lib ../target) ifdef CMD_EXE install: else # CMD_EXE INSTALL = install define INSTALL_recipe $(if $(PREFIX),,$(error variable "PREFIX" must be set)) $(INSTALL) -d $(DESTDIR)$(datadir)/$(dir) $(INSTALL) -m0644 ../$(dir)/*.* $(DESTDIR)$(datadir)/$(dir) endef # INSTALL_recipe install: $(foreach dir,$(OUTPUTDIRS),$(INSTALL_recipe)) endif # CMD_EXE define ZIP_recipe @cd .. && zip cc65 $(dir)/*.* endef # ZIP_recipe zip: $(foreach dir,$(OUTPUTDIRS),$(ZIP_recipe)) $(TARGETS): @$(MAKE) --no-print-directory $@ else # TARGET CA65FLAGS = CC65FLAGS = -Or -W error EXTZP = cbm510 \ cbm610 \ lynx MKINC = $(GEOS) \ atari \ atarixl \ nes TARGETUTIL = apple2 \ apple2enh \ atari \ geos-apple GEOSDIRS = common \ conio \ disk \ dlgbox \ file \ graph \ memory \ menuicon \ mousesprite \ process \ runtime \ system ifeq ($(TARGET),apple2enh) SRCDIR = apple2 OBJPFX = a2 DRVPFX = a2e else ifeq ($(TARGET),atarixl) SRCDIR = atari OBJPFX = atr DRVPFX = atrx else ifeq ($(TARGET),sim65c02) SRCDIR = sim6502 else SRCDIR = $(TARGET) endif SRCDIRS = $(SRCDIR) ifeq ($(TARGET),$(filter $(TARGET),$(CBMS))) SRCDIRS += cbm endif ifeq ($(TARGET),$(filter $(TARGET),$(GEOS))) SRCDIRS += $(addprefix $(TARGET)/, $(GEOSDIRS)) SRCDIRS += $(addprefix geos-common/,$(GEOSDIRS)) endif SRCDIRS += common \ conio \ dbg \ em \ joystick \ mouse \ runtime \ serial \ tgi \ zlib vpath %.s $(SRCDIRS) vpath %.c $(SRCDIRS) OBJS := $(patsubst %.s,%.o,$(foreach dir,$(SRCDIRS),$(wildcard $(dir)/*.s))) OBJS += $(patsubst %.c,%.o,$(foreach dir,$(SRCDIRS),$(wildcard $(dir)/*.c))) OBJS := $(addprefix ../libwrk/$(TARGET)/,$(sort $(notdir $(OBJS)))) DEPS = $(OBJS:.o=.d) EXTRA_SRCPAT = $(SRCDIR)/extra/%.s EXTRA_OBJPAT = ../lib/$(TARGET)-%.o EXTRA_OBJS := $(patsubst $(EXTRA_SRCPAT),$(EXTRA_OBJPAT),$(wildcard $(SRCDIR)/extra/*.s)) DEPS += $(EXTRA_OBJS:../lib/%.o=../libwrk/$(TARGET)/%.d) ZPOBJ = ../libwrk/$(TARGET)/zeropage.o ifeq ($(TARGET),$(filter $(TARGET),$(EXTZP))) ZPOBJ += ../libwrk/$(TARGET)/extzp.o endif ifeq ($(TARGET),$(filter $(TARGET),$(MKINC))) include $(SRCDIR)/Makefile.inc endif ifeq ($(TARGET),$(filter $(TARGET),$(TARGETUTIL))) include $(SRCDIR)/targetutil/Makefile.inc endif define DRVTYPE_template $1_SRCDIR = $$(SRCDIR)/$1 $1_STCDIR = ../libwrk/$$(TARGET) $1_DYNDIR = ../libwrk/$$(TARGET)/$1 $1_DRVDIR = ../target/$$(TARGET)/drv/$1 $1_SRCPAT = $$($1_SRCDIR)/$$(OBJPFX)%.s $1_STCPAT = $$($1_STCDIR)/$$(OBJPFX)%-$1.o $1_DYNPAT = $$($1_DYNDIR)/$$(OBJPFX)%.o $1_DRVPAT = $$($1_DRVDIR)/$$(DRVPFX)%.$1 $1_SRCS := $$(wildcard $$($1_SRCDIR)/*.s) $1_STCS = $$(patsubst $$($1_SRCPAT),$$($1_STCPAT),$$($1_SRCS)) $1_DYNS = $$(patsubst $$($1_SRCPAT),$$($1_DYNPAT),$$($1_SRCS)) $1_DRVS = $$(patsubst $$($1_DYNPAT),$$($1_DRVPAT),$$($1_DYNS)) $$($1_STCPAT): $$($1_SRCPAT) @echo $$(TARGET) - $$< - static @$$(CA65) -t $$(TARGET) -D DYN_DRV=0 $$(CA65FLAGS) --create-dep $$(@:.o=.d) -o $$@ $$< OBJS += $$($1_STCS) DEPS += $$($1_STCS:.o=.d) $$($1_DYNS): | $$($1_DYNDIR) $$($1_DRVPAT): $$($1_DYNPAT) $$(ZPOBJ) | $$($1_DRVDIR) @echo $$(TARGET) - $$(<F) @$$(LD65) -o $$@ -t module $$^ $$($1_DYNDIR) $$($1_DRVDIR): @$$(call MKDIR,$$@) $(TARGET): $$($1_DRVS) DEPS += $$($1_DYNS:.o=.d) endef # DRVTYPE_template $(foreach drvtype,$(DRVTYPES),$(eval $(call DRVTYPE_template,$(drvtype)))) AR65 := $(if $(wildcard ../bin/ar65*),../bin/ar65,ar65) CA65 := $(if $(wildcard ../bin/ca65*),../bin/ca65,ca65) CC65 := $(if $(wildcard ../bin/cc65*),../bin/cc65,cc65) LD65 := $(if $(wildcard ../bin/ld65*),../bin/ld65,ld65) export CC65_HOME := $(abspath ..) define ASSEMBLE_recipe $(if $(QUIET),,@echo $(TARGET) - $<) @$(CA65) -t $(TARGET) $(CA65FLAGS) --create-dep $(@:.o=.d) -o $@ $< endef # ASSEMBLE_recipe define COMPILE_recipe $(if $(QUIET),,@echo $(TARGET) - $<) @$(CC65) -t $(TARGET) $(CC65FLAGS) --create-dep $(@:.o=.d) --dep-target $@ -o $(@:.o=.s) $< @$(CA65) -t $(TARGET) -o $@ $(@:.o=.s) endef # COMPILE_recipe ../libwrk/$(TARGET)/%.o: %.s | ../libwrk/$(TARGET) $(ASSEMBLE_recipe) ../libwrk/$(TARGET)/%.o: %.c | ../libwrk/$(TARGET) $(COMPILE_recipe) $(EXTRA_OBJPAT): $(EXTRA_SRCPAT) | ../libwrk/$(TARGET) ../lib @echo $(TARGET) - $(<F) @$(CA65) -t $(TARGET) $(CA65FLAGS) --create-dep $(@:../lib/%.o=../libwrk/$(TARGET)/%.d) -o $@ $< ../lib/$(TARGET).lib: $(OBJS) | ../lib $(AR65) a $@ $? ../libwrk/$(TARGET) ../lib ../target/$(TARGET)/util: @$(call MKDIR,$@) $(TARGET): $(EXTRA_OBJS) ../lib/$(TARGET).lib -include $(DEPS) endif # TARGET ����������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/����������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014646�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/_scrsize.s������������������������������������������������������������������0000664�0000000�0000000�00000000403�13473601511�0016650�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.10.2000 ; ; Screen size variables ; .export screensize .include "apple2.inc" screensize: ldx WNDWDTH lda WNDBTM sec sbc WNDTOP tay rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/_sys.s����������������������������������������������������������������������0000664�0000000�0000000�00000003355�13473601511�0016015�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; void __fastcall__ _sys (struct regs* r); ; .export __sys .import jmpvec .include "zeropage.inc" .segment "LOWCODE" __sys: sta ptr1 stx ptr1+1 ; Save the pointer to r ; Fetch the PC and store it into the jump vector ldy #5 lda (ptr1),y sta jmpvec+2 dey lda (ptr1),y sta jmpvec+1 ; Remember the flags so we can restore them to a known state after calling the ; routine php ; Get the flags, keep the state of bit 4 and 5 using the other flags from ; the flags value passed by the caller. Push the new flags and push A. dey php pla ; Current flags -> A eor (ptr1),y and #%00110000 eor (ptr1),y pha ; Push new flags value ldy #0 lda (ptr1),y pha ; Get and assign X and Y iny lda (ptr1),y tax iny lda (ptr1),y tay ; Switch in ROM bit $C082 ; Set A and the flags, call the machine code routine pla plp jsr jmpvec ; Back from the routine. Save the flags and A. php pha ; Switch in LC bank 2 for R/O bit $C080 ; Put the register values into the regs structure tya ldy #2 sta (ptr1),y dey txa sta (ptr1),y dey pla sta (ptr1),y ldy #3 pla sta (ptr1),y ; Restore the old flags value plp ; Done rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/break.s���������������������������������������������������������������������0000664�0000000�0000000�00000004372�13473601511�0016124�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 27.09.1998 ; ; void __fastcall__ set_brk (unsigned Addr); ; void reset_brk (void); ; .export _set_brk, _reset_brk .destructor _reset_brk ; Be sure to export the following variables absolute .export _brk_a: abs, _brk_x: abs, _brk_y: abs .export _brk_sr: abs, _brk_pc: abs .include "apple2.inc" _brk_a = $45 _brk_x = $46 _brk_y = $47 _brk_sr = $48 _brk_sp = $49 _brk_pc = $3A .bss oldvec: .res 2 ; Old vector .data uservec: jmp $FFFF ; Patched at runtime .code ; Set the break vector .proc _set_brk sta uservec+1 stx uservec+2 ; Set the user vector lda oldvec ora oldvec+1 ; Did we save the vector already? bne L1 ; Jump if we installed the handler already lda BRKVec sta oldvec lda BRKVec+1 sta oldvec+1 ; Save the old vector L1: lda #<brk_handler ; Set the break vector to our routine ldx #>brk_handler sta BRKVec stx BRKVec+1 rts .endproc ; Reset the break vector .proc _reset_brk lda oldvec ldx oldvec+1 beq @L9 ; Jump if vector not installed sta BRKVec stx BRKVec+1 lda #$00 sta oldvec ; Clear the old vector stx oldvec+1 @L9: rts .endproc ; Break handler, called if a break occurs .proc brk_handler sec lda _brk_pc sbc #$02 ; Point to start of brk sta _brk_pc lda _brk_pc+1 sbc #$00 sta _brk_pc+1 clc lda _brk_sp adc #$04 ; Adjust stack pointer sta _brk_sp lda _brk_sr ; Clear brk and #$EF sta _brk_sr jsr uservec ; Call the user's routine lda _brk_pc+1 pha lda _brk_pc pha lda _brk_sr pha ldx _brk_x ldy _brk_y lda _brk_a rti ; Jump back... .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/cclear.s��������������������������������������������������������������������0000664�0000000�0000000�00000001062�13473601511�0016262�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 08.08.1998 ; ; void __fastcall__ cclearxy (unsigned char x, unsigned char y, unsigned char length); ; void __fastcall__ cclear (unsigned char length); ; .export _cclearxy, _cclear .import gotoxy, chlinedirect _cclearxy: pha ; Save the length jsr gotoxy ; Call this one, will pop params pla ; Restore the length and run into _cclear _cclear: ldx #' ' | $80 ; Blank, screen code jmp chlinedirect ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/cgetc.s���������������������������������������������������������������������0000664�0000000�0000000�00000002463�13473601511�0016124�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Kevin Ruland ; ; char cgetc (void); ; ; If open_apple key is pressed then the high-bit of the key is set. ; .export _cgetc .import cursor, putchardirect .include "apple2.inc" _cgetc: ; Cursor on ? lda cursor beq :+ ; Show caret. .ifdef __APPLE2ENH__ lda #$7F | $80 ; Checkerboard, screen code .else lda #' ' | $40 ; Blank, flashing .endif jsr putchardirect ; Returns old character in X ; Wait for keyboard strobe. : inc RNDL ; Increment random counter low bne :+ inc RNDH ; Increment random counter high : lda KBD bpl :-- ; If < 128, no key pressed ; Cursor on ? ldy cursor beq :+ ; Restore old character. pha txa jsr putchardirect pla ; At this time, the high bit of the key pressed is set. : bit KBDSTRB ; Clear keyboard strobe .ifdef __APPLE2ENH__ bit BUTN0 ; Check if OpenApple is down bmi done .endif and #$7F ; If not down, then clear high bit done: ldx #>$0000 rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/chline.s��������������������������������������������������������������������0000664�0000000�0000000�00000002023�13473601511�0016271�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 08.08.1998 ; ; void __fastcall__ chlinexy (unsigned char x, unsigned char y, unsigned char length); ; void __fastcall__ chline (unsigned char length); ; .export _chlinexy, _chline, chlinedirect .import gotoxy, cputdirect .include "zeropage.inc" .include "apple2.inc" _chlinexy: pha ; Save the length jsr gotoxy ; Call this one, will pop params pla ; Restore the length and run into _chline _chline: .ifdef __APPLE2ENH__ ldx #'_' | $80 ; Underscore, screen code .else ldx #'-' | $80 ; Minus, screen code .endif chlinedirect: stx tmp1 cmp #$00 ; Is the length zero? beq done ; Jump if done sta tmp2 : lda tmp1 ; Screen code jsr cputdirect ; Direct output dec tmp2 bne :- done: rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/close.s���������������������������������������������������������������������0000664�0000000�0000000�00000001412�13473601511�0016135�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 30.12.2004 ; ; int __fastcall__ close (int fd); ; .export _close .import closedirect, freebuffer .include "errno.inc" .include "filedes.inc" _close: ; Process fd jsr getfd ; Returns A, Y and C bcs errno ; Check for device bmi zerofd ; Close file jsr closedirect ; Preserves Y bcs oserr ; Mark fdtab slot as free zerofd: lda #$00 sta fdtab + FD::REF_NUM,y ; Cleanup I/O buffer jsr freebuffer ; Return success lda #$00 ; Set __oserror oserr: jmp __mappederrno ; Set __errno errno: jmp __directerrno ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/closedir.c������������������������������������������������������������������0000664�0000000�0000000�00000005411�13473601511�0016617�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* closedir.c */ /* */ /* Close a directory */ /* */ /* */ /* */ /* (C) 2005 Oliver Schmidt, <ol.sc@web.de> */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdlib.h> #include <fcntl.h> #include <dirent.h> #include "dir.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ int __fastcall__ closedir (DIR* dir) { int result; /* Cleanup directory file */ result = close (dir->fd); /* Cleanup DIR */ free (dir); return result; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/clrscr.s��������������������������������������������������������������������0000664�0000000�0000000�00000000172�13473601511�0016322�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Kevin Ruland ; ; void clrscr (void); ; .export _clrscr .import HOME _clrscr := HOME ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/color.s���������������������������������������������������������������������0000664�0000000�0000000�00000000634�13473601511�0016153�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; 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 .import return0, return1 _textcolor := return1 _bgcolor := return0 _bordercolor := return0����������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/cout.s����������������������������������������������������������������������0000664�0000000�0000000�00000000560�13473601511�0016005�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 03.03.2007 ; ; COUT routine ; .export COUT .include "apple2.inc" .segment "LOWCODE" COUT: ; Switch in ROM and call COUT bit $C082 jsr $FDED ; Vector to user output routine ; Switch in LC bank 2 for R/O and return bit $C080 rts ������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/cputc.s���������������������������������������������������������������������0000664�0000000�0000000�00000005403�13473601511�0016152�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; void __fastcall__ cputcxy (unsigned char x, unsigned char y, char c); ; void __fastcall__ cputc (char c); ; .ifdef __APPLE2ENH__ .constructor initconio .endif .export _cputcxy, _cputc .export cputdirect, newline, putchar, putchardirect .import gotoxy, VTABZ .include "apple2.inc" .segment "ONCE" .ifdef __APPLE2ENH__ initconio: sta SETALTCHAR ; Switch in alternate charset bit LORES ; Limit SET80COL-HISCR to text rts .endif .code ; Plot a character - also used as internal function _cputcxy: pha ; Save C jsr gotoxy ; Call this one, will pop params pla ; Restore C and run into _cputc _cputc: cmp #$0D ; Test for \r = carrage return beq left cmp #$0A ; Test for \n = line feed beq newline eor #$80 ; Invert high bit .ifndef __APPLE2ENH__ cmp #$E0 ; Test for lowercase bcc cputdirect and #$DF ; Convert to uppercase .endif cputdirect: jsr putchar inc CH ; Bump to next column lda CH cmp WNDWDTH bcc :+ jsr newline left: lda #$00 ; Goto left edge of screen sta CH : rts newline: inc CV ; Bump to next line lda CV cmp WNDBTM bcc :+ lda WNDTOP ; Goto top of screen sta CV : jmp VTABZ putchar: .ifdef __APPLE2ENH__ ldy INVFLG cpy #$FF ; Normal character display mode? beq putchardirect cmp #$E0 ; Lowercase? bcc mask and #$7F ; Inverse lowercase bra putchardirect .endif mask: and INVFLG ; Apply normal, inverse, flash putchardirect: pha ldy CH .ifdef __APPLE2ENH__ bit RD80VID ; In 80 column mode? bpl put ; No, just go ahead tya lsr ; Div by 2 tay bcs put ; Odd cols go in main memory bit HISCR ; Assume SET80COL .endif put: lda (BASL),Y ; Get current character tax ; Return old character for _cgetc pla sta (BASL),Y .ifdef __APPLE2ENH__ bit LOWSCR ; Doesn't hurt in 40 column mode .endif rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/crt0.s����������������������������������������������������������������������0000664�0000000�0000000�00000013445�13473601511�0015711�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2009-09-15 ; ; Startup code for cc65 (Apple2 version) ; .export _exit, done, return .export __STARTUP__ : absolute = 1 ; Mark as startup .import initlib, donelib .import zerobss, callmain .import __ONCE_LOAD__, __ONCE_SIZE__ ; Linker generated .import __LC_START__, __LC_LAST__ ; Linker generated .include "zeropage.inc" .include "apple2.inc" ; ------------------------------------------------------------------------ .segment "STARTUP" ; ProDOS TechRefMan, chapter 5.2.1: ; "For maximum interrupt efficiency, a system program should not ; use more than the upper 3/4 of the stack." ldx #$FF txs ; Init stack pointer ; Save space by putting some of the start-up code in the ONCE segment, ; which can be re-used by the BSS segment, the heap and the C stack. jsr init ; Clear the BSS data. jsr zerobss ; Push the command-line arguments; and, call main(). jsr callmain ; Avoid a re-entrance of donelib. This is also the exit() entry. _exit: ldx #<exit lda #>exit jsr reset ; Setup RESET vector ; Switch in ROM, in case it wasn't already switched in by a RESET. bit $C082 ; Call the module destructors. jsr donelib ; Restore the original RESET vector. exit: ldx #$02 : lda rvsave,x sta SOFTEV,x dex bpl :- ; Copy back the zero-page stuff. ldx #zpspace-1 : lda zpsave,x sta sp,x dex bpl :- ; ProDOS TechRefMan, chapter 5.2.1: ; "System programs should set the stack pointer to $FF at the ; warm-start entry point." ldx #$FF txs ; Re-init stack pointer ; We're done jmp done ; ------------------------------------------------------------------------ .segment "ONCE" ; Save the zero-page locations that we need. init: ldx #zpspace-1 : lda sp,x sta zpsave,x dex bpl :- ; Save the original RESET vector. ldx #$02 : lda SOFTEV,x sta rvsave,x dex bpl :- ; Check for ProDOS. ldy $BF00 ; MLI call entry point cpy #$4C ; Is MLI present? (JMP opcode) bne basic ; Check the ProDOS system bit map. lda $BF6F ; Protection for pages $B8 - $BF cmp #%00000001 ; Exactly system global page is protected bne basic ; No BASIC.SYSTEM; so, quit to the ProDOS dispatcher instead. lda #<quit ldx #>quit sta done+1 stx done+2 ; No BASIC.SYSTEM; so, use the addr of the ProDOS system global page. lda #<$BF00 ldx #>$BF00 bne :+ ; Branch always ; Get the highest available mem addr from the BASIC interpreter. basic: lda HIMEM ldx HIMEM+1 ; Set up the C stack. : sta sp stx sp+1 ; ProDOS TechRefMan, chapter 5.3.5: ; "Your system program should place in the RESET vector the ; address of a routine that ... closes the files." ldx #<_exit lda #>_exit jsr reset ; Setup RESET vector ; Call the module constructors. jsr initlib ; Switch in LC bank 2 for W/O. bit $C081 bit $C081 ; Set the source start address. ; Aka __LC_LOAD__ iff segment LC exists. lda #<(__ONCE_LOAD__ + __ONCE_SIZE__) ldy #>(__ONCE_LOAD__ + __ONCE_SIZE__) sta $9B sty $9C ; Set the source last address. ; Aka __LC_LOAD__ + __LC_SIZE__ iff segment LC exists. lda #<((__ONCE_LOAD__ + __ONCE_SIZE__) + (__LC_LAST__ - __LC_START__)) ldy #>((__ONCE_LOAD__ + __ONCE_SIZE__) + (__LC_LAST__ - __LC_START__)) sta $96 sty $97 ; Set the destination last address. ; Aka __LC_RUN__ + __LC_SIZE__ iff segment LC exists. lda #<__LC_LAST__ ldy #>__LC_LAST__ sta $94 sty $95 ; Call into Applesoft Block Transfer Up -- which handles zero- ; sized blocks well -- to move the content of the LC memory area. jsr $D39A ; BLTU2 ; Switch in LC bank 2 for R/O and return. bit $C080 rts ; ------------------------------------------------------------------------ .code ; Set up the RESET vector. reset: stx SOFTEV sta SOFTEV+1 eor #$A5 sta PWREDUP return: rts ; Quit to the ProDOS dispatcher. quit: jsr $BF00 ; MLI call entry point .byte $65 ; Quit .word q_param ; ------------------------------------------------------------------------ .rodata ; MLI parameter list for quit q_param:.byte $04 ; param_count .byte $00 ; quit_type .word $0000 ; reserved .byte $00 ; reserved .word $0000 ; reserved ; ------------------------------------------------------------------------ .data ; Final jump when we're done done: jmp DOSWARM ; Potentially patched at runtime ; ------------------------------------------------------------------------ .segment "INIT" zpsave: .res zpspace rvsave: .res 3 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/ctype.s���������������������������������������������������������������������0000664�0000000�0000000�00000020775�13473601511�0016171�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 ���cc65-2.18/libsrc/apple2/curdevice.s�����������������������������������������������������������������0000664�0000000�0000000�00000000761�13473601511�0017007�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2012-10-21 ; ; unsigned char getcurrentdevice (void); ; .export _getcurrentdevice .import __dos_type .include "mli.inc" _getcurrentdevice: ; Use unit number of most recent accessed device lda DEVNUM lsr lsr lsr lsr ; Check for ProDOS 8 ldx __dos_type bne :+ lda #$FF ; INVALID_DEVICE : ldx #$00 rts ���������������cc65-2.18/libsrc/apple2/cvline.s��������������������������������������������������������������������0000664�0000000�0000000�00000002073�13473601511�0016314�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 08.08.1998 ; ; void __fastcall__ cvlinexy (unsigned char x, unsigned char y, unsigned char length); ; void __fastcall__ cvline (unsigned char length); ; .export _cvlinexy, _cvline .import gotoxy, putchar, newline .include "zeropage.inc" _cvlinexy: pha ; Save the length jsr gotoxy ; Call this one, will pop params pla ; Restore the length and run into _cvline _cvline: .ifdef __APPLE2ENH__ ldx #$5F ; Left vertical line MouseText character .else ldx #'!' | $80 ; Exclamation mark, screen code .endif stx tmp1 cmp #$00 ; Is the length zero? beq done ; Jump if done sta tmp2 : lda tmp1 ; Screen code jsr putchar ; Write, no cursor advance jsr newline ; Advance cursor to next line dec tmp2 bne :- done: rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/devicedir.s�����������������������������������������������������������������0000664�0000000�0000000�00000003447�13473601511�0017000�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2010-05-24 ; ; char* __fastcall__ getdevicedir (unsigned char device, char* buf, size_t size); ; .export _getdevicedir .import popptr1, popa .include "zeropage.inc" .include "errno.inc" .include "mli.inc" _getdevicedir: ; Save size sta ptr2 stx ptr2+1 ; Save buf jsr popptr1 ; Set buf ldx ptr1+1 sta mliparam + MLI::ON_LINE::DATA_BUFFER stx mliparam + MLI::ON_LINE::DATA_BUFFER+1 ; Set device jsr popa asl asl asl asl sta mliparam + MLI::ON_LINE::UNIT_NUM ; Check for valid slot and #$70 beq erange ; Check for sufficient buf size lda ptr2+1 bne :++ ; Buf >= 256 lda ptr2 cmp #17 bcs :++ ; Buf >= 17 ; Handle errors erange: lda #<ERANGE jsr __directerrno bne :+ ; Branch always oserr: jsr __mappederrno : lda #$00 ; Return NULL tax rts ; Get volume name : lda #ON_LINE_CALL ldx #ON_LINE_COUNT jsr callmli bcs oserr ; Get volume name length ldy #$00 lda (ptr1),y and #15 ; Max volume name length sta tmp1 ; Add leading slash lda #'/' sta (ptr1),y ; Add terminating zero ldy tmp1 iny lda #$00 sta (ptr1),y sta __oserror ; Clear _oserror ; Success, return buf lda ptr1 ldx ptr1+1 rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/dioclose.s������������������������������������������������������������������0000664�0000000�0000000�00000000340�13473601511�0016630�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 24.03.2005 ; ; unsigned char __fastcall__ dio_close (dhandle_t handle); ; .export _dio_close .import dioepilog _dio_close: lda #$00 jmp dioepilog ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/diocommon.s�����������������������������������������������������������������0000664�0000000�0000000�00000001467�13473601511�0017026�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 24.03.2005 ; .export dioprolog, diocommon, dioepilog .import popax .include "errno.inc" .include "mli.inc" dioprolog: ; Set buffer sta mliparam + MLI::RW_BLOCK::DATA_BUFFER stx mliparam + MLI::RW_BLOCK::DATA_BUFFER+1 ; Get and set sect_num jsr popax sta mliparam + MLI::RW_BLOCK::BLOCK_NUM stx mliparam + MLI::RW_BLOCK::BLOCK_NUM+1 ; Get and set handle jsr popax sta mliparam + MLI::RW_BLOCK::UNIT_NUM rts diocommon: ; Call read_block or write_block ldx #RW_BLOCK_COUNT jsr callmli dioepilog: ; Return success or error sta __oserror ldx #$00 rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/dioopen.s�������������������������������������������������������������������0000664�0000000�0000000�00000001456�13473601511�0016475�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 24.03.2005 ; ; dhandle_t __fastcall__ dio_open (unsigned char device); ; .export _dio_open .import return0, __dos_type, isdevice .include "errno.inc" .include "mli.inc" _dio_open: ; Check for ProDOS 8 ldx __dos_type bne :+ lda #$01 ; "Bad system call number" bne oserr ; Branch always ; Check for valid device : tax jsr isdevice beq :+ lda #$28 ; "No device connected" ; Return oserror oserr: sta __oserror jmp return0 ; Return success : txa asl asl asl asl ldx #$00 stx __oserror rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/dioread.s�������������������������������������������������������������������0000664�0000000�0000000�00000000522�13473601511�0016440�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 24.03.2005 ; ; unsigned char __fastcall__ dio_read (dhandle_t handle, unsigned sect_num, void *buffer); ; .export _dio_read .import dioprolog, diocommon .include "mli.inc" _dio_read: jsr dioprolog lda #READ_BLOCK_CALL jmp diocommon ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/diosectcount.s��������������������������������������������������������������0000664�0000000�0000000�00000004476�13473601511�0017550�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 31.03.2005 ; ; unsigned __fastcall__ dio_query_sectcount (dhandle_t handle); ; .export _dio_query_sectcount .import _dio_query_sectsize, _malloc, _free .include "zeropage.inc" .include "errno.inc" .include "mli.inc" _dio_query_sectcount: ; Set handle sta mliparam + MLI::ON_LINE::UNIT_NUM ; Get ProDOS 8 block size (clears __oserror) jsr _dio_query_sectsize ; Alloc buffer jsr _malloc sta ptr4 stx ptr4+1 ; Set buffer sta mliparam + MLI::ON_LINE::DATA_BUFFER stx mliparam + MLI::ON_LINE::DATA_BUFFER+1 ; Check buffer (hibyte is enough) txa beq nomem ; Get device state lda #ON_LINE_CALL ldx #ON_LINE_COUNT jsr callmli bcs check ; UNIT_NUM already set .assert MLI::RW_BLOCK::UNIT_NUM = MLI::ON_LINE::UNIT_NUM, error ; DATA_BUFFER already set .assert MLI::RW_BLOCK::DATA_BUFFER = MLI::ON_LINE::DATA_BUFFER, error ; Read volume directory key block tax ; A = 0 lda #$02 sta mliparam + MLI::RW_BLOCK::BLOCK_NUM stx mliparam + MLI::RW_BLOCK::BLOCK_NUM+1 lda #READ_BLOCK_CALL ldx #RW_BLOCK_COUNT jsr callmli bcs oserr ; Get and save total blocks from volume directory header ldy #$29 lda (ptr4),y pha iny lda (ptr4),y pha ; Cleanup buffer done: lda ptr4 ldx ptr4+1 jsr _free ; Restore total blocks and return pla tax pla rts nomem: lda #$FF ; Error code for sure not used by MLI oserr: sta __oserror ; Save total blocks for failure lda #$00 pha pha beq done ; Branch always ; Check for non-ProDOS disk check: cmp #$52 ; "Not a ProDOS volume" bne oserr sta __oserror ; Save total blocks for a 16-sector disk lda #<280 pha lda #>280 pha bne done ; Branch always ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/diosectsize.s���������������������������������������������������������������0000664�0000000�0000000�00000000570�13473601511�0017361�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 31.03.2005 ; ; unsigned __fastcall__ dio_query_sectsize (dhandle_t handle); ; .export _dio_query_sectsize .include "errno.inc" _dio_query_sectsize: ; Clear error stx __oserror ; X = 0 ; Return ProDOS 8 block size txa ; X = 0 ldx #>512 rts ����������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/diowrite.s������������������������������������������������������������������0000664�0000000�0000000�00000000534�13473601511�0016662�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 24.03.2005 ; ; unsigned char __fastcall__ dio_write (dhandle_t handle, unsigned sect_num, const void *buffer); ; .export _dio_write .import dioprolog, diocommon .include "mli.inc" _dio_write: jsr dioprolog lda #WRITE_BLOCK_CALL jmp diocommon ��������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/dir.h�����������������������������������������������������������������������0000664�0000000�0000000�00000005641�13473601511�0015603�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* dir.h */ /* */ /* Apple ][ system specific DIR */ /* */ /* */ /* */ /* (C) 2005 Oliver Schmidt, <ol.sc@web.de> */ /* */ /* */ /* 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 _DIR_H #define _DIR_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ struct DIR { int fd; unsigned char entry_length; unsigned char entries_per_block; unsigned char current_entry; union { unsigned char bytes[512]; struct { unsigned prev_block; unsigned next_block; unsigned char entries[1]; } content; } block; }; /* End of dir.h */ #endif �����������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/doesclrscr.s����������������������������������������������������������������0000664�0000000�0000000�00000000744�13473601511�0017202�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2016-06-05 ; ; unsigned char doesclrscrafterexit (void); ; .export _doesclrscrafterexit .import done .include "apple2.inc" _doesclrscrafterexit: ; If the page we jump to when done equals the page ; of the warmstart vector we'll return to BASIC so ; there's no implicit clrscr() after exit(). lda done+2 sec sbc #>DOSWARM ldx #>$0000 rts ����������������������������cc65-2.18/libsrc/apple2/dosdetect.s�����������������������������������������������������������������0000664�0000000�0000000�00000002155�13473601511�0017013�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 08.03.2004 ; ; Identify DOS version we're running on as one of these: ; ; AppleDOS 3.3 - $00 ; ProDOS 8 1.0.1 - $10 ; ProDOS 8 1.0.2 - $10 ; ProDOS 8 1.1.1 - $11 ; ProDOS 8 1.2 - $12 ; ProDOS 8 1.3 - $13 ; ProDOS 8 1.4 - $14 ; ProDOS 8 1.5 - $15 ; ProDOS 8 1.6 - $16 ; ProDOS 8 1.7 - $17 ; ProDOS 8 1.8 - $18 ; ProDOS 8 1.9 - $18 ; ProDOS 8 2.0.1 - $21 ; ProDOS 8 2.0.2 - $22 ; ProDOS 8 2.0.3 - $23 ; .constructor initdostype, 25 .export __dos_type .include "mli.inc" ; Identify DOS version according to: ; - Beneath Apple ProDOS, chapter 6-63 ; - Apple II ProDOS 8 TechNote #23, ProDOS 8 Changes and Minutia ; - ProDOS TechRefMan, chapter 5.2.4 .segment "ONCE" initdostype: lda $BF00 cmp #$4C ; Is MLI present? (JMP opcode) bne done lda KVERSION ; ProDOS 8 kernel version cmp #$10 bcs :+ ora #$10 ; Make high nibble match major version : sta __dos_type done: rts .data __dos_type: .byte $00 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/emd/������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015413�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/emd/a2.auxmem.s�������������������������������������������������������������0000664�0000000�0000000�00000014116�13473601511�0017377�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Extended memory driver for the Apple II auxiliary memory ; ; Stefan Haubenthal, 2003-12-12 ; Ullrich von Bassewitz, 2002-12-02 ; .include "zeropage.inc" .include "em-kernel.inc" .include "em-error.inc" .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table .ifdef __APPLE2ENH__ module_header _a2e_auxmem_emd .else module_header _a2_auxmem_emd .endif ; Driver signature .byte $65, $6d, $64 ; "emd" .byte EMD_API_VERSION ; EM API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr PAGECOUNT .addr MAP .addr USE .addr COMMIT .addr COPYFROM .addr COPYTO ; ------------------------------------------------------------------------ ; Constants BASE = $0200 AUXCARD = $C30C ; Card signature AUXMOVE = $C311 ; Auxiliary move routine PAGES = ($C000 - BASE) / 256 ; ------------------------------------------------------------------------ ; Data. .data curpage: .byte $FF ; Current page number (invalid) .bss window: .res 256 ; Memory "window" .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present and determine the amount of ; memory available. ; Must return an EM_ERR_xx code in a/x. ; INSTALL: ldx #0 lda AUXCARD and #$f0 cmp #$80 bne @L1 lda #EM_ERR_OK rts @L1: lda #EM_ERR_NO_DEVICE ; rts ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; PAGECOUNT: Return the total number of available pages in a/x. ; PAGECOUNT: lda #<PAGES ldx #>PAGES rts ; ------------------------------------------------------------------------ ; MAP: Map the page in a/x into memory and return a pointer to the page in ; a/x. The contents of the currently mapped page (if any) may be discarded ; by the driver. ; MAP: sta curpage ; Remember the new page clc adc #>BASE sta ptr1+1 ldy #$00 sty ptr1 lda #<window sta ptr2 lda #>window sta ptr2+1 ; Transfer one page clc ; Direction flag jsr transfer ; Transfer one page ; Return the memory window lda #<window ldx #>window ; Return the window address ; Done done: rts ; ------------------------------------------------------------------------ ; USE: Tell the driver that the window is now associated with a given page. USE: sta curpage ; Remember the page lda #<window ldx #>window ; Return the window rts ; ------------------------------------------------------------------------ ; COMMIT: Commit changes in the memory window to extended storage. COMMIT: lda curpage ; Get the current page cmp #$FF beq done ; Jump if no page mapped clc adc #>BASE sta ptr2+1 ldy #$00 sty ptr2 lda #<window sta ptr1 lda #>window sta ptr1+1 lda #<$FF sta ptr4 lda #>$FF sta ptr4+1 sec ; Direction flag ; Transfer one page/all bytes transfer: php clc lda ptr1 sta $3C adc ptr4 sta $3E lda ptr1+1 sta $3D adc ptr4+1 sta $3F lda ptr2 sta $42 lda ptr2+1 sta $43 plp jmp AUXMOVE ; ------------------------------------------------------------------------ ; COPYFROM: Copy from extended into linear memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYFROM: sta ptr3 stx ptr3+1 ; Save the passed em_copy pointer ldy #EM_COPY::OFFS lda (ptr3),y sta ptr1 ldy #EM_COPY::PAGE lda (ptr3),y clc adc #>BASE sta ptr1+1 ; From ldy #EM_COPY::BUF lda (ptr3),y sta ptr2 iny lda (ptr3),y sta ptr2+1 ; To clc ; Direction flag common: ldy #EM_COPY::COUNT lda (ptr3),y ; Get bytes in last page sta ptr4 iny lda (ptr3),y ; Get number of pages sta ptr4+1 jmp transfer ; ------------------------------------------------------------------------ ; COPYTO: Copy from linear into extended memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYTO: sta ptr3 stx ptr3+1 ; Save the passed em_copy pointer ldy #EM_COPY::OFFS lda (ptr3),y sta ptr2 ldy #EM_COPY::PAGE lda (ptr3),y clc adc #>BASE sta ptr2+1 ; To ldy #EM_COPY::BUF lda (ptr3),y sta ptr1 iny lda (ptr3),y sta ptr1+1 ; From sec ; Direction flag jmp common ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/exec.s����������������������������������������������������������������������0000664�0000000�0000000�00000020530�13473601511�0015756�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2011-01-26 ; ; int __fastcall__ exec (const char* progname, const char* cmdline); ; .export _exec .import pushname, popname .import popax, done, _exit .include "zeropage.inc" .include "errno.inc" .include "apple2.inc" .include "mli.inc" ; Wrong file type typerr: lda #$4A ; "Incompatible file format" ; Cleanup name oserr: jsr popname ; Preserves A ; Set __oserror 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 sta mliparam + MLI::INFO::PATHNAME stx mliparam + MLI::INFO::PATHNAME+1 ; Get file_type and aux_type lda #GET_INFO_CALL ldx #GET_INFO_COUNT jsr callmli bcs oserr ; If we get here the program file at least exists so we copy ; the loader stub right now and patch it later to set params ldx #size - 1 : lda source,x sta target,x dex bpl :- ; Check program file type 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 ; 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 #%00000000 ; Protect no page dex bpl :- bmi prodos ; Branch always binary: cmp #$06 ; BIN file? bne typerr ; No, wrong file type ; Set BIN program load addr lda mliparam + MLI::INFO::AUX_TYPE ldx mliparam + MLI::INFO::AUX_TYPE+1 sta data_buffer stx data_buffer+1 ; Check ProDOS system bit map for presence of BASIC.SYSTEM lda $BF6F ; Protection for pages $B8 - $BF cmp #%00000001 ; Exactly system global page is protected beq setvec ; Get highest available mem addr from BASIC.SYSTEM ldx HIMEM+1 ; High byte bne setbuf ; Branch always ; BIN programs are supposed to quit through one of the two DOS ; vectors so we set up those to point to the ProDOS dispatcher setvec: ldx #$03 - 1 ; Size of JMP opcode : lda dosvec,x sta DOSWARM,x ; DOS warm start sta DOSWARM + 3,x ; DOS cold start dex bpl :- ; No BASIC.SYSTEM so use addr of ProDOS system global page prodos: ldx #>$BF00 ; High byte ; The I/O buffer needs to be page aligned setbuf: lda #$00 ; Low byte ; The I/O buffer needs four pages dex dex dex dex ; Set I/O buffer sta mliparam + MLI::OPEN::IO_BUFFER stx mliparam + MLI::OPEN::IO_BUFFER+1 ; PATHNAME already set .assert MLI::OPEN::PATHNAME = MLI::INFO::PATHNAME, error ; Lower file level to avoid program file ; being closed by C libary shutdown code ldx LEVEL stx level beq :+ dec LEVEL ; Open file : lda #OPEN_CALL ldx #OPEN_COUNT jsr callmli ; Restore file level ldx level stx LEVEL bcc :+ jmp oserr ; Get and save fd : lda mliparam + MLI::OPEN::REF_NUM sta read_ref sta close_ref .ifdef __APPLE2ENH__ ; Calling the 80 column firmware needs the ROM switched ; in, otherwise it copies the F8 ROM to the LC (@ $CEF4) bit $C082 ; ProDOS TechRefMan, chapter 5.3.1.3: ; "80-column text cards -- and other Apple IIe features -- can ; be turned off using the following sequence of instructions:" lda #$15 jsr $C300 ; Switch in LC bank 2 for R/O 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 ldx #>target sta done+1 stx done+2 ; Initiate C libary shutdown jmp _exit .bss level : .res 1 .rodata ; Read whole program file source: jsr $BF00 .byte READ_CALL .word read_param bcs error ; Close program file jsr $BF00 .byte CLOSE_CALL .word close_param 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 #$4C cmp $2000 bne jump lda #$EE cmp $2003 bne jump cmp $2004 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 ... jump: jmp (data_buffer) file_type = * - source + target .byte $00 read_param = * - source + target .byte $04 ; PARAM_COUNT read_ref = * - source + target .byte $00 ; REF_NUM data_buffer = * - source + target .addr $2000 ; DATA_BUFFER .word $FFFF ; REQUEST_COUNT .word $0000 ; TRANS_COUNT close_param = * - source + target .byte $01 ; PARAM_COUNT close_ref = * - source + target .byte $00 ; REF_NUM ; Quit to ProDOS dispatcher quit = * - source + target error: jsr $BF00 .byte $65 ; QUIT .word quit_param quit_param = * - source + target .byte $04 ; PARAM_COUNT .byte $00 ; QUIT_TYPE .word $0000 ; RESERVED .byte $00 ; RESERVED .word $0000 ; RESERVED size = * - source target = DOSWARM - size dosvec: jmp quit ������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/exehdr.s��������������������������������������������������������������������0000664�0000000�0000000�00000003470�13473601511�0016315�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2012-06-10 ; ; This module supplies an AppleSingle version 2 file header + entry with ; ID 11 according to https://tools.ietf.org/rfc/rfc1740.txt Appendix A. ; .export __EXEHDR__ : absolute = 1 ; Linker referenced .import __FILETYPE__ ; Linker generated .import __MAIN_START__, __MAIN_LAST__ ; Linker generated ; ------------------------------------------------------------------------ ; Data Fork ID01_LENGTH = __MAIN_LAST__ - __MAIN_START__ ID01_OFFSET = ID01 - START ; ProDOS File Info ID11_LENGTH = ID01 - ID11 ID11_OFFSET = ID11 - START ; ------------------------------------------------------------------------ .segment "EXEHDR" START: .byte $00, $05, $16, $00 ; Magic number .byte $00, $02, $00, $00 ; Version number .res 16 ; Filler .byte 0, 2 ; Number of entries .byte 0, 0, 0, 1 ; Entry ID 1 - Data Fork .byte 0, 0, >ID01_OFFSET, <ID01_OFFSET ; Offset .byte 0, 0, >ID01_LENGTH, <ID01_LENGTH ; Length .byte 0, 0, 0, 11 ; Entry ID 11 - ProDOS File Info .byte 0, 0, >ID11_OFFSET, <ID11_OFFSET ; Offset .byte 0, 0, >ID11_LENGTH, <ID11_LENGTH ; Length ID11: .byte 0, %11000011 ; Access - Destroy, Rename, Write, Read .byte >__FILETYPE__, <__FILETYPE__ ; File Type .byte 0, 0 ; Auxiliary Type high .byte >__MAIN_START__, <__MAIN_START__ ; Auxiliary Type low ID01: ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/extra/����������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015771�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/extra/iobuf-0800.s����������������������������������������������������������0000664�0000000�0000000�00000003571�13473601511�0017654�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 15.09.2009 ; ; ProDOS 8 I/O buffer management for memory between ; location $0800 and the cc65 program start address ; .constructor initiobuf .export iobuf_alloc, iobuf_free .import __MAIN_START__ .import incsp2, popptr1 .include "zeropage.inc" .include "errno.inc" .include "../filedes.inc" .segment "ONCE" initiobuf: ; Convert end address highbyte to table index lda #>__MAIN_START__ sec sbc #>$0800 lsr lsr ; Mark all remaining table entries as used tax lda #$FF : cpx #MAX_FDS bcc :+ rts : sta table,x inx bne :-- ; Branch always ; ------------------------------------------------------------------------ .code iobuf_alloc: ; Get and save "memptr" jsr incsp2 jsr popptr1 ; Search table for free entry ldx #$00 : lda table,x beq :+ inx cpx #MAX_FDS bcc :- lda #ENOMEM rts ; Mark table entry as used : lda #$FF sta table,x ; Convert table index to address hibyte txa asl asl clc adc #>$0800 ; Store address in "memptr" ldy #$01 sta (ptr1),y dey tya sta (ptr1),y rts iobuf_free: ; Convert address hibyte to table index txa sec sbc #>$0800 lsr lsr ; Mark table entry as free tax lda #$00 sta table,x rts ; ------------------------------------------------------------------------ .data table: .res MAX_FDS ���������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/filedes.inc�����������������������������������������������������������������0000664�0000000�0000000�00000000446�13473601511�0016760�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 30.12.2004 ; ; File descriptor management for the POSIX I/O routines ; .struct FD REF_NUM .byte FLAGS .byte BUFFER .addr .endstruct .global fdtab .global getfd MAX_FDS = 8 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/filedes.s�������������������������������������������������������������������0000664�0000000�0000000�00000002470�13473601511�0016450�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 30.12.2004 ; ; File descriptor management for the POSIX I/O routines ; .include "errno.inc" .include "fcntl.inc" .include "filedes.inc" getfd: ; Check for handle >= 256 cpx #$00 bne error ; Check for handle >= MAX_FDS cmp #MAX_FDS bcs error ; Convert handle to fdtab slot .assert .sizeof(FD) = 4, error asl asl ; Check for fdtab slot in use tay lda fdtab + FD::REF_NUM,y beq error ; Return success clc rts ; Load errno code and return error error: lda #EINVAL sec rts .data fdtab: .assert .sizeof(FD) = 4, error .byte $80 ; STDIN_FILENO ::REF_NUM .byte O_RDONLY ; STDIN_FILENO ::FLAGS .addr $0000 ; STDIN_FILENO ::BUFFER .byte $80 ; STDOUT_FILENO::REF_NUM .byte O_WRONLY ; STDOUT_FILENO::FLAGS .addr $0000 ; STDOUT_FILENO::BUFFER .byte $80 ; STDERR_FILENO::REF_NUM .byte O_WRONLY ; STDERR_FILENO::FLAGS .addr $0000 ; STDERR_FILENO::BUFFER .res (MAX_FDS - 3) * .sizeof(FD) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/filename.s������������������������������������������������������������������0000664�0000000�0000000�00000004511�13473601511�0016613�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 30.12.2004 ; ; File name handling for ProDOS 8 file I/O ; .export pushname, popname .import subysp, addysp, decsp1 .include "zeropage.inc" .include "mli.inc" pushname: sta ptr1 stx ptr1+1 ; Alloc pathname buffer ldy #64+1 ; Max pathname length + zero jsr subysp ; Check for full pathname ldy #$00 lda (ptr1),y cmp #'/' beq copy ; Check for system prefix lda PFIXPTR bne copy ; Use unit number of most recent accessed device lda DEVNUM sta mliparam + MLI::ON_LINE::UNIT_NUM ; Use allocated pathname buffer lda sp ldx sp+1 sta mliparam + MLI::ON_LINE::DATA_BUFFER stx mliparam + MLI::ON_LINE::DATA_BUFFER+1 ; Get volume name lda #ON_LINE_CALL ldx #ON_LINE_COUNT jsr callmli bcs addsp65 ; Get volume name length lda (sp),y and #15 ; Max volume name length ; Bracket volume name with slashes to form prefix sta tmp1 lda #'/' sta (sp),y ldy tmp1 iny ; Leading slash sta (sp),y iny ; Trailing slash ; Adjust source pointer for copy sty tmp1 lda ptr1 sec sbc tmp1 bcs :+ dec ptr1+1 : sta ptr1 ; Copy source to allocated pathname buffer copy: lda (ptr1),y sta (sp),y beq setlen iny cpy #64+1 ; Max pathname length + zero bcc copy ; Load oserror code lda #$40 ; "Invalid pathname" ; Free pathname buffer addsp65:ldy #64+1 bne addsp ; Branch always ; Alloc and set length byte setlen: tya jsr decsp1 ; Preserves A ldy #$00 sta (sp),y ; Return success tya rts popname: ; Cleanup stack ldy #1 + 64+1 ; Length byte + max pathname length + zero addsp: jmp addysp ; Preserves A ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/get_ostype.s����������������������������������������������������������������0000664�0000000�0000000�00000004177�13473601511�0017225�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 04.01.2005 ; ; unsigned char get_ostype (void) ; .constructor initostype .export _get_ostype ; Identify machine according to: ; Apple II Miscellaneous TechNote #7, Apple II Family Identification .segment "ONCE" initostype: sec jsr $FE1F bcs nogs tya ora #$80 done: sta ostype rts nogs: ldx #$FF next: inx lda value,x ldy index,x beq done ; $00 is no valid index cmp $FB00,y beq next : inx ldy index,x bne :- beq next ; Branch always index: .byte $B3, $00 ; Apple ][ .byte $B3, $1E, $00 ; Apple ][+ .byte $B3, $1E, $00 ; Apple /// (emulation) .byte $B3, $C0, $00 ; Apple //e .byte $B3, $C0, $DD, $BE, $00 ; Apple //e Option Card .byte $B3, $C0, $00 ; Apple //e (enhanced) .byte $B3, $C0, $BF, $00 ; Apple //c .byte $B3, $C0, $BF, $00 ; Apple //c (3.5 ROM) .byte $B3, $C0, $BF, $00 ; Apple //c (Mem. Exp.) .byte $B3, $C0, $BF, $00 ; Apple //c (Rev. Mem. Exp.) .byte $B3, $C0, $BF, $00 ; Apple //c Plus .byte $00 value: .byte $38, $10 ; Apple ][ .byte $EA, $AD, $11 ; Apple ][+ .byte $EA, $8A, $20 ; Apple /// (emulation) .byte $06, $EA, $30 ; Apple //e .byte $06, $E0, $02, $00, $40 ; Apple //e Option Card .byte $06, $E0, $31 ; Apple //e (enhanced) .byte $06, $00, $FF, $50 ; Apple //c .byte $06, $00, $00, $51 ; Apple //c (3.5 ROM) .byte $06, $00, $03, $53 ; Apple //c (Mem. Exp.) .byte $06, $00, $04, $54 ; Apple //c (Rev. Mem. Exp.) .byte $06, $00, $05, $55 ; Apple //c Plus .byte $00 .code _get_ostype: lda ostype ldx #$00 rts .segment "INIT" ostype: .res 1 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/getdevice.s�����������������������������������������������������������������0000664�0000000�0000000�00000001253�13473601511�0016772�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2012-09-04 ; ; unsigned char getfirstdevice (void); ; unsigned char __fastcall__ getnextdevice (unsigned char device); ; .export _getfirstdevice .export _getnextdevice .import __dos_type, isdevice .include "zeropage.inc" _getfirstdevice: lda #$FF ; Fall through _getnextdevice: tax next: inx cpx #$FF ; INVALID_DEVICE beq done ; Check for ProDOS 8 lda __dos_type beq next ; Check for valid device jsr isdevice bne next done: txa ldx #$00 rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/getres.s��������������������������������������������������������������������0000664�0000000�0000000�00000002345�13473601511�0016327�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 15.08.2018 ; ; int __fastcall__ clock_getres (clockid_t clk_id, struct timespec *res); ; .import __dos_type .import incsp1, return0 .include "time.inc" .include "zeropage.inc" .include "errno.inc" .include "mli.inc" _clock_getres: sta ptr1 stx ptr1+1 ; Cleanup stack jsr incsp1 ; Check for ProDOS 8 lda __dos_type beq enosys ; Presume day resolution ldx #<day_res ldy #>day_res ; Check for existing minutes or hours lda TIMELO ora TIMELO+1 beq :+ ; Switch to minute resolution ldx #<min_res ldy #>min_res ; Copy timespec : stx ptr2 sty ptr2+1 ldy #.sizeof(timespec)-1 : lda (ptr2),y sta (ptr1),y dey bpl :- ; Return success jmp return0 ; Load errno code enosys: lda #ENOSYS ; Set __errno jmp __directerrno .rodata min_res:.dword 60 .dword 0 day_res:.dword 60 * 60 * 24 .dword 0 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/gettime.s�������������������������������������������������������������������0000664�0000000�0000000�00000004200�13473601511�0016464�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 14.08.2018 ; ; int __fastcall__ clock_gettime (clockid_t clk_id, struct timespec *tp); ; .import pushax, steaxspidx, incsp1, incsp3, return0 .include "time.inc" .include "zeropage.inc" .include "errno.inc" .include "mli.inc" _clock_gettime: jsr pushax ; Clear tv_nsec (+ tv_sec) sta ptr1 stx ptr1+1 lda #$00 ldy #.sizeof(timespec)-1 : sta (ptr1),y dey bpl :- ; Update date + time lda #GET_TIME_CALL ldx #GET_TIME_COUNT jsr callmli bcs oserr ; Get date lda DATELO+1 lsr php ; Save month msb cmp #70 ; Year < 70? bcs :+ ; No, leave alone adc #100 ; Move 19xx to 20xx : sta TM + tm::tm_year lda DATELO tax ; Save day plp ; Restore month msb ror lsr lsr lsr lsr beq erange ; [1..12] allows for validity check tay dey ; Move [1..12] to [0..11] sty TM + tm::tm_mon txa ; Restore day and #%00011111 sta TM + tm::tm_mday ; Get time lda TIMELO+1 sta TM + tm::tm_hour lda TIMELO sta TM + tm::tm_min ; Make time_t lda #<TM ldx #>TM jsr _mktime ; Store tv_sec ldy #timespec::tv_sec jsr steaxspidx ; Cleanup stack jsr incsp1 ; Return success jmp return0 ; Load errno code erange: lda #ERANGE ; Cleanup stack jsr incsp3 ; Preserves A ; Set __errno jmp __directerrno ; Cleanup stack oserr: jsr incsp3 ; Preserves A ; Set __oserror jmp __mappederrno .bss TM: .tag tm ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/gotoxy.s��������������������������������������������������������������������0000664�0000000�0000000�00000001026�13473601511�0016362�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; void __fastcall__ gotoxy (unsigned char x, unsigned char y); ; void __fastcall__ gotox (unsigned char x); ; .export gotoxy, _gotoxy, _gotox .import popa, VTABZ .include "apple2.inc" gotoxy: jsr popa ; Get Y _gotoxy: clc adc WNDTOP sta CV ; Store Y jsr VTABZ jsr popa ; Get X _gotox: sta CH ; Store X rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/gotoy.s���������������������������������������������������������������������0000664�0000000�0000000�00000000451�13473601511�0016173�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; void __fastcall__ gotoy (unsigned char y); ; .export _gotoy .import VTABZ .include "apple2.inc" _gotoy: clc adc WNDTOP sta CV ; Store Y jmp VTABZ �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/home.s����������������������������������������������������������������������0000664�0000000�0000000�00000000554�13473601511�0015766�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 03.03.2007 ; ; HOME routine ; .export HOME .include "apple2.inc" .segment "LOWCODE" HOME: ; Switch in ROM and call HOME bit $C082 jsr $FC58 ; Clear current text screen ; Switch in LC bank 2 for R/O and return bit $C080 rts ����������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/initcwd.s�������������������������������������������������������������������0000664�0000000�0000000�00000001540�13473601511�0016473�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 18.04.2005 ; .export initcwd .import __cwd .include "zeropage.inc" .include "mli.inc" initcwd: ; Set static prefix buffer lda #<__cwd ldx #>__cwd sta mliparam + MLI::PREFIX::PATHNAME stx mliparam + MLI::PREFIX::PATHNAME+1 ; Get current working directory lda #GET_PREFIX_CALL ldx #PREFIX_COUNT jsr callmli ; Check for null prefix ldx __cwd beq done ; Remove length byte and trailing slash dex stx tmp1 ldx #$00 : lda __cwd + 1,x sta __cwd,x inx cpx tmp1 bcc :- ; Add terminating zero lda #$00 sta __cwd,x done: rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/iobuf.s���������������������������������������������������������������������0000664�0000000�0000000�00000000341�13473601511�0016134�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 10.9.2009 ; ; Default ProDOS 8 I/O buffer management ; .export iobuf_alloc, iobuf_free .import _posix_memalign, _free iobuf_alloc := _posix_memalign iobuf_free := _free �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/irq.s�����������������������������������������������������������������������0000664�0000000�0000000�00000004552�13473601511�0015633�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2012-11-17 ; ; IRQ handling (Apple2 version) ; .export initirq, doneirq .import callirq, __dos_type, _exit .include "apple2.inc" .macpack apple2 .segment "ONCE" initirq: ; Check for ProDOS lda __dos_type beq prterr ; Allocate interrupt vector table entry jsr $BF00 ; MLI call entry point .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 prterr: ldx #msglen-1 : lda errmsg,x jsr $FDED ; COUT dex bpl :- jmp _exit errmsg: .ifdef __APPLE2ENH__ scrcode $0D, "tpurretni colla ot deliaF", $0D .else scrcode $0D, "TPURRETNI COLLA OT DELIAF", $0D .endif msglen = * - errmsg .code doneirq: ; Check for valid interrupt vector table entry number which ; IS necessary as this gets called even if initirq failed. lda int_num beq :+ ; Deallocate interrupt vector table entry dec i_param ; Adjust parameter count jsr $BF00 ; MLI call entry point .byte $41 ; Dealloc interrupt .addr i_param : rts .segment "LOWCODE" intptr: ; ProDOS TechRefMan, chapter 6.2: ; "Each installed routine must begin with a CLD instruction." cld ; Call interruptors and check for success jsr callirq bcc :+ ; ProDOS TechRefMan, chapter 6.2: ; "When the routine that can process the interrupt is called, it ; should ... return (via an RTS) with the carry flag clear." clc rts ; ProDOS TechRefMan, chapter 6.2: ; "When a routine that cannot process the interrupt is called, ; it should return (via an RTS) with the cary flag set ..." : sec rts .data ; MLI parameter list for (de)alloc interrupt i_param:.byte $02 ; param_count int_num:.byte $00 ; int_num .addr intptr ; int_code ������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/isdevice.s������������������������������������������������������������������0000664�0000000�0000000�00000000540�13473601511�0016624�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2012-10-15 ; .export isdevice .include "zeropage.inc" .include "mli.inc" isdevice: ldy DEVCNT : lda DEVLST,y lsr lsr lsr lsr sta tmp1 cpx tmp1 beq :+ dey bpl :- : rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/joy/������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015447�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/joy/a2.stdjoy.s�������������������������������������������������������������0000664�0000000�0000000�00000007031�13473601511�0017451�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Standard joystick driver for the Apple ][. May be used multiple times ; when statically linked to the application. ; ; Ullrich von Bassewitz, 2003-05-02 ; Oliver Schmidt, 2008-02-25 ; Using the readjoy code from Stefan Haubenthal ; .include "zeropage.inc" .include "joy-kernel.inc" .include "joy-error.inc" .include "apple2.inc" .macpack module ; ------------------------------------------------------------------------ ; Constants THRESHOLD = 20 ; Deviation from center triggering movement ; ------------------------------------------------------------------------ ; ROM entry points PREAD := $FB1E ; Read paddle in X, return AD conv. value in Y ; ------------------------------------------------------------------------ ; Header. Includes jump table. .ifdef __APPLE2ENH__ module_header _a2e_stdjoy_joy .else module_header _a2_stdjoy_joy .endif ; Driver signature .byte $6A, $6F, $79 ; "joy" .byte JOY_API_VERSION ; Driver API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr COUNT .addr READJOY ; ------------------------------------------------------------------------ .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 ; Fall through ; UNINSTALL 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. COUNT: lda #$02 ; Number of joysticks we support ldx #$00 rts ; READ: Read a particular joystick passed in A. READJOY: bit $C082 ; Switch in ROM and #$01 ; Restrict joystick number ; Read horizontal paddle asl ; Joystick number -> paddle number tax ; Set paddle number (0, 2) jsr PREAD ; Read paddle value lda #$00 ; 0 0 0 0 0 0 0 0 cpy #127 - THRESHOLD ror ; !LEFT 0 0 0 0 0 0 0 cpy #127 + THRESHOLD ror ; RIGHT !LEFT 0 0 0 0 0 0 ; Read vertical paddle pha inx ; Set paddle number (1, 3) jsr PREAD ; Read paddle value pla cpy #127 - THRESHOLD ror ; !UP RIGHT !LEFT 0 0 0 0 0 cpy #127 + THRESHOLD ror ; DOWN !UP RIGHT !LEFT 0 0 0 0 ; Read primary button tay lda BUTN0-1,x ; Check button (1, 3) asl tya ror ; BTN DOWN !UP RIGHT !LEFT 0 0 0 ; Read secondary button tay inx txa and #$03 ; IIgs has fourth button at TAPEIN tax lda BUTN0-1,x ; Check button (2, 0) asl tya ror ; BTN2 BTN DOWN !UP RIGHT !LEFT 0 0 ; Finalize eor #%00010100 ; BTN2 BTN DOWN UP RIGHT LEFT 0 0 ldx #$00 bit $C080 ; Switch in LC bank 2 for R/O rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/joy_stat_stddrv.s�����������������������������������������������������������0000664�0000000�0000000�00000000646�13473601511�0020262�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Address of the static standard joystick driver ; ; Oliver Schmidt, 2012-11-01 ; ; const void joy_static_stddrv[]; ; .export _joy_static_stddrv .ifdef __APPLE2ENH__ .import _a2e_stdjoy_joy .else .import _a2_stdjoy_joy .endif .rodata .ifdef __APPLE2ENH__ _joy_static_stddrv := _a2e_stdjoy_joy .else _joy_static_stddrv := _a2_stdjoy_joy .endif ������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/joy_stddrv.s����������������������������������������������������������������0000664�0000000�0000000�00000000437�13473601511�0017225�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Name of the standard joystick driver ; ; Ullrich von Bassewitz, 2002-12-21 ; ; const char joy_stddrv[]; ; .export _joy_stddrv .rodata _joy_stddrv: .ifdef __APPLE2ENH__ .asciiz "A2E.STDJOY.JOY" .else .asciiz "A2.STDJOY.JOY" .endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/kbhit.s���������������������������������������������������������������������0000664�0000000�0000000�00000000530�13473601511�0016131�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Kevin Ruland ; Ullrich von Bassewitz, 2005-03-25 ; ; unsigned char kbhit (void); ; .export _kbhit .include "apple2.inc" _kbhit: lda KBD ; Reading KBD checks for keypress rol ; if high bit is set, key was pressed lda #$00 tax rol rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/libref.s��������������������������������������������������������������������0000664�0000000�0000000�00000000422�13473601511�0016273�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2013-05-31 ; .export em_libref, joy_libref, mouse_libref, ser_libref, tgi_libref .import _exit em_libref := _exit joy_libref := _exit mouse_libref := _exit ser_libref := _exit tgi_libref := _exit ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/lseek.s���������������������������������������������������������������������0000664�0000000�0000000�00000005303�13473601511�0016136�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Peter Ferrie, 21.11.2014 ; ; off_t __fastcall__ lseek(int fd, off_t offset, int whence); ; .export _lseek .import popax, popptr1 .macpack cpu .include "zeropage.inc" .include "errno.inc" .include "mli.inc" .include "filedes.inc" _lseek: ; Save whence sta tmp1 stx tmp2 ; Get and save offset jsr popptr1 jsr popax sta ptr2 stx ptr2+1 ; Get and process fd jsr popax jsr getfd ; Returns A, Y and C bcs errno ; Check for device cmp #$80 bcs einval ; Valid whence values are 0..2 ldx tmp2 bne einval ldx tmp1 cpx #3 bcs einval ; Set fd sta mliparam + MLI::MARK::REF_NUM txa beq cur lda #GET_EOF_CALL dex beq end ; SEEK_SET dex txa tay beq seek_common ; SEEK_CUR cur: lda #GET_MARK_CALL ; SEEK_END end: ; MARK_COUNT must == EOF_COUNT, otherwise unexpected behaviour .assert MARK_COUNT = EOF_COUNT, error ldx #MARK_COUNT jsr callmli bcs oserr lda mliparam + MLI::MARK::POSITION ldx mliparam + MLI::MARK::POSITION+1 ldy mliparam + MLI::MARK::POSITION+2 seek_common: adc ptr1 sta mliparam + MLI::MARK::POSITION txa adc ptr1+1 sta mliparam + MLI::MARK::POSITION+1 tya adc ptr2 sta mliparam + MLI::MARK::POSITION+2 lda #$00 adc ptr2+1 bne einval ; less than 0 or greater than 2^24 - 1 ; Set file pointer lda #SET_MARK_CALL ldx #MARK_COUNT jsr callmli bcs oserr ; Need to return the position in EAX .if (.cpu .bitand ::CPU_ISET_65SC02) stz sreg+1 .else lda #$00 sta sreg+1 .endif lda mliparam + MLI::MARK::POSITION+2 sta sreg ldx mliparam + MLI::MARK::POSITION+1 lda mliparam + MLI::MARK::POSITION rts ; Load errno code einval: lda #EINVAL ; Set __errno errno: jsr __directerrno ; leaves -1 in AX stx sreg ; extend return value to 32 bits stx sreg+1 rts ; Set __oserror oserr: jsr __mappederrno ; leaves -1 in AX stx sreg ; extend return value to 32 bits stx sreg+1 rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/mainargs.s������������������������������������������������������������������0000664�0000000�0000000�00000013062�13473601511�0016635�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; mainargs.s ; ; Ullrich von Bassewitz, 2003-03-07 ; Based on code from Stefan A. Haubenthal <polluks@web.de>, 2003-11-08 ; Greg King, 2003-05-18 ; Stefan Haubenthal, 2005-01-07 ; Oliver Schmidt, 2005-04-05 ; ; Scan a group of arguments that are in BASIC's input-buffer. ; Build an array that points to the beginning of each argument. ; Send, to main(), that array and the count of the arguments. ; Command-lines look like these lines: ; ; call2051 ; call2051 : rem ; call2051:rem arg1 " arg 2 is quoted " arg3 "" arg5 ; ; "call" and "rem" are entokenned; the args. are not. Leading and trailing ; spaces outside of quotes are ignored. ; TO-DO: ; Add a control-character quoting mechanism. .constructor initmainargs, 24 .import __argc, __argv, __dos_type .include "zeropage.inc" .include "apple2.inc" ; Maximum number of arguments allowed in the argument table. ; (An argument contains a comma, at least.) MAXARGS = 10 ; ProDOS stores the filename in the second half of BASIC's input buffer, so ; 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 = 127 BASIC_BUF = $200 FNAM_LEN = $280 FNAM = $281 REM = $B2 ; BASIC token-code ; Get possible command-line arguments. Goes into the special ONCE segment, ; which may be reused after the startup code is run. .segment "ONCE" initmainargs: ; Assume that the program was loaded, a moment ago, by the traditional BLOAD ; statement of BASIC.SYSTEM. Save the filename as argument #0 if available. ldx __dos_type ; No ProDOS -> argv[0] = "" beq :+ ; Terminate the filename with a zero to make it a valid C string. ldx FNAM_LEN : lda #$00 sta FNAM,x inc __argc ; argc always is equal to, at least, 1 ; Find the "rem" token. ldx #$00 : lda BASIC_BUF,x beq done ; No "rem" -> no args inx cmp #REM bne :- ; If a clock is present it is called by ProDOS on file operations. On machines ; with a slot-based clock (like the Thunder Clock) the clock firmware places ; the current date in BASIC's input buffer. Therefore we have to create a copy ; of the command-line in a different buffer before the original is potentially ; destroyed. ldy #$00 sty buffer + BUF_LEN - 1 : lda BASIC_BUF,x sta buffer,y inx iny cpy #BUF_LEN - 1 ; Keep the terminating zero intact bcc :- ; Start processing the arguments. ldx #$00 ldy #$01 * 2 ; Start with argv[1] ; Find the next argument. Stop if the end of the string or a character with the ; hibit set is reached. The later is true if the string isn't already parsed by ; BASIC (as expected) but is a still unprocessed input string. In this case the ; string isn't the expected command-line at all. We found this out the hard way ; by BRUNing the program with ProDOS on a machine with a slot-based clock (like ; the Thunder Clock). ProDOS called the clock firmware which places the current ; date as BASIC input string with hibits set in the input buffer. While looking ; for the REM token we stumbled across the first '2' character ($32+$80 = $B2) ; and interpreted the rest of the date as a spurious command-line parameter. next: lda buffer,x beq done bmi done inx cmp #' ' ; Skip leading spaces 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 ; will check now for a quoted argument, in which case we will have to skip this ; first character. cmp #'"' ; Is the argument quoted? beq :+ ; Jump if so dex ; Reset pointer to first argument character lda #' ' ; A space ends the argument : sta tmp1 ; Set end of argument marker ; Now store a pointer to the argument into the next slot. txa ; Get low byte clc adc #<buffer sta argv,y ; argv[y] = &arg iny lda #$00 adc #>buffer sta argv,y iny inc __argc ; Found another arg ; Search for the end of the argument. : lda buffer,x beq done inx cmp tmp1 bne :- ; 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 buffer-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? bcc 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 .data ; char* argv[MAXARGS+1] = {FNAM}; argv: .addr FNAM .res MAXARGS * 2 .segment "INIT" buffer: .res BUF_LEN ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/mcbdefault.s����������������������������������������������������������������0000664�0000000�0000000�00000007557�13473601511�0017156�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Default mouse callbacks for the Apple II ; ; Oliver Schmidt, 22.09.2005 ; ; All functions in this module should be interrupt safe, because they may ; be called from an interrupt handler ; .export _mouse_def_callbacks .include "apple2.inc" ; ------------------------------------------------------------------------ .bss backup: .res 1 visible:.res 1 ; ------------------------------------------------------------------------ .rodata ; Callback structure _mouse_def_callbacks: .addr hide .addr show .addr prep .addr draw .addr movex .addr movey ; ------------------------------------------------------------------------ .data .ifdef __APPLE2ENH__ cursor = $42 ; Pointer MouseText character .else cursor = '+' | $40 ; Flashing crosshair .endif getcursor: .ifdef __APPLE2ENH__ bit RD80VID ; In 80 column mode? bpl column ; No, skip bank switching switch: bit LOWSCR ; Patched at runtime .endif column: ldx #$00 ; Patched at runtime getscr: lda $0400,x ; Patched at runtime cmp #cursor rts setcursor: lda #cursor setscr: sta $0400,x ; Patched at runtime .ifdef __APPLE2ENH__ bit LOWSCR ; Doesn't hurt in 40 column mode .endif rts ; ------------------------------------------------------------------------ .code done: .ifdef __APPLE2ENH__ bit LOWSCR ; Doesn't hurt in 40 column mode .endif return: rts ; Hide the mouse cursor. hide: dec visible ; Fall through ; Prepare to move the mouse cursor. prep: jsr getcursor ; Cursor visible at current position? bne done ; No, we're done lda backup ; Get character at cursor position jmp setscr ; Draw character ; Show the mouse cursor. show: inc visible ; Fall through ; Draw the mouse cursor. draw: lda visible beq return jsr getcursor ; Cursor visible at current position? beq done ; Yes, we're done sta backup ; Save character at cursor position jmp setcursor ; Draw cursor ; Move the mouse cursor x position to the value in A/X. movex: dex ; Is position [256..279]? bmi :+ ; No, start with column 0 clc adc #$0100 .MOD 7 ; Bias position ldx #$0100 / 7 - 1 ; Bias column : sec : sbc #7 ; 280 positions / 40 columns inx bcs :- stx column+1 .ifdef __APPLE2ENH__ adc #7 / 2 ; Left or right half of 40-col column? ldx #<LOWSCR ; Columns 1,3,5..79 bcs :+ .assert LOWSCR + 1 = HISCR, error inx ; Columns 0,2,4..78 : stx switch+1 .endif rts ; Move the mouse cursor y position to the value in A/X. movey: tax ; ABCDExxx lsr ; 0ABCDExx lsr ; 00ABCDEx lsr ; 000ABCDE sta getscr+1 lsr ; 0000ABCD and #%00000011 ; 000000CD ora #>$0400 ; 000001CD sta getscr+2 sta setscr+2 txa ; ABCDExxx ror ; EABCDExx and #%11100000 ; EAB00000 ora getscr+1 ; EABABCDE and #%11111000 ; EABAB000 sta getscr+1 sta setscr+1 rts �������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/mli.inc���������������������������������������������������������������������0000664�0000000�0000000�00000011664�13473601511�0016132�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 30.12.2004 ; ; Apple ProDOS 8 MLI ; READ_BLOCK_CALL = $80 WRITE_BLOCK_CALL= $81 RW_BLOCK_COUNT = 3 GET_TIME_CALL = $82 GET_TIME_COUNT = 0 CREATE_CALL = $C0 CREATE_COUNT = 7 DESTROY_CALL = $C1 DESTROY_COUNT = 1 RENAME_CALL = $C2 RENAME_COUNT = 2 GET_INFO_CALL = $C4 GET_INFO_COUNT = $A ON_LINE_CALL = $C5 ON_LINE_COUNT = 2 SET_PREFIX_CALL = $C6 GET_PREFIX_CALL = $C7 PREFIX_COUNT = 1 OPEN_CALL = $C8 OPEN_COUNT = 3 READ_CALL = $CA WRITE_CALL = $CB RW_COUNT = 4 CLOSE_CALL = $CC CLOSE_COUNT = 1 SET_MARK_CALL = $CE GET_MARK_CALL = $CF MARK_COUNT = 2 SET_EOF_CALL = $D0 GET_EOF_CALL = $D1 EOF_COUNT = 2 .struct MLI .union .struct RW_BLOCK PARAM_COUNT .byte UNIT_NUM .byte DATA_BUFFER .addr BLOCK_NUM .word .endstruct .struct CREATE PARAM_COUNT .byte PATHNAME .addr ACCESS .byte FILE_TYPE .byte AUX_TYPE .word STORAGE_TYPE .byte CREATE_DATE .word CREATE_TIME .word .endstruct .struct DESTROY PARAM_COUNT .byte PATHNAME .addr .endstruct .struct RENAME PARAM_COUNT .byte PATHNAME .addr NEW_PATHNAME .addr .endstruct .struct INFO PARAM_COUNT .byte PATHNAME .addr ACCESS .byte FILE_TYPE .byte AUX_TYPE .word STORAGE_TYPE .byte BLOCKS .word MODE_DATE .word MODE_TIME .word CREATE_DATE .word CREATE_TIME .word .endstruct .struct ON_LINE PARAM_COUNT .byte UNIT_NUM .byte DATA_BUFFER .addr .endstruct .struct PREFIX PARAM_COUNT .byte PATHNAME .addr .endstruct .struct OPEN PARAM_COUNT .byte PATHNAME .addr IO_BUFFER .addr REF_NUM .byte .endstruct .struct RW PARAM_COUNT .byte REF_NUM .byte DATA_BUFFER .addr REQUEST_COUNT .word TRANS_COUNT .word .endstruct .struct CLOSE PARAM_COUNT .byte REF_NUM .byte .endstruct .struct MARK PARAM_COUNT .byte REF_NUM .byte POSITION .byte 3 .endstruct .struct EOF PARAM_COUNT .byte REF_NUM .byte EOF .byte 3 .endstruct .endunion .endstruct .global mliparam .global callmli DEVNUM := $BF30 ; Most recent accessed device DEVCNT := $BF31 ; Number of on-line devices (minus 1) DEVLST := $BF32 ; Up to 14 units may be active DATELO := $BF90 ; Bits 15-9 = year, 8-5 = month, 4-0 = day TIMELO := $BF92 ; Bits 12-8 = hour, 5-0 = minute LEVEL := $BF94 ; File level: used in open, flush, close MACHID := $BF98 ; Machine identification PFIXPTR := $BF9A ; If = 0, no prefix active KVERSION:= $BFFF ; Kernel version number ����������������������������������������������������������������������������cc65-2.18/libsrc/apple2/mli.s�����������������������������������������������������������������������0000664�0000000�0000000�00000001537�13473601511�0015621�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 30.12.2004 ; ; Apple ProDOS 8 MLI ; .import __dos_type .include "apple2.inc" .include "mli.inc" .bss mliparam:.tag MLI .data callmli: ; Store parameters sta call stx mliparam ; Check for ProDOS 8 lda __dos_type beq oserr ; Save random counter lda RNDL pha lda RNDH pha ; Call MLI jsr $BF00 ; MLI call entry point call: .byte $00 .addr mliparam ; Restore random counter and return tax pla sta RNDH pla sta RNDL txa rts ; Load oserror code and return oserr: lda #$01 ; "Bad system call number" sec rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/mou/������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015446�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/mou/a2.stdmou.s�������������������������������������������������������������0000664�0000000�0000000�00000030237�13473601511�0017453�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Driver for the AppleMouse II Card. ; ; Oliver Schmidt, 03.09.2005 ; .include "zeropage.inc" .include "mouse-kernel.inc" .include "apple2.inc" .macpack module ; ------------------------------------------------------------------------ SETMOUSE = $12 ; Sets mouse mode SERVEMOUSE = $13 ; Services mouse interrupt READMOUSE = $14 ; Reads mouse position CLEARMOUSE = $15 ; Clears mouse position to 0 (for delta mode) POSMOUSE = $16 ; Sets mouse position to a user-defined pos CLAMPMOUSE = $17 ; Sets mouse bounds in a window HOMEMOUSE = $18 ; Sets mouse to upper-left corner of clamp win INITMOUSE = $19 ; Resets mouse clamps to default values and ; sets mouse position to 0,0 pos1_lo := $0478 pos1_hi := $0578 pos2_lo := $04F8 pos2_hi := $05F8 status := $0778 ; ------------------------------------------------------------------------ .ifdef __APPLE2ENH__ module_header _a2e_stdmou_mou .else module_header _a2_stdmou_mou .endif ; Driver signature .byte $6D, $6F, $75 ; "mou" .byte MOUSE_API_VERSION ; Mouse driver API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr HIDE .addr SHOW .addr SETBOX .addr GETBOX .addr MOVE .addr BUTTONS .addr POS .addr INFO .addr IOCTL .addr IRQ ; Mouse driver flags .byte MOUSE_FLAG_EARLY_IRQ ; Callback table, set by the kernel before INSTALL is called CHIDE: jmp $0000 ; Hide the cursor CSHOW: jmp $0000 ; Show the cursor CPREP: jmp $0000 ; Prepare to move the cursor CDRAW: jmp $0000 ; Draw the cursor CMOVEX: jmp $0000 ; Move the cursor to X coord CMOVEY: jmp $0000 ; Move the cursor to Y coord ; ------------------------------------------------------------------------ .bss box: .tag MOUSE_BOX info: .tag MOUSE_INFO slot: .res 1 ; ------------------------------------------------------------------------ .rodata offsets:.byte $05 ; Pascal 1.0 ID byte .byte $07 ; Pascal 1.0 ID byte .byte $0B ; Pascal 1.1 generic signature byte .byte $0C ; Device signature byte values: .byte $38 ; Fixed .byte $18 ; Fixed .byte $01 ; Fixed .byte $20 ; X-Y pointing device type 0 size = * - values inibox: .word 0 ; MinX .word 0 ; MinY .word 279 ; MaxX .word 191 ; MaxY ; ------------------------------------------------------------------------ .data firmware: ; Lookup and patch firmware address lobyte lookup: ldy $FF00,x ; Patched at runtime sty jump+1 ; Modify code below ; Apple II Mouse TechNote #1, Interrupt Environment with the Mouse: ; "Enter all mouse routines (...) with the X register set to $Cn ; and Y register set to $n0, where n = the slot number." xparam: ldx #$FF ; Patched at runtime yparam: ldy #$FF ; Patched at runtime jump: jmp $FFFF ; Patched at runtime ; ------------------------------------------------------------------------ .code ; INSTALL: Is called after the driver is loaded into memory. If possible, ; check if the hardware is present. Must return an MOUSE_ERR_xx code in A/X. INSTALL: lda #<$C000 sta ptr1 lda #>$C000 sta ptr1+1 ; Search for AppleMouse II firmware in slots 1 - 7 next: inc ptr1+1 lda ptr1+1 cmp #>$C800 bcc :+ ; Mouse firmware not found lda #<MOUSE_ERR_NO_DEVICE ldx #>MOUSE_ERR_NO_DEVICE rts ; Check Pascal 1.1 Firmware Protocol ID bytes : ldx #size - 1 : ldy offsets,x lda values,x cmp (ptr1),y bne next dex bpl :- ; Get and patch firmware address hibyte lda ptr1+1 sta lookup+2 sta xparam+1 sta jump+2 ; Disable interrupts now because setting the slot number makes ; the IRQ handler (maybe called due to some non-mouse IRQ) try ; calling the firmware which isn't correctly set up yet sei ; Convert to and save slot number and #$0F sta slot ; Convert to and patch I/O register index asl asl asl asl sta yparam+1 ; The AppleMouse II Card needs the ROM switched in ; to be able to detect an Apple //e and use RDVBL bit $C082 ; Reset mouse hardware ldx #INITMOUSE jsr firmware ; Switch in LC bank 2 for R/O bit $C080 ; Turn mouse on lda #%00000001 ldx #SETMOUSE jsr firmware ; Set initial mouse clamps lda #<inibox ldx #>inibox jsr SETBOX ; Set initial mouse position ldx slot lda #<(279 / 2) sta pos1_lo,x lda #>(279 / 2) sta pos1_hi,x lda #<(191 / 2) sta pos2_lo,x lda #>(191 / 2) sta pos2_hi,x ldx #POSMOUSE jsr firmware ; Update cursor jsr update ; Turn VBL interrupt on lda #%00001001 ldx #SETMOUSE common: jsr firmware ; Enable interrupts and return success cli lda #<MOUSE_ERR_OK ldx #>MOUSE_ERR_OK rts ; UNINSTALL: Is called before the driver is removed from memory. ; No return code required (the driver is removed from memory on return). UNINSTALL: ; Hide cursor sei jsr CHIDE ; Turn mouse off lda #%00000000 ldx #SETMOUSE bne common ; Branch always ; SETBOX: Set the mouse bounding box. The parameters are passed as they come ; from the C program, that is, a pointer to a mouse_box struct in A/X. ; No checks are done if the mouse is currently inside the box, this is the job ; of the caller. It is not necessary to validate the parameters, trust the ; caller and save some code here. No return code required. SETBOX: sta ptr1 stx ptr1+1 ; Set x clamps ldx #$00 ldy #MOUSE_BOX::MINX jsr :+ ; Set y clamps ldx #$01 ldy #MOUSE_BOX::MINY ; Apple II Mouse TechNote #1, Interrupt Environment with the Mouse: ; "Disable interrupts before placing position information in the ; screen holes." : sei ; Set low clamp lda (ptr1),y sta box,y sta pos1_lo iny lda (ptr1),y sta box,y sta pos1_hi ; Skip one word iny iny ; Set high clamp iny lda (ptr1),y sta box,y sta pos2_lo iny lda (ptr1),y sta box,y sta pos2_hi txa ldx #CLAMPMOUSE bne common ; Branch always ; GETBOX: Return the mouse bounding box. The parameters are passed as they ; come from the C program, that is, a pointer to a mouse_box struct in A/X. GETBOX: sta ptr1 stx ptr1+1 ldy #.sizeof(MOUSE_BOX)-1 : lda box,y sta (ptr1),y dey bpl :- rts ; MOVE: Move the mouse to a new position. The position is passed as it comes ; from the C program, that is: x on the stack and y in A/X. The C wrapper will ; remove the parameter from the stack on return. ; No checks are done if the new position is valid (within the bounding box or ; the screen). No return code required. MOVE: ldy slot sei ; Set y sta pos2_lo,y txa sta pos2_hi,y tya tax ldy #$00 ; Start at top of stack ; Set x lda (sp),y iny sta pos1_lo,x lda (sp),y sta pos1_hi,x ; Update cursor jsr update ldx #POSMOUSE bne common ; Branch always ; HIDE: Is called to hide the mouse cursor. The mouse kernel manages a ; counter for calls to show/hide, and the driver entry point is only called ; if the mouse is currently visible and should get hidden. For most drivers, ; no special action is required besides hiding the mouse cursor. ; No return code required. HIDE: sei jsr CHIDE cli rts ; SHOW: Is called to show the mouse cursor. The mouse kernel manages a ; counter for calls to show/hide, and the driver entry point is only called ; if the mouse is currently hidden and should become visible. For most drivers, ; no special action is required besides enabling the mouse cursor. ; No return code required. SHOW: sei jsr CSHOW cli rts ; BUTTONS: Return the button mask in A/X. BUTTONS: lda info + MOUSE_INFO::BUTTONS ldx #$00 rts ; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1. ; No return code required. POS: ldy #.sizeof(MOUSE_POS)-1 bne copy ; Branch always ; INFO: Returns mouse position and current button mask in the MOUSE_INFO ; struct pointed to by ptr1. No return code required. INFO: ldy #.sizeof(MOUSE_INFO)-1 copy: sei : lda info,y sta (ptr1),y dey bpl :- cli rts ; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl ; specific data in ptr1, and the ioctl code in A. ; Must return an MOUSE_ERR_xx code in A/X. IOCTL: lda #<MOUSE_ERR_INV_IOCTL ldx #>MOUSE_ERR_INV_IOCTL rts ; IRQ: Called from the builtin runtime IRQ handler as a subroutine. All ; registers are already saved, no parameters are passed, but the carry flag ; is clear on entry. The routine must return with carry set if the interrupt ; was handled, otherwise with carry clear. IRQ: ; Check for installed mouse lda slot beq done ; Check for mouse interrupt ldx #SERVEMOUSE jsr firmware bcc :+ clc ; Interrupt not handled done: rts : ldx #READMOUSE jsr firmware ; Get status ldy slot lda status,y tax ; Save status ; Extract button down values asl ; C = Button 0 is currently down and #%00100000 ; !Z = Button 1 is currently down ; Set button mask beq :+ lda #MOUSE_BTN_RIGHT : bcc :+ ora #MOUSE_BTN_LEFT : sta info + MOUSE_INFO::BUTTONS ; Check for mouse movement txa ; Restore status and #%00100000 ; X or Y changed since last READMOUSE beq :+ ; Remove the cursor at the old position update: jsr CPREP ; Get and set the new X position ldy slot lda pos1_lo,y ldx pos1_hi,y sta info + MOUSE_POS::XCOORD stx info + MOUSE_POS::XCOORD+1 jsr CMOVEX ; Get and set the new Y position ldy slot lda pos2_lo,y ldx pos2_hi,y sta info + MOUSE_POS::YCOORD stx info + MOUSE_POS::YCOORD+1 jsr CMOVEY ; Draw the cursor at the new position : jsr CDRAW sec ; Interrupt handled rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/mouse_stat_stddrv.s���������������������������������������������������������0000664�0000000�0000000�00000000653�13473601511�0020607�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Address of the static standard mouse driver ; ; Oliver Schmidt, 2012-11-01 ; ; const void mouse_static_stddrv[]; ; .export _mouse_static_stddrv .ifdef __APPLE2ENH__ .import _a2e_stdmou_mou .else .import _a2_stdmou_mou .endif .rodata .ifdef __APPLE2ENH__ _mouse_static_stddrv := _a2e_stdmou_mou .else _mouse_static_stddrv := _a2_stdmou_mou .endif �������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/mouse_stddrv.s��������������������������������������������������������������0000664�0000000�0000000�00000000441�13473601511�0017547�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Name of the standard mouse driver ; ; Ullrich von Bassewitz, 2009-09-11 ; ; const char mouse_stddrv[]; ; .export _mouse_stddrv .rodata _mouse_stddrv: .ifdef __APPLE2ENH__ .asciiz "A2E.STDMOU.MOU" .else .asciiz "A2.STDMOU.MOU" .endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/open.s����������������������������������������������������������������������0000664�0000000�0000000�00000014200�13473601511�0015770�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 30.12.2004 ; ; int open (const char* name, int flags, ...); ; .export _open, closedirect, freebuffer .export __filetype, __auxtype, __datetime .constructor raisefilelevel .destructor closeallfiles, 5 .import pushname, popname, __dos_type .import iobuf_alloc, iobuf_free .import addysp, incsp4, incaxy, pushax, popax .include "zeropage.inc" .include "errno.inc" .include "fcntl.inc" .include "mli.inc" .include "filedes.inc" .segment "ONCE" raisefilelevel: ; Raise file level lda __dos_type beq :+ inc LEVEL : rts .code _open: ; Throw away all parameters except name ; and flags occupying together 4 bytes dey dey dey dey jsr addysp ; Start with first fdtab slot ldy #$00 ; Check for free fdtab slot : lda fdtab + FD::REF_NUM,y beq found ; Advance to next fdtab slot .assert .sizeof(FD) = 4, error iny iny iny iny ; Check for end of fdtab cpy #MAX_FDS * .sizeof(FD) bcc :- ; Load errno code lda #EMFILE ; Cleanup stack errno: jsr incsp4 ; Preserves A ; Set __errno jmp __directerrno ; Save fdtab slot found: tya pha ; Alloc I/O buffer lda #<(fdtab + FD::BUFFER) ldx #>(fdtab + FD::BUFFER) jsr incaxy jsr pushax lda #$00 ldx #>$0100 jsr pushax ; Preserves A ldx #>$0400 jsr iobuf_alloc tay ; Save errno code ; Restore fdtab slot pla sta tmp2 ; Save fdtab slot ; Check for error tya ; Restore errno code bne errno ; Get and save flags jsr popax sta tmp3 ; Get and push name jsr popax jsr pushname bne oserr1 ; Set pushed name lda sp ldx sp+1 sta mliparam + MLI::OPEN::PATHNAME stx mliparam + MLI::OPEN::PATHNAME+1 ; Check for create flag lda tmp3 ; Restore flags and #O_CREAT beq open ; PATHNAME already set .assert MLI::CREATE::PATHNAME = MLI::OPEN::PATHNAME, error ; Set all other parameters from template ldx #(MLI::CREATE::CREATE_TIME+1) - (MLI::CREATE::PATHNAME+1) - 1 : lda CREATE,x sta mliparam + MLI::CREATE::ACCESS,x dex bpl :- ; Create file lda #CREATE_CALL ldx #CREATE_COUNT jsr callmli bcc open ; Check for ordinary errors cmp #$47 ; "Duplicate filename" bne oserr2 ; Check for exclusive flag lda tmp3 ; Restore flags and #O_EXCL beq open lda #$47 ; "Duplicate filename" ; Cleanup name oserr2: jsr popname ; Preserves A oserr1: ldy tmp2 ; Restore fdtab slot ; Cleanup I/O buffer pha ; Save oserror code jsr freebuffer pla ; Restore oserror code ; Set __oserror jmp __mappederrno open: ldy tmp2 ; Restore fdtab slot ; Set allocated I/O buffer ldx fdtab + FD::BUFFER+1,y sta mliparam + MLI::OPEN::IO_BUFFER ; A = 0 stx mliparam + MLI::OPEN::IO_BUFFER+1 ; Open file lda #OPEN_CALL ldx #OPEN_COUNT jsr callmli bcs oserr2 ; Get and save fd ldx mliparam + MLI::OPEN::REF_NUM stx tmp1 ; Save fd ; Set flags and check for truncate flag lda tmp3 ; Restore flags sta fdtab + FD::FLAGS,y and #O_TRUNC beq done ; Set fd and zero size stx mliparam + MLI::EOF::REF_NUM ldx #$02 lda #$00 : sta mliparam + MLI::EOF::EOF,x dex bpl :- ; Set file size lda #SET_EOF_CALL ldx #EOF_COUNT jsr callmli bcc done ; Cleanup file pha ; Save oserror code lda tmp1 ; Restore fd jsr closedirect pla ; Restore oserror code bne oserr2 ; Branch always ; Store fd done: lda tmp1 ; Restore fd sta fdtab + FD::REF_NUM,y ; Convert fdtab slot to handle .assert .sizeof(FD) = 4, error tya lsr lsr ; Cleanup name jsr popname ; Preserves A ; Return success ldx #$00 stx __oserror rts freebuffer: ; Free I/O buffer lda #$00 ldx fdtab + FD::BUFFER+1,y jmp iobuf_free closedirect: ; Set fd sta mliparam + MLI::CLOSE::REF_NUM ; Call close lda #CLOSE_CALL ldx #CLOSE_COUNT jmp callmli closeallfiles: ; All open files with current level (or higher) lda #$00 jsr closedirect ; Restore original file level lda __dos_type beq :+ dec LEVEL : rts .data CREATE: .byte %11000011 ; ACCESS: Standard full access __filetype: .byte $06 ; FILE_TYPE: Standard binary file __auxtype: .word $0000 ; AUX_TYPE: Load address N/A .byte $01 ; STORAGE_TYPE: Standard seedling file __datetime: .word $0000 ; CREATE_DATE: Current date .word $0000 ; CREATE_TIME: Current time ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/opendir.c�������������������������������������������������������������������0000664�0000000�0000000�00000010257�13473601511�0016457�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* opendir.h */ /* */ /* Open a directory */ /* */ /* */ /* */ /* (C) 2005 Oliver Schmidt, <ol.sc@web.de> */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stddef.h> #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <dirent.h> #include "dir.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ extern char _cwd[FILENAME_MAX]; /*****************************************************************************/ /* Code */ /*****************************************************************************/ DIR* __fastcall__ opendir (register const char* name) { register DIR* dir; /* Alloc DIR */ if ((dir = malloc (sizeof (*dir))) == NULL) { /* May not have been done by malloc() */ _directerrno (ENOMEM); /* Return failure */ return NULL; } /* Interpret dot as current working directory */ if (*name == '.') { name = _cwd; } /* Open directory file */ if ((dir->fd = open (name, O_RDONLY)) != -1) { /* Read directory key block */ if (read (dir->fd, dir->block.bytes, sizeof (dir->block)) == sizeof (dir->block)) { /* Get directory entry infos from directory header */ dir->entry_length = dir->block.bytes[0x23]; dir->entries_per_block = dir->block.bytes[0x24]; /* Skip directory header entry */ dir->current_entry = 1; /* Return success */ return dir; } /* EOF: Most probably no directory file at all */ if (_oserror == 0) { _directerrno (EINVAL); } /* Cleanup directory file */ close (dir->fd); } /* Cleanup DIR */ free (dir); /* Return failure */ return NULL; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/oserrlist.s�����������������������������������������������������������������0000664�0000000�0000000�00000005512�13473601511�0017063�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Stefan Haubenthal, 2003-12-24 ; Ullrich von Bassewitz, 18.07.2002 ; ; Defines the platform specific error list. ; ; The table is built as a list of entries ; ; .byte entrylen ; .byte errorcode ; .asciiz errormsg ; ; and terminated by an entry with length zero that is returned if the ; error code could not be found. ; .export __sys_oserrlist ;---------------------------------------------------------------------------- ; Macros used to generate the list (may get moved to an include file?) ; Regular entry .macro sys_oserr_entry code, msg .local Start, End Start: .byte End - Start .byte code .asciiz msg End: .endmacro ; Sentinel entry .macro sys_oserr_sentinel msg .byte 0 ; Length is always zero .byte 0 ; Code is unused .asciiz msg .endmacro ;---------------------------------------------------------------------------- ; The error message table .rodata __sys_oserrlist: sys_oserr_entry $01, "Bad system call number" sys_oserr_entry $04, "Bad system call parameter count" sys_oserr_entry $25, "Interrupt table full" sys_oserr_entry $27, "I/O error" sys_oserr_entry $28, "No device connected" sys_oserr_entry $2B, "Disk write protected" sys_oserr_entry $2E, "Disk switched" sys_oserr_entry $2F, "Device off-line" sys_oserr_entry $40, "Invalid pathname" sys_oserr_entry $42, "Maximum number of files open" sys_oserr_entry $43, "Invalid reference number" sys_oserr_entry $44, "Directory not found" sys_oserr_entry $45, "Volume not found" sys_oserr_entry $46, "File not found" sys_oserr_entry $47, "Duplicate filename" sys_oserr_entry $48, "Volume full" sys_oserr_entry $49, "Volume directory full" sys_oserr_entry $4A, "Incompatible file format" sys_oserr_entry $4B, "Unsupported storage_type" sys_oserr_entry $4C, "End of file encountered" sys_oserr_entry $4D, "Position out of range" sys_oserr_entry $4E, "File access error" sys_oserr_entry $50, "File is open" sys_oserr_entry $51, "Directory structure damaged" sys_oserr_entry $52, "Not a ProDOS disk" sys_oserr_entry $53, "Invalid system call parameter" sys_oserr_entry $55, "Volume Control Block table full" sys_oserr_entry $56, "Bad buffer address" sys_oserr_entry $57, "Duplicate volume" sys_oserr_entry $5A, "File structure damaged" sys_oserr_sentinel "Unknown error" ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/oserror.s�������������������������������������������������������������������0000664�0000000�0000000�00000004415�13473601511�0016531�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 17.05.2000 ; ; int __fastcall__ _osmaperrno (unsigned char oserror); ; .export __osmaperrno .include "errno.inc" __osmaperrno: ldx #ErrTabSize : cmp ErrTab-2,x ; Search for the error code beq :+ ; Jump if found dex dex bne :- ; Next entry ; Code not found, return EUNKNOWN lda #<EUNKNOWN ldx #>EUNKNOWN rts ; Found the code : lda ErrTab-1,x ldx #$00 ; High byte always zero rts .rodata ErrTab: .byte $01, ENOSYS ; Bad system call number .byte $04, EINVAL ; Bad system call parameter count .byte $25, ENOMEM ; Interrupt table full .byte $27, EIO ; I/O error .byte $28, ENODEV ; No device connected .byte $2B, EACCES ; Disk write protected ; .byte $2E, EUNKNOWN ; Disk switched .byte $2F, ENODEV ; Device off-line .byte $40, EINVAL ; Invalid pathname .byte $42, EMFILE ; Maximum number of files open .byte $43, EINVAL ; Invalid reference number .byte $44, ENOENT ; Directory not found .byte $45, ENOENT ; Volume not found .byte $46, ENOENT ; File not found .byte $47, EEXIST ; Duplicate filename .byte $48, ENOSPC ; Volume full .byte $49, ENOSPC ; Volume directory full .byte $4A, ENOEXEC ; Incompatible file format .byte $4B, EINVAL ; Unsupported storage_type ; .byte $4C, EUNKNOWN ; End of file encountered .byte $4D, ESPIPE ; Position out of range .byte $4E, EACCES ; File access error .byte $50, EINVAL ; File is open ; .byte $51, EUNKNOWN ; Directory structure damaged .byte $52, ENODEV ; Not a ProDOS volume .byte $53, ERANGE ; Invalid system call parameter .byte $55, EMFILE ; Volume Control Block table full .byte $56, EINVAL ; Bad buffer address ; .byte $57, EUNKNOWN ; Duplicate volume ; .byte $5A, EUNKNOWN ; File structure damaged ErrTabSize = (* - ErrTab) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/randomize.s�����������������������������������������������������������������0000664�0000000�0000000�00000000573�13473601511�0017027�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 07.11.2002 ; ; void _randomize (void); ; /* Initialize the random number generator */ ; .export __randomize .import _srand .include "apple2.inc" __randomize: ldx RNDH ; Use random value supplied by ROM lda RNDL jmp _srand ; Initialize generator �������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/rdkey.s���������������������������������������������������������������������0000664�0000000�0000000�00000000612�13473601511�0016147�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 03.03.2007 ; ; RDKEY routine ; .export RDKEY .include "apple2.inc" .segment "LOWCODE" RDKEY: ; Switch in ROM and call RDKEY bit $C082 jsr $FD0C ; Display prompt and read key from user input routine ; Switch in LC bank 2 for R/O and return bit $C080 rts ����������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/read.s����������������������������������������������������������������������0000664�0000000�0000000�00000004512�13473601511�0015747�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 12.01.2005 ; ; int __fastcall__ read (int fd, void* buf, unsigned count); ; .constructor initprompt .export _read .import rwprolog, rwcommon .import RDKEY, COUT .include "zeropage.inc" .include "errno.inc" .include "fcntl.inc" .include "mli.inc" .include "filedes.inc" .include "apple2.inc" .segment "ONCE" initprompt: ; Set prompt <> ']' to let DOS 3.3 know that we're ; not in Applesoft immediate mode and thus keep it ; from scanning our device I/O for DOS commands. lda #$80 ; Same value used at $D52C sta PROMPT rts .code _read: ; Get parameters jsr rwprolog bcs errno tax ; Save fd ; Check for read access lda fdtab + FD::FLAGS,y and #O_RDONLY beq einval ; Check for device txa ; Restore fd bmi device ; Do read ldy #READ_CALL jmp rwcommon ; Device succeeds always device: lda #$00 sta __oserror ; Set counter to zero sta ptr3 sta ptr3+1 ; Check for zero count lda ptr2 ora ptr2+1 beq check ; Read from device and echo to device next: jsr RDKEY jsr COUT ; Clear hi bit and check for '\r' and #$7F cmp #$0D bne :+ ; Replace with '\n' and set count to zero lda #$0A ldy #$00 sty ptr2 sty ptr2+1 ; Put char into buf : ldy #$00 sta (ptr1),y ; Increment pointer inc ptr1 bne :+ inc ptr1+1 ; Increment counter : inc ptr3 bne check inc ptr3+1 ; Check for counter less than count check: lda ptr3 cmp ptr2 bcc next ldx ptr3+1 cpx ptr2+1 bcc next ; Return success, AX already set rts ; Load errno code einval: lda #EINVAL ; Set __errno errno: jmp __directerrno ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/readdir.c�������������������������������������������������������������������0000664�0000000�0000000�00000007672�13473601511�0016440�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* readdir.c */ /* */ /* Read directory entry */ /* */ /* */ /* */ /* (C) 2005 Oliver Schmidt, <ol.sc@web.de> */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stddef.h> #include <unistd.h> #include <dirent.h> #include "dir.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ struct dirent* __fastcall__ readdir (register DIR* dir) { register unsigned char* entry; /* Search for the next active directory entry */ do { /* Read next directory block if necessary */ if (dir->current_entry == dir->entries_per_block) { if (read (dir->fd, dir->block.bytes, sizeof (dir->block)) != sizeof (dir->block)) { /* Just return failure as read() has */ /* set errno if (and only if) no EOF */ return NULL; } /* Start with first entry in next block */ dir->current_entry = 0; } /* Compute pointer to current entry */ entry = dir->block.content.entries + dir->current_entry * dir->entry_length; /* Switch to next entry */ ++dir->current_entry; } while (entry[0x00] == 0); /* Move creation date/time to allow for next step below */ *(unsigned long*)&entry[0x1A] = *(unsigned long*)&entry[0x18]; /* Feature unsigned long access to EOF by extension from 3 to 4 bytes */ entry[0x18] = 0; /* Move file type to allow for next step below */ entry[0x19] = entry[0x10]; /* Zero-terminate file name */ entry[0x01 + (entry[0x00] & 0x0F)] = 0; /* Return success */ return (struct dirent*)&entry[0x01]; } ����������������������������������������������������������������������cc65-2.18/libsrc/apple2/reboot.s��������������������������������������������������������������������0000664�0000000�0000000�00000000603�13473601511�0016323�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 14.09.2009 ; ; void rebootafterexit (void); ; .constructor initreboot, 11 .export _rebootafterexit .import done, return _rebootafterexit := return .segment "ONCE" initreboot: ; Quit to PWRUP lda #<$FAA6 ldx #>$FAA6 sta done+1 stx done+2 rts �����������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/revers.s��������������������������������������������������������������������0000664�0000000�0000000�00000001326�13473601511�0016342�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2005-03-28 ; ; unsigned char __fastcall__ revers (unsigned char onoff) ; .export _revers .include "apple2.inc" _revers: tax ; Test onoff beq normal ; If zero, "normal" must be set ldx #$3F+1 ; Set "inverse" normal: dex ; $00->$FF, $40->$3F lda #$00 ; Preload return code for "normal" ldy INVFLG ; Load current flag value stx INVFLG ; Save new flag value bmi :+ ; Jump if current value is $FF (normal) lda #$01 ; Return "inverse" : ldx #$00 rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/rewinddir.c�����������������������������������������������������������������0000664�0000000�0000000�00000006274�13473601511�0017012�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* rewinddir.c */ /* */ /* Reset directory stream */ /* */ /* */ /* */ /* (C) 2005 Oliver Schmidt, <ol.sc@web.de> */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <unistd.h> #include <string.h> #include <dirent.h> #include "dir.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void __fastcall__ rewinddir (register DIR* dir) { /* Rewind directory file */ if (lseek (dir->fd, 0, SEEK_SET)) { /* Read directory key block */ if (read (dir->fd, dir->block.bytes, sizeof (dir->block)) == sizeof (dir->block)) { /* Skip directory header entry */ dir->current_entry = 1; /* Return success */ return; } } /* Assert that no subsequent readdir() finds an active entry */ memset (dir->block.bytes, 0, sizeof (dir->block)); /* Return failure */ } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/rwcommon.s������������������������������������������������������������������0000664�0000000�0000000�00000002547�13473601511�0016703�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 12.01.2005 ; .export rwprolog, rwcommon, rwepilog .import popax, popptr1 .include "zeropage.inc" .include "errno.inc" .include "fcntl.inc" .include "mli.inc" .include "filedes.inc" rwprolog: ; Save count sta ptr2 stx ptr2+1 ; Get and save buf jsr popptr1 ; Get and process fd jsr popax jmp getfd ; Returns A, Y and C rwcommon: ; Set fd sta mliparam + MLI::RW::REF_NUM ; Set buf lda ptr1 ldx ptr1+1 sta mliparam + MLI::RW::DATA_BUFFER stx mliparam + MLI::RW::DATA_BUFFER+1 ; Set count lda ptr2 ldx ptr2+1 sta mliparam + MLI::RW::REQUEST_COUNT stx mliparam + MLI::RW::REQUEST_COUNT+1 ; Call read or write tya ldx #RW_COUNT jsr callmli bcc rwepilog cmp #$4C ; "End of file encountered" bne oserr rwepilog: ; Return success sta __oserror ; A = 0 lda mliparam + MLI::RW::TRANS_COUNT ldx mliparam + MLI::RW::TRANS_COUNT+1 rts ; Set __oserror oserr: jmp __mappederrno ���������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/ser/������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015437�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/ser/a2.ssc.s����������������������������������������������������������������0000664�0000000�0000000�00000033642�13473601511�0016724�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Serial driver for the Apple II Super Serial Card. ; ; Oliver Schmidt, 21.04.2005 ; ; The driver is based on the cc65 rs232 module, which in turn is based on ; Craig Bruce device driver for the Switftlink/Turbo-232. ; ; SwiftLink/Turbo-232 v0.90 device driver, by Craig Bruce, 14-Apr-1998. ; ; This software is Public Domain. It is in Buddy assembler format. ; ; This device driver uses the SwiftLink RS-232 Serial Cartridge, available from ; Creative Micro Designs, Inc, and also supports the extensions of the Turbo232 ; Serial Cartridge. Both devices are based on the 6551 ACIA chip. It also ; supports the "hacked" SwiftLink with a 1.8432 MHz crystal. ; ; The code assumes that the kernal + I/O are in context. On the C128, call ; it from Bank 15. On the C64, don't flip out the Kernal unless a suitable ; NMI catcher is put into the RAM under then Kernal. For the SuperCPU, the ; interrupt handling assumes that the 65816 is in 6502-emulation mode. ; .include "zeropage.inc" .include "ser-kernel.inc" .include "ser-error.inc" .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table .ifdef __APPLE2ENH__ module_header _a2e_ssc_ser .else module_header _a2_ssc_ser .endif ; Driver signature .byte $73, $65, $72 ; "ser" .byte SER_API_VERSION ; Serial API version number ; Library reference .addr $0000 ; Jump table .addr SER_INSTALL .addr SER_UNINSTALL .addr SER_OPEN .addr SER_CLOSE .addr SER_GET .addr SER_PUT .addr SER_STATUS .addr SER_IOCTL .addr SER_IRQ ;---------------------------------------------------------------------------- ; I/O definitions ACIA = $C088 ACIA_DATA = ACIA+0 ; Data register ACIA_STATUS = ACIA+1 ; Status register ACIA_CMD = ACIA+2 ; Command register ACIA_CTRL = ACIA+3 ; Control register ;---------------------------------------------------------------------------- ; Global variables .bss RecvHead: .res 1 ; Head of receive buffer RecvTail: .res 1 ; Tail of receive buffer RecvFreeCnt: .res 1 ; Number of bytes in receive buffer SendHead: .res 1 ; Head of send buffer SendTail: .res 1 ; Tail of send buffer SendFreeCnt: .res 1 ; Number of bytes in send buffer Stopped: .res 1 ; Flow-stopped flag RtsOff: .res 1 ; RecvBuf: .res 256 ; Receive buffers: 256 bytes SendBuf: .res 256 ; Send buffers: 256 bytes Index: .res 1 ; I/O register index .data Slot: .byte $02 ; Default to SSC in slot 2 .rodata ; Tables used to translate RS232 params into register values BaudTable: ; bit7 = 1 means setting is invalid .byte $FF ; SER_BAUD_45_5 .byte $01 ; SER_BAUD_50 .byte $02 ; SER_BAUD_75 .byte $03 ; SER_BAUD_110 .byte $04 ; SER_BAUD_134_5 .byte $05 ; SER_BAUD_150 .byte $06 ; SER_BAUD_300 .byte $07 ; SER_BAUD_600 .byte $08 ; SER_BAUD_1200 .byte $09 ; SER_BAUD_1800 .byte $0A ; SER_BAUD_2400 .byte $0B ; SER_BAUD_3600 .byte $0C ; SER_BAUD_4800 .byte $0D ; SER_BAUD_7200 .byte $0E ; SER_BAUD_9600 .byte $0F ; SER_BAUD_19200 .byte $FF ; SER_BAUD_38400 .byte $FF ; SER_BAUD_57600 .byte $FF ; SER_BAUD_115200 .byte $FF ; SER_BAUD_230400 BitTable: .byte $60 ; SER_BITS_5 .byte $40 ; SER_BITS_6 .byte $20 ; SER_BITS_7 .byte $00 ; SER_BITS_8 StopTable: .byte $00 ; SER_STOP_1 .byte $80 ; SER_STOP_2 ParityTable: .byte $00 ; SER_PAR_NONE .byte $20 ; SER_PAR_ODD .byte $60 ; SER_PAR_EVEN .byte $A0 ; SER_PAR_MARK .byte $E0 ; SER_PAR_SPACE IdOfsTable: .byte $05 ; Pascal 1.0 ID byte .byte $07 ; Pascal 1.0 ID byte .byte $0B ; Pascal 1.1 generic signature byte .byte $0C ; Device signature byte IdValTable: .byte $38 ; Fixed .byte $18 ; Fixed .byte $01 ; Fixed .byte $31 ; Serial or parallel I/O card type 1 IdTableLen = * - IdValTable .code ;---------------------------------------------------------------------------- ; SER_INSTALL: Is called after the driver is loaded into memory. If possible, ; check if the hardware is present. Must return an SER_ERR_xx code in a/x. ; ; Since we don't have to manage the IRQ vector on the Apple II, this is ; actually the same as: ; ; SER_UNINSTALL: Is called before the driver is removed from memory. ; No return code required (the driver is removed from memory on return). ; ; and: ; ; SER_CLOSE: Close the port and disable interrupts. Called without parameters. ; Must return an SER_ERR_xx code in a/x. SER_INSTALL: SER_UNINSTALL: SER_CLOSE: ldx Index ; Check for open port beq :+ ; Deactivate DTR and disable 6551 interrupts lda #%00001010 sta ACIA_CMD,x ; Done, return an error code : lda #<SER_ERR_OK tax ; A is zero stx Index ; Mark port as closed rts ;---------------------------------------------------------------------------- ; SER_OPEN: A pointer to a ser_params structure is passed in ptr1. ; Must return an SER_ERR_xx code in a/x. SER_OPEN: ldx #<$C000 stx ptr2 lda #>$C000 ora Slot sta ptr2+1 ; Check Pascal 1.1 Firmware Protocol ID bytes : ldy IdOfsTable,x lda IdValTable,x cmp (ptr2),y bne NoDevice inx cpx #IdTableLen bcc :- ; Convert slot to I/O register index lda Slot asl asl asl asl tax ; Check if the handshake setting is valid ldy #SER_PARAMS::HANDSHAKE ; Handshake lda (ptr1),y cmp #SER_HS_HW ; This is all we support bne InvParam ; Initialize buffers ldy #$00 sty Stopped sty RecvHead sty RecvTail sty SendHead sty SendTail dey ; Y = 255 sty RecvFreeCnt sty SendFreeCnt ; Set the value for the control register, which contains stop bits, ; word length and the baud rate. ldy #SER_PARAMS::BAUDRATE lda (ptr1),y ; Baudrate index tay lda BaudTable,y ; Get 6551 value bmi InvBaud ; Branch if rate not supported sta tmp1 ldy #SER_PARAMS::DATABITS ; Databits lda (ptr1),y tay lda BitTable,y ora tmp1 sta tmp1 ldy #SER_PARAMS::STOPBITS ; Stopbits lda (ptr1),y tay lda StopTable,y ora tmp1 ora #%00010000 ; Receiver clock source = baudrate sta ACIA_CTRL,x ; Set the value for the command register. We remember the base value ; in RtsOff, since we will have to manipulate ACIA_CMD often. ldy #SER_PARAMS::PARITY ; Parity lda (ptr1),y tay lda ParityTable,y ora #%00000001 ; DTR active sta RtsOff ora #%00001000 ; Enable receive interrupts sta ACIA_CMD,x ; Done stx Index ; Mark port as open lda #<SER_ERR_OK tax ; A is zero rts ; Device (hardware) not found NoDevice:lda #<SER_ERR_NO_DEVICE ldx #>SER_ERR_NO_DEVICE rts ; Invalid parameter InvParam:lda #<SER_ERR_INIT_FAILED ldx #>SER_ERR_INIT_FAILED rts ; Baud rate not available InvBaud:lda #<SER_ERR_BAUD_UNAVAIL ldx #>SER_ERR_BAUD_UNAVAIL rts ;---------------------------------------------------------------------------- ; SER_GET: Will fetch a character from the receive buffer and store it into the ; variable pointed to by ptr1. If no data is available, SER_ERR_NO_DATA is ; returned. SER_GET: ldx Index ldy SendFreeCnt ; Send data if necessary iny ; Y == $FF? beq :+ lda #$00 ; TryHard = false jsr TryToSend ; Check for buffer empty : lda RecvFreeCnt ; (25) cmp #$FF bne :+ lda #<SER_ERR_NO_DATA ldx #>SER_ERR_NO_DATA rts ; Check for flow stopped & enough free: release flow control : ldy Stopped ; (34) beq :+ cmp #63 bcc :+ lda #$00 sta Stopped lda RtsOff ora #%00001000 sta ACIA_CMD,x ; Get byte from buffer : ldy RecvHead ; (41) lda RecvBuf,y inc RecvHead inc RecvFreeCnt ldx #$00 ; (59) sta (ptr1,x) txa ; Return code = 0 rts ;---------------------------------------------------------------------------- ; SER_PUT: Output character in A. ; Must return an SER_ERR_xx code in a/x. SER_PUT: ldx Index ; Try to send ldy SendFreeCnt iny ; Y = $FF? beq :+ pha lda #$00 ; TryHard = false jsr TryToSend pla ; Put byte into send buffer & send : ldy SendFreeCnt bne :+ lda #<SER_ERR_OVERFLOW ldx #>SER_ERR_OVERFLOW rts : ldy SendTail sta SendBuf,y inc SendTail dec SendFreeCnt lda #$FF ; TryHard = true jsr TryToSend lda #<SER_ERR_OK tax rts ;---------------------------------------------------------------------------- ; SER_STATUS: Return the status in the variable pointed to by ptr1. ; Must return an SER_ERR_xx code in a/x. SER_STATUS: ldx Index lda ACIA_STATUS,x ldx #$00 sta (ptr1,x) txa ; SER_ERR_OK rts ;---------------------------------------------------------------------------- ; SER_IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl ; specific data in ptr1, and the ioctl code in A. ; Must return an SER_ERR_xx code in a/x. SER_IOCTL: ; Check data msb and code to be 0 ora ptr1+1 bne :+ ; Check data lsb to be [1..7] ldx ptr1 beq :+ cpx #7+1 bcs :+ stx Slot tax ; SER_ERR_OK rts : lda #<SER_ERR_INV_IOCTL ldx #>SER_ERR_INV_IOCTL rts ;---------------------------------------------------------------------------- ; SER_IRQ: Called from the builtin runtime IRQ handler as a subroutine. All ; registers are already saved, no parameters are passed, but the carry flag ; is clear on entry. The routine must return with carry set if the interrupt ; was handled, otherwise with carry clear. SER_IRQ: ldx Index ; Check for open port beq Done lda ACIA_STATUS,x ; Check ACIA status for receive interrupt and #$08 beq Done ; Jump if no ACIA interrupt lda ACIA_DATA,x ; Get byte from ACIA ldy RecvFreeCnt ; Check if we have free space left beq Flow ; Jump if no space in receive buffer ldy RecvTail ; Load buffer pointer sta RecvBuf,y ; Store received byte in buffer inc RecvTail ; Increment buffer pointer dec RecvFreeCnt ; Decrement free space counter ldy RecvFreeCnt ; Check for buffer space low cpy #33 bcc Flow ; Assert flow control if buffer space low rts ; Interrupt handled (carry already set) ; Assert flow control if buffer space too low Flow: lda RtsOff sta ACIA_CMD,x sta Stopped sec ; Interrupt handled Done: rts ;---------------------------------------------------------------------------- ; Try to send a byte. Internal routine. A = TryHard TryToSend: sta tmp1 ; Remember tryHard flag Again: lda SendFreeCnt cmp #$FF beq Quit ; Bail out ; Check for flow stopped lda Stopped bne Quit ; Bail out ; Check that ACIA is ready to send lda ACIA_STATUS,x and #$10 bne Send bit tmp1 ; Keep trying if must try hard bmi Again Quit: rts ; Send byte and try again Send: ldy SendHead lda SendBuf,y sta ACIA_DATA,x inc SendHead inc SendFreeCnt jmp Again ����������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/settime.s�������������������������������������������������������������������0000664�0000000�0000000�00000003266�13473601511�0016513�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 15.08.2018 ; ; int __fastcall__ clock_settime (clockid_t clk_id, const struct timespec *tp); ; .import __dos_type .import incsp1, return0 .include "time.inc" .include "zeropage.inc" .include "errno.inc" .include "mli.inc" _clock_settime: ; Cleanup stack jsr incsp1 ; Preserves A ; Check for ProDOS 8 ldy __dos_type beq enosys ; Check for existing minutes or hours tay ; Save A lda TIMELO ora TIMELO+1 bne erange tya ; Restore A ; Get tm .assert timespec::tv_sec = 0, error jsr _localtime sta ptr1 stx ptr1+1 ; Set date ldy #tm::tm_mon lda (ptr1),y clc adc #$01 ; Move [0..11] to [1..12] asl asl asl asl asl php ; Save month msb ldy #tm::tm_mday ora (ptr1),y sta DATELO ldy #tm::tm_year lda (ptr1),y cmp #100 ; Year since 1900 < 100? bcc :+ ; Yes, leave alone sbc #100 ; Move 20xx to 19xx : plp ; Restore month msb rol sta DATELO+1 ; Return success jmp return0 ; Load errno code enosys: lda #ENOSYS bne errno ; Always ; Load errno code erange: lda #ERANGE ; Set __errno errno: jmp __directerrno ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/syschdir.s������������������������������������������������������������������0000664�0000000�0000000�00000001514�13473601511�0016663�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 17.04.2005 ; ; unsigned char __fastcall__ _syschdir (const char* name); ; .export __syschdir .import pushname, popname .import initcwd .include "zeropage.inc" .include "mli.inc" __syschdir: ; Push name jsr pushname bne oserr ; Set pushed name lda sp ldx sp+1 sta mliparam + MLI::PREFIX::PATHNAME stx mliparam + MLI::PREFIX::PATHNAME+1 ; Change directory lda #SET_PREFIX_CALL ldx #PREFIX_COUNT jsr callmli bcs cleanup ; Update current working directory jsr initcwd ; Returns with A = 0 ; Cleanup name cleanup:jsr popname ; Preserves A oserr: rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/sysmkdir.s������������������������������������������������������������������0000664�0000000�0000000�00000002700�13473601511�0016676�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 15.04.2005 ; ; unsigned char _sysmkdir (const char* name, ...); ; .export __sysmkdir .import pushname, popname .import addysp, popax .include "zeropage.inc" .include "mli.inc" __sysmkdir: ; Throw away all parameters except the name dey dey jsr addysp ; Get and push name jsr popax jsr pushname bne oserr ; Set pushed name lda sp ldx sp+1 sta mliparam + MLI::CREATE::PATHNAME stx mliparam + MLI::CREATE::PATHNAME+1 ; Set all other parameters from template ldx #(MLI::CREATE::CREATE_TIME+1) - (MLI::CREATE::PATHNAME+1) - 1 : lda CREATE,x sta mliparam + MLI::CREATE::ACCESS,x dex bpl :- ; Make directory lda #CREATE_CALL ldx #CREATE_COUNT jsr callmli ; Cleanup name jsr popname ; Preserves A oserr: rts .rodata CREATE: .byte %11000011 ; ACCESS: Standard full access .byte $0F ; FILE_TYPE: Directory file .word $0000 ; AUX_TYPE: N/A .byte $0D ; STORAGE_TYPE: Linked directory file .word $0000 ; CREATE_DATE: Current date .word $0000 ; CREATE_TIME: Current time ����������������������������������������������������������������cc65-2.18/libsrc/apple2/sysremove.s�����������������������������������������������������������������0000664�0000000�0000000�00000001261�13473601511�0017066�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 15.04.2005 ; ; unsigned char __fastcall__ _sysremove (const char* name); ; .export __sysremove .import pushname, popname .include "zeropage.inc" .include "mli.inc" __sysremove: ; Push name jsr pushname bne oserr ; Set pushed name lda sp ldx sp+1 sta mliparam + MLI::DESTROY::PATHNAME stx mliparam + MLI::DESTROY::PATHNAME+1 ; Remove file lda #DESTROY_CALL ldx #DESTROY_COUNT jsr callmli ; Cleanup name jsr popname ; Preserves A oserr: rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/sysrename.s�����������������������������������������������������������������0000664�0000000�0000000�00000002515�13473601511�0017043�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 15.04.2005 ; ; unsigned char __fastcall__ _sysrename (const char* oldname, const char* newname); ; .export __sysrename .import pushname, popname .import popax .include "zeropage.inc" .include "mli.inc" __sysrename: ; Save newname sta ptr2 stx ptr2+1 ; Get and push oldname jsr popax jsr pushname bne oserr1 ; Save pushed oldname lda sp ldx sp+1 sta ptr3 stx ptr3+1 ; Restore and push newname lda ptr2 ldx ptr2+1 jsr pushname bne oserr2 ; Restore and set pushed oldname lda ptr3 ldx ptr3+1 sta mliparam + MLI::RENAME::PATHNAME stx mliparam + MLI::RENAME::PATHNAME+1 ; Set pushed newname lda sp ldx sp+1 sta mliparam + MLI::RENAME::NEW_PATHNAME stx mliparam + MLI::RENAME::NEW_PATHNAME+1 ; Rename file lda #RENAME_CALL ldx #RENAME_COUNT jsr callmli ; Cleanup newname jsr popname ; Preserves A ; Cleanup oldname oserr2: jmp popname ; Preserves A oserr1: rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/sysrmdir.s������������������������������������������������������������������0000664�0000000�0000000�00000000301�13473601511�0016700�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 15.04.2005 ; ; unsigned char __fastcall__ _sysrmdir (const char* name); ; .export __sysrmdir .import __sysremove __sysrmdir := __sysremove �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/sysuname.s������������������������������������������������������������������0000664�0000000�0000000�00000001442�13473601511�0016677�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-08-12 ; ; unsigned char __fastcall__ _sysuname (struct utsname* buf); ; .export __sysuname, utsdata .import utscopy __sysuname = utscopy ;-------------------------------------------------------------------------- ; Data. We define a fixed utsname struct here and just copy it. .rodata utsdata: ; sysname .asciiz "cc65" ; nodename .asciiz "" ; release .byte ((.VERSION >> 8) & $0F) + '0' .byte '.' .byte ((.VERSION >> 4) & $0F) + '0' .byte $00 ; version .byte (.VERSION & $0F) + '0' .byte $00 ; machine .asciiz "Apple ][" ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/targetutil/�����������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0017032�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/targetutil/Makefile.inc�����������������������������������������������������0000664�0000000�0000000�00000000574�13473601511�0021250�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������DEPS += ../libwrk/$(TARGET)/loader.d ../libwrk/$(TARGET)/loader.o: $(SRCDIR)/targetutil/loader.s | ../libwrk/$(TARGET) $(ASSEMBLE_recipe) ../target/$(TARGET)/util/loader.system: ../libwrk/$(TARGET)/loader.o $(SRCDIR)/targetutil/loader.cfg | ../target/$(TARGET)/util $(LD65) -o $@ -C $(filter %.cfg,$^) $(filter-out %.cfg,$^) $(TARGET): ../target/$(TARGET)/util/loader.system ������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/targetutil/loader.cfg�������������������������������������������������������0000664�0000000�0000000�00000001473�13473601511�0020766�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������################################################################################# # # # LOADER.SYSTEM - an Apple][ ProDOS 8 loader for cc65 programs (Oliver Schmidt) # # # ################################################################################# MEMORY { MEMORY_2000: start = $2000, size = $0200, file = %O; MEMORY_0300: start = $0300, size = $0100; } SEGMENTS { CODE_2000: load = MEMORY_2000, type = ro; DATA_2000: load = MEMORY_2000, type = rw; CODE_0300: load = MEMORY_2000, run = MEMORY_0300, type = ro, define = yes; DATA_0300: load = MEMORY_2000, run = MEMORY_0300, type = rw, define = yes; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/targetutil/loader.s���������������������������������������������������������0000664�0000000�0000000�00000014354�13473601511�0020473�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; LOADER.SYSTEM - an Apple][ ProDOS 8 loader for cc65 programs (Oliver Schmidt) ; ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; A1L := $3C A1H := $3D STACK := $0100 BUF := $0200 PATHNAME := $0280 MLI := $BF00 VERSION := $FBB3 RDKEY := $FD0C PRBYTE := $FDDA COUT := $FDED QUIT_CALL = $65 GET_FILE_INFO_CALL = $C4 OPEN_CALL = $C8 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" GET_FILE_INFO_PARAM: .byte $0A ;PARAM_COUNT .addr PATHNAME ;PATHNAME .byte $00 ;ACCESS .byte $00 ;FILE_TYPE FILE_INFO_ADDR: .word $0000 ;AUX_TYPE .byte $00 ;STORAGE_TYPE .word $0000 ;BLOCKS_USED .word $0000 ;MOD_DATE .word $0000 ;MOD_TIME .word $0000 ;CREATE_DATE .word $0000 ;CREATE_TIME OPEN_PARAM: .byte $03 ;PARAM_COUNT .addr PATHNAME ;PATHNAME .addr MLI - 1024 ;IO_BUFFER OPEN_REF: .byte $00 ;REF_NUM LOADING: .byte $0D .asciiz "Loading " ELLIPSES: .byte " ...", $0D, $0D, $00 ; ------------------------------------------------------------------------ .segment "DATA_0300" READ_PARAM: .byte $04 ;PARAM_COUNT READ_REF: .byte $00 ;REF_NUM READ_ADDR: .addr $0000 ;DATA_BUFFER .word $FFFF ;REQUEST_COUNT .word $0000 ;TRANS_COUNT CLOSE_PARAM: .byte $01 ;PARAM_COUNT CLOSE_REF: .byte $00 ;REF_NUM QUIT_PARAM: .byte $04 ;PARAM_COUNT .byte $00 ;QUIT_TYPE .word $0000 ;RESERVED .byte $00 ;RESERVED .word $0000 ;RESERVED FILE_NOT_FOUND: .asciiz "... File Not Found" ERROR_NUMBER: .asciiz "... Error $" PRESS_ANY_KEY: .asciiz " - Press Any Key " ; ------------------------------------------------------------------------ .segment "CODE_2000" jmp :+ .byte $EE .byte $EE .byte $7F STARTUP:.res $7F ; Reset stack : ldx #$FF txs ; 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 dex bne :- ; Remove ".SYSTEM" from pathname lda PATHNAME sec sbc #.strlen(".SYSTEM") sta PATHNAME ; Add trailing '\0' to pathname tax lda #$00 sta PATHNAME+1,x ; Copy ProDOS startup filename and trailing '\0' to stack ldx STARTUP lda #$00 beq :++ ; Branch always : lda STARTUP+1,x : sta STACK,x dex bpl :-- ; Provide some user feedback lda #<LOADING ldx #>LOADING jsr PRINT lda #<(PATHNAME+1) ldx #>(PATHNAME+1) jsr PRINT lda #<ELLIPSES ldx #>ELLIPSES jsr PRINT jsr MLI .byte GET_FILE_INFO_CALL .word GET_FILE_INFO_PARAM bcc :+ jmp ERROR : jsr MLI .byte OPEN_CALL .word OPEN_PARAM bcc :+ jmp ERROR ; Copy file reference number : lda OPEN_REF sta READ_REF sta CLOSE_REF ; Get load address from aux-type lda FILE_INFO_ADDR ldx FILE_INFO_ADDR+1 sta READ_ADDR stx READ_ADDR+1 ; It's high time to leave this place jmp __CODE_0300_RUN__ ; ------------------------------------------------------------------------ .segment "CODE_0300" jsr MLI .byte READ_CALL .word READ_PARAM bcs ERROR jsr MLI .byte CLOSE_CALL .word CLOSE_PARAM bcs ERROR ; Copy REM and startup filename to BASIC input buffer ldx #$00 lda #$B2 ; REM token bne :++ ; Branch always : inx lda a:STACK-1,x : sta BUF,x bne :-- ; Go for it ... jmp (READ_ADDR) PRINT: sta A1L stx A1H ldx VERSION ldy #$00 : lda (A1L),y beq :++ cpx #$06 ; //e ? beq :+ cmp #$60 ; lowercase ? bcc :+ and #$5F ; -> uppercase : ora #$80 jsr COUT iny bne :-- ; Branch always : rts ERROR: cmp #FILE_NOT_FOUND_ERR bne :+ lda #<FILE_NOT_FOUND ldx #>FILE_NOT_FOUND jsr PRINT beq :++ ; Branch always : pha lda #<ERROR_NUMBER ldx #>ERROR_NUMBER jsr PRINT pla jsr PRBYTE : lda #<PRESS_ANY_KEY ldx #>PRESS_ANY_KEY jsr PRINT jsr RDKEY jsr MLI .byte QUIT_CALL .word QUIT_PARAM ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/tgi/������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015431�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/tgi/a2.hi.fnt���������������������������������������������������������������0000664�0000000�0000000�00000002453�13473601511�0017047�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������dÐ�Õ�Ú�à�ï�þ� %-=FKTXbry…œ©¸ÁÐßäéòü.>JZgs— ­´ÄÔãïÿ$3BR`jt€†’œ¥ª¶ÃÌÛèó*1>JVbnx…œ¨µÀÏÚåêõþ"���� ‰’’�66� þn–R�iþ----nN� ?¿ ? ?wq �mßw M:ßN)�©n ßm�6–R� 6�6N� --NN�‰n:?w1V �’Šö �RI:?·RI�’’�IVI�)­ß3M5.Mþ-N�1w6¾-�)­ßsI¿.-u�--¾>Nþ-N�I> þ3--v�--Þ.-6ßs-N� -Þ»M:?n þ-N�--¾6N �)­ß3Mñ?M1ßs-N�)­ß3M1?w ß*u �–�R²ö �I�--Þ›--–�N �)­ßs ¶N�)­ß3 >ÿnõ-u� M1ß3--þn �-­ß3Mñ?7M1ß3-u�)­ß36Mßs-N�-­ß3M1ß3M1ß3-u�--Þn?76--�--Þn?76NI�)­ß36M5ßs-u�M1ß3M1??n þn �-66-�I166ßs-N�Mñßn7 ßn �666--�M1ÿ7 þn þn �M1ß3m1n)þn �)­ß3M1ß3M1ßs-N�-­ß3Mñ?76NI�)­ß3M1ß3 ßm�-­ß3Mñ?7 ßn �)­ß3M:w þ-N�--Þ66v �M1ß3M1ß3M1ßs-N�M1ß3M1ß3MñN�M1ß3M1n >7Mq�M1ßs  ß3Mq�M1ßs 6v �--¾.-u�--Þ;.>.>.-u�rV�-->.>.>ß*-u�‰ ß³RI�’’I??M �–R�R-ß*-þ-u�6-­ß3M1ß3-u�R-õÛ6-u�I1ß*-þn þ-u�R-ß3--Þ-u� ­ßn:?6N �R-ß3M1?w ?M�6-­ß3M1ß3Mq�ñ*6¾-�Iž56ßjño�6Mñß.­ßn �566-�m5n þn �-­ß3M1ß3Mq�R-ß3M1ßs-N�-­ß3Mñ?7nI�R-5ß3M1?w .� -Þ;6vI�R-õÛ-ß-u�1-õ3Músu�M1ß3M1ÿsm�M1ß3MñN�M1ß3 þ. u�MñMq�M1ß3M1?w ?M�----� -Þ7õw5w-�666.�-7­¿5ÿ*u �) ÿ–’I �I  VI�@À@�@À@C�@À@��@C�@À@�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/tgi/a2.hi.s�����������������������������������������������������������������0000664�0000000�0000000�00000034003�13473601511�0016516�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Graphics driver for the 280x192x8 mode on the Apple II ; ; Stefan Haubenthal <polluks@sdf.lonestar.org> ; Oliver Schmidt <ol.sc@web.de> ; .include "zeropage.inc" .include "tgi-kernel.inc" .include "tgi-error.inc" .include "apple2.inc" .macpack module ; ------------------------------------------------------------------------ ; Zero page stuff HBASL := $26 HMASK := $30 PAGE := $E6 SCALE := $E7 ROT := $F9 ; Graphics entry points, by cbmnut (applenut??) cbmnut@hushmail.com TEXT := $F399 ; Return to text screen HGR2 := $F3D8 ; Initialize and clear hi-res page 2. HGR := $F3E2 ; Initialize and clear hi-res page 1. HCLR := $F3F2 ; Clear the current hi-res screen to black. BKGND := $F3F6 ; Clear the current hi-res screen to the ; last plotted color (from ($1C). HPOSN := $F411 ; Positions the hi-res cursor without ; plotting a point. ; Enter with (A) = Y-coordinate, and ; (Y,X) = X-coordinate. HPLOT := $F457 ; Calls HPOSN and tries to plot a dot at ; the cursor's position. If you are ; trying to plot a non-white color at ; a complementary color position, no ; dot will be plotted. HLIN := $F53A ; Draws a line from the last plotted ; point or line destination to: ; (X,A) = X-coordinate, and ; (Y) = Y-coordinate. HFIND := $F5CB ; Converts the hi-res coursor's position ; back to X- and Y-coordinates; stores ; X-coordinate at $E0,E1 and Y-coordinate ; at $E2. DRAW := $F601 ; Draws a shape. Enter with (Y,X) = the ; address of the shape table, and (A) = ; the rotation factor. Uses the current ; color. XDRAW := $F65D ; Draws a shape by inverting the existing ; color of the dots the shape draws over. ; Same entry parameters as DRAW. SETHCOL := $F6EC ; Set the hi-res color to (X), where (X) ; must be between 0 and 7. ; ------------------------------------------------------------------------ ; Variables mapped to the zero page segment variables. Some of these are ; used for passing parameters to the driver. X1 := ptr1 Y1 := ptr2 X2 := ptr3 Y2 := ptr4 ; ------------------------------------------------------------------------ .ifdef __APPLE2ENH__ module_header _a2e_hi_tgi .else module_header _a2_hi_tgi .endif ; Header. Includes jump table and constants. ; First part of the header is a structure that has a magic and defines the ; capabilities of the driver .byte $74, $67, $69 ; "tgi" .byte TGI_API_VERSION ; TGI API version number .addr $0000 ; Library reference .word 280 ; X resolution .word 192 ; Y resolution .byte 8 ; Number of drawing colors pages: .byte 2 ; Number of screens available .byte 7 ; System font X size .byte 8 ; System font Y size .word $00EA ; Aspect ratio (based on 4/3 display) .byte 0 ; TGI driver flags ; Next comes the jump table. With the exception of IRQ, all entries must be ; valid and may point to an RTS for test versions (function not implemented). .addr INSTALL .addr UNINSTALL .addr INIT .addr DONE .addr GETERROR .addr CONTROL .addr CLEAR .addr SETVIEWPAGE .addr SETDRAWPAGE .addr SETCOLOR .addr SETPALETTE .addr GETPALETTE .addr GETDEFPALETTE .addr SETPIXEL .addr GETPIXEL .addr LINE .addr BAR .addr TEXTSTYLE .addr OUTTEXT ; ------------------------------------------------------------------------ .bss ; Absolute variables used in the code ERROR: .res 1 ; Error code ; ------------------------------------------------------------------------ .rodata ; Constants and tables DEFPALETTE: .byte $00, $01, $02, $03, $04, $05, $06, $07 FONT: ; Beagle Bros Shape Mechanic font F.ASCII.SMALL ; modified to exactly reproduce the text glyphs .incbin "a2.hi.fnt" ; ------------------------------------------------------------------------ .code ; INSTALL routine. Is called after the driver is loaded into memory. May ; initialize anything that has to be done just once. Is probably empty ; most of the time. ; Must set an error code: NO INSTALL: .ifdef __APPLE2ENH__ ; No page switching if 80 column store is enabled bit RD80COL bpl :+ lda #$01 sta pages : .endif ; Fall through ; UNINSTALL routine. Is called before the driver is removed from memory. May ; clean up anything done by INSTALL but is probably empty most of the time. ; Must set an error code: NO UNINSTALL: rts ; INIT: Changes an already installed device from text mode to graphics mode. ; Note that INIT/DONE may be called multiple times while the driver ; is loaded, while INSTALL is only called once, so any code that is needed ; to initializes variables and so on must go here. Setting palette and ; clearing the screen is not needed because this is called by the graphics ; kernel later. ; The graphics kernel will never call INIT when a graphics mode is already ; active, so there is no need to protect against that. ; Must set an error code: YES INIT: ; Switch into graphics mode bit MIXCLR bit HIRES bit TXTCLR ; Beagle Bros Shape Mechanic fonts don't ; scale well so use fixed scaling factor lda #$01 sta SCALE ; Done, reset the error code lda #TGI_ERR_OK sta ERROR rts ; DONE: Will be called to switch the graphics device back into text mode. ; The graphics kernel will never call DONE when no graphics mode is active, ; so there is no need to protect against that. ; Must set an error code: NO DONE: ; Switch into text mode bit TXTSET bit LOWSCR .ifdef __APPLE2ENH__ ; Limit SET80COL-HISCR to text bit LORES .endif ; Reset the text window top lda #$00 sta WNDTOP rts ; GETERROR: Return the error code in A and clear it. GETERROR: lda ERROR ldx #TGI_ERR_OK stx ERROR rts ; CONTROL: Platform/driver specific entry point. ; Must set an error code: YES CONTROL: ; Check data msb and code to be 0 ora ptr1+1 bne err ; Check data lsb to be [0..1] lda ptr1 cmp #1+1 bcs err ; Set text window top tax beq :+ lda #20 : sta WNDTOP ; Switch 4 lines of text .assert MIXCLR + 1 = MIXSET, error lda MIXCLR,x ; No BIT absolute,X available ; Done, reset the error code lda #TGI_ERR_OK beq :+ ; Branch always ; Done, set the error code err: lda #TGI_ERR_INV_ARG : sta ERROR rts ; CLEAR: Clears the screen. ; Must set an error code: NO CLEAR: bit $C082 ; Switch in ROM jsr HCLR bit $C080 ; Switch in LC bank 2 for R/O rts ; SETVIEWPAGE: Set the visible page. Called with the new page in A (0..n). ; The page number is already checked to be valid by the graphics kernel. ; Must set an error code: NO (will only be called if page ok) SETVIEWPAGE: tax .assert LOWSCR + 1 = HISCR, error lda LOWSCR,x ; No BIT absolute,X available rts ; SETDRAWPAGE: Set the drawable page. Called with the new page in A (0..n). ; The page number is already checked to be valid by the graphics kernel. ; Must set an error code: NO (will only be called if page ok) SETDRAWPAGE: tax beq :+ lda #>$4000 ; Page 2 .byte $2C ; BIT absolute : lda #>$2000 ; Page 1 sta PAGE rts ; SETCOLOR: Set the drawing color (in A). The new color is already checked ; to be in a valid range (0..maxcolor-1). ; Must set an error code: NO (will only be called if color ok) SETCOLOR: bit $C082 ; Switch in ROM tax jsr SETHCOL bit $C080 ; Switch in LC bank 2 for R/O rts ; SETPALETTE: Set the palette (not available with all drivers/hardware). ; A pointer to the palette is passed in ptr1. Must set an error if palettes ; are not supported ; Must set an error code: YES SETPALETTE: lda #TGI_ERR_INV_FUNC sta ERROR rts ; GETPALETTE: Return the current palette in A/X. Even drivers that cannot ; set the palette should return the default palette here, so there's no ; way for this function to fail. ; Must set an error code: NO GETPALETTE: ; Fall through ; GETDEFPALETTE: Return the default palette for the driver in A/X. All ; drivers should return something reasonable here, even drivers that don't ; support palettes, otherwise the caller has no way to determine the colors ; of the (not changeable) palette. ; Must set an error code: NO (all drivers must have a default palette) GETDEFPALETTE: lda #<DEFPALETTE ldx #>DEFPALETTE rts ; SETPIXEL: Draw one pixel at X1/Y1 = ptr1/ptr2 with the current drawing ; color. The coordinates passed to this function are never outside the ; visible screen area, so there is no need for clipping inside this function. ; Must set an error code: NO SETPIXEL: bit $C082 ; Switch in ROM ldx X1 ldy X1+1 lda Y1 jsr HPLOT bit $C080 ; Switch in LC bank 2 for R/O rts ; GETPIXEL: Read the color value of a pixel and return it in A/X. The ; coordinates passed to this function are never outside the visible screen ; area, so there is no need for clipping inside this function. GETPIXEL: bit $C082 ; Switch in ROM ldx X1 ldy X1+1 lda Y1 jsr HPOSN lda (HBASL),y and HMASK asl beq :+ ; 0 (black) lda #$03 ; 3 (white) : bcc :+ adc #$03 ; += 4 (black -> black2, white -> white2) : ldx #$00 bit $C080 ; Switch in LC bank 2 for R/O rts ; LINE: Draw a line from X1/Y1 to X2/Y2, where X1/Y1 = ptr1/ptr2 and ; X2/Y2 = ptr3/ptr4 using the current drawing color. ; Must set an error code: NO LINE: bit $C082 ; Switch in ROM ldx X1 ldy X1+1 lda Y1 jsr HPOSN lda X2 ldx X2+1 ldy Y2 jsr HLIN bit $C080 ; Switch in LC bank 2 for R/O rts ; BAR: Draw a filled rectangle with the corners X1/Y1, X2/Y2, where ; X1/Y1 = ptr1/ptr2 and X2/Y2 = ptr3/ptr4 using the current drawing color. ; Contrary to most other functions, the graphics kernel will sort and clip ; the coordinates before calling the driver, so on entry the following ; conditions are valid: ; X1 <= X2 ; Y1 <= Y2 ; (X1 >= 0) && (X1 < XRES) ; (X2 >= 0) && (X2 < XRES) ; (Y1 >= 0) && (Y1 < YRES) ; (Y2 >= 0) && (Y2 < YRES) ; Must set an error code: NO BAR: inc Y2 : lda Y2 pha lda Y1 sta Y2 jsr LINE pla sta Y2 inc Y1 cmp Y1 bne :- rts ; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in X and Y ; direction is passend in X/Y, the text direction is passed in A. ; Must set an error code: NO TEXTSTYLE: cmp #TGI_TEXT_VERTICAL bne :+ lda #48 : sta ROT rts ; OUTTEXT: Output text at X/Y = ptr1/ptr2 using the current color and the ; current text style. The text to output is given as a zero terminated ; string with address in ptr3. ; Must set an error code: NO OUTTEXT: bit $C082 ; Switch in ROM lda X1 ldy X1+1 ldx ROT php ; Save Z flag beq :+ ; Not horizontal sec sbc #$07 ; Adjust X bcs :+ dey : tax lda Y1 plp ; Restore Z flag bne :+ ; Not vertical sec sbc #$07 ; Adjust Y : jsr HPOSN clc lda FONT+2*99 ; "connection char" adc #<FONT sta ptr4 lda FONT+2*99+1 ; "connection char" adc #>FONT sta ptr4+1 ldy #$00 : lda (ptr3),y beq :+ sty tmp1 ; Save string index sec sbc #$1F ; No control chars asl ; Offset * 2 tay clc lda FONT,y adc #<FONT tax lda FONT+1,y adc #>FONT tay lda ROT jsr DRAW ; Draw char from string ldx ptr4 ldy ptr4+1 lda ROT jsr DRAW ; Draw "connection char" ldy tmp1 ; Restore string index iny bne :- ; Branch always : bit $C080 ; Switch in LC bank 2 for R/O rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/tgi/a2.lo.s�����������������������������������������������������������������0000664�0000000�0000000�00000025354�13473601511�0016541�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Graphics driver for the 40x48x16 mode on the Apple II ; ; Stefan Haubenthal <polluks@sdf.lonestar.org> ; Oliver Schmidt <ol.sc@web.de> ; .include "zeropage.inc" .include "tgi-kernel.inc" .include "tgi-error.inc" .include "apple2.inc" .macpack module ; ------------------------------------------------------------------------ ; Zero page stuff H2 := $2C COLOR := $30 ; ROM entry points TEXT := $F399 PLOT := $F800 HLINE := $F819 CLRSC2 := $F838 SETCOL := $F864 SCRN := $F871 SETGR := $FB40 HOME := $FC58 ; Used for passing parameters to the driver X1 := ptr1 Y1 := ptr2 X2 := ptr3 Y2 := ptr4 ; ------------------------------------------------------------------------ .ifdef __APPLE2ENH__ module_header _a2e_lo_tgi .else module_header _a2_lo_tgi .endif ; Header. Includes jump table and constants. ; First part of the header is a structure that has a magic and defines the ; capabilities of the driver .byte $74, $67, $69 ; "tgi" .byte TGI_API_VERSION ; TGI API version number .addr $0000 ; Library reference .word 40 ; X resolution .word 48 ; Y resolution .byte 16 ; Number of drawing colors .byte 1 ; Number of screens available .byte 0 ; System font X size .byte 0 ; System font Y size .word $0198 ; Aspect ratio (based on 4/3 display) .byte 0 ; TGI driver flags ; Next comes the jump table. With the exception of IRQ, all entries must be ; valid and may point to an RTS for test versions (function not implemented). .addr INSTALL .addr UNINSTALL .addr INIT .addr DONE .addr GETERROR .addr CONTROL .addr CLEAR .addr SETVIEWPAGE .addr SETDRAWPAGE .addr SETCOLOR .addr SETPALETTE .addr GETPALETTE .addr GETDEFPALETTE .addr SETPIXEL .addr GETPIXEL .addr LINE .addr BAR .addr TEXTSTYLE .addr OUTTEXT ; ------------------------------------------------------------------------ .bss ERROR: .res 1 ; Error code MIX: .res 1 ; 4 lines of text ; ------------------------------------------------------------------------ .rodata DEFPALETTE: .byte $00, $01, $02, $03, $04, $05, $06, $07 .byte $08, $09, $0A, $0B, $0C, $0D, $0E, $0F TGI2COL: .byte $00, $0C, $03, $0F, $01, $09, $06, $02 .byte $04, $05, $07, $08, $0A, $0B, $0D, $0E COL2TGI: .byte $00, $04, $07, $02, $08, $09, $06, $0A .byte $0B, $05, $0C, $0D, $01, $0E, $0F, $03 MAXY: .byte 47, 39 ; ------------------------------------------------------------------------ .code ; INIT: Changes an already installed device from text mode to graphics mode. ; Note that INIT/DONE may be called multiple times while the driver ; is loaded, while INSTALL is only called once, so any code that is needed ; to initializes variables and so on must go here. Setting palette and ; clearing the screen is not needed because this is called by the graphics ; kernel later. ; The graphics kernel will never call INIT when a graphics mode is already ; active, so there is no need to protect against that. ; Must set an error code: YES INIT: ; Switch into graphics mode bit $C082 ; Switch in ROM jsr SETGR bit MIXCLR bit $C080 ; Switch in LC bank 2 for R/O ; Done, reset the error code lda #TGI_ERR_OK sta ERROR sta MIX ; Fall through ; INSTALL routine. Is called after the driver is loaded into memory. May ; initialize anything that has to be done just once. Is probably empty ; most of the time. ; Must set an error code: NO INSTALL: ; Fall through ; UNINSTALL routine. Is called before the driver is removed from memory. May ; clean up anything done by INSTALL but is probably empty most of the time. ; Must set an error code: NO UNINSTALL: ; Fall through ; SETVIEWPAGE: Set the visible page. Called with the new page in A (0..n). ; The page number is already checked to be valid by the graphics kernel. ; Must set an error code: NO (will only be called if page ok) SETVIEWPAGE: ; Fall through ; SETDRAWPAGE: Set the drawable page. Called with the new page in A (0..n). ; The page number is already checked to be valid by the graphics kernel. ; Must set an error code: NO (will only be called if page ok) SETDRAWPAGE: ; Fall through ; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in X and Y ; direction is passend in X/Y, the text direction is passed in A. ; Must set an error code: NO TEXTSTYLE: ; Fall through ; OUTTEXT: Output text at X/Y = ptr1/ptr2 using the current color and the ; current text style. The text to output is given as a zero terminated ; string with address in ptr3. ; Must set an error code: NO OUTTEXT: rts ; DONE: Will be called to switch the graphics device back into text mode. ; The graphics kernel will never call DONE when no graphics mode is active, ; so there is no need to protect against that. ; Must set an error code: NO DONE: bit $C082 ; Switch in ROM jsr TEXT jsr HOME bit $C080 ; Switch in LC bank 2 for R/O rts ; GETERROR: Return the error code in A and clear it. GETERROR: lda ERROR ldx #TGI_ERR_OK stx ERROR rts ; CLEAR: Clears the screen. ; Must set an error code: NO CLEAR: bit $C082 ; Switch in ROM lda COLOR ; Save current drawing color pha ldx MIX ldy MAXY,x ; Max Y depends on 4 lines of text jsr CLRSC2 pla sta COLOR ; Restore current drawing color bit $C080 ; Switch in LC bank 2 for R/O rts ; SETCOLOR: Set the drawing color (in A). The new color is already checked ; to be in a valid range (0..maxcolor-1). ; Must set an error code: NO (will only be called if color ok) SETCOLOR: bit $C082 ; Switch in ROM tax lda TGI2COL,x jsr SETCOL bit $C080 ; Switch in LC bank 2 for R/O rts ; CONTROL: Platform/driver specific entry point. ; Must set an error code: YES CONTROL: ; Check data msb and code to be 0 ora ptr1+1 bne err ; Check data lsb to be [0..1] lda ptr1 cmp #1+1 bcs err bit $C082 ; Switch in ROM ; Switch 4 lines of text tax .assert MIXCLR + 1 = MIXSET, error lda MIXCLR,x ; No BIT absolute,X available ; Save current switch setting txa sta MIX bne text ; Clear 8 lines of graphics lda COLOR ; Save current drawing color pha lda #39 ; Rightmost column sta H2 ldx #40 ; First line : txa ldy #$00 ; Leftmost column sty COLOR ; Black jsr HLINE ; Preserves X inx cpx #47+1 ; Last line bcc :- pla sta COLOR ; Restore current drawing color bcs :+ ; Branch always ; Clear 4 lines of text text: jsr HOME : bit $C080 ; Switch in LC bank 2 for R/O ; Done, reset the error code lda #TGI_ERR_OK beq :+ ; Branch always ; Done, set the error code err: lda #TGI_ERR_INV_ARG : sta ERROR rts ; SETPALETTE: Set the palette (not available with all drivers/hardware). ; A pointer to the palette is passed in ptr1. Must set an error if palettes ; are not supported ; Must set an error code: YES SETPALETTE: lda #TGI_ERR_INV_FUNC sta ERROR rts ; GETPALETTE: Return the current palette in A/X. Even drivers that cannot ; set the palette should return the default palette here, so there's no ; way for this function to fail. ; Must set an error code: NO GETPALETTE: ; Fall through ; GETDEFPALETTE: Return the default palette for the driver in A/X. All ; drivers should return something reasonable here, even drivers that don't ; support palettes, otherwise the caller has no way to determine the colors ; of the (not changeable) palette. ; Must set an error code: NO (all drivers must have a default palette) GETDEFPALETTE: lda #<DEFPALETTE ldx #>DEFPALETTE rts ; SETPIXEL: Draw one pixel at X1/Y1 = ptr1/ptr2 with the current drawing ; color. The coordinates passed to this function are never outside the ; visible screen area, so there is no need for clipping inside this function. ; Must set an error code: NO SETPIXEL: bit $C082 ; Switch in ROM ldy X1 lda Y1 jsr PLOT bit $C080 ; Switch in LC bank 2 for R/O rts ; GETPIXEL: Read the color value of a pixel and return it in A/X. The ; coordinates passed to this function are never outside the visible screen ; area, so there is no need for clipping inside this function. GETPIXEL: bit $C082 ; Switch in ROM ldy X1 lda Y1 jsr SCRN tax lda COL2TGI,x ldx #$00 bit $C080 ; Switch in LC bank 2 for R/O rts ; BAR: Draw a filled rectangle with the corners X1/Y1, X2/Y2, where ; X1/Y1 = ptr1/ptr2 and X2/Y2 = ptr3/ptr4 using the current drawing color. ; Contrary to most other functions, the graphics kernel will sort and clip ; the coordinates before calling the driver, so on entry the following ; conditions are valid: ; X1 <= X2 ; Y1 <= Y2 ; (X1 >= 0) && (X1 < XRES) ; (X2 >= 0) && (X2 < XRES) ; (Y1 >= 0) && (Y1 < YRES) ; (Y2 >= 0) && (Y2 < YRES) ; Must set an error code: NO BAR: bit $C082 ; Switch in ROM lda X2 sta H2 inc Y2 ldx Y1 : txa ldy X1 jsr HLINE ; Preserves X inx cpx Y2 bcc :- bit $C080 ; Switch in LC bank 2 for R/O rts ; ------------------------------------------------------------------------ .include "../../tgi/tgidrv_line.inc" ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/tgi_colors.s����������������������������������������������������������������0000664�0000000�0000000�00000000340�13473601511�0017173�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Target-specific black & white values for use by the target-shared TGI kernel ; .include "tgi-kernel.inc" .export tgi_color_black:zp = $00 .export tgi_color_white:zp = $03 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/tgi_stat_stddrv.s�����������������������������������������������������������0000664�0000000�0000000�00000000621�13473601511�0020235�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Address of the static standard tgi driver ; ; Oliver Schmidt, 2012-11-01 ; ; const void tgi_static_stddrv[]; ; .export _tgi_static_stddrv .ifdef __APPLE2ENH__ .import _a2e_hi_tgi .else .import _a2_hi_tgi .endif .rodata .ifdef __APPLE2ENH__ _tgi_static_stddrv := _a2e_hi_tgi .else _tgi_static_stddrv := _a2_hi_tgi .endif ���������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/tgi_stddrv.s����������������������������������������������������������������0000664�0000000�0000000�00000000412�13473601511�0017200�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Name of the standard tgi driver ; ; Oliver Schmidt, 2011-05-02 ; ; const char tgi_stddrv[]; ; .export _tgi_stddrv .rodata _tgi_stddrv: .ifdef __APPLE2ENH__ .asciiz "A2E.HI.TGI" .else .asciiz "A2.HI.TGI" .endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/videomode.s�����������������������������������������������������������������0000664�0000000�0000000�00000004534�13473601511�0017013�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 07.09.2009 ; ; unsigned __fastcall__ videomode (unsigned mode); ; .ifdef __APPLE2ENH__ .export _videomode .import COUT .include "apple2.inc" .segment "LOWCODE" _videomode: ; Get and save current videomode flag bit RD80VID php ; If we are in 80 column mode then the 80 column firmware is ; known to be active so we can just print the ctrl-char code ; (even if this only means staying in the current videomode) bpl :+ jsr COUT bra done ; If we are in 40 column mode and want to set 40 column mode ; then we explicitly do nothing as we neither know about the ; current state of the 80 column firmware nor want to fix it : cmp #$11 ; Ctrl-char code for 40 cols beq done ; If we are in 40 column mode and want to set 80 column mode ; then we first presume the 80 column firmware being already ; active and print the ctrl-char code (this causes a garbage ; char to be printed on the screen if isn't already active) jsr COUT ; If we successfully switched to 80 column mode then the 80 ; column firmware was in fact already active and we're done bit RD80VID bmi done ; The 80 column firmware isn't already active so we need to ; initialize it - causing the screen to be cleared and thus ; the garbage char printed above to be erased (but for some ; reason the cursor horizontal position not to be zeroed) stz CH ; Initializing the 80 column firmware needs the ROM switched ; in, otherwise it would copy the F8 ROM to the LC (@ $CEF4) bit $C082 ; Initialize 80 column firmware jsr $C300 ; PR#3 ; Switch in LC bank 2 for R/O bit $C080 ; Return ctrl-char code for setting previous ; videomode using the saved videomode flag done: lda #$11 ; Ctrl-char code for 40 cols plp bpl :+ lda #$12 ; Ctrl-char code for 80 cols : rts ; X was preserved all the way .endif ; __APPLE2ENH__ ��������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/vtabz.s���������������������������������������������������������������������0000664�0000000�0000000�00000000551�13473601511�0016161�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 03.03.2007 ; ; VTABZ routine ; .export VTABZ .include "apple2.inc" .segment "LOWCODE" VTABZ: ; Switch in ROM and call VTABZ bit $C082 jsr $FC24 ; Generate text base address ; Switch in LC bank 2 and return bit $C080 rts �������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/wherex.s��������������������������������������������������������������������0000664�0000000�0000000�00000000271�13473601511�0016334�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Kevin Ruland ; ; unsigned char wherex (void); ; .export _wherex .include "apple2.inc" _wherex: lda CH ldx #$00 rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/wherey.s��������������������������������������������������������������������0000664�0000000�0000000�00000000334�13473601511�0016335�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Kevin Ruland ; ; unsigned char wherey (void); ; .export _wherey .include "apple2.inc" _wherey: lda CV sec sbc WNDTOP ldx #$00 rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/apple2/write.s���������������������������������������������������������������������0000664�0000000�0000000�00000005146�13473601511�0016172�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 12.01.2005 ; ; int __fastcall__ write (int fd, const void* buf, unsigned count); ; .export _write .import rwprolog, rwcommon, rwepilog .import COUT .include "zeropage.inc" .include "errno.inc" .include "fcntl.inc" .include "mli.inc" .include "filedes.inc" _write: ; Get parameters jsr rwprolog bcs errno tax ; Save fd ; Check for write access lda fdtab + FD::FLAGS,y and #O_WRONLY beq einval ; Check for device txa ; Restore fd bmi device ; Check for append flag lda fdtab + FD::FLAGS,y and #O_APPEND beq write ; Set fd stx mliparam + MLI::EOF::REF_NUM ; Get file size lda #GET_EOF_CALL ldx #EOF_COUNT jsr callmli bcs oserr ; REF_NUM already set .assert MLI::MARK::REF_NUM = MLI::EOF::REF_NUM, error ; POSITION already set .assert MLI::MARK::POSITION = MLI::EOF::EOF, error ; Set file pointer lda #SET_MARK_CALL ldx #MARK_COUNT jsr callmli bcs oserr ; Do write write: lda fdtab + FD::REF_NUM,y ldy #WRITE_CALL jmp rwcommon ; Save count for epilog device: ldx ptr2 lda ptr2+1 stx mliparam + MLI::RW::TRANS_COUNT sta mliparam + MLI::RW::TRANS_COUNT+1 ; Check for zero count ora ptr2 beq done ; Get char from buf ldy #$00 next: lda (ptr1),y ; Replace '\n' with '\r' cmp #$0A bne :+ lda #$0D ; Set hi bit and write to device : ora #$80 .ifndef __APPLE2ENH__ cmp #$E0 ; Test for lowercase bcc output and #$DF ; Convert to uppercase .endif output: jsr COUT ; Preserves X and Y ; Increment pointer iny bne :+ inc ptr1+1 ; Decrement count : dex bne next dec ptr2+1 bpl next ; Return success done: lda #$00 jmp rwepilog ; Load errno code einval: lda #EINVAL ; Set __errno errno: jmp __directerrno ; Set __oserror oserr: jmp __mappederrno ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/�����������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014563�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/Makefile.inc�����������������������������������������������������������������0000664�0000000�0000000�00000003664�13473601511�0017004�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# NUMDRVS - number of supported drives (max. 16) # 4 bytes for each device are statically allocated # LINEBUF - support line buffered reads from E: (the number specifies # the length of the buffer) # UCASE_FILENAME - all filenames get uppercased # DEFAULT_DEVICE - if the string passed to the uppercase function doesn't # include a device (":" at position 2 or 3), provide "Dn:" # as a default disk device # n is the value of DEFAULT_DEVICE, unless DYNAMIC_DD is # also set, in which case it's overridden by a runtime # check (on SpartaDOS only) # needs UCASE_FILENAME to be defined, otherwise no effect # DYNAMIC_DD - determine default disk device at runtime (SpartaDOS only) # needs DEFAULT_DEVICE to be defined, otherwise no effect CA65FLAGS += -D NUMDRVS=4 -D LINEBUF=80 -D UCASE_FILENAME=1 -D DEFAULT_DEVICE=1 -D DYNAMIC_DD=1 # The following defines are only used by the 'atarixl' target: # # CHARGEN_RELOC - If defined, CHBAS and CHBASE are updated when # enabling or disabling the ROM. # If the ROM is enabled, $E0 is written to CHBAS # and CHBASE. # If the ROM is disabled, the upper byte of # __CHARGEN_START__ is written to CHBAS and CHBASE. # USEWSYNC - If defined, the code waits for horizontal retrace # before switching the ROM and updating CHBAS and # CHBASE. This define only has effect if CHARGEN_RELOC # is also defined. # Disabled by default, you should enable it if the linker script relocates the # character generator (like atarixl-largehimem.cfg). #CA65FLAGS += -D CHARGEN_RELOC -D USEWSYNC # Disable if you don't want to use page 6 for mouse P/M data. # If disabled, top of the RAM is used for P/M data. CA65FLAGS += -D USE_PAGE6 ����������������������������������������������������������������������������cc65-2.18/libsrc/atari/_scrsize.s�������������������������������������������������������������������0000664�0000000�0000000�00000000356�13473601511�0016574�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.10.2000 ; ; Screen size variables ; .export screensize .include "atari.inc" .proc screensize ldx RMARGN inx ldy #24 rts .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/_sys.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000355�13473601511�0015727�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, 17-Sep-2013 ; ; Override _sys() function for Atari targets: ; 'atari' gets the regular function ; 'atarixl' doesn't support the _sys() function ; .ifndef __ATARIXL__ .include "../common/_sys.s" .endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/bgcolor.s��������������������������������������������������������������������0000664�0000000�0000000�00000000674�13473601511�0016405�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, 02-Apr-2019 ; .export _bgcolor .include "atari.inc" _bgcolor: ldx COLOR2 ; get old value sta COLOR2 ; set new value and #$0e cmp #8 bcs bright lda #$0e .byte $2c ; bit opcode, eats the next 2 bytes bright: lda #0 sta COLOR1 txa ldx #0 ; fix X rts ��������������������������������������������������������������������cc65-2.18/libsrc/atari/bordercolor.s����������������������������������������������������������������0000664�0000000�0000000�00000000412�13473601511�0017260�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, 02-Apr-2019 ; .export _bordercolor .include "atari.inc" _bordercolor: ldx COLOR4 ; get old value sta COLOR4 ; set new value txa ldx #0 ; fix X rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/break.s����������������������������������������������������������������������0000664�0000000�0000000�00000004270�13473601511�0016036�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, 27-Feb-2000 ; ; void __fastcall__ set_brk (unsigned Addr); ; void reset_brk (void); ; .export _set_brk, _reset_brk .destructor _reset_brk .export _brk_a, _brk_x, _brk_y, _brk_sr, _brk_pc .include "atari.inc" .bss _brk_a: .res 1 _brk_x: .res 1 _brk_y: .res 1 _brk_sr: .res 1 _brk_pc: .res 2 oldvec: .res 2 ; Old vector .data uservec: jmp $FFFF ; Patched at runtime .code ; Set the break vector .proc _set_brk sta uservec+1 stx uservec+2 ; Set the user vector lda oldvec ora oldvec+1 ; Did we save the vector already? bne L1 ; Jump if we installed the handler already lda VBREAK sta oldvec lda VBREAK+1 sta oldvec+1 ; Save the old vector L1: lda #<brk_handler ; Set the break vector to our routine sta VBREAK lda #>brk_handler sta VBREAK+1 rts .endproc ; Reset the break vector .proc _reset_brk lda oldvec ldx oldvec+1 beq @L9 ; Jump if vector not installed sta VBREAK stx VBREAK+1 lda #$00 sta oldvec ; Clear the old vector stx oldvec+1 @L9: rts .endproc ; Break handler, called if a break occurs .proc brk_handler sty _brk_y stx _brk_x pla sta _brk_a pla and #$EF ; Clear break bit sta _brk_sr pla ; PC low sec sbc #2 ; Point to start of brk sta _brk_pc pla ; PC high sbc #0 sta _brk_pc+1 jsr uservec ; Call the user's routine lda _brk_pc+1 pha lda _brk_pc pha lda _brk_sr pha ldx _brk_x ldy _brk_y lda _brk_a rti ; Jump back... .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/carthdr.s��������������������������������������������������������������������0000664�0000000�0000000�00000001240�13473601511�0016373�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; Cartridge "header" ; (In fact, it's at the end of the cartridge, so more a "trailer".) ; ; Christian Groessler, 06-Jan-2014 .ifndef __ATARIXL__ .export __CART_HEADER__: absolute = 1 .import __CARTSIZE__, __CARTFLAGS__, cartinit, cartstart .include "atari.inc" .segment "CARTHDR" .word cartstart ; start routine .byte 0 ; must be zero .byte <__CARTFLAGS__ .word cartinit ; init routine .assert (__CARTSIZE__ = $2000 || __CARTSIZE__ = $4000), error, "Cartridge size must either be $2000 or $4000" .endif ; .ifndef __ATARIXL__ ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/cartinit.s�������������������������������������������������������������������0000664�0000000�0000000�00000000241�13473601511�0016561�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; Cartridge init routine ; ; Christian Groessler, 06-Jan-2014 .ifndef __ATARIXL__ .export cartinit cartinit: rts .endif ; .ifndef __ATARIXL__ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/cartstart.s������������������������������������������������������������������0000664�0000000�0000000�00000000710�13473601511�0016754�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; Cartridge start routine ; ; Christian Groessler, 06-Jan-2014 .ifndef __ATARIXL__ .export cartstart .import start, copydata .include "atari.inc" ; start routine of cartridge ; copy data segment to RAM and chain to entry point of crt0.s cartstart: jsr copydata jsr start ; run program jmp (DOSVEC) ; return to DOS .endif ; .ifndef __ATARIXL__ ��������������������������������������������������������cc65-2.18/libsrc/atari/cashdr.s���������������������������������������������������������������������0000664�0000000�0000000�00000001530�13473601511�0016212�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Cassette boot file header ; ; Christian Groessler, chris@groessler.org, 2014 ; ;DEBUG = 1 .ifndef __ATARIXL__ .include "atari.inc" .import __BSS_RUN__, __STARTADDRESS__, _cas_init .export _cas_hdr .assert ((__BSS_RUN__ - __STARTADDRESS__ + 127) / 128) < $101, error, "File to big to load from cassette" ; for a description of the cassette header, see De Re Atari, appendix C .segment "CASHDR" _cas_hdr: .byte 0 ; ignored .byte <((__BSS_RUN__ - __STARTADDRESS__ + 127) / 128) ; # of 128-byte records to read .word __STARTADDRESS__ ; load address .word _cas_init ; init address .ifdef DEBUG lda #33 ldy #80 sta (SAVMSC),y .endif clc rts .endif ; .ifdef __ATARIXL__ ������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/casinit.s��������������������������������������������������������������������0000664�0000000�0000000�00000000722�13473601511�0016402�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Cassette boot file init routine ; ; Christian Groessler, chris@groessler.org, 2014 ; ;DEBUG = 1 .ifndef __ATARIXL__ .include "atari.inc" .import start .export _cas_init .segment "ONCE" _cas_init: .ifdef DEBUG lda #34 ldy #81 sta (SAVMSC),y .endif lda #<start sta DOSVEC lda #>start sta DOSVEC+1 rts .endif ; .ifdef __ATARIXL__ ����������������������������������������������cc65-2.18/libsrc/atari/cclear.s���������������������������������������������������������������������0000664�0000000�0000000�00000001432�13473601511�0016200�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 gotoxy, cputdirect .importzp tmp1 _cclearxy: pha ; Save the length 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 #0 ; Blank - screen code jsr cputdirect ; Direct output dec tmp1 bne L1 L9: rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/cgetc.s����������������������������������������������������������������������0000664�0000000�0000000�00000001057�13473601511�0016037�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, November-2002 ; ; get a char from the keyboard ; char cgetc(void) ; .include "atari.inc" .export _cgetc .import setcursor .import KEYBDV_handler _cgetc: jsr setcursor lda #12 sta ICAX1Z ; fix problems with direct call to KEYBDV .ifdef __ATARIXL__ jsr KEYBDV_handler .else jsr @1 .endif ldx #0 rts .ifndef __ATARIXL__ @1: lda KEYBDV+5 pha lda KEYBDV+4 pha rts .endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/chline.s���������������������������������������������������������������������0000664�0000000�0000000�00000001432�13473601511�0016211�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 gotoxy, cputdirect, setcursor .importzp tmp1 CHRCODE = $12+64 _chlinexy: pha ; Save the length 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 #CHRCODE ; Horizontal line, screen code jsr cputdirect ; Direct output dec tmp1 bne L1 L9: jmp setcursor ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/clock.s����������������������������������������������������������������������0000664�0000000�0000000�00000002004�13473601511�0016036�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Piotr Fusik, 04.11.2001 ; originally by Ullrich von Bassewitz and Sidney Cadot ; ; clock_t clock (void); ; unsigned _clocks_per_sec (void); ; .export _clock, __clocks_per_sec .importzp sreg .include "atari.inc" .proc _clock ldx #5 ; Synchronize with Antic, so the interrupt won't change RTCLOK stx WSYNC ; while we're reading it. The synchronization is done same as @L1: dex ; in SETVBLV function in Atari OS. bne @L1 stx sreg+1 ; Byte 3 is always zero lda RTCLOK+2 ldx RTCLOK+1 ldy RTCLOK sty sreg rts .endproc .proc __clocks_per_sec ldx #$00 ; Clear high byte of return value lda PAL ; use hw register, PALNTS is only supported on XL/XE ROM and #$0e bne @NTSC lda #50 rts @NTSC: lda #60 rts .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/close.s����������������������������������������������������������������������0000664�0000000�0000000�00000001256�13473601511�0016060�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, May-2000 ; ; int __fastcall__ close(int fd); ; .include "atari.inc" .export _close .import __do_oserror,popax,__oserror .import fdtoiocb_down,__inviocb .proc _close jsr fdtoiocb_down ; get iocb index into X and decr. usage count bmi inverr bne ok ; not last one -> don't close yet lda #CLOSE sta ICCOM,x jsr CIOV bmi closerr ok: ldx #0 stx __oserror ; clear system specific error code txa rts inverr: jmp __inviocb closerr:jmp __do_oserror .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/clrscr.s���������������������������������������������������������������������0000664�0000000�0000000�00000001455�13473601511�0016244�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, Apr-2000 ; ; void clrscr (void); ; .export _clrscr .include "atari.inc" .importzp ptr1 .import setcursor SCRSIZE = 960 ; 40x24: size of default atari screen _clrscr:lda SAVMSC ; screen memory sta ptr1 lda SAVMSC+1 clc adc #>(SCRSIZE-1) sta ptr1+1 lda #0 ; screen code of space char sta OLDCHR ldy #<(SCRSIZE-1) ldx #>(SCRSIZE-1) _clr1: sta (ptr1),y dey bne _clr1 sta (ptr1),y dex bmi done dec ptr1+1 dey jmp _clr1 done: sta COLCRS sta ROWCRS jmp setcursor �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/cputc.s����������������������������������������������������������������������0000664�0000000�0000000�00000004311�13473601511�0016064�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Mark Keates, Christian Groessler, Piotr Fusik ; ; void cputcxy (unsigned char x, unsigned char y, char c); ; void cputc (char c); ; .export _cputcxy, _cputc .export plot, cputdirect, putchar .import gotoxy, _mul40 .importzp tmp4,ptr4 .import _revflag,setcursor .include "atari.inc" _cputcxy: pha ; Save C jsr gotoxy ; Set cursor, drop x and y pla ; Restore C _cputc: cmp #$0D ; CR bne L4 lda #0 sta COLCRS beq plot ; return L4: cmp #$0A ; LF beq newline cmp #ATEOL ; Atari-EOL? beq newline asl a ; shift out the inverse bit adc #$c0 ; grab the inverse bit; convert ATASCII to screen code bpl codeok ; screen code ok? eor #$40 ; needs correction codeok: lsr a ; undo the shift bcc cputdirect eor #$80 ; restore the inverse bit cputdirect: ; accepts screen code jsr putchar ; advance cursor inc COLCRS lda COLCRS cmp #40 bcc plot lda #0 sta COLCRS .export newline newline: inc ROWCRS lda ROWCRS cmp #24 bne plot lda #0 sta ROWCRS plot: jsr setcursor ldy COLCRS ldx ROWCRS rts ; turn off cursor, update screen, turn on cursor putchar: pha ; save char ldy #0 lda OLDCHR sta (OLDADR),y lda ROWCRS jsr _mul40 ; destroys tmp4, carry is cleared adc SAVMSC ; add start of screen memory sta ptr4 txa adc SAVMSC+1 sta ptr4+1 pla ; get char again ora _revflag sta OLDCHR ldy COLCRS sta (ptr4),y jmp setcursor �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/crt0.s�����������������������������������������������������������������������0000664�0000000�0000000�00000012452�13473601511�0015623�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Startup code for cc65 (ATARI version) ; ; Contributing authors: ; Mark Keates ; Freddy Offenga ; Christian Groessler ; Stefan Haubenthal ; .export __STARTUP__ : absolute = 1 ; Mark as startup .export _exit, start, excexit, SP_save .import initlib, donelib .import callmain, zerobss .import __RESERVED_MEMORY__ .import __MAIN_START__, __MAIN_SIZE__ .import __LOWCODE_RUN__, __LOWCODE_SIZE__ .ifdef __ATARIXL__ .import __STACKSIZE__ .import sram_init .import scrdev .import findfreeiocb .forceimport sramprep ; force inclusion of the "shadow RAM preparation" load chunk .include "save_area.inc" .endif .include "zeropage.inc" .include "atari.inc" ; ------------------------------------------------------------------------ .segment "STARTUP" rts ; fix for SpartaDOS / OS/A+ ; They first call the entry point from AUTOSTRT; and ; then, the load address (this rts here). ; We point AUTOSTRT directly after the rts. ; Real entry point: start: .ifdef __ATARIXL__ jsr sram_init .endif ; Clear the BSS data. jsr zerobss ; Set up the stack. tsx stx SP_save .ifdef __ATARIXL__ lda #<(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__) ldx #>(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__) sta sp stx sp+1 .else ; Report the memory usage. lda APPMHI ldx APPMHI+1 sta APPMHI_save ; remember old APPMHI value stx APPMHI_save+1 sec lda MEMTOP sbc #<__RESERVED_MEMORY__ sta APPMHI ; initialize our APPMHI value sta sp ; set up runtime stack part 1 lda MEMTOP+1 sbc #>__RESERVED_MEMORY__ sta APPMHI+1 sta sp+1 ; set up runtime stack part 2 .endif ; Call the module constructors. jsr initlib ; Set the left margin to 0. lda LMARGN sta LMARGN_save ldy #0 sty LMARGN ; Set the keyboard to upper-/lower-case mode. ldx SHFLOK stx SHFLOK_save sty SHFLOK ; Initialize the conio stuff. dey ; Set Y to $FF sty CH ; remove keypress which might be in the input buffer ; Push the command-line arguments; and, call main(). jsr callmain ; Call the module destructors. This is also the exit() entry. _exit: ldx SP_save txs ; Restore stack pointer ; Restore the system stuff. excexit:jsr donelib ; Run module destructors; 'excexit' is called from the exec routine ; Restore the left margin. lda LMARGN_save sta LMARGN ; Restore the kb mode. lda SHFLOK_save sta SHFLOK ; Restore APPMHI. lda APPMHI_save ldx APPMHI_save+1 sta APPMHI stx APPMHI+1 .ifdef __ATARIXL__ ; Atari XL target stuff... lda PORTB_save sta PORTB lda RAMTOP_save sta RAMTOP lda MEMTOP_save ldx MEMTOP_save+1 sta MEMTOP stx MEMTOP+1 ; Issue a GRAPHICS 0 call (copied'n'pasted from the TGI drivers), in ; order to restore screen memory to its default location just ; before the ROM. jsr findfreeiocb ; Reopen it in Graphics 0 lda #OPEN sta ICCOM,x lda #OPNIN | OPNOT sta ICAX1,x lda #0 sta ICAX2,x lda #<scrdev sta ICBAL,x lda #>scrdev sta ICBAH,x lda #3 sta ICBLL,x lda #0 sta ICBLH,x jsr CIOV_org ; No error checking here, shouldn't happen(TM); and, no way to ; recover anyway. lda #CLOSE sta ICCOM,x jsr CIOV_org .endif ; Turn on the cursor. ldx #0 stx CRSINH ; Back to DOS. rts ; *** end of main startup code ; ------------------------------------------------------------------------ .bss SP_save: .res 1 SHFLOK_save: .res 1 LMARGN_save: .res 1 .ifndef __ATARIXL__ APPMHI_save: .res 2 .endif ; ------------------------------------------------------------------------ .segment "LOWCODE" ; have at least one (empty) segment of LOWCODE, so that the next line works even if the program doesn't make use of this segment .assert (__LOWCODE_RUN__ + __LOWCODE_SIZE__ <= $4000 || __LOWCODE_RUN__ > $7FFF || __LOWCODE_SIZE__ = 0), warning, "'lowcode area' reaches into $4000..$7FFF bank memory window" ; check for LOWBSS_SIZE = 0 not needed since the only file which uses LOWBSS (irq.s) also uses LOWCODE ; check for LOWCODE_RUN > $7FFF is mostly for cartridges, where this segment is loaded high (into cart ROM) ; there is a small chance that if the user loads the program really high, LOWCODE is above $7FFF, but LOWBSS is below -- no warning emitted in this case ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/ctype.s����������������������������������������������������������������������0000664�0000000�0000000�00000031126�13473601511�0016076�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 02.06.1998 ; ; Character specification table. ; ; adapted to Atari by Christian Groessler, June 2000 ; ; 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. ; ; ; Bit assignments: ; ; 0 - Lower case char ; 1 - Upper case char ; 2 - Numeric digit ; 3 - Hex digit (both, lower and upper) ; 4 - Control character ; 5 - The space character itself ; 6 - Other whitespace (that is: '\f', '\n', '\r', '\t' and '\v') ; 7 - Space or tab character .export __ctype __ctype: .byte $00 ; 0/00 ___heart____ .byte $00 ; 1/01 ___l_tee____ .byte $00 ; 2/02 ___ctrl_B___ .byte $00 ; 3/03 ___ctrl_C___ .byte $00 ; 4/04 ___r_tee____ .byte $00 ; 5/05 ___ctrl_E___ .byte $00 ; 6/06 ___ctrl_F___ .byte $00 ; 7/07 ___ctrl_G___ .byte $00 ; 8/08 ___ctrl_H___ .byte $00 ; 9/09 ___ctrl_I___ .byte $00 ; 10/0a ___ctrl_J___ .byte $00 ; 11/0b ___ctrl_K___ .byte $00 ; 12/0c ___ctrl_L___ .byte $00 ; 13/0d ___ctrl_M___ .byte $00 ; 14/0e ___ctrl_N___ .byte $00 ; 15/0f ___ctrl_O___ .byte $00 ; 16/10 ____club____ .byte $00 ; 17/11 ___ctrl_Q___ .byte $00 ; 18/12 ___h_line___ .byte $00 ; 19/13 ___ctrl_S___ .byte $00 ; 20/14 ____ball____ .byte $00 ; 21/15 ___ctrl_U___ .byte $00 ; 22/16 ___ctrl_V___ .byte $00 ; 23/17 ___t_tee____ .byte $00 ; 24/18 ___b_tee____ .byte $00 ; 25/19 ___ctrl_Y___ .byte $00 ; 26/1a ___ctrl_Z___ .byte $10 ; 27/1b ____ESC_____ .byte $10 ; 28/1c ___crsr_up__ .byte $10 ; 29/1d ___crsr_dn__ .byte $10 ; 30/1e ___crsr_lf__ .byte $10 ; 31/1f ___crsr_rg__ .byte $A0 ; 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 $0C ; 48/30 _____0_____ .byte $0C ; 49/31 _____1_____ .byte $0C ; 50/32 _____2_____ .byte $0C ; 51/33 _____3_____ .byte $0C ; 52/34 _____4_____ .byte $0C ; 53/35 _____5_____ .byte $0C ; 54/36 _____6_____ .byte $0C ; 55/37 _____7_____ .byte $0C ; 56/38 _____8_____ .byte $0C ; 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 $0A ; 65/41 _____A_____ .byte $0A ; 66/42 _____B_____ .byte $0A ; 67/43 _____C_____ .byte $0A ; 68/44 _____D_____ .byte $0A ; 69/45 _____E_____ .byte $0A ; 70/46 _____F_____ .byte $02 ; 71/47 _____G_____ .byte $02 ; 72/48 _____H_____ .byte $02 ; 73/49 _____I_____ .byte $02 ; 74/4a _____J_____ .byte $02 ; 75/4b _____K_____ .byte $02 ; 76/4c _____L_____ .byte $02 ; 77/4d _____M_____ .byte $02 ; 78/4e _____N_____ .byte $02 ; 79/4f _____O_____ .byte $02 ; 80/50 _____P_____ .byte $02 ; 81/51 _____Q_____ .byte $02 ; 82/52 _____R_____ .byte $02 ; 83/53 _____S_____ .byte $02 ; 84/54 _____T_____ .byte $02 ; 85/55 _____U_____ .byte $02 ; 86/56 _____V_____ .byte $02 ; 87/57 _____W_____ .byte $02 ; 88/58 _____X_____ .byte $02 ; 89/59 _____Y_____ .byte $02 ; 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 __diamond__ .byte $09 ; 97/61 _____a_____ .byte $09 ; 98/62 _____b_____ .byte $09 ; 99/63 _____c_____ .byte $09 ; 100/64 _____d_____ .byte $09 ; 101/65 _____e_____ .byte $09 ; 102/66 _____f_____ .byte $01 ; 103/67 _____g_____ .byte $01 ; 104/68 _____h_____ .byte $01 ; 105/69 _____i_____ .byte $01 ; 106/6a _____j_____ .byte $01 ; 107/6b _____k_____ .byte $01 ; 108/6c _____l_____ .byte $01 ; 109/6d _____m_____ .byte $01 ; 110/6e _____n_____ .byte $01 ; 111/6f _____o_____ .byte $01 ; 112/70 _____p_____ .byte $01 ; 113/71 _____q_____ .byte $01 ; 114/72 _____r_____ .byte $01 ; 115/73 _____s_____ .byte $01 ; 116/74 _____t_____ .byte $01 ; 117/75 _____u_____ .byte $01 ; 118/76 _____v_____ .byte $01 ; 119/77 _____w_____ .byte $01 ; 120/78 _____x_____ .byte $01 ; 121/79 _____y_____ .byte $01 ; 122/7a _____z_____ .byte $00 ; 123/7b ___spade___ .byte $00 ; 124/7c __v_line___ .byte $10 ; 125/7d __CLRSCR___ .byte $D0 ; 126/7e __backtab__ .byte $D0 ; 127/7f ____tab____ .byte $00 ; 128/80 _inv_heart___ .byte $00 ; 129/81 _inv_l_tee___ .byte $00 ; 130/82 _inv_ctrl_B__ .byte $00 ; 131/83 _inv_ctrl_C__ .byte $00 ; 132/84 _inv_r_tee___ .byte $00 ; 133/85 _inv_ctrl_E__ .byte $00 ; 134/86 _inv_ctrl_F__ .byte $00 ; 135/87 _inv_ctrl_G__ .byte $00 ; 136/88 _inv_ctrl_H__ .byte $00 ; 137/89 _inv_ctrl_I__ .byte $00 ; 138/8a _inv_ctrl_J__ .byte $00 ; 139/8b _inv_ctrl_K__ .byte $00 ; 140/8c _inv_ctrl_L__ .byte $00 ; 141/8d _inv_ctrl_M__ .byte $00 ; 142/8e _inv_ctrl_N__ .byte $00 ; 143/8f _inv_ctrl_O__ .byte $00 ; 144/90 __inv__club__ .byte $00 ; 145/91 _inv_ctrl_Q__ .byte $00 ; 146/92 _inv_h_line__ .byte $00 ; 147/93 _inv_ctrl_S__ .byte $00 ; 148/94 __inv__ball__ .byte $00 ; 149/95 _inv_ctrl_U__ .byte $00 ; 150/96 _inv_ctrl_V__ .byte $00 ; 151/97 __inv_t_tee__ .byte $00 ; 152/98 __inv_b_tee__ .byte $00 ; 153/99 _inv_ctrl_Y__ .byte $00 ; 154/9a _inv_ctrl_Z__ .byte $50 ; 155/9b _____EOL_____ .byte $10 ; 156/9c ___CLRLINE___ .byte $10 ; 157/9d ___INSLINE___ .byte $10 ; 158/9e ____CLRTAB___ .byte $10 ; 159/9f ____INSTAB___ .byte $A0 ; 160/a0 __inv_SPACE__ .byte $00 ; 161/a1 ___inv_!_____ .byte $00 ; 162/a2 ___inv_"_____ .byte $00 ; 163/a3 ___inv_#_____ .byte $00 ; 164/a4 ___inv_$_____ .byte $00 ; 165/a5 ___inv_%_____ .byte $00 ; 166/a6 ___inv_&_____ .byte $00 ; 167/a7 ___inv_'_____ .byte $00 ; 168/a8 ___inv_(_____ .byte $00 ; 169/a9 ___inv_)_____ .byte $00 ; 170/aa ___inv_*_____ .byte $00 ; 171/ab ___inv_+_____ .byte $00 ; 172/ac ___inv_,_____ .byte $00 ; 173/ad ___inv_-_____ .byte $00 ; 174/ae ___inv_._____ .byte $00 ; 175/af ___inv_/_____ .byte $0C ; 176/b0 ___inv_0_____ .byte $0C ; 177/b1 ___inv_1_____ .byte $0C ; 178/b2 ___inv_2_____ .byte $0C ; 179/b3 ___inv_3_____ .byte $0C ; 180/b4 ___inv_4_____ .byte $0C ; 181/b5 ___inv_5_____ .byte $0C ; 182/b6 ___inv_6_____ .byte $0C ; 183/b7 ___inv_7_____ .byte $0C ; 184/b8 ___inv_8_____ .byte $0C ; 185/b9 ___inv_9_____ .byte $00 ; 186/ba ___inv_:_____ .byte $00 ; 187/bb ___inv_;_____ .byte $00 ; 188/bc ___inv_<_____ .byte $00 ; 189/bd ___inv_=_____ .byte $00 ; 190/be ___inv_>_____ .byte $00 ; 191/bf ___inv_?_____ .byte $00 ; 192/c0 ___inv_@_____ .byte $0A ; 193/c1 ___inv_A_____ .byte $0A ; 194/c2 ___inv_B_____ .byte $0A ; 195/c3 ___inv_C_____ .byte $0A ; 196/c4 ___inv_D_____ .byte $0A ; 197/c5 ___inv_E_____ .byte $0A ; 198/c6 ___inv_F_____ .byte $02 ; 199/c7 ___inv_G_____ .byte $02 ; 200/c8 ___inv_H_____ .byte $02 ; 201/c9 ___inv_I_____ .byte $02 ; 202/ca ___inv_J_____ .byte $02 ; 203/cb ___inv_K_____ .byte $02 ; 204/cc ___inv_L_____ .byte $02 ; 205/cd ___inv_M_____ .byte $02 ; 206/ce ___inv_N_____ .byte $02 ; 207/cf ___inv_O_____ .byte $02 ; 208/d0 ___inv_P_____ .byte $02 ; 209/d1 ___inv_Q_____ .byte $02 ; 210/d2 ___inv_R_____ .byte $02 ; 211/d3 ___inv_S_____ .byte $02 ; 212/d4 ___inv_T_____ .byte $02 ; 213/d5 ___inv_U_____ .byte $02 ; 214/d6 ___inv_V_____ .byte $02 ; 215/d7 ___inv_W_____ .byte $02 ; 216/d8 ___inv_X_____ .byte $02 ; 217/d9 ___inv_Y_____ .byte $02 ; 218/da ___inv_Z_____ .byte $00 ; 219/db ___inv_[_____ .byte $00 ; 220/dc ___inv_\_____ .byte $00 ; 221/dd ___inv_]_____ .byte $00 ; 222/de ___inv_^_____ .byte $00 ; 223/df _inv_UNDRLIN_ .byte $00 ; 224/e0 _inv_diamond_ .byte $09 ; 225/e1 ___inv_a_____ .byte $09 ; 226/e2 ___inv_b_____ .byte $09 ; 227/e3 ___inv_c_____ .byte $09 ; 228/e4 ___inv_d_____ .byte $09 ; 229/e5 ___inv_e_____ .byte $09 ; 230/e6 ___inv_f_____ .byte $01 ; 231/e7 ___inv_g_____ .byte $01 ; 232/e8 ___inv_h_____ .byte $01 ; 233/e9 ___inv_i_____ .byte $01 ; 234/ea ___inv_j_____ .byte $01 ; 235/eb ___inv_k_____ .byte $01 ; 236/ec ___inv_l_____ .byte $01 ; 237/ed ___inv_m_____ .byte $01 ; 238/ee ___inv_n_____ .byte $01 ; 239/ef ___inv_o_____ .byte $01 ; 240/f0 ___inv_p_____ .byte $01 ; 241/f1 ___inv_q_____ .byte $01 ; 242/f2 ___inv_r_____ .byte $01 ; 243/f3 ___inv_s_____ .byte $01 ; 244/f4 ___inv_t_____ .byte $01 ; 245/f5 ___inv_u_____ .byte $01 ; 246/f6 ___inv_v_____ .byte $01 ; 247/f7 ___inv_w_____ .byte $01 ; 248/f8 ___inv_x_____ .byte $01 ; 249/f9 ___inv_y_____ .byte $01 ; 250/fa ___inv_z_____ .byte $00 ; 251/fb __inv_spade__ .byte $00 ; 252/fc __inv_v_line_ .byte $10 ; 253/fd ____BEEP_____ .byte $10 ; 254/fe ____DELBS____ .byte $10 ; 255/ff ___INSERT____ ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/cvline.s���������������������������������������������������������������������0000664�0000000�0000000�00000001701�13473601511�0016226�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 08.08.1998 ; ; void cvlinexy (unsigned char x, unsigned char y, unsigned char length); ; void cvline (unsigned char length); ; .include "atari.inc" .export _cvlinexy, _cvline .import gotoxy, putchar, setcursor .importzp tmp1 CHRCODE = $7C ; Vertical bar _cvlinexy: pha ; Save the length 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 COLCRS pha lda #CHRCODE ; Vertical bar jsr putchar ; Write, no cursor advance pla sta COLCRS inc ROWCRS dec tmp1 bne L1 L9: jmp setcursor ���������������������������������������������������������������cc65-2.18/libsrc/atari/dio_cts.s��������������������������������������������������������������������0000664�0000000�0000000�00000003100�13473601511�0016365�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, October 2000 ; ; this file provides the _dio_phys_to_log function ; (previously called _dio_chs_to_snum, so the filename) ; ; on the Atari this function is a dummy, it ignores ; cylinder and head and returns as sector number the ; sector number it got ; ; unsigned char __fastcall__ dio_phys_to_log(dhandle_t handle, ; dio_phys_pos *physpos, /* input */ ; unsigned *sectnum); /* output */ ; ; dhandle_t - 16bit (ptr) ; .export _dio_phys_to_log .import popax,__oserror .importzp ptr1,ptr2,ptr3 .include "atari.inc" .proc _dio_phys_to_log sta ptr1 stx ptr1+1 ; pointer to result jsr popax sta ptr2 stx ptr2+1 ; pointer to input structure jsr popax sta ptr3 stx ptr3+1 ; pointer to handle ldy #sst_flag lda (ptr3),y and #128 beq _inv_hand ; handle not open or invalid ; ignore head and track and return the sector value ldy #diopp_sector lda (ptr2),y tax iny lda (ptr2),y ldy #1 sta (ptr1),y dey txa sta (ptr1),y ldx #0 txa ret: sta __oserror rts ; return success ; invalid handle _inv_hand: ldx #0 lda #BADIOC bne ret .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/dio_stc.s��������������������������������������������������������������������0000664�0000000�0000000�00000003211�13473601511�0016370�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, October 2000 ; ; this file provides the _dio_log_to_phys function ; (previously called _dio_snum_to_chs, so the filename) ; ; on the Atari this function is a dummy, it returns ; cylinder and head 0 and as sector the sectnum it got ; ; unsigned char __fastcall__ dio_log_to_phys(dhandle_t handle, ; unsigned *sectnum, /* input */ ; dio_phys_pos *physpos); /* output */ ; ; dhandle_t - 16bit (ptr) ; .export _dio_log_to_phys .include "atari.inc" .importzp ptr1,ptr2,ptr3 .import popax,popptr1,__oserror .proc _dio_log_to_phys sta ptr2 stx ptr2+1 ; pointer to output structure jsr popptr1 ; save pointer to input data jsr popax sta ptr3 stx ptr3+1 ; pointer to handle ldy #sst_flag lda (ptr3),y and #128 beq _inv_hand ; handle not open or invalid lda #0 tay tax sta (ptr2),y ; head iny sta (ptr2),y ; track (low) iny sta (ptr2),y ; track (high) iny lda (ptr1,x) sta (ptr2),y iny inc ptr1 bne _l1 inc ptr1+1 _l1: lda (ptr1,x) sta (ptr2),y txa ret: sta __oserror rts ; return success ; invalid handle _inv_hand: ldx #0 lda #BADIOC bne ret .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/diopncls.s�������������������������������������������������������������������0000664�0000000�0000000�00000010455�13473601511�0016567�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, February 2005 ; ; This file provides the _dio_open and _dio_close functions ; Since on the Atari no real open and close is necessary, they ; do not open or close something. The _dio_open sets the sector ; size of the drive which is later used by the _dio_read and ; _dio_write functions. To query the sector size, the _dio_open ; accesses the disk drive. ; ; dhandle_t __fastcall__ dio_open (unsigned char device); ; unsigned char __fastcall__ dio_close (dhandle_t handle); ; .export _dio_open, _dio_close .export sectsizetab .import __oserror, __sio_call, _dio_read .import pushax, addysp, subysp .importzp ptr2, sp .include "atari.inc" .bss sectsizetab: .res NUMDRVS * sst_size .code ; code for _dio_open _inv_drive: lda #NONDEV ; non-existent device sta __oserror lda #0 tax rts ; return NULL _dio_open: cmp #NUMDRVS ; valid drive id? bcs _inv_drive tay ; drive # asl a ; make index from drive id asl a tax lda #128 ; preset sectsize sta sectsizetab+sst_sectsize,x sta sectsizetab+sst_flag,x ; set flag that drive is "open" lda #0 sta sectsizetab+sst_sectsize+1,x sta __oserror ; success tya sta sectsizetab+sst_driveno,x stx ptr2 lda #<sectsizetab clc adc ptr2 sta ptr2 lda #>sectsizetab adc #0 tax stx ptr2+1 ; ptr2: pointer to sectsizetab entry ; query drive for current sector size ; procedure: ; - read sector #4 (SIO command $54) to update drive status; ; read length is 128 bytes, buffer is allocated on the stack, ; sector data is ignored; ; returned command status is ignored, we will get an error with ; a DD disk anyway (read size 128 vs. sector size 256); ; - issue SIO command $53 (get status) to retrieve the sector size; ; use the DVSTAT system area as return buffer; ; if the command returns with an error, set sector size to 128 ; bytes; ; ldy #128 jsr subysp ; allocate buffer on the stack lda sp pha lda sp+1 pha ; save sp (buffer address) on processor stack lda ptr2 ldx ptr2+1 jsr pushax ; handle ldx #0 lda #4 jsr pushax ; sect_num pla tax pla ; AX - buffer address ; sst_sectsize currently 128 jsr _dio_read ; read sector to update status ldy #128 jsr addysp ; discard stack buffer lda ptr2 ldx ptr2+1 jsr pushax ; handle ldx #0 lda #4 jsr pushax ; dummy sector #, ignored by this SIO command, ; but set to circumvent the special 1-3 sector ; handling in __sio_call ldx #>DVSTAT lda #<DVSTAT jsr pushax ; buffer address ldy #sst_sectsize lda #4 sta (ptr2),y ; 4 bytes transfer ldx #%01000000 ; direction value lda #SIO_STAT ; get status jsr __sio_call bmi error ldy #sst_sectsize lda DVSTAT and #%100000 beq s128 ;s256 lda #0 sta (ptr2),y iny lda #1 finish: sta (ptr2),y ; set default sector size fini2: lda ptr2 ldx ptr2+1 rts error: ldy #sst_sectsize s128: lda #128 bne finish ; end of _dio_open .proc _dio_close sta ptr2 stx ptr2+1 lda #0 ldy #sst_flag sta (ptr2),y sta __oserror ; success tax rts ; return no error .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/dioqsize.s�������������������������������������������������������������������0000664�0000000�0000000�00000001023�13473601511�0016572�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, February 2005 ; ; unsigned __fastcall__ dio_query_sectsize(dhandle_t handle); ; .include "atari.inc" .export _dio_query_sectsize .importzp ptr1,tmp1 .import popax, __oserror .proc _dio_query_sectsize sta ptr1 ; handle stx ptr1+1 lda #0 sta __oserror ldy #sst_sectsize+1 lda (ptr1),y tax dey lda (ptr1),y rts .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/dioread.s��������������������������������������������������������������������0000664�0000000�0000000�00000001075�13473601511�0016361�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, October 2000 ; ; this file provides the _dio_read function ; ; unsigned char __fastcall__ dio_read(dhandle_t handle,unsigned sect_num,void *buffer); ; dhandle_t - 16bit (ptr) ; .import __sio_call,pushax .export _dio_read .include "atari.inc" .proc _dio_read jsr pushax ; push buffer address ldx #%01000000 ; direction value lda #SIO_READ ; read sector command jmp __sio_call ; do the call and return to the user .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/diowrite.s�������������������������������������������������������������������0000664�0000000�0000000�00000001127�13473601511�0016576�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, October 2000 ; ; this file provides the _dio_write function ; ; unsigned char __fastcall__ dio_write(dhandle_t handle,unsigned sect_num,const void *buffer); ; dhandle_t - 16bit (ptr) ; .import __sio_call,pushax .export _dio_write .include "atari.inc" .proc _dio_write jsr pushax ; push buffer address ldx #%10000000 ; indicate i/o direction (write) lda #SIO_WRITE ; write sector command jmp __sio_call ; do the call and return to the user .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/diowritev.s������������������������������������������������������������������0000664�0000000�0000000�00000001163�13473601511�0016764�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, October 2000 ; ; this file provides the _dio_write_verify function ; ; unsigned char __fastcall__ dio_write_verify(dhandle_t handle,unsigned sect_num,const void *buffer); ; dhandle_t - 16bit (ptr) ; .import __sio_call,pushax .export _dio_write_verify .include "atari.inc" .proc _dio_write_verify jsr pushax ; push buffer address ldx #%10000000 ; indicate i/o direction (write) lda #SIO_WRITEV ; write sector command jmp __sio_call ; do the call and return to the user .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/do_oserr.s�������������������������������������������������������������������0000664�0000000�0000000�00000000434�13473601511�0016564�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; __do_oserror updates __oserror and errno. Do a JMP here right after ; calling CIOV. It will return with AX set to -1 ($FFFF). It expects the CIO ; status in Y. ; .include "errno.inc" .export __do_oserror __do_oserror: tya jmp __mappederrno ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/doesclrscr.s�����������������������������������������������������������������0000664�0000000�0000000�00000001147�13473601511�0017115�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, June-2016 ; ; unsigned char doesclrscr(void); ; ; returns 0/1 if after program termination the screen isn't/is cleared ; .export _doesclrscrafterexit .import __is_cmdline_dos .import return1 .ifdef __ATARIXL__ _doesclrscrafterexit = return1 ; the c65 runtime always clears the screen at program termination .else _doesclrscrafterexit: jsr __is_cmdline_dos ; currently (unless a DOS behaving differently is popping up) eor #$01 ; we can get by with the inverse of __is_cmdline_dos rts .endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/dosdetect.s������������������������������������������������������������������0000664�0000000�0000000�00000003174�13473601511�0016732�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Freddy Offenga, Stefan Haubenthal, Christian Groessler, March 2007 ; ; detect the DOS version we're running on ; .include "atari.inc" .constructor detect, 26 .export __dos_type ; ------------------------------------------------------------------------ ; DOS type detection .segment "ONCE" detect: lda DOS cmp #'S' ; SpartaDOS beq spdos cmp #'M' ; MyDOS beq mydos cmp #'X' ; XDOS beq xdos cmp #'R' ; RealDOS beq rdos lda #$4C ; probably default ldy #COMTAB cmp (DOSVEC),y bne done ldy #ZCRNAME cmp (DOSVEC),y bne done ldy #6 ; OS/A+ has a jmp here cmp (DOSVEC),y beq done lda #OSADOS bne set spdos: lda DOS+3 ; 'B' in BW-DOS cmp #'B' bne spdos_real lda DOS+4 ; 'W' in BW-DOS cmp #'W' bne spdos_real lda #BWDOS .byte $2C ; BIT <abs> spdos_real: lda #SPARTADOS .byte $2C ; BIT <abs> mydos: lda #MYDOS .byte $2C ; BIT <abs> rdos: lda #REALDOS .byte $2C ; BIT <abs> xdos: lda #XDOS set: sta __dos_type done: rts ; ------------------------------------------------------------------------ ; Data .data __dos_type: .byte ATARIDOS; default to ATARIDOS ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/emd/�������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015330�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/emd/atr130.s�����������������������������������������������������������������0000664�0000000�0000000�00000034727�13473601511�0016543�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Extended memory driver for the Atari 130XE memory standard ; Shawn Jefferson, 2012-08-11 ; ; Banking Register $D301: ; Bit 7: Self-Test on/off ; Bit 6: Unused ; Bit 5: Antic sees bank ; Bit 4: CPU sees bank ; Bit 3: bank control ; Bit 2: bank control ; Bit 1: BASIC on/off ; Bit 0: OS RAM on/off ; ; Masks: %11100011 $E3 Bank 0 ; %11100111 $E7 Bank 1 ; %11101011 $EB Bank 2 ; %11101111 $EF Bank 3 ; %11111111 $FF Off ; ; Based on the Extended memory driver for the Apple II auxiliary memory ; by ; Stefan Haubenthal, 2003-12-12 ; Ullrich von Bassewitz, 2002-12-02 ; .include "zeropage.inc" .include "em-kernel.inc" .include "em-error.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table .ifdef __ATARIXL__ module_header _atrx130_emd .else module_header _atr130_emd .endif ; Driver signature .byte $65, $6d, $64 ; "emd" .byte EMD_API_VERSION ; EM API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr PAGECOUNT .addr MAP .addr USE .addr COMMIT .addr COPYFROM .addr COPYTO ; ------------------------------------------------------------------------ ; Constants BANK = $4000 ; bank window STACK = $0100 ; stack location PAGES = 256 ; 4 x 16k banks ; ------------------------------------------------------------------------ ; Data. .rodata banks: .byte $E3,$E7,$EB,$EF ; 130XE banks for cpu banking stacktest: sei ldy banks sty $D301 tax ; A is set by caller inx stx $4000 ; change $4000 ldy #$FF ; STACK+13 sty $D301 cmp $4000 ; changed? beq @1 sec ; error bcs @2 @1: clc @2: sta $4000 ; restore cli rts stacktest_end: stackcopy: sei ; disable interrupts @1: dex ; pre-decrement (full page x=0) ldy #$FF ; this will be replaced STACK+3 sty $D301 ; set bank lda $FF00,x ; address to copy from STACK+8,+9 ldy #$FF ; this will be replaced STACK+11 sty $D301 sta $FF00,x ; address to copy to STACK+16,+17 cpx #0 bne @1 ldy #$FF ; portb_save STACK+23 sty $D301 cli ; enable interrupts rts stackcopy_end: stackcopy_byte: sei ldy #$FF ; STACK+2 sty $D301 lda $FFFF ; STACK+7 +8 ldy #$FF ; STACK+10 sty $D301 sta $FFFF ; STACK+15 +16 ldy #$FF ; STACK+18 sty $D301 cli rts stackcopy_byte_end: .data curpage: .byte $FF ; Current page number in bank (invalid) curbank: .byte $FF ; Current bank number .bss window: .res 256 ; Memory "window" portb_save: .res 1 ; portb state .code install_transfer: ldx #stackcopy_end - stackcopy - 1 @1: lda stackcopy,x sta STACK,x dex bpl @1 rts install_byte_transfer: ldx #stackcopy_byte_end - stackcopy_byte - 1 @2: lda stackcopy_byte,x sta STACK,x dex bpl @2 rts install_test: ldx #stacktest_end - stacktest - 1 @3: lda stacktest,x sta STACK,x dex bpl @3 rts setpage: tax ; save page and #$C0 ; mask out bank clc ror ror ; divide by 64 ror ; 64 pages in each bank ror ror ror sta curbank ; Remember the new bank txa ; bring back page and #$3F ; mask out page sta curpage ; curpage in bank rts ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present and determine the amount of ; memory available. ; Must return an EM_ERR_xx code in a/x. ; INSTALL: lda $D301 ; save state of portb sta portb_save tay jsr install_test ; doesn't touch Y sty STACK+13 lda $4000 ; test for extended memory jsr STACK bcs @1 lda #EM_ERR_OK rts @1: lda #EM_ERR_NO_DEVICE rts ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; PAGECOUNT: Return the total number of available pages in a/x. ; PAGECOUNT: lda #<PAGES ldx #>PAGES rts ; ------------------------------------------------------------------------ ; MAP: Map the page in a/x into memory and return a pointer to the page in ; a/x. The contents of the currently mapped page (if any) may be discarded ; by the driver. ; MAP: jsr setpage ; extract the bank/page add #>BANK ; $4000 + page (carry is cleared) sta ptr1+1 ;ldy #$00 ;sty ptr1 lda #<window sta ptr2 lda #>window sta ptr2+1 ; Transfer one page jsr install_transfer ; Transfer one page ldx curbank lda banks,x sta STACK+3 ; set bank to copy from ; lda ptr1 ; sta STACK+8 lda ptr1+1 sta STACK+9 ; set copy from address lda portb_save sta STACK+11 ; set portb restore sta STACK+23 ; set final portb restore lda ptr2 sta STACK+16 lda ptr2+1 sta STACK+17 ; set copy to address ldx #0 ; full page copy jsr STACK ; do the copy! ; Return the memory window lda #<window ldx #>window ; Return the window address rts ; ------------------------------------------------------------------------ ; USE: Tell the driver that the window is now associated with a given page. USE: ;sta curpage ; Remember the page jsr setpage ; extract bank/page lda #<window ldx #>window ; Return the window rts ; ------------------------------------------------------------------------ ; COMMIT: Commit changes in the memory window to extended storage. COMMIT: lda curpage ; Get the current page cmp #$FF beq commit_done ; Jump if no page mapped clc add #>BANK sta ptr2+1 ;ldy #$00 ;sty ptr2 lda #<window sta ptr1 lda #>window sta ptr1+1 ; Transfer one page/all bytes jsr install_transfer ; Transfer one page lda portb_save sta STACK+3 ; set bank to copy from sta STACK+23 ; set final portb restore lda ptr1 sta STACK+8 lda ptr1+1 sta STACK+9 ; set copy from address ldx curbank lda banks,x sta STACK+11 ; set bank to copy to ;lda ptr2 ;sta STACK+16 lda ptr2+1 sta STACK+17 ; set copy to address ldx #0 ; full page copy jsr STACK ; do the copy! commit_done: rts ; ------------------------------------------------------------------------ ; COPYFROM: Copy from extended into linear memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYFROM: sta ptr3 stx ptr3+1 ; Save the passed em_copy pointer jsr install_byte_transfer ; install the stack copy routine ldy #EM_COPY::OFFS lda (ptr3),y sta STACK+7 ; offset goes into BANK low ldy #EM_COPY::PAGE lda (ptr3),y sta tmp1 ; save page for later ;add #>BANK ;sta STACK+8 ; BANK + page goes into BANK high ldy #EM_COPY::BUF lda (ptr3),y sta STACK+15 ; buffer goes into dest low iny lda (ptr3),y sta STACK+16 ; buffer goes into dest high ldy #EM_COPY::COUNT lda (ptr3),y ; Get bytes in last page sta ptr4 iny lda (ptr3),y ; Get number of pages sta ptr4+1 lda tmp1 ; extract bank/page jsr setpage ; sets curbank/curpage lda curpage add #>BANK ; add to BANK address sta STACK+8 ; current page in bank ldx curbank lda banks,x sta STACK+2 ; set bank in stack lda portb_save sta STACK+10 ; set bank restore in stack sta STACK+18 ; set final restore too copyfrom_copy: lda ptr4 ; check if count is zero bne @4 lda ptr4+1 beq done @4: jsr STACK ; copy one byte sec lda ptr4 sub #1 sta ptr4 bcs @1 lda ptr4+1 beq @1 sub #1 sta ptr4+1 @1: inc STACK+7 ; increment address in BANK bne @2 inc STACK+8 lda STACK+8 cmp #$80 ; we stepped outside bank bne @2 inc curbank ; get next bank ldx curbank lda banks,x sta STACK+2 ; set new bank lda #$40 ; set address back to $4000 sta STACK+8 @2: inc STACK+15 ; increment buffer address bne @3 inc STACK+16 @3: jmp copyfrom_copy ; copy another byte done: rts ; ------------------------------------------------------------------------ ; COPYTO: Copy from linear into extended memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYTO: sta ptr3 stx ptr3+1 ; Save the passed em_copy pointer jsr install_byte_transfer ; install the stack copy routine ldy #EM_COPY::OFFS lda (ptr3),y sta STACK+15 ; offset goes into BANK low ldy #EM_COPY::PAGE lda (ptr3),y sta tmp1 ; save page for later ;add #>BANK ;sta STACK+16 ; BANK + page goes into BANK high ldy #EM_COPY::BUF lda (ptr3),y sta STACK+7 ; buffer goes into dest low iny lda (ptr3),y sta STACK+8 ; buffer goes into dest high ldy #EM_COPY::COUNT lda (ptr3),y ; Get bytes in last page sta ptr4 iny lda (ptr3),y ; Get number of pages sta ptr4+1 lda tmp1 ; extract bank/page jsr setpage ; sets curbank/curpage lda curpage add #>BANK ; add to BANK address sta STACK+16 ; current page in bank ldx curbank lda banks,x sta STACK+10 ; set bank in stack lda portb_save sta STACK+2 ; set bank restore in stack sta STACK+18 ; set final restore too copyto_copy: lda ptr4 ; check if count is zero bne @4 lda ptr4+1 beq done @4: jsr STACK ; copy one byte sec lda ptr4 sub #1 sta ptr4 bcs @1 lda ptr4+1 beq @1 sub #1 sta ptr4+1 @1: inc STACK+15 ; increment address in BANK bne @2 inc STACK+16 lda STACK+16 cmp #$80 ; we stepped outside bank bne @2 inc curbank ; get next bank ldx curbank lda banks,x sta STACK+10 ; set new bank lda #$40 ; set address back to $4000 sta STACK+16 @2: inc STACK+7 ; increment buffer address bne @3 inc STACK+8 @3: jmp copyto_copy ; copy another byte �����������������������������������������cc65-2.18/libsrc/atari/exec.s�����������������������������������������������������������������������0000664�0000000�0000000�00000014057�13473601511�0015702�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, 12-Jun-2016 ; ; int __fastcall__ exec (const char* progname, const char* cmdline); ; ; supports only XDOS at the moment .export _exec .import popax .import __dos_type .import findfreeiocb .import incsp2 .import excexit ; from crt0.s .import SP_save ; from crt0.s .ifdef UCASE_FILENAME .import ucase_fn .import addysp .endif .include "zeropage.inc" .include "errno.inc" .include "atari.inc" ; area $0100 to $0128 might be in use (e.g. Hias' high speed patch) CMDLINE_BUFFER = $0129 ; put progname + cmdline as one single string there ; alternatively: ;CMDLINE_BUFFER = $0480 ; put progname + cmdline as one single string there CMDLINE_MAX = 40+3 ; max. length of drive + progname + cmdline .code notsupp:lda #ENOSYS ; "unsupported system call" .byte $2C ; bit opcode, eats the next 2 bytes noiocb: lda #EMFILE ; "too many open files" jsr incsp2 ; clean up stack seterr: jmp __directerrno ; entry point _exec: ; save cmdline sta ptr3 stx ptr3+1 ldy __dos_type cpy #XDOS bne notsupp jsr findfreeiocb bne noiocb stx tmp4 ; remember IOCB index ; get program name jsr popax .ifdef UCASE_FILENAME .ifdef DEFAULT_DEVICE ldy #$80 .else ldy #$00 .endif sty tmp2 ; set flag for ucase_fn jsr ucase_fn bcc ucok1 invret: lda #EINVAL ; file name is too long bne seterr ucok1: .endif ; defined UCASE_FILENAME ; copy program name and arguments to CMDLINE_BUFFER sta ptr4 ; ptr4: pointer to program name stx ptr4+1 ldy #0 ; TODO: check stack ptr and and use min(CMDLINE_MAX,available_stack) copyp: lda (ptr4),y beq copypd sta CMDLINE_BUFFER,y iny cpy #CMDLINE_MAX bne copyp ; programe name too long beq invret .ifndef UCASE_FILENAME invret: lda #EINVAL bne seterr .endif ; file name copied, check for args copypd: tya ; put Y into X (index into CMDLINE_BUFFER) tax lda ptr3 ora ptr3+1 ; do we have arguments? beq copycd ; no ldy #0 lda (ptr3),y ; get first byte of cmdline parameter beq copycd ; nothing there... lda #' ' ; add a space btw. progname and cmdline bne copyc1 ; copy args copyc: lda (ptr3),y beq copycd iny copyc1: sta CMDLINE_BUFFER,x inx cpx #CMDLINE_MAX bne copyc ; progname + arguments too long beq invret invexe: jsr close lda #XNTBIN bne setmerr copycd: lda #ATEOL sta CMDLINE_BUFFER,x ; open the program file, read the first two bytes and compare them to $FF ldx tmp4 ; get IOCB index lda ptr4 ; ptr4 points to progname sta ICBAL,x lda ptr4+1 sta ICBAH,x lda #OPNIN ; open for input sta ICAX1,x lda #OPEN sta ICCOM,x jsr CIOV tya .ifdef UCASE_FILENAME ldy tmp3 ; get size jsr addysp ; free used space on the stack ; the following 'bpl' depends on 'addysp' restoring A as last command before 'rts' .endif ; defined UCASE_FILENAME bpl openok pha ; remember error code jsr close ; close the IOCB (required even if open failed) pla ; put error code back into A setmerr:jmp __mappederrno ; update errno from OS specific error code in A openok: lda #>buf sta ICBAH,x ; set buffer address lda #<buf sta ICBAL,x lda #0 ; set buffer length sta ICBLH,x lda #2 sta ICBLL,x lda #GETCHR ; iocb command code sta ICCOM,x jsr CIOV ; read it bmi invexe ; read operation failed, return error lda ICBLL,x ; # of bytes read cmp #2 bne invexe lda #$FF ; check file format (need $FFFF at the beginning) cmp buf bne invexe cmp buf+1 bne invexe jsr close ; close program file ; program file appears to be available and good ; here's the point of no return ldx SP_save txs ; reset stack pointer to what it was at program entry lda tmp4 ; get IOCB index pha ; and save it ('excexit' calls destructors and they might destroy tmp4) jsr excexit ; on atarixl this will enable the ROM again, making all high variables inaccessible pla tax ; IOCB index in X lda #<CMDLINE_BUFFER sta ICBAL,x ; address lda #>CMDLINE_BUFFER sta ICBAH,x lda #0 sta ICBLL,x ; length shouldn't be random, but 0 is ok sta ICBLH,x sta ICAX1,x sta ICAX2,x lda #80 ; XDOS: run DUP command sta ICCOM,x jmp CIOV_org ; no way to display an error message in case of failure, and we will return to DOS ; close IOCB, index in X .proc close lda #CLOSE sta ICCOM,x jmp CIOV ; close IOCB .endproc .bss buf: .res 2 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/exehdr.s���������������������������������������������������������������������0000664�0000000�0000000�00000000506�13473601511�0016227�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; This file defines the EXE header and main chunk load header for Atari executables .export __EXEHDR__: absolute = 1 .import __MAIN_START__, __BSS_LOAD__ .segment "EXEHDR" .word $FFFF .segment "MAINHDR" .word __MAIN_START__ .word __BSS_LOAD__ - 1 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/exetrailer.s�����������������������������������������������������������������0000664�0000000�0000000�00000000501�13473601511�0017107�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; This file defines the EXE file "trailer" which sets the entry point .export __AUTOSTART__: absolute = 1 .import start .include "atari.inc" .segment "AUTOSTRT" .word RUNAD ; defined in atari.inc .word RUNAD+1 .word start �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/fd.inc�����������������������������������������������������������������������0000664�0000000�0000000�00000001564�13473601511�0015655�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, Oct-2000 ; ; offsets and defines for fdtable (internal use only) ; MAX_FD_INDEX = 12 ; max. # of open fds MAX_FD_VAL = 8 ; we have 8 IOCBs ft_entrylen = 4 ; length of table entry (it's not sufficient to change here! ; the code sometimes does two bit shifts to multiply/divide by ; this length) ft_usa = 0 ; usage counter ft_iocb = 1 ; iocb index (0,$10,$20,etc.), $ff for empty entry ft_dev = 2 ; device of open iocb (0 - device not remembered, eg. filename specified) ft_flag = 3 ; flags ; lower 3 bits: device number (for R: and D:) ; bit 3 - seeking supported by DOS/disk combination ; bit 4 - indicates a fd opened by the program as apposed to the ; inherited ones from program start (fd 0 to fd 2) ��������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/fdtab.s����������������������������������������������������������������������0000664�0000000�0000000�00000001465�13473601511�0016035�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, Oct-2000 ; Daniel Serpell, Dec-2009 ; ; the fdtable itself is defined here ; .include "fd.inc" .export fd_table,fd_index .export ___fd_table,___fd_index ; for test(debug purposes only .data ___fd_index: fd_index: ; fd number is index into this table, entry's value specifies the fd_table entry .byte 0,0,0 ; at start, three first files are stdin/stdout/stderr. .res MAX_FD_INDEX-3,$ff ___fd_table: fd_table: ; each entry represents an open iocb .byte 3,0,'E',0 ; system console, app starts with opened iocb #0 for E: .byte 0,$ff,0,0 .byte 0,$ff,0,0 .byte 0,$ff,0,0 .byte 0,$ff,0,0 .byte 0,$ff,0,0 .byte 0,$ff,0,0 .byte 0,$ff,0,0 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/fdtable.s��������������������������������������������������������������������0000664�0000000�0000000�00000021404�13473601511�0016351�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, May-2000 ; ; fd indirection table & helper functions ; .include "atari.inc" .include "fd.inc" .importzp tmp1,tmp2,tmp3,ptr4,sp .import fd_table,fd_index .import fdt_to_fdi .export clriocb .export fdtoiocb_down .export fddecusage .export newfd .code ; gets fd in ax, decrements usage counter ; return iocb index in X ; return N bit set for invalid fd ; return Z bit set if last user ; all registers destroyed .proc fdtoiocb_down cpx #0 bne inval cmp #MAX_FD_INDEX bcs inval tax lda fd_index,x ; get index tay lda #$ff sta fd_index,x ; clear entry tya asl a ; create index into fd table asl a tax lda #$ff cmp fd_table+ft_iocb,x ; entry in use? beq inval ; no, return error lda fd_table+ft_usa,x ; get usage counter beq ok_notlast ; 0? (shouldn't happen) sec sbc #1 ; decr usage counter sta fd_table+ft_usa,x retiocb:php txa tay lda fd_table+ft_iocb,x ; get iocb tax plp bne cont lda #$ff sta fd_table+ft_iocb,y ; clear table entry lda fd_table+ft_flag,y and #16 ; opened by app? eor #16 ; return set Z if yes cont: rts ok_notlast: lda #1 ; clears Z jmp retiocb .endproc ; fdtoiocb_down inval: ldx #$ff ; sets N rts ; clear iocb except for ICHID field ; expects X to be index to IOCB (0,$10,$20,etc.) ; all registers destroyed .proc clriocb inx ; don't clear ICHID ldy #15 lda #0 loop: sta ICHID,x inx dey bne loop rts .endproc ; decrements usage counter for fd ; if 0 reached, it's marked as unused ; get fd index in tmp2 ; Y register preserved .proc fddecusage lda tmp2 ; get fd cmp #MAX_FD_INDEX bcs ret ; invalid index, do nothing tax lda fd_index,x pha lda #$ff sta fd_index,x pla asl a ; create index into fd table asl a tax lda #$ff cmp fd_table+ft_iocb,x ; entry in use? beq ret ; no, do nothing lda fd_table+ft_usa,x ; get usage counter beq ret ; 0? should not happen sec sbc #1 ; decrement by one sta fd_table+ft_usa,x bne ret ; not 0 lda #$ff ; 0, table entry unused now sta fd_table+ft_iocb,x ; clear table entry ret: rts .endproc ; fddecusage ; newfd ; ; called from open() function ; finds a fd to use for an open request ; checks whether it's a device or file (file: characters follow the ':') ; files always get an exclusive slot ; for devices it is checked whether the device is already open, and if yes, ; a link to this open device is returned ; ; Calling parameters: ; tmp3 - length of filename + 1 ; AX - points to filename ; Y - iocb to use (if we need a new open) ; Return parameters: ; tmp2 - fd num ($ff and C=0 in case of error - no free slot) ; C - 0/1 for no open needed/open should be performed ; all registers preserved! .bss ; local variables: loc_Y: .res 1 loc_ptr4_l: .res 1 loc_ptr4_h: .res 1 loc_tmp1: .res 1 loc_devnum: .res 1 loc_size: .res 1 .code .proc newfd pha txa pha tya pha ldx #0 stx loc_devnum lda tmp1 sta loc_tmp1 stx tmp1 ; init tmp1 stx tmp2 ; init tmp2 lda ptr4+1 sta loc_ptr4_h lda ptr4 sta loc_ptr4_l pla sta loc_Y pla sta ptr4+1 pla sta ptr4 ; ptr4 points to filename ldy #1 lda #':' cmp (ptr4),y ; "X:" beq colon1 iny cmp (ptr4),y ; "Xn:" beq colon2 ; no colon there!? OK, then we use a fresh iocb.... ; return error here? no, the subsequent open call should fail do_open_nd: ; do open and don't remember device lda #2 sta tmp1 do_open:lda tmp1 ora #1 sta tmp1 ; set flag to return 'open needed' : C = 1 ldx #ft_iocb ldy #$ff srchfree: tya cmp fd_table,x ; check ft_iocb field for $ff beq freefnd ; found a free slot txa clc adc #ft_entrylen tax cmp #(MAX_FD_VAL*4)+ft_iocb ; end of table reached? bcc srchfree ; error: no free slot found noslot: ldx #0 stx tmp1 ; return with C = 0 dex stx tmp2 ; iocb: $ff marks error jmp finish ; found a free slot freefnd:txa sec sbc #ft_iocb ; normalize tax lsr a lsr a sta tmp2 ; return fd lda #2 bit tmp1 ; remember device? beq l1 ; yes lda #0 ; no, put 0 in field beq l2 l1: ldy #0 lda (sp),y ; get device l2: sta fd_table+ft_dev,x ; set device lda #1 sta fd_table+ft_usa,x ; set usage counter lda loc_Y sta fd_table+ft_iocb,x ; set iocb index lda loc_devnum and #7 ; device number is 3 bits ora #16 ; indicated a fd actively opened by the app sta fd_table+ft_flag,x lda tmp2 jsr fdt_to_fdi ; get new index noslot1:bcs noslot ; no one available (noslot1: helper label for branch out of range) ;cmp #$ff ; no one available ;beq noslot ;@@@ cleanup needed sta tmp2 ; return index jmp finish ; string in "Xn:xxx" format colon2: dey lda (ptr4),y ; get device number sec sbc #'0' and #7 sta loc_devnum sta tmp2 ; save it for speed later here also lda #4 ; max. length if only device + number ("Xn:") cmp tmp3 bcc do_open_nd ; string is longer -> contains filename bcs check_dev ; handle device only string ; string in "X:xxx" format colon1: lda #3 ; max. length if device only ("X:") cmp tmp3 bcc do_open_nd ; string is longer -> contains filename ; get device and search it in fd table check_dev: ldy #0 lda (ptr4),y ; get device id tay ldx #(MAX_FD_VAL*4) - ft_entrylen srchdev:lda #$ff cmp fd_table+ft_iocb,x ; is entry valid? beq srch2 ; no, skip this entry tya cmp fd_table+ft_dev,x beq fnddev srch2: txa sec sbc #ft_entrylen+1 tax bpl srchdev ; not found, open new iocb jmp do_open ; found device in table, check device number (e.g R0 - R3) fnddev: lda fd_table+ft_flag,x and #7 cmp tmp2 ; contains devnum bne srch2 ; different device numbers ; found existing open iocb with same device txa lsr a lsr a sta tmp2 inc fd_table+ft_usa,x ; increment usage counter jsr fdt_to_fdi ; get new index bcs noslot1 ; no one available sta tmp2 ; return index ; clean up and go home finish: lda ptr4 pha lda ptr4+1 pha lda loc_Y pha lda tmp1 pha lda loc_tmp1 sta tmp1 pla lsr a ; set C as needed pla tay pla tax pla rts .endproc ; newfd ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/fdtoiocb.s�������������������������������������������������������������������0000664�0000000�0000000�00000002042�13473601511�0016536�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, May-2000 ; Moved from fdtable.s to it's own file by Daniel Serpell, 2009. ; ; Convert file descriptor to IOCB number ; .include "atari.inc" .include "fd.inc" .import fd_table,fd_index .export fdtoiocb .code ; gets fd in ax ; return iocb index in A, fd_table index in X ; return N bit set for invalid fd ; all registers destroyed .proc fdtoiocb cpx #0 bne inval cmp #MAX_FD_INDEX bcs inval tax lda fd_index,x asl a ; create index into fd table asl a tax lda #$ff cmp fd_table+ft_iocb,x ; entry in use? beq inval ; no, return error lda fd_table+ft_usa,x ; get usage counter beq inval ; 0? should not happen lda fd_table+ft_iocb,x ; get iocb rts inval: ldx #$ff ; sets N rts .endproc ; fdtoiocb ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/findfreeiocb.inc�������������������������������������������������������������0000664�0000000�0000000�00000000702�13473601511�0017674�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; find a free iocb ; no entry parameters ; return ZF = 0/1 for not found/found ; index in X if found ; all registers destroyed .proc findfreeiocb ldx #0 ldy #$FF loop: tya cmp ICHID,x beq found txa clc adc #$10 tax cmp #$80 bcc loop inx ; return ZF cleared found: rts .endproc ; findfreeiocb ��������������������������������������������������������������cc65-2.18/libsrc/atari/findfreeiocb.s���������������������������������������������������������������0000664�0000000�0000000�00000000204�13473601511�0017362�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, June-2013 ; .include "atari.inc" .export findfreeiocb .include "findfreeiocb.inc" ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/get_tv.s���������������������������������������������������������������������0000664�0000000�0000000�00000001025�13473601511�0016235�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, July 2004 ; ; unsigned char get_tv(void) ; ; returns the TV system the machine is using ; 0 - NTSC ; 1 - PAL ; .include "atari.inc" .include "get_tv.inc" .proc _get_tv ldx #TV::NTSC ; Assume NTSC lda PAL ; use hw register, PALNTS is only supported on XL/XE ROM and #$0e bne @NTSC inx ; = TV::PAL @NTSC: txa ldx #0 ; Expand to int rts .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/getargs.s��������������������������������������������������������������������0000664�0000000�0000000�00000006373�13473601511�0016414�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; get arguments from command line (when DOS supports it) ; Freddy Offenga, 4/21/2000 ; initmainargs is forcibly included by the C compiler if it encounters a ; main() function with arguments. Therefore it isn't referenced by the ; startup code but is nevertheless included in the compiled program when ; needed. ; XDOS support added 05/2016 by Christian Groessler MAXARGS = 16 ; max. amount of arguments in arg. table CL_SIZE = 64 ; command line buffer size SPACE = 32 ; SPACE char. .include "atari.inc" .import __argc, __argv .importzp ptr1 .import __dos_type .constructor initmainargs, 25 ; -------------------------------------------------------------------------- ; Get command line .segment "ONCE" nargdos:rts initmainargs: lda __dos_type ; which DOS? cmp #MAX_DOS_WITH_CMDLINE + 1 bcs nargdos ; Initialize ourcl buffer argdos: ldy #ATEOL sty ourcl+CL_SIZE ; Move SpartaDOS/XDOS command line to our own buffer cmp #XDOS bne sparta lda #<XLINE sta ptr1 lda #>XLINE sta ptr1+1 bne cpcl0 sparta: lda DOSVEC clc adc #<LBUF sta ptr1 lda DOSVEC+1 adc #>LBUF sta ptr1+1 cpcl0: ldy #0 cpcl: lda (ptr1),y sta ourcl,y iny cmp #ATEOL beq movdon cpy #CL_SIZE bne cpcl movdon: lda #0 sta ourcl,y ; null terminate behind ATEOL ; Turn command line into argv table ;ldy #0 tay eatspc: lda ourcl,y ; eat spaces cmp #ATEOL beq finargs cmp #SPACE bne rpar ; begin of argument found iny cpy #CL_SIZE bne eatspc beq finargs ; only spaces is no argument ; Store argument vector rpar: lda __argc ; low-byte asl tax ; table index tya ; ourcl index clc adc #<ourcl sta argv,x lda #>ourcl adc #0 sta argv+1,x ldx __argc inx stx __argc cpx #MAXARGS beq finargs ; Skip this arg. skiparg: ldx ourcl,y cpx #ATEOL ; end of line? beq eopar cpx #SPACE beq eopar iny cpy #CL_SIZE bne skiparg ; End of arg. -> place 0 eopar: lda #0 sta ourcl,y iny ; y behind arg. cpx #ATEOL ; was it the last arg? bne eatspc ; Finish args finargs: lda __argc asl tax lda #0 sta argv,x sta argv+1,x lda #<argv ldx #>argv sta __argv stx __argv+1 rts ; -------------------------------------------------------------------------- ; Data .segment "INIT" argv: .res (1 + MAXARGS) * 2 ; Buffer for command line / argv strings ourcl: .res CL_SIZE+1 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/getdefdev.s������������������������������������������������������������������0000664�0000000�0000000�00000006451�13473601511�0016712�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Freddy Offenga & Christian Groessler, December 2004 ; ; function to get default device: char *_getdefdev(void); ; ; AtariDOS/MyDOS: ; Default device number is derived from DUNIT. Therefore "default ; device" is the one the program was loaded from. ; ; SpartaDOS/RealDOS: ; the ZCRNAME routine is only used to get the default drive because ; ZCRNAME has two disadvantages: ; 1. It will convert D: into D1: instead of Dn: (n = default drive) ; 2. It will give a 'no arguments' status if it detects something ; like Dn: (without filename). ; ; OS/A+ DOS: ; ZCRNAME is slightly different from SpartaDOS. It will convert D: ; into Dn: where n is the default drive. .include "atari.inc" .import __dos_type .export __getdefdev ; get default device .export __defdev ; this is the default device string (e.g. "D1:") .ifdef DYNAMIC_DD .constructor __getdefdev, 24 .endif ; Get default device (LBUF will be destroyed!!) __getdefdev: lda __dos_type ; which DOS? cmp #XDOS beq xdos ; XDOS detected ; cmp #OSADOS+1 ; (redundant: #OSADOS+1 = #XDOS) bcs use_DUNIT ; neither XDOS, nor OS/A+ or SpartaDOS ldy #BUFOFF lda #0 sta (DOSVEC),y ; reset buffer offset ; Store dummy argument ldy #LBUF lda #'X' sta (DOSVEC),y iny lda #ATEOL sta (DOSVEC),y ; One extra store to avoid the buggy sequence from OS/A+ DOS: ; <D><RETURN><:> => drive number = <RETURN> iny sta (DOSVEC),y ; Create crunch vector ldy #ZCRNAME+1 lda (DOSVEC),y sta crvec+1 iny lda (DOSVEC),y sta crvec+2 jsr crvec ; Get default device ldy #COMFNAM ; COMFNAM is always "Dn:" lda (DOSVEC),y sta __defdev iny lda (DOSVEC),y done: sta __defdev+1 ; Return pointer to default device finish: lda #<__defdev ldx #>__defdev rts ; On AtariDOS or MyDOS, use the DUNIT variable to setup the default ; device. The default device will then be the one the program was ; loaded from. use_DUNIT: lda DUNIT clc adc #'0' bne done ; jump always ; XDOS default device retrieval xdos: ; check XDOS version (we need >= 2.4) lda XGLIN cmp #$4C ; there needs to be a 'JMP' opcode here bne finish ; older version, use DEFAULT_DEVICE or D1: lda XVER ; get BCD encoded version ($24 for 2.4) cmp #$24 bcc finish ; too old, below 2.4 ; good XDOS version, get default drive lda #ATEOL sta XLINE ; simulate empty command line ldy #0 jsr XMOVE ; create an FMS filename (which in this case only contains the drive) lda XFILE+1 bne done .data crvec: jmp $FFFF ; target address will be set to crunch vector ; Default device string __defdev: .ifdef DEFAULT_DEVICE .byte 'D', '0'+DEFAULT_DEVICE, ':', 0 .else .byte "D1:", 0 .endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/getdevice.s������������������������������������������������������������������0000664�0000000�0000000�00000004050�13473601511�0016705�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2012-09-04 ; Christian Groessler, 2017-12-28 ; ; unsigned char getfirstdevice (void); ; unsigned char __fastcall__ getnextdevice (unsigned char device); ; .include "atari.inc" .export _getfirstdevice .export _getnextdevice MAX_DIO_DEVICES = 8 ;------------------------------------------------------------------------------ ; _getfirstdevice _getfirstdevice: lda #$FF ; Fall through ;------------------------------------------------------------------------------ ; _getnextdevice _getnextdevice: tax next: inx cpx #MAX_DIO_DEVICES beq none jsr check_device bmi next done: txa ldx #$00 rts none: ldx #255 ; INVALID_DEVICE (see include/device.h) bne done ; jump always ;------------------------------------------------------------------------------ ; check_device - checks if a disk device is present ; input: X - device id (0 = D1, 1 = D2, ...) ; output: NF - 0/1 for detected/not detected ; X register preserved check_device: txa pha lda #SIO_STAT sta DCOMND ; set command into DCB lda #%01000000 ; direction value, "receive data" sta DSTATS ; set data flow directon lda #15 sta DTIMLO ; value got from DOS source lda #4 sta DAUX1 ; set sector # (dummy: 4) sta DBYTLO ; # of bytes to transfer lda #0 sta DAUX2 sta DBYTHI lda #>DVSTAT sta DBUFHI lda #<DVSTAT sta DBUFLO ; set buffer address into DCB lda #DISKID ; SIO bus ID of diskette drive sta DDEVIC inx stx DUNIT ; unit number (1-based) jsr SIOV ; execute SIO command pla tax lda DSTATS rts .end ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/getfd.s����������������������������������������������������������������������0000664�0000000�0000000�00000002430�13473601511�0016037�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, Oct-2000 ; ; allocates a new fd in the indirection table ; .include "atari.inc" .include "fd.inc" .include "_file.inc" .importzp tmp1 .import fd_table, fd_index .export fdt_to_fdi,getfd .code ; fdt_to_fdi ; returns a fd_index entry pointing to the given ft_table entry ; get fd_table entry in A ; return C = 0/1 for OK/error ; return fd_index entry in A if OK ; registers destroyed .proc fdt_to_fdi tay lda #$ff tax inx loop: cmp fd_index,x beq found inx cpx #MAX_FD_INDEX bcc loop rts found: tya sta fd_index,x txa clc rts .endproc ; getfd ; get a new fd pointing to a ft_table entry ; usage counter of ft_table entry incremented ; A - fd_table entry ; return C = 0/1 for OK/error ; returns fd in A if OK ; registers destroyed, tmp1 destroyed .proc getfd sta tmp1 ; save fd_table entry jsr fdt_to_fdi bcs error pha lda tmp1 asl a asl a ; also clears C tax inc fd_table+ft_usa,x ; increment usage counter pla error: rts .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/getres.s���������������������������������������������������������������������0000664�0000000�0000000�00000002127�13473601511�0016242�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 15.8.2018 ; Christian Groessler, 27.9.2018 ; ; int __fastcall__ clock_getres (clockid_t clk_id, struct timespec *res); ; .include "atari.inc" .include "time.inc" .include "errno.inc" .importzp ptr1 .import incsp1, return0, __dos_type ;---------------------------------------------------------------------------- .code _clock_getres: sta ptr1 stx ptr1+1 ; Cleanup stack jsr incsp1 ; Check for SpartaDOS-X 4.40 or newer ldy #SPARTADOS cpy __dos_type bne enosys ldy SDX_VERSION cpy #$44 bcc enosys ldy #.sizeof(timespec)-1 @L1: lda time,y sta (ptr1),y dey bpl @L1 jmp return0 enosys: lda #ENOSYS ; Set __errno jmp __directerrno ;---------------------------------------------------------------------------- ; timespec struct with tv_sec set to 1 second .rodata time: .dword 1 .dword 0 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/gettime.s��������������������������������������������������������������������0000664�0000000�0000000�00000004410�13473601511�0016404�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 14.08.2018 ; Christian Groessler, 25.09.2018 ; ; int __fastcall__ clock_gettime (clockid_t clk_id, struct timespec *tp); ; .import pushax, steaxspidx, incsp1, incsp3, return0 .import __dos_type .import sdxtry .include "time.inc" .include "zeropage.inc" .include "errno.inc" .include "atari.inc" _clock_gettime: jsr pushax ; clear tp sta ptr1 stx ptr1+1 lda #$00 ldy #.sizeof(timespec)-1 : sta (ptr1),y dey bpl :- ; only supported on SpartaDOS-X >= 4.40 lda #SPARTADOS cmp __dos_type bne notsupp lda SDX_VERSION cmp #$44 bcc notsupp ; get date/time from system (SD-X call) ; see settime.s for reasons of using sdxtry lda #0 ; init loop count (256) sta sdxtry try_get:lda #SDX_CLK_DEV ; CLK device sta SDX_DEVICE ldy #SDX_KD_GETTD ; GETTD function jsr SDX_KERNEL ; do the call bcc done dec sdxtry bne try_get lda #EBUSY bne errexit ; fill timespec ; date done: lda SDX_DATE ; mday sta TM + tm::tm_mday ldx SDX_DATE+1 ; month dex stx TM + tm::tm_mon lda SDX_DATE+2 ; year cmp #79 ; 1979: the Atari 800 came out bcs :+ adc #100 ; adjust century : sta TM + tm::tm_year ; time lda SDX_TIME sta TM + tm::tm_hour lda SDX_TIME+1 sta TM + tm::tm_min lda SDX_TIME+2 sta TM + tm::tm_sec ; make time_t lda #<TM ldx #>TM jsr _mktime ; store tv_sec into output tp struct ldy #timespec::tv_sec jsr steaxspidx ; cleanup stack jsr incsp1 ; return success jmp return0 ; load errno code notsupp:lda #ENOSYS ; cleanup stack errexit:jsr incsp3 ; Preserves A ; set __errno jmp __directerrno ; ------- .bss TM: .tag tm ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/gotox.s����������������������������������������������������������������������0000664�0000000�0000000�00000000446�13473601511�0016113�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, 19-Feb-2000 ; ; void gotox (unsigned char x); ; .include "atari.inc" .export _gotox .import setcursor _gotox: sta COLCRS ; Set X lda #0 sta COLCRS+1 jmp setcursor ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/gotoxy.s���������������������������������������������������������������������0000664�0000000�0000000�00000001014�13473601511�0016274�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; void gotoxy (unsigned char x, unsigned char y); ; .include "atari.inc" .export gotoxy, _gotoxy .import popa .import setcursor gotoxy: jsr popa ; Get Y _gotoxy: ; Set the cursor position sta ROWCRS ; Set Y jsr popa ; Get X sta COLCRS ; Set X lda #0 sta COLCRS+1 jmp setcursor ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/gotoy.s����������������������������������������������������������������������0000664�0000000�0000000�00000000372�13473601511�0016112�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, 19-Feb-2000 ; ; void gotoy (unsigned char y); ; .include "atari.inc" .export _gotoy .import setcursor _gotoy: sta ROWCRS ; Set Y jmp setcursor ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/graphics.s�������������������������������������������������������������������0000664�0000000�0000000�00000005047�13473601511�0016555�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, June 2004 ; ; this file provides an equivalent to the BASIC GRAPHICS function ; ; int __fastcall__ _graphics(unsigned char mode); ; ; .export __graphics .import findfreeiocb .import __oserror .import fddecusage .import clriocb .import fdtoiocb .import newfd .import scrdev .importzp tmp1,tmp2,tmp3 .include "atari.inc" .include "errno.inc" .code ; set new grapics mode ; gets new mode in A ; returns handle or -1 on error ; uses tmp1, tmp2, tmp3, tmp4 (in subroutines) .proc __graphics ; tax ; and #15 ; get required graphics mode ; cmp #12 ; bcs invmode ; invalid mode ; txa ; and #$c0 ; invalid bits set? ; bne invmode ; stx tmp1 sta tmp1 ; remember graphics mode parmok: jsr findfreeiocb beq iocbok ; we found one lda #<EMFILE ; "too many open files" seterr: jsr __mappederrno ; @@@ probably not correct to set errno here @@@ rts ; return -1 ;invmode:ldx #>EINVAL ; lda #<EINVAL ; bne seterr iocbok: txa tay ; move iocb # into Y lda #3 sta tmp3 ; name length + 1 lda #<scrdev ldx #>scrdev jsr newfd tya tax bcs doopen ; C set: open needed ldx #0 lda tmp2 ; get fd used jsr fdtoiocb tax doopen: txa ;brk pha jsr clriocb pla tax lda #<scrdev sta ICBAL,x lda #>scrdev sta ICBAH,x lda #OPEN sta ICCOM,x lda tmp1 ; get requested graphics mode and #15 sta ICAX2,x lda tmp1 and #$30 eor #$10 ora #12 sta ICAX1,x jsr CIOV bmi cioerr lda tmp2 ; get fd ldx #0 stx __oserror rts cioerr: sty tmp3 ; remember error code lda #CLOSE sta ICCOM,x jsr CIOV ; close IOCB again since open failed jsr fddecusage ; and decrement usage counter of fd lda tmp3 ; put error code into A jmp __mappederrno .endproc ; __graphics �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/initcwd.s��������������������������������������������������������������������0000664�0000000�0000000�00000001222�13473601511�0016405�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Stefan Haubenthal, 2008-04-29 ; .export initcwd .import findfreeiocb .import __cwd .include "atari.inc" .proc initcwd lda #0 sta __cwd jsr findfreeiocb bne oserr lda #GETCWD sta ICCOM,x lda #<__cwd sta ICBLL,x lda #>__cwd sta ICBLH,x jsr CIOV bmi oserr ldx #$FF ; ATEOL -> \0 : inx lda __cwd,x cmp #ATEOL bne :- lda #0 sta __cwd,x oserr: rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/inviocb.s��������������������������������������������������������������������0000664�0000000�0000000�00000000246�13473601511�0016402�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; set EINVAL error code and returns -1 ; .include "errno.inc" .export __inviocb __inviocb: lda #<EINVAL jmp __directerrno ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/irq.s������������������������������������������������������������������������0000664�0000000�0000000�00000003421�13473601511�0015542�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; IRQ handling (ATARI version) ; .export initirq, doneirq .import callirq .include "atari.inc" .ifdef __ATARIXL__ .import __CHARGEN_START__ .include "romswitch.inc" .endif ; ------------------------------------------------------------------------ .segment "ONCE" initirq: lda #$4C ; JMP opcode sta IRQInd lda VVBLKD ldx VVBLKD+1 sta IRQInd+1 stx IRQInd+2 lda #7 ldy #<IRQStub ldx #>IRQStub jmp SETVBV ; ------------------------------------------------------------------------ .code doneirq: lda #7 ldy IRQInd+1 ldx IRQInd+2 jmp SETVBV ; ------------------------------------------------------------------------ .segment "LOWCODE" IRQStub: cld ; Just to be sure .ifdef __ATARIXL__ .ifdef CHARGEN_RELOC lda CHBAS pha .endif .endif lda PORTB pha .ifdef __ATARIXL__ and #$FE ; disable ROM .endif ora #$10 ; map main memory into $4000..$7FFF area sta PORTB .ifdef __ATARIXL__ set_chbase >__CHARGEN_START__ .endif jsr callirq ; Call the functions pla sta PORTB ; restore old memory settings .ifdef __ATARIXL__ .ifdef CHARGEN_RELOC pla sta CHBAS sta CHBASE .endif .endif jmp IRQInd ; Jump to the saved IRQ vector ; ------------------------------------------------------------------------ .segment "LOWBSS" IRQInd: .res 3 .end �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/is_cmdline_dos.s�������������������������������������������������������������0000664�0000000�0000000�00000000553�13473601511�0017725�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, May-2016 ; ; unsigned char _is_cmdline_dos(void); ; ; returns 0 for non-commandline DOS, 1 for commandline DOS ; .export __is_cmdline_dos .import __dos_type .include "atari.inc" __is_cmdline_dos: lda #MAX_DOS_WITH_CMDLINE cmp __dos_type lda #0 rol a rts �����������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/joy/�������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015364�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/joy/atrmj8.s�����������������������������������������������������������������0000664�0000000�0000000�00000005713�13473601511�0016763�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; MultiJoy joystick driver for the Atari. May be used multiple times when linked ; to the statically application. ; ; Ullrich von Bassewitz, 2002-12-21 ; Stefan Haubenthal, 2009-04-10 ; Using code from Carsten Strotmann and help from Christian Groessler ; .include "zeropage.inc" .include "joy-kernel.inc" .include "joy-error.inc" .include "atari.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table .ifdef __ATARIXL__ module_header _atrxmj8_joy .else module_header _atrmj8_joy .endif ; Driver signature .byte $6A, $6F, $79 ; "joy" .byte JOY_API_VERSION ; Driver API version number ; Library reference .addr $0000 ; Jump table. .addr INSTALL .addr UNINSTALL .addr COUNT .addr READJOY ; ------------------------------------------------------------------------ ; Constants JOY_COUNT = 8 ; Number of joysticks we support ; ------------------------------------------------------------------------ ; Data. .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 #$30 sta PACTL lda #$F0 sta PORTA lda #$34 sta PACTL lda #JOY_ERR_OK ldx #0 ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; COUNT: Return the total number of available joysticks in a/x. ; COUNT: lda #JOY_COUNT ldx #0 rts ; ------------------------------------------------------------------------ ; READ: Read a particular joystick passed in A. ; READJOY: and #JOY_COUNT-1 ; fix joystick number tax ; Joystick number into X asl a asl a asl a asl a sta PORTA ; Read joystick lda STRIG0 ; get button asl a asl a asl a asl a ora PORTA ; add position information eor #$1F cmp oldval,x beq :+ sta oldval,x ldx #0 stx ATRACT ; we have interaction, disable "attract mode" : ldx #0 ; fix X rts .bss oldval: .res JOY_COUNT �����������������������������������������������������cc65-2.18/libsrc/atari/joy/atrstd.s�����������������������������������������������������������������0000664�0000000�0000000�00000005516�13473601511�0017060�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Standard joystick driver for the Atari. May be used multiple times when linked ; to the statically application. ; ; Ullrich von Bassewitz, 2002-12-21 ; Using the readjoy code from Christian Groessler ; .include "zeropage.inc" .include "joy-kernel.inc" .include "joy-error.inc" .include "atari.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table .ifdef __ATARIXL__ module_header _atrxstd_joy .else module_header _atrstd_joy .endif ; Driver signature .byte $6A, $6F, $79 ; "joy" .byte JOY_API_VERSION ; Driver API version number ; Library reference .addr $0000 ; Jump table. .addr INSTALL .addr UNINSTALL .addr COUNT .addr READJOY ; ------------------------------------------------------------------------ ; Constants JOY_COUNT = 4 ; Number of joysticks we support ; ------------------------------------------------------------------------ ; Data. .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 #0 ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; COUNT: Return the total number of available joysticks in a/x. ; COUNT: lda #JOY_COUNT ldx $fcd8 cpx #$a2 beq _400800 lsr a ; XL and newer machines only have 2 ports _400800: ldx #0 rts ; ------------------------------------------------------------------------ ; READ: Read a particular joystick passed in A. ; READJOY: and #JOY_COUNT-1 ; fix joystick number tax ; Joystick number into X ; Read joystick lda STRIG0,x ; get button asl a asl a asl a asl a ora STICK0,x ; add position information eor #$1F cmp oldval,x beq :+ sta oldval,x ldx #0 stx ATRACT ; we have interaction, disable "attract mode" : ldx #0 ; fix X rts .bss oldval: .res JOY_COUNT ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/joy_stat_stddrv.s������������������������������������������������������������0000664�0000000�0000000�00000000626�13473601511�0020175�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Address of the static standard joystick driver ; ; Oliver Schmidt, 2012-11-01 ; ; const void joy_static_stddrv[]; ; .export _joy_static_stddrv .ifdef __ATARIXL__ .import _atrxstd_joy .else .import _atrstd_joy .endif .rodata .ifdef __ATARIXL__ _joy_static_stddrv := _atrxstd_joy .else _joy_static_stddrv := _atrstd_joy .endif ����������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/joy_stddrv.s�����������������������������������������������������������������0000664�0000000�0000000�00000000446�13473601511�0017142�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Name of the standard joystick driver ; ; Ullrich von Bassewitz, 2002-12-21 ; ; const char joy_stddrv[]; ; .export _joy_stddrv .rodata _joy_stddrv: .ifdef __ATARIXL__ .asciiz "atrxstd.joy" .else .asciiz "atrstd.joy" .endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/kbhit.s����������������������������������������������������������������������0000664�0000000�0000000�00000000624�13473601511�0016052�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, 19-Feb-2000 ; ; unsigned char kbhit (void); ; .export _kbhit .import return1 .include "atari.inc" .proc _kbhit ldx CH ; last pressed key inx ; 255 means "no key" bne L1 txa ; X = A = 0 rts L1: jmp return1 .endproc ������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/libref.s���������������������������������������������������������������������0000664�0000000�0000000�00000000441�13473601511�0016211�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2013-05-31 ; .export em_libref, joy_libref, tgi_libref .import _exit em_libref := _exit joy_libref := _exit .ifdef __ATARIXL__ .import CIO_handler tgi_libref := CIO_handler .else tgi_libref := _exit .endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/lseek.s����������������������������������������������������������������������0000664�0000000�0000000�00000012547�13473601511�0016063�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, May 2002 ; ; this file provides the lseek() function ; ; off_t __fastcall__ lseek(int fd, off_t offset, int whence); ; .export _lseek .import incsp6,__oserror .import __inviocb,ldax0sp,ldaxysp,fdtoiocb .import __dos_type .import fd_table .importzp sreg,ptr1,ptr2,ptr3,ptr4 .importzp tmp1,tmp2,tmp3 .include "atari.inc" .include "errno.inc" .include "fd.inc" ; seeking not supported, return -1 and ENOSYS errno value no_supp:jsr incsp6 lda #<ENOSYS jsr __directerrno ; returns with $FFFF in AX sta sreg sta sreg+1 rts parmerr: iocberr:jsr incsp6 ldx #255 stx sreg stx sreg+1 jmp __inviocb ; lseek() entry point .proc _lseek cpx #0 ; sanity check whence parameter bne parmerr cmp #3 ; valid values are 0..2 bcs parmerr sta tmp1 ; remember whence ldy #5 jsr ldaxysp ; get fd jsr fdtoiocb ; convert to iocb in A, fd_table index in X bmi iocberr sta tmp3 ; remember iocb jsr chk_supp ; check, whether seeking is supported by DOS/Disk bcc no_supp ldx tmp1 ; whence beq cur dex beq end ; SEEK_SET dex stx ptr3 stx ptr3+1 stx ptr4 stx ptr4+1 beq cont ; SEEK_CUR cur: ldx tmp3 lda #NOTE sta ICCOM,x jsr CIOV ; read it bmi xxerr l01: lda ICAX3,x ; low byte of position sta ptr3 lda ICAX4,x ; med byte of position sta ptr3+1 lda ICAX5,x ; high byte of position sta ptr4 lda #0 sta ptr4+1 beq cont ; SEEK_END end: ldx tmp3 lda #GETFL sta ICCOM,x jsr CIOV bpl l01 ; error returned from CIO xxerr: tya pha jsr incsp6 pla jsr __mappederrno ; returns with $FFFF in AX sta sreg sta sreg+1 rts ; check for offset 0, SEEK_CUR (get current position) cont: ldy #3 jsr ldaxysp ; get upper word sta ptr1 stx ptr1+1 jsr ldax0sp ; get lower word stx tmp2 ora tmp2 ora ptr1 ora ptr1+1 bne seek lda tmp1 ; whence (0 = SEEK_CUR) bne seek ; offset 0, SEEK_CUR: return current fp ret: jsr incsp6 lda ptr4+1 sta sreg+1 lda ptr4 sta sreg ldx ptr3+1 lda ptr3 .if 0 ; return exactly the position DOS has ldx tmp3 lda #NOTE sta ICCOM,x jsr CIOV ; read it bmi xxerr lda #0 sta sreg+1 lda ICAX5,x ; high byte of position sta sreg lda ICAX3,x ; low byte of position pha lda ICAX4,x ; med byte of position tax pla .endif rts parmerr1: jmp parmerr ; we have to call POINT seek: jsr ldax0sp ; get lower word of new offset clc adc ptr3 sta ptr3 txa adc ptr3+1 sta ptr3+1 lda ptr1 adc ptr4 sta ptr4 lda ptr1+1 adc ptr4+1 sta ptr4+1 bne parmerr1 ; resulting value too large ldx tmp3 ; IOCB lda ptr3 sta ICAX3,x lda ptr3+1 sta ICAX4,x lda ptr4 sta ICAX5,x lda #POINT sta ICCOM,x jsr CIOV bpl ret bmi xxerr .endproc ; check whether seeking is supported ; tmp3: iocb ; X: index into fd_table ; ; On non-SpartaDOS, seeking is not supported. ; We check, whether CIO function 39 (get file size) returns OK. ; If yes, NOTE and POINT work with real file offset. ; If not, NOTE and POINT work with the standard ScNum/Offset values. ; We remember a successful check in fd_table.ft_flag, bit 3. chk_supp: lda fd_table+ft_flag,x and #8 bne supp ; do the test lda __dos_type cmp #SPARTADOS beq :+ cmp #BWDOS beq :+ cmp #REALDOS bne ns1 : txa pha lda DOS+1 ; get SpartaDOS version cmp #$40 bcs supp1 ; SD-X (ver 4.xx) supports seeking on all disks ldx tmp3 ; iocb to use lda #GETFL sta ICCOM,x jsr CIOV bmi notsupp ; error code ? should be 168 (invalid command) ; seeking is supported on this DOS/Disk combination supp1: pla tax lda #8 ora fd_table+ft_flag,x sta fd_table+ft_flag,x supp: sec rts notsupp:pla ns1: clc rts ���������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/mcbdefault.s�����������������������������������������������������������������0000664�0000000�0000000�00000000232�13473601511�0017052�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; This file defines the default mouse callback ; .import _mouse_pm_callbacks .export _mouse_def_callbacks _mouse_def_callbacks := _mouse_pm_callbacks ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/mcbpm-shape.s����������������������������������������������������������������0000664�0000000�0000000�00000001314�13473601511�0017142�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; P/M mouse shape default definition ; ; Christian Groessler, 11.04.2014 ; ; Note that the height of the mouse cursor must not exceed 32 ; lines, otherwise the display routines won't do The Right ; Thing(tm). ; .export mouse_pm_bits .export mouse_pm_height : zeropage .export mouse_pm_hotspot_x : zeropage .export mouse_pm_hotspot_y : zeropage .rodata mouse_pm_bits: .byte %11110000 .byte %11000000 .byte %10100000 .byte %10010000 .byte %10001000 .byte %00000100 .byte %00000010 mouse_pm_height = <(* - mouse_pm_bits) ; hot spot is upper left corner mouse_pm_hotspot_x = 0 mouse_pm_hotspot_y = 0 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/mcbpm.s����������������������������������������������������������������������0000664�0000000�0000000�00000013763�13473601511�0016057�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; P/M mouse callbacks for the Ataris ; ; Christian Groessler, 11.04.2014 ; ; All functions in this module should be interrupt safe, because they may ; be called from an interrupt handler ; .include "atari.inc" .importzp sp .export _mouse_pm_callbacks .constructor pm_init, 27 .destructor pm_down ; get mouse shape data .import mouse_pm_bits .importzp mouse_pm_height .importzp mouse_pm_hotspot_x .importzp mouse_pm_hotspot_y ; P/M definitions. The MOUSE_PM_NUM value can be changed to adjust the ; number of the P/M used for the mouse. All others depend on this value. ; Valid P/M numbers are 0 to 4. When 4 is used, the missiles are used ; as a player. .ifdef USE_PAGE6 MOUSE_PM_NUM = 2 ; P/M used for the mouse ; This cannot be changed since only player #2 uses the memory at $600. .else MOUSE_PM_NUM = 4 ; P/M used for the mouse ; Using player #4 (missiles) wastes the least amount of memory on the ; atari target, since top of memory is typically at $xC20, and the ; missiles use the space at $xB00-$xBFF. ; On the atarixl target this configuration (not using page 6) is not ; really satisfying since the top of memory typically lies beneath ; the ROM and there is flickering visible while the ROM is banked in. .endif MOUSE_PM_BASE = pm_base ; ZP location pointing to the hw area used by the selected P/M .if MOUSE_PM_NUM = 4 MOUSE_PM_RAW = 0 ; MOUSE_PM_RAW is the hardware P/M number for MOUSE_PM_NUM .macro set_mouse_x ; assume CF = 0 sta HPOSM3 adc #2 sta HPOSM2 adc #2 sta HPOSM1 adc #2 sta HPOSM0 .endmacro .else MOUSE_PM_RAW = MOUSE_PM_NUM + 1 .macro set_mouse_x sta HPOSP0 + MOUSE_PM_NUM .endmacro .endif ; ------------------------------------------------------------------------ .rodata ; Callback structure _mouse_pm_callbacks: .addr hide .addr show .addr prep .addr draw .addr movex .addr movey ; ------------------------------------------------------------------------ .bss omy: .res 1 ; old Mouse Y position colhlp: .res 1 ; helper variable to set P/M color ; ------------------------------------------------------------------------ .segment "EXTZP" : zeropage pm_base:.res 2 ; ------------------------------------------------------------------------ .code ; Hide the mouse cursor. hide: lda #0 sta GRACTL rts ; Show the mouse cursor. show: .if MOUSE_PM_NUM < 4 lda #2 .else lda #1 .endif sta GRACTL jmp update_colors prep: draw: rts ; Move the mouse cursor x position to the value in A/X. movex: cpx #1 ror a clc adc #48 sbc #(mouse_pm_hotspot_x - 1) & $FF set_mouse_x jmp update_colors ; Move the mouse cursor y position to the value in A/X. movey: clc adc #32 sbc #(mouse_pm_hotspot_y - 1) & $FF pha lda omy jsr clr_pm ; remove player at old position jsr update_colors pla sta omy ;jmp set_pm ; put player to new position ; fall thru ; Set P/M data from 'mouse_pm_bits' set_pm: tay ldx #0 set_l: lda mouse_pm_bits,x sta (MOUSE_PM_BASE),y inx iny beq set_end cpx #mouse_pm_height bcc set_l set_end:rts ; Clear (zero) P/M data clr_pm: ldx #mouse_pm_height tay lda #0 clr_l: sta (MOUSE_PM_BASE),y iny beq clr_end dex bne clr_l clr_end:rts pm_down = hide ; this assumes a GRAPHICS 0 screen update_colors: lda COLOR2 ; get background color and #$F0 sta colhlp lda COLOR1 and #$0F ora colhlp .if MOUSE_PM_NUM = 4 sta PCOLR0 sta PCOLR1 sta PCOLR2 sta PCOLR3 lda #0 sta SIZEM .else sta PCOLR0 + MOUSE_PM_NUM lda #0 sta SIZEP0 + MOUSE_PM_NUM .endif rts ; ------------------------------------------------------------------------ .segment "ONCE" pm_init: lda #0 .ifdef USE_PAGE6 sta MOUSE_PM_BASE ldx #6 ; page 6 stx MOUSE_PM_BASE+1 .else ; use top of memory and lower sp accordingly sta sp sta MOUSE_PM_BASE lda sp+1 and #7 ; offset within 2K cmp #3 + MOUSE_PM_RAW + 1 ; can we use it? bcc @decr ; no lda sp+1 and #$F8 @set: adc #3 + MOUSE_PM_RAW - 1 ; CF is set, so adding MOUSE_PM_RAW + 3 sta MOUSE_PM_BASE+1 sta sp+1 bne @cont ; jump always @decr: lda sp+1 and #$F8 sbc #8 - 1 ; CF is clear, subtracts 8 bcs @set ; jump always @cont: lda #0 .endif tay @iniloo:sta (MOUSE_PM_BASE),y iny bne @iniloo .ifndef USE_PAGE6 lda MOUSE_PM_BASE+1 and #$F8 .endif sta PMBASE lda #62 sta SDMCTL lda #1 sta GPRIOR jmp update_colors �������������cc65-2.18/libsrc/atari/mcbtxtchar-char.s������������������������������������������������������������0000664�0000000�0000000�00000000231�13473601511�0020015�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Default text mode mouse cursor character ; ; Christian Groessler, 11.04.2014 ; .export mouse_txt_char : zp = 96 ; 'diamond' screen code �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/mcbtxtchar.s�����������������������������������������������������������������0000664�0000000�0000000�00000005453�13473601511�0017115�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Text mode character mouse callbacks for the Ataris ; ; Christian Groessler, 03.01.2014 ; ; derived from Apple2 version by ; Oliver Schmidt, 22.09.2005 ; ; All functions in this module should be interrupt safe, because they may ; be called from an interrupt handler ; .export _mouse_txt_callbacks .importzp tmp4 .import _mul40 .importzp mouse_txt_char ; screen code of mouse cursor .include "atari.inc" ; ------------------------------------------------------------------------ .bss backup: .res 1 visible:.res 1 ; ------------------------------------------------------------------------ .segment "EXTZP" : zeropage scrptr: .res 2 ; ------------------------------------------------------------------------ .rodata ; Callback structure _mouse_txt_callbacks: .addr hide .addr show .addr prep .addr draw .addr movex .addr movey ; ------------------------------------------------------------------------ .data ; setcursor getcursor: column: ldy #$00 ; Patched at runtime lda (scrptr),y rts setcursor: column2:ldy #$00 ; Patched at runtime sta (scrptr),y rts ; ------------------------------------------------------------------------ .code done: rts ; Hide the mouse cursor. hide: dec visible prep: jsr getcursor ; Get character at cursor position cmp #mouse_txt_char ; "mouse" character bne overwr ; no, probably program has overwritten it lda backup ; jmp setcursor ; Draw character overwr: sta backup rts ; Show the mouse cursor. show: inc visible draw: lda visible beq done jsr getcursor ; Cursor visible at current position? sta backup ; Save character at cursor position lda #mouse_txt_char jmp setcursor ; Draw cursor ; Move the mouse cursor x position to the value in A/X. movex: cpx #1 ror a lsr a ; convert to character position lsr a sta column+1 sta column2+1 rts ; Move the mouse cursor y position to the value in A/X. movey: ldy tmp4 ; mul40 uses tmp4, save in Y lsr a ; convert y position to character line lsr a lsr a jsr _mul40 ; carry is cleared by _mul40 adc SAVMSC sta scrptr txa adc SAVMSC+1 sta scrptr+1 sty tmp4 ; restore tmp4 rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/mou/�������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015363�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/mou/atrami.s�����������������������������������������������������������������0000664�0000000�0000000�00000000043�13473601511�0017021�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������AMIGA_MOUSE = 1 .include "atrst.s" ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/mou/atrjoy.s�����������������������������������������������������������������0000664�0000000�0000000�00000030456�13473601511�0017067�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Driver for a "joystick mouse". ; ; C128 version: Ullrich von Bassewitz, 2004-04-05, 2009-09-26 ; Adapted to Atari: Christian Groessler, 2014-01-02 ; .include "zeropage.inc" .include "mouse-kernel.inc" .include "atari.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table .ifdef __ATARIXL__ module_header _atrxjoy_mou .else module_header _atrjoy_mou .endif HEADER: ; Driver signature .byte $6d, $6f, $75 ; "mou" .byte MOUSE_API_VERSION ; Mouse driver API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr HIDE .addr SHOW .addr SETBOX .addr GETBOX .addr MOVE .addr BUTTONS .addr POS .addr INFO .addr IOCTL .addr IRQ ; Mouse driver flags .byte MOUSE_FLAG_LATE_IRQ ; Callback table, set by the kernel before INSTALL is called CHIDE: jmp $0000 ; Hide the cursor CSHOW: jmp $0000 ; Show the cursor CPREP: jmp $0000 ; Prepare to move the cursor CDRAW: jmp $0000 ; Draw the cursor CMOVEX: jmp $0000 ; Move the cursor to X coord CMOVEY: jmp $0000 ; Move the cursor to Y coord ;---------------------------------------------------------------------------- ; Constants SCREEN_HEIGHT = 191 SCREEN_WIDTH = 319 .enum JOY UP = $01 DOWN = $02 LEFT = $04 RIGHT = $08 .endenum ;---------------------------------------------------------------------------- ; Global variables. The bounding box values are sorted so that they can be ; written with the least effort in the SETBOX and GETBOX routines, so don't ; reorder them. .bss Vars: YPos: .res 2 ; Current mouse position, Y XPos: .res 2 ; Current mouse position, X XMin: .res 2 ; X1 value of bounding box YMin: .res 2 ; Y1 value of bounding box XMax: .res 2 ; X2 value of bounding box YMax: .res 2 ; Y2 value of bounding box Buttons: .res 1 ; Button mask OldDir: .res 1 ; previous direction bits OldButton: .res 1 ; previous buttons Temp: .res 1 ; Temporary value used in the int handler ; Default values for above variables .rodata ; (We use ".proc" because we want to define both a label and a scope.) .proc DefVars .word SCREEN_HEIGHT/2 ; YPos .word SCREEN_WIDTH/2 ; XPos .word 0 ; XMin .word 0 ; YMin .word SCREEN_WIDTH ; XMax .word SCREEN_HEIGHT ; YMax .byte 0 ; Buttons .endproc .code ;---------------------------------------------------------------------------- ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present. ; Must return an MOUSE_ERR_xx code in a/x. INSTALL: ; Initialize variables. Just copy the default stuff over ldx #.sizeof(DefVars)-1 @L1: lda DefVars,x sta Vars,x dex bpl @L1 ; Make sure the mouse cursor is at the default location. lda XPos ldx XPos+1 jsr CMOVEX lda YPos ldx YPos+1 jsr CMOVEY ; Done, return zero (= MOUSE_ERR_OK) ldx #$00 txa rts ;---------------------------------------------------------------------------- ; UNINSTALL routine. Is called before the driver is removed from memory. ; No return code required (the driver is removed from memory on return). UNINSTALL = HIDE ; Hide cursor on exit ;---------------------------------------------------------------------------- ; HIDE routine. Is called to hide the mouse pointer. The mouse kernel manages ; a counter for calls to show/hide, and the driver entry point is only called ; if the mouse is currently visible and should get hidden. For most drivers, ; no special action is required besides hiding the mouse cursor. ; No return code required. HIDE: php sei jsr CHIDE plp rts ;---------------------------------------------------------------------------- ; SHOW routine. Is called to show the mouse pointer. The mouse kernel manages ; a counter for calls to show/hide, and the driver entry point is only called ; if the mouse is currently hidden and should become visible. For most drivers, ; no special action is required besides enabling the mouse cursor. ; No return code required. SHOW: php sei jsr CSHOW plp rts ;---------------------------------------------------------------------------- ; SETBOX: Set the mouse bounding box. The parameters are passed as they come ; from the C program, that is, a pointer to a mouse_box struct in a/x. ; No checks are done if the mouse is currently inside the box, this is the job ; of the caller. It is not necessary to validate the parameters, trust the ; caller and save some code here. No return code required. SETBOX: sta ptr1 stx ptr1+1 ; Save data pointer ldy #.sizeof (MOUSE_BOX)-1 php sei @L1: lda (ptr1),y sta XMin,y dey bpl @L1 plp rts ;---------------------------------------------------------------------------- ; GETBOX: Return the mouse bounding box. The parameters are passed as they ; come from the C program, that is, a pointer to a mouse_box struct in a/x. GETBOX: sta ptr1 stx ptr1+1 ; Save data pointer ldy #.sizeof (MOUSE_BOX)-1 php sei @L1: lda XMin,y sta (ptr1),y dey bpl @L1 plp rts ;---------------------------------------------------------------------------- ; MOVE: Move the mouse to a new position. The position is passed as it comes ; from the C program, that is: X on the stack and Y in a/x. The C wrapper will ; remove the parameter from the stack on return. ; No checks are done if the new position is valid (within the bounding box or ; the screen). No return code required. ; MOVE: php sei ; No interrupts pha txa pha jsr CPREP pla tax pla sta YPos stx YPos+1 ; New Y position jsr CMOVEY ; Set it ldy #$01 lda (sp),y sta XPos+1 tax dey lda (sp),y sta XPos ; New X position jsr CMOVEX ; Move the cursor jsr CDRAW plp ; Restore interrupt flag rts ;---------------------------------------------------------------------------- ; BUTTONS: Return the button mask in a/x. BUTTONS: lda Buttons ldx #$00 rts ;---------------------------------------------------------------------------- ; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1. ; No return code required. POS: ldy #MOUSE_POS::XCOORD ; Structure offset php sei ; Disable interrupts lda XPos ; Transfer the position sta (ptr1),y lda XPos+1 iny sta (ptr1),y lda YPos iny sta (ptr1),y lda YPos+1 plp ; Restore interrupt flag iny sta (ptr1),y ; Store last byte rts ; Done ;---------------------------------------------------------------------------- ; INFO: Returns mouse position and current button mask in the MOUSE_INFO ; struct pointed to by ptr1. No return code required. ; ; We're cheating here to keep the code smaller: The first fields of the ; mouse_info struct are identical to the mouse_pos struct, so we will just ; call _mouse_pos to initialize the struct pointer and fill the position ; fields. INFO: jsr POS ; Fill in the button state lda Buttons ldy #MOUSE_INFO::BUTTONS sta (ptr1),y rts ;---------------------------------------------------------------------------- ; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl ; specific data in ptr1, and the ioctl code in A. ; Must return an error code in a/x. ; IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now ldx #>MOUSE_ERR_INV_IOCTL rts ;---------------------------------------------------------------------------- ; IRQ: Irq handler entry point. Called as a subroutine but in IRQ context ; (so be careful). The routine MUST return carry set if the interrupt has been ; 'handled' - which means that the interrupt source is gone. Otherwise it ; MUST return carry clear. ; IRQ: ; Check for a pressed button and place the result into Buttons ldx #0 lda TRIG0 ; joystick #0 trigger bne @L0 ; not pressed ldx #MOUSE_BTN_LEFT @L0: stx Buttons lda PORTA ; get joystick direction bits and #15 ; clear joystick #1 bits eor #15 sta Temp jsr CPREP ; Check if user activity occurred, and if yes, disable "attract mode" lda Buttons cmp OldButton beq @ChkDir sta OldButton lda #0 sta ATRACT ; disable "attract mode" @ChkDir:lda Temp cmp OldDir beq @ChkCnt sta OldDir lda #0 sta ATRACT ; Check left/right @ChkCnt:lda Temp ; Read joystick #0 and #(JOY::LEFT | JOY::RIGHT) beq @SkipX ; ; We will cheat here and rely on the fact that either the left, OR the right ; bit can be active and #JOY::RIGHT ; Check RIGHT bit bne @Right lda #$FF tax bne @AddX ; Branch always @Right: lda #$01 ldx #$00 ; Calculate the new X coordinate (--> a/y) @AddX: add XPos tay ; Remember low byte txa adc XPos+1 tax ; Limit the X coordinate to the bounding box cpy XMin sbc XMin+1 bpl @L1 ldy XMin ldx XMin+1 jmp @L2 @L1: txa cpy XMax sbc XMax+1 bmi @L2 ldy XMax ldx XMax+1 @L2: sty XPos stx XPos+1 ; Move the mouse pointer to the new X pos tya jsr CMOVEX ; Calculate the Y movement vector @SkipX: lda Temp ; Read joystick #0 and #(JOY::UP | JOY::DOWN) ; Check up/down beq @SkipY ; ; We will cheat here and rely on the fact that either the up, OR the down ; bit can be active lsr a bcc @Down lda #$FF tax bne @AddY @Down: lda #$01 ldx #$00 ; Calculate the new Y coordinate (--> a/y) @AddY: add YPos tay ; Remember low byte txa adc YPos+1 tax ; Limit the Y coordinate to the bounding box cpy YMin sbc YMin+1 bpl @L3 ldy YMin ldx YMin+1 jmp @L4 @L3: txa cpy YMax sbc YMax+1 bmi @L4 ldy YMax ldx YMax+1 @L4: sty YPos stx YPos+1 ; Move the mouse pointer to the new X pos tya jsr CMOVEY ; Done @SkipY: jsr CDRAW clc ; Interrupt not "handled" rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/mou/atrst.s������������������������������������������������������������������0000664�0000000�0000000�00000047543�13473601511�0016721�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Mouse driver for ST & Amiga mouses and Atari trakball. ; ; Original access routines: 05/07/2000 Freddy Offenga ; Converted to driver: Christian Groessler, 2014-01-04 ; ; Defines: ; AMIGA_MOUSE - builds Amiga mouse version ; TRAK_MOUSE - builds trakball version ; If none of these defines are active, the ST mouse version ; is being built. ; ;DEBUG = 1 DISABLE_TIMEOUT = 30 ; # of vertical blank interrupts after which, if ; no mouse motion occurred, the polling IRQ gets ; disabled. ; VBI frequency is 50Hz for PAL and 60Hz for NTSC .include "zeropage.inc" .include "mouse-kernel.inc" .include "atari.inc" .macpack generic .macpack module .if .not ( .defined (AMIGA_MOUSE) .or .defined (TRAK_MOUSE)) ST_MOUSE = 1 .endif ; ------------------------------------------------------------------------ ; Header. Includes jump table .if .defined (ST_MOUSE) .ifdef __ATARIXL__ module_header _atrxst_mou .else module_header _atrst_mou .endif .elseif .defined (AMIGA_MOUSE) .ifdef __ATARIXL__ module_header _atrxami_mou .else module_header _atrami_mou .endif .elseif .defined (TRAK_MOUSE) .ifdef __ATARIXL__ module_header _atrxtrk_mou .else module_header _atrtrk_mou .endif .endif HEADER: ; Driver signature .byte $6d, $6f, $75 ; "mou" .byte MOUSE_API_VERSION ; Mouse driver API version number ; Library reference libref: .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr HIDE .addr SHOW .addr SETBOX .addr GETBOX .addr MOVE .addr BUTTONS .addr POS .addr INFO .addr IOCTL .addr IRQ ; Mouse driver flags .byte MOUSE_FLAG_LATE_IRQ ; Callback table, set by the kernel before INSTALL is called CHIDE: jmp $0000 ; Hide the cursor CSHOW: jmp $0000 ; Show the cursor CPREP: jmp $0000 ; Prepare to move the cursor CDRAW: jmp $0000 ; Draw the cursor CMOVEX: jmp $0000 ; Move the cursor to X coord CMOVEY: jmp $0000 ; Move the cursor to Y coord ;---------------------------------------------------------------------------- ; Constants SCREEN_HEIGHT = 191 SCREEN_WIDTH = 319 .enum JOY UP = $01 DOWN = $02 LEFT = $04 RIGHT = $08 .endenum ;---------------------------------------------------------------------------- ; Global variables. The bounding box values are sorted so that they can be ; written with the least effort in the SETBOX and GETBOX routines, so don't ; reorder them. .bss Vars: YPos: .res 2 ; Current mouse position, Y XPos: .res 2 ; Current mouse position, X XMin: .res 2 ; X1 value of bounding box YMin: .res 2 ; Y1 value of bounding box XMax: .res 2 ; X2 value of bounding box YMax: .res 2 ; Y2 value of bounding box Buttons: .res 1 ; Button mask OldButton: .res 1 ; previous buttons XPosWrk: .res 2 YPosWrk: .res 2 irq_enabled: .res 1 ; flag indicating that the high frequency polling interrupt is enabled old_porta_vbi: .res 1 ; previous PORTA value of the VBI interrupt (IRQ) how_long: .res 1 ; counter for how many VBI interrupts the mouse hasn't been moved in_irq: .res 1 ; flag indicating high-frequency polling interrupt is active .if .defined (AMIGA_MOUSE) .or .defined (ST_MOUSE) dumx: .res 1 dumy: .res 1 .endif .ifdef TRAK_MOUSE oldval: .res 1 .endif .ifndef __ATARIXL__ OldT2: .res 2 .else .data set_VTIMR2_handler: .byte $4C, 0, 0 .endif .rodata ; Default values for some of the above variables ; (We use ".proc" because we want to define both a label and a scope.) .proc DefVars .word (SCREEN_HEIGHT+1)/2 ; YPos .word (SCREEN_WIDTH+1)/2 ; XPos .word 0 ; XMin .word 0 ; YMin .word SCREEN_WIDTH ; XMax .word SCREEN_HEIGHT ; YMax .byte 0 ; Buttons .endproc .ifdef ST_MOUSE ; ST mouse lookup table STTab: .byte $FF,$01,$00,$01 .byte $00,$FF,$00,$01 .byte $01,$00,$FF,$00 .byte $01,$00,$01,$FF .endif .ifdef AMIGA_MOUSE ; Amiga mouse lookup table AmiTab: .byte $FF,$01,$00,$FF .byte $00,$FF,$FF,$01 .byte $01,$FF,$FF,$00 .byte $FF,$00,$01,$FF .endif .code ;---------------------------------------------------------------------------- ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present. ; Must return an MOUSE_ERR_xx code in a/x. INSTALL: ; Initialize variables. Just copy the default stuff over ldx #.sizeof(DefVars)-1 @L1: lda DefVars,x sta Vars,x dex bpl @L1 ; Make sure the mouse cursor is at the default location. lda XPos sta XPosWrk ldx XPos+1 stx XPosWrk+1 jsr CMOVEX lda YPos sta YPosWrk ldx YPos+1 stx YPosWrk+1 jsr CMOVEY ; Install timer irq routine to poll mouse. .ifdef __ATARIXL__ ; Setup pointer to wrapper install/deinstall function. lda libref sta set_VTIMR2_handler+1 lda libref+1 sta set_VTIMR2_handler+2 ; Install my handler. sec lda #<T2Han ldx #>T2Han jsr set_VTIMR2_handler .else lda VTIMR2 sta OldT2 lda VTIMR2+1 sta OldT2+1 php sei lda #<T2Han sta VTIMR2 lda #>T2Han sta VTIMR2+1 plp .endif lda #%00000001 sta AUDCTL lda #0 sta AUDC2 lda #15 sta AUDF2 sta STIMER lda PORTA and #$0f sta old_porta_vbi ; Done, return zero (= MOUSE_ERR_OK) ldx #$00 txa rts ;---------------------------------------------------------------------------- ; UNINSTALL routine. Is called before the driver is removed from memory. ; No return code required (the driver is removed from memory on return). UNINSTALL: ; uninstall timer irq routine lda POKMSK and #%11111101 ; timer 2 disable sta IRQEN sta POKMSK .ifdef __ATARIXL__ clc jsr set_VTIMR2_handler .else php sei lda OldT2 sta VTIMR2 lda OldT2+1 sta VTIMR2+1 plp .endif ; fall thru... ;---------------------------------------------------------------------------- ; HIDE routine. Is called to hide the mouse pointer. The mouse kernel manages ; a counter for calls to show/hide, and the driver entry point is only called ; if the mouse is currently visible and should get hidden. For most drivers, ; no special action is required besides hiding the mouse cursor. ; No return code required. HIDE: php sei jsr CHIDE plp rts ;---------------------------------------------------------------------------- ; SHOW routine. Is called to show the mouse pointer. The mouse kernel manages ; a counter for calls to show/hide, and the driver entry point is only called ; if the mouse is currently hidden and should become visible. For most drivers, ; no special action is required besides enabling the mouse cursor. ; No return code required. SHOW: php sei jsr CSHOW plp rts ;---------------------------------------------------------------------------- ; SETBOX: Set the mouse bounding box. The parameters are passed as they come ; from the C program, that is, a pointer to a mouse_box struct in a/x. ; No checks are done if the mouse is currently inside the box, this is the job ; of the caller. It is not necessary to validate the parameters, trust the ; caller and save some code here. No return code required. SETBOX: sta ptr1 stx ptr1+1 ; Save data pointer ldy #.sizeof (MOUSE_BOX)-1 php sei @L1: lda (ptr1),y sta XMin,y dey bpl @L1 plp rts ;---------------------------------------------------------------------------- ; GETBOX: Return the mouse bounding box. The parameters are passed as they ; come from the C program, that is, a pointer to a mouse_box struct in a/x. GETBOX: sta ptr1 stx ptr1+1 ; Save data pointer ldy #.sizeof (MOUSE_BOX)-1 php sei @L1: lda XMin,y sta (ptr1),y dey bpl @L1 plp rts ;---------------------------------------------------------------------------- ; MOVE: Move the mouse to a new position. The position is passed as it comes ; from the C program, that is: X on the stack and Y in a/x. The C wrapper will ; remove the parameter from the stack on return. ; No checks are done if the new position is valid (within the bounding box or ; the screen). No return code required. ; MOVE: php sei ; No interrupts pha txa pha jsr CPREP pla tax pla sta YPos sta YPosWrk stx YPos+1 ; New Y position stx YPosWrk+1 jsr CMOVEY ; Set it ldy #$01 lda (sp),y sta XPos+1 sta XPosWrk+1 tax dey lda (sp),y sta XPos ; New X position sta XPosWrk jsr CMOVEX ; Move the cursor jsr CDRAW plp ; Restore interrupt flag rts ;---------------------------------------------------------------------------- ; BUTTONS: Return the button mask in a/x. BUTTONS: lda Buttons ldx #$00 rts ;---------------------------------------------------------------------------- ; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1. ; No return code required. POS: ldy #MOUSE_POS::XCOORD ; Structure offset php sei ; Disable interrupts lda XPos ; Transfer the position sta (ptr1),y lda XPos+1 iny sta (ptr1),y lda YPos iny sta (ptr1),y lda YPos+1 plp ; Restore interrupt flag iny sta (ptr1),y ; Store last byte rts ; Done ;---------------------------------------------------------------------------- ; INFO: Returns mouse position and current button mask in the MOUSE_INFO ; struct pointed to by ptr1. No return code required. ; ; We're cheating here to keep the code smaller: The first fields of the ; mouse_info struct are identical to the mouse_pos struct, so we will just ; call _mouse_pos to initialize the struct pointer and fill the position ; fields. INFO: jsr POS ; Fill in the button state lda Buttons ldy #MOUSE_INFO::BUTTONS sta (ptr1),y rts ;---------------------------------------------------------------------------- ; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl ; specific data in ptr1, and the ioctl code in A. ; Must return an error code in a/x. ; IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now ldx #>MOUSE_ERR_INV_IOCTL rts ;---------------------------------------------------------------------------- ; IRQ: Irq handler entry point. Called as a subroutine but in IRQ context ; (so be careful). The routine MUST return carry set if the interrupt has been ; 'handled' - which means that the interrupt source is gone. Otherwise it ; MUST return carry clear. ; IRQ: lda PORTA ; mouse port contents and #$0f ; check port 1 only ldx irq_enabled bne @L1 ; IRQ is disabled, check for mouse motion and enable IRQ if mouse motion detected cmp old_porta_vbi beq @L3 ; no motion lda #0 sta ATRACT ; disable "attract mode" ; Turn mouse polling IRQ back on lda POKMSK ora #%00000010 ; timer 2 enable sta POKMSK sta IRQEN sta irq_enabled bne @L3 ; not reached ; IRQ is enabled @L1: cmp old_porta_vbi ; mouse motion since last VBI? sta old_porta_vbi beq @L2 ; no, increment timeout to disable IRQ lda #0 sta how_long ; yes, reinitialize wait counter beq @L3 ; not reached @L2: inc how_long ; no motion, increment wait counter lda how_long cmp #DISABLE_TIMEOUT ; timeout? bcc @L3 ; no lda #0 ; yes, turn off IRQ sta how_long ; no mouse input -- turn IRQ off sta irq_enabled lda POKMSK and #%11111101 ; timer 2 disable sta IRQEN sta POKMSK ; Check for a pressed button and place the result into Buttons @L3: ldx #0 lda TRIG0 ; joystick #0 trigger bne @L4 ; not pressed ldx #MOUSE_BTN_LEFT @L4: stx Buttons jsr CPREP ; Disable "attract mode" if button status has changed lda Buttons cmp OldButton beq @L5 sta OldButton lda #0 sta ATRACT ; Limit the X coordinate to the bounding box @L5: lda XPosWrk+1 ldy XPosWrk tax cpy XMin sbc XMin+1 bpl @L6 ldy XMin ldx XMin+1 jmp @L7 @L6: txa cpy XMax sbc XMax+1 bmi @L7 ldy XMax ldx XMax+1 @L7: sty XPos stx XPos+1 tya jsr CMOVEX ; Limit the Y coordinate to the bounding box lda YPosWrk+1 ldy YPosWrk tax cpy YMin sbc YMin+1 bpl @L8 ldy YMin ldx YMin+1 jmp @L9 @L8: txa cpy YMax sbc YMax+1 bmi @L9 ldy YMax ldx YMax+1 @L9: sty YPos stx YPos+1 tya jsr CMOVEY jsr CDRAW .ifdef DEBUG ; print on upper right corner 'E' or 'D', indicating the IRQ is enabled or disabled ldy irq_enabled beq @L10 lda #37 ; screen code for 'E' .byte $2c ; bit opcode, eats next 2 bytes @L10: lda #36 ; screen code for 'D' ldy #39 sta (SAVMSC),y .endif clc rts ;---------------------------------------------------------------------------- ; T2Han: Local IRQ routine to poll mouse ; T2Han: lda CRITIC ; if CRITIC flag is set, disable the bne disable_me ; high frequency polling IRQ, in order ; not to interfere with SIO I/O (e.g. ; floppy access or serial I/O) lda in_irq ; handler entered again? bne skip ; yes, ignore this interrupt inc in_irq cli ; enable IRQs so that we don't block them for too long tya pha txa pha .ifdef DEBUG lda RANDOM sta COLBK .endif lda PORTA tay .ifdef ST_MOUSE ; ST mouse version and #%00000011 ora dumx tax lda STTab,x bmi nxst beq xist dec XPosWrk lda XPosWrk cmp #255 bne nxst dec XPosWrk+1 jmp nxst xist: inc XPosWrk bne nxst inc XPosWrk+1 nxst: tya and #%00001100 ora dumy tax lda STTab,x bmi nyst bne yst dec YPosWrk lda YPosWrk cmp #255 bne nyst dec YPosWrk+1 jmp nyst yst: inc YPosWrk bne nyst inc YPosWrk+1 ; store old readings nyst: tya and #%00000011 asl asl sta dumx tya and #%00001100 lsr lsr sta dumy .elseif .defined (AMIGA_MOUSE) ; Amiga mouse version lsr and #%00000101 ora dumx tax lda AmiTab,x bmi nxami bne xiami dec XPosWrk lda XPosWrk cmp #255 bne nxami dec XPosWrk+1 jmp nxami xiami: inc XPosWrk bne nxami inc XPosWrk+1 nxami: tya and #%00000101 ora dumy tax lda AmiTab,x bmi nyami bne yiami dec YPosWrk lda YPosWrk cmp #255 bne nyami dec YPosWrk+1 jmp nyami yiami: inc YPosWrk bne nyami inc YPosWrk+1 ; store old readings nyami: tya and #%00001010 sta dumx tya and #%00000101 asl sta dumy .elseif .defined (TRAK_MOUSE) ; trakball version eor oldval and #%00001000 beq horiz tya and #%00000100 beq mmup inc YPosWrk bne horiz inc YPosWrk+1 bne horiz mmup: dec YPosWrk lda YPosWrk cmp #255 bne horiz dec YPosWrk+1 horiz: tya eor oldval and #%00000010 beq mmexit tya and #%00000001 beq mmleft inc XPosWrk bne mmexit inc XPosWrk+1 bne mmexit mmleft: dec XPosWrk lda XPosWrk cmp #255 bne mmexit dec XPosWrk+1 mmexit: sty oldval .endif pla tax pla tay dec in_irq skip: .ifdef __ATARIXL__ rts .else pla rti .endif ; Disable the interrupt source which caused us to be called. ; The interrupt will be enabled again by the "IRQ" routine. ; The "IRQ" routine, despite its name, is called from the ; vertical blank NMI interrupt *only* if the CRITIC flag has ; been cleared. disable_me: lda POKMSK and #%11111101 ; timer 2 disable sta IRQEN sta POKMSK lda #0 sta irq_enabled lda PORTA and #$0f sta old_porta_vbi .ifdef __ATARIXL__ rts .else pla rti .endif �������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/mou/atrtrk.s�����������������������������������������������������������������0000664�0000000�0000000�00000000042�13473601511�0017052�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������TRAK_MOUSE = 1 .include "atrst.s" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/mou/atrtt.s������������������������������������������������������������������0000664�0000000�0000000�00000032304�13473601511�0016707�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Mouse driver for Atari Touch Tablet ; ; Christian Groessler, 2014-01-05 ; .include "zeropage.inc" .include "mouse-kernel.inc" .include "atari.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table .ifdef __ATARIXL__ module_header _atrxtt_mou .else module_header _atrtt_mou .endif HEADER: ; Driver signature .byte $6d, $6f, $75 ; "mou" .byte MOUSE_API_VERSION ; Mouse driver API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr HIDE .addr SHOW .addr SETBOX .addr GETBOX .addr MOVE .addr BUTTONS .addr POS .addr INFO .addr IOCTL .addr IRQ ; Mouse driver flags .byte MOUSE_FLAG_LATE_IRQ ; Callback table, set by the kernel before INSTALL is called CHIDE: jmp $0000 ; Hide the cursor CSHOW: jmp $0000 ; Show the cursor CPREP: jmp $0000 ; Prepare to move the cursor CDRAW: jmp $0000 ; Draw the cursor CMOVEX: jmp $0000 ; Move the cursor to X coord CMOVEY: jmp $0000 ; Move the cursor to Y coord ;---------------------------------------------------------------------------- ; Constants SCREEN_HEIGHT = 191 SCREEN_WIDTH = 319 .enum JOY UP = $01 DOWN = $02 LEFT = $04 RIGHT = $08 .endenum ;---------------------------------------------------------------------------- ; Global variables. The bounding box values are sorted so that they can be ; written with the least effort in the SETBOX and GETBOX routines, so don't ; reorder them. .bss Vars: YPos: .res 2 ; Current mouse position, Y XPos: .res 2 ; Current mouse position, X XMin: .res 2 ; X1 value of bounding box YMin: .res 2 ; Y1 value of bounding box XMax: .res 2 ; X2 value of bounding box YMax: .res 2 ; Y2 value of bounding box Buttons: .res 1 ; Button mask OldButton: .res 1 ; previous buttons ; Default values for above variables .rodata ; (We use ".proc" because we want to define both a label and a scope.) .proc DefVars .word SCREEN_HEIGHT/2 ; YPos .word SCREEN_WIDTH/2 ; XPos .word 0 ; XMin .word 0 ; YMin .word SCREEN_WIDTH ; XMax .word SCREEN_HEIGHT ; YMax .byte 0 ; Buttons .endproc .code ;---------------------------------------------------------------------------- ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present. ; Must return an MOUSE_ERR_xx code in a/x. INSTALL: ; Initialize variables. Just copy the default stuff over ldx #.sizeof(DefVars)-1 @L1: lda DefVars,x sta Vars,x dex bpl @L1 ; Make sure the mouse cursor is at the default location. lda XPos ldx XPos+1 jsr CMOVEX lda YPos ldx YPos+1 jsr CMOVEY ; Done, return zero (= MOUSE_ERR_OK) ldx #$00 txa rts ;---------------------------------------------------------------------------- ; UNINSTALL routine. Is called before the driver is removed from memory. ; No return code required (the driver is removed from memory on return). UNINSTALL = HIDE ; Hide cursor on exit ;---------------------------------------------------------------------------- ; HIDE routine. Is called to hide the mouse pointer. The mouse kernel manages ; a counter for calls to show/hide, and the driver entry point is only called ; if the mouse is currently visible and should get hidden. For most drivers, ; no special action is required besides hiding the mouse cursor. ; No return code required. HIDE: php sei jsr CHIDE plp rts ;---------------------------------------------------------------------------- ; SHOW routine. Is called to show the mouse pointer. The mouse kernel manages ; a counter for calls to show/hide, and the driver entry point is only called ; if the mouse is currently hidden and should become visible. For most drivers, ; no special action is required besides enabling the mouse cursor. ; No return code required. SHOW: php sei jsr CSHOW plp rts ;---------------------------------------------------------------------------- ; SETBOX: Set the mouse bounding box. The parameters are passed as they come ; from the C program, that is, a pointer to a mouse_box struct in a/x. ; No checks are done if the mouse is currently inside the box, this is the job ; of the caller. It is not necessary to validate the parameters, trust the ; caller and save some code here. No return code required. SETBOX: sta ptr1 stx ptr1+1 ; Save data pointer ldy #.sizeof (MOUSE_BOX)-1 php sei @L1: lda (ptr1),y sta XMin,y dey bpl @L1 plp rts ;---------------------------------------------------------------------------- ; GETBOX: Return the mouse bounding box. The parameters are passed as they ; come from the C program, that is, a pointer to a mouse_box struct in a/x. GETBOX: sta ptr1 stx ptr1+1 ; Save data pointer ldy #.sizeof (MOUSE_BOX)-1 php sei @L1: lda XMin,y sta (ptr1),y dey bpl @L1 plp rts ;---------------------------------------------------------------------------- ; MOVE: Move the mouse to a new position. The position is passed as it comes ; from the C program, that is: X on the stack and Y in a/x. The C wrapper will ; remove the parameter from the stack on return. ; No checks are done if the new position is valid (within the bounding box or ; the screen). No return code required. ; MOVE: php sei ; No interrupts pha txa pha jsr CPREP pla tax pla sta YPos stx YPos+1 ; New Y position jsr CMOVEY ; Set it ldy #$01 lda (sp),y sta XPos+1 tax dey lda (sp),y sta XPos ; New X position jsr CMOVEX ; Move the cursor jsr CSHOW plp ; Restore interrupt flag rts ;---------------------------------------------------------------------------- ; BUTTONS: Return the button mask in a/x. BUTTONS: lda Buttons ldx #$00 rts ;---------------------------------------------------------------------------- ; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1. ; No return code required. POS: ldy #MOUSE_POS::XCOORD ; Structure offset php sei ; Disable interrupts lda XPos ; Transfer the position sta (ptr1),y lda XPos+1 iny sta (ptr1),y lda YPos iny sta (ptr1),y lda YPos+1 plp ; Restore interrupt flag iny sta (ptr1),y ; Store last byte rts ; Done ;---------------------------------------------------------------------------- ; INFO: Returns mouse position and current button mask in the MOUSE_INFO ; struct pointed to by ptr1. No return code required. ; ; We're cheating here to keep the code smaller: The first fields of the ; mouse_info struct are identical to the mouse_pos struct, so we will just ; call _mouse_pos to initialize the struct pointer and fill the position ; fields. INFO: jsr POS ; Fill in the button state lda Buttons ldy #MOUSE_INFO::BUTTONS sta (ptr1),y rts ;---------------------------------------------------------------------------- ; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl ; specific data in ptr1, and the ioctl code in A. ; Must return an error code in a/x. ; IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now ldx #>MOUSE_ERR_INV_IOCTL rts ;---------------------------------------------------------------------------- ; IRQ: Irq handler entry point. Called as a subroutine but in IRQ context ; (so be careful). The routine MUST return carry set if the interrupt has been ; 'handled' - which means that the interrupt source is gone. Otherwise it ; MUST return carry clear. ; IRQ: ; Check for a pressed button and place the result into Buttons ldx #0 stx Buttons lda PORTA ; get other buttons eor #255 tax and #5 ; pen button and left button are mapped to left mouse button beq @L01 lda #MOUSE_BTN_LEFT ora Buttons sta Buttons @L01: txa and #8 beq @L02 lda #MOUSE_BTN_RIGHT ora Buttons sta Buttons ; Check if button status changed, and disable "attract mode" if yes @L02: lda Buttons cmp OldButton beq @L03 sta OldButton lda #0 sta ATRACT ; If we read 228 for X or Y positions, we assume the user has lifted the pen ; and don't change the cursor position. @L03: lda PADDL0 cmp #228 beq @Cont ; CF set if equal lda PADDL1 cmp #228 ; CF set if equal @Cont: php ; remember CF jsr CPREP plp ; restore CF bcc @L04 jmp @Show @L04: ldx #0 stx XPos+1 stx YPos+1 stx ATRACT ; disable "attract mode" ; Get cursor position ; ------------------- ; The touch pad is read thru the paddle potentiometers. The possible ; values are 1..228. Since the maximum value is less than the X ; dimension we have to "stretch" this value. In order to use only ; divisions by powers of two, we use the following appoximation: ; 320/227 = 1.4096 ; 1+1/2-1/8+1/32 = 1.4062 ; For Y we subtract 1/8 of it to get in the YMax ballpark. ; 228-228/8=199.5 ; A small area in the Y dimension of the touchpad isn't used with ; this approximation. The Y value is inverted, (0,0) is the bottom ; left corner of the touchpad. ; X ldx PADDL0 ; get X postion dex ; decrement, since it's 1-based stx XPos txa lsr a tax clc adc XPos sta XPos bcc @L05 inc XPos+1 @L05: txa lsr a ; port value / 4 lsr a ; port value / 8 tax sec lda XPos stx XPos sbc XPos sta XPos bcs @L06 dec XPos+1 @L06: txa lsr a ; port value / 16 lsr a ; port value / 32 clc adc XPos sta XPos bcc @L07 inc XPos+1 @L07: tay lda XPos+1 tax ; Limit the X coordinate to the bounding box cpy XMin sbc XMin+1 bpl @L08 ldy XMin ldx XMin+1 jmp @L09 @L08: txa cpy XMax sbc XMax+1 bmi @L09 ldy XMax ldx XMax+1 @L09: sty XPos stx XPos+1 ; Move the mouse pointer to the new X pos tya jsr CMOVEX ; Y ldx PADDL1 ; get Y postion dex ; decrement, since it's 1-based stx YPos lda #228 sec sbc YPos ; invert value tax lsr a lsr a lsr a sta YPos txa sec sbc YPos sta YPos tay lda YPos+1 tax ; Limit the Y coordinate to the bounding box cpy YMin sbc YMin+1 bpl @L10 ldy YMin ldx YMin+1 jmp @L11 @L10: txa cpy YMax sbc YMax+1 bmi @L11 ldy YMax ldx YMax+1 @L11: sty YPos stx YPos+1 ; Move the mouse pointer to the new X pos tya jsr CMOVEY @Show: jsr CDRAW clc ; Interrupt not "handled" rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/mouse_stat_stddrv.s����������������������������������������������������������0000664�0000000�0000000�00000000634�13473601511�0020523�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Address of the static standard mouse driver ; ; Christian Groessler, 2014-01-02 ; ; const void mouse_static_stddrv[]; ; .export _mouse_static_stddrv .ifdef __ATARIXL__ .import _atrxst_mou .else .import _atrst_mou .endif .rodata .ifdef __ATARIXL__ _mouse_static_stddrv := _atrxst_mou .else _mouse_static_stddrv := _atrst_mou .endif ����������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/mouse_stddrv.s���������������������������������������������������������������0000664�0000000�0000000�00000000425�13473601511�0017466�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Name of the standard mouse driver ; ; Christian Groessler, 2014-01-02 ; ; const char mouse_stddrv[]; ; .export _mouse_stddrv .rodata _mouse_stddrv: .ifdef __ATARIXL__ .asciiz "ATRXST.MOU" .else .asciiz "ATRST.MOU" .endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/mouseref.s�������������������������������������������������������������������0000664�0000000�0000000�00000000345�13473601511�0016576�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, 2014-04-22 ; .export mouse_libref .ifdef __ATARIXL__ .import set_VTIMR2_handler mouse_libref := set_VTIMR2_handler .else .import _exit mouse_libref := _exit .endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/open.s�����������������������������������������������������������������������0000664�0000000�0000000�00000007741�13473601511�0015721�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, Jan-2003 ; ; int open(const char *name,int flags,...); ; .include "atari.inc" .include "fcntl.inc" .include "errno.inc" .include "fd.inc" .include "zeropage.inc" .export _open .destructor closeallfiles, 5 .import _close .import clriocb .import fddecusage,newfd .import findfreeiocb .import incsp4 .import ldaxysp,addysp .import __oserror .ifdef UCASE_FILENAME .import ucase_fn .endif .proc _open dey ; parm count < 4 shouldn't be needed to be checked dey ; (it generates a c compiler warning) dey dey beq parmok ; parameter count ok jsr addysp ; fix stack, throw away unused parameters parmok: jsr findfreeiocb beq iocbok ; we found one lda #<EMFILE ; "too many open files" seterr: jsr __directerrno jsr incsp4 ; clean up stack lda #$FF tax rts ; return -1 ; process the mode argument iocbok: stx tmp4 jsr clriocb ; init with zero ldy #1 jsr ldaxysp ; get mode ldx tmp4 pha and #O_APPEND beq no_app pla and #15 cmp #O_RDONLY ; DOS supports append with write-only only beq invret cmp #O_RDWR beq invret lda #OPNOT|APPEND bne set .ifndef UCASE_FILENAME invret: lda #<EINVAL ; file name is too long jmp seterr .endif no_app: pla and #15 cmp #O_RDONLY bne l1 lda #OPNIN set: sta ICAX1,x bne cont l1: cmp #O_WRONLY bne l2 lda #OPNOT bne set l2: ; O_RDWR lda #OPNOT|OPNIN bne set ; process the filename argument cont: ldy #3 jsr ldaxysp .ifdef UCASE_FILENAME .ifdef DEFAULT_DEVICE ldy #$80 .else ldy #$00 .endif sty tmp2 ; set flag for ucase_fn jsr ucase_fn bcc ucok1 invret: lda #<EINVAL ; file name is too long jmp seterr ucok1: .endif ; defined UCASE_FILENAME ldy tmp4 ;AX - points to filename ;Y - iocb to use, if open needed jsr newfd ; maybe we don't need to open and can reuse an iocb ; returns fd num to use in tmp2, all regs unchanged bcs doopen ; C set: open needed lda #0 ; clears N flag beq finish doopen: sta ICBAL,y txa sta ICBAH,y ldx tmp4 lda #OPEN sta ICCOM,x jsr CIOV ; clean up the stack finish: php txa pha tya pha .ifdef UCASE_FILENAME ldy tmp3 ; get size jsr addysp ; free used space on the stack .endif ; defined UCASE_FILENAME jsr incsp4 ; clean up stack pla tay pla tax plp bpl ok sty tmp3 ; remember error code lda #CLOSE sta ICCOM,x jsr CIOV ; close IOCB again since open failed jsr fddecusage ; and decrement usage counter of fd lda tmp3 ; put error code into A jmp __mappederrno ok: lda tmp2 ; get fd ldx #0 stx __oserror rts .endproc ; closeallfiles: Close all files opened by the program. .proc closeallfiles lda #MAX_FD_INDEX-1 loop: ldx #0 pha jsr _close pla clc sbc #0 bpl loop rts .endproc �������������������������������cc65-2.18/libsrc/atari/oserrlist.s������������������������������������������������������������������0000664�0000000�0000000�00000007735�13473601511�0017011�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 18.07.2002 ; Christian Groessler, 24.07.2002 ; ; Defines the platform specific error list. ; ; The table is built as a list of entries ; ; .byte entrylen ; .byte errorcode ; .asciiz errormsg ; ; and terminated by an entry with length zero that is returned if the ; error code could not be found. ; .export __sys_oserrlist ;---------------------------------------------------------------------------- ; Macros used to generate the list (may get moved to an include file?) ; Regular entry .macro sys_oserr_entry code, msg .local Start, End Start: .byte End - Start .byte code .asciiz msg End: .endmacro ; Sentinel entry .macro sys_oserr_sentinel msg .byte 0 ; Length is always zero .byte 0 ; Code is unused .asciiz msg .endmacro ;---------------------------------------------------------------------------- ; The error message table .rodata __sys_oserrlist: sys_oserr_entry 1, "no error" sys_oserr_entry 128, "BREAK key abort" sys_oserr_entry 129, "IOCB already open" sys_oserr_entry 130, "device not found" sys_oserr_entry 131, "IOCB write only" sys_oserr_entry 132, "invalid command" sys_oserr_entry 133, "IOCB not open" sys_oserr_entry 134, "invalid IOCB index" sys_oserr_entry 135, "IOCB read only" sys_oserr_entry 136, "end-of-file" sys_oserr_entry 137, "record truncated" sys_oserr_entry 138, "device timeout" sys_oserr_entry 139, "device nak" sys_oserr_entry 140, "SIO frame error" sys_oserr_entry 141, "cursor out of range" sys_oserr_entry 142, "SIO data overrun" sys_oserr_entry 143, "SIO checksum mismatch" sys_oserr_entry 144, "general device failure" sys_oserr_entry 145, "bad screen mode" sys_oserr_entry 146, "invalid function" sys_oserr_entry 147, "insufficient memory for mode" sys_oserr_entry 148, "invalid disk format" sys_oserr_entry 149, "disk format version mismatch" sys_oserr_entry 150, "R: already open/dir not found" sys_oserr_entry 151, "concurrent mode not enabled/file exists" sys_oserr_entry 152, "concurrent mode invalid buffer address/not binary" sys_oserr_entry 153, "concurrent mode enabled" sys_oserr_entry 154, "concurrent mode not active/loader symbol not defined" sys_oserr_entry 156, "invalid parameter" sys_oserr_entry 158, "insufficient memory" sys_oserr_entry 160, "drive number error" sys_oserr_entry 161, "too many open files" sys_oserr_entry 162, "no space left on device" sys_oserr_entry 163, "unrecoverable system data I/O error" sys_oserr_entry 164, "file number mismatch" sys_oserr_entry 165, "invalid file name" sys_oserr_entry 166, "point data length error" sys_oserr_entry 167, "file read-only" sys_oserr_entry 168, "invalid command for disk" sys_oserr_entry 169, "directory full" sys_oserr_entry 170, "file not found" sys_oserr_entry 171, "invalid point command" sys_oserr_entry 172, "already exists in parent directory" sys_oserr_entry 173, "bad disk" sys_oserr_entry 174, "directory not in parent directory" sys_oserr_entry 175, "directory not empty" sys_oserr_entry 176, "invalid disk format" sys_oserr_entry 180, "not a binary file" sys_oserr_entry 181, "invalid address range" sys_oserr_entry 182, "invalid parameter" sys_oserr_sentinel "unknown error" �����������������������������������cc65-2.18/libsrc/atari/oserror.s��������������������������������������������������������������������0000664�0000000�0000000�00000012662�13473601511�0016451�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, May-2000 ; ; os specific error code mapping ; int __fastcall__ _osmaperrno (unsigned char oserror); ; .include "errno.inc" .export __osmaperrno .proc __osmaperrno cmp #$80 ; error or success bcs errcode ; error, jump lda #0 ; no error, return 0 tax rts errcode:and #$7f ; create index from error number tax cpx #MAX_OSERR_VAL ; valid number? bcs inverr ; no lda maptable,x ldx #0 rts inverr: lda #<EUNKNOWN ldx #>EUNKNOWN rts .endproc .rodata maptable: .byte EINTR ;BRKABT = 128 ;($80) BREAK key abort .byte EBUSY ;PRVOPN = 129 ;($81) IOCB already open error .byte ENODEV ;NONDEV = 130 ;($82) nonexistent device error .byte EACCES ;WRONLY = 131 ;($83) IOCB opened for write only error .byte ENOSYS ;NVALID = 132 ;($84) invalid command error .byte EINVAL ;NOTOPN = 133 ;($85) device/file not open error .byte EINVAL ;BADIOC = 134 ;($86) invalid IOCB index error .byte EACCES ;RDONLY = 135 ;($87) IOCB opened for read only error .byte EINVAL ;EOFERR = 136 ;($88) end of file error (should never come, ; specially handled by read.s) .byte EIO ;TRNRCD = 137 ;($89) truncated record error .byte EIO ;TIMOUT = 138 ;($8A) peripheral device timeout error .byte EIO ;DNACK = 139 ;($8B) device does not acknowledge command .byte EIO ;FRMERR = 140 ;($8C) serial bus framing error .byte EINVAL ;CRSROR = 141 ;($8D) cursor out of range error .byte EIO ;OVRRUN = 142 ;($8E) serial bus data overrun error .byte EIO ;CHKERR = 143 ;($8F) serial bus checksum error .byte EIO ;DERROR = 144 ;($90) general device failure .byte EINVAL ;BADMOD = 145 ;($91) bad screen mode number error .byte ENOSYS ;FNCNOT = 146 ;($92) function not implemented in handler .byte ENOMEM ;SCRMEM = 147 ;($93) insufficient memory for screen mode ; codes below taken from "Mein Atari Computer" (german version of "Your Atari Computer") ; also SpartaDOS codes from http://www.atari-central.com/programming/cio_errors.txt ; MyDOS and XDOS codes from Stefan Haubenthal .byte EUNKNOWN ; 148 - [SpartaDOS] unrecognized disk format .byte EUNKNOWN ; 149 - [SpartaDOS] disk created by incompatible version of SD .byte EBUSY ; 150 - serial port already open ; [SpartaDOS] directory not found .byte EACCES ; 151 - concurrent mode I/O not enabled (serial) ; [SpartaDOS] file exists .byte EINVAL ; 152 - invalid buffer address for concurrent mode ; [SpartaDOS] not binary format .byte EAGAIN ; 153 - concurrent mode enabled (and another access tried) .byte EACCES ; 154 - concurrent mode I/O not active (serial) ; [SpartaDOS X] loader symbol not defined .byte EUNKNOWN ; 155 - haven't found documentation .byte EUNKNOWN ; 156 - [SpartaDOS X] bad parameter .byte EUNKNOWN ; 157 - haven't found documentation .byte EUNKNOWN ; 158 - [SpartaDOS X] out of memory .byte EUNKNOWN ; 159 - haven't found documentation .byte ENOENT ; 160 - drive number error (DOS) .byte EMFILE ; 161 - too many open files .byte ENOSPC ; 162 - disk full .byte EIO ; 163 - unrecoverable system data I/O error .byte ESPIPE ; 164 - file number mismatch (inv. seek or disk data strucs damaged) .byte ENOENT ; 165 - invalid file name (e.g. lowercase) .byte ESPIPE ; 166 - point data length error .byte EACCES ; 167 - file locked (read-only) .byte ENOSYS ; 168 - command invalid for disk .byte ENOSPC ; 169 - directory full .byte ENOENT ; 170 - file not found .byte ESPIPE ; 171 - point command invalid .byte EEXIST ; 172 - [MYDOS] already exists in parent directory .byte EUNKNOWN ; 173 - bad disk - format couldn't complete .byte EUNKNOWN ; 174 - [MYDOS] directory not in parent directory .byte EUNKNOWN ; 175 - [MYDOS] directory not empty .byte EUNKNOWN ; 176 - [DOS 3] incompatible file system .byte EUNKNOWN ; 177 - haven't found documentation .byte EUNKNOWN ; 178 - haven't found documentation .byte EUNKNOWN ; 179 - haven't found documentation .byte ENOEXEC ; 180 - not a binary file .byte EUNKNOWN ; 181 - [MYDOS] invalid address range .byte EUNKNOWN ; 182 - [XDOS] invalid parameter .byte EINVAL ; 183 - dummy (used by cc65 rtl, see sysremove.s) MAX_OSERR_VAL = (* - maptable) ������������������������������������������������������������������������������cc65-2.18/libsrc/atari/ostype.s���������������������������������������������������������������������0000664�0000000�0000000�00000006230�13473601511�0016273�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, July 2004 ; from Freddy Offenga's rominfo.c ; ; unsigned char get_ostype(void) ; ; x x x x x x x x - 8 bit flag ; | | | | | | | | ; | | | | | +-+-+-- main OS rev. ; | | +-+-+-------- minor OS rev. ; +-+-------------- unused ; ; main OS rev.: ; 000 - unknown ; 001 - 400/800 ROM ; 010 - 1200XL ROM ; 011 - XL/XE ROM ; 1xx - unassigned ; minor OS rev.: (depending on main OS rev.); ; 400/800: ; 000 - unknown ; 001 - Rev. A PAL ; 010 - Rev. B PAL ; 011 - Rev. A NTSC ; 100 - Rev. B NTSC ; 101 - unassigned (up to 111) ; 1200XL: ; 000 - unknown ; 001 - Rev. 10 ; 010 - Rev. 11 ; 011 - unassigned (up to 111) ; XL/XE: ; 000 - unknown ; 001 - Rev. 1 ; 010 - Rev. 2 ; 011 - Rev. 3 ; 100 - Rev. 4 ; 101 - unassigned (up to 111) ; .export _get_ostype .include "atari.inc" .include "romswitch.inc" .ifdef __ATARIXL__ .import __CHARGEN_START__ .segment "LOWCODE" .macro disable_rom_save_a pha disable_rom pla .endmacro .else ; above atarixl, below atari .macro disable_rom_save_a .endmacro .endif ; .ifdef __ATARIXL__ ; unknown ROM _unknown: lda #0 tax disable_rom_save_a rts _get_ostype: enable_rom lda $fcd8 cmp #$a2 beq _400800 lda $fff1 cmp #1 beq _1200xl lda $fff7 cmp #1 bcc _unknown cmp #5 bcs _unknown ;XL/XE ROM sec asl a asl a asl a and #%00111000 ora #%11 _fin: ldx #0 disable_rom_save_a rts ; 1200XL ROM _1200xl: lda $fff7 ; revision # cmp #10 beq _1200_10 cmp #11 beq _1200_11 lda #0 ; for unknown beq _1200_fin _1200_10: lda #%00001000 bne _1200_fin _1200_11: lda #%00010000 _1200_fin: ora #%010 bne _fin ; 400/800 ROM _400800: lda $fff8 ldx $fff9 cmp #$dd bne _400800_1 cpx #$57 bne _400800_unknown ; 400/800 NTSC Rev. A lda #%00011001 bne _fin ; 400/800 unknown _400800_unknown: lda #%00000001 bne _fin _400800_1: cmp #$d6 bne _400800_2 cpx #$57 bne _400800_unknown ; 400/800 PAL Rev. A lda #%00001001 bne _fin _400800_2: cmp #$f3 bne _400800_3 cpx #$e6 bne _400800_unknown ; 400/800 NTSC Rev. B lda #%00100001 bne _fin _400800_3: cmp #$22 bne _400800_unknown cpx #$58 bne _400800_unknown ; 400/800 PAL Rev. B lda #%00010001 bne _fin ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/posixdirent.s����������������������������������������������������������������0000664�0000000�0000000�00000011141�13473601511�0017315�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; Native: Shawn Jefferson, December 2005 ; POSIX: Stefan Haubenthal, April 2008 .include "atari.inc" .export _opendir, _readdir, _closedir .import findfreeiocb, clriocb .import __oserror, return0, __do_oserror .importzp ptr1, tmp1 .ifdef DEFAULT_DEVICE .import __defdev .endif .proc _opendir sta ptr1 stx ptr1+1 jsr findfreeiocb beq @iocbok bne cioerr @iocbok: stx diriocb jsr clriocb ldx diriocb ldy #0 ; '.' -> "D:*.*" lda (ptr1),y cmp #'.' bne @use_parm ; "." was given as parameter, use default device/dir .ifdef DEFAULT_DEVICE ; construct a "Dn:*.*" like string from the default drive lda __defdev+1 sta dddefdev+1 ; copy drive number (overwrite 2nd 'D') lda #<dddefdev sta ICBAL,x lda #>dddefdev sta ICBAH,x bne @cont .else lda #<defdev sta ICBAL,x lda #>defdev sta ICBAH,x bne @cont .endif @use_parm: lda ptr1 sta ICBAL,x lda ptr1+1 sta ICBAH,x @cont: lda #OPEN sta ICCOM,x lda #OPNIN|DIRECT sta ICAX1,x jsr CIOV bmi cioerr lda #0 sta __oserror tax lda diriocb rts .endproc cioerr: sty __oserror lda #CLOSE sta ICCOM,x jsr CIOV ; close IOCB again since open failed jmp return0 .proc _readdir tax lda #GETREC sta ICCOM,x lda #<entry sta ICBAL,x sta ptr1 lda #>entry sta ICBAH,x sta ptr1+1 lda #DSCTSZ sta ICBLL,x lda #0 sta ICBLH,x jsr CIOV bmi cioerr ldy #0 ; FREE SECTORS lda (ptr1),y cmp #'0' bcs cioerr dey @next: iny ; remove trailing spaces iny iny lda (ptr1),y dey dey sta (ptr1),y cpy #8 bcs @break cmp #' ' bne @next @break: lda #'.' ; extension dot sta (ptr1),y iny ; copy extension sty tmp1 ldy #10 lda (ptr1),y cmp #' ' bne @hasext ; no extension present: remove the trailing dot and be done ldy tmp1 dey bne @done @hasext: jsr copychar ldy #13 ; d_type sta (ptr1),y ldy #11 jsr copychar ldy #12 jsr copychar @done: lda #0 ; end of string sta (ptr1),y lda ptr1 ldx ptr1+1 rts copychar: lda (ptr1),y ; src=y dest=tmp1 ldy tmp1 cmp #' ' beq @break sta (ptr1),y iny sty tmp1 @break: rts .endproc .proc _closedir tax lda #CLOSE sta ICCOM,x jsr CIOV bmi @cioerr ldx #0 stx __oserror ; clear system specific error code txa rts @cioerr: jmp __do_oserror .endproc .data .ifdef DEFAULT_DEVICE dddefdev: .byte "D" .endif defdev: .asciiz "D:*.*" .bss diriocb: .res 1 entry: .res DSCTSZ �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/randomize.s������������������������������������������������������������������0000664�0000000�0000000�00000000657�13473601511�0016747�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, 06.11.2002 ; ; void _randomize (void); ; /* Initialize the random number generator */ ; .export __randomize .import _srand .include "atari.inc" __randomize: ldx VCOUNT ; Use vertical line counter as high byte lda RTCLOK+2 ; Use clock as low byte jmp _srand ; Initialize generator ���������������������������������������������������������������������������������cc65-2.18/libsrc/atari/read.s�����������������������������������������������������������������������0000664�0000000�0000000�00000011033�13473601511�0015660�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, Jul-2005 ; ; int __fastcall__ read(int fd,void *buf,int count) ; .include "atari.inc" .import __rwsetup,__do_oserror,__inviocb,__oserror .export _read _read: jsr __rwsetup ; do common setup for read and write beq done ; if size 0, it's a no-op cpx #$FF ; invalid iocb? beq _inviocb .ifdef LINEBUF ; E: should be always at IOCB #0 ; fixme: what happens when user closes and reopens stdin? cpx #0 ; E: handler (line oriented keyboard input)? beq do_line .endif lda #GETCHR ; iocb command code sta ICCOM,x jsr CIOV ; read it bpl done cpy #EOFERR ; eof is treated specially beq done jmp __do_oserror ; update errno done: lda ICBLL,x ; buf len lo pha ; save lda ICBLH,x ; get buf len hi tax ; to X okdone: lda #0 sta __oserror ; clear system dependend error code pla ; get buf len lo rts _inviocb: jmp __inviocb .ifdef LINEBUF ; line oriented input .segment "EXTZP" : zeropage index: .res 1 ; index into line buffer cbs: .res 1 ; current buffer size: buflen - index dataptr:.res 2 ; temp pointer to user buffer copylen:.res 1 ; temp counter .bss buflen: .res 1 ; length of used part of buffer linebuf:.res LINEBUF ; the line buffer .code do_line: lda buflen ; line buffer active? bne use_buf ; yes, get data from there ; save user buffer address & length ; update IOCB to point to line buffer lda ICBLL,x pha lda #LINEBUF sta ICBLL,x ;-------- lda ICBLH,x pha lda #0 sta ICBLH,x ;-------- lda ICBAL,x pha lda #<linebuf sta ICBAL,x ;-------- lda ICBAH,x pha lda #>linebuf sta ICBAH,x lda #GETREC sta ICCOM,x jsr CIOV ; read input data bpl newbuf cpy #EOFERR ; eof is treated specially beq newbuf pla ; fix stack pla pla pla jmp __do_oserror ; update errno newbuf: lda ICBLL,x ; get # of bytes read sta buflen lda #0 sta index ; fresh buffer ; restore user buffer address & length pla sta ICBAH,x ;-------- pla sta ICBAL,x ;-------- pla sta ICBLH,x ;-------- pla sta ICBLL,x ; fall into use_buf lda buflen ; return bytes from line buffer ; use buflen and index to access buffer ; update index ; use dataptr as a temporary pointer use_buf: sec sbc index ; size of unread data in the buffer sta cbs lda ICBLL,x ; buf len lo cmp cbs ; larger than buffer size? beq bl1 bcs btsmall ; yes, adjust length bl1: lda ICBLH,x ; get buf len hi bne btsmall ; buffer too small: buffer contents < read size ; copy ICBLL,x bytes icbll_copy: lda ICBAL,x ; buffer address sta dataptr lda ICBAH,x ; buffer address sta dataptr+1 lda ICBLL,x sta copylen pha ; remember for return value ldy #0 ldx index copy: lda linebuf,x sta (dataptr),y iny inx dec copylen bne copy pla ; length pha ; save length to return at okdone clc adc index sta index cmp buflen ; buffer used up? bcc c1 ; not yet lda #0 sta buflen ; indicate empty line buffer c1: ldx #0 jmp okdone ; return to caller btsmall: lda cbs sta ICBLL,x bpl icbll_copy .endif ; .ifdef LINEBUF �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/revers.s���������������������������������������������������������������������0000664�0000000�0000000�00000001474�13473601511�0016263�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 07.08.1998 ; ; unsigned char revers (unsigned char onoff); ; .include "atari.inc" .export _revers .export _revflag _revers: ldx #$00 ; Assume revers off tay ; Test onoff beq L1 ; Jump if off ldx #$80 ; Load on value L1: ldy #$00 ; Assume old value is zero lda _revflag ; Load old value stx _revflag ; 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 .bss _revflag: .res 1 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/romswitch.inc����������������������������������������������������������������0000664�0000000�0000000�00000003713�13473601511�0017301�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Macros to disable and enable the ROM on Atari XL systems. ; ; Christian Groessler, chris@groessler.org, 19-Sep-2013 ; ; ; Defines which modify the operation of the macros: ; ; CHARGEN_RELOC: If defined, CHBAS and CHBASE are updated when ; enabling or disabling the ROM. ; If the ROM is enabled, $E0 is written to CHBAS ; and CHBASE. ; If the ROM is disabled, the upper byte of ; __CHARGEN_START__ is written to CHBAS and CHBASE. ; USEWSYNC: If defined, the code waits for horizontal retrace ; before switching the ROM and updating CHBAS and ; CHBASE. This define only has effect if CHARGEN_RELOC ; is also defined. .ifdef __ATARIXL__ .ifdef CHARGEN_RELOC .macro set_chbase val lda #val sta CHBAS sta CHBASE .endmacro .else ; above CHARGEN_RELOC, below not .macro set_chbase val .endmacro .endif ; .ifdef CHARGEN_RELOC .if .defined(USEWSYNC) .and .defined(CHARGEN_RELOC) .macro wsync sta WSYNC .endmacro .else ; above USEWSYNC, below not .macro wsync .endmacro .endif ; "disable ROM" macros .macro disable_rom lda PORTB and #$fe wsync sta PORTB set_chbase >__CHARGEN_START__ .endmacro .macro disable_rom_quick lda PORTB and #$fe sta PORTB set_chbase >__CHARGEN_START__ .endmacro .macro disable_rom_val val lda val wsync sta PORTB set_chbase >__CHARGEN_START__ .endmacro ; "enable ROM" macros .macro enable_rom lda PORTB ora #1 wsync sta PORTB set_chbase $E0 .endmacro .macro enable_rom_quick lda PORTB ora #1 sta PORTB set_chbase $E0 .endmacro .else ; above __ATARIXL__, below not .macro disable_rom .endmacro .macro enable_rom .endmacro .endif �����������������������������������������������������cc65-2.18/libsrc/atari/rwcommon.s�������������������������������������������������������������������0000664�0000000�0000000�00000001762�13473601511�0016616�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; common iocb setup routine for read, write ; expects __fastcall__ parameters (int fd, void *buf, int count) ; .include "atari.inc" .include "errno.inc" .import popax .import fdtoiocb .export __rwsetup __rwsetup: pha ; push size in stack txa pha jsr popax ; get buffer address pha txa pha jsr popax ; get handle jsr fdtoiocb ; convert to iocb bmi iocberr ; negative (X=$FF or A>$7F) on error. tax pla ; store address sta ICBAH,x pla sta ICBAL,x pla ; store length sta ICBLH,x pla sta ICBLL,x ora ICBLH,x ; returns Z if length is 0 rts iocberr:pla pla pla pla ldx #$FF ; indicate error + clear ZF rts ��������������cc65-2.18/libsrc/atari/save_area.inc����������������������������������������������������������������0000664�0000000�0000000�00000000446�13473601511�0017210�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Atari XL, shared data between 2nd load chunk and main chunk, header file ; ; Contains old values of modified system variables and ports. ; ; Christian Groessler, chris@groessler.org, 2013 ; .import SAVMSC_save .import MEMTOP_save .import APPMHI_save .import RAMTOP_save .import PORTB_save ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/save_area.s������������������������������������������������������������������0000664�0000000�0000000�00000001013�13473601511�0016670�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Atari XL, shared data between 2nd load chunk and main chunk, definition file ; ; Contains old values of modified system variables and ports. ; ; Christian Groessler, chris@groessler.org, 2013 ; .ifdef __ATARIXL__ .export SAVMSC_save .export MEMTOP_save .export APPMHI_save .export RAMTOP_save .export PORTB_save .segment "LOWBSS" SAVMSC_save: .res 2 MEMTOP_save: .res 2 APPMHI_save: .res 2 RAMTOP_save: .res 1 PORTB_save: .res 1 .endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/savevec.s��������������������������������������������������������������������0000664�0000000�0000000�00000004027�13473601511�0016406�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; save and restore system vectors ; originally by Mark Keates ; ; void _save_vecs(void); ; void _rest_vecs(void); ; .export __save_vecs,__rest_vecs .include "atari.inc" .bss old_dli: .res 2 old_dlist: .res 2 old_vbi: .res 2 old_vbd: .res 2 old_gra: .res 1 old_dma: .res 1 old_prior: .res 1 old_cols: .res 8 old_set: .res 1 old_rmargin: .res 1 ; lmargin saved in startup code .code .proc __save_vecs lda VDSLST sta old_dli lda VDSLST+1 sta old_dli+1 lda SDLSTL sta old_dlist lda SDLSTL+1 sta old_dlist+1 lda VVBLKI sta old_vbi lda VVBLKI+1 sta old_vbi+1 lda VVBLKD sta old_vbd lda VVBLKD+1 sta old_vbd+1 lda GRACTL sta old_gra lda SDMCTL sta old_dma lda GPRIOR sta old_prior lda CHBAS sta old_set lda RMARGN sta old_rmargin ldy #7 SETUP1: lda PCOLR0,y sta old_cols,y dey bpl SETUP1 rts .endproc .proc __rest_vecs lda #6 ldx old_vbi+1 ldy old_vbi jsr SETVBV lda #7 ldx old_vbd+1 ldy old_vbd jsr SETVBV lda old_dli sta VDSLST lda old_dli+1 sta VDSLST+1 lda old_dlist sta SDLSTL lda old_dlist+1 sta SDLSTL+1 lda old_gra sta GRACTL lda old_prior sta GPRIOR lda old_dma sta SDMCTL lda old_set sta CHBAS lda old_rmargin sta RMARGN lda #$FF sta CH ldy #7 SETUP2: lda old_cols,Y sta PCOLR0,Y dey bpl SETUP2 rts .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/scrdev.s���������������������������������������������������������������������0000664�0000000�0000000�00000000140�13473601511�0016230�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; Name of the "screen" device .export scrdev .rodata scrdev: .byte "S:", 0 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/scroll.s���������������������������������������������������������������������0000664�0000000�0000000�00000006737�13473601511�0016262�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, June 2004 ; ; void __fastcall__ _scroll (signed char numlines); ; numlines > 0 scrolls up ; numlines < 0 scrolls down ; .include "atari.inc" .importzp tmp1,tmp4,ptr1,ptr2 .import _mul40,_clrscr .export __scroll .proc __scroll cmp #0 beq jmpfin ; cmp #$80 ; bcc up bpl up ;scroll down eor #$ff clc adc #1 ; make positive sta tmp1 cmp #24 ; scroll >= the whole screen? bcc down_ok jmp _clrscr down_ok:lda SAVMSC clc adc #<(40*23) sta ptr1 sta ptr2 lda SAVMSC+1 adc #>(40*23) sta ptr1+1 ; point to last line on screen sta ptr2+1 lda tmp1 jsr _mul40 sta tmp4 lda ptr2 sec sbc tmp4 sta ptr2 stx tmp4 lda ptr2+1 sbc tmp4 sta ptr2+1 lda #24 ; # of lines on screen sec sbc tmp1 ; # of lines to move tax ;very simple, could be improved scrold: ldy #39 ; # of chars on a line - 1 copy_d: lda (ptr2),y sta (ptr1),y dey bpl copy_d lda ptr1 sec sbc #40 sta ptr1 bcs u1 dec ptr1+1 u1: lda ptr2 sec sbc #40 sta ptr2 bcs u2 dec ptr2+1 u2: dex bne scrold ; fill new scrolled in lines with space ldx tmp1 ; # of new lines fild: lda #0 ldy #39 fill_d: sta (ptr1),y dey bpl fill_d dex jmpfin: beq finish lda ptr1 sec sbc #40 sta ptr1 bcs u3 dec ptr1+1 u3: jmp fild ;scroll up up: sta tmp1 ; # of lines to scroll cmp #24 ; scroll >= the whole screen? bcc up_ok jmp _clrscr ;multiply by 40 (xsize) up_ok: jsr _mul40 ; carry is cleared by _mul40 adc SAVMSC ; add start of screen mem sta ptr2 txa adc SAVMSC+1 sta ptr2+1 lda SAVMSC+1 sta ptr1+1 lda SAVMSC sta ptr1 lda #24 ; # of lines on screen sec sbc tmp1 ; # of lines to move tax ;very simple, could be improved scroll: ldy #39 ; # of chars on a line - 1 copy_l: lda (ptr2),y sta (ptr1),y dey bpl copy_l lda #40 clc adc ptr1 sta ptr1 bcc l1 inc ptr1+1 l1: lda #40 clc adc ptr2 sta ptr2 bcc l2 inc ptr2+1 l2: dex bne scroll ; fill new scrolled in lines with space ldx tmp1 ; # of new lines fill: lda #0 ldy #39 fill_l: sta (ptr1),y dey bpl fill_l dex beq finish lda #40 clc adc ptr1 sta ptr1 bcc l3 inc ptr1+1 l3: jmp fill finish: rts .endproc ���������������������������������cc65-2.18/libsrc/atari/sdxtime-bss.s����������������������������������������������������������������0000664�0000000�0000000�00000000354�13473601511�0017213�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; .bss variable used by SpartaDOS-X implementations of ; gettime.s and settime.s .export sdxtry .bss sdxtry: .res 1 ; limit of unsuccessful tries to call GETTD/SETTD ; (see settime.s) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/ser/�������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015354�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/ser/atrrdev.s����������������������������������������������������������������0000664�0000000�0000000�00000034243�13473601511�0017215�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, Dec-2001 ; converted to driver interface Dec-2013 ; ; RS232 routines using the R: device (currently tested with an 850 only) ; .include "zeropage.inc" .include "ser-kernel.inc" .include "ser-error.inc" .include "atari.inc" .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table .ifdef __ATARIXL__ module_header _atrxrdev_ser .else module_header _atrrdev_ser .endif ; Driver signature .byte $73, $65, $72 ; "ser" .byte SER_API_VERSION ; Serial API version number ; Library reference libref: .addr $0000 ; Jump table .word SER_INSTALL .word SER_UNINSTALL .word SER_OPEN .word SER_CLOSE .word SER_GET .word SER_PUT .word SER_STATUS .word SER_IOCTL .word SER_IRQ .rodata rdev: .byte "R:", ATEOL, 0 bauds: .byte 1 ; SER_BAUD_45_5 .byte 2 ; SER_BAUD_50 .byte 4 ; SER_BAUD_75 .byte 5 ; SER_BAUD_110 .byte 6 ; SER_BAUD_134_5 .byte 7 ; SER_BAUD_150 .byte 8 ; SER_BAUD_300 .byte 9 ; SER_BAUD_600 .byte 10 ; SER_BAUD_1200 .byte 11 ; SER_BAUD_1800 .byte 12 ; SER_BAUD_2400 .byte 0 ; SER_BAUD_3600 .byte 13 ; SER_BAUD_4800 .byte 0 ; SER_BAUD_7200 .byte 14 ; SER_BAUD_9600 .byte 0 ; SER_BAUD_19200 .byte 0 ; SER_BAUD_38400 .byte 0 ; SER_BAUD_57600 .byte 0 ; SER_BAUD_115200 .byte 0 ; SER_BAUD_230400 .byte 0 ; SER_BAUD_31250 .byte 0 ; SER_BAUD_62500 .byte 3 ; SER_BAUD_56_875 num_bauds = * - bauds databits: .byte 48 ; SER_BITS_5 .byte 32 ; SER_BITS_6 .byte 16 ; SER_BITS_7 .byte 0 ; SER_BITS_8 num_databits = * - databits parities: .byte 0 ; SER_PAR_NONE .byte 4+1 ; SER_PAR_ODD .byte 2+8 ; SER_PAR_EVEN ;.byte 0 ; SER_PAR_MARK ;.byte 0 ; SER_PAR_SPACE num_parities = * - parities .bss ; receive buffer RECVBUF_SZ = 256 recv_buf: .res RECVBUF_SZ cm_run: .res 1 ; concurrent mode running? .data rshand: .word $ffff ; jump table into main program, initialized from libref my_newfd: .byte $4C .word 0 my__close: .byte $4C .word 0 my_pushax: .byte $4C .word 0 my_popax: .byte $4C .word 0 my_findfreeiocb: .byte $4C .word 0 my___do_oserror: .byte $4C .word 0 my_fddecusage: .byte $4C .word 0 my_fdtoiocb: .byte $4C .word 0 my___inviocb: .byte $4C .word 0 my_clriocb: .byte $4C .word 0 my_CIOV: .byte $4C .word 0 .code invbaud: lda #<SER_ERR_BAUD_UNAVAIL ldx #>SER_ERR_BAUD_UNAVAIL openerr: rts ;---------------------------------------------------------------------------- ; SER_OPEN: A pointer to a ser_params structure is passed in ptr1. ; Must return an SER_ERR_xx code in a/x. SER_OPEN: jsr do_open bne openerr ; set line parameters lda rshand ldx #0 jsr my_fdtoiocb ; get iocb index into X bmi openerr ; shouldn't happen tax ; set baud rate, word size, stop bits and ready monitoring ; build ICAX1 value ldy #SER_PARAMS::BAUDRATE lda (ptr1),y cmp #num_bauds bcs invbaud tay lda bauds,y beq invbaud sta ICAX1,x ldy #SER_PARAMS::DATABITS lda (ptr1),y cmp #num_databits bcs init_err tay lda databits,y ora ICAX1,x sta ICAX1,x ldy #SER_PARAMS::STOPBITS lda (ptr1),y clc ror a ror a ora ICAX1,x sta ICAX1,x lda #36 ; xio 36, baud rate sta ICCOM,x lda #0 ;ICAX2 = 0, monitor nothing sta ICAX2,x sta ICBLL,x sta ICBLH,x sta ICBAL,x sta ICBAH,x jsr my_CIOV bmi cioerr ; check if the handshake setting is valid ldy #SER_PARAMS::HANDSHAKE lda (ptr1),y cmp #SER_HS_HW ; this is all we support bne init_err ; set handshake lines lda #34 ; xio 34, set cts, dtr etc sta ICCOM,x lda #192+48+3 ; DTR on, RTS on, XMT on sta ICAX1,x jsr my_CIOV bmi cioerr ; set translation and parity ldy #SER_PARAMS::PARITY lda (ptr1),y cmp #num_parities bcs init_err tay lda parities,y ora #32 ; no translation sta ICAX1,x lda #38 ; xio 38, translation and parity sta ICCOM,x jsr my_CIOV bmi cioerr lda #<SER_ERR_OK tax ; A is zero rts inverr: jmp my___inviocb cioerr: ; @@@ need to close IOCB here jsr my_fddecusage ; decrement usage counter of fd as open failed init_err: ldx #0 lda #SER_ERR_INIT_FAILED rts ;---- open the device do_open: jsr my_findfreeiocb bne init_err txa tay ; move iocb # into Y lda #3 sta tmp3 ; name length + 1 lda #<rdev ldx #>rdev jsr my_newfd tya bcs @doopen ; C set: open needed / device not already open pha jsr SER_CLOSE ;** shut down if started @@@TODO check this out!! pla @doopen:tax pha jsr my_clriocb pla tax lda #<rdev sta ICBAL,x lda #>rdev sta ICBAH,x lda #OPEN sta ICCOM,x lda #$0D ; mode in+out+concurrent sta ICAX1,x lda #0 sta ICAX2,x sta ICBLL,x ; zap buf len sta ICBLH,x jsr my_CIOV bmi cioerr lda tmp2 ; get fd (from newfd) sta rshand ldx #0 stx rshand+1 txa rts ;---------------------------------------------------------------------------- ; CLOSE: Close the port, disable interrupts and flush the buffer. Called ; without parameters. Must return an error code in a/x. ; ;---------------------------------------------------------------------------- ; SER_UNINSTALL routine. Is called before the driver is removed from memory. ; Must return an SER_ERR_xx code in a/x. ; SER_UNINSTALL: SER_CLOSE: lda rshand cmp #$ff beq @done ldx rshand+1 jsr my__close ldx #$ff stx rshand stx rshand+1 inx stx cm_run @done: lda #<SER_ERR_OK ldx #>SER_ERR_OK rts ;---------------------------------------------------------------------------- ; SER_GET: Will fetch a character from the receive buffer and store it into the ; variable pointer to by ptr1. If no data is available, SER_ERR_NO_DATA is ; return. ; SER_GET: ldy rshand cpy #$ff beq ni_err ; work only if initialized lda rshand ldx #0 jsr my_fdtoiocb tax lda cm_run ; concurrent mode already running? bne @go jsr ena_cm ; turn on concurrent mode @go: ; check whether there is any input available lda #STATIS ; status request, returns bytes pending sta ICCOM,x jsr my_CIOV bmi ser_error lda DVSTAT+1 ; get byte count pending ora DVSTAT+2 beq @nix_da ; no input waiting... ; input is available: get it! lda #GETCHR ; get raw bytes sta ICCOM,x ; in command code lda #0 sta ICBLL,x sta ICBLH,x sta ICBAL,x sta ICBAH,x jsr my_CIOV ; go get it bmi ser_error ldx #0 sta (ptr1,x) ; return received byte txa rts @nix_da:lda #SER_ERR_NO_DATA ldx #0 rts ser_error: lda #SER_ERR_OVERFLOW ; there is no large selection of serial error codes... :-/ ldx #0 rts ni_err: lda #SER_ERR_NOT_OPEN ldx #0 rts ;---------------------------------------------------------------------------- ; SER_PUT: Output character in A. ; Must return an error code in a/x. ; SER_PUT: ldy rshand cpy #$ff beq ni_err ; work only if initialized pha ; remember char to write lda rshand ldx #0 jsr my_fdtoiocb tax lda cm_run ; concurrent mode already running? bne @go jsr ena_cm ; turn on concurrent mode ; @@@TODO: check output buffer overflow @go: lda #PUTCHR ; put raw bytes sta ICCOM,x ; in command code lda #0 sta ICBLL,x sta ICBLH,x sta ICBAL,x sta ICBAH,x pla ; get the char back jsr my_CIOV ; go do it bmi ser_error lda #0 tax rts ;---------------------------------------------------------------------------- ; SER_STATUS: Return the status in the variable pointed to by ptr1. ; Must return an error code in a/x. ; SER_STATUS: ; fall through to SER_IOCTL ;---------------------------------------------------------------------------- ; SER_IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl ; specific data in ptr1, and the ioctl code in A. ; Must return an error code in a/x. ; SER_IOCTL: lda #<SER_ERR_INV_IOCTL ; We don't support ioclts for now ldx #>SER_ERR_INV_IOCTL rts ;---------------------------------------------------------------------------- ; SER_IRQ: Not used on the Atari ; SER_IRQ = $0000 ;---------------------------------------------------------------------------- ; SER_INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present. ; Must return an SER_ERR_xx code in a/x. SER_INSTALL: ; check if R: device is installed ldy #0 search: lda HATABS,y ; get device name cmp #'R' beq found iny iny iny cpy #MAXDEV bcc search ; R: device not found, return error lda #<SER_ERR_NO_DEVICE ldx #0 rts ; R: device found, initialize jump table into main program found: lda ptr3 pha lda ptr3+1 pha lda libref sta ptr3 lda libref+1 sta ptr3+1 ldy #0 lda (ptr3),y sta my_newfd+1 iny lda (ptr3),y sta my_newfd+2 iny lda (ptr3),y sta my__close+1 iny lda (ptr3),y sta my__close+2 iny lda (ptr3),y sta my_pushax+1 iny lda (ptr3),y sta my_pushax+2 iny lda (ptr3),y sta my_popax+1 iny lda (ptr3),y sta my_popax+2 iny lda (ptr3),y sta my_findfreeiocb+1 iny lda (ptr3),y sta my_findfreeiocb+2 iny lda (ptr3),y sta my___do_oserror+1 iny lda (ptr3),y sta my___do_oserror+2 iny lda (ptr3),y sta my_fddecusage+1 iny lda (ptr3),y sta my_fddecusage+2 iny lda (ptr3),y sta my_fdtoiocb+1 iny lda (ptr3),y sta my_fdtoiocb+2 iny lda (ptr3),y sta my___inviocb+1 iny lda (ptr3),y sta my___inviocb+2 iny lda (ptr3),y sta my_clriocb+1 iny lda (ptr3),y sta my_clriocb+2 iny lda (ptr3),y sta my_CIOV+1 iny lda (ptr3),y sta my_CIOV+2 ;iny pla sta ptr3+1 pla sta ptr3 lda #<SER_ERR_OK tax ; A is zero rts ; enable concurrent rs232 mode ; gets iocb index in X ; all registers destroyed .proc ena_cm lda #40 ; XIO 40, start concurrent IO sta ICCOM,x sta cm_run ; indicate concurrent mode is running lda #$0D ; value from 850 manual, p62. must be $0D?, sta ICAX1,x ; or any non-zero? lda #0 sta ICAX2,x lda #<recv_buf sta ICBAL,x lda #>recv_buf sta ICBAH,x lda #<RECVBUF_SZ sta ICBLL,x lda #>RECVBUF_SZ sta ICBLH,x jmp my_CIOV .endproc ;ena_cm �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/serref.s���������������������������������������������������������������������0000664�0000000�0000000�00000001334�13473601511�0016236�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, 2014-04-22 ; .include "atari.inc" .export ser_libref .import _close, pushax, popax .import findfreeiocb .import __do_oserror .import fddecusage .import fdtoiocb .import __inviocb .import clriocb .import newfd ser_libref := atari_ser_libref .rodata atari_ser_libref: .word newfd .word _close .word pushax .word popax .word findfreeiocb .word __do_oserror .word fddecusage .word fdtoiocb .word __inviocb .word clriocb .word CIOV ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/setcolor.s�������������������������������������������������������������������0000664�0000000�0000000�00000002067�13473601511�0016606�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, June 2004 ; ; this file provides a color functions similar to BASIC ; ; void __fastcall__ _setcolor (unsigned char color_reg, unsigned char hue, unsigned char luminace); ; void __fastcall__ _setcolor_low (unsigned char color_reg, unsigned char color_value); ; unsigned char __fastcall__ _getcolor (unsigned char color_reg); ; .export __setcolor, __setcolor_low, __getcolor .import popa .include "atari.inc" .proc __getcolor tax lda COLOR0,x ; get current value ldx #0 rts .endproc .proc __setcolor ; asl a ; not -> BASIC compatible sta lum ; remember luminance jsr popa ; get hue asl a asl a asl a asl a ora lum ; jmp __setcolor_low .endproc .proc __setcolor_low pha jsr popa tax pla sta COLOR0,x rts .endproc .bss lum: .res 1 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/setcursor.s������������������������������������������������������������������0000664�0000000�0000000�00000002142�13473601511�0016777�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, November-2002 ; ; cursor handling, internal function .include "atari.inc" .import cursor,_mul40 .export setcursor .proc setcursor ldy #0 lda OLDCHR sta (OLDADR),y lda ROWCRS jsr _mul40 ; function leaves with carry clear! adc SAVMSC ; add start of screen memory sta OLDADR txa adc SAVMSC+1 sta OLDADR+1 lda COLCRS adc OLDADR sta OLDADR bcc nc inc OLDADR+1 nc: lda (OLDADR),y sta OLDCHR ldx cursor ; current cursor setting as requested by the user beq off ldx #0 beq cont off: inx cont: stx CRSINH ; update system variable beq turnon and #$7f ; clear high bit / inverse flag finish: sta (OLDADR),y ; update on-screen display rts turnon: ora #$80 ; set high bit / inverse flag bne finish .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/settime.s��������������������������������������������������������������������0000664�0000000�0000000�00000004726�13473601511�0016432�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 15.08.2018 ; Christian Groessler, 25.09.2018 ; ; int __fastcall__ clock_settime (clockid_t clk_id, const struct timespec *tp); ; .import __dos_type .import incsp1, return0 .import sdxtry .include "time.inc" .include "zeropage.inc" .include "errno.inc" .include "atari.inc" _clock_settime: ; cleanup stack jsr incsp1 ; preserves AX ; only supported on SpartaDOS-X >= 4.40 ldy #SPARTADOS cpy __dos_type bne enosys ldy SDX_VERSION cpy #$44 bcc enosys ; create tm from tp (tv_sec) input parameter .assert timespec::tv_sec = 0, error jsr _localtime sta ptr1 stx ptr1+1 ; set date ldy #tm::tm_mday lda (ptr1),y ; get day of month sta SDX_DATE ; set day of month ldy #tm::tm_mon lda (ptr1),y ; get month (0-based) tax inx ; move [0..11] to [1..12] stx SDX_DATE+1 ldy #tm::tm_year lda (ptr1),y ; get year (0 = year 1900) cmp #100 bcc :+ sbc #100 : sta SDX_DATE+2 ldy #tm::tm_hour lda (ptr1),y ; get hour sta SDX_TIME ldy #tm::tm_min lda (ptr1),y ; get minutes sta SDX_TIME+1 ldy #tm::tm_sec lda (ptr1),y ; get seconds sta SDX_TIME+2 ; set new time/date (SD-X call) ; SpartaDOS-X User's Guide (4.48) states at page 145: ; "In the I_GETTD and I_SETTD procedures a set Carry-Flag means that the clock driver is ; busy at the moment. You should call the routine again." ; It goes on to mention that one should provide an upper limit on the number of calls, ; in order not to "hang". We are doing this here... lda #0 ; init loop count (256) sta sdxtry try_set:lda #SDX_CLK_DEV ; CLK device sta SDX_DEVICE ldy #SDX_KD_SETTD ; SETTD function jsr SDX_KERNEL ; do the call bcc done dec sdxtry bne try_set lda #EBUSY bne drcter ; jump always ; return success done: jmp return0 ; load errno code enosys: lda #ENOSYS drcter: jmp __directerrno ������������������������������������������cc65-2.18/libsrc/atari/shadow_ram_handlers.s��������������������������������������������������������0000664�0000000�0000000�00000061723�13473601511�0020764�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Atari XL shadow RAM handlers ; ; Christian Groessler, chris@groessler.org, 2013 ; ;DEBUG = 1 CHKBUF = 1 ; check if bounce buffering is needed (bounce buffering is always done if set to 0) .ifdef __ATARIXL__ SHRAM_HANDLERS = 1 .include "atari.inc" .include "save_area.inc" .include "zeropage.inc" .include "romswitch.inc" .import __CHARGEN_START__ .export sram_init .export KEYBDV_handler .export CIO_handler .export SIO_handler .export SETVBV_handler .export XMOVE_handler BUFSZ = 128 ; bounce buffer size BUFSZ_SIO = 256 .segment "ONCE" ; Turn off ROMs, install system and interrupt wrappers, set new chargen pointer sram_init: ; disable all interrupts ldx #0 stx NMIEN ; disable NMI sei ; disable ROMs disable_rom ; setup interrupt vectors lda #<my_IRQ_han sta $fffe lda #>my_IRQ_han sta $ffff lda #<my_RESET_han sta $fffc lda #>my_RESET_han sta $fffd lda #<my_NMI_han sta $fffa lda #>my_NMI_han sta $fffb ; enable interrupts cli lda #$40 sta NMIEN rts .segment "EXTZP" : zeropage zpptr1: .res 2 .segment "LOWBSS" ; bounce buffers for CIO and SIO calls bounce_buffer: .res BUFSZ_SIO .segment "LOWCODE" ; Interrupt handlers ; ------------------ ; The interrupt handlers don't look at the current state of PORTB and ; unconditionally disable the ROMs on exit. ; Please note that this works, since if the ROMs are enabled we anyway ; aren't being called here because the vectors are pointing to their ; original ROM locations. .macro int_wrap orgvec .local ret pha enable_rom_quick lda #>ret pha lda #<ret pha php jmp (orgvec) ret: disable_rom_quick pla rti .endmacro my_IRQ_han: .ifdef DEBUG php pha tya pha ldy #0 lda (SAVMSC),y clc adc #1 sta (SAVMSC),y pla tay pla plp .endif int_wrap $FFFE my_NMI_han: .ifdef DEBUG php pha tya pha ldy #39 lda (SAVMSC),y clc adc #1 sta (SAVMSC),y pla tay pla plp .endif ; set I bit to interrupted value pha txa pha tsx lda $103,x pha plp pla tax pla int_wrap $FFFA my_RESET_han: enable_rom jmp ($FFFC) ; System request handlers ; ----------------------- ; for filenames we assume they will fit into our bounce buffer ; one filename, terminated by "invalid character", located at ICBAL/ICBAH CIO_filename: .if CHKBUF jsr chk_CIO_buf_fn bcc CIO_call_a .endif jsr setup_zpptr1_y0 jsr copy_filename CIO_fn_cont: jsr bncbuf_to_iocb ldy CIO_y jsr CIO_call_a ; call CIO (maybe A isn't needed, then we could call CIO_call) php pha jsr restore_icba ; restore original ICBAL/ICBAH pla plp rts ; back to application ; two filenames, terminated and separated by "invalid character", located at ICBAL/ICBAH CIO_filename2: .if CHKBUF jsr chk_CIO_buf_fn2 bcc CIO_call_a .endif jsr setup_zpptr1_y0 jsr copy_filename iny jsr copy_filename jmp CIO_fn_cont ; CIO handler ; We have buffer pointer and length entries in the IOCB, but their ; usage depends on the function. ; Some functions don't care about any of them (pointer and length), ; and some only use the pointer (like e.g. OPEN), and some use both. ; So we need function specific handlers to correctly deal with ; buffers which are overlapping with the ROM area. ; ; FIXME: Currently only the requests used by the runtime lib are handled. CIO_handler: ; @@@ TODO: check X for valid IOCB index ((X < $80) and ((X & $F) == 0)) sta CIO_a sty CIO_y stx CIO_x lda ICCOM,x ; get function cmp #OPEN beq CIO_filename ; filename as input parameter in buffer, length not used cmp #PUTREC bcc CIO_read ; input (GETREC or GETCHR) cmp #CLOSE bcc CIO_write_jmp ; output (PUTREC or PUTCHR) beq CIO_call_a ; pass through, buffer not used cmp #RENAME ; 2 filenames as input parameters in buffer, length not used beq CIO_filename2 cmp #GETCWD bcc CIO_filename ; filename as input parameter in buffer, length not used beq CIO_invalid ; GETCWD not supported yet bcs CIO_call_a ; other commands: assume no buffer ; not reached ; enable ROM, call CIO, disable ROM CIO_call_a: lda CIO_a CIOV_call: pha lda PORTB sta cur_CIOV_PORTB enable_rom pla jsr CIOV_org php pha disable_rom_val cur_CIOV_PORTB pla plp rts CIO_write_jmp: jmp CIO_write CIO_invalid: lda CIO_a ldy #DINVCM rts ; READ handler ; ------------ CIO_read: lda ICBLL,x ora ICBLH,x beq CIO_call_a ; special I/O through A register in case buffer length is 0 .if CHKBUF jsr chk_CIO_buf bcc CIO_call_a .endif ; If the data length is larger than our bounce buffer, we have to split the request into smaller ones. ; Otherwise we can get away with one call and a copy to the final destination afterwards. lda ICBLH,x ; get high byte of length bne big_read ; not zero -> data too large for our buffers ; CHANGE HERE TO SUPPORT BOUNCE BUFFERS > 255 BYTES lda #<BUFSZ cmp ICBLL,x bcc big_read ; Data size fits into bounce buffer jsr setup_zpptr1 jsr bncbuf_to_iocb jsr CIO_call_a ; call CIO php bpl @no_err cpy #EOFERR beq @no_err pha jsr restore_icba pla plp rts ; return with error @no_err: sta CIO_a sty CIO_y jsr copy_to_user ; copy data into user buffer jsr restore_icba lda CIO_a ldy CIO_y plp rts ; return with success ; Data size does not fit into bounce buffer big_read: lda #0 sta retlen ; initialize return length sta retlen+1 jsr iocblen_to_orig_len jsr iocbptr_to_orig_ptr jsr setup_zpptr1 jsr bncbuf_to_iocb ; let ICBAL/ICBAH point to bounce buffer br_loop: jsr cmp_orig_len_bnc_bufsz ; is transfer length > bounce buffer size? bcs br_last ; no, last transfer, use remaining size lda #>BUFSZ sta ICBLH,x ; set data length lda #<BUFSZ sta ICBLL,x bne br_cont br_last: lda orig_len+1 sta ICBLH,x ; set data length lda orig_len sta ICBLL,x br_cont: sta req_len ; remember length of this request lda ICBLH,x sta req_len+1 jsr CIO_call_a ; do the request php bpl br_no_err cpy #EOFERR beq br_no_err pha jsr restore_icba pla plp rts ; return with error br_no_err: sta CIO_a sty CIO_y pla sta CIO_p jsr copy_to_user ; update retlen clc lda retlen adc ICBLL,x sta retlen lda retlen+1 adc #0 sta retlen+1 ; if the request read less bytes than requested, we're done lda ICBLL,x cmp req_len bne br_done lda ICBLH,x cmp req_len+1 bne br_done ; update user buffer pointer (zpptr1) clc lda zpptr1 adc ICBLL,x sta zpptr1 lda zpptr1+1 adc #0 sta zpptr1+1 ; update remaining length sec lda orig_len sbc ICBLL,x sta orig_len lda orig_len+1 sbc #0 sta orig_len+1 ; still something left to do (remaining length != 0)? lda orig_len ora orig_len+1 beq br_done jmp br_loop ; done, write original buffer pointer and total transfer length to IOCB and return to application br_done: lda retlen sta ICBLL,x lda retlen+1 sta ICBLH,x jsr orig_ptr_to_iocbptr lda CIO_p pha lda CIO_a ldy CIO_y plp rts ; return with success CIO_call_a_jmp: jmp CIO_call_a ; WRITE handler ; ------------- CIO_write: lda ICBLL,x ora ICBLH,x beq CIO_call_a_jmp ; special I/O through A register in case buffer length is 0 .if CHKBUF jsr chk_CIO_buf bcc CIO_call_a_jmp .endif ; If the data length is larger than our bounce buffer, we have to split the request into smaller ones. ; Otherwise we can get away with a copy to the bounce buffer and the call. lda ICBLH,x ; get high byte of length bne big_write ; not zero -> data too large for our buffers ; CHANGE HERE TO SUPPORT BOUNCE BUFFERS > 255 BYTES lda #<BUFSZ cmp ICBLL,x bcc big_write ; Data size fits into bounce buffer jsr setup_zpptr1 jsr bncbuf_to_iocb jsr copy_from_user ldy CIO_y jsr CIO_call_a php pha jsr restore_icba pla plp rts ; return to application ; Data size does not fit into bounce buffer big_write: lda #0 sta retlen ; initialize return length sta retlen+1 jsr iocblen_to_orig_len jsr iocbptr_to_orig_ptr jsr setup_zpptr1 jsr bncbuf_to_iocb ; let ICBAL/ICBAH point to bounce buffer bw_loop: jsr cmp_orig_len_bnc_bufsz ; is transfer length > bounce buffer size? bcs bw_last ; no, last transfer, use remaining size lda #>BUFSZ sta ICBLH,x ; set data length lda #<BUFSZ sta ICBLL,x bne bw_cont bw_last: lda orig_len+1 sta ICBLH,x ; set data length lda orig_len sta ICBLL,x bw_cont: sta req_len ; remember length of this request lda ICBLH,x sta req_len+1 jsr copy_from_user jsr CIO_call_a ; do the request php bpl bw_no_err plp rts ; error return bw_no_err: sta CIO_a sty CIO_y pla sta CIO_p ; update retlen clc lda retlen adc ICBLL,x sta retlen lda retlen+1 adc #0 sta retlen+1 ; if the request wrote less bytes than requested, we're done lda ICBLL,x cmp req_len bne bw_done lda ICBLH,x cmp req_len+1 bne bw_done ; update user buffer pointer (zpptr1) clc lda zpptr1 adc ICBLL,x sta zpptr1 lda zpptr1+1 adc #0 sta zpptr1+1 ; update remaining length sec lda orig_len sbc ICBLL,x sta orig_len lda orig_len+1 sbc #0 sta orig_len+1 ; still something left to do (remaining length != 0)? lda orig_len ora orig_len+1 beq bw_done jmp bw_loop bw_done: lda retlen sta ICBLL,x lda retlen+1 sta ICBLH,x jsr orig_ptr_to_iocbptr lda CIO_p pha lda CIO_a ldy CIO_y plp rts ; return with success ; check if length is larger than bounce buffer size ; input: orig_len - length ; output: A - destroyed ; CF - 0/1 for larger/not larger cmp_orig_len_bnc_bufsz: sec lda #<BUFSZ sbc orig_len lda #>BUFSZ sbc orig_len+1 rts ; copy data from bounce buffer into user buffer ; input: X - IOCB index ; zpptr1 - pointer to user buffer ; output: A - destroyed ; Y - 0 copy_to_user: ldy ICBLL,x ; get # of bytes read (CHANGE HERE TO SUPPORT BOUNCE BUFFERS > 255 BYTES) beq @copy_done @copy: dey lda bounce_buffer,y sta (zpptr1),y cpy #0 bne @copy @copy_done: rts ; copy data from user buffer into bounce buffer ; input: X - IOCB index ; zpptr1 - pointer to user buffer ; output: A - destroyed ; Y - 0 copy_from_user: ldy ICBLL,x ; get # of bytes to write (CHANGE HERE TO SUPPORT BOUNCE BUFFERS > 255 BYTES) beq @copy_done @copy: dey lda (zpptr1),y sta bounce_buffer,y cpy #0 bne @copy @copy_done: rts ; copy ICBLL/ICBLH to 'orig_len' ; input: X - IOCB index ; output: A - destroyed iocblen_to_orig_len: lda ICBLL,x sta orig_len lda ICBLH,x sta orig_len+1 rts ; copy ICBAL/ICBAH to 'orig_ptr' ; input: X - IOCB index ; output: A - destroyed iocbptr_to_orig_ptr: lda ICBAL,x sta orig_ptr lda ICBAH,x sta orig_ptr+1 rts ; copy 'orig_ptr' to ICBAL/ICBAH ; input: X - IOCB index ; output: A - destroyed orig_ptr_to_iocbptr: lda orig_ptr sta ICBAL,x lda orig_ptr+1 sta ICBAH,x rts ; restore original contents of ICBAL/ICBAH from 'zpptr1' ; input: X - IOCB index ; output: A - destroyed restore_icba: lda zpptr1 sta ICBAL,x lda zpptr1+1 sta ICBAH,x rts ; put bounce buffer address into ICBAL/ICBAH ; input: X - IOCB index ; output: A - destroyed bncbuf_to_iocb: lda #<bounce_buffer sta ICBAL,x lda #>bounce_buffer sta ICBAH,x rts ; copy file name pointed to by 'zpptr1' to 'bounce_buffer' ; input: Y - index into file name buffer and bounce_buffer ; output: Y - points to first invalid byte after file name ; A - destroyed copy_filename: lda (zpptr1),y sta bounce_buffer,y beq copy_fn_done iny cmp #ATEOL bne copy_filename dey copy_fn_done: rts ; write IOCB buffer address into zpptr1 ; input: X - IOCB index ; output: Y - 0 (for setup_zpptr1_y0, else unchanged) ; A - destroyed setup_zpptr1_y0: ldy #0 setup_zpptr1: lda ICBAL,x ; put buffer address into zp pointer sta zpptr1 lda ICBAH,x sta zpptr1+1 rts .if CHKBUF ; get length of file name pointed to by 'zpptr1' ; input: Y - index into file name ; output: Y - length ; A - destroyed get_fn_len: lda (zpptr1),y beq @done iny cmp #ATEOL bne get_fn_len dey @done: rts chk_CIO_buf_fn2: tya pha lda ICBLL,x pha lda ICBLH,x pha jsr setup_zpptr1_y0 jsr get_fn_len iny ; include terminating zero bne fn_cont chk_CIO_buf_fn: tya pha lda ICBLL,x pha lda ICBLH,x pha jsr setup_zpptr1_y0 fn_cont:jsr get_fn_len iny ; include terminating zero tya sta ICBLL,x lda #0 sta ICBLH,x jsr chk_CIO_buf pla sta ICBLH,x pla sta ICBLL,x pla tay rts ; check if a CIO input/output buffer overlaps with ROM area (>= $C000) ; input: X - IOCB index ; ICBAL/ICBAH/ICBLL/ICBLH - buffer address and length ; output: CF - 1/0 for overlap/no overlap ; A - destroyed chk_CIO_buf: lda ICBAH,x cmp #$c0 bcc @cont @ret: .ifdef DEBUG jsr CIO_buf_noti .endif rts @cont: lda ICBAL,x clc adc ICBLL,x lda ICBAH,x adc ICBLH,x bcs @ret ; ??? wraparound cmp #$c0 .ifdef DEBUG jsr CIO_buf_noti .endif rts .ifdef DEBUG ; write to screen memory on 2nd line: ; pos 0: # of accesses without buffering ; pos 1: # of accesses with buffering CIO_buf_noti: php pha tya pha bcc @nobuf inc CIObnval_dobuf jmp @cont @nobuf: inc CIObnval_nobuf @cont: ldy #40 lda CIObnval_nobuf sta (SAVMSC),y ldy #41 lda CIObnval_dobuf sta (SAVMSC),y pla tay pla plp rts CIObnval_dobuf: .byte 0 CIObnval_nobuf: .byte 0 .endif .endif ; .if CHKBUF ;--------------------------------------------------------- ; SIO handler ; We only handle SIO_STAT, SIO_READ, SIO_WRITE, and SIO_WRITEV. ; These are the only functions used by the runtime library currently. ; For other function we return NVALID status code. SIO_handler: lda DCOMND ; get command cmp #SIO_STAT beq SIO_stat cmp #SIO_READ beq SIO_read cmp #SIO_WRITE beq SIO_write cmp #SIO_WRITEV beq SIO_write ; unhandled command lda #NVALID SIO_err:sta DSTATS rts ; SIO_STAT is always called with a low buffer (by the runtime) SIO_stat: ; fall thru SIO_call: lda PORTB sta cur_SIOV_PORTB enable_rom jsr SIOV_org php pha disable_rom_val cur_SIOV_PORTB pla plp rts ; SIO read handler ; ---------------- SIO_read: .if CHKBUF jsr chk_SIO_buf bcc SIO_call .endif ; we only support transfers <= bounce buffer size jsr cmp_sio_len_bnc_bufsz bcs sio_read_len_ok lda #DERROR ; don't know a better status code for this bne SIO_err sio_read_len_ok: lda DBUFLO sta zpptr1 ; remember destination buffer address lda DBUFHI sta zpptr1+1 jsr bncbuf_to_dbuf ; put bounce buffer address to DBUFLO/DBUFHI jsr SIO_call ; do the operation pha lda DSTATS ; get status bmi sio_read_ret ; error ; copy data to user buffer sio_read_ok: lda DBYTHI ; could be 1 for 256 bytes beq srok1 ldy #0 beq srok2 srok1: ldy DBYTLO srok2: dey sio_read_copy: lda bounce_buffer,y sta (zpptr1),y dey cpy #$ff bne sio_read_copy sio_read_ret: jsr orgbuf_to_dbuf pla rts ; success return ; SIO write handler ; ----------------- SIO_write: .if CHKBUF jsr chk_SIO_buf bcc SIO_call .endif ; we only support transfers <= bounce buffer size jsr cmp_sio_len_bnc_bufsz bcs sio_write_len_ok lda #DERROR ; don't know a better status code for this jmp SIO_err sio_write_len_ok: lda DBUFLO sta zpptr1 ; get source buffer address lda DBUFHI sta zpptr1+1 ; copy data from user buffer to bounce buffer lda DBYTHI ; could be 1 for 256 bytes beq swok1 ldy #0 beq swok2 swok1: ldy DBYTLO swok2: dey sio_write_copy: lda (zpptr1),y sta bounce_buffer,y dey cpy #$ff bne sio_write_copy jsr bncbuf_to_dbuf ; put bounce buffer address to DBUFLO/DBUFHI jsr SIO_call ; do the operation pha jsr orgbuf_to_dbuf pla rts ; check if SIO length is larger than bounce buffer size ; input: orig_len - length ; output: A - destroyed ; CF - 0/1 for larger/not larger cmp_sio_len_bnc_bufsz: sec lda #<BUFSZ_SIO sbc DBYTLO lda #>BUFSZ_SIO sbc DBYTHI rts ; put bounce buffer address into DBUFLO/DBUFHI ; input: (--) ; output: A - destroyed bncbuf_to_dbuf: lda #<bounce_buffer sta DBUFLO lda #>bounce_buffer sta DBUFHI rts ; put original buffer address into DBUFLO/DBUFHI ; input: zpptr1 - original pointer ; output: A - destroyed orgbuf_to_dbuf: lda zpptr1 sta DBUFLO lda zpptr1+1 sta DBUFHI rts .if CHKBUF ; check if a SIO input/output buffer overlaps with ROM area (>= $C000) ; input: DBUFLO/DBUFHI/DBYTLO/DBYTHI - buffer address and length ; output: CF - 1/0 for overlap/no overlap ; A - destroyed chk_SIO_buf: lda DBUFHI cmp #$c0 bcc @cont @ret: .ifdef DEBUG jsr SIO_buf_noti .endif rts @cont: lda DBUFLO clc adc DBYTLO lda DBUFHI adc DBYTHI bcs @ret ; ??? wraparound cmp #$c0 .ifdef DEBUG jsr SIO_buf_noti .endif rts .ifdef DEBUG ; write to screen memory on 2nd line: ; pos 38: # of accesses without buffering ; pos 39: # of accesses with buffering SIO_buf_noti: php pha tya pha bcc @nobuf inc SIObnval_dobuf jmp @cont @nobuf: inc SIObnval_nobuf @cont: ldy #78 lda SIObnval_nobuf sta (SAVMSC),y ldy #79 lda SIObnval_dobuf sta (SAVMSC),y pla tay pla plp rts SIObnval_dobuf: .byte 0 SIObnval_nobuf: .byte 0 .endif .endif ; .if CHKBUF ;--------------------------------------------------------- KEYBDV_handler: lda #>(kret-1) pha lda #<(kret-1) pha lda PORTB sta cur_KEYBDV_PORTB enable_rom lda KEYBDV+5 pha lda KEYBDV+4 pha rts ; call keyboard handler kret: pha disable_rom_val cur_KEYBDV_PORTB pla rts ;--------------------------------------------------------- SETVBV_handler: pha lda PORTB sta cur_SETVBV_PORTB enable_rom pla jsr SETVBV_org php pha disable_rom_val cur_SETVBV_PORTB pla plp rts ;--------------------------------------------------------- XMOVE_handler: pha lda PORTB sta cur_XMOVE_PORTB enable_rom pla jsr XMOVE_org php pha disable_rom_val cur_XMOVE_PORTB pla plp rts CIO_a: .res 1 CIO_x: .res 1 CIO_y: .res 1 CIO_p: .res 1 cur_CIOV_PORTB: .res 1 cur_SIOV_PORTB: .res 1 cur_KEYBDV_PORTB: .res 1 cur_SETVBV_PORTB: .res 1 cur_XMOVE_PORTB: .res 1 orig_ptr: .res 2 orig_len: .res 2 req_len: .res 2 retlen: .res 2 .endif ; .ifdef __ATARIXL__ ���������������������������������������������cc65-2.18/libsrc/atari/shadow_ram_prepare.s���������������������������������������������������������0000664�0000000�0000000�00000022752�13473601511�0020621�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Atari XL shadow RAM preparation routines ; ; Tasks: ; - move screen memory below load address ; - copy ROM chargen to its new place ; - copy shadow RAM contents to their destination ; ; Christian Groessler, chris@groessler.org, 2013 ; ;DEBUG = 1 .ifdef __ATARIXL__ .export sramprep .import __SRPREP_LOAD__, __SRPREPCHNK_LAST__ .import __SHADOW_RAM_LOAD__, __SHADOW_RAM_SIZE__, __SHADOW_RAM_RUN__ .import __SHADOW_RAM2_LOAD__, __SHADOW_RAM2_SIZE__, __SHADOW_RAM2_RUN__ .import __CHARGEN_START__, __CHARGEN_SIZE__ .import __STARTADDRESS__ ; needed by xlmemchk.inc .include "zeropage.inc" .include "atari.inc" .include "save_area.inc" .macro print_string text .local start, cont jmp cont start: .byte text, ATEOL cont: ldx #0 ; channel 0 lda #<start sta ICBAL,x ; address lda #>start sta ICBAH,x lda #<(cont - start) sta ICBLL,x ; length lda #>(cont - start) sta ICBLH,x lda #PUTCHR sta ICCOM,x jsr CIOV_org .endmacro ; ------------------------------------------------------------------------ ; EXE load chunk header .segment "SRPREPHDR" .word __SRPREP_LOAD__ .word __SRPREPCHNK_LAST__ - 1 ; ------------------------------------------------------------------------ ; Actual code .segment "SRPREP" ; ***** entry point ***** sramprep: .ifdef DEBUG print_string "entering stage #2" .endif ; save values of modified system variables and ports lda RAMTOP sta RAMTOP_save lda MEMTOP sta MEMTOP_save lda MEMTOP+1 sta MEMTOP_save+1 lda APPMHI sta APPMHI_save lda APPMHI+1 sta APPMHI_save+1 lda PORTB sta PORTB_save ; disable BASIC lda PORTB ora #2 sta PORTB .include "xlmemchk.inc" ; calculate lowest address used and new value for RAMTOP ldx lowadr stx MEMTOP lda lowadr+1 sta MEMTOP+1 lda lodadr+1 sta RAMTOP ; set APPMHI to MEMLO (+ 1 for sanity) lda MEMLO clc adc #1 sta APPMHI lda MEMLO+1 adc #0 sta APPMHI+1 ; issue a GRAPHICS 0 call (copied'n'pasted from TGI drivers) to move screen memory down jsr findfreeiocb .ifdef DEBUG ; only check in debug version, this shouldn't really happen(tm) beq iocbok print_string "Internal error, no free IOCB!" jsr delay jsr delay jsr delay jsr restore ; restore stuff we've changed jmp (DOSVEC) ; abort loading iocbok: .endif ; reopen it in Graphics 0 lda #OPEN sta ICCOM,x lda #OPNIN | OPNOT sta ICAX1,x lda #0 sta ICAX2,x lda #<screen_device sta ICBAL,x lda #>screen_device sta ICBAH,x lda #<screen_device_length sta ICBLL,x lda #>screen_device_length sta ICBLH,x jsr CIOV_org bpl scrok ; shouldn't happen(tm) print_string "Internal error, aborting..." jsr delay jsr delay jsr delay jsr restore ; restore stuff we've changed jmp (DOSVEC) ; abort loading scrok: ; now close it again -- we don't need it anymore lda #CLOSE sta ICCOM,x jsr CIOV_org ; copy chargen to low memory, just after the next possible address beyond our loaded chunk data .ifdef DEBUG print_string "copy chargen to low memory" .endif lda #>__SRPREPCHNK_LAST__ sta ptr3+1 lda #<__SRPREPCHNK_LAST__ sta ptr3 beq cg_addr_ok ; page align the new chargen address inc ptr3+1 lda #0 sta ptr3 cg_addr_ok: lda ptr3+1 and #3 beq cg_addr_ok2 ; align to next 1K boundary lda ptr3+1 and #$fc clc adc #4 sta ptr3+1 cg_addr_ok2: lda #<DCSORG sta ptr1 lda #>DCSORG sta ptr1+1 lda ptr3 sta ptr2 lda ptr3+1 pha ; needed later to set CHBAS/CHBASE sta ptr2+1 lda #>__CHARGEN_SIZE__ sta tmp2 lda #<__CHARGEN_SIZE__ sta tmp1 jsr memcopy .ifdef DEBUG print_string "now setting up high memory" .endif ; disable ROM sei ldx #0 stx NMIEN ; disable NMI lda PORTB and #$fe tax pla ; get temp. chargen address sta WSYNC ; wait for horiz. retrace stx PORTB ; now ROM is mapped out ; switch to temporary chargen sta CHBASE sta CHBAS ; copy shadow RAM contents to their destination (segment SHADOW_RAM) lda #<__SHADOW_RAM_SIZE__ bne do_copy lda #>__SHADOW_RAM_SIZE__ beq no_copy ; we have no shadow RAM contents ; ptr1 - src; ptr2 - dest; tmp1, tmp2 - len do_copy:lda #<__SHADOW_RAM_LOAD__ sta ptr1 lda #>__SHADOW_RAM_LOAD__ sta ptr1+1 lda #<__SHADOW_RAM_RUN__ sta ptr2 lda #>__SHADOW_RAM_RUN__ sta ptr2+1 lda #<__SHADOW_RAM_SIZE__ sta tmp1 lda #>__SHADOW_RAM_SIZE__ sta tmp2 jsr memcopy no_copy: ; copy shadow RAM #2 contents to their destination (segment SHADOW_RAM2) lda #<__SHADOW_RAM2_SIZE__ bne do_copy2 lda #>__SHADOW_RAM2_SIZE__ beq no_copy2 ; we have no shadow RAM #2 contents ; ptr1 - src; ptr2 - dest; tmp1, tmp2 - len do_copy2: lda #<__SHADOW_RAM2_LOAD__ sta ptr1 lda #>__SHADOW_RAM2_LOAD__ sta ptr1+1 lda #<__SHADOW_RAM2_RUN__ sta ptr2 lda #>__SHADOW_RAM2_RUN__ sta ptr2+1 lda #<__SHADOW_RAM2_SIZE__ sta tmp1 lda #>__SHADOW_RAM2_SIZE__ sta tmp2 jsr memcopy no_copy2: ; copy chargen to its new (final) location lda ptr3 sta ptr1 lda ptr3+1 sta ptr1+1 lda #<__CHARGEN_START__ sta ptr2 lda #>__CHARGEN_START__ sta ptr2+1 lda #>__CHARGEN_SIZE__ sta tmp2 lda #<__CHARGEN_SIZE__ sta tmp1 jsr memcopy ; re-enable ROM lda PORTB ora #1 ldx #>DCSORG sta WSYNC ; wait for horiz. retrace sta PORTB stx CHBASE stx CHBAS lda #$40 sta NMIEN ; enable VB again cli ; and enable IRQs .ifdef DEBUG print_string "Stage #2 OK" print_string "loading main chunk" jsr delay .endif rts .include "findfreeiocb.inc" ; routine taken from http://www.obelisk.demon.co.uk/6502/algorithms.html ; ; copy memory ; ptr1 - source ; ptr2 - destination ; tmp2:tmp1 - len .proc memcopy ldy #0 ldx tmp2 beq last pagecp: lda (ptr1),y sta (ptr2),y iny bne pagecp inc ptr1+1 inc ptr2+1 dex bne pagecp last: cpy tmp1 beq done lda (ptr1),y sta (ptr2),y iny bne last done: rts .endproc ; clean up after a fatal error restore:lda RAMTOP_save sta RAMTOP lda MEMTOP_save sta MEMTOP lda MEMTOP_save+1 sta MEMTOP+1 lda APPMHI_save sta APPMHI lda APPMHI_save+1 sta APPMHI+1 rts ; short delay .proc delay lda #10 @loop: jsr delay1 clc sbc #0 bne @loop rts delay1: ldx #0 ldy #0 @loop: dey bne @loop dex bne @loop rts .endproc .ifdef DEBUG .byte "HERE ****************** HERE ***************>>>>>>" sramsize: .word __SHADOW_RAM_SIZE__ .endif ; .ifdef DEBUG screen_device: .byte "S:",0 screen_device_length = * - screen_device .ifdef DEBUG .byte " ** srprep ** end-->" .endif ; ------------------------------------------------------------------------ ; Provide empty SHADOW_RAM and SHADOW_RAM2 segments in order that the ; linker is happy if the user program doesn't have these segments. .segment "SHADOW_RAM" .segment "SHADOW_RAM2" ; ------------------------------------------------------------------------ ; EXE load chunk "trailer" - sets INITAD .segment "SRPREPTRL" .word INITAD .word INITAD+1 .word sramprep .endif ; .ifdef __ATARIXL__ ����������������������cc65-2.18/libsrc/atari/shadow_ram_timerirq1.s�������������������������������������������������������0000664�0000000�0000000�00000003414�13473601511�0021072�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Atari XL shadow RAM timer IRQ #1 handler ; ; Christian Groessler, chris@groessler.org, 2014 ; ;DEBUG = 1 .ifdef __ATARIXL__ SHRAM_HANDLERS = 1 .include "atari.inc" .include "romswitch.inc" .export set_VTIMR1_handler .segment "LOWBSS" VTIMR1_handler: .res 3 .segment "BSS" old_VTIMR1_handler: .res 2 .segment "LOWCODE" ; timer interrupt handler: ; disable ROM, call user handler, enable ROM again my_VTIMR1_handler: disable_rom_quick jsr VTIMR1_handler enable_rom_quick pla rti .segment "CODE" ; install or remove VTIMR1 handler ; input: CF - 0/1 for remove/install handler ; AX - pointer to handler (if CF=1) ; registers destroyed set_VTIMR1_handler: bcc @remove ; install vector stx VTIMR1_handler+2 sta VTIMR1_handler+1 ; save passed vector in low memory lda #$4C ; "JMP" opcode sta VTIMR1_handler lda VTIMR1 sta old_VTIMR1_handler lda VTIMR1+1 sta old_VTIMR1_handler+1 lda #<my_VTIMR1_handler php sei sta VTIMR1 lda #>my_VTIMR1_handler sta VTIMR1+1 plp rts @remove: php sei lda old_VTIMR1_handler sta VTIMR1 lda old_VTIMR1_handler+1 sta VTIMR1+1 plp rts .endif ; .ifdef __ATARIXL__ ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/shadow_ram_timerirq2.s�������������������������������������������������������0000664�0000000�0000000�00000003414�13473601511�0021073�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Atari XL shadow RAM timer IRQ #2 handler ; ; Christian Groessler, chris@groessler.org, 2019 ; ;DEBUG = 1 .ifdef __ATARIXL__ SHRAM_HANDLERS = 1 .include "atari.inc" .include "romswitch.inc" .export set_VTIMR2_handler .segment "LOWBSS" VTIMR2_handler: .res 3 .segment "BSS" old_VTIMR2_handler: .res 2 .segment "LOWCODE" ; timer interrupt handler: ; disable ROM, call user handler, enable ROM again my_VTIMR2_handler: disable_rom_quick jsr VTIMR2_handler enable_rom_quick pla rti .segment "CODE" ; install or remove VTIMR2 handler ; input: CF - 0/1 for remove/install handler ; AX - pointer to handler (if CF=1) ; registers destroyed set_VTIMR2_handler: bcc @remove ; install vector stx VTIMR2_handler+2 sta VTIMR2_handler+1 ; save passed vector in low memory lda #$4C ; "JMP" opcode sta VTIMR2_handler lda VTIMR2 sta old_VTIMR2_handler lda VTIMR2+1 sta old_VTIMR2_handler+1 lda #<my_VTIMR2_handler php sei sta VTIMR2 lda #>my_VTIMR2_handler sta VTIMR2+1 plp rts @remove: php sei lda old_VTIMR2_handler sta VTIMR2 lda old_VTIMR2_handler+1 sta VTIMR2+1 plp rts .endif ; .ifdef __ATARIXL__ ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/siocall.s��������������������������������������������������������������������0000664�0000000�0000000�00000004457�13473601511�0016407�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, October 2000 ; ; This file provides the __sio_call function ; The function does a SIO call, it's not completely ; generic (e.g. transfer size is fixed), it's used ; to save space with _dio_read and _dio_write functions. ; ; unsigned char __fastcall__ _sio_call(dhandle_t handle, ; unsigned sect_num, ; void *buffer, ; unsigned sio_val); ; dhandle_t - 16bit (ptr) ; sio_val is (sio_command | sio_direction << 8) ; .export __sio_call .include "atari.inc" .import popa,popax,popptr1 .import sectsizetab,__oserror .importzp ptr1 .proc __sio_call sta DCOMND ; set command into DCB stx DSTATS ; set data flow directon jsr popax ; get buffer address sta DBUFLO ; set buffer address into DCB stx DBUFHI jsr popax sta DAUX1 ; set sector # stx DAUX2 jsr popptr1 ldy #sst_flag lda (ptr1),y and #128 beq _inv_hand ; handle not open or invalid ldy #sst_driveno lda (ptr1),y clc adc #1 sta DUNIT ; unit number (d1,d2,d3,...) lda DAUX2 ; high byte sector # bne _realsz lda DAUX1 cmp #4 ; sectors 1 to 3 are special (always 128 bytes) bcs _realsz lda #$80 sta DBYTLO asl a sta DBYTHI beq _cont _realsz:ldy #sst_sectsize lda (ptr1),y sta DBYTLO iny lda (ptr1),y sta DBYTHI _cont: lda #DISKID ; SIO bus ID of diskette drive sta DDEVIC lda #15 sta DTIMLO ; value got from DOS source jsr SIOV ; execute ldx #0 lda DSTATS bmi _req_err ; error occurred txa ; no error occurred _req_err: sta __oserror rts _inv_hand: ldx #0 lda #BADIOC bne _req_err .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/syschdir.s�������������������������������������������������������������������0000664�0000000�0000000�00000004131�13473601511�0016576�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Stefan Haubenthal, 2005-12-24 ; Based on on code by Christian Groessler ; ; unsigned char __fastcall__ _syschdir (const char* name); ; for SpartaDOS, RealDOS, and MyDOS ; .include "atari.inc" .import findfreeiocb .import __dos_type .import initcwd .importzp tmp4 .ifdef UCASE_FILENAME .importzp tmp3 .import addysp .import ucase_fn .ifdef DEFAULT_DEVICE .importzp tmp2 .endif .endif .export __syschdir .proc __syschdir pha ; save input parameter txa pha jsr findfreeiocb beq iocbok ; we found one pla pla ; fix up stack lda #TMOF ; too many open files rts iocbok: stx tmp4 ; remember IOCB index pla tax pla ; get argument again .ifdef UCASE_FILENAME .ifdef DEFAULT_DEVICE ldy #$80 sty tmp2 ; set flag for ucase_fn .endif jsr ucase_fn bcc ucok1 lda #183 ; see oserror.s rts ucok1: .endif ; defined UCASE_FILENAME ldy tmp4 ; IOCB index sta ICBAL,y ; store pointer to filename txa sta ICBAH,y tya tax lda __dos_type cmp #SPARTADOS beq :+ cmp #REALDOS beq :+ cmp #BWDOS beq :+ lda #CHDIR_MYDOS .byte $2C ; BIT <abs> : lda #CHDIR_SPDOS sta ICCOM,x lda #0 sta ICAX1,x sta ICAX2,x sta ICBLL,x sta ICBLH,x jsr CIOV .ifdef UCASE_FILENAME tya pha ldy tmp3 ; get size jsr addysp ; free used space on the stack pla tay .endif ; defined UCASE_FILENAME bmi cioerr jsr initcwd lda #0 rts cioerr: tya rts .endproc ; __syschdir ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/sysmkdir.s�������������������������������������������������������������������0000664�0000000�0000000�00000004275�13473601511�0016624�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Initial version: Stefan Haubenthal, 2005-12-24 ; Some fixes: Christian Groessler, 2009-01-28 ; ; unsigned char _sysmkdir (const char* name, ...); ; for SpartaDOS and MYDOS ; .include "atari.inc" .include "errno.inc" .import addysp .import popax .import findfreeiocb .importzp tmp4 .ifdef UCASE_FILENAME .importzp tmp3 .import ucase_fn .ifdef DEFAULT_DEVICE .importzp tmp2 .endif .endif .export __sysmkdir .proc __sysmkdir dey ; parm count < 2 shouldn't be needed to be... dey ; ...checked (it generates a C compiler warning) beq parmok ; branch if parameter count ok jsr addysp ; fix stack, throw away unused parameters parmok: jsr popax ; get name pha ; save input parameter txa pha jsr findfreeiocb beq iocbok ; we found one pla pla ; fix up stack lda #TMOF ; too many open files rts iocbok: stx tmp4 ; remember IOCB index pla tax pla ; get argument again .ifdef UCASE_FILENAME .ifdef DEFAULT_DEVICE ldy #$80 sty tmp2 ; set flag for ucase_fn .endif jsr ucase_fn bcc ucok1 lda #183 ; see oserror.s rts ucok1: .endif ; defined UCASE_FILENAME ldy tmp4 ; IOCB index sta ICBAL,y ; store pointer to filename txa sta ICBAH,y tya tax lda #MKDIR sta ICCOM,x lda #8 sta ICAX1,x lda #0 sta ICAX2,x sta ICBLL,x sta ICBLH,x jsr CIOV .ifdef UCASE_FILENAME tya pha ldy tmp3 ; get size jsr addysp ; free used space on the stack pla tay .endif ; defined UCASE_FILENAME bmi cioerr lda #0 rts cioerr: tya rts .endproc ; __sysmkdir �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/sysremove.s������������������������������������������������������������������0000664�0000000�0000000�00000003331�13473601511�0017003�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, Aug-2003 ; ; int remove (const char* name); ; .include "atari.inc" .include "errno.inc" .import findfreeiocb .importzp tmp4 .ifdef UCASE_FILENAME .importzp tmp3 .import addysp .import ucase_fn .ifdef DEFAULT_DEVICE .importzp tmp2 .endif .endif .export __sysremove .proc __sysremove pha ; save input parameter txa pha jsr findfreeiocb beq iocbok ; we found one pla pla ; fix up stack lda #TMOF ; too many open files rts iocbok: stx tmp4 ; remember IOCB index pla tax pla ; get argument again .ifdef UCASE_FILENAME .ifdef DEFAULT_DEVICE ldy #$80 sty tmp2 ; set flag for ucase_fn .endif jsr ucase_fn bcc ucok1 lda #183 ; see oserror.s rts ucok1: .endif ; defined UCASE_FILENAME ldy tmp4 ; IOCB index sta ICBAL,y ; store pointer to filename txa sta ICBAH,y tya tax lda #DELETE sta ICCOM,x lda #0 sta ICAX1,x sta ICAX2,x sta ICBLL,x sta ICBLH,x jsr CIOV .ifdef UCASE_FILENAME tya pha ldy tmp3 ; get size jsr addysp ; free used space on the stack pla tay .endif ; defined UCASE_FILENAME bmi cioerr lda #0 rts cioerr: tya rts .endproc ; __sysremove �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/sysrename.s������������������������������������������������������������������0000664�0000000�0000000�00000007645�13473601511�0016771�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, 2013-07-24 ; ; unsigned char __fastcall__ _sysrename (const char* oldname, const char* newname); ; .include "atari.inc" .import findfreeiocb .importzp tmp4, sp, ptr2, ptr3 .import incsp2, subysp, addysp, popax .ifdef UCASE_FILENAME .importzp tmp3 .import ucase_fn .ifdef DEFAULT_DEVICE .importzp tmp2 .endif .endif .export __sysrename .proc __sysrename pha ; save input parameter txa pha jsr findfreeiocb beq iocbok ; we found one pla pla ; fix up stack jsr incsp2 lda #TMOF ; too many open files rts iocbok: stx tmp4 ; remember IOCB index pla sta ptr2+1 ; remember newname pla sta ptr2 ; ditto. jsr popax ; get oldname ldy #0 sty sspc+1 ; initialize stack space .ifdef UCASE_FILENAME ; uppercase first (old) name and prepend device if needed .ifdef DEFAULT_DEVICE ldy #$80 sty tmp2 ; set flag for ucase_fn .endif jsr ucase_fn bcc ucok1 lda #183 ; see oserror.s rts ucok1: sta ptr3 stx ptr3+1 ; remember pointer to uppercased old name lda tmp3 ; # of bytes reserved on the stack sta sspc ; remember... ; uppercase second (new) name and don't prepend device .ifdef DEFAULT_DEVICE ldy #0 sty tmp2 ; set flag for ucase_fn .endif lda ptr2 ldx ptr2+1 jsr ucase_fn bcc ucok2 ldy tmp3 ; get size jsr addysp ; free used space on the stack lda #183 ; see oserror.s rts ucok2: sta ptr2 ; remember pointer to uppercased new name stx ptr2+1 ; update sspc -- # of bytes used on the stack lda sspc clc adc tmp3 sta sspc bcc ukok4 inc sspc+1 ukok4: .else sta ptr3 stx ptr3+1 sty sspc .endif ; create a string on the stack with the old filename and the new filename separated by an invalid character (space in our case) ; ptr2 - pointer to new name ; ptr3 - pointer to old name lda #128 tay clc adc sspc sta sspc bcc L1 inc sspc+1 L1: jsr subysp ; make room on the stack ; copy old name ldy #0 con: lda (ptr3),y sta (sp),y beq copyend iny bne con copyend:lda #$20 ; space sta (sp),y iny tya ; get current offset (beyond old name) clc adc sp sta ptr3 lda sp+1 adc #0 sta ptr3+1 ; ptr3 now contains pointer to space for new filename ; copy new name ldy #0 cnn: lda (ptr2),y sta (ptr3),y beq copend2 iny bne cnn copend2:ldx tmp4 lda sp sta ICBAL,x lda sp+1 sta ICBAH,x lda #RENAME sta ICCOM,x lda #0 sta ICAX1,x sta ICAX2,x sta ICBLL,x sta ICBLH,x jsr CIOV tya pha ; clean up stack lda sp clc adc sspc sta sp lda sp+1 adc sspc+1 sta sp+1 ; handle status pla tay bmi cioerr lda #0 rts cioerr: tya rts .endproc ; __sysrename .bss sspc: .res 2 ; stack space used �������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/sysrmdir.s�������������������������������������������������������������������0000664�0000000�0000000�00000004312�13473601511�0016623�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Stefan Haubenthal, 2005-12-24 ; Christian Groessler, 2013-07-16 ; ; unsigned char __fastcall__ _sysrmdir (const char* name); ; ; for SpartaDOS and MyDOS ; .include "atari.inc" .export __sysrmdir .import __sysremove .import __dos_type .import findfreeiocb .importzp tmp4 .ifdef UCASE_FILENAME .import ucase_fn .import addysp .importzp tmp3 .ifdef DEFAULT_DEVICE .importzp tmp2 .endif .endif .proc __sysrmdir pha lda __dos_type cmp #OSADOS+1 bcc do_sparta ; OS/A and SpartaDOS cmp #MYDOS bne not_impl ; neither MyDOS, OS/A, nor SpartaDOS pla jmp __sysremove ; MyDOS not_impl: pla lda #NVALID rts iocberr: pla ; cleanup stack pla lda #TMOF rts do_sparta: txa pha jsr findfreeiocb bne iocberr ; no IOCB available stx tmp4 ; remember IOCB pla tax pla .ifdef UCASE_FILENAME .ifdef DEFAULT_DEVICE ldy #$80 sty tmp2 ; set flag for ucase_fn .endif jsr ucase_fn bcc ucok1 lda #183 ; see oserror.s rts ucok1: .endif ; defined UCASE_FILENAME ldy tmp4 ; IOCB index sta ICBAL,y ; store pointer to filename txa sta ICBAH,y tya tax lda #RMDIR sta ICCOM,x lda #0 sta ICAX1,x lda #0 sta ICAX2,x sta ICBLL,x sta ICBLH,x jsr CIOV .ifdef UCASE_FILENAME tya pha ldy tmp3 ; get size jsr addysp ; free used space on the stack pla tay .endif ; defined UCASE_FILENAME bmi cioerr lda #0 rts cioerr: tya rts .endproc ; __sysrmdir ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/system_check.s���������������������������������������������������������������0000664�0000000�0000000�00000014377�13473601511�0017444�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Atari startup system check ; ; This routine gets loaded prior to the main part of the executable ; and checks if the system is compatible to run the program. ; For the XL target it checks whether the system is an XL type one ; and that enough memory is installed (which isn't the case for a 600XL). ; For the non-XL target it checks whether there is enough memory ; installed to run the program. ; For both targets it checks that the program won't load below MEMLO. ; If one of the checks fails, the loading of the main program ; is aborted by jumping to DOSVEC. ; ; Christian Groessler, chris@groessler.org, 2013 ; ;DEBUG = 1 .export __SYSTEM_CHECK__, __SYSCHK_END__ .import __STARTADDRESS__ ; the following imports are only needed for the 'atari' target version .import __BSS_SIZE__, __BSS_RUN__ .import __STACKSIZE__ .import __RESERVED_MEMORY__ ; import our header and trailers .forceimport __SYSCHKHDR__, __SYSCHKTRL__ .include "zeropage.inc" .include "atari.inc" .macro print_string text .local start, cont jmp cont start: .byte text, ATEOL cont: ldx #0 ; channel 0 lda #<start sta ICBAL,x ; address lda #>start sta ICBAH,x lda #<(cont - start) sta ICBLL,x ; length lda #>(cont - start) sta ICBLH,x lda #PUTCHR sta ICCOM,x jsr CIOV_org .endmacro .macro print_string2 addr, len ldx #0 ; channel 0 lda #<addr sta ICBAL,x ; address lda #>addr sta ICBAH,x lda #<len sta ICBLL,x ; length lda #>len sta ICBLH,x lda #PUTCHR sta ICCOM,x jsr CIOV_org .endmacro ; ------------------------------------------------------------------------ ; code .segment "SYSCHK" rts ; for older DOSes which unconditionally run the first load chunk .ifdef __ATARIXL__ ; check for SpartaDOS and its usage of RAM below ROM ; return CF 0/1 for ok/bad sdcheck:lda DOS cmp #'S' bne sdcrts0 ; not SpartaDOS, assume RAM is not used ; check for BW-DOS, which always reports itself as SpartaDOS, but doesn't use memory under the ROM lda DOS+3 ; 'B' in BW-DOS cmp #'B' bne sdnobw lda DOS+4 ; 'W' in BW-DOS cmp #'W' beq sdcrts0 ; BW-DOS does not use RAM below ROM sdnobw: lda DOS+1 ; SD version cmp #$40 ; SD-X has $40 or higher bcc sdcrts1 ; older versions (except maybe 1.x) always use the RAM under the ROM ldy #31 ; offset for OSRMFLG lda (DOSVEC),y ; get OSRMFLG bne sdcrts1 sdcrts0:clc rts sdcrts1:sec rts ramrom_txt: .byte "Memory under ROM is in use.", ATEOL .byte "Cannot run this program.", ATEOL ramrom_txt_len = * - ramrom_txt lmemerrxl_txt: .byte "Not enough memory to move screen", ATEOL .byte "memory to low memory. Consider using", ATEOL .byte "a higher load address.", ATEOL lmemerrxl_txt_len = * - lmemerrxl_txt ; no XL machine no_xl: print_string "This program needs an XL machine." jmp fail ; ***** entry point (atarixl) ***** syschk: lda $fcd8 ; from ostype.s cmp #$a2 beq no_xl ; we have an XL machine, now check memory lda RAMSIZ cmp #$80 bcs sys_ok jmp mem_err sys_ok: jsr sdcheck ; check for SpartaDOS-X, and if found, whether it uses the RAM under the ROM bcc sd_ok print_string2 ramrom_txt, ramrom_txt_len jmp fail sd_ok: .include "xlmemchk.inc" ; calculate lowest address we will use when we move the screen buffer down lda MEMLO cmp lowadr lda MEMLO+1 sbc lowadr+1 bcc memlo_ok ; load address was too low print_string2 lmemerrxl_txt, lmemerrxl_txt_len jsr delay ; long text takes longer to read, give user additional time jmp fail .else ; above 'atarixl', below 'atari' .define CIOV_org CIOV ; the print_string macros use CIOV_org, map this to CIOV lmemerr_txt: .byte "Program would load below MEMLO.", ATEOL .byte "Consider using a higher load address.", ATEOL lmemerr_txt_len = * - lmemerr_txt ; ***** entry point (atari) ***** syschk: sec lda MEMTOP sbc #<__RESERVED_MEMORY__ sta tmp lda MEMTOP+1 sbc #>__RESERVED_MEMORY__ sta tmp+1 lda tmp sec sbc #<__STACKSIZE__ sta tmp lda tmp+1 sbc #>__STACKSIZE__ sta tmp+1 ;tmp contains address which must be above .bss's end lda tmp cmp #<(__BSS_RUN__ + __BSS_SIZE__) lda tmp+1 sbc #>(__BSS_RUN__ + __BSS_SIZE__) bcc mem_err ; program doesn't fit into memory lda MEMLO cmp #<__STARTADDRESS__ lda MEMLO+1 sbc #>__STARTADDRESS__ bcc memlo_ok ; load address was too low print_string2 lmemerr_txt, lmemerr_txt_len jsr delay ; long text takes longer to read, give user additional time jmp fail .endif ; all is well(tm), launch the application memlo_ok: .ifdef DEBUG print_string "Stage #1 OK" jsr delay .endif rts ; not enough memory mem_err:print_string "Not enough memory." fail: jsr delay jmp (DOSVEC) ; short delay .proc delay lda #10 @loop: jsr delay1 clc sbc #0 bne @loop rts delay1: ldx #0 ldy #0 @loop: dey bne @loop dex bne @loop rts .endproc __SYSTEM_CHECK__=syschk __SYSCHK_END__: .ifndef __ATARIXL__ tmp: ; outside of the load chunk, some kind of poor man's .bss .endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/system_check_hdr.s�����������������������������������������������������������0000664�0000000�0000000�00000000605�13473601511�0020266�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Atari startup system check headers ; ; Christian Groessler, chris@groessler.org, 2013 ; .export __SYSCHKHDR__: absolute = 1 .import __SYSCHK_LOAD__, __SYSCHK_END__ ; ------------------------------------------------------------------------ ; Chunk header .segment "SYSCHKHDR" .word __SYSCHK_LOAD__ .word __SYSCHK_END__ - 1 ���������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/system_check_trailer.s�������������������������������������������������������0000664�0000000�0000000�00000000670�13473601511�0021155�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Atari startup system check headers ; ; Christian Groessler, chris@groessler.org, 2013 ; .export __SYSCHKTRL__: absolute = 1 .import __SYSTEM_CHECK__ .include "atari.inc" ; ------------------------------------------------------------------------ ; Chunk "trailer" - sets INITAD .segment "SYSCHKTRL" .word INITAD .word INITAD+1 .word __SYSTEM_CHECK__ ������������������������������������������������������������������������cc65-2.18/libsrc/atari/sysuname.s�������������������������������������������������������������������0000664�0000000�0000000�00000001437�13473601511�0016620�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-08-12 ; ; unsigned char __fastcall__ _sysuname (struct utsname* buf); ; .export __sysuname, utsdata .import utscopy __sysuname = utscopy ;-------------------------------------------------------------------------- ; Data. We define a fixed utsname struct here and just copy it. .rodata utsdata: ; sysname .asciiz "cc65" ; nodename .asciiz "" ; release .byte ((.VERSION >> 8) & $0F) + '0' .byte '.' .byte ((.VERSION >> 4) & $0F) + '0' .byte $00 ; version .byte (.VERSION & $0F) + '0' .byte $00 ; machine .asciiz "Atari" ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/targetutil/������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0016747�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/targetutil/Makefile.inc������������������������������������������������������0000664�0000000�0000000�00000000507�13473601511�0021161�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������DEPS += ../libwrk/$(TARGET)/w2cas.d ../libwrk/$(TARGET)/w2cas.o: $(SRCDIR)/targetutil/w2cas.c | ../libwrk/$(TARGET) $(COMPILE_recipe) ../target/$(TARGET)/util/w2cas.com: ../libwrk/$(TARGET)/w2cas.o ../lib/$(TARGET).lib | ../target/$(TARGET)/util $(LD65) -o $@ -t $(TARGET) $^ $(TARGET): ../target/$(TARGET)/util/w2cas.com �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/targetutil/w2cas.c�����������������������������������������������������������0000664�0000000�0000000�00000010643�13473601511�0020136�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* w2cas.c -- write file to cassette ** ** This program writes a boot file (typically linked with ** 'atari-cassette.cfg') to the cassette. ** Only files < 32K are supported, since the loading of ** larger files requires a special loader inside the program. ** ** Christian Groessler, chris@groessler.org, 2014 */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <6502.h> #include <atari.h> #include <cc65.h> #include <conio.h> static int verbose = 1; static char C_dev[] = "C:"; static struct __iocb *findfreeiocb(void) { int i; for (i = 0; i < 8; i++) { if (OS.iocb[i].handler == 0xff) return &OS.iocb[i]; } return NULL; } int main(int argc, char **argv) { char *filename, *x; char buf[20]; FILE *file; unsigned char *buffer; size_t filen, buflen = 32768l + 1; struct regs regs; struct __iocb *iocb = findfreeiocb(); int iocb_num; /* if DOS will automatically clear the screen after the program exits, wait for a keypress... */ if (doesclrscrafterexit()) atexit((void (*)(void))cgetc); if (! iocb) { fprintf(stderr, "couldn't find a free iocb\n"); return 1; } iocb_num = (iocb - OS.iocb) * 16; if (verbose) printf("using iocb index $%02X ($%04X)\n", iocb_num, iocb); if (argc < 2) { printf("\nfilename: "); x = fgets(buf, 19, stdin); printf("\n"); if (! x) { printf("empty filename, exiting...\n"); return 1; } if (*x && *(x + strlen(x) - 1) == '\n') *(x + strlen(x) - 1) = 0; if (! strlen(x)) { /* empty filename */ printf("empty filename, exiting...\n"); return 1; } filename = x; } else { filename = *(argv+1); } /* allocate buffer */ buffer = malloc(buflen); if (! buffer) { buflen = _heapmaxavail(); /* get as much as we can */ buffer = malloc(buflen); if (! buffer) { fprintf(stderr, "cannot alloc %ld bytes -- aborting...\n", (long)buflen); return 1; } } if (verbose) printf("buffer size: %ld bytes\n", (long)buflen); /* open file */ file = fopen(filename, "rb"); if (! file) { free(buffer); fprintf(stderr, "cannot open '%s': %s\n", filename, strerror(errno)); return 1; } /* read file -- file length must be < 32K */ if (verbose) printf("reading input file...\n"); filen = fread(buffer, 1, buflen, file); if (! filen) { fprintf(stderr, "read error\n"); file_err: fclose(file); free(buffer); return 1; } if (filen > 32767l) { fprintf(stderr, "file is too large (must be < 32768)\n"); goto file_err; } if (filen == buflen) { /* we have a buffer < 32768 and the file fits into it (and is most probably larger) */ fprintf(stderr, "not enough memory\n"); goto file_err; } if (verbose) printf("file size: %ld bytes\n", (long)filen); /* close input file */ fclose(file); /* open cassette */ if (verbose) printf("opening cassette...\n"); iocb->buffer = C_dev; iocb->aux1 = 8; /* open for output */ iocb->aux2 = 128; /* short breaks and no stop between data blocks */ iocb->command = IOCB_OPEN; regs.x = iocb_num; regs.pc = 0xe456; /* CIOV */ _sys(®s); if (regs.y != 1) { fprintf(stderr, "CIO call to open cassette returned %d\n", regs.y); free(buffer); return 1; } /* write file */ if (verbose) printf("writing to cassette...\n"); iocb->buffer = buffer; iocb->buflen = filen; iocb->command = IOCB_PUTCHR; regs.x = iocb_num; regs.pc = 0xe456; /* CIOV */ _sys(®s); if (regs.y != 1) { fprintf(stderr, "CIO call to write file returned %d\n", regs.y); free(buffer); iocb->command = IOCB_CLOSE; regs.x = iocb_num; regs.pc = 0xe456; /* CIOV */ _sys(®s); return 1; } /* free buffer */ free(buffer); /* close cassette */ iocb->command = IOCB_CLOSE; regs.x = iocb_num; regs.pc = 0xe456; /* CIOV */ _sys(®s); if (regs.y != 1) { fprintf(stderr, "CIO call to close cassette returned %d\n", regs.y); return 1; } /* all is fine */ printf("success\n"); return 0; } ���������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/tgi/�������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015346�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/tgi/atari_tgi_common.inc�����������������������������������������������������0000664�0000000�0000000�00000100233�13473601511�0021353�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Generic Atari graphics driver ; .macpack longbranch .macpack module .ifdef __ATARIXL__ CIO_vec := my_CIOV .else CIO_vec := CIOV .endif ; ****************************************************************************** ; ---------------------------------------------------------------------- ; ; Header. Includes jump table and constants. ; ; ---------------------------------------------------------------------- .ifdef __ATARIXL__ .define LABEL_X "x" .else .define LABEL_X "" .endif .if pages = 2 .define LABEL_P2 "p2" .else .define LABEL_P2 "" .endif module_header .ident (.sprintf ("_atr%s%d%s_tgi", LABEL_X, ::grmode, LABEL_P2)) ; Header .byte $74, $67, $69 ; "tgi" .byte TGI_API_VERSION ; TGI API version number libref: .addr $0000 ; Library reference .word x_res ; X resolution .word y_res ; Y resolution .byte colors ; Number of drawing colors .byte pages ; Number of screens available .byte 8 ; System font X size .byte 8 ; System font Y size .word aspect ; Aspect ratio .byte 0 ; TGI driver flags ; Function table .addr INSTALL .addr UNINSTALL .addr INIT .addr DONE .addr GETERROR .addr CONTROL .addr CLEAR .addr SETVIEWPAGE .addr SETDRAWPAGE .addr SETCOLOR .addr SETPALETTE .addr GETPALETTE .addr GETDEFPALETTE .addr SETPIXEL .addr GETPIXEL .addr LINE .addr BAR .addr TEXTSTYLE .addr OUTTEXT ; ****************************************************************************** ; ---------------------------------------------------------------------- ; ; Parameters ; ; ---------------------------------------------------------------------- x1 := ptr1 y1 := ptr2 x2 := ptr3 y2 := ptr4 radius := tmp1 ; ****************************************************************************** ; ---------------------------------------------------------------------- ; ; Global variables ; ; ---------------------------------------------------------------------- sptr := regsave + 2 .bss error: .res 1 ; Error code .if ::grmode = 9 || ::grmode = 11 palette = default_palette .else palette: .res colors ; The current palette .endif mask: .res 1 ; Current pixel mask griocb: .res 1 ; IOCB channel number for graphics .if pages = 2 p0scr: .res 1 ; High byte of screen address for screen page 0 p0dls: .res 1 ; High byte of display list address for screen page 0 ; Page 1's addresses are 8K higher .endif .data mag_x: .byte 1 ; Horizontal text scaling factor mag_y: .byte 1 ; Vertical text scaling factor mag_x8: .word 8 ; Horizontal text scaling factor * 8 mag_y8: .word 8 ; Vertical text scaling factor * 8 text_dir: .byte 0 ; Text direction, .ifdef __ATARIXL__ my_CIOV: .byte $4C, 0, 0 .endif .code ; ****************************************************************************** .macro put_pixel ; ---------------------------------------------------------------------- ; ; Put a pixel at (sptr),y using x as the bit mask offset ; ; ---------------------------------------------------------------------- lda (sptr),y eor mask and mask_table,x eor (sptr),y sta (sptr),y .endmacro ; ****************************************************************************** .rodata screen_device: .byte "S:",$9B ; Device code for screen screen_device_length := * - screen_device .code .proc INIT ; ---------------------------------------------------------------------- ; ; INIT: Switch to graphics mode ; ; ---------------------------------------------------------------------- .code ; Initialize drawing color .if ::ppb = 8 ldx #$FF .elseif ::ppb = 4 ldx #$55 .elseif ::ppb = 2 ldx #$11 .endif stx mask .ifdef __ATARIXL__ ; setup pointer to CIO lda libref sta my_CIOV+1 lda libref+1 sta my_CIOV+2 .endif ; Find a free IOCB lda #$70 search: tax ldy ICHID,x cpy #$FF beq found sub #$10 bcs search ; Not enough resources available (free IOCB or memory) ; enter with C cleared! nores: lda #TGI_ERR_NO_RES bcc exit found: ; Check if enough RAM is available lda #0 sub #<mem_needed tay lda RAMTOP sbc #>mem_needed cmp APPMHI + 1 bcc nores bne switch cpy APPMHI bcc nores ; not enough memory ; Switch into graphics mode switch: lda #OPEN sta ICCOM,x lda #OPNIN | OPNOT sta ICAX1,x lda #::grmode sta ICAX2,x lda #<screen_device sta ICBAL,x lda #>screen_device sta ICBAH,x lda #<screen_device_length sta ICBLL,x lda #>screen_device_length sta ICBLH,x jsr CIO_vec .if ::pages = 2 ; Reserve 8K of high memory lda RAMTOP sub #32 sta RAMTOP ; Close and reopen graphics lda #CLOSE sta ICCOM,x jsr CIO_vec ; Reopen graphics lda #OPEN sta ICCOM,x lda #OPNIN | OPNOT sta ICAX1,x lda #::grmode sta ICAX2,x lda #<screen_device sta ICBAL,x lda #>screen_device sta ICBAH,x lda #<screen_device_length sta ICBLL,x lda #>screen_device_length sta ICBLH,x jsr CIO_vec ; Save screen pointers lda SAVMSC + 1 sta p0scr lda SDLSTH sta p0dls .endif ; ::pages = 2 stx griocb ; Reset the error code and return lda #TGI_ERR_OK exit: sta error rts .endproc ; ****************************************************************************** .proc DONE ; ---------------------------------------------------------------------- ; ; DONE: Switch back to text mode ; ; ---------------------------------------------------------------------- .code .if ::pages = 2 ; Free 8K of high memory lda RAMTOP add #32 sta RAMTOP .endif ; Clear griocb lda #$FF ldx griocb sta griocb ; Close the S: device lda #CLOSE sta ICCOM,x jsr CIO_vec ; Reopen it in Graphics 0 lda #OPEN sta ICCOM,x lda #OPNIN | OPNOT sta ICAX1,x lda #0 sta ICAX2,x lda #<screen_device sta ICBAL,x lda #>screen_device sta ICBAH,x lda #<screen_device_length sta ICBLL,x lda #>screen_device_length sta ICBLH,x jsr CIO_vec ; Now close it again; we don't need it anymore :) lda #CLOSE sta ICCOM,x jmp CIO_vec .endproc ; ****************************************************************************** .proc GETERROR ; ---------------------------------------------------------------------- ; ; GETERROR: Return the error code in A and clear it ; ; ---------------------------------------------------------------------- .code ldx #TGI_ERR_OK lda error stx error rts .endproc ; ****************************************************************************** .proc CLEAR ; ---------------------------------------------------------------------- ; ; CLEAR: Clear the screen ; ; ---------------------------------------------------------------------- .code ; Load the screen address in sptr lda SAVMSC sta sptr lda SAVMSC + 1 sta sptr + 1 ; Fill with zero lda #0 tay .if >::scrsize > 0 ; Clear full pages if any ldx #>::scrsize loop1: sta (sptr),y iny bne loop1 inc sptr + 1 dex bne loop1 .endif .if <::scrsize > 0 ; Clear the rest, if any loop2: sta (sptr),y iny cpy #<::scrsize bne loop2 .endif rts .endproc ; ****************************************************************************** .proc GETPALETTE ; ---------------------------------------------------------------------- ; ; GETPALETTE: Return the current palette in A/X ; ; ---------------------------------------------------------------------- .code lda #<palette ldx #>palette rts .endproc ; ****************************************************************************** .proc GETDEFPALETTE ; ---------------------------------------------------------------------- ; ; GETDEFPALETTE: Return the default palette in A/X ; ; ---------------------------------------------------------------------- .code lda #<default_palette ldx #>default_palette rts .endproc ; ****************************************************************************** .proc SETCOLOR ; ---------------------------------------------------------------------- ; ; SETCOLOR: Set the drawing color (in A) ; ; ---------------------------------------------------------------------- .code tax .if ::grmode = 9 ; Map colors like this: 0 -> 0, 1 -> 15, 2 -> 1, 3 -> 2 etc. beq cont cpx #1 bne map ldx #16 map: dex cont: .endif lda masks,x sta mask rts .endproc ; ****************************************************************************** .proc CALC ; ---------------------------------------------------------------------- ; ; CALC: Calculate the screen address ; in ; x1 (ptr1) x coordinate ; y1 (ptr2) y coordinate ; out ; sptr + y screen address ; x bit mask index ; ; ---------------------------------------------------------------------- .bss temp: .res 1 .code ; calculate line offset lda y1 + 1 sta temp lda y1 .if ::x_res / ::ppb = 40 yrep = 3 .elseif ::x_res / ::ppb = 20 yrep = 2 .elseif ::x_res / ::ppb = 10 yrep = 1 .endif .repeat yrep asl a rol temp .endrepeat sta sptr ldx temp stx sptr + 1 .repeat 2 asl a rol temp .endrepeat add sptr sta sptr lda temp adc sptr + 1 sta sptr + 1 ; calculate bit mask offset lda x1 and #ppb - 1 tax ; calculate row offset lda x1 + 1 sta temp lda x1 .if ::ppb = 8 xrep = 3 .elseif ::ppb = 4 xrep = 2 .elseif ::ppb = 2 xrep = 1 .endif .repeat xrep lsr temp ror a .endrepeat tay ; sptr += SAVMSC lda SAVMSC add sptr sta sptr lda SAVMSC + 1 adc sptr + 1 sta sptr + 1 ; We're done! rts .endproc ; ****************************************************************************** .proc SETPIXEL ; ---------------------------------------------------------------------- ; ; Draw one pixel at x1, y1 ; ; ---------------------------------------------------------------------- .code jsr CALC put_pixel rts .endproc ; ****************************************************************************** .proc GETPIXEL ; ---------------------------------------------------------------------- ; ; GETPIXEL: Read the color value of a pixel and return it in A/X ; ; ---------------------------------------------------------------------- .code jsr CALC lda (sptr),y and mask_table,x .if ::ppb = 8 beq zero lda #1 zero: ldx #0 rts .elseif ::ppb = 4 loop: cpx #3 beq done4 lsr a lsr a inx bne loop done4: and #$03 ldx #0 rts .elseif ::ppb = 2 dex bne shift and #$0F jmp exit shift: lsr a lsr a lsr a lsr a exit: .if ::grmode = 9 ; Mode 9 mapping ; Map colors like this: 0 -> 0, 15 -> 1, 2 -> 3, 3 -> 4 etc. beq done9 cmp #15 bne map9 lda #0 map9: add #1 done9: .endif .if ::grmode = 10 ; Mode 10 mapping ; Map out of range colors like this: ; 9 -> 8 ; 10 -> 8 ; 11 -> 8 ; 12 -> 0 ; 13 -> 1 ; 14 -> 2 ; 15 -> 3 cmp #9 bcc done10 sub #12 bcs done10 lda #8 done10: .endif ; ::grmode = 10 ; Done! ldx #0 rts .endif ; ::ppb = 2 .endproc ; ****************************************************************************** .proc LINE ; ---------------------------------------------------------------------- ; ; LINE: Draw a line from x1,y1 to x2,y2 ; ; ---------------------------------------------------------------------- .ifdef USE_CIO_LINE ; position ptr1, ptr2 lda x1 sta OLDCOL lda x1 + 1 sta OLDCOL + 1 lda y1 sta OLDROW ; plot jsr SETPIXEL ; position ptr3,ptr4 lda x2 sta COLCRS lda x2 + 1 sta COLCRS + 1 lda y2 sta ROWCRS ; drawto ldx griocb lda #DRAWLN sta ICCOM,x lda mask .if ::grmode = 10 and #$0f .else and #colors - 1 .endif sta ATACHR jmp CIO_vec .else ; USE_CIO_LINE ; locals dx := sreg dy := y1 dx2 := x2 dy2 := y2 iy := tmp1 err := tmp3 .code ; dx = x2 - x1 lda x2 sub x1 sta dx lda x2 + 1 sbc x1 + 1 sta dx + 1 ; if dx is positive, no problem bcs dx_positive ; if dx is negative, swap x1,y1 with x2,y2 lda x1 ; x1 <-> x2, low byte ldx x2 sta x2 stx x1 lda x1 + 1 ; x1 <-> x2, high byte ldx x2 + 1 sta x2 + 1 stx x1 + 1 lda y1 ; y1 <-> y2, low byte ldx y2 sta y2 stx y1 lda y1 + 1 ; y1 <-> y2, high byte ldx y2 + 1 sta y2 + 1 stx y1 + 1 ; Calculate again jmp LINE dx_positive: ; Calculate coords jsr CALC ; dy = y2 - y1 lda y2 sub y1 sta dy lda y2 + 1 sbc y1 + 1 sta dy + 1 ; if dy is negative bcs dy_positive ; dy = -dy lda #0 sub dy sta dy lda #0 sbc dy + 1 sta dy + 1 ; iy = -row_size lda #<(65536 - x_res / ppb) sta iy lda #>(65536 - x_res / ppb) sta iy + 1 bne skip_iy_1 ; always dy_positive: ; iy = row_size lda #<(x_res / ppb) sta iy lda #>(x_res / ppb) sta iy + 1 skip_iy_1: ; dx2 = dx * 2 lda dx asl a sta dx2 lda dx + 1 rol a sta dx2 + 1 ; dy2 = dy * 2 lda dy asl a sta dy2 lda dy + 1 rol a sta dy2 + 1 ; if dx >= dy lda dx cmp dy lda dx + 1 sbc dy + 1 bcc dy_major ; dx is the major axis ; err = dy2 - dx lda dy2 sub dx sta err lda dy2 + 1 sbc dx + 1 sta err + 1 .scope loop: ; main loop put_pixel ; if err >= 0 lda err + 1 bmi err_neg ; err -= dx2 lda err sub dx2 sta err lda err + 1 sbc dx2 + 1 sta err + 1 ; move_vertical (iy) lda sptr add iy sta sptr lda sptr + 1 adc iy + 1 sta sptr + 1 err_neg: ; err += dy2 lda err add dy2 sta err lda err + 1 adc dy2 + 1 sta err + 1 ; move_right inx cpx #ppb bne end_move ldx #0 iny bne end_move inc sptr + 1 end_move: ; loop while dx-- >= 0 lda dx ora dx + 1 beq exit dec dx lda dx cmp #$FF bne loop dec dx + 1 jmp loop exit: rts .endscope dy_major: ; dy is the major axis ; err = dx2 - dy; lda dx2 sub dy sta err lda dx2 + 1 sbc dy + 1 sta err + 1 .scope loop: ; main loop put_pixel ; if err >= 0 lda err + 1 bmi end_move ; err -= dy2 lda err sub dy2 sta err lda err + 1 sbc dy2 + 1 sta err + 1 ; move_right inx cpx #ppb bne end_move ldx #0 iny bne end_move inc sptr + 1 end_move: ; err += dx2 lda err add dx2 sta err lda err + 1 adc dx2 + 1 sta err + 1 ; move_vertical(iy) lda sptr add iy sta sptr lda sptr + 1 adc iy + 1 sta sptr + 1 ; loop while dy-- >= 0 lda dy ora dy + 1 beq exit dec dy lda dy cmp #$FF bne loop dec dy + 1 jmp loop exit: rts .endscope .endif ; USE_CIO_LINE .endproc ; ****************************************************************************** .proc clipped_bar ; ---------------------------------------------------------------------- ; ; Clip and draw bar, this function will disappear when text clipping ; will be done int the TGI kernel ; ; ---------------------------------------------------------------------- .code lda y1 + 1 bne off lda y1 cmp #y_res bcs off lda x1 + 1 .if >(::x_res - 1) > 0 cmp #>x_res bcc check2 .endif bne off lda x1 cmp #<x_res bcc check2 off: rts check2: lda y2 + 1 bne off lda y2 cmp #y_res bcs off lda x2 + 1 .if >(::x_res - 1) > 0 cmp #>x_res bcc BAR .endif bne off lda x2 cmp #<x_res bcs off .endproc ; ****************************************************************************** .proc BAR ; ---------------------------------------------------------------------- ; ; BAR: Draw a filled rectangle with the corners at x1,y1,x2,y2 ; ; ---------------------------------------------------------------------- ; locals lmem := sreg .bss lmask: .res 1 rmask: .res 1 dy: .res 1 dx: .res 1 fmask: .res 1 .code ; dy = y2 - y1 + 1 lda y2 sub y1 sta dy inc dy ; Calculate upper left corner jsr CALC ; Save the values tya add sptr sta lmem lda sptr + 1 adc #0 sta lmem + 1 lda bar_table,x sta lmask ; Calculate upper right corner lda x2 sta x1 .if >(::x_res - 1) > 0 lda x2 + 1 sta x1 + 1 .endif jsr CALC ; Save the values tya add sptr sta sptr bcc skips inc sptr + 1 skips: inx lda bar_table,x eor #$FF sta rmask ; Calculate memory difference between x1 and x2 lda sptr sub lmem sta dx loop: ; Main loop ldy #0 ldx dx beq same ; Left lda (lmem),y eor mask and lmask eor (lmem),y sta (lmem),y iny ; Between lda mask jmp next btwn: sta (lmem),y iny next: dex bne btwn ; Right lda (lmem),y eor mask and rmask eor (lmem),y sta (lmem),y jmp cont same: ; Same byte lda lmask and rmask sta fmask lda (lmem),y eor mask and fmask eor (lmem),y sta (lmem),y cont: ; Go to next row lda lmem add #<(x_res / ppb) sta lmem bcc skipm inc lmem + 1 skipm: ; Loop while --dy > 0 dec dy bne loop rts .endproc ; ****************************************************************************** .proc TEXTSTYLE ; ---------------------------------------------------------------------- ; ; TEXTSTYLE: Set text style. Scale factors in X and Y and direction in A ; ; ---------------------------------------------------------------------- .code stx mag_x sty mag_y ; Save text direction in bit 8 so that we can use BIT instruction later lsr a ror a sta text_dir ; Save 8 * scaling factors lda #0 sta mag_x8 + 1 sta mag_y8 + 1 ; Save 8 * mag_x txa .repeat 3 asl a rol mag_x8 + 1 .endrepeat sta mag_x8 ; Save 8 * mag_y tya .repeat 3 asl a rol mag_y8 + 1 .endrepeat sta mag_y8 ; Done! rts .endproc ; ****************************************************************************** .proc OUTTEXT ; ---------------------------------------------------------------------- ; ; OUTTEXT: Draw text at x1, y1. String is in ptr3 ; ; ---------------------------------------------------------------------- ; locals string := tmp1 pixels := tmp4 font := regsave .bss rows: .res 1 .if >(::x_res - 1) > 0 oldx1: .res 2 oldx2: .res 2 .else oldx1: .res 1 oldx2: .res 1 .endif oldy1: .res 1 oldy2: .res 1 inv: .res 1 .code ; Don't draw zero sized characters lda mag_x ora mag_y bne not0 rts not0: ; Save string address, ptr3 is needed by BAR lda ptr3 sta string lda ptr3 + 1 sta string + 1 bit text_dir bmi vert ; Calculate x2 lda mag_x sub #1 add x1 sta x2 .if >(::x_res - 1) > 0 lda x1 + 1 adc #0 sta x2 + 1 .else lda #0 sta x2 + 1 .endif ; Calculate y2 and adjust y1 dec y1 lda y1 sta y2 sub mag_y add #1 sta y1 lda #0 sta y2 + 1 jmp while ; Calculate for vertical text vert: lda x1 sub #1 sta x2 lda x1 + 1 sbc #0 sta x2 + 1 lda x1 sub mag_y sta x1 lda x1 + 1 sbc #0 sta x1 + 1 lda mag_x sub #1 add y1 sta y2 lda #0 sta y2 + 1 jmp while ; Main loop loop: inc string bne skiph inc string + 1 skiph: ; Save coords bit text_dir bmi scvert ldx y1 stx oldy1 ldx y2 stx oldy2 jmp draw scvert: ldx x1 stx oldx1 ldx x2 stx oldx2 .if >(::x_res - 1) > 0 ldx x1 + 1 stx oldx1 + 1 ldx x2 + 1 stx oldx2 + 1 .endif ; Draw one character draw: ; Extract the inverse mask ldx #0 asl a bcc noinv dex noinv: stx inv ; Calculate font data address ldx CHBAS cmp #$20*2 bpl lowhalf ; Semigraphic or lowercase inx inx lowhalf: asl a bcc lowquarter ; Letter inx lowquarter: asl a sta font stx font+1 ; Save old coords bit text_dir bpl hor lda y1 sta oldy1 lda y2 sta oldy2 jmp cont hor: lda x1 sta oldx1 lda x2 sta oldx2 .if >(::x_res - 1) > 0 lda x1 + 1 sta oldx1 + 1 lda x2 + 1 sta oldx2 + 1 .endif ; Get glyph pixels cont: ldy #7 ; Put one row of the glyph putrow: sty rows lda (font),y eor inv sec rol a sta pixels ; Put one column of the row putcol: bcc next_col lda x1 pha lda x1 + 1 pha jsr clipped_bar pla sta x1 + 1 pla sta x1 next_col: ; Go to next column ; increase x coords bit text_dir bmi vertinc lda mag_x add x1 sta x1 bcc L1 inc x1 + 1 L1: lda mag_x add x2 sta x2 bcc L2 inc x2 + 1 jmp L2 vertinc: lda y1 sub mag_x sta y1 lda y2 sub mag_x sta y2 L2: asl pixels bne putcol next_row: ; Go to next row bit text_dir bmi verty lda y1 sub mag_y sta y1 bcs L3 dec y1 + 1 L3: lda y2 sub mag_y sta y2 bcs L6 dec y2 + 1 L4: jmp L6 verty: lda x1 sub mag_y sta x1 bcs L5 dec x1 + 1 L5: lda x2 sub mag_y sta x2 bcs L6 dec x2 + 1 L6: ; Restore old values bit text_dir bpl reshor lda oldy1 sta y1 lda oldy2 sta y2 jmp nextrow reshor: lda oldx1 sta x1 lda oldx2 sta x2 .if >(::x_res - 1) > 0 lda oldx1 + 1 sta x1 + 1 lda oldx2 + 1 sta x2 + 1 .endif ; Next row nextrow: ldy rows dey jpl putrow ; Restore coords bit text_dir bmi resvert ldx oldy1 stx y1 ldx oldy2 stx y2 ldx #0 stx y1 + 1 stx y2 + 1 lda mag_x8 add x1 sta x1 lda mag_x8 + 1 adc x1 + 1 sta x1 + 1 lda mag_x8 add x2 sta x2 lda mag_x8 + 1 adc x2 + 1 sta x2 + 1 jmp while resvert: ldx oldx1 stx x1 ldx oldx2 stx x2 .if >(::x_res - 1) > 0 ldx oldx1 + 1 stx x1 + 1 ldx oldx2 + 1 stx x2 + 1 .endif lda y1 sub mag_x8 sta y1 lda y1 +1 sbc mag_x8 + 1 sta y1 + 1 lda y2 sub mag_x8 sta y2 lda y2 +1 sbc mag_x8 + 1 sta y2 + 1 ; End of loop while: ldy #0 lda (string),y jne loop ; Check for null character rts .endproc .if pages = 2 ; ****************************************************************************** .proc SETVIEWPAGE ; ---------------------------------------------------------------------- ; ; SETVIEWPAGE, page in A ; ; ---------------------------------------------------------------------- .code tax beq cont lda #32 cont: add p0dls cmp SDLSTH beq done ; We're already in the desired page ldx RTCLOK + 2 sta SDLSTH ; Wait until next VBLANK wait: cpx RTCLOK + 2 beq wait ; Done done: rts .endproc ; ****************************************************************************** .proc SETDRAWPAGE ; ---------------------------------------------------------------------- ; ; SETDRAWPAGE, page in A ; ; ---------------------------------------------------------------------- .code tax beq cont lda #32 cont: add p0scr sta SAVMSC + 1 rts .endproc .endif ; ****************************************************************************** ; ---------------------------------------------------------------------- ; ; Unimplemented functions that require an error code ; ; ---------------------------------------------------------------------- CONTROL: lda #TGI_ERR_INV_FUNC sta error ; fall through ; ****************************************************************************** ; ---------------------------------------------------------------------- ; ; Unimplemented functions that don't require an error code ; ; ---------------------------------------------------------------------- INSTALL: UNINSTALL: .if pages = 1 SETVIEWPAGE: SETDRAWPAGE: .endif rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/tgi/atr10.s������������������������������������������������������������������0000664�0000000�0000000�00000004162�13473601511�0016464�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Graphics driver for the 80x192x9 (CIO mode 10, ANTIC mode F, GTIA mode $80) on the Atari. ; ; Fatih Aygun (2009) ; .include "atari.inc" .include "zeropage.inc" .include "tgi-kernel.inc" .include "tgi-error.inc" .macpack generic ; ****************************************************************************** ; ---------------------------------------------------------------------- ; ; Constants and tables ; ; ---------------------------------------------------------------------- ; Graphics mode grmode = 10 ; X resolution x_res = 80 ; Y resolution y_res = 192 ; Number of colors colors = 9 ; Pixels per byte ppb = 2 ; Screen memory size in bytes scrsize = x_res * y_res / ppb ; Pixel aspect ratio aspect = $0330 ; based on 4/3 display ; Free memory needed mem_needed = 7147 ; Number of screen pages pages = 1 .rodata mask_table: ; Mask table to set pixels .byte %11110000, %00001111 masks: ; Color masks .byte $00, $11, $22, $33, $44, $55, $66, $77, $88 bar_table: ; Mask table for BAR .byte %11111111, %00001111, %00000000 default_palette: .byte $00, $0E, $32, $96, $68, $C4, $74, $EE, $4A .code ; ****************************************************************************** .proc SETPALETTE ; ---------------------------------------------------------------------- ; ; SETPALETTE: Set the palette (in ptr1) ; ; ---------------------------------------------------------------------- .code ; Copy the palette ldy #colors - 1 loop: lda (ptr1),y sta palette,y sta PCOLR0,y dey bpl loop ; Done, reset the error code lda #TGI_ERR_OK sta error rts .endproc .include "atari_tgi_common.inc" ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/tgi/atr10p2.s����������������������������������������������������������������0000664�0000000�0000000�00000004163�13473601511�0016727�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Graphics driver for the 80x192x9 (CIO mode 10, ANTIC mode F, GTIA mode $80) on the Atari. ; ; Fatih Aygun (2009) ; .include "atari.inc" .include "zeropage.inc" .include "tgi-kernel.inc" .include "tgi-error.inc" .macpack generic ; ****************************************************************************** ; ---------------------------------------------------------------------- ; ; Constants and tables ; ; ---------------------------------------------------------------------- ; Graphics mode grmode = 10 ; X resolution x_res = 80 ; Y resolution y_res = 192 ; Number of colors colors = 9 ; Pixels per byte ppb = 2 ; Screen memory size in bytes scrsize = x_res * y_res / ppb ; Pixel aspect ratio aspect = $0330 ; based on 4/3 display ; Free memory needed mem_needed = 15339 ; Number of screen pages pages = 2 .rodata mask_table: ; Mask table to set pixels .byte %11110000, %00001111 masks: ; Color masks .byte $00, $11, $22, $33, $44, $55, $66, $77, $88 bar_table: ; Mask table for BAR .byte %11111111, %00001111, %00000000 default_palette: .byte $00, $0E, $32, $96, $68, $C4, $74, $EE, $4A .code ; ****************************************************************************** .proc SETPALETTE ; ---------------------------------------------------------------------- ; ; SETPALETTE: Set the palette (in ptr1) ; ; ---------------------------------------------------------------------- .code ; Copy the palette ldy #colors - 1 loop: lda (ptr1),y sta palette,y sta PCOLR0,y dey bpl loop ; Done, reset the error code lda #TGI_ERR_OK sta error rts .endproc .include "atari_tgi_common.inc" �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/tgi/atr11.s������������������������������������������������������������������0000664�0000000�0000000�00000004015�13473601511�0016462�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Graphics driver for the 80x192x16h (CIO mode 11, ANTIC mode F, GTIA mode $C0) on the Atari. ; ; Fatih Aygun (2009) ; .include "atari.inc" .include "zeropage.inc" .include "tgi-kernel.inc" .include "tgi-error.inc" .macpack generic ; ****************************************************************************** ; ---------------------------------------------------------------------- ; ; Constants and tables ; ; ---------------------------------------------------------------------- ; Graphics mode grmode = 11 ; X resolution x_res = 80 ; Y resolution y_res = 192 ; Number of colors colors = 16 ; Pixels per byte ppb = 2 ; Screen memory size in bytes scrsize = x_res * y_res / ppb ; Pixel aspect ratio aspect = $0330 ; based on 4/3 display ; Free memory needed mem_needed = 7147 ; Number of screen pages pages = 1 .rodata mask_table: ; Mask table to set pixels .byte %11110000, %00001111 masks: ; Color masks .byte $00, $11, $22, $33, $44, $55, $66, $77, $88, $99, $aa, $bb, $cc, $dd, $ee, $ff bar_table: ; Mask table for BAR .byte %11111111, %00001111, %00000000 default_palette: .byte $00, $10, $20, $30, $40, $50, $60, $70, $80, $90, $A0, $B0, $C0, $D0, $E0, $F0 .code ; ****************************************************************************** .proc SETPALETTE ; ---------------------------------------------------------------------- ; ; SETPALETTE: Set the palette (in ptr1) ; ; ---------------------------------------------------------------------- .code ; No palettes lda #TGI_ERR_INV_FUNC sta error rts .endproc .include "atari_tgi_common.inc" �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/tgi/atr14.s������������������������������������������������������������������0000664�0000000�0000000�00000004452�13473601511�0016472�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Graphics driver for the 160x192x2 (CIO mode 14, ANTIC mode C) on the Atari. ; ; Fatih Aygun (2009) ; .include "atari.inc" .include "zeropage.inc" .include "tgi-kernel.inc" .include "tgi-error.inc" .macpack generic ; ****************************************************************************** ; ---------------------------------------------------------------------- ; ; Constants and tables ; ; ---------------------------------------------------------------------- ; Graphics mode grmode = 14 ; X resolution x_res = 160 ; Y resolution y_res = 192 ; Number of colors colors = 2 ; Pixels per byte ppb = 8 ; Screen memory size in bytes scrsize = x_res * y_res / ppb ; Pixel aspect ratio aspect = $0198 ; based on 4/3 display ; Free memory needed mem_needed = 3305 ; Number of screen pages pages = 1 .rodata mask_table: ; Mask table to set pixels .byte %10000000, %01000000, %00100000, %00010000, %00001000, %00000100, %00000010, %00000001 masks: ; Color masks .byte %00000000, %11111111 bar_table: ; Mask table for BAR .byte %11111111, %01111111, %00111111, %00011111, %00001111, %00000111, %00000011, %00000001, %00000000 default_palette: .byte $00, $0E .code ; ****************************************************************************** .proc SETPALETTE ; ---------------------------------------------------------------------- ; ; SETPALETTE: Set the palette (in ptr1) ; ; ---------------------------------------------------------------------- .code ; Copy the palette ldy #colors - 1 loop: lda (ptr1),y sta palette,y dey bpl loop ; Get the color entries from the palette lda palette sta COLOR4 lda palette + 1 sta COLOR0 ; Done, reset the error code lda #TGI_ERR_OK sta error rts .endproc .include "atari_tgi_common.inc" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/tgi/atr15.s������������������������������������������������������������������0000664�0000000�0000000�00000004530�13473601511�0016470�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Graphics driver for the 160x192x2 (CIO mode 15, ANTIC mode E) on the Atari. ; ; Fatih Aygun (2009) ; .include "atari.inc" .include "zeropage.inc" .include "tgi-kernel.inc" .include "tgi-error.inc" .macpack generic ; ****************************************************************************** ; ---------------------------------------------------------------------- ; ; Constants and tables ; ; ---------------------------------------------------------------------- ; Graphics mode grmode = 15 ; X resolution x_res = 160 ; Y resolution y_res = 192 ; Number of colors colors = 4 ; Pixels per byte ppb = 4 ; Screen memory size in bytes scrsize = x_res * y_res / ppb ; Pixel aspect ratio aspect = $0198 ; based on 4/3 display ; Free memory needed mem_needed = 7147 ; Number of screen pages pages = 1 .rodata mask_table: ; Mask table to set pixels .byte %11000000, %00110000, %00001100, %00000011 masks: ; Color masks .byte %00000000, %01010101, %10101010, %11111111 bar_table: ; Mask table for BAR .byte %11111111, %00111111, %00001111, %00000011, %00000000 default_palette: .byte $00, $0E, $32, $96 .code ; ****************************************************************************** .proc SETPALETTE ; ---------------------------------------------------------------------- ; ; SETPALETTE: Set the palette (in ptr1) ; ; ---------------------------------------------------------------------- .code ; Copy the palette ldy #colors - 1 loop: lda (ptr1),y sta palette,y dey bpl loop ; Get the color entries from the palette lda palette sta COLOR4 lda palette + 1 sta COLOR0 lda palette + 2 sta COLOR1 lda palette + 3 sta COLOR2 ; Done, reset the error code lda #TGI_ERR_OK sta error rts .endproc .include "atari_tgi_common.inc" ������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/tgi/atr15p2.s����������������������������������������������������������������0000664�0000000�0000000�00000004531�13473601511�0016733�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Graphics driver for the 160x192x2 (CIO mode 15, ANTIC mode E) on the Atari. ; ; Fatih Aygun (2009) ; .include "atari.inc" .include "zeropage.inc" .include "tgi-kernel.inc" .include "tgi-error.inc" .macpack generic ; ****************************************************************************** ; ---------------------------------------------------------------------- ; ; Constants and tables ; ; ---------------------------------------------------------------------- ; Graphics mode grmode = 15 ; X resolution x_res = 160 ; Y resolution y_res = 192 ; Number of colors colors = 4 ; Pixels per byte ppb = 4 ; Screen memory size in bytes scrsize = x_res * y_res / ppb ; Pixel aspect ratio aspect = $0198 ; based on 4/3 display ; Free memory needed mem_needed = 15339 ; Number of screen pages pages = 2 .rodata mask_table: ; Mask table to set pixels .byte %11000000, %00110000, %00001100, %00000011 masks: ; Color masks .byte %00000000, %01010101, %10101010, %11111111 bar_table: ; Mask table for BAR .byte %11111111, %00111111, %00001111, %00000011, %00000000 default_palette: .byte $00, $0E, $32, $96 .code ; ****************************************************************************** .proc SETPALETTE ; ---------------------------------------------------------------------- ; ; SETPALETTE: Set the palette (in ptr1) ; ; ---------------------------------------------------------------------- .code ; Copy the palette ldy #colors - 1 loop: lda (ptr1),y sta palette,y dey bpl loop ; Get the color entries from the palette lda palette sta COLOR4 lda palette + 1 sta COLOR0 lda palette + 2 sta COLOR1 lda palette + 3 sta COLOR2 ; Done, reset the error code lda #TGI_ERR_OK sta error rts .endproc .include "atari_tgi_common.inc" �����������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/tgi/atr3.s�������������������������������������������������������������������0000664�0000000�0000000�00000004517�13473601511�0016412�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Graphics driver for the 40x24x4 (CIO mode 3, ANTIC mode 8) on the Atari. ; ; Fatih Aygun (2009) ; .include "atari.inc" .include "zeropage.inc" .include "tgi-kernel.inc" .include "tgi-error.inc" .macpack generic ; ****************************************************************************** ; ---------------------------------------------------------------------- ; ; Constants and tables ; ; ---------------------------------------------------------------------- ; Graphics mode grmode = 3 ; X resolution x_res = 40 ; Y resolution y_res = 24 ; Number of colors colors = 4 ; Pixels per byte ppb = 4 ; Screen memory size in bytes scrsize = x_res * y_res / ppb ; Pixel aspect ratio aspect = $00CC ; based on 4/3 display ; Free memory needed mem_needed = 1 ; Number of screen pages pages = 1 .rodata mask_table: ; Mask table to set pixels .byte %11000000, %00110000, %00001100, %00000011 masks: ; Color masks .byte %00000000, %01010101, %10101010, %11111111 bar_table: ; Mask table for BAR .byte %11111111, %00111111, %00001111, %00000011, %00000000 default_palette: .byte $00, $0E, $32, $96 .code ; ****************************************************************************** .proc SETPALETTE ; ---------------------------------------------------------------------- ; ; SETPALETTE: Set the palette (in ptr1) ; ; ---------------------------------------------------------------------- .code ; Copy the palette ldy #colors - 1 loop: lda (ptr1),y sta palette,y dey bpl loop ; Get the color entries from the palette lda palette sta COLOR4 lda palette + 1 sta COLOR0 lda palette + 2 sta COLOR1 lda palette + 3 sta COLOR2 ; Done, reset the error code lda #TGI_ERR_OK sta error rts .endproc .include "atari_tgi_common.inc" ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/tgi/atr4.s�������������������������������������������������������������������0000664�0000000�0000000�00000004441�13473601511�0016407�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Graphics driver for the 80x48x2 (CIO mode 4, ANTIC mode 9) on the Atari. ; ; Fatih Aygun (2009) ; .include "atari.inc" .include "zeropage.inc" .include "tgi-kernel.inc" .include "tgi-error.inc" .macpack generic ; ****************************************************************************** ; ---------------------------------------------------------------------- ; ; Constants and tables ; ; ---------------------------------------------------------------------- ; Graphics mode grmode = 4 ; X resolution x_res = 80 ; Y resolution y_res = 48 ; Number of colors colors = 2 ; Pixels per byte ppb = 8 ; Screen memory size in bytes scrsize = x_res * y_res / ppb ; Pixel aspect ratio aspect = $00CC ; based on 4/3 display ; Free memory needed mem_needed = 1 ; Number of screen pages pages = 1 .rodata mask_table: ; Mask table to set pixels .byte %10000000, %01000000, %00100000, %00010000, %00001000, %00000100, %00000010, %00000001 masks: ; Color masks .byte %00000000, %11111111 bar_table: ; Mask table for BAR .byte %11111111, %01111111, %00111111, %00011111, %00001111, %00000111, %00000011, %00000001, %00000000 default_palette: .byte $00, $0E .code ; ****************************************************************************** .proc SETPALETTE ; ---------------------------------------------------------------------- ; ; SETPALETTE: Set the palette (in ptr1) ; ; ---------------------------------------------------------------------- .code ; Copy the palette ldy #colors - 1 loop: lda (ptr1),y sta palette,y dey bpl loop ; Get the color entries from the palette lda palette sta COLOR4 lda palette + 1 sta COLOR0 ; Done, reset the error code lda #TGI_ERR_OK sta error rts .endproc .include "atari_tgi_common.inc" �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/tgi/atr5.s�������������������������������������������������������������������0000664�0000000�0000000�00000004521�13473601511�0016407�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Graphics driver for the 80x48x4 (CIO mode 5, ANTIC mode A) on the Atari. ; ; Fatih Aygun (2009) ; .include "atari.inc" .include "zeropage.inc" .include "tgi-kernel.inc" .include "tgi-error.inc" .macpack generic ; ****************************************************************************** ; ---------------------------------------------------------------------- ; ; Constants and tables ; ; ---------------------------------------------------------------------- ; Graphics mode grmode = 5 ; X resolution x_res = 80 ; Y resolution y_res = 48 ; Number of colors colors = 4 ; Pixels per byte ppb = 4 ; Screen memory size in bytes scrsize = x_res * y_res / ppb ; Pixel aspect ratio aspect = $00CC ; based on 4/3 display ; Free memory needed mem_needed = 185 ; Number of screen pages pages = 1 .rodata mask_table: ; Mask table to set pixels .byte %11000000, %00110000, %00001100, %00000011 masks: ; Color masks .byte %00000000, %01010101, %10101010, %11111111 bar_table: ; Mask table for BAR .byte %11111111, %00111111, %00001111, %00000011, %00000000 default_palette: .byte $00, $0E, $32, $96 .code ; ****************************************************************************** .proc SETPALETTE ; ---------------------------------------------------------------------- ; ; SETPALETTE: Set the palette (in ptr1) ; ; ---------------------------------------------------------------------- .code ; Copy the palette ldy #colors - 1 loop: lda (ptr1),y sta palette,y dey bpl loop ; Get the color entries from the palette lda palette sta COLOR4 lda palette + 1 sta COLOR0 lda palette + 2 sta COLOR1 lda palette + 3 sta COLOR2 ; Done, reset the error code lda #TGI_ERR_OK sta error rts .endproc .include "atari_tgi_common.inc" �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/tgi/atr6.s�������������������������������������������������������������������0000664�0000000�0000000�00000004446�13473601511�0016416�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Graphics driver for the 160x96x2 (CIO mode 6, ANTIC mode B) on the Atari. ; ; Fatih Aygun (2009) ; .include "atari.inc" .include "zeropage.inc" .include "tgi-kernel.inc" .include "tgi-error.inc" .macpack generic ; ****************************************************************************** ; ---------------------------------------------------------------------- ; ; Constants and tables ; ; ---------------------------------------------------------------------- ; Graphics mode grmode = 6 ; X resolution x_res = 160 ; Y resolution y_res = 96 ; Number of colors colors = 2 ; Pixels per byte ppb = 8 ; Screen memory size in bytes scrsize = x_res * y_res / ppb ; Pixel aspect ratio aspect = $00CC ; based on 4/3 display ; Free memory needed mem_needed = 1193 ; Number of screen pages pages = 1 .rodata mask_table: ; Mask table to set pixels .byte %10000000, %01000000, %00100000, %00010000, %00001000, %00000100, %00000010, %00000001 masks: ; Color masks .byte %00000000, %11111111 bar_table: ; Mask table for BAR .byte %11111111, %01111111, %00111111, %00011111, %00001111, %00000111, %00000011, %00000001, %00000000 default_palette: .byte $00, $0E .code ; ****************************************************************************** .proc SETPALETTE ; ---------------------------------------------------------------------- ; ; SETPALETTE: Set the palette (in ptr1) ; ; ---------------------------------------------------------------------- .code ; Copy the palette ldy #colors - 1 loop: lda (ptr1),y sta palette,y dey bpl loop ; Get the color entries from the palette lda palette sta COLOR4 lda palette + 1 sta COLOR0 ; Done, reset the error code lda #TGI_ERR_OK sta error rts .endproc .include "atari_tgi_common.inc" ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/tgi/atr7.s�������������������������������������������������������������������0000664�0000000�0000000�00000004524�13473601511�0016414�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Graphics driver for the 160x96x4 (CIO mode 7, ANTIC mode D) on the Atari. ; ; Fatih Aygun (2009) ; .include "atari.inc" .include "zeropage.inc" .include "tgi-kernel.inc" .include "tgi-error.inc" .macpack generic ; ****************************************************************************** ; ---------------------------------------------------------------------- ; ; Constants and tables ; ; ---------------------------------------------------------------------- ; Graphics mode grmode = 7 ; X resolution x_res = 160 ; Y resolution y_res = 96 ; Number of colors colors = 4 ; Pixels per byte ppb = 4 ; Screen memory size in bytes scrsize = x_res * y_res / ppb ; Pixel aspect ratio aspect = $00CC ; based on 4/3 display ; Free memory needed mem_needed = 3209 ; Number of screen pages pages = 1 .rodata mask_table: ; Mask table to set pixels .byte %11000000, %00110000, %00001100, %00000011 masks: ; Color masks .byte %00000000, %01010101, %10101010, %11111111 bar_table: ; Mask table for BAR .byte %11111111, %00111111, %00001111, %00000011, %00000000 default_palette: .byte $00, $0E, $32, $96 .code ; ****************************************************************************** .proc SETPALETTE ; ---------------------------------------------------------------------- ; ; SETPALETTE: Set the palette (in ptr1) ; ; ---------------------------------------------------------------------- .code ; Copy the palette ldy #colors - 1 loop: lda (ptr1),y sta palette,y dey bpl loop ; Get the color entries from the palette lda palette sta COLOR4 lda palette + 1 sta COLOR0 lda palette + 2 sta COLOR1 lda palette + 3 sta COLOR2 ; Done, reset the error code lda #TGI_ERR_OK sta error rts .endproc .include "atari_tgi_common.inc" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/tgi/atr8.s�������������������������������������������������������������������0000664�0000000�0000000�00000004447�13473601511�0016421�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Graphics driver for the 320x192x2 (CIO mode 8, ANTIC mode F) on the Atari. ; ; Fatih Aygun (2009) ; .include "atari.inc" .include "zeropage.inc" .include "tgi-kernel.inc" .include "tgi-error.inc" .macpack generic ; ****************************************************************************** ; ---------------------------------------------------------------------- ; ; Constants and tables ; ; ---------------------------------------------------------------------- ; Graphics mode grmode = 8 ; X resolution x_res = 320 ; Y resolution y_res = 192 ; Number of colors colors = 2 ; Pixels per byte ppb = 8 ; Screen memory size in bytes scrsize = x_res * y_res / ppb ; Pixel aspect ratio aspect = $00CC ; based on 4/3 display ; Free memory needed mem_needed = 7147 ; Number of screen pages pages = 1 .rodata mask_table: ; Mask table to set pixels .byte %10000000, %01000000, %00100000, %00010000, %00001000, %00000100, %00000010, %00000001 masks: ; Color masks .byte %00000000, %11111111 bar_table: ; Mask table for BAR .byte %11111111, %01111111, %00111111, %00011111, %00001111, %00000111, %00000011, %00000001, %00000000 default_palette: .byte $00, $0E .code ; ****************************************************************************** .proc SETPALETTE ; ---------------------------------------------------------------------- ; ; SETPALETTE: Set the palette (in ptr1) ; ; ---------------------------------------------------------------------- .code ; Copy the palette ldy #colors - 1 loop: lda (ptr1),y sta palette,y dey bpl loop ; Get the color entries from the palette lda palette sta COLOR2 lda palette + 1 sta COLOR1 ; Done, reset the error code lda #TGI_ERR_OK sta error rts .endproc .include "atari_tgi_common.inc" �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/tgi/atr8p2.s�����������������������������������������������������������������0000664�0000000�0000000�00000004450�13473601511�0016655�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Graphics driver for the 320x192x2 (CIO mode 8, ANTIC mode F) on the Atari. ; ; Fatih Aygun (2009) ; .include "atari.inc" .include "zeropage.inc" .include "tgi-kernel.inc" .include "tgi-error.inc" .macpack generic ; ****************************************************************************** ; ---------------------------------------------------------------------- ; ; Constants and tables ; ; ---------------------------------------------------------------------- ; Graphics mode grmode = 8 ; X resolution x_res = 320 ; Y resolution y_res = 192 ; Number of colors colors = 2 ; Pixels per byte ppb = 8 ; Screen memory size in bytes scrsize = x_res * y_res / ppb ; Pixel aspect ratio aspect = $00CC ; based on 4/3 display ; Free memory needed mem_needed = 15339 ; Number of screen pages pages = 2 .rodata mask_table: ; Mask table to set pixels .byte %10000000, %01000000, %00100000, %00010000, %00001000, %00000100, %00000010, %00000001 masks: ; Color masks .byte %00000000, %11111111 bar_table: ; Mask table for BAR .byte %11111111, %01111111, %00111111, %00011111, %00001111, %00000111, %00000011, %00000001, %00000000 default_palette: .byte $00, $0E .code ; ****************************************************************************** .proc SETPALETTE ; ---------------------------------------------------------------------- ; ; SETPALETTE: Set the palette (in ptr1) ; ; ---------------------------------------------------------------------- .code ; Copy the palette ldy #colors - 1 loop: lda (ptr1),y sta palette,y dey bpl loop ; Get the color entries from the palette lda palette sta COLOR2 lda palette + 1 sta COLOR1 ; Done, reset the error code lda #TGI_ERR_OK sta error rts .endproc .include "atari_tgi_common.inc" ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/tgi/atr9.s�������������������������������������������������������������������0000664�0000000�0000000�00000004013�13473601511�0016407�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Graphics driver for the 80x192x16b (CIO mode 9, ANTIC mode F, GTIA mode $40) on the Atari. ; ; Fatih Aygun (2009) ; .include "atari.inc" .include "zeropage.inc" .include "tgi-kernel.inc" .include "tgi-error.inc" .macpack generic ; ****************************************************************************** ; ---------------------------------------------------------------------- ; ; Constants and tables ; ; ---------------------------------------------------------------------- ; Graphics mode grmode = 9 ; X resolution x_res = 80 ; Y resolution y_res = 192 ; Number of colors colors = 16 ; Pixels per byte ppb = 2 ; Screen memory size in bytes scrsize = x_res * y_res / ppb ; Pixel aspect ratio aspect = $0330 ; based on 4/3 display ; Free memory needed mem_needed = 7147 ; Number of screen pages pages = 1 .rodata mask_table: ; Mask table to set pixels .byte %11110000, %00001111 masks: ; Color masks .byte $00, $11, $22, $33, $44, $55, $66, $77, $88, $99, $aa, $bb, $cc, $dd, $ee, $ff bar_table: ; Mask table for BAR .byte %11111111, %00001111, %00000000 default_palette: .byte $00, $0F, $01, $02, $03, $04, $05, $06, $07, $08, $09, $0A, $0B, $0C, $0D, $0E .code ; ****************************************************************************** .proc SETPALETTE ; ---------------------------------------------------------------------- ; ; SETPALETTE: Set the palette (in ptr1) ; ; ---------------------------------------------------------------------- .code ; No palettes lda #TGI_ERR_INV_FUNC sta error rts .endproc .include "atari_tgi_common.inc" ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/tgi/atr9p2.s�����������������������������������������������������������������0000664�0000000�0000000�00000004014�13473601511�0016652�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Graphics driver for the 80x192x16b (CIO mode 9, ANTIC mode F, GTIA mode $40) on the Atari. ; ; Fatih Aygun (2009) ; .include "atari.inc" .include "zeropage.inc" .include "tgi-kernel.inc" .include "tgi-error.inc" .macpack generic ; ****************************************************************************** ; ---------------------------------------------------------------------- ; ; Constants and tables ; ; ---------------------------------------------------------------------- ; Graphics mode grmode = 9 ; X resolution x_res = 80 ; Y resolution y_res = 192 ; Number of colors colors = 16 ; Pixels per byte ppb = 2 ; Screen memory size in bytes scrsize = x_res * y_res / ppb ; Pixel aspect ratio aspect = $0330 ; based on 4/3 display ; Free memory needed mem_needed = 15339 ; Number of screen pages pages = 2 .rodata mask_table: ; Mask table to set pixels .byte %11110000, %00001111 masks: ; Color masks .byte $00, $11, $22, $33, $44, $55, $66, $77, $88, $99, $aa, $bb, $cc, $dd, $ee, $ff bar_table: ; Mask table for BAR .byte %11111111, %00001111, %00000000 default_palette: .byte $00, $0F, $01, $02, $03, $04, $05, $06, $07, $08, $09, $0A, $0B, $0C, $0D, $0E .code ; ****************************************************************************** .proc SETPALETTE ; ---------------------------------------------------------------------- ; ; SETPALETTE: Set the palette (in ptr1) ; ; ---------------------------------------------------------------------- .code ; No palettes lda #TGI_ERR_INV_FUNC sta error rts .endproc .include "atari_tgi_common.inc" ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/tgi_stat_stddrv.s������������������������������������������������������������0000664�0000000�0000000�00000000611�13473601511�0020151�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Address of the static standard tgi driver ; ; Oliver Schmidt, 2012-11-01 ; ; const void tgi_static_stddrv[]; ; .export _tgi_static_stddrv .ifdef __ATARIXL__ .import _atrx8_tgi .else .import _atr8_tgi .endif .rodata .ifdef __ATARIXL__ _tgi_static_stddrv := _atrx8_tgi .else _tgi_static_stddrv := _atr8_tgi .endif �����������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/tgi_stddrv.s�����������������������������������������������������������������0000664�0000000�0000000�00000000426�13473601511�0017122�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Name of the standard tgi driver ; ; Oliver Schmidt, 2011-05-02 ; ; const char tgi_stddrv[]; ; .export _tgi_stddrv .rodata _tgi_stddrv: .ifdef __ATARIXL__ .asciiz "atrx8.tgi" .else .asciiz "atr8.tgi" .endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/toascii.s��������������������������������������������������������������������0000664�0000000�0000000�00000000425�13473601511�0016403�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; unsigned char __fastcall__ toascii (unsigned char c); ; /* Convert a target specific character to ascii */ ; .export _toascii .proc _toascii ; Clear the inverse video bit and #$7F ; X must be zero on return ldx #0 ; Done! rts .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/ucase_fn.s�������������������������������������������������������������������0000664�0000000�0000000�00000006332�13473601511�0016536�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, Dec-2001 ; ; ucase_fn ; helper routine to convert a string (file name) to uppercase ; used by open.s and remove.s ; ; Calling parameters: ; AX - points to filename ; tmp2 - 0/$80 for don't/do prepend default device if no device ; is present in the passed string (only .ifdef DEFAULT_DEVICE) ; Return parameters: ; C - 0/1 for OK/Error (filename too long) ; AX - points to uppercased version of the filename on the stack ; tmp3 - amount of bytes used on the stack (needed for cleanup) ; Uses: ; ptr4 - scratch pointer used to remember original AX pointer ; ; .include "atari.inc" .ifdef DEFAULT_DEVICE .importzp tmp2 .import __defdev .endif .importzp tmp3,ptr4,sp .import subysp,addysp .export ucase_fn .proc ucase_fn ; we make sure that the filename doesn't contain lowercase letters ; we copy the filename we got onto the stack, uppercase it and use this ; one to open the iocb ; we're using tmp3, ptr4 ; save the original pointer sta ptr4 stx ptr4+1 .ifdef DEFAULT_DEVICE lda tmp2 beq hasdev ; don't fiddle with device part ; bit #0 of tmp2 is used as an additional flag whether device name is present in passed string (1 = present, 0 = not present) ldy #1 inc tmp2 ; initialize flag: device present lda #':' cmp (ptr4),y beq hasdev iny cmp (ptr4),y beq hasdev dec tmp2 ; set flag: no device in passed string hasdev: .endif ldy #128 sty tmp3 ; save size jsr subysp ; make room on the stack ; copy filename to the temp. place on the stack, while uppercasing it ldy #0 loop2: lda (ptr4),y sta (sp),y beq copy_end bmi L1 ; Not lowercase (also, invalid, should reject) cmp #'a' bcc L1 ; Not lowercase and #$DF ; make upper case char, assume ASCII chars sta (sp),y ; store back L1: iny bpl loop2 ; bpl: this way we only support a max. length of 127 ; Filename too long jsr addysp ; restore the stack sec ; indicate error rts copy_end: .ifdef DEFAULT_DEVICE lda #1 bit tmp2 ; is a device present in the string? bne hasdev2 ; yes, don't prepend something bpl hasdev2 ; check input parameter (tmp2 != $80) ldy #128+3 ; no, prepend "Dn:" (__defdev) sty tmp3 ; adjust stack size used ldy #3 jsr subysp ; adjust stack pointer dey cpdev: lda __defdev,y sta (sp),y ; insert device name, number and ':' dey bpl cpdev hasdev2: .endif ; leave A and X pointing to the modified filename lda sp ldx sp+1 clc ; indicate success rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/wherex.s���������������������������������������������������������������������0000664�0000000�0000000�00000000274�13473601511�0016254�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Carsten Strotmann, 30.12.2002 ; ; unsigned char wherex (void); ; .export _wherex .include "atari.inc" _wherex: lda COLCRS ldx #0 rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/wherey.s���������������������������������������������������������������������0000664�0000000�0000000�00000000274�13473601511�0016255�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Carsten Strotmann, 30.12.2002 ; ; unsigned char wherey (void); ; .export _wherey .include "atari.inc" _wherey: lda ROWCRS ldx #0 rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/write.s����������������������������������������������������������������������0000664�0000000�0000000�00000001425�13473601511�0016103�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; int __fastcall__ write (int fd, const void* buf, unsigned count); ; .include "atari.inc" .import __rwsetup,__do_oserror,__inviocb,__oserror .export _write _write: jsr __rwsetup ; do common setup beq write9 ; if size 0, it's a no-op cpx #$FF ; invalid iocb? beq _inviocb lda #PUTCHR sta ICCOM,x jsr CIOV bpl write9 jmp __do_oserror ; update errno write9: lda ICBLL,x ; get buf len low pha lda ICBLH,x ; buf len high tax lda #0 sta __oserror ; clear system dependend error code pla rts _inviocb: jmp __inviocb �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari/xlmemchk.inc�����������������������������������������������������������������0000664�0000000�0000000�00000006125�13473601511�0017072�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, Jun-2013 ; ; This routine is used in preparation to move the screen memory ; in front of the program. ; ; It calculates the value to put into RAMTOP for a subsequent ; "GRAPHICS 0" call, and the lowest address which will be used ; by the screen memory afterwards. ; ; inputs: ; __STARTADDRESS__ - load address of the program ; outputs: ; lodadr - (high byte only) value to ; write into RAMTOP ; lowadr - lowest address occupied by ; screen data ; ; When setting a display mode, the ROM takes the RAMTOP value ; and subtracts the size of the screen memory from it. This will ; become the new screen memory address. ; From this address it subtracts the size of the display list. ; This will become the new display list address. ; Screen memory cannot cross 4K boundaries and a display list ; cannot cross a 1K boundary. ; ; Work out a sane value for RAMTOP to prevent boundary crossing. ; RAMTOP is only one byte, it counts in memory pages. ; ; The ROM doesn't do this boundary checking, since it doesn't ; expect RAMTOP to have (rather) arbitrary values. For a ; "GRAPHICS 0" call and RAMTOP representing the possible physically ; available memory, boundary crossing cannot happen. SCRBUFSZ = (40 * 24) ; size of mode 0 screen buffer DLSZ = 32 ; size of mode 0 display list scrmemtst: ; subtract screen memory size from our load address lda lodadr sec sbc #<SCRBUFSZ sta tstadr lda lodadr+1 sbc #>SCRBUFSZ sta tstadr+1 ; check if a 4K boundary is crossed lda lodadr+1 and #$f0 sta tmp lda tstadr+1 and #$f0 cmp tmp beq scrmemok ; if lodadr is at an exact 4K boundary, it's still ok lda lodadr+1 and #$0f beq scrmemok ; 4K boundary will be crossed, use this 4K boundary address as lodadr al4k: lda lodadr+1 and #$f0 sta lodadr+1 bne scrmemtst ; not reached .ifdef DEBUG .byte "XLMEMCHK:>" .endif lodadr: .word __STARTADDRESS__ & $FF00 ; our program's load address, rounded down to page boundary tstadr: .res 2 lowadr: .res 2 tmp: .res 1 ; subtract display list size from calculated screen address scrmemok: lda tstadr sec sbc #<DLSZ sta lowadr lda tstadr+1 sbc #>DLSZ sta lowadr+1 .if 0 ; this cannot happen ; check if a 1K boundary is crossed lda tstadr+1 and #$fc sta tmp lda lowadr+1 and #$fc cmp tmp bne al4k ; 1K boundary will be crossed, decrease lodadr .endif ; address of display list is ok ; decrease lowadr by two lda lowadr sec sbc #2 sta lowadr bcs dec_cont dec lowadr+1 dec_cont: �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari2600/�������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015073�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari2600/crt0.s�������������������������������������������������������������������0000664�0000000�0000000�00000002071�13473601511�0016127�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; Atari VCS 2600 startup code for cc65 ; ; Florent Flament (contact@florentflament.com), 2017 .export _exit .export __STARTUP__ : absolute = 1 .import __RAM_START__, __RAM_SIZE__ .import copydata .import _main .include "zeropage.inc" .segment "STARTUP" start: ; Clear decimal mode cld ; Initialization Loop: ; * Clears Atari 2600 whole memory (128 bytes) including BSS segment ; * Clears TIA registers ; * Sets system stack pointer to $ff (i.e top of zero-page) ldx #0 txa clearLoop: dex txs pha bne clearLoop ; Initialize data jsr copydata ; Initialize C stack pointer lda #<(__RAM_START__ + __RAM_SIZE__) ldx #>(__RAM_START__ + __RAM_SIZE__) sta sp stx sp+1 ; Call main jsr _main _exit: jmp _exit .segment "VECTORS" .word start ; NMI .word start ; Reset .word start ; IRQ �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari2600/ctype.s������������������������������������������������������������������0000664�0000000�0000000�00000020742�13473601511�0016410�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-10-10 ; ; Character specification table. ; .include "ctype.inc" ; The tables are readonly, put them into the rodata segment .rodata ; The following 256 byte wide table specifies attributes for the isxxx type ; of functions. Doing it by a table means some overhead in space, but it ; has major advantages: ; ; * It is fast. If it weren't for the slow parameter passing of cc65, one ; could even define macros for the isxxx functions (this is usually ; done on other platforms). ; ; * It is highly portable. The only unportable part is the table itself, ; all real code goes into the common library. ; ; * We save some code in the isxxx functions. __ctype: .byte CT_CTRL ; 0/00 ___ctrl_@___ .byte CT_CTRL ; 1/01 ___ctrl_A___ .byte CT_CTRL ; 2/02 ___ctrl_B___ .byte CT_CTRL ; 3/03 ___ctrl_C___ .byte CT_CTRL ; 4/04 ___ctrl_D___ .byte CT_CTRL ; 5/05 ___ctrl_E___ .byte CT_CTRL ; 6/06 ___ctrl_F___ .byte CT_CTRL ; 7/07 ___ctrl_G___ .byte CT_CTRL ; 8/08 ___ctrl_H___ .byte CT_CTRL | CT_OTHER_WS | CT_SPACE_TAB ; 9/09 ___ctrl_I___ .byte CT_CTRL | CT_OTHER_WS ; 10/0a ___ctrl_J___ .byte CT_CTRL | CT_OTHER_WS ; 11/0b ___ctrl_K___ .byte CT_CTRL | CT_OTHER_WS ; 12/0c ___ctrl_L___ .byte CT_CTRL | CT_OTHER_WS ; 13/0d ___ctrl_M___ .byte CT_CTRL ; 14/0e ___ctrl_N___ .byte CT_CTRL ; 15/0f ___ctrl_O___ .byte CT_CTRL ; 16/10 ___ctrl_P___ .byte CT_CTRL ; 17/11 ___ctrl_Q___ .byte CT_CTRL ; 18/12 ___ctrl_R___ .byte CT_CTRL ; 19/13 ___ctrl_S___ .byte CT_CTRL ; 20/14 ___ctrl_T___ .byte CT_CTRL ; 21/15 ___ctrl_U___ .byte CT_CTRL ; 22/16 ___ctrl_V___ .byte CT_CTRL ; 23/17 ___ctrl_W___ .byte CT_CTRL ; 24/18 ___ctrl_X___ .byte CT_CTRL ; 25/19 ___ctrl_Y___ .byte CT_CTRL ; 26/1a ___ctrl_Z___ .byte CT_CTRL ; 27/1b ___ctrl_[___ .byte CT_CTRL ; 28/1c ___ctrl_\___ .byte CT_CTRL ; 29/1d ___ctrl_]___ .byte CT_CTRL ; 30/1e ___ctrl_^___ .byte CT_CTRL ; 31/1f ___ctrl_____ .byte CT_SPACE | CT_SPACE_TAB ; 32/20 ___SPACE___ .byte CT_NONE ; 33/21 _____!_____ .byte CT_NONE ; 34/22 _____"_____ .byte CT_NONE ; 35/23 _____#_____ .byte CT_NONE ; 36/24 _____$_____ .byte CT_NONE ; 37/25 _____%_____ .byte CT_NONE ; 38/26 _____&_____ .byte CT_NONE ; 39/27 _____'_____ .byte CT_NONE ; 40/28 _____(_____ .byte CT_NONE ; 41/29 _____)_____ .byte CT_NONE ; 42/2a _____*_____ .byte CT_NONE ; 43/2b _____+_____ .byte CT_NONE ; 44/2c _____,_____ .byte CT_NONE ; 45/2d _____-_____ .byte CT_NONE ; 46/2e _____._____ .byte CT_NONE ; 47/2f _____/_____ .byte CT_DIGIT | CT_XDIGIT ; 48/30 _____0_____ .byte CT_DIGIT | CT_XDIGIT ; 49/31 _____1_____ .byte CT_DIGIT | CT_XDIGIT ; 50/32 _____2_____ .byte CT_DIGIT | CT_XDIGIT ; 51/33 _____3_____ .byte CT_DIGIT | CT_XDIGIT ; 52/34 _____4_____ .byte CT_DIGIT | CT_XDIGIT ; 53/35 _____5_____ .byte CT_DIGIT | CT_XDIGIT ; 54/36 _____6_____ .byte CT_DIGIT | CT_XDIGIT ; 55/37 _____7_____ .byte CT_DIGIT | CT_XDIGIT ; 56/38 _____8_____ .byte CT_DIGIT | CT_XDIGIT ; 57/39 _____9_____ .byte CT_NONE ; 58/3a _____:_____ .byte CT_NONE ; 59/3b _____;_____ .byte CT_NONE ; 60/3c _____<_____ .byte CT_NONE ; 61/3d _____=_____ .byte CT_NONE ; 62/3e _____>_____ .byte CT_NONE ; 63/3f _____?_____ .byte CT_NONE ; 64/40 _____@_____ .byte CT_UPPER | CT_XDIGIT ; 65/41 _____A_____ .byte CT_UPPER | CT_XDIGIT ; 66/42 _____B_____ .byte CT_UPPER | CT_XDIGIT ; 67/43 _____C_____ .byte CT_UPPER | CT_XDIGIT ; 68/44 _____D_____ .byte CT_UPPER | CT_XDIGIT ; 69/45 _____E_____ .byte CT_UPPER | CT_XDIGIT ; 70/46 _____F_____ .byte CT_UPPER ; 71/47 _____G_____ .byte CT_UPPER ; 72/48 _____H_____ .byte CT_UPPER ; 73/49 _____I_____ .byte CT_UPPER ; 74/4a _____J_____ .byte CT_UPPER ; 75/4b _____K_____ .byte CT_UPPER ; 76/4c _____L_____ .byte CT_UPPER ; 77/4d _____M_____ .byte CT_UPPER ; 78/4e _____N_____ .byte CT_UPPER ; 79/4f _____O_____ .byte CT_UPPER ; 80/50 _____P_____ .byte CT_UPPER ; 81/51 _____Q_____ .byte CT_UPPER ; 82/52 _____R_____ .byte CT_UPPER ; 83/53 _____S_____ .byte CT_UPPER ; 84/54 _____T_____ .byte CT_UPPER ; 85/55 _____U_____ .byte CT_UPPER ; 86/56 _____V_____ .byte CT_UPPER ; 87/57 _____W_____ .byte CT_UPPER ; 88/58 _____X_____ .byte CT_UPPER ; 89/59 _____Y_____ .byte CT_UPPER ; 90/5a _____Z_____ .byte CT_NONE ; 91/5b _____[_____ .byte CT_NONE ; 92/5c _____\_____ .byte CT_NONE ; 93/5d _____]_____ .byte CT_NONE ; 94/5e _____^_____ .byte CT_NONE ; 95/5f _UNDERLINE_ .byte CT_NONE ; 96/60 ___grave___ .byte CT_LOWER | CT_XDIGIT ; 97/61 _____a_____ .byte CT_LOWER | CT_XDIGIT ; 98/62 _____b_____ .byte CT_LOWER | CT_XDIGIT ; 99/63 _____c_____ .byte CT_LOWER | CT_XDIGIT ; 100/64 _____d_____ .byte CT_LOWER | CT_XDIGIT ; 101/65 _____e_____ .byte CT_LOWER | CT_XDIGIT ; 102/66 _____f_____ .byte CT_LOWER ; 103/67 _____g_____ .byte CT_LOWER ; 104/68 _____h_____ .byte CT_LOWER ; 105/69 _____i_____ .byte CT_LOWER ; 106/6a _____j_____ .byte CT_LOWER ; 107/6b _____k_____ .byte CT_LOWER ; 108/6c _____l_____ .byte CT_LOWER ; 109/6d _____m_____ .byte CT_LOWER ; 110/6e _____n_____ .byte CT_LOWER ; 111/6f _____o_____ .byte CT_LOWER ; 112/70 _____p_____ .byte CT_LOWER ; 113/71 _____q_____ .byte CT_LOWER ; 114/72 _____r_____ .byte CT_LOWER ; 115/73 _____s_____ .byte CT_LOWER ; 116/74 _____t_____ .byte CT_LOWER ; 117/75 _____u_____ .byte CT_LOWER ; 118/76 _____v_____ .byte CT_LOWER ; 119/77 _____w_____ .byte CT_LOWER ; 120/78 _____x_____ .byte CT_LOWER ; 121/79 _____y_____ .byte CT_LOWER ; 122/7a _____z_____ .byte CT_NONE ; 123/7b _____{_____ .byte CT_NONE ; 124/7c _____|_____ .byte CT_NONE ; 125/7d _____}_____ .byte CT_NONE ; 126/7e _____~_____ .byte CT_OTHER_WS ; 127/7f ____DEL____ .res 128, CT_NONE ; 128-255 ������������������������������cc65-2.18/libsrc/atari5200/�������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015072�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari5200/_scrsize.s���������������������������������������������������������������0000664�0000000�0000000�00000000447�13473601511�0017104�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, 02-Apr-2019 ; ; Screen size variables ; .export screensize .importzp screen_width, screen_height .include "atari.inc" .proc screensize ldx #screen_width ldy #screen_height rts .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari5200/bgcolor.s����������������������������������������������������������������0000664�0000000�0000000�00000000676�13473601511�0016716�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Greg King, 10-Apr-2019 ; .export _bgcolor .include "atari5200.inc" .data old_bg_index: .byte COLOR_BLACK ; see conioscreen.s for default palette .code _bgcolor: and #$03 tax ldy COLOR0,x lda old_bg_index sty COLOR4 ; set new value stx old_bg_index ldx #0 ; fix high byte rts .end ������������������������������������������������������������������cc65-2.18/libsrc/atari5200/cartentry.s��������������������������������������������������������������0000664�0000000�0000000�00000000603�13473601511�0017270�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; Cartridge entry point ; ; Christian Groessler, 01-Mar-2014 .export __CART_ENTRY__: absolute = 1 .import __CARTSIZE__, start .forceimport __CART_YEAR__, __CART_NAME__ .segment "CARTENTRY" .word start ; entry point .assert (__CARTSIZE__ = $4000 || __CARTSIZE__ = $8000), error, "Cartridge size must either be $4000 or $8000" �����������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari5200/cartname.s���������������������������������������������������������������0000664�0000000�0000000�00000000445�13473601511�0017053�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; default cartridge name ; ; Christian Groessler, 01-Mar-2014 .export __CART_NAME__: absolute = 1 .macpack atari .segment "CARTNAME" scrcode " cc" .byte '6' + 32, '5' + 32 ; use playfield 1 scrcode " compiled" ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari5200/cartyear.s���������������������������������������������������������������0000664�0000000�0000000�00000000330�13473601511�0017064�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; Cartridge copyright year ; ; Christian Groessler, 01-Mar-2014 .export __CART_YEAR__: absolute = 1 .segment "CARTYEAR" .byte '9' + 32,'8' + 32 ; "98", but using playfield 1 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari5200/cclear.s�����������������������������������������������������������������0000664�0000000�0000000�00000000035�13473601511�0016505�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������.include "../atari/cclear.s" ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari5200/chline.s�����������������������������������������������������������������0000664�0000000�0000000�00000001421�13473601511�0016516�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 gotoxy, cputdirect .importzp tmp1 .include "atari5200.inc" _chlinexy: pha ; Save the length 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 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari5200/clock.s������������������������������������������������������������������0000664�0000000�0000000�00000001303�13473601511�0016346�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; from Atari computer version by Christian Groessler, 2014 ; ; clock_t clock (void); ; unsigned _clocks_per_sec (void); ; .export _clock .importzp sreg .include "atari5200.inc" .proc _clock ldx #5 ; Synchronize with Antic, so the interrupt won't change RTCLOK stx WSYNC ; while we're reading it. The synchronization is done same as @L1: dex ; in SETVBLV function in Atari OS. bne @L1 stx sreg+1 ; Byte 3 is always zero stx sreg ; Byte 2 is always zero, too lda RTCLOK+1 ldx RTCLOK rts .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari5200/clrscr.s�����������������������������������������������������������������0000664�0000000�0000000�00000001376�13473601511�0016555�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, May-2014 ; ; void clrscr (void); ; .export _clrscr .include "atari5200.inc" .importzp ptr1 SCRSIZE = 480 ; 20x24: size of default conio atari5200 screen _clrscr:lda SAVMSC ; screen memory sta ptr1 lda SAVMSC+1 clc adc #>(SCRSIZE-1) sta ptr1+1 lda #0 ; screen code of space char ldy #<(SCRSIZE-1) ldx #>(SCRSIZE-1) _clr1: sta (ptr1),y dey bne _clr1 sta (ptr1),y dex bmi done dec ptr1+1 dey jmp _clr1 done: sta COLCRS_5200 sta ROWCRS_5200 rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari5200/conioscreen.s������������������������������������������������������������0000664�0000000�0000000�00000004446�13473601511�0017575�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; setup default CONIO screen (20x24, Antic mode 6, BASIC mode 1) ; ; 28-May-2014, Christian Groessler <chris@groessler.org> .include "atari5200.inc" SCREEN_BUF_SIZE = 20 * 24 SCREEN_BUF = $4000 - SCREEN_BUF_SIZE .export screen_setup .export screen_width, screen_height .export conio_color screen_width = 20 screen_height = 24 .segment "ONCE" ; initialize color registers, display list, and screen memory screen_setup: ; initialize SAVMSC lda #<SCREEN_BUF sta SAVMSC lda #>SCREEN_BUF sta SAVMSC+1 ; initialize cursor position lda #0 sta COLCRS_5200 sta ROWCRS_5200 ; clear screen buffer ldy #<(SCREEN_BUF_SIZE-1) ldx #>(SCREEN_BUF_SIZE-1) clrscr: sta (SAVMSC),y dey cpy #$FF bne clrscr dex cpx #$FF bne clrscr ; set default colors lda #GTIA_COLOR_WHITE sta COLOR0 lda #GTIA_COLOR_LIGHTRED sta COLOR1 lda #GTIA_COLOR_LIGHTGREEN sta COLOR2 lda #GTIA_COLOR_BLACK sta COLOR3 sta COLOR4 ; background ; set display list lda #<dlist sta SDLSTL lda #>dlist sta SDLSTH rts .bss conio_color: .res 1 .segment "DLIST" ; display list for 20x24 text mode dlist: .repeat 3 .byte DL_BLK8 .endrepeat .byte DL_CHR20x8x2 | DL_LMS .word SCREEN_BUF .repeat 23 .byte DL_CHR20x8x2 .endrepeat .byte DL_JVB .word dlist ; end of display list .assert ((* >> 10) = (dlist >> 10)), error, "Display list crosses 1K boundary" .end ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari5200/cputc.s������������������������������������������������������������������0000664�0000000�0000000�00000004307�13473601511�0016400�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; adapted from Atari version ; Christian Groessler, 2014 ; ; void cputcxy (unsigned char x, unsigned char y, char c); ; void cputc (char c); ; .include "atari5200.inc" .export _cputcxy, _cputc .export plot, cputdirect, putchar .import gotoxy, _mul20 .import conio_color .importzp screen_width, screen_height .importzp ptr4 .import screen_setup .constructor initconio initconio = screen_setup _cputcxy: pha ; Save C jsr gotoxy ; Set cursor, drop x and y pla ; Restore C _cputc: cmp #$0D ; CR bne L4 lda #0 sta COLCRS_5200 beq plot ; return L4: cmp #$0A ; LF beq newline cmp #ATEOL ; Atari-EOL? beq newline tay rol a rol a rol a rol a and #3 tax tya and #$9F ora ataint,x cputdirect: ; accepts screen code jsr putchar ; advance cursor inc COLCRS_5200 lda COLCRS_5200 cmp #screen_width bcc plot lda #0 sta COLCRS_5200 .export newline newline: inc ROWCRS_5200 lda ROWCRS_5200 cmp #screen_height bne plot lda #0 sta ROWCRS_5200 plot: ldy COLCRS_5200 ldx ROWCRS_5200 rts putchar: pha ; save char lda ROWCRS_5200 jsr _mul20 ; destroys tmp4, carry is cleared adc SAVMSC ; add start of screen memory sta ptr4 txa adc SAVMSC+1 sta ptr4+1 pla ; get char again and #$3F ; clear palette index bits ora conio_color ; use currently selected palette ldy COLCRS_5200 sta (ptr4),y rts .rodata ataint: .byte 64,0,32,96 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari5200/crt0.s�������������������������������������������������������������������0000664�0000000�0000000�00000002172�13473601511�0016130�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Startup code for cc65 (Atari5200 version) ; ; Christian Groessler (chris@groessler.org), 2014 ; .export _exit, start .export __STARTUP__ : absolute = 1 ; Mark as startup .import __RAM_START__, __RAM_SIZE__ .import __RESERVED_MEMORY__ .import initlib, donelib, callmain .import zerobss, copydata .include "zeropage.inc" .include "atari5200.inc" start: ; Clear the BSS data. jsr zerobss ; Initialize the data. jsr copydata ; Set up the stack. lda #<(__RAM_START__ + __RAM_SIZE__ - __RESERVED_MEMORY__) ldx #>(__RAM_START__ + __RAM_SIZE__ - __RESERVED_MEMORY__) sta sp stx sp+1 ; Set argument stack ptr ; Call the module constructors. jsr initlib ; Push the command-line arguments; and, call main(). jsr callmain ; Call the module destructors. This is also the exit() entry. _exit: jsr donelib ; Run module destructors ; A 5200 program isn't supposed to exit. halt: jmp halt ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari5200/ctype.s������������������������������������������������������������������0000664�0000000�0000000�00000000135�13473601511�0016401�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; Character specification table. ; ; same as for "atari" target .include "../atari/ctype.s" �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari5200/cvline.s�����������������������������������������������������������������0000664�0000000�0000000�00000001613�13473601511�0016537�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 08.08.1998 ; ; void cvlinexy (unsigned char x, unsigned char y, unsigned char length); ; void cvline (unsigned char length); ; .include "atari5200.inc" .export _cvlinexy, _cvline .import gotoxy, putchar .importzp tmp1 _cvlinexy: pha ; Save the length 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 COLCRS_5200 pha lda #CH_VLINE ; Vertical bar jsr putchar ; Write, no cursor advance pla sta COLCRS_5200 inc ROWCRS_5200 dec tmp1 bne L1 L9: rts ���������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari5200/extra/�������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0016215�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari5200/extra/conioscreen-20x12.s������������������������������������������������0000664�0000000�0000000�00000004454�13473601511�0021471�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; setup alternative CONIO screen (20x12, Antic mode 7, BASIC mode 2) ; ; 02-Apr-2019, Christian Groessler <chris@groessler.org> .include "atari5200.inc" SCREEN_BUF_SIZE = 20 * 12 SCREEN_BUF = $4000 - SCREEN_BUF_SIZE .export screen_setup .export screen_width, screen_height .export conio_color screen_width = 20 screen_height = 12 .segment "ONCE" ; initialize color registers, display list, and screen memory screen_setup: ; initialize SAVMSC lda #<SCREEN_BUF sta SAVMSC lda #>SCREEN_BUF sta SAVMSC+1 ; initialize cursor position lda #0 sta COLCRS_5200 sta ROWCRS_5200 ; clear screen buffer ldy #<(SCREEN_BUF_SIZE-1) ldx #>(SCREEN_BUF_SIZE-1) clrscr: sta (SAVMSC),y dey cpy #$FF bne clrscr dex cpx #$FF bne clrscr ; set default colors lda #GTIA_COLOR_WHITE sta COLOR0 lda #GTIA_COLOR_LIGHTRED sta COLOR1 lda #GTIA_COLOR_LIGHTGREEN sta COLOR2 lda #GTIA_COLOR_BLACK sta COLOR3 sta COLOR4 ; background ; set display list lda #<dlist sta SDLSTL lda #>dlist sta SDLSTH rts .bss conio_color: .res 1 .segment "DLIST" ; display list for 20x12 text mode dlist: .repeat 3 .byte DL_BLK8 .endrepeat .byte DL_CHR20x16x2 | DL_LMS .word SCREEN_BUF .repeat 11 .byte DL_CHR20x16x2 .endrepeat .byte DL_JVB .word dlist ; end of display list .assert ((* >> 10) = (dlist >> 10)), error, "Display list crosses 1K boundary" .end ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari5200/get_tv.s�����������������������������������������������������������������0000664�0000000�0000000�00000000520�13473601511�0016543�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, 2014 ; ; unsigned char get_tv (void); ; /* Return the video mode the machine is using */ ; .include "get_tv.inc" ;-------------------------------------------------------------------------- ; _get_tv .proc _get_tv lda #<TV::NTSC ldx #>TV::NTSC rts .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari5200/gotox.s������������������������������������������������������������������0000664�0000000�0000000�00000000316�13473601511�0016416�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, 13-Mar-2014 ; ; void gotox (unsigned char x); ; .include "atari5200.inc" .export _gotox _gotox: sta COLCRS_5200 ; Set X rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari5200/gotoxy.s�����������������������������������������������������������������0000664�0000000�0000000�00000000663�13473601511�0016614�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, 13-Mar-2014 ; ; void gotoxy (unsigned char x, unsigned char y); ; .include "atari5200.inc" .export gotoxy, _gotoxy .import popa gotoxy: jsr popa ; Get Y _gotoxy: ; Set the cursor position sta ROWCRS_5200 ; Set Y jsr popa ; Get X sta COLCRS_5200 ; Set X rts �����������������������������������������������������������������������������cc65-2.18/libsrc/atari5200/gotoy.s������������������������������������������������������������������0000664�0000000�0000000�00000000316�13473601511�0016417�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, 13-Mar-2014 ; ; void gotoy (unsigned char y); ; .include "atari5200.inc" .export _gotoy _gotoy: sta ROWCRS_5200 ; Set Y rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari5200/irq.s��������������������������������������������������������������������0000664�0000000�0000000�00000002702�13473601511�0016052�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; IRQ handling (ATARI 5200 version) ; .export initirq, doneirq .import callirq .include "atari5200.inc" ; ------------------------------------------------------------------------ .segment "ONCE" initirq: lda VVBLKD ldx VVBLKD+1 sta IRQInd+1 stx IRQInd+2 ldy #<IRQStub ldx #>IRQStub jmp SETVBV ; ------------------------------------------------------------------------ .code doneirq: ldy IRQInd+1 ldx IRQInd+2 ;jmp SETVBV ; fall thru ; ------------------------------------------------------------------------ ; Set deferred vertical blank interrupt ; logic copied from Atari computer ROM SETVBV: txa ldx #5 sta WSYNC ; waste 20 CPU cycles @1: dex ; to allow VBLANK to happen bne @1 ; if this is line "7C" sta VVBLKD+1 sty VVBLKD rts ; ------------------------------------------------------------------------ .segment "LOWCODE" IRQStub: cld ; Just to be sure jsr callirq ; Call the functions jmp IRQInd ; Jump to the saved IRQ vector ; ------------------------------------------------------------------------ .data IRQInd: jmp $0000 ��������������������������������������������������������������cc65-2.18/libsrc/atari5200/joy/���������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015673�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari5200/joy/atr5200std.s���������������������������������������������������������0000664�0000000�0000000�00000006421�13473601511�0017672�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Standard joystick driver for the Atari 5200. ; ; Christian Groessler, 2014-05-28 ; .include "zeropage.inc" .include "joy-kernel.inc" .include "joy-error.inc" .include "atari5200.inc" .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _atr5200std_joy ; Driver signature .byte $6A, $6F, $79 ; "joy" .byte JOY_API_VERSION ; Driver API version number ; Library reference .addr $0000 ; Jump table. .addr INSTALL .addr UNINSTALL .addr COUNT .addr READJOY .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 #$04 ; enable POT input from the joystick ports, see section "GTIA" in sta CONSOL ; http://www.atarimuseum.com/videogames/consoles/5200/conv_to_5200.html lda #JOY_ERR_OK ldx #0 ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; COUNT: Return the total number of available joysticks in a/x. ; COUNT: lda $FD32 ; check ROM version cmp #$E8 bne @2port lda #4 .byte $2C ; bit opcode, eats the next 2 bytes @2port: lda #2 ldx #0 rts ; ------------------------------------------------------------------------ ; READ: Read a particular joystick passed in A. ; CENTER = 228 / 2 SENSIVITY = 16 READJOY: and #3 ; put joystick number in range, just in case sta jsnum ; remember joystick number tay asl a tax ; Joystick number * 2 (0-6) into X, index into ZP shadow registers lda #0 ; Initialize return value cmp TRIG0,y bne @notrg ora #$10 ; JOY_BTN ; Read joystick @notrg: ldy PADDL0,x ; get horizontal position cpy #CENTER-SENSIVITY bcs @chkleft ora #4 ; JOY_LEFT bne @updown @chkleft: cpy #CENTER+SENSIVITY bcc @updown ora #8 ; JOY_RIGHT @updown:ldy PADDL0+1,x ; get vertical position cpy #CENTER-SENSIVITY bcs @chkdown ora #1 ; JOY_UP bne @done @chkdown: cpy #CENTER+SENSIVITY bcc @done ora #2 ; JOY_DOWN @done: ldx #0 ldy jsnum cmp oldval,y beq @ret sta oldval,y stx ATRACT @ret: rts .bss oldval:.res 4 jsnum: .res 1 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari5200/joy_stat_stddrv.s��������������������������������������������������������0000664�0000000�0000000�00000000350�13473601511�0020476�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Address of the static standard joystick driver ; ; Christian Groessler, 2014-05-12 ; ; const void joy_static_stddrv[]; ; .export _joy_static_stddrv .import _atr5200std_joy _joy_static_stddrv := _atr5200std_joy ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari5200/libref.s�����������������������������������������������������������������0000664�0000000�0000000�00000000202�13473601511�0016513�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, 2014-05-12 ; .export joy_libref .import _exit joy_libref := _exit ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari5200/randomize.s��������������������������������������������������������������0000664�0000000�0000000�00000000664�13473601511�0017254�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, 01-Mar-2014 ; ; void _randomize (void); ; /* Initialize the random number generator */ ; .export __randomize .import _srand .include "atari5200.inc" __randomize: ldx VCOUNT ; Use vertical line counter as high byte lda RTCLOK+1 ; Use clock as low byte jmp _srand ; Initialize generator ����������������������������������������������������������������������������cc65-2.18/libsrc/atari5200/setcursor.s��������������������������������������������������������������0000664�0000000�0000000�00000000310�13473601511�0017301�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; Dummy version, there is no visible cursor in the default CONIO screen ; ; 28-May-2014, Christian Groessler <chris@groessler.org> .export setcursor .proc setcursor rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari5200/sysuname.s���������������������������������������������������������������0000664�0000000�0000000�00000001443�13473601511�0017124�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-08-12 ; ; unsigned char __fastcall__ _sysuname (struct utsname* buf); ; .export __sysuname, utsdata .import utscopy __sysuname = utscopy ;-------------------------------------------------------------------------- ; Data. We define a fixed utsname struct here and just copy it. .rodata utsdata: ; sysname .asciiz "cc65" ; nodename .asciiz "" ; release .byte ((.VERSION >> 8) & $0F) + '0' .byte '.' .byte ((.VERSION >> 4) & $0F) + '0' .byte $00 ; version .byte (.VERSION & $0F) + '0' .byte $00 ; machine .asciiz "Atari5200" �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari5200/textcolor.s��������������������������������������������������������������0000664�0000000�0000000�00000001253�13473601511�0017302�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, 02-Apr-2019 ; ; unsigned char __fastcall__ textcolor (unsigned char color); ; ; "color" value is a palette index (0..3) or COLOR_xxx value (0..3) .export _textcolor .import conio_color _textcolor: ; move bits #0 and #1 to bits #6 and #7 and #3 clc ror a ror a ror a ; new conio_color value ldx conio_color ; get old value sta conio_color ; store new value txa ; move bits #6 and #7 to bits #0 and #1 clc rol a rol a rol a ldx #0 rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari5200/wherex.s�����������������������������������������������������������������0000664�0000000�0000000�00000000305�13473601511�0016556�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Carsten Strotmann, 30.12.2002 ; ; unsigned char wherex (void); ; .export _wherex .include "atari5200.inc" _wherex: lda COLCRS_5200 ldx #0 rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari5200/wherey.s�����������������������������������������������������������������0000664�0000000�0000000�00000000305�13473601511�0016557�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Carsten Strotmann, 30.12.2002 ; ; unsigned char wherey (void); ; .export _wherey .include "atari5200.inc" _wherey: lda ROWCRS_5200 ldx #0 rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atari5200/y2k.inc������������������������������������������������������������������0000664�0000000�0000000�00000002477�13473601511�0016304�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������;----------------------------------------------------------- ; Y2K FIX by Alan Davis, Dennis Debro, and Ronen Habot ;----------------------------------------------------------- Y2K LDY #$00 ; Copy BIOS opening screen to RAM LDA #$FD STA TEMPH LDA #$58 ; Assume 2 port system LDX $FD32 CPX #$E8 ; Is this a 4 port? BNE Y2K0 ; Jump if not LDA #$42 ; Yes, 4 port system Y2K0 STA TEMPL Y2K1 LDA (TEMPL),Y STA $0600,Y INY BNE Y2K1 LDY #$50 INC TEMPH Y2K2 LDA (TEMPL),Y STA $0700,Y DEY BPL Y2K2 LDA #$D4 ; Point to copyright string STA $0724 LDA #$BF STA $0725 LDX #$0B ; Store NOP's @ end LDA #$EA Y2K3 STA $0732,X DEX BPL Y2K3 LDA #$60 ; Store RTS opcode @ end STA $0750 JSR $0600 ; Show title screen LDY #$00 ; Clear RAM from $0600-$3FFF STY $80 LDA #$06 STA $81 JSR CLRRAM RTS �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/�����������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014606�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/_scrsize.s�������������������������������������������������������������������0000664�0000000�0000000�00000000413�13473601511�0016611�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2003-04-13, Ullrich von Bassewitz ; 2013-07-16, Greg King ; ; Screen size variables ; .export screensize .include "atmos.inc" .proc screensize ldx #SCREEN_XSIZE ldy #SCREEN_YSIZE rts .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/atmos.s����������������������������������������������������������������������0000664�0000000�0000000�00000001654�13473601511�0016123�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Expose include-file symbol names to C code. ; .export _atmos_ping, _atmos_shoot, _atmos_explode .export _atmos_zap, _atmos_tick, _atmos_tock .include "atmos.inc" .proc _atmos_ping bit $31 bvs L1 ; Atmos? jmp PING L1: jmp PING1 .endproc .proc _atmos_shoot bit $31 bvs L1 ; Atmos? jmp SHOOT L1: jmp SHOOT1 .endproc .proc _atmos_explode bit $31 bvs L1 ; Atmos? jmp EXPLODE L1: jmp EXPLODE1 .endproc .proc _atmos_zap bit $31 bvs L1 ; Atmos? jmp ZAP L1: jmp ZAP1 .endproc .proc _atmos_tick bit $31 bvs L1 ; Atmos? jmp TICK L1: jmp TICK1 .endproc .proc _atmos_tock bit $31 bvs L1 ; Atmos? jmp TOCK L1: jmp TOCK1 .endproc ������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/atmos_load.s�����������������������������������������������������������������0000664�0000000�0000000�00000001230�13473601511�0017110�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; Based on code by Twilighte. ; 2012-05-06, Stefan Haubenthal ; 2013-07-22, Greg King ; ; void __fastcall__ atmos_load(const char* name); .export _atmos_load .import store_filename .include "atmos.inc" .proc _atmos_load sei jsr store_filename ldx #$00 stx AUTORUN ; don't try to run the file stx LANGFLAG ; BASIC stx JOINFLAG ; don't join it to another BASIC program stx VERIFYFLAG ; load the file jsr cload_bit cli rts cload_bit: pha jmp $e874 .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/atmos_save.s�����������������������������������������������������������������0000664�0000000�0000000�00000001221�13473601511�0017127�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; Based on code by Twilighte. ; 2012-05-06, Stefan Haubenthal ; 2013-07-22, Greg King ; ; void __fastcall__ atmos_save(const char* name, const void* start, const void* end); .export _atmos_save .import popax, store_filename .include "atmos.inc" .proc _atmos_save sei sta FILEEND stx FILEEND+1 jsr popax sta FILESTART stx FILESTART+1 jsr popax jsr store_filename lda #00 sta AUTORUN jsr csave_bit cli rts csave_bit: php jmp $e92c .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/bashdr.s���������������������������������������������������������������������0000664�0000000�0000000�00000002216�13473601511�0016236�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2010-11-14, Ullrich von Bassewitz ; 2016-03-17, Greg King ; ; This module supplies a small BASIC stub program that uses CALL ; to jump to the machine-language code that follows it. ; ; 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: ; ------------------------------------------------------------------------ ; This padding is needed by a bug in the ROM. ; (The CLOAD command starts BASIC's variables table on top of the last byte ; that was loaded [instead of at the next address].) .segment "BASTAIL" .byte 0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/capslock.s�������������������������������������������������������������������0000664�0000000�0000000�00000002225�13473601511�0016572�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; When Oric computers are in BASIC's command mode, the keyboard is in CAPS lock ; mode (because Oric BASIC keywords must be typed in upper-case). This ; constructor disables that mode, so that text will be typed as lower-case ; (which is the default on other cc65 platforms). ; This module is linked by the conio and POSIX input functions. ; ; 2014-09-04, Greg King ; .constructor disable_caps .destructor restore_caps .include "atmos.inc" ;-------------------------------------------------------------------------- ; Put this constructor into a segment whose space ; will be re-used by BSS, the heap, and the C stack. ; .segment "ONCE" ; Turn the capitals lock off. disable_caps: lda CAPSLOCK sta capsave lda #$7F sta CAPSLOCK rts ;-------------------------------------------------------------------------- .code ; Restore the old capitals-lock state. restore_caps: lda capsave sta CAPSLOCK rts ;-------------------------------------------------------------------------- .segment "INIT" capsave: .res 1 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/cclear.s���������������������������������������������������������������������0000664�0000000�0000000�00000002064�13473601511�0016225�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-04-13 ; ; void cclearxy (unsigned char x, unsigned char y, unsigned char length); ; void cclear (unsigned char length); ; .export _cclearxy, _cclear .import setscrptr .import rvs .import popax .importzp ptr2 .include "atmos.inc" _cclearxy: pha ; Save the length jsr popax ; Get X and Y sta CURS_Y ; Store Y stx CURS_X ; Store X pla ; Restore the length and run into _cclear _cclear: tax ; Is the length zero? beq @L9 ; Jump if done jsr setscrptr ; Set ptr2 to screen, won't use X lda #' ' ora rvs @L1: sta (ptr2),y ; Write one char iny ; Next char bne @L2 inc ptr2+1 ; Bump high byte of screen pointer @L2: dex bne @L1 @L9: rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/cgetc.s����������������������������������������������������������������������0000664�0000000�0000000�00000002172�13473601511�0016061�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2003-04-13, Ullrich von Bassewitz ; 2014-09-04, Greg King ; ; char cgetc (void); ; .export _cgetc .import cursor .forceimport disable_caps .include "atmos.inc" ; ------------------------------------------------------------------------ ; .proc _cgetc lda KEYBUF ; Do we have a character? bmi @L2 ; Yes: Get it ; No character, enable cursor and wait lda cursor ; Should cursor be off? beq @L1 ; Skip if so lsr STATUS sec ; Cursor ON rol STATUS @L1: lda KEYBUF bpl @L1 ; If the cursor was enabled, disable it now ldx cursor beq @L2 dec STATUS ; Clear bit zero ; We have the character, clear the "available" flag @L2: and #$7F ; Mask out avail flag sta KEYBUF ldx #>$0000 ldy MODEKEY cpy #FUNCTKEY bne @L3 ora #$80 ; FUNCT-key pressed ; Done @L3: rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/chline.s���������������������������������������������������������������������0000664�0000000�0000000�00000002345�13473601511�0016240�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 setscrptr .import rvs .import popax .importzp ptr2 .include "atmos.inc" _chlinexy: pha ; Save the length jsr popax ; Get X and Y sta CURS_Y ; Store Y stx CURS_X ; Store X pla ; Restore the length and run into _chline _chline: tax ; Is the length zero? beq @L9 ; Jump if done jsr setscrptr ; Set ptr2 to screen, won't use X txa ; Length into A clc adc CURS_X sta CURS_X ; Correct X position by length lda #'-' ; Horizontal line screen code ora rvs @L1: sta (ptr2),y ; Write one char iny ; Next char bne @L2 inc ptr2+1 ; Bump high byte of screen pointer @L2: dex bne @L1 @L9: rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/clock.s����������������������������������������������������������������������0000664�0000000�0000000�00000001112�13473601511�0016060�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-04-13 ; ; clock_t clock (void); ; .export _clock .import negax .importzp sreg .include "atmos.inc" .proc _clock ; Clear the timer high 16 bits ldy #$00 sty sreg sty sreg+1 ; Read the timer sei ; Disable interrupts lda TIMER3 ldx TIMER3+1 cli ; Reenable interrupts ; Since the timer is counting downwards, return the negated value jmp negax .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/clrscr.s���������������������������������������������������������������������0000664�0000000�0000000�00000001751�13473601511�0016266�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2003-04-13, Ullrich von Bassewitz ; 2013-07-16, Greg King ; .export _clrscr .importzp ptr2 .include "atmos.inc" ; ------------------------------------------------------------------------ ; void clrscr (void); .proc _clrscr ; Set the cursor to top left cursor position ldy #$00 sty CURS_X sty CURS_Y ; Set ptr2 to the screen position (left upper border) lda #<SCREEN sta ptr2 lda #>SCREEN sta ptr2+1 ; Clear full pages. Y is still zero ldx #>(SCREEN_YSIZE * SCREEN_XSIZE) lda #' ' @L1: sta (ptr2),y iny ; Bump low byte of address bne @L1 inc ptr2+1 ; Bump high byte of address dex bne @L1 ; Clear the remaining page @L2: sta (ptr2),y iny cpy #<(SCREEN_YSIZE * SCREEN_XSIZE) bne @L2 rts .endproc �����������������������cc65-2.18/libsrc/atmos/color.s����������������������������������������������������������������������0000664�0000000�0000000�00000000634�13473601511�0016113�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-04-13 ; ; 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 .import return0, return1 _textcolor = return1 _bgcolor = return0 _bordercolor = return0 ����������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/cputc.s����������������������������������������������������������������������0000664�0000000�0000000�00000005300�13473601511�0016106�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2003-04-13, Ullrich von Bassewitz ; 2013-07-16, Greg King ; ; void cputcxy (unsigned char x, unsigned char y, char c); ; void cputc (char c); ; .export _cputcxy, _cputc .export setscrptr, putchar .constructor initcputc .import rvs .import popax .importzp ptr2 .include "atmos.inc" _cputcxy: pha ; Save C jsr popax ; Get X and Y sta CURS_Y ; Store Y stx CURS_X ; Store X pla ; Restore C ; Plot a character - also used as internal function _cputc: cmp #$0D ; CR? bne L1 lda #0 sta CURS_X ; Carriage return rts L1: cmp #$0A ; LF? bne output inc CURS_Y ; Newline rts ; Output the character, then advance the cursor position output: jsr putchar advance: iny cpy #SCREEN_XSIZE bne L3 inc CURS_Y ; new line ldy #0 ; + cr L3: sty CURS_X rts ; ------------------------------------------------------------------------ ; Set ptr2 to the screen, load the X offset into Y .code .proc setscrptr ldy CURS_Y ; Get line number into Y lda ScrTabLo,y ; Get low byte of line address sta ptr2 lda ScrTabHi,y ; Get high byte of line address sta ptr2+1 ldy CURS_X ; Get X offset rts .endproc ; ------------------------------------------------------------------------ ; Write one character to the screen without doing anything else, return X ; position in Y .code .proc putchar ora rvs ; Set revers bit pha ; And save jsr setscrptr ; Set ptr2 to the screen pla ; Restore the character sta (ptr2),y ; Set char rts .endproc ; ------------------------------------------------------------------------ ; Screen address table .rodata ScrTabLo: .repeat SCREEN_YSIZE, Line .byte <(SCREEN + Line * SCREEN_XSIZE) .endrep ScrTabHi: .repeat SCREEN_YSIZE, Line .byte >(SCREEN + Line * SCREEN_XSIZE) .endrep ; ------------------------------------------------------------------------ ; Switch the cursor off. Code goes into the ONCE segment, ; which will be reused after it is run. .segment "ONCE" initcputc: lsr STATUS asl STATUS ; Clear bit zero rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/crt0.s�����������������������������������������������������������������������0000664�0000000�0000000�00000004432�13473601511�0015645�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Startup code for cc65 (Oric version) ; ; By Debrune Jérôme <jede@oric.org> and Ullrich von Bassewitz <uz@cc65.org> ; 2016-03-18, Greg King ; .export _exit .export __STARTUP__ : absolute = 1 ; Mark as startup .import initlib, donelib .import callmain, zerobss .import __MAIN_START__, __MAIN_SIZE__ .include "zeropage.inc" .include "atmos.inc" ; ------------------------------------------------------------------------ ; Place the startup code in a special segment. .segment "STARTUP" tsx stx spsave ; Save system stk ptr ; Save space by putting some of the start-up code in a segment ; that will be re-used. jsr init ; Clear the BSS variables (after the constructors have been run). jsr zerobss ; Push the command-line arguments; and, call main(). jsr callmain ; Call the module destructors. This is also the exit() entry. _exit: jsr donelib ; Restore the system stuff. ldx spsave txs lda stsave sta STATUS ; Copy back the zero-page stuff. ldx #zpspace - 1 L2: lda zpsave,x sta sp,x dex bpl L2 ; Back to BASIC. rts ; ------------------------------------------------------------------------ ; Put this code in a place that will be re-used by BSS, the heap, ; and the C stack. .segment "ONCE" ; Save the zero-page area that we're about to use. init: ldx #zpspace - 1 L1: lda sp,x sta zpsave,x dex bpl L1 ; Currently, color isn't supported on the text screen. ; Unprotect screen columns 0 and 1 (where each line's color codes would sit). lda STATUS sta stsave and #%11011111 sta STATUS ; Set up the C stack. lda #<(__MAIN_START__ + __MAIN_SIZE__) ldx #>(__MAIN_START__ + __MAIN_SIZE__) sta sp stx sp+1 ; Set argument stack ptr ; Call the module constructors. jmp initlib ; ------------------------------------------------------------------------ .segment "INIT" spsave: .res 1 stsave: .res 1 zpsave: .res zpspace ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/ctype.s����������������������������������������������������������������������0000664�0000000�0000000�00000030437�13473601511�0016125�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-04-13 ; ; Character specification table. ; ; 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. ; ; ; Bit assignments: ; ; 0 - Lower case char ; 1 - Upper case char ; 2 - Numeric digit ; 3 - Hex digit (both, lower and upper) ; 4 - Control character ; 5 - The space character itself ; 6 - Other whitespace (that is: '\f', '\n', '\r', '\t' and '\v') ; 7 - Space or tab character .export __ctype __ctype: .byte $10 ; 0/00 ___ctrl_@___ .byte $10 ; 1/01 ___ctrl_A___ .byte $10 ; 2/02 ___ctrl_B___ .byte $10 ; 3/03 ___ctrl_C___ .byte $10 ; 4/04 ___ctrl_D___ .byte $10 ; 5/05 ___ctrl_E___ .byte $10 ; 6/06 ___ctrl_F___ .byte $10 ; 7/07 ___ctrl_G___ .byte $10 ; 8/08 ___ctrl_H___ .byte $D0 ; 9/09 ___ctrl_I___ .byte $50 ; 10/0a ___ctrl_J___ .byte $50 ; 11/0b ___ctrl_K___ .byte $50 ; 12/0c ___ctrl_L___ .byte $50 ; 13/0d ___ctrl_M___ .byte $10 ; 14/0e ___ctrl_N___ .byte $10 ; 15/0f ___ctrl_O___ .byte $10 ; 16/10 ___ctrl_P___ .byte $10 ; 17/11 ___ctrl_Q___ .byte $10 ; 18/12 ___ctrl_R___ .byte $10 ; 19/13 ___ctrl_S___ .byte $10 ; 20/14 ___ctrl_T___ .byte $10 ; 21/15 ___ctrl_U___ .byte $10 ; 22/16 ___ctrl_V___ .byte $10 ; 23/17 ___ctrl_W___ .byte $10 ; 24/18 ___ctrl_X___ .byte $10 ; 25/19 ___ctrl_Y___ .byte $10 ; 26/1a ___ctrl_Z___ .byte $10 ; 27/1b ___ctrl_[___ .byte $10 ; 28/1c ___ctrl_\___ .byte $10 ; 29/1d ___ctrl_]___ .byte $10 ; 30/1e ___ctrl_^___ .byte $10 ; 31/1f ___ctrl_____ .byte $A0 ; 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 $0C ; 48/30 _____0_____ .byte $0C ; 49/31 _____1_____ .byte $0C ; 50/32 _____2_____ .byte $0C ; 51/33 _____3_____ .byte $0C ; 52/34 _____4_____ .byte $0C ; 53/35 _____5_____ .byte $0C ; 54/36 _____6_____ .byte $0C ; 55/37 _____7_____ .byte $0C ; 56/38 _____8_____ .byte $0C ; 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 $0A ; 65/41 _____A_____ .byte $0A ; 66/42 _____B_____ .byte $0A ; 67/43 _____C_____ .byte $0A ; 68/44 _____D_____ .byte $0A ; 69/45 _____E_____ .byte $0A ; 70/46 _____F_____ .byte $02 ; 71/47 _____G_____ .byte $02 ; 72/48 _____H_____ .byte $02 ; 73/49 _____I_____ .byte $02 ; 74/4a _____J_____ .byte $02 ; 75/4b _____K_____ .byte $02 ; 76/4c _____L_____ .byte $02 ; 77/4d _____M_____ .byte $02 ; 78/4e _____N_____ .byte $02 ; 79/4f _____O_____ .byte $02 ; 80/50 _____P_____ .byte $02 ; 81/51 _____Q_____ .byte $02 ; 82/52 _____R_____ .byte $02 ; 83/53 _____S_____ .byte $02 ; 84/54 _____T_____ .byte $02 ; 85/55 _____U_____ .byte $02 ; 86/56 _____V_____ .byte $02 ; 87/57 _____W_____ .byte $02 ; 88/58 _____X_____ .byte $02 ; 89/59 _____Y_____ .byte $02 ; 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 ___grave___ .byte $09 ; 97/61 _____a_____ .byte $09 ; 98/62 _____b_____ .byte $09 ; 99/63 _____c_____ .byte $09 ; 100/64 _____d_____ .byte $09 ; 101/65 _____e_____ .byte $09 ; 102/66 _____f_____ .byte $01 ; 103/67 _____g_____ .byte $01 ; 104/68 _____h_____ .byte $01 ; 105/69 _____i_____ .byte $01 ; 106/6a _____j_____ .byte $01 ; 107/6b _____k_____ .byte $01 ; 108/6c _____l_____ .byte $01 ; 109/6d _____m_____ .byte $01 ; 110/6e _____n_____ .byte $01 ; 111/6f _____o_____ .byte $01 ; 112/70 _____p_____ .byte $01 ; 113/71 _____q_____ .byte $01 ; 114/72 _____r_____ .byte $01 ; 115/73 _____s_____ .byte $01 ; 116/74 _____t_____ .byte $01 ; 117/75 _____u_____ .byte $01 ; 118/76 _____v_____ .byte $01 ; 119/77 _____w_____ .byte $01 ; 120/78 _____x_____ .byte $01 ; 121/79 _____y_____ .byte $01 ; 122/7a _____z_____ .byte $00 ; 123/7b _____{_____ .byte $00 ; 124/7c _____|_____ .byte $00 ; 125/7d _____}_____ .byte $00 ; 126/7e _____~_____ .byte $40 ; 127/7f ____DEL____ .byte $00 ; 128/80 ___________ .byte $00 ; 129/81 ___________ .byte $00 ; 130/82 ___________ .byte $00 ; 131/83 ___________ .byte $00 ; 132/84 ___________ .byte $00 ; 133/85 ___________ .byte $00 ; 134/86 ___________ .byte $00 ; 135/87 ___________ .byte $00 ; 136/88 ___________ .byte $00 ; 137/89 ___________ .byte $00 ; 138/8a ___________ .byte $00 ; 139/8b ___________ .byte $00 ; 140/8c ___________ .byte $00 ; 141/8d ___________ .byte $00 ; 142/8e ___________ .byte $00 ; 143/8f ___________ .byte $00 ; 144/90 ___________ .byte $00 ; 145/91 ___________ .byte $00 ; 146/92 ___________ .byte $10 ; 147/93 ___________ .byte $00 ; 148/94 ___________ .byte $00 ; 149/95 ___________ .byte $00 ; 150/96 ___________ .byte $00 ; 151/97 ___________ .byte $00 ; 152/98 ___________ .byte $00 ; 153/99 ___________ .byte $00 ; 154/9a ___________ .byte $00 ; 155/9b ___________ .byte $00 ; 156/9c ___________ .byte $00 ; 157/9d ___________ .byte $00 ; 158/9e ___________ .byte $00 ; 159/9f ___________ .byte $00 ; 160/a0 ___________ .byte $00 ; 161/a1 ___________ .byte $00 ; 162/a2 ___________ .byte $00 ; 163/a3 ___________ .byte $00 ; 164/a4 ___________ .byte $00 ; 165/a5 ___________ .byte $00 ; 166/a6 ___________ .byte $00 ; 167/a7 ___________ .byte $00 ; 168/a8 ___________ .byte $00 ; 169/a9 ___________ .byte $00 ; 170/aa ___________ .byte $00 ; 171/ab ___________ .byte $00 ; 172/ac ___________ .byte $00 ; 173/ad ___________ .byte $00 ; 174/ae ___________ .byte $00 ; 175/af ___________ .byte $00 ; 176/b0 ___________ .byte $00 ; 177/b1 ___________ .byte $00 ; 178/b2 ___________ .byte $00 ; 179/b3 ___________ .byte $00 ; 180/b4 ___________ .byte $00 ; 181/b5 ___________ .byte $00 ; 182/b6 ___________ .byte $00 ; 183/b7 ___________ .byte $00 ; 184/b8 ___________ .byte $00 ; 185/b9 ___________ .byte $00 ; 186/ba ___________ .byte $00 ; 187/bb ___________ .byte $00 ; 188/bc ___________ .byte $00 ; 189/bd ___________ .byte $00 ; 190/be ___________ .byte $00 ; 191/bf ___________ .byte $02 ; 192/c0 ___________ .byte $02 ; 193/c1 ___________ .byte $02 ; 194/c2 ___________ .byte $02 ; 195/c3 ___________ .byte $02 ; 196/c4 ___________ .byte $02 ; 197/c5 ___________ .byte $02 ; 198/c6 ___________ .byte $02 ; 199/c7 ___________ .byte $02 ; 200/c8 ___________ .byte $02 ; 201/c9 ___________ .byte $02 ; 202/ca ___________ .byte $02 ; 203/cb ___________ .byte $02 ; 204/cc ___________ .byte $02 ; 205/cd ___________ .byte $02 ; 206/ce ___________ .byte $02 ; 207/cf ___________ .byte $02 ; 208/d0 ___________ .byte $02 ; 209/d1 ___________ .byte $02 ; 210/d2 ___________ .byte $02 ; 211/d3 ___________ .byte $02 ; 212/d4 ___________ .byte $02 ; 213/d5 ___________ .byte $02 ; 214/d6 ___________ .byte $02 ; 215/d7 ___________ .byte $02 ; 216/d8 ___________ .byte $02 ; 217/d9 ___________ .byte $02 ; 218/da ___________ .byte $02 ; 219/db ___________ .byte $02 ; 220/dc ___________ .byte $02 ; 221/dd ___________ .byte $02 ; 222/de ___________ .byte $00 ; 223/df ___________ .byte $01 ; 224/e0 ___________ .byte $01 ; 225/e1 ___________ .byte $01 ; 226/e2 ___________ .byte $01 ; 227/e3 ___________ .byte $01 ; 228/e4 ___________ .byte $01 ; 229/e5 ___________ .byte $01 ; 230/e6 ___________ .byte $01 ; 231/e7 ___________ .byte $01 ; 232/e8 ___________ .byte $01 ; 233/e9 ___________ .byte $01 ; 234/ea ___________ .byte $01 ; 235/eb ___________ .byte $01 ; 236/ec ___________ .byte $01 ; 237/ed ___________ .byte $01 ; 238/ee ___________ .byte $01 ; 239/ef ___________ .byte $01 ; 240/f0 ___________ .byte $01 ; 241/f1 ___________ .byte $01 ; 242/f2 ___________ .byte $01 ; 243/f3 ___________ .byte $01 ; 244/f4 ___________ .byte $01 ; 245/f5 ___________ .byte $01 ; 246/f6 ___________ .byte $01 ; 247/f7 ___________ .byte $01 ; 248/f8 ___________ .byte $01 ; 249/f9 ___________ .byte $01 ; 250/fa ___________ .byte $01 ; 251/fb ___________ .byte $01 ; 252/fc ___________ .byte $01 ; 253/fd ___________ .byte $01 ; 254/fe ___________ .byte $00 ; 255/ff ___________ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/cvline.s���������������������������������������������������������������������0000664�0000000�0000000�00000001677�13473601511�0016265�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-04-13 ; ; void cvlinexy (unsigned char x, unsigned char y, unsigned char length); ; void cvline (unsigned char length); ; .export _cvlinexy, _cvline .import setscrptr .import rvs .import popax .importzp ptr2 .include "atmos.inc" _cvlinexy: pha ; Save the length jsr popax ; Get X and Y sta CURS_Y ; Store Y stx CURS_X ; Store X pla ; Restore the length and run into _cvline _cvline: tax ; Is the length zero? beq @L9 ; Jump if done @L1: jsr setscrptr ; Set ptr2 to screen, won't use X lda #'|' ora rvs sta (ptr2),y ; Write one char inc CURS_Y @L2: dex bne @L1 @L9: rts �����������������������������������������������������������������cc65-2.18/libsrc/atmos/gotox.s����������������������������������������������������������������������0000664�0000000�0000000�00000000340�13473601511�0016127�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-04-13 ; ; void gotox (unsigned char x); ; .export _gotox .include "atmos.inc" .proc _gotox sta CURS_X ; Set X rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/gotoxy.s���������������������������������������������������������������������0000664�0000000�0000000�00000000651�13473601511�0016325�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2003-04-13, Ullrich von Bassewitz ; 2017-06-15, Greg King ; ; void gotoxy (unsigned char x, unsigned char y); ; .export gotoxy, _gotoxy .import popa .include "atmos.inc" gotoxy: jsr popa ; Get Y .proc _gotoxy sta CURS_Y ; Set Y jsr popa ; Get X sta CURS_X ; Set X rts .endproc ���������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/gotoy.s����������������������������������������������������������������������0000664�0000000�0000000�00000000340�13473601511�0016130�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-04-13 ; ; void gotoy (unsigned char y); ; .export _gotoy .include "atmos.inc" .proc _gotoy sta CURS_Y ; Set Y rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/irq.s������������������������������������������������������������������������0000664�0000000�0000000�00000002240�13473601511�0015563�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; IRQ handling (Oric version) ; .export initirq, doneirq .import callirq .include "atmos.inc" ; ------------------------------------------------------------------------ .segment "ONCE" initirq: lda IRQVec ldx IRQVec+1 sta IRQInd+1 stx IRQInd+2 lda #<IRQStub ldx #>IRQStub jmp setvec ; ------------------------------------------------------------------------ .code doneirq: lda IRQInd+1 ldx IRQInd+2 setvec: sei sta IRQVec stx IRQVec+1 cli rts ; ------------------------------------------------------------------------ .segment "LOWCODE" IRQStub: cld ; Just to be sure pha txa pha tya pha jsr callirq ; Call the functions pla tay pla tax pla jmp IRQInd ; Jump to the saved IRQ vector ; ------------------------------------------------------------------------ .data IRQInd: jmp $0000 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/joy/�������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015407�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/joy/atmos-ijk.s��������������������������������������������������������������0000664�0000000�0000000�00000006531�13473601511�0017476�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; IJK joystick driver for the Atmos ; Can be used multiple times when statically linked to the application. ; ; 2002-12-20, Based on Ullrich von Bassewitz's code. ; 2017-11-01, Stefan Haubenthal ; .include "joy-kernel.inc" .include "joy-error.inc" .include "atmos.inc" .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _atmos_ijk_joy ; Driver signature .byte $6A, $6F, $79 ; "joy" .byte JOY_API_VERSION ; Driver API version number ; Library reference .addr $0000 ; Jump table. .addr INSTALL .addr UNINSTALL .addr COUNT .addr READ ; ------------------------------------------------------------------------ ; Constants JOY_COUNT = 2 ; 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 #%11000000 sta VIA::DDRA sta VIA::PRA lda VIA::PRA and #%00100000 bne ijkPresent lda #<JOY_ERR_NO_DEVICE .byte $2C ; Skip next opcode ijkPresent: lda #<JOY_ERR_OK ldx #>JOY_ERR_OK ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; COUNT: Return the total number of available joysticks in a/x. ; COUNT: lda #<JOY_COUNT ldx #>JOY_COUNT rts ; ------------------------------------------------------------------------ ; READ: Read a particular joystick passed in A. ; READ: bne right ; Ensure Printer Strobe is set to Output lda #%10110111 sta VIA::DDRB ; Set Strobe Low lda #%00000000 sta VIA::PRB ; Set Top two bits of PortA to Output and rest as Input lda #%11000000 sta VIA::DDRA ; Select Left Joystick lda #%01111111 sta VIA::PRA ; Read back Left Joystick state lda VIA::PRA ; Mask out unused bits and #%00011111 ; Invert Bits eor #%00011111 ; Index table to conform to Generic Format tax lda GenericIJKBits,X bne L1 right: ; Select Right Joystick lda #%10111111 sta VIA::PRA ; Read back Right Joystick state and rejig bits lda VIA::PRA and #%00011111 eor #%00011111 tax lda GenericIJKBits,X ; Restore VIA PortA state L1: ldx #%11111111 stx VIA::DDRA inx ; x=0 rts .rodata GenericIJKBits: .byte 0,2,1,3,32,34,33,0,8,10,9,0,40,42,41,0 .byte 16,18,17,0,48,50,49,0,0,0,0,0,0,0,0,0 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/joy/atmos-pase.s�������������������������������������������������������������0000664�0000000�0000000�00000005146�13473601511�0017652�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; P.A.S.E. joystick driver for the Atmos ; Can be used multiple times when statically linked to the application. ; ; 2002-12-20, Based on Ullrich von Bassewitz's code. ; 2009-12-21, Stefan Haubenthal ; 2013-07-15, Greg King ; .include "joy-kernel.inc" .include "joy-error.inc" .include "atmos.inc" .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _atmos_pase_joy ; Driver signature .byte $6A, $6F, $79 ; "joy" .byte JOY_API_VERSION ; Driver API version number ; Library reference .addr $0000 ; Jump table. .addr INSTALL .addr UNINSTALL .addr COUNT .addr READ ; ------------------------------------------------------------------------ ; Constants JOY_COUNT = 2 ; Number of joysticks we support ; ------------------------------------------------------------------------ ; Data. .bss temp1: .byte $00 temp2: .byte $00 .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 #0 ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; COUNT: Return the total number of available joysticks in a/x. ; COUNT: lda #JOY_COUNT ldx #0 rts ; ------------------------------------------------------------------------ ; READ: Read a particular joystick passed in A. ; READ: tay lda VIA::PRA pha lda VIA::DDRA pha lda #%11000000 sta VIA::DDRA lda #%10000000 sta VIA::PRA2 lda VIA::PRA2 sta temp1 lda #%01000000 sta VIA::PRA2 lda VIA::PRA sta temp2 pla sta VIA::DDRA pla sta VIA::PRA2 ldx #0 tya bne @L1 lda temp1 eor #$FF rts @L1: lda temp2 eor #$FF rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/joy_stat_stddrv.s������������������������������������������������������������0000664�0000000�0000000�00000000354�13473601511�0020216�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Address of the static standard joystick driver ; ; Oliver Schmidt, 2012-11-01 ; ; const void joy_static_stddrv[]; ; .export _joy_static_stddrv .import _atmos_pase_joy .rodata _joy_static_stddrv := _atmos_pase_joy ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/joy_stddrv.s�����������������������������������������������������������������0000664�0000000�0000000�00000000267�13473601511�0017166�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Name of the standard joystick driver ; ; Oliver Schmidt, 2012-11-01 ; ; const char joy_stddrv[]; ; .export _joy_stddrv .rodata _joy_stddrv: .asciiz "atmos-pase.joy" �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/kbhit.s����������������������������������������������������������������������0000664�0000000�0000000�00000000644�13473601511�0016077�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-04-13 ; ; int kbhit (void); ; .export _kbhit .include "atmos.inc" _kbhit: ldx #$00 ; Load high byte lda KEYBUF ; Flag for new char in bit 7 asl a ; Shift bit 7 into carry txa ; A = 0 rol a ; Move old bit 7 into bit 0 rts ��������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/libref.s���������������������������������������������������������������������0000664�0000000�0000000�00000000307�13473601511�0016235�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2013-05-31 ; .export joy_libref, ser_libref, tgi_libref .import _exit joy_libref := _exit ser_libref := _exit tgi_libref := _exit �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/mainargs.s�������������������������������������������������������������������0000664�0000000�0000000�00000007302�13473601511�0016575�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2003-03-07, Ullrich von Bassewitz ; 2011-01-28, Stefan Haubenthal ; 2014-09-10, Greg King ; ; Set up arguments for main ; .constructor initmainargs, 24 .import __argc, __argv .include "atmos.inc" .macpack generic MAXARGS = 10 ; Maximum number of arguments allowed REM = $9D ; BASIC token-code ;--------------------------------------------------------------------------- ; Get possible command-line arguments. Goes into the special ONCE segment, ; which will be reused after the startup code is run. .segment "ONCE" .proc initmainargs ; Assume that the program was loaded, a moment ago, by the traditional LOAD ; statement. Save the "most-recent filename" as argument #0. ldy #FNAME_LEN ; Limit the length lda #0 ; The terminating NUL character beq L1 ; Branch always L0: lda CFOUND_NAME,y L1: sta name,y dey bpl L0 inc __argc ; argc always is equal to, at least, 1 ; Find the "rem" token. ldx #0 L2: lda BASIC_BUF,x beq done ; No "rem", no args. inx cmp #REM bne L2 ; The arguments must be copied to a safe place because BASIC's input buffer ; might be re-used by the stdin console. ldy #(SCREEN_XSIZE * 2 - 1) - 1 L3: lda BASIC_BUF,y sta args,y dey bpl L3 ldy #1 * 2 ; Point to second argv slot ; Find the next argument next: lda BASIC_BUF,x beq done ; End of line reached inx cmp #' ' ; Skip leading spaces 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 ; will check now for a quoted argument, in which case we will have to skip this ; first character. found: cmp #'"' ; Is the argument quoted? beq setterm ; Jump if so dex ; Reset pointer to first argument character lda #' ' ; A space ends the argument setterm:sta term ; Set end of argument marker ; Now, store a pointer, to the argument, into the next slot. txa ; Get low byte add #<args sta argv,y ; argv[y]=&arg lda #>$0000 adc #>args sta argv+1,y iny iny inc __argc ; Found another arg ; Search for the end of the argument argloop:lda BASIC_BUF,x beq done inx cmp term bne argloop ; 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 #0 sta args-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? bcc 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 .endproc .segment "INIT" term: .res 1 name: .res FNAME_LEN + 1 args: .res SCREEN_XSIZE * 2 - 1 .data ; This array has zeroes when initmainargs starts. ; char* argv[MAXARGS+1]={name}; argv: .addr name .res MAXARGS * 2 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/oserrlist.s������������������������������������������������������������������0000664�0000000�0000000�00000005300�13473601511�0017016�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Stefan Haubenthal, 2004-05-25 ; Ullrich von Bassewitz, 18.07.2002 ; ; Defines the platform specific error list. ; ; The table is built as a list of entries ; ; .byte entrylen ; .byte errorcode ; .asciiz errormsg ; ; and terminated by an entry with length zero that is returned if the ; error code could not be found. ; .export __sys_oserrlist ;---------------------------------------------------------------------------- ; Macros used to generate the list (may get moved to an include file?) ; Regular entry .macro sys_oserr_entry code, msg .local Start, End Start: .byte End - Start .byte code .asciiz msg End: .endmacro ; Sentinel entry .macro sys_oserr_sentinel msg .byte 0 ; Length is always zero .byte 0 ; Code is unused .asciiz msg .endmacro ;---------------------------------------------------------------------------- ; The error message table .rodata __sys_oserrlist: sys_oserr_entry 1, "File not found" sys_oserr_entry 2, "Invalid command end" sys_oserr_entry 3, "No drive number" sys_oserr_entry 4, "Bad drive number" sys_oserr_entry 5, "Invalid filename" sys_oserr_entry 6, "fderr=(error number)" sys_oserr_entry 7, "Illegal attribute" sys_oserr_entry 8, "Wildcard(s) not allowed" sys_oserr_entry 9, "File already exists" sys_oserr_entry 10, "Insufficient disc space" sys_oserr_entry 11, "File open" sys_oserr_entry 12, "Illegal quantity" sys_oserr_entry 13, "End address missing" sys_oserr_entry 14, "Start address > end address" sys_oserr_entry 15, "Missing 'to'" sys_oserr_entry 16, "Renamed file not on same disc" sys_oserr_entry 17, "Unknown array" sys_oserr_entry 18, "Target drive not source drive" sys_oserr_entry 19, "Destination not specified" sys_oserr_entry 20, "Cannot merge and overwrite" sys_oserr_entry 21, "Single target file illegal" sys_oserr_entry 22, "Syntax" sys_oserr_entry 23, "Filename missing" sys_oserr_entry 24, "Source file missing" sys_oserr_entry 25, "Type mismatch" sys_oserr_entry 26, "Disc write-protected" sys_oserr_entry 27, "Incompatible drives" sys_oserr_entry 28, "File not open" sys_oserr_entry 29, "File end" sys_oserr_sentinel "Unknown error" ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/oserror.s��������������������������������������������������������������������0000664�0000000�0000000�00000000516�13473601511�0016467�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/read.s�����������������������������������������������������������������������0000664�0000000�0000000�00000003504�13473601511�0015707�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2014-08-22, Greg King ; ; int read (int fd, void* buf, unsigned count); ; ; This function is a hack! It lets us get text from the stdin console. ; .export _read .constructor initstdin .import popax, popptr1 .importzp ptr1, ptr2, ptr3 .forceimport disable_caps .macpack generic .include "atmos.inc" .proc _read sta ptr3 stx ptr3+1 ; save count as result eor #$FF sta ptr2 txa eor #$FF sta ptr2+1 ; Remember -count-1 jsr popptr1 ; get buf jsr popax ; get fd and discard L1: inc ptr2 bnz L2 inc ptr2+1 bze L9 ; no more room in buf ; If there are no more characters in BASIC's input buffer, then get a line from ; the console into that buffer. L2: ldx text_count bpl L3 jsr GETLINE ldx #<(0 - 1) L3: inx lda BASIC_BUF,x bnz L4 ; (zero-terminated buffer) ldx #<-1 lda #$0A ; return newline char. at end of line L4: stx text_count ldy #0 sta (ptr1),y inc ptr1 bnz L1 inc ptr1+1 bnz L1 ; branch always ; No error, return count. L9: lda ptr3 ldx ptr3+1 rts .endproc ;-------------------------------------------------------------------------- ; initstdin: Reset the stdin console. .segment "ONCE" initstdin: ldx #<-1 stx text_count rts ;-------------------------------------------------------------------------- .segment "INIT" text_count: .res 1 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/revers.s���������������������������������������������������������������������0000664�0000000�0000000�00000001665�13473601511�0016310�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 07.08.1998 ; ; unsigned char revers (unsigned char onoff); ; .export _revers .export rvs ; ------------------------------------------------------------------------ ; .code .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 ; ------------------------------------------------------------------------ ; .bss rvs: .res 1 ���������������������������������������������������������������������������cc65-2.18/libsrc/atmos/ser/�������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015377�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/ser/atmos-acia.s�������������������������������������������������������������0000664�0000000�0000000�00000030251�13473601511�0017602�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Serial driver for the Telestrat integrated serial controller and the ; Atmos with a serial add-on. ; ; 2012-03-05, Stefan Haubenthal ; 2013-07-15, Greg King ; ; The driver is based on the cc65 rs232 module, which in turn is based on ; Craig Bruce device driver for the Switftlink/Turbo-232. ; ; SwiftLink/Turbo-232 v0.90 device driver, by Craig Bruce, 14-Apr-1998. ; ; This software is Public Domain. It is in Buddy assembler format. ; ; This device driver uses the SwiftLink RS-232 Serial Cartridge, available from ; Creative Micro Designs, Inc, and also supports the extensions of the Turbo232 ; Serial Cartridge. Both devices are based on the 6551 ACIA chip. It also ; supports the "hacked" SwiftLink with a 1.8432 MHz crystal. ; ; The code assumes that the kernal + I/O are in context. On the C128, call ; it from Bank 15. On the C64, don't flip out the Kernal unless a suitable ; NMI catcher is put into the RAM under then Kernal. For the SuperCPU, the ; interrupt handling assumes that the 65816 is in 6502-emulation mode. ; .include "zeropage.inc" .include "ser-kernel.inc" .include "ser-error.inc" .include "atmos.inc" .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _atmos_acia_ser ; Driver signature .byte $73, $65, $72 ; "ser" .byte SER_API_VERSION ; Serial API version number ; Library reference .addr $0000 ; Jump table .addr SER_INSTALL .addr SER_UNINSTALL .addr SER_OPEN .addr SER_CLOSE .addr SER_GET .addr SER_PUT .addr SER_STATUS .addr SER_IOCTL .addr SER_IRQ ;---------------------------------------------------------------------------- ; Global variables .bss RecvHead: .res 1 ; Head of receive buffer RecvTail: .res 1 ; Tail of receive buffer RecvFreeCnt: .res 1 ; Number of bytes in receive buffer SendHead: .res 1 ; Head of send buffer SendTail: .res 1 ; Tail of send buffer SendFreeCnt: .res 1 ; Number of bytes in send buffer Stopped: .res 1 ; Flow-stopped flag RtsOff: .res 1 ; RecvBuf: .res 256 ; Receive buffers: 256 bytes SendBuf: .res 256 ; Send buffers: 256 bytes Index: .res 1 ; I/O register index .rodata ; Tables used to translate RS232 params into register values BaudTable: ; bit7 = 1 means setting is invalid .byte $FF ; SER_BAUD_45_5 .byte $01 ; SER_BAUD_50 .byte $02 ; SER_BAUD_75 .byte $03 ; SER_BAUD_110 .byte $04 ; SER_BAUD_134_5 .byte $05 ; SER_BAUD_150 .byte $06 ; SER_BAUD_300 .byte $07 ; SER_BAUD_600 .byte $08 ; SER_BAUD_1200 .byte $09 ; SER_BAUD_1800 .byte $0A ; SER_BAUD_2400 .byte $0B ; SER_BAUD_3600 .byte $0C ; SER_BAUD_4800 .byte $0D ; SER_BAUD_7200 .byte $0E ; SER_BAUD_9600 .byte $0F ; SER_BAUD_19200 .byte $FF ; SER_BAUD_38400 .byte $FF ; SER_BAUD_57600 .byte $FF ; SER_BAUD_115200 .byte $FF ; SER_BAUD_230400 BitTable: .byte $60 ; SER_BITS_5 .byte $40 ; SER_BITS_6 .byte $20 ; SER_BITS_7 .byte $00 ; SER_BITS_8 StopTable: .byte $00 ; SER_STOP_1 .byte $80 ; SER_STOP_2 ParityTable: .byte $00 ; SER_PAR_NONE .byte $20 ; SER_PAR_ODD .byte $60 ; SER_PAR_EVEN .byte $A0 ; SER_PAR_MARK .byte $E0 ; SER_PAR_SPACE .code ;---------------------------------------------------------------------------- ; SER_INSTALL: Is called after the driver is loaded into memory. If possible, ; check if the hardware is present. Must return an SER_ERR_xx code in a/x. ; ; Since we don't have to manage the IRQ vector on the Telestrat/Atmos, this is ; actually the same as: ; ; SER_UNINSTALL: Is called before the driver is removed from memory. ; No return code required (the driver is removed from memory on return). ; ; and: ; ; SER_CLOSE: Close the port and disable interrupts. Called without parameters. ; Must return an SER_ERR_xx code in a/x. SER_INSTALL: SER_UNINSTALL: SER_CLOSE: ldx Index ; Check for open port beq :+ ; Deactivate DTR and disable 6551 interrupts lda #%00001010 sta ACIA::CMD,x ; Done, return an error code : lda #<SER_ERR_OK tax ; A is zero stx Index ; Mark port as closed rts ;---------------------------------------------------------------------------- ; SER_OPEN: A pointer to a ser_params structure is passed in ptr1. ; Must return an SER_ERR_xx code in a/x. SER_OPEN: ; Check if the handshake setting is valid ldy #SER_PARAMS::HANDSHAKE ; Handshake lda (ptr1),y cmp #SER_HS_HW ; This is all we support bne InvParam ; Initialize buffers ldy #$00 sty Stopped sty RecvHead sty RecvTail sty SendHead sty SendTail dey ; Y = 255 sty RecvFreeCnt sty SendFreeCnt ; Set the value for the control register, which contains stop bits, ; word length and the baud rate. ldy #SER_PARAMS::BAUDRATE lda (ptr1),y ; Baudrate index tay lda BaudTable,y ; Get 6551 value bmi InvBaud ; Branch if rate not supported sta tmp1 ldy #SER_PARAMS::DATABITS ; Databits lda (ptr1),y tay lda BitTable,y ora tmp1 sta tmp1 ldy #SER_PARAMS::STOPBITS ; Stopbits lda (ptr1),y tay lda StopTable,y ora tmp1 ora #%00010000 ; Receiver clock source = baudrate sta ACIA::CTRL ; Set the value for the command register. We remember the base value ; in RtsOff, since we will have to manipulate ACIA::CMD often. ldy #SER_PARAMS::PARITY ; Parity lda (ptr1),y tay lda ParityTable,y ora #%00000001 ; DTR active sta RtsOff ora #%00001000 ; Enable receive interrupts sta ACIA::CMD ; Done stx Index ; Mark port as open lda #<SER_ERR_OK tax ; A is zero rts ; Invalid parameter InvParam:lda #<SER_ERR_INIT_FAILED ldx #>SER_ERR_INIT_FAILED rts ; Baud rate not available InvBaud:lda #<SER_ERR_BAUD_UNAVAIL ldx #>SER_ERR_BAUD_UNAVAIL rts ;---------------------------------------------------------------------------- ; SER_GET: Will fetch a character from the receive buffer and store it into the ; variable pointed to by ptr1. If no data is available, SER_ERR_NO_DATA is ; returned. SER_GET: ldy SendFreeCnt ; Send data if necessary iny ; Y == $FF? beq :+ lda #$00 ; TryHard = false jsr TryToSend ; Check for buffer empty : lda RecvFreeCnt ; (25) cmp #$FF bne :+ lda #<SER_ERR_NO_DATA ldx #>SER_ERR_NO_DATA rts ; Check for flow stopped & enough free: release flow control : ldy Stopped ; (34) beq :+ cmp #63 bcc :+ lda #$00 sta Stopped lda RtsOff ora #%00001000 sta ACIA::CMD ; Get byte from buffer : ldy RecvHead ; (41) lda RecvBuf,y inc RecvHead inc RecvFreeCnt ldx #$00 ; (59) sta (ptr1,x) txa ; Return code = 0 rts ;---------------------------------------------------------------------------- ; SER_PUT: Output character in A. ; Must return an SER_ERR_xx code in a/x. SER_PUT: ; Try to send ldy SendFreeCnt iny ; Y = $FF? beq :+ pha lda #$00 ; TryHard = false jsr TryToSend pla ; Put byte into send buffer & send : ldy SendFreeCnt bne :+ lda #<SER_ERR_OVERFLOW ldx #>SER_ERR_OVERFLOW rts : ldy SendTail sta SendBuf,y inc SendTail dec SendFreeCnt lda #$FF ; TryHard = true jsr TryToSend lda #<SER_ERR_OK tax rts ;---------------------------------------------------------------------------- ; SER_STATUS: Return the status in the variable pointed to by ptr1. ; Must return an SER_ERR_xx code in a/x. SER_STATUS: lda ACIA::STATUS ldx #$00 sta (ptr1,x) txa ; SER_ERR_OK rts ;---------------------------------------------------------------------------- ; SER_IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl ; specific data in ptr1, and the ioctl code in A. ; Must return an SER_ERR_xx code in a/x. SER_IOCTL: lda #<SER_ERR_INV_IOCTL ldx #>SER_ERR_INV_IOCTL rts ;---------------------------------------------------------------------------- ; SER_IRQ: Called from the builtin runtime IRQ handler as a subroutine. All ; registers are already saved, no parameters are passed, but the carry flag ; is clear on entry. The routine must return with carry set if the interrupt ; was handled, otherwise with carry clear. SER_IRQ: ldx Index ; Check for open port beq Done lda ACIA::STATUS,x ; Check ACIA status for receive interrupt and #$08 beq Done ; Jump if no ACIA interrupt lda ACIA::DATA,x ; Get byte from ACIA ldy RecvFreeCnt ; Check if we have free space left beq Flow ; Jump if no space in receive buffer ldy RecvTail ; Load buffer pointer sta RecvBuf,y ; Store received byte in buffer inc RecvTail ; Increment buffer pointer dec RecvFreeCnt ; Decrement free space counter ldy RecvFreeCnt ; Check for buffer space low cpy #33 bcc Flow ; Assert flow control if buffer space low rts ; Interrupt handled (carry already set) ; Assert flow control if buffer space too low Flow: lda RtsOff sta ACIA::CMD,x sta Stopped sec ; Interrupt handled Done: rts ;---------------------------------------------------------------------------- ; Try to send a byte. Internal routine. A = TryHard TryToSend: sta tmp1 ; Remember tryHard flag Again: lda SendFreeCnt cmp #$FF beq Quit ; Bail out ; Check for flow stopped lda Stopped bne Quit ; Bail out ; Check that ACIA is ready to send lda ACIA::STATUS and #$10 bne Send bit tmp1 ; Keep trying if must try hard bmi Again Quit: rts ; Send byte and try again Send: ldy SendHead lda SendBuf,y sta ACIA::DATA inc SendHead inc SendFreeCnt jmp Again �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/store_filename.s�������������������������������������������������������������0000664�0000000�0000000�00000000513�13473601511�0017765�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; Helper function .export store_filename .importzp ptr1 .include "atmos.inc" store_filename: sta ptr1 stx ptr1+1 ldy #FNAME_LEN - 1 ; store filename : lda (ptr1),y sta CFILE_NAME,y dey bpl :- rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/sysuname.s�������������������������������������������������������������������0000664�0000000�0000000�00000002240�13473601511�0016634�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-08-12 ; ; unsigned char __fastcall__ _sysuname (struct utsname* buf); ; .export __sysuname, utsdata .import utscopy __sysuname = utscopy ;-------------------------------------------------------------------------- ; Data. We define a fixed utsname struct here and just copy it. .rodata utsdata: ; sysname .asciiz "cc65" ; nodename .asciiz "" ; release .byte ((.VERSION >> 8) & $0F) + '0' .byte '.' .if ((.VERSION >> 4) & $0F) > 9 .byte ((.VERSION >> 4) & $0F) / 10 + '0' .byte ((.VERSION >> 4) & $0F) .MOD 10 + '0' .else .byte ((.VERSION >> 4) & $0F) + '0' .endif .byte $00 ; version .if (.VERSION & $0F) > 9 .byte (.VERSION & $0F) / 10 + '0' .byte (.VERSION & $0F) .MOD 10 + '0' .else .byte (.VERSION & $0F) + '0' .endif .byte $00 ; machine .asciiz "Oric Atmos" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/tapehdr.s��������������������������������������������������������������������0000664�0000000�0000000�00000002313�13473601511�0016420�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Based on code by Debrune Jérôme <jede@oric.org> ; 2016-03-17, 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 __AUTORUN__, __PROGFLAG__ .import __BASHEAD_START__, __MAIN_LAST__ ; ------------------------------------------------------------------------ ; 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 __MAIN_LAST__ - 1 ; $2AB Address of end of file .dbyt __BASHEAD_START__ ; $2A9 Address of start of file .byte $00 ; $2A8 ; File name (a maximum of 17 characters), zero-terminated .asciiz .sprintf("%u", .time) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/tgi/�������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015371�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/tgi/atmos-228-200-3.s��������������������������������������������������������0000664�0000000�0000000�00000026174�13473601511�0017662�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Graphics driver for the 228x200x3 palette mode on the Atmos ; ; Stefan Haubenthal <polluks@sdf.lonestar.org> ; 2014-09-10, Greg King <gregdk@users.sf.net> ; .include "zeropage.inc" .include "tgi-kernel.inc" .include "tgi-error.inc" .include "atmos.inc" .macpack generic .macpack module XSIZE = 6 ; System font width YSIZE = 8 ; System font height ; ------------------------------------------------------------------------ ; Header. Includes jump table and constants. module_header _atmos_228_200_3_tgi ; The first part of the header is a structure that has a signature, ; and defines the capabilities of the driver. .byte "tgi" .byte TGI_API_VERSION ; TGI API version number .addr $0000 ; Library reference .word 228 ; x resolution .word 200 ; y resolution .byte 3 ; Number of drawing colors .byte 1 ; Number of screens available .byte XSIZE ; System font x size .byte YSIZE ; System font y size .word $011C ; Aspect ratio (based on 4/3 display) .byte 0 ; TGI driver flags ; Next comes the jump table. Currently, all entries must be valid; ; and, may point to an RTS, for test versions (function not implemented). .addr INSTALL .addr UNINSTALL .addr INIT .addr DONE .addr GETERROR .addr CONTROL .addr CLEAR .addr SETVIEWPAGE .addr SETDRAWPAGE .addr SETCOLOR .addr SETPALETTE .addr GETPALETTE .addr GETDEFPALETTE .addr SETPIXEL .addr GETPIXEL .addr LINE .addr BAR .addr TEXTSTYLE .addr OUTTEXT ; ------------------------------------------------------------------------ ; Data. ; Variables mapped to the zero-page segment variables. These are ; used for passing parameters to the driver. X1 := ptr1 Y1 := ptr2 X2 := ptr3 Y2 := ptr4 ; Absolute variables used in the code .bss ERROR: .res 1 ; Error code MODE: .res 1 ; Graphics mode PALETTE: .res 2 ; Constant table .rodata ; Default colors: black background, white foreground ; (The third "color" actually flips a pixel ; between the foreground and background colors.) ; DEFPALETTE: .byte 0, 1 .code ; ------------------------------------------------------------------------ ; INIT: Changes an already installed device from text mode to graphics mode. ; Note that INIT/DONE may be called multiple times while the driver ; is loaded, while INSTALL is called only once. So, any code that is needed ; to initialize variables and so on must go here. Setting palette and ; clearing the screen are not needed because they are called by the graphics ; kernel later. ; The graphics kernel never will call INIT when a graphics mode is already ; active, so there is no need to protect against that. ; ; Must set an error code: YES ; INIT: ; Switch into graphics mode. jsr HIRES ; Done, reset the error code. ; ------------------------------------------------------------------------ ; GETERROR: Return the error code in A, and clear it. GETERROR: ldx #TGI_ERR_OK lda ERROR stx ERROR ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. May ; initialize anything that has to be done just once. Is probably empty ; most of the time. ; ; Must set an error code: NO ; INSTALL: ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. May ; clean up anything done by INSTALL, but probably is empty most of the time. ; ; Must set an error code: NO ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; DONE: Will be called to switch the graphics device back into text mode. ; The graphics kernel never will call DONE when no graphics mode is active, ; so there is no need to protect against that. ; ; Must set an error code: NO ; DONE := TEXT ; ------------------------------------------------------------------------ ; CONTROL: Platform-/driver-specific entry point. ; ; Must set an error code: YES ; CONTROL: sta PATTERN lda #TGI_ERR_OK sta ERROR rts ; ------------------------------------------------------------------------ ; CLEAR: Clears the screen. ; ; Must set an error code: NO ; CLEAR := HIRES ; ------------------------------------------------------------------------ ; SETVIEWPAGE: Set the visible page. Called with the new page in A (0..n). ; The page number already is checked to be valid, by the graphics kernel. ; ; Must set an error code: NO (will be called only if page OK) ; SETVIEWPAGE: ; ------------------------------------------------------------------------ ; SETDRAWPAGE: Set the drawable page. Called with the new page in A (0..n). ; The page number already is checked to be valid, by the graphics kernel. ; ; Must set an error code: NO (will be called only if page OK) ; SETDRAWPAGE: rts ; ------------------------------------------------------------------------ ; SETCOLOR: Set the drawing color (in A). The new color already is checked ; to be in a valid range (0..maxcolor-1). ; ; Must set an error code: NO (will be called only if color OK) ; SETCOLOR: sta MODE rts ; ------------------------------------------------------------------------ ; SETPALETTE: Set the palette (not available with all drivers/hardware). ; A pointer to the palette is passed in ptr1. Must set an error if palettes ; are not supported. ; ; Must set an error code: YES ; SETPALETTE: ldy #0 jsr flipcolor sty PARAM1+1 jsr PAPER ldy #1 jsr flipcolor dey ; TGI_ERR_OK sty ERROR sty PARAM1+1 jmp INK flipcolor: lda (ptr1),y sta PALETTE,y cmp #1 beq @flip cmp #7 bne @keep @flip: eor #1 ^ 7 @keep: sta PARAM1 rts ; ------------------------------------------------------------------------ ; GETPALETTE: Return the current palette in A/X. Even drivers that cannot ; set the palette should return the default palette here, so there's no ; way for this function to fail. ; ; Must set an error code: NO ; GETPALETTE: lda #<PALETTE ldx #>PALETTE rts ; ------------------------------------------------------------------------ ; GETDEFPALETTE: Return the default palette for the driver in A/X. All ; drivers should return something reasonable here, even drivers that don't ; support palettes; otherwise, the caller has no way to determine the colors ; of the (not changeable) palette. ; ; Must set an error code: NO (all drivers must have a default palette) ; GETDEFPALETTE: lda #<DEFPALETTE ldx #>DEFPALETTE rts ; ------------------------------------------------------------------------ ; SETPIXEL: Draw one pixel at X1/Y1 = ptr1/ptr2 with the current drawing ; color. The co-ordinates passed to this function are never outside the ; visible screen area, so there is no need for clipping inside this function. ; ; Must set an error code: NO ; SETPIXEL: lda Y1 sta PARAM2 lda MODE mymode: sta PARAM3 lda X1 add #2 * XSIZE ; Skip screen attribute columns sta PARAM1 lda #>$0000 sta PARAM1+1 sta PARAM2+1 sta PARAM3+1 jmp CURSET ; ------------------------------------------------------------------------ ; GETPIXEL: Read the color value of a pixel, and return it in A/X. The ; co-ordinates passed to this function are never outside the visible screen ; area, so there is no need for clipping inside this function. GETPIXEL: lda X1 sta PARAM1 lda Y1 sta PARAM2 lda #>$0000 sta PARAM1+1 sta PARAM2+1 jsr POINT lda PARAM1 and #%00000001 ldx #>$0000 rts ; ------------------------------------------------------------------------ ; LINE: Draw a line from X1/Y1 to X2/Y2, where X1/Y1 = ptr1/ptr2 and ; X2/Y2 = ptr3/ptr4, using the current drawing color. ; ; Must set an error code: NO ; LINE: jsr SETPIXEL lda X2 sub X1 sta PARAM1 lda X2+1 sbc X1+1 sta PARAM1+1 lda Y2 sub Y1 sta PARAM2 lda Y2+1 sbc Y1+1 sta PARAM2+1 lda MODE sta PARAM3 ldx #>$0000 stx PARAM3+1 jmp DRAW ; ------------------------------------------------------------------------ ; BAR: Draw a filled rectangle with the corners X1/Y1, X2/Y2, where ; X1/Y1 = ptr1/ptr2 and X2/Y2 = ptr3/ptr4, using the current drawing color. ; Contrary to most other functions, the graphics kernel will sort and clip ; the co-ordinates before calling the driver; so, on entry, the following ; conditions are valid: ; X1 <= X2 ; Y1 <= Y2 ; (X1 >= 0) && (X1 < XRES) ; (X2 >= 0) && (X2 < XRES) ; (Y1 >= 0) && (Y1 < YRES) ; (Y2 >= 0) && (Y2 < YRES) ; ; Must set an error code: NO ; BAR: inc Y2 @L1: lda Y2 pha lda Y1 sta Y2 jsr LINE pla sta Y2 inc Y1 cmp Y1 bne @L1 rts ; ------------------------------------------------------------------------ ; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in the x ; and y directions is passed in X/Y, the text direction is passed in A. ; ; Must set an error code: NO ; TEXTSTYLE: rts ; ------------------------------------------------------------------------ ; OUTTEXT: Output text at x/y = ptr1/ptr2, using the current color and the ; current text style. The text to output is given as a zero-terminated ; string with its address in ptr3. ; ; Must set an error code: NO ; OUTTEXT: lda Y1 sub #(YSIZE - 1) sta PARAM2 lda #3 ; (Move graphics cursor; don't draw) jsr mymode ldy #0 @next: lda (ptr3),y beq @end sta PARAM1 lda #0 sta PARAM2 sta PARAM1+1 sta PARAM2+1 sta PARAM3+1 lda MODE sta PARAM3 tya pha jsr CHAR lda #XSIZE sta PARAM1 lda #0 sta PARAM2 sta PARAM1+1 sta PARAM2+1 sta PARAM3+1 lda #3 sta PARAM3 jsr CURMOV pla tay iny bne @next @end: rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/tgi/atmos-240-200-2.s��������������������������������������������������������0000664�0000000�0000000�00000025257�13473601511�0017654�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Graphics driver for the 240x200x2 monochrome mode on the Atmos ; ; Stefan Haubenthal <polluks@sdf.lonestar.org> ; 2014-09-10, Greg King <gregdk@users.sf.net> ; .include "zeropage.inc" .include "tgi-kernel.inc" .include "tgi-error.inc" .include "atmos.inc" .macpack generic .macpack module XSIZE = 6 ; System font width YSIZE = 8 ; System font height ; ------------------------------------------------------------------------ ; Header. Includes jump table and constants. module_header _atmos_240_200_2_tgi ; First part of the header is a structure that has a magic and defines the ; capabilities of the driver .byte $74, $67, $69 ; "tgi" .byte TGI_API_VERSION ; TGI API version number .addr $0000 ; Library reference .word 240 ; X resolution .word 200 ; Y resolution .byte 2 ; Number of drawing colors .byte 1 ; Number of screens available .byte XSIZE ; System font X size .byte YSIZE ; System font Y size .word $011C ; Aspect ratio (based on 4/3 display) .byte 0 ; TGI driver flags ; Next comes the jump table. Currently all entries must be valid and may point ; to an RTS for test versions (function not implemented). .addr INSTALL .addr UNINSTALL .addr INIT .addr DONE .addr GETERROR .addr CONTROL .addr CLEAR .addr SETVIEWPAGE .addr SETDRAWPAGE .addr SETCOLOR .addr SETPALETTE .addr GETPALETTE .addr GETDEFPALETTE .addr SETPIXEL .addr GETPIXEL .addr LINE .addr BAR .addr TEXTSTYLE .addr OUTTEXT ; ------------------------------------------------------------------------ ; Data. ; Variables mapped to the zero page segment variables. Some of these are ; used for passing parameters to the driver. X1 := ptr1 Y1 := ptr2 X2 := ptr3 Y2 := ptr4 ; Absolute variables used in the code .bss ERROR: .res 1 ; Error code MODE: .res 1 ; Graphics mode ; Constant table .rodata DEFPALETTE: .byte 0, 1 .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. May ; initialize anything that has to be done just once. Is probably empty ; most of the time. ; ; Must set an error code: NO ; INSTALL: ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. May ; clean up anything done by INSTALL but is probably empty most of the time. ; ; Must set an error code: NO ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; INIT: Changes an already installed device from text mode to graphics ; mode. ; Note that INIT/DONE may be called multiple times while the driver ; is loaded, while INSTALL is only called once, so any code that is needed ; to initializes variables and so on must go here. Setting palette and ; clearing the screen is not needed because this is called by the graphics ; kernel later. ; The graphics kernel will never call INIT when a graphics mode is already ; active, so there is no need to protect against that. ; ; Must set an error code: YES ; INIT: ; Switch into graphics mode jsr HIRES ; Done, reset the error code lda #TGI_ERR_OK sta ERROR rts ; ------------------------------------------------------------------------ ; DONE: Will be called to switch the graphics device back into text mode. ; The graphics kernel will never call DONE when no graphics mode is active, ; so there is no need to protect against that. ; ; Must set an error code: NO ; DONE := TEXT ; ------------------------------------------------------------------------ ; GETERROR: Return the error code in A and clear it. GETERROR: ldx #TGI_ERR_OK lda ERROR stx ERROR rts ; ------------------------------------------------------------------------ ; CONTROL: Platform/driver specific entry point. ; ; Must set an error code: YES ; CONTROL: sta PATTERN lda #TGI_ERR_OK sta ERROR rts ; ------------------------------------------------------------------------ ; CLEAR: Clears the screen. ; ; Must set an error code: NO ; CLEAR := HIRES ; ------------------------------------------------------------------------ ; SETVIEWPAGE: Set the visible page. Called with the new page in A (0..n). ; The page number is already checked to be valid by the graphics kernel. ; ; Must set an error code: NO (will only be called if page ok) ; SETVIEWPAGE: ; ------------------------------------------------------------------------ ; SETDRAWPAGE: Set the drawable page. Called with the new page in A (0..n). ; The page number is already checked to be valid by the graphics kernel. ; ; Must set an error code: NO (will only be called if page ok) ; SETDRAWPAGE: rts ; ------------------------------------------------------------------------ ; SETCOLOR: Set the drawing color (in A). The new color is already checked ; to be in a valid range (0..maxcolor-1). ; ; Must set an error code: NO (will only be called if color ok) ; SETCOLOR: sta MODE rts ; ------------------------------------------------------------------------ ; SETPALETTE: Set the palette (not available with all drivers/hardware). ; A pointer to the palette is passed in ptr1. Must set an error if palettes ; are not supported ; ; Must set an error code: YES ; SETPALETTE: lda #TGI_ERR_INV_FUNC ; This resolution has no palette sta ERROR rts ; ------------------------------------------------------------------------ ; GETPALETTE: Return the current palette in A/X. Even drivers that cannot ; set the palette should return the default palette here, so there's no ; way for this function to fail. ; ; Must set an error code: NO ; GETPALETTE: ; ------------------------------------------------------------------------ ; GETDEFPALETTE: Return the default palette for the driver in A/X. All ; drivers should return something reasonable here, even drivers that don't ; support palettes, otherwise the caller has no way to determine the colors ; of the (not changeable) palette. ; ; Must set an error code: NO (all drivers must have a default palette) ; GETDEFPALETTE: lda #<DEFPALETTE ldx #>DEFPALETTE rts ; ------------------------------------------------------------------------ ; SETPIXEL: Draw one pixel at X1/Y1 = ptr1/ptr2 with the current drawing ; color. The coordinates passed to this function are never outside the ; visible screen area, so there is no need for clipping inside this function. ; ; Must set an error code: NO ; SETPIXEL: lda Y1 sta PARAM2 lda MODE mymode: sta PARAM3 lda X1 sta PARAM1 lda #>$0000 sta PARAM1+1 sta PARAM2+1 sta PARAM3+1 jmp CURSET ; ------------------------------------------------------------------------ ; GETPIXEL: Read the color value of a pixel and return it in A/X. The ; coordinates passed to this function are never outside the visible screen ; area, so there is no need for clipping inside this function. GETPIXEL: lda X1 sta PARAM1 lda Y1 sta PARAM2 lda #>$0000 sta PARAM1+1 sta PARAM2+1 jsr POINT lda PARAM1 and #%00000001 ldx #>$0000 rts ; ------------------------------------------------------------------------ ; LINE: Draw a line from X1/Y1 to X2/Y2, where X1/Y1 = ptr1/ptr2 and ; X2/Y2 = ptr3/ptr4 using the current drawing color. ; ; Must set an error code: NO ; LINE: jsr SETPIXEL lda X2 sub X1 sta PARAM1 lda X2+1 sbc X1+1 sta PARAM1+1 lda Y2 sub Y1 sta PARAM2 lda Y2+1 sbc Y1+1 sta PARAM2+1 lda MODE sta PARAM3 ldx #>$0000 stx PARAM3+1 jmp DRAW ; ------------------------------------------------------------------------ ; BAR: Draw a filled rectangle with the corners X1/Y1, X2/Y2, where ; X1/Y1 = ptr1/ptr2 and X2/Y2 = ptr3/ptr4 using the current drawing color. ; Contrary to most other functions, the graphics kernel will sort and clip ; the coordinates before calling the driver, so on entry the following ; conditions are valid: ; X1 <= X2 ; Y1 <= Y2 ; (X1 >= 0) && (X1 < XRES) ; (X2 >= 0) && (X2 < XRES) ; (Y1 >= 0) && (Y1 < YRES) ; (Y2 >= 0) && (Y2 < YRES) ; ; Must set an error code: NO ; BAR: inc Y2 @L1: lda Y2 pha lda Y1 sta Y2 jsr LINE pla sta Y2 inc Y1 cmp Y1 bne @L1 rts ; ------------------------------------------------------------------------ ; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in X and Y ; direction is passend in X/Y, the text direction is passed in A. ; ; Must set an error code: NO ; TEXTSTYLE: rts ; ------------------------------------------------------------------------ ; OUTTEXT: Output text at X/Y = ptr1/ptr2 using the current color and the ; current text style. The text to output is given as a zero terminated ; string with address in ptr3. ; ; Must set an error code: NO ; OUTTEXT: lda Y1 sub #(YSIZE - 1) sta PARAM2 lda #3 ; (Move graphics cursor; don't draw) jsr mymode ldy #0 @next: lda (ptr3),y beq @end sta PARAM1 lda #0 sta PARAM2 sta PARAM1+1 sta PARAM2+1 sta PARAM3+1 lda MODE sta PARAM3 tya pha jsr CHAR lda #XSIZE sta PARAM1 lda #0 sta PARAM2 sta PARAM1+1 sta PARAM2+1 sta PARAM3+1 lda #3 sta PARAM3 jsr CURMOV pla tay iny bne @next @end: rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/tgi_stat_stddrv.s������������������������������������������������������������0000664�0000000�0000000�00000000361�13473601511�0020176�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Address of the static standard tgi driver ; ; Oliver Schmidt, 2012-11-01 ; ; const void tgi_static_stddrv[]; ; .export _tgi_static_stddrv .import _atmos_240_200_2_tgi .rodata _tgi_static_stddrv := _atmos_240_200_2_tgi �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/tgi_stddrv.s�����������������������������������������������������������������0000664�0000000�0000000�00000000267�13473601511�0017150�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Name of the standard tgi driver ; ; Oliver Schmidt, 2012-11-01 ; ; const char tgi_stddrv[]; ; .export _tgi_stddrv .rodata _tgi_stddrv: .asciiz "atmos-240-200-2.tgi" �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/wherex.s���������������������������������������������������������������������0000664�0000000�0000000�00000000344�13473601511�0016275�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-04-13 ; ; unsigned char wherex (void); ; .export _wherex .include "atmos.inc" .proc _wherex ldx #$00 lda CURS_X rts .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/wherey.s���������������������������������������������������������������������0000664�0000000�0000000�00000000345�13473601511�0016277�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-04-13 ; ; unsigned char wherey (void); ; .export _wherey .include "atmos.inc" .proc _wherey ldx #$00 lda CURS_Y rts .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/atmos/write.s����������������������������������������������������������������������0000664�0000000�0000000�00000002017�13473601511�0016124�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-04-13 ; ; int write (int fd, const void* buf, int count); ; ; This function is a hack! ; .export _write .import popax, popptr1 .importzp ptr1, ptr2, ptr3, tmp1 .include "atmos.inc" .proc _write sta ptr3 stx ptr3+1 ; save count as result eor #$FF sta ptr2 txa eor #$FF sta ptr2+1 ; Remember -count-1 jsr popptr1 ; get buf jsr popax ; get fd and discard L1: inc ptr2 bne L2 inc ptr2+1 beq L9 L2: ldy #0 lda (ptr1),y tax cpx #$0A ; Check for \n bne L3 jsr PRINT ldx #$0D L3: jsr PRINT inc ptr1 bne L1 inc ptr1+1 jmp L1 ; No error, return count L9: lda ptr3 ldx ptr3+1 rts .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014140�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/_scrsize.s��������������������������������������������������������������������0000664�0000000�0000000�00000000545�13473601511�0016151�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.10.2000 ; ; Screen size variables ; .export screensize .include "c128.inc" .proc screensize ldx #40 ; Assume 40 column mode bit MODE bpl C40 ; Jump if 40 column mode ldx #80 C40: ldy #25 rts .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/acc_c128_speed.s��������������������������������������������������������������0000664�0000000�0000000�00000002745�13473601511�0016777�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2018-04-23, Marco van den Heuvel ; 2018-04-26, Greg King ; ; unsigned char __fastcall__ set_c128_speed (unsigned char speed); ; ;/* Set the speed of the C128 8502 CPU; using SPEED_SLOW will switch to ; * 1 Mhz (slow) mode, SPEED_2X or SPEED_FAST will switch to 2Mhz (fast) mode. ; * ; * Note that any value higher or equal to SPEED_2X will switch to fast mode. ; * ; * This function will return the actual speed the CPU is at, after trying ; * to set the requested speed; to my knowledge, the switching should not fail. ; * ; * For C64 programs, a check for a C128 in C64 mode is needed; make sure you ; * use 'detect_c128();' before using. ; * ; * For C128 programs, no detect function call is needed. ; */ ; unsigned char get_c128_speed (void); ; ;/* Get the speed of the C128 8502 CPU. ; * ; * Possible return values: ; * SPEED_SLOW : Slow mode ; * SPEED_2X : Fast mode ; * ; * For C64 programs, a check for a C128 in C64 mode is needed; make sure you ; * use 'detect_c128();' before using. ; * ; * For C128 programs, no detect function call is needed. ; */ .export _set_c128_speed .export _get_c128_speed .include "accelerator.inc" _set_c128_speed: cmp #SPEED_2X lda #$00 ; clear VIC-IIe test bit rol a ; carry flag is speed bit sta C128_VICIIE_CLK _get_c128_speed: lda C128_VICIIE_CLK and #$01 ldx #>$0000 rts ���������������������������cc65-2.18/libsrc/c128/acc_detect_c128.s�������������������������������������������������������������0000664�0000000�0000000�00000001011�13473601511�0017130�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Marco van den Heuvel, 2018-04-23 ; ; unsigned char detect_c128 (void); ; ;/* Check if the C128 8502 CPU is the current CPU. ; * ; * Possible return values: ; * 0x00 : C128 8502 is not the current CPU ; * 0x01 : C128 8502 is the current CPU ; */ .export _detect_c128 .include "accelerator.inc" _detect_c128: ldx #$00 lda #$01 ; Make sure the CPU is a 8502 .byte $3A ; NOP on 8502, DEA on 65(S)C(E)02, 4510 and 65816 rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/acc_detect_scpu.s�������������������������������������������������������������0000664�0000000�0000000�00000001453�13473601511�0017437�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Marco van den Heuvel, 2018-04-08 ; ; unsigned char detect_scpu (void); ; ;/* Check for the presence of the SuperCPU cartridge. ; * ; * Possible return values: ; * 0x00 : SuperCPU cartridge not present ; * 0x01 : SuperCPU cartridge present ; */ .export _detect_scpu .include "accelerator.inc" _detect_scpu: ldx #$00 txa ; Make sure the current CPU is a 65816 clc .byte $E2,$01 ; NOP #$01 on 6510 and 65(S)C02, LDA $(01,S),Y on 65CE02 and 4510, SEP #$01 on 65816 bcc not_found ; carry will be set on 65816 ; 65816 has been detected, make sure it's the SuperCPU cartridge lda SuperCPU_Detect asl bcs not_found found: lda #$01 not_found: rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/acc_scpu_speed.s��������������������������������������������������������������0000664�0000000�0000000�00000003145�13473601511�0017267�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Marco van den Heuvel, 2018-04-09 ; ; unsigned char __fastcall__ set_scpu_speed (unsigned char speed); ; ;/* Set the speed of the SuperCPU cartridge, using SPEED_SLOW will switch to ; * 1 Mhz mode, SPEED_20X or SPEED_FAST will switch to 20 Mhz mode. ; * ; * Note that any value lower than SPEED_20X will switch to 1 Mhz mode, and ; * any value higher or equal to SPEED_20X will switch to 20 Mhz mode. ; * ; * This function will return the actual speed the CPU is at after trying ; * to set the requested speed, if this is not the speed that was requested ; * then possibly the hardware speed switch prevented any software speed ; * switching. ; * ; * This function does not check for the presence of the SuperCPU cartridge, ; * make sure you use 'detect_scpu();' before using. ; */ ; unsigned char get_scpu_speed (void); ; ;/* Get the speed of the SuperCPU cartridge. ; * ; * Possible return values: ; * SPEED_1X : 1 Mhz mode ; * SPEED_20X : 20 Mhz mode ; * ; * This function does not check for the presence of the SuperCPU cartridge, ; * make sure you use 'detect_scpu();' before using. ; */ .export _set_scpu_speed .export _get_scpu_speed .include "accelerator.inc" _set_scpu_speed: cmp #SPEED_20X bcs high_speed low_speed: sta SuperCPU_Slow jmp _get_scpu_speed high_speed: sta SuperCPU_Fast _get_scpu_speed: ldx #$00 lda SuperCPU_Speed_Mode asl asl bcc is_fast_speed lda #SPEED_1X rts is_fast_speed: lda #SPEED_20X rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/break.s�����������������������������������������������������������������������0000664�0000000�0000000�00000005562�13473601511�0015420�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 27.09.1998 ; ; void __fastcall__ set_brk (unsigned Addr); ; void reset_brk (void); ; .export _set_brk, _reset_brk .destructor _reset_brk .export _brk_a, _brk_x, _brk_y, _brk_sr, _brk_pc .importzp ptr1 .include "c128.inc" .bss _brk_a: .res 1 _brk_x: .res 1 _brk_y: .res 1 _brk_sr: .res 1 _brk_pc: .res 2 .data uservec: jmp $FFFF ; Patched at runtime .code ; Set the break vector .proc _set_brk sta uservec+1 stx uservec+2 ; Set the user vector lda brk_old+1 ora brk_old+2 ; Did we save the vector already? bne @L1 ; Jump if we installed the handler already lda BRKVec ; Save the old vector sta brk_old+1 lda BRKVec+1 sta brk_old+2 lda #<brk_stub ; Set the break vector to our stub ldx #>brk_stub sta BRKVec stx BRKVec+1 lda #<brk_handler ; Set the indirect vector to our handler ldx #>brk_handler sta brk_ind+1 stx brk_ind+2 @L1: rts .endproc ; Reset the break vector .proc _reset_brk lda brk_old+1 ldx brk_old+2 beq @L9 ; Jump if vector not installed sta BRKVec stx BRKVec+1 lda #$00 sta brk_old+1 ; Clear the saved vector sta brk_old+2 @L9: rts .endproc ; Break handler, called if a break occurs .proc brk_handler pla sta _brk_y pla sta _brk_x pla sta _brk_a pla and #$EF ; Clear break bit sta _brk_sr pla ; PC low sec sbc #2 ; Point to start of brk sta _brk_pc pla ; PC high sbc #0 sta _brk_pc+1 jsr uservec ; Call the user's routine lda _brk_pc+1 pha lda _brk_pc pha lda _brk_sr pha ldx _brk_x ldy _brk_y lda _brk_a rti ; Jump back... .endproc ; Break stub, must go into low (non banked) memory .segment "LOWCODE" .proc brk_stub pla ; Get original MMU_CR value sta MMU_CR ; And set it jmp brk_ind ; Jump indirect to break .endproc ; ------------------------------------------------------------------------ ; Data .data ; Old break vector preceeded by a jump opcode brk_old: jmp $0000 ; Indirect vectors preceeded by a jump opcode brk_ind: jmp $0000 ����������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/c64mode.s���������������������������������������������������������������������0000664�0000000�0000000�00000000363�13473601511�0015567�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-02-13 ; ; void c64mode (void); ; /* Switch the C128 into C64 mode. Note: This function will not return! */ ; .export _c64mode .import C64MODE _c64mode = C64MODE �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/cgetc.s�����������������������������������������������������������������������0000664�0000000�0000000�00000003420�13473601511�0015410�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; char cgetc (void); ; .export _cgetc .constructor initcgetc .destructor donecgetc .import cursor .include "cbm_kernal.inc" .include "c128.inc" ;-------------------------------------------------------------------------- _cgetc: lda KEY_COUNT ; Get number of characters bne L2 ; Jump if there are already chars waiting ; Switch on the cursor if needed. We MUST always switch the cursor on, ; before switching it off, because switching it off will restore the ; character attribute remembered when it was switched on. So just switching ; it off will restore the wrong character attribute. jsr CURS_SET ; Set cursor to current position jsr CURS_ON lda cursor bne L1 lda #$01 jsr CURS_OFF L1: lda KEY_COUNT ; Check characters again beq L1 jsr CURS_OFF ; Switch cursor off, if characters available L2: jsr KBDREAD ; Read char and return in A ldx #0 rts ;-------------------------------------------------------------------------- ; Module constructor/destructor .segment "INIT" keyvec: .res 2 .segment "ONCE" initcgetc: ; Save the old vector lda KeyStoreVec ldx KeyStoreVec+1 sta keyvec stx keyvec+1 ; Set the new vector. I can only hope that this works for other C128 ; versions... lda #<$C6B7 ldx #>$C6B7 jmp SetVec .code donecgetc: lda keyvec ldx keyvec+1 SetVec: sei sta KeyStoreVec stx KeyStoreVec+1 cli rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/clrscr.s����������������������������������������������������������������������0000664�0000000�0000000�00000000235�13473601511�0015614�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; void clrscr (void); ; .export _clrscr .include "cbm_kernal.inc" _clrscr = CLRSCR �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/color.s�����������������������������������������������������������������������0000664�0000000�0000000�00000004343�13473601511�0015446�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; 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 .import return0 .include "c128.inc" _textcolor: bit MODE ; Check 80/40 column mode bmi @L1 ; Jump if 80 columns ; 40 column mode ldx CHARCOLOR ; Get the old color sta CHARCOLOR ; Set the new color txa ; Old color -> A ldx #$00 ; Load high byte rts ; 80 column mode @L1: tax ; Move new color to X lda CHARCOLOR ; Get old color + attributes and #$F0 ; Keep old attributes ora $CE5C,x ; Translate VIC color -> VDC color ldx CHARCOLOR ; Get the old color sta CHARCOLOR ; Set the new color + old attributes txa ; Old color -> A and #$0F ; Mask out attributes ldx #$00 ; Load high byte ; translate vdc->vic colour vdctovic: ldy #16 @L2: cmp $CE5C-1,y beq @L3 dey bne @L2 @L3: tya rts _bgcolor: bit MODE bmi @L1 ; 40 column mode ldx VIC_BG_COLOR0 ; get old value sta VIC_BG_COLOR0 ; set new value txa ldx #$00 rts ; 80 column mode @L1: tax ; Move new color to X lda $CE5C,x ; Translate VIC color -> VDC color pha ldx #26 jsr $CDDA ; Read vdc register 26 jsr vdctovic tay pla ldx #26 jsr $CDCC ; Write vdc register 26 tya ldx #$00 rts _bordercolor: bit MODE bmi @L1 ; 40 column mode ldx VIC_BORDERCOLOR ; get old value sta VIC_BORDERCOLOR ; set new value txa ldx #$00 rts ; 80 column mode @L1: jmp return0 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/conio.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000251�13473601511�0015431�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; Low level stuff for screen output/console input ; .exportzp CURS_X, CURS_Y .include "c128.inc" �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/cpeekc.s����������������������������������������������������������������������0000664�0000000�0000000�00000002603�13473601511�0015557�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2016-02-28, Groepaz ; 2017-06-26, Greg King ; ; char cpeekc (void); ; .export _cpeekc .import plot, popa .include "zeropage.inc" .include "c128.inc" _cpeekc: lda MODE bmi @c80 ldy CURS_X lda (SCREEN_PTR),y ; get char @return: and #<~$80 ; remove reverse flag ; Convert the screen code into a PetSCII code. ; $00 - $1F: +$40 ; $20 - $3F ; $40 - $5f: +$20 ; $60 - $7F: +$40 cmp #$20 bcs @sk1 ;(bge) ora #$40 rts @sk1: cmp #$40 bcc @end ;(blt) cmp #$60 bcc @sk2 ;(blt) ;sec adc #$20 - $01 @sk2: ;clc ; both above cmp and adc clear carry flag adc #$20 @end: rts @c80: lda SCREEN_PTR ldy SCREEN_PTR+1 clc adc CURS_X bcc @s iny ; get byte from VDC mem @s: ldx #VDC_DATA_LO stx VDC_INDEX @L0: bit VDC_INDEX bpl @L0 sta VDC_DATA dex stx VDC_INDEX sty VDC_DATA ldx #VDC_RAM_RW stx VDC_INDEX @L1: bit VDC_INDEX bpl @L1 ; wait for blanking lda VDC_DATA jmp @return �����������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/cpeekcolor.s������������������������������������������������������������������0000664�0000000�0000000�00000002007�13473601511�0016451�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2016-02-28, Groepaz ; 2017-06-26, Greg King ; ; unsigned char cpeekcolor (void); ; .export _cpeekcolor .include "c128.inc" _cpeekcolor: bit MODE bmi @c80 ldy CURS_X lda (CRAM_PTR),y ; get color and #$0F ldx #>$0000 rts @c80: lda CRAM_PTR ldy CRAM_PTR+1 clc adc CURS_X bcc @s iny ; get byte from VDC mem @s: ldx #VDC_DATA_LO stx VDC_INDEX @L0: bit VDC_INDEX bpl @L0 sta VDC_DATA dex stx VDC_INDEX sty VDC_DATA ldx #VDC_RAM_RW stx VDC_INDEX @L1: bit VDC_INDEX bpl @L1 ; wait for blanking lda VDC_DATA and #$0F ; translate VDC->VIC colour vdctovic: ldy #$0F + 1 @L2: dey cmp $CE5C,y bne @L2 tya ldx #>$0000 rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/cpeekrevers.s�����������������������������������������������������������������0000664�0000000�0000000�00000002033�13473601511�0016640�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2016-02-28, Groepaz ; 2017-06-26, Greg King ; ; unsigned char cpeekrevers (void); ; .export _cpeekrevers .include "zeropage.inc" .include "c128.inc" _cpeekrevers: lda MODE bmi @c80 ldy CURS_X lda (SCREEN_PTR),y ; get char @return: and #$80 ; get reverse flag asl a tax ; ldx #>$0000 rol a ; return boolean value rts @c80: lda SCREEN_PTR ldy SCREEN_PTR+1 clc adc CURS_X bcc @s iny ; get byte from VDC mem @s: ldx #VDC_DATA_LO stx VDC_INDEX @L0: bit VDC_INDEX bpl @L0 sta VDC_DATA dex stx VDC_INDEX sty VDC_DATA ldx #VDC_RAM_RW stx VDC_INDEX @L1: bit VDC_INDEX bpl @L1 ; wait for blanking lda VDC_DATA jmp @return �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/cpeeks.s����������������������������������������������������������������������0000664�0000000�0000000�00000007007�13473601511�0015602�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2017-07-05, Greg King ; 2017-12-12, Groepaz ; ; void cpeeks (char* s, unsigned length); ; .export _cpeeks .import popax .importzp ptr1, ptr2, ptr3, tmp1, tmp2 .macpack generic ; FIXME c128 needs special version that handles the 80-column VDC. .include "c128.inc" _cpeeks: eor #<$FFFF ; counting a word upward is faster sta ptr3 ; so, we use -(length + 1) txa eor #>$FFFF sta ptr3+1 lda MODE bmi c80 lda SCREEN_PTR ldx SCREEN_PTR+1 sta ptr2 stx ptr2+1 ldy CURS_X sty tmp2 jsr popax sta tmp1 ; (will be a .Y index) stx ptr1+1 ldx #<$0000 stx ptr1 bze L3 ; branch always L4: ldy tmp2 lda (ptr2),y ; get char iny bnz L2 inc ptr2+1 L2: sty tmp2 and #<~$80 ; remove reverse bit ; Convert the screen code into a PetSCII code. ; $00 - $1F: +$40 ; $20 - $3F ; $40 - $5f: +$20 ; $60 - $7F: +$40 cmp #$20 blt @sk1 ;(bcc) cmp #$40 blt L5 cmp #$60 blt @sk2 ;(bcc) clc @sk1: adc #$20 @sk2: ;clc ; both above cmp and adc clear carry flag adc #$20 L5: ldy tmp1 sta (ptr1),y iny bnz L1 inc ptr1+1 L1: sty tmp1 L3: inc ptr3 ; count length bnz L4 inc ptr3+1 bnz L4 txa ; terminate the string ldy tmp1 sta (ptr1),y rts ;----------------------------------------------------------- c80: lda SCREEN_PTR clc adc CURS_X sta ptr2 lda SCREEN_PTR+1 adc #0 sta ptr2+1 jsr popax sta tmp1 ; (will be a .Y index) stx ptr1+1 ldx #<$0000 stx ptr1 bze L3a ; branch always L4a: lda ptr2 ldy ptr2+1 inc ptr2 bne @s inc ptr2+1 @s: ; get byte from VDC mem ldx #VDC_DATA_LO stx VDC_INDEX @L0: bit VDC_INDEX bpl @L0 sta VDC_DATA dex stx VDC_INDEX sty VDC_DATA ldx #VDC_RAM_RW stx VDC_INDEX @L1: bit VDC_INDEX bpl @L1 ; wait for blanking lda VDC_DATA and #<~$80 ; remove reverse bit ; Convert the screen code into a PetSCII code. ; $00 - $1F: +$40 ; $20 - $3F ; $40 - $5f: +$20 ; $60 - $7F: +$40 cmp #$20 blt @sk1 ;(bcc) cmp #$40 blt L5a cmp #$60 blt @sk2 ;(bcc) clc @sk1: adc #$20 @sk2: ;clc ; both above cmp and adc clear carry flag adc #$20 L5a: ldy tmp1 sta (ptr1),y iny bnz L1a inc ptr1+1 L1a: sty tmp1 L3a: inc ptr3 ; count length bnz L4a inc ptr3+1 bnz L4a lda #0 ; terminate the string ldy tmp1 sta (ptr1),y rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/cputc.s�����������������������������������������������������������������������0000664�0000000�0000000�00000004275�13473601511�0015452�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2000-08-06, 2002-12-21 ; Using lots of code from MagerValp, MagerValp@cling.gu.se ; ; void cputcxy (unsigned char x, unsigned char y, char c); ; void cputc (char c); ; .export _cputcxy, _cputc, cputdirect, putchar .export newline, plot .import gotoxy .include "cbm_kernal.inc" .include "c128.inc" newline = NEWLINE ;-------------------------------------------------------------------------- .code _cputcxy: pha ; Save C jsr gotoxy ; Set cursor, drop x and y pla ; Restore C ; Plot a character - also used as internal function _cputc: cmp #$0A ; CR? beq cr ; Output a cr cmp #$0D ; LF? bne L2 jmp NEWLINE ; Update cursor position ; Printable char of some sort L2: cmp #' ' bcc cputdirect ; Other control char tay bmi L5 cmp #$60 bcc L3 and #$DF bne cputdirect ; Branch always L3: and #$3F ; Output one character to the screen. We will disable scrolling while doing so cputdirect: tax ; Save output char lda SCROLL pha ; Save scroll flag lda #$C0 sta SCROLL ; Disable scrolling txa ; Restore output char jsr PRINT pla sta SCROLL ; Restore old scroll flag rts ; Handle character if high bit set L5: and #$7F cmp #$7E ; PI? bne L6 lda #$5E ; Load screen code for PI bne cputdirect L6: ora #$40 bne cputdirect ; Branch always ; Carriage return cr: lda #0 sta CURS_X ; 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 = $CC2F �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/crt0.s������������������������������������������������������������������������0000664�0000000�0000000�00000005523�13473601511�0015201�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Startup code for cc65 (C128 version) ; .export _exit .export __STARTUP__ : absolute = 1 ; Mark as startup .import initlib, donelib .import zerobss .import push0, callmain .import RESTOR, BSOUT, CLRCH .import __MAIN_START__, __MAIN_SIZE__, __STACKSIZE__ .importzp ST .include "zeropage.inc" .include "c128.inc" ; ------------------------------------------------------------------------ ; Startup code .segment "STARTUP" Start: ; Switch to the second charset. lda #14 jsr BSOUT ; Before doing anything else, we have to set up our banking configuration. ; Otherwise, just the lowest 16K are actually RAM. Writing through the ROM ; to the underlying RAM works; but, it is bad style. lda MMU_CR ; Get current memory configuration... pha ; ...and save it for later lda #MMU_CFG_CC65 ; Bank0 with Kernal ROM sta MMU_CR ; Save the zero-page locations that we need. ldx #zpspace-1 L1: lda sp,x sta zpsave,x dex bpl L1 ; Clear the BSS data. jsr zerobss ; Save some system stuff; and, set up the stack. pla ; Get MMU setting sta mmusave tsx stx spsave ; Save the system stack pointer 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. jsr initlib ; Set the bank for the file name to our execution bank. We must do this ; *after* calling the constructors because some of them might depend on ; the original value of this register. lda #0 sta FNAM_BANK ; Push the command-line arguments; and, call main(). jsr callmain ; Back from main() [this is also the exit() entry]. Run the module destructors. _exit: pha ; Save the return code on stack jsr donelib ; Copy back the zero-page stuff. ldx #zpspace-1 L2: lda zpsave,x sta sp,x dex bpl L2 ; Place the program return code into BASIC's status variable. pla sta ST ; Reset the stack and the memory configuration. ldx spsave txs ldx mmusave stx MMU_CR ; Done, return to BASIC. rts ; ------------------------------------------------------------------------ ; Data .segment "INIT" zpsave: .res zpspace ; ------------------------------------------------------------------------ .bss spsave: .res 1 mmusave:.res 1 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/dbgbreak.s_�������������������������������������������������������������������0000664�0000000�0000000�00000000661�13473601511�0016227�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 10.08.1998 ; ; unsigned DbgSetBreakVec (unsigned Addr); ; .export _DbgSetBreakVec .import popax, utstax .include "../cbm/cbm.inc" _DbgSetBreakVec: jsr popax ; Get the new address ldy BRKVec sta BRKVec lda BRKVec+1 stx BRKVec+1 tax tya jmp utstax �������������������������������������������������������������������������������cc65-2.18/libsrc/c128/devnum.s����������������������������������������������������������������������0000664�0000000�0000000�00000000157�13473601511�0015625�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2010-02-14 ; .include "c128.inc" .exportzp devnum := DEVNUM �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/emd/��������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014705�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/emd/c128-efnram.s�������������������������������������������������������������0000775�0000000�0000000�00000017007�13473601511�0017024�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Extended memory driver for the C128 External Function RAM. Driver works ; without problems when statically linked. ; ; Marco van den Heuvel, 2015-11-30 ; .include "zeropage.inc" .include "em-kernel.inc" .include "em-error.inc" .include "c128.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c128_efnram_emd ; Driver signature .byte $65, $6d, $64 ; "emd" .byte EMD_API_VERSION ; EM API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr PAGECOUNT .addr MAP .addr USE .addr COMMIT .addr COPYFROM .addr COPYTO ; ------------------------------------------------------------------------ ; Constants BASE = $8000 PAGES = 127 ; Do not touch MMU ; ------------------------------------------------------------------------ ; Data. .bss curpage: .res 2 ; Current page number window: .res 256 ; Memory "window" .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present and determine the amount of ; memory available. ; Must return an EM_ERR_xx code in a/x. ; INSTALL: ldx #0 stx ptr1 ldx #$80 stx ptr1+1 ldx #<ptr1 stx FETVEC stx STAVEC ldy #0 ldx #MMU_CFG_EFROM sei jsr FETCH tax inx txa sta tmp1 ldx #MMU_CFG_EFROM sei jsr STASH ldx #MMU_CFG_EFROM jsr FETCH cli cmp tmp1 beq @ram_present lda #<EM_ERR_NO_DEVICE ldx #>EM_ERR_NO_DEVICE rts @ram_present: ldx #$FF stx curpage stx curpage+1 ; Invalidate the current page inx txa ; A = X = EM_ERR_OK ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; PAGECOUNT: Return the total number of available pages in a/x. ; PAGECOUNT: lda #<PAGES ldx #>PAGES rts ; ------------------------------------------------------------------------ ; MAP: Map the page in a/x into memory and return a pointer to the page in ; a/x. The contents of the currently mapped page (if any) may be discarded ; by the driver. ; MAP: sta curpage stx curpage+1 ; Remember the new page clc adc #>BASE sta ptr1+1 ldy #$00 sty ptr1 lda #<ptr1 sta FETVEC sei ; Transfer one page @L1: ldx #MMU_CFG_EFROM jsr FETCH sta window,y iny bne @L1 ; Return the memory window cli lda #<window ldx #>window ; Return the window address rts ; ------------------------------------------------------------------------ ; USE: Tell the driver that the window is now associated with a given page. USE: sta curpage stx curpage+1 ; Remember the page lda #<window ldx #>window ; Return the window rts ; ------------------------------------------------------------------------ ; COMMIT: Commit changes in the memory window to extended storage. COMMIT: lda curpage ; Get the current page ldx curpage+1 bmi done ; Jump if no page mapped clc adc #>BASE sta ptr1+1 ldy #$00 sty ptr1 lda #<ptr1 sta STAVEC sei ; Transfer one page. Y must be zero on entry @L1: lda window,y ldx #MMU_CFG_EFROM jsr STASH iny bne @L1 cli ; Done done: rts ; ------------------------------------------------------------------------ ; COPYFROM: Copy from extended into linear memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYFROM: sta ptr3 stx ptr3+1 ; Save the passed em_copy pointer ldy #EM_COPY::OFFS lda (ptr3),y sta ptr1 ldy #EM_COPY::PAGE lda (ptr3),y clc adc #>BASE sta ptr1+1 ; From ldy #EM_COPY::BUF lda (ptr3),y sta ptr2 iny lda (ptr3),y sta ptr2+1 ; To lda #<ptr1 sta FETVEC ldy #EM_COPY::COUNT+1 lda (ptr3),y ; Get number of pages beq @L2 ; Skip if no full pages sta tmp1 ; Copy full pages ldy #$00 sei @L1: ldx #MMU_CFG_EFROM jsr FETCH sta (ptr2),y iny bne @L1 inc ptr1+1 inc ptr2+1 dec tmp1 bne @L1 ; Copy the remainder of the page @L2: ldy #EM_COPY::COUNT lda (ptr3),y ; Get bytes in last page beq @L4 sta tmp1 ldy #$00 @L3: ldx #MMU_CFG_EFROM jsr FETCH sta (ptr2),y iny dec tmp1 bne @L3 ; Done @L4: cli rts ; ------------------------------------------------------------------------ ; COPYTO: Copy from linear into extended memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYTO: sta ptr3 stx ptr3+1 ; Save the passed em_copy pointer ldy #EM_COPY::OFFS lda (ptr3),y sta ptr1 ldy #EM_COPY::PAGE lda (ptr3),y clc adc #>BASE sta ptr1+1 ; To ldy #EM_COPY::BUF lda (ptr3),y sta ptr2 iny lda (ptr3),y sta ptr2+1 ; From lda #<ptr1 sta STAVEC ldy #EM_COPY::COUNT+1 lda (ptr3),y ; Get number of pages beq @L2 ; Skip if no full pages sta tmp1 ; Copy full pages sei ldy #$00 @L1: lda (ptr2),y ldx #MMU_CFG_EFROM jsr STASH iny bne @L1 inc ptr1+1 inc ptr2+1 dec tmp1 bne @L1 ; Copy the remainder of the page @L2: ldy #EM_COPY::COUNT lda (ptr3),y ; Get bytes in last page beq @L4 sta tmp1 ldy #$00 @L3: lda (ptr2),y ldx #MMU_CFG_EFROM jsr STASH iny dec tmp1 bne @L3 ; Done @L4: cli rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/emd/c128-georam.s�������������������������������������������������������������0000664�0000000�0000000�00000020226�13473601511�0017020�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Extended memory driver for the GEORAM cartridge. Driver works without ; problems when statically linked. ; ; Ullrich von Bassewitz, 2002-11-29 ; ; GEORAM page size checking routine by ; Marco van den Heuvel, 2010-01-21 ; .include "zeropage.inc" .include "em-kernel.inc" .include "em-error.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c128_georam_emd ; Driver signature .byte $65, $6d, $64 ; "emd" .byte EMD_API_VERSION ; EM API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr PAGECOUNT .addr MAP .addr USE .addr COMMIT .addr COPYFROM .addr COPYTO ; ------------------------------------------------------------------------ ; Constants GR_WINDOW = $DE00 ; Address of GEORAM window GR_PAGE_LO = $DFFE ; Page register low GR_PAGE_HI = $DFFF ; Page register high ; ------------------------------------------------------------------------ ; Data. .data pagecount: .res 2 ; Number of available pages .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present and determine the amount of ; memory available. ; Must return an EM_ERR_xx code in a/x. ; INSTALL: ldx GR_WINDOW cpx GR_WINDOW bne @notpresent inc GR_WINDOW cpx GR_WINDOW beq @notpresent lda #4 jsr check cpy GR_WINDOW beq @has64k lda #8 jsr check cpy GR_WINDOW beq @has128k lda #16 jsr check cpy GR_WINDOW beq @has256k lda #32 jsr check cpy GR_WINDOW beq @has512k lda #64 jsr check cpy GR_WINDOW beq @has1024k lda #128 jsr check cpy GR_WINDOW beq @has2048k ldx #>16384 bne @setok @has64k: ldx #>256 bne @setok @has128k: ldx #>512 bne @setok @has256k: ldx #>1024 bne @setok @has512k: ldx #>2048 bne @setok @has1024k: ldx #>4096 bne @setok @has2048k: ldx #>8192 bne @setok @notpresent: lda #<EM_ERR_NO_DEVICE ldx #>EM_ERR_NO_DEVICE rts @setok: lda #0 sta pagecount stx pagecount+1 lda #<EM_ERR_OK ldx #>EM_ERR_OK rts check: ldx #0 stx GR_PAGE_LO stx GR_PAGE_HI ldy GR_WINDOW iny sta GR_PAGE_HI sty GR_WINDOW ldx #0 stx GR_PAGE_HI ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; PAGECOUNT: Return the total number of available pages in a/x. ; PAGECOUNT: lda pagecount ldx pagecount+1 rts ; ------------------------------------------------------------------------ ; USE: Tell the driver that the window is now associated with a given page. ; The GeoRAM cartridge does not copy but actually map the window, so USE is ; identical to MAP. USE = MAP ; ------------------------------------------------------------------------ ; MAP: Map the page in a/x into memory and return a pointer to the page in ; a/x. The contents of the currently mapped page (if any) may be discarded ; by the driver. ; MAP: sta tmp1 txa asl tmp1 rol a asl tmp1 rol a sta GR_PAGE_HI lda tmp1 lsr a lsr a sta GR_PAGE_LO lda #<GR_WINDOW ldx #>GR_WINDOW ; Use the RTS from COMMIT below to save a precious byte of storage ; ------------------------------------------------------------------------ ; COMMIT: Commit changes in the memory window to extended storage. COMMIT: rts ; ------------------------------------------------------------------------ ; COPYFROM: Copy from extended into linear memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYFROM: jsr setup ; Setup is: ; ; - ptr1 contains the struct pointer ; - ptr2 contains the linear memory buffer ; - ptr3 contains -(count-1) ; - tmp1 contains the low page register value ; - tmp2 contains the high page register value ; - X contains the page offset ; - Y contains zero jmp @L5 @L1: lda GR_WINDOW,x sta (ptr2),y iny bne @L2 inc ptr2+1 @L2: inx beq @L4 ; Bump count and repeat @L3: inc ptr3 bne @L1 inc ptr3+1 bne @L1 rts ; Bump page register @L4: inc tmp1 ; Bump low page register bit tmp1 ; Check for overflow in bit 6 bvc @L6 ; Jump if no overflow inc tmp2 @L5: lda tmp2 sta GR_PAGE_HI @L6: lda tmp1 sta GR_PAGE_LO jmp @L3 ; ------------------------------------------------------------------------ ; COPYTO: Copy from linear into extended memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYTO: jsr setup ; Setup is: ; ; - ptr1 contains the struct pointer ; - ptr2 contains the linear memory buffer ; - ptr3 contains -(count-1) ; - tmp1 contains the low page register value ; - tmp2 contains the high page register value ; - X contains the page offset ; - Y contains zero jmp @L5 @L1: lda (ptr2),y sta GR_WINDOW,x iny bne @L2 inc ptr2+1 @L2: inx beq @L4 ; Bump count and repeat @L3: inc ptr3 bne @L1 inc ptr3+1 bne @L1 rts ; Bump page register @L4: inc tmp1 ; Bump low page register bit tmp1 ; Check for overflow in bit 6 bvc @L6 ; Jump if no overflow inc tmp2 @L5: lda tmp2 sta GR_PAGE_HI @L6: lda tmp1 sta GR_PAGE_LO jmp @L3 ; ------------------------------------------------------------------------ ; Helper function for COPYFROM and COPYTO: Store the pointer to the request ; structure and prepare data for the copy setup: sta ptr1 stx ptr1+1 ; Save passed pointer ; Get the page number from the struct and adjust it so that it may be used ; with the hardware. That is: lower 6 bits in tmp1, high bits in tmp2. ldy #EM_COPY::PAGE+1 lda (ptr1),y sta tmp2 dey lda (ptr1),y asl a rol tmp2 asl a rol tmp2 lsr a lsr a sta tmp1 ; Get the buffer pointer into ptr2 ldy #EM_COPY::BUF lda (ptr1),y sta ptr2 iny lda (ptr1),y sta ptr2+1 ; Get the count, calculate -(count-1) and store it into ptr3 ldy #EM_COPY::COUNT lda (ptr1),y eor #$FF sta ptr3 iny lda (ptr1),y eor #$FF sta ptr3+1 ; Get the page offset into X and clear Y ldy #EM_COPY::OFFS lda (ptr1),y tax ldy #$00 ; Done rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/emd/c128-ifnram.s�������������������������������������������������������������0000775�0000000�0000000�00000017007�13473601511�0017030�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Extended memory driver for the C128 Internal Function RAM. Driver works ; without problems when statically linked. ; ; Marco van den Heuvel, 2015-11-30 ; .include "zeropage.inc" .include "em-kernel.inc" .include "em-error.inc" .include "c128.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c128_ifnram_emd ; Driver signature .byte $65, $6d, $64 ; "emd" .byte EMD_API_VERSION ; EM API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr PAGECOUNT .addr MAP .addr USE .addr COMMIT .addr COPYFROM .addr COPYTO ; ------------------------------------------------------------------------ ; Constants BASE = $8000 PAGES = 127 ; Do not touch MMU ; ------------------------------------------------------------------------ ; Data. .bss curpage: .res 2 ; Current page number window: .res 256 ; Memory "window" .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present and determine the amount of ; memory available. ; Must return an EM_ERR_xx code in a/x. ; INSTALL: ldx #0 stx ptr1 ldx #$80 stx ptr1+1 ldx #<ptr1 stx FETVEC stx STAVEC ldy #0 ldx #MMU_CFG_IFROM sei jsr FETCH tax inx txa sta tmp1 ldx #MMU_CFG_IFROM sei jsr STASH ldx #MMU_CFG_IFROM jsr FETCH cli cmp tmp1 beq @ram_present lda #<EM_ERR_NO_DEVICE ldx #>EM_ERR_NO_DEVICE rts @ram_present: ldx #$FF stx curpage stx curpage+1 ; Invalidate the current page inx txa ; A = X = EM_ERR_OK ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; PAGECOUNT: Return the total number of available pages in a/x. ; PAGECOUNT: lda #<PAGES ldx #>PAGES rts ; ------------------------------------------------------------------------ ; MAP: Map the page in a/x into memory and return a pointer to the page in ; a/x. The contents of the currently mapped page (if any) may be discarded ; by the driver. ; MAP: sta curpage stx curpage+1 ; Remember the new page clc adc #>BASE sta ptr1+1 ldy #$00 sty ptr1 lda #<ptr1 sta FETVEC sei ; Transfer one page @L1: ldx #MMU_CFG_IFROM jsr FETCH sta window,y iny bne @L1 ; Return the memory window cli lda #<window ldx #>window ; Return the window address rts ; ------------------------------------------------------------------------ ; USE: Tell the driver that the window is now associated with a given page. USE: sta curpage stx curpage+1 ; Remember the page lda #<window ldx #>window ; Return the window rts ; ------------------------------------------------------------------------ ; COMMIT: Commit changes in the memory window to extended storage. COMMIT: lda curpage ; Get the current page ldx curpage+1 bmi done ; Jump if no page mapped clc adc #>BASE sta ptr1+1 ldy #$00 sty ptr1 lda #<ptr1 sta STAVEC sei ; Transfer one page. Y must be zero on entry @L1: lda window,y ldx #MMU_CFG_IFROM jsr STASH iny bne @L1 cli ; Done done: rts ; ------------------------------------------------------------------------ ; COPYFROM: Copy from extended into linear memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYFROM: sta ptr3 stx ptr3+1 ; Save the passed em_copy pointer ldy #EM_COPY::OFFS lda (ptr3),y sta ptr1 ldy #EM_COPY::PAGE lda (ptr3),y clc adc #>BASE sta ptr1+1 ; From ldy #EM_COPY::BUF lda (ptr3),y sta ptr2 iny lda (ptr3),y sta ptr2+1 ; To lda #<ptr1 sta FETVEC ldy #EM_COPY::COUNT+1 lda (ptr3),y ; Get number of pages beq @L2 ; Skip if no full pages sta tmp1 ; Copy full pages ldy #$00 sei @L1: ldx #MMU_CFG_IFROM jsr FETCH sta (ptr2),y iny bne @L1 inc ptr1+1 inc ptr2+1 dec tmp1 bne @L1 ; Copy the remainder of the page @L2: ldy #EM_COPY::COUNT lda (ptr3),y ; Get bytes in last page beq @L4 sta tmp1 ldy #$00 @L3: ldx #MMU_CFG_IFROM jsr FETCH sta (ptr2),y iny dec tmp1 bne @L3 ; Done @L4: cli rts ; ------------------------------------------------------------------------ ; COPYTO: Copy from linear into extended memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYTO: sta ptr3 stx ptr3+1 ; Save the passed em_copy pointer ldy #EM_COPY::OFFS lda (ptr3),y sta ptr1 ldy #EM_COPY::PAGE lda (ptr3),y clc adc #>BASE sta ptr1+1 ; To ldy #EM_COPY::BUF lda (ptr3),y sta ptr2 iny lda (ptr3),y sta ptr2+1 ; From lda #<ptr1 sta STAVEC ldy #EM_COPY::COUNT+1 lda (ptr3),y ; Get number of pages beq @L2 ; Skip if no full pages sta tmp1 ; Copy full pages sei ldy #$00 @L1: lda (ptr2),y ldx #MMU_CFG_IFROM jsr STASH iny bne @L1 inc ptr1+1 inc ptr2+1 dec tmp1 bne @L1 ; Copy the remainder of the page @L2: ldy #EM_COPY::COUNT lda (ptr3),y ; Get bytes in last page beq @L4 sta tmp1 ldy #$00 @L3: lda (ptr2),y ldx #MMU_CFG_IFROM jsr STASH iny dec tmp1 bne @L3 ; Done @L4: cli rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/emd/c128-ram.s����������������������������������������������������������������0000664�0000000�0000000�00000015707�13473601511�0016335�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Extended memory driver for the C128 RAM in bank #1. Driver works without ; problems when statically linked. ; ; Ullrich von Bassewitz, 2002-12-04 ; .include "zeropage.inc" .include "em-kernel.inc" .include "em-error.inc" .include "c128.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c128_ram_emd ; Driver signature .byte $65, $6d, $64 ; "emd" .byte EMD_API_VERSION ; EM API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr PAGECOUNT .addr MAP .addr USE .addr COMMIT .addr COPYFROM .addr COPYTO ; ------------------------------------------------------------------------ ; Constants BASE = $400 TOPMEM = $FF00 PAGES = (TOPMEM - BASE) / 256 ; ------------------------------------------------------------------------ ; Data. .bss curpage: .res 2 ; Current page number window: .res 256 ; Memory "window" .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present and determine the amount of ; memory available. ; Must return an EM_ERR_xx code in a/x. ; INSTALL: ldx #$FF stx curpage stx curpage+1 ; Invalidate the current page inx txa ; A = X = EM_ERR_OK ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; PAGECOUNT: Return the total number of available pages in a/x. ; PAGECOUNT: lda #<PAGES ldx #>PAGES rts ; ------------------------------------------------------------------------ ; MAP: Map the page in a/x into memory and return a pointer to the page in ; a/x. The contents of the currently mapped page (if any) may be discarded ; by the driver. ; MAP: sta curpage stx curpage+1 ; Remember the new page clc adc #>BASE sta ptr1+1 ldy #$00 sty ptr1 lda #<ptr1 sta FETVEC sei ; Transfer one page @L1: ldx #MMU_CFG_RAM1 jsr FETCH sta window,y iny bne @L1 cli ; Return the memory window lda #<window ldx #>window ; Return the window address rts ; ------------------------------------------------------------------------ ; USE: Tell the driver that the window is now associated with a given page. USE: sta curpage stx curpage+1 ; Remember the page lda #<window ldx #>window ; Return the window rts ; ------------------------------------------------------------------------ ; COMMIT: Commit changes in the memory window to extended storage. COMMIT: lda curpage ; Get the current page ldx curpage+1 bmi done ; Jump if no page mapped clc adc #>BASE sta ptr1+1 ldy #$00 sty ptr1 lda #<ptr1 sta STAVEC sei ; Transfer one page. Y must be zero on entry @L1: lda window,y ldx #MMU_CFG_RAM1 jsr STASH iny bne @L1 cli ; Done done: rts ; ------------------------------------------------------------------------ ; COPYFROM: Copy from extended into linear memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYFROM: sta ptr3 stx ptr3+1 ; Save the passed em_copy pointer ldy #EM_COPY::OFFS lda (ptr3),y sta ptr1 ldy #EM_COPY::PAGE lda (ptr3),y clc adc #>BASE sta ptr1+1 ; From ldy #EM_COPY::BUF lda (ptr3),y sta ptr2 iny lda (ptr3),y sta ptr2+1 ; To lda #<ptr1 sta FETVEC ldy #EM_COPY::COUNT+1 lda (ptr3),y ; Get number of pages beq @L2 ; Skip if no full pages sta tmp1 ; Copy full pages ldy #$00 sei @L1: ldx #MMU_CFG_RAM1 jsr FETCH sta (ptr2),y iny bne @L1 inc ptr1+1 inc ptr2+1 dec tmp1 bne @L1 ; Copy the remainder of the page @L2: ldy #EM_COPY::COUNT lda (ptr3),y ; Get bytes in last page beq @L4 sta tmp1 ldy #$00 @L3: ldx #MMU_CFG_RAM1 jsr FETCH sta (ptr2),y iny dec tmp1 bne @L3 ; Done @L4: cli rts ; ------------------------------------------------------------------------ ; COPYTO: Copy from linear into extended memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYTO: sta ptr3 stx ptr3+1 ; Save the passed em_copy pointer ldy #EM_COPY::OFFS lda (ptr3),y sta ptr1 ldy #EM_COPY::PAGE lda (ptr3),y clc adc #>BASE sta ptr1+1 ; To ldy #EM_COPY::BUF lda (ptr3),y sta ptr2 iny lda (ptr3),y sta ptr2+1 ; From lda #<ptr1 sta STAVEC ldy #EM_COPY::COUNT+1 lda (ptr3),y ; Get number of pages beq @L2 ; Skip if no full pages sta tmp1 ; Copy full pages ldy #$00 sei @L1: lda (ptr2),y ldx #MMU_CFG_RAM1 jsr STASH iny bne @L1 inc ptr1+1 inc ptr2+1 dec tmp1 bne @L1 ; Copy the remainder of the page @L2: ldy #EM_COPY::COUNT lda (ptr3),y ; Get bytes in last page beq @L4 sta tmp1 ldy #$00 @L3: lda (ptr2),y ldx #MMU_CFG_RAM1 jsr STASH iny dec tmp1 bne @L3 ; Done @L4: cli rts ���������������������������������������������������������cc65-2.18/libsrc/c128/emd/c128-ram2.s���������������������������������������������������������������0000664�0000000�0000000�00000023412�13473601511�0016407�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Extended memory driver for the C128 RAM in banks #1, #2 and #3. Driver works without ; problems when statically linked. ; ; Ullrich von Bassewitz, 2002-12-04 ; ; Updated to use banks 2 and 3 as well by ; Marco van den Heuvel, 2010-01-21 ; .include "zeropage.inc" .include "em-kernel.inc" .include "em-error.inc" .include "c128.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c128_ram2_emd ; Driver signature .byte $65, $6d, $64 ; "emd" .byte EMD_API_VERSION ; EM API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr PAGECOUNT .addr MAP .addr USE .addr COMMIT .addr COPYFROM .addr COPYTO ; ------------------------------------------------------------------------ ; Constants BASE = $400 ; ------------------------------------------------------------------------ ; Data. .bss curpage: .res 2 ; Current page number curbank: .res 1 ; Current bank number copybank: .res 2 ; temp bank number window: .res 256 ; Memory "window" pagecount: .res 2 ; Number of available pages .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present and determine the amount of ; memory available. ; Must return an EM_ERR_xx code in a/x. ; INSTALL: ldx #0 stx ptr1 ldx #4 stx ptr1+1 ldx #<ptr1 stx FETVEC stx STAVEC ldy #0 ldx #MMU_CFG_RAM1 jsr FETCH sta tmp1 ldx #MMU_CFG_RAM3 jsr FETCH cmp tmp1 bne @has_4_banks tax inx txa ldx #MMU_CFG_RAM1 jsr STASH ldx #MMU_CFG_RAM3 jsr FETCH cmp tmp1 beq @has_4_banks ldx #0 lda #251 bne @setok @has_4_banks: ldx #2 lda #241 @setok: sta pagecount stx pagecount+1 ldx #$FF stx curpage stx curpage+1 ; Invalidate the current page inx txa ; A = X = EM_ERR_OK ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; PAGECOUNT: Return the total number of available pages in a/x. ; PAGECOUNT: lda pagecount ldx pagecount+1 rts ; ------------------------------------------------------------------------ ; MAP: Map the page in a/x into memory and return a pointer to the page in ; a/x. The contents of the currently mapped page (if any) may be discarded ; by the driver. ; MAP: sei sta curpage stx curpage+1 ; Remember the new page jsr calculate_bank_and_correct_page stx curbank clc adc #>BASE sta ptr1+1 ldy #$00 sty ptr1 lda #<ptr1 sta FETVEC ; Transfer one page @L1: ldx curbank jsr getcurbankmmu jsr FETCH sta window,y iny bne @L1 ; Return the memory window lda #<window ldx #>window ; Return the window address cli rts ; ------------------------------------------------------------------------ ; USE: Tell the driver that the window is now associated with a given page. USE: sta curpage stx curpage+1 ; Remember the page lda #<window ldx #>window ; Return the window rts ; ------------------------------------------------------------------------ ; COMMIT: Commit changes in the memory window to extended storage. COMMIT: sei lda curpage ; Get the current page ldx curpage+1 bmi done ; Jump if no page mapped jsr calculate_bank_and_correct_page stx curbank clc adc #>BASE sta ptr1+1 ldy #$00 sty ptr1 lda #<ptr1 sta STAVEC ; Transfer one page. Y must be zero on entry @L1: lda window,y ldx curbank jsr getcurbankmmu jsr STASH iny bne @L1 cli ; Done done: rts ; ------------------------------------------------------------------------ ; COPYFROM: Copy from extended into linear memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYFROM: sei jsr setup ; Setup is: ; ; - ptr1 contains the struct pointer ; - ptr2 contains the linear memory buffer ; - ptr3 contains -(count-1) ; - ptr4 contains the page buffer and offset ; - tmp1 contains the bank ; - tmp2 contains zero (used for linear memory buffer offset) lda #<ptr4 sta FETVEC jmp @L3 @L1: ldx tmp1 jsr getcurbankmmu ldy #0 jsr FETCH ldy tmp2 sta (ptr2),y inc tmp2 bne @L2 inc ptr2+1 @L2: inc ptr4 beq @L4 ; Bump count and repeat @L3: inc ptr3 bne @L1 inc ptr3+1 bne @L1 cli rts ; Bump page register @L4: inc ptr4+1 lda ptr4+1 cmp #$ff bne @L3 lda #4 sta ptr4+1 inc tmp1 @L5: jmp @L3 ; ------------------------------------------------------------------------ ; COPYTO: Copy from linear into extended memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYTO: sei jsr setup ; Setup is: ; ; - ptr1 contains the struct pointer ; - ptr2 contains the linear memory buffer ; - ptr3 contains -(count-1) ; - ptr4 contains the page buffer and offset ; - tmp1 contains the bank ; - tmp2 contains zero (used for linear memory buffer offset) lda #<ptr4 sta STAVEC jmp @L3 @L1: ldy tmp2 lda (ptr2),y ldx tmp1 jsr getcurbankmmu ldy #0 jsr STASH inc tmp2 bne @L2 inc ptr2+1 @L2: inc ptr4 beq @L4 ; Bump count and repeat @L3: inc ptr3 bne @L1 inc ptr3+1 bne @L1 cli rts ; Bump page register @L4: inc ptr4+1 lda ptr4+1 cmp #$ff bne @L3 inc tmp1 lda #4 sta ptr4+1 @L5: jmp @L3 ; ------------------------------------------------------------------------ ; Helper function to calculate the correct bank and page ; when addressing bank 2 or 3 calculate_bank_and_correct_page: cpx #2 beq @calculate_bank_3_with_2 cpx #1 beq @calculate_bank_2_or_3_with_1 sec sbc #251 bcs @calculate_bank_2_with_0 ldx #1 lda curpage rts @calculate_bank_3_with_2: lda curpage clc adc #10 @calculate_bank_3_with_1: ldx #3 rts @calculate_bank_2_or_3_with_1: sec sbc #246 bcs @calculate_bank_3_with_1 lda curpage clc adc #5 @calculate_bank_2_with_0: ldx #2 rts ; ------------------------------------------------------------------------ ; Helper function to get the correct mmu value in x getcurbankmmu: cpx #1 beq @bank1 cpx #2 beq @bank2 ldx #MMU_CFG_RAM3 rts @bank2: ldx #MMU_CFG_RAM2 rts @bank1: ldx #MMU_CFG_RAM1 rts ; ------------------------------------------------------------------------ ; Helper function for COPYFROM and COPYTO: Store the pointer to the request ; structure and prepare data for the copy setup: sta ptr1 stx ptr1+1 ; Save passed pointer ; Get the page number from the struct and adjust it so that it may be used ; with the hardware. That is: page pointer in ptr4 and bank in tmp1 ldy #EM_COPY::PAGE+1 lda (ptr1),y tax dey lda (ptr1),y sta curpage jsr calculate_bank_and_correct_page clc adc #4 sta ptr4+1 stx tmp1 ; Get the buffer pointer into ptr2 ldy #EM_COPY::BUF lda (ptr1),y sta ptr2 iny lda (ptr1),y sta ptr2+1 ; Get the count, calculate -(count-1) and store it into ptr3 ldy #EM_COPY::COUNT lda (ptr1),y eor #$FF sta ptr3 iny lda (ptr1),y eor #$FF sta ptr3+1 ; Get the page offset into the low byte of ptr4 clear tmp2 ldy #EM_COPY::OFFS lda (ptr1),y sta ptr4 lda #0 sta tmp2 ; Done rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/emd/c128-ramcart.s������������������������������������������������������������0000664�0000000�0000000�00000016052�13473601511�0017201�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Extended memory driver for the RamCart 64/128KB cartridge. Driver works ; without problems when statically linked. ; Code is based on GEORAM code by Ullrich von Bassewitz. ; Maciej 'YTM/Elysium' Witkowiak <ytm@elysium.pl> ; 06,22.12.2002 ; .include "zeropage.inc" .include "em-kernel.inc" .include "em-error.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c128_ramcart_emd ; Driver signature .byte $65, $6d, $64 ; "emd" .byte EMD_API_VERSION ; EM API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr PAGECOUNT .addr MAP .addr USE .addr COMMIT .addr COPYFROM .addr COPYTO ; ------------------------------------------------------------------------ ; Constants RAMC_WINDOW = $DF00 ; Address of RamCart window RAMC_PAGE_LO = $DE00 ; Page register low RAMC_PAGE_HI = $DE01 ; Page register high (only for RC128) ; ------------------------------------------------------------------------ ; Data. .bss pagecount: .res 2 ; Number of pages available .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present and determine the amount of ; memory available. ; Must return an EM_ERR_xx code in a/x. ; INSTALL: ldx RAMC_WINDOW cpx RAMC_WINDOW bne @notpresent lda #0 sta RAMC_PAGE_LO sta RAMC_PAGE_HI ldx RAMC_WINDOW cpx RAMC_WINDOW bne @notpresent lda #2 sta RAMC_WINDOW cmp RAMC_WINDOW beq @cont cpx RAMC_WINDOW beq @readonly @cont: ldy #1 sty RAMC_PAGE_HI sty RAMC_WINDOW dey sty RAMC_PAGE_HI iny cpy RAMC_WINDOW beq @rc64 ; we're on rc128 ldx #>512 bne @setsize @rc64: ldx #>256 @setsize: lda #0 sta pagecount stx pagecount+1 lda #<EM_ERR_OK ldx #>EM_ERR_OK rts @notpresent: @readonly: lda #<EM_ERR_NO_DEVICE ldx #>EM_ERR_NO_DEVICE ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; PAGECOUNT: Return the total number of available pages in a/x. ; PAGECOUNT: lda pagecount ldx pagecount+1 rts ; ------------------------------------------------------------------------ ; USE: Tell the driver that the window is now associated with a given page. ; The RamCart cartridge does not copy but actually map the window, so USE is ; identical to MAP. USE = MAP ; ------------------------------------------------------------------------ ; MAP: Map the page in a/x into memory and return a pointer to the page in ; a/x. The contents of the currently mapped page (if any) may be discarded ; by the driver. ; MAP: sta RAMC_PAGE_LO stx RAMC_PAGE_HI lda #<RAMC_WINDOW ldx #>RAMC_WINDOW ; Use the RTS from COMMIT below to save a precious byte of storage ; ------------------------------------------------------------------------ ; COMMIT: Commit changes in the memory window to extended storage. COMMIT: rts ; ------------------------------------------------------------------------ ; COPYFROM: Copy from extended into linear memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYFROM: jsr setup ; Setup is: ; ; - ptr1 contains the struct pointer ; - ptr2 contains the linear memory buffer ; - ptr3 contains -(count-1) ; - tmp1 contains the low page register value ; - tmp2 contains the high page register value ; - X contains the page offset ; - Y contains zero jmp @L5 @L1: lda RAMC_WINDOW,x sta (ptr2),y iny bne @L2 inc ptr2+1 @L2: inx beq @L4 ; Bump count and repeat @L3: inc ptr3 bne @L1 inc ptr3+1 bne @L1 rts ; Bump page register @L4: inc tmp1 bne @L5 inc tmp2 @L5: lda tmp1 sta RAMC_PAGE_LO lda tmp2 sta RAMC_PAGE_HI jmp @L3 ; ------------------------------------------------------------------------ ; COPYTO: Copy from linear into extended memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYTO: jsr setup ; Setup is: ; ; - ptr1 contains the struct pointer ; - ptr2 contains the linear memory buffer ; - ptr3 contains -(count-1) ; - tmp1 contains the low page register value ; - tmp2 contains the high page register value ; - X contains the page offset ; - Y contains zero jmp @L5 @L1: lda (ptr2),y sta RAMC_WINDOW,x iny bne @L2 inc ptr2+1 @L2: inx beq @L4 ; Bump count and repeat @L3: inc ptr3 bne @L1 inc ptr3+1 bne @L1 rts ; Bump page register @L4: inc tmp1 bne @L5 inc tmp2 @L5: lda tmp1 sta RAMC_PAGE_LO lda tmp2 sta RAMC_PAGE_HI jmp @L3 ; ------------------------------------------------------------------------ ; Helper function for COPYFROM and COPYTO: Store the pointer to the request ; structure and prepare data for the copy setup: sta ptr1 stx ptr1+1 ; Save passed pointer ; Get the page number from the struct and adjust it so that it may be used ; with the hardware. That is: lower 6 bits in tmp1, high bits in tmp2. ldy #EM_COPY::PAGE+1 lda (ptr1),y sta tmp2 dey lda (ptr1),y sta tmp1 ; Get the buffer pointer into ptr2 ldy #EM_COPY::BUF lda (ptr1),y sta ptr2 iny lda (ptr1),y sta ptr2+1 ; Get the count, calculate -(count-1) and store it into ptr3 ldy #EM_COPY::COUNT lda (ptr1),y eor #$FF sta ptr3 iny lda (ptr1),y eor #$FF sta ptr3+1 ; Get the page offset into X and clear Y ldy #EM_COPY::OFFS lda (ptr1),y tax ldy #$00 ; Done rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/emd/c128-reu.s����������������������������������������������������������������0000664�0000000�0000000�00000017276�13473601511�0016354�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Extended memory driver for the Commodore REU. Driver works without ; problems when statically linked. ; ; Ullrich von Bassewitz, 2002-11-29 ; .include "zeropage.inc" .include "em-kernel.inc" .include "em-error.inc" .include "c128.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c128_reu_emd ; Driver signature .byte $65, $6d, $64 ; "emd" .byte EMD_API_VERSION ; EM API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr PAGECOUNT .addr MAP .addr USE .addr COMMIT .addr COPYFROM .addr COPYTO ; ------------------------------------------------------------------------ ; Constants REU_STATUS = $DF00 ; Status register REU_COMMAND = $DF01 ; Command register REU_C64ADDR = $DF02 ; C64 base address register REU_REUADDR = $DF04 ; REU base address register REU_COUNT = $DF07 ; Transfer count register REU_IRQMASK = $DF09 ; IRQ mask register REU_CONTROL = $DF0A ; Control register REU_TRIGGER = $FF00 ; REU command trigger OP_COPYFROM = $ED OP_COPYTO = $EC OP_COPYFROM_ALOAD = $B1 OP_COPYTO_ALOAD = $B0 ; ------------------------------------------------------------------------ ; Data. .bss pagecount: .res 2 ; Number of pages available curpage: .res 2 ; Current page number window: .res 256 ; Memory "window" reu_params: .word $0000 ; Host address, lo, hi .word $0000 ; Exp address, lo, hi .byte $00 ; Expansion bank no. .word $0000 ; # bytes to move, lo, hi .byte $00 ; Interrupt mask reg. .byte $00 ; Adress control reg. .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present and determine the amount of ; memory available. ; Must return an EM_ERR_xx code in a/x. ; INSTALL: ldx #$00 ; High byte of return code lda #$55 sta REU_REUADDR cmp REU_REUADDR ; Check for presence of REU bne nodevice asl a ; A = $AA sta REU_REUADDR cmp REU_REUADDR ; Check for presence of REU bne nodevice ; determine the size php sei ldy #$FF loop: sty window jsr reu_size_check_common ldx #OP_COPYTO_ALOAD stx REU_COMMAND dey cpy #$FF bne loop iny size_loop: jsr reu_size_check_common ldx #OP_COPYFROM_ALOAD stx REU_COMMAND cpy window bne size_found iny bne size_loop size_found: plp ldx #$00 cpy #$00 ; too many pages, shave off 2 bne pagecount_ok dex dex dey pagecount_ok: stx pagecount sty pagecount+1 lda #<EM_ERR_OK ldx #>EM_ERR_OK rts ; common REU setup for size check reu_size_check_common: sty REU_REUADDR+2 ldx #<window stx REU_C64ADDR ldx #>window stx REU_C64ADDR+1 ldx #$00 stx REU_REUADDR stx REU_REUADDR+1 stx REU_COUNT+1 stx REU_CONTROL inx stx REU_COUNT rts ; No REU found nodevice: lda #EM_ERR_NO_DEVICE ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; PAGECOUNT: Return the total number of available pages in a/x. ; PAGECOUNT: lda pagecount ldx pagecount+1 rts ; ------------------------------------------------------------------------ ; MAP: Map the page in a/x into memory and return a pointer to the page in ; a/x. The contents of the currently mapped page (if any) may be discarded ; by the driver. ; MAP: sta curpage stx curpage+1 ; Remember the new page ldy #OP_COPYFROM jsr common ; Copy the window lda #<window ldx #>window ; Return the window address done: rts ; ------------------------------------------------------------------------ ; USE: Tell the driver that the window is now associated with a given page. USE: sta curpage stx curpage+1 ; Remember the page lda #<window ldx #>window ; Return the window rts ; ------------------------------------------------------------------------ ; COMMIT: Commit changes in the memory window to extended storage. COMMIT: lda curpage ldx curpage+1 ; Do we have a page mapped? bmi done ; Jump if no page mapped ldy #OP_COPYTO common: sty tmp1 ldy #<window sty REU_C64ADDR ldy #>window sty REU_C64ADDR+1 ldy #0 sty REU_REUADDR+0 sta REU_REUADDR+1 stx REU_REUADDR+2 sty REU_COUNT+0 ldy #1 sty REU_COUNT+1 ; Move 256 bytes bne transfer1 ; Transfer 256 bytes into REU ; ------------------------------------------------------------------------ ; COPYFROM: Copy from extended into linear memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYFROM: ldy #OP_COPYFROM .byte $2C ; ------------------------------------------------------------------------ ; COPYTO: Copy from linear into extended memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYTO: ldy #OP_COPYTO sty tmp1 ; Remember the passed pointer sta ptr1 stx ptr1+1 ; Save the pointer ; The structure passed to the functions has the same layout as the registers ; of the Commodore REU, so register programming is easy. ldy #7-1 @L1: lda (ptr1),y sta REU_C64ADDR,y dey bpl @L1 ; Invalidate the page in the memory window sty curpage+1 ; Y = $FF ; Reload the REU command and start the transfer transfer1: ldy tmp1 ; Transfer subroutine for the REU. Expects command in Y. transfer: sty REU_COMMAND ; Issue command ldy MMU_CR ; Save the current MMU settings lda #MMU_CFG_RAM0 ; sei ; sta MMU_CR ; Enable RAM in bank #0 lda REU_TRIGGER ; Don't change $FF00 sta REU_TRIGGER ; Start the transfer... sty MMU_CR ; Restore the old configuration cli rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/emd/c128-vdc.s����������������������������������������������������������������0000664�0000000�0000000�00000023073�13473601511�0016325�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Extended memory driver for the VDC RAM available on all C128 machines ; (based on code by Ullrich von Bassewitz) ; Maciej 'YTM/Elysium' Witkowiak <ytm@elysium.pl> ; 06,20.12.2002 .include "zeropage.inc" .include "em-kernel.inc" .include "em-error.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c128_vdc_emd ; Driver signature .byte $65, $6d, $64 ; "emd" .byte EMD_API_VERSION ; EM API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr PAGECOUNT .addr MAP .addr USE .addr COMMIT .addr COPYFROM .addr COPYTO ; ------------------------------------------------------------------------ ; Constants VDC_ADDR_REG = $D600 ; VDC address VDC_DATA_REG = $D601 ; VDC data VDC_DATA_HI = 18 ; used registers VDC_DATA_LO = 19 VDC_CSET = 28 VDC_DATA = 31 ; ------------------------------------------------------------------------ ; Data. .data pagecount: .word 64 ; $0000-$3fff as 16k default curpage: .word $ffff ; currently mapped-in page (invalid) .bss window: .res 256 ; memory window .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present and determine the amount of ; memory available. ; Must return an EM_ERR_xx code in a/x. ; INSTALL: ; do test for VDC presence here??? ldx #VDC_CSET ; determine size of RAM... jsr vdcgetreg sta tmp1 ora #%00010000 jsr vdcputreg ; turn on 64k jsr settestadr1 ; save original value of test byte jsr vdcgetbyte sta tmp2 lda #$55 ; write $55 here ldy #ptr1 jsr test64k ; read it here and there lda #$aa ; write $aa here ldy #ptr2 jsr test64k ; read it here and there jsr settestadr1 lda tmp2 jsr vdcputbyte ; restore original value of test byte lda ptr1 ; do bytes match? cmp ptr1+1 bne @have64k lda ptr2 cmp ptr2+1 bne @have64k ldx #VDC_CSET lda tmp1 jsr vdcputreg ; restore 16/64k flag jmp @endok ; and leave default values for 16k @have64k: lda #<256 ldx #>256 sta pagecount stx pagecount+1 @endok: lda #<EM_ERR_OK ldx #>EM_ERR_OK rts test64k: sta tmp1 sty ptr3 lda #0 sta ptr3+1 jsr settestadr1 lda tmp1 jsr vdcputbyte ; write $55 jsr settestadr1 jsr vdcgetbyte ; read here pha jsr settestadr2 jsr vdcgetbyte ; and there ldy #1 sta (ptr3),y pla dey sta (ptr3),y rts settestadr1: ldy #$02 ; test page 2 (here) .byte $2c settestadr2: ldy #$42 ; or page 64+2 (there) lda #0 jmp vdcsetsrcaddr ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: ;on C128 restore font and clear the screen? rts ; ------------------------------------------------------------------------ ; PAGECOUNT: Return the total number of available pages in a/x. ; PAGECOUNT: lda pagecount ldx pagecount+1 rts ; ------------------------------------------------------------------------ ; MAP: Map the page in a/x into memory and return a pointer to the page in ; a/x. The contents of the currently mapped page (if any) may be discarded ; by the driver. ; MAP: sta curpage stx curpage+1 sta ptr1+1 ldy #0 sty ptr1 lda #<window sta ptr2 lda #>window sta ptr2+1 jsr transferin lda #<window ldx #>window rts ; copy a single page from (ptr1):VDCRAM to (ptr2):RAM transferin: lda ptr1 ldy ptr1+1 jsr vdcsetsrcaddr ; set source address in VDC ldy #0 ldx #VDC_DATA stx VDC_ADDR_REG @L0: bit VDC_ADDR_REG bpl @L0 lda VDC_DATA_REG ; get 2 bytes at a time to speed-up sta (ptr2),y ; (in fact up to 8 bytes could be fetched with special VDC config) iny lda VDC_DATA_REG sta (ptr2),y iny bne @L0 rts ; ------------------------------------------------------------------------ ; USE: Tell the driver that the window is now associated with a given page. USE: sta curpage stx curpage+1 ; Remember the page lda #<window ldx #>window ; Return the window done: rts ; ------------------------------------------------------------------------ ; COMMIT: Commit changes in the memory window to extended storage. COMMIT: lda curpage ; jump if no page mapped ldx curpage+1 bmi done sta ptr1+1 ldy #0 sty ptr1 lda #<window sta ptr2 lda #>window sta ptr2+1 ; fall through to transferout ; copy a single page from (ptr2):RAM to (ptr1):VDCRAM transferout: lda ptr1 ldy ptr1+1 jsr vdcsetsrcaddr ; set source address in VDC ldy #0 ldx #VDC_DATA stx VDC_ADDR_REG @L0: bit VDC_ADDR_REG bpl @L0 lda (ptr2),y ; speedup does not work for writing sta VDC_DATA_REG iny bne @L0 rts ; ------------------------------------------------------------------------ ; COPYFROM: Copy from extended into linear memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYFROM: jsr setup beq @L2 ; Skip if no full pages ; Copy full pages @L1: jsr transferin inc ptr1+1 inc ptr2+1 dec tmp1 bne @L1 ; Copy the remainder of the page @L2: ldy #EM_COPY::COUNT lda (ptr3),y ; Get bytes in last page beq @L4 sta tmp1 ; Transfer the bytes in the last page ldy #0 @L3: jsr vdcgetbyte sta (ptr2),y iny dec tmp1 lda tmp1 bne @L3 @L4: rts ; ------------------------------------------------------------------------ ; COPYTO: Copy from linear into extended memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYTO: jsr setup beq @L2 ; Skip if no full pages ; Copy full pages @L1: jsr transferout inc ptr1+1 inc ptr2+1 dec tmp1 bne @L1 ; Copy the remainder of the page @L2: ldy #EM_COPY::COUNT lda (ptr3),y ; Get bytes in last page beq @L4 sta tmp1 ; Transfer the bytes in the last page ldy #0 @L3: lda (ptr2),y jsr vdcputbyte iny dec tmp1 lda tmp1 bne @L3 @L4: rts ;------------------------------------------------------------------------- ; Helper functions to handle VDC ram ; vdcsetsrcaddr: ldx #VDC_DATA_LO stx VDC_ADDR_REG @L0: bit VDC_ADDR_REG bpl @L0 sta VDC_DATA_REG dex tya stx VDC_ADDR_REG sta VDC_DATA_REG rts vdcgetbyte: ldx #VDC_DATA vdcgetreg: stx VDC_ADDR_REG @L0: bit VDC_ADDR_REG bpl @L0 lda VDC_DATA_REG rts vdcputbyte: ldx #VDC_DATA vdcputreg: stx VDC_ADDR_REG @L0: bit VDC_ADDR_REG bpl @L0 sta VDC_DATA_REG rts ; ------------------------------------------------------------------------ ; Helper function for COPYFROM and COPYTO: Store the pointer to the request ; structure and prepare data for the copy ; setup: sta ptr3 stx ptr3+1 ; Save the passed em_copy pointer ldy #EM_COPY::OFFS lda (ptr3),y sta ptr1 ldy #EM_COPY::PAGE lda (ptr3),y sta ptr1+1 ; From ldy #EM_COPY::BUF lda (ptr3),y sta ptr2 iny lda (ptr3),y sta ptr2+1 ; To ldy #EM_COPY::COUNT+1 lda (ptr3),y ; Get number of pages sta tmp1 rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/fast.s������������������������������������������������������������������������0000664�0000000�0000000�00000000477�13473601511�0015271�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-02-13 ; ; void fast (void); ; /* Switch the CPU into 2MHz mode. Note: This will disable video when in ; ** 40 column mode. ; */ ; .export _fast .include "c128.inc" .proc _fast lda #$01 sta VIC_CLK_128 rts .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/get_tv.s����������������������������������������������������������������������0000664�0000000�0000000�00000000744�13473601511�0015621�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2002-12-03 ; ; unsigned char get_tv (void); ; /* Return the video mode the machine is using */ ; .include "get_tv.inc" .include "c128.inc" ;-------------------------------------------------------------------------- ; _get_tv .proc _get_tv ldx #TV::PAL ; Assume PAL lda PALFLAG bne pal dex ; NTSC pal: txa ldx #0 rts .endproc ����������������������������cc65-2.18/libsrc/c128/gettime.s���������������������������������������������������������������������0000664�0000000�0000000�00000003641�13473601511�0015766�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Stefan Haubenthal, 27.7.2009 ; Oliver Schmidt, 14.8.2018 ; ; int __fastcall__ clock_gettime (clockid_t clk_id, struct timespec *tp); ; .include "time.inc" .include "c128.inc" .importzp sreg, tmp1, tmp2 .import pushax, pusheax, tosmul0ax, steaxspidx, incsp1, return0 .import TM, load_tenth ;---------------------------------------------------------------------------- .code .proc _clock_gettime jsr pushax jsr pushax lda CIA1_TODHR sed tax ; Save PM flag and #%01111111 cmp #$12 ; 12 AM/PM bcc @L1 sbc #$12 @L1: inx ; Get PM flag bpl @L2 clc adc #$12 @L2: cld jsr BCD2dec sta TM + tm::tm_hour lda CIA1_TODMIN jsr BCD2dec sta TM + tm::tm_min lda CIA1_TODSEC jsr BCD2dec sta TM + tm::tm_sec lda #<TM ldx #>TM jsr _mktime ldy #timespec::tv_sec jsr steaxspidx ; Pops address pushed by 2. pushax jsr load_tenth jsr pusheax lda CIA1_TOD10 ldx #>$0000 jsr tosmul0ax ldy #timespec::tv_nsec jsr steaxspidx ; Pops address pushed by 1. pushax jsr incsp1 jmp return0 .endproc ;---------------------------------------------------------------------------- ; dec = (((BCD>>4)*10) + (BCD&0xf)) .proc BCD2dec tax and #%00001111 sta tmp1 txa and #%11110000 ; *16 lsr ; *8 sta tmp2 lsr lsr ; *2 adc tmp2 ; = *10 adc tmp1 rts .endproc �����������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/irq.s�������������������������������������������������������������������������0000664�0000000�0000000�00000003410�13473601511�0015115�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; IRQ handling (C128 version) ; .export initirq, doneirq .import callirq .include "c128.inc" ; ------------------------------------------------------------------------ .segment "ONCE" initirq: lda IRQVec ldx IRQVec+1 sta IRQInd+1 stx IRQInd+2 lda #<IRQStub ldx #>IRQStub jmp setvec ; ------------------------------------------------------------------------ .code doneirq: lda IRQInd+1 ldx IRQInd+2 setvec: sei sta IRQVec stx IRQVec+1 cli rts ; ------------------------------------------------------------------------ ; The C128 has ROM parallel to the RAM starting from $4000. The startup code ; above will change this setting so that we have RAM from $0000-$BFFF. This ; works quite well with the exception of interrupts: The interrupt handler ; is in ROM, and the ROM switches back to the ROM configuration, which means ; that parts of our program may not be accessible. To solve this, we place ; the following code into a special segment called "LOWCODE" which will be ; placed just above the startup code, so it goes into a RAM area that is ; not banked. .segment "LOWCODE" IRQStub: cld ; Just to be sure lda MMU_CR ; Get old register value pha ; And save on stack lda #MMU_CFG_CC65 ; Bank 0 with kernal ROM sta MMU_CR jsr callirq ; Call the functions pla ; Get old register value sta MMU_CR jmp IRQInd ; Jump to the saved IRQ vector ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/isfast.s����������������������������������������������������������������������0000664�0000000�0000000�00000000453�13473601511�0015617�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Marco van den Heuvel, 2018-03-19 ; ; unsigned char isfast (void); ; /* Returns 1 if the CPU is in 2MHz mode. */ ; .export _isfast .include "c128.inc" .proc _isfast lda VIC_CLK_128 and #$01 ldx #$00 rts .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/joy/��������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014741�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/joy/c128-ptvjoy.s�������������������������������������������������������������0000664�0000000�0000000�00000006507�13473601511�0017143�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; PTV-4 Player joystick driver for the C128 ; ; Ullrich von Bassewitz, 2003-09-28, using the C64 driver from ; Groepaz/Hitmen, 2002-12-23, which is ; obviously based on Ullrichs driver :) ; .include "zeropage.inc" .include "joy-kernel.inc" .include "joy-error.inc" .include "c128.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c128_ptvjoy_joy ; Driver signature .byte $6A, $6F, $79 ; "joy" .byte JOY_API_VERSION ; Driver API version number ; Library reference .addr $0000 ; Jump table. .addr INSTALL .addr UNINSTALL .addr COUNT .addr READ ; ------------------------------------------------------------------------ ; 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 ; ------------------------------------------------------------------------ ; UNINSTALL 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. ; COUNT: lda #<JOY_COUNT ldx #>JOY_COUNT rts ; ------------------------------------------------------------------------ ; READ: Read a particular joystick passed in A. ; READ: tax ; Joystick number into X bne joy2 ; Read joystick 1 joy1: lda #$7F sei sta CIA1_PRA lda CIA1_PRB cli and #$1F eor #$1F rts ; Read joystick 2 joy2: dex bne joy3 lda #$E0 ldy #$FF sei sta CIA1_DDRA lda CIA1_PRA sty CIA1_DDRA cli and #$1F eor #$1F rts ; Read joystick 3 joy3: lda #%10000000 ; cia 2 port B Data-Direction sta CIA2_DDRB ; bit 7: out bit 6-0: in dex bne joy4 lda #$80 ; cia 2 port B read/write sta CIA2_PRB ; (output one at PB7) lda CIA2_PRB ; cia 2 port B read/write and #$1f ; get bit 4-0 (PB4-PB0) eor #$1f rts ; Read joystick 4 joy4: lda #$00 ; cia 2 port B read/write sta CIA2_PRB ; (output zero at PB7) lda CIA2_PRB ; cia 2 port B read/write and #$0f ; get bit 3-0 (PB3-PB0) sta tmp1 ; joy 4 directions lda CIA2_PRB ; cia 2 port B read/write and #%00100000 ; get bit 5 (PB5) lsr ora tmp1 eor #$1f ldx #0 rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/joy/c128-stdjoy.s�������������������������������������������������������������0000664�0000000�0000000�00000004673�13473601511�0017126�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Standard joystick driver for the C128. May be used multiple times when linked ; to the statically application. ; ; Ullrich von Bassewitz, 2002-12-21 ; .include "zeropage.inc" .include "joy-kernel.inc" .include "joy-error.inc" .include "c128.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c128_stdjoy_joy ; Driver signature .byte $6A, $6F, $79 ; "joy" .byte JOY_API_VERSION ; Driver API version number ; Library reference .addr $0000 ; Jump table. .addr INSTALL .addr UNINSTALL .addr COUNT .addr READ ; ------------------------------------------------------------------------ ; Constants JOY_COUNT = 2 ; Number of joysticks we support ; ------------------------------------------------------------------------ ; Data. .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 ; ------------------------------------------------------------------------ ; UNINSTALL 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. ; COUNT: lda #<JOY_COUNT ldx #>JOY_COUNT rts ; ------------------------------------------------------------------------ ; READ: Read a particular joystick passed in A. ; READ: tax ; Joystick number into X bne joy2 ; Read joystick 1 joy1: lda #$7F sei sta CIA1_PRA lda CIA1_PRB back: cli and #$1F eor #$1F rts ; Read joystick 2 joy2: ldx #0 lda #$E0 ldy #$FF sei sta CIA1_DDRA lda CIA1_PRA sty CIA1_DDRA jmp back ���������������������������������������������������������������������cc65-2.18/libsrc/c128/joy_stat_stddrv.s�������������������������������������������������������������0000664�0000000�0000000�00000000356�13473601511�0017552�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Address of the static standard joystick driver ; ; Oliver Schmidt, 2012-11-01 ; ; const void joy_static_stddrv[]; ; .export _joy_static_stddrv .import _c128_stdjoy_joy .rodata _joy_static_stddrv := _c128_stdjoy_joy ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/joy_stddrv.s������������������������������������������������������������������0000664�0000000�0000000�00000000300�13473601511�0016504�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Name of the standard joystick driver ; ; Ullrich von Bassewitz, 2002-12-21 ; ; const char joy_stddrv[]; ; .export _joy_stddrv .rodata _joy_stddrv: .asciiz "c128-stdjoy.joy" ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/kbhit.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000650�13473601511�0015426�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 18.08.1998 ; ; unsigned char kbhit (void); ; .export _kbhit .include "c128.inc" .proc _kbhit ldx #0 ; High byte of return is always zero lda KEY_COUNT ; Get number of characters ; ora FKEY_COUNT ; Or with number of chars from function keys beq L9 lda #1 L9: rts .endproc ����������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/kbrepeat.s��������������������������������������������������������������������0000664�0000000�0000000�00000000473�13473601511�0016125�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; unsigned char __fastcall__ kbrepeat (unsigned char mode); ; .export _kbrepeat .include "c128.inc" _kbrepeat: ldx KBDREPEAT ; get old value sta KBDREPEAT ; store new value txa ; return old value ldx #0 rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/kernal.s����������������������������������������������������������������������0000664�0000000�0000000�00000002541�13473601511�0015602�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 19.11.2002 ; ; C128 kernal functions ; .include "cbm_kernal.inc" .export C64MODE .export SWAPPER .export SETBNK .export CINT .export IOINIT .export RAMTAS .export RESTOR .export VECTOR .export SETMSG .export SECOND .export TKSA .export MEMTOP .export MEMBOT .export SCNKEY .export SETTMO .export ACPTR .export CIOUT .export UNTLK .export UNLSN .export LISTEN .export TALK .export READST .export SETLFS .export SETNAM .export OPEN .export CLOSE .export CHKIN .export CKOUT .export CLRCH .export BASIN .export BSOUT .export LOAD .export SAVE .export SETTIM .export RDTIM .export STOP .export GETIN .export CLALL .export UDTIM .export SCREEN .export PLOT .export IOBASE ���������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/libref.s����������������������������������������������������������������������0000664�0000000�0000000�00000000511�13473601511�0015564�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2013-05-31, Oliver Schmidt ; 2013-06-11, Greg King ; .export em_libref .export joy_libref .export ser_libref .export tgi_libref .import _exit em_libref := _exit joy_libref := _exit ser_libref := _exit tgi_libref := _exit ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/mainargs.s��������������������������������������������������������������������0000664�0000000�0000000�00000010351�13473601511�0016125�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; mainargs.s ; ; Ullrich von Bassewitz, 2003-03-07 ; Based on code from Stefan A. Haubenthal, <polluks@web.de> ; 2003-05-18, Greg King ; 2004-04-28, 2005-02-26, Ullrich von Bassewitz ; ; Scan a group of arguments that are in BASIC's input-buffer. ; Build an array that points to the beginning of each argument. ; Send, to main(), that array and the count of the arguments. ; ; Command-lines look like these lines: ; ; run ; run : rem ; run:rem arg1 " arg 2 is quoted " arg3 "" arg5 ; ; "run" and "rem" are entokenned; the args. are not. Leading and trailing ; spaces outside of quotes are ignored. ; ; TO-DO: ; - The "file-name" might be a path-name; don't copy the directory-components. ; - Add a control-character quoting mechanism. .constructor initmainargs, 24 .import __argc, __argv .include "cbm_kernal.inc" .include "c128.inc" MAXARGS = 10 ; Maximum number of arguments allowed REM = $8f ; BASIC token-code NAME_LEN = 16 ; Maximum length of command-name ; Get possible command-line arguments. Goes into the special ONCE segment, ; which may be reused after the startup code is run .segment "ONCE" initmainargs: ; Assume that the program was loaded, a moment ago, by the traditional LOAD ; statement. Save the "most-recent filename" as argument #0. lda #0 ; The terminating NUL character ldy FNAM_LEN cpy #NAME_LEN + 1 bcc L1 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 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. inx cmp #REM bne L2 ldy #1 * 2 ; Find the next argument next: lda BASIC_BUF,x beq done ; End of line reached inx cmp #' ' ; Skip leading spaces 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 ; will check now for a quoted argument, in which case we will have to skip this ; first character. found: cmp #'"' ; Is the argument quoted? beq setterm ; Jump if so dex ; Reset pointer to first argument character lda #' ' ; A space ends the argument setterm:sta term ; Set end of argument marker ; Now store a pointer to the argument into the next slot. Since the BASIC ; input buffer is located at the start of a RAM page, no calculations are ; necessary. txa ; Get low byte sta argv,y ; argv[y]= &arg iny lda #>BASIC_BUF sta argv,y iny inc __argc ; Found another arg ; Search for the end of the argument argloop:lda BASIC_BUF,x beq done inx cmp term bne argloop ; 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 #0 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? bcc 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 .segment "INIT" term: .res 1 name: .res NAME_LEN + 1 .data ; char* argv[MAXARGS+1]={name}; argv: .addr name .res MAXARGS * 2 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/mcbdefault.s������������������������������������������������������������������0000664�0000000�0000000�00000007674�13473601511�0016450�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Default mouse callbacks for the C128 ; ; Ullrich von Bassewitz, 2004-03-20 ; ; All functions in this module should be interrupt safe, because they may ; 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. 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 "ONCE" 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 sta VIC_SPR_ENA rts ; -------------------------------------------------------------------------- ; Show the mouse pointer. Always called with interrupts disabled. show: lda #MOUSE_SPR_MASK ora VIC_SPR_ENA sta VIC_SPR_ENA ; Fall through ; -------------------------------------------------------------------------- ; Prepare to move the mouse pointer. Always called with interrupts disabled. prep: ; Fall through ; -------------------------------------------------------------------------- ; Draw the mouse pointer. Always called with interrupts disabled. draw: rts ; -------------------------------------------------------------------------- ; Move the mouse pointer X position to the value in a/x. Always called with ; interrupts disabled. movex: ; Add the X correction and set the low byte. This frees A. add #24 ; X correction sta VIC_SPR_X ; Set the high byte txa adc #0 bne @L1 ; Branch if high byte not zero lda VIC_SPR_HI_X ; Get high X bits of all sprites and #MOUSE_SPR_NMASK ; Clear high bit for sprite sta VIC_SPR_HI_X rts @L1: lda VIC_SPR_HI_X ; Get high X bits of all sprites ora #MOUSE_SPR_MASK ; Set high bit for sprite sta VIC_SPR_HI_X rts ; -------------------------------------------------------------------------- ; Move the mouse pointer Y position to the value in a/x. Always called with ; interrupts disabled. movey: clc ldx PALFLAG bne @L2 adc #50 ; FIXME: Should be NTSC, is PAL value sta VIC_SPR_Y ; Set Y position rts @L2: adc #50 ; Add PAL correction sta VIC_SPR_Y ; Set Y position rts ; -------------------------------------------------------------------------- ; Callback structure .rodata _mouse_def_callbacks: .addr hide .addr show .addr prep .addr draw .addr movex .addr movey ��������������������������������������������������������������������cc65-2.18/libsrc/c128/mou/��������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014740�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/mou/c128-1351.s���������������������������������������������������������������0000664�0000000�0000000�00000034415�13473601511�0016177�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Driver for the 1351 proportional mouse. Parts of the code are from ; the Commodore 1351 mouse users guide. ; ; 2009-09-26, Ullrich von Bassewitz ; 2014-04-26, Christian Groessler ; 2014-04-30, Greg King ; .include "zeropage.inc" .include "mouse-kernel.inc" .include "c128.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c128_1351_mou HEADER: ; Driver signature .byte $6d, $6f, $75 ; "mou" .byte MOUSE_API_VERSION ; Mouse driver API version number ; Library reference libref: .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr HIDE .addr SHOW .addr SETBOX .addr GETBOX .addr MOVE .addr BUTTONS .addr POS .addr INFO .addr IOCTL .addr IRQ ; Mouse driver flags .byte MOUSE_FLAG_LATE_IRQ ; Callback table, set by the kernel before INSTALL is called CHIDE: jmp $0000 ; Hide the cursor CSHOW: jmp $0000 ; Show the cursor CPREP: jmp $0000 ; Prepare to move the cursor CDRAW: jmp $0000 ; Draw the cursor CMOVEX: jmp $0000 ; Move the cursor to X coord CMOVEY: jmp $0000 ; Move the cursor to Y coord ;---------------------------------------------------------------------------- ; Constants SCREEN_HEIGHT = 200 SCREEN_WIDTH = 320 ;---------------------------------------------------------------------------- ; Global variables. The bounding box values are sorted so that they can be ; written with the least effort in the SETBOX and GETBOX routines, so don't ; reorder them. .bss Vars: OldPotX: .res 1 ; Old hw counter values OldPotY: .res 1 YPos: .res 2 ; Current mouse position, Y XPos: .res 2 ; Current mouse position, X XMin: .res 2 ; X1 value of bounding box YMin: .res 2 ; Y1 value of bounding box XMax: .res 2 ; X2 value of bounding box YMax: .res 2 ; Y2 value of bounding box OldValue: .res 1 ; Temp for MoveCheck routine NewValue: .res 1 ; Temp for MoveCheck routine INIT_save: .res 1 Buttons: .res 1 ; Button mask ; Keyboard buffer fill level at start of interrupt old_key_count: .res 1 ; original IRQ vector old_irq: .res 2 .rodata ; Default values for above variables ; (We use ".proc" because we want to define both a label and a scope.) .proc DefVars .byte 0, 0 ; OldPotX/OldPotY .word SCREEN_HEIGHT/2 ; YPos .word SCREEN_WIDTH/2 ; XPos .word 0 ; XMin .word 0 ; YMin .word SCREEN_WIDTH - 1 ; XMax .word SCREEN_HEIGHT - 1 ; YMax .endproc .code ;---------------------------------------------------------------------------- ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present. ; Must return an MOUSE_ERR_xx code in a/x. INSTALL: ; Disable the BASIC interpreter's interrupt-driven sprite-motion code. ; That allows direct access to the VIC-IIe's sprite registers. lda INIT_STATUS sta INIT_save lda #%11000000 sta INIT_STATUS ; Initialize variables. Just copy the default stuff over ldx #.sizeof(DefVars)-1 @L1: lda DefVars,x sta Vars,x dex bpl @L1 ; Be sure the mouse cursor is invisible and at the default location. We ; need to do that here, because our mouse interrupt handler doesn't set the ; mouse position if it hasn't changed. sei jsr CHIDE lda XPos ldx XPos+1 jsr CMOVEX lda YPos ldx YPos+1 jsr CMOVEY ; Initialize our IRQ magic ; remember ROM IRQ continuation address lda IRQInd+2 sta old_irq+1 lda IRQInd+1 sta old_irq lda libref sta ptr3 lda libref+1 sta ptr3+1 ; set ROM IRQ continuation address to point to the provided routine ldy #2 lda (ptr3),y sta IRQInd+1 iny lda (ptr3),y sta IRQInd+2 ; set address of our IRQ callback routine ; since it's called via "rts" we have to use "address-1" iny lda #<(callback-1) sta (ptr3),y iny lda #>(callback-1) sta (ptr3),y iny ; set ROM entry point vector ; since it's called via "rts" we have to decrement it by one lda old_irq sec sbc #1 sta (ptr3),y iny lda old_irq+1 sbc #0 sta (ptr3),y cli ; Done, return zero (= MOUSE_ERR_OK) ldx #$00 txa rts ;---------------------------------------------------------------------------- ; UNINSTALL routine. Is called before the driver is removed from memory. ; No return code required (the driver is removed from memory on return). UNINSTALL: lda old_irq sei sta IRQInd+1 lda old_irq+1 sta IRQInd+2 ;cli ; This will be done at end of HIDE jsr HIDE ; Hide cursor on exit lda INIT_save sta INIT_STATUS rts ;---------------------------------------------------------------------------- ; HIDE routine. Is called to hide the mouse pointer. The mouse kernel manages ; a counter for calls to show/hide, and the driver entry point is only called ; if the mouse is currently visible and should get hidden. For most drivers, ; no special action is required besides hiding the mouse cursor. ; No return code required. HIDE: sei jsr CHIDE cli rts ;---------------------------------------------------------------------------- ; SHOW routine. Is called to show the mouse pointer. The mouse kernel manages ; a counter for calls to show/hide, and the driver entry point is only called ; if the mouse is currently hidden and should become visible. For most drivers, ; no special action is required besides enabling the mouse cursor. ; No return code required. SHOW: sei jsr CSHOW cli rts ;---------------------------------------------------------------------------- ; SETBOX: Set the mouse bounding box. The parameters are passed as they come ; from the C program, that is, a pointer to a mouse_box struct in a/x. ; No checks are done if the mouse is currently inside the box, this is the job ; of the caller. It is not necessary to validate the parameters, trust the ; caller and save some code here. No return code required. SETBOX: sta ptr1 stx ptr1+1 ; Save data pointer ldy #.sizeof (MOUSE_BOX)-1 sei @L1: lda (ptr1),y sta XMin,y dey bpl @L1 cli rts ;---------------------------------------------------------------------------- ; GETBOX: Return the mouse bounding box. The parameters are passed as they ; come from the C program, that is, a pointer to a mouse_box struct in a/x. GETBOX: sta ptr1 stx ptr1+1 ; Save data pointer ldy #.sizeof (MOUSE_BOX)-1 sei @L1: lda XMin,y sta (ptr1),y dey bpl @L1 cli rts ;---------------------------------------------------------------------------- ; MOVE: Move the mouse to a new position. The position is passed as it comes ; from the C program, that is: X on the stack and Y in a/x. The C wrapper will ; remove the parameter from the stack on return. ; No checks are done if the new position is valid (within the bounding box or ; the screen). No return code required. ; MOVE: sei ; No interrupts sta YPos stx YPos+1 ; New Y position jsr CMOVEY ; Set it ldy #$01 lda (sp),y sta XPos+1 tax dey lda (sp),y sta XPos ; New X position jsr CMOVEX ; Move the cursor cli ; Allow interrupts rts ;---------------------------------------------------------------------------- ; BUTTONS: Return the button mask in a/x. BUTTONS: lda Buttons ldx #$00 rts ;---------------------------------------------------------------------------- ; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1. ; No return code required. POS: ldy #MOUSE_POS::XCOORD ; Structure offset sei ; Disable interrupts lda XPos ; Transfer the position sta (ptr1),y lda XPos+1 iny sta (ptr1),y lda YPos iny sta (ptr1),y lda YPos+1 cli ; Enable interrupts iny sta (ptr1),y ; Store last byte rts ; Done ;---------------------------------------------------------------------------- ; INFO: Returns mouse position and current button mask in the MOUSE_INFO ; struct pointed to by ptr1. No return code required. ; ; We're cheating here to keep the code smaller: The first fields of the ; mouse_info struct are identical to the mouse_pos struct, so we will just ; call _mouse_pos to initialize the struct pointer and fill the position ; fields. INFO: jsr POS ; Fill in the button state lda Buttons ldy #MOUSE_INFO::BUTTONS sta (ptr1),y rts ;---------------------------------------------------------------------------- ; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl ; specific data in ptr1, and the ioctl code in A. ; Must return an error code in a/x. ; IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioctls, for now ldx #>MOUSE_ERR_INV_IOCTL rts ;---------------------------------------------------------------------------- ; IRQ: Irq handler entry point. Called as a subroutine but in IRQ context ; (so be careful). The routine MUST return carry set if the interrupt has been ; 'handled' - which means that the interrupt source is gone. Otherwise it ; MUST return carry clear. ; IRQ: jsr CPREP lda KEY_COUNT sta old_key_count lda #$7F sta CIA1_PRA lda CIA1_PRB ; Read joystick #0 and #$1F eor #$1F ; Make all bits active high sta Buttons lda SID_ADConv1 ; Get mouse X movement ldy OldPotX jsr MoveCheck ; Calculate movement vector sty OldPotX ; Skip processing if nothing has changed bcc @SkipX ; Calculate the new X coordinate (--> a/y) add XPos tay ; Remember low byte txa adc XPos+1 tax ; Limit the X coordinate to the bounding box cpy XMin sbc XMin+1 bpl @L1 ldy XMin ldx XMin+1 jmp @L2 @L1: txa cpy XMax sbc XMax+1 bmi @L2 ldy XMax ldx XMax+1 @L2: sty XPos stx XPos+1 ; Move the mouse pointer to the new X pos tya jsr CMOVEX ; Calculate the Y movement vector @SkipX: lda SID_ADConv2 ; Get mouse Y movement ldy OldPotY jsr MoveCheck ; Calculate movement sty OldPotY ; Skip processing if nothing has changed bcc @SkipY ; Calculate the new Y coordinate (--> a/y) sta OldValue lda YPos sub OldValue tay stx OldValue lda YPos+1 sbc OldValue tax ; Limit the Y coordinate to the bounding box cpy YMin sbc YMin+1 bpl @L3 ldy YMin ldx YMin+1 jmp @L4 @L3: txa cpy YMax sbc YMax+1 bmi @L4 ldy YMax ldx YMax+1 @L4: sty YPos stx YPos+1 ; Move the mouse pointer to the new X pos tya jsr CMOVEY ; Done @SkipY: jsr CDRAW clc ; Interrupt not "handled" rts ; -------------------------------------------------------------------------- ; ; Move check routine, called for both coordinates. ; ; Entry: y = old value of pot register ; a = current value of pot register ; Exit: y = value to use for old value ; x/a = delta value for position ; MoveCheck: sty OldValue sta NewValue ldx #$00 sub OldValue ; a = mod64 (new - old) and #%01111111 cmp #%01000000 ; if (a > 0) bcs @L1 ; lsr a ; a /= 2; beq @L2 ; if (a != 0) ldy NewValue ; y = NewValue sec rts ; return @L1: ora #%11000000 ; else or in high order bits cmp #$FF ; if (a != -1) beq @L2 sec ror a ; a /= 2 dex ; high byte = -1 (X = $FF) ldy NewValue sec rts @L2: txa ; A = $00 clc rts .define OLD_BUTTONS Buttons ; tells callback.inc where the old port status is stored .include "callback.inc" ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/mou/c128-inkwell.s������������������������������������������������������������0000664�0000000�0000000�00000035077�13473601511�0017260�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Driver for the Inkwell Systems 170-C and 184-C lightpens. ; ; 2014-04-26, Christian Groessler ; 2014-09-10, Greg King ; .include "zeropage.inc" .include "mouse-kernel.inc" .include "c128.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table. module_header _c128_inkwell_mou HEADER: ; Driver signature .byte $6d, $6f, $75 ; ASCII "mou" .byte MOUSE_API_VERSION ; Mouse driver API version number ; Library reference libref: .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr HIDE .addr SHOW .addr SETBOX .addr GETBOX .addr MOVE .addr BUTTONS .addr POS .addr INFO .addr IOCTL .addr IRQ ; Mouse driver flags .byte MOUSE_FLAG_EARLY_IRQ ; Callback table, set by the kernel before INSTALL is called. CHIDE: jmp $0000 ; Hide the cursor CSHOW: jmp $0000 ; Show the cursor CPREP: jmp $0000 ; Prepare to move the cursor CDRAW: jmp $0000 ; Draw the cursor CMOVEX: jmp $0000 ; Move the cursor to X co-ord. CMOVEY: jmp $0000 ; Move the cursor to Y co-ord. ;---------------------------------------------------------------------------- ; Constants ; This driver is for the 40-column screen. XSIZE = 40 YSIZE = 25 SCREEN_WIDTH = XSIZE * 8 SCREEN_HEIGHT = YSIZE * 8 ;---------------------------------------------------------------------------- ; Global variables. The bounding box values are sorted so that they can be ; written with the least effort in the SETBOX and GETBOX routines; so, don't ; re-order them. .rodata ; Default values for below variables ; (We use ".proc" because we want to define both a label and a scope.) .proc DefVars .word 0 ; XMin .word 0 ; YMin .word SCREEN_WIDTH - 1 ; XMax .word SCREEN_HEIGHT - 1 ; YMax .byte %00000000 ; Buttons .endproc .bss Vars: XMin: .res 2 ; X1 value of bounding box YMin: .res 2 ; Y1 value of bounding box XMax: .res 2 ; X2 value of bounding box YMax: .res 2 ; Y2 value of bounding box Buttons: .res 1 ; Button status bits XPos: .res 2 ; Current lightpen position, X YPos: .res 2 ; Current lightpen position, Y OldPenX: .res 1 ; Previous HW-counter values OldPenY: .res 1 INIT_save: .res 1 ; Keyboard buffer fill level at start of interrupt old_key_count: .res 1 ; Original IRQ vector old_irq: .res 2 .data ; Default Inkwell calibration. ; The first number is the width of the left border; ; the second number is the actual calibration value. ; See a comment below (at "Calculate the new X co-ordinate") ; for the reason for the third number. XOffset: .byte (24 + 24) / 2 ; x-offset ; Jump to a function that puts a new calibration value into XOffset. Calibrate: jmp $0000 .code ;---------------------------------------------------------------------------- ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present. ; Must return a MOUSE_ERR_xx code in .XA. INSTALL: ; Disable the BASIC interpreter's interrupt-driven sprite-motion code. ; That allows direct access to the VIC-IIe's sprite registers. lda INIT_STATUS sta INIT_save lda #%11000000 sta INIT_STATUS ; Initiate some variables. Just copy the default stuff over. ldx #.sizeof (DefVars) - 1 @L0: lda DefVars,x sta Vars,x dex bpl @L0 ldx VIC_LPEN_X ldy VIC_LPEN_Y stx OldPenX sty OldPenY ; Initiate our IRQ magic. ; Remember the ROM IRQ continuation address. ldx IRQInd+2 lda IRQInd+1 stx old_irq+1 sta old_irq lda libref ldx libref+1 sta ptr3 ; Point to mouse_adjuster stx ptr3+1 ; Set the ROM IRQ continuation address to point to the provided routine. ldy #2 lda (ptr3),y iny sei sta IRQInd+1 lda (ptr3),y sta IRQInd+2 ; Set the address of our IRQ callback routine. ; Because it's called via "rts", we must use "address-1". iny lda #<(callback-1) sta (ptr3),y iny lda #>(callback-1) sta (ptr3),y ; Set the ROM entry-point vector. ; Because it's called via "rts", we must decrement it by one. iny lda old_irq sub #<$0001 sta (ptr3),y iny lda old_irq+1 sbc #>$0001 sta (ptr3),y cli ; Call a calibration function through the library-reference. ldy #1 lda (ptr3),y bze @L1 ; Don't call pointer if it's NULL sta Calibrate+2 ; Point to function dey lda (ptr3),y sta Calibrate+1 lda #<XOffset ; Function will set this variable ldx #>XOffset jsr Calibrate ; Be sure that the lightpen cursor is invisible and at the default location. ; It needs to be done here because the lightpen interrupt handler doesn't ; set the lightpen position if it hasn't changed. @L1: sei jsr CHIDE lda #<(SCREEN_HEIGHT / 2) ldx #>(SCREEN_HEIGHT / 2) jsr MoveY lda #<(SCREEN_WIDTH / 2) ldx #>(SCREEN_WIDTH / 2) jsr MoveX cli ; Done, return zero. lda #MOUSE_ERR_OK tax rts ;---------------------------------------------------------------------------- ; UNINSTALL routine. Is called before the driver is removed from memory. ; No return code required (the driver is removed from memory on return). UNINSTALL: lda old_irq ldx old_irq+1 sei sta IRQInd+1 stx IRQInd+2 ;cli ; This will be done at end of HIDE jsr HIDE ; Hide cursor on exit lda INIT_save sta INIT_STATUS rts ;---------------------------------------------------------------------------- ; HIDE routine. Is called to hide the lightpen pointer. The mouse kernel manages ; a counter for calls to show/hide, and the driver entry point is called only ; if the mouse is currently visible, and should get hidden. For most drivers, ; no special action is required besides hiding the lightpen cursor. ; No return code required. HIDE: sei jsr CHIDE cli rts ;---------------------------------------------------------------------------- ; SHOW routine. Is called to show the lightpen pointer. The mouse kernel manages ; a counter for calls to show/hide, and the driver entry point is called only ; if the mouse is currently hidden, and should become visible. For most drivers, ; no special action is required besides enabling the lightpen cursor. ; No return code required. SHOW: sei jsr CSHOW cli rts ;---------------------------------------------------------------------------- ; SETBOX: Set the lightpen bounding box. The parameters are passed as they come ; from the C program, that is, a pointer to a mouse_box struct in .XA. ; No checks are done if the lightpen is currently inside the box, that is the job ; of the caller. It is not necessary to validate the parameters; trust the ; caller; and, save some code here. No return code required. SETBOX: sta ptr1 stx ptr1+1 ; Save data pointer ldy #.sizeof (MOUSE_BOX) - 1 sei @L1: lda (ptr1),y sta XMin,y dey bpl @L1 cli rts ;---------------------------------------------------------------------------- ; GETBOX: Return the lightpen bounding box. The parameters are passed as they ; come from the C program, that is, a pointer to a mouse_box struct in .XA. GETBOX: sta ptr1 stx ptr1+1 ; Save data pointer ldy #.sizeof (MOUSE_BOX) - 1 @L1: lda XMin,y sta (ptr1),y dey bpl @L1 rts ;---------------------------------------------------------------------------- ; MOVE: Move the mouse to a new position. The position is passed as it comes ; from the C program, that is: X on the stack and Y in .XA. The C wrapper will ; remove the parameter from the stack on return. ; No checks are done if the new position is valid (within the bounding box or ; the screen). No return code required. ; MOVE: sei ; No interrupts jsr MoveY ldy #$01 lda (sp),y tax dey lda (sp),y jsr MoveX ; Move the cursor cli ; Allow interrupts rts ;---------------------------------------------------------------------------- ; BUTTONS: Return the button mask in .XA. BUTTONS: lda Buttons ldx #>$0000 ; Make the lightpen buttons look like a 1351 mouse. asl a asl SID_ADConv2 ; PotY rol a eor #MOUSE_BTN_RIGHT and #MOUSE_BTN_LEFT | MOUSE_BTN_RIGHT rts ;---------------------------------------------------------------------------- ; POS: Return the lightpen position in the MOUSE_POS struct pointed to by ptr1. ; No return code required. POS: ldy #MOUSE_POS::XCOORD ; Structure offset sei ; Disable interrupts lda XPos ; Transfer the position sta (ptr1),y lda XPos+1 iny sta (ptr1),y lda YPos iny sta (ptr1),y lda YPos+1 cli ; Enable interrupts iny sta (ptr1),y ; Store last byte rts ;---------------------------------------------------------------------------- ; INFO: Returns lightpen position and current button mask in the MOUSE_INFO ; struct pointed to by ptr1. No return code required. ; ; We're cheating here, to keep the code smaller: The first fields of the ; mouse_info struct are identical to the mouse_pos struct; so, we'll just ; call _mouse_pos to initiate the struct pointer, and fill the position ; fields. INFO: jsr POS ; Fill in the button state jsr BUTTONS ; Will not touch ptr1 ldy #MOUSE_INFO::BUTTONS sta (ptr1),y rts ;---------------------------------------------------------------------------- ; IOCTL: Driver-defined entry point. The wrapper will pass a pointer to ioctl- ; specific data in ptr1, and the ioctl code in .A. ; Must return an error code in .XA. ; IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioctls, for now ldx #>MOUSE_ERR_INV_IOCTL rts ;---------------------------------------------------------------------------- ; IRQ: IRQ handler entry point. Called as a subroutine, but in the IRQ context ; (so, be careful). The routine MUST return carry set if the interrupt has been ; 'handled' -- which means that the interrupt source is gone. Otherwise, it ; MUST return carry clear. ; IRQ: jsr CPREP lda KEY_COUNT sta old_key_count ; Record the state of the buttons. ; Try to avoid crosstalk between the keyboard and the lightpen. ldy #%00000000 ; Set ports A and B to input sty CIA1_DDRB sty CIA1_DDRA ; Keyboard won't look like buttons ;lda #%01111111 ; (Keyboard scan leaves this in port A) ;sta CIA1_PRA lda CIA1_PRB ; Read Control Port 1 dec CIA1_DDRA ; Set port A back to output eor #%11111111 ; Bit goes up when button goes down sta Buttons ; Read the VIC-II lightpen registers. lda VIC_LPEN_Y cmp OldPenY ; Skip processing if nothing has changed. beq @SkipY sta OldPenY ; Subtract the height of the top border, so that the lightpen co-ordinate ; will match the TGI co-ordinate. sub #50 tay ; Remember low byte ldx #>$0000 ; Limit the Y co-ordinate to the bounding box. txa cpy YMin sbc YMin+1 bpl @L3 ldy YMin ldx YMin+1 jmp @L4 @L3: txa cpy YMax sbc YMax+1 bmi @L4 ldy YMax ldx YMax+1 @L4: tya jsr MoveY @SkipY: lda VIC_LPEN_X cmp OldPenX ; Skip processing if nothing has changed. beq @SkipX sta OldPenX ; Adjust the value by the calibration offset. sub XOffset ; Calculate the new X co-ordinate. ; The VIC-II register is eight bits; but, the screen co-ordinate is nine bits. ; Therefore, the VIC-II number is doubled. Then, it points to every other pixel; ; but, it can reach across the screen. asl a tay ; Remember low byte lda #>$0000 rol a tax ; Remember high byte ; Limit the X co-ordinate to the bounding box. cpy XMin sbc XMin+1 bpl @L1 ldy XMin ldx XMin+1 jmp @L2 @L1: txa cpy XMax sbc XMax+1 bmi @L2 ldy XMax ldx XMax+1 @L2: tya jsr MoveX ; Done @SkipX: jsr CDRAW clc ; Interrupt not "handled" rts ; Move the lightpen pointer to the new Y pos. MoveY: sta YPos stx YPos+1 jmp CMOVEY ; Move the lightpen pointer to the new X pos. MoveX: sta XPos stx XPos+1 jmp CMOVEX .define OLD_BUTTONS Buttons ; Tells callback.inc where the old port status is stored .include "callback.inc" �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/mou/c128-joy.s����������������������������������������������������������������0000664�0000000�0000000�00000032425�13473601511�0016406�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Driver for a "joystick mouse". ; ; 2009-09-26, Ullrich von Bassewitz ; 2014-04-26, Christian Groessler ; 2014-05-01, Greg King ; .include "zeropage.inc" .include "mouse-kernel.inc" .include "c128.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c128_joy_mou HEADER: ; Driver signature .byte $6d, $6f, $75 ; "mou" .byte MOUSE_API_VERSION ; Mouse driver API version number ; Library reference libref: .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr HIDE .addr SHOW .addr SETBOX .addr GETBOX .addr MOVE .addr BUTTONS .addr POS .addr INFO .addr IOCTL .addr IRQ ; Mouse driver flags .byte MOUSE_FLAG_LATE_IRQ ; Callback table, set by the kernel before INSTALL is called CHIDE: jmp $0000 ; Hide the cursor CSHOW: jmp $0000 ; Show the cursor CPREP: jmp $0000 ; Prepare to move the cursor CDRAW: jmp $0000 ; Draw the cursor CMOVEX: jmp $0000 ; Move the cursor to X coord CMOVEY: jmp $0000 ; Move the cursor to Y coord ;---------------------------------------------------------------------------- ; Constants SCREEN_HEIGHT = 200 SCREEN_WIDTH = 320 .enum JOY UP = $01 DOWN = $02 LEFT = $04 RIGHT = $08 FIRE = $10 .endenum ;---------------------------------------------------------------------------- ; Global variables. The bounding box values are sorted so that they can be ; written with the least effort in the SETBOX and GETBOX routines, so don't ; reorder them. .bss Vars: YPos: .res 2 ; Current mouse position, Y XPos: .res 2 ; Current mouse position, X XMin: .res 2 ; X1 value of bounding box YMin: .res 2 ; Y1 value of bounding box XMax: .res 2 ; X2 value of bounding box YMax: .res 2 ; Y2 value of bounding box Buttons: .res 1 ; Button mask INIT_save: .res 1 ; Keyboard buffer fill level at start of interrupt old_key_count: .res 1 ; original IRQ vector old_irq: .res 2 .rodata ; Default values for above variables ; (We use ".proc" because we want to define both a label and a scope.) .proc DefVars .word SCREEN_HEIGHT/2 ; YPos .word SCREEN_WIDTH/2 ; XPos .word 0 ; XMin .word 0 ; YMin .word SCREEN_WIDTH - 1 ; XMax .word SCREEN_HEIGHT - 1 ; YMax .byte 0 ; Buttons .endproc .code ;---------------------------------------------------------------------------- ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present. ; Must return an MOUSE_ERR_xx code in a/x. INSTALL: ; Disable the BASIC interpreter's interrupt-driven sprite-motion code. ; That allows direct access to the VIC-IIe's sprite registers. lda INIT_STATUS sta INIT_save lda #%11000000 sta INIT_STATUS ; Initialize variables. Just copy the default stuff over ldx #.sizeof(DefVars)-1 @L1: lda DefVars,x sta Vars,x dex bpl @L1 ; Be sure the mouse cursor is invisible and at the default location. We ; need to do that here, because our mouse interrupt handler doesn't set the ; mouse position if it hasn't changed. sei jsr CHIDE lda XPos ldx XPos+1 jsr CMOVEX lda YPos ldx YPos+1 jsr CMOVEY ; Initialize our IRQ magic ; remember ROM IRQ continuation address lda IRQInd+2 sta old_irq+1 lda IRQInd+1 sta old_irq lda libref sta ptr3 lda libref+1 sta ptr3+1 ; set ROM IRQ continuation address to point to the provided routine ldy #2 lda (ptr3),y sta IRQInd+1 iny lda (ptr3),y sta IRQInd+2 ; set address of our IRQ callback routine ; since it's called via "rts" we have to use "address-1" iny lda #<(callback-1) sta (ptr3),y iny lda #>(callback-1) sta (ptr3),y iny ; set ROM entry point vector ; since it's called via "rts" we have to decrement it by one lda old_irq sec sbc #1 sta (ptr3),y iny lda old_irq+1 sbc #0 sta (ptr3),y cli ; Done, return zero (= MOUSE_ERR_OK) ldx #$00 txa rts ;---------------------------------------------------------------------------- ; UNINSTALL routine. Is called before the driver is removed from memory. ; No return code required (the driver is removed from memory on return). UNINSTALL: lda old_irq sei sta IRQInd+1 lda old_irq+1 sta IRQInd+2 ;cli ; This will be done at end of HIDE jsr HIDE ; Hide cursor on exit lda INIT_save sta INIT_STATUS rts ;---------------------------------------------------------------------------- ; HIDE routine. Is called to hide the mouse pointer. The mouse kernel manages ; a counter for calls to show/hide, and the driver entry point is only called ; if the mouse is currently visible and should get hidden. For most drivers, ; no special action is required besides hiding the mouse cursor. ; No return code required. HIDE: sei jsr CHIDE cli rts ;---------------------------------------------------------------------------- ; SHOW routine. Is called to show the mouse pointer. The mouse kernel manages ; a counter for calls to show/hide, and the driver entry point is only called ; if the mouse is currently hidden and should become visible. For most drivers, ; no special action is required besides enabling the mouse cursor. ; No return code required. SHOW: sei jsr CSHOW cli rts ;---------------------------------------------------------------------------- ; SETBOX: Set the mouse bounding box. The parameters are passed as they come ; from the C program, that is, a pointer to a mouse_box struct in a/x. ; No checks are done if the mouse is currently inside the box, this is the job ; of the caller. It is not necessary to validate the parameters, trust the ; caller and save some code here. No return code required. SETBOX: sta ptr1 stx ptr1+1 ; Save data pointer ldy #.sizeof (MOUSE_BOX)-1 sei @L1: lda (ptr1),y sta XMin,y dey bpl @L1 cli rts ;---------------------------------------------------------------------------- ; GETBOX: Return the mouse bounding box. The parameters are passed as they ; come from the C program, that is, a pointer to a mouse_box struct in a/x. GETBOX: sta ptr1 stx ptr1+1 ; Save data pointer ldy #.sizeof (MOUSE_BOX)-1 sei @L1: lda XMin,y sta (ptr1),y dey bpl @L1 cli rts ;---------------------------------------------------------------------------- ; MOVE: Move the mouse to a new position. The position is passed as it comes ; from the C program, that is: X on the stack and Y in a/x. The C wrapper will ; remove the parameter from the stack on return. ; No checks are done if the new position is valid (within the bounding box or ; the screen). No return code required. ; MOVE: sei ; No interrupts sta YPos stx YPos+1 ; New Y position jsr CMOVEY ; Set it ldy #$01 lda (sp),y sta XPos+1 tax dey lda (sp),y sta XPos ; New X position jsr CMOVEX ; Move the cursor cli ; Allow interrupts rts ;---------------------------------------------------------------------------- ; BUTTONS: Return the button mask in a/x. BUTTONS: lda Buttons ldx #$00 and #MOUSE_BTN_LEFT ; Left button -- same as JOY::FIRE rts ;---------------------------------------------------------------------------- ; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1. ; No return code required. POS: ldy #MOUSE_POS::XCOORD ; Structure offset sei ; Disable interrupts lda XPos ; Transfer the position sta (ptr1),y lda XPos+1 iny sta (ptr1),y lda YPos iny sta (ptr1),y lda YPos+1 cli ; Enable interrupts iny sta (ptr1),y ; Store last byte rts ; Done ;---------------------------------------------------------------------------- ; INFO: Returns mouse position and current button mask in the MOUSE_INFO ; struct pointed to by ptr1. No return code required. ; ; We're cheating here to keep the code smaller: The first fields of the ; mouse_info struct are identical to the mouse_pos struct, so we will just ; call _mouse_pos to initialize the struct pointer and fill the position ; fields. INFO: jsr POS ; Fill in the button state jsr BUTTONS ldy #MOUSE_INFO::BUTTONS sta (ptr1),y rts ;---------------------------------------------------------------------------- ; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl ; specific data in ptr1, and the ioctl code in A. ; Must return an error code in a/x. ; IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioctls for now ldx #>MOUSE_ERR_INV_IOCTL rts ;---------------------------------------------------------------------------- ; IRQ: Irq handler entry point. Called as a subroutine but in IRQ context ; (so be careful). The routine MUST return carry set if the interrupt has been ; 'handled' - which means that the interrupt source is gone. Otherwise it ; MUST return carry clear. ; IRQ: jsr CPREP lda KEY_COUNT sta old_key_count lda #$7F sta CIA1_PRA lda CIA1_PRB ; Read joystick #0 and #$1F eor #$1F ; Make all bits active high sta Buttons ; Check left/right and #(JOY::LEFT | JOY::RIGHT) beq @SkipX ; ; We will cheat here and rely on the fact that either the left, OR the right ; bit can be active and #JOY::RIGHT ; Check RIGHT bit bne @Right lda #$FF tax bne @AddX ; Branch always @Right: lda #$01 ldx #$00 ; Calculate the new X coordinate (--> a/y) @AddX: add XPos tay ; Remember low byte txa adc XPos+1 tax ; Limit the X coordinate to the bounding box cpy XMin sbc XMin+1 bpl @L1 ldy XMin ldx XMin+1 jmp @L2 @L1: txa cpy XMax sbc XMax+1 bmi @L2 ldy XMax ldx XMax+1 @L2: sty XPos stx XPos+1 ; Move the mouse pointer to the new X pos tya jsr CMOVEX ; Calculate the Y movement vector @SkipX: lda Buttons ; Read joystick #0 and #(JOY::UP | JOY::DOWN) ; Check up/down beq @SkipY ; ; We will cheat here and rely on the fact that either the up, OR the down ; bit can be active lsr a ; Check UP bit bcc @Down lda #$FF tax bne @AddY @Down: lda #$01 ldx #$00 ; Calculate the new Y coordinate (--> a/y) @AddY: add YPos tay ; Remember low byte txa adc YPos+1 tax ; Limit the Y coordinate to the bounding box cpy YMin sbc YMin+1 bpl @L3 ldy YMin ldx YMin+1 jmp @L4 @L3: txa cpy YMax sbc YMax+1 bmi @L4 ldy YMax ldx YMax+1 @L4: sty YPos stx YPos+1 ; Move the mouse pointer to the new X pos tya jsr CMOVEY ; Done @SkipY: jsr CDRAW clc ; Interrupt not "handled" rts .define OLD_BUTTONS Buttons ; tells callback.inc where the old port status is stored .include "callback.inc" �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/mou/c128-pot.s����������������������������������������������������������������0000664�0000000�0000000�00000031761�13473601511�0016411�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Driver for a potentiometer "mouse", e.g. Koala Pad ; ; 2006-08-20, Stefan Haubenthal ; 2009-09-26, Ullrich von Bassewitz ; 2014-04-26, Christian Groessler ; 2014-05-05, Greg King ; .include "zeropage.inc" .include "mouse-kernel.inc" .include "c128.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c128_pot_mou HEADER: ; Driver signature .byte $6d, $6f, $75 ; "mou" .byte MOUSE_API_VERSION ; Mouse driver API version number ; Library reference libref: .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr HIDE .addr SHOW .addr SETBOX .addr GETBOX .addr MOVE .addr BUTTONS .addr POS .addr INFO .addr IOCTL .addr IRQ ; Mouse driver flags .byte MOUSE_FLAG_LATE_IRQ ; Callback table, set by the kernel before INSTALL is called CHIDE: jmp $0000 ; Hide the cursor CSHOW: jmp $0000 ; Show the cursor CPREP: jmp $0000 ; Prepare to move the cursor CDRAW: jmp $0000 ; Draw the cursor CMOVEX: jmp $0000 ; Move the cursor to X coord CMOVEY: jmp $0000 ; Move the cursor to Y coord ;---------------------------------------------------------------------------- ; Constants SCREEN_HEIGHT = 200 SCREEN_WIDTH = 320 .enum JOY UP = $01 DOWN = $02 LEFT = $04 RIGHT = $08 FIRE = $10 .endenum ;---------------------------------------------------------------------------- ; Global variables. The bounding box values are sorted so that they can be ; written with the least effort in the SETBOX and GETBOX routines, so don't ; reorder them. .bss Vars: YPos: .res 2 ; Current mouse position, Y XPos: .res 2 ; Current mouse position, X XMin: .res 2 ; X1 value of bounding box YMin: .res 2 ; Y1 value of bounding box XMax: .res 2 ; X2 value of bounding box YMax: .res 2 ; Y2 value of bounding box Buttons: .res 1 ; Button mask INIT_save: .res 1 ; Keyboard buffer fill level at start of interrupt old_key_count: .res 1 ; Original IRQ vector old_irq: .res 2 .rodata ; Default values for above variables ; (We use ".proc" because we want to define both a label and a scope.) .proc DefVars .word SCREEN_HEIGHT/2 ; YPos .word SCREEN_WIDTH/2 ; XPos .word 0 ; XMin .word 0 ; YMin .word SCREEN_WIDTH - 1 ; XMax .word SCREEN_HEIGHT - 1 ; YMax .byte 0 ; Buttons .endproc .code ;---------------------------------------------------------------------------- ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present. ; Must return an MOUSE_ERR_xx code in a/x. INSTALL: ; Disable the BASIC interpreter's interrupt-driven sprite-motion code. ; That allows direct access to the VIC-IIe's sprite registers. lda INIT_STATUS sta INIT_save lda #%11000000 sta INIT_STATUS ; Initialize variables. Just copy the default stuff over ldx #.sizeof(DefVars)-1 @L1: lda DefVars,x sta Vars,x dex bpl @L1 ; Be sure the mouse cursor is invisible and at the default location. We ; need to do that here, because our mouse interrupt handler doesn't set the ; mouse position if it hasn't changed. sei jsr CHIDE lda XPos ldx XPos+1 jsr CMOVEX lda YPos ldx YPos+1 jsr CMOVEY ; Initiate our IRQ magic. ; Remember the ROM IRQ continuation address. ldx IRQInd+2 lda IRQInd+1 stx old_irq+1 sta old_irq lda libref ldx libref+1 sta ptr3 stx ptr3+1 ; Set the ROM IRQ continuation address to point to the provided routine. ldy #2 lda (ptr3),y sta IRQInd+1 iny lda (ptr3),y sta IRQInd+2 ; Set the address of our IRQ callback routine. ; Because it's called via "rts", we must use "address-1". iny lda #<(callback-1) sta (ptr3),y iny lda #>(callback-1) sta (ptr3),y ; Set the ROM entry-point vector. ; Because it's called via "rts", we must decrement it by one. iny lda old_irq sub #<1 sta (ptr3),y iny lda old_irq+1 sbc #>1 sta (ptr3),y cli ; Done, return zero (= MOUSE_ERR_OK) ldx #$00 txa rts ;---------------------------------------------------------------------------- ; UNINSTALL routine. Is called before the driver is removed from memory. ; No return code required (the driver is removed from memory on return). UNINSTALL: lda old_irq ldx old_irq+1 sei sta IRQInd+1 stx IRQInd+2 ;cli ; This will be done at end of HIDE jsr HIDE ; Hide cursor on exit lda INIT_save sta INIT_STATUS rts ;---------------------------------------------------------------------------- ; HIDE routine. Is called to hide the mouse pointer. The mouse kernel manages ; a counter for calls to show/hide, and the driver entry point is only called ; if the mouse is currently visible and should get hidden. For most drivers, ; no special action is required besides hiding the mouse cursor. ; No return code required. HIDE: sei jsr CHIDE cli rts ;---------------------------------------------------------------------------- ; SHOW routine. Is called to show the mouse pointer. The mouse kernel manages ; a counter for calls to show/hide, and the driver entry point is only called ; if the mouse is currently hidden and should become visible. For most drivers, ; no special action is required besides enabling the mouse cursor. ; No return code required. SHOW: sei jsr CSHOW cli rts ;---------------------------------------------------------------------------- ; SETBOX: Set the mouse bounding box. The parameters are passed as they come ; from the C program, that is, a pointer to a mouse_box struct in a/x. ; No checks are done if the mouse is currently inside the box, this is the job ; of the caller. It is not necessary to validate the parameters, trust the ; caller and save some code here. No return code required. SETBOX: sta ptr1 stx ptr1+1 ; Save data pointer ldy #.sizeof (MOUSE_BOX)-1 sei @L1: lda (ptr1),y sta XMin,y dey bpl @L1 cli rts ;---------------------------------------------------------------------------- ; GETBOX: Return the mouse bounding box. The parameters are passed as they ; come from the C program, that is, a pointer to a mouse_box struct in a/x. GETBOX: sta ptr1 stx ptr1+1 ; Save data pointer ldy #.sizeof (MOUSE_BOX)-1 sei @L1: lda XMin,y sta (ptr1),y dey bpl @L1 cli rts ;---------------------------------------------------------------------------- ; MOVE: Move the mouse to a new position. The position is passed as it comes ; from the C program, that is: X on the stack and Y in a/x. The C wrapper will ; remove the parameter from the stack on return. ; No checks are done if the new position is valid (within the bounding box or ; the screen). No return code required. ; MOVE: sei ; No interrupts sta YPos stx YPos+1 ; New Y position jsr CMOVEY ; Set it ldy #$01 lda (sp),y sta XPos+1 tax dey lda (sp),y sta XPos ; New X position jsr CMOVEX ; Move the cursor cli ; Allow interrupts rts ;---------------------------------------------------------------------------- ; BUTTONS: Return the button mask in a/x. BUTTONS: lda Buttons ldx #$00 ; Make the buttons look like a 1351 mouse. and #JOY::LEFT | JOY::RIGHT lsr a lsr a ;clc ; ("lsr" shifted zero into carry flag) adc #%00001110 ; Shift bit 1 over to bit 4 and #MOUSE_BTN_LEFT | MOUSE_BTN_RIGHT rts ;---------------------------------------------------------------------------- ; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1. ; No return code required. POS: ldy #MOUSE_POS::XCOORD ; Structure offset sei ; Disable interrupts lda XPos ; Transfer the position sta (ptr1),y lda XPos+1 iny sta (ptr1),y lda YPos iny sta (ptr1),y lda YPos+1 cli ; Enable interrupts iny sta (ptr1),y ; Store last byte rts ; Done ;---------------------------------------------------------------------------- ; INFO: Returns mouse position and current button mask in the MOUSE_INFO ; struct pointed to by ptr1. No return code required. ; ; We're cheating here to keep the code smaller: The first fields of the ; mouse_info struct are identical to the mouse_pos struct, so we will just ; call _mouse_pos to initialize the struct pointer and fill the position ; fields. INFO: jsr POS ; Fill in the button state jsr BUTTONS ldy #MOUSE_INFO::BUTTONS sta (ptr1),y rts ;---------------------------------------------------------------------------- ; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl ; specific data in ptr1, and the ioctl code in A. ; Must return an error code in a/x. ; IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioctls for now ldx #>MOUSE_ERR_INV_IOCTL rts ;---------------------------------------------------------------------------- ; IRQ: Irq handler entry point. Called as a subroutine but in IRQ context ; (so be careful). ; IRQ: jsr CPREP lda KEY_COUNT sta old_key_count lda #$7F sta CIA1_PRA lda CIA1_PRB ; Read port #1 eor #%11111111 ; Make all bits active high sta Buttons ldx #%01000000 ; Read port 1 paddles stx CIA1_PRA ldy #<256 : dey bne :- ldx SID_ADConv1 stx XPos ldx SID_ADConv2 stx YPos lda #$FF tax bne @AddX ; Branch always lda #$01 ldx #$00 ; Calculate the new X coordinate (--> a/y) @AddX: add XPos tay ; Remember low byte txa adc XPos+1 tax ; Limit the X coordinate to the bounding box cpy XMin sbc XMin+1 bpl @L1 ldy XMin ldx XMin+1 jmp @L2 @L1: txa cpy XMax sbc XMax+1 bmi @L2 ldy XMax ldx XMax+1 @L2: sty XPos stx XPos+1 ; Move the mouse pointer to the new X pos tya jsr CMOVEX lda #$FF tax bne @AddY @Down: lda #$01 ldx #$00 ; Calculate the new Y coordinate (--> a/y) @AddY: add YPos tay ; Remember low byte txa adc YPos+1 tax ; Limit the Y coordinate to the bounding box cpy YMin sbc YMin+1 bpl @L3 ldy YMin ldx YMin+1 jmp @L4 @L3: txa cpy YMax sbc YMax+1 bmi @L4 ldy YMax ldx YMax+1 @L4: sty YPos stx YPos+1 ; Move the mouse pointer to the new X pos tya jsr CMOVEY jsr CDRAW clc ; Interrupt not "handled" rts .define OLD_BUTTONS Buttons ; Tells callback.inc where the old port status is stored .include "callback.inc" ���������������cc65-2.18/libsrc/c128/mou/callback.inc��������������������������������������������������������������0000664�0000000�0000000�00000001565�13473601511�0017176�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Callback routine called from the IRQ handler after the ROM IRQ handler ; had been run. ; ; Christian Groessler, 24.04.2014 ; ; Check if there was button/joystick activity before and/or after the ROM handler. ; If there was activity, discard the key presses since they are most ; probably "phantom" key presses. callback: ldx old_key_count cpx KEY_COUNT beq @nokey lda OLD_BUTTONS ; keypress before? bne @discard_key ; yes, discard key lda #$7F sta CIA1_PRA lda CIA1_PRB ; Read joystick #0 and #$1F eor #$1F ; keypress after beq @nokey ; no, probably a real key press @discard_key: stx KEY_COUNT ; set old keyboard buffer fill level @nokey: rts �������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/mouse_stat_stddrv.s�����������������������������������������������������������0000664�0000000�0000000�00000000355�13473601511�0020100�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Address of the static standard mouse driver ; ; Oliver Schmidt, 2012-11-01 ; ; const void mouse_static_stddrv[]; ; .export _mouse_static_stddrv .import _c128_1351_mou .rodata _mouse_static_stddrv := _c128_1351_mou �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/mouse_stddrv.s����������������������������������������������������������������0000664�0000000�0000000�00000000300�13473601511�0017033�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Name of the standard mouse driver ; ; Ullrich von Bassewitz, 2009-09-11 ; ; const char mouse_stddrv[]; ; .export _mouse_stddrv .rodata _mouse_stddrv: .asciiz "c128-1351.mou" ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/mouseref.s��������������������������������������������������������������������0000664�0000000�0000000�00000005516�13473601511�0016160�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Pointer for library references by device drivers. ; ; Helper-routines for the interrupt handler that rejects bogus keypresses ; that are caused by mouse-like devices. ; ; 2013-07-25, Greg King ; 2014-04-26, Christian Groessler ; .include "c128.inc" .export mouse_libref, _pen_adjuster .data mouse_libref: ; generic label for mouse-kernel ; A program optionally can set this pointer to a function that gives ; a calibration value to a driver. If this pointer isn't NULL, ; then a driver that wants a value can call that function. ; ; The function might read a value from a file; or, it might ask the user ; to help calibrate the driver. ; ; void __fastcall__ (*pen_adjuster)(unsigned char *) = NULL; ; _pen_adjuster: .addr $0000 .addr IRQStub2 callback: ; callback into mouse driver after ROM IRQ handler has been run .addr $0000 ; (filled in by mouse driver) jmp_rom_hdlr: ; original ROM indirect IRQ handler address .addr $0000 ; (filled in by mouse driver) .segment "LOWCODE" ; Called from irq.s when it thinks it chains to the original handler. ; ROM is banked in again. In order to call the callback we have to ; bank it out one more time. IRQStub2: ; Call ROM handler and prepare stack so that it will return to us. ; setup fake IRQ stack frame which will return to "IRQCont" lda #>@IRQCont pha lda #<@IRQCont pha php ; mimic the contents saved on the stack by the ROM IRQ entry handler pha ; A pha ; X pha ; Y lda #MMU_CFG_CC65 ; MMU configuration which will be active after the ROM handler returns pha ; map out ROM ldy MMU_CR sta MMU_CR ; push address of ROM handler on stack and jump to it lda jmp_rom_hdlr+1 pha lda jmp_rom_hdlr pha sty MMU_CR ; map in ROM rts ; jump to ROM handler ; our MMU configuration byte we pushed on the stack before (MMU_CFG_CC65) is now active @IRQCont: ; call mouse driver callback routine lda #>(@IRQCont2-1) pha lda #<(@IRQCont2-1) pha lda callback+1 pha lda callback pha rts ; jump to callback routine @IRQCont2: ; return from interrupt ; We could just jump to $FF33, but since I don't know whether this address is valid in all ; ROM versions, duplicate that code here. pla sta MMU_CR ; MMU configuration register pla tay pla tax pla rti ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/pencalib.c��������������������������������������������������������������������0000664�0000000�0000000�00000005144�13473601511�0016065�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** Calibrate lightpen drivers to the current video hardware. ** ** 2013-07-25, Greg King ** */ #include <conio.h> #include <mouse.h> #include <pen.h> #define COMMAND1 "Adjust by clicking on line." #define COMMAND2 "Finish by clicking off bar." /* There is a delay between when the VIC sends its signal, and when the display ** shows that signal. There is another delay between the display and when the ** lightpen says that it saw that signal. Each display and pen is different. ** Therefore, the driver must be calibrated to them. A white bar is painted on ** the screen; and, a line is drawn down the middle of it. When the user ** clicks on that line, the difference between its position and where the VIC ** thinks that the pen is pointing becomes an offset that is subtracted from ** what the VIC sees. */ void __fastcall__ pen_calibrate (unsigned char *XOffset) { unsigned char oldBg = bgcolor (COLOR_BLUE); unsigned char oldText = textcolor (COLOR_GRAY3); unsigned char oldRev = revers (1); unsigned char sprite0Color = VIC.spr_color[0]; unsigned char width, width2, height, height4, height8; struct mouse_info info; screensize (&width, &height); width2 = width / 2; height4 = height / 4; height8 = height4 * 8; /* Draw a bar and line. */ clrscr (); cclearxy (0, height4, height4 * width); cvlinexy (width2, height4 + 1, height4 - 2); /* Print instructions. */ revers (0); cputsxy (width2 - (sizeof COMMAND1) / 2, height / 2 + 1, COMMAND1); cputsxy (width2 - (sizeof COMMAND2) / 2, height / 2 + 3, COMMAND2); VIC.spr_color[0] = COLOR_GRAY2; mouse_show (); mouse_move (width2 * 8, height8 / 2); for (;;) { /* Wait for the main button to be released. */ do ; while ((mouse_buttons () & MOUSE_BTN_LEFT)); /* Wait for the main button to be pressed. */ do { mouse_info (&info); } while (!(info.buttons & MOUSE_BTN_LEFT)); /* Find out if the pen is on or off the bar. */ if (info.pos.y < height8 || info.pos.y >= height8 * 2) { break; } /* On the bar; adjust the offset. */ /* Characters are eight pixels wide. ** The VIC-II sees every other pixel; ** so, we use half of the difference. */ *XOffset += (info.pos.x - (width2 * 8 + 8/2)) / 2; } /* Off the bar; wait for the main button to be released. */ do ; while ((mouse_buttons () & MOUSE_BTN_LEFT)); mouse_hide (); VIC.spr_color[0] = sprite0Color; revers (oldRev); textcolor (oldText); bgcolor (oldBg); clrscr (); } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/randomize.s�������������������������������������������������������������������0000664�0000000�0000000�00000000670�13473601511�0016317�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2002-11-05, Ullrich von Bassewitz ; 2015-09-11, Greg King ; ; void _randomize (void); ; /* Initialize the random number generator */ ; .export __randomize .import _srand .include "c128.inc" __randomize: ldx VIC_HLINE ; Use VIC rasterline as high byte lda TIME+2 ; Use 60HZ clock as low byte jmp _srand ; Initialize generator ������������������������������������������������������������������������cc65-2.18/libsrc/c128/revers.s����������������������������������������������������������������������0000664�0000000�0000000�00000001402�13473601511�0015627�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 07.08.1998 ; ; unsigned char revers (unsigned char onoff); ; .export _revers .include "c128.inc" .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 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/ser/��������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014731�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/ser/c128-swlink.s�������������������������������������������������������������0000664�0000000�0000000�00000035071�13473601511�0017105�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Serial driver for the C128 using a Swiftlink or Turbo-232 cartridge. ; ; Ullrich von Bassewitz, 2003-04-18 ; ; The driver is based on the cc65 rs232 module, which in turn is based on ; Craig Bruce device driver for the Switftlink/Turbo-232. ; ; SwiftLink/Turbo-232 v0.90 device driver, by Craig Bruce, 14-Apr-1998. ; ; This software is Public Domain. It is in Buddy assembler format. ; ; This device driver uses the SwiftLink RS-232 Serial Cartridge, available from ; Creative Micro Designs, Inc, and also supports the extensions of the Turbo232 ; Serial Cartridge. Both devices are based on the 6551 ACIA chip. It also ; supports the "hacked" SwiftLink with a 1.8432 MHz crystal. ; ; The code assumes that the kernal + I/O are in context. On the C128, call ; it from Bank 15. On the C64, don't flip out the Kernal unless a suitable ; NMI catcher is put into the RAM under then Kernal. For the SuperCPU, the ; interrupt handling assumes that the 65816 is in 6502-emulation mode. ; .include "zeropage.inc" .include "ser-kernel.inc" .include "ser-error.inc" .include "c128.inc" .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c128_swlink_ser ; Driver signature .byte $73, $65, $72 ; "ser" .byte SER_API_VERSION ; Serial API version number ; Library reference .addr $0000 ; Jump table .word SER_INSTALL .word SER_UNINSTALL .word SER_OPEN .word SER_CLOSE .word SER_GET .word SER_PUT .word SER_STATUS .word SER_IOCTL .word SER_IRQ ;---------------------------------------------------------------------------- ; I/O definitions ACIA = $DE00 ACIA_DATA = ACIA+0 ; Data register ACIA_STATUS = ACIA+1 ; Status register ACIA_CMD = ACIA+2 ; Command register ACIA_CTRL = ACIA+3 ; Control register ;---------------------------------------------------------------------------- ; ; Global variables ; ; We reuse the RS232 zero page variables for the driver, since the ROM ; routines cannot be used together with this driver (may also use $A0F ; and following in case of problems). RecvHead := $A7 ; Head of receive buffer RecvTail := $A8 ; Tail of receive buffer RecvFreeCnt := $A9 ; Number of bytes in receive buffer SendHead := $AA ; Head of send buffer SendTail := $AB ; Tail of send buffer SendFreeCnt := $B4 ; Number of bytes free in send buffer Stopped := $B5 ; Flow-stopped flag RtsOff := $B6 ; ; Send and receive buffers: 256 bytes each RecvBuf := $0C00 ; Use the ROM buffers SendBuf := $0D00 .rodata ; Tables used to translate RS232 params into register values BaudTable: ; bit7 = 1 means setting is invalid .byte $FF ; SER_BAUD_45_5 .byte $FF ; SER_BAUD_50 .byte $FF ; SER_BAUD_75 .byte $FF ; SER_BAUD_110 .byte $FF ; SER_BAUD_134_5 .byte $02 ; SER_BAUD_150 .byte $05 ; SER_BAUD_300 .byte $06 ; SER_BAUD_600 .byte $07 ; SER_BAUD_1200 .byte $FF ; SER_BAUD_1800 .byte $08 ; SER_BAUD_2400 .byte $09 ; SER_BAUD_3600 .byte $0A ; SER_BAUD_4800 .byte $0B ; SER_BAUD_7200 .byte $0C ; SER_BAUD_9600 .byte $0E ; SER_BAUD_19200 .byte $0F ; SER_BAUD_38400 .byte $FF ; SER_BAUD_57600 .byte $FF ; SER_BAUD_115200 .byte $FF ; SER_BAUD_230400 BitTable: .byte $60 ; SER_BITS_5 .byte $40 ; SER_BITS_6 .byte $20 ; SER_BITS_7 .byte $00 ; SER_BITS_8 StopTable: .byte $00 ; SER_STOP_1 .byte $80 ; SER_STOP_2 ParityTable: .byte $00 ; SER_PAR_NONE .byte $20 ; SER_PAR_ODD .byte $60 ; SER_PAR_EVEN .byte $A0 ; SER_PAR_MARK .byte $E0 ; SER_PAR_SPACE .code ;---------------------------------------------------------------------------- ; Interrupt stub that is copied into low RAM. The startup code uses a special ; memory configuration with just kernal and I/O enabled (anything else is RAM). ; The NMI handler in ROM will switch back to a configuration where just the ; low 16K RAM are accessible. So we have to copy a smal piece of code into ; low RAM that enables the cc65 configuration and then jumps to the real NMI ; handler. NmiStubOrig := * .org $1150 ; BASIC graphics area .proc NmiStub lda #MMU_CFG_CC65 ; Bank 0 with kernal ROM... sta MMU_CR ; ...enable jsr NmiHandler ; Call the actual NMI handler lda #$00 ; Get ROM config... sta MMU_CR ; ...and enable it Vector := *+1 .byte $4C ; Jump to the saved IRQ vector .endproc .reloc ;---------------------------------------------------------------------------- ; SER_INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present. ; Must return an SER_ERR_xx code in a/x. SER_INSTALL: ; Deactivate DTR and disable 6551 interrupts lda #%00001010 sta ACIA_CMD ; Copy the NMI stub into low memory ldy #.sizeof (NmiStub)-1 @L1: lda NmiStubOrig,y sta NmiStub,y dey bpl @L1 ; Set up the nmi vector lda NMIVec ldy NMIVec+1 sta NmiStub::Vector+0 sty NmiStub::Vector+1 lda #<NmiStub ldy #>NmiStub SetNMI: sta NMIVec sty NMIVec+1 ; Done, return an error code lda #<SER_ERR_OK tax ; A is zero rts ;---------------------------------------------------------------------------- ; SER_UNINSTALL routine. Is called before the driver is removed from memory. ; Must return an SER_ERR_xx code in a/x. SER_UNINSTALL: ; Stop interrupts, drop DTR lda #%00001010 sta ACIA_CMD ; Restore NMI vector and return OK lda NmiStub::Vector+0 ldy NmiStub::Vector+1 jmp SetNMI ;---------------------------------------------------------------------------- ; PARAMS routine. A pointer to a ser_params structure is passed in ptr1. ; Must return an SER_ERR_xx code in a/x. SER_OPEN: ; Check if the handshake setting is valid ldy #SER_PARAMS::HANDSHAKE ; Handshake lda (ptr1),y cmp #SER_HS_HW ; This is all we support bne InvParam ; Initialize buffers jsr InitBuffers ; Set the value for the control register, which contains stop bits, word ; length and the baud rate. ldy #SER_PARAMS::BAUDRATE lda (ptr1),y ; Baudrate index tay lda BaudTable,y ; Get 6551 value bmi InvBaud ; Branch if rate not supported sta tmp1 ldy #SER_PARAMS::DATABITS ; Databits lda (ptr1),y tay lda BitTable,y ora tmp1 sta tmp1 ldy #SER_PARAMS::STOPBITS ; Stopbits lda (ptr1),y tay lda StopTable,y ora tmp1 ora #%00010000 ; Receiver clock source = baudrate sta ACIA_CTRL ; Set the value for the command register. We remember the base value in ; RtsOff, since we will have to manipulate ACIA_CMD often. ldy #SER_PARAMS::PARITY ; Parity lda (ptr1),y tay lda ParityTable,y ora #%00000001 ; DTR active sta RtsOff ora #%00001000 ; Enable receive interrupts sta ACIA_CMD ; Done lda #<SER_ERR_OK tax ; A is zero rts ; Invalid parameter InvParam: lda #<SER_ERR_INIT_FAILED ldx #>SER_ERR_INIT_FAILED rts ; Baud rate not available InvBaud: lda #<SER_ERR_BAUD_UNAVAIL ldx #>SER_ERR_BAUD_UNAVAIL rts ;---------------------------------------------------------------------------- ; SER_CLOSE: Close the port, disable interrupts and flush the buffer. Called ; without parameters. Must return an error code in a/x. ; SER_CLOSE: ; Stop interrupts, drop DTR lda #%00001010 sta ACIA_CMD ; Initalize buffers. Returns zero in a jsr InitBuffers ; Return OK lda #<SER_ERR_OK tax ; A is zero rts ;---------------------------------------------------------------------------- ; SER_GET: Will fetch a character from the receive buffer and store it into the ; variable pointer to by ptr1. If no data is available, SER_ERR_NO_DATA is ; return. ; SER_GET: ldx SendFreeCnt ; Send data if necessary inx ; X == $FF? beq @L1 lda #$00 jsr TryToSend ; Check for buffer empty @L1: lda RecvFreeCnt ; (25) cmp #$ff bne @L2 lda #<SER_ERR_NO_DATA ldx #>SER_ERR_NO_DATA rts ; Check for flow stopped & enough free: release flow control @L2: ldx Stopped ; (34) beq @L3 cmp #63 bcc @L3 lda #$00 sta Stopped lda RtsOff ora #%00001000 sta ACIA_CMD ; Get byte from buffer @L3: ldx RecvHead ; (41) lda RecvBuf,x inc RecvHead inc RecvFreeCnt ldx #$00 ; (59) sta (ptr1,x) txa ; Return code = 0 rts ;---------------------------------------------------------------------------- ; SER_PUT: Output character in A. ; Must return an error code in a/x. ; SER_PUT: ; Try to send ldx SendFreeCnt inx ; X = $ff? beq @L2 pha lda #$00 jsr TryToSend pla ; Put byte into send buffer & send @L2: ldx SendFreeCnt bne @L3 lda #<SER_ERR_OVERFLOW ; X is already zero rts @L3: ldx SendTail sta SendBuf,x inc SendTail dec SendFreeCnt lda #$ff jsr TryToSend lda #<SER_ERR_OK tax rts ;---------------------------------------------------------------------------- ; SER_STATUS: Return the status in the variable pointed to by ptr1. ; Must return an error code in a/x. ; SER_STATUS: lda ACIA_STATUS ldx #0 sta (ptr1,x) txa ; SER_ERR_OK rts ;---------------------------------------------------------------------------- ; SER_IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl ; specific data in ptr1, and the ioctl code in A. ; Must return an error code in a/x. ; SER_IOCTL: lda #<SER_ERR_INV_IOCTL ; We don't support ioclts for now ldx #>SER_ERR_INV_IOCTL rts ;---------------------------------------------------------------------------- ; IRQ: Not used on the C128 ; SER_IRQ = $0000 ;---------------------------------------------------------------------------- ; ; NMI handler ; C128 NMI overhead=76 cycles: int=7, maxLatency=6, ROMenter=33, ROMexit=30 ; C64 NMI overhead=76 cycles: int=7, maxLatency=6, ROMenter=34, ROMexit=29 ; ; timing: normal=76+43+9=128 cycles, assertFlow=76+52+9=137 cycles ; ; C128 @ 115.2k: 177 cycles avail (fast) ; C64 @ 57.6k: 177 cycles avail, worstAvail=177-43? = 134 ; SCPU @ 230.4k: 868 cycles avail: for a joke! ; ; Note: Because of the C128 banking, a small stub has to go into low memory, ; since the ROM NMI entry point switches to a configuration, where only the ; low 16K of RAM are visible. The entry code switches into the standard cc65 ; configuration (I/O + 16K kernal) and then jumps here. Registers are already ; saved by the ROM code. NmiHandler: lda ACIA_STATUS ;(4) ;status ;check for byte received and #$08 ;(2) beq @L9 ;(2*) cld lda ACIA_DATA ;(4) data ;get byte and put into receive buffer ldy RecvTail ;(4) ldx RecvFreeCnt ;(4) beq @L9 ;(2*) Jump if no space in receive buffer sta RecvBuf,y ;(5) inc RecvTail ;(6) dec RecvFreeCnt ;(6) cpx #33 ;(2) check for buffer space low bcc @L2 ;(2*) rts ; Assert flow control @L2: lda RtsOff ;(3) assert flow control if buffer space too low sta ACIA_CMD ;(4) command sta Stopped ;(3) @L9: rts ;---------------------------------------------------------------------------- ; Try to send a byte. Internal routine. A = TryHard .proc TryToSend sta tmp1 ; Remember tryHard flag @L0: lda SendFreeCnt cmp #$ff beq @L3 ; Bail out ; Check for flow stopped @L1: lda Stopped bne @L3 ; Bail out ; Check that swiftlink is ready to send @L2: lda ACIA_STATUS and #$10 bne @L4 bit tmp1 ;keep trying if must try hard bmi @L0 @L3: rts ; Send byte and try again @L4: ldx SendHead lda SendBuf,x sta ACIA_DATA inc SendHead inc SendFreeCnt jmp @L0 .endproc ;---------------------------------------------------------------------------- ; Initialize buffers InitBuffers: ldx #0 stx Stopped stx RecvHead stx RecvTail stx SendHead stx SendTail dex ; X = 255 stx RecvFreeCnt stx SendFreeCnt rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/settime.s���������������������������������������������������������������������0000664�0000000�0000000�00000003465�13473601511�0016006�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 16.8.2018 ; ; int __fastcall__ clock_settime (clockid_t clk_id, const struct timespec *tp); ; .include "time.inc" .include "c128.inc" .importzp sreg, ptr1 .import pushax, pusheax, ldax0sp, ldeaxidx .import tosdiveax, incsp3, return0 .import TM, load_tenth ;---------------------------------------------------------------------------- .code .proc _clock_settime jsr pushax .assert timespec::tv_sec = 0, error jsr _localtime sta ptr1 stx ptr1+1 ldy #.sizeof(tm)-1 @L1: lda (ptr1),y sta TM,y dey bpl @L1 lda TM + tm::tm_hour jsr dec2BCD tax ; Force flags bne @L2 lda #$92 ; 12 AM bne @L3 @L2: cmp #$13 ; 1 PM bcc @L3 sed sbc #$12 cld ora #%10000000 @L3: sta CIA1_TODHR lda TM + tm::tm_min jsr dec2BCD sta CIA1_TODMIN lda TM + tm::tm_sec jsr dec2BCD sta CIA1_TODSEC jsr ldax0sp ldy #3+timespec::tv_nsec jsr ldeaxidx jsr pusheax jsr load_tenth jsr tosdiveax sta CIA1_TOD10 jsr incsp3 jmp return0 .endproc ;---------------------------------------------------------------------------- ; Just sum up the value in BCD mode. ; http://forum.6502.org/viewtopic.php?p=7629#p7629 .proc dec2BCD tax dex bmi @L9 lda #0 clc sed @L1: adc #1 dex bpl @L1 cld @L9: rts .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/slow.s������������������������������������������������������������������������0000664�0000000�0000000�00000000410�13473601511�0015303�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-02-13 ; ; void slow (void); ; /* Switch the CPU into 1MHz mode. */ ; */ ; .export _slow .include "c128.inc" .proc _slow lda #$00 sta VIC_CLK_128 rts .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/status.s����������������������������������������������������������������������0000664�0000000�0000000�00000000134�13473601511�0015645�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2012-09-30 ; .exportzp ST := $90 ; IEC status byte ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/sysuname.s��������������������������������������������������������������������0000664�0000000�0000000�00000001447�13473601511�0016176�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-08-12 ; ; unsigned char __fastcall__ _sysuname (struct utsname* buf); ; .export __sysuname, utsdata .import utscopy __sysuname = utscopy ;-------------------------------------------------------------------------- ; Data. We define a fixed utsname struct here and just copy it. .rodata utsdata: ; sysname .asciiz "cc65" ; nodename .asciiz "" ; release .byte ((.VERSION >> 8) & $0F) + '0' .byte '.' .byte ((.VERSION >> 4) & $0F) + '0' .byte $00 ; version .byte (.VERSION & $0F) + '0' .byte $00 ; machine .asciiz "Commodore 128" �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/tgi/��������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014723�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/tgi/c128-hi.s�����������������������������������������������������������������0000664�0000000�0000000�00000053336�13473601511�0016174�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Graphics driver for the 320x200x2 mode on the C128. ; ; Based on Stephen L. Judd's GRLIB code. ; ; 2018-03-13, Sven Klose ; 2018-07-22, Scott Hutter ; 2018-07-28, Greg King ; .include "zeropage.inc" .include "tgi-kernel.inc" .include "tgi-error.inc" .include "c128.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table and constants. module_header _c128_hi_tgi ; First part of the header is a structure that has a magic and defines the ; capabilities of the driver .byte $74, $67, $69 ; "tgi" .byte TGI_API_VERSION ; TGI API version number .addr $0000 ; Library reference .word 320 ; X resolution .word 200 ; Y resolution .byte 2 ; Number of drawing colors .byte 1 ; Number of screens available .byte 8 ; System font X size .byte 8 ; System font Y size .word $00D4 ; Aspect ratio (based on 4/3 display) .byte 0 ; TGI driver flags ; Next comes the jump table. With the exception of IRQ, all entries must be ; valid and may point to an RTS for test versions (function not implemented). .addr INSTALL .addr UNINSTALL .addr INIT .addr DONE .addr GETERROR .addr CONTROL .addr CLEAR .addr SETVIEWPAGE .addr SETDRAWPAGE .addr SETCOLOR .addr SETPALETTE .addr GETPALETTE .addr GETDEFPALETTE .addr SETPIXEL .addr GETPIXEL .addr LINE .addr BAR .addr TEXTSTYLE .addr OUTTEXT ; ------------------------------------------------------------------------ ; Data. ; Variables mapped to the zero page segment variables. Some of these are ; used for passing parameters to the driver. X1 := ptr1 Y1 := ptr2 X2 := ptr3 Y2 := ptr4 TEXT := ptr3 TEMP := tmp4 TEMP2 := sreg POINT := regsave CHUNK := X2 ; Used in the line routine OLDCHUNK := X2+1 ; Ditto ; Absolute variables used in the code .bss ERROR: .res 1 ; Error code PALETTE: .res 2 ; The current palette BITMASK: .res 1 ; $00 = clear, $FF = set pixels ; Line routine stuff DX: .res 2 DY: .res 2 ; BAR variables X1SAVE: .res 2 Y1SAVE: .res 1 X2SAVE: .res 2 Y2SAVE: .res 1 ; Text output stuff TEXTMAGX: .res 1 TEXTMAGY: .res 1 TEXTDIR: .res 1 ; Constants and tables .rodata DEFPALETTE: .byte $00, $01 ; White on black PALETTESIZE = * - DEFPALETTE BITTAB: .byte $80,$40,$20,$10,$08,$04,$02,$01 BITCHUNK: .byte $FF,$7F,$3F,$1F,$0F,$07,$03,$01 CHARROM := $D000 ; Character ROM base address VBASE := $C000 ; Video memory base address CBASE := $E000 ; Color memory base address .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. May ; initialize anything that has to be done just once. Is probably empty ; most of the time. ; ; Must set an error code: NO ; INSTALL: ; rts ; fall through ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. May ; clean up anything done by INSTALL but is probably empty most of the time. ; ; Must set an error code: NO ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; INIT: Changes an already installed device from text mode to graphics ; mode. ; Note that INIT/DONE may be called multiple times while the driver ; is loaded, while INSTALL is only called once, so any code that is needed ; to initializes variables and so on must go here. Setting palette and ; clearing the screen is not needed because this is called by the graphics ; kernel later. ; The graphics kernel will never call INIT when a graphics mode is already ; active, so there is no need to protect against that. ; ; Must set an error code: YES ; INIT: ; Initialize variables. ldx #$FF ; Foreground color stx BITMASK ; Switch into graphics mode. ; Select a video bank: ; bank 0 = $03 ($0000-$3FFF) (default) ; bank 1 = $02 ($4000-$7FFF) ; bank 2 = $01 ($8000-$BFFF) ; bank 3 = $00 ($C000-$FFFF) (TGI) lda CIA2_PRA and #<~$03 ; Bank 3 sta CIA2_PRA lda #$80 ; color-map at $E000, bitmap at $C000 sta VM2 ; Make the VIC-IIe read RAM instead of the font ROM. lda #%00000100 sta CHARDIS ; Switch to bitmap mode. lda #%00100000 sta GRAPHM lda #TGI_ERR_OK sta ERROR rts ; ------------------------------------------------------------------------ ; DONE: Will be called to switch the graphics device back into text mode. ; The graphics kernel will never call DONE when no graphics mode is active, ; so there is no need to protect against that. ; ; Must set an error code: NO ; DONE: ; Select the text video bank. lda CIA2_PRA ora #$03 ; Bank 0 sta CIA2_PRA ; Make the VIC-IIe read the font ROM instead of RAM. lda #%00000000 sta CHARDIS ;lda #%00000000 ; Switch back to text mode sta GRAPHM ; Restore a value that's needed by BASIC's GRAPHIC 1 statement. lda #$78 ; color-map at $1C00, bitmap at $2000 sta VM2 rts ; ------------------------------------------------------------------------ ; GETERROR: Return the error code in A and clear it. GETERROR: ldx #TGI_ERR_OK lda ERROR stx ERROR rts ; ------------------------------------------------------------------------ ; CONTROL: Platform/driver specific entry point. ; ; Must set an error code: YES ; CONTROL: lda #TGI_ERR_INV_FUNC sta ERROR rts ; ------------------------------------------------------------------------ ; CLEAR: Clears the screen. ; ; Must set an error code: NO ; CLEAR: ldy #$00 tya ldx #MMU_CFG_RAM0 sei stx MMU_CR @L1: sta VBASE+$0000,y sta VBASE+$0100,y sta VBASE+$0200,y sta VBASE+$0300,y sta VBASE+$0400,y sta VBASE+$0500,y sta VBASE+$0600,y sta VBASE+$0700,y sta VBASE+$0800,y sta VBASE+$0900,y sta VBASE+$0A00,y sta VBASE+$0B00,y sta VBASE+$0C00,y sta VBASE+$0D00,y sta VBASE+$0E00,y sta VBASE+$0F00,y sta VBASE+$1000,y sta VBASE+$1100,y sta VBASE+$1200,y sta VBASE+$1300,y sta VBASE+$1400,y sta VBASE+$1500,y sta VBASE+$1600,y sta VBASE+$1700,y sta VBASE+$1800,y sta VBASE+$1900,y sta VBASE+$1A00,y sta VBASE+$1B00,y sta VBASE+$1C00,y sta VBASE+$1D00,y sta VBASE+$1E00,y sta VBASE+$1F00,y iny bne @L1 ldx #MMU_CFG_CC65 stx MMU_CR cli rts ; ------------------------------------------------------------------------ ; SETVIEWPAGE: Set the visible page. Called with the new page in A (0..n). ; The page number is already checked to be valid by the graphics kernel. ; ; Must set an error code: NO (will only be called if page ok) ; SETVIEWPAGE: ; rts ; fall through ; ------------------------------------------------------------------------ ; SETDRAWPAGE: Set the drawable page. Called with the new page in A (0..n). ; The page number is already checked to be valid by the graphics kernel. ; ; Must set an error code: NO (will only be called if page ok) ; SETDRAWPAGE: rts ; ------------------------------------------------------------------------ ; SETCOLOR: Set the drawing color (in A). The new color is already checked ; to be in a valid range (0..maxcolor-1). ; ; Must set an error code: NO (will only be called if color ok) ; SETCOLOR: tax beq @L1 lda #$FF @L1: sta BITMASK rts ; ------------------------------------------------------------------------ ; SETPALETTE: Set the palette (not available with all drivers/hardware). ; A pointer to the palette is passed in ptr1. Must set an error if palettes ; are not supported ; ; Must set an error code: YES ; SETPALETTE: ldy #PALETTESIZE - 1 @L1: lda (ptr1),y ; Copy the palette and #$0F ; Make a valid color sta PALETTE,y dey bpl @L1 ; Get the color entries from the palette lda PALETTE+1 ; Foreground color asl a asl a asl a asl a ora PALETTE ; Background color ; Initialize the color map with the new color settings (it is below the ; Kernal ROM). ldy #$00 ldx #MMU_CFG_RAM0 sei stx MMU_CR @L2: sta CBASE+$0000,y sta CBASE+$0100,y sta CBASE+$0200,y sta CBASE+$02e8,y iny bne @L2 ldx #MMU_CFG_CC65 stx MMU_CR cli ; Done, reset the error code lda #TGI_ERR_OK sta ERROR rts ; ------------------------------------------------------------------------ ; GETPALETTE: Return the current palette in A/X. Even drivers that cannot ; set the palette should return the default palette here, so there's no ; way for this function to fail. ; ; Must set an error code: NO ; GETPALETTE: lda #<PALETTE ldx #>PALETTE rts ; ------------------------------------------------------------------------ ; GETDEFPALETTE: Return the default palette for the driver in A/X. All ; drivers should return something reasonable here, even drivers that don't ; support palettes, otherwise the caller has no way to determine the colors ; of the (not changeable) palette. ; ; Must set an error code: NO (all drivers must have a default palette) ; GETDEFPALETTE: lda #<DEFPALETTE ldx #>DEFPALETTE rts ; ------------------------------------------------------------------------ ; SETPIXEL: Draw one pixel at X1/Y1 = ptr1/ptr2 with the current drawing ; color. The coordinates passed to this function are never outside the ; visible screen area, so there is no need for clipping inside this function. ; ; Must set an error code: NO ; SETPIXEL: jsr CALC ; Calculate coordinates lda #MMU_CFG_RAM0 ; Work behind ROMs sei sta MMU_CR lda (POINT),Y eor BITMASK and BITTAB,X eor (POINT),Y sta (POINT),Y ldx #MMU_CFG_CC65 stx MMU_CR cli rts ; ------------------------------------------------------------------------ ; GETPIXEL: Read the color value of a pixel and return it in A/X. The ; coordinates passed to this function are never outside the visible screen ; area, so there is no need for clipping inside this function. GETPIXEL: jsr CALC ; Calculate coordinates lda #MMU_CFG_RAM0 ; Work behind ROMs sei sta MMU_CR lda (POINT),Y and BITTAB,X beq @L1 lda #$01 ; Foreground color @L1: ldy #MMU_CFG_CC65 sty MMU_CR cli ldx #$00 ; Clear high byte rts ; ------------------------------------------------------------------------ ; LINE: Draw a line from X1/Y1 to X2/Y2, where X1/Y1 = ptr1/ptr2 and ; X2/Y2 = ptr3/ptr4 using the current drawing color. ; ; X1,X2 etc. are set up above (x2=LINNUM in particular) ; Format is LINE x2,y2,x1,y1 ; ; Must set an error code: NO ; LINE: @CHECK: lda X2 ;Make sure x1<x2 sec sbc X1 tax lda X2+1 sbc X1+1 bpl @CONT lda Y2 ;If not, swap P1 and P2 ldy Y1 sta Y1 sty Y2 lda Y2+1 ldy Y1+1 sta Y1+1 sty Y2+1 lda X1 ldy X2 sty X1 sta X2 lda X2+1 ldy X1+1 sta X1+1 sty X2+1 bcc @CHECK @CONT: sta DX+1 stx DX ldx #$C8 ;INY lda Y2 ;Calculate dy sec sbc Y1 tay lda Y2+1 sbc Y1+1 bpl @DYPOS ;Is y2>=y1? lda Y1 ;Otherwise dy=y1-y2 sec sbc Y2 tay ldx #$88 ;DEY @DYPOS: sty DY ; 8-bit DY -- FIX ME? stx YINCDEC stx XINCDEC jsr CALC ; Set up .X, .Y, and POINT lda BITCHUNK,X sta OLDCHUNK sta CHUNK lda #MMU_CFG_RAM0 ; Work behind ROMs sei sta MMU_CR ldx DY cpx DX ;Who's bigger: dy or dx? bcc STEPINX ;If dx, then... lda DX+1 bne STEPINX ; ; Big steps in Y ; ; To simplify my life, just use PLOT to plot points. ; ; No more! ; Added special plotting routine -- cool! ; ; X is now counter, Y is y-coordinate ; ; On entry, X=DY=number of loop iterations, and Y= ; Y1 AND #$07 STEPINY: lda #00 sta OLDCHUNK ;So plotting routine will work right lda CHUNK lsr ;Strip the bit eor CHUNK sta CHUNK txa beq YCONT2 ;If dy=0, it's just a point @CONT: lsr ;Init counter to dy/2 ; ; Main loop ; YLOOP: sta TEMP lda (POINT),y eor BITMASK and CHUNK eor (POINT),y sta (POINT),y YINCDEC: iny ;Advance Y coordinate cpy #8 bcc @CONT ;No prob if Y=0..7 jsr FIXY @CONT: lda TEMP ;Restore A sec sbc DX bcc YFIXX YCONT: dex ;X is counter bne YLOOP YCONT2: lda (POINT),y ;Plot endpoint eor BITMASK and CHUNK eor (POINT),y sta (POINT),y ldx #MMU_CFG_CC65 stx MMU_CR cli rts YFIXX: ;x=x+1 adc DY lsr CHUNK bne YCONT ;If we pass a column boundary... ror CHUNK ;then reset CHUNK to $80 sta TEMP2 lda POINT ;And add 8 to POINT adc #8 sta POINT bcc @CONT inc POINT+1 @CONT: lda TEMP2 dex bne YLOOP beq YCONT2 ; ; Big steps in X direction ; ; On entry, X=DY=number of loop iterations, and Y= ; Y1 AND #$07 .bss COUNTHI: .byte $00 ;Temporary counter ;only used once .code STEPINX: ldx DX lda DX+1 sta COUNTHI cmp #$80 ror ;Need bit for initialization sta Y1 ;High byte of counter txa bne @CONT ;Could be $100 dec COUNTHI @CONT: ror ; ; Main loop ; XLOOP: lsr CHUNK beq XFIXC ;If we pass a column boundary... XCONT1: sbc DY bcc XFIXY ;Time to step in Y? XCONT2: dex bne XLOOP dec COUNTHI ;High bits set? bpl XLOOP lsr CHUNK ;Advance to last point jsr LINEPLOT ;Plot the last chunk ldx #MMU_CFG_CC65 stx MMU_CR cli rts ; ; CHUNK has passed a column, so plot and increment pointer ; and fix up CHUNK, OLDCHUNK. ; XFIXC: sta TEMP jsr LINEPLOT lda #$FF sta CHUNK sta OLDCHUNK lda POINT clc adc #8 sta POINT lda TEMP bcc XCONT1 inc POINT+1 jmp XCONT1 ; ; Check to make sure there isn't a high bit, plot chunk, ; and update Y-coordinate. ; XFIXY: dec Y1 ;Maybe high bit set bpl XCONT2 adc DX sta TEMP lda DX+1 adc #$FF ;Hi byte sta Y1 jsr LINEPLOT ;Plot chunk lda CHUNK sta OLDCHUNK lda TEMP XINCDEC: iny ;Y-coord cpy #8 ;0..7 is ok bcc XCONT2 sta TEMP jsr FIXY lda TEMP jmp XCONT2 ; ; Subroutine to plot chunks/points (to save a little ; room, gray hair, etc.) ; LINEPLOT: ; Plot the line chunk lda (POINT),Y eor BITMASK ora CHUNK and OLDCHUNK eor CHUNK eor (POINT),Y sta (POINT),Y rts ; ; Subroutine to fix up pointer when Y decreases through ; zero or increases through 7. ; FIXY: cpy #255 ;Y=255 or Y=8 beq @DECPTR @INCPTR: ;Add 320 to pointer ldy #0 ;Y increased through 7 lda POINT adc #<320 sta POINT lda POINT+1 adc #>320 sta POINT+1 rts @DECPTR: ;Okay, subtract 320 then ldy #7 ;Y decreased through 0 lda POINT sec sbc #<320 sta POINT lda POINT+1 sbc #>320 sta POINT+1 rts ; ------------------------------------------------------------------------ ; BAR: Draw a filled rectangle with the corners X1/Y1, X2/Y2, where ; X1/Y1 = ptr1/ptr2 and X2/Y2 = ptr3/ptr4 using the current drawing color. ; Contrary to most other functions, the graphics kernel will sort and clip ; the coordinates before calling the driver, so on entry the following ; conditions are valid: ; X1 <= X2 ; Y1 <= Y2 ; (X1 >= 0) && (X1 < XRES) ; (X2 >= 0) && (X2 < XRES) ; (Y1 >= 0) && (Y1 < YRES) ; (Y2 >= 0) && (Y2 < YRES) ; ; Must set an error code: NO ; ; Note: This function needs optimization. It's just a cheap translation of ; the original C wrapper and could be written much smaller (besides that, ; calling LINE is not a good idea either). BAR: lda X2 sta X2SAVE lda X2+1 sta X2SAVE+1 lda Y2 sta Y2SAVE lda X1 sta X1SAVE lda X1+1 sta X1SAVE+1 lda Y1 sta Y1SAVE @L1: sta Y2 lda #>200 sta Y1+1 sta Y2+1 jsr LINE lda Y1SAVE cmp Y2SAVE beq @L4 inc Y1SAVE lda X1SAVE sta X1 lda X1SAVE+1 sta X1+1 lda X2SAVE sta X2 lda X2SAVE+1 sta X2+1 lda Y1SAVE sta Y1 jmp @L1 @L4: rts ; ------------------------------------------------------------------------ ; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in X and Y ; direction is passend in X/Y, the text direction is passed in A. ; ; Must set an error code: NO ; TEXTSTYLE: stx TEXTMAGX sty TEXTMAGY sta TEXTDIR rts ; ------------------------------------------------------------------------ ; OUTTEXT: Output text at X/Y = ptr1/ptr2 using the current color and the ; current text style. The text to output is given as a zero terminated ; string with address in ptr3. ; ; Must set an error code: NO ; OUTTEXT: ; Calculate a pointer to the representation of the character in the ; character ROM ldx #((>(CHARROM + $0800)) >> 3) ldy #0 lda (TEXT),y bmi @L1 ldx #((>(CHARROM + $0000)) >> 3) @L1: stx ptr4+1 asl a rol ptr4+1 asl a rol ptr4+1 asl a rol ptr4+1 sta ptr4 rts ; ------------------------------------------------------------------------ ; Calculate all variables to plot the pixel at X1/Y1. CALC: lda Y1 sta TEMP2 and #7 tay lda Y1+1 lsr ; Neg is possible ror TEMP2 lsr ror TEMP2 lsr ror TEMP2 lda #00 sta POINT lda TEMP2 cmp #$80 ror ror POINT cmp #$80 ror ror POINT ; row*64 adc TEMP2 ; +row*256 clc adc #>VBASE ; +bitmap base sta POINT+1 lda X1 tax and #$F8 clc adc POINT ; +(X AND #$F8) sta POINT lda X1+1 adc POINT+1 sta POINT+1 txa and #7 tax rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/tgi/c128-vdc.s����������������������������������������������������������������0000664�0000000�0000000�00000050775�13473601511�0016354�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Graphics driver for the 640x200x2 mode on the C128 VDC ; Maciej 'YTM/Elysium' Witkowiak <ytm@elysium.pl> ; 23.12.2002 ; 2004-04-04, Greg King ; ; NOTES: ; For any smart monkey that will try to optimize this: PLEASE do tests on ; real VDC, not only VICE. ; ; Only DONE routine contains C128-mode specific stuff, everything else will ; work in C64-mode of C128 (C64 needs full VDC init then). ; ; With special initialization and CALC we can get 320x200 double-pixel mode. ; ; Color translation values for BROWN and GRAY3 are obviously wrong, they ; could be replaced by equiv. of ORANGE and GRAY2 but this would give only ; 14 of 16 colors available. ; ; Register 25 ($19) is said to require different value for VDC v1, but I ; couldn't find what it should be. .include "zeropage.inc" .include "tgi-kernel.inc" .include "tgi-error.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Constants VDC_ADDR_REG = $D600 ; VDC address VDC_DATA_REG = $D601 ; VDC data VDC_DSP_HI = 12 ; registers used VDC_DSP_LO = 13 VDC_DATA_HI = 18 VDC_DATA_LO = 19 VDC_VSCROLL = 24 VDC_HSCROLL = 25 VDC_COLORS = 26 VDC_CSET = 28 VDC_COUNT = 30 VDC_DATA = 31 ; ------------------------------------------------------------------------ ; Header. Includes jump table and constants. module_header _c128_vdc_tgi ; First part of the header is a structure that has a magic and defines the ; capabilities of the driver .byte $74, $67, $69 ; "tgi" .byte TGI_API_VERSION ; TGI API version number .addr $0000 ; Library reference xres: .word 640 ; X resolution yres: .word 200 ; Y resolution .byte 2 ; Number of drawing colors pages: .byte 1 ; Number of screens available .byte 8 ; System font X size .byte 8 ; System font Y size .word $006A ; Aspect ratio (based on 4/3 display) .byte 0 ; TGI driver flags ; Next comes the jump table. Currently all entries must be valid and may point ; to an RTS for test versions (function not implemented). .addr INSTALL .addr UNINSTALL .addr INIT .addr DONE .addr GETERROR .addr CONTROL .addr CLEAR .addr SETVIEWPAGE .addr SETDRAWPAGE .addr SETCOLOR .addr SETPALETTE .addr GETPALETTE .addr GETDEFPALETTE .addr SETPIXEL .addr GETPIXEL .addr LINE .addr BAR .addr TEXTSTYLE .addr OUTTEXT ; ------------------------------------------------------------------------ ; Data. ; Variables mapped to the zero page segment variables. Some of these are ; used for passing parameters to the driver. X1 = ptr1 Y1 = ptr2 X2 = ptr3 Y2 = ptr4 ADDR = tmp1 TEMP = tmp3 TEMP2 = tmp4 ; HORLINE TEMP3 = sreg ; HORLINE ; Absolute variables used in the code .bss SCRBASE: .res 1 ; High byte of screen base ERROR: .res 1 ; Error code PALETTE: .res 2 ; The current palette BITMASK: .res 1 ; $00 = clear, $FF = set pixels OLDCOLOR: .res 1 ; colors before entering gfx mode ; Text output stuff TEXTMAGX: .res 1 TEXTMAGY: .res 1 TEXTDIR: .res 1 ; Constants and tables .rodata DEFPALETTE: .byte $00, $0f ; White on black PALETTESIZE = * - DEFPALETTE BITTAB: .byte $80,$40,$20,$10,$08,$04,$02,$01 BITMASKL: .byte %11111111, %01111111, %00111111, %00011111 .byte %00001111, %00000111, %00000011, %00000001 BITMASKR: .byte %10000000, %11000000, %11100000, %11110000 .byte %11111000, %11111100, %11111110, %11111111 ; color translation table (indexed by VIC color) COLTRANS: .byte $00, $0f, $08, $06, $0a, $04, $02, $0c .byte $0d, $0b, $09, $01, $0e, $05, $03, $07 ; colors BROWN and GRAY3 are wrong ; VDC initialization table (reg),(val),...,$ff InitVDCTab: .byte VDC_DSP_HI, 0 ; viewpage 0 as default .byte VDC_DSP_LO, 0 .byte VDC_HSCROLL, $87 .byte $ff SCN80CLR: .byte 27,88,147,27,88,0 .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. May ; initialize anything that has to be done just once. Is probably empty ; most of the time. ; ; Must set an error code: NO ; INSTALL: ; check for VDC version and update register $19 value ; check for VDC ram size and update number of available screens ldx #VDC_CSET ; determine size of RAM... jsr VDCReadReg sta tmp1 ora #%00010000 jsr VDCWriteReg ; turn on 64k jsr settestadr1 ; save original value of test byte jsr VDCReadByte sta tmp2 lda #$55 ; write $55 here ldy #ptr1 jsr test64k ; read it here and there lda #$aa ; write $aa here ldy #ptr2 jsr test64k ; read it here and there jsr settestadr1 lda tmp2 jsr VDCWriteByte ; restore original value of test byte lda ptr1 ; do bytes match? cmp ptr1+1 bne @have64k lda ptr2 cmp ptr2+1 bne @have64k ldx #VDC_CSET lda tmp1 jsr VDCWriteReg ; restore 16/64k flag jmp @endok ; and leave default values for 16k @have64k: lda #4 sta pages @endok: lda #0 sta SCRBASE ; draw page 0 as default rts test64k: sta tmp1 sty ptr3 lda #0 sta ptr3+1 jsr settestadr1 lda tmp1 jsr VDCWriteByte ; write $55 jsr settestadr1 jsr VDCReadByte ; read here pha jsr settestadr2 jsr VDCReadByte ; and there ldy #1 sta (ptr3),y pla dey sta (ptr3),y rts settestadr1: ldy #$02 ; test page 2 (here) .byte $2c settestadr2: ldy #$42 ; or page 64+2 (there) lda #0 jmp VDCSetSourceAddr ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. May ; clean up anything done by INSTALL but is probably empty most of the time. ; ; Must set an error code: NO ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; INIT: Changes an already installed device from text mode to graphics ; mode. ; Note that INIT/DONE may be called multiple times while the driver ; is loaded, while INSTALL is only called once, so any code that is needed ; to initializes variables and so on must go here. Setting palette and ; clearing the screen is not needed because this is called by the graphics ; kernel later. ; The graphics kernel will never call INIT when a graphics mode is already ; active, so there is no need to protect against that. ; ; Must set an error code: YES ; INIT: ; Initialize variables @L1: ldx #$FF stx BITMASK ; Remeber current color value ldx #VDC_COLORS jsr VDCReadReg sta OLDCOLOR ; Switch into graphics mode (set view page 0) ldy #0 @L2: ldx InitVDCTab,y bmi @L3 iny lda InitVDCTab,y jsr VDCWriteReg iny bne @L2 @L3: ; Done, reset the error code lda #TGI_ERR_OK sta ERROR rts ; ------------------------------------------------------------------------ ; DONE: Will be called to switch the graphics device back into text mode. ; The graphics kernel will never call DONE when no graphics mode is active, ; so there is no need to protect against that. ; ; Must set an error code: NO ; DONE: ; This part is C128-mode specific jsr $e179 ; reload character set and setup VDC jsr $ff62 lda $d7 ; in 80-columns? bne @L01 @L0: lda SCN80CLR,y beq @L1 jsr $ffd2 ; print \xe,clr,\xe iny bne @L0 @L01: lda #147 jsr $ffd2 ; print clr @L1: lda #0 ; restore view page ldx #VDC_DSP_HI jsr VDCWriteReg lda OLDCOLOR ldx #VDC_COLORS jsr VDCWriteReg ; restore color (background) lda #$47 ldx #VDC_HSCROLL jmp VDCWriteReg ; switch to text screen ; ------------------------------------------------------------------------ ; GETERROR: Return the error code in A and clear it. GETERROR: ldx #TGI_ERR_OK lda ERROR stx ERROR rts ; ------------------------------------------------------------------------ ; CONTROL: Platform/driver specific entry point. ; ; Must set an error code: YES ; CONTROL: lda #TGI_ERR_INV_FUNC sta ERROR rts ; ------------------------------------------------------------------------ ; CLEAR: Clears the screen. ; ; Must set an error code: NO ; CLEAR: lda #0 ldy SCRBASE jsr VDCSetSourceAddr lda #0 ldx #VDC_VSCROLL jsr VDCWriteReg ; set fill mode lda #0 jsr VDCWriteByte ; put 1rst byte (fill value) ldy #62 ; 62 times lda #0 ; 256 bytes ldx #VDC_COUNT @L1: jsr VDCWriteReg dey bne @L1 lda #127 jmp VDCWriteReg ; 1+62*256+127=16000=(640*256)/8 ; ------------------------------------------------------------------------ ; SETVIEWPAGE: Set the visible page. Called with the new page in A (0..n). ; The page number is already checked to be valid by the graphics kernel. ; ; Must set an error code: NO (will only be called if page ok) ; SETVIEWPAGE: clc ror ror ror ldx #VDC_DSP_HI jmp VDCWriteReg ; ------------------------------------------------------------------------ ; SETDRAWPAGE: Set the drawable page. Called with the new page in A (0..n). ; The page number is already checked to be valid by the graphics kernel. ; ; Must set an error code: NO (will only be called if page ok) ; SETDRAWPAGE: clc ror ror ror sta SCRBASE rts ; ------------------------------------------------------------------------ ; SETCOLOR: Set the drawing color (in A). The new color is already checked ; to be in a valid range (0..maxcolor-1). ; ; Must set an error code: NO (will only be called if color ok) ; SETCOLOR: tax beq @L1 lda #$FF @L1: sta BITMASK rts ; ------------------------------------------------------------------------ ; SETPALETTE: Set the palette (not available with all drivers/hardware). ; A pointer to the palette is passed in ptr1. Must set an error if palettes ; are not supported ; ; Must set an error code: YES ; SETPALETTE: ldy #PALETTESIZE - 1 @L1: lda (ptr1),y ; Copy the palette and #$0F ; Make a valid color sta PALETTE,y dey bpl @L1 ; Get the color entries from the palette ldy PALETTE+1 ; Foreground color lda COLTRANS,y asl a asl a asl a asl a ldy PALETTE ; Background color ora COLTRANS,y ldx #VDC_COLORS jsr VDCWriteReg lda #TGI_ERR_OK ; Clear error code sta ERROR rts ; ------------------------------------------------------------------------ ; GETPALETTE: Return the current palette in A/X. Even drivers that cannot ; set the palette should return the default palette here, so there's no ; way for this function to fail. ; ; Must set an error code: NO ; GETPALETTE: lda #<PALETTE ldx #>PALETTE rts ; ------------------------------------------------------------------------ ; GETDEFPALETTE: Return the default palette for the driver in A/X. All ; drivers should return something reasonable here, even drivers that don't ; support palettes, otherwise the caller has no way to determine the colors ; of the (not changeable) palette. ; ; Must set an error code: NO (all drivers must have a default palette) ; GETDEFPALETTE: lda #<DEFPALETTE ldx #>DEFPALETTE rts ; ------------------------------------------------------------------------ ; SETPIXEL: Draw one pixel at X1/Y1 = ptr1/ptr2 with the current drawing ; color. The coordinates passed to this function are never outside the ; visible screen area, so there is no need for clipping inside this function. ; ; Must set an error code: NO ; SETPIXEL: jsr CALC ; Calculate coordinates stx TEMP lda ADDR ldy ADDR+1 jsr VDCSetSourceAddr jsr VDCReadByte ldx TEMP sta TEMP eor BITMASK and BITTAB,X eor TEMP pha lda ADDR ldy ADDR+1 jsr VDCSetSourceAddr pla jsr VDCWriteByte @L9: rts ; ------------------------------------------------------------------------ ; GETPIXEL: Read the color value of a pixel and return it in A/X. The ; coordinates passed to this function are never outside the visible screen ; area, so there is no need for clipping inside this function. GETPIXEL: jsr CALC ; Calculate coordinates stx TEMP ; preserve X lda ADDR ldy ADDR+1 jsr VDCSetSourceAddr jsr VDCReadByte ldx TEMP ldy #$00 and BITTAB,X beq @L1 iny @L1: tya ; Get color value into A ldx #$00 ; Clear high byte rts ; ------------------------------------------------------------------------ ; BAR: Draw a filled rectangle with the corners X1/Y1, X2/Y2, where ; X1/Y1 = ptr1/ptr2 and X2/Y2 = ptr3/ptr4 using the current drawing color. ; Contrary to most other functions, the graphics kernel will sort and clip ; the coordinates before calling the driver, so on entry the following ; conditions are valid: ; X1 <= X2 ; Y1 <= Y2 ; (X1 >= 0) && (X1 < XRES) ; (X2 >= 0) && (X2 < XRES) ; (Y1 >= 0) && (Y1 < YRES) ; (Y2 >= 0) && (Y2 < YRES) ; ; Must set an error code: NO ; BAR: inc Y2 bne HORLINE inc Y2+1 ; Original code for a horizontal line HORLINE: lda X1 pha lda X1+1 pha jsr CALC ; get data for LEFT lda BITMASKL,x ; remember left address and bitmask pha lda ADDR pha lda ADDR+1 pha lda X2 sta X1 lda X2+1 sta X1+1 jsr CALC ; get data for RIGHT lda BITMASKR,x sta TEMP3 pla ; recall data for LEFT sta X1+1 pla sta X1 ; put left address into X1 pla cmp #%11111111 ; if left bit <> 0 beq @L1 sta TEMP2 ; do left byte only... lda X1 ldy X1+1 jsr VDCSetSourceAddr jsr VDCReadByte sta TEMP eor BITMASK and TEMP2 eor TEMP pha lda X1 ldy X1+1 jsr VDCSetSourceAddr pla jsr VDCWriteByte inc X1 ; ... and proceed bne @L1 inc X1+1 ; do right byte (if Y2=0 ++ADDR and skip) @L1: lda TEMP3 cmp #%11111111 ; if right bit <> 7 bne @L11 inc ADDR ; right bit = 7 - the next one is the last bne @L10 inc ADDR+1 @L10: bne @L2 @L11: lda ADDR ; do right byte only... ldy ADDR+1 jsr VDCSetSourceAddr jsr VDCReadByte sta TEMP eor BITMASK and TEMP3 eor TEMP pha lda ADDR ldy ADDR+1 jsr VDCSetSourceAddr pla jsr VDCWriteByte @L2: ; do the fill in the middle lda ADDR ; calculate offset in full bytes sec sbc X1 beq @L3 ; if equal - there are no more bytes sta ADDR lda X1 ; setup for the left side ldy X1+1 jsr VDCSetSourceAddr lda BITMASK ; get color jsr VDCWriteByte ; put 1st value ldx ADDR dex beq @L3 ; 1 byte already written stx ADDR ; if there are more bytes - fill them... ldx #VDC_VSCROLL lda #0 jsr VDCWriteReg ; setup for fill ldx #VDC_COUNT lda ADDR jsr VDCWriteReg ; ... fill them NOW! @L3: pla sta X1+1 pla sta X1 ; End of horizontal line code inc Y1 bne @L4 inc Y1+1 @L4: lda Y1 cmp Y2 bne @L5 lda Y1+1 cmp Y2+1 bne @L5 rts @L5: jmp HORLINE ; ------------------------------------------------------------------------ ; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in X and Y ; direction is passend in X/Y, the text direction is passed in A. ; ; Must set an error code: NO ; TEXTSTYLE: stx TEXTMAGX sty TEXTMAGY sta TEXTDIR rts ; ------------------------------------------------------------------------ ; OUTTEXT: Output text at X/Y = ptr1/ptr2 using the current color and the ; current text style. The text to output is given as a zero terminated ; string with address in ptr3. ; ; Must set an error code: NO ; OUTTEXT: rts ; ------------------------------------------------------------------------ ; Calculate all variables to plot the pixel at X1/Y1. ;------------------------ ;< X1,Y1 - pixel ;> ADDR - address of card ;> X - bit number (X1 & 7) CALC: lda Y1+1 sta ADDR+1 lda Y1 asl rol ADDR+1 asl rol ADDR+1 ; Y*4 clc adc Y1 sta ADDR lda Y1+1 adc ADDR+1 sta ADDR+1 ; Y*4+Y=Y*5 lda ADDR asl rol ADDR+1 asl rol ADDR+1 asl rol ADDR+1 asl rol ADDR+1 sta ADDR ; Y*5*16=Y*80 lda X1+1 sta TEMP lda X1 lsr TEMP ror lsr TEMP ror lsr TEMP ror clc adc ADDR sta ADDR lda ADDR+1 ; ADDR = Y*80+x/8 adc TEMP sta ADDR+1 lda ADDR+1 adc SCRBASE sta ADDR+1 lda X1 and #7 tax rts ;------------- ; VDC helpers VDCSetSourceAddr: pha tya ldx #VDC_DATA_HI jsr VDCWriteReg pla ldx #VDC_DATA_LO bne VDCWriteReg VDCReadByte: ldx #VDC_DATA VDCReadReg: stx VDC_ADDR_REG @L0: bit VDC_ADDR_REG bpl @L0 lda VDC_DATA_REG rts VDCWriteByte: ldx #VDC_DATA VDCWriteReg: stx VDC_ADDR_REG @L0: bit VDC_ADDR_REG bpl @L0 sta VDC_DATA_REG rts ; ------------------------------------------------------------------------ .include "../../tgi/tgidrv_line.inc" ���cc65-2.18/libsrc/c128/tgi/c128-vdc2.s���������������������������������������������������������������0000664�0000000�0000000�00000051730�13473601511�0016426�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Graphics driver for the 640x480x2 mode on the C128 VDC 64k ; (values for this mode based on Fred Bowen's document) ; Maciej 'YTM/Elysium' Witkowiak <ytm@elysium.pl> ; 23.12.2002 ; 2004-04-04, Greg King ; ; NOTES: ; For any smart monkey that will try to optimize this: PLEASE do tests on ; real VDC, not only VICE. ; ; Only DONE routine contains C128-mode specific stuff, everything else will ; work in C64-mode of C128 (C64 needs full VDC init then). ; ; With special initialization and CALC we can get 320x200 double-pixel mode. ; ; Color translation values for BROWN and GRAY3 are obviously wrong, they ; could be replaced by equiv. of ORANGE and GRAY2 but this would give only ; 14 of 16 colors available. ; ; Register 25 ($19) is said to require different value for VDC v1, but I ; couldn't find what it should be. .include "zeropage.inc" .include "tgi-kernel.inc" .include "tgi-error.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Constants VDC_ADDR_REG = $D600 ; VDC address VDC_DATA_REG = $D601 ; VDC data VDC_DSP_HI = 12 ; registers used VDC_DSP_LO = 13 VDC_DATA_HI = 18 VDC_DATA_LO = 19 VDC_VSCROLL = 24 VDC_HSCROLL = 25 VDC_COLORS = 26 VDC_CSET = 28 VDC_COUNT = 30 VDC_DATA = 31 ; ------------------------------------------------------------------------ ; Header. Includes jump table and constants. module_header _c128_vdc2_tgi ; First part of the header is a structure that has a magic and defines the ; capabilities of the driver .byte $74, $67, $69 ; "tgi" .byte TGI_API_VERSION ; TGI API version number .addr $0000 ; Library reference xres: .word 640 ; X resolution yres: .word 480 ; Y resolution .byte 2 ; Number of drawing colors pages: .byte 0 ; Number of screens available .byte 8 ; System font X size .byte 8 ; System font Y size .word $0100 ; Aspect ratio (based on 4/3 display) .byte 0 ; TGI driver flags ; Next comes the jump table. Currently all entries must be valid and may point ; to an RTS for test versions (function not implemented). .addr INSTALL .addr UNINSTALL .addr INIT .addr DONE .addr GETERROR .addr CONTROL .addr CLEAR .addr SETVIEWPAGE .addr SETDRAWPAGE .addr SETCOLOR .addr SETPALETTE .addr GETPALETTE .addr GETDEFPALETTE .addr SETPIXEL .addr GETPIXEL .addr LINE .addr BAR .addr TEXTSTYLE .addr OUTTEXT ; ------------------------------------------------------------------------ ; Data. ; Variables mapped to the zero page segment variables. Some of these are ; used for passing parameters to the driver. X1 = ptr1 Y1 = ptr2 X2 = ptr3 Y2 = ptr4 ADDR = tmp1 TEMP = tmp3 TEMP2 = tmp4 ; HORLINE TEMP3 = sreg ; HORLINE ; Absolute variables used in the code .bss ERROR: .res 1 ; Error code PALETTE: .res 2 ; The current palette BITMASK: .res 1 ; $00 = clear, $FF = set pixels OLDCOLOR: .res 1 ; colors before entering gfx mode ; Text output stuff TEXTMAGX: .res 1 TEXTMAGY: .res 1 TEXTDIR: .res 1 ; Constants and tables .rodata DEFPALETTE: .byte $00, $0f ; White on black PALETTESIZE = * - DEFPALETTE BITTAB: .byte $80,$40,$20,$10,$08,$04,$02,$01 BITMASKL: .byte %11111111, %01111111, %00111111, %00011111 .byte %00001111, %00000111, %00000011, %00000001 BITMASKR: .byte %10000000, %11000000, %11100000, %11110000 .byte %11111000, %11111100, %11111110, %11111111 ; color translation table (indexed by VIC color) COLTRANS: .byte $00, $0f, $08, $06, $0a, $04, $02, $0c .byte $0d, $0b, $09, $01, $0e, $05, $03, $07 ; colors BROWN and GRAY3 are wrong ; VDC initialization table (reg),(val),...,$ff InitVDCTab: .byte VDC_DSP_HI, 0 ; viewpage 0 as default .byte VDC_DSP_LO, 0 .byte VDC_HSCROLL, $87 .byte 2, $66 .byte 4, $4c .byte 5, $06 .byte 6, $4c .byte 7, $47 .byte 8, $03 .byte 9, $06 .byte 27, $00 .byte $ff SCN80CLR: .byte 27,88,147,27,88,0 .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. May ; initialize anything that has to be done just once. Is probably empty ; most of the time. ; ; Must set an error code: NO ; INSTALL: ; check for VDC version and update register $19 value ; check for VDC ram size and update number of available screens ldx #VDC_CSET ; determine size of RAM... jsr VDCReadReg sta tmp1 ora #%00010000 jsr VDCWriteReg ; turn on 64k jsr settestadr1 ; save original value of test byte jsr VDCReadByte sta tmp2 lda #$55 ; write $55 here ldy #ptr1 jsr test64k ; read it here and there lda #$aa ; write $aa here ldy #ptr2 jsr test64k ; read it here and there jsr settestadr1 lda tmp2 jsr VDCWriteByte ; restore original value of test byte lda ptr1 ; do bytes match? cmp ptr1+1 bne @have64k lda ptr2 cmp ptr2+1 bne @have64k ldx #VDC_CSET lda tmp1 jsr VDCWriteReg ; restore 16/64k flag jmp @endok ; and leave default values for 16k @have64k: lda #1 sta pages @endok: rts test64k: sta tmp1 sty ptr3 lda #0 sta ptr3+1 jsr settestadr1 lda tmp1 jsr VDCWriteByte ; write $55 jsr settestadr1 jsr VDCReadByte ; read here pha jsr settestadr2 jsr VDCReadByte ; and there ldy #1 sta (ptr3),y pla dey sta (ptr3),y rts settestadr1: ldy #$02 ; test page 2 (here) .byte $2c settestadr2: ldy #$42 ; or page 64+2 (there) lda #0 jmp VDCSetSourceAddr ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. May ; clean up anything done by INSTALL but is probably empty most of the time. ; ; Must set an error code: NO ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; INIT: Changes an already installed device from text mode to graphics ; mode. ; Note that INIT/DONE may be called multiple times while the driver ; is loaded, while INSTALL is only called once, so any code that is needed ; to initializes variables and so on must go here. Setting palette and ; clearing the screen is not needed because this is called by the graphics ; kernel later. ; The graphics kernel will never call INIT when a graphics mode is already ; active, so there is no need to protect against that. ; ; Must set an error code: YES ; INIT: lda pages ; is there enough memory? bne @L1 ; Jump if there is one screen lda #TGI_ERR_INV_MODE ; Error bne @L9 ; Initialize variables @L1: ldx #$FF stx BITMASK ; Remeber current color value ldx #VDC_COLORS jsr VDCReadReg sta OLDCOLOR ; Switch into graphics mode (set view page 0) ldy #0 @L2: ldx InitVDCTab,y bmi @L3 iny lda InitVDCTab,y jsr VDCWriteReg iny bne @L2 @L3: ; Done, reset the error code lda #TGI_ERR_OK @L9: sta ERROR rts ; ------------------------------------------------------------------------ ; DONE: Will be called to switch the graphics device back into text mode. ; The graphics kernel will never call DONE when no graphics mode is active, ; so there is no need to protect against that. ; ; Must set an error code: NO ; DONE: ; This part is C128-mode specific jsr $e179 ; reload character set and setup VDC jsr $ff62 lda $d7 ; in 80-columns? bne @L01 @L0: lda SCN80CLR,y beq @L1 jsr $ffd2 ; print \xe,clr,\xe iny bne @L0 @L01: lda #147 jsr $ffd2 ; print clr @L1: lda #0 ; restore view page ldx #VDC_DSP_HI jsr VDCWriteReg lda OLDCOLOR ldx #VDC_COLORS jsr VDCWriteReg ; restore color (background) lda #$47 ldx #VDC_HSCROLL jmp VDCWriteReg ; switch to text screen ; ------------------------------------------------------------------------ ; GETERROR: Return the error code in A and clear it. GETERROR: ldx #TGI_ERR_OK lda ERROR stx ERROR rts ; ------------------------------------------------------------------------ ; CONTROL: Platform/driver specific entry point. ; ; Must set an error code: YES ; CONTROL: lda #TGI_ERR_INV_FUNC sta ERROR rts ; ------------------------------------------------------------------------ ; CLEAR: Clears the screen. ; ; Must set an error code: NO ; CLEAR: lda #0 tay jsr VDCSetSourceAddr lda #0 ldx #VDC_VSCROLL jsr VDCWriteReg ; set fill mode lda #0 jsr VDCWriteByte ; put 1rst byte (fill value) ldy #159 ; 159 times lda #0 ; 256 bytes ldx #VDC_COUNT @L1: jsr VDCWriteReg dey bne @L1 rts ; ------------------------------------------------------------------------ ; SETVIEWPAGE: Set the visible page. Called with the new page in A (0..n). ; The page number is already checked to be valid by the graphics kernel. ; ; Must set an error code: NO (will only be called if page ok) ; SETVIEWPAGE: rts ; ------------------------------------------------------------------------ ; SETDRAWPAGE: Set the drawable page. Called with the new page in A (0..n). ; The page number is already checked to be valid by the graphics kernel. ; ; Must set an error code: NO (will only be called if page ok) ; SETDRAWPAGE: rts ; ------------------------------------------------------------------------ ; SETCOLOR: Set the drawing color (in A). The new color is already checked ; to be in a valid range (0..maxcolor-1). ; ; Must set an error code: NO (will only be called if color ok) ; SETCOLOR: tax beq @L1 lda #$FF @L1: sta BITMASK rts ; ------------------------------------------------------------------------ ; SETPALETTE: Set the palette (not available with all drivers/hardware). ; A pointer to the palette is passed in ptr1. Must set an error if palettes ; are not supported ; ; Must set an error code: YES ; SETPALETTE: ldy #PALETTESIZE - 1 @L1: lda (ptr1),y ; Copy the palette and #$0F ; Make a valid color sta PALETTE,y dey bpl @L1 ; Get the color entries from the palette ldy PALETTE+1 ; Foreground color lda COLTRANS,y asl a asl a asl a asl a ldy PALETTE ; Background color ora COLTRANS,y ldx #VDC_COLORS jsr VDCWriteReg lda #TGI_ERR_OK ; Clear error code sta ERROR rts ; ------------------------------------------------------------------------ ; GETPALETTE: Return the current palette in A/X. Even drivers that cannot ; set the palette should return the default palette here, so there's no ; way for this function to fail. ; ; Must set an error code: NO ; GETPALETTE: lda #<PALETTE ldx #>PALETTE rts ; ------------------------------------------------------------------------ ; GETDEFPALETTE: Return the default palette for the driver in A/X. All ; drivers should return something reasonable here, even drivers that don't ; support palettes, otherwise the caller has no way to determine the colors ; of the (not changeable) palette. ; ; Must set an error code: NO (all drivers must have a default palette) ; GETDEFPALETTE: lda #<DEFPALETTE ldx #>DEFPALETTE rts ; ------------------------------------------------------------------------ ; SETPIXEL: Draw one pixel at X1/Y1 = ptr1/ptr2 with the current drawing ; color. The coordinates passed to this function are never outside the ; visible screen area, so there is no need for clipping inside this function. ; ; Must set an error code: NO ; SETPIXEL: jsr CALC ; Calculate coordinates stx TEMP lda ADDR ldy ADDR+1 jsr VDCSetSourceAddr jsr VDCReadByte ldx TEMP sta TEMP eor BITMASK and BITTAB,X eor TEMP pha lda ADDR ldy ADDR+1 jsr VDCSetSourceAddr pla jsr VDCWriteByte @L9: rts ; ------------------------------------------------------------------------ ; GETPIXEL: Read the color value of a pixel and return it in A/X. The ; coordinates passed to this function are never outside the visible screen ; area, so there is no need for clipping inside this function. GETPIXEL: jsr CALC ; Calculate coordinates stx TEMP ; preserve X lda ADDR ldy ADDR+1 jsr VDCSetSourceAddr jsr VDCReadByte ldx TEMP ldy #$00 and BITTAB,X beq @L1 iny @L1: tya ; Get color value into A ldx #$00 ; Clear high byte rts ; ------------------------------------------------------------------------ ; BAR: Draw a filled rectangle with the corners X1/Y1, X2/Y2, where ; X1/Y1 = ptr1/ptr2 and X2/Y2 = ptr3/ptr4 using the current drawing color. ; Contrary to most other functions, the graphics kernel will sort and clip ; the coordinates before calling the driver, so on entry the following ; conditions are valid: ; X1 <= X2 ; Y1 <= Y2 ; (X1 >= 0) && (X1 < XRES) ; (X2 >= 0) && (X2 < XRES) ; (Y1 >= 0) && (Y1 < YRES) ; (Y2 >= 0) && (Y2 < YRES) ; ; Must set an error code: NO ; BAR: inc Y2 bne HORLINE inc Y2+1 ; Original code for a horizontal line HORLINE: lda X1 pha lda X1+1 pha jsr CALC ; get data for LEFT lda BITMASKL,x ; remember left address and bitmask pha lda ADDR pha lda ADDR+1 pha lda X2 sta X1 lda X2+1 sta X1+1 jsr CALC ; get data for RIGHT lda BITMASKR,x sta TEMP3 pla ; recall data for LEFT sta X1+1 pla sta X1 ; put left address into X1 pla cmp #%11111111 ; if left bit <> 0 beq @L1 sta TEMP2 ; do left byte only... lda X1 ldy X1+1 jsr VDCSetSourceAddr jsr VDCReadByte sta TEMP eor BITMASK and TEMP2 eor TEMP pha lda X1 ldy X1+1 jsr VDCSetSourceAddr pla jsr VDCWriteByte inc X1 ; ... and proceed bne @L1 inc X1+1 ; do right byte (if Y2=0 ++ADDR and skip) @L1: lda TEMP3 cmp #%11111111 ; if right bit <> 7 bne @L11 inc ADDR ; right bit = 7 - the next one is the last bne @L10 inc ADDR+1 @L10: bne @L2 @L11: lda ADDR ; do right byte only... ldy ADDR+1 jsr VDCSetSourceAddr jsr VDCReadByte sta TEMP eor BITMASK and TEMP3 eor TEMP pha lda ADDR ldy ADDR+1 jsr VDCSetSourceAddr pla jsr VDCWriteByte @L2: ; do the fill in the middle lda ADDR ; calculate offset in full bytes sec sbc X1 beq @L3 ; if equal - there are no more bytes sta ADDR lda X1 ; setup for the left side ldy X1+1 jsr VDCSetSourceAddr lda BITMASK ; get color jsr VDCWriteByte ; put 1st value ldx ADDR dex beq @L3 ; 1 byte already written stx ADDR ; if there are more bytes - fill them... ldx #VDC_VSCROLL lda #0 jsr VDCWriteReg ; setup for fill ldx #VDC_COUNT lda ADDR jsr VDCWriteReg ; ... fill them NOW! @L3: pla sta X1+1 pla sta X1 ; End of horizontal line code inc Y1 bne @L4 inc Y1+1 @L4: lda Y1 cmp Y2 bne @L5 lda Y1+1 cmp Y2+1 bne @L5 rts @L5: jmp HORLINE ; ------------------------------------------------------------------------ ; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in X and Y ; direction is passend in X/Y, the text direction is passed in A. ; ; Must set an error code: NO ; TEXTSTYLE: stx TEXTMAGX sty TEXTMAGY sta TEXTDIR rts ; ------------------------------------------------------------------------ ; OUTTEXT: Output text at X/Y = ptr1/ptr2 using the current color and the ; current text style. The text to output is given as a zero terminated ; string with address in ptr3. ; ; Must set an error code: NO ; OUTTEXT: rts ; ------------------------------------------------------------------------ ; Calculate all variables to plot the pixel at X1/Y1. ;------------------------ ;< X1,Y1 - pixel ;> ADDR - address of card ;> X - bit number (X1 & 7) CALC: lda Y1 pha lda Y1+1 pha lsr ror Y1 ; Y=Y/2 sta Y1+1 sta ADDR+1 lda Y1 asl rol ADDR+1 asl rol ADDR+1 ; Y*4 clc adc Y1 sta ADDR lda Y1+1 adc ADDR+1 sta ADDR+1 ; Y*4+Y=Y*5 lda ADDR asl rol ADDR+1 asl rol ADDR+1 asl rol ADDR+1 asl rol ADDR+1 sta ADDR ; Y*5*16=Y*80 lda X1+1 sta TEMP lda X1 lsr TEMP ror lsr TEMP ror lsr TEMP ror clc adc ADDR sta ADDR lda ADDR+1 ; ADDR = Y*80+x/8 adc TEMP sta ADDR+1 pla sta Y1+1 pla sta Y1 and #1 beq @even ; even line - no offset lda ADDR clc adc #<21360 sta ADDR lda ADDR+1 adc #>21360 sta ADDR+1 ; odd lines are 21360 bytes farther @even: lda X1 and #7 tax rts ;------------- ; VDC helpers VDCSetSourceAddr: pha tya ldx #VDC_DATA_HI jsr VDCWriteReg pla ldx #VDC_DATA_LO bne VDCWriteReg VDCReadByte: ldx #VDC_DATA VDCReadReg: stx VDC_ADDR_REG @L0: bit VDC_ADDR_REG bpl @L0 lda VDC_DATA_REG rts VDCWriteByte: ldx #VDC_DATA VDCWriteReg: stx VDC_ADDR_REG @L0: bit VDC_ADDR_REG bpl @L0 sta VDC_DATA_REG rts ; ------------------------------------------------------------------------ .include "../../tgi/tgidrv_line.inc" ����������������������������������������cc65-2.18/libsrc/c128/tgi_stat_stddrv.s�������������������������������������������������������������0000664�0000000�0000000�00000000343�13473601511�0017530�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Address of the static standard tgi driver ; ; Oliver Schmidt, 2012-11-01 ; ; const void tgi_static_stddrv[]; ; .export _tgi_static_stddrv .import _c128_vdc_tgi .rodata _tgi_static_stddrv := _c128_vdc_tgi ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/tgi_stddrv.s������������������������������������������������������������������0000664�0000000�0000000�00000000260�13473601511�0016473�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Name of the standard tgi driver ; ; Oliver Schmidt, 2011-05-02 ; ; const char tgi_stddrv[]; ; .export _tgi_stddrv .rodata _tgi_stddrv: .asciiz "c128-vdc.tgi" ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/tmcommon.s��������������������������������������������������������������������0000664�0000000�0000000�00000003206�13473601511�0016156�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 16.8.2018 ; ; Common stuff for the clock routines ; .include "c128.inc" .include "get_tv.inc" .export TM, load_tenth .constructor inittime .importzp sreg .import _get_tv ;---------------------------------------------------------------------------- .code .proc load_tenth lda #<(100 * 1000 * 1000 / $10000) ldx #>(100 * 1000 * 1000 / $10000) sta sreg stx sreg+1 lda #<(100 * 1000 * 1000) ldx #>(100 * 1000 * 1000) rts .endproc ;---------------------------------------------------------------------------- ; 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 "ONCE" .proc inittime lda CIA1_TOD10 sta CIA1_TOD10 jsr _get_tv cmp #TV::PAL bne @60Hz lda CIA1_CRA ora #$80 sta CIA1_CRA @60Hz: rts .endproc ;---------------------------------------------------------------------------- ; TM struct with date set to 1970-01-01 .data TM: .word 0 ; tm_sec .word 0 ; tm_min .word 0 ; tm_hour .word 1 ; tm_mday .word 0 ; tm_mon .word 70 ; tm_year .word 0 ; tm_wday .word 0 ; tm_yday .word 0 ; tm_isdst ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/toggle_videomode.s������������������������������������������������������������0000664�0000000�0000000�00000001037�13473601511�0017641�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-02-13 ; ; void toggle_videomode (void); ; /* Toggle the video mode between 40 and 80 chars (calls SWAPPER) */ ; .export _toggle_videomode .import SWAPPER, BSOUT ; This function is deprecated .assert 0, ldwarning, "toggle_videomode() is deprecated, please use videomode() instead!" .proc _toggle_videomode jsr SWAPPER ; Toggle the mode lda #14 jmp BSOUT ; Switch to lower case chars .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/videomode.s�������������������������������������������������������������������0000664�0000000�0000000�00000001447�13473601511�0016305�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2009-09-07 ; ; unsigned __fastcall__ videomode (unsigned Mode); ; /* Set the video mode, return the old mode */ ; .export _videomode .import SWAPPER, BSOUT .include "c128.inc" .proc _videomode cmp MODE ; Do we have this mode already? beq @L9 lda MODE ; Get current mode ... pha ; ... and save it jsr SWAPPER ; Toggle the mode lda #14 jsr BSOUT ; Switch to lower case chars pla ; Get old mode into A ; Done, old mode is in A @L9: ldx #$00 ; Clear high byte rts .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c128/waitvsync.s�������������������������������������������������������������������0000664�0000000�0000000�00000000700�13473601511�0016350�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Written by Groepaz <groepaz@gmx.net> ; ; void waitvsync (void); ; .export _waitvsync .include "c128.inc" _waitvsync: bit MODE bmi @c80 @l1: bit VIC_CTRL1 bpl @l1 @l2: bit VIC_CTRL1 bmi @l2 rts @c80: ;FIXME: do we have to switch banks? @l3: lda VDC_INDEX and #$20 beq @l3 rts ����������������������������������������������������������������cc65-2.18/libsrc/c16/�������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014054�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c16/_scrsize.s���������������������������������������������������������������������0000664�0000000�0000000�00000000241�13473601511�0016056�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.10.2000 ; ; Screen size variables ; .export screensize .import SCREEN screensize = SCREEN ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c16/break.s������������������������������������������������������������������������0000664�0000000�0000000�00000004314�13473601511�0015326�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 27.09.1998 ; ; void __fastcall__ set_brk (unsigned Addr); ; void reset_brk (void); ; .export _set_brk, _reset_brk .destructor _reset_brk .export _brk_a, _brk_x, _brk_y, _brk_sr, _brk_pc .include "plus4.inc" .bss _brk_a: .res 1 _brk_x: .res 1 _brk_y: .res 1 _brk_sr: .res 1 _brk_pc: .res 2 oldvec: .res 2 ; Old vector .data uservec: jmp $FFFF ; Patched at runtime .code ; Set the break vector .proc _set_brk sta uservec+1 stx uservec+2 ; Set the user vector lda oldvec ora oldvec+1 ; Did we save the vector already? bne L1 ; Jump if we installed the handler already lda BRKVec sta oldvec lda BRKVec+1 sta oldvec+1 ; Save the old vector L1: lda #<brk_handler ; Set the break vector to our routine ldx #>brk_handler sta BRKVec stx BRKVec+1 rts .endproc ; Reset the break vector .proc _reset_brk lda oldvec ldx oldvec+1 beq @L9 ; Jump if vector not installed sta BRKVec stx BRKVec+1 lda #$00 sta oldvec ; Clear the old vector stx oldvec+1 @L9: rts .endproc ; Break handler, called if a break occurs .proc brk_handler pla sta _brk_y pla sta _brk_x pla sta _brk_a pla and #$EF ; Clear break bit sta _brk_sr pla ; PC low sec sbc #2 ; Point to start of brk sta _brk_pc pla ; PC high sbc #0 sta _brk_pc+1 jsr uservec ; Call the user's routine lda _brk_pc+1 pha lda _brk_pc pha lda _brk_sr pha ldx _brk_x ldy _brk_y lda _brk_a rti ; Jump back... .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c16/cgetc.s������������������������������������������������������������������������0000664�0000000�0000000�00000004117�13473601511�0015330�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; char cgetc (void); ; .export _cgetc .import cursor .include "cbm_kernal.inc" .include "plus4.inc" ; -------------------------------------------------------------------------- _cgetc: lda KEY_COUNT ; Get number of characters ora FKEY_COUNT ; Or with number of function key chars bne L2 ; Jump if there are already chars waiting ; Switch on the cursor if needed ldy CURS_X lda (CRAM_PTR),y ; Get current char pha ; And save it lda CHARCOLOR sta (CRAM_PTR),y lda cursor beq L1 ; Jump if no cursor tya clc adc SCREEN_PTR sta TED_CURSLO lda SCREEN_PTR+1 adc #$00 sbc #$0B ; + carry = $C00 (screen address) sta TED_CURSHI L1: lda KEY_COUNT ora FKEY_COUNT beq L1 pla sta (CRAM_PTR),y lda #$ff sta TED_CURSLO ; Cursor off sta TED_CURSHI L2: jsr KBDREAD ; Read char and return in A ldx #0 rts ; -------------------------------------------------------------------------- ; Make the function keys return function key codes instead of the current ; strings so the program will see and may handle them. ; Undo this change when the program ends .constructor initkbd .destructor donekbd .segment "ONCE" .proc initkbd ldy #7 @L1: lda fnkeys,y sta FKEY_SPACE+8,y lda #$01 ; Lower 8 places are all $01 sta FKEY_SPACE,y dey bpl @L1 rts .endproc fnkeys: .byte 133, 137, 134, 138, 135, 139, 136, 140 .code .proc donekbd ldx #$39 ; Copy the original function keys @L1: lda FKEY_ORIG,x sta FKEY_SPACE,x dex bpl @L1 rts .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c16/clrscr.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000235�13473601511�0015530�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; void clrscr (void); ; .export _clrscr .include "cbm_kernal.inc" _clrscr = CLRSCR �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c16/color.s������������������������������������������������������������������������0000664�0000000�0000000�00000001330�13473601511�0015353�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; 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 "plus4.inc" _textcolor: ldx CHARCOLOR ; get old value sta CHARCOLOR ; set new value txa rts _bgcolor: ldx TED_BGCOLOR ; get old value sta TED_BGCOLOR ; set new value txa rts _bordercolor: ldx TED_BORDERCOLOR ; get old value sta TED_BORDERCOLOR ; set new value txa rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c16/conio.s������������������������������������������������������������������������0000664�0000000�0000000�00000000252�13473601511�0015346�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; Low level stuff for screen output/console input ; .exportzp CURS_X, CURS_Y .include "plus4.inc" ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c16/cputc.s������������������������������������������������������������������������0000664�0000000�0000000�00000004470�13473601511�0015363�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; void cputcxy (unsigned char x, unsigned char y, char c); ; void cputc (char c); ; .export _cputcxy, _cputc, cputdirect, putchar .export newline, plot .import gotoxy .import PLOT .include "plus4.inc" _cputcxy: pha ; Save C jsr gotoxy ; Set cursor, drop x and y pla ; Restore C ; Plot a character - also used as internal function _cputc: cmp #$0A ; CR? bne L1 lda #0 sta CURS_X beq plot ; Recalculate pointers L1: cmp #$0D ; LF? beq newline ; Recalculate pointers ; Printable char of some sort cmp #' ' bcc cputdirect ; Other control char tay bmi L10 cmp #$60 bcc L2 and #$DF bne cputdirect ; Branch always L2: and #$3F cputdirect: jsr putchar ; Write the character to the screen ; Advance cursor position advance: iny cpy #XSIZE bne L3 jsr newline ; new line ldy #0 ; + cr L3: sty CURS_X rts newline: clc lda #XSIZE adc SCREEN_PTR sta SCREEN_PTR bcc L4 inc SCREEN_PTR+1 clc L4: lda #XSIZE adc CRAM_PTR sta CRAM_PTR bcc L5 inc CRAM_PTR+1 L5: inc CURS_Y rts ; Handle character if high bit set L10: and #$7F cmp #$7E ; PI? bne L11 lda #$5E ; Load screen code for PI bne cputdirect L11: ora #$40 bne cputdirect ; 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 ldy CURS_X sta (SCREEN_PTR),y ; Set char lda CHARCOLOR sta (CRAM_PTR),y ; Set color rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c16/crt0.s�������������������������������������������������������������������������0000664�0000000�0000000�00000004220�13473601511�0015106�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Startup code for cc65 (C16 version) ; ; Note: The C16 is actually the Plus/4 with just 16KB of memory. So, many ; things are similar here; and, we even use the plus4.inc include file. ; .export _exit .export __STARTUP__ : absolute = 1 ; Mark as startup .import initlib, donelib .import callmain, zerobss .import MEMTOP, RESTOR, BSOUT, CLRCH .importzp ST .include "zeropage.inc" .include "plus4.inc" ; ------------------------------------------------------------------------ ; Startup code .segment "STARTUP" 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 jsr BSOUT ; Clear the BSS data. jsr zerobss ; Save some system stuff; and, set up the stack. tsx stx spsave ; save system stk ptr sec jsr MEMTOP ; Get top memory cpy #$80 ; We can only use the low 32K :-( bcc MemOk ldy #$80 ldx #$00 MemOk: stx sp sty sp+1 ; set argument stack ptr ; Call the module constructors. jsr initlib ; Push the command-line arguments; and, call main(). jsr callmain ; Call the module destructors. This is also the exit() entry. _exit: pha ; Save the return code on stack jsr donelib ; Run module destructors ; Copy back the zero-page stuff. ldx #zpspace-1 L2: lda zpsave,x sta sp,x dex bpl L2 ; Store the return code into BASIC's status variable. pla sta ST ; Restore the stack pointer. ldx spsave txs ; Back to BASIC. rts ; ------------------------------------------------------------------------ .segment "INIT" zpsave: .res zpspace ; ------------------------------------------------------------------------ .bss spsave: .res 1 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c16/devnum.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000156�13473601511�0015540�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2010-02-14 ; .include "c16.inc" .exportzp devnum := DEVNUM ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c16/emd/���������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014621�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c16/emd/c16-ram.s������������������������������������������������������������������0000664�0000000�0000000�00000015614�13473601511�0016162�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Extended memory driver for the C16 hidden RAM. Driver works without ; problems when statically linked. ; ; Ullrich von Bassewitz, 2003-12-15 ; .include "zeropage.inc" .include "em-kernel.inc" .include "em-error.inc" .include "plus4.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c16_ram_emd ; Driver signature .byte $65, $6d, $64 ; "emd" .byte EMD_API_VERSION ; EM API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr PAGECOUNT .addr MAP .addr USE .addr COMMIT .addr COPYFROM .addr COPYTO ; ------------------------------------------------------------------------ ; Constants BASE = $8000 ; ------------------------------------------------------------------------ ; Data. .bss pages: .res 1 ; Number of pages curpage: .res 1 ; Current page number window: .res 256 ; Memory "window" .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present and determine the amount of ; memory available. ; Must return an EM_ERR_xx code in a/x. ; INSTALL: ; Determine how much memory is available. We will use all memory above ; $8000 up to MEMTOP sec jsr $FF99 ; MEMTOP: Get top memory into Y/X tya sub #>BASE ; Low 32 K are used bcc nomem beq nomem ; Offering zero pages is a bad idea sta pages ldx #$FF stx curpage ; Invalidate the current page inx ; X = 0 txa ; A = X = EM_ERR_OK rts nomem: ldx #>EM_ERR_NO_DEVICE lda #<EM_ERR_NO_DEVICE ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; PAGECOUNT: Return the total number of available pages in a/x. ; PAGECOUNT: lda pages ldx #$00 ; 128 pages max rts ; ------------------------------------------------------------------------ ; MAP: Map the page in a/x into memory and return a pointer to the page in ; a/x. The contents of the currently mapped page (if any) may be discarded ; by the driver. ; MAP: sta curpage ; Remember the new page add #>BASE sta ptr1+1 ldy #$00 sty ptr1 lda #<window sta ptr2 lda #>window sta ptr2+1 ; Transfer one page jsr transfer ; Transfer one page ; Return the memory window lda #<window ldx #>window ; Return the window address rts ; ------------------------------------------------------------------------ ; USE: Tell the driver that the window is now associated with a given page. USE: sta curpage ; Remember the page lda #<window ldx #>window ; Return the window rts ; ------------------------------------------------------------------------ ; COMMIT: Commit changes in the memory window to extended storage. COMMIT: lda curpage ; Get the current page bmi done ; Jump if no page mapped add #>BASE sta ptr2+1 ldy #$00 sty ptr2 lda #<window sta ptr1 lda #>window sta ptr1+1 ; Transfer one page. Y must be zero on entry. Because we bank out the ; kernal, we will run the routine with interrupts disabled but leave ; short breath times. Unroll the following loop to make it somewhat faster. transfer: sei sta ENABLE_RAM .repeat 8 lda (ptr1),y sta (ptr2),y iny .endrepeat sta ENABLE_ROM cli bne transfer ; Done done: rts ; ------------------------------------------------------------------------ ; COPYFROM: Copy from extended into linear memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYFROM: sta ptr3 stx ptr3+1 ; Save the passed em_copy pointer ldy #EM_COPY::OFFS lda (ptr3),y sta ptr1 ldy #EM_COPY::PAGE lda (ptr3),y add #>BASE sta ptr1+1 ; From ldy #EM_COPY::BUF lda (ptr3),y sta ptr2 iny lda (ptr3),y sta ptr2+1 ; To common: ldy #EM_COPY::COUNT+1 lda (ptr3),y ; Get number of pages beq @L2 ; Skip if no full pages sta tmp1 ; Copy full pages allowing interrupts after each page copied ldy #$00 @L1: jsr transfer inc ptr1+1 inc ptr2+1 dec tmp1 bne @L1 ; Copy the remainder of the page @L2: ldy #EM_COPY::COUNT lda (ptr3),y ; Get bytes in last page beq @L4 tax sei ; Disable ints sta ENABLE_RAM ; Bank out the ROM ; Transfer the bytes in the last page ldy #$00 @L3: lda (ptr1),y sta (ptr2),y iny dex bne @L3 ; Restore the old memory configuration, allow interrupts sta ENABLE_ROM cli ; Done @L4: rts ; ------------------------------------------------------------------------ ; COPYTO: Copy from linear into extended memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYTO: sta ptr3 stx ptr3+1 ; Save the passed em_copy pointer ldy #EM_COPY::OFFS lda (ptr3),y sta ptr2 ldy #EM_COPY::PAGE lda (ptr3),y add #>BASE sta ptr2+1 ; To ldy #EM_COPY::BUF lda (ptr3),y sta ptr1 iny lda (ptr3),y sta ptr1+1 ; From jmp common ��������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c16/fast.s�������������������������������������������������������������������������0000664�0000000�0000000�00000000444�13473601511�0015177�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Marco van den Heuvel, 2018-03-20 ; ; void fast (void); ; /* Switch the CPU into double clock mode. */ ; .export _fast .include "plus4.inc" .proc _fast lda TED_CLK and #%11111101 sta TED_CLK rts .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c16/get_tv.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000035�13473601511�0015526�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������.include "../plus4/get_tv.s" ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c16/irq.s��������������������������������������������������������������������������0000664�0000000�0000000�00000002047�13473601511�0015036�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; IRQ handling (C16 version) ; .export initirq, doneirq .import callirq .include "plus4.inc" ; ------------------------------------------------------------------------ .segment "ONCE" initirq: lda IRQVec ldx IRQVec+1 sta IRQInd+1 stx IRQInd+2 lda #<IRQStub ldx #>IRQStub jmp setvec ; ------------------------------------------------------------------------ .code doneirq: lda IRQInd+1 ldx IRQInd+2 setvec: sei sta IRQVec stx IRQVec+1 cli rts ; ------------------------------------------------------------------------ .segment "LOWCODE" IRQStub: cld ; Just to be sure jsr callirq ; Call the functions jmp IRQInd ; Jump to the saved IRQ vector ; ------------------------------------------------------------------------ .data IRQInd: jmp $0000 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c16/isfast.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000474�13473601511�0015536�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Marco van den Heuvel, 2018-03-20 ; ; unsigned char isfast (void); ; /* Returns 1 if the CPU is in double clock mode. */ ; .export _isfast .include "plus4.inc" .proc _isfast lda TED_CLK lsr and #$01 ldx #$00 rts .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c16/joy/���������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014655�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c16/joy/c16-stdjoy.s���������������������������������������������������������������0000664�0000000�0000000�00000000415�13473601511�0016744�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Standard joystick driver for the C16. May be used multiple times when linked ; to the statically application. ; ; Ullrich von Bassewitz, 2002-12-21 ; .define MODULE_LABEL _c16_stdjoy_joy .include "../../plus4/joy/plus4-stdjoy.s" ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c16/joy_stat_stddrv.s��������������������������������������������������������������0000664�0000000�0000000�00000000354�13473601511�0017464�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Address of the static standard joystick driver ; ; Oliver Schmidt, 2012-11-01 ; ; const void joy_static_stddrv[]; ; .export _joy_static_stddrv .import _c16_stdjoy_joy .rodata _joy_static_stddrv := _c16_stdjoy_joy ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c16/joy_stddrv.s�������������������������������������������������������������������0000664�0000000�0000000�00000000277�13473601511�0016435�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Name of the standard joystick driver ; ; Ullrich von Bassewitz, 2002-12-21 ; ; const char joy_stddrv[]; ; .export _joy_stddrv .rodata _joy_stddrv: .asciiz "c16-stdjoy.joy" ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c16/kbhit.s������������������������������������������������������������������������0000664�0000000�0000000�00000000655�13473601511�0015347�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; unsigned char kbhit (void); ; .export _kbhit .include "plus4.inc" .proc _kbhit ldx #0 ; High byte of return is always zero lda KEY_COUNT ; Get number of characters ora FKEY_COUNT ; Or with number of chars from function keys beq L9 lda #1 L9: rts .endproc �����������������������������������������������������������������������������������cc65-2.18/libsrc/c16/kclose.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000410�13473601511�0015513�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-21 ; ; CLOSE replacement function ; .export CLOSE .proc CLOSE clc ; Force C64 compatible behaviour jmp $FFC3 ; Call the ROM routine .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c16/kernal.s�����������������������������������������������������������������������0000664�0000000�0000000�00000002342�13473601511�0015515�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 19.11.2002 ; ; C16 kernal functions ; .include "cbm_kernal.inc" .export CINT .export IOINIT .export RAMTAS .export RESTOR .export VECTOR .export SETMSG .export SECOND .export TKSA .export MEMTOP .export MEMBOT .export SCNKEY .export SETTMO .export ACPTR .export CIOUT .export UNTLK .export UNLSN .export LISTEN .export TALK .export READST .export SETLFS .export SETNAM .export OPEN .export CHKIN .export CKOUT .export CLRCH .export BASIN .export BSOUT .export LOAD .export SAVE .export SETTIM .export RDTIM .export STOP .export GETIN .export CLALL .export UDTIM .export SCREEN .export PLOT .export IOBASE ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c16/libref.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000241�13473601511�0015500�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2013-05-31 ; .export em_libref, joy_libref .import _exit em_libref := _exit joy_libref := _exit ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c16/mainargs.s���������������������������������������������������������������������0000664�0000000�0000000�00000010102�13473601511�0016033�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; mainargs.s ; ; Ullrich von Bassewitz, 2003-03-07 ; Based on code from Stefan A. Haubenthal, <polluks@web.de> ; 2003-05-18, Greg King ; 2004-04-28, 2005-02-26, Ullrich von Bassewitz ; ; Scan a group of arguments that are in BASIC's input-buffer. ; Build an array that points to the beginning of each argument. ; Send, to main(), that array and the count of the arguments. ; ; Command-lines look like these lines: ; ; run ; run : rem ; run:rem arg1 " arg 2 is quoted " arg3 "" arg5 ; ; "run" and "rem" are entokenned; the args. are not. Leading and trailing ; spaces outside of quotes are ignored. ; ; TO-DO: ; - The "file-name" might be a path-name; don't copy the directory-components. ; - Add a control-character quoting mechanism. .constructor initmainargs, 24 .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 ; Get possible command-line arguments. Goes into the special ONCE segment, ; which may be reused after the startup code is run .segment "ONCE" initmainargs: ; Assume that the program was loaded, a moment ago, by the traditional LOAD ; statement. Save the "most-recent filename" as argument #0. lda #0 ; The terminating NUL character ldy FNAM_LEN cpy #NAME_LEN + 1 bcc L1 ldy #NAME_LEN ; Limit the length bne L1 ; Branch always L0: lda #FNAM ; Vector address jsr FETCH ; Load byte from RAM 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. inx cmp #REM bne L2 ldy #1 * 2 ; Find the next argument next: lda BASIC_BUF,x beq done ; End of line reached inx cmp #' ' ; Skip leading spaces 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 ; will check now for a quoted argument, in which case we will have to skip this ; first character. found: cmp #'"' ; Is the argument quoted? beq setterm ; Jump if so dex ; Reset pointer to first argument character lda #' ' ; A space ends the argument setterm:sta term ; Set end of argument marker ; Now store a pointer to the argument into the next slot. Since the BASIC ; input buffer is located at the start of a RAM page, no calculations are ; necessary. txa ; Get low byte sta argv,y ; argv[y]= &arg iny lda #>BASIC_BUF sta argv,y iny inc __argc ; Found another arg ; Search for the end of the argument argloop:lda BASIC_BUF,x beq done inx cmp term bne argloop ; 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 #0 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? bcc 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 .segment "INIT" term: .res 1 name: .res NAME_LEN + 1 .data ; char* argv[MAXARGS+1]={name}; argv: .addr name .res MAXARGS * 2 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c16/randomize.s��������������������������������������������������������������������0000664�0000000�0000000�00000000671�13473601511�0016234�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2002-11-05, Ullrich von Bassewitz ; 2015-09-11, Greg King ; ; void _randomize (void); ; /* Initialize the random number generator */ ; .export __randomize .import _srand .include "plus4.inc" __randomize: ldx TED_VLINELO ; Use TED rasterline as high byte lda TIME+2 ; Use 60HZ clock as low byte jmp _srand ; Initialize generator �����������������������������������������������������������������������cc65-2.18/libsrc/c16/revers.s�����������������������������������������������������������������������0000664�0000000�0000000�00000001403�13473601511�0015544�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 07.08.1998 ; ; unsigned char revers (unsigned char onoff); ; .export _revers .include "plus4.inc" .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 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c16/slow.s�������������������������������������������������������������������������0000664�0000000�0000000�00000000444�13473601511�0015226�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Marco van den Heuvel, 2018-03-28 ; ; void slow (void); ; /* Switch the CPU into single clock mode. */ ; .export _slow .include "plus4.inc" .proc _slow lda TED_CLK ora #%00000010 sta TED_CLK rts .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c16/status.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000134�13473601511�0015561�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2012-09-30 ; .exportzp ST := $90 ; IEC status byte ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c16/sysuname.s���������������������������������������������������������������������0000664�0000000�0000000�00000001446�13473601511�0016111�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-08-12 ; ; unsigned char __fastcall__ _sysuname (struct utsname* buf); ; .export __sysuname, utsdata .import utscopy __sysuname = utscopy ;-------------------------------------------------------------------------- ; Data. We define a fixed utsname struct here and just copy it. .rodata utsdata: ; sysname .asciiz "cc65" ; nodename .asciiz "" ; release .byte ((.VERSION >> 8) & $0F) + '0' .byte '.' .byte ((.VERSION >> 4) & $0F) + '0' .byte $00 ; version .byte (.VERSION & $0F) + '0' .byte $00 ; machine .asciiz "Commodore 16" ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/�������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014057�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/_scrsize.s���������������������������������������������������������������������0000664�0000000�0000000�00000000241�13473601511�0016061�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.10.2000 ; ; Screen size variables ; .export screensize .import SCREEN screensize = SCREEN ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/acc_c128_speed.s���������������������������������������������������������������0000664�0000000�0000000�00000000114�13473601511�0016702�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Marco van den Heuvel, 2018-04-23 ; .include "../c128/acc_c128_speed.s" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/acc_c64dtv_speed.s�������������������������������������������������������������0000664�0000000�0000000�00000003526�13473601511�0017351�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Marco van den Heuvel, 2018-04-14 ; ; unsigned char __fastcall__ set_c64dtv_speed (unsigned char speed); ; ;/* Set the speed of the C64DTV, using SPEED_SLOW will switch to ; * slow mode, SPEED_2X or SPEED_FAST will switch to fast mode. ; * ; * Note that any value higher or equal to SPEED_2X will switch to fast mode. ; * ; * This function will return the actual speed the CPU is at after trying ; * to set the requested speed, to my knowledge the switching should not fail. ; * ; * This function does not check for the presence of the C64DTV, ; * make sure you use 'detect_c64dtv();' before using. ; */ ; unsigned char get_c64dtv_speed (void); ; ;/* Get the speed of the C64DTV. ; * ; * Possible return values: ; * SPEED_1X : slow mode ; * SPEED_2X : fast mode ; * ; * This function does not check for the presence of the C64DTV, ; * make sure you use 'detect_c64dtv();' before using. ; */ .export _set_c64dtv_speed .export _get_c64dtv_speed .include "accelerator.inc" _set_c64dtv_speed: cmp #SPEED_2X bcs high_speed low_speed: ldx #C64DTV_Slow set_speed: .byte $32,$99 ; SAC #$99 set accumulator to reg 9 (cpu control) txa ; (re)set skip and burst bits .byte $32,$00 ; SAC #$00 set accumulator back to reg 0 jmp _get_c64dtv_speed high_speed: ldx #C64DTV_Fast bne set_speed _get_c64dtv_speed: .byte $32,$99 ; SAC #$99 set accumulator to reg 9 (cpu control) tax .byte $32,$00 ; SAC #$00 set accumulator back to reg 0 txa and #C64DTV_Fast bne in_fast_mode lda #$00 .byte $2C in_fast_mode: lda #$01 ldx #$00 rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/acc_c65_speed.s����������������������������������������������������������������0000775�0000000�0000000�00000003560�13473601511�0016635�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Marco van den Heuvel, 2018-04-27 ; ; unsigned char __fastcall__ set_c65_speed (unsigned char speed); ; ;/* Set the speed of the C65 CPU, using SPEED_SLOW will switch to ; * 1 Mhz mode, SPEED_3X or SPEED_FAST will switch to 3.5 Mhz (fast) mode. ; * ; * Note that any value higher or equal to SPEED_3X will switch to fast mode. ; * ; * This function will return the actual speed the CPU is at after trying ; * to set the requested speed, to my knowledge the switching should not fail. ; * ; * This function does not check for the presence of a C65/C64DX in C64 mode, ; * make sure you use 'detect_c65();' before using. ; */ ; unsigned char get_c65_speed (void); ; ;/* Get the speed of the C65 CPU. ; * ; * Possible return values: ; * SPEED_SLOW : 1 Mhz mode ; * SPEED_3X : 3.5 Mhz mode ; * ; * This function does not check for the presence of a C65/C64DX in C64 mode, ; * make sure you use 'detect_c65();' before using. ; */ .export _set_c65_speed .export _get_c65_speed .include "accelerator.inc" _set_c65_speed: tay jsr activate_new_vic_mode cpy #SPEED_3X bcs high_speed low_speed: and #$BF store_speed: sta C65_VICIII_CTRL_B lda C65_VICIII_CTRL_B jmp return_c65_speed high_speed: ora #$40 bne store_speed _get_c65_speed: jsr activate_new_vic_mode return_c65_speed: sta C65_VICIII_KEY and #$40 beq speed_is_slow ; when this branch is taken then register A is already set to SPEED_SLOW lda #SPEED_3X speed_is_slow: ldx #$00 rts activate_new_vic_mode: lda #C65_VICIII_UNLOCK_1 sta C65_VICIII_KEY lda #C65_VICIII_UNLOCK_2 sta C65_VICIII_KEY lda C65_VICIII_CTRL_B rts ������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/acc_chameleon_speed.s����������������������������������������������������������0000775�0000000�0000000�00000004721�13473601511�0020173�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Marco van den Heuvel, 2018-04-25 ; ; unsigned char __fastcall__ set_chameleon_speed (unsigned char speed); ; ;/* Set the speed of the Chameleon cartridge, the following inputs ; * are accepted: ; * SPEED_SLOW : 1 Mhz mode ; * SPEED_1X : 1 Mhz mode ; * SPEED_2X : 2 Mhz mode ; * SPEED_3X : 3 Mhz mode ; * SPEED_4X : 4 Mhz mode ; * SPEED_5X : 5 Mhz mode ; * SPEED_6X : 6 Mhz mode ; * SPEED_FAST : Maximum speed mode ; * ; * Note that any value higher or equal to SPEED_7X will switch to maximum ; * speed mode. ; * ; * This function will return the actual speed the CPU is at after trying ; * to set the requested speed, to my knowledge the switching should not fail. ; * ; * This function does not check for the presence of the Chameleon cartridge, ; * make sure you use 'detect_chameleon();' before using. ; */ ; unsigned char get_chameleon_speed (void); ; ;/* Get the speed of the Chameleon cartridge. ; * ; * Possible return values: ; * SPEED_SLOW : Slow mode ; * SPEED_2X : 2Mhz mode ; * SPEED_3X : 3Mhz mode ; * SPEED_4X : 4Mhz mode ; * SPEED_5X : 5Mhz mode ; * SPEED_6X : 6Mhz mode ; * SPEED_FAST : Maximum speed mode ; * ; * This function does not check for the presence of the Chameleon cartridge, ; * make sure you use 'detect_chameleon();' before using. ; */ .export _set_chameleon_speed .export _get_chameleon_speed .include "accelerator.inc" _set_chameleon_speed: cmp #SPEED_7X bcs maximum_speed cmp #SPEED_1X beq low_speed ora #$80 set_speed: jsr activate_regs sta CHAMELEON_CFGTUR jmp return_speed low_speed: lda #CHAMELEON_CFGTUR_LIMIT_1MHZ bne set_speed maximum_speed: lda #CHAMELEON_CFGTUR_LIMIT_NONE bne set_speed _get_chameleon_speed: jsr activate_regs return_speed: ldx #$00 lda CHAMELEON_CFGTUR tay and #%10000000 beq return_value tya and #%00001000 bne is_slow_mode tya and #%00000111 beq is_max_mode return_value: ldy #CHAMELEON_DISABLE_REGS sty CHAMELEON_CFGENA rts is_slow_mode: txa bne return_value is_max_mode: lda #SPEED_FAST bne return_value activate_regs: ldy #CHAMELEON_ENABLE_REGS sty CHAMELEON_CFGENA rts �����������������������������������������������cc65-2.18/libsrc/c64/acc_detect_c128.s��������������������������������������������������������������0000664�0000000�0000000�00000001351�13473601511�0017056�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2018-04-20, Marco van den Heuvel ; 2018-04-26, Greg King ; ; unsigned char detect_c128 (void); ; ;/* Check for the presence of a C128 in C64 mode. ; * ; * Possible return values: ; * 0x00 : C128 in C64 mode not present ; * 0x01 : C128 in C64 mode present ; */ .export _detect_c128 .include "accelerator.inc" _detect_c128: ldx #>$0001 lda #<$0001 ; Make sure the CPU is an 8502. .byte $3A ; NOP on 8502, DEA on 65(S)C(E)02, 4510, and 65816 beq detect_end ; Make sure a C128 VIC-IIe is present. ldy C128_VICIIE_CLK cpy #$FF bne detect_end txa ; return zero when not VIC-IIe detect_end: rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/acc_detect_c64dtv.s������������������������������������������������������������0000664�0000000�0000000�00000001636�13473601511�0017521�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Marco van den Heuvel, 2018-04-14 ; ; unsigned char detect_c64dtv (void); ; ;/* Check for the presence of the C64DTV. ; * ; * Possible return values: ; * 0x00 : C64DTV not present ; * 0x01 : C64DTV present ; */ .export _detect_c64dtv .include "accelerator.inc" _detect_c64dtv: ldy C64DTV_Extended_Regs lda #$00 ldx $D000 ; Make sure the CPU is a 6510 .byte $1A ; NOP on 8502, INA on 65(S)C(E)02, 4510 and 65816 bne not_found lda #$01 sta C64DTV_Extended_Regs ; Check if $D000 is mirrored at $D040 cpx $D040 bne found inc $D000 cpx $D040 bne not_found found: lda #$01 .byte $2C not_found: lda #$00 stx $D000 ldx #$00 sty C64DTV_Extended_Regs rts ��������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/acc_detect_c65.s���������������������������������������������������������������0000775�0000000�0000000�00000002674�13473601511�0017012�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Marco van den Heuvel, 2018-04-27 ; ; unsigned char detect_c65 (void); ; ;/* Check for the presence of a C65/C64DX in C64 mode. ; * ; * Possible return values: ; * 0x00 : C65/C64DX in C64 mode not present ; * 0x01 : C65/C64DX in C64 mode present ; */ .export _detect_c65 .include "accelerator.inc" _detect_c65: ldy $D000 ; Make sure the CPU is not a 65816 clc .byte $E2,$01 ; NOP #$01 on 6510 and 65(S)C02, LDA $(01,S),Y on 65CE02 and 4510, SEP #$01 on 65816 lda #$00 tax bcs not_found ; carry will be set on 65816 ; Make sure the CPU is not a 6510 .byte $1A ; NOP on 6510, INA on 65(S)C(E)02 beq not_found txa ; Make sure the CPU is a 65CE02/4510 .byte $A3,$A3 ; NOP NOP on 65(S)C02, LDZ #$A3 on 65CE02 and 4510 .byte $6B ; NOP on 65(S)C02, TZA on 65CE02 and 4510 cmp #$A3 bne not_found ; Switch to VICIII mode and check if $D040 is a mirror of $D000 ldy #C65_VICIII_UNLOCK_1 sty C65_VICIII_KEY ldy #C65_VICIII_UNLOCK_2 sty C65_VICIII_KEY cpy $D040 bne found inc $D000 cpy $D040 bne not_found found: lda #$01 not_found: sty $D000 sta C65_VICIII_KEY rts ��������������������������������������������������������������������cc65-2.18/libsrc/c64/acc_detect_chameleon.s���������������������������������������������������������0000775�0000000�0000000�00000001516�13473601511�0020342�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Marco van den Heuvel, 2018-04-25 ; ; unsigned char detect_chameleon (void); ; ;/* Check for the presence of the Chameleon cartridge. ; * ; * Possible return values: ; * 0x00 : Chameleon cartridge not present ; * 0x01 : Chameleon cartridge present ; */ .export _detect_chameleon .include "accelerator.inc" _detect_chameleon: lda #$00 tax ; Make sure the CPU is a 6510 .byte $1A ; NOP on 6510, INA on 65(S)C(E)02, 4510 and 65816 bne not_found ldy CHAMELEON_CFGENA lda #CHAMELEON_ENABLE_REGS sta CHAMELEON_CFGENA lda CHAMELEON_CFGENA sty CHAMELEON_CFGENA cmp #$FF beq not_found found: lda #$01 .byte $24 not_found: txa rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/acc_detect_scpu.s��������������������������������������������������������������0000664�0000000�0000000�00000001453�13473601511�0017356�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Marco van den Heuvel, 2018-04-08 ; ; unsigned char detect_scpu (void); ; ;/* Check for the presence of the SuperCPU cartridge. ; * ; * Possible return values: ; * 0x00 : SuperCPU cartridge not present ; * 0x01 : SuperCPU cartridge present ; */ .export _detect_scpu .include "accelerator.inc" _detect_scpu: ldx #$00 txa ; Make sure the current CPU is a 65816 clc .byte $E2,$01 ; NOP #$01 on 6510 and 65(S)C02, LDA $(01,S),Y on 65CE02 and 4510, SEP #$01 on 65816 bcc not_found ; carry will be set on 65816 ; 65816 has been detected, make sure it's the SuperCPU cartridge lda SuperCPU_Detect asl bcs not_found found: lda #$01 not_found: rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/acc_detect_turbomaster.s�������������������������������������������������������0000775�0000000�0000000�00000002335�13473601511�0020756�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Marco van den Heuvel, 2018-04-30 ; ; unsigned char detect_turbomaster (void); ; ;/* Check for the presence of a Turbo Master cartridge. ; * ; * Possible return values: ; * 0x00 : TurboMaster cartridge not present ; * 0x01 : TurboMaster cartridge present ; */ .export _detect_turbomaster .include "accelerator.inc" _detect_turbomaster: lda #$00 tax ; Make sure the current CPU is not a 6510 .byte $1A ; NOP on 8502, INA on 65(S)C(E)02, 4510 and 65816 beq not_found ; Make sure the current CPU is not a 65816 clc .byte $E2,$01 ; NOP #$01 on 65(S)C02, LDA $(01,S),Y on 65CE02 and 4510, SEP #$01 on 65816 bcs not_found ; carry will be set on 65816 ; Make sure the current CPU is not a 65CE02/4510 .byte $A3,$A3 ; NOP NOP on 65(S)C02 and LDZ #$00 on 65CE02 and 4510 .byte $6B ; NOP on 65(S)C02 and TZA on 65CE02 and 4510 cmp #$A3 beq not_found ; Check for turbo master basic replacement ldy TURBOMASTER_DETECT cpy #$A2 beq found not_found: txa found: rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/acc_scpu_speed.s���������������������������������������������������������������0000664�0000000�0000000�00000003145�13473601511�0017206�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Marco van den Heuvel, 2018-04-09 ; ; unsigned char __fastcall__ set_scpu_speed (unsigned char speed); ; ;/* Set the speed of the SuperCPU cartridge, using SPEED_SLOW will switch to ; * 1 Mhz mode, SPEED_20X or SPEED_FAST will switch to 20 Mhz mode. ; * ; * Note that any value lower than SPEED_20X will switch to 1 Mhz mode, and ; * any value higher or equal to SPEED_20X will switch to 20 Mhz mode. ; * ; * This function will return the actual speed the CPU is at after trying ; * to set the requested speed, if this is not the speed that was requested ; * then possibly the hardware speed switch prevented any software speed ; * switching. ; * ; * This function does not check for the presence of the SuperCPU cartridge, ; * make sure you use 'detect_scpu();' before using. ; */ ; unsigned char get_scpu_speed (void); ; ;/* Get the speed of the SuperCPU cartridge. ; * ; * Possible return values: ; * SPEED_1X : 1 Mhz mode ; * SPEED_20X : 20 Mhz mode ; * ; * This function does not check for the presence of the SuperCPU cartridge, ; * make sure you use 'detect_scpu();' before using. ; */ .export _set_scpu_speed .export _get_scpu_speed .include "accelerator.inc" _set_scpu_speed: cmp #SPEED_20X bcs high_speed low_speed: sta SuperCPU_Slow jmp _get_scpu_speed high_speed: sta SuperCPU_Fast _get_scpu_speed: ldx #$00 lda SuperCPU_Speed_Mode asl asl bcc is_fast_speed lda #SPEED_1X rts is_fast_speed: lda #SPEED_20X rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/acc_turbomaster_speed.s��������������������������������������������������������0000775�0000000�0000000�00000003116�13473601511�0020604�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Marco van den Heuvel, 2018-04-30 ; ; unsigned char __fastcall__ set_turbomaster_speed (unsigned char speed); ; ;/* Set the speed of the Turbo Master cartridge, using SPEED_SLOW will switch to ; * 1 Mhz mode, SPEED_4X or SPEED_FAST will switch to 4 Mhz mode. ; * ; * Note that any value higher or equal to SPEED_4X will switch to 4 Mhz mode, ; * any value lower than SPEED_4X will switch to 1 Mhz mode. ; * ; * This function will return the actual speed the CPU is at after trying ; * to set the requested speed, if the speed is different it might indicate ; * that the hardware switch has locked the speed. ; * ; * This function does not check for the presence of a Turbo Master cartridge, ; * make sure you use 'detect_turbomaster();' before using. ; */ ; unsigned char get_turbomaster_speed (void); ; ;/* Get the speed of the Turbo Master cartridge. ; * ; * Possible return values: ; * SPEED_SLOW : 1 Mhz mode ; * SPEED_4X : 4 Mhz mode ; * ; * This function does not check for the presence of a Turbo Master cartridge, ; * make sure you use 'detect_turbomaster();' before using. ; */ .export _set_turbomaster_speed .export _get_turbomaster_speed .include "accelerator.inc" _set_turbomaster_speed: tay lda TURBOMASTER_SPEED_REG asl cpy #SPEED_4X ror store_speed: sta TURBOMASTER_SPEED_REG _get_turbomaster_speed: ldx #$00 lda TURBOMASTER_SPEED_REG and #$80 beq is_slow_speed is_high_speed: lda #SPEED_4X is_slow_speed: rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/bordercolor.s������������������������������������������������������������������0000664�0000000�0000000�00000000474�13473601511�0016564�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/break.s������������������������������������������������������������������������0000664�0000000�0000000�00000004312�13473601511�0015327�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 27.09.1998 ; ; void __fastcall__ set_brk (unsigned Addr); ; void reset_brk (void); ; .export _set_brk, _reset_brk .destructor _reset_brk .export _brk_a, _brk_x, _brk_y, _brk_sr, _brk_pc .include "c64.inc" .bss _brk_a: .res 1 _brk_x: .res 1 _brk_y: .res 1 _brk_sr: .res 1 _brk_pc: .res 2 oldvec: .res 2 ; Old vector .data uservec: jmp $FFFF ; Patched at runtime .code ; Set the break vector .proc _set_brk sta uservec+1 stx uservec+2 ; Set the user vector lda oldvec ora oldvec+1 ; Did we save the vector already? bne L1 ; Jump if we installed the handler already lda BRKVec sta oldvec lda BRKVec+1 sta oldvec+1 ; Save the old vector L1: lda #<brk_handler ; Set the break vector to our routine ldx #>brk_handler sta BRKVec stx BRKVec+1 rts .endproc ; Reset the break vector .proc _reset_brk lda oldvec ldx oldvec+1 beq @L9 ; Jump if vector not installed sta BRKVec stx BRKVec+1 lda #$00 sta oldvec ; Clear the old vector stx oldvec+1 @L9: rts .endproc ; Break handler, called if a break occurs .proc brk_handler pla sta _brk_y pla sta _brk_x pla sta _brk_a pla and #$EF ; Clear break bit sta _brk_sr pla ; PC low sec sbc #2 ; Point to start of brk sta _brk_pc pla ; PC high sbc #0 sta _brk_pc+1 jsr uservec ; Call the user's routine lda _brk_pc+1 pha lda _brk_pc pha lda _brk_sr pha ldx _brk_x ldy _brk_y lda _brk_a rti ; Jump back... .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/cgetc.s������������������������������������������������������������������������0000664�0000000�0000000�00000003002�13473601511�0015323�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; char cgetc (void); ; .export _cgetc .import cursor .include "cbm_kernal.inc" .include "c64.inc" _cgetc: lda KEY_COUNT ; Get number of characters bne L3 ; Jump if there are already chars waiting ; Switch on the cursor if needed lda CURS_FLAG pha lda cursor jsr setcursor L1: lda KEY_COUNT beq L1 ldx #0 pla bne L2 inx L2: txa jsr setcursor L3: jsr KBDREAD ; Read char and return in A ldx #0 rts ; Switch the cursor on or off .proc setcursor tax ; On or off? bne seton ; Go set it on lda CURS_FLAG ; Is the cursor currently off? bne crs9 ; Jump if yes lda #1 sta CURS_FLAG ; Mark it as off lda CURS_STATE ; Cursor currently displayed? beq crs8 ; Jump if no ldy CURS_X ; Get the character column lda (SCREEN_PTR),y ; Get character eor #$80 sta (SCREEN_PTR),y ; Store character back lda CURS_COLOR sta (CRAM_PTR),y ; Store color back crs8: lda #0 sta CURS_STATE ; Cursor not displayed crs9: rts seton: lda #0 sta CURS_FLAG rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/clrscr.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000235�13473601511�0015533�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; void clrscr (void); ; .export _clrscr .include "cbm_kernal.inc" _clrscr = CLRSCR �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/color.s������������������������������������������������������������������������0000664�0000000�0000000�00000000777�13473601511�0015374�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; unsigned char __fastcall__ textcolor (unsigned char color); ; unsigned char __fastcall__ bgcolor (unsigned char color); ; .export _textcolor, _bgcolor .include "c64.inc" _textcolor: ldx CHARCOLOR ; get old value sta CHARCOLOR ; set new value txa rts _bgcolor: ldx VIC_BG_COLOR0 ; get old value sta VIC_BG_COLOR0 ; set new value txa rts �cc65-2.18/libsrc/c64/conio.s������������������������������������������������������������������������0000664�0000000�0000000�00000000250�13473601511�0015347�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; Low level stuff for screen output/console input ; .exportzp CURS_X, CURS_Y .include "c64.inc" ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/cputc.s������������������������������������������������������������������������0000664�0000000�0000000�00000004535�13473601511�0015370�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 1998-08-06, 2009-09-26 ; ; void __fastcall__ cputcxy (unsigned char x, unsigned char y, char c); ; void __fastcall__ cputc (char c); ; .export _cputcxy, _cputc, cputdirect, putchar .export newline, plot .import gotoxy .import PLOT .include "c64.inc" _cputcxy: pha ; Save C jsr gotoxy ; Set cursor, drop x and y pla ; Restore C ; Plot a character - also used as internal function _cputc: cmp #$0A ; CR? bne L1 lda #0 sta CURS_X beq plot ; Recalculate pointers L1: cmp #$0D ; LF? beq newline ; Recalculate pointers ; Printable char of some sort cmp #' ' bcc cputdirect ; Other control char tay bmi L10 cmp #$60 bcc L2 and #$DF bne cputdirect ; Branch always L2: and #$3F cputdirect: jsr putchar ; Write the character to the screen ; Advance cursor position advance: iny cpy #XSIZE bne L3 jsr newline ; new line ldy #0 ; + cr L3: sty CURS_X rts newline: clc lda #XSIZE adc SCREEN_PTR sta SCREEN_PTR bcc L4 inc SCREEN_PTR+1 clc L4: lda #XSIZE adc CRAM_PTR sta CRAM_PTR bcc L5 inc CRAM_PTR+1 L5: inc CURS_Y rts ; Handle character if high bit set L10: and #$7F cmp #$7E ; PI? bne L11 lda #$5E ; Load screen code for PI bne cputdirect L11: ora #$40 bne cputdirect ; 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 ldy CURS_X sta (SCREEN_PTR),y ; Set char lda CHARCOLOR sta (CRAM_PTR),y ; Set color rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/crt0.s�������������������������������������������������������������������������0000664�0000000�0000000�00000005075�13473601511�0015122�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Startup code for cc65 (C64 version) ; .export _exit .export __STARTUP__ : absolute = 1 ; Mark as startup .import initlib, donelib .import zerobss, callmain .import BSOUT .import __MAIN_START__, __MAIN_SIZE__ ; Linker generated .import __STACKSIZE__ ; from configure file .importzp ST .include "zeropage.inc" .include "c64.inc" ; ------------------------------------------------------------------------ ; Startup code .segment "STARTUP" Start: ; Switch off the BASIC ROM. lda $01 sta mmusave ; Save the memory configuration and #$F8 ora #$06 ; Enable Kernal+I/O, disable BASIC sta $01 tsx stx spsave ; Save the system stack ptr ; Save space by putting some of the start-up code in the ONCE segment, ; which can be re-used by the BSS segment, the heap and the C stack. jsr init ; Clear the BSS data. jsr zerobss ; Push the command-line arguments; and, call main(). jsr callmain ; Back from main() [this is also the exit() entry]. Run the module destructors. _exit: pha ; Save the return code on stack jsr donelib ; Copy back the zero-page stuff. ldx #zpspace-1 L2: lda zpsave,x sta sp,x dex bpl L2 ; Place the program return code into BASIC's status variable. pla sta ST ; Restore the system stuff. ldx spsave txs ; Restore stack pointer ldx mmusave stx $01 ; Restore memory configuration ; Back to BASIC. rts ; ------------------------------------------------------------------------ .segment "ONCE" init: ; 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__) ldx #>(__MAIN_START__ + __MAIN_SIZE__) sta sp stx sp+1 ; Set argument stack ptr ; Switch to the second charset. lda #14 jsr BSOUT ; Call the module constructors. jmp initlib ; ------------------------------------------------------------------------ ; Data .segment "INIT" mmusave:.res 1 spsave: .res 1 zpsave: .res zpspace �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/devnum.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000156�13473601511�0015543�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2010-02-14 ; .include "c64.inc" .exportzp devnum := DEVNUM ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/emd/���������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014624�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/emd/c64-65816.s����������������������������������������������������������������0000664�0000000�0000000�00000024053�13473601511�0016077�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Extended memory driver for 65816 based extra RAM. Driver works without ; problems when statically linked. ; ; Marco van den Heuvel, 2015-12-01 ; .include "zeropage.inc" .include "em-kernel.inc" .include "em-error.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c64_65816_emd ; Driver signature .byte $65, $6d, $64 ; "emd" .byte EMD_API_VERSION ; EM API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr PAGECOUNT .addr MAP .addr USE .addr COMMIT .addr COPYFROM .addr COPYTO ; ------------------------------------------------------------------------ ; Data. .bss isnotscpu: .res 1 ; SuperCPU not present curpage: .res 1 ; Current page number curbank: .res 1 ; Current bank number (+1) bankcount: .res 1 ; Number of available banks (pages = banks * 256) window: .res 256 ; Memory "window" .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present and determine the amount of ; memory available. ; Must return an EM_ERR_xx code in a/x. ; INSTALL: sei clc sed lda #$99 adc #$01 ; on 65C02, 65SC02, 65CE02, 65802 and 65816 sets the zero flag correctly cld bne @not_present clc .P816 sep #$01 ; nop #$01 on 65C02/65SC02 and lda ($01,s),y on 65CE02 .P02 bcc @not_present lda $d0bc and #$80 sta isnotscpu lda $07e8 pha ; save value incase it was used somewhere else ldx #$ff @fillloop: ; fill from top (bank 255) to bottom txa pha .P816 plb ; pull dbr .P02 stx $07e8 dex cpx #$ff bne @fillloop inx @compareloop: ; check from bottom to top txa pha .P816 plb .P02 cmp $07e8 bne @found_pages .P816 inc .P02 sta $07e8 cmp $07e8 bne @found_pages inx bne @compareloop @found_pages: dex lda #$00 pha .P816 plb .P02 pla sta $07e8 cli lda isnotscpu bne @noextradex dex @noextradex: stx bankcount lda #<EM_ERR_OK ldx #>EM_ERR_OK rts @not_present: cli lda #<EM_ERR_NO_DEVICE ldx #>EM_ERR_NO_DEVICE ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; PAGECOUNT: Return the total number of available pages in a/x. ; PAGECOUNT: lda #$00 ; a whole bank is either usable or not ldx bankcount rts ; ------------------------------------------------------------------------ ; MAP: Map the page in a/x into memory and return a pointer to the page in ; a/x. The contents of the currently mapped page (if any) may be discarded ; by the driver. ; MAP: sta curpage ; Remember the new page stx curbank ; Remember the new bank sta ptr2+1 ; src address low lda #$00 sta ptr2 ; src address high inx ldy isnotscpu ; check if not scpu bne @notscpu inx @notscpu: stx tmp2 ; src bank sta tmp1 ; dst bank sta ptr3+1 ; length high lda #$ff sta ptr3 ; length low lda #<window sta ptr1 ; dst address low ldx #>window stx ptr1+1 ; dst address high jsr transfer rts ; ------------------------------------------------------------------------ ; USE: Tell the driver that the window is now associated with a given page. USE: sta curpage ; Remember the page stx curbank ; Remember the bank lda #<window ldx #>window ; Return the window rts ; ------------------------------------------------------------------------ ; COMMIT: Commit changes in the memory window to extended storage. COMMIT: lda curpage ; Get the current page sta ptr1+1 ; dst high ldx #$00 stx ptr1 ; dst low lda #<window sta ptr2 ; src low lda #>window sta ptr2+1 ; src high stx ptr3+1 ; length high lda #$ff sta ptr3 ; length low stx tmp2 ; src bank ldy curbank ; Get the current bank iny ldx isnotscpu bne @notascpu iny @notascpu: sty tmp1 ; dst bank jsr transfer rts ; ------------------------------------------------------------------------ ; COPYFROM: Copy from extended into linear memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYFROM: sta ptr4 stx ptr4+1 ; Save the passed em_copy pointer ldy #EM_COPY::COUNT+1 ; start at the end of the struct lda (ptr4),y ; get high byte of count tax dey lda (ptr4),y ; get low byte of count bne @nodex dex @nodex: .P816 dec .P02 sta ptr3 ; length low stx ptr3+1 ; length high dey lda (ptr4),y ; get bank .P816 inc .P02 ldx isnotscpu bne @notscpu64 .P816 inc .P02 @notscpu64: sta tmp2 ; src bank dey lda (ptr4),y ; get page sta ptr2+1 ; src high dey lda (ptr4),y ; get offset in page sta ptr2 ; src low dey lda (ptr4),y ; get memory buffer high sta ptr1+1 ; dst high dey lda (ptr4),y ; get memory buffer low sta ptr1 ; dst low lda #$00 sta tmp1 ; dst bank jsr transfer rts ; ------------------------------------------------------------------------ ; COPYTO: Copy from linear into extended memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYTO: sta ptr4 stx ptr4+1 ; Save the passed em_copy pointer ldy #EM_COPY::COUNT+1 ; start at the end of the struct lda (ptr4),y ; get high byte of count tax dey lda (ptr4),y ; get low byte of count bne @nodex2 dex @nodex2: .P816 dec .P02 sta ptr3 ; length low txa sta ptr3+1 ; length high dey lda (ptr4),y ; get bank .P816 inc .P02 ldx isnotscpu bne @notascpu64 .P816 inc .P02 @notascpu64: sta tmp1 ; dst bank dey lda (ptr4),y ; get page sta ptr1+1 ; dst high dey lda (ptr4),y ; get page offset sta ptr1 ; dst low dey lda (ptr4),y ; get memory buffer high sta ptr2+1 ; src low dey lda (ptr4),y ; get memory buffer low sta ptr2 ; src high lda #$00 sta tmp2 ; src bank jsr transfer rts ; ------------------------------------------------------------------------ ; Helper function for moving a block, the following is used: ; ptr1: dst ; ptr2: src ; ptr3: length ; tmp1: dst bank ; tmp2: src bank transfer: .P816 .A8 .I8 sei pha phx phy ldx tmp1 ; load srcbank stx @move+1 ; store srcbank in move + 1 ldy tmp2 ; load dstbank sty @move+2 ; store dstbank in move + 2 clc ; switch to native mode xce php ; save status bits rep #%00110000 ; set A and index to 16bit .A16 .I16 ldy ptr1 ldx ptr2 lda ptr3 @move: mvn 0,0 plp ; restore status bits .A8 .I8 lda #$00 pha plb ; restore dbr sec xce ; switch to emul mode ply plx pla cli rts .P02 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/emd/c64-c256k.s����������������������������������������������������������������0000664�0000000�0000000�00000027010�13473601511�0016234�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Extended memory driver for the C256K memory expansion ; Marco van den Heuvel, 2010-01-27 ; .include "zeropage.inc" .include "em-kernel.inc" .include "em-error.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c64_c256k_emd ; Driver signature .byte $65, $6d, $64 ; "emd" .byte EMD_API_VERSION ; EM API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr PAGECOUNT .addr MAP .addr USE .addr COMMIT .addr COPYFROM .addr COPYTO ; ------------------------------------------------------------------------ ; Constants BASE = $4000 PAGES = 3 * 256 TARGETLOC = $200 ; Target location for copy/check code PIA = $DFC0 ; ------------------------------------------------------------------------ ; Data. .data ; This function is used to copy code from and to the extended memory .proc copy template: .org ::TARGETLOC ; Assemble for target location entry: stx PIA stashop = $91 ; 'sta' opcode operation := * ; Location and opcode is patched at runtime address := *+1 lda ($00),y ldx #$dc stx PIA rts .reloc .endproc ; This function is used to check for the existence of the extended memory .proc check template: .org ::TARGETLOC entry: ldy #$00 ; Assume hardware not present lda #$fc sta PIA lda $01 tax and #$f8 sta $01 lda $4000 cmp $c000 bne done ; Jump if not found inc $c000 cmp $4000 beq done ; Jump if not found ; Hardware is present iny done: stx $01 ldx #$dc stx PIA rts .reloc .endproc .bss curpage: .res 2 ; Current page number curbank: .res 1 ; Current bank window: .res 256 ; Memory "window" ; Since the functions above are copied to $200, the current contents of this ; memory area must be saved into backup storage. Allocate enough space. backup: .res .max (.sizeof (copy), .sizeof (check)) .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present and determine the amount of ; memory available. ; Must return an EM_ERR_xx code in a/x. ; INSTALL: lda PIA+1 ; Select Peripheral Registers ora #4 sta PIA+1 tax lda PIA+3 ora #4 sta PIA+3 tay lda #$DC ; Set the default memory bank data sta PIA lda #$FE sta PIA+2 txa ; Select Data Direction Registers and #$FB sta PIA+1 tya and #$FB sta PIA+3 lda #$FF ; Set the ports to output sta PIA sta PIA+2 txa and #$C7 ora #$30 ; Set CA1 and sta PIA+1 ; select Peripheral Registers sty PIA+3 jsr backup_and_setup_check_routine jsr check::entry cli ldx #.sizeof (check) - 1 jsr restore_data cpy #$01 beq @present lda #<EM_ERR_NO_DEVICE ldx #>EM_ERR_NO_DEVICE rts @present: lda #<EM_ERR_OK ldx #>EM_ERR_OK ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; PAGECOUNT: Return the total number of available pages in a/x. ; PAGECOUNT: lda #<PAGES ldx #>PAGES rts ; ------------------------------------------------------------------------ ; MAP: Map the page in a/x into memory and return a pointer to the page in ; a/x. The contents of the currently mapped page (if any) may be discarded ; by the driver. ; MAP: sei sta curpage ; Remember the new page stx curpage+1 jsr adjust_page_and_bank stx curbank clc adc #>BASE sta ptr1+1 ldy #0 sty ptr1 jsr backup_and_setup_copy_routine ldx #<ptr1 stx copy::address @L1: ldx curbank jsr copy::entry ldx ptr1 sta window,x inc ptr1 bne @L1 ; Return the memory window jsr restore_copy_routine lda #<window ldx #>window ; Return the window address cli rts ; ------------------------------------------------------------------------ ; USE: Tell the driver that the window is now associated with a given page. USE: sta curpage ; Remember the page stx curpage+1 lda #<window ldx #>window ; Return the window rts ; ------------------------------------------------------------------------ ; COMMIT: Commit changes in the memory window to extended storage. COMMIT: sei lda curpage ; Get the current page ldx curpage+1 jsr adjust_page_and_bank stx curbank clc adc #>BASE sta ptr1+1 ldy #0 sty ptr1 jsr backup_and_setup_copy_routine ldx #<ptr1 stx copy::address ldx #<copy::stashop stx copy::operation @L1: ldx ptr1 lda window,x ldx curbank jsr copy::entry inc ptr1 bne @L1 ; Return the memory window jsr restore_copy_routine done: cli rts ; ------------------------------------------------------------------------ ; COPYFROM: Copy from extended into linear memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYFROM: sei jsr setup jsr backup_and_setup_copy_routine ; Setup is: ; ; - ptr1 contains the struct pointer ; - ptr2 contains the linear memory buffer ; - ptr3 contains -(count-1) ; - ptr4 contains the page memory buffer plus offset ; - tmp1 contains zero (to be used for linear memory buffer offset) ; - tmp2 contains the bank value lda #<ptr4 sta copy::address jmp @L3 @L1: ldx tmp2 ldy #0 jsr copy::entry ldy tmp1 sta (ptr2),y inc tmp1 bne @L2 inc ptr2+1 @L2: inc ptr4 beq @L4 ; Bump count and repeat @L3: inc ptr3 bne @L1 inc ptr3+1 bne @L1 jsr restore_copy_routine cli rts ; Bump page register @L4: inc ptr4+1 lda ptr4+1 cmp #$80 bne @L3 lda #>BASE sta ptr4+1 lda tmp2 clc adc #$10 sta tmp2 jmp @L3 ; ------------------------------------------------------------------------ ; COPYTO: Copy from linear into extended memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYTO: sei jsr setup jsr backup_and_setup_copy_routine ; Setup is: ; ; - ptr1 contains the struct pointer ; - ptr2 contains the linear memory buffer ; - ptr3 contains -(count-1) ; - ptr4 contains the page memory buffer plus offset ; - tmp1 contains zero (to be used for linear memory buffer offset) ; - tmp2 contains the bank value lda #<ptr4 sta copy::address lda #<copy::stashop sta copy::operation jmp @L3 @L1: ldy tmp1 lda (ptr2),y ldx tmp2 ldy #0 jsr copy::entry inc tmp1 bne @L2 inc ptr2+1 @L2: inc ptr4 beq @L4 ; Bump count and repeat @L3: inc ptr3 bne @L1 inc ptr3+1 bne @L1 jsr restore_copy_routine cli rts ; Bump page register @L4: inc ptr4+1 lda ptr4+1 cmp #$80 bne @L3 lda #>BASE sta ptr4+1 lda tmp2 clc adc #$10 sta tmp2 jmp @L3 ; ------------------------------------------------------------------------ ; Helper function for COPYFROM and COPYTO: Store the pointer to the request ; structure and prepare data for the copy setup: sta ptr1 stx ptr1+1 ; Save passed pointer ; Get the page number from the struct and adjust it so that it may be used ; with the hardware. That is: ptr4 has the page address and page offset ; tmp2 will hold the bank value ldy #EM_COPY::PAGE+1 lda (ptr1),y tax ldy #EM_COPY::PAGE lda (ptr1),y jsr adjust_page_and_bank clc adc #>BASE sta ptr4+1 stx tmp2 ; Get the buffer pointer into ptr2 ldy #EM_COPY::BUF lda (ptr1),y sta ptr2 iny lda (ptr1),y sta ptr2+1 ; Get the count, calculate -(count-1) and store it into ptr3 ldy #EM_COPY::COUNT lda (ptr1),y eor #$FF sta ptr3 iny lda (ptr1),y eor #$FF sta ptr3+1 ; Get the page offset into ptr4 and clear tmp1 ldy #EM_COPY::OFFS lda (ptr1),y sta ptr4 lda #0 sta tmp1 ; Done rts ; Helper routines for copying to and from the +256k ram backup_and_setup_copy_routine: ldx #.sizeof (copy) - 1 @L1: lda copy::entry,x sta backup,x lda copy::template,x sta copy::entry,x dex bpl @L1 rts backup_and_setup_check_routine: ldx #.sizeof (check) - 1 @L1: lda check::entry,x sta backup,x lda check::template,x sta check::entry,x dex bpl @L1 rts restore_copy_routine: ldx #.sizeof (copy) - 1 restore_data: lda backup,x sta TARGETLOC,x dex bpl restore_data rts ; Helper routine to correct for the bank and page adjust_page_and_bank: sta tmp4 lda #$0C sta tmp3 lda tmp4 and #$c0 lsr lsr ora tmp3 sta tmp3 txa asl asl asl asl asl asl ora tmp3 tax lda tmp4 and #$3f rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/emd/c64-dqbb.s�����������������������������������������������������������������0000664�0000000�0000000�00000023541�13473601511�0016317�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Extended memory driver for the Double Quick Brown Box cartridge ; Marco van den Heuvel, 2010-01-27 ; .include "zeropage.inc" .include "em-kernel.inc" .include "em-error.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c64_dqbb_emd ; Driver signature .byte $65, $6d, $64 ; "emd" .byte EMD_API_VERSION ; EM API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr PAGECOUNT .addr MAP .addr USE .addr COMMIT .addr COPYFROM .addr COPYTO ; ------------------------------------------------------------------------ ; Constants BASE = $8000 PAGES = ($C000 - BASE) / 256 TARGETLOC = $200 ; Target location for copy/check code CONTROL = $DE00 ; ------------------------------------------------------------------------ ; Data. .proc check template: .org ::TARGETLOC ; Assemble for target location entry: lda $01 pha lda #$37 sta $01 ldx #$14 ldy #$90 sty CONTROL lda $8000 stx CONTROL cmp $8000 bne present sty CONTROL inc $8000 stx CONTROL cmp $8000 beq present dec $8000 ldy #$00 done: pla sta $01 rts present: sty CONTROL ldy #$01 bne done .reloc .endproc .proc copy template: .org ::TARGETLOC ; Assemble for target location entry: .proc fetch stx CONTROL ldx $01 lda #$37 sta $01 address := *+1 ; Patched at runtime lda ($00),y stx $01 ldx #$90 stx CONTROL rts .endproc .proc stash stx CONTROL ldx $01 ldy #$37 sty $01 ldy #$00 address := *+1 ; Patched at runtime sta ($00),y stx $01 ldx #$90 stx CONTROL rts .endproc .reloc .endproc .bss curpage: .res 1 ; Current page number window: .res 256 ; Memory "window" ; Since the functions above are copied to $200, the current contents of this ; memory area must be saved into backup storage. Allocate enough space. backup: .res .max (.sizeof (copy), .sizeof (check)) .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present and determine the amount of ; memory available. ; Must return an EM_ERR_xx code in a/x. ; INSTALL: sei jsr backup_and_setup_check_routine jsr check::entry cli ldx #.sizeof (check) - 1 jsr restore_data cpy #$01 beq @present lda #<EM_ERR_NO_DEVICE ldx #>EM_ERR_NO_DEVICE rts @present: lda #<EM_ERR_OK ldx #>EM_ERR_OK ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; PAGECOUNT: Return the total number of available pages in a/x. ; PAGECOUNT: lda #<PAGES ldx #>PAGES rts ; ------------------------------------------------------------------------ ; MAP: Map the page in a/x into memory and return a pointer to the page in ; a/x. The contents of the currently mapped page (if any) may be discarded ; by the driver. ; MAP: sei sta curpage ; Remember the new page clc adc #>BASE sta ptr1+1 ldy #0 sty ptr1 jsr backup_and_setup_copy_routine ldx #<ptr1 stx copy::fetch::address @L1: ldx #$14 jsr copy::fetch ldx ptr1 sta window,x inc ptr1 bne @L1 ; Return the memory window jsr restore_copy_routine lda #<window ldx #>window ; Return the window address cli rts ; ------------------------------------------------------------------------ ; USE: Tell the driver that the window is now associated with a given page. USE: sta curpage ; Remember the page lda #<window ldx #>window ; Return the window rts ; ------------------------------------------------------------------------ ; COMMIT: Commit changes in the memory window to extended storage. COMMIT: sei lda curpage ; Get the current page clc adc #>BASE sta ptr1+1 ldy #0 sty ptr1 jsr backup_and_setup_copy_routine ldx #<ptr1 stx copy::stash::address @L1: ldx ptr1 lda window,x ldx #$14 jsr copy::stash inc ptr1 bne @L1 ; Return the memory window jsr restore_copy_routine cli rts ; ------------------------------------------------------------------------ ; COPYFROM: Copy from extended into linear memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYFROM: sei pha txa pha jsr backup_and_setup_copy_routine pla tax pla jsr setup ; Setup is: ; ; - ptr1 contains the struct pointer ; - ptr2 contains the linear memory buffer ; - ptr3 contains -(count-1) ; - ptr4 contains the page memory buffer plus offset ; - tmp1 contains zero (to be used for linear memory buffer offset) lda #<ptr4 sta copy::fetch::address jmp @L3 @L1: ldx #$14 ldy #0 jsr copy::fetch ldy tmp1 sta (ptr2),y inc tmp1 bne @L2 inc ptr2+1 @L2: inc ptr4 beq @L4 ; Bump count and repeat @L3: inc ptr3 bne @L1 inc ptr3+1 bne @L1 jsr restore_copy_routine cli rts ; Bump page register @L4: inc ptr4+1 jmp @L3 ; ------------------------------------------------------------------------ ; COPYTO: Copy from linear into extended memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYTO: sei pha txa pha jsr backup_and_setup_copy_routine pla tax pla jsr setup ; Setup is: ; ; - ptr1 contains the struct pointer ; - ptr2 contains the linear memory buffer ; - ptr3 contains -(count-1) ; - ptr4 contains the page memory buffer plus offset ; - tmp1 contains zero (to be used for linear memory buffer offset) lda #<ptr4 sta copy::stash::address jmp @L3 @L1: ldy tmp1 lda (ptr2),y ldx #$14 ldy #0 jsr copy::stash inc tmp1 bne @L2 inc ptr2+1 @L2: inc ptr4 beq @L4 ; Bump count and repeat @L3: inc ptr3 bne @L1 inc ptr3+1 bne @L1 jsr restore_copy_routine cli rts ; Bump page register @L4: inc ptr4+1 jmp @L3 ; ------------------------------------------------------------------------ ; Helper function for COPYFROM and COPYTO: Store the pointer to the request ; structure and prepare data for the copy setup: sta ptr1 stx ptr1+1 ; Save passed pointer ; Get the page number from the struct and adjust it so that it may be used ; with the hardware. That is: ptr4 has the page address and page offset ; tmp2 will hold the bank value ldy #EM_COPY::PAGE lda (ptr1),y clc adc #>BASE sta ptr4+1 ; Get the buffer pointer into ptr2 ldy #EM_COPY::BUF lda (ptr1),y sta ptr2 iny lda (ptr1),y sta ptr2+1 ; Get the count, calculate -(count-1) and store it into ptr3 ldy #EM_COPY::COUNT lda (ptr1),y eor #$FF sta ptr3 iny lda (ptr1),y eor #$FF sta ptr3+1 ; Get the page offset into ptr4 and clear tmp1 ldy #EM_COPY::OFFS lda (ptr1),y sta ptr4 lda #0 sta tmp1 ; Done rts ; Helper routines for copying to and from the +256k ram backup_and_setup_copy_routine: ldx #.sizeof (copy) - 1 @L1: lda copy::entry,x sta backup,x lda copy::template,x sta copy::entry,x dex bpl @L1 rts backup_and_setup_check_routine: ldx #.sizeof (check) - 1 @L1: lda check::entry,x sta backup,x lda check::template,x sta check::entry,x dex bpl @L1 rts restore_copy_routine: ldx #.sizeof (copy) - 1 restore_data: lda backup,x sta TARGETLOC,x dex bpl restore_data rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/emd/c64-georam.s���������������������������������������������������������������0000664�0000000�0000000�00000020226�13473601511�0016656�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Extended memory driver for the GEORAM cartridge. Driver works without ; problems when statically linked. ; ; Ullrich von Bassewitz, 2002-11-29 ; ; GEORAM page size checking routine by ; Marco van den Heuvel, 2010-01-21 ; .include "zeropage.inc" .include "em-kernel.inc" .include "em-error.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c64_georam_emd ; Driver signature .byte $65, $6d, $64 ; "emd" .byte EMD_API_VERSION ; EM API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr PAGECOUNT .addr MAP .addr USE .addr COMMIT .addr COPYFROM .addr COPYTO ; ------------------------------------------------------------------------ ; Constants GR_WINDOW = $DE00 ; Address of GEORAM window GR_PAGE_LO = $DFFE ; Page register low GR_PAGE_HI = $DFFF ; Page register high ; ------------------------------------------------------------------------ ; Data. .data pagecount: .res 2 ; Number of available pages .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present and determine the amount of ; memory available. ; Must return an EM_ERR_xx code in a/x. ; INSTALL: ldx GR_WINDOW cpx GR_WINDOW bne @notpresent inc GR_WINDOW cpx GR_WINDOW beq @notpresent lda #4 jsr check cpy GR_WINDOW beq @has64k lda #8 jsr check cpy GR_WINDOW beq @has128k lda #16 jsr check cpy GR_WINDOW beq @has256k lda #32 jsr check cpy GR_WINDOW beq @has512k lda #64 jsr check cpy GR_WINDOW beq @has1024k lda #128 jsr check cpy GR_WINDOW beq @has2048k ldx #>16384 bne @setok @has64k: ldx #>256 bne @setok @has128k: ldx #>512 bne @setok @has256k: ldx #>1024 bne @setok @has512k: ldx #>2048 bne @setok @has1024k: ldx #>4096 bne @setok @has2048k: ldx #>8192 bne @setok @notpresent: lda #<EM_ERR_NO_DEVICE ldx #>EM_ERR_NO_DEVICE rts @setok: lda #0 sta pagecount stx pagecount+1 lda #<EM_ERR_OK ldx #>EM_ERR_OK rts check: ldx #0 stx GR_PAGE_LO stx GR_PAGE_HI ldy GR_WINDOW iny sta GR_PAGE_HI sty GR_WINDOW ldx #0 stx GR_PAGE_HI ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; PAGECOUNT: Return the total number of available pages in a/x. ; PAGECOUNT: lda pagecount ldx pagecount+1 rts ; ------------------------------------------------------------------------ ; USE: Tell the driver that the window is now associated with a given page. ; The GeoRAM cartridge does not copy but actually map the window, so USE is ; identical to MAP. USE = MAP ; ------------------------------------------------------------------------ ; MAP: Map the page in a/x into memory and return a pointer to the page in ; a/x. The contents of the currently mapped page (if any) may be discarded ; by the driver. ; MAP: sta tmp1 txa asl tmp1 rol a asl tmp1 rol a sta GR_PAGE_HI lda tmp1 lsr a lsr a sta GR_PAGE_LO lda #<GR_WINDOW ldx #>GR_WINDOW ; Use the RTS from COMMIT below to save a precious byte of storage ; ------------------------------------------------------------------------ ; COMMIT: Commit changes in the memory window to extended storage. COMMIT: rts ; ------------------------------------------------------------------------ ; COPYFROM: Copy from extended into linear memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYFROM: jsr setup ; Setup is: ; ; - ptr1 contains the struct pointer ; - ptr2 contains the linear memory buffer ; - ptr3 contains -(count-1) ; - tmp1 contains the low page register value ; - tmp2 contains the high page register value ; - X contains the page offset ; - Y contains zero jmp @L5 @L1: lda GR_WINDOW,x sta (ptr2),y iny bne @L2 inc ptr2+1 @L2: inx beq @L4 ; Bump count and repeat @L3: inc ptr3 bne @L1 inc ptr3+1 bne @L1 rts ; Bump page register @L4: inc tmp1 ; Bump low page register bit tmp1 ; Check for overflow in bit 6 bvc @L6 ; Jump if no overflow inc tmp2 @L5: lda tmp2 sta GR_PAGE_HI @L6: lda tmp1 sta GR_PAGE_LO jmp @L3 ; ------------------------------------------------------------------------ ; COPYTO: Copy from linear into extended memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYTO: jsr setup ; Setup is: ; ; - ptr1 contains the struct pointer ; - ptr2 contains the linear memory buffer ; - ptr3 contains -(count-1) ; - tmp1 contains the low page register value ; - tmp2 contains the high page register value ; - X contains the page offset ; - Y contains zero jmp @L5 @L1: lda (ptr2),y sta GR_WINDOW,x iny bne @L2 inc ptr2+1 @L2: inx beq @L4 ; Bump count and repeat @L3: inc ptr3 bne @L1 inc ptr3+1 bne @L1 rts ; Bump page register @L4: inc tmp1 ; Bump low page register bit tmp1 ; Check for overflow in bit 6 bvc @L6 ; Jump if no overflow inc tmp2 @L5: lda tmp2 sta GR_PAGE_HI @L6: lda tmp1 sta GR_PAGE_LO jmp @L3 ; ------------------------------------------------------------------------ ; Helper function for COPYFROM and COPYTO: Store the pointer to the request ; structure and prepare data for the copy setup: sta ptr1 stx ptr1+1 ; Save passed pointer ; Get the page number from the struct and adjust it so that it may be used ; with the hardware. That is: lower 6 bits in tmp1, high bits in tmp2. ldy #EM_COPY::PAGE+1 lda (ptr1),y sta tmp2 dey lda (ptr1),y asl a rol tmp2 asl a rol tmp2 lsr a lsr a sta tmp1 ; Get the buffer pointer into ptr2 ldy #EM_COPY::BUF lda (ptr1),y sta ptr2 iny lda (ptr1),y sta ptr2+1 ; Get the count, calculate -(count-1) and store it into ptr3 ldy #EM_COPY::COUNT lda (ptr1),y eor #$FF sta ptr3 iny lda (ptr1),y eor #$FF sta ptr3+1 ; Get the page offset into X and clear Y ldy #EM_COPY::OFFS lda (ptr1),y tax ldy #$00 ; Done rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/emd/c64-isepic.s���������������������������������������������������������������0000664�0000000�0000000�00000014204�13473601511�0016657�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Extended memory driver for the ISEPIC cartridge. ; Marco van den Heuvel, 2010-01-24 ; .include "zeropage.inc" .include "em-kernel.inc" .include "em-error.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c64_isepic_emd ; Driver signature .byte $65, $6d, $64 ; "emd" .byte EMD_API_VERSION ; EM API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr PAGECOUNT .addr MAP .addr USE .addr COMMIT .addr COPYFROM .addr COPYTO ; ------------------------------------------------------------------------ ; Constants IP_WINDOW = $DF00 ; Address of ISEPIC window IP_CTRL_BASE = $DE00 PAGES = 8 ; ------------------------------------------------------------------------ ; Code. .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present and determine the amount of ; memory available. ; Must return an EM_ERR_xx code in a/x. ; INSTALL: lda #0 sta IP_CTRL_BASE ldx IP_WINDOW cpx IP_WINDOW bne @notpresent inc IP_WINDOW cpx IP_WINDOW beq @notpresent ldx IP_WINDOW sta IP_CTRL_BASE+1 inx stx IP_WINDOW dex sta IP_CTRL_BASE cpx IP_WINDOW beq @setok @notpresent: lda #<EM_ERR_NO_DEVICE ldx #>EM_ERR_NO_DEVICE rts @setok: lda #<EM_ERR_OK ldx #>EM_ERR_OK ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; PAGECOUNT: Return the total number of available pages in a/x. ; PAGECOUNT: lda #<PAGES ldx #>PAGES rts ; ------------------------------------------------------------------------ ; USE: Tell the driver that the window is now associated with a given page. ; The Isepic cartridge does not copy but actually map the window, so USE is ; identical to MAP. USE := MAP ; ------------------------------------------------------------------------ ; MAP: Map the page in a/x into memory and return a pointer to the page in ; a/x. The contents of the currently mapped page (if any) may be discarded ; by the driver. ; MAP: tax sta IP_CTRL_BASE,x lda #<IP_WINDOW ldx #>IP_WINDOW ; Use the RTS from COMMIT below to save a precious byte of storage ; ------------------------------------------------------------------------ ; COMMIT: Commit changes in the memory window to extended storage. COMMIT: rts ; ------------------------------------------------------------------------ ; COPYFROM: Copy from extended into linear memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYFROM: jsr setup ; Setup is: ; ; - ptr1 contains the struct pointer ; - ptr2 contains the linear memory buffer ; - ptr3 contains -(count-1) ; - tmp1 contains the low page register value ; - X contains the page offset ; - Y contains zero jmp @L5 @L1: lda IP_WINDOW,x sta (ptr2),y iny bne @L2 inc ptr2+1 @L2: inx beq @L4 ; Bump count and repeat @L3: inc ptr3 bne @L1 inc ptr3+1 bne @L1 rts ; Bump page register @L4: inc tmp1 ; Bump low page register @L5: stx tmp2 ldx tmp1 sta IP_CTRL_BASE,x ldx tmp2 jmp @L3 ; ------------------------------------------------------------------------ ; COPYTO: Copy from linear into extended memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYTO: jsr setup ; Setup is: ; ; - ptr1 contains the struct pointer ; - ptr2 contains the linear memory buffer ; - ptr3 contains -(count-1) ; - tmp1 contains the low page register value ; - X contains the page offset ; - Y contains zero jmp @L5 @L1: lda (ptr2),y sta IP_WINDOW,x iny bne @L2 inc ptr2+1 @L2: inx beq @L4 ; Bump count and repeat @L3: inc ptr3 bne @L1 inc ptr3+1 bne @L1 rts ; Bump page register @L4: inc tmp1 ; Bump page register @L5: stx tmp2 ldx tmp1 sta IP_CTRL_BASE,x ldx tmp2 jmp @L3 ; ------------------------------------------------------------------------ ; Helper function for COPYFROM and COPYTO: Store the pointer to the request ; structure and prepare data for the copy setup: sta ptr1 stx ptr1+1 ; Save passed pointer ; Get the page number from the struct and remember it. ldy #EM_COPY::PAGE lda (ptr1),y sta tmp1 ; Get the buffer pointer into ptr2 ldy #EM_COPY::BUF lda (ptr1),y sta ptr2 iny lda (ptr1),y sta ptr2+1 ; Get the count, calculate -(count-1) and store it into ptr3 ldy #EM_COPY::COUNT lda (ptr1),y eor #$FF sta ptr3 iny lda (ptr1),y eor #$FF sta ptr3+1 ; Get the page offset into X and clear Y ldy #EM_COPY::OFFS lda (ptr1),y tax ldy #0 ; Done rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/emd/c64-ram.s������������������������������������������������������������������0000664�0000000�0000000�00000015146�13473601511�0016170�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Extended memory driver for the C64 hidden RAM. Driver works without ; problems when statically linked. ; ; Ullrich von Bassewitz, 2002-12-02 ; .include "zeropage.inc" .include "em-kernel.inc" .include "em-error.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c64_ram_emd ; Driver signature .byte $65, $6d, $64 ; "emd" .byte EMD_API_VERSION ; EM API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr PAGECOUNT .addr MAP .addr USE .addr COMMIT .addr COPYFROM .addr COPYTO ; ------------------------------------------------------------------------ ; Constants BASE = $D000 PAGES = ($FF00 - BASE) / 256 ; ------------------------------------------------------------------------ ; Data. .bss curpage: .res 1 ; Current page number window: .res 256 ; Memory "window" .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present and determine the amount of ; memory available. ; Must return an EM_ERR_xx code in a/x. ; INSTALL: ldx #$FF stx curpage ; Invalidate the current page inx ; X = 0 txa ; A = X = EM_ERR_OK ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; PAGECOUNT: Return the total number of available pages in a/x. ; PAGECOUNT: lda #<PAGES ldx #>PAGES rts ; ------------------------------------------------------------------------ ; MAP: Map the page in a/x into memory and return a pointer to the page in ; a/x. The contents of the currently mapped page (if any) may be discarded ; by the driver. ; MAP: sta curpage ; Remember the new page clc adc #>BASE sta ptr1+1 ldy #$00 sty ptr1 lda #<window sta ptr2 lda #>window sta ptr2+1 ; Transfer one page jsr transfer ; Transfer one page ; Return the memory window lda #<window ldx #>window ; Return the window address rts ; ------------------------------------------------------------------------ ; USE: Tell the driver that the window is now associated with a given page. USE: sta curpage ; Remember the page lda #<window ldx #>window ; Return the window rts ; ------------------------------------------------------------------------ ; COMMIT: Commit changes in the memory window to extended storage. COMMIT: lda curpage ; Get the current page bmi done ; Jump if no page mapped clc adc #>BASE sta ptr2+1 ldy #$00 sty ptr2 lda #<window sta ptr1 lda #>window sta ptr1+1 ; Transfer one page. Y must be zero on entry transfer: ldx $01 ; Remember c64 control port txa and #$F8 ; Bank out ROMs, I/O sei sta $01 ; Unroll the following loop loop: .repeat 8 lda (ptr1),y sta (ptr2),y iny .endrepeat bne loop ; Restore the old memory configuration, allow interrupts stx $01 ; Restore the old configuration cli ; Done done: rts ; ------------------------------------------------------------------------ ; COPYFROM: Copy from extended into linear memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYFROM: sta ptr3 stx ptr3+1 ; Save the passed em_copy pointer ldy #EM_COPY::OFFS lda (ptr3),y sta ptr1 ldy #EM_COPY::PAGE lda (ptr3),y clc adc #>BASE sta ptr1+1 ; From ldy #EM_COPY::BUF lda (ptr3),y sta ptr2 iny lda (ptr3),y sta ptr2+1 ; To common: ldy #EM_COPY::COUNT+1 lda (ptr3),y ; Get number of pages beq @L2 ; Skip if no full pages sta tmp1 ; Copy full pages allowing interrupts after each page copied ldy #$00 @L1: jsr transfer inc ptr1+1 inc ptr2+1 dec tmp1 bne @L1 ; Copy the remainder of the page @L2: ldy #EM_COPY::COUNT lda (ptr3),y ; Get bytes in last page beq @L4 tax lda $01 ; Remember c64 control port pha and #$F8 ; Bank out ROMs, I/O sei sta $01 ; Transfer the bytes in the last page ldy #$00 @L3: lda (ptr1),y sta (ptr2),y iny dex bne @L3 ; Restore the old memory configuration, allow interrupts pla sta $01 ; Restore the old configuration cli ; Done @L4: rts ; ------------------------------------------------------------------------ ; COPYTO: Copy from linear into extended memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYTO: sta ptr3 stx ptr3+1 ; Save the passed em_copy pointer ldy #EM_COPY::OFFS lda (ptr3),y sta ptr2 ldy #EM_COPY::PAGE lda (ptr3),y clc adc #>BASE sta ptr2+1 ; To ldy #EM_COPY::BUF lda (ptr3),y sta ptr1 iny lda (ptr3),y sta ptr1+1 ; From jmp common ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/emd/c64-ramcart.s��������������������������������������������������������������0000664�0000000�0000000�00000016060�13473601511�0017036�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Extended memory driver for the RamCart 64/128KB cartridge. Driver works ; without problems when statically linked. ; Code is based on GEORAM code by Ullrich von Bassewitz. ; Maciej 'YTM/Elysium' Witkowiak <ytm@elysium.pl> ; 06,22.12.2002 ; .include "zeropage.inc" .include "em-kernel.inc" .include "em-error.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c64_ramcart_emd ; Driver signature .byte $65, $6d, $64 ; "emd" .byte EMD_API_VERSION ; EM API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr PAGECOUNT .addr MAP .addr USE .addr COMMIT .addr COPYFROM .addr COPYTO ; ------------------------------------------------------------------------ ; Constants RAMC_WINDOW = $DF00 ; Address of RamCart window RAMC_PAGE_LO = $DE00 ; Page register low RAMC_PAGE_HI = $DE01 ; Page register high (only for RC128) ; ------------------------------------------------------------------------ ; Data. .bss pagecount: .res 2 ; Number of available pages .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present and determine the amount of ; memory available. ; Must return an EM_ERR_xx code in a/x. ; INSTALL: ldx RAMC_WINDOW cpx RAMC_WINDOW bne @notpresent lda #0 sta RAMC_PAGE_LO sta RAMC_PAGE_HI ldx RAMC_WINDOW cpx RAMC_WINDOW bne @notpresent lda #2 sta RAMC_WINDOW cmp RAMC_WINDOW beq @cont cpx RAMC_WINDOW beq @readonly @cont: ldy #1 sty RAMC_PAGE_HI sty RAMC_WINDOW dey sty RAMC_PAGE_HI iny cpy RAMC_WINDOW beq @rc64 ; we're on rc128 ldx #>512 bne @setsize @rc64: ldx #>256 @setsize: lda #0 sta pagecount stx pagecount+1 lda #<EM_ERR_OK ldx #>EM_ERR_OK rts @notpresent: @readonly: lda #<EM_ERR_NO_DEVICE ldx #>EM_ERR_NO_DEVICE ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; PAGECOUNT: Return the total number of available pages in a/x. ; PAGECOUNT: lda pagecount ldx pagecount+1 rts ; ------------------------------------------------------------------------ ; USE: Tell the driver that the window is now associated with a given page. ; The RamCart cartridge does not copy but actually map the window, so USE is ; identical to MAP. USE = MAP ; ------------------------------------------------------------------------ ; MAP: Map the page in a/x into memory and return a pointer to the page in ; a/x. The contents of the currently mapped page (if any) may be discarded ; by the driver. ; MAP: sta RAMC_PAGE_LO stx RAMC_PAGE_HI lda #<RAMC_WINDOW ldx #>RAMC_WINDOW ; Use the RTS from COMMIT below to save a precious byte of storage ; ------------------------------------------------------------------------ ; COMMIT: Commit changes in the memory window to extended storage. COMMIT: rts ; ------------------------------------------------------------------------ ; COPYFROM: Copy from extended into linear memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYFROM: jsr setup ; Setup is: ; ; - ptr1 contains the struct pointer ; - ptr2 contains the linear memory buffer ; - ptr3 contains -(count-1) ; - tmp1 contains the low page register value ; - tmp2 contains the high page register value ; - X contains the page offset ; - Y contains zero jmp @L5 @L1: lda RAMC_WINDOW,x sta (ptr2),y iny bne @L2 inc ptr2+1 @L2: inx beq @L4 ; Bump count and repeat @L3: inc ptr3 bne @L1 inc ptr3+1 bne @L1 rts ; Bump page register @L4: inc tmp1 bne @L5 inc tmp2 @L5: lda tmp1 sta RAMC_PAGE_LO lda tmp2 sta RAMC_PAGE_HI jmp @L3 ; ------------------------------------------------------------------------ ; COPYTO: Copy from linear into extended memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYTO: jsr setup ; Setup is: ; ; - ptr1 contains the struct pointer ; - ptr2 contains the linear memory buffer ; - ptr3 contains -(count-1) ; - tmp1 contains the low page register value ; - tmp2 contains the high page register value ; - X contains the page offset ; - Y contains zero jmp @L5 @L1: lda (ptr2),y sta RAMC_WINDOW,x iny bne @L2 inc ptr2+1 @L2: inx beq @L4 ; Bump count and repeat @L3: inc ptr3 bne @L1 inc ptr3+1 bne @L1 rts ; Bump page register @L4: inc tmp1 bne @L5 inc tmp2 @L5: lda tmp1 sta RAMC_PAGE_LO lda tmp2 sta RAMC_PAGE_HI jmp @L3 ; ------------------------------------------------------------------------ ; Helper function for COPYFROM and COPYTO: Store the pointer to the request ; structure and prepare data for the copy setup: sta ptr1 stx ptr1+1 ; Save passed pointer ; Get the page number from the struct and adjust it so that it may be used ; with the hardware. That is: lower 6 bits in tmp1, high bits in tmp2. ldy #EM_COPY::PAGE+1 lda (ptr1),y sta tmp2 dey lda (ptr1),y sta tmp1 ; Get the buffer pointer into ptr2 ldy #EM_COPY::BUF lda (ptr1),y sta ptr2 iny lda (ptr1),y sta ptr2+1 ; Get the count, calculate -(count-1) and store it into ptr3 ldy #EM_COPY::COUNT lda (ptr1),y eor #$FF sta ptr3 iny lda (ptr1),y eor #$FF sta ptr3+1 ; Get the page offset into X and clear Y ldy #EM_COPY::OFFS lda (ptr1),y tax ldy #$00 ; Done rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/emd/c64-reu.s������������������������������������������������������������������0000664�0000000�0000000�00000017276�13473601511�0016212�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Extended memory driver for the Commodore REU. Driver works without ; problems when statically linked. ; ; Ullrich von Bassewitz, 2002-11-29 ; .include "zeropage.inc" .include "em-kernel.inc" .include "em-error.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c64_reu_emd ; Driver signature .byte $65, $6d, $64 ; "emd" .byte EMD_API_VERSION ; EM API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr PAGECOUNT .addr MAP .addr USE .addr COMMIT .addr COPYFROM .addr COPYTO ; ------------------------------------------------------------------------ ; Constants REU_STATUS = $DF00 ; Status register REU_COMMAND = $DF01 ; Command register REU_C64ADDR = $DF02 ; C64 base address register REU_REUADDR = $DF04 ; REU base address register REU_COUNT = $DF07 ; Transfer count register REU_IRQMASK = $DF09 ; IRQ mask register REU_CONTROL = $DF0A ; Control register REU_TRIGGER = $FF00 ; REU command trigger OP_COPYFROM = $ED OP_COPYTO = $EC OP_COPYFROM_ALOAD = $B1 OP_COPYTO_ALOAD = $B0 ; ------------------------------------------------------------------------ ; Data. .bss pagecount: .res 2 ; Number of pages available curpage: .res 2 ; Current page number window: .res 256 ; Memory "window" reu_params: .word $0000 ; Host address, lo, hi .word $0000 ; Exp address, lo, hi .byte $00 ; Expansion bank no. .word $0000 ; # bytes to move, lo, hi .byte $00 ; Interrupt mask reg. .byte $00 ; Adress control reg. .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present and determine the amount of ; memory available. ; Must return an EM_ERR_xx code in a/x. ; INSTALL: ldx #$00 ; High byte of return code lda #$55 sta REU_REUADDR cmp REU_REUADDR ; Check for presence of REU bne nodevice asl a ; A = $AA sta REU_REUADDR cmp REU_REUADDR ; Check for presence of REU bne nodevice ; determine the size php sei ldy #$FF loop: sty window jsr reu_size_check_common ldx #OP_COPYTO_ALOAD stx REU_COMMAND dey cpy #$FF bne loop iny size_loop: jsr reu_size_check_common ldx #OP_COPYFROM_ALOAD stx REU_COMMAND cpy window bne size_found iny bne size_loop size_found: plp ldx #$00 cpy #$00 ; too many pages, shave off 2 bne pagecount_ok dex dex dey pagecount_ok: stx pagecount sty pagecount+1 lda #<EM_ERR_OK ldx #>EM_ERR_OK rts ; common REU setup for size check reu_size_check_common: sty REU_REUADDR+2 ldx #<window stx REU_C64ADDR ldx #>window stx REU_C64ADDR+1 ldx #$00 stx REU_REUADDR stx REU_REUADDR+1 stx REU_COUNT+1 stx REU_CONTROL inx stx REU_COUNT rts ; No REU found nodevice: lda #EM_ERR_NO_DEVICE ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; PAGECOUNT: Return the total number of available pages in a/x. ; PAGECOUNT: lda pagecount ldx pagecount+1 rts ; ------------------------------------------------------------------------ ; MAP: Map the page in a/x into memory and return a pointer to the page in ; a/x. The contents of the currently mapped page (if any) may be discarded ; by the driver. ; MAP: sta curpage stx curpage+1 ; Remember the new page ldy #OP_COPYFROM jsr common ; Copy the window lda #<window ldx #>window ; Return the window address done: rts ; ------------------------------------------------------------------------ ; USE: Tell the driver that the window is now associated with a given page. USE: sta curpage stx curpage+1 ; Remember the page lda #<window ldx #>window ; Return the window rts ; ------------------------------------------------------------------------ ; COMMIT: Commit changes in the memory window to extended storage. COMMIT: lda curpage ldx curpage+1 ; Do we have a page mapped? bmi done ; Jump if no page mapped ldy #OP_COPYTO common: sty tmp1 ldy #<window sty REU_C64ADDR ldy #>window sty REU_C64ADDR+1 ldy #0 sty REU_REUADDR+0 sta REU_REUADDR+1 stx REU_REUADDR+2 sty REU_COUNT+0 ldy #1 sty REU_COUNT+1 ; Move 256 bytes bne transfer1 ; Transfer 256 bytes into REU ; ------------------------------------------------------------------------ ; COPYFROM: Copy from extended into linear memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYFROM: ldy #OP_COPYFROM .byte $2C ; ------------------------------------------------------------------------ ; COPYTO: Copy from linear into extended memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYTO: ldy #OP_COPYTO sty tmp1 ; Remember the passed pointer sta ptr1 stx ptr1+1 ; Save the pointer ; The structure passed to the functions has the same layout as the registers ; of the Commodore REU, so register programming is easy. ldy #7-1 @L1: lda (ptr1),y sta REU_C64ADDR,y dey bpl @L1 ; Invalidate the page in the memory window sty curpage+1 ; Y = $FF ; Reload the REU command and start the transfer transfer1: ldy tmp1 ; Transfer subroutine for the REU. Expects command in Y. transfer: sty REU_COMMAND ; Issue command ldy $01 ; Save the value of the c64 control port... tya ; and #$F8 ; Disable ROMs and I/O. sei ; sta $01 lda REU_TRIGGER ; Don't change $FF00 sta REU_TRIGGER ; Start the transfer... sty $01 ; Restore the old configuration cli rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/emd/c64-vdc.s������������������������������������������������������������������0000664�0000000�0000000�00000023634�13473601511�0016166�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Extended memory driver for the VDC RAM available on all C128 machines ; (based on code by Ullrich von Bassewitz) ; Maciej 'YTM/Elysium' Witkowiak <ytm@elysium.pl> ; 06,20.12.2002 ; ; VDC test added by ; Marco van den Heuvel, 2010-01-22 ; .include "zeropage.inc" .include "em-kernel.inc" .include "em-error.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c64_vdc_emd ; Driver signature .byte $65, $6d, $64 ; "emd" .byte EMD_API_VERSION ; EM API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr PAGECOUNT .addr MAP .addr USE .addr COMMIT .addr COPYFROM .addr COPYTO ; ------------------------------------------------------------------------ ; Constants VDC_ADDR_REG = $D600 ; VDC address VDC_DATA_REG = $D601 ; VDC data VDC_DATA_HI = 18 ; used registers VDC_DATA_LO = 19 VDC_CSET = 28 VDC_DATA = 31 ; ------------------------------------------------------------------------ ; Data. .data pagecount: .word 64 ; $0000-$3fff as 16k default curpage: .word $ffff ; currently mapped-in page (invalid) .bss window: .res 256 ; memory window .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present and determine the amount of ; memory available. ; Must return an EM_ERR_xx code in a/x. ; INSTALL: ldx #0 ldy #0 lda #VDC_CSET ; determine size of RAM... sta VDC_ADDR_REG @L0: bit VDC_ADDR_REG bmi @present inx bne @L0 iny bne @L0 lda #<EM_ERR_NO_DEVICE ldx #>EM_ERR_NO_DEVICE rts @present: ldx #VDC_CSET ; determine size of RAM... jsr vdcgetreg sta tmp1 ora #%00010000 jsr vdcputreg ; turn on 64k jsr settestadr1 ; save original value of test byte jsr vdcgetbyte sta tmp2 lda #$55 ; write $55 here ldy #ptr1 jsr test64k ; read it here and there lda #$aa ; write $aa here ldy #ptr2 jsr test64k ; read it here and there jsr settestadr1 lda tmp2 jsr vdcputbyte ; restore original value of test byte lda ptr1 ; do bytes match? cmp ptr1+1 bne @have64k lda ptr2 cmp ptr2+1 bne @have64k ldx #VDC_CSET lda tmp1 jsr vdcputreg ; restore 16/64k flag jmp @endok ; and leave default values for 16k @have64k: lda #<256 ldx #>256 sta pagecount stx pagecount+1 @endok: lda #<EM_ERR_OK ldx #>EM_ERR_OK rts test64k: sta tmp1 sty ptr3 lda #0 sta ptr3+1 jsr settestadr1 lda tmp1 jsr vdcputbyte ; write $55 jsr settestadr1 jsr vdcgetbyte ; read here pha jsr settestadr2 jsr vdcgetbyte ; and there ldy #1 sta (ptr3),y pla dey sta (ptr3),y rts settestadr1: ldy #$02 ; test page 2 (here) .byte $2c settestadr2: ldy #$42 ; or page 64+2 (there) lda #0 jmp vdcsetsrcaddr ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: ;on C128 restore font and clear the screen? rts ; ------------------------------------------------------------------------ ; PAGECOUNT: Return the total number of available pages in a/x. ; PAGECOUNT: lda pagecount ldx pagecount+1 rts ; ------------------------------------------------------------------------ ; MAP: Map the page in a/x into memory and return a pointer to the page in ; a/x. The contents of the currently mapped page (if any) may be discarded ; by the driver. ; MAP: sta curpage stx curpage+1 sta ptr1+1 ldy #0 sty ptr1 lda #<window sta ptr2 lda #>window sta ptr2+1 jsr transferin lda #<window ldx #>window rts ; copy a single page from (ptr1):VDCRAM to (ptr2):RAM transferin: lda ptr1 ldy ptr1+1 jsr vdcsetsrcaddr ; set source address in VDC ldy #0 ldx #VDC_DATA stx VDC_ADDR_REG @L0: bit VDC_ADDR_REG bpl @L0 lda VDC_DATA_REG ; get 2 bytes at a time to speed-up sta (ptr2),y ; (in fact up to 8 bytes could be fetched with special VDC config) iny lda VDC_DATA_REG sta (ptr2),y iny bne @L0 rts ; ------------------------------------------------------------------------ ; USE: Tell the driver that the window is now associated with a given page. USE: sta curpage stx curpage+1 ; Remember the page lda #<window ldx #>window ; Return the window done: rts ; ------------------------------------------------------------------------ ; COMMIT: Commit changes in the memory window to extended storage. COMMIT: lda curpage ; jump if no page mapped ldx curpage+1 bmi done sta ptr1+1 ldy #0 sty ptr1 lda #<window sta ptr2 lda #>window sta ptr2+1 ; fall through to transferout ; copy a single page from (ptr2):RAM to (ptr1):VDCRAM transferout: lda ptr1 ldy ptr1+1 jsr vdcsetsrcaddr ; set source address in VDC ldy #0 ldx #VDC_DATA stx VDC_ADDR_REG @L0: bit VDC_ADDR_REG bpl @L0 lda (ptr2),y ; speedup does not work for writing sta VDC_DATA_REG iny bne @L0 rts ; ------------------------------------------------------------------------ ; COPYFROM: Copy from extended into linear memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYFROM: jsr setup beq @L2 ; Skip if no full pages ; Copy full pages @L1: jsr transferin inc ptr1+1 inc ptr2+1 dec tmp1 bne @L1 ; Copy the remainder of the page @L2: ldy #EM_COPY::COUNT lda (ptr3),y ; Get bytes in last page beq @L4 sta tmp1 ; Transfer the bytes in the last page ldy #0 @L3: jsr vdcgetbyte sta (ptr2),y iny dec tmp1 lda tmp1 bne @L3 @L4: rts ; ------------------------------------------------------------------------ ; COPYTO: Copy from linear into extended memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYTO: jsr setup beq @L2 ; Skip if no full pages ; Copy full pages @L1: jsr transferout inc ptr1+1 inc ptr2+1 dec tmp1 bne @L1 ; Copy the remainder of the page @L2: ldy #EM_COPY::COUNT lda (ptr3),y ; Get bytes in last page beq @L4 sta tmp1 ; Transfer the bytes in the last page ldy #0 @L3: lda (ptr2),y jsr vdcputbyte iny dec tmp1 lda tmp1 bne @L3 @L4: rts ;------------------------------------------------------------------------- ; Helper functions to handle VDC ram ; vdcsetsrcaddr: ldx #VDC_DATA_LO stx VDC_ADDR_REG @L0: bit VDC_ADDR_REG bpl @L0 sta VDC_DATA_REG dex tya stx VDC_ADDR_REG sta VDC_DATA_REG rts vdcgetbyte: ldx #VDC_DATA vdcgetreg: stx VDC_ADDR_REG @L0: bit VDC_ADDR_REG bpl @L0 lda VDC_DATA_REG rts vdcputbyte: ldx #VDC_DATA vdcputreg: stx VDC_ADDR_REG @L0: bit VDC_ADDR_REG bpl @L0 sta VDC_DATA_REG rts ; ------------------------------------------------------------------------ ; Helper function for COPYFROM and COPYTO: Store the pointer to the request ; structure and prepare data for the copy ; setup: sta ptr3 stx ptr3+1 ; Save the passed em_copy pointer ldy #EM_COPY::OFFS lda (ptr3),y sta ptr1 ldy #EM_COPY::PAGE lda (ptr3),y sta ptr1+1 ; From ldy #EM_COPY::BUF lda (ptr3),y sta ptr2 iny lda (ptr3),y sta ptr2+1 ; To ldy #EM_COPY::COUNT+1 lda (ptr3),y ; Get number of pages sta tmp1 rts ����������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/emd/dtv-himem.s����������������������������������������������������������������0000664�0000000�0000000�00000015452�13473601511�0016711�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Extended memory driver for the C64 D2TV (the second or PAL version). ; Driver works without problems when statically linked. ; ; Ullrich von Bassewitz, 2005-11-27 ; .include "zeropage.inc" .include "em-kernel.inc" .include "em-error.inc" .import _get_ostype .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _dtv_himem_emd ; Driver signature .byte $65, $6d, $64 ; "emd" .byte EMD_API_VERSION ; EM API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr PAGECOUNT .addr MAP .addr USE .addr COMMIT .addr COPYFROM .addr COPYTO ; ------------------------------------------------------------------------ ; Constants OP_COPYFROM = %00001101 OP_COPYTO = %00001111 START_BANK = 2 ; Start at $20000 PAGES = (2048 - 128) * 4 ; ------------------------------------------------------------------------ ; Data. .bss window: .res 256 ; Memory "window" .data ; The MAP and COMMIT entries will actually call COPYFROM/COPYTO with ; a pointer to the following data structure: dma_params: .word window ; Host address .byte 0 ; Offset in page curpage: .word $0000 ; Page .word .sizeof (window); # bytes to move, lo, hi .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present and determine the amount of ; memory available. ; Must return an EM_ERR_xx code in a/x. ; INSTALL: ; Check for a DTV ldx #1 stx $d03f ldx $d040 cpx $d000 bne @present inc $d000 cpx $d040 beq @present dec $d000 ; DTV not found lda #<EM_ERR_NO_DEVICE ldx #>EM_ERR_NO_DEVICE rts @present: ldx #$FF stx curpage+1 ; Invalidate curpage inx ; X = 0 txa ; A/X = EM_ERR_OK ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; PAGECOUNT: Return the total number of available pages in a/x. ; PAGECOUNT: lda #<PAGES ldx #>PAGES rts ; ------------------------------------------------------------------------ ; MAP: Map the page in a/x into memory and return a pointer to the page in ; a/x. The contents of the currently mapped page (if any) may be discarded ; by the driver. ; MAP: sta curpage stx curpage+1 ; Remember the new page lda #<dma_params ldx #>dma_params jsr COPYFROM ; Copy data into the window lda #<window ldx #>window ; Return the window address done: rts ; ------------------------------------------------------------------------ ; USE: Tell the driver that the window is now associated with a given page. USE: sta curpage stx curpage+1 ; Remember the page lda #<window ldx #>window ; Return the window rts ; ------------------------------------------------------------------------ ; COMMIT: Commit changes in the memory window to extended storage. COMMIT: lda curpage+1 ; Do we have a page mapped? bmi done ; Jump if no page mapped lda #<dma_params ldx #>dma_params ; Run into COPYTO ; ------------------------------------------------------------------------ ; COPYTO: Copy from linear into extended memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYTO: sta ptr1 stx ptr1+1 ; Save the pointer ldx #OP_COPYTO ; Load the command bne transfer ; ------------------------------------------------------------------------ ; COPYFROM: Copy from extended into linear memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYFROM: sta ptr1 stx ptr1+1 ; Save the pointer ldx #OP_COPYFROM ; DTV DMA transfer routine. Expects the command in X. ; NOTE: We're using knowledge about field order in the EM_COPY struct here! transfer: jsr WAIT ; Wait until DMA is finished ; Modulo disable ldy #$00 sty $d31e ; Setup the target address and the source and target steps. Y contains zero, ; which is EM_COPY::BUF. sty $d307 ; Source step high = 0 sty $d309 ; Dest step high = 0 lda (ptr1),y sta $d303 ; Dest address low iny ; Y = 1 sty $d306 ; Source step low = 1 sty $d308 ; Dest step low = 1 lda (ptr1),y sta $d304 lda #$40 ; Dest is always RAM, start at $00000 sta $d305 ; Setup the source address. Incrementing Y will make it point to EM_COPY::OFFS. ; We will allow page numbers higher than PAGES and map them to ROM. This will ; allow reading the ROM by specifying a page starting with PAGES. iny ; EM_COPY::OFFS lda (ptr1),y sta $d300 iny ; EM_COPY::PAGE lda (ptr1),y sta $d301 iny lda (ptr1),y adc #START_BANK ; Carry clear here from WAIT and #$3f cmp #>PAGES+START_BANK ; Valid range? bcs @L1 ; Jump if no ora #$40 ; Address RAM @L1: sta $d302 ; Length iny ; EM_COPY::COUNT lda (ptr1),y sta $d30a iny lda (ptr1),y sta $d30b ; Start DMA stx $d31f ; Wait until DMA is done WAIT: lda $d31f lsr a bcs WAIT rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/extra/�������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015202�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/extra/soft80.s�����������������������������������������������������������������0000664�0000000�0000000�00000004727�13473601511�0016523�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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_cpeekc.s .import soft80_cpeekc .export _cpeekc := soft80_cpeekc ; cpeekc.s ; soft80_cpeekcolor.s .import soft80_cpeekcolor .export _cpeekcolor := soft80_cpeekcolor ; cpeekcolor.s ; soft80_cpeekrevers.s .import soft80_cpeekrevers .export _cpeekrevers := soft80_cpeekrevers ; cpeekrevers.s ; soft80_cpeeks.s .import soft80_cpeeks .export _cpeeks := soft80_cpeeks ; cpeeks.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 .import return1 .export _doesclrscrafterexit := return1 �����������������������������������������cc65-2.18/libsrc/c64/extra/soft80mono.s�������������������������������������������������������������0000664�0000000�0000000�00000005311�13473601511�0017402�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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_cpeekc.s .import soft80_cpeekc .export _cpeekc := soft80_cpeekc ; cpeekc.s ; soft80mono_cpeekcolor.s .import soft80mono_cpeekcolor .export _cpeekcolor := soft80mono_cpeekcolor ; cpeekcolor.s ; soft80mono_cpeekrevers.s .import soft80_cpeekrevers .export _cpeekrevers := soft80_cpeekrevers ; cpeekrevers.s ; soft80mono_cpeeks.s .import soft80_cpeeks .export _cpeeks := soft80_cpeeks ; cpeeks.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 .import return1 .export _doesclrscrafterexit := return1 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/extra/tgimousedata.s�����������������������������������������������������������0000664�0000000�0000000�00000001251�13473601511�0020053�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; C64 sprite addresses for the TGI mouse pointer ; ; 2017-01-13, Greg King ; In order to provide a visible mouse pointer during TGI's graphics mode, ; the object file "c64-tgimousedata.o" must be linked explicitly into ; a program file. Example: ; ; cl65 -t c64 -o program-file main-code.c subroutines.s c64-tgimousedata.o ; ; Note: Currently, a program cannot have default ; pointers for both text and graphic modes. ; The TGI graphics mode uses VIC-II's 16K bank number three. ; ; Address of the TGI bitmap's color RAM COLORMAP := $D000 .export mcb_spritepointer := COLORMAP + $03F8 .export mcb_spritememory := COLORMAP + $0400 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/get_ostype.s�������������������������������������������������������������������0000664�0000000�0000000�00000001161�13473601511�0016424�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Stefan Haubenthal, Jul 10 2003 ; ; C64DTV detection by ; Marco van den Heuvel, 2010-01-28 ; ; unsigned char get_ostype(void) ; ; $AA US ; $64 PET-64 ; $43 SX-64 ; $03 EU_NEW ; $00 EU_OLD ; $FF C64DTV ; .export _get_ostype .proc _get_ostype ldx #0 ; Clear high byte ldy #1 sty $d03f ldy $d040 cpy $d000 bne @c64dtv inc $d000 cpy $d040 beq @c64dtv ; Normal C64 lda $ff80 rts ; C64 DTV @c64dtv: stx $d03f lda #$ff rts .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/get_tv.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000556�13473601511�0015541�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2002-12-03 ; ; unsigned char get_tv (void); ; /* Return the video mode the machine is using */ ; .include "c64.inc" .include "get_tv.inc" ;-------------------------------------------------------------------------- ; _get_tv .proc _get_tv lda PALFLAG ldx #0 rts .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/gettime.s����������������������������������������������������������������������0000664�0000000�0000000�00000003640�13473601511�0015704�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Stefan Haubenthal, 27.7.2009 ; Oliver Schmidt, 14.8.2018 ; ; int __fastcall__ clock_gettime (clockid_t clk_id, struct timespec *tp); ; .include "time.inc" .include "c64.inc" .importzp sreg, tmp1, tmp2 .import pushax, pusheax, tosmul0ax, steaxspidx, incsp1, return0 .import TM, load_tenth ;---------------------------------------------------------------------------- .code .proc _clock_gettime jsr pushax jsr pushax lda CIA1_TODHR sed tax ; Save PM flag and #%01111111 cmp #$12 ; 12 AM/PM bcc @L1 sbc #$12 @L1: inx ; Get PM flag bpl @L2 clc adc #$12 @L2: cld jsr BCD2dec sta TM + tm::tm_hour lda CIA1_TODMIN jsr BCD2dec sta TM + tm::tm_min lda CIA1_TODSEC jsr BCD2dec sta TM + tm::tm_sec lda #<TM ldx #>TM jsr _mktime ldy #timespec::tv_sec jsr steaxspidx ; Pops address pushed by 2. pushax jsr load_tenth jsr pusheax lda CIA1_TOD10 ldx #>$0000 jsr tosmul0ax ldy #timespec::tv_nsec jsr steaxspidx ; Pops address pushed by 1. pushax jsr incsp1 jmp return0 .endproc ;---------------------------------------------------------------------------- ; dec = (((BCD>>4)*10) + (BCD&0xf)) .proc BCD2dec tax and #%00001111 sta tmp1 txa and #%11110000 ; *16 lsr ; *8 sta tmp2 lsr lsr ; *2 adc tmp2 ; = *10 adc tmp1 rts .endproc ������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/irq.s��������������������������������������������������������������������������0000664�0000000�0000000�00000002045�13473601511�0015037�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; IRQ handling (C64 version) ; .export initirq, doneirq .import callirq .include "c64.inc" ; ------------------------------------------------------------------------ .segment "ONCE" initirq: lda IRQVec ldx IRQVec+1 sta IRQInd+1 stx IRQInd+2 lda #<IRQStub ldx #>IRQStub jmp setvec ; ------------------------------------------------------------------------ .code doneirq: lda IRQInd+1 ldx IRQInd+2 setvec: sei sta IRQVec stx IRQVec+1 cli rts ; ------------------------------------------------------------------------ .segment "LOWCODE" IRQStub: cld ; Just to be sure jsr callirq ; Call the functions jmp IRQInd ; Jump to the saved IRQ vector ; ------------------------------------------------------------------------ .data IRQInd: jmp $0000 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/joy/���������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014660�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/joy/c64-hitjoy.s���������������������������������������������������������������0000664�0000000�0000000�00000012061�13473601511�0016744�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; DXS/HIT-4 Player joystick driver for the C64 ; ; Groepaz/Hitmen, 2002-12-23 ; obviously based on Ullrichs driver :) ; .include "zeropage.inc" .include "joy-kernel.inc" .include "joy-error.inc" .include "c64.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c64_hitjoy_joy ; Driver signature .byte $6A, $6F, $79 ; "joy" .byte JOY_API_VERSION ; Driver API version number ; Library reference .addr $0000 ; Jump table. .addr INSTALL .addr UNINSTALL .addr COUNT .addr READ ; ------------------------------------------------------------------------ ; Constants JOY_COUNT = 4 ; Number of joysticks we support ; ------------------------------------------------------------------------ ; Data. Written in the IRQ, read by the READ routine .bss temp3: .byte 0 temp4: .byte 0 .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 ; ------------------------------------------------------------------------ ; UNINSTALL 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. ; COUNT: lda #<JOY_COUNT ldx #>JOY_COUNT rts ; ------------------------------------------------------------------------ ; READ: Read a particular joystick passed in A. ; readadapter: sei ; cia 2 setup ldy #$00 ; port b direction sty $dd03 ; => input sty $dd05 ; cia2 timer a highbyte sty $dc05 ; cia1 timer a highbyte iny sty $dd04 ; cia2 timer a lowbyte sty $dc04 ; cia1 timer a lowbyte lda #%00010001 sta $dd0e ; control register a ; timer: start ; continous ; forced load ; serial port: input ; cia 1 setup lda #%01010001 sta $dc0e ; control register a ; timer: start ; continous ; forced load ; serial port: output ; read directions 3 lda $dd01 ;read cia 2 port b and #$0f sta temp3 ; read button 3 lda $dd02 ;cia 2 port a and #%11111011 ;data direction sta $dd02 ;=> bit 2 input lda $dd00 ;read cia 2 p.A and #%00000100 ;check bit 2 asl a asl a ora temp3 sta temp3 ; read directions 4 lda $dd01 ;read cia 2 port b lsr a lsr a lsr a lsr a sta temp4 ; read button 4 ldx #$ff ;serial data register stx $dc0c ;=> writing $ff causes ;cia to output some ;count signals at cnt1 ldx $dd0c ;read cia 2 serial in beq fire ;button press if zero lda temp4 ora #%00010000 sta temp4 fire: ; FIXME: to be really 100% correct this should restore the correct timer ; values for the respective machine (PAL: $4025, NTSC: $4295) ; however, this should hardly be a problem in a real world program lda #$41 sta $dc05 lda #0 sta $dc04 cli rts READ: pha jsr readadapter pla tax ; Joystick number into X bne joy2 ; Read joystick 1 joy1: lda #$7F sei sta CIA1_PRA lda CIA1_PRB cli and #$1F eor #$1F rts ; Read joystick 2 joy2: dex bne joy3 ; ldx #0 lda #$E0 ldy #$FF sei sta CIA1_DDRA lda CIA1_PRA sty CIA1_DDRA cli and #$1F eor #$1F rts ; Read joystick 3 joy3: dex bne joy4 lda temp3 eor #$1F rts ; Read joystick 4 joy4: lda temp4 eor #$1F ldx #0 rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/joy/c64-numpad.s���������������������������������������������������������������0000664�0000000�0000000�00000010452�13473601511�0016724�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Joystick driver using C128 number pad in 64 mode. ; May be used multiple times when linked to the statically application. ; ; Stefan Haubenthal, 2004-01-26 ; Based on Ullrich von Bassewitz, 2002-12-20 ; .include "zeropage.inc" .include "joy-kernel.inc" .include "joy-error.inc" .include "c64.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c64_numpad_joy ; Driver signature .byte $6A, $6F, $79 ; "joy" .byte JOY_API_VERSION ; Driver API version number ; Library reference .addr $0000 ; Jump table. .addr INSTALL .addr UNINSTALL .addr COUNT .addr READ ; ------------------------------------------------------------------------ ; Constants JOY_COUNT = 1 ; Number of joysticks we support ; ------------------------------------------------------------------------ ; Data. .rodata ; <U>p '8' key ; <D>own '2' key ; <L>eft '4' key ; <R>ight '6' key ; <B>utton '5' or ENTER key masktable: ; Input: LDRBU ; Output: BRLDU .byte %00000000 ; $00 .byte %00000001 ; $01 .byte %00010000 ; $02 .byte %00010001 ; $03 .byte %00001000 ; $04 .byte %00001001 ; $05 .byte %00011000 ; $06 .byte %00011001 ; $07 .byte %00000010 ; $08 .byte %00000011 ; $09 .byte %00010010 ; $0A .byte %00010011 ; $0B .byte %00001010 ; $0C .byte %00001011 ; $0D .byte %00011010 ; $0E .byte %00011011 ; $0F .byte %00000100 ; $10 .byte %00000101 ; $11 .byte %00010100 ; $12 .byte %00010101 ; $13 .byte %00001100 ; $14 .byte %00001101 ; $15 .byte %00011100 ; $16 .byte %00011101 ; $17 .byte %00000110 ; $18 .byte %00000111 ; $19 .byte %00010110 ; $1A .byte %00010111 ; $1B .byte %00001110 ; $1C .byte %00001111 ; $1D .byte %00011110 ; $1E .byte %00011111 ; $1F .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 ; Assume we have a joystick ldx VIC_CLK_128 ; Test for a C128 cpx #$FF bne @C128 ; Jump if we have one lda #JOY_ERR_NO_DEVICE ; No C128 -> no numpad @C128: ldx #0 ; Set high byte ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; COUNT: Return the total number of available joysticks in a/x. ; COUNT: lda #JOY_COUNT ldx #0 rts ; ------------------------------------------------------------------------ ; READ: Read a particular joystick passed in A. ; READ: tax ; Clear high byte lda #$FD ; For ENTER and '6' ldy #$FE ; For '8', '5', '2', '4' sei sta VIC_KBD_128 lda CIA1_PRB and #%00110000 eor #%00110000 lsr ; Map ENTER ... lsr ; ... onto '5' sty VIC_KBD_128 eor CIA1_PRB iny sty VIC_KBD_128 ; Reset to $FF cli and #%00111110 eor #%00111110 lsr tay lda masktable,y ; Convert LDRBU to BRLDU rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/joy/c64-ptvjoy.s���������������������������������������������������������������0000664�0000000�0000000�00000006346�13473601511�0017002�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; PTV-4 Player joystick driver for the C64 ; ; Groepaz/Hitmen, 2002-12-23 ; obviously based on Ullrichs driver :) ; .include "zeropage.inc" .include "joy-kernel.inc" .include "joy-error.inc" .include "c64.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c64_ptvjoy_joy ; Driver signature .byte $6A, $6F, $79 ; "joy" .byte JOY_API_VERSION ; Driver API version number ; Library reference .addr $0000 ; Jump table. .addr INSTALL .addr UNINSTALL .addr COUNT .addr READ ; ------------------------------------------------------------------------ ; 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 ; ------------------------------------------------------------------------ ; UNINSTALL 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. ; COUNT: lda #<JOY_COUNT ldx #>JOY_COUNT rts ; ------------------------------------------------------------------------ ; READ: Read a particular joystick passed in A. ; READ: tax ; Joystick number into X bne joy2 ; Read joystick 1 joy1: lda #$7F sei sta CIA1_PRA lda CIA1_PRB cli and #$1F eor #$1F rts ; Read joystick 2 joy2: dex bne joy3 lda #$E0 ldy #$FF sei sta CIA1_DDRA lda CIA1_PRA sty CIA1_DDRA cli and #$1F eor #$1F rts ; Read joystick 3 joy3: lda #%10000000 ; cia 2 port B Data-Direction sta CIA2_DDRB ; bit 7: out bit 6-0: in dex bne joy4 lda #$80 ; cia 2 port B read/write sta CIA2_PRB ; (output one at PB7) lda CIA2_PRB ; cia 2 port B read/write and #$1F ; get bit 4-0 (PB4-PB0) eor #$1F rts ; Read joystick 4 joy4: lda #$00 ; cia 2 port B read/write sta CIA2_PRB ; (output zero at PB7) lda CIA2_PRB ; cia 2 port B read/write and #$0F ; get bit 3-0 (PB3-PB0) sta tmp1 ; joy 4 directions lda CIA2_PRB ; cia 2 port B read/write and #%00100000 ; get bit 5 (PB5) lsr ora tmp1 eor #$1F ldx #0 rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/joy/c64-stdjoy.s���������������������������������������������������������������0000664�0000000�0000000�00000004747�13473601511�0016766�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Standard joystick driver for the C64. May be used multiple times when linked ; to the statically application. ; ; Ullrich von Bassewitz, 2002-12-20 ; .include "zeropage.inc" .include "joy-kernel.inc" .include "joy-error.inc" .include "c64.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c64_stdjoy_joy ; Driver signature .byte $6A, $6F, $79 ; "joy" .byte JOY_API_VERSION ; Driver API version number ; Library reference .addr $0000 ; Jump table. .addr INSTALL .addr UNINSTALL .addr COUNT .addr READ ; ------------------------------------------------------------------------ ; Constants JOY_COUNT = 2 ; Number of joysticks we support ; ------------------------------------------------------------------------ ; Data. .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 ; ------------------------------------------------------------------------ ; UNINSTALL 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. ; COUNT: lda #<JOY_COUNT ldx #>JOY_COUNT rts ; ------------------------------------------------------------------------ ; READ: Read a particular joystick passed in A. ; READ: tax ; Joystick number into X bne joy2 ; Read joystick 1 joy1: lda #$7F sei sta CIA1_PRA lda CIA1_PRB cli and #$1F eor #$1F rts ; Read joystick 2 joy2: ldx #0 lda #$E0 ldy #$FF sei sta CIA1_DDRA lda CIA1_PRA sty CIA1_DDRA cli and #$1F eor #$1F rts �������������������������cc65-2.18/libsrc/c64/joy_stat_stddrv.s��������������������������������������������������������������0000664�0000000�0000000�00000000354�13473601511�0017467�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Address of the static standard joystick driver ; ; Oliver Schmidt, 2012-11-01 ; ; const void joy_static_stddrv[]; ; .export _joy_static_stddrv .import _c64_stdjoy_joy .rodata _joy_static_stddrv := _c64_stdjoy_joy ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/joy_stddrv.s�������������������������������������������������������������������0000664�0000000�0000000�00000000277�13473601511�0016440�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Name of the standard joystick driver ; ; Ullrich von Bassewitz, 2002-12-21 ; ; const char joy_stddrv[]; ; .export _joy_stddrv .rodata _joy_stddrv: .asciiz "c64-stdjoy.joy" ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/kbhit.s������������������������������������������������������������������������0000664�0000000�0000000�00000000534�13473601511�0015346�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; unsigned char kbhit (void); ; .export _kbhit .include "c64.inc" .proc _kbhit ldx #0 ; High byte of return is always zero lda KEY_COUNT ; Get number of characters beq L9 lda #1 L9: rts .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/kbrepeat.s���������������������������������������������������������������������0000664�0000000�0000000�00000000472�13473601511�0016043�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; unsigned char __fastcall__ kbrepeat (unsigned char mode); ; .export _kbrepeat .include "c64.inc" _kbrepeat: ldx KBDREPEAT ; get old value sta KBDREPEAT ; store new value txa ; return old value ldx #0 rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/kernal.s�����������������������������������������������������������������������0000664�0000000�0000000�00000002343�13473601511�0015521�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 19.11.2002 ; ; C64 kernal functions ; .include "cbm_kernal.inc" .export CINT .export IOINIT .export RAMTAS .export RESTOR .export VECTOR .export SETMSG .export SECOND .export TKSA .export MEMTOP .export MEMBOT .export SCNKEY .export SETTMO .export ACPTR .export CIOUT .export UNTLK .export UNLSN .export LISTEN .export TALK .export READST .export SETLFS .export SETNAM .export OPEN .export CLOSE .export CHKIN .export CKOUT .export CLRCH .export BASIN .export BSOUT .export LOAD .export SAVE .export SETTIM .export RDTIM .export STOP .export GETIN .export CLALL .export UDTIM .export SCREEN .export IOBASE ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/kplot.s������������������������������������������������������������������������0000664�0000000�0000000�00000000743�13473601511�0015400�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2002-12-09, 2009-09-27 ; ; PLOT replacement function for the C64. The kernal function in the -02 kernals ; does not set the pointer to the color RAM correctly, so we need to fix that. ; .export PLOT .proc PLOT bcs @L1 jsr $FFF0 ; Set cursor position jmp $EA24 ; Set pointer to color RAM @L1: jmp $FFF0 ; Get cursor position .endproc �����������������������������cc65-2.18/libsrc/c64/libref.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000511�13473601511�0015503�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2013-05-31, Oliver Schmidt ; 2013-06-11, Greg King ; .export em_libref .export joy_libref .export ser_libref .export tgi_libref .import _exit em_libref := _exit joy_libref := _exit ser_libref := _exit tgi_libref := _exit ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/mainargs.s���������������������������������������������������������������������0000664�0000000�0000000�00000007763�13473601511�0016061�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; mainargs.s ; ; Ullrich von Bassewitz, 2003-03-07 ; Based on code from Stefan A. Haubenthal, <polluks@web.de> ; 2003-05-18, Greg King ; 2004-04-28, 2005-02-26, Ullrich von Bassewitz ; ; Scan a group of arguments that are in BASIC's input-buffer. ; Build an array that points to the beginning of each argument. ; Send, to main(), that array and the count of the arguments. ; ; Command-lines look like these lines: ; ; run ; run : rem ; run:rem arg1 " arg 2 is quoted " arg3 "" arg5 ; ; "run" and "rem" are entokenned; the args. are not. Leading and trailing ; spaces outside of quotes are ignored. ; ; TO-DO: ; - The "file-name" might be a path-name; don't copy the directory-components. ; - Add a control-character quoting mechanism. .constructor initmainargs, 24 .import __argc, __argv .include "c64.inc" MAXARGS = 10 ; Maximum number of arguments allowed REM = $8f ; BASIC token-code NAME_LEN = 16 ; Maximum length of command-name ; Get possible command-line arguments. Goes into the special ONCE segment, ; which may be reused after the startup code is run .segment "ONCE" initmainargs: ; Assume that the program was loaded, a moment ago, by the traditional LOAD ; statement. Save the "most-recent filename" as argument #0. lda #0 ; The terminating NUL character ldy FNAM_LEN cpy #NAME_LEN + 1 bcc L1 ldy #NAME_LEN ; Limit the length bne L1 ; Branch always L0: lda (FNAM),y L1: sta name,y dey bpl L0 inc __argc ; argc always is equal to, at least, 1 ; Find the "rem" token. ldx #0 L2: lda BASIC_BUF,x beq done ; No "rem," no args. inx cmp #REM bne L2 ldy #1 * 2 ; Find the next argument next: lda BASIC_BUF,x beq done ; End of line reached inx cmp #' ' ; Skip leading spaces 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 ; will check now for a quoted argument, in which case we will have to skip this ; first character. found: cmp #'"' ; Is the argument quoted? beq setterm ; Jump if so dex ; Reset pointer to first argument character lda #' ' ; A space ends the argument setterm:sta term ; Set end of argument marker ; Now store a pointer to the argument into the next slot. Since the BASIC ; input buffer is located at the start of a RAM page, no calculations are ; necessary. txa ; Get low byte sta argv,y ; argv[y]= &arg iny lda #>BASIC_BUF sta argv,y iny inc __argc ; Found another arg ; Search for the end of the argument argloop:lda BASIC_BUF,x beq done inx cmp term bne argloop ; 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 #0 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? bcc 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 .segment "INIT" term: .res 1 name: .res NAME_LEN + 1 .data ; char* argv[MAXARGS+1]={name}; argv: .addr name .res MAXARGS * 2 �������������cc65-2.18/libsrc/c64/mcbdefault.s�������������������������������������������������������������������0000664�0000000�0000000�00000007706�13473601511�0016363�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Default mouse callbacks for the C64 ; ; Ullrich von Bassewitz, 2004-03-20 ; ; All functions in this module should be interrupt safe, because they may ; 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" .macpack generic ; Sprite definitions. The first value can be changed to adjust the number ; of the sprite used for the mouse. All others depend on this value. MOUSE_SPR = 0 ; Sprite used for the mouse 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 "ONCE" 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 sta VIC_SPR_ENA rts ; -------------------------------------------------------------------------- ; Show the mouse pointer. Always called with interrupts disabled. show: lda #MOUSE_SPR_MASK ora VIC_SPR_ENA sta VIC_SPR_ENA ; Fall through ; -------------------------------------------------------------------------- ; Prepare to move the mouse pointer. Always called with interrupts disabled. prep: ; Fall through ; -------------------------------------------------------------------------- ; Draw the mouse pointer. Always called with interrupts disabled. draw: rts ; -------------------------------------------------------------------------- ; Move the mouse pointer X position to the value in a/x. Always called with ; interrupts disabled. movex: ; Add the X correction and set the low byte. This frees A. add #24 ; X correction sta VIC_SPR_X ; Set the high byte txa adc #0 bne @L1 ; Branch if high byte not zero lda VIC_SPR_HI_X ; Get high X bits of all sprites and #MOUSE_SPR_NMASK ; Clear high bit for sprite sta VIC_SPR_HI_X rts @L1: lda VIC_SPR_HI_X ; Get high X bits of all sprites ora #MOUSE_SPR_MASK ; Set high bit for sprite sta VIC_SPR_HI_X rts ; -------------------------------------------------------------------------- ; Move the mouse pointer Y position to the value in a/x. Always called with ; interrupts disabled. movey: add #50 ; Y correction (first visible line) sta VIC_SPR_Y ; Set Y position rts ; -------------------------------------------------------------------------- ; Callback structure .rodata _mouse_def_callbacks: .addr hide .addr show .addr prep .addr draw .addr movex .addr movey ����������������������������������������������������������cc65-2.18/libsrc/c64/mcbspritedata.s����������������������������������������������������������������0000664�0000000�0000000�00000000217�13473601511�0017065�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; VIC sprite data for the mouse pointer .export mcb_spritememory := $0340 .export mcb_spritepointer := $07F8 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/mou/���������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014657�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/mou/c64-1351.s�����������������������������������������������������������������0000664�0000000�0000000�00000034117�13473601511�0016034�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Driver for the 1351 proportional mouse. Parts of the code are from ; the Commodore 1351 mouse users guide. ; ; 2009-09-26, Ullrich von Bassewitz ; 2010-02-06, Greg King ; ; The driver prevents the keyboard from interfering by changing the ; keyboard's output port into an input port while the driver reads its ; controller device. That disables a wire that is left active by the ; Kernal. That wire is used by the STOP-key to break out of BASIC ; programs -- CC65 programs don't use that feature. The wire is shared ; by these keys: STOP, "Q", Commodore, Space, "2", CTRL, Left-Arrow, and ; "1". I listed them, in order, from bit 7 over to bit 0. The ; rightmost five keys can look like joystick switches. ; ; The driver prevents the mouse/joystick from interfering by "blinding" ; the keyboard scanner while any button/switch is active. It changes ; the input port into an output port, then stores all zero-bits in that ; port's latch. Reading from an output port sees the bitwise-AND of the ; latch and the input signals. Therefore, the scanner thinks that eight ; keys are being pushed at the same time. It doesn't know what to do ; about that condition; so, it does nothing. The driver lets the ; scanner see normally, again, when no buttons/switches are active. ; .include "zeropage.inc" .include "mouse-kernel.inc" .include "c64.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c64_1351_mou HEADER: ; Driver signature .byte $6d, $6f, $75 ; "mou" .byte MOUSE_API_VERSION ; Mouse driver API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr HIDE .addr SHOW .addr SETBOX .addr GETBOX .addr MOVE .addr BUTTONS .addr POS .addr INFO .addr IOCTL .addr IRQ ; Mouse driver flags .byte MOUSE_FLAG_LATE_IRQ ; Callback table, set by the kernel before INSTALL is called CHIDE: jmp $0000 ; Hide the cursor CSHOW: jmp $0000 ; Show the cursor CPREP: jmp $0000 ; Prepare to move the cursor CDRAW: jmp $0000 ; Draw the cursor CMOVEX: jmp $0000 ; Move the cursor to X coord CMOVEY: jmp $0000 ; Move the cursor to Y coord ;---------------------------------------------------------------------------- ; Constants SCREEN_HEIGHT = YSIZE * 8 - 1 ; (origin is zero) SCREEN_WIDTH = XSIZE * 8 - 1 ;---------------------------------------------------------------------------- ; Global variables. The bounding box values are sorted so that they can be ; written with the least effort in the SETBOX and GETBOX routines, so don't ; reorder them. .bss Vars: OldPotX: .res 1 ; Old hw counter values OldPotY: .res 1 XPos: .res 2 ; Current mouse position, X YPos: .res 2 ; Current mouse position, Y XMin: .res 2 ; X1 value of bounding box YMin: .res 2 ; Y1 value of bounding box XMax: .res 2 ; X2 value of bounding box YMax: .res 2 ; Y2 value of bounding box Buttons: .res 1 ; button status bits OldValue: .res 1 ; Temp for MoveCheck routine NewValue: .res 1 ; Temp for MoveCheck routine .rodata ; Default values for above variables ; (We use ".proc" because we want to define both a label and a scope.) .proc DefVars .byte 0, 0 ; OldPotX/OldPotY .word SCREEN_WIDTH/2 ; XPos .word SCREEN_HEIGHT/2 ; YPos .word 0 ; XMin .word 0 ; YMin .word SCREEN_WIDTH ; XMax .word SCREEN_HEIGHT ; YMax .byte %00000000 ; Buttons .endproc .code ;---------------------------------------------------------------------------- ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present. ; Must return an MOUSE_ERR_xx code in a/x. INSTALL: ; Initialize variables. Just copy the default stuff over ldx #.sizeof(DefVars)-1 @L1: lda DefVars,x sta Vars,x dex bpl @L1 ; Be sure the mouse cursor is invisible and at the default location. We ; need to do that here, because our mouse interrupt handler doesn't set the ; mouse position if it hasn't changed. sei jsr CHIDE lda XPos ldx XPos+1 jsr CMOVEX lda YPos ldx YPos+1 jsr CMOVEY cli ; Done, return zero (= MOUSE_ERR_OK) ldx #$00 txa rts ;---------------------------------------------------------------------------- ; UNINSTALL routine. Is called before the driver is removed from memory. ; No return code required (the driver is removed from memory on return). UNINSTALL = HIDE ; Hide cursor on exit ;---------------------------------------------------------------------------- ; HIDE routine. Is called to hide the mouse pointer. The mouse kernel manages ; a counter for calls to show/hide, and the driver entry point is only called ; if the mouse is currently visible and should get hidden. For most drivers, ; no special action is required besides hiding the mouse cursor. ; No return code required. HIDE: sei jsr CHIDE cli rts ;---------------------------------------------------------------------------- ; SHOW routine. Is called to show the mouse pointer. The mouse kernel manages ; a counter for calls to show/hide, and the driver entry point is only called ; if the mouse is currently hidden and should become visible. For most drivers, ; no special action is required besides enabling the mouse cursor. ; No return code required. SHOW: sei jsr CSHOW cli rts ;---------------------------------------------------------------------------- ; SETBOX: Set the mouse bounding box. The parameters are passed as they come ; from the C program, that is, a pointer to a mouse_box struct in a/x. ; No checks are done if the mouse is currently inside the box, this is the job ; of the caller. It is not necessary to validate the parameters, trust the ; caller and save some code here. No return code required. SETBOX: sta ptr1 stx ptr1+1 ; Save data pointer ldy #.sizeof (MOUSE_BOX)-1 sei @L1: lda (ptr1),y sta XMin,y dey bpl @L1 cli rts ;---------------------------------------------------------------------------- ; GETBOX: Return the mouse bounding box. The parameters are passed as they ; come from the C program, that is, a pointer to a mouse_box struct in a/x. GETBOX: sta ptr1 stx ptr1+1 ; Save data pointer ldy #.sizeof (MOUSE_BOX)-1 @L1: lda XMin,y sta (ptr1),y dey bpl @L1 rts ;---------------------------------------------------------------------------- ; MOVE: Move the mouse to a new position. The position is passed as it comes ; from the C program, that is: X on the stack and Y in a/x. The C wrapper will ; remove the parameter from the stack on return. ; No checks are done if the new position is valid (within the bounding box or ; the screen). No return code required. ; MOVE: sei ; No interrupts sta YPos stx YPos+1 ; New Y position jsr CMOVEY ; Set it ldy #$01 lda (sp),y sta XPos+1 tax dey lda (sp),y sta XPos ; New X position jsr CMOVEX ; Move the cursor cli ; Allow interrupts rts ;---------------------------------------------------------------------------- ; BUTTONS: Return the button mask in a/x. BUTTONS: lda Buttons ldx #0 and #$1F rts ;---------------------------------------------------------------------------- ; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1. ; No return code required. POS: ldy #MOUSE_POS::XCOORD ; Structure offset sei ; Disable interrupts lda XPos ; Transfer the position sta (ptr1),y lda XPos+1 iny sta (ptr1),y lda YPos iny sta (ptr1),y lda YPos+1 cli ; Enable interrupts iny sta (ptr1),y ; Store last byte rts ; Done ;---------------------------------------------------------------------------- ; INFO: Returns mouse position and current button mask in the MOUSE_INFO ; struct pointed to by ptr1. No return code required. ; ; We're cheating here to keep the code smaller: The first fields of the ; mouse_info struct are identical to the mouse_pos struct, so we will just ; call _mouse_pos to initialize the struct pointer and fill the position ; fields. INFO: jsr POS ; Fill in the button state jsr BUTTONS ; Will not touch ptr1 ldy #MOUSE_INFO::BUTTONS sta (ptr1),y rts ;---------------------------------------------------------------------------- ; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl ; specific data in ptr1, and the ioctl code in A. ; Must return an error code in a/x. ; IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now ldx #>MOUSE_ERR_INV_IOCTL rts ;---------------------------------------------------------------------------- ; IRQ: Irq handler entry point. Called as a subroutine but in IRQ context ; (so be careful). The routine MUST return carry set if the interrupt has been ; 'handled' - which means that the interrupt source is gone. Otherwise it ; MUST return carry clear. ; IRQ: jsr CPREP ; Record the state of the buttons. ; Avoid crosstalk between the keyboard and the mouse. ldy #%00000000 ; Set ports A and B to input sty CIA1_DDRB sty CIA1_DDRA ; Keyboard won't look like mouse lda CIA1_PRB ; Read Control-Port 1 dec CIA1_DDRA ; Set port A back to output eor #%11111111 ; Bit goes up when button goes down sta Buttons beq @L0 ;(bze) dec CIA1_DDRB ; Mouse won't look like keyboard sty CIA1_PRB ; Set "all keys pushed" @L0: lda SID_ADConv1 ; Get mouse X movement ldy OldPotX jsr MoveCheck ; Calculate movement vector ; Skip processing if nothing has changed bcc @SkipX sty OldPotX ; Calculate the new X coordinate (--> a/y) add XPos tay ; Remember low byte txa adc XPos+1 tax ; Limit the X coordinate to the bounding box cpy XMin sbc XMin+1 bpl @L1 ldy XMin ldx XMin+1 jmp @L2 @L1: txa cpy XMax sbc XMax+1 bmi @L2 ldy XMax ldx XMax+1 @L2: sty XPos stx XPos+1 ; Move the mouse pointer to the new X pos tya jsr CMOVEX ; Calculate the Y movement vector @SkipX: lda SID_ADConv2 ; Get mouse Y movement ldy OldPotY jsr MoveCheck ; Calculate movement ; Skip processing if nothing has changed bcc @SkipY sty OldPotY ; Calculate the new Y coordinate (--> a/y) sta OldValue lda YPos sub OldValue tay stx OldValue lda YPos+1 sbc OldValue tax ; Limit the Y coordinate to the bounding box cpy YMin sbc YMin+1 bpl @L3 ldy YMin ldx YMin+1 jmp @L4 @L3: txa cpy YMax sbc YMax+1 bmi @L4 ldy YMax ldx YMax+1 @L4: sty YPos stx YPos+1 ; Move the mouse pointer to the new Y pos tya jsr CMOVEY ; Done @SkipY: jsr CDRAW clc ; Interrupt not "handled" rts ; -------------------------------------------------------------------------- ; ; Move check routine, called for both coordinates. ; ; Entry: y = old value of pot register ; a = current value of pot register ; Exit: y = value to use for old value ; x/a = delta value for position ; MoveCheck: sty OldValue sta NewValue ldx #$00 sub OldValue ; a = mod64 (new - old) and #%01111111 cmp #%01000000 ; if (a > 0) bcs @L1 ; lsr a ; a /= 2; beq @L2 ; if (a != 0) ldy NewValue ; y = NewValue sec rts ; return @L1: ora #%11000000 ; else, "or" in high-order bits cmp #$FF ; if (a != -1) beq @L2 sec ror a ; a /= 2 dex ; high byte = -1 (X = $FF) ldy NewValue sec rts @L2: txa ; A = $00 clc rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/mou/c64-inkwell.s��������������������������������������������������������������0000664�0000000�0000000�00000031476�13473601511�0017115�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Driver for the Inkwell Systems 170-C and 184-C lightpens. ; ; 2014-09-10, Greg King ; .include "zeropage.inc" .include "mouse-kernel.inc" .include "c64.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table. module_header _c64_inkwell_mou HEADER: ; Driver signature .byte $6d, $6f, $75 ; ASCII "mou" .byte MOUSE_API_VERSION ; Mouse driver API version number ; Library reference LIBREF: .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr HIDE .addr SHOW .addr SETBOX .addr GETBOX .addr MOVE .addr BUTTONS .addr POS .addr INFO .addr IOCTL .addr IRQ ; Mouse driver flags .byte MOUSE_FLAG_EARLY_IRQ ; Callback table, set by the kernel before INSTALL is called. CHIDE: jmp $0000 ; Hide the cursor CSHOW: jmp $0000 ; Show the cursor CPREP: jmp $0000 ; Prepare to move the cursor CDRAW: jmp $0000 ; Draw the cursor CMOVEX: jmp $0000 ; Move the cursor to X co-ord. CMOVEY: jmp $0000 ; Move the cursor to Y co-ord. ;---------------------------------------------------------------------------- ; Constants SCREEN_WIDTH = XSIZE * 8 SCREEN_HEIGHT = YSIZE * 8 ;---------------------------------------------------------------------------- ; Global variables. The bounding box values are sorted so that they can be ; written with the least effort in the SETBOX and GETBOX routines; so, don't ; re-order them. .rodata ; Default values for below variables ; (We use ".proc" because we want to define both a label and a scope.) .proc DefVars .word 0 ; XMin .word 0 ; YMin .word SCREEN_WIDTH - 1 ; XMax .word SCREEN_HEIGHT - 1 ; YMax .byte %00000000 ; Buttons .endproc .bss Vars: XMin: .res 2 ; X1 value of bounding box YMin: .res 2 ; Y1 value of bounding box XMax: .res 2 ; X2 value of bounding box YMax: .res 2 ; Y2 value of bounding box Buttons: .res 1 ; Button status bits XPos: .res 2 ; Current lightpen position, X YPos: .res 2 ; Current lightpen position, Y OldPenX: .res 1 ; Previous HW-counter values OldPenY: .res 1 .data ; Default Inkwell calibration. ; The first number is the width of the left border; ; the second number is the actual calibration value. ; See a comment below (at "Calculate the new X co-ordinate") ; for the reason for the third number. XOffset: .byte (24 + 24) / 2 ; x-offset ; Jump to a function that puts a new calibration value into XOffset. Calibrate: jmp $0000 .code ;---------------------------------------------------------------------------- ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present. ; Must return a MOUSE_ERR_xx code in .XA. INSTALL: ; Initiate variables. Just copy the default stuff over. ldx #.sizeof (DefVars) - 1 @L0: lda DefVars,x sta Vars,x dex bpl @L0 ldx VIC_LPEN_X ldy VIC_LPEN_Y stx OldPenX sty OldPenY ; Call a calibration function through the library-reference. lda LIBREF ldx LIBREF+1 sta ptr1 ; Point to mouse_adjuster stx ptr1+1 ldy #1 lda (ptr1),y bze @L1 ; Don't call pointer if it's NULL sta Calibrate+2 ; Point to function dey lda (ptr1),y sta Calibrate+1 lda #<XOffset ; Function will set this variable ldx #>XOffset jsr Calibrate ; Be sure that the lightpen cursor is invisible and at the default location. ; It needs to be done here because the lightpen interrupt handler doesn't ; set the lightpen position if it hasn't changed. @L1: sei jsr CHIDE lda #<(SCREEN_HEIGHT / 2) ldx #>(SCREEN_HEIGHT / 2) jsr MoveY lda #<(SCREEN_WIDTH / 2) ldx #>(SCREEN_WIDTH / 2) jsr MoveX cli ; Done, return zero. lda #MOUSE_ERR_OK tax rts ;---------------------------------------------------------------------------- ; UNINSTALL routine. Is called before the driver is removed from memory. ; No return code required (the driver is removed from memory on return). UNINSTALL := HIDE ; Hide cursor on exit ;---------------------------------------------------------------------------- ; HIDE routine. Is called to hide the lightpen pointer. The mouse kernel manages ; a counter for calls to show/hide, and the driver entry point is called only ; if the mouse is currently visible, and should get hidden. For most drivers, ; no special action is required besides hiding the lightpen cursor. ; No return code required. HIDE: sei jsr CHIDE cli rts ;---------------------------------------------------------------------------- ; SHOW routine. Is called to show the lightpen pointer. The mouse kernel manages ; a counter for calls to show/hide, and the driver entry point is called only ; if the mouse is currently hidden, and should become visible. For most drivers, ; no special action is required besides enabling the lightpen cursor. ; No return code required. SHOW: sei jsr CSHOW cli rts ;---------------------------------------------------------------------------- ; SETBOX: Set the lightpen bounding box. The parameters are passed as they come ; from the C program, that is, a pointer to a mouse_box struct in .XA. ; No checks are done if the lightpen is currently inside the box, that is the job ; of the caller. It is not necessary to validate the parameters; trust the ; caller; and, save some code here. No return code required. SETBOX: sta ptr1 stx ptr1+1 ; Save data pointer ldy #.sizeof (MOUSE_BOX) - 1 sei @L1: lda (ptr1),y sta XMin,y dey bpl @L1 cli rts ;---------------------------------------------------------------------------- ; GETBOX: Return the lightpen bounding box. The parameters are passed as they ; come from the C program, that is, a pointer to a mouse_box struct in .XA. GETBOX: sta ptr1 stx ptr1+1 ; Save data pointer ldy #.sizeof (MOUSE_BOX) - 1 @L1: lda XMin,y sta (ptr1),y dey bpl @L1 rts ;---------------------------------------------------------------------------- ; MOVE: Move the mouse to a new position. The position is passed as it comes ; from the C program, that is: X on the stack and Y in .XA. The C wrapper will ; remove the parameter from the stack on return. ; No checks are done if the new position is valid (within the bounding box or ; the screen). No return code required. ; MOVE: sei ; No interrupts jsr MoveY ldy #$01 lda (sp),y tax dey lda (sp),y jsr MoveX ; Move the cursor cli ; Allow interrupts rts ;---------------------------------------------------------------------------- ; BUTTONS: Return the button mask in .XA. BUTTONS: lda Buttons ldx #>$0000 ; Make the lightpen buttons look like a 1351 mouse. asl a asl SID_ADConv2 ; PotY rol a eor #MOUSE_BTN_RIGHT and #MOUSE_BTN_LEFT | MOUSE_BTN_RIGHT rts ;---------------------------------------------------------------------------- ; POS: Return the lightpen position in the MOUSE_POS struct pointed to by ptr1. ; No return code required. POS: ldy #MOUSE_POS::XCOORD ; Structure offset sei ; Disable interrupts lda XPos ; Transfer the position sta (ptr1),y lda XPos+1 iny sta (ptr1),y lda YPos iny sta (ptr1),y lda YPos+1 cli ; Enable interrupts iny sta (ptr1),y ; Store last byte rts ;---------------------------------------------------------------------------- ; INFO: Returns lightpen position and current button mask in the MOUSE_INFO ; struct pointed to by ptr1. No return code required. ; ; We're cheating here, to keep the code smaller: The first fields of the ; mouse_info struct are identical to the mouse_pos struct; so, we'll just ; call _mouse_pos to initiate the struct pointer, and fill the position ; fields. INFO: jsr POS ; Fill in the button state jsr BUTTONS ; Will not touch ptr1 ldy #MOUSE_INFO::BUTTONS sta (ptr1),y rts ;---------------------------------------------------------------------------- ; IOCTL: Driver-defined entry point. The wrapper will pass a pointer to ioctl- ; specific data in ptr1, and the ioctl code in .A. ; Must return an error code in .XA. ; IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioctls, for now ldx #>MOUSE_ERR_INV_IOCTL rts ;---------------------------------------------------------------------------- ; IRQ: IRQ handler entry point. Called as a subroutine, but in the IRQ context ; (so, be careful). The routine MUST return carry set if the interrupt has been ; 'handled' -- which means that the interrupt source is gone. Otherwise, it ; MUST return carry clear. ; IRQ: jsr CPREP ; Record the state of the buttons. ; Try to avoid crosstalk between the keyboard and the lightpen. ldy #%00000000 ; Set ports A and B to input sty CIA1_DDRB sty CIA1_DDRA ; Keyboard won't look like buttons lda CIA1_PRB ; Read Control-Port 1 dec CIA1_DDRA ; Set port A back to output eor #%11111111 ; Bit goes up when button goes down sta Buttons bze @L0 lda #%11101111 ; (Don't change bit that feeds VIC-II) sta CIA1_DDRB ; Buttons won't look like keyboard sty CIA1_PRB ; Set "all keys pushed" ; Read the VIC-II lightpen registers. @L0: lda VIC_LPEN_Y cmp OldPenY ; Skip processing if nothing has changed. beq @SkipY sta OldPenY ; Subtract the height of the top border, so that the lightpen co-ordinate ; will match the TGI co-ordinate. sub #50 tay ; Remember low byte ldx #>$0000 ; Limit the Y co-ordinate to the bounding box. txa cpy YMin sbc YMin+1 bpl @L3 ldy YMin ldx YMin+1 jmp @L4 @L3: txa cpy YMax sbc YMax+1 bmi @L4 ldy YMax ldx YMax+1 @L4: tya jsr MoveY @SkipY: lda VIC_LPEN_X cmp OldPenX ; Skip processing if nothing has changed. beq @SkipX sta OldPenX ; Adjust the value by the calibration offset. sub XOffset ; Calculate the new X co-ordinate. ; The VIC-II register is eight bits; but, the screen co-ordinate is nine bits. ; Therefore, the VIC-II number is doubled. Then, it points to every other pixel; ; but, it can reach across the screen. asl a tay ; Remember low byte lda #>$0000 rol a tax ; Remember high byte ; Limit the X co-ordinate to the bounding box. cpy XMin sbc XMin+1 bpl @L1 ldy XMin ldx XMin+1 jmp @L2 @L1: txa cpy XMax sbc XMax+1 bmi @L2 ldy XMax ldx XMax+1 @L2: tya jsr MoveX ; Done @SkipX: jsr CDRAW clc ; Interrupt not "handled" rts ; Move the lightpen pointer to the new Y pos. MoveY: sta YPos stx YPos+1 jmp CMOVEY ; Move the lightpen pointer to the new X pos. MoveX: sta XPos stx XPos+1 jmp CMOVEX ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/mou/c64-joy.s������������������������������������������������������������������0000664�0000000�0000000�00000032467�13473601511�0016252�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Driver for a "joystick mouse". ; ; Ullrich von Bassewitz, 2004-03-29, 2009-09-26 ; 2014-03-17, Greg King ; ; The driver prevents the keyboard from interfering by changing the ; keyboard's output port into an input port while the driver reads its ; controller device. That disables a wire that is left active by the ; Kernal. That wire is used by the STOP-key to break out of BASIC ; programs -- CC65 programs don't use that feature. The wire is shared ; by these keys: STOP, "Q", Commodore, Space, "2", CTRL, Left-Arrow, and ; "1". I listed them, in order, from bit 7 over to bit 0. The ; rightmost five keys can look like joystick switches. ; ; The driver prevents the mouse/joystick from interfering by "blinding" ; the keyboard scanner while any button/switch is active. It changes ; the input port into an output port, then stores all zero-bits in that ; port's latch. Reading from an output port sees the bitwise-AND of the ; latch and the input signals. Therefore, the scanner thinks that eight ; keys are being pushed at the same time. It doesn't know what to do ; about that condition; so, it does nothing. The driver lets the ; scanner see normally, again, when no buttons/switches are active. ; .include "zeropage.inc" .include "mouse-kernel.inc" .include "c64.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c64_joy_mou HEADER: ; Driver signature .byte $6d, $6f, $75 ; "mou" .byte MOUSE_API_VERSION ; Mouse driver API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr HIDE .addr SHOW .addr SETBOX .addr GETBOX .addr MOVE .addr BUTTONS .addr POS .addr INFO .addr IOCTL .addr IRQ ; Mouse driver flags .byte MOUSE_FLAG_LATE_IRQ ; Callback table, set by the kernel before INSTALL is called CHIDE: jmp $0000 ; Hide the cursor CSHOW: jmp $0000 ; Show the cursor CPREP: jmp $0000 ; Prepare to move the cursor CDRAW: jmp $0000 ; Draw the cursor CMOVEX: jmp $0000 ; Move the cursor to X coord CMOVEY: jmp $0000 ; Move the cursor to Y coord ;---------------------------------------------------------------------------- ; Constants SCREEN_HEIGHT = 200 SCREEN_WIDTH = 320 .enum JOY UP = $01 DOWN = $02 LEFT = $04 RIGHT = $08 FIRE = $10 .endenum ;---------------------------------------------------------------------------- ; Global variables. The bounding box values are sorted so that they can be ; written with the least effort in the SETBOX and GETBOX routines, so don't ; reorder them. .bss Vars: YPos: .res 2 ; Current mouse position, Y XPos: .res 2 ; Current mouse position, X XMin: .res 2 ; X1 value of bounding box YMin: .res 2 ; Y1 value of bounding box XMax: .res 2 ; X2 value of bounding box YMax: .res 2 ; Y2 value of bounding box Buttons: .res 1 ; Button mask ; Temporary value used in the int handler Temp: .res 1 .rodata ; Default values for above variables ; (We use ".proc" because we want to define both a label and a scope.) .proc DefVars .word SCREEN_HEIGHT/2 ; YPos .word SCREEN_WIDTH/2 ; XPos .word 0 ; XMin .word 0 ; YMin .word SCREEN_WIDTH - 1 ; XMax .word SCREEN_HEIGHT - 1 ; YMax .byte 0 ; Buttons .endproc .code ;---------------------------------------------------------------------------- ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present. ; Must return an MOUSE_ERR_xx code in a/x. INSTALL: ; Initialize variables. Just copy the default stuff over ldx #.sizeof(DefVars)-1 @L1: lda DefVars,x sta Vars,x dex bpl @L1 ; Be sure the mouse cursor is invisible and at the default location. We ; need to do that here, because our mouse interrupt handler doesn't set the ; mouse position if it hasn't changed. sei jsr CHIDE lda XPos ldx XPos+1 jsr CMOVEX lda YPos ldx YPos+1 jsr CMOVEY cli ; Done, return zero (= MOUSE_ERR_OK) ldx #$00 txa rts ;---------------------------------------------------------------------------- ; UNINSTALL routine. Is called before the driver is removed from memory. ; No return code required (the driver is removed from memory on return). UNINSTALL = HIDE ; Hide cursor on exit ;---------------------------------------------------------------------------- ; HIDE routine. Is called to hide the mouse pointer. The mouse kernel manages ; a counter for calls to show/hide, and the driver entry point is only called ; if the mouse is currently visible and should get hidden. For most drivers, ; no special action is required besides hiding the mouse cursor. ; No return code required. HIDE: sei jsr CHIDE cli rts ;---------------------------------------------------------------------------- ; SHOW routine. Is called to show the mouse pointer. The mouse kernel manages ; a counter for calls to show/hide, and the driver entry point is only called ; if the mouse is currently hidden and should become visible. For most drivers, ; no special action is required besides enabling the mouse cursor. ; No return code required. SHOW: sei jsr CSHOW cli rts ;---------------------------------------------------------------------------- ; SETBOX: Set the mouse bounding box. The parameters are passed as they come ; from the C program, that is, a pointer to a mouse_box struct in a/x. ; No checks are done if the mouse is currently inside the box, this is the job ; of the caller. It is not necessary to validate the parameters, trust the ; caller and save some code here. No return code required. SETBOX: sta ptr1 stx ptr1+1 ; Save data pointer ldy #.sizeof (MOUSE_BOX)-1 sei @L1: lda (ptr1),y sta XMin,y dey bpl @L1 cli rts ;---------------------------------------------------------------------------- ; GETBOX: Return the mouse bounding box. The parameters are passed as they ; come from the C program, that is, a pointer to a mouse_box struct in a/x. GETBOX: sta ptr1 stx ptr1+1 ; Save data pointer ldy #.sizeof (MOUSE_BOX)-1 @L1: lda XMin,y sta (ptr1),y dey bpl @L1 rts ;---------------------------------------------------------------------------- ; MOVE: Move the mouse to a new position. The position is passed as it comes ; from the C program, that is: X on the stack and Y in a/x. The C wrapper will ; remove the parameter from the stack on return. ; No checks are done if the new position is valid (within the bounding box or ; the screen). No return code required. ; MOVE: sei ; No interrupts sta YPos stx YPos+1 ; New Y position jsr CMOVEY ; Set it ldy #$01 lda (sp),y sta XPos+1 tax dey lda (sp),y sta XPos ; New X position jsr CMOVEX ; Move the cursor cli ; Allow interrupts rts ;---------------------------------------------------------------------------- ; BUTTONS: Return the button mask in a/x. BUTTONS: lda Buttons ldx #$00 rts ;---------------------------------------------------------------------------- ; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1. ; No return code required. POS: ldy #MOUSE_POS::XCOORD ; Structure offset sei ; Disable interrupts lda XPos ; Transfer the position sta (ptr1),y lda XPos+1 iny sta (ptr1),y lda YPos iny sta (ptr1),y lda YPos+1 cli ; Enable interrupts iny sta (ptr1),y ; Store last byte rts ; Done ;---------------------------------------------------------------------------- ; INFO: Returns mouse position and current button mask in the MOUSE_INFO ; struct pointed to by ptr1. No return code required. ; ; We're cheating here to keep the code smaller: The first fields of the ; mouse_info struct are identical to the mouse_pos struct, so we will just ; call _mouse_pos to initialize the struct pointer and fill the position ; fields. INFO: jsr POS ; Fill in the button state lda Buttons ldy #MOUSE_INFO::BUTTONS sta (ptr1),y rts ;---------------------------------------------------------------------------- ; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl ; specific data in ptr1, and the ioctl code in A. ; Must return an error code in a/x. ; IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now ldx #>MOUSE_ERR_INV_IOCTL rts ;---------------------------------------------------------------------------- ; IRQ: Irq handler entry point. Called as a subroutine but in IRQ context ; (so be careful). The routine MUST return carry set if the interrupt has been ; 'handled' - which means that the interrupt source is gone. Otherwise it ; MUST return carry clear. ; IRQ: jsr CPREP ; Avoid crosstalk between the keyboard and a joystick. ldy #%00000000 ; Set ports A and B to input sty CIA1_DDRB sty CIA1_DDRA ; Keyboard won't look like joystick lda CIA1_PRB ; Read Control-Port 1 dec CIA1_DDRA ; Set port A back to output eor #%11111111 ; Bit goes up when switch goes down beq @Save ;(bze) dec CIA1_DDRB ; Joystick won't look like keyboard sty CIA1_PRB ; Set "all keys pushed" @Save: sta Temp ; Check for a pressed button and place the result into Buttons ldx #$00 ; Assume no button pressed and #JOY::FIRE ; Check fire button beq @L0 ; Jump if not pressed ldx #MOUSE_BTN_LEFT ; Left (only) button is pressed @L0: stx Buttons ; Check left/right lda Temp ; Read joystick #0 and #(JOY::LEFT | JOY::RIGHT) beq @SkipX ; ; We will cheat here and rely on the fact that either the left, OR the right ; bit can be active and #JOY::RIGHT ; Check RIGHT bit bne @Right lda #$FF tax bne @AddX ; Branch always @Right: lda #$01 ldx #$00 ; Calculate the new X coordinate (--> a/y) @AddX: add XPos tay ; Remember low byte txa adc XPos+1 tax ; Limit the X coordinate to the bounding box cpy XMin sbc XMin+1 bpl @L1 ldy XMin ldx XMin+1 jmp @L2 @L1: txa cpy XMax sbc XMax+1 bmi @L2 ldy XMax ldx XMax+1 @L2: sty XPos stx XPos+1 ; Move the mouse pointer to the new X pos tya jsr CMOVEX ; Calculate the Y movement vector @SkipX: lda Temp ; Read joystick #0 and #(JOY::UP | JOY::DOWN) ; Check up/down beq @SkipY ; ; We will cheat here and rely on the fact that either the up, OR the down ; bit can be active lsr a ; Check UP bit bcc @Down lda #$FF tax bne @AddY @Down: lda #$01 ldx #$00 ; Calculate the new Y coordinate (--> a/y) @AddY: add YPos tay ; Remember low byte txa adc YPos+1 tax ; Limit the Y coordinate to the bounding box cpy YMin sbc YMin+1 bpl @L3 ldy YMin ldx YMin+1 jmp @L4 @L3: txa cpy YMax sbc YMax+1 bmi @L4 ldy YMax ldx YMax+1 @L4: sty YPos stx YPos+1 ; Move the mouse pointer to the new X pos tya jsr CMOVEY ; Done @SkipY: jsr CDRAW clc ; Interrupt not "handled" rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/mou/c64-pot.s������������������������������������������������������������������0000664�0000000�0000000�00000025763�13473601511�0016254�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Driver for a potentiometer "mouse", e.g. Koala Pad ; ; 2006-08-20, Stefan Haubenthal ; 2009-09-26, Ullrich von Bassewitz ; 2014-05-05, Greg King ; .include "zeropage.inc" .include "mouse-kernel.inc" .include "c64.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c64_pot_mou HEADER: ; Driver signature .byte $6d, $6f, $75 ; "mou" .byte MOUSE_API_VERSION ; Mouse driver API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr HIDE .addr SHOW .addr SETBOX .addr GETBOX .addr MOVE .addr BUTTONS .addr POS .addr INFO .addr IOCTL .addr IRQ ; Mouse driver flags .byte MOUSE_FLAG_LATE_IRQ ; Callback table, set by the kernel before INSTALL is called CHIDE: jmp $0000 ; Hide the cursor CSHOW: jmp $0000 ; Show the cursor CPREP: jmp $0000 ; Prepare to move the cursor CDRAW: jmp $0000 ; Draw the cursor CMOVEX: jmp $0000 ; Move the cursor to X coord CMOVEY: jmp $0000 ; Move the cursor to Y coord ;---------------------------------------------------------------------------- ; Constants SCREEN_HEIGHT = 200 SCREEN_WIDTH = 320 .enum JOY UP = $01 DOWN = $02 LEFT = $04 RIGHT = $08 FIRE = $10 .endenum ;---------------------------------------------------------------------------- ; Global variables. The bounding box values are sorted so that they can be ; written with the least effort in the SETBOX and GETBOX routines, so don't ; reorder them. .bss Vars: YPos: .res 2 ; Current mouse position, Y XPos: .res 2 ; Current mouse position, X XMin: .res 2 ; X1 value of bounding box YMin: .res 2 ; Y1 value of bounding box XMax: .res 2 ; X2 value of bounding box YMax: .res 2 ; Y2 value of bounding box Buttons: .res 1 ; Button mask ; Temporary value used in the int handler Temp: .res 1 .rodata ; Default values for above variables ; (We use ".proc" because we want to define both a label and a scope.) .proc DefVars .word SCREEN_HEIGHT/2 ; YPos .word SCREEN_WIDTH/2 ; XPos .word 0 ; XMin .word 0 ; YMin .word SCREEN_WIDTH - 1 ; XMax .word SCREEN_HEIGHT - 1 ; YMax .byte 0 ; Buttons .endproc .code ;---------------------------------------------------------------------------- ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present. ; Must return an MOUSE_ERR_xx code in a/x. INSTALL: ; Initialize variables. Just copy the default stuff over ldx #.sizeof(DefVars)-1 @L1: lda DefVars,x sta Vars,x dex bpl @L1 ; Be sure the mouse cursor is invisible and at the default location. We ; need to do that here, because our mouse interrupt handler doesn't set the ; mouse position if it hasn't changed. sei jsr CHIDE lda XPos ldx XPos+1 jsr CMOVEX lda YPos ldx YPos+1 jsr CMOVEY cli ; Done, return zero (= MOUSE_ERR_OK) ldx #$00 txa rts ;---------------------------------------------------------------------------- ; UNINSTALL routine. Is called before the driver is removed from memory. ; No return code required (the driver is removed from memory on return). UNINSTALL = HIDE ; Hide cursor on exit ;---------------------------------------------------------------------------- ; HIDE routine. Is called to hide the mouse pointer. The mouse kernel manages ; a counter for calls to show/hide, and the driver entry point is only called ; if the mouse is currently visible and should get hidden. For most drivers, ; no special action is required besides hiding the mouse cursor. ; No return code required. HIDE: sei jsr CHIDE cli rts ;---------------------------------------------------------------------------- ; SHOW routine. Is called to show the mouse pointer. The mouse kernel manages ; a counter for calls to show/hide, and the driver entry point is only called ; if the mouse is currently hidden and should become visible. For most drivers, ; no special action is required besides enabling the mouse cursor. ; No return code required. SHOW: sei jsr CSHOW cli rts ;---------------------------------------------------------------------------- ; SETBOX: Set the mouse bounding box. The parameters are passed as they come ; from the C program, that is, a pointer to a mouse_box struct in a/x. ; No checks are done if the mouse is currently inside the box, this is the job ; of the caller. It is not necessary to validate the parameters, trust the ; caller and save some code here. No return code required. SETBOX: sta ptr1 stx ptr1+1 ; Save data pointer ldy #.sizeof (MOUSE_BOX)-1 sei @L1: lda (ptr1),y sta XMin,y dey bpl @L1 cli rts ;---------------------------------------------------------------------------- ; GETBOX: Return the mouse bounding box. The parameters are passed as they ; come from the C program, that is, a pointer to a mouse_box struct in a/x. GETBOX: sta ptr1 stx ptr1+1 ; Save data pointer ldy #.sizeof (MOUSE_BOX)-1 sei @L1: lda XMin,y sta (ptr1),y dey bpl @L1 cli rts ;---------------------------------------------------------------------------- ; MOVE: Move the mouse to a new position. The position is passed as it comes ; from the C program, that is: X on the stack and Y in a/x. The C wrapper will ; remove the parameter from the stack on return. ; No checks are done if the new position is valid (within the bounding box or ; the screen). No return code required. ; MOVE: sei ; No interrupts sta YPos stx YPos+1 ; New Y position jsr CMOVEY ; Set it ldy #$01 lda (sp),y sta XPos+1 tax dey lda (sp),y sta XPos ; New X position jsr CMOVEX ; Move the cursor cli ; Allow interrupts rts ;---------------------------------------------------------------------------- ; BUTTONS: Return the button mask in a/x. BUTTONS: lda Buttons ldx #$00 rts ;---------------------------------------------------------------------------- ; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1. ; No return code required. POS: ldy #MOUSE_POS::XCOORD ; Structure offset sei ; Disable interrupts lda XPos ; Transfer the position sta (ptr1),y lda XPos+1 iny sta (ptr1),y lda YPos iny sta (ptr1),y lda YPos+1 cli ; Enable interrupts iny sta (ptr1),y ; Store last byte rts ; Done ;---------------------------------------------------------------------------- ; INFO: Returns mouse position and current button mask in the MOUSE_INFO ; struct pointed to by ptr1. No return code required. ; ; We're cheating here to keep the code smaller: The first fields of the ; mouse_info struct are identical to the mouse_pos struct, so we will just ; call _mouse_pos to initialize the struct pointer and fill the position ; fields. INFO: jsr POS ; Fill in the button state lda Buttons ldy #MOUSE_INFO::BUTTONS sta (ptr1),y rts ;---------------------------------------------------------------------------- ; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl ; specific data in ptr1, and the ioctl code in A. ; Must return an error code in a/x. ; IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioclts for now ldx #>MOUSE_ERR_INV_IOCTL rts ;---------------------------------------------------------------------------- ; IRQ: Irq handler entry point. Called as a subroutine but in IRQ context ; (so be careful). ; IRQ: jsr CPREP lda #$7F sta CIA1_PRA lda CIA1_PRB ; Read port #1 and #%00001100 eor #%00001100 ; Make all bits active high asl sta Buttons lsr lsr lsr and #%00000001 ora Buttons sta Buttons ldx #%01000000 stx CIA1_PRA ldy #0 : dey bne :- ldx SID_ADConv1 stx XPos ldx SID_ADConv2 stx YPos lda #$FF tax bne @AddX ; Branch always lda #$01 ldx #$00 ; Calculate the new X coordinate (--> a/y) @AddX: add XPos tay ; Remember low byte txa adc XPos+1 tax ; Limit the X coordinate to the bounding box cpy XMin sbc XMin+1 bpl @L1 ldy XMin ldx XMin+1 jmp @L2 @L1: txa cpy XMax sbc XMax+1 bmi @L2 ldy XMax ldx XMax+1 @L2: sty XPos stx XPos+1 ; Move the mouse pointer to the new X pos tya jsr CMOVEX lda #$FF tax bne @AddY @Down: lda #$01 ldx #$00 ; Calculate the new Y coordinate (--> a/y) @AddY: add YPos tay ; Remember low byte txa adc YPos+1 tax ; Limit the Y coordinate to the bounding box cpy YMin sbc YMin+1 bpl @L3 ldy YMin ldx YMin+1 jmp @L4 @L3: txa cpy YMax sbc YMax+1 bmi @L4 ldy YMax ldx YMax+1 @L4: sty YPos stx YPos+1 ; Move the mouse pointer to the new X pos tya jsr CMOVEY jsr CDRAW clc ; Interrupt not "handled" rts �������������cc65-2.18/libsrc/c64/mouse_stat_stddrv.s������������������������������������������������������������0000664�0000000�0000000�00000000353�13473601511�0020015�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Address of the static standard mouse driver ; ; Oliver Schmidt, 2012-11-01 ; ; const void mouse_static_stddrv[]; ; .export _mouse_static_stddrv .import _c64_1351_mou .rodata _mouse_static_stddrv := _c64_1351_mou �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/mouse_stddrv.s�����������������������������������������������������������������0000664�0000000�0000000�00000000276�13473601511�0016766�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Name of the standard mouse driver ; ; Ullrich von Bassewitz, 2009-09-11 ; ; const char mouse_stddrv[]; ; .export _mouse_stddrv .rodata _mouse_stddrv: .asciiz "c64-1351.mou" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/mouseref.s���������������������������������������������������������������������0000664�0000000�0000000�00000001152�13473601511�0016067�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Pointer for library references by device drivers. ; ; 2013-07-25, Greg King ; .export mouse_libref, _pen_adjuster .data mouse_libref: ; generic label for mouse-kernel ; A program optionally can set this pointer to a function that gives ; a calibration value to a driver. If this pointer isn't NULL, ; then a driver that wants a value can call that function. ; ; The function might read a value from a file; or, it might ask the user ; to help calibrate the driver. ; ; void __fastcall__ (*pen_adjuster)(unsigned char *) = NULL; ; _pen_adjuster: .addr $0000 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/pencalib.c���������������������������������������������������������������������0000664�0000000�0000000�00000005146�13473601511�0016006�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** Calibrate lightpen drivers to the current video hardware. ** ** 2013-07-25, Greg King ** */ #include <conio.h> #include <mouse.h> #include <pen.h> #define COMMAND1 "Adjust by clicking on line." #define COMMAND2 "Finish by clicking off bar." /* ** There is a delay between when the VIC sends its signal, and when the display ** shows that signal. There is another delay between the display and when ** the lightpen says that it saw that signal. Each display and pen is different. ** Therefore, the driver must be calibrated to them. A white bar is painted on ** the screen; and, a line is drawn down the middle of it. When the user clicks ** on that line, the difference between its position and where the VIC thinks ** that the pen is pointing becomes an offset that is subtracted from what the ** VIC sees. */ void __fastcall__ pen_calibrate (unsigned char *XOffset) { unsigned char oldBg = bgcolor (COLOR_BLUE); unsigned char oldText = textcolor (COLOR_GRAY3); unsigned char oldRev = revers (1); unsigned char sprite0Color = VIC.spr_color[0]; unsigned char width, width2, height, height4, height8; struct mouse_info info; screensize (&width, &height); width2 = width / 2; height4 = height / 4; height8 = height4 * 8; /* Draw a bar and line. */ clrscr (); cclearxy (0, height4, height4 * width); cvlinexy (width2, height4 + 1, height4 - 2); revers (0); /* Print instructions. */ cputsxy (width2 - (sizeof COMMAND1) / 2, height / 2 + 1, COMMAND1); cputsxy (width2 - (sizeof COMMAND2) / 2, height / 2 + 3, COMMAND2); VIC.spr_color[0] = COLOR_GRAY2; mouse_show (); mouse_move (width2 * 8, height8 / 2); for (;;) { /* Wait for the main button to be released. */ do ; while ((mouse_buttons () & MOUSE_BTN_LEFT)); /* Wait for the main button to be pressed. */ do { mouse_info (&info); } while (!(info.buttons & MOUSE_BTN_LEFT)); /* Find out if the pen is on or off the bar. */ if (info.pos.y < height8 || info.pos.y >= height8 * 2) { break; } /* On the bar; adjust the offset. */ /* Characters are eight pixels wide. ** The VIC-II sees every other pixel; ** so, we use half of the difference. */ *XOffset += (info.pos.x - (width2 * 8 + 8/2)) / 2; } /* Off the bar; wait for the main button to be released. */ do ; while ((mouse_buttons () & MOUSE_BTN_LEFT)); mouse_hide (); VIC.spr_color[0] = sprite0Color; revers (oldRev); textcolor (oldText); bgcolor (oldBg); clrscr (); } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/randomize.s��������������������������������������������������������������������0000664�0000000�0000000�00000000667�13473601511�0016244�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2002-11-05, Ullrich von Bassewitz ; 2015-09-11, Greg King ; ; void _randomize (void); ; /* Initialize the random number generator */ ; .export __randomize .import _srand .include "c64.inc" __randomize: ldx VIC_HLINE ; Use VIC rasterline as high byte lda TIME+2 ; Use 60HZ clock as low byte jmp _srand ; Initialize generator �������������������������������������������������������������������������cc65-2.18/libsrc/c64/revers.s�����������������������������������������������������������������������0000664�0000000�0000000�00000001401�13473601511�0015545�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 07.08.1998 ; ; unsigned char revers (unsigned char onoff); ; .export _revers .include "c64.inc" .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 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/ser/���������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014650�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/ser/c64-swlink.s���������������������������������������������������������������0000664�0000000�0000000�00000032523�13473601511�0016742�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Serial driver for the C64 using a Swiftlink or Turbo-232 cartridge. ; ; Ullrich von Bassewitz, 2003-04-18 ; ; The driver is based on the cc65 rs232 module, which in turn is based on ; Craig Bruce device driver for the Switftlink/Turbo-232. ; ; SwiftLink/Turbo-232 v0.90 device driver, by Craig Bruce, 14-Apr-1998. ; ; This software is Public Domain. It is in Buddy assembler format. ; ; This device driver uses the SwiftLink RS-232 Serial Cartridge, available from ; Creative Micro Designs, Inc, and also supports the extensions of the Turbo232 ; Serial Cartridge. Both devices are based on the 6551 ACIA chip. It also ; supports the "hacked" SwiftLink with a 1.8432 MHz crystal. ; ; The code assumes that the kernal + I/O are in context. On the C128, call ; it from Bank 15. On the C64, don't flip out the Kernal unless a suitable ; NMI catcher is put into the RAM under then Kernal. For the SuperCPU, the ; interrupt handling assumes that the 65816 is in 6502-emulation mode. ; .include "zeropage.inc" .include "ser-kernel.inc" .include "ser-error.inc" .include "cbm_kernal.inc" .include "c64.inc" .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c64_swlink_ser ; Driver signature .byte $73, $65, $72 ; "ser" .byte SER_API_VERSION ; Serial API version number ; Library reference .addr $0000 ; Jump table .word SER_INSTALL .word SER_UNINSTALL .word SER_OPEN .word SER_CLOSE .word SER_GET .word SER_PUT .word SER_STATUS .word SER_IOCTL .word SER_IRQ ;---------------------------------------------------------------------------- ; I/O definitions ACIA = $DE00 ACIA_DATA = ACIA+0 ; Data register ACIA_STATUS = ACIA+1 ; Status register ACIA_CMD = ACIA+2 ; Command register ACIA_CTRL = ACIA+3 ; Control register ;---------------------------------------------------------------------------- ; ; Global variables ; ; We reuse the RS232 zero page variables for the driver, since the ROM ; routines cannot be used together with this driver. RecvHead = $B5 ; Head of receive buffer RecvTail = $BD ; Tail of receive buffer RecvFreeCnt = $F7 ; Number of bytes in receive buffer SendHead = $F8 ; Head of send buffer SendTail = $F9 ; Tail of send buffer SendFreeCnt = $FA ; Number of bytes free in send buffer .bss Stopped: .res 1 ; Flow-stopped flag RtsOff: .res 1 ; ; Send and receive buffers: 256 bytes each RecvBuf: .res 256 SendBuf: .res 256 .data NmiContinue: .byte $4c ; JMP instruction for NMI save -- continue NmiSave: .res 2 ; normal NMI handler .rodata ; Tables used to translate RS232 params into register values BaudTable: ; bit7 = 1 means setting is invalid .byte $FF ; SER_BAUD_45_5 .byte $FF ; SER_BAUD_50 .byte $FF ; SER_BAUD_75 .byte $FF ; SER_BAUD_110 .byte $FF ; SER_BAUD_134_5 .byte $02 ; SER_BAUD_150 .byte $05 ; SER_BAUD_300 .byte $06 ; SER_BAUD_600 .byte $07 ; SER_BAUD_1200 .byte $FF ; SER_BAUD_1800 .byte $08 ; SER_BAUD_2400 .byte $09 ; SER_BAUD_3600 .byte $0A ; SER_BAUD_4800 .byte $0B ; SER_BAUD_7200 .byte $0C ; SER_BAUD_9600 .byte $0E ; SER_BAUD_19200 .byte $0F ; SER_BAUD_38400 .byte $FF ; SER_BAUD_57600 .byte $FF ; SER_BAUD_115200 .byte $FF ; SER_BAUD_230400 BitTable: .byte $60 ; SER_BITS_5 .byte $40 ; SER_BITS_6 .byte $20 ; SER_BITS_7 .byte $00 ; SER_BITS_8 StopTable: .byte $00 ; SER_STOP_1 .byte $80 ; SER_STOP_2 ParityTable: .byte $00 ; SER_PAR_NONE .byte $20 ; SER_PAR_ODD .byte $60 ; SER_PAR_EVEN .byte $A0 ; SER_PAR_MARK .byte $E0 ; SER_PAR_SPACE .code ;---------------------------------------------------------------------------- ; SER_INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present. ; Must return an SER_ERR_xx code in a/x. SER_INSTALL: ; Deactivate DTR and disable 6551 interrupts lda #%00001010 sta ACIA_CMD ; Set up the nmi vector lda NMIVec ldy NMIVec+1 sta NmiSave+0 sty NmiSave+1 lda #<NmiHandler ldy #>NmiHandler SetNMI: sta NMIVec sty NMIVec+1 ; Done, return an error code lda #<SER_ERR_OK tax ; A is zero rts ;---------------------------------------------------------------------------- ; SER_UNINSTALL routine. Is called before the driver is removed from memory. ; Must return an SER_ERR_xx code in a/x. SER_UNINSTALL: ; Stop interrupts, drop DTR lda #%00001010 sta ACIA_CMD ; Restore NMI vector and return OK lda NmiSave+0 ldy NmiSave+1 jmp SetNMI ;---------------------------------------------------------------------------- ; PARAMS routine. A pointer to a ser_params structure is passed in ptr1. ; Must return an SER_ERR_xx code in a/x. SER_OPEN: ; Check if the handshake setting is valid ldy #SER_PARAMS::HANDSHAKE ; Handshake lda (ptr1),y cmp #SER_HS_HW ; This is all we support bne InvParam ; Initialize buffers jsr InitBuffers ; Set the value for the control register, which contains stop bits, word ; length and the baud rate. ldy #SER_PARAMS::BAUDRATE lda (ptr1),y ; Baudrate index tay lda BaudTable,y ; Get 6551 value bmi InvBaud ; Branch if rate not supported sta tmp1 ldy #SER_PARAMS::DATABITS ; Databits lda (ptr1),y tay lda BitTable,y ora tmp1 sta tmp1 ldy #SER_PARAMS::STOPBITS ; Stopbits lda (ptr1),y tay lda StopTable,y ora tmp1 ora #%00010000 ; Receiver clock source = baudrate sta ACIA_CTRL ; Set the value for the command register. We remember the base value in ; RtsOff, since we will have to manipulate ACIA_CMD often. ldy #SER_PARAMS::PARITY ; Parity lda (ptr1),y tay lda ParityTable,y ora #%00000001 ; DTR active sta RtsOff ora #%00001000 ; Enable receive interrupts sta ACIA_CMD ; Done lda #<SER_ERR_OK tax ; A is zero rts ; Invalid parameter InvParam: lda #<SER_ERR_INIT_FAILED ldx #>SER_ERR_INIT_FAILED rts ; Baud rate not available InvBaud: lda #<SER_ERR_BAUD_UNAVAIL ldx #>SER_ERR_BAUD_UNAVAIL rts ;---------------------------------------------------------------------------- ; SER_CLOSE: Close the port, disable interrupts and flush the buffer. Called ; without parameters. Must return an error code in a/x. ; SER_CLOSE: ; Stop interrupts, drop DTR lda #%00001010 sta ACIA_CMD ; Initalize buffers. Returns zero in a jsr InitBuffers ; Return OK lda #<SER_ERR_OK tax ; A is zero rts ;---------------------------------------------------------------------------- ; SER_GET: Will fetch a character from the receive buffer and store it into the ; variable pointer to by ptr1. If no data is available, SER_ERR_NO_DATA is ; return. ; SER_GET: ldx SendFreeCnt ; Send data if necessary inx ; X == $FF? beq @L1 lda #$00 jsr TryToSend ; Check for buffer empty @L1: lda RecvFreeCnt ; (25) cmp #$ff bne @L2 lda #<SER_ERR_NO_DATA ldx #>SER_ERR_NO_DATA rts ; Check for flow stopped & enough free: release flow control @L2: ldx Stopped ; (34) beq @L3 cmp #63 bcc @L3 lda #$00 sta Stopped lda RtsOff ora #%00001000 sta ACIA_CMD ; Get byte from buffer @L3: ldx RecvHead ; (41) lda RecvBuf,x inc RecvHead inc RecvFreeCnt ldx #$00 ; (59) sta (ptr1,x) txa ; Return code = 0 rts ;---------------------------------------------------------------------------- ; SER_PUT: Output character in A. ; Must return an error code in a/x. ; SER_PUT: ; Try to send ldx SendFreeCnt inx ; X = $ff? beq @L2 pha lda #$00 jsr TryToSend pla ; Put byte into send buffer & send @L2: ldx SendFreeCnt bne @L3 lda #<SER_ERR_OVERFLOW ; X is already zero rts @L3: ldx SendTail sta SendBuf,x inc SendTail dec SendFreeCnt lda #$ff jsr TryToSend lda #<SER_ERR_OK tax rts ;---------------------------------------------------------------------------- ; SER_STATUS: Return the status in the variable pointed to by ptr1. ; Must return an error code in a/x. ; SER_STATUS: lda ACIA_STATUS ldx #0 sta (ptr1,x) txa ; SER_ERR_OK rts ;---------------------------------------------------------------------------- ; SER_IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl ; specific data in ptr1, and the ioctl code in A. ; Must return an error code in a/x. ; SER_IOCTL: lda #<SER_ERR_INV_IOCTL ; We don't support ioclts for now ldx #>SER_ERR_INV_IOCTL rts ;---------------------------------------------------------------------------- ; SER_IRQ: Not used on the C64 ; SER_IRQ = $0000 ;---------------------------------------------------------------------------- ; ; NMI handler ; C128 NMI overhead=76 cycles: int=7, maxLatency=6, ROMenter=33, ROMexit=30 ; C64 NMI overhead=76 cycles: int=7, maxLatency=6, ROMenter=34, ROMexit=29 ; ; timing: normal=76+43+9=128 cycles, assertFlow=76+52+9=137 cycles ; ; C128 @ 115.2k: 177 cycles avail (fast) ; C64 @ 57.6k: 177 cycles avail, worstAvail=177-43? = 134 ; SCPU @ 230.4k: 868 cycles avail: for a joke! ; NmiHandler: pha lda ACIA_STATUS ;(4) ;status ;check for byte received and #$08 ;(2) beq @L9 ;(2*) cld txa pha tya pha @L1: lda ACIA_DATA ;(4) data ;get byte and put into receive buffer ldy RecvTail ;(4) ldx RecvFreeCnt ;(4) beq @L3 ;(2*) Jump if no space in receive buffer sta RecvBuf,y ;(5) inc RecvTail ;(6) dec RecvFreeCnt ;(6) cpx #33 ;(2) check for buffer space low bcc @L2 ;(2*) jmp NMIEXIT ;(3) ; Assert flow control @L2: lda RtsOff ;(3) assert flow control if buffer space too low sta ACIA_CMD ;(4) command sta Stopped ;(3) @L3: jmp NMIEXIT ;(3) @L9: pla jmp NmiContinue ;---------------------------------------------------------------------------- ; Try to send a byte. Internal routine. A = TryHard .proc TryToSend sta tmp1 ; Remember tryHard flag @L0: lda SendFreeCnt cmp #$ff beq @L3 ; Bail out ; Check for flow stopped @L1: lda Stopped bne @L3 ; Bail out ; Check that swiftlink is ready to send @L2: lda ACIA_STATUS and #$10 bne @L4 bit tmp1 ;keep trying if must try hard bmi @L0 @L3: rts ; Send byte and try again @L4: ldx SendHead lda SendBuf,x sta ACIA_DATA inc SendHead inc SendFreeCnt jmp @L0 .endproc ;---------------------------------------------------------------------------- ; Initialize buffers InitBuffers: ldx #0 stx Stopped stx RecvHead stx RecvTail stx SendHead stx SendTail dex ; X = 255 stx RecvFreeCnt stx SendFreeCnt rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/settime.s����������������������������������������������������������������������0000664�0000000�0000000�00000003464�13473601511�0015724�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 16.8.2018 ; ; int __fastcall__ clock_settime (clockid_t clk_id, const struct timespec *tp); ; .include "time.inc" .include "c64.inc" .importzp sreg, ptr1 .import pushax, pusheax, ldax0sp, ldeaxidx .import tosdiveax, incsp3, return0 .import TM, load_tenth ;---------------------------------------------------------------------------- .code .proc _clock_settime jsr pushax .assert timespec::tv_sec = 0, error jsr _localtime sta ptr1 stx ptr1+1 ldy #.sizeof(tm)-1 @L1: lda (ptr1),y sta TM,y dey bpl @L1 lda TM + tm::tm_hour jsr dec2BCD tax ; Force flags bne @L2 lda #$92 ; 12 AM bne @L3 @L2: cmp #$13 ; 1 PM bcc @L3 sed sbc #$12 cld ora #%10000000 @L3: sta CIA1_TODHR lda TM + tm::tm_min jsr dec2BCD sta CIA1_TODMIN lda TM + tm::tm_sec jsr dec2BCD sta CIA1_TODSEC jsr ldax0sp ldy #3+timespec::tv_nsec jsr ldeaxidx jsr pusheax jsr load_tenth jsr tosdiveax sta CIA1_TOD10 jsr incsp3 jmp return0 .endproc ;---------------------------------------------------------------------------- ; Just sum up the value in BCD mode. ; http://forum.6502.org/viewtopic.php?p=7629#p7629 .proc dec2BCD tax dex bmi @L9 lda #0 clc sed @L1: adc #1 dex bpl @L1 cld @L9: rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/soft80.inc���������������������������������������������������������������������0000664�0000000�0000000�00000002777�13473601511�0015712�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 �cc65-2.18/libsrc/c64/soft80_cgetc.s�����������������������������������������������������������������0000664�0000000�0000000�00000004230�13473601511�0016532�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 "cbm_kernal.inc" .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 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/soft80_charset.s���������������������������������������������������������������0000664�0000000�0000000�00000017141�13473601511�0017103�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 "ONCE" 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 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/soft80_color.s�����������������������������������������������������������������0000664�0000000�0000000�00000010270�13473601511�0016564�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/soft80_conio.s�����������������������������������������������������������������0000664�0000000�0000000�00000007605�13473601511�0016565�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 "ONCE" 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 "INIT" 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 ���������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/soft80_cpeekc.s����������������������������������������������������������������0000664�0000000�0000000�00000004552�13473601511�0016706�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2017-12-28, Groepaz ; ; char cpeekc (void); ; .export soft80_cpeekc, soft80_cpeekchar .include "c64.inc" .include "soft80.inc" .macpack longbranch .segment "CODE" soft80_cpeekc: jsr soft80_cpeekchar ; 0-1F -> A0-BF ; 20-7F -> 20-7F cmp #$20 bcs @sk ;clc adc #$a0 @sk: ldx #0 rts soft80_cpeekchar: sei lda #$34 sta $01 lda CURS_X and #$01 jne @l1a ; test non-inverted character (left side) ldx #0 @l2aa: ldy #0 .repeat 8,line lda (SCREEN_PTR),y and #$f0 cmp soft80_hi_charset+(line*$80),x bne @l2b .if (line < 7) iny .endif .endrepeat @backok: lda #$36 sta $01 cli txa ; return char in A ldx #$00 ; revers flag rts @l2b: inx cpx #$80 jne @l2aa ; test inverted character (left side) ldx #0 @l2aa2: ldy #0 .repeat 8,line lda (SCREEN_PTR),y and #$f0 eor #$f0 cmp soft80_hi_charset+(line*$80),x bne @l2b2 .if (line < 7) iny .endif .endrepeat @backokrevers: lda #$36 sta $01 cli txa ; return char in A ldx #$01 ; revers flag rts @l2b2: inx cpx #$80 jne @l2aa2 @backerr: lda #$36 sta $01 cli ldx #0 txa rts ; test non-inverted character (right side) @l1a: ldx #0 @l1aa: ldy #0 .repeat 8,line lda (SCREEN_PTR),y and #$0f eor soft80_lo_charset+(line*$80),x bne @l2bb .if line < 7 iny .endif .endrepeat jmp @backok @l2bb: inx cpx #$80 bne @l1aa ; test inverted character (right side) ldx #0 @l1aa2: ldy #0 .repeat 8,line lda (SCREEN_PTR),y and #$0f eor #$0f eor soft80_lo_charset+(line*$80),x bne @l2bb2 .if line < 7 iny .endif .endrepeat jmp @backokrevers @l2bb2: inx cpx #$80 bne @l1aa2 jmp @backerr ������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/soft80_cpeekcolor.s������������������������������������������������������������0000664�0000000�0000000�00000000503�13473601511�0017572�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2017-12-27, Groepaz ; ; unsigned char cpeekcolor (void); ; .export soft80_cpeekcolor .include "c64.inc" .include "soft80.inc" .segment "CODE" soft80_cpeekcolor: ldy #0 lda (CRAM_PTR),y and #$0f ldx #0 rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/soft80_cpeekrevers.s�����������������������������������������������������������0000664�0000000�0000000�00000000367�13473601511�0017772�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2017-12-28, Groepaz ; ; unsigned char cpeekrevers (void); ; .import soft80_cpeekchar .export soft80_cpeekrevers soft80_cpeekrevers: jsr soft80_cpeekchar txa ldx #0 rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/soft80_cpeeks.s����������������������������������������������������������������0000664�0000000�0000000�00000002625�13473601511�0016725�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2017-12-27, groepaz ; ; void cpeeks (char* s, unsigned length); ; .export soft80_cpeeks .import soft80_cpeekc, soft80_kplot, popax .importzp ptr1, ptr2 .include "c64.inc" .include "soft80.inc" soft80_cpeeks: eor #<$FFFF ; counting a word upward is faster sta ptr2 ; so, we use -(length + 1) txa eor #>$FFFF sta ptr2+1 jsr popax sta ptr1 stx ptr1+1 ; save current cursor position lda CURS_X pha lda CURS_Y pha ; get the string @lp: jsr soft80_cpeekc ldy #0 sta (ptr1),y ; advance cursor position ldy CURS_X ldx CURS_Y iny cpy #charsperline bne @sk2 ldy #0 inx @sk2: sty CURS_X stx CURS_Y clc jsr soft80_kplot inc ptr1 bne @sk inc ptr1+1 @sk: inc ptr2 bne @lp inc ptr2+1 bne @lp ; terminate the string lda #0 ldy #0 sta (ptr1),y ; restore the cursor position pla tax ; CURS_Y pla tay ; CURS_X clc jmp soft80_kplot �����������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/soft80_cputc.s�����������������������������������������������������������������0000664�0000000�0000000�00000032360�13473601511�0016570�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 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 gotoxy ; Set cursor, drop x and y 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 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/soft80_kclrscr.s���������������������������������������������������������������0000664�0000000�0000000�00000003025�13473601511�0017111�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/soft80_kplot.s�����������������������������������������������������������������0000664�0000000�0000000�00000002424�13473601511�0016601�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ ; ; 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 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/soft80_scrsize.s���������������������������������������������������������������0000664�0000000�0000000�00000000413�13473601511�0017126�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/soft80mono_cgetc.s�������������������������������������������������������������0000664�0000000�0000000�00000003220�13473601511�0017421�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 "cbm_kernal.inc" .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 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/soft80mono_color.s�������������������������������������������������������������0000664�0000000�0000000�00000003517�13473601511�0017463�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/soft80mono_conio.s�������������������������������������������������������������0000664�0000000�0000000�00000010256�13473601511�0017452�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 "ONCE" 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 "INIT" 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 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/soft80mono_cpeekcolor.s��������������������������������������������������������0000664�0000000�0000000�00000000440�13473601511�0020463�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2017-12-27, Groepaz ; ; unsigned char cpeekcolor (void); ; .export soft80mono_cpeekcolor .include "c64.inc" .include "soft80.inc" .segment "CODE" soft80mono_cpeekcolor: lda CHARCOLOR ldx #0 rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/soft80mono_cputc.s�������������������������������������������������������������0000664�0000000�0000000�00000011564�13473601511�0017464�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 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 gotoxy ; Set cursor, drop x and y 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 ��������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/soft80mono_kclrscr.s�����������������������������������������������������������0000664�0000000�0000000�00000002421�13473601511�0020001�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/soft80mono_kplot.s�������������������������������������������������������������0000664�0000000�0000000�00000002145�13473601511�0017472�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ ; ; 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 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/status.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000134�13473601511�0015564�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2012-09-30 ; .exportzp ST := $90 ; IEC status byte ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/sysuname.s���������������������������������������������������������������������0000664�0000000�0000000�00000001535�13473601511�0016113�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-08-12 ; ; unsigned char __fastcall__ _sysuname (struct utsname* buf); ; .export __sysuname, utsdata .import utscopy __sysuname = utscopy ;-------------------------------------------------------------------------- ; Data. We define a fixed utsname struct here and just copy it. .rodata utsdata: ; sysname .asciiz "cc65" ; nodename .asciiz "" ; release .byte ((.VERSION >> 8) & $0F) + '0' .byte '.' .byte ((.VERSION >> 4) & $0F) + '0' .byte $00 ; version .byte (.VERSION & $0F) + '0' .byte $00 ; machine .asciiz "Commodore 64" �������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/tgi/���������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014642�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/tgi/c64-hi.s�������������������������������������������������������������������0000664�0000000�0000000�00000053514�13473601511�0016030�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Graphics driver for the 320x200x2 mode on the C64. ; ; Based on Stephen L. Judd's GRLIB code. ; ; 2017-01-13, Greg King ; 2018-03-13, Sven Klose ; .include "zeropage.inc" .include "tgi-kernel.inc" .include "tgi-error.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table and constants. module_header _c64_hi_tgi ; First part of the header is a structure that has a magic and defines the ; capabilities of the driver .byte $74, $67, $69 ; "tgi" .byte TGI_API_VERSION ; TGI API version number .addr $0000 ; Library reference .word 320 ; X resolution .word 200 ; Y resolution .byte 2 ; Number of drawing colors .byte 1 ; Number of screens available .byte 8 ; System font X size .byte 8 ; System font Y size .word $00D4 ; Aspect ratio (based on 4/3 display) .byte 0 ; TGI driver flags ; Next comes the jump table. With the exception of IRQ, all entries must be ; valid and may point to an RTS for test versions (function not implemented). .addr INSTALL .addr UNINSTALL .addr INIT .addr DONE .addr GETERROR .addr CONTROL .addr CLEAR .addr SETVIEWPAGE .addr SETDRAWPAGE .addr SETCOLOR .addr SETPALETTE .addr GETPALETTE .addr GETDEFPALETTE .addr SETPIXEL .addr GETPIXEL .addr LINE .addr BAR .addr TEXTSTYLE .addr OUTTEXT ; ------------------------------------------------------------------------ ; Data. ; Variables mapped to the zero page segment variables. Some of these are ; used for passing parameters to the driver. X1 := ptr1 Y1 := ptr2 X2 := ptr3 Y2 := ptr4 TEXT := ptr3 TEMP := tmp4 TEMP2 := sreg POINT := regsave CHUNK := X2 ; Used in the line routine OLDCHUNK := X2+1 ; Dito ; Absolute variables used in the code .bss ERROR: .res 1 ; Error code PALETTE: .res 2 ; The current palette BITMASK: .res 1 ; $00 = clear, $FF = set pixels ; INIT/DONE OLDD018: .res 1 ; Old register value ; Line routine stuff DX: .res 2 DY: .res 2 ; BAR variables X1SAVE: .res 2 Y1SAVE: .res 2 X2SAVE: .res 2 Y2SAVE: .res 2 ; Text output stuff TEXTMAGX: .res 1 TEXTMAGY: .res 1 TEXTDIR: .res 1 ; Constants and tables .rodata DEFPALETTE: .byte $00, $01 ; White on black PALETTESIZE = * - DEFPALETTE BITTAB: .byte $80,$40,$20,$10,$08,$04,$02,$01 BITCHUNK: .byte $FF,$7F,$3F,$1F,$0F,$07,$03,$01 CHARROM := $D000 ; Character rom base address CBASE := $D000 ; Color memory base address VBASE := $E000 ; Video memory base address .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. May ; initialize anything that has to be done just once. Is probably empty ; most of the time. ; ; Must set an error code: NO ; INSTALL: ; rts ; fall through ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. May ; clean up anything done by INSTALL but is probably empty most of the time. ; ; Must set an error code: NO ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; INIT: Changes an already installed device from text mode to graphics ; mode. ; Note that INIT/DONE may be called multiple times while the driver ; is loaded, while INSTALL is only called once, so any code that is needed ; to initializes variables and so on must go here. Setting palette and ; clearing the screen is not needed because this is called by the graphics ; kernel later. ; The graphics kernel will never call INIT when a graphics mode is already ; active, so there is no need to protect against that. ; ; Must set an error code: YES ; INIT: ; Initialize variables ldx #$FF stx BITMASK ; Switch into graphics mode lda $DD02 ; Set the data direction regs ora #3 sta $DD02 lda $DD00 and #$FC ; Switch to bank 3 sta $DD00 lda $D018 sta OLDD018 lda #$48 ; Set color map to $D000, screen to $E000 sta $D018 lda $D011 ; And turn on bitmap ora #$20 DONE1: sta $D011 ; Done, reset the error code lda #TGI_ERR_OK sta ERROR rts ; ------------------------------------------------------------------------ ; DONE: Will be called to switch the graphics device back into text mode. ; The graphics kernel will never call DONE when no graphics mode is active, ; so there is no need to protect against that. ; ; Must set an error code: NO ; DONE: lda $DD02 ; Set the data direction regs ora #3 sta $DD02 lda $DD00 ora #$03 ; Bank 0 sta $DD00 lda OLDD018 ; Screen mem --> $0400 sta $D018 lda $D011 and #<~$20 sta $D011 rts ; ------------------------------------------------------------------------ ; GETERROR: Return the error code in A and clear it. GETERROR: ldx #TGI_ERR_OK lda ERROR stx ERROR rts ; ------------------------------------------------------------------------ ; CONTROL: Platform/driver specific entry point. ; ; Must set an error code: YES ; CONTROL: lda #TGI_ERR_INV_FUNC sta ERROR rts ; ------------------------------------------------------------------------ ; CLEAR: Clears the screen. ; ; Must set an error code: NO ; CLEAR: ldy #$00 tya @L1: sta VBASE+$0000,y sta VBASE+$0100,y sta VBASE+$0200,y sta VBASE+$0300,y sta VBASE+$0400,y sta VBASE+$0500,y sta VBASE+$0600,y sta VBASE+$0700,y sta VBASE+$0800,y sta VBASE+$0900,y sta VBASE+$0A00,y sta VBASE+$0B00,y sta VBASE+$0C00,y sta VBASE+$0D00,y sta VBASE+$0E00,y sta VBASE+$0F00,y sta VBASE+$1000,y sta VBASE+$1100,y sta VBASE+$1200,y sta VBASE+$1300,y sta VBASE+$1400,y sta VBASE+$1500,y sta VBASE+$1600,y sta VBASE+$1700,y sta VBASE+$1800,y sta VBASE+$1900,y sta VBASE+$1A00,y sta VBASE+$1B00,y sta VBASE+$1C00,y sta VBASE+$1D00,y sta VBASE+$1E00,y sta VBASE+$1E40,y ; preserve vectors iny bne @L1 rts ; ------------------------------------------------------------------------ ; SETVIEWPAGE: Set the visible page. Called with the new page in A (0..n). ; The page number is already checked to be valid by the graphics kernel. ; ; Must set an error code: NO (will only be called if page ok) ; SETVIEWPAGE: ; rts ; fall through ; ------------------------------------------------------------------------ ; SETDRAWPAGE: Set the drawable page. Called with the new page in A (0..n). ; The page number is already checked to be valid by the graphics kernel. ; ; Must set an error code: NO (will only be called if page ok) ; SETDRAWPAGE: rts ; ------------------------------------------------------------------------ ; SETCOLOR: Set the drawing color (in A). The new color is already checked ; to be in a valid range (0..maxcolor-1). ; ; Must set an error code: NO (will only be called if color ok) ; SETCOLOR: tax beq @L1 lda #$FF @L1: sta BITMASK rts ; ------------------------------------------------------------------------ ; SETPALETTE: Set the palette (not available with all drivers/hardware). ; A pointer to the palette is passed in ptr1. Must set an error if palettes ; are not supported ; ; Must set an error code: YES ; SETPALETTE: ldy #PALETTESIZE - 1 @L1: lda (ptr1),y ; Copy the palette and #$0F ; Make a valid color sta PALETTE,y dey bpl @L1 ; Get the color entries from the palette lda PALETTE+1 ; Foreground color asl a asl a asl a asl a ora PALETTE ; Background color tax ; Initialize the color map with the new color settings (it is below the ; I/O area) ldy #$00 sei lda $01 ; Get ROM config pha ; Save it and #%11111100 ; Clear bit 0 and 1 sta $01 txa ; Load color code @L2: sta CBASE+$0000,y sta CBASE+$0100,y sta CBASE+$0200,y sta CBASE+$02e8,y iny bne @L2 pla sta $01 cli ; Done, reset the error code lda #TGI_ERR_OK sta ERROR rts ; ------------------------------------------------------------------------ ; GETPALETTE: Return the current palette in A/X. Even drivers that cannot ; set the palette should return the default palette here, so there's no ; way for this function to fail. ; ; Must set an error code: NO ; GETPALETTE: lda #<PALETTE ldx #>PALETTE rts ; ------------------------------------------------------------------------ ; GETDEFPALETTE: Return the default palette for the driver in A/X. All ; drivers should return something reasonable here, even drivers that don't ; support palettes, otherwise the caller has no way to determine the colors ; of the (not changeable) palette. ; ; Must set an error code: NO (all drivers must have a default palette) ; GETDEFPALETTE: lda #<DEFPALETTE ldx #>DEFPALETTE rts ; ------------------------------------------------------------------------ ; SETPIXEL: Draw one pixel at X1/Y1 = ptr1/ptr2 with the current drawing ; color. The coordinates passed to this function are never outside the ; visible screen area, so there is no need for clipping inside this function. ; ; Must set an error code: NO ; SETPIXEL: jsr CALC ; Calculate coordinates sei ; Get underneath ROM lda $01 pha lda #$34 sta $01 lda (POINT),Y eor BITMASK and BITTAB,X eor (POINT),Y sta (POINT),Y pla sta $01 cli @L9: rts ; ------------------------------------------------------------------------ ; GETPIXEL: Read the color value of a pixel and return it in A/X. The ; coordinates passed to this function are never outside the visible screen ; area, so there is no need for clipping inside this function. GETPIXEL: jsr CALC ; Calculate coordinates sei ; Get underneath ROM lda $01 pha lda #$34 sta $01 lda (POINT),Y ldy #$00 and BITTAB,X beq @L1 iny @L1: pla sta $01 cli tya ; Get color value into A ldx #$00 ; Clear high byte rts ; ------------------------------------------------------------------------ ; LINE: Draw a line from X1/Y1 to X2/Y2, where X1/Y1 = ptr1/ptr2 and ; X2/Y2 = ptr3/ptr4 using the current drawing color. ; ; X1,X2 etc. are set up above (x2=LINNUM in particular) ; Format is LINE x2,y2,x1,y1 ; ; Must set an error code: NO ; LINE: @CHECK: lda X2 ;Make sure x1<x2 sec sbc X1 tax lda X2+1 sbc X1+1 bpl @CONT lda Y2 ;If not, swap P1 and P2 ldy Y1 sta Y1 sty Y2 lda Y2+1 ldy Y1+1 sta Y1+1 sty Y2+1 lda X1 ldy X2 sty X1 sta X2 lda X2+1 ldy X1+1 sta X1+1 sty X2+1 bcc @CHECK @CONT: sta DX+1 stx DX ldx #$C8 ;INY lda Y2 ;Calculate dy sec sbc Y1 tay lda Y2+1 sbc Y1+1 bpl @DYPOS ;Is y2>=y1? lda Y1 ;Otherwise dy=y1-y2 sec sbc Y2 tay ldx #$88 ;DEY @DYPOS: sty DY ; 8-bit DY -- FIX ME? stx YINCDEC stx XINCDEC jsr CALC ; Set up .X, .Y, and POINT lda BITCHUNK,X sta OLDCHUNK sta CHUNK sei ; Get underneath ROM lda #$34 sta $01 ldx DY cpx DX ;Who's bigger: dy or dx? bcc STEPINX ;If dx, then... lda DX+1 bne STEPINX ; ; Big steps in Y ; ; To simplify my life, just use PLOT to plot points. ; ; No more! ; Added special plotting routine -- cool! ; ; X is now counter, Y is y-coordinate ; ; On entry, X=DY=number of loop iterations, and Y= ; Y1 AND #$07 STEPINY: lda #00 sta OLDCHUNK ;So plotting routine will work right lda CHUNK lsr ;Strip the bit eor CHUNK sta CHUNK txa beq YCONT2 ;If dy=0, it's just a point @CONT: lsr ;Init counter to dy/2 ; ; Main loop ; YLOOP: sta TEMP lda (POINT),y eor BITMASK and CHUNK eor (POINT),y sta (POINT),y YINCDEC: iny ;Advance Y coordinate cpy #8 bcc @CONT ;No prob if Y=0..7 jsr FIXY @CONT: lda TEMP ;Restore A sec sbc DX bcc YFIXX YCONT: dex ;X is counter bne YLOOP YCONT2: lda (POINT),y ;Plot endpoint eor BITMASK and CHUNK eor (POINT),y sta (POINT),y lda #$36 sta $01 cli rts YFIXX: ;x=x+1 adc DY lsr CHUNK bne YCONT ;If we pass a column boundary... ror CHUNK ;then reset CHUNK to $80 sta TEMP2 lda POINT ;And add 8 to POINT adc #8 sta POINT bcc @CONT inc POINT+1 @CONT: lda TEMP2 dex bne YLOOP beq YCONT2 ; ; Big steps in X direction ; ; On entry, X=DY=number of loop iterations, and Y= ; Y1 AND #$07 .bss COUNTHI: .byte $00 ;Temporary counter ;only used once .code STEPINX: ldx DX lda DX+1 sta COUNTHI cmp #$80 ror ;Need bit for initialization sta Y1 ;High byte of counter txa bne @CONT ;Could be $100 dec COUNTHI @CONT: ror ; ; Main loop ; XLOOP: lsr CHUNK beq XFIXC ;If we pass a column boundary... XCONT1: sbc DY bcc XFIXY ;Time to step in Y? XCONT2: dex bne XLOOP dec COUNTHI ;High bits set? bpl XLOOP lsr CHUNK ;Advance to last point jsr LINEPLOT ;Plot the last chunk lda #$36 sta $01 cli rts ; ; CHUNK has passed a column, so plot and increment pointer ; and fix up CHUNK, OLDCHUNK. ; XFIXC: sta TEMP jsr LINEPLOT lda #$FF sta CHUNK sta OLDCHUNK lda POINT clc adc #8 sta POINT lda TEMP bcc XCONT1 inc POINT+1 jmp XCONT1 ; ; Check to make sure there isn't a high bit, plot chunk, ; and update Y-coordinate. ; XFIXY: dec Y1 ;Maybe high bit set bpl XCONT2 adc DX sta TEMP lda DX+1 adc #$FF ;Hi byte sta Y1 jsr LINEPLOT ;Plot chunk lda CHUNK sta OLDCHUNK lda TEMP XINCDEC: iny ;Y-coord cpy #8 ;0..7 is ok bcc XCONT2 sta TEMP jsr FIXY lda TEMP jmp XCONT2 ; ; Subroutine to plot chunks/points (to save a little ; room, gray hair, etc.) ; LINEPLOT: ; Plot the line chunk lda (POINT),Y eor BITMASK ora CHUNK and OLDCHUNK eor CHUNK eor (POINT),Y sta (POINT),Y rts ; ; Subroutine to fix up pointer when Y decreases through ; zero or increases through 7. ; FIXY: cpy #255 ;Y=255 or Y=8 beq @DECPTR @INCPTR: ;Add 320 to pointer ldy #0 ;Y increased through 7 lda POINT adc #<320 sta POINT lda POINT+1 adc #>320 sta POINT+1 rts @DECPTR: ;Okay, subtract 320 then ldy #7 ;Y decreased through 0 lda POINT sec sbc #<320 sta POINT lda POINT+1 sbc #>320 sta POINT+1 rts ; ------------------------------------------------------------------------ ; BAR: Draw a filled rectangle with the corners X1/Y1, X2/Y2, where ; X1/Y1 = ptr1/ptr2 and X2/Y2 = ptr3/ptr4 using the current drawing color. ; Contrary to most other functions, the graphics kernel will sort and clip ; the coordinates before calling the driver, so on entry the following ; conditions are valid: ; X1 <= X2 ; Y1 <= Y2 ; (X1 >= 0) && (X1 < XRES) ; (X2 >= 0) && (X2 < XRES) ; (Y1 >= 0) && (Y1 < YRES) ; (Y2 >= 0) && (Y2 < YRES) ; ; Must set an error code: NO ; ; Note: This function needs optimization. It's just a cheap translation of ; the original C wrapper and could be written much smaller (besides that, ; calling LINE is not a good idea either). BAR: lda Y2 sta Y2SAVE lda Y2+1 sta Y2SAVE+1 lda X2 sta X2SAVE lda X2+1 sta X2SAVE+1 lda Y1 sta Y1SAVE lda Y1+1 sta Y1SAVE+1 lda X1 sta X1SAVE lda X1+1 sta X1SAVE+1 @L1: lda Y1 sta Y2 lda Y1+1 sta Y2+1 jsr LINE lda Y1SAVE cmp Y2SAVE bne @L2 lda Y1SAVE cmp Y2SAVE beq @L4 @L2: inc Y1SAVE bne @L3 inc Y1SAVE+1 @L3: lda Y1SAVE sta Y1 lda Y1SAVE+1 sta Y1+1 lda X1SAVE sta X1 lda X1SAVE+1 sta X1+1 lda X2SAVE sta X2 lda X2SAVE+1 sta X2+1 jmp @L1 @L4: rts ; ------------------------------------------------------------------------ ; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in X and Y ; direction is passend in X/Y, the text direction is passed in A. ; ; Must set an error code: NO ; TEXTSTYLE: stx TEXTMAGX sty TEXTMAGY sta TEXTDIR rts ; ------------------------------------------------------------------------ ; OUTTEXT: Output text at X/Y = ptr1/ptr2 using the current color and the ; current text style. The text to output is given as a zero terminated ; string with address in ptr3. ; ; Must set an error code: NO ; OUTTEXT: ; Calculate a pointer to the representation of the character in the ; character ROM ldx #((>(CHARROM + $0800)) >> 3) ldy #0 lda (TEXT),y bmi @L1 ldx #((>(CHARROM + $0000)) >> 3) @L1: stx ptr4+1 asl a rol ptr4+1 asl a rol ptr4+1 asl a rol ptr4+1 sta ptr4 rts ; ------------------------------------------------------------------------ ; Calculate all variables to plot the pixel at X1/Y1. CALC: lda Y1 sta TEMP2 and #7 tay lda Y1+1 lsr ; Neg is possible ror TEMP2 lsr ror TEMP2 lsr ror TEMP2 lda #00 sta POINT lda TEMP2 cmp #$80 ror ror POINT cmp #$80 ror ror POINT ; row*64 adc TEMP2 ; +row*256 clc adc #>VBASE ; +bitmap base sta POINT+1 lda X1 tax and #$F8 clc adc POINT ; +(X AND #$F8) sta POINT lda X1+1 adc POINT+1 sta POINT+1 txa and #7 tax rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/tgi_stat_stddrv.s��������������������������������������������������������������0000664�0000000�0000000�00000000337�13473601511�0017452�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Address of the static standard tgi driver ; ; Oliver Schmidt, 2012-11-01 ; ; const void tgi_static_stddrv[]; ; .export _tgi_static_stddrv .import _c64_hi_tgi .rodata _tgi_static_stddrv := _c64_hi_tgi �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/tgi_stddrv.s�������������������������������������������������������������������0000664�0000000�0000000�00000000256�13473601511�0016417�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Name of the standard tgi driver ; ; Oliver Schmidt, 2011-05-02 ; ; const char tgi_stddrv[]; ; .export _tgi_stddrv .rodata _tgi_stddrv: .asciiz "c64-hi.tgi" ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/tmcommon.s���������������������������������������������������������������������0000664�0000000�0000000�00000003331�13473601511�0016074�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 16.8.2018 ; ; Common stuff for the clock routines ; .include "c64.inc" .include "get_tv.inc" .export TM, load_tenth .constructor inittime .importzp sreg .import _get_tv, _get_ostype ;---------------------------------------------------------------------------- .code .proc load_tenth lda #<(100 * 1000 * 1000 / $10000) ldx #>(100 * 1000 * 1000 / $10000) sta sreg stx sreg+1 lda #<(100 * 1000 * 1000) ldx #>(100 * 1000 * 1000) rts .endproc ;---------------------------------------------------------------------------- ; 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 "ONCE" .proc inittime lda CIA1_TOD10 sta CIA1_TOD10 jsr _get_tv cmp #TV::PAL bne @60Hz jsr _get_ostype cmp #$43 beq @60Hz lda CIA1_CRA ora #$80 sta CIA1_CRA @60Hz: rts .endproc ;---------------------------------------------------------------------------- ; TM struct with date set to 1970-01-01 .data TM: .word 0 ; tm_sec .word 0 ; tm_min .word 0 ; tm_hour .word 1 ; tm_mday .word 0 ; tm_mon .word 70 ; tm_year .word 0 ; tm_wday .word 0 ; tm_yday .word 0 ; tm_isdst �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/c64/waitvsync.s��������������������������������������������������������������������0000664�0000000�0000000�00000000414�13473601511�0016271�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Written by Groepaz <groepaz@gmx.net> ; ; void waitvsync (void); ; .export _waitvsync .include "c64.inc" _waitvsync: @l1: bit VIC_CTRL1 bpl @l1 @l2: bit VIC_CTRL1 bmi @l2 rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/�������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014224�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/c_acptr.s����������������������������������������������������������������������0000664�0000000�0000000�00000000334�13473601511�0016023�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 03.06.1999 ; ; unsigned char cbm_k_acptr (void); ; .include "cbm.inc" .export _cbm_k_acptr _cbm_k_acptr: jsr ACPTR ldx #0 rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/c_basin.s����������������������������������������������������������������������0000664�0000000�0000000�00000000373�13473601511�0016011�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 03.06.1999 ; ; unsigned char cbm_k_basin (void); ; .include "cbm.inc" .export _cbm_k_basin _cbm_k_basin: jsr BASIN ldx #0 ; Clear high byte rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/c_bsout.s����������������������������������������������������������������������0000664�0000000�0000000�00000000274�13473601511�0016051�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 03.06.1999 ; ; void __fastcall__ cbm_k_bsout (unsigned char C); ; .include "cbm.inc" .export _cbm_k_bsout _cbm_k_bsout = BSOUT ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/c_chkin.s����������������������������������������������������������������������0000664�0000000�0000000�00000000507�13473601511�0016010�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Marc 'BlackJack' Rintsch, 20.03.2001 ; ; unsigned char __fastcall__ cbm_k_chkin (unsigned char FN); ; .include "cbm.inc" .export _cbm_k_chkin _cbm_k_chkin: tax jsr CHKIN ldx #0 ; Clear high byte bcs @NotOk txa @NotOk: rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/c_ciout.s����������������������������������������������������������������������0000664�0000000�0000000�00000000260�13473601511�0016033�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 03.06.1999 ; ; void __fastcall__ cbm_k_ciout (unsigned char C); ; .include "cbm.inc" .export _cbm_k_ciout := CIOUT ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/c_ckout.s����������������������������������������������������������������������0000664�0000000�0000000�00000000503�13473601511�0016035�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 03.06.1999 ; ; unsigned char __fastcall__ cbm_k_ckout (unsigned char FN); ; .include "cbm.inc" .export _cbm_k_ckout _cbm_k_ckout: tax jsr CKOUT ldx #0 ; Clear high byte bcs @NotOk txa @NotOk: rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/c_clall.s����������������������������������������������������������������������0000664�0000000�0000000�00000000227�13473601511�0016002�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 03.06.1999 ; ; void cbm_k_clall (void); ; .include "cbm.inc" .export _cbm_k_clall := CLALL �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/c_close.s����������������������������������������������������������������������0000664�0000000�0000000�00000000330�13473601511�0016013�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 03.06.1999 ; ; void __fastcall__ cbm_k_close (unsigned char FN); ; .include "cbm.inc" .export _cbm_k_close _cbm_k_close: clc jmp CLOSE ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/c_clrch.s����������������������������������������������������������������������0000664�0000000�0000000�00000000244�13473601511�0016005�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 03.06.1999 ; ; void cbm_k_clrch (void); ; .include "cbm.inc" .export _cbm_k_clrch _cbm_k_clrch = CLRCH ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/c_getin.s����������������������������������������������������������������������0000664�0000000�0000000�00000000333�13473601511�0016017�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2012-07-01 ; ; unsigned char cbm_k_getin (void); ; .include "cbm.inc" .export _cbm_k_getin _cbm_k_getin: jsr GETIN ldx #0 rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/c_iobase.s���������������������������������������������������������������������0000664�0000000�0000000�00000000403�13473601511�0016151�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 03.06.1999 ; ; unsigned cbm_k_iobase (void); ; .include "cbm.inc" .export _cbm_k_iobase _cbm_k_iobase: jsr IOBASE txa pha tya tax pla rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/c_listen.s���������������������������������������������������������������������0000664�0000000�0000000�00000000264�13473601511�0016212�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 03.06.1999 ; ; void __fastcall__ cbm_k_listen (unsigned char dev); ; .include "cbm.inc" .export _cbm_k_listen := LISTEN ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/c_load.s�����������������������������������������������������������������������0000664�0000000�0000000�00000001142�13473601511�0015627�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 03.06.1999 ; ; unsigned int __fastcall__ cbm_k_load (unsigned char flag, unsigned addr); ; .include "cbm.inc" .export _cbm_k_load .import __oserror .import popa .importzp ptr1 _cbm_k_load: sta ptr1 stx ptr1+1 jsr popa ; get flag ldx ptr1 ldy ptr1+1 jsr LOAD bcc @Ok sta __oserror ldx ptr1 ldy ptr1+1 @Ok: txa pha tya tax pla rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/c_open.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000432�13473601511�0015652�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 03.06.1999 ; ; unsigned char cbm_k_open (void); ; .include "cbm.inc" .export _cbm_k_open _cbm_k_open: jsr OPEN ldx #0 ; Clear high byte bcs @NotOk txa @NotOk: rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/c_readst.s���������������������������������������������������������������������0000664�0000000�0000000�00000000377�13473601511�0016203�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 03.06.1999 ; ; unsigned char cbm_k_readst (void); ; .include "cbm.inc" .export _cbm_k_readst _cbm_k_readst: jsr READST ldx #0 ; Clear high byte rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/c_save.s�����������������������������������������������������������������������0000664�0000000�0000000�00000001115�13473601511�0015646�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Marc 'BlackJack' Rintsch, 11.06.1999 ; ; unsigned char __fastcall__ cbm_k_save(unsigned int start, unsigned int end); ; .include "cbm.inc" .export _cbm_k_save .import popptr1 .importzp ptr1, tmp1 _cbm_k_save: sta tmp1 ; store end address stx tmp1+1 jsr popptr1 ; pop start address lda #ptr1 ldx tmp1 ldy tmp1+1 jsr SAVE ldx #0 ; Clear high byte bcs @NotOk txa @NotOk: rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/c_scnkey.s���������������������������������������������������������������������0000664�0000000�0000000�00000000216�13473601511�0016205�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2016-08-07, Greg King ; ; void cbm_k_scnkey (void); ; .include "cbm.inc" .export _cbm_k_scnkey := SCNKEY ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/c_second.s���������������������������������������������������������������������0000664�0000000�0000000�00000000270�13473601511�0016164�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Bas Wassink, 23.05.2018 ; ; void __fastcall__ cbm_k_second (unsigned char addr) ; .include "cbm.inc" .export _cbm_k_second _cbm_k_second = SECOND ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/c_setlfs.s���������������������������������������������������������������������0000664�0000000�0000000�00000001050�13473601511�0016206�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 03.06.1999 ; ; void __fastcall__ cbm_k_setlfs (unsigned char LFN, ; unsigned char DEV, ; unsigned char SA); ; .include "cbm.inc" .export _cbm_k_setlfs .import popa .importzp tmp1 _cbm_k_setlfs: sta tmp1 ; Save SA jsr popa ; Get DEV tax jsr popa ; Get LFN ldy tmp1 ; Get SA jmp SETLFS ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/c_setnam.s���������������������������������������������������������������������0000664�0000000�0000000�00000001021�13473601511�0016173�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 03.06.1999 ; ; void __fastcall__ cbm_k_setnam (const char* Name); ; .include "cbm.inc" .export _cbm_k_setnam .importzp ptr1 _cbm_k_setnam: sta ptr1 ; Store pointer to file name stx ptr1+1 ldy #$FF @Loop: iny ; Get length of name lda (ptr1),y bne @Loop tya ; Length ldx ptr1 ldy ptr1+1 jmp SETNAM ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/c_talk.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000256�13473601511�0015650�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 03.06.1999 ; ; void __fastcall__ cbm_k_talk (unsigned char dev); ; .include "cbm.inc" .export _cbm_k_talk := TALK ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/c_tksa.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000260�13473601511�0015652�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Bas Wassink, 22.05.2018 ; ; void __fastcall__ cbm_k_tksa (unsigned char addr) ; .include "cbm.inc" .export _cbm_k_tksa _cbm_k_tksa = TKSA ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/c_udtim.s����������������������������������������������������������������������0000664�0000000�0000000�00000000213�13473601511�0016030�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2016-08-07, Greg King ; ; void cbm_k_udtim (void); ; .include "cbm.inc" .export _cbm_k_udtim := UDTIM �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/c_unlsn.s����������������������������������������������������������������������0000664�0000000�0000000�00000000227�13473601511�0016052�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 03.06.1999 ; ; void cbm_k_unlsn (void); ; .include "cbm.inc" .export _cbm_k_unlsn := UNLSN �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/c_untlk.s����������������������������������������������������������������������0000664�0000000�0000000�00000000244�13473601511�0016047�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 03.06.1999 ; ; void cbm_k_untlk (void); ; .include "cbm.inc" .export _cbm_k_untlk _cbm_k_untlk = UNTLK ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/cbm.inc������������������������������������������������������������������������0000664�0000000�0000000�00000002151�13473601511�0015457�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Include file for the Commdore 6502 machines ; ;----------------------------------------------------------------------------- ; Subroutines available in the CBM jump table ; .import C64MODE .import SWAPPER .import SETBNK .import CINT .import IOINIT .import RAMTAS .import VECTOR .import RESTOR .import SETMSG .import SECOND .import TKSA .import MEMTOP .import MEMBOT .import SCNKEY .import SETTMO .import ACPTR .import CIOUT .import UNTLK .import UNLSN .import LISTEN .import TALK .import READST .import SETLFS .import SETNAM .import OPEN .import CLOSE .import LOAD .import SAVE .import SETTIM .import RDTIM .import SCREEN .import PLOT .import IOBASE .import CHKIN .import CKOUT .import CLRCH .import BASIN .import CHRIN .import BSOUT .import CHROUT .import STOP .import GETIN .import CLALL .import UDTIM ;----------------------------------------------------------------------------- ; Device numbers ; CBMDEV_KBD = 0 CBMDEV_DATASETTE= 1 CBMDEV_RS232 = 2 CBMDEV_SCREEN = 3 ;----------------------------------------------------------------------------- ; Disk stuff ; MAX_DRIVES = 23 FIRST_DRIVE = 8 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/cbm_close.s��������������������������������������������������������������������0000664�0000000�0000000�00000000264�13473601511�0016340�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Marc 'BlackJack' Rintsch, 18.03.2001 ; ; void __fastcall__ cbm_close (unsigned char lfn); ; .import _cbm_k_close .export _cbm_close _cbm_close = _cbm_k_close ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/cbm_dir.c����������������������������������������������������������������������0000664�0000000�0000000�00000012603�13473601511�0015771�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* This is a very simplified version of the POSIX opendir(), */ /* readdir(), and closedir() -- for Commodore computers. */ /* Created by Josef Soucek, 2003. E-mail: josef.soucek@ct.cz */ /* 2003-01-21 -- Version 0.1 */ /* 2009-10-10 -- Version 0.3 */ /* 2011-04-07 -- Version 0.4, groepaz */ /* 2011-04-14 -- Version 0.5, Greg King */ /* Tested with floppy-drive and IDE64 devices. */ /* Not tested with messed (buggy) directory listings. */ /* Limits filenames to 16 chars. (VICE supports more */ /* in directory listings). */ #include <stdarg.h> #include <cbm.h> #include <errno.h> /* Opens directory listing. Returns 0 if opening directory was successful; ** otherwise, an error-code corresponding to cbm_open(). As an optional ** argument, the name of the directory may be passed to the function. If ** no explicit name is specified, "$" is used. */ unsigned char cbm_opendir (unsigned char lfn, unsigned char device, ...) { va_list ap; const char* name = "$"; /* The name used in cbm_open may optionally be passed */ if (__argsize__ == 4) { va_start (ap, device); name = va_arg (ap, const char*); va_end (ap); } /* Open the directory */ if (cbm_open (lfn, device, CBM_READ, name) == 0) { if ((_oserror = cbm_k_chkin (lfn)) == 0) { /* Ignore start address */ cbm_k_basin(); cbm_k_basin(); cbm_k_clrch(); if (cbm_k_readst()) { cbm_close(lfn); _oserror = 4; /* directory cannot be read */ } } } return _oserror; } /* Reads one directory line into cbm_dirent structure. ** Returns 0 if reading directory-line was successful. ** Returns non-zero if reading directory failed, or no more file-names to read. ** Returns 2 on last line. Then, l_dirent->size = the number of "blocks free." */ unsigned char __fastcall__ cbm_readdir (unsigned char lfn, register struct cbm_dirent* l_dirent) { unsigned char byte, i = 0; unsigned char is_header = 0; unsigned char rv = 1; if (!cbm_k_chkin(lfn)) { if (!cbm_k_readst()) { /* skip 2 bytes, next-BASIC-line pointer */ cbm_k_basin(); cbm_k_basin(); /* File-size or drive/partition number */ l_dirent->size = cbm_k_basin() | (cbm_k_basin() << 8); byte = cbm_k_basin(); switch (byte) { /* "B" BLOCKS FREE. */ case 'b': /* Read until end; careless callers might call us again. */ while (!cbm_k_readst()) { cbm_k_basin(); } rv = 2; /* EOF */ goto ret_val; /* Reverse-text shows when this is the directory header. */ case 0x12: /* RVS_ON */ is_header = 1; } while (byte != '\"') { /* prevent endless loop */ if (cbm_k_readst()) { rv = 3; goto ret_val; } byte = cbm_k_basin(); } while ((byte = cbm_k_basin()) != '\"') { /* prevent endless loop */ if (cbm_k_readst()) { rv = 4; goto ret_val; } if (i < sizeof (l_dirent->name) - 1) { l_dirent->name[i] = byte; ++i; } } l_dirent->name[i] = '\0'; if (is_header) { l_dirent->type = CBM_T_HEADER; /* Get the disk-format code. */ i = 6; do { l_dirent->access = byte = cbm_k_basin(); } while (--i != 0); } else { /* Go to the file-type column. */ while ((byte = cbm_k_basin()) == ' ') { /* prevent endless loop */ if (cbm_k_readst()) { rv = 5; goto ret_val; } } l_dirent->access = CBM_A_RW; /* "Splat" files shouldn't be read. */ if (byte == '*') { l_dirent->access = CBM_A_WO; byte = cbm_k_basin(); } /* Determine the file type */ l_dirent->type = _cbm_filetype (byte); /* Notice whether it's a directory or a deleted file. */ if (cbm_k_basin() == 'i' && byte == 'd') { l_dirent->type = CBM_T_DIR; } cbm_k_basin(); /* Locked files shouldn't be written. */ if ((byte = cbm_k_basin()) == '<') { l_dirent->access = (l_dirent->access == CBM_A_WO) ? 0 : CBM_A_RO; } } /* Read to the end of the line. */ while (byte != 0) { /* prevent endless loop */ if (cbm_k_readst()) { rv = 6; goto ret_val; } byte = cbm_k_basin(); } rv = 0; goto ret_val; } } ret_val: cbm_k_clrch(); return rv; } void __fastcall__ cbm_closedir (unsigned char lfn) { cbm_close(lfn); } �����������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/cbm_filetype.s�����������������������������������������������������������������0000664�0000000�0000000�00000003167�13473601511�0017061�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Determine the CBM file type. From cbm_dir.c by Josef Soucek. Moved into an ; assembler function by Ullrich von Bassewitz 2012-06-03 ; ; unsigned char __fastcall__ _cbm_filetype (unsigned char c); ; .include "cbm_filetype.inc" .macpack generic ; -------------------------------------------------------------------------- ; Table with types for a list of start characters .rodata .proc TypeTable .byte CBM_T_CBM ; c .byte CBM_T_DEL ; d .byte CBM_T_OTHER ; e .byte CBM_T_OTHER ; f .byte CBM_T_OTHER ; g .byte CBM_T_OTHER ; h .byte CBM_T_OTHER ; i .byte CBM_T_OTHER ; j .byte CBM_T_OTHER ; k .byte CBM_T_LNK ; l .byte CBM_T_OTHER ; m .byte CBM_T_OTHER ; n .byte CBM_T_OTHER ; o .byte CBM_T_PRG ; p .byte CBM_T_OTHER ; q .byte CBM_T_REL ; r .byte CBM_T_SEQ ; s .byte CBM_T_OTHER ; t .byte CBM_T_USR ; u .byte CBM_T_VRP ; v .endproc ; -------------------------------------------------------------------------- ; Mapper function .code .proc __cbm_filetype ldx #0 ; Clear high byte ; Check that the given char is in table range sec sbc #'c' bcc L1 cmp #.sizeof (TypeTable) bge L1 ; Ok, load the type tay lda TypeTable,y rts ; Out of table range, return CBM_T_OTHER L1: lda #CBM_T_OTHER rts .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/cbm_load.c���������������������������������������������������������������������0000664�0000000�0000000�00000001305�13473601511�0016127�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** Marc 'BlackJack' Rintsch, 06.03.2001 ** ** unsigned int __fastcall__ cbm_load(const char* name, ** unsigned char device, ** const unsigned char* data); */ #include <cbm.h> /* loads file "name" from given device to given address or to the load address ** of the file if "data" is 0 */ 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). */ cbm_k_setlfs(0, device, data == 0); cbm_k_setnam(name); return (cbm_k_load(0, (unsigned int)data) - (unsigned int)data); } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/cbm_open.s���������������������������������������������������������������������0000664�0000000�0000000�00000002145�13473601511�0016174�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.06.2002 ; ; Original C code by Marc 'BlackJack' Rintsch, 18.03.2001 ; ; unsigned char __fastcall__ cbm_open (unsigned char lfn, ; unsigned char device, ; unsigned char sec_addr, ; const char* name); ; /* Opens a file. Works just like the BASIC command. ; ** Returns 0 if opening was successful, otherwise an errorcode (see table ; ** below). ; */ ; { ; cbm_k_setlfs(lfn, device, sec_addr); ; cbm_k_setnam(name); ; return _oserror = cbm_k_open(); ; } ; .export _cbm_open .import popa .import _cbm_k_setlfs, _cbm_k_setnam, _cbm_k_open .import __oserror _cbm_open: pha txa pha ; Save name jsr popa ; Get sec_addr jsr _cbm_k_setlfs ; Call SETLFS, pop all args pla tax pla ; Get name jsr _cbm_k_setnam jsr _cbm_k_open sta __oserror rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/cbm_read.s���������������������������������������������������������������������0000664�0000000�0000000�00000005157�13473601511�0016154�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.06.2002 ; ; Original C code by Marc 'BlackJack' Rintsch, 19.03.2001 ; ; int __fastcall__ cbm_read (unsigned char lfn, void* buffer, unsigned int size) ; /* Reads up to "size" bytes from a file to "buffer". ; ** Returns the number of actually read bytes, 0 if there are no bytes left ; ** (EOF) or -1 in case of an error. _oserror contains an errorcode then (see ; ** table below). ; */ ; { ; static unsigned int bytesread; ; static unsigned char tmp; ; ; /* if we can't change to the inputchannel #lfn then return an error */ ; if (_oserror = cbm_k_chkin(lfn)) return -1; ; ; bytesread = 0; ; ; while (bytesread<size && !cbm_k_readst()) { ; tmp = cbm_k_basin(); ; ; /* the kernal routine BASIN sets ST to EOF if the end of file ; ** is reached the first time, then we have store tmp. ; ** every subsequent call returns EOF and READ ERROR in ST, then ; ** we have to exit the loop here immediatly. ; */ ; if (cbm_k_readst() & 0xBF) break; ; ; ((unsigned char*)buffer)[bytesread++] = tmp; ; } ; ; cbm_k_clrch(); ; return bytesread; ; } ; .include "cbm.inc" .export _cbm_read .importzp ptr1, ptr2, ptr3, tmp1 .import popax, popa .import __oserror _cbm_read: eor #$FF sta ptr1 txa eor #$FF sta ptr1+1 ; Save -size-1 jsr popax sta ptr2 stx ptr2+1 ; Save buffer jsr popa tax jsr CHKIN bcs @E1 ; Branch on error ; bytesread = 0; lda #$00 sta ptr3 sta ptr3+1 beq @L3 ; Branch always ; Loop @L1: jsr READST cmp #0 ; Status ok? bne @L4 jsr BASIN ; Read next char from file sta tmp1 ; Save it for later jsr READST and #$BF bne @L4 lda tmp1 ldy #0 sta (ptr2),y ; Save read byte inc ptr2 bne @L2 inc ptr2+1 ; ++buffer; @L2: inc ptr3 bne @L3 inc ptr3+1 ; ++bytesread; @L3: inc ptr1 bne @L1 inc ptr1+1 bne @L1 @L4: jsr CLRCH lda ptr3 ldx ptr3+1 ; return bytesread; rts ; CHKIN failed @E1: sta __oserror lda #$FF tax rts ; return -1 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/cbm_save.c���������������������������������������������������������������������0000664�0000000�0000000�00000001276�13473601511�0016155�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** Marc 'BlackJack' Rintsch, 11.03.2001 ** ** unsigned char cbm_save(const char* name, ** char device, ** unsigned char* data, ** unsigned int size); */ #include <cbm.h> #include <errno.h> /* saves a memory area from start to end-1 to a file. */ unsigned char __fastcall__ cbm_save (const char* name, unsigned char device, const void* data, unsigned int size) { cbm_k_setlfs(0, device, 0); cbm_k_setnam(name); return _oserror = cbm_k_save((unsigned int)data, ((unsigned int)data) + size); } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/cbm_write.s��������������������������������������������������������������������0000664�0000000�0000000�00000003747�13473601511�0016376�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 15.11.2002 ; ; Original C code by Marc 'BlackJack' Rintsch, 25.03.2001 ; ; int __fastcall__ cbm_write(unsigned char lfn, void* buffer, unsigned int size) ; { ; ; static unsigned int byteswritten; ; ; /* if we can't change to the outputchannel #lfn then return an error */ ; if (_oserror = cbm_k_ckout(lfn)) return -1; ; ; byteswritten = 0; ; ; while (byteswritten<size && !cbm_k_readst()) { ; cbm_k_bsout(((unsigned char*)buffer)[byteswritten++]); ; } ; ; if (cbm_k_readst()) { ; _oserror = 5; /* device not present */ ; byteswritten = -1; ; } ; ; cbm_k_clrch(); ; ; return byteswritten; ; } ; .include "cbm.inc" .export _cbm_write .importzp ptr1, ptr2, ptr3 .import popax, popa .import __oserror _cbm_write: sta ptr3 stx ptr3+1 ; Save size eor #$FF sta ptr1 txa eor #$FF sta ptr1+1 ; Save -size-1 jsr popax sta ptr2 stx ptr2+1 ; Save buffer jsr popa tax jsr CKOUT bcs @E2 ; Branch on error bcc @L3 ; Branch always ; Loop @L1: jsr READST cmp #0 ; Status ok? bne @E1 ldy #0 lda (ptr2),y ; inc ptr2 bne @L2 inc ptr2+1 ; A = *buffer++; @L2: jsr BSOUT ; cbm_k_bsout (A); @L3: inc ptr1 ; --size; bne @L1 inc ptr1+1 bne @L1 jsr CLRCH lda ptr3 ldx ptr3+1 ; return size; rts ; Error entry, called when READST fails @E1: lda #5 ; Error entry, error code is in A @E2: sta __oserror lda #$FF tax rts ; return -1 �������������������������cc65-2.18/libsrc/cbm/cclear.s�����������������������������������������������������������������������0000664�0000000�0000000�00000001365�13473601511�0015646�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 gotoxy, cputdirect .importzp tmp1 _cclearxy: pha ; Save the length 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 #$20 ; Blank - screen code jsr cputdirect ; Direct output dec tmp1 bne L1 L9: rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/chline.s�����������������������������������������������������������������������0000664�0000000�0000000�00000001365�13473601511�0015657�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 gotoxy, cputdirect .importzp tmp1, chlinechar _chlinexy: pha ; Save the length 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 #chlinechar ; Horizontal line, screen code jsr cputdirect ; Direct output dec tmp1 bne L1 L9: rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/clinechars.s�������������������������������������������������������������������0000664�0000000�0000000�00000000175�13473601511�0016526�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Chars used by chline () and cvline () ; .exportzp chlinechar = 64 .exportzp cvlinechar = 93 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/clock.s������������������������������������������������������������������������0000664�0000000�0000000�00000000504�13473601511�0015502�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 21.09.1998 ; ; clock_t clock (void); ; .include "cbm.inc" .export _clock .importzp sreg .proc _clock lda #0 ; Byte 3 is always zero sta sreg+1 jsr RDTIM sty sreg rts .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/close.s������������������������������������������������������������������������0000664�0000000�0000000�00000003376�13473601511�0015526�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 16.11.2002 ; ; int __fastcall__ close (int fd); ; .export _close .import readdiskerror, closecmdchannel .importzp tmp2 .include "errno.inc" .include "cbm.inc" .include "filedes.inc" ;-------------------------------------------------------------------------- ; _close .proc _close ; Check if we have a valid handle cpx #$00 bne invalidfd cmp #MAX_FDS ; Is it valid? bcs invalidfd ; Jump if no sta tmp2 ; Save the handle ; Check if the file is actually open tax lda fdtab,x ; Get flags for this handle and #LFN_OPEN beq invalidfd ; Valid lfn, close it. The close call is always error free, at least as far ; as the kernal is involved lda #LFN_CLOSED sta fdtab,x txa ; Get handle clc adc #LFN_OFFS ; Make LFN from handle jsr CLOSE ; Read the drive error channel, then close it ldy tmp2 ; Get the handle ldx unittab,y ; Get the disk for this handle jsr readdiskerror ; Read the disk error code pha ; Save it on stack ldy tmp2 ldx unittab,y jsr closecmdchannel ; Close the disk command channel pla ; Get the error code from the disk jmp __mappederrno ; Set _oserror and _errno, return 0/-1 ; Error entry: The given file descriptor is not valid or not open invalidfd: lda #EBADF jmp __directerrno ; Set _errno, clear _oserror, return -1 .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/closedir.s���������������������������������������������������������������������0000664�0000000�0000000�00000001275�13473601511�0016221�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2012-05-30 ; ; Based on C code by Groepaz ; ; int __fastcall__ closedir(DIR *dir); ; .include "dir.inc" .include "zeropage.inc" .import _close, _free .proc _closedir sta ptr1 stx ptr1+1 ; Load dir->fd ldy #DIR::fd+1 lda (ptr1),y tax dey lda (ptr1),y ; Close the file jsr _close ; Save the error code pha txa pha ; Free the memory block lda ptr1 ldx ptr1+1 jsr _free ; Return the error code from close() pla tax pla rts .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/cpeekc.s�����������������������������������������������������������������������0000664�0000000�0000000�00000002354�13473601511�0015646�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2016-02-28, Groepaz ; 2017-06-22, Greg King ; ; char cpeekc (void); ; .export _cpeekc ; Get a system-specific file. ; Note: The cbm610, and c128 targets need special ; versions that handle RAM banking and the 80-column VDC. .if .def(__C16__) .include "plus4.inc" ; both C16 and Plus4 .elseif .def(__C64__) .include "c64.inc" .elseif .def(__CBM510__) .import CURS_X: zp, SCREEN_PTR: zp .include "cbm510.inc" .elseif .def(__PET__) .include "pet.inc" .elseif .def(__VIC20__) .include "vic20.inc" .endif _cpeekc: ldy CURS_X lda (SCREEN_PTR),y ; get screen code ldx #>$0000 and #<~$80 ; remove reverse bit ; Convert the screen code into a PetSCII code. ; $00 - $1F: +$40 ; $20 - $3F ; $40 - $5f: +$20 ; $60 - $7F: +$40 cmp #$20 bcs @sk1 ;(bge) ora #$40 rts @sk1: cmp #$40 bcc @end ;(blt) cmp #$60 bcc @sk2 ;(blt) ;sec adc #$20 - $01 @sk2: ;clc ; both above cmp and adc clear carry flag adc #$20 @end: rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/cpeekcolor.s�������������������������������������������������������������������0000664�0000000�0000000�00000001174�13473601511�0016541�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2016-02-28, Groepaz ; 2017-06-22, Greg King ; ; unsigned char cpeekcolor (void); ; .export _cpeekcolor ; Get a system-specific file. ; Note: The cbm510, cbm610, c128, and Pet targets need special ; versions that handle RAM banking, the 80-column VDC, and monochrome. .if .def(__C16__) .include "plus4.inc" ; both C16 and Plus4 .elseif .def(__C64__) .include "c64.inc" .elseif .def(__VIC20__) .include "vic20.inc" .endif _cpeekcolor: ldy CURS_X lda (CRAM_PTR),y ; get color and #$0F ldx #>$0000 rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/cpeekrevers.s������������������������������������������������������������������0000664�0000000�0000000�00000001620�13473601511�0016725�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2016-02-28, Groepaz ; 2017-06-15, Greg King ; ; unsigned char cpeekrevers (void); ; .export _cpeekrevers ; Get a system-specific file. ; Note: The cbm610, and c128 targets need special ; versions that handle RAM banking and the 80-column VDC. .if .def(__C16__) .include "plus4.inc" ; both C16 and Plus4 .elseif .def(__C64__) .include "c64.inc" .elseif .def(__CBM510__) .import CURS_X: zp, SCREEN_PTR: zp .include "cbm510.inc" .elseif .def(__PET__) .include "pet.inc" .elseif .def(__VIC20__) .include "vic20.inc" .endif _cpeekrevers: ldy CURS_X lda (SCREEN_PTR),y ; get screen code and #$80 ; get reverse bit asl a tax ; ldx #>$0000 rol a ; return boolean value rts ����������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/cpeeks.s�����������������������������������������������������������������������0000664�0000000�0000000�00000004246�13473601511�0015670�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2017-07-05, Greg King ; ; void cpeeks (char* s, unsigned length); ; .export _cpeeks .import popax .importzp ptr1, ptr2, ptr3, tmp1, tmp2 .macpack generic ; Get a system-specific file. ; Note: The cbm610, and c128 targets need special ; versions that handle RAM banking and the 80-column VDC. .if .def(__C16__) .include "plus4.inc" ; both C16 and Plus4 .elseif .def(__C64__) .include "c64.inc" .elseif .def(__CBM510__) .import CURS_X: zp, SCREEN_PTR: zp .include "cbm510.inc" .elseif .def(__PET__) .include "pet.inc" .elseif .def(__VIC20__) .include "vic20.inc" .endif _cpeeks: eor #<$FFFF ; counting a word upward is faster sta ptr3 ; so, we use -(length + 1) txa eor #>$FFFF sta ptr3+1 lda SCREEN_PTR ldx SCREEN_PTR+1 sta ptr2 stx ptr2+1 ldy CURS_X sty tmp2 jsr popax sta tmp1 ; (will be a .Y index) stx ptr1+1 ldx #<$0000 stx ptr1 bze L3 ; branch always L4: ldy tmp2 lda (ptr2),y ; get char iny bnz L2 inc ptr2+1 L2: sty tmp2 and #<~$80 ; remove reverse bit ; Convert the screen code into a PetSCII code. ; $00 - $1F: +$40 ; $20 - $3F ; $40 - $5f: +$20 ; $60 - $7F: +$40 cmp #$20 blt @sk1 ;(bcc) cmp #$40 blt L5 cmp #$60 blt @sk2 ;(bcc) clc @sk1: adc #$20 @sk2: ;clc ; both above cmp and adc clear carry flag adc #$20 L5: ldy tmp1 sta (ptr1),y iny bnz L1 inc ptr1+1 L1: sty tmp1 L3: inc ptr3 ; count length bnz L4 inc ptr3+1 bnz L4 txa ; terminate the string ldy tmp1 sta (ptr1),y rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/ctype.s������������������������������������������������������������������������0000664�0000000�0000000�00000050125�13473601511�0015537�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Character specification table. ; ; Ullrich von Bassewitz, 02.06.1998 ; 2003-05-02, Greg King ; ; 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_ �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/curdevice.s��������������������������������������������������������������������0000664�0000000�0000000�00000000533�13473601511�0016362�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2012-10-21 ; ; unsigned char getcurrentdevice (void); ; .export _getcurrentdevice .import curunit ;------------------------------------------------------------------------------ ; _getcurrentdevice .proc _getcurrentdevice lda curunit ldx #$00 rts .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/cvline.s�����������������������������������������������������������������������0000664�0000000�0000000�00000001511�13473601511�0015666�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 gotoxy, putchar, newline .importzp tmp1, cvlinechar _cvlinexy: pha ; Save the length 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 #cvlinechar ; Vertical bar jsr putchar ; Write, no cursor advance jsr newline ; Advance cursor to next line dec tmp1 bne L1 L9: rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/devicedir.s��������������������������������������������������������������������0000664�0000000�0000000�00000002474�13473601511�0016355�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2012-09-10 ; ; char* __fastcall__ getdevicedir (unsigned char device, char* buf, size_t size); ; .export _getdevicedir .import diskinit, devicestr, fnunit .import popa, popax .importzp ptr2, ptr3 .include "errno.inc" ;------------------------------------------------------------------------------ ; _getdevicedir .proc _getdevicedir ; Save size sta ptr3 stx ptr3+1 ; Save buf jsr popax sta ptr2 stx ptr2+1 ; Check device readiness jsr popa jsr diskinit beq size jsr __mappederrno bne fail ; Branch always ; Check for sufficient buf size size: lda ptr3+1 bne okay ; Buf >= 256 lda ptr3 cmp #3 bcs okay ; Buf >= 3 lda #<ERANGE jsr __directerrno fail: lda #0 ; Return NULL tax rts ; Copy device string representation into buf okay: lda fnunit ; Set by diskinit jsr devicestr ; Returns 0 in A sta __oserror ; Clear _oserror ; Success, return buf lda ptr2 ldx ptr2+1 rts .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/dir.h��������������������������������������������������������������������������0000664�0000000�0000000�00000002611�13473601511�0015153�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** Internal include file, do not use directly. ** Written by Ullrich von Bassewitz. Based on code by Groepaz. */ #ifndef _DIR_H #define _DIR_H #include <dirent.h> /*****************************************************************************/ /* Data */ /*****************************************************************************/ struct DIR { int fd; /* File descriptor for directory */ unsigned off; /* Current byte offset in directory */ char name[16+1]; /* Name passed to opendir */ }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned char __fastcall__ _dirread (DIR* dir, void* buf, unsigned char count); /* Read characters from the directory into the supplied buffer. Makes sure, ** errno is set in case of a short read. Return true if the read was ** successful and false otherwise. */ unsigned char __fastcall__ _dirread1 (DIR* dir, void* buf); /* Read one byte from the directory into the supplied buffer. Makes sure, ** errno is set in case of a short read. Return true if the read was ** successful and false otherwise. */ /* End of dir.h */ #endif �����������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/dir.inc������������������������������������������������������������������������0000664�0000000�0000000�00000001162�13473601511�0015475�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Internal include file, do not use directly. ; Written by Ullrich von Bassewitz. Based on C code by Groepaz. ; ;------------------------------------------------------------------------------ ; Data structures .struct DIR fd .word off .word name .byte 16+1 .endstruct ;------------------------------------------------------------------------------ ; C callable functions .global _opendir .global _closedir .global _readdir .global _seekdir .global _telldir .global _rewinddir .global __dirread .global __dirread1 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/dir.s��������������������������������������������������������������������������0000664�0000000�0000000�00000004647�13473601511�0015201�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2012-06-01 ; ; Helper functions for open-/read-/closedir .include "dir.inc" .include "errno.inc" .include "zeropage.inc" .import pushax .import _read ;--------------------------------------------------------------------------- ; ; unsigned char __fastcall__ _dirread1 (DIR* dir, void* buf); ; /* Read one byte from the directory into the supplied buffer. Makes sure, ; ** errno is set in case of a short read. Return true if the read was ; ** successful and false otherwise. ; */ __dirread1: jsr pushax ; Push buf lda #1 ; Load count = 1 ; Run directly into __dirread ;--------------------------------------------------------------------------- ; ; unsigned char __fastcall__ _dirread (DIR* dir, void* buf, unsigned char count); ; /* Read characters from the directory into the supplied buffer. Makes sure, ; ** errno is set in case of a short read. Return true if the read was ; ** successful and false otherwise. ; */ __dirread: ; Save count pha ; Replace dir by dir->fd ldy #2 lda (sp),y sta ptr1 iny lda (sp),y sta ptr1+1 ldy #DIR::fd+1 lda (ptr1),y pha dey lda (ptr1),y ldy #2 sta (sp),y pla iny sta (sp),y ; Get count, save it again, clear the high byte and call read(). By the ; previous actions, the stack frame is as read() needs it, and read() will ; also drop it. pla pha ldx #0 jsr _read ; Check for errors. cpx #$FF bne L3 ; read() returned an error, so errno is already set pla ; Drop count inx ; X = 0 L1: txa ; Return zero L2: rts ; read() was successful, check number of bytes read. We assume that read will ; not return more than count, so X is zero if we come here. L3: sta tmp1 ; Save returned count pla ; Our count cmp tmp1 beq L2 ; Ok, return count ; Didn't read enough bytes. This is an error for us, but errno is not set lda #<EIO sta __errno stx __errno+1 ; X is zero bne L1 ; Branch always �����������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/diskcmd.s����������������������������������������������������������������������0000664�0000000�0000000�00000014133�13473601511�0016030�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2002-11-17, 2009-02-22 ; ; Handle disk command channels ; .export isdisk .export opencmdchannel .export closecmdchannel .export readdiskerror .export writediskcmd .export writefndiskcmd .import fncmd, fnlen, fnunit .importzp tmp1, ptr1 .include "cbm.inc" .include "filedes.inc" ;-------------------------------------------------------------------------- ; isdisk: Return carry clear if the unit number in X is a disk, return ; carry set if not. .proc isdisk cpx #FIRST_DRIVE ; Disk unit? bcc @L1 ; Branch if no disk cpx #FIRST_DRIVE+MAX_DRIVES rts @L1: sec rts .endproc ;-------------------------------------------------------------------------- ; Open the command channel for the disk unit in X. The function returns an ; error code in A and sets the flags according to the contents of A. opencmdchannel: jsr isdisk ; Disk unit? bcs success ; Is this channel already open? ldy opentab-FIRST_DRIVE,x bne isopen ; Open the command channel, Carry is still clear stx tmp1 ; Save the unit number txa ; Get unit number adc #(LFN_OFFS+MAX_FDS-FIRST_DRIVE) ldy #15 ; Secondary address for cmd channel jsr SETLFS lda #0 jsr SETNAM ; No name supplied to OPEN jsr OPEN bcs done ; Error, code is in A ; Command channel is open now. Increment the count ldx tmp1 ; Unit number ldy opentab-FIRST_DRIVE,x isopen: iny tya sta opentab-FIRST_DRIVE,x ; Done, return success success:lda #$00 done: cmp #$00 ; Set flags for return code rts ;-------------------------------------------------------------------------- ; closecmdchannel: Decrement the counter for the disk command channel and ; close the channel if the counter drops to zero. The function expects the ; drive number in X and returns an error code in A. The flags for the return ; code are set when the function returns. closecmdchannel: jsr isdisk ; Disk unit? bcs success ; Is this channel really open? ldy opentab-FIRST_DRIVE,x beq success ; OOPS! Channel is not open ; Decrement the count and stor it back dey tya sta opentab-FIRST_DRIVE,x ; If the counter is now zero, close the channel. We still have carry clear ; when we come here. bne success txa ; Make LFN from drive number adc #(LFN_OFFS+MAX_FDS-FIRST_DRIVE) jsr CLOSE bcs done bcc success ;-------------------------------------------------------------------------- ; readdiskerror: Read a disk error from an already open command channel. ; Returns an error code in A, which may either be the code read from the ; command channel, or another error when accessing the command channel failed. readdiskerror: jsr isdisk bcs success ; Read the command channel. We won't check the status after the channel is ; open, because this seems to be unnecessary in most cases. txa clc ; Make LFN from drive number adc #(LFN_OFFS+MAX_FDS-FIRST_DRIVE) tax jsr CHKIN ; Make the command channel input bcs done ; Bail out with error code in A jsr BASIN and #$0F ; Make digit value from PETSCII sta tmp1 asl a ; * 2 asl a ; * 4, carry clear adc tmp1 ; * 5 asl a ; * 10 sta tmp1 jsr BASIN and #$0F ; Make digit value from PETSCII clc adc tmp1 ; Errors below 20 are not real errors. Fix that cmp #20+1 bcs @L1 lda #$00 @L1: pha ; Read the remainder of the message and throw it away @L2: jsr BASIN cmp #$0D bne @L2 ; Close the input channel jsr CLRCH ; Restore the error code (will also set the flags) and return pla rts ;-------------------------------------------------------------------------- ; writefndiskcmd: Write the contents of fncmd to the command channel of the ; drive in fnunit. Returns an error code in A, flags are set according to ; the contents of A. writefndiskcmd: lda #<fncmd sta ptr1 lda #>fncmd sta ptr1+1 ldx fnlen inx ; Account for command char in fncmd txa ; Length of name into A ldx fnunit ; Unit ; Run directly into writediskcmd ; jmp writediskcmd ;-------------------------------------------------------------------------- ; writediskcmd: Gets pointer to data in ptr1, length in A. Writes all data ; to the command channel of the drive in X. Returns an error code in A, ; flags are set according to the contents of A. writediskcmd: jsr isdisk bcs success ; No disk - already done ; Remember the length sta tmp1 ; Write to the command channel. txa clc ; Make LFN from drive number adc #(LFN_OFFS+MAX_FDS-FIRST_DRIVE) tax jsr CKOUT ; Make the command channel output bcs done ; Bail out with error code in A ldy #$00 @L1: cpy tmp1 bcs @L3 lda (ptr1),y iny jsr BSOUT bcc @L1 @L2: pha jsr CLRCH pla rts @L3: jsr CLRCH lda #$00 rts ;-------------------------------------------------------------------------- ; Data .bss opentab: .res MAX_DRIVES, 0 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/diskinit.s���������������������������������������������������������������������0000664�0000000�0000000�00000001622�13473601511�0016227�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2012-10-17 ; .export diskinit .import opencmdchannel, closecmdchannel .import writefndiskcmd, readdiskerror .import isdisk, fnunit, fncmd ;------------------------------------------------------------------------------ ; diskinit .proc diskinit ; Save device sta fnunit ; Check for disk device tax jsr isdisk bcc open lda #9 ; "Illegal device" rts ; Open channel open: jsr opencmdchannel bne done ; Write command lda #'i' ; Init command sta fncmd jsr writefndiskcmd bne close ; Read error ldx fnunit jsr readdiskerror ; Close channel close: pha ldx fnunit jsr closecmdchannel pla done: rts .endproc ��������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/exec.c�������������������������������������������������������������������������0000664�0000000�0000000�00000012063�13473601511�0015316�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** Program-chaining function for Commodore platforms. ** ** 2015-09-27, Greg King ** ** This function exploits the program-chaining feature in CBM BASIC's ROM. ** ** CC65's CBM programs have a BASIC program stub. We start those programs by ** RUNning that stub; it SYSes to the Machine Language code. Normally, after ** the ML code exits, the BASIC ROM continues running the stub. But, it has ** no more statements; so, the program stops. ** ** This function puts the desired program's name and device number into a LOAD ** statement. Then, it points BASIC to that statement, so that the ROM will run ** that statement after this program quits. The ROM will load the next program, ** and will execute it (because the LOAD will be seen in a running program). */ #include <fcntl.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <device.h> #if defined(__CBM610__) # include <cbm610.h> #elif defined(__CBM510__) # include <cbm510.h> #endif /* 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 CLR:LOAD""+"" ,01 ** After this function has written into the line, it might look like this: ** 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 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 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; /* fake previous line */ const struct line* const next; const unsigned line_num; 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, 0x9C, ':', 0x93, "\"\"", 0xAA, '\"', "\" ", /* format: "123:1234567890123456\"" */ ',', "01" }; #pragma data-name(pop) /* These values are platform-specific. */ 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 void basbuf_len[]; #pragma zpsym("basbuf_len") int __fastcall__ exec (const char* progname, const char* cmdline) { static int fd; static unsigned char dv, n; /* Exclude devices that can't load files. */ /* (Use hand optimization, to make smaller code.) */ dv = getcurrentdevice (); if (dv < 8 && __AX__ != 1 || __AX__ > 30) { return _mappederrno (9); /* illegal device number */ } utoa (dv, basic.unit, 10); /* 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); } n = 0; do { if ((basic.name[n] = progname[n]) == '\0') { break; } } 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[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 [status], will be destroyed by LOAD. ** So, don't bother to set it here.) */ exit (__AX__); } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/execvars.s���������������������������������������������������������������������0000664�0000000�0000000�00000001564�13473601511�0016236�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Platform-specific variables for the exec program-chaining function ; .if .defined (__C128__) .include "c128.inc" .elseif .defined (__C16__) .include "c16.inc" .elseif .defined (__C64__) .include "c64.inc" .elseif .defined (__CBM510__) .include "cbm510.inc" .elseif .defined (__CBM610__) .include "cbm610.inc" .elseif .defined (__PET__) .include "pet.inc" .elseif .defined (__PLUS4__) .include "plus4.inc" .else .include "vic20.inc" .endif ; exec() is written in C. ; Provide the spellings that the C compiler wants to use. .ifdef VARTAB .exportzp _vartab := VARTAB .exportzp _memsize := MEMSIZE .endif .exportzp _txtptr := TXTPTR .export _basbuf := BASIC_BUF .exportzp _basbuf_len = BASIC_BUF_LEN ��������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/exehdr.s�����������������������������������������������������������������������0000664�0000000�0000000�00000002240�13473601511�0015665�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2010-11-14 ; ; This module supplies a small BASIC stub program that jumps to the machine ; language code that follows it using SYS. ; ; The following symbol is used by linker config to force the module ; to get included into the output file .export __EXEHDR__: absolute = 1 .segment "EXEHDR" .addr Next .word .version ; Line number .byte $9E ; SYS token ; .byte <(((Start / 10000) .mod 10) + '0') .byte <(((Start / 1000) .mod 10) + '0') .byte <(((Start / 100) .mod 10) + '0') .byte <(((Start / 10) .mod 10) + '0') .byte <(((Start / 1) .mod 10) + '0') .byte $00 ; End of BASIC line Next: .word 0 ; BASIC end marker Start: ; If the start address is larger than 4 digits, the header generated above ; will not contain the highest digit. Instead of wasting one more digit that ; is almost never used, check it at link time and generate an error so the ; user knows something is wrong. .assert (Start < 10000), error, "Start address too large for generated BASIC stub" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/filedes.inc��������������������������������������������������������������������0000664�0000000�0000000�00000001176�13473601511�0016337�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 16.11.2002 ; ; File descriptor management for the POSIX I/O routines ; .global fdtab ; Handle table .global unittab ; Unit table .global freefd ; Return a table entry MAX_FDS = 8 ; Maximum number of file descriptors LFN_OFFS = 3 ; Start with logical file number 3 LFN_CLOSED = $00 ; LFN is closed LFN_READ = $01 ; Open for reading LFN_WRITE = $02 ; Open for writing LFN_OPEN = (LFN_READ | LFN_WRITE) LFN_EOF = $80 ; Read to EOF LFN_STDIN = LFN_OFFS+0 LFN_STDOUT = LFN_OFFS+1 LFN_STDERR = LFN_OFFS+2 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/filedes.s����������������������������������������������������������������������0000664�0000000�0000000�00000001550�13473601511�0016024�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 16.11.2002 ; ; File descriptor management for the POSIX I/O routines ; .include "cbm.inc" .include "filedes.inc" .code ;-------------------------------------------------------------------------- ; freefd: Find a free file handle and return it in X. Return carry clear if we ; found one, return a carry if no free lfns are left. .proc freefd ldx #0 clc loop: lda fdtab,x beq found inx cpx #MAX_FDS bcc loop found: rts .endproc ;-------------------------------------------------------------------------- ; Data .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 ��������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/filename.s���������������������������������������������������������������������0000664�0000000�0000000�00000011653�13473601511�0016176�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 16.11.2002 ; ; File name handling for CBM file I/O ; .export fnparse, fnparsename, fnset .export fnadd, fnaddmode, fncomplete, fndefunit .export fnunit, fnlen, fnisfile, fncmd, fnbuf .import curunit, __filetype .importzp ptr1, tmp1 .include "ctype.inc" .include "cbm.inc" ;------------------------------------------------------------------------------ ; fnparsename: Parse a filename (without drive spec) passed in in ptr1 and y. .proc fnparsename lda #0 sta tmp1 ; Remember length of name nameloop: lda (ptr1),y ; Get next char from filename beq namedone ; Jump if end of name reached ; Check the maximum length, store the character ldx tmp1 cpx #16 ; Maximum length reached? bcs invalidname lda (ptr1),y ; Reload char jsr fnadd ; Add character to name iny ; Next char from name inc tmp1 ; Increment length of name bne nameloop ; Branch always ; Invalid file name invalidname: lda #33 ; Invalid file name ; Done, we've successfully parsed the name. namedone: rts .endproc ;------------------------------------------------------------------------------ ; fnparse: Parse a full filename passed in in a/x. Will set the following ; variables: ; ; fnlen -> length of filename ; fnbuf -> filename including drive spec ; fnunit -> unit from spec or default unit ; ; Returns an error code in A or zero if all is ok. .proc fnparse sta ptr1 stx ptr1+1 ; Save pointer to name ; For now we will always use the default unit jsr fndefunit ; Check the name for a drive spec ldy #0 lda (ptr1),y cmp #'0' beq digit cmp #'1' bne nodrive digit: sta fnbuf+0 iny lda (ptr1),y cmp #':' bne nodrive ; We found a drive spec, copy it to the buffer sta fnbuf+1 iny ; Skip colon bne drivedone ; Branch always ; We did not find a drive spec, always use drive zero nodrive: lda #'0' sta fnbuf+0 lda #':' sta fnbuf+1 ldy #$00 ; Reposition to start of name ; Drive spec done. We do now have a drive spec in the buffer. drivedone: lda #2 ; Length of drive spec sta fnlen ; Assume this is a standard file on disk sta fnisfile ; Special treatment for directory. If the file name is "$", things are ; actually different: $ is directory for unit 0, $0 dito, $1 is directory ; for unit 1. For simplicity, we won't check anything else if the first ; character of the file name is '$'. lda (ptr1),y ; Get first character cmp #'$' ; bne fnparsename ; Juggle stuff ldx fnbuf+0 ; unit stx fnbuf+1 sta fnbuf+0 ; Add the file mask lda #':' sta fnbuf+2 lda #'*' sta fnbuf+3 lda #4 sta fnlen ; No need to check the name. Length is already 2 lda #0 ; ok flag sta fnisfile ; This is not a real file rts .endproc ;-------------------------------------------------------------------------- ; fndefunit: Use the default unit .proc fndefunit lda curunit sta fnunit rts .endproc ;-------------------------------------------------------------------------- ; fnset: Tell the kernal about the file name .proc fnset lda fnlen ldx #<fnbuf ldy #>fnbuf jmp SETNAM .endproc ;-------------------------------------------------------------------------- ; fncomplete: Complete a filename by adding ",t,m" where t is the file type ; and m is the access mode passed in in the A register ; ; fnaddmode: Add ",m" to a filename, where "m" is passed in A fncomplete: pha ; Save mode lda __filetype jsr fnaddmode ; Add the type pla fnaddmode: pha lda #',' jsr fnadd pla fnadd: ldx fnlen inc fnlen sta fnbuf,x rts ;-------------------------------------------------------------------------- ; Data .bss fnunit: .res 1 fnlen: .res 1 fnisfile: .res 1 ; Flags standard file (as opposed to "$") .data fncmd: .byte 's' ; Use as scratch command fnbuf: .res 35 ; Either 0:0123456789012345,t,m ; Or 0:0123456789012345=0123456789012345 �������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/filetype.s���������������������������������������������������������������������0000664�0000000�0000000�00000000333�13473601511�0016230�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2012-07-15 ; ; Default file type used when creating new files ; .export __filetype .data __filetype: .byte 's' ; Create sequential files by default �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/filevars.s���������������������������������������������������������������������0000664�0000000�0000000�00000000654�13473601511�0016230�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 15.11.2002 ; ; Variables used for CBM file I/O ; .export curunit .constructor initcurunit, 30 .importzp devnum .segment "INIT" curunit: .res 1 .segment "ONCE" .proc initcurunit lda devnum bne @L0 lda #8 ; Default is disk sta devnum @L0: sta curunit rts .endproc ������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/getdevice.s��������������������������������������������������������������������0000664�0000000�0000000�00000003132�13473601511�0016346�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2012-09-04 ; ; unsigned char getfirstdevice (void); ; unsigned char __fastcall__ getnextdevice (unsigned char device); ; .export _getfirstdevice .export _getnextdevice .import isdisk .import opencmdchannel .import closecmdchannel .importzp ST .importzp tmp2 ;------------------------------------------------------------------------------ ; _getfirstdevice _getfirstdevice: lda #$FF ; Fall through ;------------------------------------------------------------------------------ ; _getnextdevice _getnextdevice: tax next: inx cpx #$FF beq done ; [open|close]cmdchannel already call isdisk internally but they ; interpret a non-disk as a no-op while we need to interpret it ; as an error here jsr isdisk bcs next ; [open|close]cmdchannel don't call into the Kernal at all if they ; only [in|de]crement the reference count of the shared cmdchannel ; so we need to explicitly initialize ST here lda #$00 sta ST stx tmp2 jsr opencmdchannel ldx tmp2 jsr closecmdchannel ldx tmp2 ; As we had to reference ST above anyway we can as well do so ; here too (instead of calling READST) lda ST ; Either the Kernal calls above were successfull or there was ; already a cmdchannel to the device open - which is a pretty ; good indication of its existence ;-) bmi next done: txa ldx #$00 rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/getres.s�����������������������������������������������������������������������0000664�0000000�0000000�00000001336�13473601511�0015704�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 15.8.2018 ; ; int __fastcall__ clock_getres (clockid_t clk_id, struct timespec *res); ; .include "time.inc" .importzp ptr1 .import incsp1, return0 ;---------------------------------------------------------------------------- .code .proc _clock_getres sta ptr1 stx ptr1+1 ldy #.sizeof(timespec)-1 @L1: lda time,y sta (ptr1),y dey bpl @L1 jsr incsp1 jmp return0 .endproc ;---------------------------------------------------------------------------- ; timespec struct with tv_nsec set to 1/10 second .rodata time: .dword 0 .dword 100 * 1000 * 1000 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/gotox.s������������������������������������������������������������������������0000664�0000000�0000000�00000000415�13473601511�0015550�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 07.08.1998 ; ; void gotox (unsigned char x); ; .export _gotox .import plot .importzp CURS_X _gotox: sta CURS_X ; Set new position jmp plot ; And activate it ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/gotoxy.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000676�13473601511�0015752�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; void gotoxy (unsigned char x, unsigned char y); ; .export gotoxy, _gotoxy .import popa, plot .importzp CURS_X, CURS_Y gotoxy: jsr popa ; Get Y _gotoxy: sta CURS_Y ; Set Y jsr popa ; Get X sta CURS_X ; Set X jmp plot ; Set the cursor position ������������������������������������������������������������������cc65-2.18/libsrc/cbm/gotoy.s������������������������������������������������������������������������0000664�0000000�0000000�00000000420�13473601511�0015545�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 0.08.1998 ; ; void gotoy (unsigned char y); ; .export _gotoy .import plot .importzp CURS_Y _gotoy: sta CURS_Y ; Set the new position jmp plot ; And activate it ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/initcwd.s����������������������������������������������������������������������0000664�0000000�0000000�00000001646�13473601511�0016060�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Stefan Haubenthal, 2005-06-08 ; ; CBM _curunit to _cwd ; .export initcwd, devicestr .import curunit, __cwd .import pusha0, tosudiva0 .importzp sreg, ptr1, ptr2 .macpack generic initcwd: lda #<__cwd ldx #>__cwd sta ptr2 stx ptr2+1 lda curunit ; Fall through ;------------------------------------------------------------------------------ ; Convert unit number in A into string representation pointed to by ptr2. devicestr: jsr pusha0 lda #10 jsr tosudiva0 ldy #0 lda sreg beq @L0 ; >=10 add #'0' sta (ptr2),y iny @L0: lda ptr1 ; rem add #'0' sta (ptr2),y iny lda #0 sta (ptr2),y rts ������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/loadaddr.s���������������������������������������������������������������������0000664�0000000�0000000�00000000617�13473601511�0016166�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2010-11-13 ; ; This module supplies the load address that is expected by Commodore ; machines in the first two bytes of an excutable disk file. ; ; The following symbol is used by linker config to force the module ; to get included into the output file .export __LOADADDR__: absolute = 1 .segment "LOADADDR" .addr *+2 �����������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/mcbpointercolor.s��������������������������������������������������������������0000664�0000000�0000000�00000000266�13473601511�0017615�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; VIC sprite color for the mouse pointer .export _mouse_def_pointercolor .segment "ONCE" _mouse_def_pointercolor: .byte $01 ; White ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/mcbpointershape.s��������������������������������������������������������������0000664�0000000�0000000�00000002334�13473601511�0017575�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; VIC sprite data for the mouse pointer (an arrow) .export _mouse_def_pointershape .segment "ONCE" _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 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/open.s�������������������������������������������������������������������������0000664�0000000�0000000�00000011662�13473601511�0015357�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 16.11.2002 ; ; int open (const char* name, int flags, ...); /* May take a mode argument */ .export _open .destructor closeallfiles, 5 .import addysp, popax .import scratch, fnparse, fnaddmode, fncomplete, fnset .import opencmdchannel, closecmdchannel, readdiskerror .import fnunit, fnisfile .import _close .importzp sp, tmp2, tmp3 .include "errno.inc" .include "fcntl.inc" .include "filedes.inc" .include "cbm.inc" ;-------------------------------------------------------------------------- ; closeallfiles: Close all open files. .proc closeallfiles ldx #MAX_FDS-1 loop: lda fdtab,x beq next ; Skip unused entries ; Close this file txa pha ; Save current value of X ldx #0 jsr _close pla tax ; Next file next: dex bpl loop rts .endproc ;-------------------------------------------------------------------------- ; _open .proc _open ; Throw away any additional parameters passed through the ellipsis dey ; Parm count < 4 shouldn't be needed to be... dey ; ...checked (it generates a c compiler warning) dey dey beq parmok ; Branch if parameter count ok jsr addysp ; Fix stack, throw away unused parameters ; Parameters ok. Pop the flags and save them into tmp3 parmok: jsr popax ; Get flags sta tmp3 ; Get the filename from stack and parse it. Bail out if is not ok jsr popax ; Get name jsr fnparse ; Parse it tax bne oserror ; Bail out if problem with name ; Get a free file handle and remember it in tmp2 jsr freefd lda #EMFILE ; Load error code bcs seterrno ; Jump in case of errors stx tmp2 ; Check the flags. We cannot have both, read and write flags set, and we cannot ; open a file for writing without creating it. lda tmp3 and #(O_RDWR | O_CREAT) cmp #O_RDONLY ; Open for reading? beq doread ; Yes: Branch cmp #(O_WRONLY | O_CREAT) ; Open for writing? beq dowrite ; Invalid open mode lda #EINVAL ; Error entry. Sets _errno, clears _oserror, returns -1 seterrno: jmp __directerrno ; Error entry: Close the file and exit. OS error code is in A on entry closeandexit: pha lda tmp2 clc adc #LFN_OFFS jsr CLOSE ldx fnunit jsr closecmdchannel pla ; Error entry: Set oserror and errno using error code in A and return -1 oserror:jmp __mappederrno ; Read bit is set. Add an 'r' to the name doread: lda #'r' jsr fnaddmode ; Add the mode to the name lda #LFN_READ bne common ; Branch always ; If O_TRUNC is set, scratch the file, but ignore any errors dowrite: lda tmp3 and #O_TRUNC beq notrunc jsr scratch ; Complete the the file name. Check for append mode here. notrunc: lda tmp3 ; Get the mode again and #O_APPEND ; Append mode? bne append ; Branch if yes ; Setup the name for create mode lda #'w' jsr fncomplete ; Add type and mode to the name jmp appendcreate ; Append bit is set. Add an 'a' to the name append: lda #'a' jsr fnaddmode ; Add open mode to file name appendcreate: lda #LFN_WRITE ; Common read/write code. Flags in A, handle in tmp2 common: sta tmp3 jsr fnset ; Set the file name lda tmp2 clc adc #LFN_OFFS ldx fnunit ldy fnisfile ; Is this a standard file on disk? beq nofile ; Branch if not tay ; Use the LFN also as SA for files nofile: ; ... else use SA=0 (read) jsr SETLFS ; Set the file params jsr OPEN bcs oserror ; Open the the drive command channel and read it ldx fnunit jsr opencmdchannel bne closeandexit ldx fnunit jsr readdiskerror bne closeandexit ; Branch on error ; File is open. Mark it as open in the table ldx tmp2 lda tmp3 sta fdtab,x lda fnunit sta unittab,x ; Remember ; Done. Return the handle in a/x txa ; Handle ldx #0 stx __oserror ; Clear _oserror rts .endproc ������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/opendir.c����������������������������������������������������������������������0000664�0000000�0000000�00000002634�13473601511�0016035�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** Ullrich von Bassewitz, 2012-05-30. Based on code by Groepaz. */ #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include "dir.h" DIR* __fastcall__ opendir (register const char* name) { unsigned char buf[2]; DIR* dir = 0; DIR d; /* Setup the actual file name that is sent to the disk. We accept "0:", ** "1:" and "." as directory names. */ d.name[0] = '$'; if (name == 0 || name[0] == '\0' || (name[0] == '.' && name[1] == '\0')) { d.name[1] = '\0'; } else if ((name[0] == '0' || name[0] == '1') && name[1] == ':' && name[2] == '\0') { d.name[1] = name[0]; d.name[2] = '\0'; } else { errno = EINVAL; goto exitpoint; } /* Set the offset of the first entry */ d.off = sizeof (buf); /* Open the directory on disk for reading */ d.fd = open (d.name, O_RDONLY); if (d.fd >= 0) { /* Skip the load address */ if (_dirread (&d, buf, sizeof (buf))) { /* Allocate memory for the DIR structure returned */ dir = malloc (sizeof (*dir)); /* Copy the contents of d */ if (dir) { memcpy (dir, &d, sizeof (d)); } else { /* Set an appropriate error code */ errno = ENOMEM; } } } exitpoint: /* Done */ return dir; } ����������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/oserrlist.s��������������������������������������������������������������������0000664�0000000�0000000�00000007211�13473601511�0016437�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2002-07-18, Ullrich von Bassewitz ; 2014-05-28, Greg King ; ; Defines the platform-specific error list. ; ; The table is built as a list of entries: ; ; .byte entrylen ; .byte errorcode ; .asciiz errormsg ; ; and, terminated by an entry with length zero that is returned if the ; error code could not be found. ; .export __sys_oserrlist ;---------------------------------------------------------------------------- ; Macros used to generate the list (may get moved to an include file?) ; Regular entry .macro sys_oserr_entry code, msg .local Start, End Start: .byte End - Start .byte code .asciiz msg End: .endmacro ; Sentinel entry .macro sys_oserr_sentinel msg .byte 0 ; Length is always zero .byte 0 ; Code is unused .asciiz msg .endmacro ;---------------------------------------------------------------------------- ; The error message table .rodata __sys_oserrlist: sys_oserr_entry 1, "Too many open files" sys_oserr_entry 2, "File is open" sys_oserr_entry 3, "File not open" sys_oserr_entry 4, "File not found" sys_oserr_entry 5, "Device not present" sys_oserr_entry 6, "File not input" sys_oserr_entry 7, "File not output" sys_oserr_entry 8, "Filename missing" sys_oserr_entry 9, "Illegal device" sys_oserr_entry 20, "Read error (No sector header)" sys_oserr_entry 21, "Read error (No sync mark)" sys_oserr_entry 22, "Read error (No sector data)" sys_oserr_entry 23, "Read error (Bad data checksum)" sys_oserr_entry 24, "Read error (Decoding problem)" sys_oserr_entry 25, "Write error (Verify failed)" sys_oserr_entry 26, "Write protected" sys_oserr_entry 27, "Read error (Bad header checksum)" sys_oserr_entry 28, "Write error (overrun)" sys_oserr_entry 29, "Disk ID mismatch" sys_oserr_entry 30, "Syntax error (Command not recognized)" sys_oserr_entry 31, "Syntax error (Command not implemented)" sys_oserr_entry 32, "Syntax error (Command too long)" sys_oserr_entry 33, "Syntax error (Invalid write filename)" sys_oserr_entry 34, "Syntax error (No file given)" sys_oserr_entry 39, "System file not found" sys_oserr_entry 49, "Invalid format" sys_oserr_entry 50, "Record not present" sys_oserr_entry 51, "Overflow in record" sys_oserr_entry 52, "File too large" sys_oserr_entry 60, "Write file open" sys_oserr_entry 61, "File not open" sys_oserr_entry 62, "File not found" sys_oserr_entry 63, "File exists" sys_oserr_entry 64, "File type mismatch" sys_oserr_entry 65, "No block" sys_oserr_entry 66, "Illegal track or sector" sys_oserr_entry 67, "Illegal system track or sector" sys_oserr_entry 70, "No channel" sys_oserr_entry 71, "BAM error" sys_oserr_entry 72, "Disk full" sys_oserr_entry 73, "DOS version mismatch" sys_oserr_entry 74, "Drive not ready" sys_oserr_entry 75, "Format error" sys_oserr_entry 77, "Illegal partition" sys_oserr_entry 78, "Bad system area" sys_oserr_sentinel "Unknown error" ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/oserror.s����������������������������������������������������������������������0000664�0000000�0000000�00000005647�13473601511�0016117�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2000-05-17, Ullrich von Bassewitz ; 2014-05-28, Greg King ; ; int __fastcall__ _osmaperrno (unsigned char oserror); ; /* Map a system-specific error into a system-independent code. */ ; .include "errno.inc" .code __osmaperrno: ldx #ErrTabSize @L1: cmp ErrTab-2,x ; Search for the error code beq @L2 ; Jump if found dex dex bne @L1 ; Next entry ; Code not found, return EUNKNOWN lda #<EUNKNOWN ldx #>EUNKNOWN rts ; Found the code @L2: lda ErrTab-1,x ldx #$00 ; High byte always zero rts .rodata ErrTab: .byte 1, EMFILE ; Too many open files .byte 2, EINVAL ; File is open .byte 3, EINVAL ; File not open .byte 4, ENOENT ; File not found .byte 5, ENODEV ; Device not present .byte 6, EINVAL ; File not input .byte 7, EINVAL ; File not output .byte 8, EINVAL ; Filename missing .byte 9, ENODEV ; Illegal device .byte 20, EBUSY ; No sector header .byte 21, EBUSY ; No sync mark .byte 22, EIO ; No sector data .byte 23, EIO ; Checksum error .byte 24, EIO ; Decode error .byte 25, EIO ; Verify error .byte 26, EACCES ; Write protected .byte 27, EIO ; Checksum error .byte 28, EIO ; Write overrun .byte 29, EBUSY ; Disk ID mismatch .byte 30, EINVAL ; Command not recognized .byte 31, ENOSYS ; Command not implemented .byte 32, EINVAL ; Command too long .byte 33, EINVAL ; Invalid write filename .byte 34, EINVAL ; No file given .byte 39, ENOENT ; System file not found .byte 49, EACCES ; Invalid format .byte 50, ESPIPE ; Record not present .byte 51, ENOSPC ; Overflow in record .byte 52, ENOSPC ; File too large .byte 60, EBUSY ; Write file open .byte 61, EINVAL ; File not open .byte 62, ENOENT ; File not found .byte 63, EEXIST ; File exists .byte 64, EINVAL ; File type mismatch .byte 65, ESPIPE ; No block .byte 66, EINVAL ; Illegal track or sector .byte 67, EIO ; Illegal system track or sector .byte 70, EBUSY ; No channel .byte 71, EIO ; BAM error .byte 72, ENOSPC ; Disk full .byte 73, EACCES ; DOS version mismatch .byte 74, ENODEV ; Drive not ready .byte 75, EIO ; Format error .byte 77, EINVAL ; Illegal partition .byte 78, EIO ; Bad system area ErrTabSize = (* - ErrTab) �����������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/overlayaddr.s������������������������������������������������������������������0000664�0000000�0000000�00000001421�13473601511�0016722�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2013-05-28 ; ; This module supplies the load addresses that are expected by Commodore ; machines in the first two bytes of overlay disk files. ; ; The following symbol is used by linker config to force the module ; to get included into the output file .export __OVERLAYADDR__: absolute = 1 .segment "OVL1ADDR" .addr *+2 .segment "OVL2ADDR" .addr *+2 .segment "OVL3ADDR" .addr *+2 .segment "OVL4ADDR" .addr *+2 .segment "OVL5ADDR" .addr *+2 .segment "OVL6ADDR" .addr *+2 .segment "OVL7ADDR" .addr *+2 .segment "OVL8ADDR" .addr *+2 .segment "OVL9ADDR" .addr *+2 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/penadjust.c��������������������������������������������������������������������0000664�0000000�0000000�00000002534�13473601511�0016371�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** Main lightpen driver calibration functions. ** ** 2013-07-25, Greg King */ #include <stddef.h> #include <fcntl.h> #include <unistd.h> #include <pen.h> static const char *name; /* Get a lightpen calibration value from a file if it exists. Otherwise, call ** pen_calibrate() to create a value; then, write it into a file, so that it ** will be available at the next time that the lightpen is used. ** Might change the screen. */ static void __fastcall__ adjuster (unsigned char *XOffset) { int fd = open (name, O_RDONLY); if (fd < 0) { pen_calibrate (XOffset); fd = open (name, O_WRONLY | O_CREAT | O_EXCL); if (fd >= 0) { (void) write (fd, XOffset, 1); close (fd); } } else { (void) read (fd, XOffset, 1); close (fd); } } /* pen_adjust() is optional; if you want to use its feature, ** then it must be called before a driver is installed. ** Note: This function merely saves the file-name pointer, and sets ** the pen_adjuster pointer. The file will be read only when a driver ** is installed, and only if that driver wants to be calibrated. */ void __fastcall__ pen_adjust (const char *filename) { if (filename != NULL && filename[0] != '\0') { name = filename; pen_adjuster = adjuster; } else { pen_adjuster = pen_calibrate; } } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/read.s�������������������������������������������������������������������������0000664�0000000�0000000�00000007153�13473601511�0015331�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2002-11-16, Ullrich von Bassewitz ; 2013-12-23, Greg King ; ; int read (int fd, void* buf, unsigned count); ; .export _read .constructor initstdin .import rwcommon .import popax .importzp ptr1, ptr2, ptr3, tmp1, tmp2, tmp3 .include "cbm.inc" .include "errno.inc" .include "fcntl.inc" .include "filedes.inc" ;-------------------------------------------------------------------------- ; initstdin: Open the stdin file descriptors for the keyboard .segment "ONCE" .proc initstdin lda #STDIN_FILENO + LFN_OFFS ldx #CBMDEV_KBD ldy #$FF jsr SETLFS jmp OPEN ; Will always succeed .endproc ;-------------------------------------------------------------------------- ; _read .code .proc _read jsr rwcommon ; Pop params, check handle bcs invalidfd ; Invalid handle ; Check if the LFN is valid and the file is open for writing adc #LFN_OFFS ; Carry is already clear tax lda fdtab-LFN_OFFS,x; Get flags for this handle tay and #LFN_READ ; File open for writing? beq invalidfd ; Check the EOF flag. If it is set, don't read anything tya ; Get flags again bmi eof ; Remember the device number. ldy unittab-LFN_OFFS,x sty unit ; Valid lfn. Make it the input file jsr CHKIN bcc @L3 ; Branch if ok jmp __mappederrno ; Store into __oserror, map to errno, return -1 ; Read the next byte @L0: jsr BASIN sta tmp1 ; Save the input byte ldx unit bne @L0_1 ; Not keyboard/screen-editor cmp #$0D ; Is it a Carriage Return? bne @L0_1 jsr BSOUT ; Yes, echo it (because editor didn't) @L0_1: jsr READST ; Read the IEEE status sta tmp3 ; Save it and #%10111111 ; Check anything but the EOI bit bne devnotpresent ; Assume device not present ; Store the byte just read ldy #0 lda tmp1 sta (ptr1),y inc ptr1 bne @L1 inc ptr1+1 ; *buf++ = A; ; Increment the byte count @L1: inc ptr3 bne @L2 inc ptr3+1 ; Get the status again and check the EOI bit @L2: lda tmp3 and #%01000000 ; Check for EOI bne @L4 ; Jump if end of file reached ; Decrement the count @L3: inc ptr2 bne @L0 inc ptr2+1 bne @L0 beq done ; Branch always ; Set the EOI flag and bail out @L4: ldx tmp2 ; Get the handle lda #LFN_EOF ora fdtab,x sta fdtab,x ; Read done, close the input channel done: jsr CLRCH ; Clear _oserror and return the number of chars read eof: lda #0 sta __oserror lda ptr3 ldx ptr3+1 rts ; Error entry: Device not present devnotpresent: lda #ENODEV jmp __directerrno ; Sets _errno, clears _oserror, returns -1 ; Error entry: The given file descriptor is not valid or not open invalidfd: lda #EBADF jmp __directerrno ; Sets _errno, clears _oserror, returns -1 .endproc ;-------------------------------------------------------------------------- .bss unit: .res 1 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/readdir.c����������������������������������������������������������������������0000664�0000000�0000000�00000006655�13473601511�0016016�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** Ullrich von Bassewitz, 2012-05-30. Based on code by Groepaz. */ #include <fcntl.h> #include <unistd.h> #include <errno.h> #include <cbm.h> #include "dir.h" #include <stdio.h> struct dirent* __fastcall__ readdir (register DIR* dir) { register unsigned char* b; register unsigned char i; register unsigned char count; static unsigned char s; static unsigned char j; unsigned char buffer[0x40]; static struct dirent entry; /* Remember the directory offset for this entry */ entry.d_off = dir->off; /* Skip the basic line-link */ if (!_dirread (dir, buffer, 2)) { /* errno already set */ goto exitpoint; } /* Read the number of blocks */ if (!_dirread (dir, &entry.d_blocks, sizeof (entry.d_blocks))) { goto exitpoint; } /* Read the next file entry into the buffer */ for (count = 0, b = buffer; count < sizeof (buffer); ++b) { if (!_dirread1 (dir, b)) { goto exitpoint; } ++count; if (*b == '\0') { break; } } /* Bump the directory offset and include the bytes for line-link and size */ dir->off += count + 4; /* End of directory is reached if the buffer contains "blocks free". It is ** sufficient here to check for the leading 'b'. buffer will contain at ** least one byte if we come here. */ if (buffer[0] == 'b') { goto exitpoint; } /* Parse the buffer for the filename and file type */ i = 0; j = 0; s = 0; b = buffer; while (i < count) { switch (s) { case 0: /* Searching for start of file name */ if (*b == '"') { s = 1; } break; case 1: /* Within file name */ if (*b == '"') { /* End of file name found. */ entry.d_name[j] = '\0'; entry.d_namlen = j; if (entry.d_off > 2) { /* Proceed with file type */ s = 2; } else { /* This is a disk header, so we're done */ entry.d_type = _CBM_T_HEADER; return &entry; } } else if (j < sizeof (entry.d_name) - 1) { entry.d_name[j] = *b; ++j; } break; case 2: /* Searching for file type */ if (*b != ' ') { entry.d_type = _cbm_filetype (*b); if (*b == 'd') { /* May be DEL or DIR, check next char */ s = 3; } else { /* Done */ return &entry; } } break; case 3: /* Distinguish DEL or DIR file type entries */ switch (*b) { case 'e': break; case 'i': entry.d_type = _CBM_T_DIR; break; default: entry.d_type = _CBM_T_OTHER; break; } return &entry; } ++i; ++b; } /* Something went wrong when parsing the directory entry */ _errno = EIO; exitpoint: return 0; } �����������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/rewinddir.s��������������������������������������������������������������������0000664�0000000�0000000�00000000721�13473601511�0016377�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2012-06-03 ; ; Based on C code by Groepaz ; ; void __fastcall__ rewinddir (DIR *dir); ; .include "dir.inc" .include "zeropage.inc" .import pushax .proc _rewinddir jsr pushax ; Push dir ldx #0 stx sreg+1 stx sreg lda #32 ; Pass 32 as offset ... jmp _seekdir ; ... to seekdir .endproc �����������������������������������������������cc65-2.18/libsrc/cbm/rwcommon.s���������������������������������������������������������������������0000664�0000000�0000000�00000002133�13473601511�0016250�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 17.11.2002 ; ; Common stuff for the read/write routines ; .export rwcommon .import popax, popptr1 .importzp ptr1, ptr2, ptr3, tmp2 .include "errno.inc" .include "filedes.inc" ;-------------------------------------------------------------------------- ; rwcommon: Pop the parameters from stack, preprocess them and place them ; into zero page locations. Return carry set if the handle is invalid, ; return carry clear if it is ok. If the carry is clear, the handle is ; returned in A. .proc rwcommon eor #$FF sta ptr2 txa eor #$FF sta ptr2+1 ; Remember -count-1 jsr popptr1 ; Get buf to ptr1, Y=0 by call sty ptr3 sty ptr3+1 ; Clear ptr3 jsr popax ; Get the handle cpx #$01 bcs @L9 cmp #MAX_FDS ; Set carry if fd too large sta tmp2 @L9: rts ; Return with result in carry .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/scratch.s����������������������������������������������������������������������0000664�0000000�0000000�00000001554�13473601511�0016044�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2002-11-16, 2009-02-22 ; ; Scratch a file on disk ; .export scratch .import opencmdchannel, closecmdchannel, writefndiskcmd .import fnunit, fncmd .include "cbm.inc" ;-------------------------------------------------------------------------- ; scratch: Scratch a file on disk. Expects the name of the file to be already ; parsed. Returns an error code in A, which may either be the code read from ; the command channel, or another error when accessing the command channel ; failed. .proc scratch ldx fnunit jsr opencmdchannel bne done lda #'s' ; Scratch command sta fncmd jsr writefndiskcmd pha ldx fnunit jsr closecmdchannel pla done: rts .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/seekdir.c����������������������������������������������������������������������0000664�0000000�0000000�00000002306�13473601511�0016017�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** 2012-06-03, Ullrich von Bassewitz. Based on code by Groepaz. ** 2014-07-16, Greg King */ #include <fcntl.h> #include <unistd.h> #include <errno.h> #include "dir.h" void __fastcall__ seekdir (register DIR* dir, long offs) { unsigned o; unsigned char count; unsigned char buf[128]; /* Make sure that we have a reasonable value for offs. We reject ** negative numbers by converting them to (very high) unsigned values. */ if ((unsigned long)offs > 0x1000uL) { errno = EINVAL; return; } /* Close the directory file descriptor */ close (dir->fd); /* Reopen it using the old name */ dir->fd = open (dir->name, O_RDONLY); if (dir->fd < 0) { /* Oops! */ return; } /* Skip until we've reached the target offset in the directory */ o = dir->off = (unsigned)offs; while (o) { /* Determine size of next chunk to read */ if (o > sizeof (buf)) { count = sizeof (buf); o -= sizeof (buf); } else { count = (unsigned char)o; o = 0; } /* Skip */ if (!_dirread (dir, buf, count)) { return; } } } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/syschdir.s���������������������������������������������������������������������0000664�0000000�0000000�00000003432�13473601511�0016242�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2012-10-16, Oliver Schmidt ; 2014-07-16, Greg King ; ; unsigned char __fastcall__ _syschdir (const char* name); ; .export __syschdir .import diskinit, fnunit, curunit, initcwd .importzp ptr1, tmp1, tmp2 ;-------------------------------------------------------------------------- ; __syschdir .proc __syschdir ; Save name sta ptr1 stx ptr1+1 ; Process first character ldy #0 lda (ptr1),y beq err jsr getdigit bcs err tax ; Process second character iny lda (ptr1),y beq init jsr getdigit bcs err stx tmp1 ; First digit sta tmp2 ; Second digit ; Multiply first digit by 10 txa asl a ; * 2 asl a ; * 4, carry cleared adc tmp1 ; * 5 asl a ; * 10, carry cleared ; Add second digit to product adc tmp2 tax ; Process third character iny lda (ptr1),y bne err ; Check device readiness init: txa jsr diskinit bne done ; Success, update cwd lda fnunit ; Set by diskinit sta curunit jmp initcwd ; Returns with A = 0 ; Return with error in A err: lda #9 ; "Illegal device" done: rts .endproc ;-------------------------------------------------------------------------- ; getdigit -- Converts PetSCII to binary. ; Sets carry if the character is outside of '0'-'9'. .proc getdigit sec sbc #'0' bcs @L0 sec rts @L0: cmp #10 rts .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/sysremove.s��������������������������������������������������������������������0000664�0000000�0000000�00000000762�13473601511�0016451�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 16.11.2002 ; ; unsigned char __fastcall__ _sysremove (const char* name); ; .export __sysremove .import fnparse, scratch ;-------------------------------------------------------------------------- ; __sysremove: .proc __sysremove jsr fnparse ; Parse the given file name bne err ; Jump if yes jmp scratch ; Scratch the file, return an error code err: rts .endproc ��������������cc65-2.18/libsrc/cbm/sysrename.s��������������������������������������������������������������������0000664�0000000�0000000�00000002227�13473601511�0016421�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2009-02-22 ; ; unsigned char __fastcall__ _sysrename (const char *oldpath, const char *newpath); ; .export __sysrename .import fnparse, fnadd, fnparsename .import opencmdchannel, closecmdchannel .import writefndiskcmd, readdiskerror .import popptr1 .import fncmd, fnunit .importzp ptr1 ;-------------------------------------------------------------------------- ; __sysrename: .proc __sysrename jsr fnparse ; Parse first filename, pops newpath bne done lda #'=' jsr fnadd jsr popptr1 ; ldy #0 Y=0 guaranteed by popptr1 jsr fnparsename ; Parse second filename bne done ldx fnunit jsr opencmdchannel bne done lda #'r' ; Rename command sta fncmd jsr writefndiskcmd ; ldx fnunit ; jsr readdiskerror pha ldx fnunit jsr closecmdchannel pla done: rts .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/telldir.s����������������������������������������������������������������������0000664�0000000�0000000�00000000762�13473601511�0016054�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2012-06-03 ; ; Based on C code by Groepaz ; ; long __fastcall__ telldir (DIR *dir); ; .include "dir.inc" .include "zeropage.inc" .proc _telldir sta ptr1 stx ptr1+1 ; Clear high word of returned value lda #0 sta sreg sta sreg+1 ; Return dir->off ldy #DIR::off+1 lda (ptr1),y tax dey lda (ptr1),y rts .endproc ��������������cc65-2.18/libsrc/cbm/toascii.s����������������������������������������������������������������������0000664�0000000�0000000�00000001220�13473601511�0016036�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2009-11-02 ; ; unsigned char __fastcall__ toascii (unsigned char c); ; /* Convert a target specific character to ascii */ ; .export _toascii .macpack generic .proc _toascii ; X must be zero on return ldx #0 ; Check for code between 65 and 90 cmp #$41 blt @L1 cmp #$5B bge @L1 ; Code between 65 and 90 ora #$20 rts ; Check for code between 193 and 219 @L1: cmp #$C1 blt @L9 cmp #$DC bge @L9 ; Code between 193 and 219 and #$7F @L9: rts .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/wherex.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000341�13473601511�0015710�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; unsigned char wherex (void); ; .export _wherex .import CURS_X: zp .proc _wherex lda CURS_X ldx #$00 rts .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/wherey.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000341�13473601511�0015711�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; unsigned char wherey (void); ; .export _wherey .import CURS_Y: zp .proc _wherey lda CURS_Y ldx #$00 rts .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm/write.s������������������������������������������������������������������������0000664�0000000�0000000�00000005146�13473601511�0015550�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 16.11.2002 ; ; int write (int fd, const void* buf, unsigned count); ; .export _write .constructor initstdout .import rwcommon .importzp sp, ptr1, ptr2, ptr3 .include "cbm.inc" .include "errno.inc" .include "fcntl.inc" .include "filedes.inc" ;-------------------------------------------------------------------------- ; initstdout: Open the stdout and stderr file descriptors for the screen. .segment "ONCE" .proc initstdout lda #STDOUT_FILENO + LFN_OFFS jsr @L1 lda #STDERR_FILENO + LFN_OFFS @L1: ldx #CBMDEV_SCREEN ldy #$FF jsr SETLFS jmp OPEN ; Will always succeed .endproc ;-------------------------------------------------------------------------- ; _write .code .proc _write jsr rwcommon ; Pop params, check handle bcs invalidfd ; Invalid handle ; Check if the LFN is valid and the file is open for writing adc #LFN_OFFS ; Carry is already clear tax lda fdtab-LFN_OFFS,x; Get flags for this handle and #LFN_WRITE ; File open for writing? beq invalidfd ; Valid lfn. Make it the output file jsr CKOUT bcc @L2 @error: jmp __mappederrno ; Store into __oserror, map to errno, return -1 ; Output the next character from the buffer @L0: ldy #0 lda (ptr1),y inc ptr1 bne @L1 inc ptr1+1 ; A = *buf++; @L1: jsr BSOUT ; Check the status pha jsr READST lsr a ; Bit zero is write timeout bne devnotpresent2 pla bcs @L3 ; Count characters written inc ptr3 bne @L2 inc ptr3+1 ; Decrement count @L2: inc ptr2 bne @L0 inc ptr2+1 bne @L0 ; Wrote all chars or disk full. Close the output channel @L3: jsr CLRCH ; Clear _oserror and return the number of chars written lda #0 sta __oserror lda ptr3 ldx ptr3+1 rts ; Error entry: Device not present devnotpresent2: pla devnotpresent: lda #ENODEV jmp __directerrno ; Sets _errno, clears _oserror, returns -1 ; Error entry: The given file descriptor is not valid or not open invalidfd: lda #EBADF jmp __directerrno ; Sets _errno, clears _oserror, returns -1 .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/����������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014452�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/_scrsize.s������������������������������������������������������������������0000664�0000000�0000000�00000000250�13473601511�0016454�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.10.2000 ; ; Screen size variables ; .export screensize .import SCREEN screensize = SCREEN ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/banking.s�������������������������������������������������������������������0000664�0000000�0000000�00000001150�13473601511�0016244�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 28.09.1998 ; ; Banking routines for the 510. ; .export set_bank, sys_bank, restore_bank .importzp ptr1, segsave .include "cbm510.inc" .code .proc sys_bank pha lda IndReg sta segsave lda #$0F sta IndReg pla rts .endproc .proc set_bank pha lda IndReg sta segsave pla sta IndReg rts .endproc .proc restore_bank pha lda segsave sta IndReg pla rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/break.s���������������������������������������������������������������������0000664�0000000�0000000�00000004500�13473601511�0015721�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 27.09.1998 ; ; void __fastcall__ set_brk (unsigned Addr); ; void reset_brk (void); ; .export _set_brk, _reset_brk .export _brk_a, _brk_x, _brk_y, _brk_sr, _brk_pc .import _atexit, BRKVec .include "cbm510.inc" .bss _brk_a: .res 1 _brk_x: .res 1 _brk_y: .res 1 _brk_sr: .res 1 _brk_pc: .res 2 _brk_01: .res 1 oldvec: .res 2 ; Old vector .data uservec: jmp $FFFF ; Patched at runtime .code ; Set the break vector .proc _set_brk sta uservec+1 stx uservec+2 ; Set the user vector lda oldvec ora oldvec+1 ; Did we save the vector already? bne L1 ; Jump if we installed the handler already lda BRKVec sta oldvec lda BRKVec+1 sta oldvec+1 ; Save the old vector L1: lda #<brk_handler ; Set the break vector to our routine ldx #>brk_handler sta BRKVec stx BRKVec+1 rts .endproc ; Reset the break vector .proc _reset_brk lda oldvec ldx oldvec+1 beq @L9 ; Jump if vector not installed sta BRKVec stx BRKVec+1 lda #$00 sta oldvec ; Clear the old vector stx oldvec+1 @L9: rts .endproc ; Break handler, called if a break occurs .proc brk_handler pla sta _brk_01 pla sta _brk_y pla sta _brk_x pla sta _brk_a pla and #$EF ; Clear break bit sta _brk_sr pla ; PC low sec sbc #2 ; Point to start of brk sta _brk_pc pla ; PC high sbc #0 sta _brk_pc+1 jsr uservec ; Call the user's routine lda _brk_01 sta IndReg lda _brk_pc+1 pha lda _brk_pc pha lda _brk_sr pha ldx _brk_x ldy _brk_y lda _brk_a rti ; Jump back... .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/cgetc.s���������������������������������������������������������������������0000664�0000000�0000000�00000007657�13473601511�0015742�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 16.09.2001 ; ; char cgetc (void); ; .export _cgetc .condes k_blncur, 2 .import cursor .include "cbm510.inc" .include "extzp.inc" ; ------------------------------------------------------------------------ .proc _cgetc lda keyidx ; Characters waiting? bne L3 ; Jump if so ; Switch on the cursor if needed lda CURS_FLAG pha lda cursor jsr setcursor L1: lda keyidx beq L1 ldx #0 pla bne L2 inx L2: txa jsr setcursor ; Read the character from the keyboard buffer L3: ldx #$00 ; Get index ldy keybuf ; Get first character in the buffer sei L4: lda keybuf+1,x ; Move up the remaining chars sta keybuf,x inx cpx keyidx bne L4 dec keyidx cli ldx #$00 ; High byte tya ; First char from buffer rts .endproc ; ------------------------------------------------------------------------ ; .proc setcursor ldy #$00 ; tax ; On or off? bne @L9 ; Go set it on lda CURS_FLAG ; Is the cursor currently off? bne @L8 ; Jump if yes lda #1 sta CURS_FLAG ; Mark it as off lda CURS_STATE ; Cursor currently displayed? sty CURS_STATE ; Cursor will be cleared later beq @L8 ; Jump if no ; Switch to the system bank, load Y with the cursor X coordinate lda #$0F sta IndReg ; Access system bank ldy CURS_X ; Reset the current cursor lda CURS_COLOR sta (CRAM_PTR),y ; Store cursor color lda ExecReg sta IndReg ; Switch to our segment lda (SCREEN_PTR),y eor #$80 ; Toggle reverse flag sta (SCREEN_PTR),y ; Done @L8: rts @L9: sty CURS_FLAG ; Cursor on (Y = 0) rts .endproc ; ------------------------------------------------------------------------ ; Blink the cursor in the interrupt. A blinking cursor is only available if ; we use the cgetc() function, so we will export this IRQ handler only in ; case the module is included into a program. .proc k_blncur lda CURS_FLAG ; Is the cursor on? bne curend ; Jump if not dec CURS_BLINK bne curend ; Re-initialize the blink counter lda #20 ; Initial value sta CURS_BLINK ; Load Y with the cursor X coordinate ldy CURS_X ; Check if the cursor state was on or off before lda CURS_COLOR ; Load color behind cursor lsr CURS_STATE ; Cursor currently displayed? bcs curset ; Jump if yes ; Cursor was off before, switch it on inc CURS_STATE ; Mark as displayed lda (CRAM_PTR),y ; Get color behind cursor... sta CURS_COLOR ; ...and remember it lda CHARCOLOR ; Use character color ; Set the cursor with color in A curset: sta (CRAM_PTR),y ; Store cursor color lda ExecReg sta IndReg ; Switch to our segment lda (SCREEN_PTR),y eor #$80 ; Toggle reverse flag sta (SCREEN_PTR),y ; Switch back to the system bank lda #$0F sta IndReg curend: rts .endproc ���������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/clrscr.s��������������������������������������������������������������������0000664�0000000�0000000�00000002603�13473601511�0016127�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 14.09.2001 ; .export _clrscr .import plot .include "cbm510.inc" .include "extzp.inc" ; ------------------------------------------------------------------------ ; void clrscr (void); .proc _clrscr lda #0 sta CURS_X sta CURS_Y jsr plot ; Set cursor to top left corner ldx #$00 ; Count jsr clearpage jsr clearpage jsr clearpage ldx #<(40*25) ; Count jsr clearpage ; Clear remainder of last page jmp plot ; Set screen pointer again .endproc .proc clearpage txa pha ; Save count lda #$20 ; Screencode for blank ldy #$00 @L1: sta (SCREEN_PTR),y iny dex bne @L1 inc SCREEN_PTR+1 pla tax ; Reload count lda IndReg pha lda #$0F sta IndReg ; Switch to the system bank lda CHARCOLOR ; Load color ldy #$00 @L2: sta (CRAM_PTR),y iny dex bne @L2 inc CRAM_PTR+1 pla sta IndReg ; Restore the old indirect bank rts .endproc �����������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/color.s���������������������������������������������������������������������0000664�0000000�0000000�00000004101�13473601511�0015750�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 13.09.2001 ; .export _textcolor, _bgcolor, _bordercolor .import sys_bank, restore_bank .import vic: zp, CHARCOLOR: zp .include "cbm510.inc" ; ------------------------------------------------------------------------ ; unsigned char __fastcall__ textcolor (unsigned char color); ; /* Set the color for text output. The old color setting is returned. */ ; .proc _textcolor ldx CHARCOLOR ; get old value sta CHARCOLOR ; set new value txa rts .endproc ; ------------------------------------------------------------------------ ; unsigned char __fastcall__ bgcolor (unsigned char color); ; /* Set the color for the background. The old color setting is returned. */ ; .proc _bgcolor jsr sys_bank ; Switch to the system bank pha ; Save new color ldy #VIC_BG_COLOR0 lda (vic),y ; Get current color... tax ; ...into X pla ; Get new color sta (vic),y ; Set new color txa ; Get old color into X jmp restore_bank ; Restore the old color .endproc ; ------------------------------------------------------------------------ ; unsigned char __fastcall__ bordercolor (unsigned char color); ; /* Set the color for the border. The old color setting is returned. */ .proc _bordercolor jsr sys_bank ; Switch to the system bank pha ; Save new color ldy #VIC_BORDERCOLOR lda (vic),y ; Get current color... tax ; ...into X pla ; Get new color sta (vic),y ; Set new color txa ; Get old color into X jmp restore_bank ; Restore the old color .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/cpeekcolor.s����������������������������������������������������������������0000664�0000000�0000000�00000000671�13473601511�0016770�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2016-02-28, Groepaz ; 2017-06-19, Greg King ; ; unsigned char cpeekcolor (void); ; .export _cpeekcolor .import CURS_X: zp, CRAM_PTR: zp .include "cbm510.inc" _cpeekcolor: ldx IndReg lda #$0F sta IndReg ldy CURS_X lda (CRAM_PTR),y ; get color stx IndReg and #$0F ldx #>$0000 rts �����������������������������������������������������������������������cc65-2.18/libsrc/cbm510/cputc.s���������������������������������������������������������������������0000664�0000000�0000000�00000006024�13473601511�0015756�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 14.09.2001 ; ; void cputcxy (unsigned char x, unsigned char y, char c); ; void cputc (char c); ; .export _cputcxy, _cputc, cputdirect, putchar .export newline, plot .import gotoxy .import __VIDRAM_START__ .import CURS_X: zp, CURS_Y: zp, CHARCOLOR: zp, RVS: zp .import SCREEN_PTR: zp, CRAM_PTR: zp .include "cbm510.inc" .macpack generic ; ------------------------------------------------------------------------ ; _cputcxy: pha ; Save C jsr gotoxy ; Set cursor, drop x and y pla ; Restore C ; Plot a character - also used as internal function _cputc: cmp #$0A ; CR? bne L1 lda #0 sta CURS_X beq plot ; Recalculate pointers L1: cmp #$0D ; LF? beq newline ; Recalculate pointers ; Printable char of some sort cmp #' ' bcc cputdirect ; Other control char tay bmi L10 cmp #$60 bcc L2 and #$DF bne cputdirect ; Branch always L2: and #$3F cputdirect: jsr putchar ; Write the character to the screen ; Advance cursor position advance: iny cpy #XSIZE bne L3 jsr newline ; new line ldy #0 ; + cr L3: sty CURS_X rts ; Handle character if high bit set L10: and #$7F cmp #$7E ; PI? bne L11 lda #$5E ; Load screen code for PI bne cputdirect L11: ora #$40 bne cputdirect ; Branch always ; Move the cursor into the next line newline: inc CURS_Y ; Set cursor position, calculate RAM pointers plot: ldx CURS_Y lda LineLSBTab,x sta SCREEN_PTR sta CRAM_PTR lda LineMSBTab,x sta SCREEN_PTR+1 add #.hibyte(COLOR_RAM - __VIDRAM_START__) sta CRAM_PTR+1 rts ; Write one character to the screen without doing anything else, return X ; position in Y putchar: ora RVS ; Set revers bit ldy CURS_X sta (SCREEN_PTR),y ; Set char ldx IndReg lda #$0F sta IndReg lda CHARCOLOR sta (CRAM_PTR),y ; Set color stx IndReg rts ; ------------------------------------------------------------------------- ; Low bytes of the start address of the screen lines .rodata LineLSBTab: .repeat 25, I .byte .lobyte(__VIDRAM_START__ + I * 40) .endrep ; ------------------------------------------------------------------------- ; High bytes of the start address of the screen lines LineMSBTab: .repeat 25, I .byte .hibyte(__VIDRAM_START__ + I * 40) .endrep ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/crt0.s����������������������������������������������������������������������0000664�0000000�0000000�00000035702�13473601511�0015515�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Startup code for cc65 (CBM 500 version) ; .export _exit, BRKVec .export __STARTUP__ : absolute = 1 ; Mark as startup .import _clrscr, initlib, donelib, callirq_y .import push0, callmain .import __CHARRAM_START__, __CHARRAM_SIZE__, __VIDRAM_START__ .import __BSS_RUN__, __BSS_SIZE__, __EXTZP_RUN__ .import __INTERRUPTOR_COUNT__ .import scnkey, UDTIM .include "zeropage.inc" .include "extzp.inc" .include "cbm510.inc" ; ------------------------------------------------------------------------ ; The BASIC header and a small BASIC program. Since it isn't possible to start ; programs in other banks using SYS, the BASIC program will write a small ; machine code program into memory at $100; and, start that machine code ; program. The machine code program will then start the machine language ; code in bank 0, which will initialize the system by copying stuff from ; the system bank, and start the application. ; ; Here's the BASIC program that's in the following lines: ; ; 10 for i=0 to 4 ; 20 read j ; 30 poke 256+i,j ; 40 next i ; 50 sys 256 ; 60 data 120,169,0,133,0 ; ; The machine program in the data lines is: ; ; sei ; lda #$00 ; sta $00 <-- Switch to bank 0 after this command ; ; Initialization is complex not only because of the jumping from one bank ; into another, but also because we want to save memory; and because of ; that, we will use the system memory ($00-$3FF) for initialization stuff ; that is overwritten later. ; .segment "EXEHDR" .byte $03,$00,$11,$00,$0a,$00,$81,$20,$49,$b2,$30,$20,$a4,$20,$34,$00 .byte $19,$00,$14,$00,$87,$20,$4a,$00,$27,$00,$1e,$00,$97,$20,$32,$35 .byte $36,$aa,$49,$2c,$4a,$00,$2f,$00,$28,$00,$82,$20,$49,$00,$39,$00 .byte $32,$00,$9e,$20,$32,$35,$36,$00,$4f,$00,$3c,$00,$83,$20,$31,$32 .byte $30,$2c,$31,$36,$39,$2c,$30,$2c,$31,$33,$33,$2c,$30,$00,$00,$00 ;------------------------------------------------------------------------------ ; A table that contains values that must be transferred from the system zero- ; page into our zero-page. Contains pairs of bytes; first one is the address ; in the system ZP, second one is our ZP address. The table goes into page 2; ; but, is declared here because it is needed earlier. .SEGMENT "PAGE2" ; (We use .proc because we need both a label and a scope.) .proc transfer_table .byte $9F, DEVNUM .byte $CA, CURS_Y .byte $CB, CURS_X .byte $E6, CURS_FLAG .byte $E7, CURS_BLINK .byte $EC, CHARCOLOR .endproc ;------------------------------------------------------------------------------ ; Page 3 data. This page contains the break vector and the bankswitch ; subroutine that is copied into high memory on startup. The space occupied by ; this routine will later be used for a copy of the bank 15 stack. It must be ; saved since we're going to destroy it when calling bank 15. .segment "PAGE3" BRKVec: .addr _exit ; BRK indirect vector .proc callbank15 excrts = $FEFE .org $FEC3 entry: php pha lda #$0F ; Bank 15 sta IndReg txa pha tya pha sei ldy #$FF lda (sysp1),y tay lda ExecReg sta (sysp1),y dey lda #.hibyte(excrts-1) sta (sysp1),y dey lda #.lobyte(excrts-1) sta (sysp1),y tya sec sbc #7 sta $1FF ; Save new sp tay tsx pla iny sta (sysp1),y pla iny sta (sysp1),y pla iny sta (sysp1),y pla iny sta (sysp1),y lda $105,x sec sbc #3 iny sta (sysp1),y lda $106,x sbc #0 iny sta (sysp1),y ldy $1FF ; Restore sp in bank 15 lda #.hibyte(expull-1) sta (sysp1),y dey lda #.lobyte(expull-1) sta (sysp1),y dey pla pla tsx stx $1FF tya tax txs lda IndReg jmp $FFF6 expull: pla tay pla tax pla plp rts .if (expull <> $FF26) .error "Symbol expull must be aligned with Kernal in bank 15" .endif .reloc .endproc ;------------------------------------------------------------------------------ ; The code in the target bank when switching back will be put at the bottom ; of the stack. We will jump here to switch segments. The range $F2..$FF is ; not used by any Kernal routine. .segment "STARTUP" Back: sta ExecReg ; We are at $100 now. The following snippet is a copy of the code that is poked ; in the system bank memory by the BASIC header program; it's only for ; documentation, and not actually used here: sei lda #$00 sta ExecReg ; This is the actual starting point of our code after switching banks for ; startup. Beware: The following code will get overwritten as soon as we ; use the stack (since it's in page 1)! We jump to another location since ; we need some space for subroutines that aren't used later. jmp Origin ; Hardware vectors, copied to $FFF6 .proc vectors sta ExecReg rts nop .word nmi ; NMI vector .word 0 ; Reset -- not used .word irq ; IRQ vector .endproc ; Initializers for the extended zero-page. See "extzp.s". .proc extzp .word $0100 ; sysp1 .word $0300 ; sysp3 .word $d800 ; vic .word $da00 ; sid .word $db00 ; cia1 .word $dc00 ; cia2 .word $dd00 ; acia .word $de00 ; tpi1 .word $df00 ; tpi2 .word $eab1 ; ktab1 .word $eb11 ; ktab2 .word $eb71 ; ktab3 .word $ebd1 ; ktab4 .endproc ; Switch the indirect segment to the system bank. Origin: lda #$0F sta IndReg ; Initialize the extended zero-page. ldx #.sizeof(extzp)-1 L1: lda extzp,x sta <__EXTZP_RUN__,x dex bpl L1 ; Save the old stack pointer from the system bank; and, set up our hw sp. tsx txa ldy #$FF sta (sysp1),y ; Save system stack point into $F:$1FF ldx #$FE ; Leave $1FF untouched for cross-bank calls txs ; Set up our own stack ; Copy stuff from the system zero-page to ours. lda #.sizeof(transfer_table) sta ktmp L2: ldx ktmp ldy transfer_table-2,x lda transfer_table-1,x tax lda (sysp0),y sta $00,x dec ktmp dec ktmp bne L2 ; Set the interrupt, NMI, and other vectors. ldx #.sizeof(vectors)-1 L3: lda vectors,x sta $10000 - .sizeof(vectors),x dex bpl L3 ; Set up the C stack. lda #.lobyte(callbank15::entry) sta sp lda #.hibyte(callbank15::entry) sta sp+1 ; Set up the subroutine and jump vector table that redirects Kernal calls to ; the system bank. ldy #.sizeof(callbank15) @L1: lda callbank15-1,y sta callbank15::entry-1,y dey bne @L1 ; Set up the jump vector table. Y is zero on entry. ldx #45-1 ; Number of vectors @L2: lda #$20 ; JSR opcode sta $FF6F,y iny lda #.lobyte(callbank15::entry) sta $FF6F,y iny lda #.hibyte(callbank15::entry) sta $FF6F,y iny dex bpl @L2 ; Set the indirect segment to the bank that we're executing in. lda ExecReg sta IndReg ; Zero the BSS segment. We will do that here instead of calling the routine ; in the common library, since we have the memory anyway; and this way, ; it's reused later. lda #<__BSS_RUN__ sta ptr1 lda #>__BSS_RUN__ sta ptr1+1 lda #0 tay ; Clear full pages. ldx #>__BSS_SIZE__ beq Z2 Z1: sta (ptr1),y iny bne Z1 inc ptr1+1 ; Next page dex bne Z1 ; Clear the remaining page. Z2: ldx #<__BSS_SIZE__ beq Z4 Z3: sta (ptr1),y iny dex bne Z3 Z4: jmp Init ; ------------------------------------------------------------------------ ; We are at $200 now. We may now start calling subroutines safely since ; the code we execute is no longer in the stack page. .segment "PAGE2" ; Copy the character ROM from the system bank into the execution bank. Init: lda #<$C000 sta ptr1 lda #>$C000 sta ptr1+1 lda #<__CHARRAM_START__ sta ptr2 lda #>__CHARRAM_START__ sta ptr2+1 lda #>__CHARRAM_SIZE__ ; 16 * 256 bytes to copy sta tmp1 ldy #$00 ccopy: lda #$0F sta IndReg ; Access the system bank ccopy1: lda (ptr1),y sta __VIDRAM_START__,y iny bne ccopy1 lda ExecReg sta IndReg ccopy2: lda __VIDRAM_START__,y sta (ptr2),y iny bne ccopy2 inc ptr1+1 inc ptr2+1 ; Bump high pointer bytes dec tmp1 bne ccopy ; Clear the video memory. We will do this before switching the video to bank 0, ; to avoid garbage when doing so. jsr _clrscr ; Reprogram the VIC so that the text screen and the character ROM are in the ; execution bank. This is done in three steps: lda #$0F ; We need access to the system bank sta IndReg ; Place the VIC video RAM into bank 0. ; CA (STATVID) = 0 ; CB (VICDOTSEL) = 0 ldy #TPI::CR lda (tpi1),y sta vidsave+0 and #%00001111 ora #%10100000 sta (tpi1),y ; Set bit 14/15 of the VIC address range to the high bits of __VIDRAM_START__. ; PC6/PC7 (VICBANKSEL 0/1) = 11 ldy #TPI::PRC lda (tpi2),y sta vidsave+1 and #$3F ora #<((>__VIDRAM_START__) & $C0) sta (tpi2),y ; Set the VIC base address register to the addresses of the video and ; character RAM. ldy #VIC_VIDEO_ADR lda (vic),y sta vidsave+2 and #$01 ora #<(((__VIDRAM_START__ >> 6) & $F0) | ((__CHARRAM_START__ >> 10) & $0E) | $02) ; and #$0F ; ora #<(((>__VIDRAM_START__) << 2) & $F0) sta (vic),y ; Switch back to the execution bank. lda ExecReg sta IndReg ; Activate the chained interrupt handlers; then, enable interrupts. lda #.lobyte(__INTERRUPTOR_COUNT__*2) sta irqcount cli ; Call module constructors. jsr initlib ; Push the command-line arguments; and, call main(). jsr callmain ; Call the module destructors. This is also the exit() entry and the default entry ; point for the break vector. _exit: pha ; Save the return code on stack jsr donelib ; Run module destructors lda #$00 sta irqcount ; Disable custom irq handlers ; Address the system bank. lda #$0F sta IndReg ; Switch back the video to the system bank. ldy #TPI::CR lda vidsave+0 sta (tpi1),y ldy #TPI::PRC lda vidsave+1 sta (tpi2),y ldy #VIC_VIDEO_ADR lda vidsave+2 sta (vic),y ; Copy stuff back from our zero-page to the system's. .if 0 lda #.sizeof(transfer_table) sta ktmp @L0: ldx ktmp ldy transfer_table-2,x lda transfer_table-1,x tax lda $00,x sta (sysp0),y dec ktmp dec ktmp bne @L0 .endif ; Place the program return code into BASIC's status variable. pla ldy #$9C ; ST sta (sysp0),y ; Set up the welcome code at the stack bottom in the system bank. ldy #$FF lda (sysp1),y ; Load system bank sp tax iny ; Y = 0 lda #$58 ; CLI opcode sta (sysp1),y iny lda #$60 ; RTS opcode sta (sysp1),y lda IndReg sei txs jmp Back ; ------------------------------------------------------------------------- ; The IRQ handler goes into PAGE2. For performance reasons, and to allow ; easier chaining, we do handle the IRQs in the execution bank (instead of ; passing them to the system bank). ; This is the mapping of the active IRQ register of the 6525 (tpi1): ; ; Bit 7 6 5 4 3 2 1 0 ; | | | | ^ 50 Hz. ; | | | ^ SRQ IEEE 488 ; | | ^ CIA ; | ^ IRQB ext. Port ; ^ ACIA irq: pha txa pha tya pha lda IndReg pha lda ExecReg sta IndReg ; Be sure to address our segment tsx lda $105,x ; Get the flags from the stack and #$10 ; Test break flag bne dobrk ; It's an IRQ. cld ; Call the chained IRQ handlers. ldy irqcount beq irqskip jsr callirq_y ; Call the functions ; Done with the chained IRQ handlers; check the TPI for IRQs, and handle them. irqskip:lda #$0F sta IndReg ldy #TPI::AIR lda (tpi1),y ; Interrupt Register 6525 beq noirq ; 50/60Hz. interrupt cmp #%00000001 ; ticker IRQ? bne irqend jsr scnkey ; Poll the keyboard jsr UDTIM ; Bump the time ; Done. irqend: ldy #TPI::AIR sta (tpi1),y ; Clear interrupt noirq: pla sta IndReg pla tay pla tax pla nmi: rti dobrk: jmp (BRKVec) ; ------------------------------------------------------------------------- ; Data area .data vidsave:.res 3 .bss irqcount: .byte 0 ��������������������������������������������������������������cc65-2.18/libsrc/cbm510/devnum.s��������������������������������������������������������������������0000664�0000000�0000000�00000000160�13473601511�0016131�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2010-02-14 ; .include "extzp.inc" .exportzp devnum := DEVNUM ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/doesclrscr.s����������������������������������������������������������������0000664�0000000�0000000�00000000662�13473601511�0017005�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2016-06, Christian Groessler ; 2017-07-05, Greg King ; ; unsigned char doesclrscrafterexit (void); ; ; Returns 0/1 if, after program termination, the screen isn't/is cleared. ; .import return1 ; cc65's CBM510 programs switch to a display screen in the program RAM bank; ; then, they switch back to the system bank when they exit. ; The screen is cleared. .export _doesclrscrafterexit := return1 ������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/emd/������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015217�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/emd/cbm510-ram.s������������������������������������������������������������0000664�0000000�0000000�00000016171�13473601511�0017155�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Extended memory driver for the CBM510 additional RAM banks. Driver works ; without problems when linked statically. ; ; Ullrich von Bassewitz, 2002-12-09, 2003-12-27 ; .include "zeropage.inc" .include "em-kernel.inc" .include "em-error.inc" .include "cbm510.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _cbm510_ram_emd ; Driver signature .byte $65, $6d, $64 ; "emd" .byte EMD_API_VERSION ; EM API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr PAGECOUNT .addr MAP .addr USE .addr COMMIT .addr COPYFROM .addr COPYTO ; ------------------------------------------------------------------------ ; Constants RAMBANK = 1 OFFS = 2 ; ------------------------------------------------------------------------ ; Data. .bss curpage: .res 1 ; Current page number window: .res 256 ; Memory "window" pagecount: .res 1 ; Number of available pages .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present and determine the amount of ; memory available. ; Must return an EM_ERR_xx code in a/x. ; INSTALL: lda #$FF sta curpage ; Invalidate the current page sta pagecount ; Assume all memory available sec jsr $FF99 ; MEMTOP cmp #RAMBANK ; Top of memory in bank 2? bne @L1 ; No: We can use all the memory txa sub #OFFS tya sbc #$00 sta pagecount @L1: lda #<EM_ERR_OK ldx #>EM_ERR_OK ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; PAGECOUNT: Return the total number of available pages in a/x. ; PAGECOUNT: lda pagecount ldx #0 rts ; ------------------------------------------------------------------------ ; MAP: Map the page in a/x into memory and return a pointer to the page in ; a/x. The contents of the currently mapped page (if any) may be discarded ; by the driver. ; MAP: sta curpage ; Remember the new page sta ptr1+1 lda #OFFS sta ptr1 ; Transfer one page ldx IndReg lda #RAMBANK sta IndReg ldy #$00 @L1: .repeat 2 lda (ptr1),y sta window,y iny .endrepeat bne @L1 stx IndReg ; Return the memory window lda #<window ldx #>window ; Return the window address rts ; ------------------------------------------------------------------------ ; USE: Tell the driver that the window is now associated with a given page. USE: sta curpage ; Remember the page lda #<window ldx #>window ; Return the window rts ; ------------------------------------------------------------------------ ; COMMIT: Commit changes in the memory window to extended storage. COMMIT: lda curpage ; Get the current page cmp #$FF beq done ; Jump if no page mapped sta ptr1+1 lda #OFFS sta ptr1 ; Transfer one page ldx IndReg lda #RAMBANK sta IndReg ldy #$00 @L1: .repeat 2 lda window,y sta (ptr1),y iny .endrepeat bne @L1 stx IndReg ; Done done: rts ; ------------------------------------------------------------------------ ; COPYFROM: Copy from extended into linear memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYFROM: jsr setup ; Setup the buffer address in this bank. sta copyfrom_buf stx copyfrom_buf+1 ; Check if we must copy full pages ldx ptr2+1 beq @L2 ; Copy full pages ldx #$00 @L1: jsr copyfrom inc ptr1+1 inc copyfrom_buf+1 @L2: dec ptr2+1 bne @L1 ; Copy the remaining page ldx ptr2 beq @L3 jsr copyfrom ; Restore the indirect segment @L3: lda ExecReg sta IndReg ; Done rts ; ------------------------------------------------------------------------ ; COPYTO: Copy from linear into extended memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYTO: jsr setup ; Setup the buffer address in this bank. sta copyto_buf stx copyto_buf+1 ; Check if we must copy full pages ldx ptr2+1 beq @L2 ; Copy full pages ldx #$00 @L1: jsr copyto inc ptr1+1 inc copyto_buf+1 @L2: dec ptr2+1 bne @L1 ; Copy the remaining page ldx ptr2 beq @L3 jsr copyto ; Restore the indirect segment @L3: lda ExecReg sta IndReg ; Done rts ; ------------------------------------------------------------------------ ; setup: Helper function for COPYFROM and COPYTO, will setup parameters. ; setup: sta ptr3 stx ptr3+1 ; Save the passed em_copy pointer ldy #EM_COPY::OFFS lda (ptr3),y add #OFFS sta ptr1 ldy #EM_COPY::PAGE lda (ptr3),y adc #$00 sta ptr1+1 ldy #EM_COPY::COUNT lda (ptr3),y sta ptr2 iny lda (ptr3),y sta ptr2+1 ; Get count into ptr2 ldy #EM_COPY::BUF+1 lda (ptr3),y tax dey lda (ptr3),y ; Get the buffer pointer into a/x ldy #RAMBANK sty IndReg ldy #$00 rts ; ------------------------------------------------------------------------ ; copyfrom .data copyfrom: lda (ptr1),y copyfrom_buf = * + 1 sta $0000,y iny dex bne copyfrom rts ; ------------------------------------------------------------------------ ; copyto .data copyto: copyto_buf = * + 1 lda $0000,y sta (ptr1),y iny dex bne copyto rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/extzp.inc�������������������������������������������������������������������0000664�0000000�0000000�00000001215�13473601511�0016316�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-27 ; ; Additional zero page locations for the CBM510. ; ; ------------------------------------------------------------------------ .globalzp sysp1, sysp3, vic, sid, ipccia, cia1, cia2, acia .globalzp tpi1, tpi2, ktab1, ktab2, ktab3, ktab4 .globalzp sysp0, time, segsave, ktmp, CURS_X, CURS_Y, CURS_FLAG .globalzp CURS_STATE, CURS_BLINK, CURS_COLOR, CHARCOLOR, RVS .globalzp DEVNUM, SCREEN_PTR, CRAM_PTR .globalzp keyidx, keybuf, keyscanbuf, keysave, modkey .globalzp norkey, graphmode, lastidx, rptdelay, rptcount �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/extzp.s���������������������������������������������������������������������0000664�0000000�0000000�00000003417�13473601511�0016015�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-02-16 ; ; Additional zero page locations for the CBM510. ; 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 ; The following values get initialized from a table in the startup code. ; While this sounds crazy, it has reasons that have to do with modules (and ; we have the space anyway). So when changing anything, be sure to adjust the ; initializer table sysp1: .res 2 sysp3: .res 2 vic: .res 2 sid: .res 2 cia1: .res 2 cia2: .res 2 acia: .res 2 tpi1: .res 2 tpi2: .res 2 ktab1: .res 2 ktab2: .res 2 ktab3: .res 2 ktab4: .res 2 sysp0: .word $0000 time: .dword $0000 segsave: .byte 0 ktmp: .byte 0 CURS_X: .byte 0 CURS_Y: .byte 0 CURS_FLAG: .byte 0 CURS_STATE: .byte 0 CURS_BLINK: .byte 0 CURS_COLOR: .byte 0 CHARCOLOR: .byte 0 RVS: .byte 0 DEVNUM: .byte 0 SCREEN_PTR: .word 0 CRAM_PTR: .word 0 ; Stuff for our own kbd polling routine keyidx: .byte 0 ; Number of keys in keyboard buffer keybuf: .res 10 ; Keyboard buffer keyscanbuf: .byte 0 keysave: .byte 0 modkey: .byte 0 norkey: .byte 0 graphmode: .byte 0 lastidx: .byte 0 rptdelay: .byte 0 rptcount: .byte 0 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/gettime.s�������������������������������������������������������������������0000664�0000000�0000000�00000004352�13473601511�0016300�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2009-07-27, Stefan Haubenthal ; 2009-09-24, Ullrich von Bassewitz ; 2018-08-18, Oliver Schmidt ; 2018-08-19, Greg King ; ; int __fastcall__ clock_gettime (clockid_t clk_id, struct timespec *tp); ; .include "time.inc" .include "cbm510.inc" .include "extzp.inc" .import pushax, pusheax, tosmul0ax, steaxspidx, incsp1 .import sys_bank, restore_bank .import TM, load_tenth .importzp sreg, tmp1, tmp2 ;---------------------------------------------------------------------------- .code .proc _clock_gettime jsr pushax jsr pushax jsr sys_bank ldy #CIA::TODHR lda (cia2),y sed tax ; Save PM flag and #%01111111 cmp #$12 ; 12 AM/PM bcc @L1 sbc #$12 @L1: inx ; Get PM flag bpl @L2 clc adc #$12 @L2: cld jsr BCD2dec sta TM + tm::tm_hour ldy #CIA::TODMIN lda (cia2),y jsr BCD2dec sta TM + tm::tm_min ldy #CIA::TODSEC lda (cia2),y jsr BCD2dec sta TM + tm::tm_sec ldy #CIA::TOD10 lda (cia2),y jsr restore_bank pha lda #<TM ldx #>TM jsr _mktime ldy #timespec::tv_sec jsr steaxspidx ; Pops address pushed by 2. pushax jsr load_tenth jsr pusheax pla ldx #>$0000 jsr tosmul0ax ldy #timespec::tv_nsec jsr steaxspidx ; Pops address pushed by 1. pushax lda #$00 tax jmp incsp1 .endproc ;---------------------------------------------------------------------------- ; dec = (((BCD>>4)*10) + (BCD&0xf)) .proc BCD2dec tax and #%00001111 sta tmp1 txa and #%11110000 ; *16 lsr ; *8 sta tmp2 lsr lsr ; *2 adc tmp2 ; = *10 adc tmp1 rts .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/irq.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000156�13473601511�0015433�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; IRQ handling (CBM 500 version) ; .export initirq, doneirq initirq: doneirq: rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/joy/������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015253�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/joy/cbm510-std.s������������������������������������������������������������0000664�0000000�0000000�00000006304�13473601511�0017221�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Standard joystick driver for the Commodore 510 (aka P500). May be used ; multiple times when linked to the statically application. ; ; Ullrich von Bassewitz, 2003-02-16 ; .include "zeropage.inc" .include "../extzp.inc" .include "joy-kernel.inc" .include "joy-error.inc" .include "cbm510.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _cbm510_std_joy ; Driver signature .byte $6A, $6F, $79 ; "joy" .byte JOY_API_VERSION ; Driver API version number ; Library reference .addr $0000 ; Jump table. .addr INSTALL .addr UNINSTALL .addr COUNT .addr READ ; ------------------------------------------------------------------------ ; Constants JOY_COUNT = 2 ; Number of joysticks we support ; ------------------------------------------------------------------------ ; Data. .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 ; ------------------------------------------------------------------------ ; UNINSTALL 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. ; COUNT: lda #<JOY_COUNT ldx #>JOY_COUNT rts ; ------------------------------------------------------------------------ ; READ: Read a particular joystick passed in A. ; READ: ldx #$0F ; Switch to the system bank stx IndReg tax ; Save joystick number ; Get the direction bits ldy #CIA::PRB lda (cia2),y ; Read joystick inputs sta tmp1 ; Get the push button bits ldy #CIA::PRA lda (cia2),y ; Make the result value cpx #$00 ; Joystick 0? bne @L1 ; Jump if no ; Joystick 1, push button is in bit 6, direction in bit 0-3 asl a jmp @L2 ; Joystick 2, push button is in bit 7, direction in bit 5-7 @L1: ldx #$00 ; High byte of return value lsr tmp1 lsr tmp1 lsr tmp1 lsr tmp1 ; Mask the relavant bits, get the push button bit @L2: asl a ; push button bit into carry lda tmp1 and #$0F bcc @L3 ora #$10 @L3: eor #$1F ; All bits are inverted ; Switch back to the execution bank and return the joystick mask in a/x ldy ExecReg sty IndReg rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/joy_stat_stddrv.s�����������������������������������������������������������0000664�0000000�0000000�00000000354�13473601511�0020062�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Address of the static standard joystick driver ; ; Oliver Schmidt, 2012-11-01 ; ; const void joy_static_stddrv[]; ; .export _joy_static_stddrv .import _cbm510_std_joy .rodata _joy_static_stddrv := _cbm510_std_joy ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/joy_stddrv.s����������������������������������������������������������������0000664�0000000�0000000�00000000267�13473601511�0017032�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Name of the standard joystick driver ; ; Oliver Schmidt, 2012-11-01 ; ; const char joy_stddrv[]; ; .export _joy_stddrv .rodata _joy_stddrv: .asciiz "cbm510-std.joy" �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/kbhit.s���������������������������������������������������������������������0000664�0000000�0000000�00000000536�13473601511�0015743�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; unsigned char kbhit (void); ; .export _kbhit .import keyidx: zp .proc _kbhit ldx #0 ; High byte of return is always zero lda keyidx ; Get number of characters beq L9 lda #1 L9: rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/kclose.s��������������������������������������������������������������������0000664�0000000�0000000�00000000617�13473601511�0016122�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-21 ; ; CLOSE kernal call. ; ; NOTE: The CLOSE system call in the CBM610 kernal will only remove the file ; entry and not close the file on IEC if the carry is clear on entry. To make ; this somewhat compatible with the C64, set the carry before jumping to the ; kernal. .export CLOSE .proc CLOSE sec jmp $FFC3 .endproc �����������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/kernal.s��������������������������������������������������������������������0000664�0000000�0000000�00000001722�13473601511�0016114�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-20 ; ; CBM510 kernal functions ; .include "cbm_kernal.inc" .export CINT .export IOINIT .export RESTOR .export VECTOR .export SETMSG .export SECOND .export TKSA .export MEMTOP .export MEMBOT .export SCNKEY .export SETTMO .export ACPTR .export CIOUT .export UNTLK .export UNLSN .export LISTEN .export TALK .export SETLFS .export CHKIN .export CKOUT .export CLRCH .export BASIN .export BSOUT .export LOAD .export SAVE .export STOP .export GETIN .export CLALL .export PLOT ����������������������������������������������cc65-2.18/libsrc/cbm510/kiobase.s�������������������������������������������������������������������0000664�0000000�0000000�00000000332�13473601511�0016251�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-19 ; ; IOBASE kernal call ; .export IOBASE .import cia : zeropage .proc IOBASE ldx cia ldy cia+1 rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/kopen.s���������������������������������������������������������������������0000664�0000000�0000000�00000000732�13473601511�0015754�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-20 ; ; OPEN kernal call. ; ; NOTE: The OPEN system call in the CBM610 kernal is different from the ; standard. It evaluates the carry flag and does a normal open if carry clear ; and some strange things (output sa 15 + name on IEC) if carry set. To be ; compatible with our CBM file stuff, we have to clear the carry before ; calling the real OPEN. .export OPEN .proc OPEN clc jmp $FFC0 .endproc ��������������������������������������cc65-2.18/libsrc/cbm510/krdtim.s��������������������������������������������������������������������0000664�0000000�0000000�00000000412�13473601511�0016125�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-19 ; ; RDTIM kernal call ; .export RDTIM .import time : zeropage .proc RDTIM sei lda time+0 ldx time+1 ldy time+2 cli rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/kreadst.s�������������������������������������������������������������������0000664�0000000�0000000�00000001047�13473601511�0016275�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-19 ; ; READST kernal call ; .export READST .import sys_bank, restore_bank .import sysp0: zp, ktmp: zp .include "cbm510.inc" .proc READST jsr sys_bank sty ktmp ; Save Y register ldy #$9C ; STATUS lda (sysp0),y ; Load STATUS from system bank ldy ktmp jmp restore_bank ; Will set condition codes on A .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/kscnkey.s�������������������������������������������������������������������0000664�0000000�0000000�00000005712�13473601511�0016312�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 13.09.2001 ; ; Keyboard polling stuff for the 510. ; .export scnkey .importzp tpi2, ktab1, ktab2, ktab3, ktab4 .importzp keyidx, keybuf, keyscanbuf, keysave, modkey, norkey .importzp graphmode, lastidx, rptdelay, rptcount .include "cbm510.inc" .proc scnkey lda #$FF sta modkey sta norkey lda #$00 sta keyscanbuf ldy #TPI::PRB sta (tpi2),y ldy #TPI::PRA sta (tpi2),y jsr Poll and #$3F eor #$3F bne L1 jmp NoKey L1: lda #$FF ldy #TPI::PRA sta (tpi2),y asl a ldy #TPI::PRB sta (tpi2),y jsr Poll pha sta modkey ora #$30 bne L3 ; Branch always L2: jsr Poll L3: ldx #$05 ldy #$00 L4: lsr a bcc L5 inc keyscanbuf dex bpl L4 sec ldy #TPI::PRB lda (tpi2),y rol a sta (tpi2),y ldy #TPI::PRA lda (tpi2),y rol a sta (tpi2),y bcs L2 pla bcc NoKey ; Branch always L5: ldy keyscanbuf sty norkey pla asl a asl a asl a bcc L6 bmi L7 lda (ktab2),y ; Shifted normal key ldx graphmode beq L8 lda (ktab3),y ; Shifted key in graph mode bne L8 L6: lda (ktab4),y ; Key with ctrl pressed bne L8 L7: lda (ktab1),y ; Normal key L8: tax cpx #$FF ; Valid key? beq Done cpy lastidx beq Repeat ldx #$13 stx rptdelay ldx keyidx cpx #$09 beq NoKey cpy #$59 bne PutKey cpx #$08 beq NoKey sta keybuf,x inx bne PutKey NoKey: ldy #$FF Done: sty lastidx End: lda #$7F ldy #TPI::PRA sta (tpi2),y ldy #TPI::PRB lda #$FF sta (tpi2),y rts Repeat: dec rptdelay bpl End inc rptdelay dec rptcount bpl End inc rptcount ldx keyidx bne End PutKey: sta keybuf,x inx stx keyidx ldx #$03 stx rptcount bne Done .endproc ; Poll the keyboard port until it's stable .proc Poll ldy #TPI::PRC L1: lda (tpi2),y sta keysave lda (tpi2),y cmp keysave bne L1 rts .endproc ������������������������������������������������������cc65-2.18/libsrc/cbm510/kscreen.s�������������������������������������������������������������������0000664�0000000�0000000�00000000331�13473601511�0016265�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-19 ; ; SCREEN kernal call ; .export SCREEN .proc SCREEN ldx #40 ; Columns ldy #25 ; Lines rts .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/ksetnam.s�������������������������������������������������������������������0000664�0000000�0000000�00000001747�13473601511�0016311�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-18 ; ; SETNAM kernal call. ; ; NOTE: The routine does not work like that in the CBM610 kernal (which works ; different than that on all other CBMs). Instead, it works like on all other ; Commodore machines. No segment has to be passed, the current segment is ; assumed. .export SETNAM .import sys_bank, restore_bank .import sysp0: zp, ktmp: zp .include "cbm510.inc" .proc SETNAM pha jsr sys_bank sty ktmp txa ldy #$90 ; FNAM sta (sysp0),y lda ktmp iny sta (sysp0),y lda ExecReg ; Assume name is always in this segment ldy #$92 ; FNAM_SEG sta (sysp0),y ldy #$9D ; FNAM_LEN pla sta (sysp0),y ldy ktmp jmp restore_bank .endproc �������������������������cc65-2.18/libsrc/cbm510/ksettim.s�������������������������������������������������������������������0000664�0000000�0000000�00000000415�13473601511�0016316�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-19 ; ; SETTIM kernal call ; .export SETTIM .import time : zeropage .proc SETTIM sei sta time+0 stx time+1 sty time+2 cli rts .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/kudtim.s��������������������������������������������������������������������0000664�0000000�0000000�00000000616�13473601511�0016136�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-21 ; ; udtim routine for the 610. We will not check for the stop key here, since ; C programs will not use it. ; .export UDTIM .import time: zp .proc UDTIM inc time bne L9 inc time+1 bne L9 inc time+2 bne L9 inc time+3 L9: rts .endproc ������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/libref.s��������������������������������������������������������������������0000664�0000000�0000000�00000000306�13473601511�0016100�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2013-05-31 ; .export em_libref, joy_libref, ser_libref .import _exit em_libref := _exit joy_libref := _exit ser_libref := _exit ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/mainargs.s������������������������������������������������������������������0000664�0000000�0000000�00000011104�13473601511�0016434�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; mainargs.s ; ; 2003-03-07, Ullrich von Bassewitz, ; based on code from Stefan A. Haubenthal, <polluks@web.de> ; 2005-02-26, Ullrich von Bassewitz ; 2014-09-10, Greg King ; ; Scan a group of arguments that are in BASIC's input-buffer. ; Build an array that points to the beginning of each argument. ; Send, to main(), that array and the count of the arguments. ; ; Command-lines look like these lines: ; ; run ; run : rem ; run:rem arg1 " arg 2 is quoted " arg3 "" arg5 ; ; "run" and "rem" are entokenned; the args. are not. Leading and trailing ; spaces outside of quotes are ignored. ; ; TO-DO: ; - The "file-name" might be a path-name; don't copy the directory-components. ; - Add a control-character quoting mechanism. .constructor initmainargs, 24 .import __argc, __argv .import sys_bank, restore_bank .import sysp0:zp, ptr1:zp .include "cbm510.inc" .macpack generic MAXARGS = 10 ; Maximum number of arguments allowed REM = $8f ; BASIC token-code NAME_LEN = 16 ; Maximum length of command-name ; Get possible command-line arguments. Goes into the special ONCE segment, ; which may be reused after the startup code is run. ; .segment "ONCE" 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 sta ptr1 iny lda (sysp0),y sta ptr1+1 iny ; FNAM_BANK lda (sysp0),y tax 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 ; Limit the length bne L1 ; Branch always L0: lda (ptr1),y 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. 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 ; 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 lda #' ' ; A space ends the argument 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 lda #>$0000 adc #>BASIC_BUF sta argv+1,y iny iny inc __argc ; Found another arg ; Search for the end of the argument. argloop:lda BASIC_BUF,x bze done inx cmp term bne argloop ; 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 .segment "INIT" term: .res 1 name: .res NAME_LEN + 1 .data ; char* argv[MAXARGS+1]={name}; argv: .addr name .res MAXARGS * 2 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/mcbdefault.s����������������������������������������������������������������0000664�0000000�0000000�00000010712�13473601511�0016745�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Default mouse callbacks for the CBM510 (P128) ; ; 2004-03-20, Ullrich von Bassewitz2 ; 2013-06-25, Greg King ; ; All functions in this module should be interrupt-safe because they might ; 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" .include "cbm510.inc" .macpack generic ; 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 "ONCE" 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 ldy #VIC_SPR_ENA lda (vic),y and #MOUSE_SPR_NMASK sta (vic),y ldy ExecReg sty IndReg rts ; -------------------------------------------------------------------------- ; Show the mouse pointer. Always called with interrupts disabled. show: ldy #15 sty IndReg ldy #VIC_SPR_ENA lda (vic),y ora #MOUSE_SPR_MASK sta (vic),y ldy ExecReg sty IndReg ; Fall through ; -------------------------------------------------------------------------- ; Prepare to move the mouse pointer. Always called with interrupts disabled. prep: ; Fall through ; -------------------------------------------------------------------------- ; Draw the mouse pointer. Always called with interrupts disabled. draw: rts ; -------------------------------------------------------------------------- ; Move the mouse pointer x position to the value in .XA. Always called with ; interrupts disabled. movex: ldy #15 sty IndReg ; Add the x correction; and, set the low byte. That frees .A. add #<24 ; x correction ldy #VIC_SPR_X sta (vic),y ; Set the high byte ldy #VIC_SPR_HI_X txa adc #>24 bnz @L1 ; Branch if high byte not zero lda (vic),y ; Get high x bits of all sprites and #MOUSE_SPR_NMASK ; Clear high bit for sprite sta (vic),y @L0: ldy ExecReg sty IndReg rts @L1: lda (vic),y ; Get high x bits of all sprites ora #MOUSE_SPR_MASK ; Set high bit for sprite sta (vic),y bnz @L0 ; Branch always ; -------------------------------------------------------------------------- ; Move the mouse pointer y position to the value in .XA. Always called with ; interrupts disabled. movey: ldy #15 sty IndReg add #50 ; y correction (first visible line) ldy #VIC_SPR_Y sta (vic),y ; Set y position ldy ExecReg sty IndReg rts ; -------------------------------------------------------------------------- ; Callback structure .rodata _mouse_def_callbacks: .addr hide .addr show .addr prep .addr draw .addr movex .addr movey ������������������������������������������������������cc65-2.18/libsrc/cbm510/mou/������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015252�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/mou/cbm510-inkwl.s����������������������������������������������������������0000664�0000000�0000000�00000031750�13473601511�0017555�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Driver for the Inkwell Systems 170-C and 184-C lightpens. ; ; This driver reads only the main button on the 184-C. ; ; 2014-09-10, Greg King ; .include "zeropage.inc" .include "../extzp.inc" .include "mouse-kernel.inc" .include "cbm510.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table. module_header _cbm510_inkwl_mou HEADER: ; Driver signature .byte $6d, $6f, $75 ; ASCII "mou" .byte MOUSE_API_VERSION ; Mouse driver API version number ; Library reference LIBREF: .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr HIDE .addr SHOW .addr SETBOX .addr GETBOX .addr MOVE .addr BUTTONS .addr POS .addr INFO .addr IOCTL .addr IRQ ; Mouse driver flags .byte MOUSE_FLAG_EARLY_IRQ ; Callback table, set by the kernel before INSTALL is called. CHIDE: jmp $0000 ; Hide the cursor CSHOW: jmp $0000 ; Show the cursor CPREP: jmp $0000 ; Prepare to move the cursor CDRAW: jmp $0000 ; Draw the cursor CMOVEX: jmp $0000 ; Move the cursor to X co-ord. CMOVEY: jmp $0000 ; Move the cursor to Y co-ord. ;---------------------------------------------------------------------------- ; Constants SCREEN_WIDTH = XSIZE * 8 SCREEN_HEIGHT = YSIZE * 8 ;---------------------------------------------------------------------------- ; Global variables. The bounding box values are sorted so that they can be ; written with the least effort in the SETBOX and GETBOX routines; so, don't ; re-order them. .rodata ; Default values for below variables ; (We use ".proc" because we want to define both a label and a scope.) .proc DefVars .word 0 ; XMin .word 0 ; YMin .word SCREEN_WIDTH - 1 ; XMax .word SCREEN_HEIGHT - 1 ; YMax .endproc .bss Vars: XMin: .res 2 ; X1 value of bounding box YMin: .res 2 ; Y1 value of bounding box XMax: .res 2 ; X2 value of bounding box YMax: .res 2 ; Y2 value of bounding box XPos: .res 2 ; Current lightpen position, X YPos: .res 2 ; Current lightpen position, Y OldPenX: .res 1 ; Previous HW-counter values OldPenY: .res 1 .data ; Default Inkwell calibration. ; The first number is the width of the left border; ; the second number is the actual calibration value. ; See a comment below (at "Calculate the new X co-ordinate") ; for the reason for the third number. XOffset: .byte (24 + 24) / 2 ; x-offset ; Jump to a function that puts a new calibration value into XOffset. Calibrate: jmp $0000 .code ;---------------------------------------------------------------------------- ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present. ; Must return a MOUSE_ERR_xx code in .XA. INSTALL: ; Initiate variables. Just copy the default stuff over. ldx #.sizeof (DefVars) - 1 @L0: lda DefVars,x sta Vars,x dex bpl @L0 ldx #15 ; Change to system bank stx IndReg ldy #VIC_LPEN_X lda (vic),y sta OldPenX ldy #VIC_LPEN_Y lda (vic),y sta OldPenY ldx ExecReg ; Change back to execution bank stx IndReg ; Call a calibration function through the library-reference. lda LIBREF ldx LIBREF+1 sta ptr1 ; Point to mouse_adjuster stx ptr1+1 ldy #1 lda (ptr1),y bze @L1 ; Don't call pointer if it's NULL sta Calibrate+2 ; Point to function dey lda (ptr1),y sta Calibrate+1 lda #<XOffset ; Function will set this variable ldx #>XOffset jsr Calibrate ; Be sure that the lightpen cursor is invisible and at the default location. ; It needs to be done here because the lightpen interrupt handler doesn't ; set the lightpen position if it hasn't changed. @L1: sei jsr CHIDE lda #<(SCREEN_HEIGHT / 2) ldx #>(SCREEN_HEIGHT / 2) jsr MoveY lda #<(SCREEN_WIDTH / 2) ldx #>(SCREEN_WIDTH / 2) jsr MoveX cli ; Done, return zero. lda #MOUSE_ERR_OK tax rts ;---------------------------------------------------------------------------- ; UNINSTALL routine. Is called before the driver is removed from memory. ; No return code required (the driver is removed from memory on return). UNINSTALL := HIDE ; Hide cursor on exit ;---------------------------------------------------------------------------- ; HIDE routine. Is called to hide the lightpen pointer. The mouse kernel manages ; a counter for calls to show/hide, and the driver entry point is called only ; if the mouse is currently visible, and should get hidden. For most drivers, ; no special action is required besides hiding the lightpen cursor. ; No return code required. HIDE: sei jsr CHIDE cli rts ;---------------------------------------------------------------------------- ; SHOW routine. Is called to show the lightpen pointer. The mouse kernel manages ; a counter for calls to show/hide, and the driver entry point is called only ; if the mouse is currently hidden, and should become visible. For most drivers, ; no special action is required besides enabling the lightpen cursor. ; No return code required. SHOW: sei jsr CSHOW cli rts ;---------------------------------------------------------------------------- ; SETBOX: Set the lightpen bounding box. The parameters are passed as they come ; from the C program, that is, a pointer to a mouse_box struct in .XA. ; No checks are done if the lightpen is currently inside the box, that is the job ; of the caller. It is not necessary to validate the parameters; trust the ; caller; and, save some code here. No return code required. SETBOX: sta ptr1 stx ptr1+1 ; Save data pointer ldy #.sizeof (MOUSE_BOX) - 1 sei @L1: lda (ptr1),y sta XMin,y dey bpl @L1 cli rts ;---------------------------------------------------------------------------- ; GETBOX: Return the lightpen bounding box. The parameters are passed as they ; come from the C program, that is, a pointer to a mouse_box struct in .XA. GETBOX: sta ptr1 stx ptr1+1 ; Save data pointer ldy #.sizeof (MOUSE_BOX) - 1 @L1: lda XMin,y sta (ptr1),y dey bpl @L1 rts ;---------------------------------------------------------------------------- ; MOVE: Move the mouse to a new position. The position is passed as it comes ; from the C program, that is: X on the stack and Y in .XA. The C wrapper will ; remove the parameter from the stack on return. ; No checks are done if the new position is valid (within the bounding box or ; the screen). No return code required. ; MOVE: sei ; No interrupts jsr MoveY ldy #$01 lda (sp),y tax dey lda (sp),y jsr MoveX ; Move the cursor cli ; Allow interrupts rts ;---------------------------------------------------------------------------- ; BUTTONS: Return the button mask in .XA. BUTTONS: ldx #15 ; To system bank stx IndReg ldy #CIA::PRB lda (cia2),y ; Read joystick inputs ldx ExecReg ; Back to execution bank stx IndReg ; Joystick 1, directions in bits 3-0. ; Make the lightpen button look like a 1351 mouse. asl a ; Move joystick-left bit ... asl a ; ... to fire-button bit eor #MOUSE_BTN_LEFT and #MOUSE_BTN_LEFT ldx #>$0000 rts ;---------------------------------------------------------------------------- ; POS: Return the lightpen position in the MOUSE_POS struct pointed to by ptr1. ; No return code required. POS: ldy #MOUSE_POS::XCOORD ; Structure offset sei ; Disable interrupts lda XPos ; Transfer the position sta (ptr1),y lda XPos+1 iny sta (ptr1),y lda YPos iny sta (ptr1),y lda YPos+1 cli ; Enable interrupts iny sta (ptr1),y ; Store last byte rts ;---------------------------------------------------------------------------- ; INFO: Returns lightpen position and current button mask in the MOUSE_INFO ; struct pointed to by ptr1. No return code required. ; ; We're cheating here, to keep the code smaller: The first fields of the ; mouse_info struct are identical to the mouse_pos struct; so, we'll just ; call _mouse_pos to initiate the struct pointer, and fill the position ; fields. INFO: jsr POS ; Fill in the button state jsr BUTTONS ; Will not touch ptr1 ldy #MOUSE_INFO::BUTTONS sta (ptr1),y rts ;---------------------------------------------------------------------------- ; IOCTL: Driver-defined entry point. The wrapper will pass a pointer to ioctl- ; specific data in ptr1, and the ioctl code in .A. ; Must return an error code in .XA. ; IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioctls, for now ldx #>MOUSE_ERR_INV_IOCTL rts ;---------------------------------------------------------------------------- ; IRQ: Irq.-handler entry point. Called as a subroutine, but in the IRQ context ; (so, be careful). The routine MUST return carry set if the interrupt has been ; 'handled' -- which means that the interrupt source is gone. Otherwise, it ; MUST return carry clear. ; IRQ: jsr CPREP ldx #15 ; To system bank stx IndReg ; Read the VIC-II lightpen registers. ldy #VIC_LPEN_Y lda (vic),y cmp OldPenY ; Skip processing if nothing has changed. beq @SkipY sta OldPenY ldx ExecReg ; Back to execution bank stx IndReg ; Subtract the height of the top border, so that the lightpen co-ordinate ; will match the TGI co-ordinate. sub #50 tay ; Remember low byte ldx #>$0000 ; Limit the Y co-ordinate to the bounding box. txa cpy YMin sbc YMin+1 bpl @L3 ldy YMin ldx YMin+1 jmp @L4 @L3: txa cpy YMax sbc YMax+1 bmi @L4 ldy YMax ldx YMax+1 @L4: tya jsr MoveY ldx #15 ; To system bank stx IndReg @SkipY: ldy #VIC_LPEN_X lda (vic),y ldx ExecReg ; Back to execution bank stx IndReg cmp OldPenX ; Skip processing if nothing has changed. beq @SkipX sta OldPenX ; Adjust the value by the calibration offset. sub XOffset ; Calculate the new X co-ordinate. ; The VIC-II register is eight bits; but, the screen co-ordinate is nine bits. ; Therefore, the VIC-II number is doubled. Then, it points to every other pixel; ; but, it can reach across the screen. asl a tay ; Remember low byte lda #>$0000 rol a tax ; Remember high byte ; Limit the X co-ordinate to the bounding box. cpy XMin sbc XMin+1 bpl @L1 ldy XMin ldx XMin+1 jmp @L2 @L1: txa cpy XMax sbc XMax+1 bmi @L2 ldy XMax ldx XMax+1 @L2: tya jsr MoveX ; Done @SkipX: jsr CDRAW clc ; Interrupt not "handled" rts ; Move the lightpen pointer to the new Y pos. MoveY: sta YPos stx YPos+1 jmp CMOVEY ; Move the lightpen pointer to the new X pos. MoveX: sta XPos stx XPos+1 jmp CMOVEX ������������������������cc65-2.18/libsrc/cbm510/mou/cbm510-joy.s������������������������������������������������������������0000664�0000000�0000000�00000030516�13473601511�0017231�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Driver for a "joystick mouse". ; ; 2009-09-26, Ullrich von Bassewitz ; 2014-09-10, Greg King ; .include "zeropage.inc" .include "../extzp.inc" .include "mouse-kernel.inc" .include "cbm510.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _cbm510_joy_mou HEADER: ; Driver signature .byte $6d, $6f, $75 ; ASCII "mou" .byte MOUSE_API_VERSION ; Mouse driver API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr HIDE .addr SHOW .addr SETBOX .addr GETBOX .addr MOVE .addr BUTTONS .addr POS .addr INFO .addr IOCTL .addr IRQ ; Mouse driver flags .byte MOUSE_FLAG_LATE_IRQ ; Callback table, set by the kernel before INSTALL is called. CHIDE: jmp $0000 ; Hide the cursor CSHOW: jmp $0000 ; Show the cursor CPREP: jmp $0000 ; Prepare to move the cursor CDRAW: jmp $0000 ; Draw the cursor CMOVEX: jmp $0000 ; Move the cursor to x co-ord. CMOVEY: jmp $0000 ; Move the cursor to y co-ord. ;---------------------------------------------------------------------------- ; Constants SCREEN_HEIGHT = YSIZE * 8 SCREEN_WIDTH = XSIZE * 8 .scope JOY UP = %00000001 DOWN = %00000010 LEFT = %00000100 RIGHT = %00001000 FIRE = %00010000 .endscope ;---------------------------------------------------------------------------- ; Global variables. The bounding box values are sorted so that they can be ; written with the least effort in the SETBOX and GETBOX routines; so, don't ; re-order them. .bss Vars: YPos: .res 2 ; Current mouse position, y XPos: .res 2 ; Current mouse position, x XMin: .res 2 ; X1 value of bounding box YMin: .res 2 ; Y1 value of bounding box XMax: .res 2 ; X2 value of bounding box YMax: .res 2 ; Y2 value of bounding box ; Temporary value used in the interrupt handler Temp: .res 1 .rodata ; Default values for above variables ; (We use ".proc" because we want to define both a label and a scope.) .proc DefVars .word SCREEN_HEIGHT / 2 ; YPos .word SCREEN_WIDTH / 2 ; XPos .word 0 ; XMin .word 0 ; YMin .word SCREEN_WIDTH - 1 ; XMax .word SCREEN_HEIGHT - 1 ; YMax .endproc .code ;---------------------------------------------------------------------------- ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present. ; Must return a MOUSE_ERR_xx code in .XA. INSTALL: ; Initiate variables; just copy the default stuff over. ldx #.sizeof(DefVars) - 1 @L1: lda DefVars,x sta Vars,x dex bpl @L1 ; Be sure the mouse cursor is invisible and at the default location. We ; need to do that here because our mouse interrupt handler doesn't set the ; mouse position if it hasn't changed. sei jsr CHIDE lda XPos ldx XPos+1 jsr CMOVEX lda YPos ldx YPos+1 jsr CMOVEY cli ; Done, return zero. ldx #>MOUSE_ERR_OK txa rts ;---------------------------------------------------------------------------- ; UNINSTALL routine. Is called before the driver is removed from memory. ; No return code required (the driver is removed from memory, on return). UNINSTALL := HIDE ; Hide cursor, on exit ;---------------------------------------------------------------------------- ; HIDE routine. Is called to hide the mouse pointer. The mouse kernel manages ; a counter for calls to show/hide; and, the driver entry point is called only ; if the mouse currently is visible and should get hidden. For most drivers, ; no special action is required besides hiding the mouse cursor. ; No return code required. HIDE: sei jsr CHIDE cli rts ;---------------------------------------------------------------------------- ; SHOW routine. Is called to show the mouse pointer. The mouse kernel manages ; a counter for calls to show/hide; and, the driver entry point is called only ; if the mouse currently is hidden and should become visible. For most drivers, ; no special action is required besides enabling the mouse cursor. ; No return code required. SHOW: sei jsr CSHOW cli rts ;---------------------------------------------------------------------------- ; SETBOX: Set the mouse bounding box. The parameters are passed as they come ; from the C program, that is, a pointer to a mouse_box struct in .XA. ; No checks are done if the mouse currently is inside the box; that is the job ; of the caller. It is not necessary to validate the parameters; trust the ; caller, and save some code here. No return code required. SETBOX: sta ptr1 stx ptr1+1 ; Save data pointer ldy #.sizeof (MOUSE_BOX) - 1 sei @L1: lda (ptr1),y sta XMin,y dey bpl @L1 cli rts ;---------------------------------------------------------------------------- ; GETBOX: Return the mouse bounding box. The parameters are passed as they ; come from the C program, that is, a pointer to a mouse_box struct in .XA. GETBOX: sta ptr1 stx ptr1+1 ; Save data pointer ldy #.sizeof (MOUSE_BOX) - 1 @L1: lda XMin,y sta (ptr1),y dey bpl @L1 rts ;---------------------------------------------------------------------------- ; MOVE: Move the mouse to a new position. The position is passed as it comes ; from the C program, that is: x on the stack and y in .XA. The C wrapper will ; remove the parameter from the stack, on return. ; No checks are done if the new position is valid (within the bounding box or ; the screen). No return code required. ; MOVE: sei ; No interrupts jsr MoveY ; Set new y position ldy #1 lda (sp),y sta XPos+1 tax dey lda (sp),y jsr MoveX ; Move the pointer cli ; Allow interrupts rts ;---------------------------------------------------------------------------- ; BUTTONS: Return the button mask in .XA. ; Joystick 2's fire button is the left mouse button. ; Joystick 1's fire button is the right mouse button. BUTTONS: ldx #15 ; Switch to the system bank stx IndReg ; Get the fire-button bits ldy #CIA::PRA lda (cia2),y ; Switch back to the execution bank. ldy ExecReg sty IndReg ; Joystick 2, fire button is in bit 7. ; Joystick 1, fire button is in bit 6. and #%11000000 asl a ; Move bits 7,6 to bits 1,0 rol a rol a adc #%00001110 ; Move bit 1 to bit 4 and #MOUSE_BTN_LEFT | MOUSE_BTN_RIGHT ; Bits go up when buttons go down. eor #MOUSE_BTN_LEFT | MOUSE_BTN_RIGHT ldx #>$0000 rts ;---------------------------------------------------------------------------- ; INFO: Returns mouse position and current button mask in the MOUSE_INFO ; struct pointed to by ptr1. No return code required. ; ; We're cheating here to keep the code smaller: The first fields of the ; mouse_info struct are identical to the mouse_pos struct; so, we just will ; use _mouse_pos to fill the position fields. INFO: jsr BUTTONS ; Fill in the button state. ldy #MOUSE_INFO::BUTTONS sta (ptr1),y ; jmp POS ; Fall through ;---------------------------------------------------------------------------- ; POS: Return the mouse position in the MOUSE_POS struct pointed to by ptr1. ; No return code required. POS: ldy #MOUSE_POS::XCOORD ; Structure offset sei ; Disable interrupts lda XPos ; Transfer the position sta (ptr1),y lda XPos+1 iny sta (ptr1),y lda YPos iny sta (ptr1),y lda YPos+1 cli ; Enable interrupts iny sta (ptr1),y ; Store last byte rts ; Done ;---------------------------------------------------------------------------- ; IOCTL: Driver-defined entry point. The wrapper will pass a pointer to ioctl- ; specific data in ptr1, and the ioctl code in .A. ; Must return an error code in .XA. ; IOCTL: lda #<MOUSE_ERR_INV_IOCTL ; We don't support ioctls, for now ldx #>MOUSE_ERR_INV_IOCTL rts ;---------------------------------------------------------------------------- ; IRQ: Irq.-handler entry point. Called as a subroutine, but in the IRQ context ; (so, be careful). The routine MUST return carry set if the interrupt has been ; 'handled' -- which means that the interrupt source is gone. Otherwise, it ; MUST return carry clear. ; Reads joystick 2. ; IRQ: jsr CPREP ldy #15 ; Switch to the system bank sty IndReg ; Get the direction bits. ldy #CIA::PRB lda (cia2),y ; Read joystick inputs ; Switch back to the execution bank. ldy ExecReg sty IndReg ; Joystick 2, directions in bits 7-4. ; Mask the relevant bits. and #$F0 eor #$F0 ; All bits are inverted sta Temp ; Check left/right. and #(JOY::LEFT | JOY::RIGHT) << 4 bze @SkipX ; We will cheat here, and rely on the fact that either the left OR the right ; bit can be active. and #JOY::RIGHT << 4 ; Check RIGHT bit bnz @Right lda #<-$0001 tax bnz @AddX ; Branch always @Right: lda #<$0001 ldx #>$0001 ; Calculate the new x co-ordinate (--> .YA). @AddX: add XPos tay ; Remember low byte txa adc XPos+1 tax ; Limit the x co-ordinate to the bounding box. cpy XMin sbc XMin+1 bpl @L1 ldy XMin ldx XMin+1 jmp @L2 @L1: txa cpy XMax sbc XMax+1 bmi @L2 ldy XMax ldx XMax+1 @L2: tya jsr MoveX ; Calculate the y movement vector. @SkipX: lda Temp ; Get joystick again and #(JOY::UP | JOY::DOWN) << 4 ; Check up/down bze @SkipY ; We will cheat here, and rely on the fact that either the up OR the down ; bit can be active. and #JOY::UP << 4 ; Check UP bit bze @Down lda #<-$0001 tax bnz @AddY @Down: lda #<$0001 ldx #>$0001 ; Calculate the new y co-ordinate (--> .YA). @AddY: add YPos tay ; Remember low byte txa adc YPos+1 tax ; Limit the y co-ordinate to the bounding box. cpy YMin sbc YMin+1 bpl @L3 ldy YMin ldx YMin+1 jmp @L4 @L3: txa cpy YMax sbc YMax+1 bmi @L4 ldy YMax ldx YMax+1 @L4: tya jsr MoveY ; Done @SkipY: jsr CDRAW clc ; Interrupt not "handled" rts ; Move the mouse pointer to the new x pos. MoveX: sta XPos stx XPos+1 jmp CMOVEX ; Move the mouse pointer to the new y pos. MoveY: sta YPos stx YPos+1 jmp CMOVEY ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/mouse_stat_stddrv.s���������������������������������������������������������0000664�0000000�0000000�00000000376�13473601511�0020415�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Address of the static standard mouse driver ; ; 2012-11-01, Oliver Schmidt ; 2013-08-06, Greg King ; ; const void mouse_static_stddrv[]; ; .export _mouse_static_stddrv .import _cbm510_joy_mou _mouse_static_stddrv := _cbm510_joy_mou ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/mouse_stddrv.s��������������������������������������������������������������0000664�0000000�0000000�00000000331�13473601511�0017351�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Name of the standard mouse driver ; ; 2009-09-11, Ullrich von Bassewitz ; 2013-06-25, Greg King ; ; const char mouse_stddrv[]; ; .export _mouse_stddrv .rodata _mouse_stddrv: .asciiz "cbm510-joy.mou" �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/mouseref.s������������������������������������������������������������������0000664�0000000�0000000�00000001152�13473601511�0016462�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Pointer for library references by device drivers. ; ; 2013-07-25, Greg King ; .export mouse_libref, _pen_adjuster .data mouse_libref: ; generic label for mouse-kernel ; A program optionally can set this pointer to a function that gives ; a calibration value to a driver. If this pointer isn't NULL, ; then a driver that wants a value can call that function. ; ; The function might read a value from a file; or, it might ask the user ; to help calibrate the driver. ; ; void __fastcall__ (*pen_adjuster)(unsigned char *) = NULL; ; _pen_adjuster: .addr $0000 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/peeksys.s�������������������������������������������������������������������0000664�0000000�0000000�00000002220�13473601511�0016315�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 14.09.2001 ; .export _peekbsys, _peekwsys .importzp ptr1 .include "cbm510.inc" ; ------------------------------------------------------------------------ ; unsigned char __fastcall__ peekbsys (unsigned addr); .proc _peekbsys sta ptr1 ; Store argument pointer stx ptr1+1 ldx IndReg lda #$0F sta IndReg ldy #$00 lda (ptr1),y stx IndReg ldx #$00 ; Extend to word rts .endproc ; ------------------------------------------------------------------------ ; unsigned __fastcall__ peekwsys (unsigned addr); .proc _peekwsys sta ptr1 ; Store argument pointer stx ptr1+1 ldx IndReg lda #$0F sta IndReg ldy #$00 lda (ptr1),y ; Get low byte pha iny lda (ptr1),y ; Get high byte stx IndReg tax ; High byte -> X pla ; Low byte -> A rts .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/pencalib.c������������������������������������������������������������������0000775�0000000�0000000�00000005246�13473601511�0016405�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** Calibrate lightpen drivers to the current video hardware. ** ** 2013-09-05, Greg King ** */ #include <conio.h> #include <mouse.h> #include <pen.h> #define COMMAND1 "Adjust by clicking on line." #define COMMAND2 "Finish by clicking off bar." /* ** There is a delay between when the VIC sends its signal, and when the display ** shows that signal. There is another delay between the display and when ** the lightpen says that it saw that signal. Each display and pen is different. ** Therefore, the driver must be calibrated to them. A white bar is painted on ** the screen; and, a line is drawn down the middle of it. When the user clicks ** on that line, the difference between its position and where the VIC thinks ** that the pen is pointing becomes an offset that is subtracted from what the ** VIC sees. */ void __fastcall__ pen_calibrate (unsigned char *XOffset) { unsigned char oldBg = bgcolor (COLOR_BLUE); unsigned char oldText = textcolor (COLOR_GRAY3); unsigned char oldRev = revers (1); unsigned char sprite0Color = peekbsys ((unsigned)&VIC.spr_color[0]); unsigned char width, width2, height, height4, height8; struct mouse_info info; screensize (&width, &height); width2 = width / 2; height4 = height / 4; height8 = height4 * 8; /* Draw a bar and line. */ clrscr (); cclearxy (0, height4, height4 * width); cvlinexy (width2, height4 + 1, height4 - 2); revers (0); /* Print instructions. */ cputsxy (width2 - (sizeof COMMAND1) / 2, height / 2 + 1, COMMAND1); cputsxy (width2 - (sizeof COMMAND2) / 2, height / 2 + 3, COMMAND2); pokebsys ((unsigned)&VIC.spr_color[0], COLOR_GRAY2); mouse_show (); mouse_move (width2 * 8, height8 / 2); for (;;) { /* Wait for the main button to be released. */ do ; while ((mouse_buttons () & MOUSE_BTN_LEFT)); /* Wait for the main button to be pressed. */ do { mouse_info (&info); } while (!(info.buttons & MOUSE_BTN_LEFT)); /* Find out if the pen is on or off the bar. */ if (info.pos.y < height8 || info.pos.y >= height8 * 2) { break; } /* On the bar; adjust the offset. */ /* Characters are eight pixels wide. ** The VIC-II sees every other pixel; ** so, we use half of the difference. */ *XOffset += (info.pos.x - (width2 * 8 + 8/2)) / 2; } /* Off the bar; wait for the main button to be released. */ do ; while ((mouse_buttons () & MOUSE_BTN_LEFT)); mouse_hide (); pokebsys ((unsigned)&VIC.spr_color[0], sprite0Color); revers (oldRev); textcolor (oldText); bgcolor (oldBg); clrscr (); } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/pokesys.s�������������������������������������������������������������������0000664�0000000�0000000�00000002075�13473601511�0016337�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 13.09.2001 ; ; void pokebsys (unsigned Addr, unsigned char Val); ; void pokewsys (unsigned Addr, unsigned Val); .export _pokebsys, _pokewsys .import popsreg .importzp sreg, tmp1 .include "cbm510.inc" ; ------------------------------------------------------------------------ ; .proc _pokebsys jsr popsreg ; Get the address ldx IndReg ldy #$0F sty IndReg ; Switch to the system bank ldy #$00 sta (sreg),y stx IndReg rts .endproc ; ------------------------------------------------------------------------ ; .proc _pokewsys stx tmp1 ; Save high byte jsr popsreg ; Get the address ldx IndReg ldy #$0F sty IndReg ; Switch to the system bank ldy #$00 sta (sreg),y iny lda tmp1 sta (sreg),y stx IndReg rts .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/randomize.s�����������������������������������������������������������������0000664�0000000�0000000�00000000575�13473601511�0016635�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2002-11-05, Ullrich von Bassewitz ; 2015-09-11, Greg King ; ; void _randomize (void); ; /* Initialize the random number generator */ ; .export __randomize .import _srand .importzp time __randomize: ldx time+2 ; Use 50/60HZ clock lda time+1 jmp _srand ; Initialize generator �����������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/revers.s��������������������������������������������������������������������0000664�0000000�0000000�00000001377�13473601511�0016154�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 07.08.1998 ; ; unsigned char revers (unsigned char onoff); ; .export _revers .import RVS: zp .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 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/ser/������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015243�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/ser/cbm510-std.s������������������������������������������������������������0000664�0000000�0000000�00000030725�13473601511�0017215�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Serial driver for the builtin 6551 ACIA of the Commodore 510. ; ; Ullrich von Bassewitz, 2003-12-18 ; ; The driver is based on the cc65 rs232 module, which in turn is based on ; Craig Bruce device driver for the Switftlink/Turbo-232. ; ; SwiftLink/Turbo-232 v0.90 device driver, by Craig Bruce, 14-Apr-1998. ; ; This software is Public Domain. It is in Buddy assembler format. ; ; This device driver uses the SwiftLink RS-232 Serial Cartridge, available from ; Creative Micro Designs, Inc, and also supports the extensions of the Turbo232 ; Serial Cartridge. Both devices are based on the 6551 ACIA chip. It also ; supports the "hacked" SwiftLink with a 1.8432 MHz crystal. ; ; The code assumes that the kernal + I/O are in context. On the C128, call ; it from Bank 15. On the C64, don't flip out the Kernal unless a suitable ; NMI catcher is put into the RAM under then Kernal. For the SuperCPU, the ; interrupt handling assumes that the 65816 is in 6502-emulation mode. ; .include "zeropage.inc" .include "../extzp.inc" .include "ser-kernel.inc" .include "ser-error.inc" .include "cbm510.inc" .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _cbm510_std_ser ; Driver signature .byte $73, $65, $72 ; "ser" .byte SER_API_VERSION ; Serial API version number ; Library reference .addr $0000 ; Jump table .word SER_INSTALL .word SER_UNINSTALL .word SER_OPEN .word SER_CLOSE .word SER_GET .word SER_PUT .word SER_STATUS .word SER_IOCTL .word SER_IRQ ;---------------------------------------------------------------------------- ; ; Global variables ; .bss RecvHead: .res 1 ; Head of receive buffer RecvTail: .res 1 ; Tail of receive buffer RecvFreeCnt: .res 1 ; Number of bytes in receive buffer SendHead: .res 1 ; Head of send buffer SendTail: .res 1 ; Tail of send buffer SendFreeCnt: .res 1 ; Number of bytes in send buffer Stopped: .res 1 ; Flow-stopped flag RtsOff: .res 1 ; ; Send and receive buffers: 256 bytes each RecvBuf: .res 256 SendBuf: .res 256 .rodata ; Tables used to translate RS232 params into register values BaudTable: ; bit7 = 1 means setting is invalid .byte $FF ; SER_BAUD_45_5 .byte $01 ; SER_BAUD_50 .byte $02 ; SER_BAUD_75 .byte $03 ; SER_BAUD_110 .byte $04 ; SER_BAUD_134_5 .byte $05 ; SER_BAUD_150 .byte $06 ; SER_BAUD_300 .byte $07 ; SER_BAUD_600 .byte $08 ; SER_BAUD_1200 .byte $09 ; SER_BAUD_1800 .byte $0A ; SER_BAUD_2400 .byte $0B ; SER_BAUD_3600 .byte $0C ; SER_BAUD_4800 .byte $0D ; SER_BAUD_7200 .byte $0E ; SER_BAUD_9600 .byte $0F ; SER_BAUD_19200 .byte $FF ; SER_BAUD_38400 .byte $FF ; SER_BAUD_57600 .byte $FF ; SER_BAUD_115200 .byte $FF ; SER_BAUD_230400 BitTable: .byte $60 ; SER_BITS_5 .byte $40 ; SER_BITS_6 .byte $20 ; SER_BITS_7 .byte $00 ; SER_BITS_8 StopTable: .byte $00 ; SER_STOP_1 .byte $80 ; SER_STOP_2 ParityTable: .byte $00 ; SER_PAR_NONE .byte $20 ; SER_PAR_ODD .byte $60 ; SER_PAR_EVEN .byte $A0 ; SER_PAR_MARK .byte $E0 ; SER_PAR_SPACE .code ;---------------------------------------------------------------------------- ; SER_INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present. ; Must return an SER_ERR_xx code in a/x. ; ; Since we don't have to manage the IRQ vector on the Plus/4, this is actually ; the same as: ; ; SER_UNINSTALL routine. Is called before the driver is removed from memory. ; Must return an SER_ERR_xx code in a/x. ; and: ; ; SER_CLOSE: Close the port, disable interrupts and flush the buffer. Called ; without parameters. Must return an error code in a/x. ; SER_INSTALL: SER_UNINSTALL: SER_CLOSE: ; Deactivate DTR and disable 6551 interrupts lda #%00001010 jsr write_cmd ; Done, return an error code lda #<SER_ERR_OK tax ; A is zero rts ;---------------------------------------------------------------------------- ; PARAMS routine. A pointer to a ser_params structure is passed in ptr1. ; Must return an SER_ERR_xx code in a/x. SER_OPEN: ; Check if the handshake setting is valid ldy #SER_PARAMS::HANDSHAKE ; Handshake lda (ptr1),y cmp #SER_HS_HW ; This is all we support bne InvParam ; Initialize buffers ldx #0 stx Stopped stx RecvHead stx RecvTail stx SendHead stx SendTail dex ; X = 255 stx RecvFreeCnt stx SendFreeCnt ; Set the value for the control register, which contains stop bits, word ; length and the baud rate. ldy #SER_PARAMS::BAUDRATE lda (ptr1),y ; Baudrate index tay lda BaudTable,y ; Get 6551 value bmi InvBaud ; Branch if rate not supported sta tmp1 ldy #SER_PARAMS::DATABITS ; Databits lda (ptr1),y tay lda BitTable,y ora tmp1 sta tmp1 ldy #SER_PARAMS::STOPBITS ; Stopbits lda (ptr1),y tay lda StopTable,y ora tmp1 ora #%00010000 ; Receiver clock source = baudrate ldy #ACIA::CTRL jsr write ; Set the value for the command register. We remember the base value in ; RtsOff, since we will have to manipulate ACIA_CMD often. ldy #SER_PARAMS::PARITY ; Parity lda (ptr1),y tay lda ParityTable,y ora #%00000001 ; DTR active sta RtsOff ora #%00001000 ; Enable receive interrupts jsr write_cmd ; Done lda #<SER_ERR_OK tax ; A is zero rts ; Invalid parameter InvParam: lda #<SER_ERR_INIT_FAILED ldx #>SER_ERR_INIT_FAILED rts ; Baud rate not available InvBaud: lda #<SER_ERR_BAUD_UNAVAIL ldx #>SER_ERR_BAUD_UNAVAIL rts ;---------------------------------------------------------------------------- ; SER_GET: Will fetch a character from the receive buffer and store it into the ; variable pointer to by ptr1. If no data is available, SER_ERR_NO_DATA is ; return. ; SER_GET: ldx SendFreeCnt ; Send data if necessary inx ; X == $FF? beq @L1 lda #$00 jsr TryToSend ; Check for buffer empty @L1: lda RecvFreeCnt cmp #$ff bne @L2 lda #<SER_ERR_NO_DATA ldx #>SER_ERR_NO_DATA rts ; Check for flow stopped & enough free: release flow control @L2: ldx Stopped beq @L3 cmp #63 bcc @L3 lda #$00 sta Stopped lda RtsOff ora #%00001000 jsr write_cmd ; Get byte from buffer @L3: ldx RecvHead lda RecvBuf,x inc RecvHead inc RecvFreeCnt ldx #$00 sta (ptr1,x) txa ; Return code = 0 rts ;---------------------------------------------------------------------------- ; SER_PUT: Output character in A. ; Must return an error code in a/x. ; SER_PUT: ; Try to send ldx SendFreeCnt inx ; X = $ff? beq @L2 pha lda #$00 jsr TryToSend pla ; Put byte into send buffer & send @L2: ldx SendFreeCnt bne @L3 lda #<SER_ERR_OVERFLOW ; X is already zero rts @L3: ldx SendTail sta SendBuf,x inc SendTail dec SendFreeCnt lda #$ff jsr TryToSend lda #<SER_ERR_OK tax rts ;---------------------------------------------------------------------------- ; SER_STATUS: Return the status in the variable pointed to by ptr1. ; Must return an error code in a/x. ; SER_STATUS: lda #$0F sta IndReg ldy #ACIA::STATUS lda (acia),y ldx #0 sta (ptr1,x) lda IndReg sta ExecReg txa ; SER_ERR_OK rts ;---------------------------------------------------------------------------- ; SER_IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl ; specific data in ptr1, and the ioctl code in A. ; Must return an error code in a/x. ; SER_IOCTL: lda #<SER_ERR_INV_IOCTL ; We don't support ioclts for now ldx #>SER_ERR_INV_IOCTL rts ;---------------------------------------------------------------------------- ; SER_IRQ: Called from the builtin runtime IRQ handler as a subroutine. All ; registers are already save, no parameters are passed, but the carry flag ; is clear on entry. The routine must return with carry set if the interrupt ; was handled, otherwise with carry clear. ; SER_IRQ: lda #$0F sta IndReg ; Switch to the system bank ldy #ACIA::STATUS lda (acia),y ; Check ACIA status for receive interrupt and #$08 beq @L9 ; Jump if no ACIA interrupt (carry still clear) ldy #ACIA::DATA lda (acia),y ; Get byte from ACIA ldx RecvFreeCnt ; Check if we have free space left beq @L1 ; Jump if no space in receive buffer ldy RecvTail ; Load buffer pointer sta RecvBuf,y ; Store received byte in buffer inc RecvTail ; Increment buffer pointer dec RecvFreeCnt ; Decrement free space counter cpx #33 ; Check for buffer space low bcs @L9 ; Assert flow control if buffer space low ; Assert flow control if buffer space too low @L1: lda RtsOff ldy #ACIA::CMD sta (acia),y sta Stopped sec ; Interrupt handled ; Done, switch back to the execution segment @L9: lda ExecReg sta IndReg rts ;---------------------------------------------------------------------------- ; Try to send a byte. Internal routine. A = TryHard .proc TryToSend sta tmp1 ; Remember tryHard flag lda #$0F sta IndReg ; Switch to the system bank @L0: lda SendFreeCnt cmp #$ff beq @L3 ; Bail out ; Check for flow stopped @L1: lda Stopped bne @L3 ; Bail out ; Check that swiftlink is ready to send @L2: ldy #ACIA::STATUS lda (acia),y and #$10 bne @L4 bit tmp1 ; Keep trying if must try hard bmi @L0 ; Switch back the bank and return @L3: lda ExecReg sta IndReg rts ; Send byte and try again @L4: ldx SendHead lda SendBuf,x ldy #ACIA::DATA sta (acia),y inc SendHead inc SendFreeCnt jmp @L0 .endproc ;---------------------------------------------------------------------------- ; Write to the ACIA changing the indirect segment. Offset is in Y, value in A. write_cmd: ldy #ACIA::CMD write: pha lda #$0F sta IndReg pla sta (acia),y lda ExecReg sta IndReg rts �������������������������������������������cc65-2.18/libsrc/cbm510/settime.s�������������������������������������������������������������������0000664�0000000�0000000�00000004201�13473601511�0016305�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2018-08-18, Oliver Schmidt ; 2018-08-19, Greg King ; ; int __fastcall__ clock_settime (clockid_t clk_id, const struct timespec *tp); ; .include "time.inc" .include "cbm510.inc" .include "extzp.inc" .importzp sreg, ptr1 .import pushax, pusheax, ldax0sp, ldeaxidx .import sys_bank, restore_bank .import tosdiveax, incsp3, return0 .import TM, load_tenth ;---------------------------------------------------------------------------- .code .proc _clock_settime jsr pushax .assert timespec::tv_sec = 0, error jsr _localtime sta ptr1 stx ptr1+1 ldy #.sizeof(tm)-1 @L1: lda (ptr1),y sta TM,y dey bpl @L1 jsr sys_bank lda TM + tm::tm_hour jsr dec2BCD tax ; Force flags bne @L2 lda #$92 ; 12 AM bne @L3 @L2: cmp #$13 ; 1 PM bcc @L3 sed sbc #$12 cld ora #%10000000 @L3: ldy #CIA::TODHR sta (cia2),y lda TM + tm::tm_min jsr dec2BCD ldy #CIA::TODMIN sta (cia2),y lda TM + tm::tm_sec jsr dec2BCD ldy #CIA::TODSEC sta (cia2),y jsr restore_bank jsr ldax0sp ldy #3+timespec::tv_nsec jsr ldeaxidx jsr pusheax jsr load_tenth jsr tosdiveax jsr sys_bank ldy #CIA::TOD10 sta (cia2),y jsr restore_bank lda #$00 tax jmp incsp3 .endproc ;---------------------------------------------------------------------------- ; Just sum up the value in BCD mode. ; http://forum.6502.org/viewtopic.php?p=7629#p7629 .proc dec2BCD tax dex bmi @L9 lda #0 clc sed @L1: adc #1 dex bpl @L1 cld @L9: rts .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/sysuname.s������������������������������������������������������������������0000664�0000000�0000000�00000001447�13473601511�0016510�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-08-12 ; ; unsigned char __fastcall__ _sysuname (struct utsname* buf); ; .export __sysuname, utsdata .import utscopy __sysuname = utscopy ;-------------------------------------------------------------------------- ; Data. We define a fixed utsname struct here and just copy it. .rodata utsdata: ; sysname .asciiz "cc65" ; nodename .asciiz "" ; release .byte ((.VERSION >> 8) & $0F) + '0' .byte '.' .byte ((.VERSION >> 4) & $0F) + '0' .byte $00 ; version .byte (.VERSION & $0F) + '0' .byte $00 ; machine .asciiz "Commodore 510" �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/tmcommon.s������������������������������������������������������������������0000664�0000000�0000000�00000002001�13473601511�0016460�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 16.8.2018 ; ; Common stuff for the clock routines ; .include "cbm510.inc" .export TM, load_tenth .importzp sreg ;---------------------------------------------------------------------------- .code .proc load_tenth lda #<(100 * 1000 * 1000 / $10000) ldx #>(100 * 1000 * 1000 / $10000) sta sreg stx sreg+1 lda #<(100 * 1000 * 1000) ldx #>(100 * 1000 * 1000) rts .endproc ;---------------------------------------------------------------------------- ; TM struct with date set to 1970-01-01 .data TM: .word 0 ; tm_sec .word 0 ; tm_min .word 0 ; tm_hour .word 1 ; tm_mday .word 0 ; tm_mon .word 70 ; tm_year .word 0 ; tm_wday .word 0 ; tm_yday .word 0 ; tm_isdst �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm510/waitvsync.s�����������������������������������������������������������������0000664�0000000�0000000�00000000770�13473601511�0016671�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Written by Groepaz <groepaz@gmx.net> ; ; void waitvsync (void); ; .export _waitvsync .import PALFLAG .import sys_bank, restore_bank .importzp vic .include "cbm510.inc" _waitvsync: jsr sys_bank ; Switch to the system bank sei ldy #VIC_CTRL1 @l1: lda (vic),y bpl @l1 @l2: lda (vic),y bmi @l2 cli jmp restore_bank ��������cc65-2.18/libsrc/cbm610/����������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014453�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/_scrsize.s������������������������������������������������������������������0000664�0000000�0000000�00000000250�13473601511�0016455�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.10.2000 ; ; Screen size variables ; .export screensize .import SCREEN screensize = SCREEN ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/banking.s�������������������������������������������������������������������0000664�0000000�0000000�00000001152�13473601511�0016247�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 28.09.1998 ; ; Banking routines for the 610. ; .export set_bank, sys_bank, restore_bank .importzp ptr1, segsave .include "cbm610.inc" .code .proc sys_bank pha lda IndReg sta segsave lda #$0F sta IndReg pla rts .endproc .proc set_bank pha lda IndReg sta segsave pla sta IndReg rts .endproc .proc restore_bank pha lda segsave sta IndReg pla rts .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/break.s���������������������������������������������������������������������0000664�0000000�0000000�00000004500�13473601511�0015722�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 27.09.1998 ; ; void __fastcall__ set_brk (unsigned Addr); ; void reset_brk (void); ; .export _set_brk, _reset_brk .export _brk_a, _brk_x, _brk_y, _brk_sr, _brk_pc .import _atexit, BRKVec .include "cbm610.inc" .bss _brk_a: .res 1 _brk_x: .res 1 _brk_y: .res 1 _brk_sr: .res 1 _brk_pc: .res 2 _brk_01: .res 1 oldvec: .res 2 ; Old vector .data uservec: jmp $FFFF ; Patched at runtime .code ; Set the break vector .proc _set_brk sta uservec+1 stx uservec+2 ; Set the user vector lda oldvec ora oldvec+1 ; Did we save the vector already? bne L1 ; Jump if we installed the handler already lda BRKVec sta oldvec lda BRKVec+1 sta oldvec+1 ; Save the old vector L1: lda #<brk_handler ; Set the break vector to our routine ldx #>brk_handler sta BRKVec stx BRKVec+1 rts .endproc ; Reset the break vector .proc _reset_brk lda oldvec ldx oldvec+1 beq @L9 ; Jump if vector not installed sta BRKVec stx BRKVec+1 lda #$00 sta oldvec ; Clear the old vector stx oldvec+1 @L9: rts .endproc ; Break handler, called if a break occurs .proc brk_handler pla sta _brk_01 pla sta _brk_y pla sta _brk_x pla sta _brk_a pla and #$EF ; Clear break bit sta _brk_sr pla ; PC low sec sbc #2 ; Point to start of brk sta _brk_pc pla ; PC high sbc #0 sta _brk_pc+1 jsr uservec ; Call the user's routine lda _brk_01 sta IndReg lda _brk_pc+1 pha lda _brk_pc pha lda _brk_sr pha ldx _brk_x ldy _brk_y lda _brk_a rti ; Jump back... .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/cgetc.s���������������������������������������������������������������������0000664�0000000�0000000�00000002301�13473601511�0015720�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; char cgetc (void); ; .export _cgetc .import plot, write_crtc .import cursor .import keyidx: zp, keybuf: zp, config: zp _cgetc: lda keyidx ; Get number of characters bne L2 ; Jump if there are already chars waiting ; Switch on the cursor if needed lda cursor beq L1 ; Jump if no cursor jsr plot ; Set the current cursor position ldy #10 lda config ; Cursor format jsr write_crtc ; Set the cursor formar L1: lda keyidx beq L1 ldy #10 lda #$20 ; Cursor off jsr write_crtc L2: ldx #$00 ; Get index ldy keybuf ; Get first character in the buffer sei L3: lda keybuf+1,x ; Move up the remaining chars sta keybuf,x inx cpx keyidx bne L3 dec keyidx cli ldx #$00 ; High byte tya ; First char from buffer rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/clrscr.s��������������������������������������������������������������������0000664�0000000�0000000�00000001521�13473601511�0016126�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.09.1998 ; ; void clrscr (void); ; .export _clrscr .import plot .import CURS_X: zp, CURS_Y: zp, CharPtr: zp .include "cbm610.inc" .proc _clrscr lda #0 sta CURS_X sta CURS_Y jsr plot ; Set cursor to top left corner lda IndReg pha lda #$0F sta IndReg ; Switch to the system bank ldx #8 ldy #$00 lda #$20 ; Screencode for blank L1: sta (CharPtr),y iny bne L1 inc CharPtr+1 dex bne L1 pla sta IndReg ; Restore old indirect segment jmp plot ; Set screen pointer again .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/color.s���������������������������������������������������������������������0000664�0000000�0000000�00000000702�13473601511�0015754�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; 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 .import return0, return1 .include "cbm610.inc" _textcolor = return1 _bgcolor = return0 _bordercolor = return0 ��������������������������������������������������������������cc65-2.18/libsrc/cbm610/cpeekc.s��������������������������������������������������������������������0000664�0000000�0000000�00000001644�13473601511�0016076�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2016-02-28, Groepaz ; 2017-06-19, Greg King ; ; char cpeekc (void); ; .export _cpeekc .import CURS_X: zp, CharPtr: zp .include "cbm610.inc" _cpeekc: ldx IndReg ldy #$0F sty IndReg ldy CURS_X lda (CharPtr),y ; get char from system bank stx IndReg ldx #>$0000 and #<~$80 ; remove reverse bit ; Convert the screen code into a PetSCII code. ; $00 - $1F: +$40 ; $20 - $3F ; $40 - $5f: +$20 ; $60 - $7F: +$40 cmp #$20 bcs @sk1 ;(bge) ora #$40 rts @sk1: cmp #$40 bcc @end ;(blt) cmp #$60 bcc @sk2 ;(blt) ;sec adc #$20 - $01 @sk2: ;clc ; both above cmp and adc clear carry flag adc #$20 @end: rts ��������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/cpeekcolor.s����������������������������������������������������������������0000664�0000000�0000000�00000000247�13473601511�0016770�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2017-06-03, Greg King ; ; unsigned char cpeekcolor (void); ; .import return1 .export _cpeekcolor := return1 ; always COLOR_WHITE ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/cpeekrevers.s���������������������������������������������������������������0000664�0000000�0000000�00000001175�13473601511�0017161�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2016-02-28, Groepaz ; 2017-06-19, Greg King ; ; unsigned char cpeekrevers (void); ; .export _cpeekrevers .import plot .import CURS_X: zp, CharPtr: zp .include "cbm610.inc" _cpeekrevers: ldx IndReg ldy #$0F sty IndReg ldy CURS_X lda (CharPtr),y ; get char from system bank stx IndReg ldx #>$0000 and #$80 ; get reverse bit asl a tax ; ldx #>$0000 rol a ; return boolean value rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/cpeeks.s��������������������������������������������������������������������0000664�0000000�0000000�00000003524�13473601511�0016115�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2017-07-05, Greg King ; ; void cpeeks (char* s, unsigned length); ; .export _cpeeks .import popax .importzp ptr1, ptr2, ptr3, tmp1, tmp2 .importzp CURS_X, CharPtr .include "cbm610.inc" .macpack generic _cpeeks: eor #<$FFFF ; counting a word upward is faster sta ptr3 ; so, we use -(length + 1) txa eor #>$FFFF sta ptr3+1 lda CharPtr ldx CharPtr+1 sta ptr2 stx ptr2+1 ldy CURS_X sty tmp2 jsr popax sta tmp1 ; (will be a .Y index) stx ptr1+1 ldx IndReg ldy #<$0000 sty ptr1 bze L3 ; branch always L4: ldy #$0F sty IndReg ldy tmp2 lda (ptr2),y ; get char from system bank stx IndReg iny bnz L2 inc ptr2+1 L2: sty tmp2 and #<~$80 ; remove reverse bit ; Convert the screen code into a PetSCII code. ; $00 - $1F: +$40 ; $20 - $3F ; $40 - $5f: +$20 ; $60 - $7F: +$40 cmp #$20 blt @sk1 ;(bcc) cmp #$40 blt L5 cmp #$60 blt @sk2 ;(bcc) clc @sk1: adc #$20 @sk2: ;clc ; both above cmp and adc clear carry flag adc #$20 L5: ldy tmp1 sta (ptr1),y iny bnz L1 inc ptr1+1 L1: sty tmp1 L3: inc ptr3 ; count length bnz L4 inc ptr3+1 bnz L4 lda #$00 ; terminate the string ldy tmp1 sta (ptr1),y rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/cputc.s���������������������������������������������������������������������0000664�0000000�0000000�00000007462�13473601511�0015766�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; void cputcxy (unsigned char x, unsigned char y, char c); ; void cputc (char c); ; .export _cputcxy, _cputc, cputdirect, putchar .export newline, plot .destructor setsyscursor .import gotoxy .import PLOT .import ktmp: zp, crtc: zp, CURS_X: zp, CURS_Y: zp, RVS: zp .import CharPtr: zp .include "cbm610.inc" _cputcxy: pha ; Save C jsr gotoxy ; Set cursor, drop x and y pla ; Restore C ; Plot a character - also used as internal function _cputc: cmp #$0A ; CR? bne L1 lda #0 sta CURS_X beq plot ; Recalculate pointers L1: cmp #$0D ; LF? beq newline ; Recalculate pointers ; Printable char of some sort cmp #' ' bcc cputdirect ; Other control char tay bmi L10 cmp #$60 bcc L2 and #$DF bne cputdirect ; Branch always L2: and #$3F cputdirect: jsr putchar ; Write the character to the screen ; Advance cursor position advance: iny cpy #XSIZE bne L3 jsr newline ; new line ldy #0 ; + cr L3: sty CURS_X rts newline: clc lda #XSIZE adc CharPtr sta CharPtr bcc L4 inc CharPtr+1 L4: inc CURS_Y rts ; Handle character if high bit set L10: and #$7F cmp #$7E ; PI? bne L11 lda #$5E ; Load screen code for PI bne cputdirect L11: ora #$40 bne cputdirect ; Branch always ; Write one character to the screen without doing anything else, return X ; position in Y putchar: ldx IndReg ldy #$0F sty IndReg ora RVS ; Set revers bit ldy CURS_X sta (CharPtr),y ; Set char stx IndReg rts ; Set cursor position, calculate RAM pointers plot: ldx CURS_Y lda LineLSBTab,x sta CharPtr lda LineMSBTab,x sta CharPtr+1 lda IndReg pha lda #$0F sta IndReg ldy #$00 clc sei sta (crtc),y lda CharPtr adc CURS_X iny sta (crtc),y dey lda #$0E sta (crtc),y iny lda (crtc),y and #$F8 sta ktmp lda CharPtr+1 adc #$00 and #$07 ora ktmp sta (crtc),y cli pla sta IndReg rts ; ------------------------------------------------------------------------- ; Cleanup routine that sets the kernal cursor position to ours .segment "PAGE2" setsyscursor: ldy CURS_X ldx CURS_Y clc jmp PLOT ; Set the new cursor ; ------------------------------------------------------------------------- ; Low bytes of the start address of the screen lines .rodata LineLSBTab: .byte $00,$50,$A0,$F0,$40,$90,$E0,$30 .byte $80,$D0,$20,$70,$C0,$10,$60,$B0 .byte $00,$50,$A0,$F0,$40,$90,$E0,$30 .byte $80 ; ------------------------------------------------------------------------- ; High bytes of the start address of the screen lines LineMSBTab: .byte $D0,$D0,$D0,$D0,$D1,$D1,$D1,$D2 .byte $D2,$D2,$D3,$D3,$D3,$D4,$D4,$D4 .byte $D5,$D5,$D5,$D5,$D6,$D6,$D6,$D7 .byte $D7 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/crt0.s����������������������������������������������������������������������0000664�0000000�0000000�00000030656�13473601511�0015521�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Startup code for cc65 (CBM 600/700 version) ; .export _exit, BRKVec .export __STARTUP__ : absolute = 1 ; Mark as startup .import callirq_y, initlib, donelib .import push0, callmain .import __BSS_RUN__, __BSS_SIZE__, __EXTZP_RUN__ .import __INTERRUPTOR_COUNT__ .import scnkey, UDTIM .include "zeropage.inc" .include "extzp.inc" .include "cbm610.inc" ; ------------------------------------------------------------------------ ; The BASIC header and a small BASIC program. Since it isn't possible to start ; programs in other banks using SYS, the BASIC program will write a small ; machine code program into memory at $100; and, start that machine code ; program. The machine code program will then start the machine language ; code in bank 1, which will initialize the system by copying stuff from ; the system bank, and start the application. ; ; Here's the BASIC program that's in the following lines: ; ; 10 for i=0 to 4 ; 20 read j ; 30 poke 256+i,j ; 40 next i ; 50 sys 256 ; 60 data 120,169,1,133,0 ; ; The machine program in the data lines is: ; ; sei ; lda #$01 ; sta $00 <-- Switch to bank 1 after this command ; ; Initialization is complex not only because of the jumping from one bank ; into another. but also because we want to save memory; and because of ; that, we will use the system memory ($00-$3FF) for initialization stuff ; that is overwritten later. ; .segment "EXEHDR" .byte $03,$00,$11,$00,$0a,$00,$81,$20,$49,$b2,$30,$20,$a4,$20,$34,$00 .byte $19,$00,$14,$00,$87,$20,$4a,$00,$27,$00,$1e,$00,$97,$20,$32,$35 .byte $36,$aa,$49,$2c,$4a,$00,$2f,$00,$28,$00,$82,$20,$49,$00,$39,$00 .byte $32,$00,$9e,$20,$32,$35,$36,$00,$4f,$00,$3c,$00,$83,$20,$31,$32 .byte $30,$2c,$31,$36,$39,$2c,$31,$2c,$31,$33,$33,$2c,$30,$00,$00,$00 ;------------------------------------------------------------------------------ ; A table that contains values that must be transferred from the system zero- ; page into our zero-page. Contains pairs of bytes, first one is the address ; in the system ZP, second one is our ZP address. The table goes into page 2; ; but, is declared here because it is needed earlier. .SEGMENT "PAGE2" ; (We use .proc because we need both a label and a scope.) .proc transfer_table .byte $9F, DEVNUM .byte $CA, CURS_Y .byte $CB, CURS_X .byte $CC, graphmode .byte $D4, config .endproc ;------------------------------------------------------------------------------ ; Page 3 data. This page contains the break vector and the bankswitch ; subroutine that is copied into high memory on startup. The space occupied by ; this routine will later be used for a copy of the bank 15 stack. It must be ; saved since we're going to destroy it when calling bank 15. .segment "PAGE3" BRKVec: .addr _exit ; BRK indirect vector .proc callbank15 excrts := $FF05 ; In bank 15 ROM .org $FECB entry: php pha lda #$0F ; Bank 15 sta IndReg txa pha tya pha sei ldy #$FF lda (sysp1),y tay lda ExecReg sta (sysp1),y dey lda #.hibyte(excrts-1) sta (sysp1),y dey lda #.lobyte(excrts-1) sta (sysp1),y tya sec sbc #7 sta $1FF ; Save new sp tay tsx pla iny sta (sysp1),y pla iny sta (sysp1),y pla iny sta (sysp1),y pla iny sta (sysp1),y lda $105,x sec sbc #3 iny sta (sysp1),y lda $106,x sbc #0 iny sta (sysp1),y ldy $1FF ; Restore sp in bank 15 lda #.hibyte(expull-1) sta (sysp1),y dey lda #.lobyte(expull-1) sta (sysp1),y dey pla pla tsx stx $1FF tya tax txs lda IndReg jmp $FFF6 expull: pla tay pla tax pla plp rts .if (expull <> $FF2E) .error "Symbol expull must be aligned with Kernal in bank 15" .endif .reloc .endproc ;------------------------------------------------------------------------------ ; The code in the target bank when switching back will be put at the bottom ; of the stack. We will jump here to switch segments. The range $F2..$FF is ; not used by any Kernal routine. .segment "STARTUP" Back: sta ExecReg ; We are at $100 now. The following snippet is a copy of the code that is poked ; in the system bank memory by the BASIC header program; it's only for ; documentation, and not actually used here: sei lda #$01 sta ExecReg ; This is the actual starting point of our code after switching banks for ; startup. Beware: The following code will get overwritten as soon as we ; use the stack (since it's in page 1)! We jump to another location since ; we need some space for subroutines that aren't used later. jmp Origin ; Hardware vectors, copied to $FFF6 .proc vectors sta ExecReg rts nop .word nmi ; NMI vector .word 0 ; Reset -- not used .word irq ; IRQ vector .endproc ; Initializers for the extended zero-page. See "extzp.s". .proc extzp .word $0100 ; sysp1 .word $0300 ; sysp3 .word $d800 ; crtc .word $da00 ; sid .word $db00 ; ipccia .word $dc00 ; cia .word $dd00 ; acia .word $de00 ; tpi1 .word $df00 ; tpi2 .word $ea29 ; ktab1 .word $ea89 ; ktab2 .word $eae9 ; ktab3 .word $eb49 ; ktab4 .endproc ; Switch the indirect segment to the system bank. Origin: lda #$0F sta IndReg ; Initialize the extended zero-page. ldx #.sizeof(extzp)-1 L1: lda extzp,x sta <__EXTZP_RUN__,x dex bpl L1 ; Save the old stack pointer from the system bank; and, set up our hw sp. tsx txa ldy #$FF sta (sysp1),y ; Save system stack point into $F:$1FF ldx #$FE ; Leave $1FF untouched for cross-bank calls txs ; Set up our own stack ; Copy stuff from the system zero-page to ours. lda #.sizeof(transfer_table) sta ktmp L2: ldx ktmp ldy transfer_table-2,x lda transfer_table-1,x tax lda (sysp0),y sta $00,x dec ktmp dec ktmp bne L2 ; Set the interrupt, NMI, and other vectors. ldx #.sizeof(vectors)-1 L3: lda vectors,x sta $10000 - .sizeof(vectors),x dex bpl L3 ; Set up the C stack. lda #.lobyte(callbank15::entry) sta sp lda #.hibyte(callbank15::entry) sta sp+1 ; Set up the subroutine and jump vector table that redirects Kernal calls to ; the system bank. ldy #.sizeof(callbank15) @L1: lda callbank15-1,y sta callbank15::entry-1,y dey bne @L1 ; Set up the jump vector table. Y is zero on entry. ldx #45-1 ; Number of vectors @L2: lda #$20 ; JSR opcode sta $FF6F,y iny lda #.lobyte(callbank15::entry) sta $FF6F,y iny lda #.hibyte(callbank15::entry) sta $FF6F,y iny dex bpl @L2 ; Set the indirect segment to the bank that we're executing in. lda ExecReg sta IndReg ; Zero the BSS segment. We will do that here instead of calling the routine ; in the common library, since we have the memory anyway; and this way, ; it's reused later. lda #<__BSS_RUN__ sta ptr1 lda #>__BSS_RUN__ sta ptr1+1 lda #0 tay ; Clear full pages. ldx #>__BSS_SIZE__ beq Z2 Z1: sta (ptr1),y iny bne Z1 inc ptr1+1 ; Next page dex bne Z1 ; Clear the remaining page. Z2: ldx #<__BSS_SIZE__ beq Z4 Z3: sta (ptr1),y iny dex bne Z3 Z4: jmp Init ; ------------------------------------------------------------------------ ; We are at $200 now. We may now start calling subroutines safely since ; the code we execute is no longer in the stack page. .segment "PAGE2" ; Activate the chained interrupt handlers; then, enable interrupts. Init: lda #.lobyte(__INTERRUPTOR_COUNT__*2) sta irqcount cli ; Call module constructors. jsr initlib ; Push the command-line arguments; and, call main(). jsr callmain ; Call the module destructors. This is also the exit() entry and the default entry ; point for the break vector. _exit: pha ; Save the return code jsr donelib ; Run module destructors lda #$00 sta irqcount ; Disable custom irq handlers ; Address the system bank. lda #$0F sta IndReg ; Copy stuff back from our zero-page to the system's. .if 0 lda #.sizeof(transfer_table) sta ktmp @L0: ldx ktmp ldy transfer_table-2,x lda transfer_table-1,x tax lda $00,x sta (sysp0),y dec ktmp dec ktmp bne @L0 .endif ; Place the program return code into BASIC's status variable. pla ldy #$9C ; ST sta (sysp0),y ; Set up the welcome code at the stack bottom in the system bank. ldy #$FF lda (sysp1),y ; Load system bank sp tax iny ; Y = 0 lda #$58 ; CLI opcode sta (sysp1),y iny lda #$60 ; RTS opcode sta (sysp1),y lda IndReg sei txs jmp Back ; ------------------------------------------------------------------------- ; The IRQ handler goes into PAGE2. For performance reasons, and to allow ; easier chaining, we do handle the IRQs in the execution bank (instead of ; passing them to the system bank). ; This is the mapping of the active IRQ register of the 6525 (tpi1): ; ; Bit 7 6 5 4 3 2 1 0 ; | | | | ^ 50 Hz. ; | | | ^ SRQ IEEE 488 ; | | ^ CIA ; | ^ IRQB ext. Port ; ^ ACIA irq: pha txa pha tya pha lda IndReg pha lda ExecReg sta IndReg ; Be sure to address our segment tsx lda $105,x ; Get the flags from the stack and #$10 ; Test break flag bne dobrk ; It's an IRQ. cld ; Call the chained IRQ handlers. ldy irqcount beq irqskip jsr callirq_y ; Call the functions ; Done with the chained IRQ handlers; check the TPI for IRQs, and handle them. irqskip:lda #$0F sta IndReg ldy #TPI::AIR lda (tpi1),y ; Interrupt Register 6525 beq noirq ; 50/60Hz. interrupt cmp #%00000001 ; ticker IRQ? bne irqend jsr scnkey ; Poll the keyboard jsr UDTIM ; Bump the time ; Done. irqend: ldy #TPI::AIR sta (tpi1),y ; Clear interrupt noirq: pla sta IndReg pla tay pla tax pla nmi: rti dobrk: jmp (BRKVec) ; ------------------------------------------------------------------------- ; Data area .bss irqcount: .byte 0 ����������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/crtc.s����������������������������������������������������������������������0000664�0000000�0000000�00000001650�13473601511�0015574�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 28.09.1998 ; ; Write to the CRTC. ; .export write_crtc, read_crtc .importzp crtc, ktmp .include "cbm610.inc" ; Write a value to the CRTC. The index is in Y, the value in A .proc write_crtc sta ktmp lda IndReg pha lda #$0F sta IndReg tya ldy #$00 sei sta (crtc),y iny lda ktmp sta (crtc),y cli pla sta IndReg lda ktmp rts .endproc .proc read_crtc sty ktmp lda IndReg pha lda #$0F sta IndReg lda ktmp ldy #$00 sei sta (crtc),y iny lda (crtc),y cli tay pla sta IndReg tya ldy ktmp rts .endproc ����������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/devnum.s��������������������������������������������������������������������0000664�0000000�0000000�00000000160�13473601511�0016132�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2010-02-14 ; .include "extzp.inc" .exportzp devnum := DEVNUM ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/emd/������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015220�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/emd/cbm610-ram.s������������������������������������������������������������0000664�0000000�0000000�00000016171�13473601511�0017157�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Extended memory driver for the CBM610 additional RAM banks. Driver works ; without problems when linked statically. ; ; Ullrich von Bassewitz, 2002-12-09, 2003-12-20 ; .include "zeropage.inc" .include "em-kernel.inc" .include "em-error.inc" .include "cbm610.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _cbm610_ram_emd ; Driver signature .byte $65, $6d, $64 ; "emd" .byte EMD_API_VERSION ; EM API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr PAGECOUNT .addr MAP .addr USE .addr COMMIT .addr COPYFROM .addr COPYTO ; ------------------------------------------------------------------------ ; Constants RAMBANK = 2 OFFS = 2 ; ------------------------------------------------------------------------ ; Data. .bss curpage: .res 1 ; Current page number window: .res 256 ; Memory "window" pagecount: .res 1 ; Number of available pages .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present and determine the amount of ; memory available. ; Must return an EM_ERR_xx code in a/x. ; INSTALL: lda #$FF sta curpage ; Invalidate the current page sta pagecount ; Assume all memory available sec jsr $FF99 ; MEMTOP cmp #RAMBANK ; Top of memory in bank 2? bne @L1 ; No: We can use all the memory txa sub #OFFS tya sbc #$00 sta pagecount @L1: lda #<EM_ERR_OK ldx #>EM_ERR_OK ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; PAGECOUNT: Return the total number of available pages in a/x. ; PAGECOUNT: lda pagecount ldx #0 rts ; ------------------------------------------------------------------------ ; MAP: Map the page in a/x into memory and return a pointer to the page in ; a/x. The contents of the currently mapped page (if any) may be discarded ; by the driver. ; MAP: sta curpage ; Remember the new page sta ptr1+1 lda #OFFS sta ptr1 ; Transfer one page ldx IndReg lda #RAMBANK sta IndReg ldy #$00 @L1: .repeat 2 lda (ptr1),y sta window,y iny .endrepeat bne @L1 stx IndReg ; Return the memory window lda #<window ldx #>window ; Return the window address rts ; ------------------------------------------------------------------------ ; USE: Tell the driver that the window is now associated with a given page. USE: sta curpage ; Remember the page lda #<window ldx #>window ; Return the window rts ; ------------------------------------------------------------------------ ; COMMIT: Commit changes in the memory window to extended storage. COMMIT: lda curpage ; Get the current page cmp #$FF beq done ; Jump if no page mapped sta ptr1+1 lda #OFFS sta ptr1 ; Transfer one page ldx IndReg lda #RAMBANK sta IndReg ldy #$00 @L1: .repeat 2 lda window,y sta (ptr1),y iny .endrepeat bne @L1 stx IndReg ; Done done: rts ; ------------------------------------------------------------------------ ; COPYFROM: Copy from extended into linear memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYFROM: jsr setup ; Setup the buffer address in this bank. sta copyfrom_buf stx copyfrom_buf+1 ; Check if we must copy full pages ldx ptr2+1 beq @L2 ; Copy full pages ldx #$00 @L1: jsr copyfrom inc ptr1+1 inc copyfrom_buf+1 @L2: dec ptr2+1 bne @L1 ; Copy the remaining page ldx ptr2 beq @L3 jsr copyfrom ; Restore the indirect segment @L3: lda ExecReg sta IndReg ; Done rts ; ------------------------------------------------------------------------ ; COPYTO: Copy from linear into extended memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYTO: jsr setup ; Setup the buffer address in this bank. sta copyto_buf stx copyto_buf+1 ; Check if we must copy full pages ldx ptr2+1 beq @L2 ; Copy full pages ldx #$00 @L1: jsr copyto inc ptr1+1 inc copyto_buf+1 @L2: dec ptr2+1 bne @L1 ; Copy the remaining page ldx ptr2 beq @L3 jsr copyto ; Restore the indirect segment @L3: lda ExecReg sta IndReg ; Done rts ; ------------------------------------------------------------------------ ; setup: Helper function for COPYFROM and COPYTO, will setup parameters. ; setup: sta ptr3 stx ptr3+1 ; Save the passed em_copy pointer ldy #EM_COPY::OFFS lda (ptr3),y add #OFFS sta ptr1 ldy #EM_COPY::PAGE lda (ptr3),y adc #$00 sta ptr1+1 ldy #EM_COPY::COUNT lda (ptr3),y sta ptr2 iny lda (ptr3),y sta ptr2+1 ; Get count into ptr2 ldy #EM_COPY::BUF+1 lda (ptr3),y tax dey lda (ptr3),y ; Get the buffer pointer into a/x ldy #RAMBANK sty IndReg ldy #$00 rts ; ------------------------------------------------------------------------ ; copyfrom .data copyfrom: lda (ptr1),y copyfrom_buf = * + 1 sta $0000,y iny dex bne copyfrom rts ; ------------------------------------------------------------------------ ; copyto .data copyto: copyto_buf = * + 1 lda $0000,y sta (ptr1),y iny dex bne copyto rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/extzp.inc�������������������������������������������������������������������0000664�0000000�0000000�00000001031�13473601511�0016313�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-20 ; ; Additional zero page locations for the CBM610. ; ; ------------------------------------------------------------------------ .globalzp sysp1, sysp3, crtc, sid, ipccia, cia, acia, tpi1, tpi2 .globalzp ktab1, ktab2, ktab3, ktab4 .globalzp sysp0, time, segsave, ktmp, CURS_X, CURS_Y, RVS, DEVNUM .globalzp config, CharPtr, keyidx, keybuf, keyscanbuf, keysave .globalzp modkey, norkey, graphmode, lastidx, rptdelay, rptcount �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/extzp.s���������������������������������������������������������������������0000664�0000000�0000000�00000003211�13473601511�0016006�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-20 ; ; Additional zero page locations for the CBM610. ; NOTE: This file is actually linked to an application with its full contents, ; so the program comes up with the values given in this file. ; ; ------------------------------------------------------------------------ .include "extzp.inc" .segment "EXTZP" : zeropage ; The following values get initialized from a table in the startup code. ; While this sounds crazy, it has reasons that have to do with modules (and ; we have the space anyway). So when changing anything, be sure to adjust the ; initializer table sysp1: .word $0000 sysp3: .word $0000 crtc: .word $0000 sid: .word $0000 ipccia: .word $0000 cia: .word $0000 acia: .word $0000 tpi1: .word $0000 tpi2: .word $0000 ktab1: .word $0000 ktab2: .word $0000 ktab3: .word $0000 ktab4: .word $0000 sysp0: .word $0000 time: .dword $0000 segsave: .byte 0 ktmp: .byte 0 CURS_X: .byte 0 CURS_Y: .byte 0 RVS: .byte 0 DEVNUM: .byte 0 config: .byte 0 CharPtr: .word 0 ; Stuff for our own kbd polling routine keyidx: .byte 0 ; Number of keys in keyboard buffer keybuf: .res 10 ; Keyboard buffer keyscanbuf: .byte 0 keysave: .byte 0 modkey: .byte 0 norkey: .byte 0 graphmode: .byte 0 lastidx: .byte 0 rptdelay: .byte 0 rptcount: .byte 0 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/get_tv.s��������������������������������������������������������������������0000664�0000000�0000000�00000000541�13473601511�0016127�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Stefan Haubenthal, 2009-08-02 ; ; unsigned char get_tv (void); ; /* Return the video mode the machine is using */ ; .include "get_tv.inc" ;-------------------------------------------------------------------------- ; _get_tv .proc _get_tv lda #<TV::OTHER ; CRTC ldx #>TV::OTHER rts .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/gettime.s�������������������������������������������������������������������0000664�0000000�0000000�00000004346�13473601511�0016304�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2009-07-27, Stefan Haubenthal ; 2009-09-24, Ullrich von Bassewitz ; 2018-08-18, Oliver Schmidt ; 2018-08-19, Greg King ; ; int __fastcall__ clock_gettime (clockid_t clk_id, struct timespec *tp); ; .include "time.inc" .include "cbm610.inc" .include "extzp.inc" .import pushax, pusheax, tosmul0ax, steaxspidx, incsp1 .import sys_bank, restore_bank .import TM, load_tenth .importzp sreg, tmp1, tmp2 ;---------------------------------------------------------------------------- .code .proc _clock_gettime jsr pushax jsr pushax jsr sys_bank ldy #CIA::TODHR lda (cia),y sed tax ; Save PM flag and #%01111111 cmp #$12 ; 12 AM/PM bcc @L1 sbc #$12 @L1: inx ; Get PM flag bpl @L2 clc adc #$12 @L2: cld jsr BCD2dec sta TM + tm::tm_hour ldy #CIA::TODMIN lda (cia),y jsr BCD2dec sta TM + tm::tm_min ldy #CIA::TODSEC lda (cia),y jsr BCD2dec sta TM + tm::tm_sec ldy #CIA::TOD10 lda (cia),y jsr restore_bank pha lda #<TM ldx #>TM jsr _mktime ldy #timespec::tv_sec jsr steaxspidx ; Pops address pushed by 2. pushax jsr load_tenth jsr pusheax pla ldx #>$0000 jsr tosmul0ax ldy #timespec::tv_nsec jsr steaxspidx ; Pops address pushed by 1. pushax lda #$00 tax jmp incsp1 .endproc ;---------------------------------------------------------------------------- ; dec = (((BCD>>4)*10) + (BCD&0xf)) .proc BCD2dec tax and #%00001111 sta tmp1 txa and #%11110000 ; *16 lsr ; *8 sta tmp2 lsr lsr ; *2 adc tmp2 ; = *10 adc tmp1 rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/irq.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000162�13473601511�0015431�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; IRQ handling (CBM 600/700 version) ; .export initirq, doneirq initirq: doneirq: rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/kbhit.s���������������������������������������������������������������������0000664�0000000�0000000�00000000534�13473601511�0015742�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; unsigned char kbhit (void); ; .export _kbhit .import keyidx: zp .proc _kbhit ldx #0 ; High byte of return is always zero lda keyidx ; Get number of characters beq L9 lda #1 L9: rts .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/kclose.s��������������������������������������������������������������������0000664�0000000�0000000�00000000617�13473601511�0016123�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-21 ; ; CLOSE kernal call. ; ; NOTE: The CLOSE system call in the CBM610 kernal will only remove the file ; entry and not close the file on IEC if the carry is clear on entry. To make ; this somewhat compatible with the C64, set the carry before jumping to the ; kernal. .export CLOSE .proc CLOSE sec jmp $FFC3 .endproc �����������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/kernal.s��������������������������������������������������������������������0000664�0000000�0000000�00000001722�13473601511�0016115�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-20 ; ; CBM610 kernal functions ; .include "cbm_kernal.inc" .export CINT .export IOINIT .export RESTOR .export VECTOR .export SETMSG .export SECOND .export TKSA .export MEMTOP .export MEMBOT .export SCNKEY .export SETTMO .export ACPTR .export CIOUT .export UNTLK .export UNLSN .export LISTEN .export TALK .export SETLFS .export CHKIN .export CKOUT .export CLRCH .export BASIN .export BSOUT .export LOAD .export SAVE .export STOP .export GETIN .export CLALL .export PLOT ����������������������������������������������cc65-2.18/libsrc/cbm610/kiobase.s�������������������������������������������������������������������0000664�0000000�0000000�00000000332�13473601511�0016252�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-19 ; ; IOBASE kernal call ; .export IOBASE .import cia : zeropage .proc IOBASE ldx cia ldy cia+1 rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/kopen.s���������������������������������������������������������������������0000664�0000000�0000000�00000000732�13473601511�0015755�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-20 ; ; OPEN kernal call. ; ; NOTE: The OPEN system call in the CBM610 kernal is different from the ; standard. It evaluates the carry flag and does a normal open if carry clear ; and some strange things (output sa 15 + name on IEC) if carry set. To be ; compatible with our CBM file stuff, we have to clear the carry before ; calling the real OPEN. .export OPEN .proc OPEN clc jmp $FFC0 .endproc ��������������������������������������cc65-2.18/libsrc/cbm610/krdtim.s��������������������������������������������������������������������0000664�0000000�0000000�00000000412�13473601511�0016126�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-19 ; ; RDTIM kernal call ; .export RDTIM .import time : zeropage .proc RDTIM sei lda time+0 ldx time+1 ldy time+2 cli rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/kreadst.s�������������������������������������������������������������������0000664�0000000�0000000�00000001047�13473601511�0016276�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-19 ; ; READST kernal call ; .export READST .import sys_bank, restore_bank .import sysp0: zp, ktmp: zp .include "cbm610.inc" .proc READST jsr sys_bank sty ktmp ; Save Y register ldy #$9C ; STATUS lda (sysp0),y ; Load STATUS from system bank ldy ktmp jmp restore_bank ; Will set condition codes on A .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/kscnkey.s�������������������������������������������������������������������0000664�0000000�0000000�00000006104�13473601511�0016307�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 28.09.1998 ; ; Keyboard polling stuff for the 610. ; .export scnkey .importzp tpi2, ktab1, ktab2, ktab3, ktab4 .importzp keyidx, keybuf, keyscanbuf, keysave, modkey, norkey .importzp graphmode, lastidx, rptdelay, rptcount .include "cbm610.inc" .proc scnkey lda #$FF sta modkey sta norkey lda #$00 sta keyscanbuf ldy #TPI::PRB sta (tpi2),y ldy #TPI::PRA sta (tpi2),y jsr Poll and #$3F eor #$3F bne L1 jmp NoKey L1: lda #$FF ldy #TPI::PRA sta (tpi2),y asl a ldy #TPI::PRB sta (tpi2),y jsr Poll pha sta modkey ora #$30 bne L3 ; Branch always L2: jsr Poll L3: ldx #$05 ldy #$00 L4: lsr a bcc L5 inc keyscanbuf dex bpl L4 sec ldy #TPI::PRB lda (tpi2),y rol a sta (tpi2),y ldy #TPI::PRA lda (tpi2),y rol a sta (tpi2),y bcs L2 pla bcc NoKey ; Branch always L5: ldy keyscanbuf sty norkey pla asl a asl a asl a bcc L6 bmi L7 lda (ktab2),y ; Shifted normal key ldx graphmode beq L8 lda (ktab3),y ; Shifted key in graph mode bne L8 L6: lda (ktab4),y ; Key with ctrl pressed bne L8 L7: lda (ktab1),y ; Normal key L8: tax cpx #$FF ; Valid key? beq Done cpy lastidx beq Repeat ldx #$13 stx rptdelay ldx keyidx cpx #$09 beq NoKey cpy #$59 bne PutKey cpx #$08 beq NoKey sta keybuf,x inx bne PutKey NoKey: ldy #$FF Done: sty lastidx End: lda #$7F ldy #TPI::PRA sta (tpi2),y ldy #TPI::PRB lda #$FF sta (tpi2),y rts Repeat: dec rptdelay bpl End inc rptdelay dec rptcount bpl End inc rptcount ldx keyidx bne End PutKey: sta keybuf,x inx stx keyidx ldx #$03 stx rptcount bne Done .endproc ; Poll the keyboard port until it's stable ; This code goes into page 2, since it is included in every program and ; there's space left in p2 .segment "PAGE2" .proc Poll ldy #TPI::PRC L1: lda (tpi2),y sta keysave lda (tpi2),y cmp keysave bne L1 rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/kscreen.s�������������������������������������������������������������������0000664�0000000�0000000�00000000331�13473601511�0016266�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-19 ; ; SCREEN kernal call ; .export SCREEN .proc SCREEN ldx #80 ; Columns ldy #25 ; Lines rts .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/ksetnam.s�������������������������������������������������������������������0000664�0000000�0000000�00000001745�13473601511�0016310�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-18 ; ; SETNAM kernal call. ; ; NOTE: The routine does not work like that in the CBM610 kernal (which works ; different than that on all other CBMs). Instead, it works like on all other ; Commodore machines. No segment has to be passed, the current segment is ; assumed. .export SETNAM .import sys_bank, restore_bank .import sysp0: zp, ktmp: zp .include "cbm610.inc" .proc SETNAM pha jsr sys_bank sty ktmp txa ldy #$90 ; FNAM sta (sysp0),y lda ktmp iny sta (sysp0),y lda ExecReg ; Assume name is always in this segment ldy #$92 ; FNAM_SEG sta (sysp0),y ldy #$9D ; FNAM_LEN pla sta (sysp0),y ldy ktmp jmp restore_bank .endproc ���������������������������cc65-2.18/libsrc/cbm610/ksettim.s�������������������������������������������������������������������0000664�0000000�0000000�00000000415�13473601511�0016317�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-19 ; ; SETTIM kernal call ; .export SETTIM .import time : zeropage .proc SETTIM sei sta time+0 stx time+1 sty time+2 cli rts .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/kudtim.s��������������������������������������������������������������������0000664�0000000�0000000�00000000616�13473601511�0016137�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-21 ; ; udtim routine for the 610. We will not check for the stop key here, since ; C programs will not use it. ; .export UDTIM .import time: zp .proc UDTIM inc time bne L9 inc time+1 bne L9 inc time+2 bne L9 inc time+3 L9: rts .endproc ������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/libref.s��������������������������������������������������������������������0000664�0000000�0000000�00000000241�13473601511�0016077�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2013-05-31 ; .export em_libref, ser_libref .import _exit em_libref := _exit ser_libref := _exit ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/mainargs.s������������������������������������������������������������������0000664�0000000�0000000�00000010733�13473601511�0016444�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; mainargs.s ; ; 2003-03-07, Ullrich von Bassewitz, ; based on code from Stefan A. Haubenthal, <polluks@web.de> ; 2005-02-26, Ullrich von Bassewitz ; 2014-09-10, Greg King ; ; Scan a group of arguments that are in BASIC's input-buffer. ; Build an array that points to the beginning of each argument. ; Send, to main(), that array and the count of the arguments. ; ; Command-lines look like these lines: ; ; run ; run : rem ; run:rem arg1 " arg 2 is quoted " arg3 "" arg5 ; ; "run" and "rem" are entokenned; the args. are not. Leading and trailing ; spaces outside of quotes are ignored. ; ; TO-DO: ; - The "file-name" might be a path-name; don't copy the directory-components. ; - Add a control-character quoting mechanism. .constructor initmainargs, 24 .import __argc, __argv .import sys_bank, restore_bank .import sysp0:zp, ptr1:zp .include "cbm610.inc" .macpack generic MAXARGS = 10 ; Maximum number of arguments allowed REM = $8f ; BASIC token-code NAME_LEN = 16 ; Maximum length of command-name ; Get possible command-line arguments. Goes into the special ONCE segment, ; which may be reused after the startup code is run. ; .segment "ONCE" initmainargs: ; Assume that the program was loaded, a moment ago, by the traditional LOAD ; statement. Save the "most-recent filename" as argument #0. jsr sys_bank ldy #FNAM lda (sysp0),y ; Get file-name pointer from system bank sta ptr1 iny lda (sysp0),y sta ptr1+1 iny ; FNAM_BANK lda (sysp0),y tax 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 ; Limit the length bne L1 ; Branch always L0: lda (ptr1),y 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. 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 ; 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 lda #' ' ; A space ends the argument 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 lda #>$0000 adc #>BASIC_BUF sta argv+1,y iny iny inc __argc ; Found another arg ; Search for the end of the argument. argloop:lda BASIC_BUF,x bze done inx cmp term bne argloop ; 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 .segment "INIT" term: .res 1 name: .res NAME_LEN + 1 .data ; char* argv[MAXARGS+1]={name}; argv: .addr name .res MAXARGS * 2 �������������������������������������cc65-2.18/libsrc/cbm610/peeksys.s�������������������������������������������������������������������0000664�0000000�0000000�00000002220�13473601511�0016316�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 14.09.2001 ; .export _peekbsys, _peekwsys .importzp ptr1 .include "cbm610.inc" ; ------------------------------------------------------------------------ ; unsigned char __fastcall__ peekbsys (unsigned addr); .proc _peekbsys sta ptr1 ; Store argument pointer stx ptr1+1 ldx IndReg lda #$0F sta IndReg ldy #$00 lda (ptr1),y stx IndReg ldx #$00 ; Extend to word rts .endproc ; ------------------------------------------------------------------------ ; unsigned __fastcall__ peekwsys (unsigned addr); .proc _peekwsys sta ptr1 ; Store argument pointer stx ptr1+1 ldx IndReg lda #$0F sta IndReg ldy #$00 lda (ptr1),y ; Get low byte pha iny lda (ptr1),y ; Get high byte stx IndReg tax ; High byte -> X pla ; Low byte -> A rts .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/pokesys.s�������������������������������������������������������������������0000664�0000000�0000000�00000001576�13473601511�0016345�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 29.09.1998 ; ; void pokebsys (unsigned Addr, unsigned char Val); ; void pokewsys (unsigned Addr, unsigned Val); .export _pokebsys, _pokewsys .import popsreg .importzp sreg, tmp1 .include "cbm610.inc" _pokebsys: jsr popsreg ; Get the address ldx IndReg ldy #$0F sty IndReg ; Switch to the system bank ldy #$00 sta (sreg),y stx IndReg rts _pokewsys: stx tmp1 ; Save high byte jsr popsreg ; Get the address ldx IndReg ldy #$0F sty IndReg ; Switch to the system bank ldy #$00 sta (sreg),y iny lda tmp1 sta (sreg),y stx IndReg rts ����������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/randomize.s�����������������������������������������������������������������0000664�0000000�0000000�00000000575�13473601511�0016636�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2002-11-05, Ullrich von Bassewitz ; 2015-09-11, Greg King ; ; void _randomize (void); ; /* Initialize the random number generator */ ; .export __randomize .import _srand .importzp time __randomize: ldx time+2 ; Use 50/60HZ clock lda time+1 jmp _srand ; Initialize generator �����������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/revers.s��������������������������������������������������������������������0000664�0000000�0000000�00000001505�13473601511�0016146�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 07.08.1998 ; ; unsigned char revers (unsigned char onoff); ; .export _revers .import RVS: zp .include "cbm610.inc" .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 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/ser/������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015244�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/ser/cbm610-std.s������������������������������������������������������������0000664�0000000�0000000�00000030727�13473601511�0017221�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Serial driver for the builtin 6551 ACIA of the Commodore 610. ; ; Ullrich von Bassewitz, 2003-12-18 ; ; The driver is based on the cc65 rs232 module, which in turn is based on ; Craig Bruce device driver for the Switftlink/Turbo-232. ; ; SwiftLink/Turbo-232 v0.90 device driver, by Craig Bruce, 14-Apr-1998. ; ; This software is Public Domain. It is in Buddy assembler format. ; ; This device driver uses the SwiftLink RS-232 Serial Cartridge, available from ; Creative Micro Designs, Inc, and also supports the extensions of the Turbo232 ; Serial Cartridge. Both devices are based on the 6551 ACIA chip. It also ; supports the "hacked" SwiftLink with a 1.8432 MHz crystal. ; ; The code assumes that the kernal + I/O are in context. On the C128, call ; it from Bank 15. On the C64, don't flip out the Kernal unless a suitable ; NMI catcher is put into the RAM under then Kernal. For the SuperCPU, the ; interrupt handling assumes that the 65816 is in 6502-emulation mode. ; .include "zeropage.inc" .include "../extzp.inc" .include "ser-kernel.inc" .include "ser-error.inc" .include "cbm610.inc" .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _cbm610_std_ser ; Driver signature .byte $73, $65, $72 ; "ser" .byte SER_API_VERSION ; Serial API version number ; Library reference .addr $0000 ; Jump table .word SER_INSTALL .word SER_UNINSTALL .word SER_OPEN .word SER_CLOSE .word SER_GET .word SER_PUT .word SER_STATUS .word SER_IOCTL .word SER_IRQ ;---------------------------------------------------------------------------- ; ; Global variables ; .bss RecvHead: .res 1 ; Head of receive buffer RecvTail: .res 1 ; Tail of receive buffer RecvFreeCnt: .res 1 ; Number of bytes in receive buffer SendHead: .res 1 ; Head of send buffer SendTail: .res 1 ; Tail of send buffer SendFreeCnt: .res 1 ; Number of bytes in send buffer Stopped: .res 1 ; Flow-stopped flag RtsOff: .res 1 ; ; Send and receive buffers: 256 bytes each RecvBuf: .res 256 SendBuf: .res 256 .rodata ; Tables used to translate RS232 params into register values BaudTable: ; bit7 = 1 means setting is invalid .byte $FF ; SER_BAUD_45_5 .byte $01 ; SER_BAUD_50 .byte $02 ; SER_BAUD_75 .byte $03 ; SER_BAUD_110 .byte $04 ; SER_BAUD_134_5 .byte $05 ; SER_BAUD_150 .byte $06 ; SER_BAUD_300 .byte $07 ; SER_BAUD_600 .byte $08 ; SER_BAUD_1200 .byte $09 ; SER_BAUD_1800 .byte $0A ; SER_BAUD_2400 .byte $0B ; SER_BAUD_3600 .byte $0C ; SER_BAUD_4800 .byte $0D ; SER_BAUD_7200 .byte $0E ; SER_BAUD_9600 .byte $0F ; SER_BAUD_19200 .byte $FF ; SER_BAUD_38400 .byte $FF ; SER_BAUD_57600 .byte $FF ; SER_BAUD_115200 .byte $FF ; SER_BAUD_230400 BitTable: .byte $60 ; SER_BITS_5 .byte $40 ; SER_BITS_6 .byte $20 ; SER_BITS_7 .byte $00 ; SER_BITS_8 StopTable: .byte $00 ; SER_STOP_1 .byte $80 ; SER_STOP_2 ParityTable: .byte $00 ; SER_PAR_NONE .byte $20 ; SER_PAR_ODD .byte $60 ; SER_PAR_EVEN .byte $A0 ; SER_PAR_MARK .byte $E0 ; SER_PAR_SPACE .code ;---------------------------------------------------------------------------- ; SER_INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present. ; Must return an SER_ERR_xx code in a/x. ; ; Since we don't have to manage the IRQ vector on the Plus/4, this is actually ; the same as: ; ; SER_UNINSTALL routine. Is called before the driver is removed from memory. ; Must return an SER_ERR_xx code in a/x. ; ; and: ; ; SER_CLOSE: Close the port, disable interrupts and flush the buffer. Called ; without parameters. Must return an error code in a/x. ; SER_INSTALL: SER_UNINSTALL: SER_CLOSE: ; Deactivate DTR and disable 6551 interrupts lda #%00001010 jsr write_cmd ; Done, return an error code lda #<SER_ERR_OK tax ; A is zero rts ;---------------------------------------------------------------------------- ; PARAMS routine. A pointer to a ser_params structure is passed in ptr1. ; Must return an SER_ERR_xx code in a/x. SER_OPEN: ; Check if the handshake setting is valid ldy #SER_PARAMS::HANDSHAKE ; Handshake lda (ptr1),y cmp #SER_HS_HW ; This is all we support bne InvParam ; Initialize buffers ldx #0 stx Stopped stx RecvHead stx RecvTail stx SendHead stx SendTail dex ; X = 255 stx RecvFreeCnt stx SendFreeCnt ; Set the value for the control register, which contains stop bits, word ; length and the baud rate. ldy #SER_PARAMS::BAUDRATE lda (ptr1),y ; Baudrate index tay lda BaudTable,y ; Get 6551 value bmi InvBaud ; Branch if rate not supported sta tmp1 ldy #SER_PARAMS::DATABITS ; Databits lda (ptr1),y tay lda BitTable,y ora tmp1 sta tmp1 ldy #SER_PARAMS::STOPBITS ; Stopbits lda (ptr1),y tay lda StopTable,y ora tmp1 ora #%00010000 ; Receiver clock source = baudrate ldy #ACIA::CTRL jsr write ; Set the value for the command register. We remember the base value in ; RtsOff, since we will have to manipulate ACIA_CMD often. ldy #SER_PARAMS::PARITY ; Parity lda (ptr1),y tay lda ParityTable,y ora #%00000001 ; DTR active sta RtsOff ora #%00001000 ; Enable receive interrupts jsr write_cmd ; Done lda #<SER_ERR_OK tax ; A is zero rts ; Invalid parameter InvParam: lda #<SER_ERR_INIT_FAILED ldx #>SER_ERR_INIT_FAILED rts ; Baud rate not available InvBaud: lda #<SER_ERR_BAUD_UNAVAIL ldx #>SER_ERR_BAUD_UNAVAIL rts ;---------------------------------------------------------------------------- ; SER_GET: Will fetch a character from the receive buffer and store it into the ; variable pointer to by ptr1. If no data is available, SER_ERR_NO_DATA is ; return. ; SER_GET: ldx SendFreeCnt ; Send data if necessary inx ; X == $FF? beq @L1 lda #$00 jsr TryToSend ; Check for buffer empty @L1: lda RecvFreeCnt cmp #$ff bne @L2 lda #<SER_ERR_NO_DATA ldx #>SER_ERR_NO_DATA rts ; Check for flow stopped & enough free: release flow control @L2: ldx Stopped beq @L3 cmp #63 bcc @L3 lda #$00 sta Stopped lda RtsOff ora #%00001000 jsr write_cmd ; Get byte from buffer @L3: ldx RecvHead lda RecvBuf,x inc RecvHead inc RecvFreeCnt ldx #$00 sta (ptr1,x) txa ; Return code = 0 rts ;---------------------------------------------------------------------------- ; SER_PUT: Output character in A. ; Must return an error code in a/x. ; SER_PUT: ; Try to send ldx SendFreeCnt inx ; X = $ff? beq @L2 pha lda #$00 jsr TryToSend pla ; Put byte into send buffer & send @L2: ldx SendFreeCnt bne @L3 lda #<SER_ERR_OVERFLOW ; X is already zero rts @L3: ldx SendTail sta SendBuf,x inc SendTail dec SendFreeCnt lda #$ff jsr TryToSend lda #<SER_ERR_OK tax rts ;---------------------------------------------------------------------------- ; SER_STATUS: Return the status in the variable pointed to by ptr1. ; Must return an error code in a/x. ; SER_STATUS: lda #$0F sta IndReg ldy #ACIA::STATUS lda (acia),y ldx #0 sta (ptr1,x) lda IndReg sta ExecReg txa ; SER_ERR_OK rts ;---------------------------------------------------------------------------- ; SER_IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl ; specific data in ptr1, and the ioctl code in A. ; Must return an error code in a/x. ; SER_IOCTL: lda #<SER_ERR_INV_IOCTL ; We don't support ioclts for now ldx #>SER_ERR_INV_IOCTL rts ;---------------------------------------------------------------------------- ; SER_IRQ: Called from the builtin runtime IRQ handler as a subroutine. All ; registers are already save, no parameters are passed, but the carry flag ; is clear on entry. The routine must return with carry set if the interrupt ; was handled, otherwise with carry clear. ; SER_IRQ: lda #$0F sta IndReg ; Switch to the system bank ldy #ACIA::STATUS lda (acia),y ; Check ACIA status for receive interrupt and #$08 beq @L9 ; Jump if no ACIA interrupt (carry still clear) ldy #ACIA::DATA lda (acia),y ; Get byte from ACIA ldx RecvFreeCnt ; Check if we have free space left beq @L1 ; Jump if no space in receive buffer ldy RecvTail ; Load buffer pointer sta RecvBuf,y ; Store received byte in buffer inc RecvTail ; Increment buffer pointer dec RecvFreeCnt ; Decrement free space counter cpx #33 ; Check for buffer space low bcs @L9 ; Assert flow control if buffer space low ; Assert flow control if buffer space too low @L1: lda RtsOff ldy #ACIA::CMD sta (acia),y sta Stopped sec ; Interrupt handled ; Done, switch back to the execution segment @L9: lda ExecReg sta IndReg rts ;---------------------------------------------------------------------------- ; Try to send a byte. Internal routine. A = TryHard .proc TryToSend sta tmp1 ; Remember tryHard flag lda #$0F sta IndReg ; Switch to the system bank @L0: lda SendFreeCnt cmp #$ff beq @L3 ; Bail out ; Check for flow stopped @L1: lda Stopped bne @L3 ; Bail out ; Check that swiftlink is ready to send @L2: ldy #ACIA::STATUS lda (acia),y and #$10 bne @L4 bit tmp1 ; Keep trying if must try hard bmi @L0 ; Switch back the bank and return @L3: lda ExecReg sta IndReg rts ; Send byte and try again @L4: ldx SendHead lda SendBuf,x ldy #ACIA::DATA sta (acia),y inc SendHead inc SendFreeCnt jmp @L0 .endproc ;---------------------------------------------------------------------------- ; Write to the ACIA changing the indirect segment. Offset is in Y, value in A. write_cmd: ldy #ACIA::CMD write: pha lda #$0F sta IndReg pla sta (acia),y lda ExecReg sta IndReg rts �����������������������������������������cc65-2.18/libsrc/cbm610/settime.s�������������������������������������������������������������������0000664�0000000�0000000�00000004175�13473601511�0016320�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2018-08-18, Oliver Schmidt ; 2018-08-19, Greg King ; ; int __fastcall__ clock_settime (clockid_t clk_id, const struct timespec *tp); ; .include "time.inc" .include "cbm610.inc" .include "extzp.inc" .importzp sreg, ptr1 .import pushax, pusheax, ldax0sp, ldeaxidx .import sys_bank, restore_bank .import tosdiveax, incsp3, return0 .import TM, load_tenth ;---------------------------------------------------------------------------- .code .proc _clock_settime jsr pushax .assert timespec::tv_sec = 0, error jsr _localtime sta ptr1 stx ptr1+1 ldy #.sizeof(tm)-1 @L1: lda (ptr1),y sta TM,y dey bpl @L1 jsr sys_bank lda TM + tm::tm_hour jsr dec2BCD tax ; Force flags bne @L2 lda #$92 ; 12 AM bne @L3 @L2: cmp #$13 ; 1 PM bcc @L3 sed sbc #$12 cld ora #%10000000 @L3: ldy #CIA::TODHR sta (cia),y lda TM + tm::tm_min jsr dec2BCD ldy #CIA::TODMIN sta (cia),y lda TM + tm::tm_sec jsr dec2BCD ldy #CIA::TODSEC sta (cia),y jsr restore_bank jsr ldax0sp ldy #3+timespec::tv_nsec jsr ldeaxidx jsr pusheax jsr load_tenth jsr tosdiveax jsr sys_bank ldy #CIA::TOD10 sta (cia),y jsr restore_bank lda #$00 tax jmp incsp3 .endproc ;---------------------------------------------------------------------------- ; Just sum up the value in BCD mode. ; http://forum.6502.org/viewtopic.php?p=7629#p7629 .proc dec2BCD tax dex bmi @L9 lda #0 clc sed @L1: adc #1 dex bpl @L1 cld @L9: rts .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/sysuname.s������������������������������������������������������������������0000664�0000000�0000000�00000001447�13473601511�0016511�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-08-12 ; ; unsigned char __fastcall__ _sysuname (struct utsname* buf); ; .export __sysuname, utsdata .import utscopy __sysuname = utscopy ;-------------------------------------------------------------------------- ; Data. We define a fixed utsname struct here and just copy it. .rodata utsdata: ; sysname .asciiz "cc65" ; nodename .asciiz "" ; release .byte ((.VERSION >> 8) & $0F) + '0' .byte '.' .byte ((.VERSION >> 4) & $0F) + '0' .byte $00 ; version .byte (.VERSION & $0F) + '0' .byte $00 ; machine .asciiz "Commodore 610" �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/cbm610/tmcommon.s������������������������������������������������������������������0000664�0000000�0000000�00000002001�13473601511�0016461�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 16.8.2018 ; ; Common stuff for the clock routines ; .include "cbm610.inc" .export TM, load_tenth .importzp sreg ;---------------------------------------------------------------------------- .code .proc load_tenth lda #<(100 * 1000 * 1000 / $10000) ldx #>(100 * 1000 * 1000 / $10000) sta sreg stx sreg+1 lda #<(100 * 1000 * 1000) ldx #>(100 * 1000 * 1000) rts .endproc ;---------------------------------------------------------------------------- ; TM struct with date set to 1970-01-01 .data TM: .word 0 ; tm_sec .word 0 ; tm_min .word 0 ; tm_hour .word 1 ; tm_mday .word 0 ; tm_mon .word 70 ; tm_year .word 0 ; tm_wday .word 0 ; tm_yday .word 0 ; tm_isdst �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/����������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014753�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/_afailed.c������������������������������������������������������������������0000664�0000000�0000000�00000000420�13473601511�0016637�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** _afailed.c ** ** 1998-06-06, Ullrich von Bassewitz ** 2015-03-13, Greg King */ #include <stdio.h> #include <stdlib.h> void __fastcall__ _afailed (char* file, unsigned line) { fprintf (stderr, "ASSERTION FAILED IN %s(%u)\n", file, line); exit (2); } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/_cwd.s����������������������������������������������������������������������0000664�0000000�0000000�00000001432�13473601511�0016053�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-08-12, 2005-04-16 ; ; Place to store the current working directory. ; ; __cwd is initialized by a platform specific function named "initcwd" called ; by the constructor defined in this module. ; .export __cwd .export __cwd_buf_size .constructor cwd_init .import initcwd .include "stdio.inc" __cwd_buf_size = FILENAME_MAX cwd_init := initcwd .segment "INIT" __cwd: .res __cwd_buf_size ; NOTE: Some of the code working with directories is not able to handle ; strings longer than 255 chars, so don't make __cwd larger than 256 without ; checking the other sources. .assert __cwd_buf_size < 256, error, "__cwd_buf_size must not be > 255" ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/_directerrno.s��������������������������������������������������������������0000664�0000000�0000000�00000001314�13473601511�0017615�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/_environ.s������������������������������������������������������������������0000664�0000000�0000000�00000001146�13473601511�0016760�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2005-04-21 ; ; extern char** _environ; ; ; ; __environ is a pointer to the environment. ; __envcount is the number of entries in the environment. ; __envsize is the size of the allocated array. ; ; The maximum number of environment entries is 64. putenv() will set errno ; to ENOMEM when trying to increase the number beyond this limit. ; .export __environ, __envcount, __envsize .import initenv .constructor env_init env_init := initenv .data __environ: .addr 0 __envcount: .byte 0 __envsize: .byte 0 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/_fdesc.s��������������������������������������������������������������������0000664�0000000�0000000�00000001557�13473601511�0016372�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 17.06.1998 ; ; int _fdesc (void); ; /* Find a free descriptor slot */ .export __fdesc .import return0 .include "stdio.inc" .include "_file.inc" .proc __fdesc ldy #0 lda #_FOPEN Loop: and __filetab + _FILE::f_flags,y ; load flags beq Found ; jump if closed .repeat .sizeof(_FILE) iny .endrepeat cpy #(FOPEN_MAX * .sizeof(_FILE)) ; Done? bne Loop ; File table is full jmp return0 ; Free slot found, get address Found: tya ; Offset clc adc #<__filetab ldx #>__filetab ; High byte bcc @L1 ; Jump if no overflow inx ; Bump high byte @L1: rts .endproc �������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/_file.h���������������������������������������������������������������������0000664�0000000�0000000�00000001422�13473601511�0016201�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** _file.h ** ** (C) Copyright 1998, 2002 Ullrich von Bassewitz (uz@cc65.org) ** */ #ifndef __FILE_H #define __FILE_H #include <stdio.h> /* Definition of struct _FILE */ struct _FILE { char f_fd; char f_flags; unsigned char f_pushback; }; /* File table. Beware: FOPEN_MAX is hardcoded in the ASM files! */ extern FILE _filetab[FOPEN_MAX]; /* Flags field */ #define _FCLOSED 0x00 #define _FOPEN 0x01 #define _FEOF 0x02 #define _FERROR 0x04 #define _FPUSHBACK 0x08 FILE* __fastcall__ _fopen (const char* name, const char* mode, FILE* f); /* Open the specified file and fill the descriptor values into f */ FILE* _fdesc (void); /* Find a free FILE descriptor */ /* End of _file.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/_file.s���������������������������������������������������������������������0000664�0000000�0000000�00000001404�13473601511�0016214�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 31.05.1998 ; ; Data for the stdio file stream. ; .export __filetab .include "stdio.inc" .include "fcntl.inc" .include "_file.inc" ;---------------------------------------------------------------------------- ; File data .data __filetab: .byte 0, _FOPEN, 0 ; stdin .byte 1, _FOPEN, 0 ; stdout .byte 2, _FOPEN, 0 ; stderr .repeat FOPEN_MAX - 3 .byte 0, _FCLOSED, 0 ; free slot .endrepeat ; Standard file descriptors _stdin: .word __filetab + (STDIN_FILENO * .sizeof(_FILE)) _stdout: .word __filetab + (STDOUT_FILENO * .sizeof(_FILE)) _stderr: .word __filetab + (STDERR_FILENO * .sizeof(_FILE)) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/_fopen.s��������������������������������������������������������������������0000664�0000000�0000000�00000005611�13473601511�0016410�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.11.2002 ; ; FILE* __fastcall__ _fopen (const char* name, const char* mode, FILE* f); ; /* Open the specified file and fill the descriptor values into f */ ; .export __fopen .import _open .import pushax, incsp4, return0 .importzp sp, ptr1 .include "errno.inc" .include "fcntl.inc" .include "_file.inc" ; ------------------------------------------------------------------------ ; Code .proc __fopen sta file stx file+1 ; Save f ; Get a pointer to the mode string ldy #1 lda (sp),y sta ptr1+1 dey lda (sp),y sta ptr1 ; Look at the first character in mode ldx #$00 ; Mode will be in X lda (ptr1),y ; Get first char from mode cmp #'w' bne @L1 ldx #(O_WRONLY | O_CREAT | O_TRUNC) bne @L3 @L1: cmp #'r' bne @L2 ldx #O_RDONLY bne @L3 @L2: cmp #'a' bne invmode ldx #(O_WRONLY | O_CREAT | O_APPEND) ; Look at more chars from the mode string @L3: iny ; Next char beq invmode lda (ptr1),y beq modeok ; End of mode string reached cmp #'+' bne @L4 txa ora #O_RDWR ; Always do r/w in addition to anything else tax bne @L3 @L4: cmp #'b' beq @L3 ; Binary mode is ignored ; Invalid mode invmode: lda #EINVAL jsr __seterrno ; Set __errno, returns zero in A tax ; a/x = 0 jmp incsp4 ; Mode string successfully parsed. Store the binary mode onto the stack in ; the same place where the mode string pointer was before. Then call open() modeok: ldy #$00 txa ; Mode -> A sta (sp),y tya iny sta (sp),y ldy #4 ; Size of arguments in bytes jsr _open ; Will cleanup the stack ; Check the result of the open() call cpx #$FF bne openok cmp #$FF bne openok jmp return0 ; Failure, errno/_oserror already set ; Open call succeeded openok: ldy file sty ptr1 ldy file+1 sty ptr1+1 ldy #_FILE::f_fd sta (ptr1),y ; file->f_fd = fd; ldy #_FILE::f_flags lda #_FOPEN sta (ptr1),y ; file->f_flags = _FOPEN; ; Return the pointer to the file structure lda ptr1 ldx ptr1+1 rts .endproc ; ------------------------------------------------------------------------ ; Data .bss file: .res 2 �����������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/_heap.s���������������������������������������������������������������������0000664�0000000�0000000�00000001457�13473601511�0016222�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 03.06.1998 ; ; Heap variables and initialization. ; .constructor initheap, 24 .import __BSS_RUN__, __BSS_SIZE__, __STACKSIZE__ .importzp sp .include "_heap.inc" .data __heaporg: .word __BSS_RUN__+__BSS_SIZE__ ; Linker calculates this symbol __heapptr: .word __BSS_RUN__+__BSS_SIZE__ ; Dito __heapend: .word __BSS_RUN__+__BSS_SIZE__ __heapfirst: .word 0 __heaplast: .word 0 ; Initialization. Will be called from startup! .segment "ONCE" initheap: sec lda sp sbc #<__STACKSIZE__ sta __heapend lda sp+1 sbc #>__STACKSIZE__ sta __heapend+1 rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/_heapadd.s������������������������������������������������������������������0000664�0000000�0000000�00000002542�13473601511�0016667�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 21.7.2000 ; ; Add a block to the heap free list ; ; void __fastcall__ _heapadd (void* mem, size_t size); ; ; .importzp ptr1, ptr2 .import popax .import heapadd .export __heapadd .include "_heap.inc" .macpack generic ;----------------------------------------------------------------------------- ; Code __heapadd: sta ptr1 ; Store size in ptr1 stx ptr1+1 jsr popax ; Get the block pointer sta ptr2 stx ptr2+1 ; Store block pointer in ptr2 ; Check if size is greater or equal than min_size. Otherwise we don't care ; about the block (this may only happen for user supplied blocks, blocks ; from the heap are always large enough to hold a freeblock structure). lda ptr1 ; Load low byte ldx ptr1+1 ; Load/check high byte bne @L1 cmp #HEAP_MIN_BLOCKSIZE bcs @L1 rts ; Block not large enough ; The block is large enough. Set the size field in the block. @L1: ldy #usedblock::size sta (ptr2),y iny txa sta (ptr2),y ; Call the internal function since variables are now setup correctly jmp heapadd ��������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/_heapblocksize.s������������������������������������������������������������0000664�0000000�0000000�00000003405�13473601511�0020123�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2004-07-17 ; ; size_t __fastcall__ _heapblocksize (const void* ptr); ; ; Return the size of an allocated block. ; .importzp ptr1, ptr2 .export __heapblocksize .include "_heap.inc" .macpack generic .macpack cpu ;----------------------------------------------------------------------------- ; Code __heapblocksize: ; Below the user data is a pointer that points to the start of the real ; (raw) memory block. The first word of this block is the size. To access ; the raw block pointer, we will decrement the high byte of the pointer, ; the pointer is then at offset 254/255. sta ptr1 dex stx ptr1+1 ldy #$FE lda (ptr1),y sta ptr2 ; Place the raw block pointer into ptr2 iny lda (ptr1),y sta ptr2+1 ; Load the size from the raw block ldy #usedblock::size+1 lda (ptr2),y tax .if (.cpu .bitand CPU_ISET_65SC02) lda (ptr2) .else dey lda (ptr2),y .endif ; Correct the raw block size so that is shows the user visible portion. To ; do that, we must decrease the size by the amount of unused memory, which is ; the difference between the user space pointer and the raw memory block ; pointer. Since we have decremented the user space pointer by 256, we will ; have to correct the result. ; ; return size - (ptr1 + 256 - ptr2) ; return size - ptr1 - 256 + ptr2 dex ; - 256 add ptr2 pha txa adc ptr2+1 tax pla sub ptr1 pha txa sbc ptr1+1 tax pla ; Done rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/_heapmaxavail.s�������������������������������������������������������������0000664�0000000�0000000�00000003152�13473601511�0017737�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-02-01 ; ; Return the size of the largest free block on the heap. ; ; size_t _heapmaxavail (void); ; ; .importzp ptr1, ptr2 .export __heapmaxavail .include "_heap.inc" .macpack generic ;----------------------------------------------------------------------------- ; Code __heapmaxavail: ; size_t Size = (_heapend - _heapptr) * sizeof (*_heapend); lda __heapend sub __heapptr sta ptr2 lda __heapend+1 sbc __heapptr+1 sta ptr2+1 ; struct freeblock* F = _heapfirst; lda __heapfirst sta ptr1 lda __heapfirst+1 @L1: sta ptr1+1 ; while (F) { ora ptr1 beq @L3 ; Jump if end of free list reached ; if (Size < F->size) { ldy #freeblock::size lda ptr2 sub (ptr1),y iny lda ptr2+1 sbc (ptr1),y bcs @L2 ; Size = F->size; ldy #freeblock::size lda (ptr1),y sta ptr2 iny lda (ptr1),y sta ptr2+1 ; F = F->next; @L2: iny ; Points to F->next lda (ptr1),y tax iny lda (ptr1),y stx ptr1 jmp @L1 ; if (Size < HEAP_ADMIN_SPACE) return 0; @L3: lda ptr2 sub #HEAP_ADMIN_SPACE ldx ptr2+1 bcs @L5 bne @L4 txa rts ; return Size - HEAP_ADMIN_SPACE; @L4: dex @L5: rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/_heapmemavail.s�������������������������������������������������������������0000664�0000000�0000000�00000002646�13473601511�0017737�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-02-01 ; ; Return the amount of free memory on the heap. ; ; size_t _heapmemavail (void); ; ; .importzp ptr1, ptr2 .export __heapmemavail .include "_heap.inc" .macpack generic ;----------------------------------------------------------------------------- ; Code __heapmemavail: ; size_t Size = 0; lda #0 sta ptr2 sta ptr2+1 ; struct freeblock* F = _heapfirst; lda __heapfirst sta ptr1 lda __heapfirst+1 @L1: sta ptr1+1 ; while (F) { ora ptr1 beq @L2 ; Jump if end of free list reached ; Size += F->size; ldy #freeblock::size lda (ptr1),y add ptr2 sta ptr2 iny lda (ptr1),y adc ptr2+1 sta ptr2+1 ; F = F->next; iny ; Points to F->next lda (ptr1),y tax iny lda (ptr1),y stx ptr1 jmp @L1 ; return Size + (_heapend - _heapptr) * sizeof (*_heapend); @L2: lda ptr2 add __heapend sta ptr2 lda ptr2+1 adc __heapend+1 tax lda ptr2 sub __heapptr sta ptr2 txa sbc __heapptr+1 tax lda ptr2 rts ������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/_hextab.c�������������������������������������������������������������������0000664�0000000�0000000�00000000461�13473601511�0016532�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** Ullrich von Bassewitz, 11.08.1998 ** ** Hex conversion table. Must be in C since the compiler will convert ** to the correct character set for the target platform. */ const unsigned char _hextab [16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/_idiv32by16r16.s������������������������������������������������������������0000664�0000000�0000000�00000001351�13473601511�0017431�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2009-11-04 ; ; CC65 library: 32by16 => 16 signed division ; .export _idiv32by16r16 .import idiv32by16r16, incsp4 .include "zeropage.inc" ;--------------------------------------------------------------------------- ; 32by16 division. .proc _idiv32by16r16 pha ; Save rhs ; Copy from stack to zeropage. This assumes ptr1 and ptr2 are adjacent. ldy #3 @L1: lda (sp),y sta ptr1,y dey bpl @L1 lda #4 clc adc sp sta sp bcc @L2 inc sp+1 @L2: pla ; Old rhs jmp idiv32by16r16 .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/_imul16x16r32.s�������������������������������������������������������������0000664�0000000�0000000�00000000726�13473601511�0017306�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2010-11-03 ; ; CC65 library: 16x16 => 32 signed multiplication ; .export _imul16x16r32 .import imul16x16r32, popax .include "zeropage.inc" ;--------------------------------------------------------------------------- ; 16x16 => 32 signed multiplication routine. .proc _imul16x16r32 sta ptr1 stx ptr1+1 jsr popax jmp imul16x16r32 .endproc ������������������������������������������cc65-2.18/libsrc/common/_imul8x8r16.s���������������������������������������������������������������0000664�0000000�0000000�00000000642�13473601511�0017147�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2014-03-27, Oliver Schmidt ; 2014-05-08, Greg King ; ; CC65 library: 8x8 => 16 signed multiplication ; .export _imul8x8r16 .import imul8x8r16, popa, ptr1:zp ;--------------------------------------------------------------------------- ; 8x8 => 16 signed multiplication routine. .proc _imul8x8r16 sta ptr1 jsr popa jmp imul8x8r16 .endproc ����������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/_longminstr.c���������������������������������������������������������������0000664�0000000�0000000�00000000531�13473601511�0017451�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** Ullrich von Bassewitz, 2012-11-26 ** ** Minimum value of a long. Is used in ascii conversions, since this value ** has no positive counterpart than can be represented in 32 bits. In C, ** since the compiler will convert to the correct character set for the ** target platform. */ const unsigned char _longminstr[] = "-2147483648"; �����������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/_mappederrno.s��������������������������������������������������������������0000664�0000000�0000000�00000002073�13473601511�0017614�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/_oserror.s������������������������������������������������������������������0000664�0000000�0000000�00000000330�13473601511�0016765�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 16.05.2000 ; ; extern unsigned char _oserror; ; /* Operating system specific errors from the low level functions */ .export __oserror .bss __oserror: .res 1 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/_poserror.c�����������������������������������������������������������������0000664�0000000�0000000�00000005621�13473601511�0017135�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* _poserror.c */ /* */ /* Output a system dependent error code */ /* */ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> #include <errno.h> void __fastcall__ _poserror (const char* msg) { /* Fetch the message that corresponds to _oserror */ const char* errormsg = _stroserror (_oserror); /* Different output depending on msg */ if (msg) { fprintf (stderr, "%s: %s\n", msg, errormsg); } else { fprintf (stderr, "%s\n", errormsg); } } ���������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/_printf.h�������������������������������������������������������������������0000664�0000000�0000000�00000001637�13473601511�0016574�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** _printf.h ** ** (C) Copyright 1998 Ullrich von Bassewitz (uz@cc65.org) ** */ #ifndef __PRINTF_H #define __PRINTF_H /* Forward */ struct outdesc; /* Type of the function that is called to output data */ typedef void __cdecl__ (* outfunc) (struct outdesc* desc, const char* buf, unsigned count); /* Control structure passed to the low level worker function. ** Beware: This function will access the structure on the assembly level, ** so check this when altering the structure. */ struct outdesc { int ccount; /* Character counter */ outfunc fout; /* Routine used to output data */ void* ptr; /* Data internal to print routine */ unsigned uns; /* Data internal to print routine */ }; /* Internal formatting routine */ void __fastcall__ _printf (struct outdesc* d, const char* format, va_list ap); /* End of _printf.h */ #endif �������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/_printf.s�������������������������������������������������������������������0000664�0000000�0000000�00000052124�13473601511�0016604�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; _printf: Basic layer for all printf type functions. ; ; Ullrich von Bassewitz, 2000-10-21 ; .include "zeropage.inc" .export __printf .import popax, pushax, pusheax, decsp6, push1, axlong, axulong .import _ltoa, _ultoa .import _strlower, _strlen .macpack generic ; ---------------------------------------------------------------------------- ; We will store variables into the register bank in the zeropage. Define ; equates for these variables. ArgList = regbank+0 ; Argument list pointer Format = regbank+2 ; Format string OutData = regbank+4 ; Function parameters ; ---------------------------------------------------------------------------- ; Other zero page cells Base = ptr1 FSave = ptr1 FCount = ptr2 .code ; ---------------------------------------------------------------------------- ; Get one character from the format string and increment the pointer. Will ; return zero in Y. GetFormatChar: ldy #0 lda (Format),y IncFormatPtr: inc Format bne @L1 inc Format+1 @L1: rts ; ---------------------------------------------------------------------------- ; Output a pad character: outfunc (d, &padchar, 1) OutputPadChar: lda PadChar ; ---------------------------------------------------------------------------- ; Call the output function with one character in A Output1: sta CharArg jsr PushOutData lda #<CharArg ldx #>CharArg jsr pushax jsr push1 jmp CallOutFunc ; fout (OutData, &CharArg, 1) ; ---------------------------------------------------------------------------- ; Decrement the argument list pointer by 2 DecArgList2: lda ArgList sub #2 sta ArgList bcs @L1 dec ArgList+1 @L1: rts ; ---------------------------------------------------------------------------- ; Get an unsigned int or long argument depending on the IsLong flag. GetUnsignedArg: lda IsLong ; Check flag bne GetLongArg ; Long sets all jsr GetIntArg ; Get an integer argument jmp axulong ; Convert to unsigned long ; ---------------------------------------------------------------------------- ; Get an signed int or long argument depending on the IsLong flag. GetSignedArg: lda IsLong ; Check flag bne GetLongArg ; Long sets all jsr GetIntArg ; Get an integer argument jmp axlong ; Convert to long ; ---------------------------------------------------------------------------- ; Get a long argument from the argument list. Returns 0 in Y. GetLongArg: jsr GetIntArg ; Get high word sta sreg stx sreg+1 ; Run into GetIntArg fetching the low word ; ---------------------------------------------------------------------------- ; Get an integer argument from the argument list. Returns 0 in Y. GetIntArg: jsr DecArgList2 ldy #1 lda (ArgList),y tax dey lda (ArgList),y rts ; ---------------------------------------------------------------------------- ; Read an integer from the format string. Will return zero in Y. ReadInt: ldy #0 sty ptr1 sty ptr1+1 ; Start with zero @Loop: lda (Format),y ; Get format string character sub #'0' ; Make number from ascii digit bcc @L9 ; Jump if done cmp #9+1 bcs @L9 ; Jump if done ; Skip the digit character jsr IncFormatPtr ; Add the digit to the value we have in ptr1 pha ; Save digit value lda ptr1 ldx ptr1+1 asl ptr1 rol ptr1+1 ; * 2 asl ptr1 rol ptr1+1 ; * 4, assume carry clear adc ptr1 sta ptr1 txa adc ptr1+1 sta ptr1+1 ; * 5 asl ptr1 rol ptr1+1 ; * 10, assume carry clear pla adc ptr1 ; Add digit value sta ptr1 bcc @Loop inc ptr1+1 bcs @Loop ; Branch always ; We're done converting @L9: lda ptr1 ldx ptr1+1 ; Load result rts ; ---------------------------------------------------------------------------- ; Put a character into the argument buffer and increment the buffer index PutBuf: ldy BufIdx inc BufIdx sta Buf,y rts ; ---------------------------------------------------------------------------- ; Get a pointer to the current buffer end and push it onto the stack PushBufPtr: lda #<Buf ldx #>Buf add BufIdx bcc @L1 inx @L1: jmp pushax ; ---------------------------------------------------------------------------- ; Push OutData onto the software stack PushOutData: lda OutData ldx OutData+1 jmp pushax ; ---------------------------------------------------------------------------- ; Output Width pad characters ; PadLoop: jsr OutputPadChar OutputPadding: inc Width bne PadLoop inc Width+1 bne PadLoop rts ; ---------------------------------------------------------------------------- ; Output the argument itself: outfunc (d, str, arglen); ; OutputArg: jsr PushOutData lda Str ldx Str+1 jsr pushax lda ArgLen ldx ArgLen+1 jsr pushax jmp CallOutFunc ; ---------------------------------------------------------------------------- ; ltoa: Wrapper for _ltoa that pushes all arguments ltoa: sty Base ; Save base jsr pusheax ; Push value jsr PushBufPtr ; Push the buffer pointer... lda Base ; Restore base jmp _ltoa ; ultoa (l, s, base); ; ---------------------------------------------------------------------------- ; ultoa: Wrapper for _ultoa that pushes all arguments ultoa: sty Base ; Save base jsr pusheax ; Push value jsr PushBufPtr ; Push the buffer pointer... lda Base ; Restore base jmp _ultoa ; ultoa (l, s, base); ; ---------------------------------------------------------------------------- ; __printf: ; Save the register bank variables into the save area pha ; Save low byte of ap ldy #5 Save: lda regbank,y sta RegSave,y dey bpl Save ; Get the parameters from the stack pla ; Restore low byte of ap sta ArgList ; Argument list pointer stx ArgList+1 jsr popax ; Format string sta Format stx Format+1 jsr popax ; Output descriptor sta OutData stx OutData+1 ; Initialize the output counter in the output descriptor to zero lda #0 tay sta (OutData),y iny sta (OutData),y ; Get the output function from the output descriptor and remember it iny lda (OutData),y sta CallOutFunc+1 iny lda (OutData),y sta CallOutFunc+2 ; Start parsing the format string MainLoop: lda Format ; Remember current format pointer sta FSave lda Format+1 sta FSave+1 ldy #0 ; Index @L1: lda (Format),y ; Get next char beq @L2 ; Jump on end of string cmp #'%' ; Format spec? beq @L2 iny ; Bump pointer bne @L1 inc Format+1 ; Bump high byte of pointer bne @L1 ; Branch always ; Found a '%' character or end of string. Update the Format pointer so it is ; current (points to this character). @L2: tya ; Low byte of offset add Format sta Format bcc @L3 inc Format+1 ; Calculate, how many characters must be output. Beware: This number may ; be zero. A still contains the low byte of the pointer. @L3: sub FSave sta FCount lda Format+1 sbc FSave+1 sta FCount+1 ora FCount ; Is the result zero? beq @L4 ; Jump if yes ; Output the characters that we have until now. To make the call to out ; faster, build the stack frame by hand (don't use pushax) jsr decsp6 ; 3 args ldy #5 lda OutData+1 sta (sp),y dey lda OutData sta (sp),y dey lda FSave+1 sta (sp),y dey lda FSave sta (sp),y dey lda FCount+1 sta (sp),y dey lda FCount sta (sp),y jsr CallOutFunc ; Call the output function ; We're back from out(), or we didn't call it. Check for end of string. @L4: jsr GetFormatChar ; Get one char, zero in Y tax ; End of format string reached? bne NotDone ; End not reached ; End of format string reached. Restore the zeropage registers and return. ldx #5 Rest: lda RegSave,x sta regbank,x dex bpl Rest rts ; Still a valid format character. Check for '%' and a '%%' sequence. Output ; anything that is not a format specifier. On intro, Y is zero. NotDone: cmp #'%' bne @L1 lda (Format),y ; Check for "%%" cmp #'%' bne FormatSpec ; Jump if really a format specifier jsr IncFormatPtr ; Skip the second '%' @L1: jsr Output1 ; Output the character... jmp MainLoop ; ...and continue ; We have a real format specifier ; Format is: %[flags][width][.precision][mod]type ; Y is zero on entry. FormatSpec: ; Initialize the flags lda #0 ldx #FormatVarSize-1 @L1: sta FormatVars,x dex bpl @L1 ; Start with reading the flags if there are any. X is $FF which is used ; for "true" ReadFlags: lda (Format),y ; Get next char... cmp #'-' bne @L1 stx LeftJust beq @L4 @L1: cmp #'+' bne @L2 stx AddSign beq @L4 @L2: cmp #' ' bne @L3 stx AddBlank beq @L4 @L3: cmp #'#' bne ReadPadding stx AltForm @L4: jsr IncFormatPtr jmp ReadFlags ; ...and start over ; Done with flags, read the pad char. Y is still zero if we come here. ReadPadding: ldx #' ' ; PadChar cmp #'0' bne @L1 tax ; PadChar is '0' jsr IncFormatPtr lda (Format),y ; Read current for later @L1: stx PadChar ; Read the width. Even here, Y is still zero. A contains the current character ; from the format string ReadWidth: cmp #'*' bne @L1 jsr IncFormatPtr jsr GetIntArg ; Width is an additional argument jmp @L2 @L1: jsr ReadInt ; Read integer from format string... @L2: sta Width stx Width+1 ; ...and remember in Width ; Read the precision. Even here, Y is still zero. sty Prec ; Assume Precision is zero sty Prec+1 lda (Format),y ; Load next format string char cmp #'.' ; Precision given? bne ReadMod ; Branch if no precision given ReadPrec: jsr IncFormatPtr ; Skip the '.' lda (Format),y cmp #'*' ; Variable precision? bne @L1 jsr IncFormatPtr ; Skip the '*' jsr GetIntArg ; Get integer argument jmp @L2 @L1: jsr ReadInt ; Read integer from format string @L2: sta Prec stx Prec+1 ; Read the modifiers. Y is still zero. ReadMod: lda (Format),y cmp #'z' ; size_t - same as unsigned beq @L2 cmp #'h' ; short - same as int beq @L2 cmp #'t' ; ptrdiff_t - same as int beq @L2 cmp #'j' ; intmax_t/uintmax_t - same as long beq @L1 cmp #'L' ; long double beq @L1 cmp #'l' ; long int bne DoFormat @L1: lda #$FF sta IsLong @L2: jsr IncFormatPtr jmp ReadMod ; Initialize the argument buffer pointers. We use a static buffer (ArgBuf) to ; assemble strings. A zero page index (BufIdx) is used to keep the current ; write position. A pointer to the buffer (Str) is used to point to the the ; argument in case we will not use the buffer but a user supplied string. ; Y is zero when we come here. DoFormat: sty BufIdx ; Clear BufIdx ldx #<Buf stx Str ldx #>Buf stx Str+1 ; Skip the current format character, then check it (current char in A) jsr IncFormatPtr ; Is it a character? cmp #'c' bne CheckInt ; It is a character jsr GetIntArg ; Get the argument (promoted to int) sta Buf ; Place it as zero terminated string... lda #0 sta Buf+1 ; ...into the buffer jmp HaveArg ; Done ; Is it an integer? CheckInt: cmp #'d' beq @L1 cmp #'i' bne CheckCount ; It is an integer @L1: ldx #0 lda AddBlank ; Add a blank for positives? beq @L2 ; Jump if no ldx #' ' @L2: lda AddSign ; Add a plus for positives (precedence)? beq @L3 ldx #'+' @L3: stx Leader ; Integer argument jsr GetSignedArg ; Get argument as a long ldy sreg+1 ; Check sign bmi @Int1 ldy Leader beq @Int1 sty Buf inc BufIdx @Int1: ldy #10 ; Base jsr ltoa ; Push arguments, call _ltoa jmp HaveArg ; Is it a count pseudo format? CheckCount: cmp #'n' bne CheckOctal ; It is a count pseudo argument jsr GetIntArg sta ptr1 stx ptr1+1 ; Get user supplied pointer ldy #0 lda (OutData),y ; Low byte of OutData->ccount sta (ptr1),y iny lda (OutData),y ; High byte of OutData->ccount sta (ptr1),y jmp MainLoop ; Done ; Check for an octal digit CheckOctal: cmp #'o' bne CheckPointer ; Integer in octal representation jsr GetSignedArg ; Get argument as a long ldy AltForm ; Alternative form? beq @Oct1 ; Jump if no pha ; Save low byte of value stx tmp1 ora tmp1 ora sreg ora sreg+1 ora Prec ora Prec+1 ; Check if value or Prec != 0 beq @Oct1 lda #'0' jsr PutBuf pla ; Restore low byte @Oct1: ldy #8 ; Load base jsr ltoa ; Push arguments, call _ltoa jmp HaveArg ; Check for a pointer specifier (%p) CheckPointer: cmp #'p' bne CheckString ; It's a pointer. Use %#x conversion ldx #0 stx IsLong ; IsLong = 0; inx stx AltForm ; AltForm = 1; lda #'x' bne IsHex ; Branch always ; Check for a string specifier (%s) CheckString: cmp #'s' bne CheckUnsigned ; It's a string jsr GetIntArg ; Get 16bit argument sta Str stx Str+1 jmp HaveArg ; Check for an unsigned integer (%u) CheckUnsigned: cmp #'u' bne CheckHex ; It's an unsigned integer jsr GetUnsignedArg ; Get argument as unsigned long ldy #10 ; Load base jsr ultoa ; Push arguments, call _ultoa jmp HaveArg ; Check for a hexadecimal integer (%x) CheckHex: cmp #'x' beq IsHex cmp #'X' bne UnknownFormat ; Hexadecimal integer IsHex: pha ; Save the format spec lda AltForm beq @L1 lda #'0' jsr PutBuf lda #'X' jsr PutBuf @L1: jsr GetUnsignedArg ; Get argument as an unsigned long ldy #16 ; Load base jsr ultoa ; Push arguments, call _ultoa pla ; Get the format spec cmp #'x' ; Lower case? bne @L2 lda Str ldx Str+1 jsr _strlower ; Make characters lower case @L2: jmp HaveArg ; Unknown format character, skip it UnknownFormat: jmp MainLoop ; We have the argument, do argument string formatting HaveArg: ; ArgLen = strlen (Str); lda Str ldx Str+1 jsr _strlen ; Get length of argument sta ArgLen stx ArgLen+1 ; if (Prec && Prec < ArgLen) ArgLen = Prec; lda Prec ora Prec+1 beq @L1 ldx Prec cpx ArgLen lda Prec+1 tay sbc ArgLen+1 bcs @L1 stx ArgLen sty ArgLen+1 ; if (Width > ArgLen) { ; Width -= ArgLen; /* padcount */ ; } else { ; Width = 0; ; } ; Since width is used as a counter below, calculate -(width+1) @L1: sec lda Width sbc ArgLen tax lda Width+1 sbc ArgLen+1 bcs @L2 lda #0 tax @L2: eor #$FF sta Width+1 txa eor #$FF sta Width ; /* Do padding on the left side if needed */ ; if (!leftjust) { ; /* argument right justified */ ; while (width) { ; fout (d, &padchar, 1); ; --width; ; } ; } lda LeftJust bne @L3 jsr OutputPadding ; Output the argument itself @L3: jsr OutputArg ; /* Output right padding bytes if needed */ ; if (leftjust) { ; /* argument left justified */ ; while (width) { ; fout (d, &padchar, 1); ; --width; ; } ; } lda LeftJust beq @L4 jsr OutputPadding ; Done, parse next chars from format string @L4: jmp MainLoop ; ---------------------------------------------------------------------------- ; Local data (all static) .bss ; Save area for the zero page registers RegSave: .res regbanksize ; One character argument for OutFunc CharArg: .byte 0 ; Format variables FormatVars: LeftJust: .byte 0 AddSign: .byte 0 AddBlank: .byte 0 AltForm: .byte 0 PadChar: .byte 0 Width: .word 0 Prec: .word 0 IsLong: .byte 0 Leader: .byte 0 BufIdx: .byte 0 ; Argument string pointer FormatVarSize = * - FormatVars ; Argument buffer and pointer Buf: .res 20 Str: .word 0 ArgLen: .res 2 .data ; Stuff from OutData. Is used as a vector and must be aligned CallOutFunc: jmp $0000 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/_scanf.c��������������������������������������������������������������������0000664�0000000�0000000�00000065171�13473601511�0016362�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** _scanf.c ** ** (c) Copyright 2001-2005, Ullrich von Bassewitz <uz@cc65.org> ** 2014-09-10, Greg King <greg.king5@verizon.net> ** ** This is the basic layer for all scanf-type functions. It should be ** rewritten in assembly, at some time in the future. So, some of the code ** is not as elegant as it could be. */ #include <stddef.h> #include <stdarg.h> #include <stdbool.h> #include <stdio.h> #include <string.h> #include <setjmp.h> #include <limits.h> #include <errno.h> #include <ctype.h> /* _scanf() can give EOF to these functions. But, the macroes can't ** understand it; so, they are removed. */ #undef isspace #undef isxdigit #include "_scanf.h" #pragma static-locals(on) /*****************************************************************************/ /* SetJmp return codes */ /*****************************************************************************/ enum { RC_OK, /* setjmp() call */ RC_NOCONV, /* No conversion possible */ RC_EOF /* EOF reached */ }; /*****************************************************************************/ /* Data */ /*****************************************************************************/ static const char* format; /* Copy of function argument */ static const struct scanfdata* D_; /* Copy of function argument */ static va_list ap; /* Copy of function argument */ static jmp_buf JumpBuf; /* "Label" that is used for failures */ static char F; /* Character from format string */ static unsigned CharCount; /* Characters read so far */ static int C; /* Character from input */ static unsigned Width; /* Maximum field width */ static long IntVal; /* Converted int value */ static int Assignments; /* Number of assignments */ static unsigned char IntBytes; /* Number of bytes-1 for int conversions */ /* Flags */ static bool Converted; /* Some object was converted */ static bool Positive; /* Flag for positive value */ static bool NoAssign; /* Suppress assignment */ static bool Invert; /* Do we need to invert the charset? */ static unsigned char CharSet[(1+UCHAR_MAX)/CHAR_BIT]; static const unsigned char Bits[CHAR_BIT] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; /* We need C to be 16 bits since we cannot check for EOF otherwise. ** Unfortunately, this causes the code to be quite larger, even if for most ** purposes, checking the low byte would be enough, since if C is EOF, the ** low byte will not match any useful character anyway (at least for the ** supported platforms - I know that this is not portable). So the following ** macro is used to access just the low byte of C. */ #define CHAR(c) (*((unsigned char*)&(c))) /*****************************************************************************/ /* Character sets */ /*****************************************************************************/ /* We don't want the optimizer to ruin our "perfect" ;-) ** assembly code! */ #pragma optimize (push, off) static unsigned FindBit (void) /* Locate the character's bit in the charset array. ** < .A - Argument character ** > .X - Offset of the byte in the character-set mask ** > .A - Bit-mask */ { asm ("pha"); asm ("lsr a"); /* Divide by CHAR_BIT */ asm ("lsr a"); asm ("lsr a"); asm ("tax"); /* Byte's offset */ asm ("pla"); asm ("and #%b", CHAR_BIT-1); asm ("tay"); /* Bit's offset */ asm ("lda %v,y", Bits); return (unsigned) __AX__; } #pragma optimize (pop) static void __fastcall__ AddCharToSet (unsigned char /* C */) /* Set the given bit in the character set */ { FindBit(); asm ("ora %v,x", CharSet); asm ("sta %v,x", CharSet); } #pragma optimize (push, off) static unsigned char IsCharInSet (void) /* Check if the char. is part of the character set. */ { /* Get the character from C. */ asm ("lda #$00"); asm ("ldx %v+1", C); asm ("bne L1"); /* EOF never is in the set */ asm ("lda %v", C); FindBit(); asm ("and %v,x", CharSet); asm ("L1:"); asm ("ldx #$00"); return (unsigned char) __AX__; } #pragma optimize (pop) static void InvertCharSet (void) /* Invert the character set */ { asm ("ldy #%b", sizeof (CharSet) - 1); asm ("L1:"); asm ("lda %v,y", CharSet); asm ("eor #$FF"); asm ("sta %v,y", CharSet); asm ("dey"); asm ("bpl L1"); } /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void PushBack (void) /* Push back the last (unused) character, provided it is not EOF. */ { /* Get the character from C. */ /* Only the high-byte needs to be checked for EOF. */ asm ("ldx %v+1", C); asm ("bne %g", Done); asm ("lda %v", C); /* Put unget()'s first argument on the stack. */ asm ("jsr pushax"); /* Copy D into the zero-page. */ (const struct scanfdata*) __AX__ = D_; asm ("sta ptr1"); asm ("stx ptr1+1"); /* Copy the unget vector to jmpvec. */ asm ("ldy #%b", offsetof (struct scanfdata, unget)); asm ("lda (ptr1),y"); asm ("sta jmpvec+1"); asm ("iny"); asm ("lda (ptr1),y"); asm ("sta jmpvec+2"); /* Load D->data into __AX__. */ asm ("ldy #%b", offsetof (struct scanfdata, data) + 1); asm ("lda (ptr1),y"); asm ("tax"); asm ("dey"); asm ("lda (ptr1),y"); /* Call the unget routine. */ asm ("jsr jmpvec"); /* Take back that character's count. */ asm ("lda %v", CharCount); asm ("bne %g", Yank); asm ("dec %v+1", CharCount); Yank: asm ("dec %v", CharCount); Done: ; } static void ReadChar (void) /* Get an input character, count characters */ { /* Move D to ptr1 */ asm ("lda %v", D_); asm ("ldx %v+1", D_); asm ("sta ptr1"); asm ("stx ptr1+1"); /* Copy the get vector to jmpvec */ asm ("ldy #%b", offsetof (struct scanfdata, get)); asm ("lda (ptr1),y"); asm ("sta jmpvec+1"); asm ("iny"); asm ("lda (ptr1),y"); asm ("sta jmpvec+2"); /* Load D->data into __AX__ */ asm ("ldy #%b", offsetof (struct scanfdata, data) + 1); asm ("lda (ptr1),y"); asm ("tax"); asm ("dey"); asm ("lda (ptr1),y"); /* Call the get routine */ asm ("jsr jmpvec"); /* Assign the result to C */ asm ("sta %v", C); asm ("stx %v+1", C); /* If C is EOF, don't bump the character counter. ** Only the high-byte needs to be checked. */ asm ("inx"); asm ("beq %g", Done); /* Must bump CharCount. */ asm ("inc %v", CharCount); asm ("bne %g", Done); asm ("inc %v+1", CharCount); Done: ; } #pragma optimize (push, off) static void __fastcall__ Error (unsigned char /* Code */) /* Does a longjmp using the given code */ { asm ("pha"); (char*) __AX__ = JumpBuf; asm ("jsr pushax"); asm ("pla"); asm ("ldx #>$0000"); asm ("jmp %v", longjmp); } #pragma optimize (pop) static void CheckEnd (void) /* Stop a scan if it prematurely reaches the end of a string or a file. */ { /* Only the high-byte needs to be checked for EOF. */ asm ("ldx %v+1", C); asm ("beq %g", Done); Error (RC_EOF); Done: ; } static void SkipWhite (void) /* Skip white space in the input and return the first non white character */ { while ((bool) isspace (C)) { ReadChar (); } } #pragma optimize (push, off) static void ReadSign (void) /* Read an optional sign and skip it. Store 1 in Positive if the value is ** positive, store 0 otherwise. */ { /* We can ignore the high byte of C here, since if it is EOF, the lower ** byte won't match anyway. */ asm ("lda %v", C); asm ("cmp #'-'"); asm ("bne %g", NotNeg); /* Negative value */ asm ("sta %v", Converted); asm ("jsr %v", ReadChar); asm ("lda #$00"); /* Flag as negative */ asm ("beq %g", Store); /* Positive value */ NotNeg: asm ("cmp #'+'"); asm ("bne %g", Pos); asm ("sta %v", Converted); asm ("jsr %v", ReadChar); /* Skip the + sign */ Pos: asm ("lda #$01"); /* Flag as positive */ Store: asm ("sta %v", Positive); } #pragma optimize (pop) static unsigned char __fastcall__ HexVal (char C) /* Convert a digit to a value */ { return (bool) isdigit (C) ? C - '0' : (char) tolower ((int) C) - ('a' - 10); } static void __fastcall__ ReadInt (unsigned char Base) /* Read an integer, and store it into IntVal. */ { unsigned char Val, CharCount = 0; /* Read the integer value */ IntVal = 0L; while ((bool) isxdigit (C) && ++Width != 0 && (Val = HexVal ((char) C)) < Base) { ++CharCount; IntVal = IntVal * (long) Base + (long) Val; ReadChar (); } /* If we didn't convert anything, it's a failure. */ if (CharCount == 0) { Error (RC_NOCONV); } /* Another conversion */ Converted = true; } static void AssignInt (void) /* Assign the integer value in Val to the next argument. The function makes ** several non-portable assumptions, to reduce code size: ** - signed and unsigned types have the same representation. ** - short and int have the same representation. ** - all pointer types have the same representation. */ { if (NoAssign == false) { /* Get the next argument pointer */ (void*) __AX__ = va_arg (ap, void*); /* Put the argument pointer into the zero-page. */ asm ("sta ptr1"); asm ("stx ptr1+1"); /* Get the number of bytes-1 to copy */ asm ("ldy %v", IntBytes); /* Assign the integer value */ Loop: asm ("lda %v,y", IntVal); asm ("sta (ptr1),y"); asm ("dey"); asm ("bpl %g", Loop); /* Another assignment */ asm ("inc %v", Assignments); asm ("bne %g", Done); asm ("inc %v+1", Assignments); Done: ; } } static void __fastcall__ ScanInt (unsigned char Base) /* Scan an integer including white space, sign and optional base spec, ** and store it into IntVal. */ { /* Skip whitespace */ SkipWhite (); /* Read an optional sign */ ReadSign (); /* If Base is unknown (zero), figure it out */ if (Base == 0) { if (CHAR (C) == '0') { ReadChar (); switch (CHAR (C)) { case 'x': case 'X': Base = 16; Converted = true; ReadChar (); break; default: Base = 8; /* Restart at the beginning of the number because it might ** be only a single zero digit (which already was read). */ PushBack (); C = '0'; } } else { Base = 10; } } /* Read the integer value */ ReadInt (Base); /* Apply the sign */ if (Positive == false) { IntVal = -IntVal; } /* Assign the value to the next argument unless suppressed */ AssignInt (); } static char GetFormat (void) /* Pick up the next character from the format string. */ { /* return (F = *format++); */ (const char*) __AX__ = format; asm ("sta regsave"); asm ("stx regsave+1"); ++format; asm ("ldy #0"); asm ("lda (regsave),y"); asm ("ldx #>$0000"); return (F = (char) __AX__); } int __fastcall__ _scanf (const struct scanfdata* D, const char* format_, va_list ap_) /* This is the routine used to do the actual work. It is called from several ** types of wrappers to implement the actual ISO xxscanf functions. */ { register char* S; bool HaveWidth; /* True if a width was given */ bool Match; /* True if a character-set has any matches */ char Start; /* Walks over a range */ /* Place copies of the arguments into global variables. This is not very ** nice, but on a 6502 platform it gives better code, since the values ** do not have to be passed as parameters. */ D_ = D; format = format_; ap = ap_; /* Initialize variables */ Converted = false; Assignments = 0; CharCount = 0; /* Set up the jump "label". CheckEnd() will use that label when EOF ** is reached. ReadInt() will use it when number-conversion fails. */ if ((unsigned char) setjmp (JumpBuf) == RC_OK) { Again: /* Get the next input character */ ReadChar (); /* Walk over the format string */ while (GetFormat ()) { /* Check for a conversion */ if (F != '%') { /* Check for a match */ if ((bool) isspace ((int) F)) { /* Special white space handling: Any whitespace in the ** format string matches any amount of whitespace including ** none(!). So this match will never fail. */ SkipWhite (); continue; } Percent: /* ### Note: The opposite test (C == F) ** would be optimized into buggy code! */ if (C != (int) F) { /* A mismatch -- we will stop scanning the input, ** and return the number of assigned conversions. */ goto NoConv; } /* A match -- get the next input character, and continue. */ goto Again; } else { /* A conversion. Skip the percent sign. */ /* 0. Check for %% */ if (GetFormat () == '%') { goto Percent; } /* 1. Assignment suppression */ NoAssign = (F == '*'); if (NoAssign) { GetFormat (); } /* 2. Maximum field width */ Width = UINT_MAX; HaveWidth = (bool) isdigit (F); if (HaveWidth) { Width = 0; do { /* ### Non portable ### */ Width = Width * 10 + (F & 0x0F); } while ((bool) isdigit (GetFormat ())); } if (Width == 0) { /* Invalid specification */ /* Note: This method of leaving the function might seem ** to be crude, but it optimizes very well because ** the four exits can share this code. */ _seterrno (EINVAL); Assignments = EOF; PushBack (); return Assignments; } /* Increment-and-test makes better code than test-and-decrement ** does. So, change the width into a form that can be used in ** that way. */ Width = ~Width; /* 3. Length modifier */ IntBytes = sizeof(int) - 1; switch (F) { case 'h': if (*format == 'h') { IntBytes = sizeof(char) - 1; ++format; } GetFormat (); break; case 'l': if (*format == 'l') { /* Treat long long as long */ ++format; } /* FALLTHROUGH */ case 'j': /* intmax_t */ IntBytes = sizeof(long) - 1; /* FALLTHROUGH */ case 'z': /* size_t */ case 't': /* ptrdiff_t */ /* Same size as int */ case 'L': /* long double - ignore this one */ GetFormat (); } /* 4. Conversion specifier */ switch (F) { /* 'd' and 'u' conversions are actually the same, since the ** standard says that even the 'u' modifier allows an ** optionally signed integer. */ case 'd': /* Optionally signed decimal integer */ case 'u': ScanInt (10); break; case 'i': /* Optionally signed integer with a base */ ScanInt (0); break; case 'o': /* Optionally signed octal integer */ ScanInt (8); break; case 'x': case 'X': /* Optionally signed hexadecimal integer */ ScanInt (16); break; case 's': /* Whitespace-terminated string */ SkipWhite (); CheckEnd (); /* Is it an input failure? */ Converted = true; /* No, conversion will succeed */ if (NoAssign == false) { S = va_arg (ap, char*); } while (C != EOF && (bool) isspace (C) == false && ++Width) { if (NoAssign == false) { *S++ = C; } ReadChar (); } /* Terminate the string just read */ if (NoAssign == false) { *S = '\0'; ++Assignments; } break; case 'c': /* Fixed-length string, NOT zero-terminated */ if (HaveWidth == false) { /* No width given, default is 1 */ Width = ~1u; } CheckEnd (); /* Is it an input failure? */ Converted = true; /* No, at least 1 char. available */ if (NoAssign == false) { S = va_arg (ap, char*); /* ## This loop is convenient for us, but it isn't ** standard C. The standard implies that a failure ** shouldn't put anything into the array argument. */ while (++Width) { CheckEnd (); /* Is it a matching failure? */ *S++ = C; ReadChar (); } ++Assignments; } else { /* Just skip as many chars as given */ while (++Width) { CheckEnd (); /* Is it a matching failure? */ ReadChar (); } } break; case '[': /* String using characters from a set */ /* Clear the set */ memset (CharSet, 0, sizeof (CharSet)); /* Skip the left-bracket, and test for inversion. */ Invert = (GetFormat () == '^'); if (Invert) { GetFormat (); } if (F == ']') { /* Empty sets aren't allowed; so, a right-bracket ** at the beginning must be a member of the set. */ AddCharToSet (F); GetFormat (); } /* Read the characters that are part of the set */ while (F != '\0' && F != ']') { if (*format == '-') { /* Look ahead at next char. */ /* A range. Get start and end, skip the '-' */ Start = F; ++format; switch (GetFormat ()) { case '\0': case ']': /* '-' as last char means: include '-' */ AddCharToSet (Start); AddCharToSet ('-'); break; default: /* Include all characters ** that are in the range. */ while (1) { AddCharToSet (Start); if (Start == F) { break; } ++Start; } /* Get next char after range */ GetFormat (); } } else { /* Just a character */ AddCharToSet (F); /* Get next char */ GetFormat (); } } /* Don't go beyond the end of the format string. */ /* (Maybe, this should mean an invalid specification.) */ if (F == '\0') { --format; } /* Invert the set if requested */ if (Invert) { InvertCharSet (); } /* We have the set in CharSet. Read characters and ** store them into a string while they are part of ** the set. */ Match = false; if (NoAssign == false) { S = va_arg (ap, char*); } while (IsCharInSet () && ++Width) { if (NoAssign == false) { *S++ = C; } Match = Converted = true; ReadChar (); } /* At least one character must match the set. */ if (Match == false) { goto NoConv; } if (NoAssign == false) { *S = '\0'; ++Assignments; } break; case 'p': /* Pointer, general format is 0xABCD. ** %hhp --> zero-page pointer ** %hp --> near pointer ** %lp --> far pointer */ SkipWhite (); if (CHAR (C) != '0') { goto NoConv; } Converted = true; ReadChar (); switch (CHAR (C)) { case 'x': case 'X': break; default: goto NoConv; } ReadChar (); ReadInt (16); AssignInt (); break; case 'n': /* Store the number of characters consumed so far ** (the read-ahead character hasn't been consumed). */ IntVal = (long) (CharCount - (C == EOF ? 0u : 1u)); AssignInt (); /* Don't count it. */ if (NoAssign == false) { --Assignments; } break; case 'S': case 'C': /* Wide characters */ case 'a': case 'A': case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': /* Optionally signed float */ /* Those 2 groups aren't implemented. */ _seterrno (ENOSYS); Assignments = EOF; PushBack (); return Assignments; default: /* Invalid specification */ _seterrno (EINVAL); Assignments = EOF; PushBack (); return Assignments; } } } } else { NoConv: /* Coming here means a failure. If that happens at EOF, with no ** conversion attempts, then it is considered an error; otherwise, ** the number of assignments is returned (the default behaviour). */ if (C == EOF && Converted == false) { Assignments = EOF; /* Special case: error */ } } /* Put the read-ahead character back into the input stream. */ PushBack (); /* Return the number of conversion-and-assignments. */ return Assignments; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/_scanf.h��������������������������������������������������������������������0000664�0000000�0000000�00000001722�13473601511�0016357�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** _scanf.h ** ** (c) Copyright 2004, Ullrich von Bassewitz <uz@cc65.org> ** */ #ifndef __SCANF_H #define __SCANF_H /* Type of the function that is called to input data. The function will ** return EOF if no more data is available. */ typedef int __fastcall__ (*getfunc) (void* data); /* Type of the function that is called to put back unused data */ typedef int __fastcall__ (*ungetfunc) (int c, void* data); /* Control structure passed to the low level worker function. ** Beware: This structure is mirrored in the _scanf.inc assembler include ** file, so check this when altering the structure. */ struct scanfdata { getfunc get; /* Pointer to input routine */ ungetfunc unget; /* Pointer to pushback routine */ void* data; /* Pointer to struct. used outside of _scanf() */ }; /* Internal scanning routine */ int __fastcall__ _scanf (const struct scanfdata* d, const char* format, va_list ap); /* End of _scanf.h */ #endif ����������������������������������������������cc65-2.18/libsrc/common/_scanf.inc������������������������������������������������������������������0000664�0000000�0000000�00000000546�13473601511�0016704�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2004-11-27 ; ;---------------------------------------------------------------------------- ; Structure passed to _scanf .struct SCANFDATA GET .addr UNGET .addr DATA .addr .endstruct ;---------------------------------------------------------------------------- ; Global data .global __scanf ����������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/_seterrno.s�����������������������������������������������������������������0000664�0000000�0000000�00000000621�13473601511�0017136�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2004-05-13 ; ; __seterrno: Will set __errno to the value in A and return zero in A. Other ; registers aren't changed. The function is C callable, but ; currently only called from asm code. ; .include "errno.inc" .code .proc __seterrno sta __errno lda #0 sta __errno+1 rts .endproc ���������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/_swap.s���������������������������������������������������������������������0000664�0000000�0000000�00000002027�13473601511�0016251�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 1998-12-09, 2004-11-30 ; ; void __fastcall__ _swap (void* p, void* q, size_t size); ; .export __swap .import popax, popptr1 .importzp ptr1, ptr2, ptr3 __swap: eor #$FF sta ptr3 txa eor #$FF sta ptr3+1 ; Save -(size+1) into ptr3 jsr popax ; Get q sta ptr2 stx ptr2+1 jsr popptr1 ; Get p ; Prepare for swap ; ldy #$00 is guaranteed by popptr1 ; Swap loop @L1: inc ptr3 ; Bump counter low byte beq @L3 ; Branch on overflow @L2: lda (ptr1),y tax lda (ptr2),y sta (ptr1),y txa sta (ptr2),y iny bne @L1 inc ptr1+1 inc ptr2+1 bne @L1 ; Branch always (hopefully) ; Bump the high counter byte @L3: inc ptr3+1 bne @L2 ; Done rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/_sys.s����������������������������������������������������������������������0000664�0000000�0000000�00000003054�13473601511�0016116�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; void __fastcall__ _sys (struct regs* r); ; ; Ullrich von Bassewitz, 16.12.1998 ; .export __sys .import jmpvec .importzp ptr1 __sys: sta ptr1 stx ptr1+1 ; Save the pointer to r ; Fetch the PC and store it into the jump vector ldy #5 lda (ptr1),y sta jmpvec+2 dey lda (ptr1),y sta jmpvec+1 ; Remember the flags so we can restore them to a known state after calling the ; routine php ; Get the flags, keep the state of bit 4 and 5 using the other flags from ; the flags value passed by the caller. Push the new flags and push A. dey php pla ; Current flags -> A eor (ptr1),y and #%00110000 eor (ptr1),y pha ; Push new flags value ldy #0 lda (ptr1),y pha ; Get and assign X and Y iny lda (ptr1),y tax iny lda (ptr1),y tay ; Set a and the flags, call the machine code routine pla plp jsr jmpvec ; Back from the routine. Save the flags and A. php pha ; Put the register values into the regs structure tya ldy #2 sta (ptr1),y dey txa sta (ptr1),y dey pla sta (ptr1),y ldy #3 pla sta (ptr1),y ; Restore the old flags value plp ; Done rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/_udiv32by16r16.s������������������������������������������������������������0000664�0000000�0000000�00000001341�13473601511�0017444�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2009-11-04 ; ; CC65 library: 32by16 => 16 unsigned division ; .export _udiv32by16r16 .import udiv32by16r16m, incsp4 .include "zeropage.inc" ;--------------------------------------------------------------------------- ; 32by16 division. .proc _udiv32by16r16 sta ptr3 stx ptr3+1 ; Store rhs ; Copy from stack to zeropage. This assumes ptr1 and ptr2 are adjacent. ldy #3 @L1: lda (sp),y sta ptr1,y dey bpl @L1 lda #4 clc adc sp sta sp bcc @L2 inc sp+1 @L2: jmp udiv32by16r16m .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/_umul16x16r32.s�������������������������������������������������������������0000664�0000000�0000000�00000000732�13473601511�0017317�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2010-11-03 ; ; CC65 library: 16x16 => 32 unsigned multiplication ; .export _umul16x16r32 .import umul16x16r32, popax .include "zeropage.inc" ;--------------------------------------------------------------------------- ; 16x16 => 32 unsigned multiplication routine. .proc _umul16x16r32 sta ptr1 stx ptr1+1 jsr popax jmp umul16x16r32 .endproc ��������������������������������������cc65-2.18/libsrc/common/_umul16x8r32.s��������������������������������������������������������������0000664�0000000�0000000�00000001116�13473601511�0017235�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2011-07-10 ; ; CC65 library: 16x8 => 32 unsigned multiplication ; .export _umul16x8r32 .import umul8x16r24, popax .include "zeropage.inc" ;--------------------------------------------------------------------------- ; 16x8 => 32 unsigned multiplication routine. We use 8x16 => 24 and clear ; the high byte of the result .proc _umul16x8r32 sta ptr1 lda #0 sta sreg+1 ; Clear high byte of result jsr popax jmp umul8x16r24 .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/_umul8x8r16.s���������������������������������������������������������������0000664�0000000�0000000�00000000616�13473601511�0017164�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2014-03-27 ; ; CC65 library: 8x8 => 16 unsigned multiplication ; .export _umul8x8r16 .import umul8x8r16, popa, ptr1:zp ;--------------------------------------------------------------------------- ; 8x8 => 16 unsigned multiplication routine. .proc _umul8x8r16 sta ptr1 jsr popa jmp umul8x8r16 .endproc ������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/abort.c���������������������������������������������������������������������0000664�0000000�0000000�00000000355�13473601511�0016231�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** abort.c ** ** Ullrich von Bassewitz, 02.06.1998 */ #include <stdio.h> #include <stdlib.h> #include <signal.h> void abort (void) { raise (SIGABRT); fputs ("ABNORMAL PROGRAM TERMINATION\n", stderr); exit (3); } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/asctime.c�������������������������������������������������������������������0000664�0000000�0000000�00000005755�13473601511�0016560�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* asctime.c */ /* */ /* Convert a broken down time into a string */ /* */ /* */ /* */ /* (C) 2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <time.h> /*****************************************************************************/ /* Code */ /*****************************************************************************/ char* __fastcall__ asctime (const struct tm* timep) { static char buf[26]; /* Format into given buffer and return the result */ return strftime (buf, sizeof (buf), "%c\n", timep)? buf : 0; } �������������������cc65-2.18/libsrc/common/atexit.s��������������������������������������������������������������������0000664�0000000�0000000�00000003237�13473601511�0016442�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.06.1998 ; ; int atexit (void (*f) (void)); ; .export _atexit .destructor doatexit, 17 .import callax .include "errno.inc" .macpack cpu ; --------------------------------------------------------------------------- .proc _atexit ldy exitfunc_index cpy #exitfunc_max ; Slot available? beq @Error ; Jump if no ; Enter the function into the table sta exitfunc_table,y iny txa sta exitfunc_table,y iny sty exitfunc_index ; Done, return zero lda #0 tax rts ; Error, no space left @Error: lda #ENOSPC ; No space left jsr __seterrno ldx #$FF ; Return -1 txa rts .endproc ; --------------------------------------------------------------------------- .code .proc doatexit ldy exitfunc_index ; Get index beq @L9 ; Jump if done dey lda exitfunc_table,y tax dey lda exitfunc_table,y sty exitfunc_index jsr callax ; Call the function .if (.cpu .bitand ::CPU_ISET_65SC02) bra doatexit .else jmp doatexit ; Next one .endif @L9: rts .endproc ; --------------------------------------------------------------------------- .bss exitfunc_index: .res 1 ; Index into table, inc'ed by 2 exitfunc_table: .res 10 ; 5 exit functions exitfunc_max = <(* - exitfunc_table) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/atoi.s����������������������������������������������������������������������0000664�0000000�0000000�00000005631�13473601511�0016100�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 05.06.1998 ; ; int atoi (const char* s); ; long atol (const char* s); ; .export _atoi, _atol .import negeax, __ctype .importzp sreg, ptr1, ptr2, tmp1 .include "ctype.inc" ; ; Conversion routine (32 bit) ; _atoi: _atol: sta ptr1 ; Store s stx ptr1+1 ldy #0 sty ptr2 sty ptr2+1 ; initial value (32 bit) sty sreg sty sreg+1 ; Skip whitespace L1: lda (ptr1),y tax lda __ctype,x ; get character classification and #CT_SPACE_TAB ; tab or space? beq L2 ; jump if no iny bne L1 inc ptr1+1 bne L1 ; branch always ; Check for a sign. The character is in X L2: txa ; get char ldx #0 ; flag: positive cmp #'+' ; ### portable? beq L3 cmp #'-' ; ### portable? bne L5 dex ; flag: negative L3: iny bne L5 inc ptr1+1 ; Store the sign flag and setup for conversion L5: stx tmp1 ; remember sign flag L6: lda (ptr1),y ; get next char tax lda __ctype,x ; get character classification and #$04 ; digit? beq L8 ; done ; Multiply ptr2 (the converted value) by 10 jsr mul2 ; * 2 lda sreg+1 pha lda sreg pha lda ptr2+1 pha lda ptr2 pha ; Save value jsr mul2 ; * 4 jsr mul2 ; * 8 clc pla adc ptr2 sta ptr2 pla adc ptr2+1 sta ptr2+1 pla adc sreg sta sreg pla adc sreg+1 sta sreg+1 ; x*2 + x*8 = x*10 ; Get the character back and add it txa ; get char back sec sbc #'0' ; make numeric value clc adc ptr2 sta ptr2 bcc L7 inc ptr2+1 bne L7 inc sreg bne L7 inc sreg+1 ; Next character L7: iny bne L6 inc ptr1+1 bne L6 ; Conversion done. Load the low 16 bit into A/X L8: lda ptr2 ldx ptr2+1 ; Negate the value if necessary, otherwise we're done ldy tmp1 ; sign beq L9 ; Branch if positive ; Negate the 32 bit value in ptr2/sreg jmp negeax ; ; Helper functions ; mul2: asl ptr2 rol ptr2+1 rol sreg rol sreg+1 ; * 2 L9: rts �������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/bsearch.c�������������������������������������������������������������������0000664�0000000�0000000�00000002213�13473601511�0016524�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** bsearch.c ** ** 1998-06-17, Ullrich von Bassewitz ** 2015-06-21, Greg King */ #include <stdlib.h> void* __fastcall__ bsearch (const void* key, const void* base, size_t n, size_t size, int __fastcall__ (* cmp) (const void*, const void*)) { int current; int result; int found = 0; int first = 0; int last = n - 1; /* Binary search */ while (first <= last) { /* Set current to mid of range */ current = (last + first) / 2; /* Do a compare */ result = cmp ((void*) (((int) base) + current*size), key); if (result < 0) { first = current + 1; } else { last = current - 1; if (result == 0) { /* Found one entry that matches the search key. However there may be ** more than one entry with the same key value and ANSI guarantees ** that we return the first of a row of items with the same key. */ found = 1; } } } /* Did we find the entry? */ return (void*) (found? ((int) base) + first*size : 0); } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/calloc.s��������������������������������������������������������������������0000664�0000000�0000000�00000002273�13473601511�0016400�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 15.11.2001 ; ; Allocate a block and zero it. ; ; void* __fastcall__ calloc (size_t count, size_t size); ; .export _calloc .import _malloc, __bzero .import tosumulax, pushax ; ------------------------------------------------------------------------- .proc _calloc ; We have the first argument in a/x and the second on the stack. Calling ; tosumulax will give the product of both in a/x. jsr tosumulax ; Save size for later sta Size stx Size+1 ; malloc() is a fastcall function, so we do already have the argument in ; the right place jsr _malloc ; Check for a NULL pointer cpx #0 bne ClearBlock cmp #0 bne ClearBlock ; We have a NULL pointer, bail out rts ; No NULL pointer, clear the block. _bzero will return a pointer to the ; block which is exactly what we want. ClearBlock: jsr pushax ; ptr lda Size ldx Size+1 ; Size jmp __bzero .endproc ; ------------------------------------------------------------------------- ; Data .bss Size: .res 2 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/chdir.s���������������������������������������������������������������������0000664�0000000�0000000�00000001127�13473601511�0016231�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-08-12 ; ; int __fastcall__ chdir (const char* name); ; .export _chdir .import __syschdir .import __mappederrno ;-------------------------------------------------------------------------- ; The function calls __syschdir, which must check the directory, set it, and ; copy it to __cwd if it is valid. The copycwd may be used for the latter. .proc _chdir jsr __syschdir ; Call the machine specific function jmp __mappederrno ; Store into _oserror, set errno, return 0/-1 .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/copydata.s������������������������������������������������������������������0000664�0000000�0000000�00000002022�13473601511�0016737�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 1998-12-07, 2004-12-01 ; ; Copy the data segment from the LOAD to the RUN location ; .export copydata .import __DATA_LOAD__, __DATA_RUN__, __DATA_SIZE__ .importzp ptr1, ptr2, tmp1 copydata: lda #<__DATA_LOAD__ ; Source pointer sta ptr1 lda #>__DATA_LOAD__ sta ptr1+1 lda #<__DATA_RUN__ ; Target pointer sta ptr2 lda #>__DATA_RUN__ sta ptr2+1 ldx #<~__DATA_SIZE__ lda #>~__DATA_SIZE__ ; Use -(__DATASIZE__+1) sta tmp1 ldy #$00 ; Copy loop @L1: inx beq @L3 @L2: lda (ptr1),y sta (ptr2),y iny bne @L1 inc ptr1+1 inc ptr2+1 ; Bump pointers bne @L1 ; Branch always (hopefully) ; Bump the high counter byte @L3: inc tmp1 bne @L2 ; Done rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/creat.s���������������������������������������������������������������������0000664�0000000�0000000�00000001417�13473601511�0016240�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-06-12 ; ; int __fastcall__ creat (const char* name, unsigned mode); ; .export _creat .import _open .import pushax .include "fcntl.inc" ; The call ; ; creat (name, mode); ; ; is equivalent to ; ; open (name, O_CREAT | O_WRONLY | O_TRUNC, mode); ; .proc _creat pha txa pha ; Save mode lda #<(O_CREAT | O_WRONLY | O_TRUNC) ldx #>(O_CREAT | O_WRONLY | O_TRUNC) jsr pushax pla tax pla jsr pushax ; Push mode on argument stack ldy #6 ; Number of argument bytes jmp _open .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/ctime.s���������������������������������������������������������������������0000664�0000000�0000000�00000000433�13473601511�0016240�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 12.11.2002 ; ; char* __fastcall__ ctime (time_t* timep); ; .export _ctime .import _localtime, _asctime .proc _ctime ; return asctime (localtime (timep)); jsr _localtime jmp _asctime .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/divt.s����������������������������������������������������������������������0000664�0000000�0000000�00000002154�13473601511�0016107�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; divt.s ; ; 2002-10-22, Greg King ; ; This signed-division function returns both the quotient and the remainder, ; in this structure: ; ; typedef struct { ; int rem, quot; ; } div_t; ; ; div_t __fastcall__ div (int numer, int denom); ; .export _div .import tosdivax, negax .importzp sreg, ptr1, tmp1 _div: jsr tosdivax ; Division-operator does most of the work ldy sreg ; low byte remainder from sreg sta sreg ; store low byte quotient to sreg lda sreg+1 ; high byte remainder from sreg stx sreg+1 ; store high byte quotient to sreg tax ; high byte remainder to x tya ; low byte remainder to a ; Adjust the sign of the remainder. ; It must be the same as the sign of the dividend. ; bit tmp1 ; Load high-byte of left argument bpl Pos ; Jump if sign-of-result is positive jmp negax ; Result is negative, adjust the sign Pos: rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/doesclrscr.s����������������������������������������������������������������0000664�0000000�0000000�00000000361�13473601511�0017302�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, June-2016 ; ; unsigned char doesclrscr(void); ; ; returns 0/1 if after program termination the screen isn't/is cleared ; .export _doesclrscrafterexit .import return0 _doesclrscrafterexit = return0 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/errno.s���������������������������������������������������������������������0000664�0000000�0000000�00000000276�13473601511�0016271�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2003-08-12, Ullrich von Bassewitz ; 2015-09-24, Greg King ; ; extern int _errno; ; /* Library errors go here. */ ; .include "errno.inc" .bss __errno: .word 0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/errormsg.c������������������������������������������������������������������0000664�0000000�0000000�00000002004�13473601511�0016753�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** errormsg.c ** ** Ullrich von Bassewitz, 17.05.2000 */ const char* const _sys_errlist[] = { "Unknown error", /* 0 */ "No such file or directory", /* ENOENT */ "Out of memory", /* ENOMEM */ "Permission denied", /* EACCES */ "No such device", /* ENODEV */ "Too many open files", /* EMFILE */ "Device or resource busy", /* EBUSY */ "Invalid argument", /* EINVAL */ "No space left on device", /* ENOSPC */ "File exists", /* EEXIST */ "Try again", /* EAGAIN */ "I/O error", /* EIO */ "Interrupted system call", /* EINTR */ "Function not implemented", /* ENOSYS */ "Illegal seek", /* ESPIPE */ "Range error", /* ERANGE */ "Bad file number", /* EBADF */ "Exec format error", /* ENOEXEC */ "Unknown OS error code", /* EUNKNOWN */ }; ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/fclose.s��������������������������������������������������������������������0000664�0000000�0000000�00000001715�13473601511�0016416�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.11.2002 ; ; int __fastcall__ fclose (FILE* f); ; /* Close a file */ ; .export _fclose .import _close .importzp ptr1 .include "errno.inc" .include "_file.inc" ; ------------------------------------------------------------------------ ; Code .proc _fclose sta ptr1 stx ptr1+1 ; Store f ; Check if the file is really open ldy #_FILE::f_flags lda (ptr1),y and #_FOPEN bne @L1 ; File is not open lda #EINVAL jsr __seterrno lda #$FF ; Return -1 tax rts ; File is open. Reset the flags and close the file. @L1: lda #_FCLOSED sta (ptr1),y ldy #_FILE::f_fd lda (ptr1),y ldx #0 jmp _close ; Will set errno and return an error flag .endproc ���������������������������������������������������cc65-2.18/libsrc/common/fdopen.c��������������������������������������������������������������������0000664�0000000�0000000�00000001437�13473601511�0016377�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** fdopen.c ** ** Ullrich von Bassewitz, 17.06.1998 */ #include <stdio.h> #include <fcntl.h> #include <errno.h> #include "_file.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ FILE* __fastcall__ fdopen (int handle, const char* /*mode*/) { register FILE* f; /* Find a free file slot */ if ((f = _fdesc ())) { /* Insert the handle, and return the descriptor */ f->f_fd = handle; f->f_flags = _FOPEN; } else { /* No slots */ _seterrno (EMFILE); /* Too many files */ } /* Return the file descriptor */ return f; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/fgetc.c���������������������������������������������������������������������0000664�0000000�0000000�00000002161�13473601511�0016207�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** fgetc.c ** ** (C) Copyright 1998, 2002 Ullrich von Bassewitz (uz@cc65.org) ** */ #include <stdio.h> #include <unistd.h> #include "_file.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ int __fastcall__ fgetc (register FILE* f) { unsigned char c; /* Check if the file is open or if there is an error condition */ if ((f->f_flags & _FOPEN) == 0 || (f->f_flags & (_FERROR | _FEOF)) != 0) { return EOF; } /* If we have a pushed back character, return it */ if (f->f_flags & _FPUSHBACK) { f->f_flags &= ~_FPUSHBACK; return f->f_pushback; } /* Read one byte */ switch (read (f->f_fd, &c, 1)) { case -1: /* Error */ f->f_flags |= _FERROR; return EOF; case 0: /* EOF */ f->f_flags |= _FEOF; return EOF; default: /* Char read */ return c; } } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/fgetpos.c�������������������������������������������������������������������0000664�0000000�0000000�00000000707�13473601511�0016572�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** fgetpos.c ** ** Christian Groessler, 07-Aug-2000 */ #include <stdio.h> /*****************************************************************************/ /* Code */ /*****************************************************************************/ int __fastcall__ fgetpos (FILE* f, fpos_t* pos) { *pos = ftell (f); if (*pos != -1) return 0; return -1; } ���������������������������������������������������������cc65-2.18/libsrc/common/fgets.c���������������������������������������������������������������������0000664�0000000�0000000�00000002431�13473601511�0016227�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** Ullrich von Bassewitz, 11.08.1998 ** ** char* fgets (char* s, int size, FILE* f); */ #include <stdio.h> #include <errno.h> #include "_file.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ char* __fastcall__ fgets (char* s, unsigned size, register FILE* f) { register char* p = s; unsigned i; int c; if (size == 0) { /* Invalid size */ return (char*) _seterrno (EINVAL); } /* Read input */ i = 0; while (--size) { /* Get next character */ if ((c = fgetc (f)) == EOF) { /* Error or EOF */ if ((f->f_flags & _FERROR) != 0 || i == 0) { /* ERROR or EOF on first char */ *p = '\0'; return 0; } else { /* EOF with data already read */ break; } } /* One char more */ *p = c; ++p; ++i; /* Stop at end of line */ if ((char)c == '\n') { break; } } /* Terminate the string */ *p = '\0'; /* Done */ return s; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/fmisc.s���������������������������������������������������������������������0000664�0000000�0000000�00000003130�13473601511�0016235�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 31.05.1998 ; ; Several small file stream functions ; .export _clearerr, _feof, _ferror, _fileno, _fflush .import return0 .importzp ptr1 .include "_file.inc" .include "errno.inc" ; ; Get the FILE* parameter, check if the file is open. Returns zero in A ; and zero flag set in case of an error. .proc getf sta ptr1 stx ptr1+1 ldy #_FILE::f_flags lda (ptr1),y ; get f->f_flags and #_FOPEN ; file open? rts .endproc ; ; void clearerr (FILE* f); ; .proc _clearerr jsr getf beq err lda (ptr1),y and #<~(_FEOF | _FERROR) sta (ptr1),y err: rts .endproc ; ; int feof (FILE* f); ; .proc _feof jsr getf beq @L1 ; Return 0 on error lda (ptr1),y and #_FEOF @L1: ldx #0 rts .endproc ; ; int ferror (FILE* f); ; .proc _ferror jsr getf beq @L1 ; Return 0 on error lda (ptr1),y and #_FERROR @L1: ldx #0 rts .endproc ; ; int fileno (FILE* f); ; .proc _fileno jsr getf beq error ldy #_FILE::f_fd lda (ptr1),y ldx #0 rts ; If the file is not valid, fileno must set errno and return -1 error: lda #<EBADF jsr __seterrno lda #$FF tax rts .endproc ; ; int __fastcall__ fflush (FILE* f); ; _fflush = return0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/fopen.s���������������������������������������������������������������������0000664�0000000�0000000�00000001676�13473601511�0016260�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.11.2002 ; ; FILE* __fastcall__ fopen (const char* name, const char* mode) ; /* Open a file */ ; .export _fopen .import __fopen, __fdesc .import pushax, return0 .include "errno.inc" ; ------------------------------------------------------------------------ ; Code .proc _fopen ; Bring the mode parameter on the stack jsr pushax ; Allocate a new file stream jsr __fdesc ; Check if we have a stream cmp #$00 bne @L1 cpx #$00 bne @L1 ; Failed to allocate a file stream lda #EMFILE jsr __seterrno ; Set __errno, will return 0 in A tax rts ; Return zero ; Open the file and return the file descriptor. All arguments are already ; in place: name and mode on the stack, and f in a/x @L1: jmp __fopen .endproc ������������������������������������������������������������������cc65-2.18/libsrc/common/fprintf.s�������������������������������������������������������������������0000664�0000000�0000000�00000003157�13473601511�0016615�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; int fprintf (FILE* f, const char* Format, ...); ; ; Ullrich von Bassewitz, 1.12.2000 ; .export _fprintf .import addysp, decsp4, _vfprintf .importzp sp, ptr1 .macpack generic ; ---------------------------------------------------------------------------- ; Data .bss ParamSize: .res 1 ; Number of parameter bytes ; ---------------------------------------------------------------------------- ; Code .code _fprintf: sty ParamSize ; Number of param bytes passed in Y ; We have to push f and format, both in the order they already have on stack. ; To make this somewhat more efficient, we will create space on the stack and ; then do a copy of the complete block instead of pushing each parameter ; separately. Since the size of the arguments passed is the same as the size ; of the fixed arguments, this will allow us to calculate the pointer to the ; fixed size arguments easier (they're just ParamSize bytes away). jsr decsp4 ; Calculate a pointer to the Format argument lda ParamSize add sp sta ptr1 ldx sp+1 bcc @L1 inx @L1: stx ptr1+1 ; Now copy both, f and format ldy #4-1 @L2: lda (ptr1),y sta (sp),y dey bpl @L2 ; Load va_list (last and __fastcall__ parameter to vfprintf) lda ptr1 ldx ptr1+1 ; Call vfprintf jsr _vfprintf ; Cleanup the stack. We will return what we got from vfprintf ldy ParamSize jmp addysp �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/fputc.c���������������������������������������������������������������������0000664�0000000�0000000�00000001450�13473601511�0016240�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** fputc.c ** ** Ullrich von Bassewitz, 02.06.1998 */ #include <stdio.h> #include <unistd.h> #include "_file.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ int __fastcall__ fputc (int c, register FILE* f) { /* Check if the file is open or if there is an error condition */ if ((f->f_flags & _FOPEN) == 0 || (f->f_flags & (_FERROR | _FEOF)) != 0) { goto ReturnEOF; } /* Write the byte */ if (write (f->f_fd, &c, 1) != 1) { /* Error */ f->f_flags |= _FERROR; ReturnEOF: return EOF; } /* Return the byte written */ return c & 0xFF; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/fputs.c���������������������������������������������������������������������0000664�0000000�0000000�00000000737�13473601511�0016267�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** int fputs (const char* s, FILE* f); ** ** Ullrich von Bassewitz, 11.08.1998 */ #include <stdio.h> #include <string.h> #include <unistd.h> #include "_file.h" int __fastcall__ fputs (const char* s, register FILE* f) { /* Check if the file is open or if there is an error condition */ if ((f->f_flags & _FOPEN) == 0 || (f->f_flags & (_FERROR | _FEOF)) != 0) { return EOF; } /* Write the string */ return write (f->f_fd, s, strlen (s)); } ���������������������������������cc65-2.18/libsrc/common/fread.s���������������������������������������������������������������������0000664�0000000�0000000�00000012674�13473601511�0016232�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2002-11-22, 2004-05-14 ; ; size_t __fastcall__ fread (void* buf, size_t size, size_t count, FILE* file); ; /* Read from a file */ ; .export _fread .import _read .import pusha0, pushax .import incsp4, incsp6 .import ldaxysp, ldax0sp .import pushwysp .import tosumulax, tosudivax .importzp ptr1, sp .include "errno.inc" .include "_file.inc" .macpack generic ; ------------------------------------------------------------------------ ; Code .proc _fread ; We will place a pointer to the file descriptor into the register bank .import regbank: zp file = regbank ; Save two bytes from the register bank ldy file+0 sty save ldy file+1 sty save+1 ; Save the file pointer into the register bank sta file stx file+1 ; Check if the file is open ldy #_FILE::f_flags lda (file),y and #_FOPEN ; Is the file open? beq @L1 ; Branch if no ; Check if the stream is in an error state lda (file),y ; get file->f_flags again and #_FERROR beq @L2 ; File not open or in error state @L1: lda #EINVAL jsr __seterrno ; Set __errno, return zero in A tax ; a/x = 0 jmp @L99 ; Bail out ; Remember if we have a pushed back character and reset the flag. @L2: tax ; X = 0 lda (file),y and #_FPUSHBACK beq @L3 lda (file),y and #<~_FPUSHBACK sta (file),y ; file->f_flags &= ~_FPUSHBACK; inx ; X = 1 @L3: stx pb ; Build the stackframe for read() ldy #_FILE::f_fd lda (file),y jsr pusha0 ; file->f_fd ldy #9 jsr pushwysp ; buf ; Stack is now: buf/size/count/file->fd/buf ; Calculate the number of bytes to read: count * size ldy #7 jsr pushwysp ; count ldy #9 jsr ldaxysp ; Get size jsr tosumulax ; count * size -> a/x ; Check if count is zero. cmp #0 bne @L4 cpx #0 bne @L4 ; Count is zero, drop the stack frame just built and return count jsr incsp4 ; Drop file->fd/buf jsr ldax0sp ; Get count jmp @L99 ; Bail out ; Check if we have a buffered char from ungetc @L4: ldy pb beq @L6 ; We have a buffered char from ungetc. Save the low byte from count pha ; Copy the buffer pointer into ptr1, and increment the pointer value passed ; to read() by one, so read() starts to store data at buf+1. ldy #0 lda (sp),y sta ptr1 add #1 sta (sp),y iny lda (sp),y sta ptr1+1 adc #0 sta (sp),y ; ptr1 = buf++; ; Get the buffered character and place it as first character into the read ; buffer. ldy #_FILE::f_pushback lda (file),y ldy #0 sta (ptr1),y ; *buf = file->f_pushback; ; Restore the low byte of count and decrement count by one. This may result ; in count being zero, so check for that. pla sub #1 bcs @L5 dex @L5: cmp #0 bne @L6 cpx #0 beq @L8 ; Call read(). This will leave the original 3 params on the stack @L6: jsr _read ; Check for errors in read cpx #$FF bne @L8 cmp #$FF bne @L8 ; Error in read. Set the stream error flag and bail out. errno has already ; been set by read(). On entry to label @L7, X must be zero. inx ; X = 0 lda #_FERROR @L7: ldy #_FILE::f_flags ; X must be zero here! ora (file),y sta (file),y txa ; a/x = 0 beq @L99 ; Return zero ; Read was ok, account for the pushed back character (if any). @L8: add pb bcc @L9 inx ; Check for end of file. @L9: cmp #0 ; Zero bytes read? bne @L10 cpx #0 bne @L10 ; Zero bytes read. Set the EOF flag lda #_FEOF bne @L7 ; Set flag and return zero ; Return the number of items successfully read. Since we've checked for ; bytes == 0 above, size cannot be zero here, so the division is safe. @L10: jsr pushax ; Push number of bytes read ldy #5 jsr ldaxysp ; Get size jsr tosudivax ; bytes / size -> a/x @L99: ldy save ; Restore zp register sty file ldy save+1 sty file+1 jmp incsp6 ; Drop params, return .endproc ; ------------------------------------------------------------------------ ; Data .bss save: .res 2 pb: .res 1 ��������������������������������������������������������������������cc65-2.18/libsrc/common/free.s����������������������������������������������������������������������0000664�0000000�0000000�00000040656�13473601511�0016073�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 19.03.2000 ; ; Free a block on the heap. ; ; void __fastcall__ free (void* block); ; ; ; C implementation was: ; ; void free (void* block) ; /* Release an allocated memory block. The function will accept NULL pointers ; ** (and do nothing in this case). ; */ ; { ; unsigned* b; ; unsigned size; ; struct freeblock* f; ; ; ; /* Allow NULL arguments */ ; if (block == 0) { ; return; ; } ; ; /* Get a pointer to the real memory block, then get the size */ ; b = (unsigned*) block; ; size = *--b; ; ; /* Check if the block is at the top of the heap */ ; if (((int) b) + size == (int) _hptr) { ; ; /* Decrease _hptr to release the block */ ; _hptr = (unsigned*) (((int) _hptr) - size); ; ; /* Check if the last block in the freelist is now at heap top. If so, ; ** remove this block from the freelist. ; */ ; if (f = _hlast) { ; if (((int) f) + f->size == (int) _hptr) { ; /* Remove the last block */ ; _hptr = (unsigned*) (((int) _hptr) - f->size); ; if (_hlast = f->prev) { ; /* Block before is now last block */ ; f->prev->next = 0; ; } else { ; /* The freelist is empty now */ ; _hfirst = 0; ; } ; } ; } ; ; } else { ; ; /* Not at heap top, enter the block into the free list */ ; _hadd (b, size); ; ; } ; } ; .importzp ptr1, ptr2, ptr3, ptr4 .export _free, heapadd .include "_heap.inc" .macpack generic ;----------------------------------------------------------------------------- ; Code _free: sta ptr2 stx ptr2+1 ; Save block ; Is the argument NULL? If so, bail out. ora ptr2+1 ; Is the argument NULL? bne @L1 ; Jump if no rts ; Bail out if yes ; There's a pointer below the user space that points to the real start of the ; raw block. We will decrement the high pointer byte and use an offset of 254 ; to save some code. The first word of the raw block is the total size of the ; block. Remember the block size in ptr1. @L1: dec ptr2+1 ; Decrement high pointer byte ldy #$FF lda (ptr2),y ; High byte of real block address tax dey lda (ptr2),y stx ptr2+1 sta ptr2 ; Set ptr2 to start of real block ldy #usedblock::size+1 lda (ptr2),y ; High byte of size sta ptr1+1 ; Save it dey lda (ptr2),y sta ptr1 ; Check if the block is on top of the heap add ptr2 tay lda ptr2+1 adc ptr1+1 cpy __heapptr bne heapadd ; Add to free list cmp __heapptr+1 bne heapadd ; The pointer is located at the heap top. Lower the heap top pointer to ; release the block. @L3: lda ptr2 sta __heapptr lda ptr2+1 sta __heapptr+1 ; Check if the last block in the freelist is now at heap top. If so, remove ; this block from the freelist. lda __heaplast sta ptr1 ora __heaplast+1 beq @L9 ; Jump if free list empty lda __heaplast+1 sta ptr1+1 ; Pointer to last block now in ptr1 ldy #freeblock::size lda (ptr1),y ; Low byte of block size add ptr1 tax iny ; High byte of block size lda (ptr1),y adc ptr1+1 cmp __heapptr+1 bne @L9 ; Jump if last block not on top of heap cpx __heapptr bne @L9 ; Jump if last block not on top of heap ; Remove the last block lda ptr1 sta __heapptr lda ptr1+1 sta __heapptr+1 ; Correct the next pointer of the now last block ldy #freeblock::prev+1 ; Offset of ->prev field lda (ptr1),y sta ptr2+1 ; Remember f->prev in ptr2 sta __heaplast+1 dey lda (ptr1),y sta ptr2 ; Remember f->prev in ptr2 sta __heaplast ora __heaplast+1 ; -> prev == 0? bne @L8 ; Jump if free list not empty ; Free list is now empty (A = 0) sta __heapfirst sta __heapfirst+1 ; Done @L9: rts ; Block before is now last block. ptr2 points to f->prev. @L8: lda #$00 dey ; Points to high byte of ->next sta (ptr2),y dey ; Low byte of f->prev->next sta (ptr2),y rts ; Done ; The block is not on top of the heap. Add it to the free list. This was ; formerly a separate function called __hadd that was implemented in C as ; shown here: ; ; void _hadd (void* mem, size_t size) ; /* Add an arbitrary memory block to the heap. This function is used by ; ** free(), but it does also allow usage of otherwise unused memory ; ** blocks as heap space. The given block is entered in the free list ; ** without any checks, so beware! ; */ ; { ; struct freeblock* f; ; struct freeblock* left; ; struct freeblock* right; ; ; if (size >= sizeof (struct freeblock)) { ; ; /* Set the admin data */ ; f = (struct freeblock*) mem; ; f->size = size; ; ; /* Check if the freelist is empty */ ; if (_hfirst == 0) { ; ; /* The freelist is empty until now, insert the block */ ; f->prev = 0; ; f->next = 0; ; _hfirst = f; ; _hlast = f; ; ; } else { ; ; /* We have to search the free list. As we are doing so, we check ; ** if it is possible to combine this block with another already ; ** existing block. Beware: The block may be the "missing link" ; ** between *two* other blocks. ; */ ; left = 0; ; right = _hfirst; ; while (right && f > right) { ; left = right; ; right = right->next; ; } ; ; ; /* OK, the current block must be inserted between left and right (but ; ** beware: one of the two may be zero!). Also check for the condition ; ** that we have to merge two or three blocks. ; */ ; if (right) { ; /* Check if we must merge the block with the right one */ ; if (((unsigned) f) + size == (unsigned) right) { ; /* Merge with the right block */ ; f->size += right->size; ; if (f->next = right->next) { ; f->next->prev = f; ; } else { ; /* This is now the last block */ ; _hlast = f; ; } ; } else { ; /* No merge, just set the link */ ; f->next = right; ; right->prev = f; ; } ; } else { ; f->next = 0; ; /* Special case: This is the new freelist end */ ; _hlast = f; ; } ; if (left) { ; /* Check if we must merge the block with the left one */ ; if ((unsigned) f == ((unsigned) left) + left->size) { ; /* Merge with the left block */ ; left->size += f->size; ; if (left->next = f->next) { ; left->next->prev = left; ; } else { ; /* This is now the last block */ ; _hlast = left; ; } ; } else { ; /* No merge, just set the link */ ; left->next = f; ; f->prev = left; ; } ; } else { ; f->prev = 0; ; /* Special case: This is the new freelist start */ ; _hfirst = f; ; } ; } ; } ; } ; ; ; On entry, ptr2 must contain a pointer to the block, which must be at least ; HEAP_MIN_BLOCKSIZE bytes in size, and ptr1 contains the total size of the ; block. ; ; Check if the free list is empty, storing _hfirst into ptr3 for later heapadd: lda __heapfirst sta ptr3 lda __heapfirst+1 sta ptr3+1 ora ptr3 bne SearchFreeList ; The free list is empty, so this is the first and only block. A contains ; zero if we come here. ldy #freeblock::next-1 @L2: iny ; f->next = f->prev = 0; sta (ptr2),y cpy #freeblock::prev+1 ; Done? bne @L2 lda ptr2 ldx ptr2+1 sta __heapfirst stx __heapfirst+1 ; _heapfirst = f; sta __heaplast stx __heaplast+1 ; _heaplast = f; rts ; Done ; We have to search the free list. As we are doing so, check if it is possible ; to combine this block with another, already existing block. Beware: The ; block may be the "missing link" between two blocks. ; ptr3 contains _hfirst (the start value of the search) when execution reaches ; this point, Y contains size+1. We do also know that _heapfirst (and therefore ; ptr3) is not zero on entry. SearchFreeList: lda #0 sta ptr4 sta ptr4+1 ; left = 0; ldy #freeblock::next+1 ldx ptr3 @Loop: lda ptr3+1 ; High byte of right cmp ptr2+1 bne @L1 cpx ptr2 beq @L2 @L1: bcs CheckRightMerge @L2: stx ptr4 ; left = right; sta ptr4+1 dey ; Points to next lda (ptr3),y ; right = right->next; tax iny ; Points to next+1 lda (ptr3),y stx ptr3 sta ptr3+1 ora ptr3 bne @Loop ; If we come here, the right pointer is zero, so we don't need to check for ; a merge. The new block is the new freelist end. ; A is zero when we come here, Y points to next+1 sta (ptr2),y ; Clear high byte of f->next dey sta (ptr2),y ; Clear low byte of f->next lda ptr2 ; _heaplast = f; sta __heaplast lda ptr2+1 sta __heaplast+1 ; Since we have checked the case that the freelist is empty before, if the ; right pointer is NULL, the left *cannot* be NULL here. So skip the ; pointer check and jump right to the left block merge jmp CheckLeftMerge2 ; The given block must be inserted between left and right, and right is not ; zero. CheckRightMerge: lda ptr2 add ptr1 ; f + size tax lda ptr2+1 adc ptr1+1 cpx ptr3 bne NoRightMerge cmp ptr3+1 bne NoRightMerge ; Merge with the right block. Do f->size += right->size; ldy #freeblock::size lda ptr1 add (ptr3),y sta (ptr2),y iny ; Points to size+1 lda ptr1+1 adc (ptr3),y sta (ptr2),y ; Set f->next = right->next and remember f->next in ptr1 (we don't need the ; size stored there any longer) iny ; Points to next lda (ptr3),y ; Low byte of right->next sta (ptr2),y ; Store to low byte of f->next sta ptr1 iny ; Points to next+1 lda (ptr3),y ; High byte of right->next sta (ptr2),y ; Store to high byte of f->next sta ptr1+1 ora ptr1 beq @L1 ; Jump if f->next zero ; f->next->prev = f; iny ; Points to prev lda ptr2 ; Low byte of f sta (ptr1),y ; Low byte of f->next->prev iny ; Points to prev+1 lda ptr2+1 ; High byte of f sta (ptr1),y ; High byte of f->next->prev jmp CheckLeftMerge ; Done ; f->next is zero, this is now the last block @L1: lda ptr2 ; _heaplast = f; sta __heaplast lda ptr2+1 sta __heaplast+1 jmp CheckLeftMerge ; No right merge, just set the link. NoRightMerge: ldy #freeblock::next ; f->next = right; lda ptr3 sta (ptr2),y iny ; Points to next+1 lda ptr3+1 sta (ptr2),y iny ; Points to prev lda ptr2 ; right->prev = f; sta (ptr3),y iny ; Points to prev+1 lda ptr2+1 sta (ptr3),y ; Check if the left pointer is zero CheckLeftMerge: lda ptr4 ; left == NULL? ora ptr4+1 bne CheckLeftMerge2 ; Jump if there is a left block ; We don't have a left block, so f is actually the new freelist start ldy #freeblock::prev sta (ptr2),y ; f->prev = 0; iny sta (ptr2),y lda ptr2 ; _heapfirst = f; sta __heapfirst lda ptr2+1 sta __heapfirst+1 rts ; Done ; Check if the left block is adjacent to the following one CheckLeftMerge2: ldy #freeblock::size ; Calculate left + left->size lda (ptr4),y ; Low byte of left->size add ptr4 tax iny ; Points to size+1 lda (ptr4),y ; High byte of left->size adc ptr4+1 cpx ptr2 bne NoLeftMerge cmp ptr2+1 bne NoLeftMerge ; Jump if blocks not adjacent ; Merge with the left block. Do left->size += f->size; dey ; Points to size lda (ptr4),y add (ptr2),y sta (ptr4),y iny ; Points to size+1 lda (ptr4),y adc (ptr2),y sta (ptr4),y ; Set left->next = f->next and remember left->next in ptr1. iny ; Points to next lda (ptr2),y ; Low byte of f->next sta (ptr4),y sta ptr1 iny ; Points to next+1 lda (ptr2),y ; High byte of f->next sta (ptr4),y sta ptr1+1 ora ptr1 ; left->next == NULL? beq @L1 ; Do left->next->prev = left iny ; Points to prev lda ptr4 ; Low byte of left sta (ptr1),y iny lda ptr4+1 ; High byte of left sta (ptr1),y rts ; Done ; This is now the last block, do _heaplast = left @L1: lda ptr4 sta __heaplast lda ptr4+1 sta __heaplast+1 rts ; Done ; No merge of the left block, just set the link. Y points to size+1 if ; we come here. Do left->next = f. NoLeftMerge: iny ; Points to next lda ptr2 ; Low byte of left sta (ptr4),y iny lda ptr2+1 ; High byte of left sta (ptr4),y ; Do f->prev = left iny ; Points to prev lda ptr4 sta (ptr2),y iny lda ptr4+1 sta (ptr2),y rts ; Done ����������������������������������������������������������������������������������cc65-2.18/libsrc/common/freopen.c�������������������������������������������������������������������0000664�0000000�0000000�00000001677�13473601511�0016570�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** freopen.c ** ** Ullrich von Bassewitz, 17.06.1998 */ #include <stdio.h> #include <fcntl.h> #include <errno.h> #include "_file.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ FILE* __fastcall__ freopen (const char* name, const char* mode, FILE* f) { /* Check if the file is open, if so, close it */ if ((f->f_flags & _FOPEN) == 0) { /* File is not open */ return (FILE*) _seterrno (EINVAL); /* File not input */ } /* Close the file. Don't bother setting the flag, it will get ** overwritten by _fopen. */ if (close (f->f_fd) < 0) { /* An error occured, errno is already set */ return 0; } /* Open the file and return the descriptor */ return _fopen (name, mode, f); } �����������������������������������������������������������������cc65-2.18/libsrc/common/fscanf.s��������������������������������������������������������������������0000664�0000000�0000000�00000003705�13473601511�0016404�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; int fscanf (FILE* f, const char* format, ...); ; ; Ullrich von Bassewitz, 2004-11-28 ; .export _fscanf .import addysp, decsp4, _vfscanf .importzp sp, ptr1 .macpack generic ; ---------------------------------------------------------------------------- ; Data .bss ParamSize: .res 1 ; Number of parameter bytes ; ---------------------------------------------------------------------------- ; int fscanf (FILE* f, const char* format, ...) ; /* Standard C function */ ; { ; va_list ap; ; ; /* Setup for variable arguments */ ; va_start (ap, format); ; ; /* Call vfscanf(). Since we know that va_end won't do anything, we will ; ** save the call and return the value directly. ; */ ; return vfscanf (f, format, ap); ; } ; .code _fscanf: sty ParamSize ; Number of param bytes passed in Y ; We have to push f and format, both in the order they already have on stack. ; To make this somewhat more efficient, we will create space on the stack and ; then do a copy of the complete block instead of pushing each parameter ; separately. Since the size of the arguments passed is the same as the size ; of the fixed arguments, this will allow us to calculate the pointer to the ; fixed size arguments easier (they're just ParamSize bytes away). jsr decsp4 ; Calculate a pointer to the Format argument lda ParamSize add sp sta ptr1 ldx sp+1 bcc @L1 inx @L1: stx ptr1+1 ; Now copy both, f and format ldy #4-1 @L2: lda (ptr1),y sta (sp),y dey bpl @L2 ; Load va_list (last and __fastcall__ parameter to vfscanf) lda ptr1 ldx ptr1+1 ; Call vfscanf jsr _vfscanf ; Cleanup the stack. We will return what we got from vfscanf ldy ParamSize jmp addysp �����������������������������������������������������������cc65-2.18/libsrc/common/fseek.c���������������������������������������������������������������������0000664�0000000�0000000�00000002610�13473601511�0016213�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** fseek.c ** ** Christian Groessler, 2000-08-07 ** Ullrich von Bassewitz, 2004-05-12 */ #include <stdio.h> #include <errno.h> #include <unistd.h> #include "_file.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ int __fastcall__ fseek (register FILE* f, long offset, int whence) { long res; /* Is the file open? */ if ((f->f_flags & _FOPEN) == 0) { _seterrno (EINVAL); /* File not open */ return -1; } /* If we have a pushed back character, and whence is relative to the ** current position, correct the offset. */ if ((f->f_flags & _FPUSHBACK) && whence == SEEK_CUR) { --offset; } /* Do the seek */ res = lseek(f->f_fd, offset, whence); /* If the seek was successful. Discard any effects of the ungetc function, ** and clear the end-of-file indicator. Otherwise set the error indicator ** on the stream, and return -1. We will check for >= 0 here, because that ** saves some code, and we don't have files with 2 gigabytes in size ** anyway:-) */ if (res >= 0) { f->f_flags &= ~(_FEOF | _FPUSHBACK); return 0; } else { f->f_flags |= _FERROR; return -1; } } ������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/fsetpos.c�������������������������������������������������������������������0000664�0000000�0000000�00000000664�13473601511�0016610�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** fsetpos.c ** ** Christian Groessler, 07-Aug-2000 */ #include <stdio.h> /*****************************************************************************/ /* Code */ /*****************************************************************************/ int __fastcall__ fsetpos (FILE* f, const fpos_t *pos) { return fseek (f, (fpos_t)*pos, SEEK_SET); } ����������������������������������������������������������������������������cc65-2.18/libsrc/common/ftell.c���������������������������������������������������������������������0000664�0000000�0000000�00000001701�13473601511�0016224�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** ftell.c ** ** Christian Groessler, 2000-08-07 ** Ullrich von Bassewitz, 2004-05-13 */ #include <stdio.h> #include <errno.h> #include <unistd.h> #include "_file.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ long __fastcall__ ftell (register FILE* f) { long pos; /* Is the file open? */ if ((f->f_flags & _FOPEN) == 0) { _seterrno (EINVAL); /* File not open */ return -1L; } /* Call the low level function */ pos = lseek (f->f_fd, 0L, SEEK_CUR); /* If we didn't have an error, correct the return value in case we have ** a pushed back character. */ if (pos > 0 && (f->f_flags & _FPUSHBACK)) { --pos; } /* -1 for error, comes from lseek() */ return pos; } ���������������������������������������������������������������cc65-2.18/libsrc/common/fwrite.s��������������������������������������������������������������������0000664�0000000�0000000�00000006262�13473601511�0016445�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.11.2002 ; ; size_t __fastcall__ fwrite (const void* buf, size_t size, size_t count, FILE* file); ; /* Write to a file */ ; .export _fwrite .import _write .import pushax, incsp6, addysp, ldaxysp, pushwysp, return0 .import tosumulax, tosudivax .importzp ptr1 .include "errno.inc" .include "_file.inc" ; ------------------------------------------------------------------------ ; Code .proc _fwrite ; Save file and place it into ptr1 sta file sta ptr1 stx file+1 stx ptr1+1 ; Check if the file is open ldy #_FILE::f_flags lda (ptr1),y and #_FOPEN ; Is the file open? bne @L2 ; Branch if yes ; File not open @L1: lda #EBADF jsr __seterrno ; Returns with A = 0 tax ; A = X = 0 jmp incsp6 ; Check if the stream is in an error state @L2: lda (ptr1),y ; get file->f_flags again and #_FERROR bne @L1 ; Build the stackframe for write() ldy #_FILE::f_fd lda (ptr1),y ldx #$00 jsr pushax ; file->f_fd ldy #9 jsr pushwysp ; buf ; Stack is now: buf/size/count/file->fd/buf ; Calculate the number of bytes to write: count * size ldy #7 jsr pushwysp ; count ldy #9 jsr ldaxysp ; Get size jsr tosumulax ; count * size -> a/x ; Check if the number of bytes is zero. Don't call write in this case cpx #0 bne @L3 cmp #0 bne @L3 ; The number of bytes to write is zero, just return count ldy #5 jsr ldaxysp ; Get count ldy #10 jmp addysp ; Drop params, return ; Call write(). This will leave the original 3 params on the stack @L3: jsr _write ; Check for errors in write cpx #$FF bne @L4 cmp #$FF bne @L4 ; Error in write. Set the stream error flag and bail out. errno is already ; set by write(). lda file sta ptr1 lda file+1 sta ptr1+1 ldy #_FILE::f_flags lda (ptr1),y ora #_FERROR sta (ptr1),y bne @L1 ; Return zero ; Write was ok. Return the number of items successfully written. Since we've ; checked for bytes == 0 above, size cannot be zero here, so the division is ; safe. @L4: jsr pushax ; Push number of bytes written ldy #5 jsr ldaxysp ; Get size jsr tosudivax ; bytes / size -> a/x jmp incsp6 ; Drop params, return .endproc ; ------------------------------------------------------------------------ ; Data .bss file: .res 2 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/getchar.c�������������������������������������������������������������������0000664�0000000�0000000�00000000675�13473601511�0016544�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** getchar.c ** ** Ullrich von Bassewitz, 11.12.1998 */ #include <stdio.h> #undef getchar /* This is usually declared as a macro */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ int getchar (void) { return fgetc (stdin); } �������������������������������������������������������������������cc65-2.18/libsrc/common/getcpu.s��������������������������������������������������������������������0000664�0000000�0000000�00000011413�13473601511�0016426�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 02.04.1999 ; ; unsigned char getcpu (void); ; .include "zeropage.inc" .export _getcpu ; --------------------------------------------------------------------------- ; Subroutine to detect an 816. Returns ; ; - carry clear and 0 in A for a NMOS 6502 CPU ; - carry set and 1 in A for a 65C02 ; - carry set and 2 in A for a 65816 ; - carry set and 3 in A for a 4510 ; - carry set and 4 in A for a 65SC02 ; - carry set and 5 in A for a 65CE02 ; - carry set and 6 in A for a HuC6280 ; - carry clear and 7 in A for a 2a03/2a07 ; - carry set and 8 in A for a 45GS02 ; ; This function uses a $1A opcode which is a INA on the 816 and ignored ; (interpreted as a NOP) on a NMOS 6502. There are several CMOS versions ; of the 6502, but all of them interpret unknown opcodes as NOP so this is ; just what we want. .p816 ; Enable 65816 instructions _getcpu: lda #0 inc a ; .byte $1A ; nop on nmos, inc on every cmos cmp #1 bcc @IsNMOS ; This is at least a 65C02, check for a 65CE02/4510 .byte $42,$EA ; neg on 65CE02/4510, nop #$EA on 65C02, wdm $EA on 65816 cmp #1 beq @HasINCA ; This is at least a 65CE02, check for 4510 lda #5 ; CPU_65CE02 constant ldx #0 ; to make sure MAP doesn't do anything, the upper nybl of X and Z must be clear .byte $5C ; map on 4510, aug on 65CE02 (acts like 4 byte nop) lda #3 ; CPU_4510 constant nop cmp #5 beq @LoadXAndReturn ; It is either a 4510 (C65) or a 45GS02 (MEGA65) ; 45GS02 supports 32-bit ZP indirect, so use that to check CPU type ; without requiring a functioning MEGA65 hypervisor. ; We setup a read of $200xx, then store a different value in $xx ; and then re-read $200xx to see if it is unchanged. ; Setup 32-bit pointer to $00020000+tmp1 lda #<$020000+tmp1 sta regsave lda #>$020000+tmp1 sta regsave+1 sta regsave+3 ; also write to upper byte of pointer to save an extra LDA #$00 lda #^$020000+tmp1 sta regsave+2 ; Prefixing LDA ($nn),Z with a NOP uses 32-bit ZP pointer on 45GS02, ; but normal 16-bit ZP pointer on 4510 ; (We assume Z=$00, which will be the normal case) nop ; prefix to tell next instruction to be 32-bit ZP .byte $b2,regsave ; LDA (regsave),Z eor #$ff ; change the value sta tmp1 ; store in $xx ; now try again to load it: If the same, then 45GS02, as $200xx is unchanged nop ; prefix to tell next instruction to be 32-bit ZP .byte $b2,regsave ; LDA (regsave),Z cmp tmp1 ; does the loaded value match what is in $xx? bne @Is45GS02 ; $200xx and $xx have different values, so must be a MEGA65 45GS02 @Is4510: lda #3 ; CPU_4510 constant ldx #0 ; load high byte of word rts @Is45GS02: lda #8 ; CPU_45GS02 constant ldx #0 ; load high byte of word rts ; 6502 type of cpu, check for a 2a03/2a07 @IsNMOS: sed ; set decimal mode, no decimal mode on the 2a03/2a07 lda #9 clc adc #1 ; $01+$09 = $10 on 6502, $01+$09 = $0A on 2a03/2a07 cld cmp #$0a beq @Is2a03 lda #0 ; CPU_6502 constant beq @LoadXAndReturn @Is2a03: lda #7 ; CPU_2A0x constant bne @LoadXAndReturn ; 65C02 cpu type, check for HuC6280 @CheckHuC6280: ldx #6 ; CPU_HUC6280 constant .byte $22,$EA ; sax nop on HuC6280 (A=$06, X=$01), nop #$EA on 65C02 (A=$01, X=$06) bne @LoadXAndReturn ; Check for 65816/65802 @HasINCA: xba ; .byte $EB, put $01 in B accu (nop on 65C02/65SC02) dec a ; .byte $3A, A=$00 xba ; .byte $EB, A=$01 if 65816/65802 and A=$00 if 65C02/65SC02 inc a ; .byte $1A, A=$02 if 65816/65802 and A=$01 if 65C02/65SC02 cmp #2 beq @LoadXAndReturn ; check for 65SC02 ldy $F7 ldx #0 stx $F7 .byte $F7,$F7 ; nop nop on 65SC02, smb7 $F7 on 65C02 ldx $F7 sty $F7 cpx #$00 bne @CheckHuC6280 lda #4 ; CPU_65SC02 constant @LoadXAndReturn: ldx #0 rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/getcwd.s��������������������������������������������������������������������0000664�0000000�0000000�00000002645�13473601511�0016423�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-08-12 ; ; char* __fastcall__ getcwd (char* buf, size_t size); ; .export _getcwd .import popptr1 .import __cwd .importzp ptr1, ptr2 .include "errno.inc" ;-------------------------------------------------------------------------- .proc _getcwd ; Remember -size-1 because this simplifies the following loop eor #$FF sta ptr2 txa eor #$FF sta ptr2+1 jsr popptr1 ; Get buf to ptr1 ; Copy __cwd to the given buffer checking the length ; ldy #$00 is guaranteed by popptr1 loop: inc ptr2 bne @L1 inc ptr2+1 beq overflow ; Copy one character, end the loop if the zero terminator is reached. We ; don't support directories longer than 255 characters for now. @L1: lda __cwd,y sta (ptr1),y beq done iny bne loop ; For some reason the cwd is longer than 255 characters. This should not ; happen, we handle it as if the passed buffer was too short. ; ; String overflow, return ERANGE overflow: lda #<ERANGE jsr __seterrno ; Returns 0 in A tax ; Return zero rts ; Success, return buf done: lda ptr1 ldx ptr1+1 rts .endproc �������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/getenv.s��������������������������������������������������������������������0000664�0000000�0000000�00000002166�13473601511�0016434�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2005-04-21 ; ; char* __fastcall__ getenv (const char* name); ; ; Beware: putenv() knows about zero page usage in this module! ; .export _getenv .import __environ, __envcount .import searchenv .import return0 .import ptr1:zp, ptr3:zp, tmp1:zp .code ;---------------------------------------------------------------------------- ; getenv() .proc _getenv sta ptr1 stx ptr1+1 ; Save name ; Search for the string in the environment. searchenv will set the N flag if ; the string is not found, otherwise X contains the index of the entry, ptr3 ; contains the entry and Y the offset of the '=' in the string. jsr searchenv bpl found jmp return0 ; Not found, return NULL ; Found the entry. Calculate the pointer to the right side of the environment ; variable. Because we want to skip the '=', we will set the carry. found: ldx ptr3+1 ; High byte of result tya sec adc ptr3 bcc @L9 inx @L9: rts .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/getopt.c��������������������������������������������������������������������0000664�0000000�0000000�00000004716�13473601511�0016431�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** This is part of a changed public domain getopt implementation that ** had the following text on top: ** ** I got this off net.sources from Henry Spencer. ** It is a public domain getopt(3) like in System V. ** I have made the following modifications: ** ** A test main program was added, ifdeffed by GETOPT. ** This main program is a public domain implementation ** of the getopt(1) program like in System V. The getopt ** program can be used to standardize shell option handling. ** e.g. cc -DGETOPT getopt.c -o getopt */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #define ARGCH ':' #define BADCH '?' #define EMSG "" int opterr = 1; /* useless, never set or used */ int optind = 1; /* index into parent argv vector */ int optopt; /* character checked for validity */ char *optarg; /* argument associated with option */ #define tell(s) fputs(*argv,stderr);fputs(s,stderr); \ fputc(optopt,stderr);fputc('\n',stderr);return(BADCH); int __fastcall__ getopt (int argc, char* const* argv, const char* optstring) /* Get option letter from argument vector */ { static char *place = EMSG; /* option letter processing */ register char *oli; /* option letter list index */ if (!*place) { /* update scanning pointer */ if (optind >= argc || *(place = argv[optind]) != '-' || !*++place) { return (EOF); } if (*place == '-') { /* found "--" */ ++optind; return (EOF); } } /* option letter okay? */ if ((optopt = (int) *place++) == ARGCH || !(oli = strchr (optstring, optopt))) { if (!*place) { ++optind; } tell (": illegal option -- "); } if (*++oli != ARGCH) { /* don't need argument */ optarg = NULL; if (!*place) { ++optind; } } else { /* need an argument */ if (*place) { /* no white space */ optarg = place; } else if (argc <= ++optind) { /* no arg */ place = EMSG; tell (": option requires an argument -- "); } else { /* white space */ optarg = argv[optind]; } place = EMSG; ++optind; } return (optopt); /* dump back option letter */ } ��������������������������������������������������cc65-2.18/libsrc/common/gets.c����������������������������������������������������������������������0000664�0000000�0000000�00000002153�13473601511�0016062�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** gets.c ** ** Ullrich von Bassewitz, 11.08.1998 */ #include <stdio.h> #include "_file.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ char* __fastcall__ gets (char* s) { register char* p = s; int c; unsigned i = 0; while (1) { /* Get next character */ if ((c = fgetc (stdin)) == EOF) { /* Error or EOF */ *p = '\0'; if (stdin->f_flags & _FERROR) { /* ERROR */ return 0; } else { /* EOF */ if (i) { return s; } else { return 0; } } } /* One char more. Newline ends the input */ if ((char) c == '\n') { *p = '\0'; break; } else { *p = c; ++p; ++i; } } /* Done */ return s; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/gmtime.c��������������������������������������������������������������������0000664�0000000�0000000�00000007040�13473601511�0016402�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* gmtime.c */ /* */ /* Convert calendar time into broken down time in UTC */ /* */ /* */ /* */ /* (C) 2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <time.h> /*****************************************************************************/ /* Code */ /*****************************************************************************/ struct tm* __fastcall__ gmtime (const time_t* timep) { static struct tm timebuf; time_t t; /* Check the argument */ if (timep == 0 || (long) (t = *timep) < 0) { /* Invalid arg */ return 0; } /* Since our ints are just 16 bits, split the given time into seconds, ** hours and days. Each of the values will fit in a 16 bit variable. ** The mktime routine will then do the rest. */ timebuf.tm_sec = t % 3600; timebuf.tm_min = 0; timebuf.tm_hour = (t / 3600) % 24; timebuf.tm_mday = (t / (3600UL * 24UL)) + 1; timebuf.tm_mon = 0; timebuf.tm_year = 70; /* Base value is 1/1/1970 */ /* Call mktime to do the final conversion */ mktime (&timebuf); /* Return the result */ return &timebuf; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/interrupt.s�����������������������������������������������������������������0000664�0000000�0000000�00000004657�13473601511�0017207�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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); ; .export _set_irq, _reset_irq .interruptor clevel_irq, 1 ; Export as low priority IRQ handler .import popax, __ZP_START__, jmpvec .include "zeropage.inc" .macpack generic ; --------------------------------------------------------------------------- .data irqvec: jmp $00FF ; Patched at runtime ; --------------------------------------------------------------------------- .bss irqsp: .res 2 zpsave: .res zpsavespace ; --------------------------------------------------------------------------- .code .proc _set_irq ; Keep clevel_irq from being called right now sei ; Set irq stack pointer to stack_addr + stack_size sta irqsp stx irqsp+1 jsr popax add irqsp sta irqsp txa adc irqsp+1 sta irqsp+1 ; Set irq vector to irq_handler jsr popax sta irqvec+1 stx irqvec+2 ; Set the user vector ; Restore interrupt requests and return cli rts .endproc .proc _reset_irq lda #$00 sta irqvec+2 ; High byte is enough rts .endproc .proc clevel_irq ; Is C level interrupt request vector set? lda irqvec+2 ; High byte is enough bne @L1 clc ; Interrupt not handled rts ; Save our zero page locations @L1: ldx #.sizeof(::zpsave)-1 @L2: lda <__ZP_START__,x sta zpsave,x dex bpl @L2 ; Save jmpvec lda jmpvec+1 pha lda jmpvec+2 pha ; Set C level interrupt stack lda irqsp ldx irqsp+1 sta sp stx sp+1 ; Call C level interrupt request handler jsr irqvec ; Mark interrupt handled / not handled lsr ; Restore our zero page content ldx #.sizeof(::zpsave)-1 @L3: lda zpsave,x sta <__ZP_START__,x dex bpl @L3 ; Restore jmpvec and return pla sta jmpvec+2 pla sta jmpvec+1 rts .endproc ���������������������������������������������������������������������������������cc65-2.18/libsrc/common/isalnum.s�������������������������������������������������������������������0000664�0000000�0000000�00000000714�13473601511�0016611�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 02.06.1998 ; ; int isalnum (int c); ; .export _isalnum .include "ctype.inc" _isalnum: cpx #$00 ; Char range ok? bne @L1 ; Jump if no tay lda __ctype,y ; Get character classification and #CT_ALNUM ; Mask character/digit bits rts @L1: lda #$00 ; Return false tax rts ����������������������������������������������������cc65-2.18/libsrc/common/isalpha.s�������������������������������������������������������������������0000664�0000000�0000000�00000000706�13473601511�0016563�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 02.06.1998 ; ; int isalpha (int c); ; .export _isalpha .include "ctype.inc" _isalpha: cpx #$00 ; Char range ok? bne @L1 ; Jump if no tay lda __ctype,y ; Get character classification and #CT_ALPHA ; Mask character bits rts @L1: lda #$00 ; Return false tax rts ����������������������������������������������������������cc65-2.18/libsrc/common/isblank.s�������������������������������������������������������������������0000664�0000000�0000000�00000000737�13473601511�0016571�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 02.06.1998 ; ; int isblank (int c); ; ; cc65 (and GNU) extension. ; .export _isblank .include "ctype.inc" _isblank: cpx #$00 ; Char range ok? bne @L1 ; Jump if no tay lda __ctype,y ; Get character classification and #CT_SPACE_TAB ; Mask blank bit rts @L1: lda #$00 ; Return false tax rts ���������������������������������cc65-2.18/libsrc/common/iscntrl.s�������������������������������������������������������������������0000664�0000000�0000000�00000000715�13473601511�0016620�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 02.06.1998 ; ; int iscntrl (int c); ; .export _iscntrl .include "ctype.inc" _iscntrl: cpx #$00 ; Char range ok? bne @L1 ; Jump if no tay lda __ctype,y ; Get character classification and #CT_CTRL ; Mask control character bit rts @L1: lda #$00 ; Return false tax rts ���������������������������������������������������cc65-2.18/libsrc/common/isdigit.s�������������������������������������������������������������������0000664�0000000�0000000�00000000701�13473601511�0016571�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 02.06.1998 ; ; int isdigit (int c); ; .export _isdigit .include "ctype.inc" _isdigit: cpx #$00 ; Char range ok? bne @L1 ; Jump if no tay lda __ctype,y ; Get character classification and #CT_DIGIT ; Mask digit bit rts @L1: lda #$00 ; Return false tax rts ���������������������������������������������������������������cc65-2.18/libsrc/common/isgraph.s�������������������������������������������������������������������0000664�0000000�0000000�00000001232�13473601511�0016572�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 1998-06-02, Ullrich von Bassewitz ; 2014-09-10, Greg King ; ; int isgraph (int c); ; .export _isgraph .include "ctype.inc" _isgraph: cpx #>$0000 ; Char range OK? bne @L1 ; Jump if no tay lda __ctype,y ; Get character classification and #CT_CTRL_SPACE ; Mask character bits cmp #1 ; If false, then set "borrow" flag lda #0 sbc #0 ; Invert logic rts ; Return NOT control and NOT space @L1: lda #<0 ; Return false tax rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/islower.s�������������������������������������������������������������������0000664�0000000�0000000�00000000706�13473601511�0016626�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 02.06.1998 ; ; int islower (int c); ; .export _islower .include "ctype.inc" _islower: cpx #$00 ; Char range ok? bne @L1 ; Jump if no tay lda __ctype,y ; Get character classification and #CT_LOWER ; Mask lower char bit rts @L1: lda #$00 ; Return false tax rts ����������������������������������������������������������cc65-2.18/libsrc/common/isprint.s�������������������������������������������������������������������0000664�0000000�0000000�00000000775�13473601511�0016640�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 02.06.1998 ; ; int isprint (int c); ; .export _isprint .include "ctype.inc" _isprint: cpx #$00 ; Char range ok? bne @L1 ; Jump if no tay lda __ctype,y ; Get character classification eor #CT_CTRL ; NOT a control char and #CT_CTRL ; Mask control char bit rts @L1: lda #$00 ; Return false tax rts ���cc65-2.18/libsrc/common/ispunct.s�������������������������������������������������������������������0000664�0000000�0000000�00000001245�13473601511�0016626�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 1998-06-02, Ullrich von Bassewitz ; 2014-09-10, Greg King ; ; int ispunct (int c); ; .export _ispunct .include "ctype.inc" _ispunct: cpx #>$0000 ; Char range OK? bne @L1 ; Jump if no tay lda __ctype,y ; Get character classification and #CT_NOT_PUNCT ; Mask relevant bits cmp #1 ; If false, then set "borrow" flag lda #0 sbc #0 ; Invert logic rts ; Return NOT (space | control | digit | alpha) @L1: lda #<0 ; Return false tax rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/isspace.s�������������������������������������������������������������������0000664�0000000�0000000�00000000716�13473601511�0016572�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 02.06.1998 ; ; int isspace (int c); ; .export _isspace .include "ctype.inc" _isspace: cpx #$00 ; Char range ok? bne @L1 ; Jump if no tay lda __ctype,y ; Get character classification and #(CT_SPACE | CT_OTHER_WS) ; Mask space bits rts @L1: lda #$00 ; Return false tax rts ��������������������������������������������������cc65-2.18/libsrc/common/isupper.s�������������������������������������������������������������������0000664�0000000�0000000�00000000706�13473601511�0016631�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 02.06.1998 ; ; int isupper (int c); ; .export _isupper .include "ctype.inc" _isupper: cpx #$00 ; Char range ok? bne @L1 ; Jump if no tay lda __ctype,y ; Get character classification and #CT_UPPER ; Mask upper char bit rts @L1: lda #$00 ; Return false tax rts ����������������������������������������������������������cc65-2.18/libsrc/common/isxdigit.s������������������������������������������������������������������0000664�0000000�0000000�00000000705�13473601511�0016765�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 02.06.1998 ; ; int isxdigit (int c); ; .export _isxdigit .include "ctype.inc" _isxdigit: cpx #$00 ; Char range ok? bne @L1 ; Jump if no tay lda __ctype,y ; Get character classification and #CT_XDIGIT ; Mask xdigit bit rts @L1: lda #$00 ; Return false tax rts �����������������������������������������������������������cc65-2.18/libsrc/common/itoa.s����������������������������������������������������������������������0000664�0000000�0000000�00000005501�13473601511�0016074�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 31.05.1998 ; ; char* itoa (int value, char* s, int radix); ; char* utoa (unsigned value, char* s, int radix); ; .export _itoa, _utoa .import addysp1 .import __hextab .importzp sp, sreg, ptr2, ptr3, tmp1 .rodata specval: .byte '-', '3', '2', '7', '6', '8', 0 .code ; ; Common subroutine to pop the parameters and put them into core ; dopop: sta tmp1 ; will loose high byte ldy #0 lda (sp),y sta ptr2 sta ptr3 iny lda (sp),y sta ptr2+1 sta ptr3+1 iny lda (sp),y sta sreg iny lda (sp),y sta sreg+1 jmp addysp1 ; Bump stack pointer ; ; itoa ; _itoa: jsr dopop ; pop the arguments ; We must handle $8000 in a special way, since it is the only negative ; number that has no positive 16-bit counterpart ldy tmp1 ; get radix cpy #10 bne utoa cmp #$00 bne L2 cpx #$80 bne L2 ldy #6 L1: lda specval,y ; copy -32768 sta (ptr2),y dey bpl L1 jmp L10 ; Check if the value is negative. If so, write a - sign and negate the ; number. L2: lda sreg+1 ; get high byte bpl utoa lda #'-' ldy #0 sta (ptr2),y ; store sign inc ptr2 bne L3 inc ptr2+1 L3: lda sreg eor #$FF clc adc #$01 sta sreg lda sreg+1 eor #$FF adc #$00 sta sreg+1 jmp utoa ; ; utoa ; _utoa: jsr dopop ; pop the arguments ; Convert to string by dividing and push the result onto the stack utoa: lda #$00 pha ; sentinel ; Divide sreg/tmp1 -> sreg, remainder in a L5: ldy #16 ; 16 bit lda #0 ; remainder L6: asl sreg rol sreg+1 rol a cmp tmp1 bcc L7 sbc tmp1 inc sreg L7: dey bne L6 tay ; get remainder into y lda __hextab,y ; get hex character pha ; save char value on stack lda sreg ora sreg+1 bne L5 ; Get the characters from the stack into the string ldy #0 L9: pla sta (ptr2),y beq L10 ; jump if sentinel iny bne L9 ; jump always ; Done! Return the target string L10: lda ptr3 ldx ptr3+1 rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/labs.s����������������������������������������������������������������������0000664�0000000�0000000�00000000571�13473601511�0016063�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 17.06.1998 ; ; long __fastcall__ labs (long val); ; intmax_t __fastcall imaxabs (intmax_t val); ; .export _labs, _imaxabs .import negeax .importzp sreg _labs: _imaxabs: ldy sreg+1 ; test hi byte bpl L1 jmp negeax ; Negate if negative L1: rts ���������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/locale.c��������������������������������������������������������������������0000664�0000000�0000000�00000003534�13473601511�0016363�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** locale.c ** ** Ullrich von Bassewitz, 11.12.1998 */ #include <locale.h> #include <limits.h> /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* For memory efficiency use a separate empty string */ static char EmptyString [] = ""; static struct lconv lc = { EmptyString, /* currency_symbol */ ".", /* decimal_point */ EmptyString, /* grouping */ EmptyString, /* int_curr_symbol */ EmptyString, /* mon_decimal_point */ EmptyString, /* mon_grouping */ EmptyString, /* mon_thousands_sep */ EmptyString, /* negative_sign */ EmptyString, /* positive_sign */ EmptyString, /* thousands_sep */ CHAR_MAX, /* frac_digits */ CHAR_MAX, /* int_frac_digits */ CHAR_MAX, /* n_cs_precedes */ CHAR_MAX, /* n_sep_by_space */ CHAR_MAX, /* n_sign_posn */ CHAR_MAX, /* p_cs_precedes */ CHAR_MAX, /* p_sep_by_space */ CHAR_MAX, /* p_sign_posn */ }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ struct lconv* localeconv (void) { return &lc; } char* __fastcall__ setlocale (int, const char* locale) { if (locale == 0 || (locale [0] == 'C' && locale [1] == '\0') || locale [0] == '\0') { /* No change, or value already set, our locale is the "C" locale */ return "C"; } else { /* Cannot set this one */ return 0; } } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/localtime.c�����������������������������������������������������������������0000664�0000000�0000000�00000006103�13473601511�0017070�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* localtime.c */ /* */ /* Convert calendar time into broken down local time */ /* */ /* */ /* */ /* (C) 2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <time.h> /*****************************************************************************/ /* Code */ /*****************************************************************************/ struct tm* __fastcall__ localtime (const time_t* timep) { time_t t; /* Check for a valid time spec */ if (timep == 0) { return 0; } /* Get the time and correct for the time zone offset */ t = *timep + _tz.timezone; /* Use gmtime for conversion */ return gmtime (&t); } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/longjmp.s�������������������������������������������������������������������0000664�0000000�0000000�00000002110�13473601511�0016577�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 1998-06-06, Ullrich von Bassewitz ; 2015-09-11, Greg King ; ; void __fastcall__ longjmp (jmp_buf buf, int retval); ; .export _longjmp .import popptr1 .importzp sp, ptr1, ptr2 _longjmp: sta ptr2 ; Save retval stx ptr2+1 ora ptr2+1 ; Check for 0 bne @L1 inc ptr2 ; 0 is illegal, according to the standard ... ; ... and, must be replaced by 1 @L1: jsr popptr1 ; get buf ; ldy #0 is guaranteed by popptr1 ; Get the old parameter stack lda (ptr1),y iny sta sp lda (ptr1),y iny sta sp+1 ; Get the old stack pointer lda (ptr1),y iny tax txs ; Get the return address and push it on the stack lda (ptr1),y iny pha lda (ptr1),y pha ; Load the return value and return to the caller lda ptr2 ldx ptr2+1 rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/ltoa.s����������������������������������������������������������������������0000664�0000000�0000000�00000006121�13473601511�0016076�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 11.06.1998 ; ; char* ltoa (long value, char* s, int radix); ; char* ultoa (unsigned long value, char* s, int radix); ; .export _ltoa, _ultoa .import popax, popptr1, negeax .import __hextab, __longminstr .importzp sreg, ptr1, ptr2, ptr3, tmp1 .macpack cpu .code ; ; Common subroutine to pop the parameters and put them into core ; dopop: sta tmp1 ; will loose high byte jsr popax ; get s to ptr2 sta ptr2 stx ptr2+1 sta ptr3 ; save for return stx ptr3+1 jsr popptr1 ; get low word of value to ptr1 jsr popax ; get high word of value to sreg sta sreg stx sreg+1 rts ; ; ltoa ; _ltoa: jsr dopop ; pop the arguments ; We must handle $80000000 in a special way, since it is the only negative ; number that has no positive 32-bit counterpart ldx sreg+1 ; get high byte ldy tmp1 ; get radix cpy #10 bne ultoa lda sreg ora ptr1+1 ora ptr1 bne L2 cpx #$80 bne L2 ldy #11 L1: lda __longminstr,y ; copy -2147483648 sta (ptr2),y dey bpl L1 jmp L10 ; Check if the value is negative. If so, write a - sign and negate the ; number. L2: txa ; get high byte bpl ultoa lda #'-' .if (.cpu .bitand CPU_ISET_65SC02) sta (ptr2) .else ldy #0 sta (ptr2),y ; store sign .endif inc ptr2 bne L3 inc ptr2+1 L3: lda ptr1 ; negate val ldx ptr1+1 jsr negeax sta ptr1 stx ptr1+1 jmp ultoa ; ; utoa ; _ultoa: jsr dopop ; pop the arguments ; Convert to string by dividing and push the result onto the stack ultoa: lda #$00 pha ; sentinel ; Divide val/tmp1 -> val, remainder in a L5: ldy #32 ; 32 bit lda #0 ; remainder L6: asl ptr1 rol ptr1+1 rol sreg rol sreg+1 rol a cmp tmp1 bcc L7 sbc tmp1 inc ptr1 L7: dey bne L6 tay ; get remainder into y lda __hextab,y ; get hex character pha ; save char value on stack lda ptr1 ora ptr1+1 ora sreg ora sreg+1 bne L5 ; Get the characters from the stack into the string ldy #0 L9: pla sta (ptr2),y beq L10 ; jump if sentinel iny bne L9 ; jump always ; Done! Return the target string L10: lda ptr3 ldx ptr3+1 rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/lz4.s�����������������������������������������������������������������������0000664�0000000�0000000�00000011455�13473601511�0015656�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Lauri Kasanen, 6 Jun 2017 ; (C) Mega Cat Studios ; An optimized LZ4 decompressor ; ; Almost 7 times faster, uses no RAM (vs 14 bytes BSS), and takes 1/4 the space ; vs the official C source. ; .importzp sp, sreg, regsave, regbank .importzp tmp1, tmp2, tmp3, tmp4, ptr1, ptr2, ptr3, ptr4 .macpack longbranch .import memcpy_upwards,pushax,popax .export _decompress_lz4 out = regsave written = regsave + 2 tmp = tmp1 token = tmp2 offset = ptr3 in = sreg outlen = ptr4 ; --------------------------------------------------------------- ; void decompress_lz4 (const u8 *in, u8 * const out, const u16 outlen) ; --------------------------------------------------------------- .segment "CODE" .proc _decompress_lz4: near sta outlen stx outlen+1 jsr popax sta out stx out+1 jsr popax sta in stx in+1 ; ; written = 0; ; lda #$00 sta written ; ; while (written < outlen) { ; jmp L0046 ; ; token = *in++; ; L0004: ldy #$00 lda (in),y sta token inc in bne L000A inc in+1 L000A: ; ; offset = token >> 4; ; ldx #$00 lsr a lsr a lsr a lsr a sta offset stx offset+1 ; ; token &= 0xf; ; token += 4; // Minmatch ; lda token and #$0F clc adc #$04 sta token ; ; if (offset == 15) { ; lda offset cmp #$0F L0013: bne L001A ; ; tmp = *in++; ; ldy #$00 lda (in),y sta tmp inc in bne L0017 inc in+1 L0017: ; ; offset += tmp; ; clc adc offset sta offset lda #$00 adc offset+1 sta offset+1 ; ; if (tmp == 255) ; lda tmp cmp #$FF ; ; goto moreliterals; ; jmp L0013 ; ; if (offset) { ; L001A: lda offset ora offset+1 beq L001C ; ; memcpy(&out[written], in, offset); ; lda out clc adc written sta ptr2 lda out+1 adc written+1 tax lda ptr2 stx ptr2+1 jsr pushax lda in ldx in+1 sta ptr1 stx ptr1+1 ; ldy #$00 - not needed as pushax zeroes Y jsr memcpy_upwards ; ; written += offset; ; lda offset clc adc written sta written lda offset+1 adc written+1 sta written+1 ; ; in += offset; ; lda offset clc adc in sta in lda offset+1 adc in+1 sta in+1 ; ; if (written >= outlen) ; L001C: lda written cmp outlen lda written+1 sbc outlen+1 ; ; return; ; bcc L0047 rts ; ; memcpy(&offset, in, 2); ; L0047: ldy #$00 lda (in),y sta offset iny lda (in),y sta offset+1 ; ; in += 2; ; lda #$02 clc adc in sta in bcc L002F inc in+1 ; ; copysrc = out + written - offset; ; L002F: lda out clc adc written tay lda out+1 adc written+1 tax tya sec sbc offset sta ptr1 txa sbc offset+1 sta ptr1+1 ; ; offset = token; ; lda #$00 sta offset+1 lda token sta offset ; ; if (token == 19) { ; cmp #$13 L0045: bne L003C ; ; tmp = *in++; ; ldy #$00 lda (in),y sta tmp inc in bne L0039 inc in+1 L0039: ; ; offset += tmp; ; clc adc offset sta offset tya adc offset+1 sta offset+1 ; ; if (tmp == 255) ; lda tmp cmp #$FF ; ; goto morematches; ; jmp L0045 ; ; memcpy(&out[written], copysrc, offset); ; L003C: lda out clc adc written sta ptr2 lda out+1 adc written+1 tax lda ptr2 stx ptr2+1 jsr pushax jsr memcpy_upwards ; ; written += offset; ; lda offset clc adc written sta written lda offset+1 adc written+1 L0046: sta written+1 ; ; while (written < outlen) { ; lda written cmp outlen lda written+1 sbc outlen+1 jcc L0004 rts .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/malloc.s��������������������������������������������������������������������0000664�0000000�0000000�00000024532�13473601511�0016414�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 17.7.2000 ; ; Allocate a block from the heap. ; ; void* __fastcall__ malloc (size_t size); ; ; ; C implementation was: ; ; void* malloc (size_t size) ; /* Allocate memory from the given heap. The function returns a pointer to the ; ** allocated memory block or a NULL pointer if not enough memory is available. ; ** Allocating a zero size block is not allowed. ; */ ; { ; struct freeblock* f; ; unsigned* p; ; ; ; /* Check for a size of zero, then add the administration space and round ; ** up the size if needed. ; */ ; if (size == 0) { ; return 0; ; } ; size += HEAP_ADMIN_SPACE; ; if (size < sizeof (struct freeblock)) { ; size = sizeof (struct freeblock); ; } ; ; /* Search the freelist for a block that is big enough */ ; f = _hfirst; ; while (f && f->size < size) { ; f = f->next; ; } ; ; /* Did we find one? */ ; if (f) { ; ; /* We found a block big enough. If the block can hold just the ; ** requested size, use the block in full. Beware: When slicing blocks, ; ** there must be space enough to create a new one! If this is not the ; ** case, then use the complete block. ; */ ; if (f->size - size < sizeof (struct freeblock)) { ; ; /* Use the actual size */ ; size = f->size; ; ; /* Remove the block from the free list */ ; if (f->prev) { ; /* We have a previous block */ ; f->prev->next = f->next; ; } else { ; /* This is the first block, correct the freelist pointer */ ; _hfirst = f->next; ; } ; if (f->next) { ; /* We have a next block */ ; f->next->prev = f->prev; ; } else { ; /* This is the last block, correct the freelist pointer */ ; _hlast = f->prev; ; } ; ; } else { ; ; /* We must slice the block found. Cut off space from the upper ; ** end, so we can leave the actual free block chain intact. ; */ ; ; /* Decrement the size of the block */ ; f->size -= size; ; ; /* Set f to the now unused space above the current block */ ; f = (struct freeblock*) (((unsigned) f) + f->size); ; ; } ; ; /* Setup the pointer for the block */ ; p = (unsigned*) f; ; ; } else { ; ; /* We did not find a block big enough. Try to use new space from the ; ** heap top. ; */ ; if (((unsigned) _hend) - ((unsigned) _hptr) < size) { ; /* Out of heap space */ ; return 0; ; } ; ; ; /* There is enough space left, take it from the heap top */ ; p = _hptr; ; _hptr = (unsigned*) (((unsigned) _hptr) + size); ; ; } ; ; /* New block is now in p. Fill in the size and return the user pointer */ ; *p++ = size; ; return p; ; } ; .importzp ptr1, ptr2, ptr3 .export _malloc .include "_heap.inc" .macpack generic ;----------------------------------------------------------------------------- ; Code _malloc: sta ptr1 ; Store size in ptr1 stx ptr1+1 ; Check for a size of zero, if so, return NULL ora ptr1+1 beq Done ; a/x already contains zero ; Add the administration space and round up the size if needed lda ptr1 add #HEAP_ADMIN_SPACE sta ptr1 bcc @L1 inc ptr1+1 @L1: ldx ptr1+1 bne @L2 cmp #HEAP_MIN_BLOCKSIZE+1 bcs @L2 lda #HEAP_MIN_BLOCKSIZE sta ptr1 ; High byte is already zero ; Load a pointer to the freelist into ptr2 @L2: lda __heapfirst sta ptr2 lda __heapfirst+1 sta ptr2+1 ; Search the freelist for a block that is big enough. We will calculate ; (f->size - size) here and keep it, since we need the value later. jmp @L4 @L3: ldy #freeblock::size lda (ptr2),y sub ptr1 tax ; Remember low byte for later iny ; Y points to freeblock::size+1 lda (ptr2),y sbc ptr1+1 bcs BlockFound ; Beware: Contents of a/x/y are known! ; Next block in list iny ; Points to freeblock::next lda (ptr2),y tax iny ; Points to freeblock::next+1 lda (ptr2),y stx ptr2 sta ptr2+1 @L4: ora ptr2 bne @L3 ; We did not find a block big enough. Try to use new space from the heap top. lda __heapptr add ptr1 ; _heapptr + size tay lda __heapptr+1 adc ptr1+1 bcs OutOfHeapSpace ; On overflow, we're surely out of space cmp __heapend+1 bne @L5 cpy __heapend @L5: bcc TakeFromTop beq TakeFromTop ; Out of heap space OutOfHeapSpace: lda #0 tax Done: rts ; There is enough space left, take it from the heap top TakeFromTop: ldx __heapptr ; p = _heapptr; stx ptr2 ldx __heapptr+1 stx ptr2+1 sty __heapptr ; _heapptr += size; sta __heapptr+1 jmp FillSizeAndRet ; Done ; We found a block big enough. If the block can hold just the ; requested size, use the block in full. Beware: When slicing blocks, ; there must be space enough to create a new one! If this is not the ; case, then use the complete block. ; On input, x/a do contain the remaining size of the block. The zero ; flag is set if the high byte of this remaining size is zero. BlockFound: bne SliceBlock ; Block is large enough to slice cpx #HEAP_MIN_BLOCKSIZE ; Check low byte bcs SliceBlock ; Jump if block is large enough to slice ; The block is too small to slice it. Use the block in full. The block ; does already contain the correct size word, all we have to do is to ; remove it from the free list. ldy #freeblock::prev+1 ; Load f->prev lda (ptr2),y sta ptr3+1 dey lda (ptr2),y sta ptr3 dey ; Points to freeblock::next+1 ora ptr3+1 beq @L1 ; Jump if f->prev zero ; We have a previous block, ptr3 contains its address. ; Do f->prev->next = f->next lda (ptr2),y ; Load high byte of f->next sta (ptr3),y ; Store high byte of f->prev->next dey ; Points to next lda (ptr2),y ; Load low byte of f->next sta (ptr3),y ; Store low byte of f->prev->next jmp @L2 ; This is the first block, correct the freelist pointer ; Do _hfirst = f->next @L1: lda (ptr2),y ; Load high byte of f->next sta __heapfirst+1 dey ; Points to next lda (ptr2),y ; Load low byte of f->next sta __heapfirst ; Check f->next. Y points always to next if we come here @L2: lda (ptr2),y ; Load low byte of f->next sta ptr3 iny ; Points to next+1 lda (ptr2),y ; Load high byte of f->next sta ptr3+1 iny ; Points to prev ora ptr3 beq @L3 ; Jump if f->next zero ; We have a next block, ptr3 contains its address. ; Do f->next->prev = f->prev lda (ptr2),y ; Load low byte of f->prev sta (ptr3),y ; Store low byte of f->next->prev iny ; Points to prev+1 lda (ptr2),y ; Load high byte of f->prev sta (ptr3),y ; Store high byte of f->prev->next jmp RetUserPtr ; Done ; This is the last block, correct the freelist pointer. ; Do _hlast = f->prev @L3: lda (ptr2),y ; Load low byte of f->prev sta __heaplast iny ; Points to prev+1 lda (ptr2),y ; Load high byte of f->prev sta __heaplast+1 jmp RetUserPtr ; Done ; We must slice the block found. Cut off space from the upper end, so we ; can leave the actual free block chain intact. SliceBlock: ; Decrement the size of the block. Y points to size+1. dey ; Points to size lda (ptr2),y ; Low byte of f->size sub ptr1 sta (ptr2),y tax ; Save low byte of f->size in X iny ; Points to size+1 lda (ptr2),y ; High byte of f->size sbc ptr1+1 sta (ptr2),y ; Set f to the space above the current block, which is the new block returned ; to the caller. txa ; Get low byte of f->size add ptr2 tax lda (ptr2),y ; Get high byte of f->size adc ptr2+1 stx ptr2 sta ptr2+1 ; Fill the size and start address into the admin space of the block ; (struct usedblock) and return the user pointer FillSizeAndRet: ldy #usedblock::size ; p->size = size; lda ptr1 ; Low byte of block size sta (ptr2),y iny ; Points to freeblock::size+1 lda ptr1+1 sta (ptr2),y RetUserPtr: ldy #usedblock::start ; p->start = p lda ptr2 sta (ptr2),y iny lda ptr2+1 sta (ptr2),y ; Return the user pointer, which points behind the struct usedblock lda ptr2 ; return ++p; ldx ptr2+1 add #HEAP_ADMIN_SPACE bcc @L9 inx @L9: rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/memchr.s��������������������������������������������������������������������0000664�0000000�0000000�00000002230�13473601511�0016407�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-05-05 ; ; void* __fastcall__ memchr (const void* p, int c, size_t n); ; .export _memchr .import popax, popptr1, return0 .importzp ptr1, ptr2 .proc _memchr eor #$FF sta ptr2 txa eor #$FF sta ptr2+1 ; Save ones complement of n jsr popax ; get c pha jsr popptr1 ; get p ; ldy #$00 is guaranteed by popptr1 pla ; Get c ldx ptr2 ; Use X as low counter byte L1: inx beq L3 L2: cmp (ptr1),y beq found iny bne L1 inc ptr1+1 bne L1 ; Branch always L3: inc ptr2+1 ; Bump counter high byte bne L2 ; Not found, return NULL notfound: jmp return0 ; Found, return pointer to char found: ldx ptr1+1 ; get high byte of pointer tya ; low byte offset clc adc ptr1 bcc L9 inx L9: rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/memcmp.s��������������������������������������������������������������������0000664�0000000�0000000�00000003345�13473601511�0016422�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 15.09.2000 ; ; int memcmp (const void* p1, const void* p2, size_t count); ; .export _memcmp .import popax, popptr1, return0 .importzp ptr1, ptr2, ptr3 _memcmp: ; Calculate (-count-1) and store it into ptr3. This is some overhead here but ; saves time in the compare loop eor #$FF sta ptr3 txa eor #$FF sta ptr3+1 ; Get the pointer parameters jsr popax ; Get p2 sta ptr2 stx ptr2+1 jsr popptr1 ; Get p1 ; Loop initialization ;ldy #$00 ; Initialize pointer (Y=0 guaranteed by popptr1) ldx ptr3 ; Load low counter byte into X ; Head of compare loop: Test for the end condition Loop: inx ; Bump low byte of (-count-1) beq BumpHiCnt ; Jump on overflow ; Do the compare Comp: lda (ptr1),y cmp (ptr2),y bne NotEqual ; Jump if bytes not equal ; Bump the pointers iny ; Increment pointer bne Loop inc ptr1+1 ; Increment high bytes inc ptr2+1 bne Loop ; Branch always (pointer wrap is illegal) ; Entry on low counter byte overflow BumpHiCnt: inc ptr3+1 ; Bump high byte of (-count-1) bne Comp ; Jump if not done jmp return0 ; Count is zero, areas are identical ; Not equal, check which one is greater NotEqual: bcs Greater ldx #$FF ; Make result negative rts Greater: ldx #$01 ; Make result positive rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/memcpy.s��������������������������������������������������������������������0000664�0000000�0000000�00000005256�13473601511�0016441�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-08-20 ; Performance increase (about 20%) by ; Christian Krueger, 2009-09-13 ; ; void* __fastcall__ memcpy (void* dest, const void* src, size_t n); ; ; NOTE: This function contains entry points for memmove, which will ressort ; to memcpy for an upwards copy. Don't change this module without looking ; at memmove! ; .export _memcpy, memcpy_upwards, memcpy_getparams .import popax, popptr1 .importzp sp, ptr1, ptr2, ptr3 ; ---------------------------------------------------------------------- _memcpy: jsr memcpy_getparams memcpy_upwards: ; assert Y = 0 ldx ptr3+1 ; Get high byte of n beq L2 ; Jump if zero L1: .repeat 2 ; Unroll this a bit to make it faster... lda (ptr1),Y ; copy a byte sta (ptr2),Y iny .endrepeat bne L1 inc ptr1+1 inc ptr2+1 dex ; Next 256 byte block bne L1 ; Repeat if any ; the following section could be 10% faster if we were able to copy ; back to front - unfortunately we are forced to copy strict from ; low to high since this function is also used for ; memmove and blocks could be overlapping! ; { L2: ; assert Y = 0 ldx ptr3 ; Get the low byte of n beq done ; something to copy L3: lda (ptr1),Y ; copy a byte sta (ptr2),Y iny dex bne L3 ; } done: jmp popax ; Pop ptr and return as result ; ---------------------------------------------------------------------- ; Get the parameters from stack as follows: ; ; size --> ptr3 ; src --> ptr1 ; dest --> ptr2 ; First argument (dest) will remain on stack and is returned in a/x! memcpy_getparams: ; IMPORTANT! Function has to leave with Y=0! sta ptr3 stx ptr3+1 ; save n to ptr3 jsr popptr1 ; save src to ptr1 ; save dest to ptr2 iny ; Y=0 guaranteed by popptr1, we need '1' here... ; (direct stack access is three cycles faster ; (total cycle count with return)) lda (sp),y tax stx ptr2+1 ; save high byte of ptr2 dey ; Y = 0 lda (sp),y ; Get ptr2 low sta ptr2 rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/memmove.s�������������������������������������������������������������������0000664�0000000�0000000�00000004642�13473601511�0016612�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2003-08-20, Ullrich von Bassewitz ; 2009-09-13, Christian Krueger -- performance increase (about 20%), 2013-07-25 improved unrolling ; 2015-10-23, Greg King ; ; void* __fastcall__ memmove (void* dest, const void* src, size_t size); ; ; NOTE: This function uses entry points from memcpy! ; .export _memmove .import memcpy_getparams, memcpy_upwards, popax .importzp ptr1, ptr2, ptr3, ptr4, tmp1 .macpack generic .macpack longbranch ; ---------------------------------------------------------------------- _memmove: jsr memcpy_getparams ; Check for the copy direction. If dest < src, we must copy upwards (start at ; low addresses and increase pointers), otherwise we must copy downwards ; (start at high addresses and decrease pointers). cmp ptr1 txa sbc ptr1+1 jcc memcpy_upwards ; Branch if dest < src (upwards copy) ; Copy downwards. Adjust the pointers to the end of the memory regions. lda ptr1+1 add ptr3+1 sta ptr1+1 lda ptr2+1 add ptr3+1 sta ptr2+1 ; handle fractions of a page size first ldy ptr3 ; count, low byte bne @entry ; something to copy? beq PageSizeCopy ; here like bra... @copyByte: lda (ptr1),y sta (ptr2),y @entry: dey bne @copyByte lda (ptr1),y ; copy remaining byte sta (ptr2),y PageSizeCopy: ; assert Y = 0 ldx ptr3+1 ; number of pages beq done ; none? -> done @initBase: dec ptr1+1 ; adjust base... dec ptr2+1 dey ; in entry case: 0 -> FF @copyBytes: .repeat 3 ; unroll this a bit to make it faster... lda (ptr1),y ; important: unrolling three times gives a nice sta (ptr2),y ; 255/3 = 85 loop which ends at 0 dey .endrepeat @copyEntry: ; in entry case: 0 -> FF bne @copyBytes lda (ptr1),y ; Y = 0, copy last byte sta (ptr2),y dex ; one page to copy less bne @initBase ; still a page to copy? ; Done, return dest done: jmp popax ; Pop ptr and return as result ����������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/memset.s��������������������������������������������������������������������0000664�0000000�0000000�00000006147�13473601511�0016441�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; void* __fastcall__ memset (void* ptr, int c, size_t n); ; void* __fastcall__ _bzero (void* ptr, size_t n); ; void __fastcall__ bzero (void* ptr, size_t n); ; ; Ullrich von Bassewitz, 29.05.1998 ; Performance increase (about 20%) by ; Christian Krueger, 12.09.2009, slightly improved 12.01.2011 ; ; NOTE: bzero will return it's first argument as memset does. It is no problem ; to declare the return value as void, since it may 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 a/x is of any use. ; .export _memset, _bzero, __bzero .import popax .importzp sp, ptr1, ptr2, ptr3 _bzero: __bzero: sta ptr3 stx ptr3+1 ; Save n ldx #0 ; Fill with zeros beq common _memset: sta ptr3 ; Save n stx ptr3+1 jsr popax ; Get c tax ; Common stuff for memset and bzero from here common: ; Fill value is in X! ldy #1 lda (sp),y sta ptr1+1 ; save high byte of ptr dey ; Y = 0 lda (sp),y ; Get ptr sta ptr1 lsr ptr3+1 ; divide number of ror ptr3 ; bytes by two to increase bcc evenCount ; speed (ptr3 = ptr3/2) oddCount: ; y is still 0 here txa ; restore fill value sta (ptr1),y ; save value and increase inc ptr1 ; dest. pointer bne evenCount inc ptr1+1 evenCount: lda ptr1 ; build second pointer section clc adc ptr3 ; ptr2 = ptr1 + (length/2) <- ptr3 sta ptr2 lda ptr1+1 adc ptr3+1 sta ptr2+1 txa ; restore fill value ldx ptr3+1 ; Get high byte of n beq L2 ; Jump if zero ; Set 256/512 byte blocks ; y is still 0 here L1: .repeat 2 ; Unroll this a bit to make it faster sta (ptr1),y ; Set byte in lower section sta (ptr2),y ; Set byte in upper section iny .endrepeat bne L1 inc ptr1+1 inc ptr2+1 dex ; Next 256 byte block bne L1 ; Repeat if any ; Set the remaining bytes if any L2: ldy ptr3 ; Get the low byte of n beq leave ; something to set? No -> leave L3: dey sta (ptr1),y ; set bytes in low sta (ptr2),y ; and high section bne L3 ; flags still up to date from dey! leave: jmp popax ; Pop ptr and return as result �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/mkdir.s���������������������������������������������������������������������0000664�0000000�0000000�00000000720�13473601511�0016244�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2005-08-30 ; ; int mkdir (const char* name, ...); /* May take a mode argument */ ; .export _mkdir .import __sysmkdir .import __mappederrno ;-------------------------------------------------------------------------- .proc _mkdir jsr __sysmkdir ; Call the machine specific function jmp __mappederrno ; Store into _oserror, set errno, return 0/-1 .endproc ������������������������������������������������cc65-2.18/libsrc/common/mktime.c��������������������������������������������������������������������0000664�0000000�0000000�00000015104�13473601511�0016406�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* mktime.c */ /* */ /* Make calendar time from broken down time and cleanup */ /* */ /* */ /* */ /* (C) 2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <limits.h> #include <stdlib.h> #include <time.h> /*****************************************************************************/ /* Data */ /*****************************************************************************/ #define JANUARY 0 #define FEBRUARY 1 #define DECEMBER 11 #define JAN_1_1970 4 /* 1/1/1970 is a thursday */ static const unsigned char MonthLength [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; static const unsigned MonthDays [] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ static unsigned char __fastcall__ IsLeapYear (unsigned Year) /* Returns 1 if the given year is a leap year */ { return (((Year % 4) == 0) && ((Year % 100) != 0 || (Year % 400) == 0)); } time_t __fastcall__ mktime (register struct tm* TM) /* Make a time in seconds since 1/1/1970 from the broken down time in TM. ** A call to mktime does also correct the time in TM to contain correct ** values. */ { register div_t D; int Max; unsigned DayCount; /* Check if TM is valid */ if (TM == 0) { /* Invalid data */ goto Error; } /* Adjust seconds. */ D = div (TM->tm_sec, 60); TM->tm_sec = D.rem; /* Adjust minutes */ if (TM->tm_min + D.quot < 0) { goto Error; } TM->tm_min += D.quot; D = div (TM->tm_min, 60); TM->tm_min = D.rem; /* Adjust hours */ if (TM->tm_hour + D.quot < 0) { goto Error; } TM->tm_hour += D.quot; D = div (TM->tm_hour, 24); TM->tm_hour = D.rem; /* Adjust days */ if (TM->tm_mday + D.quot < 0) { goto Error; } TM->tm_mday += D.quot; /* Adjust month and year. This is an iterative process, since changing ** the month will change the allowed days for this month. */ while (1) { /* Make sure, month is in the range 0..11 */ D = div (TM->tm_mon, 12); TM->tm_mon = D.rem; if (TM->tm_year + D.quot < 0) { goto Error; } TM->tm_year += D.quot; /* Now check if mday is in the correct range, if not, correct month ** and eventually year and repeat the process. */ if (TM->tm_mon == FEBRUARY && IsLeapYear (TM->tm_year + 1900)) { Max = 29; } else { Max = MonthLength[TM->tm_mon]; } if (TM->tm_mday > Max) { /* Must correct month and eventually, year */ if (TM->tm_mon == DECEMBER) { TM->tm_mon = JANUARY; ++TM->tm_year; } else { ++TM->tm_mon; } TM->tm_mday -= Max; } else { /* Done */ break; } } /* Ok, all time/date fields are now correct. Calculate the days in this ** year. */ TM->tm_yday = MonthDays[TM->tm_mon] + TM->tm_mday - 1; if (TM->tm_mon > FEBRUARY && IsLeapYear (TM->tm_year + 1900)) { ++TM->tm_yday; } /* Calculate days since 1/1/1970. In the complete epoch (1/1/1970 to ** somewhere in 2038) all years dividable by 4 are leap years, so ** dividing by 4 gives the days that must be added cause of leap years. ** (and the last leap year before 1970 was 1968) */ DayCount = ((unsigned) (TM->tm_year-70)) * 365U + (((unsigned) (TM->tm_year-(68+1))) / 4) + TM->tm_yday; /* Calculate the weekday */ TM->tm_wday = (JAN_1_1970 + DayCount) % 7; /* No (US) daylight saving (for now) */ TM->tm_isdst = 0; /* Return seconds since 1970 */ return DayCount * 86400UL + ((unsigned) TM->tm_hour) * 3600UL + ((unsigned) TM->tm_min) * 60U + ((unsigned) TM->tm_sec) - _tz.timezone; Error: /* Error exit */ return (time_t) -1L; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/modfree.s�������������������������������������������������������������������0000664�0000000�0000000�00000005204�13473601511�0016561�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������;*****************************************************************************/ ;* */ ;* modfree.s */ ;* */ ;* Free loaded o65 modules */ ;* */ ;* */ ;* */ ;* (C) 2002 Ullrich von Bassewitz */ ;* Wacholderweg 14 */ ;* D-70597 Stuttgart */ ;* EMail: uz@musoftware.de */ ;* */ ;* */ ;* 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. */ ;* */ ;*****************************************************************************/ .export _mod_free .import _free _mod_free = _free ; Just free the memory ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/modload.s�������������������������������������������������������������������0000664�0000000�0000000�00000040067�13473601511�0016565�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������;*****************************************************************************/ ;* */ ;* modload.s */ ;* */ ;* o65 module loader for the cc65 library */ ;* */ ;* */ ;* */ ;* (C) 2002 Ullrich von Bassewitz */ ;* Wacholderweg 14 */ ;* D-70597 Stuttgart */ ;* EMail: uz@musoftware.de */ ;* */ ;* */ ;* This software is provided 'as-is', without any expressed or implied */ ;* warranty. In no event will the authors be held liable for any damages */ ;* arising from the use of this software. */ ;* */ ;* Permission is granted to anyone to use this software for any purpose, */ ;* including commercial applications, and to alter it and redistribute it */ ;* freely, subject to the following restrictions: */ ;* */ ;* 1. The origin of this software must not be misrepresented; you must not */ ;* claim that you wrote the original software. If you use this software */ ;* in a product, an acknowledgment in the product documentation would be */ ;* appreciated but is not required. */ ;* 2. Altered source versions must be plainly marked as such, and must not */ ;* be misrepresented as being the original software. */ ;* 3. This notice may not be removed or altered from any source */ ;* distribution. */ ;* */ ;*****************************************************************************/ .include "o65.inc" .include "modload.inc" .include "zeropage.inc" .import pushax, pusha0, push0, push1, decax1 .import _malloc, _free, _bzero .import __ZP_START__ ; Linker generated .macpack generic ;------------------------------------------------------------------------------ ; Variables stored in the register bank in the zero page. Placing the variables ; here will protect them when calling other C functions. Module = regbank+0 ; Pointer to module memory Ctrl = regbank+2 ; Pointer to mod_ctrl structure TPtr = regbank+4 ; Pointer to module data for relocation ;------------------------------------------------------------------------------ ; Static module data .bss ; Save areas and error recovery data Stack: .byte 0 ; Old stackpointer RegBankSave: .res regbanksize ; Save area for register bank ; The header of the o65 file. Since we don't need the first 8 bytes any ; longer, once we've checked them, we will overlay them with other data to ; save a few bytes. Header: .tag O65_HDR ; The o65 header ; Input InputByte = Header ; Byte read from input ; Relocation RelocVal = Header + 1 ; Relocation value .data Read: jmp $FFFF ; Jump to read routine .rodata ExpectedHdr: .byte O65_MARKER_0, O65_MARKER_1 ; non C64 marker .byte O65_MAGIC_0, O65_MAGIC_1, O65_MAGIC_2 ; Magic ("o65") .byte O65_VERSION ; Version .word O65_MODE_CC65 ; Mode word ExpectedHdrSize = * - ExpectedHdr ;------------------------------------------------------------------------------ ; PushCallerData: Push the callerdata member from control structure onto the ; C stack. .code PushCallerData: ldy #MOD_CTRL::CALLERDATA+1 lda (Ctrl),y tax dey lda (Ctrl),y jmp pushax ;------------------------------------------------------------------------------ ; RestoreRegBank: Restore the register bank contents from the save area. Will ; destroy A and X (the latter will be zero on return). .code RestoreRegBank: ldx #6 @L1: lda RegBankSave-1,x sta regbank-1,x dex bne @L1 rts ;------------------------------------------------------------------------------ ; GetReloc: Return a relocation value based on the segment in A. ; The routine uses some knowledge about the values to make the code shorter. .code GetReloc: cmp #O65_SEGID_TEXT bcc FormatError cmp #O65_SEGID_ZP beq @L1 bcs FormatError ; Text, data and bss segment lda Module ldx Module+1 ; Return start address of buffer rts ; Zero page relocation @L1: lda #<__ZP_START__ ldx #>__ZP_START__ rts ;------------------------------------------------------------------------------ ; ReadByte: Read one byte with error checking into InputByte and A. ; ReadAndCheckError: Call read with the current C stack and check for errors. .bss ReadSize: .res 2 .code ReadByte: ; C->read (C->callerdata, &B, 1) jsr PushCallerData lda #<InputByte ldx #>InputByte jsr pushax ldx #0 lda #1 ; This is a second entry point used by the other calls to Read ReadAndCheckError: sta ReadSize stx ReadSize+1 jsr Read ; Check the return code and bail out in case of problems cmp ReadSize bne @L1 cpx ReadSize+1 beq @L2 ; Jump if ok @L1: lda #MLOAD_ERR_READ bne CleanupAndExit ; Done @L2: lda InputByte ; If called ReadByte, load the byte read Done: rts ;------------------------------------------------------------------------------ ; FormatError: Bail out with an o65 format error .code FormatError: lda #MLOAD_ERR_FMT ; bne CleanupAndExit ; Branch always ;------------------------------------------------------------------------------ ; CleanupAndExit: Free any allocated resources, restore the stack and return ; to the caller. .code CleanupAndExit: ; Restore the stack so we may return to the caller from here ldx Stack txs ; Save the error return code pha ; Check if we have to free the allocated block lda Module ldx Module+1 bne @L1 tay ; Test high byte beq @L2 @L1: jsr _free ; Free the allocated block ; Restore the register bank @L2: jsr RestoreRegBank ; Restore the error code and return to the caller ldx #$00 ; Load the high byte pla rts ;------------------------------------------------------------------------------ ; RelocSeg: Relocate the segment pointed to by a/x .code RelocSeg: jsr decax1 ; Start value is segment-1 sta TPtr stx TPtr+1 Loop: jsr ReadByte ; Read byte from relocation table beq Done ; Bail out if end of table reached cmp #255 ; Special offset? bne @L1 ; Increment offset by 254 and continue lda TPtr add #254 sta TPtr bcc Loop inc TPtr+1 jmp Loop ; Increment offset by A @L1: add TPtr sta TPtr bcc @L2 inc TPtr+1 ; Read the relocation byte, extract the segment id, fetch the corresponding ; relocation value and place it into ptr1 @L2: jsr ReadByte and #O65_SEGID_MASK jsr GetReloc sta RelocVal stx RelocVal+1 ; Get the relocation byte again, this time extract the relocation type. lda InputByte and #O65_RTYPE_MASK ; Check for and handle the different relocation types. cmp #O65_RTYPE_WORD beq RelocWord cmp #O65_RTYPE_HIGH beq RelocHigh cmp #O65_RTYPE_LOW bne FormatError ; Relocate the low byte RelocLow: ldy #0 clc lda RelocVal bcc AddCommon ; Relocate a high byte RelocHigh: jsr ReadByte ; Read low byte from relocation table ldy #0 clc adc RelocVal ; We just need the carry AddHigh: lda RelocVal+1 AddCommon: adc (TPtr),y sta (TPtr),y jmp Loop ; Done, next entry ; Relocate a word RelocWord: ldy #0 clc lda RelocVal adc (TPtr),y sta (TPtr),y iny bne AddHigh ; Branch always (add high byte) ;------------------------------------------------------------------------------ ; mod_load: Load and relocate an o65 module .code _mod_load: ; Save the register bank and clear the Module pointer pha ldy #6 @L1: lda regbank-1,y sta RegBankSave-1,y dey bne @L1 sty Module sty Module+1 pla ; Save the passed parameter sta Ctrl stx Ctrl+1 ; Save the stack pointer so we can bail out even from subroutines tsx stx Stack ; Get the read function pointer from the control structure and place it into ; our call vector ldy #MOD_CTRL::READ lda (Ctrl),y sta Read+1 iny lda (Ctrl),y sta Read+2 ; Read the o65 header: C->read (C->callerdata, &H, sizeof (H)) jsr PushCallerData lda #<Header ldx #>Header jsr pushax lda #.sizeof(O65_HDR) ldx #0 ; Always less than 256 jsr ReadAndCheckError ; Bails out in case of errors ; We read the o65 header successfully. Validate it. ldy #ExpectedHdrSize-1 ValidateHeader: lda Header,y cmp ExpectedHdr,y bne HeaderError dey bpl ValidateHeader ; Header is ok as far as we can say now. Read all options, check for the ; OS option and ignore all others. The OS option contains a version number ; and the module id as additional data. iny ; Y = $00 sty TPtr+1 ; Flag for OS option read Opt: jsr ReadByte ; Read the length byte beq OptDone ; Jump if done sta TPtr ; Use TPtr as a counter ; An option has a length of at least 2 bytes cmp #2 bcc HeaderError ; Must be 2 bytes total at least ; Check for the OS option dec TPtr jsr ReadByte ; Get the option type cmp #O65_OPT_OS ; OS option? bne SkipOpt ; No: Skip lda TPtr ; Get remaining length+1 cmp #5 ; CC65 has 6 bytes total bne OSError jsr ReadByte ; Get the operating system cmp #O65_OS_CC65 bne OSError ; Wrong operating system jsr ReadByte ; Get the version number, expect zero bne OSError ; Wrong version jsr ReadByte ; Get low byte of id ldy #MOD_CTRL::MODULE_ID sta (Ctrl),y jsr ReadByte ldy #MOD_CTRL::MODULE_ID+1 sta (Ctrl),y inc TPtr+1 ; Remember that we got the OS jmp Opt ; Skip one option SkipOpt: dec TPtr beq Opt ; Next option jsr ReadByte ; Skip one byte jmp SkipOpt ; Operating system error OSError: lda #MLOAD_ERR_OS jmp CleanupAndExit ; Options done, check that we got the OS option OptDone: lda TPtr+1 bne CalcSizes ; Entry point for header errors HeaderError: lda #MLOAD_ERR_HDR jmp CleanupAndExit ; Skipped all options. Calculate the size of text+data and of text+data+bss ; (the latter is the size of the memory block we need). We will store the ; total module size also into the control structure for evaluation by the ; caller CalcSizes: lda Header + O65_HDR::TLEN add Header + O65_HDR::DLEN sta TPtr lda Header + O65_HDR::TLEN + 1 adc Header + O65_HDR::DLEN + 1 sta TPtr+1 lda TPtr add Header + O65_HDR::BLEN pha ; Save low byte of total size ldy #MOD_CTRL::MODULE_SIZE sta (Ctrl),y lda TPtr+1 adc Header + O65_HDR::BLEN + 1 iny sta (Ctrl),y tax pla ; Restore low byte of total size ; Total memory size is now in a/x. Allocate memory and remember the result, ; both, locally and in the control structure so it the caller can access ; the memory block. After that, check if we got the requested memory. jsr _malloc sta Module stx Module+1 ldy #MOD_CTRL::MODULE sta (Ctrl),y txa iny sta (Ctrl),y ora Module bne GotMem ; Could not allocate memory lda #MLOAD_ERR_MEM jmp CleanupAndExit ; Control structure is complete now. Clear the bss segment. ; bzero (bss_addr, bss_size) GotMem: lda Module add TPtr pha lda Module+1 adc TPtr+1 ; Module + tlen + dlen tax pla jsr pushax lda Header + O65_HDR::BLEN ldx Header + O65_HDR::BLEN+1 jsr _bzero ; bzero (bss, bss_size); ; Load code and data segment into memory. The sum of the sizes of ; code+data segment is still in TPtr. ; C->read (C->callerdata, C->module, H.tlen + H.dlen) jsr PushCallerData lda Module ldx Module+1 jsr pushax lda TPtr ldx TPtr+1 jsr ReadAndCheckError ; Bails out in case of errors ; We've got the code and data segments in memory. Next section contains ; undefined references which we don't support. So check if the count of ; undefined references is actually zero. jsr ReadByte bne Undef jsr ReadByte beq Reloc Undef: jmp FormatError ; Number of undefined references was zero. Next come the relocation tables ; for code and data segment. Relocate the code segment Reloc: lda Module ldx Module + 1 ; Code segment address jsr RelocSeg ; Relocate the data segment lda Module add Header + O65_HDR::TLEN pha lda Module + 1 adc Header + O65_HDR::TLEN + 1 tax pla ; Data segment address in a/x jsr RelocSeg ; We're done. Restore the register bank and return a success code jsr RestoreRegBank ; X will be zero on return lda #MLOAD_OK rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/mul20.s���������������������������������������������������������������������0000664�0000000�0000000�00000002464�13473601511�0016104�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; mul20.s ; ; This file is part of ; cc65 - a freeware C compiler for 6502 based systems ; ; https://github.com/cc65/cc65 ; ; See "LICENSE" file for legal information. ; ; ; unsigned int __fastcall__ mul20(unsigned char value); ; ; REMARKS: Function is defined to return with carry-flag cleared .importzp tmp4 .export _mul20 .proc _mul20 ; = 30 bytes, 41/46 cycles sta tmp4 ; remember value for later addition... ldx #0 ; clear high-byte asl a ; * 2 bcc mul4 ; high-byte affected? ldx #2 ; this will be the 1st high-bit soon... mul4: asl a ; * 4 bcc mul5 ; high-byte affected? inx ; => yes, apply to 0 high-bit clc ; prepare addition mul5: adc tmp4 ; * 5 bcc mul10 ; high-byte affected? inx ; yes, correct... mul10: stx tmp4 ; continue with classic shifting... asl a ; * 10 rol tmp4 asl a ; * 20 rol tmp4 ldx tmp4 ; deliver high-byte in X rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/mul40.s���������������������������������������������������������������������0000664�0000000�0000000�00000002561�13473601511�0016104�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; mul40.s ; ; This file is part of ; cc65 - a freeware C compiler for 6502 based systems ; ; https://github.com/cc65/cc65 ; ; See "LICENSE" file for legal information. ; ; ; unsigned int __fastcall__ mul40(unsigned char value); ; ; REMARKS: Function is defined to return with carry-flag cleared .importzp tmp4 .export _mul40 .proc _mul40 ; = 33 bytes, 48/53 cycles sta tmp4 ; remember value for later addition... ldx #0 ; clear high-byte asl a ; * 2 bcc mul4 ; high-byte affected? ldx #2 ; this will be the 1st high-bit soon... mul4: asl a ; * 4 bcc mul5 ; high-byte affected? inx ; => yes, apply to 0 high-bit clc ; prepare addition mul5: adc tmp4 ; * 5 bcc mul10 ; high-byte affected? inx ; yes, correct... mul10: stx tmp4 ; continue with classic shifting... asl a ; * 10 rol tmp4 asl a ; * 20 rol tmp4 asl a ; * 40 rol tmp4 ldx tmp4 ; deliver high-byte in X rts .endproc �����������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/perror.c��������������������������������������������������������������������0000664�0000000�0000000�00000005606�13473601511�0016437�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* perror.c */ /* */ /* Print a system error message */ /* */ /* */ /* */ /* (C) 1998-2010, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> #include <errno.h> void __fastcall__ perror (const char* msg) { /* Fetch the message that corresponds to errno */ const char* errormsg = strerror (_errno); /* Different output depending on msg */ if (msg) { fprintf (stderr, "%s: %s\n", msg, errormsg); } else { fprintf (stderr, "%s\n", errormsg); } } ��������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/pmemalign.c�����������������������������������������������������������������0000664�0000000�0000000�00000017075�13473601511�0017102�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* posix_memalign */ /* */ /* Allocate an aligned memory block */ /* */ /* */ /* */ /* (C) 2004-2005 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided "as-is," without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated, but is not required. */ /* 2. Alterred source versions must be marked plainly as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or alterred from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stddef.h> /* define NULL */ #include <stdlib.h> /* declare function's prototype */ #include <_heap.h> #include <errno.h> #define EOK 0 /* No errors (non-standard name) */ /* This is a very simple version of an aligned memory allocator. We will ** allocate a greater block, so that we can place the aligned block (that is ** returned) within it. We use our knowledge about the internal heap ** structures to free the unused parts of the bigger block (the two chunks ** below and above the aligned block). */ int __fastcall__ posix_memalign (void** memptr, size_t alignment, size_t size) /* Allocate a block of memory with the given "size", which is aligned to a ** memory address that is a multiple of "alignment". "alignment" MUST NOT be ** zero, and MUST be a power of two; otherwise, this function will return ** EINVAL. The function returns ENOMEM if not enough memory is available ** to satisfy the request. "memptr" must point to a variable; that variable ** will return the address of the allocated memory. Use free() to release that ** allocated block. */ { size_t rawsize; size_t uppersize; size_t lowersize; register struct usedblock* b; /* points to raw Block */ register struct usedblock* u; /* points to User block */ register struct usedblock* p; /* Points to upper block */ /* Handle requests for zero-sized blocks */ if (size == 0) { *memptr = NULL; return EINVAL; } /* Test alignment: is it a power of two? There must be only one bit set. */ if (alignment == 0 || (alignment & --alignment) != 0) { *memptr = NULL; return EINVAL; } /* Augment the block size up to the alignment, and allocate memory. ** We don't need to account for the additional admin. data that's needed to ** manage the used block, because the block returned by malloc() has that ** overhead added one time; and, the worst thing that might happen is that ** we cannot free the upper and lower blocks. */ b = malloc (size + alignment); /* Handle out-of-memory */ if (b == NULL) { *memptr = NULL; return ENOMEM; } /* Create (and return) a new pointer that points to the user-visible ** aligned block. */ u = *memptr = (struct usedblock*) (((unsigned)b + alignment) & ~alignment); /* Get a pointer to the (raw) upper block */ p = (struct usedblock*) ((char*)u + size); /* Get the raw-block pointer, which is located just below the visible ** unaligned block. The first word of this raw block is the total size ** of the block, including the admin. space. */ b = (b-1)->start; rawsize = b->size; /* Check if we can free the space above the user block. That is the case ** if the size of the block is at least sizeof (struct freeblock) bytes, ** and the size of the remaining block is at least that size, too. ** If the upper block is smaller, then we just will pass it to the caller, ** together with the requested aligned block. */ uppersize = rawsize - (lowersize = (char*)p - (char*)b); if (uppersize >= sizeof (struct freeblock) && lowersize >= sizeof (struct freeblock)) { /* Setup the usedblock structure */ p->size = uppersize; p->start = p; /* Generate a pointer to the (upper) user space, and free that block */ free (p + 1); /* Decrease the raw-block size by the amount of space just freed */ rawsize = lowersize; } /* Check if we can free the space below the user block. That is the case ** if the size of the block is at least sizeof (struct freeblock) bytes, ** and the size of the remaining block is at least that size, too. If the ** lower block is smaller, we just will pass it to the caller, together ** with the requested aligned block. ** Beware: We need an additional struct usedblock, in the lower block, ** which is part of the block that is passed back to the caller. */ lowersize = ((char*)u - (char*)b) - sizeof (struct usedblock); if ( lowersize >= sizeof (struct freeblock) && (rawsize - lowersize) >= sizeof (struct freeblock)) { /* b already points to the raw lower-block. ** Set up the usedblock structure. */ b->size = lowersize; b->start = b; /* Generate a pointer to the (lower) user space, and free that block */ free (b + 1); /* Decrease the raw-block size by the amount of space just freed */ rawsize -= lowersize; /* Set b to the raw user-block (that will be returned) */ b = u - 1; } /* u points to the user-visible block, while b points to the raw block, ** and rawsize contains the length of the raw block. Set up the usedblock ** structure, but beware: If we didn't free the lower block, then it is ** split; which means that we must use b to write the size, ** and u to write the start field. */ b->size = rawsize; (u-1)->start = b; return EOK; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/printf.s��������������������������������������������������������������������0000664�0000000�0000000�00000003337�13473601511�0016447�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; int printf (const char* Format, ...); ; ; Ullrich von Bassewitz, 1.12.2000 ; .export _printf .import _stdout, pushax, addysp, _vfprintf .importzp sp, ptr1 .macpack generic ; ---------------------------------------------------------------------------- ; Data .bss ParamSize: .res 1 ; Number of parameter bytes ; ---------------------------------------------------------------------------- ; Code .code _printf: sty ParamSize ; Number of param bytes passed in Y ; We are using a (hopefully) clever trick here to reduce code size. On entry, ; the stack pointer points to the last pushed parameter of the variable ; parameter list. Adding the number of parameter bytes, would result in a ; pointer that points *after* the Format parameter. ; Since we have to push stdout anyway, we will do that here, so ; ; * we will save the subtraction of 2 (__fixargs__) later ; * we will have the address of the Format parameter which needs to ; be pushed next. ; lda _stdout ldx _stdout+1 jsr pushax ; Now calculate the va_list pointer, which does points to Format lda sp ldx sp+1 add ParamSize bcc @L1 inx @L1: sta ptr1 stx ptr1+1 ; Push Format ldy #1 lda (ptr1),y tax dey lda (ptr1),y jsr pushax ; Load va_list (last and __fastcall__ parameter to vfprintf) lda ptr1 ldx ptr1+1 ; Call vfprintf jsr _vfprintf ; Cleanup the stack. We will return what we got from vfprintf ldy ParamSize jmp addysp �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/putchar.s�������������������������������������������������������������������0000664�0000000�0000000�00000000567�13473601511�0016615�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2004-10-06 ; ; int __fastcall__ putchar (int c); ; .export _putchar .import pushax .import _stdout .import _fputc .code _putchar: jsr pushax ; Push c lda _stdout ldx _stdout+1 jmp _fputc ; __fastcall__ function �����������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/putenv.s��������������������������������������������������������������������0000664�0000000�0000000�00000010733�13473601511�0016464�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2005-04-21 ; ; int putenv (char* s); ; ; Note: The function will place s into the environment, *not* a copy! ; .export _putenv .import _malloc, _free .import searchenv, copyenvptr .import __environ, __envcount, __envsize .import return0 .import ptr1:zp, ptr2:zp, ptr3:zp, tmp1:zp .include "errno.inc" .code ;---------------------------------------------------------------------------- ; putenv() .proc _putenv sta ptr1 sta name stx ptr1+1 ; Save name stx name+1 ; Loop over the name to find the '='. If there is no '=', set errno to EINVAL ; and return an error. ldy #$FF @L0: iny lda (ptr1),y bne @L1 lda #EINVAL jmp error ; End of string without '=' found @L1: cmp #'=' bne @L0 ; Remember the offset of the equal sign and replace it by a zero. sty tmp1 lda #$00 sta (ptr1),y ; Search for the string in the environment. searchenv will set the N flag if ; the string is not found, otherwise X contains the index of the entry, ptr2 ; contains the entry and Y the offset of the '=' in the string. ptr3 will ; point to the environment. jsr searchenv ; Before doing anything else, restore the old environment string. ldy tmp1 lda #'=' sta (ptr1),y ; Check the result of searchenv txa ; Did we find the entry? bpl addentry ; Jump if yes ; We didn't find the entry, so we have to add a new one. Before doing so, we ; must check if the size of the _environ array must be increased. ; Note: There must be one additional slot for the final NULL entry. ldx __envcount inx cpx __envsize bcc addnewentry ; Jump if space enough ; We need to increase the size of the environ array. Calculate the new size. ; We will not support a size larger than 64 entries, double the size with ; each overflow, and the starting size is 8 entries. lda __envsize bne @L2 lda #4 ; Start with 4*2 entries @L2: asl a ; Double current size bmi nomem ; Bail out if > 64 sta newsize ; Remember the new size ; Call malloc() and store the result in ptr2 asl a ; Make words ldx #$00 jsr _malloc sta ptr2 stx ptr2+1 ; Check the result of malloc ora ptr2+1 beq nomem ; Copy the old environment pointer to ptr3, and the new one to __environ. ldx #1 @L3: lda __environ,x sta ptr3,x lda ptr2,x sta __environ,x dex bpl @L3 ; Use the new size. lda newsize sta __envsize ; Copy the old environment data into the new space. lda __envcount asl a tay jmp @L5 @L4: lda (ptr3),y sta (ptr2),y @L5: dey bpl @L4 ; Free the old environment space lda ptr3 ldx ptr3+1 jsr _free ; Since free() has destroyed ptr2, we need another copy ... jsr copyenvptr ; Copy __environ to ptr2 ; Bump the environment count and remember it in X. Add the final NULL entry. addnewentry: inc __envcount ldx __envcount txa asl a tay lda #$00 sta (ptr2),y iny sta (ptr2),y ; The index of the new entry is the old environment count. dex txa ; Add the new entry to the slot with index in X. The pointer to the environment ; is already in ptr2, either by a call to searchenv, or by above code. addentry: asl a tay lda name sta (ptr2),y iny lda name+1 sta (ptr2),y ; Done jmp return0 ; Error entries nomem: lda #ENOMEM error: jsr __seterrno lda #$FF ; Return -1 tax rts .endproc ;---------------------------------------------------------------------------- ; data .bss name: .addr 0 ; Pointer to name newsize: .byte 0 ; New environment size �������������������������������������cc65-2.18/libsrc/common/puts.c����������������������������������������������������������������������0000664�0000000�0000000�00000001260�13473601511�0016111�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** puts.c ** ** Ullrich von Bassewitz, 11.08.1998 */ #include <stdio.h> #include <string.h> #include <unistd.h> #include "_file.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ int __fastcall__ puts (const char* s) { static char nl = '\n'; /* Assume stdout is always open */ if (write (stdout->f_fd, s, strlen (s)) < 0 || write (stdout->f_fd, &nl, 1) < 0) { stdout->f_flags |= _FERROR; return -1; } /* Done */ return 0; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/qsort.c���������������������������������������������������������������������0000664�0000000�0000000�00000002723�13473601511�0016273�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** qsort.c ** ** 1998.12.09, Ullrich von Bassewitz ** 2015-06-21, Greg King */ #include <stdlib.h> static void QuickSort (register unsigned char* Base, int Lo, int Hi, register size_t Size, int __fastcall__ (* Compare) (const void*, const void*)) /* Internal recursive function. Works with ints, but this shouldn't be ** a problem. */ { int I, J; /* Quicksort */ while (Hi > Lo) { I = Lo + Size; J = Hi; while (I <= J) { while (I <= J && Compare (Base + Lo, Base + I) >= 0) { I += Size; } while (I <= J && Compare (Base + Lo, Base + J) < 0) { J -= Size; } if (I <= J) { _swap (Base + I, Base + J, Size); I += Size; J -= Size; } } if (J != Lo) { _swap (Base + J, Base + Lo, Size); } if (((unsigned) J) * 2 > (Hi + Lo)) { QuickSort (Base, J + Size, Hi, Size, Compare); Hi = J - Size; } else { QuickSort (Base, Lo, J - Size, Size, Compare); Lo = J + Size; } } } void __fastcall__ qsort (void* base, size_t nmemb, size_t size, int __fastcall__ (* compare) (const void*, const void*)) /* Quicksort implementation */ { if (nmemb > 1) { QuickSort (base, 0, (nmemb-1) * size, size, compare); } } ���������������������������������������������cc65-2.18/libsrc/common/raise.s���������������������������������������������������������������������0000664�0000000�0000000�00000002301�13473601511�0016236�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-03-14 ; ; int __fastcall__ raise (int sig); ; .import jmpvec .include "signal.inc" ;---------------------------------------------------------------------------- ; int __fastcall__ raise (int sig); _raise: cpx #0 bne invalidsig cmp #SIGCOUNT bcs invalidsig ; Save the signal number low byte, then setup the function vector pha asl a tax lda sigtable,x sta jmpvec+1 lda sigtable+1,x sta jmpvec+2 ; Reset the signal handler to SIG_DFL (I don't like this because it may ; introduce race conditions, but it's the simplest way to satisfy the ; standard). lda #<__sig_dfl sta sigtable,x lda #>__sig_dfl sta sigtable+1,x ; Restore the signal number and call the function pla ; Low byte ldx #0 ; High byte jsr jmpvec ; Call signal function ; raise() returns zero on success and any other value on failure lda #0 tax invalidsig: rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/rand.s����������������������������������������������������������������������0000664�0000000�0000000�00000003327�13473601511�0016070�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Randum number generator ; ; Written and donated by Sidney Cadot - sidney@ch.twi.tudelft.nl ; 2016-11-07, modified by Brad Smith ; ; May be distributed with the cc65 runtime using the same license. ; ; ; int rand (void); ; void srand (unsigned seed); ; ; Uses 4-byte state. ; Multiplier must be 1 (mod 4) ; Added value must be 1 (mod 2) ; This guarantees max. period (2**32) ; The lowest bits have poor entropy and ; exhibit easily detectable patterns, so ; only the upper bits 16-22 and 24-31 of the ; 4-byte state are returned. ; ; The best 8 bits, 24-31 are returned in the ; low byte A to provide the best entropy in the ; most commonly used part of the return value. ; .export _rand, _srand .data ; The seed. When srand() is not called, the C standard says that that rand() ; should behave as if srand() was called with an argument of 1 before. rand: .dword 1 .code _rand: clc lda rand+0 ; SEED *= $01010101 adc rand+1 sta rand+1 adc rand+2 sta rand+2 adc rand+3 sta rand+3 clc lda rand+0 ; SEED += $31415927 adc #$27 sta rand+0 lda rand+1 adc #$59 sta rand+1 lda rand+2 adc #$41 sta rand+2 and #$7f ; Suppress sign bit (make it positive) tax lda rand+3 adc #$31 sta rand+3 rts ; return bit (16-22,24-31) in (X,A) _srand: sta rand+0 ; Store the seed stx rand+1 lda #0 sta rand+2 ; Set MSW to zero sta rand+3 rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/realloc.c�������������������������������������������������������������������0000664�0000000�0000000�00000011043�13473601511�0016537�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* realloc.c */ /* */ /* Change the size of an allocated memory block */ /* */ /* */ /* */ /* (C) 1998-2004 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdlib.h> #include <string.h> #include <_heap.h> void* __fastcall__ realloc (void* block, register size_t size) { register struct usedblock* b; struct usedblock* newblock; unsigned oldsize; unsigned newhptr; /* Check the block parameter */ if (!block) { /* Block is NULL, same as malloc */ return malloc (size); } /* Check the size parameter */ if (size == 0) { /* Block is not NULL, but size is: free the block */ free (block); return 0; } /* Make the internal used size from the given size */ size += HEAP_ADMIN_SPACE; if (size < sizeof (struct freeblock)) { size = sizeof (struct freeblock); } /* The word below the user block contains a pointer to the start of the ** raw memory block. The first word of this raw memory block is the full ** size of the block. Get a pointer to the real block, get the old block ** size. */ b = (((struct usedblock*) block) - 1)->start; oldsize = b->size; /* Is the block at the current heap top? */ if (((unsigned) b) + oldsize == ((unsigned) _heapptr)) { /* Check if we've enough memory at the heap top */ newhptr = ((unsigned) _heapptr) - oldsize + size; if (newhptr <= ((unsigned) _heapend)) { /* Ok, there's space enough */ _heapptr = (unsigned*) newhptr; b->size = size; b->start = b; return block; } } /* The given block was not located on top of the heap, or there's no ** room left. Try to allocate a new block and copy the data. */ if (newblock = malloc (size)) { /* Adjust the old size to the user visible portion */ oldsize -= HEAP_ADMIN_SPACE; /* If the new block is larger than the old one, copy the old ** data only */ if (size > oldsize) { size = oldsize; } /* Copy the block data */ memcpy (newblock, block, size); free (block); } return newblock; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/remove.s��������������������������������������������������������������������0000664�0000000�0000000�00000000705�13473601511�0016436�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-08-12 ; ; int __fastcall__ remove (const char* name); ; .export _remove .import __sysremove .import __mappederrno ;-------------------------------------------------------------------------- .proc _remove jsr __sysremove ; Call the machine specific function jmp __mappederrno ; Store into _oserror, set errno, return 0/-1 .endproc �����������������������������������������������������������cc65-2.18/libsrc/common/rename.s��������������������������������������������������������������������0000664�0000000�0000000�00000000735�13473601511�0016413�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-08-12 ; ; int __fastcall__ rename (const char* oldname, const char* newname); ; .export _rename .import __sysrename .import __mappederrno ;-------------------------------------------------------------------------- .proc _rename jsr __sysrename ; Call the machine specific function jmp __mappederrno ; Store into _oserror, set errno, return 0/-1 .endproc �����������������������������������cc65-2.18/libsrc/common/rewind.c��������������������������������������������������������������������0000664�0000000�0000000�00000000655�13473601511�0016415�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** rewind.c ** ** Christian Groessler, 07-Aug-2000 */ #include <stdio.h> /*****************************************************************************/ /* Code */ /*****************************************************************************/ void __fastcall__ rewind (FILE* f) { fseek(f, 0L, SEEK_SET); clearerr(f); } �����������������������������������������������������������������������������������cc65-2.18/libsrc/common/rmdir.s���������������������������������������������������������������������0000664�0000000�0000000�00000000666�13473601511�0016264�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2005-08-30 ; ; int __fastcall__ rmdir (const char* name); ; .export _rmdir .import __sysrmdir .import __mappederrno ;-------------------------------------------------------------------------- .proc _rmdir jsr __sysrmdir ; Call the machine specific function jmp __mappederrno ; Store into _oserror, set errno, return 0/-1 .endproc ��������������������������������������������������������������������������cc65-2.18/libsrc/common/scanf.s���������������������������������������������������������������������0000664�0000000�0000000�00000003400�13473601511�0016226�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; int scanf(const char* Format, ...); ; ; 2000-12-01, Ullrich von Bassewitz ; 2004-12-31, Greg King ; .export _scanf .import _stdin, pushax, addysp, _vfscanf .import sp:zp, ptr1:zp .macpack generic ; ---------------------------------------------------------------------------- ; Code ; _scanf: sty ArgSize ; Number of argument bytes passed in .Y ; We are using a (hopefully) clever trick here to reduce code size. On entry, ; the stack pointer points to the last pushed argument of the variable ; argument list. Adding the number of argument bytes, would result in a ; pointer that points _above_ the Format argument. ; Because we have to push stdin anyway, we will do that here, so: ; ; * we will save the subtraction of 2 (__fixargs__) later; ; * we will have the address of the Format argument which needs to ; be pushed next. lda _stdin ldx _stdin+1 jsr pushax ; Now, calculate the va_list pointer, which does point to Format. lda sp ldx sp+1 add ArgSize bcc @L1 inx @L1: sta ptr1 stx ptr1+1 ; Push a copy of Format. ldy #1 lda (ptr1),y tax dey lda (ptr1),y jsr pushax ; Load va_list [last and __fastcall__ argument to vfscanf()]. lda ptr1 ldx ptr1+1 ; Call vfscanf(). jsr _vfscanf ; Clean up the stack. We will return what we got from vfscanf(). ldy ArgSize jmp addysp ; ---------------------------------------------------------------------------- ; Data ; .bss ArgSize: .res 1 ; Number of argument bytes ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/searchenv.s�����������������������������������������������������������������0000664�0000000�0000000�00000004136�13473601511�0017121�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2005-04-21 ; ; Search the environment for a string. ; .export searchenv, copyenvptr .import __environ, __envcount .import ptr1:zp, ptr2:zp, ptr3:zp .code ;---------------------------------------------------------------------------- ; searchenv: ; ; ptr1 must contain the string to search for. On exit, the N flag will tell ; if the entry was found, and X will contain the index of the environment ; string in the environment (a negative value if the entry was not found). ; On success, ptr3 will contain the entry and Y the offset of the '=' within ; the string. .proc searchenv ; Copy the pointer to the environment to the zero page jsr copyenvptr ; Loop over all environment entries trying to find the requested one. ldx __envcount @L0: dex bmi @L9 ; Out of entries ; Since the maximum number of entries is 64, the index can only be 63, so ; the following shift cannot overflow and the carry is clear. txa asl a ; Mul by two for word access tay lda (ptr2),y sta ptr3 iny lda (ptr2),y sta ptr3+1 ; ptr1 points to name, ptr3 points to the next environment entry. Compare the ; two. The following loop limits the length of name to 255 bytes. ldy #$00 @L1: lda (ptr1),y beq @L2 ; Jump on end of name cmp (ptr3),y bne @L0 ; Next environment entry iny bne @L1 ; End of name reached, check if the environment entry contains a '=' char @L2: lda (ptr3),y cmp #'=' bne @L0 ; Next environment entry ; Done. The function result is in X and the N flag is set correctly. @L9: rts .endproc ;---------------------------------------------------------------------------- ; copyenvptr: Copy _environ to ptr2 ; .proc copyenvptr lda __environ sta ptr2 lda __environ+1 sta ptr2+1 rts .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/setjmp.s��������������������������������������������������������������������0000664�0000000�0000000�00000001551�13473601511�0016443�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 1998-06-06, Ullrich von Bassewitz ; 2015-09-11, Greg King ; ; int __fastcall__ setjmp (jmp_buf buf); ; .export __setjmp .import return0 .importzp sp, ptr1 __setjmp: sta ptr1 ; Save buf stx ptr1+1 ldy #0 ; The parameter stack is now empty, put it into buf lda sp sta (ptr1),y iny lda sp+1 sta (ptr1),y iny ; Put the return stack pointer next tsx inx inx ; drop return address txa sta (ptr1),y iny ; Last thing is the return address. pla tax pla sta (ptr1),y ; high byte first iny pha txa sta (ptr1),y pha ; Return zero jmp return0 �������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/signal.s��������������������������������������������������������������������0000664�0000000�0000000�00000003252�13473601511�0016416�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2002-12-16 ; ; __sigfunc __fastcall__ signal (int sig, __sigfunc func); ; .import popax .importzp ptr1 .include "signal.inc" .include "errno.inc" ; Default signal functions: The standard specifies explicitly that the values ; for SIG_IGN and SIG_DFL must be distinct, so we make them so by using both ; rts exits we have. This works because signal functions are __fastcall__, so ; we don't have arguments on the stack. ;---------------------------------------------------------------------------- ; __sigfunc __fastcall__ signal (int sig, __sigfunc func); _signal: sta ptr1 stx ptr1+1 ; Remember func jsr popax ; Get sig cpx #0 bne invalidsig cmp #SIGCOUNT bcs invalidsig ; Signal number is valid. Replace the pointer in the table saving the old ; value temporarily on the stack. asl a ; Prepare for word access tax sei ; Disable interrupts in case of async signals lda sigtable,x pha lda ptr1 sta sigtable,x lda sigtable+1,x pha lda ptr1+1 sta sigtable+1,x cli ; Reenable interrupts ; Get the old value from the stack and return it pla tax pla __sig_ign: rts ; Error entry: We use our knowledge that SIG_ERR is zero here to save a byte invalidsig: lda #<EINVAL jsr __seterrno ; Returns 0 in A tax ; A/X = 0 __sig_dfl: rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/sigtable.s������������������������������������������������������������������0000664�0000000�0000000�00000000746�13473601511�0016740�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2002-12-16 ; ; Signal vector table ; .export sigtable .include "signal.inc" ;---------------------------------------------------------------------------- ; .data sigtable: .word __sig_dfl ; SIGABRT .word __sig_dfl ; SIGFPE .word __sig_dfl ; SIGILL .word __sig_dfl ; SIGINT .word __sig_dfl ; SIGSEGV .word __sig_dfl ; SIGTERM ��������������������������cc65-2.18/libsrc/common/sincos.s��������������������������������������������������������������������0000664�0000000�0000000�00000007576�13473601511�0016454�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Fixed point cosine/sine functions. ; ; int __fastcall__ _sin (unsigned x); ; int __fastcall__ _cos (unsigned x); ; ; Returns the cosine/sine for the given argument as angular degree. ; Valid argument range is 0..360 for both functions. They will return ; garbage if the argument is not in a valid range. Result is in 8.8 fixed ; point format, so $100 is 1.0 and $FF00 is -1.0. ; ; ; Ullrich von Bassewitz, 2009-10-29 ; .export __cos, __sin ; --------------------------------------------------------------------------- ; Sinus table covering values from 0..86° as 0.8 fixed point values. Values ; for 87..90° are actually 1.0 (= $100), will therefore not fit in the table ; and are covered specially in the code below. .rodata _sintab: .byte $00, $04, $09, $0D, $12, $16, $1B, $1F, $24, $28 .byte $2C, $31, $35, $3A, $3E, $42, $47, $4B, $4F, $53 .byte $58, $5C, $60, $64, $68, $6C, $70, $74, $78, $7C .byte $80, $84, $88, $8B, $8F, $93, $96, $9A, $9E, $A1 .byte $A5, $A8, $AB, $AF, $B2, $B5, $B8, $BB, $BE, $C1 .byte $C4, $C7, $CA, $CC, $CF, $D2, $D4, $D7, $D9, $DB .byte $DE, $E0, $E2, $E4, $E6, $E8, $EA, $EC, $ED, $EF .byte $F1, $F2, $F3, $F5, $F6, $F7, $F8, $F9, $FA, $FB .byte $FC, $FD, $FE, $FE, $FF, $FF, $FF ; --------------------------------------------------------------------------- ; Cosine function. Is actually implemented as _cos(x) = _sin(x+90) .code __cos: ; _cos(x) = _sin(x+90) clc adc #90 bcc @L1 inx ; If x is now larger than 360, we need to subtract 360. @L1: cpx #>360 bne @L2 cmp #<360 @L2: bcc __sin sbc #<360 bcs @L3 dex @L3: dex ; --------------------------------------------------------------------------- ; Sine function. Uses ; ; table lookup for 0..89° ; _sin(x) = _sin(180-x) for 90°..179° ; _sin(x) = -_sin(x-180) for 180..360° ; ; Plus special handling for the values missing in the table. __sin: ; If the high byte is non zero, argument is > 255 cpx #0 bne L3 cmp #180 bcs L4 ; 0..179° cmp #90 bcc L1 ; 90..179°. Value is identical to _sin(180-val). Carry is set on entry. ; ; 180-val := -val + 180. ; With ; -val := (val ^ $FF) + 1 ; we get ; 180-val = (val ^ $FF) + 1 + 180 ; Since carry is set, we can drop the "+ 1". ; eor #$FF adc #180 ; 180-val ; 0..89°. Values for 87..90° are actually 1.0. Since this format doesn't fit ; into the table, we have to check for it manually. L1: cmp #87 bcc L2 ; The value is 1.0 ldx #>(1 << 8) lda #<(1 << 8) rts ; 0..86°. Read the value from the table. L2: tay ldx #0 lda _sintab,y rts ; 180..360°. _sin(x) = -_sin(x-180). Since the argument is in range 0..180 ; after the subtraction, we don't need to handle the high byte. L3: sec L4: sbc #180 cmp #90 bcc L5 ; 270..360°. Value is identical to -_sin(180-val). Carry is set on entry. ; ; 180-val := -val + 180. ; With ; -val := (val ^ $FF) + 1 ; we get ; 180-val = (val ^ $FF) + 1 + 180 ; Since carry is set, we can drop the "+ 1". ; eor #$FF adc #180 ; 180-val ; 180..269°. Values for 267..269° are actually -1.0. Since this format doesn't ; fit into the table, we have to check for it manually. L5: ldx #$FF cmp #87 bcc L6 ; The value is -1.0 lda #<(-1 << 8) rts ; 180..266°. Read the value from the table. Carry is clear on entry. L6: tay txa ; A = $FF eor _sintab,y adc #1 bcc L7 inx L7: rts ����������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/sleep.c���������������������������������������������������������������������0000664�0000000�0000000�00000000642�13473601511�0016231�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** sleep.c ** ** Stefan Haubenthal, 2003-06-11 ** Ullrich von Bassewitz, 2003-06-12 ** */ #include <time.h> #include <unistd.h> /* We cannot implement this function without a working clock function */ #if defined(CLOCKS_PER_SEC) unsigned __fastcall__ sleep (unsigned wait) { clock_t goal = clock () + ((clock_t) wait) * CLOCKS_PER_SEC; while ((long) (goal - clock ()) > 0) ; return 0; } #endif ����������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/snprintf.s������������������������������������������������������������������0000664�0000000�0000000�00000003215�13473601511�0017003�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; int snprintf (char* buf, size_t size, const char* Format, ...); ; ; Ullrich von Bassewitz, 2009-09-26 ; .export _snprintf .import pushax, addysp, decsp6, _vsnprintf .importzp sp, ptr1 .macpack generic ; ---------------------------------------------------------------------------- ; Data .bss ParamSize: .res 1 ; Number of parameter bytes ; ---------------------------------------------------------------------------- ; Code .code _snprintf: sty ParamSize ; Number of param bytes passed in Y ; We have to push buf/size/format, both in the order they already have on stack. ; To make this somewhat more efficient, we will create space on the stack and ; then do a copy of the complete block instead of pushing each parameter ; separately. Since the size of the arguments passed is the same as the size ; of the fixed arguments, this will allow us to calculate the pointer to the ; fixed size arguments easier (they're just ParamSize bytes away). jsr decsp6 ; Calculate a pointer to the Format argument lda ParamSize add sp sta ptr1 ldx sp+1 bcc @L1 inx @L1: stx ptr1+1 ; Now copy buf/size/format ldy #6-1 @L2: lda (ptr1),y sta (sp),y dey bpl @L2 ; Load va_list (last and __fastcall__ parameter to vsprintf) lda ptr1 ldx ptr1+1 ; Call vsnprintf jsr _vsnprintf ; Cleanup the stack. We will return what we got from vsprintf ldy ParamSize jmp addysp �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/sprintf.s�������������������������������������������������������������������0000664�0000000�0000000�00000003175�13473601511�0016632�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; int sprintf (char* buf, const char* Format, ...); ; ; Ullrich von Bassewitz, 1.12.2000 ; .export _sprintf .import pushax, addysp, decsp4, _vsprintf .importzp sp, ptr1 .macpack generic ; ---------------------------------------------------------------------------- ; Data .bss ParamSize: .res 1 ; Number of parameter bytes ; ---------------------------------------------------------------------------- ; Code .code _sprintf: sty ParamSize ; Number of param bytes passed in Y ; We have to push buf and format, both in the order they already have on stack. ; To make this somewhat more efficient, we will create space on the stack and ; then do a copy of the complete block instead of pushing each parameter ; separately. Since the size of the arguments passed is the same as the size ; of the fixed arguments, this will allow us to calculate the pointer to the ; fixed size arguments easier (they're just ParamSize bytes away). jsr decsp4 ; Calculate a pointer to the Format argument lda ParamSize add sp sta ptr1 ldx sp+1 bcc @L1 inx @L1: stx ptr1+1 ; Now copy both, buf and format ldy #4-1 @L2: lda (ptr1),y sta (sp),y dey bpl @L2 ; Load va_list (last and __fastcall__ parameter to vsprintf) lda ptr1 ldx ptr1+1 ; Call vsprintf jsr _vsprintf ; Cleanup the stack. We will return what we got from vsprintf ldy ParamSize jmp addysp ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/sscanf.s��������������������������������������������������������������������0000664�0000000�0000000�00000003743�13473601511�0016423�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; int sscanf (const char* str, const char* format, ...); ; ; Ullrich von Bassewitz, 2004-11-28 ; .export _sscanf .import addysp, decsp4, _vsscanf .importzp sp, ptr1 .macpack generic ; ---------------------------------------------------------------------------- ; Data .bss ParamSize: .res 1 ; Number of parameter bytes ; ---------------------------------------------------------------------------- ; Code ; int sscanf (const char* str, const char* format, ...) ; /* Standard C function */ ; { ; va_list ap; ; ; /* Setup for variable arguments */ ; va_start (ap, format); ; ; /* Call vsscanf(). Since we know that va_end won't do anything, we will ; ** save the call and return the value directly. ; */ ; return vsscanf (str, format, ap); ; } ; .code _sscanf: sty ParamSize ; Number of param bytes passed in Y ; We have to push buf and format, both in the order they already have on stack. ; To make this somewhat more efficient, we will create space on the stack and ; then do a copy of the complete block instead of pushing each parameter ; separately. Since the size of the arguments passed is the same as the size ; of the fixed arguments, this will allow us to calculate the pointer to the ; fixed size arguments easier (they're just ParamSize bytes away). jsr decsp4 ; Calculate a pointer to the fixed parameters lda ParamSize add sp sta ptr1 ldx sp+1 bcc @L1 inx @L1: stx ptr1+1 ; Now copy both, str and format ldy #4-1 @L2: lda (ptr1),y sta (sp),y dey bpl @L2 ; Load va_list (last and __fastcall__ parameter to vsscanf) lda ptr1 ldx ptr1+1 ; Call vsscanf jsr _vsscanf ; Cleanup the stack. We will return what we got from vsscanf ldy ParamSize jmp addysp �����������������������������cc65-2.18/libsrc/common/strcat.s��������������������������������������������������������������������0000664�0000000�0000000�00000002205�13473601511�0016436�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 31.05.1998 ; Christian Krueger: 2013-Jul-24, minor optimizations ; ; char* strcat (char* dest, const char* src); ; .export _strcat .import popax .importzp ptr1, ptr2, tmp3 .macpack cpu _strcat: sta ptr1 ; Save src stx ptr1+1 jsr popax ; Get dest sta tmp3 ; Remember for function return tay .if (.cpu .bitand ::CPU_ISET_65SC02) stz ptr2 .else lda #0 sta ptr2 ; access from page start, y contains low byte .endif stx ptr2+1 findEndOfDest: lda (ptr2),y beq endOfDestFound iny bne findEndOfDest inc ptr2+1 bne findEndOfDest endOfDestFound: sty ptr2 ; advance pointer to last y position ldy #0 ; reset new y-offset copyByte: lda (ptr1),y sta (ptr2),y beq done iny bne copyByte inc ptr1+1 inc ptr2+1 bne copyByte ; like bra here ; return pointer to dest done: lda tmp3 ; X does still contain high byte rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/strchr.s��������������������������������������������������������������������0000664�0000000�0000000�00000002312�13473601511�0016442�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 31.05.1998 ; Christian Krueger, 2013-Aug-04, minor optimization ; ; const char* strchr (const char* s, int c); ; .export _strchr .import popax .importzp ptr1, tmp1 .macpack cpu _strchr: sta tmp1 ; Save c jsr popax ; get s tay ; low byte of pointer to y stx ptr1+1 .if (.cpu .bitand ::CPU_ISET_65SC02) stz ptr1 .else lda #0 sta ptr1 ; access from page start, y contains low byte .endif Loop: lda (ptr1),y ; Get next char beq EOS ; Jump on end of string cmp tmp1 ; Found? beq Found ; Jump if yes iny bne Loop inc ptr1+1 bne Loop ; Branch always ; End of string. Check if we're searching for the terminating zero EOS: lda tmp1 ; Get the char we're searching for bne NotFound ; Jump if not searching for terminator ; Found. Set pointer to c. Found: ldx ptr1+1 ; Load high byte of pointer tya ; low byte is in y rts ; Not found, return NULL NotFound: lda #0 tax rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/strcmp.s��������������������������������������������������������������������0000664�0000000�0000000�00000001263�13473601511�0016451�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 31.05.1998 ; ; int strcmp (const char* s1, const char* s2); ; .export _strcmp .import popptr1 .importzp ptr1, ptr2 _strcmp: sta ptr2 ; Save s2 stx ptr2+1 jsr popptr1 ; Get s1 ;ldy #0 ; Y=0 guaranteed by popptr1 loop: lda (ptr1),y cmp (ptr2),y bne L1 tax ; end of strings? beq L3 iny bne loop inc ptr1+1 inc ptr2+1 bne loop L1: bcs L2 ldx #$FF rts L2: ldx #$01 L3: rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/strcoll.s�������������������������������������������������������������������0000664�0000000�0000000�00000000400�13473601511�0016613�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 11.12.1998 ; ; int strcoll (const char* s1, const char* s2); ; ; Since we don't have locales, this function is equivalent to strcmp. ; .export _strcoll .import _strcmp _strcoll = _strcmp ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/strcpy.s��������������������������������������������������������������������0000664�0000000�0000000�00000001143�13473601511�0016462�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 31.05.1998 ; ; char* strcpy (char* dest, const char* src); ; .export _strcpy .import popax .importzp ptr1, ptr2 _strcpy: sta ptr1 ; Save src stx ptr1+1 jsr popax ; Get dest sta ptr2 stx ptr2+1 ldy #$00 L1: lda (ptr1),y sta (ptr2),y beq L9 iny bne L1 inc ptr1+1 inc ptr2+1 bne L1 L9: lda ptr2 ; X still contains high byte rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/strcspn.s�������������������������������������������������������������������0000664�0000000�0000000�00000003222�13473601511�0016632�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 11.06.1998 ; Christian Krueger: 05-Aug-2013, optimization ; ; size_t strcspn (const char* s1, const char* s2); ; .export _strcspn .import popptr1, _strlen .importzp ptr1, ptr2, tmp1, tmp2 _strcspn: jsr _strlen ; get length in a/x and transfer s2 to ptr2 ; Note: It does not make sense to ; have more than 255 test chars, so ; we don't support a high byte here! (ptr2+1 is ; also unchanged in strlen then (important!)) ; -> the original implementation also ; ignored this case sta tmp1 ; tmp1 = strlen of test chars jsr popptr1 ; get and save s1 to ptr1 ldx #0 ; low counter byte stx tmp2 ; high counter byte loadChar: ldy #0 lda (ptr1),y ; get next char from s1 beq leave ; handly byte of s1 advance: inc ptr1 ; advance string position to test bne check inc ptr1+1 dey ; correct next iny (faster/shorter than bne...) checkNext: iny check: cpy tmp1 ; compare with length of test character string beq endOfTestChars cmp (ptr2),y ; found matching char? bne checkNext leave: txa ; restore position of finding ldx tmp2 ; and return rts endOfTestChars: inx bne loadChar inc tmp2 bne loadChar ; like bra... ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/strdup.s��������������������������������������������������������������������0000664�0000000�0000000�00000003665�13473601511�0016472�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 18.07.2000 ; ; char* __fastcall__ strdup (const char* S); ; ; Note: The code knowns which zero page locations are used by malloc. ; .importzp sp, tmp1, ptr4 .import pushax, decsp4, incsp4 .import _strlen, _malloc, _memcpy .export _strdup .macpack cpu .macpack generic _strdup: ; Since we need some place to store the intermediate results, allocate a ; stack frame. To make this somewhat more efficient, create the stackframe ; as needed for the final call to the memcpy function. pha ; decsp will destroy A (but not X) jsr decsp4 ; Target/source ; Store the pointer into the source slot ldy #1 txa sta (sp),y pla .if (.cpu .bitand CPU_ISET_65SC02) sta (sp) .else dey sta (sp),y .endif ; Get length of S (which is still in a/x) jsr _strlen ; Calculate strlen(S)+1 (the space needed) add #1 bcc @L1 inx ; Save the space we're about to allocate in ptr4 @L1: sta ptr4 stx ptr4+1 ; Allocate memory. _malloc will not use ptr4 jsr _malloc ; Store the result into the target stack slot ldy #2 sta (sp),y ; Store low byte sta tmp1 txa ; Get high byte iny sta (sp),y ; Store high byte ; Check for a NULL pointer ora tmp1 beq OutOfMemory ; Copy the string. memcpy will return the target string which is exactly ; what we need here. It will also drop the allocated stack frame. lda ptr4 ldx ptr4+1 ; Load size jmp _memcpy ; Copy string, drop stackframe ; Out of memory, return NULL (A = 0) OutOfMemory: tax jmp incsp4 ; Drop stack frame ���������������������������������������������������������������������������cc65-2.18/libsrc/common/strerror.s������������������������������������������������������������������0000664�0000000�0000000�00000001566�13473601511�0017031�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 17.05.2000 ; ; char* __fastcall__ strerror (int errcode); ; /* Map an error number to an error message */ ; .export _strerror .import __sys_errlist .include "errno.inc" _strerror: cpx #$00 ; High byte must be zero bne @L1 ; Jump if invalid error cmp #EMAX ; Valid error code (map EUNKNOWN to 0)? bcc @L2 ; Jump if ok ; The given error code is invalid @L1: lda #<EINVAL sta __errno lda #>EINVAL ; = 0 sta __errno+1 ; lda #$00 ; A contains zero: "Unknown error" ; Load the pointer to the error message and return @L2: asl a ; * 2 tay ldx __sys_errlist+1,y lda __sys_errlist,y rts ������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/strftime.c������������������������������������������������������������������0000664�0000000�0000000�00000017600�13473601511�0016760�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* strftime.c */ /* */ /* Convert broken down time to a string in a user specified format */ /* */ /* */ /* */ /* (C) 2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> #include <stdio.h> #include <time.h> /* Use static local variables for speed */ #pragma static-locals (on); /*****************************************************************************/ /* Code */ /*****************************************************************************/ size_t __fastcall__ strftime (char* buf, size_t bufsize, const char* format, const struct tm* tm) { static const char* const days[7] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; static const char* const months[12] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; unsigned count; unsigned len; char c; char arg[40]; const char* argptr; /* Copy until we reach the end of the format string or a format specifier */ count = 0; while (1) { if (count >= bufsize) { /* Not enough buffer space available */ return 0; } if ((c = *format++) == '\0') { /* End of format string reached */ *buf = '\0'; return count; } if (c == '%') { /* Format specifier */ argptr = arg; switch (*format++) { case '%': arg[0] = '%'; arg[1] = '\0'; break; case 'A': argptr = days[tm->tm_wday]; break; case 'B': argptr = months[tm->tm_mon]; break; case 'D': sprintf (arg, "%02d/%02d/%02d", tm->tm_mon + 1, tm->tm_mday, tm->tm_year % 100); break; case 'F': /* C99 */ sprintf (arg, "%04d-%02d-%02d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday); break; case 'H': sprintf (arg, "%02d", tm->tm_hour); break; case 'I': sprintf (arg, "%02d", (tm->tm_hour + 11) % 12 + 1); break; case 'M': sprintf (arg, "%02d", tm->tm_min); break; case 'P': /* GNU extension */ argptr = (tm->tm_hour >= 12)? "pm" : "am"; break; case 'S': sprintf (arg, "%02d", tm->tm_sec); break; case 'U': sprintf (arg, "%02d", (tm->tm_yday + 7 - tm->tm_wday) / 7); break; case 'W': sprintf (arg, "%02d", (tm->tm_yday + 7 - (tm->tm_wday? tm->tm_wday - 1 : 6)) / 7); break; case 'X': sprintf (arg, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec); break; case 'Y': sprintf (arg, "%4d", tm->tm_year + 1900); break; case 'Z': argptr = tm->tm_isdst? _tz.dstname : _tz.tzname; break; case 'a': sprintf (arg, "%.3s", days[tm->tm_wday]); break; case 'b': sprintf (arg, "%.3s", months[tm->tm_mon]); break; case 'c': sprintf (arg, "%.3s %.3s%3d %02d:%02d:%02d %d", days[tm->tm_wday], months[tm->tm_mon], tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_year + 1900); break; case 'd': sprintf (arg, "%02d", tm->tm_mday); break; case 'j': sprintf (arg, "%03d", tm->tm_yday + 1); break; case 'm': sprintf (arg, "%02d", tm->tm_mon + 1); break; case 'p': argptr = (tm->tm_hour >= 12)? "PM" : "AM"; break; case 'w': sprintf (arg, "%d", tm->tm_wday); break; case 'x': sprintf (arg, "%04d-%02d-%02d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday); break; case 'y': sprintf (arg, "%02d", tm->tm_year % 100); break; default: /* Unknown format specifier, convert to empty string */ arg[0] = '\0'; break; } /* Check if we have enough space to copy the argument string */ len = strlen (argptr); count += len; if (count < bufsize) { memcpy (buf, argptr, len); buf += len; } } else { /* No format character, just copy */ *buf++ = c; ++count; } } } ��������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/stricmp.s�������������������������������������������������������������������0000664�0000000�0000000�00000003357�13473601511�0016630�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 03.06.1998 ; ; int stricmp (const char* s1, const char* s2); /* DOS way */ ; int strcasecmp (const char* s1, const char* s2); /* UNIX way */ ; .export _stricmp, _strcasecmp .import popptr1 .import __ctype .importzp ptr1, ptr2, tmp1 .include "ctype.inc" _stricmp: _strcasecmp: sta ptr2 ; Save s2 stx ptr2+1 jsr popptr1 ; get s1 ; ldy #0 ; Y=0 guaranteed by popptr1 loop: lda (ptr2),y ; get char from second string tax lda __ctype,x ; get character classification and #CT_LOWER ; lower case char? beq L1 ; jump if no txa ; get character back clc adc #<('A'-'a') ; make upper case char tax ; L1: stx tmp1 ; remember upper case equivalent lda (ptr1),y ; get character from first string tax lda __ctype,x ; get character classification and #CT_LOWER ; lower case char? beq L2 ; jump if no txa ; get character back clc adc #<('A'-'a') ; make upper case char tax L2: cpx tmp1 ; compare characters bne L3 txa ; end of strings? beq L5 ; a/x both zero iny bne loop inc ptr1+1 inc ptr2+1 bne loop L3: bcs L4 ldx #$FF rts L4: ldx #$01 L5: rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/strlen.s��������������������������������������������������������������������0000664�0000000�0000000�00000001240�13473601511�0016443�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 31.05.1998 ; ; Note: strspn & strcspn call internally this function and rely on ; the usage of only ptr2 here! Keep in mind when appling changes ; and check the other implementations too! ; ; int strlen (const char* s); ; .export _strlen .importzp ptr2 _strlen: sta ptr2 ; Save s stx ptr2+1 ldx #0 ; YX used as counter ldy #0 L1: lda (ptr2),y beq L9 iny bne L1 inc ptr2+1 inx bne L1 L9: tya ; get low byte of counter, hi's all set rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/strlower.s������������������������������������������������������������������0000664�0000000�0000000�00000002330�13473601511�0017016�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 1998-06-02, Ullrich von Bassewitz ; 2013-08-28, Greg King ; ; char* __fastcall__ strlower (char* s); ; char* __fastcall__ strlwr (char* s); ; ; Non-ANSI ; .export _strlower, _strlwr .import popax .import __ctype .importzp ptr1, ptr2 .include "ctype.inc" _strlower: _strlwr: sta ptr1 ; Save s (working copy) stx ptr1+1 sta ptr2 stx ptr2+1 ; save function result ldy #0 loop: lda (ptr1),y ; get character beq L9 ; jump if done tax lda __ctype,x ; get character classification and #CT_UPPER ; upper case char? beq L1 ; jump if no txa ; get character back into accu sec sbc #<('A'-'a') ; make lower case char sta (ptr1),y ; store back L1: iny ; next char bne loop inc ptr1+1 ; handle offset overflow bne loop ; branch always ; Done, return the argument string L9: lda ptr2 ldx ptr2+1 rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/strncat.s�������������������������������������������������������������������0000664�0000000�0000000�00000002555�13473601511�0016624�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 31.05.1998 ; Christian Krueger: 12-Aug-2013, minor optimizations ; ; char* strncat (char* dest, const char* src, size_t n); ; .export _strncat .import popax, popptr1 .importzp ptr1, ptr2, ptr3, tmp1, tmp2 .macpack cpu _strncat: eor #$FF ; one's complement to count upwards sta tmp1 txa eor #$FF sta tmp2 jsr popptr1 ; get src jsr popax ; get dest sta ptr3 ; remember for function return stx ptr3+1 stx ptr2+1 tay ; low byte as offset in Y .if (.cpu .bitand ::CPU_ISET_65SC02) stz ptr2 .else ldx #0 stx ptr2 ; destination on page boundary .endif ; find end of dest L1: lda (ptr2),y beq L2 iny bne L1 inc ptr2+1 bne L1 ; end found, apply offset to dest ptr and reset y L2: sty ptr2 ; copy src. We've put the ones complement of the count into the counter, so ; we'll increment the counter on top of the loop L3: ldy #0 ldx tmp1 ; low counter byte L4: inx bne L5 inc tmp2 beq L6 ; jump if done L5: lda (ptr1),y sta (ptr2),y beq L7 iny bne L4 inc ptr1+1 inc ptr2+1 bne L4 ; done, set the trailing zero and return pointer to dest L6: lda #0 sta (ptr2),y L7: lda ptr3 ldx ptr3+1 rts ���������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/strncmp.s�������������������������������������������������������������������0000664�0000000�0000000�00000003502�13473601511�0016625�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.05.2000 ; ; int strncmp (const char* s1, const char* s2, unsigned n); ; .export _strncmp .import popax, popptr1 .importzp ptr1, ptr2, ptr3 _strncmp: ; Convert the given counter value in a/x from a downward counter into an ; upward counter, so we can increment the counter in the loop below instead ; of decrementing it. This adds some overhead now, but is cheaper than ; executing a more complex test in each iteration of the loop. We do also ; correct the value by one, so we can do the test on top of the loop. eor #$FF sta ptr3 txa eor #$FF sta ptr3+1 ; Get the remaining arguments jsr popax ; get s2 sta ptr2 stx ptr2+1 jsr popptr1 ; get s1 ; Loop setup ;ldy #0 Y=0 guaranteed by popptr1 ; Start of compare loop. Check the counter. Loop: inc ptr3 beq IncHi ; Increment high byte ; Compare a byte from the strings Comp: lda (ptr1),y cmp (ptr2),y bne NotEqual ; Jump if strings different tax ; End of strings? beq Equal1 ; Jump if EOS reached, a/x == 0 ; Increment the pointers iny bne Loop inc ptr1+1 inc ptr2+1 bne Loop ; Branch always ; Increment hi byte IncHi: inc ptr3+1 bne Comp ; Jump if counter not zero ; Exit code if strings are equal. a/x not set Equal: lda #$00 tax Equal1: rts ; Exit code if strings not equal NotEqual: bcs L1 ldx #$FF ; Make result negative rts L1: ldx #$01 ; Make result positive rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/strncpy.s�������������������������������������������������������������������0000664�0000000�0000000�00000003172�13473601511�0016644�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-05-04 ; ; char* __fastcall__ strncpy (char* dest, const char* src, unsigned size); ; .export _strncpy .import popax, popptr1 .importzp ptr1, ptr2, tmp1, tmp2, tmp3 .proc _strncpy eor #$FF sta tmp1 txa eor #$FF sta tmp2 ; Store -size - 1 jsr popptr1 ; get src jsr popax ; get dest sta ptr2 stx ptr2+1 stx tmp3 ; remember for function return ; Copy src -> dest up to size bytes ldx tmp1 ; Load low byte of ones complement of size ldy #$00 L1: inx bne L2 inc tmp2 beq L9 L2: lda (ptr1),y ; Copy one character sta (ptr2),y beq L5 ; Bail out if terminator reached (A = 0) iny bne L1 inc ptr1+1 inc ptr2+1 ; Bump high bytes bne L1 ; Branch always ; Fill the remaining bytes. L3: inx ; Counter low byte beq L6 ; Branch on overflow L4: sta (ptr2),y ; Clear one byte L5: iny ; Bump pointer bne L3 inc ptr2+1 ; Bump high byte bne L3 ; Branch always ; Bump the counter high byte L6: inc tmp2 bne L4 ; Done, return dest L9: lda ptr2 ; Get low byte ldx tmp3 ; Get unchanged high byte rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/strnicmp.s������������������������������������������������������������������0000664�0000000�0000000�00000005450�13473601511�0017002�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Groessler, 10.02.2009 ; derived from strncmp.s and stricmp.s ; ; int __fastcall__ strnicmp (const char* s1, const char* s2, size_t count); ; int __fastcall__ strncasecmp (const char* s1, const char* s2, size_t count); ; .export _strnicmp, _strncasecmp .import popax, popptr1, __ctype .importzp ptr1, ptr2, ptr3, tmp1 .include "ctype.inc" _strnicmp: _strncasecmp: ; Convert the given counter value in a/x from a downward counter into an ; upward counter, so we can increment the counter in the loop below instead ; of decrementing it. This adds some overhead now, but is cheaper than ; executing a more complex test in each iteration of the loop. We do also ; correct the value by one, so we can do the test on top of the loop. eor #$FF sta ptr3 txa eor #$FF sta ptr3+1 ; Get the remaining arguments jsr popax ; get s2 sta ptr2 stx ptr2+1 jsr popptr1 ; get s1 ; Loop setup ; ldy #0 Y=0 guaranteed by popptr1 ; Start of compare loop. Check the counter. Loop: inc ptr3 beq IncHi ; Increment high byte ; Compare a byte from the strings Comp: lda (ptr2),y tax lda __ctype,x ; get character classification and #CT_LOWER ; lower case char? beq L1 ; jump if no txa ; get character back sec sbc #<('a'-'A') ; make upper case char tax ; L1: stx tmp1 ; remember upper case equivalent lda (ptr1),y ; get character from first string tax lda __ctype,x ; get character classification and #CT_LOWER ; lower case char? beq L2 ; jump if no txa ; get character back sec sbc #<('a'-'A') ; make upper case char tax L2: cpx tmp1 ; compare characters bne NotEqual ; Jump if strings different txa ; End of strings? beq Equal1 ; Jump if EOS reached, a/x == 0 ; Increment the pointers iny bne Loop inc ptr1+1 inc ptr2+1 bne Loop ; Branch always ; Increment hi byte IncHi: inc ptr3+1 bne Comp ; Jump if counter not zero ; Exit code if strings are equal. a/x not set Equal: lda #$00 tax Equal1: rts ; Exit code if strings not equal NotEqual: bcs L3 ldx #$FF ; Make result negative rts L3: ldx #$01 ; Make result positive rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/stroserr.s������������������������������������������������������������������0000664�0000000�0000000�00000003046�13473601511�0017025�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 17.07.2002 ; ; const char* __fastcall__ _stroserror (unsigned char errcode); ; /* Map an operating system error number to an error message. */ ; .export __stroserror .import __sys_oserrlist .importzp ptr1, tmp1 .macpack generic ; The table is built as a list of entries ; ; .byte entrylen ; .byte errorcode ; .asciiz errormsg ; ; and terminated by an entry with length zero that is returned if the ; error code could not be found. __stroserror: sta tmp1 ; Save the error code ldy #<__sys_oserrlist sty ptr1 ldy #>__sys_oserrlist sty ptr1+1 ; Setup pointer to message table @L1: ldy #0 lda (ptr1),y ; Get the length beq Done ; Bail out if end of list reached iny lda (ptr1),y ; Compare the error code cmp tmp1 beq Done ; Jump if found ; Not found, move pointer to next entry dey clc lda ptr1 adc (ptr1),y sta ptr1 bcc @L1 inc ptr1+1 bcs @L1 ; Branch always ; We've found the code or reached the end of the list Done: ldx ptr1+1 lda ptr1 add #2 ; Add a total of #2 bcc @L1 inx ; Bump high byte @L1: rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/strpbrk.s�������������������������������������������������������������������0000664�0000000�0000000�00000002743�13473601511�0016634�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 1998-06-11, Ullrich von Bassewitz ; 2018-05-29, Greg King ; ; char* __fastcall__ strpbrk (const char* str, const char* set); ; .export _strpbrk .import popax .importzp ptr1, ptr2, tmp2, tmp3 _strpbrk: sta ptr2 ; store set stx ptr2+1 jsr popax stx ptr1+1 ; store str's high byte ldx #<$0000 stx ptr1 tay ; use str's low byte as index L1: lda (ptr1),y ; get next char from str beq L9 ; jump if done sta tmp2 ; save char sty tmp3 ; save index into str ldy #$00 L3: lda (ptr2),y ; look at each char in set beq L4 ; jump if done cmp tmp2 beq L6 ; break out of loops if something found iny bne L3 ; The character was not found in set. Increment the counter; and start over. L4: ldy tmp3 ; reload index iny bne L1 inc ptr1+1 bne L1 ; branch always ; A character was found. Return its str pointer. L6: ldx ptr1+1 lda tmp3 ; get .Y offset rts ; None of the characters in set was found -- return NULL. L9: ;ldx #>$0000 ; (set by prolog) ;lda #<$0000 ; (set by '\0' at end of str) rts �����������������������������cc65-2.18/libsrc/common/strqtok.c�������������������������������������������������������������������0000664�0000000�0000000�00000003725�13473601511�0016635�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** strqtok() is like strtok(): It finds pieces of text, in a string, that are ** surrounded by given delimiter characters. It returns each piece, in turn, ** as a string, until every piece has been found. Then, it returns NULL. But, ** strqtok() recognizes quotation marks. A mark makes delimiters look ordinary ** until another quotation mark is seen. That allows us to include delimiters ** in tokens. (This version doesn't allow escaped quotation marks.) ** ** 2014-04-19, Daniel Serpell ** 2014-04-21, Paul Foerster ** 2014-04-25, Greg King */ #include <string.h> char* __fastcall__ strqtok (register char* s1, const char* s2) { static char c; static char* start; static char* next = ""; if (s1 == NULL) { s1 = next; if (c == '\"') { goto inQuote; } } /* Search for the start of a token. */ while (strchr (s2, c = *s1)) { if (c == '\0') { /* No more tokens. */ return NULL; } ++s1; } if (c == '\"') { goto skipQuote; } /* Save the start of the token. */ start = s1; /* Search for the end of a non-quoted token. */ while ((c = *s1) != '\"' && !strchr (s2, c)) { ++s1; } if (c == '\0') { /* The end of the last token is the end of the token list; ** don't go beyond it. */ goto found; } /* (A possible begin-quote mark will be rememberred.) */ goto terminate; skipQuote: ++s1; inQuote: /* Don't let a quote mark be rememberred. */ c = '\0'; /* Save the start of the token. */ start = s1; /* Search for the end of a quoted token. */ if ((s1 = strchr (s1, '\"')) == NULL) { /* The quoted token ended with '\0'; therefore, point to a '\0', ** so that the next call will return NULL. */ next = ""; return start; } terminate: *s1 = '\0'; ++s1; found: next = s1; return start; } �������������������������������������������cc65-2.18/libsrc/common/strrchr.s�������������������������������������������������������������������0000664�0000000�0000000�00000002120�13473601511�0016621�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 31.05.1998 ; Christian Krueger: 2013-Aug-01, optimization ; ; char* strrchr (const char* s, int c); ; .export _strrchr .import popax .importzp ptr1, tmp1, tmp2 _strrchr: sta tmp1 ; Save c jsr popax ; get s tay ; low byte to y stx ptr1+1 ldx #0 ; default function result is NULL, X is high byte... stx tmp2 ; tmp2 is low-byte stx ptr1 ; low-byte of source string is in Y, so clear real one... testChar: lda (ptr1),y ; get char beq finished ; jump if end of string cmp tmp1 ; found? bne nextChar ; jump if no charFound: sty tmp2 ; y has low byte of location, save it ldx ptr1+1 ; x holds high-byte of result nextChar: iny bne testChar inc ptr1+1 bne testChar ; here like bra... ; return the pointer to the last occurrence finished: lda tmp2 ; high byte in X is already correct... rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/strspn.s��������������������������������������������������������������������0000664�0000000�0000000�00000003175�13473601511�0016476�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 11.06.1998 ; Christian Krueger: 08-Aug-2013, optimization ; ; size_t strspn (const char* s1, const char* s2); ; .export _strspn .import popptr1, _strlen .importzp ptr1, ptr2, tmp1, tmp2 _strspn: jsr _strlen ; get length in a/x and transfer s2 to ptr2 ; Note: It does not make sense to ; have more than 255 test chars, so ; we don't support a high byte here! (ptr2+1 is ; also unchanged in strlen then (important!)) ; -> the original implementation also ; ignored this case sta tmp1 ; tmp1 = strlen of test chars jsr popptr1 ; get and save s1 to ptr1 ldx #0 ; low counter byte stx tmp2 ; high counter byte loadChar: ldy #0 lda (ptr1),y ; get next char from s1 beq leave ; handly byte of s1 advance: inc ptr1 ; advance string position to test bne check inc ptr1+1 dey ; correct next iny (faster/shorter than bne...) checkNext: iny check: cpy tmp1 ; compare with length of test character string beq leave cmp (ptr2),y ; found matching char? bne checkNext foundTestChar: inx bne loadChar inc tmp2 bne loadChar ; like bra... leave: txa ; restore position of finding ldx tmp2 ; and return rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/strstr.s��������������������������������������������������������������������0000664�0000000�0000000�00000005062�13473601511�0016503�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 11.12.1998 ; ; char* strstr (const char* haystack, const char* needle); ; .export _strstr .import popptr1 .importzp ptr1, ptr2, ptr3, ptr4, tmp1 _strstr: sta ptr2 ; Save needle stx ptr2+1 sta ptr4 ; Setup temp copy for later jsr popptr1 ; Get haystack to ptr1 ; If needle is empty, return haystack ; ldy #$00 Y=0 guaranteed by popptr1 lda (ptr2),y ; Get first byte of needle beq @Found ; Needle is empty --> we're done ; Search for the beginning of the string (this is not an optimal search ; strategy [in fact, it's pretty dumb], but it's simple to implement). sta tmp1 ; Save start of needle @L1: lda (ptr1),y ; Get next char from haystack beq @NotFound ; Jump if end cmp tmp1 ; Start of needle found? beq @L2 ; Jump if so iny ; Next char bne @L1 inc ptr1+1 ; Bump high byte bne @L1 ; Branch always ; We found the start of needle in haystack @L2: tya ; Get offset clc adc ptr1 sta ptr1 ; Make ptr1 point to start bcc @L3 inc ptr1+1 ; ptr1 points to the start of needle now. Setup temporary pointers for the ; search. The low byte of ptr4 is already set. @L3: sta ptr3 lda ptr1+1 sta ptr3+1 lda ptr2+1 sta ptr4+1 ldy #1 ; First char is identical, so start on second ; Do the compare @L4: lda (ptr4),y ; Get char from needle beq @Found ; Jump if end of needle (-> found) cmp (ptr3),y ; Compare with haystack bne @L5 ; Jump if not equal iny ; Next char bne @L4 inc ptr3+1 inc ptr4+1 ; Bump hi byte of pointers bne @L4 ; Next char (branch always) ; The strings did not compare equal, search next start of needle @L5: ldy #1 ; Start after this char bne @L1 ; Branch always ; We found the start of needle @Found: lda ptr1 ldx ptr1+1 rts ; We reached end of haystack without finding needle @NotFound: lda #$00 ; return NULL tax rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/strtoimax.s�����������������������������������������������������������������0000664�0000000�0000000�00000000310�13473601511�0017163�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2009-09-17 ; ; intmax_t __fastcall__ strtoimax (const char* nptr, char** endptr, int base); ; .import _strtol .export _strtoimax = _strtol ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/strtok.c��������������������������������������������������������������������0000664�0000000�0000000�00000003107�13473601511�0016446�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** strtok.c ** ** Ullrich von Bassewitz, 11.12.1998 */ #include <string.h> /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Memory location that holds the last input */ static char* Last = 0; /*****************************************************************************/ /* Code */ /*****************************************************************************/ char* __fastcall__ strtok (register char* s1, const char* s2) { char c; char* start; /* Use the stored location if called with a NULL pointer */ if (s1 == 0) { s1 = Last; } /* If s1 is empty, there are no more tokens. Return 0 in this case. */ if (*s1 == '\0') { return 0; } /* Search the address of the first element in s1 that equals none ** of the characters in s2. */ while ((c = *s1) && strchr (s2, c) != 0) { ++s1; } if (c == '\0') { /* No more tokens found */ Last = s1; return 0; } /* Remember the start of the token */ start = s1; /* Search for the end of the token */ while ((c = *s1) && strchr (s2, c) == 0) { ++s1; } if (c == '\0') { /* Last element */ Last = s1; } else { *s1 = '\0'; Last = s1 + 1; } /* Return the start of the token */ return start; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/strtol.c��������������������������������������������������������������������0000664�0000000�0000000�00000005620�13473601511�0016451�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <limits.h> #include <ctype.h> #include <errno.h> #include <stdlib.h> long __fastcall__ strtol (const char* nptr, char** endptr, int base) /* Convert a string to a long int */ { register const char* S = nptr; unsigned long Val = 0; unsigned char Minus = 0; unsigned char Ovf = 0; unsigned CvtCount = 0; unsigned char DigitVal; unsigned long MaxVal; unsigned char MaxDigit; /* Skip white space */ while (isspace (*S)) { ++S; } /* Check for leading + or - sign */ switch (*S) { case '-': Minus = 1; /* FALLTHROUGH */ case '+': ++S; } /* If base is zero, we may have a 0 or 0x prefix. If base is 16, we may ** have a 0x prefix. */ if (base == 0) { if (*S == '0') { ++S; if (*S == 'x' || *S == 'X') { ++S; base = 16; } else { base = 8; } } else { base = 10; } } else if (base == 16 && *S == '0' && (S[1] == 'x' || S[1] == 'X')) { S += 2; } /* Determine the maximum valid number and (if the number is equal to this ** value) the maximum valid digit. */ if (Minus) { MaxVal = LONG_MIN; } else { MaxVal = LONG_MAX; } MaxDigit = MaxVal % base; MaxVal /= base; /* Convert the number */ while (1) { /* Convert the digit into a numeric value */ if (isdigit (*S)) { DigitVal = *S - '0'; } else if (isupper (*S)) { DigitVal = *S - ('A' - 10); } else if (islower (*S)) { DigitVal = *S - ('a' - 10); } else { /* Unknown character */ break; } /* Don't accept a character that doesn't match base */ if (DigitVal >= base) { break; } /* Don't accept anything that makes the final value invalid */ if (Val > MaxVal || (Val == MaxVal && DigitVal > MaxDigit)) { Ovf = 1; } /* Calculate the next value if digit is not invalid */ if (Ovf == 0) { Val = (Val * base) + DigitVal; ++CvtCount; } /* Next character from input */ ++S; } /* Store the end pointer. If no conversion was performed, the value of ** nptr is returned in endptr. */ if (endptr) { if (CvtCount > 0) { *endptr = (char*) S; } else { *endptr = (char*) nptr; } } /* Handle overflow */ if (Ovf) { _seterrno (ERANGE); if (Minus) { return LONG_MIN; } else { return LONG_MAX; } } /* Return the result */ if (Minus) { return -(long)Val; } else { return Val; } } ����������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/strtoul.c�������������������������������������������������������������������0000664�0000000�0000000�00000005430�13473601511�0016635�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <limits.h> #include <ctype.h> #include <errno.h> #include <stdlib.h> unsigned long __fastcall__ strtoul (const char* nptr, char** endptr, int base) /* Convert a string to a long unsigned int */ { register const char* S = nptr; unsigned long Val = 0; unsigned char Minus = 0; unsigned char Ovf = 0; unsigned CvtCount = 0; unsigned char DigitVal; unsigned long MaxVal; unsigned char MaxDigit; /* Skip white space */ while (isspace (*S)) { ++S; } /* Check for leading + or - sign */ switch (*S) { case '-': Minus = 1; /* FALLTHROUGH */ case '+': ++S; } /* If base is zero, we may have a 0 or 0x prefix. If base is 16, we may ** have a 0x prefix. */ if (base == 0) { if (*S == '0') { ++S; if (*S == 'x' || *S == 'X') { ++S; base = 16; } else { base = 8; } } else { base = 10; } } else if (base == 16 && *S == '0' && (S[1] == 'x' || S[1] == 'X')) { S += 2; } /* Determine the maximum valid number and (if the number is equal to this ** value) the maximum valid digit. */ MaxDigit = ULONG_MAX % base; MaxVal = ULONG_MAX / base; /* Convert the number */ while (1) { /* Convert the digit into a numeric value */ if (isdigit (*S)) { DigitVal = *S - '0'; } else if (isupper (*S)) { DigitVal = *S - ('A' - 10); } else if (islower (*S)) { DigitVal = *S - ('a' - 10); } else { /* Unknown character */ break; } /* Don't accept a character that doesn't match base */ if (DigitVal >= base) { break; } /* Don't accept anything that makes the final value invalid */ if (Val > MaxVal || (Val == MaxVal && DigitVal > MaxDigit)) { Ovf = 1; } /* Calculate the next value if digit is not invalid */ if (Ovf == 0) { Val = (Val * base) + DigitVal; ++CvtCount; } /* Next character from input */ ++S; } /* Store the end pointer. If no conversion was performed, the value of ** nptr is returned in endptr. */ if (endptr) { if (CvtCount > 0) { *endptr = (char*) S; } else { *endptr = (char*) nptr; } } /* Handle overflow */ if (Ovf) { _seterrno (ERANGE); return ULONG_MAX; } /* Return the result */ if (Minus) { return (unsigned long) -(long)Val; } else { return Val; } } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/strtoumax.s�����������������������������������������������������������������0000664�0000000�0000000�00000000313�13473601511�0017202�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2009-09-17 ; ; uintmax_t __fastcall__ strtoumax (const char* nptr, char** endptr, int base); ; .import _strtoul .export _strtoumax = _strtoul ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/strupper.s������������������������������������������������������������������0000664�0000000�0000000�00000002330�13473601511�0017021�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 1998-06-02, Ullrich von Bassewitz ; 2013-08-28, Greg King ; ; char* __fastcall__ strupper (char* s); ; char* __fastcall__ strupr (char* s); ; ; Non-ANSI ; .export _strupper, _strupr .import popax .import __ctype .importzp ptr1, ptr2 .include "ctype.inc" _strupper: _strupr: sta ptr1 ; Save s (working copy) stx ptr1+1 sta ptr2 stx ptr2+1 ; save function result ldy #0 loop: lda (ptr1),y ; get character beq L9 ; jump if done tax lda __ctype,x ; get character classification and #CT_LOWER ; lower case char? beq L1 ; jump if no txa ; get character back into accu clc adc #<('A'-'a') ; make upper case char sta (ptr1),y ; store back L1: iny ; next char bne loop inc ptr1+1 ; handle offset overflow bne loop ; branch always ; Done, return the argument string L9: lda ptr2 ldx ptr2+1 rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/strxfrm.c�������������������������������������������������������������������0000664�0000000�0000000�00000000335�13473601511�0016625�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** strxfrm.c ** ** Ullrich von Bassewitz, 11.12.1998 */ #include <string.h> size_t __fastcall__ strxfrm (char* dest, const char* src, size_t count) { strncpy (dest, src, count); return strlen (src); } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/system.c��������������������������������������������������������������������0000664�0000000�0000000�00000000474�13473601511�0016450�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** system.c ** ** Stefan Haubenthal, 2003-05-26 ** Ullrich von Bassewitz, 2003-05-27 */ #include <stdio.h> #include <stdlib.h> int __fastcall__ system (const char* s) { if (s == NULL) { return 0; /* no shell */ } else { return -1; /* always fail */ } } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/tgi_colors.s����������������������������������������������������������������0000664�0000000�0000000�00000000340�13473601511�0017300�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Target-specific black & white values for use by the target-shared TGI kernel ; .include "tgi-kernel.inc" .export tgi_color_black:zp = $00 .export tgi_color_white:zp = $01 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/time.s����������������������������������������������������������������������0000664�0000000�0000000�00000002730�13473601511�0016077�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 12.11.2002 ; ; time_t __fastcall__ time (time_t* timep); ; .export _time .import decsp1, ldeaxi .importzp ptr1, sreg, tmp1, tmp2 .include "time.inc" .code .proc _time pha txa pha ; Save timep ; Get the time (machine dependent) jsr decsp1 lda #<time ldx #>time jsr _clock_gettime sta tmp2 lda #<time ldx #>time .assert timespec::tv_sec = 0, error jsr ldeaxi sta tmp1 ; Save low byte of result ; Restore timep and check if it is NULL pla sta ptr1+1 pla sta ptr1 ; Restore timep ora ptr1+1 ; timep == 0? beq @L1 ; timep is not NULL, store the result there ldy #3 lda sreg+1 sta (ptr1),y dey lda sreg sta (ptr1),y dey txa sta (ptr1),y dey lda tmp1 sta (ptr1),y ; If the result is != 0, return -1 @L1: lda tmp2 beq @L2 tax sta sreg sta sreg+1 rts ; Reload the low byte of the result and return @L2: lda tmp1 rts .endproc ; ------------------------------------------------------------------------ ; Data .bss time: .tag timespec ����������������������������������������cc65-2.18/libsrc/common/timezone.c������������������������������������������������������������������0000664�0000000�0000000�00000006042�13473601511�0016753�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* timezone.c */ /* */ /* Timezone specification */ /* */ /* */ /* */ /* (C) 2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <time.h> /*****************************************************************************/ /* Data */ /*****************************************************************************/ struct _timezone _tz = { 0, /* True if daylight savings time active */ 0, /* Number of seconds behind UTC */ "UTC", /* Name of timezone, e.g. CET */ "UTC" /* Name when daylight true, e.g. CEST */ }; ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/toascii.s�������������������������������������������������������������������0000664�0000000�0000000�00000000302�13473601511�0016565�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; unsigned char __fastcall__ toascii (unsigned char c); ; /* Convert a target specific character to ascii */ ; .export _toascii _toascii: ldx #>$0000 rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/tolower.s�������������������������������������������������������������������0000664�0000000�0000000�00000001241�13473601511�0016630�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 02.06.1998 ; ; int tolower (int c); ; .export _tolower .import __ctype _tolower: cpx #$00 ; Outside valid range? bne L9 ; If so, return the argument unchanged tay ; Get C into Y lda __ctype,y ; Get character classification lsr a lsr a ; Get bit 1 (upper case char) into carry tya ; Get char back into A bcc L9 ; Jump if no upper case char sbc #<('A'-'a') ; Make lower case char (carry already set) L9: rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/toupper.s�������������������������������������������������������������������0000664�0000000�0000000�00000001234�13473601511�0016635�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 02.06.1998 ; ; int toupper (int c); ; .export _toupper .import __ctype _toupper: cpx #$00 ; Outside valid range? bne L9 ; If so, return the argument unchanged tay ; Get c into Y lda __ctype,y ; Get character classification lsr a ; Get bit 0 (lower char) into carry tya ; Get C back into A bcc L9 ; Jump if not lower char clc adc #<('A'-'a') ; make upper case char L9: rts ; CC are set ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/uname.s���������������������������������������������������������������������0000664�0000000�0000000�00000000702�13473601511�0016243�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-08-12 ; ; int __fastcall__ uname (struct utsname* buf); ; .export _uname .import __sysuname .import __mappederrno ;-------------------------------------------------------------------------- .proc _uname jsr __sysuname ; Call the machine specific function jmp __mappederrno ; Store into _oserror, set errno, return 0/-1 .endproc ��������������������������������������������������������������cc65-2.18/libsrc/common/ungetc.s��������������������������������������������������������������������0000664�0000000�0000000�00000002566�13473601511�0016435�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2004-05-12 ; ; int __fastcall__ ungetc (int c, FILE* f); ; /* Push back a character into a file stream. */ ; .export _ungetc .import popax .import ptr1: zp, tmp1: zp .include "_file.inc" .include "errno.inc" ; ------------------------------------------------------------------------ ; Code .proc _ungetc ; Save the file pointer to ptr1 sta ptr1 stx ptr1+1 ; Get c from stack and save the lower byte in tmp1 jsr popax sta tmp1 ; c must be in char range txa bne error ; Check if the file is open ldy #_FILE::f_flags lda (ptr1),y and #_FOPEN ; Is the file open? beq error ; Branch if no ; Set the pushback flag and reset the end-of-file indicator lda (ptr1),y ora #_FPUSHBACK and #<~_FEOF sta (ptr1),y ; Store the character into the pushback buffer ldy #_FILE::f_pushback lda tmp1 sta (ptr1),y ; Done, return c ldx #0 rts ; File is not open or the character is invalid error: lda #EINVAL jsr __seterrno lda #$FF ; Return -1 tax rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/unlink.s��������������������������������������������������������������������0000664�0000000�0000000�00000000333�13473601511�0016436�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-06-12 ; ; int __fastcall__ unlink (const char* name); ; .export _unlink .import _remove ; unlink is just an alias for remove _unlink = _remove �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/utscopy.s�������������������������������������������������������������������0000664�0000000�0000000�00000003546�13473601511�0016655�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-08-12 ; ; This module contains a utility function for the machine dependent parts ; of uname (__sysuname): It copies a packed struct utsname (just the strings ; without padding) into a struct utsname. The source of the data is an ; external symbol named "utsdata", the target is passed in a/x. ; The function is written so that it is a direct replacement for __sysuname ; for systems where utsdata is fixed. It may also be called via jump or ; subroutine on systems where utsdata must be changed at runtime. ; .export utscopy .import utsdata .importzp ptr1, tmp1 .include "utsname.inc" ;-------------------------------------------------------------------------- ; Data. .rodata ; Table with offsets into struct utsname fieldoffs: .byte utsname::sysname .byte utsname::nodename .byte utsname::release .byte utsname::version .byte utsname::machine fieldcount = * - fieldoffs ;-------------------------------------------------------------------------- .code .proc utscopy sta ptr1 stx ptr1+1 ; Save buf ldx #0 stx tmp1 ; Field number next: ldy tmp1 cpy #fieldcount beq done inc tmp1 ; Bump field counter lda fieldoffs,y ; Get next field offset tay ; Field offset -> y loop: lda utsdata,x sta (ptr1),y inx ; Next char in utsdata cmp #$00 ; Check for end of string beq next ; Jump for next field iny ; Next char in utsname struct bne loop ; Copy string done: lda #$00 ; Always successful rts .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/vfprintf.s������������������������������������������������������������������0000664�0000000�0000000�00000006562�13473601511�0017006�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; vfprintf.s ; ; int fastcall vfprintf(FILE* f, const char* Format, va_list ap); ; ; 2005-02-08, Ullrich von Bassewitz ; 2005-02-11, Greg King .export _vfprintf .import push1, pushwysp, incsp6 .import _fwrite, __printf .importzp sp, ptr1 .macpack generic .data ; ---------------------------------------------------------------------------- ; Static data for the _vfprintf routine ; outdesc: ; Static outdesc structure ccount: .res 2 .word out ; Output function pointer ptr: .res 2 ; Points to output file .res 2 ; (Not used by this function) .code ; ---------------------------------------------------------------------------- ; Callback routine used for the actual output. ; ; Since we know, that this routine is always called with "our" outdesc, we ; 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 cdecl out (struct outdesc* d, const char* buf, unsigned count) ; /* Routine used for writing */ ; { ; register size_t cnt; ; ; /* Write to the file */ ; if ((cnt = fwrite(buf, 1, count, ptr)) == 0) { ; ccount = -1; ; } else { ; ccount += cnt; ; } ; } ; About to call ; ; fwrite (buf, 1, count, ptr); ; out: ldy #5 jsr pushwysp ; Push buf jsr push1 ; Push #1 ldy #7 jsr pushwysp ; Push count lda ptr ldx ptr+1 jsr _fwrite sta ptr1 ; Save function result stx ptr1+1 ; Check the return value. ora ptr1+1 bne @Ok ; We had an error. Store -1 into ccount .ifp02 lda #<-1 .else dec a .endif sta ccount bne @Done ; Branch always ; Result was ok, count bytes written @Ok: lda ptr1 add ccount sta ccount txa adc ccount+1 @Done: sta ccount+1 jmp incsp6 ; Drop stackframe ; ---------------------------------------------------------------------------- ; vfprintf - formatted output ; ; int fastcall vfprintf(FILE* f, const char* format, va_list ap) ; { ; static struct outdesc d = { ; 0, ; out ; }; ; ; /* Setup descriptor */ ; d.ccount = 0; ; d.ptr = f; ; ; /* Do formatting and output */ ; _printf (&d, format, ap); ; ; /* Return bytes written */ ; return d.ccount; ; } ; _vfprintf: pha ; Save low byte of ap ; Setup the outdesc structure lda #0 sta ccount sta ccount+1 ; Clear character-count ; Reorder the stack. Replace f on the stack by &d, so the stack frame is ; exactly as _printf expects it. Parameters will get dropped by _printf. ldy #2 lda (sp),y ; Low byte of f sta ptr lda #<outdesc sta (sp),y iny lda (sp),y ; High byte of f sta ptr+1 lda #>outdesc sta (sp),y ; Restore low byte of ap and call _printf pla jsr __printf ; Return the number of bytes written lda ccount ldx ccount+1 rts ����������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/vfscanf.s�������������������������������������������������������������������0000664�0000000�0000000�00000004726�13473601511�0016576�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; int __fastcall__ vfscanf (FILE* f, const char* format, va_list ap); ; ; 2004-11-27, Ullrich von Bassewitz ; 2004-12-21, Greg King ; .export _vfscanf .import _fgetc, _ungetc, _ferror .include "zeropage.inc" .include "_scanf.inc" .include "stdio.inc" count := ptr3 ; Result of scan ; ---------------------------------------------------------------------------- ; Static scanfdata structure for the _vfscanf routine ; .data d: .addr _fgetc ; GET .addr _ungetc ; UNGET .addr 0 ; data ; ---------------------------------------------------------------------------- ; int __fastcall__ vfscanf (FILE* f, const char* format, va_list ap) ; /* Standard C function */ ; { ; /* Initialize the data struct. We do only need the given file as user data, ; ** because the (getfunc) and (ungetfunc) functions are crafted so that they ; ** match the standard-I/O fgetc() and ungetc(). ; */ ; static struct scanfdata d = { ; ( getfunc) fgetc, ; (ungetfunc) ungetc ; }; ; static int count; ; ; d.data = (void*) f; ; ; /* Call the internal function */ ; count = _scanf (&d, format, ap); ; ; /* And, return the result */ ; return ferror (f) ? EOF : count; ; } ; ; Because _scanf() has the same parameter stack as vfscanf(), with f replaced ; by &d, we will do exactly that. _scanf() then will clean up the stack. ; Beware: Since ap is a fastcall parameter, we must not destroy a/x. ; .code _vfscanf: pha ; Save low byte of ap ; Swap f against &d on the stack, placing f into d.data ldy #2 ; Offset of f on the stack lda (sp),y sta d + SCANFDATA::DATA lda #<d sta (sp),y iny ; High byte lda (sp),y sta d + SCANFDATA::DATA + 1 lda #>d sta (sp),y ; Restore the low byte of ap, and call the _scanf function pla jsr __scanf sta count stx count+1 ; Return -1 if there was a read error during the scan lda d + SCANFDATA::DATA ; Get f ldx d + SCANFDATA::DATA+1 jsr _ferror tay beq L1 lda #<EOF tax rts ; Or, return the result of the scan L1: lda count ldx count+1 rts ������������������������������������������cc65-2.18/libsrc/common/vprintf.s�������������������������������������������������������������������0000664�0000000�0000000�00000001553�13473601511�0016633�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-06-02 ; ; int __fastcall__ vprintf (const char* format, va_list ap); ; .export _vprintf .import _vfprintf, _stdout .import decsp2 .importzp sp .proc _vprintf ; Save A which contains the low part of ap pha ; Allocate one more word on the stack jsr decsp2 ; Move the format parameter down and store stdout in it's place ldy #2 lda (sp),y ldy #0 sta (sp),y ldy #3 lda (sp),y ldy #1 sta (sp),y iny lda _stdout sta (sp),y iny lda _stdout+1 sta (sp),y ; Restore A pla ; Call vfprintf (stdout, format, ap) which will cleanup the stack and return jmp _vfprintf .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/vscanf.s��������������������������������������������������������������������0000664�0000000�0000000�00000002227�13473601511�0016422�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; int __fastcall__ vscanf (const char* format, va_list ap); ; ; Ullrich von Bassewitz, 2004-11-27 ; .export _vscanf .import _vfscanf .import _stdin .import decsp2 .include "zeropage.inc" ; ---------------------------------------------------------------------------- ; int __fastcall__ vscanf (const char* format, va_list ap) ; /* Standard C function */ ; { ; return vfscanf (stdin, format, ap); ; } ; .code _vscanf: pha ; Save low byte of ap ; Decrement the stack pointer by two for the additional parameter. jsr decsp2 ; Won't touch X ; Move the format down ldy #2 lda (sp),y ; Load byte of format ldy #0 sta (sp),y ldy #3 lda (sp),y ldy #1 sta (sp),y ; Store stdin into the stack frame iny lda _stdin sta (sp),y iny lda _stdin+1 sta (sp),y ; Restore the low byte of ap and jump to vfscanf, which will cleanup the stack pla jmp _vfscanf �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/vsnprintf.s�����������������������������������������������������������������0000664�0000000�0000000�00000012170�13473601511�0017171�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; int __fastcall__ vsnprintf (char* Buf, size_t size, const char* Format, va_list ap); ; ; 2009-09-26, Ullrich von Bassewitz ; 2015-07-17, Greg King ; .export _vsnprintf, vsnprintf .import ldaxysp, popax, incsp2, incsp6 .import _memcpy, __printf .importzp sp, ptr1 .include "errno.inc" .macpack generic .data ; ---------------------------------------------------------------------------- ; ; Static data for the _vsnprintf routine ; outdesc: ; Static outdesc structure ccount: .word 0 ; ccount func: .word out ; Output function pointer bufptr: .word 0 ; ptr bufsize:.word 0 ; Buffer size .code ; ---------------------------------------------------------------------------- ; vsprintf - formatted output into a buffer ; ; int __fastcall__ vsnprintf (char* buf, size_t size, const char* format, va_list ap); ; _vsnprintf: pha ; Save ap txa pha ; Setup the outdesc structure. This is also an additional entry point for ; vsprintf with ap on stack vsnprintf: lda #0 sta ccount+0 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. 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 sta ptr1 lda #<outdesc sta (sp),y iny lda (sp),y bmi L9 ; More than $7FFF sta ptr1+1 lda #>outdesc sta (sp),y ; Write size-1 to outdesc.uns. It will be -1 if there is no buffer. ldy ptr1+1 ldx ptr1 bne L1 dey L1: dex stx bufsize+0 sty bufsize+1 ; Copy buf to the outdesc.ptr ldy #5 jsr ldaxysp 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 L5: pla tax pla jsr __printf ; Terminate the string if there is a buffer. The last char. is at either ; bufptr+bufsize or bufptr+ccount, whichever is smaller. ldx bufsize+1 bmi L4 ; -1 -- No buffer lda bufsize+0 cpx ccount+1 bne L2 cmp ccount+0 L2: bcc L3 lda ccount+0 ldx ccount+1 clc L3: adc bufptr+0 sta ptr1 txa adc bufptr+1 sta ptr1+1 lda #0 tay sta (ptr1),y ; Return the number of bytes written and drop buf L4: lda ccount+0 ldx ccount+1 jmp incsp2 ; Bail out if size is too high. 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 __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, ; we don't need the pointer passed on the stack. out: ; Calculate the space left in the buffer. If no space is left, don't copy ; any characters lda bufsize+0 ; Low byte of buffer size sec 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 @L9: lda #$0000 sta ptr1 sta ptr1+1 ; No space left ; Replace the pointer to d by a pointer to the write position in the buffer ; for the call to memcpy that follows. @L0: lda bufptr+0 clc adc ccount+0 ldy #4 sta (sp),y lda bufptr+1 adc ccount+1 iny sta (sp),y ; Get Count from stack jsr popax ; outdesc.ccount += Count; pha clc adc ccount+0 sta ccount+0 txa adc ccount+1 sta ccount+1 pla ; if (Count > Left) Count = Left; cpx ptr1+1 bne @L1 cmp ptr1 @L1: bcc @L2 lda ptr1 ldx ptr1+1 ; Jump to memcpy, which will cleanup the stack and return to the caller @L2: jmp _memcpy ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/vsprintf.s������������������������������������������������������������������0000664�0000000�0000000�00000001715�13473601511�0017016�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; int __fastcall__ vsprintf (char* Buf, const char* Format, va_list ap); ; ; Ullrich von Bassewitz, 2009-09-26 ; .export _vsprintf .import pushw0sp, staxysp .import vsnprintf ; ---------------------------------------------------------------------------- ; vsprintf - formatted output into a buffer ; ; int __fastcall__ vsprintf (char* buf, const char* format, va_list ap); ; _vsprintf: pha ; Save low byte of ap txa pha ; Save high byte of op ; Build a stackframe for vsnprintf. To do that, we move format one word down, ; and store 0x7FFF (INT_MAX) as size. jsr pushw0sp ; Get format and push it lda #$FF ldx #$7F ; INT_MAX ldy #2 jsr staxysp ; Contine by jumping to vsnprintf, which expects ap on the CPU stack and will ; cleanup the C stack jmp vsnprintf ���������������������������������������������������cc65-2.18/libsrc/common/vsscanf.s�������������������������������������������������������������������0000664�0000000�0000000�00000010273�13473601511�0016605�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; int __fastcall__ vsscanf (const char* str, const char* format, va_list ap); ; /* Standard C function */ ; ; 2004-11-28, Ullrich von Bassewitz ; 2014-09-10, Greg King ; .export _vsscanf .import popax, __scanf .importzp sp, ptr1, ptr2 .macpack generic ; ---------------------------------------------------------------------------- ; Structure used to pass data to the callback functions .struct SSCANFDATA STR .addr INDEX .word .endstruct ; ---------------------------------------------------------------------------- ; static int __fastcall__ get (struct sscanfdata* d) ; /* Read a character from the input string and return it */ ; { ; char C = d->str[d->index]; ; if (C == '\0') { ; return EOF; ; } ; /* Increment index only if end not reached */ ; ++d->index; ; return C; ; } ; .code .proc get sta ptr1 stx ptr1+1 ; Save d ; Get d->str adding the high byte of index to the pointer, so we can access ; the byte in the string with just the low byte as index ldy #SSCANFDATA::STR lda (ptr1),y sta ptr2 iny lda (ptr1),y ldy #SSCANFDATA::INDEX+1 add (ptr1),y sta ptr2+1 ; Load the low byte of the index and fetch the byte from the string dey ; = SSCANFDATA::INDEX lda (ptr1),y tay lda (ptr2),y ; Return EOF if we are at the end of the string bne L1 lda #<-1 tax rts ; Bump the index (beware: A contains the char we must return) L1: tax ; Save return value tya ; Low byte of index ldy #SSCANFDATA::INDEX add #<$0001 sta (ptr1),y iny lda (ptr1),y adc #>$0001 sta (ptr1),y ; Return the char just read txa ldx #>$0000 rts .endproc ; ---------------------------------------------------------------------------- ; static int __fastcall__ unget (int c, struct sscanfdata* d) ; /* Push back a character onto the input stream */ ; { ; /* We do assume here that the _scanf routine will not push back anything ; ** not read, so we can ignore c safely and won't check the index. ; */ ; --d->index; ; return c; ; } ; .code .proc unget sta ptr1 stx ptr1+1 ; Save d ; Decrement the index ldy #SSCANFDATA::INDEX lda (ptr1),y sub #<$0001 sta (ptr1),y iny lda (ptr1),y sbc #>$0001 sta (ptr1),y ; Return c jmp popax .endproc ; ---------------------------------------------------------------------------- ; int __fastcall__ vsscanf (const char* str, const char* format, va_list ap) ; /* Standard C function */ ; { ; /* Initialize the data structs. The sscanfdata struct will be passed back ; ** to the get and unget functions by _scanf(). ; */ ; static struct sscanfdata sd; ; static const struct scanfdata d = { ; ( getfunc) get, ; (ungetfunc) unget, ; (void*) &sd ; }; ; ; sd.str = str; ; sd.index = 0; ; ; /* Call the internal function and return the result */ ; return _scanf (&d, format, ap); ; } ; .bss sd: .tag SSCANFDATA .rodata d: .addr get .addr unget .addr sd .code .proc _vsscanf ; Save the low byte of ap (which is passed in a/x) pha ; Initialize sd and at the same time replace str on the stack by a pointer ; to d ldy #2 ; Stack offset of str lda (sp),y sta sd + SSCANFDATA::STR lda #<d sta (sp),y iny lda (sp),y sta sd + SSCANFDATA::STR+1 lda #>d sta (sp),y lda #$00 sta sd + SSCANFDATA::INDEX sta sd + SSCANFDATA::INDEX+1 ; Restore the low byte of ap, and jump to _scanf() which will clean up the stack pla jmp __scanf .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/common/zerobss.s�������������������������������������������������������������������0000664�0000000�0000000�00000001272�13473601511�0016630�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 1998-09-17, 2005-02-26. ; ; Zero the bss segment. ; .export zerobss .import __BSS_RUN__, __BSS_SIZE__ .importzp ptr1 .code zerobss: lda #<__BSS_RUN__ sta ptr1 lda #>__BSS_RUN__ sta ptr1+1 lda #0 tay ; Clear full pages L1: ldx #>__BSS_SIZE__ beq L3 L2: sta (ptr1),y iny bne L2 inc ptr1+1 dex bne L2 ; Clear remaining page (y is zero on entry) L3: cpy #<__BSS_SIZE__ beq L4 sta (ptr1),y iny bne L3 ; Done L4: rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/conio/�����������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014572�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/conio/_cursor.s��������������������������������������������������������������������0000664�0000000�0000000�00000000200�13473601511�0016422�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.10.2000 ; ; Cursor related variables ; .export cursor .bss cursor: .res 1 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/conio/cprintf.s��������������������������������������������������������������������0000664�0000000�0000000�00000002305�13473601511�0016423�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; int cprintf (const char* Format, ...); ; ; Ullrich von Bassewitz, 1.12.2000 ; .export _cprintf .import pushax, addysp, _vcprintf .importzp sp, ptr1 .macpack generic ; ---------------------------------------------------------------------------- ; Data .bss ParamSize: .res 1 ; Number of parameter bytes ; ---------------------------------------------------------------------------- ; Code .code _cprintf: sty ParamSize ; Number of param bytes passed in Y ; Calculate a pointer that points to Format dey dey ; Sub size of Format tya add sp sta ptr1 ldx sp+1 bcc @L1 inx @L1: stx ptr1+1 ; Push Format ldy #1 lda (ptr1),y tax dey lda (ptr1),y jsr pushax ; Load va_list (last and __fastcall__ parameter to vfprintf) lda ptr1 ldx ptr1+1 ; Call vcprintf jsr _vcprintf ; Cleanup the stack. We will return what we got from vcprintf ldy ParamSize jmp addysp ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/conio/cputhex.s��������������������������������������������������������������������0000664�0000000�0000000�00000001372�13473601511�0016441�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 08.08.1998 ; ; void cputhex8 (unsigned char val); ; void cputhex16 (unsigned val); ; .export _cputhex8, _cputhex16 .import _cputc .import __hextab _cputhex16: pha ; Save low byte txa ; Get high byte into A jsr _cputhex8 ; Output high byte pla ; Restore low byte and run into _cputhex8 _cputhex8: pha ; Save the value lsr a lsr a lsr a lsr a tay lda __hextab,y jsr _cputc pla and #$0F tay lda __hextab,y jmp _cputc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/conio/cputs.s����������������������������������������������������������������������0000664�0000000�0000000�00000001631�13473601511�0016115�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; void cputsxy (unsigned char x, unsigned char y, const char* s); ; void cputs (const char* s); ; .export _cputsxy, _cputs .import gotoxy, _cputc .importzp ptr1, tmp1 _cputsxy: sta ptr1 ; Save s for later stx ptr1+1 jsr gotoxy ; Set cursor, pop x and y jmp L0 ; Same as cputs... _cputs: sta ptr1 ; Save s stx ptr1+1 L0: ldy #0 L1: lda (ptr1),y beq L9 ; Jump if done iny sty tmp1 ; Save offset jsr _cputc ; Output char, advance cursor ldy tmp1 ; Get offset bne L1 ; Next char inc ptr1+1 ; Bump high byte bne L1 ; Done L9: rts �������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/conio/cscanf.s���������������������������������������������������������������������0000664�0000000�0000000�00000002440�13473601511�0016213�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; int cscanf(const char* format, ...); ; ; 2000-12-01, Ullrich von Bassewitz ; 2005-01-01, Greg King ; .export _cscanf .import pushax, addysp, _vcscanf .macpack generic .include "zeropage.inc" ; ---------------------------------------------------------------------------- ; Code ; _cscanf: sty ArgSize ; Number of argument bytes passed in .Y dey ; subtract size of format pointer dey tya ; Now, calculate the va_list pointer -- which points to format. ldx sp+1 add sp bcc @L1 inx @L1: sta ptr1 stx ptr1+1 ; Push a copy of the format pointer onto the stack. ldy #1 lda (ptr1),y tax dey lda (ptr1),y jsr pushax ; Load va_list [last and __fastcall__ argument for vcscanf()]. lda ptr1 ldx ptr1+1 ; Call vcscanf(). jsr _vcscanf ; Clean up the stack. We will return what we got from vcscanf(). ldy ArgSize jmp addysp ; ---------------------------------------------------------------------------- ; Data ; .bss ArgSize: .res 1 ; Number of argument bytes ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/conio/cursor.s���������������������������������������������������������������������0000664�0000000�0000000�00000000607�13473601511�0016276�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 17.06.1998 ; ; unsigned char cursor (unsigned char onoff); ; .export _cursor .import cursor .proc _cursor tay ; onoff into Y ldx #0 ; High byte of result lda cursor ; Get old value sty cursor ; Set new value rts .endproc �������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/conio/scrsize.s��������������������������������������������������������������������0000664�0000000�0000000�00000001377�13473601511�0016450�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 08.08.1998 ; ; void screensize (unsigned char* x, unsigned char* y); ; .export _screensize .import popptr1 .import screensize .importzp ptr1, ptr2 .macpack cpu .proc _screensize sta ptr2 ; Store the y pointer stx ptr2+1 jsr popptr1 ; Get the x pointer into ptr1 jsr screensize ; Get screensize into X/Y tya ; Get Y size into A .if (.cpu .bitand ::CPU_ISET_65SC02) sta (ptr2) txa sta (ptr1) .else ldy #0 sta (ptr2),y txa sta (ptr1),y .endif rts .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/conio/vcprintf.s�������������������������������������������������������������������0000664�0000000�0000000�00000006576�13473601511�0016627�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; int __fastcall__ vcprintf (const char* Format, va_list ap); ; ; Ullrich von Bassewitz, 2.12.2000 ; .export _vcprintf .import pushax, popax, popptr1 .import __printf, _cputc .importzp sp, ptr1, ptr2, ptr3, tmp1 .macpack generic .data ; ---------------------------------------------------------------------------- ; ; Static data for the _vsprintf routine ; outdesc: ; Static outdesc structure .word 0 ; ccount .word out ; Output function pointer .word 0 ; ptr .word 0 ; uns .code ; ---------------------------------------------------------------------------- ; Callback routine used for the actual output. ; ; static void __cdecl__ out (struct outdesc* d, const char* buf, unsigned count) ; /* Routine used for writing */ ; { ; /* Fast screen output */ ; d->ccount += count; ; while (count) { ; cputc (*buf); ; ++buf; ; --count; ; } ; } ; ; We're using ptr1 and tmp1, since we know that the cputc routine will not use ; them (they're also used in cputs, so they must be safe). out: jsr popax ; count sta ptr2 eor #$FF sta outdesc+6 txa sta ptr2+1 eor #$FF sta outdesc+7 jsr popptr1 ; buf jsr popax ; d sta ptr3 stx ptr3+1 ; Sum up the total count of characters ldy #0 ; ccount in struct outdesc sty tmp1 ; Initialize tmp1 while we have zero available lda (ptr3),y add ptr2 sta (ptr3),y iny lda (ptr3),y adc ptr2+1 sta (ptr3),y ; Loop outputting characters @L1: inc outdesc+6 beq @L4 @L2: ldy tmp1 lda (ptr1),y iny bne @L3 inc ptr1+1 @L3: sty tmp1 jsr _cputc jmp @L1 @L4: inc outdesc+7 bne @L2 rts ; ---------------------------------------------------------------------------- ; vcprintf - formatted console i/o ; ; int __fastcall__ vcprintf (const char* format, va_list ap) ; { ; struct outdesc d; ; ; /* Setup descriptor */ ; d.fout = out; ; ; /* Do formatting and output */ ; _printf (&d, format, ap); ; ; /* Return bytes written */ ; return d.ccount; ; } _vcprintf: sta ptr1 ; Save ap stx ptr1+1 ; Setup the outdesc structure lda #0 sta outdesc sta outdesc+1 ; Clear ccount ; Get the format parameter and push it again ldy #1 lda (sp),y tax dey lda (sp),y jsr pushax ; Replace the passed format parameter on the stack by &d - this creates ; exactly the stack frame _printf expects. Parameters will get dropped ; by _printf. ldy #2 ; Low byte of d lda #<outdesc sta (sp),y iny lda #>outdesc sta (sp),y ; Restore ap and call _printf lda ptr1 ldx ptr1+1 jsr __printf ; Return the number of bytes written. lda outdesc ; ccount ldx outdesc+1 rts ����������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/conio/vcscanf.s��������������������������������������������������������������������0000664�0000000�0000000�00000006350�13473601511�0016405�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; int fastcall vcscanf(const char* format, va_list ap); ; ; 2014-09-10, Greg King ; .export _vcscanf .import _cgetc, _cputc .import popax, pushax, swapstk .include "../common/_scanf.inc" ; static bool pushed; ; static char back; ; .bss pushed: .res 1 back: .res 1 .code ; /* Call-back functions: ; ** (Note: These prototypes must NOT be declared with fastcall! They don't ; ** use (getfunc)'s and (ungetfunc)'s last parameter. Leaving it out of these ; ** prototypes makes more efficient code.) ; */ ; ---------------------------------------------------------------------------- ; /* Read a character from the console, and return it to an internal function */ ; static int get(void) { ; static char C; ; ; if (pushed) { ; pushed = false; ; return (int)back; ; } ; cputc(C = cgetc()); /* echo a typed character */ ; return (int)C; ; } ; get: ldx pushed beq L1 ; Return the old, pushed-back character (instead of getting a new one). ; dex ; ldx #>$0000 stx pushed lda back rts ; Directly read the keyboard. ; L1: jsr _cgetc ; Echo the character to the screen. ; pha jsr _cputc pla ldx #>$0000 rts ; ---------------------------------------------------------------------------- ; static int cdecl unget(int c) { ; pushed = true; ; return back = c; ; } ; unget: ldx #1 stx pushed jsr popax ; get the first argument sta back rts ; ---------------------------------------------------------------------------- ; int fastcall vcscanf(const char* format, va_list ap) { ; /* Initiate the data structure. ; ** Don't initiate the member that these conio functions don't use. ; */ ; static const struct scanfdata d = { ; ( getfunc) get, ; (ungetfunc)unget ; }; ; ; /* conio is very interactive. So, don't use any pushed-back character. ; ** Start fresh, each time that this function is called. ; */ ; pushed = false; ; ; /* Call the internal function, and return the result. */ ; return _scanf(&d, format, ap); ; } ; ; Beware: Because ap is a fastcall parameter, we must not destroy .XA. ; .proc _vcscanf ; ---------------------------------------------------------------------------- ; Static, constant scanfdata structure for the _vcscanf routine. ; .rodata d: .addr get ; SCANFDATA::GET .addr unget ; SCANFDATA::UNGET ; .addr 0 ; SCANFDATA::DATA (not used) .code pha ; Save low byte of ap txa pha ; Save high byte of ap ldx #0 stx pushed ; Put &d on the stack in front of the format pointer. lda #<d ldx #>d jsr swapstk ; Swap .XA with top-of-stack jsr pushax ; Put format pointer back on stack ; Restore ap, and jump to _scanf which will clean up the stack. pla tax pla jmp __scanf .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/creativision/����������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0016162�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/creativision/_scrsize.s������������������������������������������������������������0000664�0000000�0000000�00000000322�13473601511�0020164�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������;* ;** _scrsize.s ;* .export screensize .include "creativision.inc" .proc screensize ldx #SCREEN_COLS ldy #SCREEN_ROWS rts .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/creativision/boxchars.inc����������������������������������������������������������0000664�0000000�0000000�00000002176�13473601511�0020474�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; Boxchars boxchars: ; Vertical Line .byte $18 .byte $18 .byte $18 .byte $18 .byte $18 .byte $18 .byte $18 .byte $18 ; Horizontal Line .byte $00 .byte $00 .byte $00 .byte $FF .byte $00 .byte $00 .byte $00 .byte $00 ; Top Left .byte $00 .byte $00 .byte $00 .byte $1F .byte $18 .byte $18 .byte $18 .byte $18 ; Top Right .byte $00 .byte $00 .byte $00 .byte $F8 .byte $18 .byte $18 .byte $18 .byte $18 ; Bottom Left .byte $18 .byte $18 .byte $18 .byte $1F .byte $00 .byte $00 .byte $00 .byte $00 ; Bottom Right .byte $18 .byte $18 .byte $18 .byte $F8 .byte $00 .byte $00 .byte $00 .byte $00 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/creativision/cclear.s��������������������������������������������������������������0000664�0000000�0000000�00000001047�13473601511�0017601�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������;* ;* 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 length jsr popa ; get Y jsr _gotoxy pla _cclear: cmp #0 ; Zero length? beq L2 sta tmp1 L1: lda #$20 ; Space jsr cputdirect dec tmp1 bne L1 L2: rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/creativision/cgetc.s���������������������������������������������������������������0000664�0000000�0000000�00000000340�13473601511�0017430�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������;* cgetc .export _cgetc .include "creativision.inc" _cgetc: lda #$80 L1: bit ZP_KEYBOARD bpl L1 lda ZP_KEYBOARD and #$7F rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/creativision/chline.s��������������������������������������������������������������0000664�0000000�0000000�00000001434�13473601511�0017612�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������;* 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 "creativision.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 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/creativision/clrscr.s��������������������������������������������������������������0000664�0000000�0000000�00000001664�13473601511�0017645�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������;* ;* clrscr ;* ;* NB: All screen functions assume Graphics Mode 1 in a default configuration. ;* Therefore, this is hard coded to use $1000-$12FF as screen VRAM. .export _clrscr .include "creativision.inc" _clrscr: sei ; Disable interrupts. Default INT handler reads VDP_STATUS ; and would lose any setup done here. lda #$00 ; VRAM offset low sta VDP_CONTROL_W lda #$50 ; VRAM offset high ($10 OR $40) sta VDP_CONTROL_W lda #$40 ; Space char from ROM setup ldx #0 ldy #3 L1: sta VDP_DATA_W inx bne L1 dey bne L1 cli ; Let interrupts go again lda #0 sta CURSOR_X sta CURSOR_Y sta SCREEN_PTR lda #$10 sta SCREEN_PTR+1 rts ����������������������������������������������������������������������������cc65-2.18/libsrc/creativision/color.s���������������������������������������������������������������0000664�0000000�0000000�00000000656�13473601511�0017473�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������;* ;* 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 .import return0 .include "creativision.inc" _bordercolor = return0; _textcolor = return0; _bgcolor = return0; ����������������������������������������������������������������������������������cc65-2.18/libsrc/creativision/cputc.s���������������������������������������������������������������0000664�0000000�0000000�00000005352�13473601511�0017471�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Written by Groepaz/Hitmen <groepaz@gmx.net> ; Cleanup by Ullrich von Bassewitz <uz@cc65.org> ; ; void cputcxy (unsigned char x, unsigned char y, char c); ; void cputc (char c); ; .export _cputcxy, _cputc, cputdirect, putchar .export newline .constructor initconio .import popa, _gotoxy .import setcursor .importzp tmp3,tmp4 .include "creativision.inc" .include "boxchars.inc" ;----------------------------------------------------------------------------- .code _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 CURSOR_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 CURSOR_X iny cpy #SCREEN_COLS bne L3 inc CURSOR_Y ; new line ldy #0 ; + cr L3: sty CURSOR_X jmp plot newline: inc CURSOR_Y ; Set cursor position, calculate RAM pointers plot: ldy CURSOR_X ldx CURSOR_Y jmp setcursor ; Set the new cursor ; Write one character to the screen without doing anything else, return X ; position in Y putchar: cmp #$5B bcc IS_UPPER clc sbc #$1F IS_UPPER: cmp #$20 bcc BAD_CHAR pha lda SCREEN_PTR sei sta VDP_CONTROL_W lda SCREEN_PTR+1 ora #$40 sta VDP_CONTROL_W pla clc adc #160 sta VDP_DATA_W cli BAD_CHAR: jmp plot ;----------------------------------------------------------------------------- ; Initialize the conio subsystem. "INIT" segment is nothing special on the ; Creativision, it is part of the "ROM" memory. .segment "INIT" initconio: lda #$0 sta SCREEN_PTR lda #$10 sta SCREEN_PTR+1 ; Copy box characters to slot sei lda #08 sta VDP_CONTROL_W lda #$46 sta VDP_CONTROL_W ldx #0 LL: lda boxchars,x sta VDP_DATA_W inx cpx #48 bne LL cli jmp plot ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/creativision/crt0.s����������������������������������������������������������������0000664�0000000�0000000�00000006427�13473601511�0017227�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Startup code for cc65 (CreatiVision version) ; .export _exit .export __STARTUP__ : absolute = 1 ; Mark as startup .export irq2 .import zerobss, copydata .import initlib, donelib, callmain .import __VECTORS_LOAD__, __VECTORS_RUN__, __VECTORS_SIZE__ .import __ZP_LAST__, __STACKSIZE__, __RAM_START__ .include "creativision.inc" .include "zeropage.inc" ; ------------------------------------------------------------------------ entry: ; Init the CPU sei cld ; Copy the IRQ vectors ldx #<__VECTORS_SIZE__ - 1 : lda __VECTORS_LOAD__,x sta __VECTORS_RUN__,x dex bpl :- ; Setup the CPU stack ptr ldx #<__RAM_START__ - 1 txs ; Clear the BSS data jsr zerobss ; Copy data from ROM to RAM jsr copydata ; Setup the argument stack ptr lda #<(__ZP_LAST__ + __STACKSIZE__) ldx #>(__ZP_LAST__ + __STACKSIZE__) sta sp stx sp+1 ; Call module constructors jsr initlib ; enable vertical blank interrupts in the display controller lda #$E0 ; 16K RAM, Active Display, Mode 1, VBI enabled ldx #$01 ; Register 1 jsr BIOS_WRITE_VDP_REG ; Start interrupts cli ; Call main() jsr callmain ; Call module destructors. This is also the _exit entry. _exit: jsr donelib ; A Creativision program isn't supposed to exit. loop: jmp loop ; ------------------------------------------------------------------------ ; Define the IRQ vectors. .segment "VECTORS" irq1: jmp BIOS_IRQ1_ADDR irq2: jmp BIOS_IRQ2_ADDR ; ------------------------------------------------------------------------ ; Define CART setup values for BIOS. .segment "SETUP" ; BIOS Jump Start ; This is where the entry point of the program needs to be .addr entry .addr irq2 .res 4 ; VDP Setup ; This sets to Graphics Mode 1 .byte $00 ; Register 0 .byte $C0 ; Register 1 16K RAM, Active Display, Mode 1, VBI disabled .byte $04 ; Register 2 Name Table at $1000 - $12FF .byte $60 ; Register 3 Colour Table at $1800 - $181F .byte $00 ; Register 4 Pattern Table at $0000 - $07FF .byte $10 ; Register 5 Sprite Attribute at $0800 - $087F .byte $01 ; Register 6 Sprite Pattern .byte $F1 ; Register 7 Text colour Foreground / background .res 4 ; BIOS Vector after NMI or RESET ; Keeping with retail cartridges, we jump back to BIOS ROM and have it ; setup zeropage etc, and show the Creativision logo and copyright. .addr BIOS_NMI_RESET_ADDR ; BIOS Short Interrupt Handler ; Vectored from BIOS ROM:FE2C. This should contain a pointer to the user's ; BIOS interrupt handler. .addr irq1 ; ------------------------------------------------------------------------ �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/creativision/ctype.s���������������������������������������������������������������0000664�0000000�0000000�00000015333�13473601511�0017477�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 02.06.1998 ; ; Character specification table. ; ; 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. ; ; ; Bit assignments: ; ; 0 - Lower case char ; 1 - Upper case char ; 2 - Numeric digit ; 3 - Hex digit (both, lower and upper) ; 4 - Control character ; 5 - The space character itself ; 6 - Other whitespace (that is: '\f', '\n', '\r', '\t' and '\v') ; 7 - Space or tab character .export __ctype __ctype: .repeat 2 ; 2 times for normal and inverted .byte $10 ; 0/00 ___ctrl_@___ .byte $10 ; 1/01 ___ctrl_A___ .byte $10 ; 2/02 ___ctrl_B___ .byte $10 ; 3/03 ___ctrl_C___ .byte $10 ; 4/04 ___ctrl_D___ .byte $10 ; 5/05 ___ctrl_E___ .byte $10 ; 6/06 ___ctrl_F___ .byte $10 ; 7/07 ___ctrl_G___ .byte $10 ; 8/08 ___ctrl_H___ .byte $D0 ; 9/09 ___ctrl_I___ .byte $50 ; 10/0a ___ctrl_J___ .byte $50 ; 11/0b ___ctrl_K___ .byte $50 ; 12/0c ___ctrl_L___ .byte $50 ; 13/0d ___ctrl_M___ .byte $10 ; 14/0e ___ctrl_N___ .byte $10 ; 15/0f ___ctrl_O___ .byte $10 ; 16/10 ___ctrl_P___ .byte $10 ; 17/11 ___ctrl_Q___ .byte $10 ; 18/12 ___ctrl_R___ .byte $10 ; 19/13 ___ctrl_S___ .byte $10 ; 20/14 ___ctrl_T___ .byte $10 ; 21/15 ___ctrl_U___ .byte $10 ; 22/16 ___ctrl_V___ .byte $10 ; 23/17 ___ctrl_W___ .byte $10 ; 24/18 ___ctrl_X___ .byte $10 ; 25/19 ___ctrl_Y___ .byte $10 ; 26/1a ___ctrl_Z___ .byte $10 ; 27/1b ___ctrl_[___ .byte $10 ; 28/1c ___ctrl_\___ .byte $10 ; 29/1d ___ctrl_]___ .byte $10 ; 30/1e ___ctrl_^___ .byte $10 ; 31/1f ___ctrl_____ .byte $A0 ; 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 $0C ; 48/30 _____0_____ .byte $0C ; 49/31 _____1_____ .byte $0C ; 50/32 _____2_____ .byte $0C ; 51/33 _____3_____ .byte $0C ; 52/34 _____4_____ .byte $0C ; 53/35 _____5_____ .byte $0C ; 54/36 _____6_____ .byte $0C ; 55/37 _____7_____ .byte $0C ; 56/38 _____8_____ .byte $0C ; 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 $0A ; 65/41 _____A_____ .byte $0A ; 66/42 _____B_____ .byte $0A ; 67/43 _____C_____ .byte $0A ; 68/44 _____D_____ .byte $0A ; 69/45 _____E_____ .byte $0A ; 70/46 _____F_____ .byte $02 ; 71/47 _____G_____ .byte $02 ; 72/48 _____H_____ .byte $02 ; 73/49 _____I_____ .byte $02 ; 74/4a _____J_____ .byte $02 ; 75/4b _____K_____ .byte $02 ; 76/4c _____L_____ .byte $02 ; 77/4d _____M_____ .byte $02 ; 78/4e _____N_____ .byte $02 ; 79/4f _____O_____ .byte $02 ; 80/50 _____P_____ .byte $02 ; 81/51 _____Q_____ .byte $02 ; 82/52 _____R_____ .byte $02 ; 83/53 _____S_____ .byte $02 ; 84/54 _____T_____ .byte $02 ; 85/55 _____U_____ .byte $02 ; 86/56 _____V_____ .byte $02 ; 87/57 _____W_____ .byte $02 ; 88/58 _____X_____ .byte $02 ; 89/59 _____Y_____ .byte $02 ; 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 ___grave___ .byte $09 ; 97/61 _____a_____ .byte $09 ; 98/62 _____b_____ .byte $09 ; 99/63 _____c_____ .byte $09 ; 100/64 _____d_____ .byte $09 ; 101/65 _____e_____ .byte $09 ; 102/66 _____f_____ .byte $01 ; 103/67 _____g_____ .byte $01 ; 104/68 _____h_____ .byte $01 ; 105/69 _____i_____ .byte $01 ; 106/6a _____j_____ .byte $01 ; 107/6b _____k_____ .byte $01 ; 108/6c _____l_____ .byte $01 ; 109/6d _____m_____ .byte $01 ; 110/6e _____n_____ .byte $01 ; 111/6f _____o_____ .byte $01 ; 112/70 _____p_____ .byte $01 ; 113/71 _____q_____ .byte $01 ; 114/72 _____r_____ .byte $01 ; 115/73 _____s_____ .byte $01 ; 116/74 _____t_____ .byte $01 ; 117/75 _____u_____ .byte $01 ; 118/76 _____v_____ .byte $01 ; 119/77 _____w_____ .byte $01 ; 120/78 _____x_____ .byte $01 ; 121/79 _____y_____ .byte $01 ; 122/7a _____z_____ .byte $00 ; 123/7b _____{_____ .byte $00 ; 124/7c _____|_____ .byte $00 ; 125/7d _____}_____ .byte $00 ; 126/7e _____~_____ .byte $40 ; 127/7f ____DEL____ .endrepeat �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/creativision/cvline.s��������������������������������������������������������������0000664�0000000�0000000�00000001630�13473601511�0017626�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 "creativision.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 ��������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/creativision/gotox.s���������������������������������������������������������������0000664�0000000�0000000�00000000560�13473601511�0017507�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-05-02 ; ; void gotox (unsigned char x); ; .export _gotox .import setcursor .include "creativision.inc" .proc _gotox sta CURSOR_X ; Set new position tay ldx CURSOR_Y jmp setcursor ; Set the cursor to the new position .endproc ������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/creativision/gotoxy.s��������������������������������������������������������������0000664�0000000�0000000�00000001045�13473601511�0017677�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 1998-08-06, Ullrich von Bassewitz ; 2017-06-15, Greg King ; ; void gotoxy (unsigned char x, unsigned char y); ; .export gotoxy, _gotoxy .import setcursor .import popa .include "creativision.inc" gotoxy: jsr popa ; Get Y .proc _gotoxy sta CURSOR_Y ; Set Y jsr popa ; Get X sta CURSOR_X ; Set X tay ldx CURSOR_Y jmp setcursor ; Set the cursor position .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/creativision/gotoy.s���������������������������������������������������������������0000664�0000000�0000000�00000000560�13473601511�0017510�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-05-02 ; ; void gotoy (unsigned char y); ; .export _gotoy .import setcursor .include "creativision.inc" .proc _gotoy sta CURSOR_Y ; Set new position tax ldy CURSOR_X jmp setcursor ; Set the cursor to the new position .endproc ������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/creativision/irq.s�����������������������������������������������������������������0000664�0000000�0000000�00000001574�13473601511�0017150�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; IRQ handling (CreatiVision version) ; .export initirq, doneirq .import callirq, irq2 .include "creativision.inc" ; ------------------------------------------------------------------------ .segment "ONCE" initirq: lda #<IRQStub ldx #>IRQStub jmp setvec ; ------------------------------------------------------------------------ .code doneirq: lda #<BIOS_IRQ2_ADDR ldx #>BIOS_IRQ2_ADDR setvec: sei sta irq2+1 stx irq2+2 cli rts ; ------------------------------------------------------------------------ .segment "CODE" IRQStub: cld ; Just to be sure jsr callirq ; Call the functions jmp BIOS_IRQ2_ADDR ; Jump to the BIOS IRQ vector ������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/creativision/joy/������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0016763�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/creativision/joy/creativision-stdjoy.s���������������������������������������������0000664�0000000�0000000�00000020103�13473601511�0023154�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Standard joystick driver for the Creativision. ; ; Christian Groessler, 2017-03-08 ; .include "zeropage.inc" .include "joy-kernel.inc" .include "joy-error.inc" .include "creativision.inc" .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _creativisionstd_joy ; Driver signature .byte $6A, $6F, $79 ; "joy" .byte JOY_API_VERSION ; Driver API version number ; Library reference .addr $0000 ; Jump table. .addr INSTALL .addr UNINSTALL .addr COUNT .addr READJOY ; ------------------------------------------------------------------------ ; Constants JOY_COUNT = 2 ; Number of joysticks we support ; Symbolic names for joystick masks (similar names like the defines in joystick.h, but not related to them) JOY_UP = $10 JOY_DOWN = $04 JOY_LEFT = $20 JOY_RIGHT = $08 ; ------------------------------------------------------------------------ ; Code .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 #0 ; rts ; Fall through ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; COUNT: Return the total number of available joysticks in a/x. ; COUNT: lda #<JOY_COUNT ldx #>JOY_COUNT rts ; ------------------------------------------------------------------------ ; READ: Read a particular joystick passed in A. ; READJOY: and #1 ; fix joystick number bne READJOY_1 ; read right joystick ; Read left joystick ldx ZP_JOY0_DIR lda ZP_JOY0_BUTTONS jmp convert ; convert joystick state to cc65 values ; Read right joystick READJOY_1: ldx ZP_JOY1_DIR lda ZP_JOY1_BUTTONS lsr a lsr a ;jmp convert ; convert joystick state to cc65 values ; fall thru... ; ------------------------------------------------------------------------ ; convert: make runtime lib compatible values ; inputs: ; A - buttons ; X - direction ; convert: ; ------ ; buttons: ; Port values are for the left hand joystick (right hand joystick ; values were shifted to the right to be identical). ; Why are there two bits indicating a pressed trigger? ; According to the "Second book of programs for the Dick Smith Wizard" ; (pg. 88ff), the left hand button gives the value of ; %00010001 and the right hand button gives %00100010 ; Why two bits? Can there be cases that just one of those bits is set? ; Until these questions have been answered, we only use the lower two ; bits and ignore the upper ones... and #%00000011 ; button status came in in A, strip high bits sta retval ; initialize 'retval' with button status ; ------ ; direction: ; CV has a 16-direction joystick ; ; port values: (compass points) ; N - $49 - %01001001 ; NNE - $48 - %01001000 ; NE - $47 - %01000111 ; ENE - $46 - %01000110 ; E - $45 - %01000101 ; ESE - $44 - %01000100 ; SE - $43 - %01000011 ; SSE - $42 - %01000010 ; S - $41 - %01000001 ; SSW - $40 - %01000000 ; SW - $4F - %01001111 ; WSW - $4E - %01001110 ; W - $4D - %01001101 ; WNW - $4C - %01001100 ; NW - $4B - %01001011 ; NNW - $4A - %01001010 ; center - $00 - %00000000 ; ; mapping to cc65 definitions (4-direction joystick with 8 possible directions thru combinations) ; N, E, S, W -> JOY_UP, JOY_RIGHT, JOY_DOWN, JOY_LEFT ; NE, SE, SW, NW -> (JOY_UP | JOY_RIGHT), (JOY_DOWN | JOY_RIGHT), (JOY_DOWN | JOY_LEFT), (JOY_UP | JOY_LEFT) ; NNE, ENE, ESE, SSE, SSW, WSW, WNW, NNW: ; toggle between straight and diagonal direction for every call, e.g. ; NNE: ; call to READJOY: return JOY_UP | JOY_RIGHT ; call to READJOY: return JOY_UP ; call to READJOY: return JOY_UP | JOY_RIGHT ; call to READJOY: return JOY_UP ; call to READJOY: return JOY_UP | JOY_RIGHT ; etc... txa ; move direction status into A beq done ; center position (no bits are set), nothing to do and #$0F ; get rid of the "$40" bit bit bit0 ; is it a "three letter" direction (NNE, ENE, etc.)? beq special ; yes (bit #0 is zero) lsr a ; create index into table tax lda dirtable,x done: ora retval ; include "button" bits ldx #0 rts ; NNE, ENE, ESE, SSE, SSW, WSW, WNW, NNW special: lsr a tax lda toggler ; toggle the toggler eor #$01 sta toggler bne spec_1 ; toggler is 1, use spectable_1 entry lda spectable_0,x ; toggler is 0, use spectable_0 entry bne done ; jump always spec_1: lda spectable_1,x bne done ; jump always ; ------------------------------------------------------------------------ ; .rodata ; a mapping table of "port values" to "cc65 values" ; port value had been shifted one bit to the right (range 0..7) dirtable: .byte JOY_DOWN ; S .byte JOY_DOWN | JOY_RIGHT ; SE .byte JOY_RIGHT ; E .byte JOY_UP | JOY_RIGHT ; NE .byte JOY_UP ; N .byte JOY_UP | JOY_LEFT ; NW .byte JOY_LEFT ; W .byte JOY_DOWN | JOY_LEFT ; SW ; two "special" mapping tables for three-letter directions (NNE, etc.) spectable_0: .byte JOY_DOWN ; SSW .byte JOY_DOWN ; SSE .byte JOY_RIGHT ; ESE .byte JOY_RIGHT ; ENE .byte JOY_RIGHT ; NNE .byte JOY_UP ; NNW .byte JOY_LEFT ; WNW .byte JOY_LEFT ; WSW spectable_1: .byte JOY_DOWN | JOY_LEFT ; SSW .byte JOY_DOWN | JOY_RIGHT ; SSE .byte JOY_DOWN | JOY_RIGHT ; ESE .byte JOY_UP | JOY_RIGHT ; ENE .byte JOY_UP | JOY_RIGHT ; NNE .byte JOY_UP | JOY_LEFT ; NNW .byte JOY_UP | JOY_LEFT ; WNW .byte JOY_DOWN | JOY_LEFT ; WSW ; ------------------------------------------------------------------------ ; bit0: .byte $01 ; ------------------------------------------------------------------------ ; .bss toggler: .res 1 retval: .res 1 .end �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/creativision/joy_stat_stddrv.s�����������������������������������������������������0000664�0000000�0000000�00000000362�13473601511�0021571�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Address of the static standard joystick driver ; ; Christian Groessler, 2017-02-06 ; ; const void joy_static_stddrv[]; ; .export _joy_static_stddrv .import _creativisionstd_joy _joy_static_stddrv := _creativisionstd_joy ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/creativision/libref.s��������������������������������������������������������������0000664�0000000�0000000�00000000202�13473601511�0017603�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2013-05-31 ; .export joy_libref .import _exit joy_libref := _exit ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/creativision/psg.s�����������������������������������������������������������������0000664�0000000�0000000�00000002511�13473601511�0017136�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; void __fastcall__ psg_outb( unsigned char b ); ; void __fastcall__ psg_delayms( unsigned char c); ; void __fastcall__ bios_playsound( void *b, unsigned char c); ; void psg_silence( void ); .export _psg_outb, _psg_silence, _psg_delay .export _bios_playsound .import popa .include "creativision.inc" _psg_outb: ;* Let BIOS output the value jmp $FE77 _psg_silence: jmp $FE54 _psg_delay: tay l1: lda #200 l2: sbc #1 bne l2 lda #200 l3: sbc #1 bne l3 dey bne l1 rts ;* Creativision Sound Player ;* ;* Based on BIOS sound player. ;* Pass a pointer to a set of note triples, terminated with a tempo byte ;* and the len (max 255) _bios_playsound: pha ; Save Length Byte sei lda #$D5 ; BIOS volume table low sta $4 lda #$FC ; BIOS volume table high sta $5 jsr popa ; Get Sound table pointer low sta $0 jsr popa ; Get Sound table pointer high sta $1 pla tay ; Put length in Y dey php jmp $FBED ; Let BIOS do it's thing ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/creativision/setcursor.s�����������������������������������������������������������0000664�0000000�0000000�00000001411�13473601511�0020374�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Written by Groepaz/Hitmen <groepaz@gmx.net> ; Cleanup by Ullrich von Bassewitz <uz@cc65.org> ; ; Set the cursor position .export setcursor .include "creativision.inc" ;----------------------------------------------------------------------------- .proc setcursor tya clc adc addrlo,x sta SCREEN_PTR lda addrhi,x adc #0 sta SCREEN_PTR+1 rts .endproc ;----------------------------------------------------------------------------- ; Tables with screen addresses addrlo: .repeat SCREEN_ROWS,line .byte <($1000+(line*SCREEN_COLS)) .endrepeat addrhi: .repeat SCREEN_ROWS,line .byte >($1000+(line*SCREEN_COLS)) .endrepeat �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/creativision/sysuname.s������������������������������������������������������������0000664�0000000�0000000�00000001443�13473601511�0020214�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-08-12 ; ; unsigned char __fastcall__ _sysuname (struct utsname* buf); ; .export __sysuname, utsdata .import utscopy __sysuname = utscopy ;-------------------------------------------------------------------------- ; Data. We define a fixed utsname struct here and just copy it. .rodata utsdata: ; sysname .asciiz "cc65" ; nodename .asciiz "" ; release .byte ((.VERSION >> 8) & $0F) + '0' .byte '.' .byte ((.VERSION >> 4) & $0F) + '0' .byte $00 ; version .byte (.VERSION & $0F) + '0' .byte $00 ; machine .asciiz "CREATIVISION" �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/creativision/wherex.s��������������������������������������������������������������0000664�0000000�0000000�00000000353�13473601511�0017651�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-05-02 ; ; unsigned char wherex (void); ; .export _wherex .include "creativision.inc" .proc _wherex lda CURSOR_X ldx #$00 rts .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/creativision/wherey.s��������������������������������������������������������������0000664�0000000�0000000�00000000353�13473601511�0017652�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-05-02 ; ; unsigned char wherey (void); ; .export _wherey .include "creativision.inc" .proc _wherey lda CURSOR_Y ldx #$00 rts .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/dbg/�������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014217�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/dbg/asmtab.s�����������������������������������������������������������������������0000664�0000000�0000000�00000003405�13473601511�0015654�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 07.08.1998 ; ; Tables needed for the line assembler/disassembler. ; .export OffsetTab .export AdrFlagTab .export SymbolTab1, SymbolTab2 .export MnemoTab1, MnemoTab2 ; ------------------------------------------------------------------------- ; Assembler tables .rodata OffsetTab: .byte $40,$02,$45,$03,$D0,$08,$40,$09 .byte $30,$22,$45,$33,$D0,$08,$40,$09 .byte $40,$02,$45,$33,$D0,$08,$40,$09 .byte $40,$02,$45,$B3,$D0,$08,$40,$09 .byte $00,$22,$44,$33,$D0,$8C,$44,$00 .byte $11,$22,$44,$33,$D0,$8C,$44,$9A .byte $10,$22,$44,$33,$D0,$08,$40,$09 .byte $10,$22,$44,$33,$D0,$08,$40,$09 .byte $62,$13,$78,$A9 AdrFlagTab: .byte $00,$21,$81,$82,$00,$00,$59,$4D .byte $91,$92,$86,$4A,$85,$9D SymbolTab1: .byte $2C,$29,$2C,$23,$28,$24 SymbolTab2: .byte $59,$00,$58,$24,$24,$00 MnemoTab1: .byte $1C,$8A,$1C,$23,$5D,$8B,$1B,$A1 .byte $9D,$8A,$1D,$23,$9D,$8B,$1D,$A1 .byte $00,$29,$19,$AE,$69,$A8,$19,$23 .byte $24,$53,$1B,$23,$24,$53,$19,$A1 .byte $00,$1A,$5B,$5B,$A5,$69,$24,$24 .byte $AE,$AE,$A8,$AD,$29,$00,$7C,$00 .byte $15,$9C,$6D,$9C,$A5,$69,$29,$53 .byte $84,$13,$34,$11,$A5,$69,$23,$A0 MnemoTab2: .byte $D8,$62,$5A,$48,$26,$62,$94,$88 .byte $54,$44,$C8,$54,$68,$44,$E8,$94 .byte $00,$B4,$08,$84,$74,$B4,$28,$6E .byte $74,$F4,$CC,$4A,$72,$F2,$A4,$8A .byte $00,$AA,$A2,$A2,$74,$74,$74,$72 .byte $44,$68,$B2,$32,$B2,$00,$22,$00 .byte $1A,$1A,$26,$26,$72,$72,$88,$C8 .byte $C4,$CA,$26,$48,$44,$44,$A2,$C8 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/dbg/dbg.c��������������������������������������������������������������������������0000664�0000000�0000000�00000107122�13473601511�0015122�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** dbg.c ** ** Ullrich von Bassewitz, 08.08.1998 ** */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <conio.h> #include <ctype.h> #include <6502.h> #include <dbg.h> /*****************************************************************************/ /* Function forwards */ /*****************************************************************************/ /* Forwards for handler functions */ static char AsmHandler (void); static char RegHandler (void); static char StackHandler (void); static char CStackHandler (void); static char DumpHandler (void); static char HelpHandler (void); /* Forwards for other functions */ static void DisplayPrompt (const char* s); static void SingleStep (char StepInto); static void RedrawStatic (char Frame); static void Redraw (char Frame); static char GetKeyUpdate (void); /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Color definitions */ #if defined(__C16__) # define COLOR_BORDER (BCOLOR_DARKBLUE | CATTR_LUMA6) # define COLOR_BACKGROUND COLOR_WHITE # define COLOR_TEXTHIGH COLOR_BLACK # define COLOR_TEXTLOW COLOR_GRAY1 # define COLOR_FRAMEHIGH COLOR_BLACK # define COLOR_FRAMELOW COLOR_GRAY2 #else # if defined(COLOR_GRAY3) # define COLOR_BORDER COLOR_BLACK # define COLOR_BACKGROUND COLOR_BLACK # define COLOR_TEXTHIGH COLOR_WHITE # define COLOR_TEXTLOW COLOR_GRAY3 # define COLOR_FRAMEHIGH COLOR_WHITE # define COLOR_FRAMELOW COLOR_GRAY3 # else # if defined(__APPLE2__) # define COLOR_BORDER COLOR_BLACK # define COLOR_BACKGROUND COLOR_BLACK # define COLOR_TEXTHIGH COLOR_BLACK # define COLOR_TEXTLOW COLOR_BLACK # define COLOR_FRAMEHIGH COLOR_BLACK # define COLOR_FRAMELOW COLOR_BLACK # else # define COLOR_BORDER COLOR_BLACK # define COLOR_BACKGROUND COLOR_BLACK # define COLOR_TEXTHIGH COLOR_WHITE # define COLOR_TEXTLOW COLOR_WHITE # define COLOR_FRAMEHIGH COLOR_WHITE # define COLOR_FRAMELOW COLOR_WHITE # endif # endif #endif #ifndef COLOR_BLACK # define COLOR_BLACK 0 #endif #ifndef COLOR_WHITE # define COLOR_WHITE 1 #endif /* Screen definitions */ #if defined(__CBM610__) # define BIGSCREEN # define MAX_X 80 # define MAX_Y 25 # define DUMP_BYTES 16 #elif defined(__APPLE2__) || defined(__ATARI__) # define MAX_X 40 # define MAX_Y 24 # define DUMP_BYTES 8 #else # define MAX_X 40 # define MAX_Y 25 # define DUMP_BYTES 8 #endif /* Replacement key definitions */ #ifndef CH_DEL # define CH_DEL ('H' - 'A' + 1) /* Ctrl+H */ #endif /* Replacement char definitions */ #ifndef CH_ULCORNER # define CH_ULCORNER '+' #endif #ifndef CH_URCORNER # define CH_URCORNER '+' #endif #ifndef CH_LLCORNER # define CH_LLCORNER '+' #endif #ifndef CH_LRCORNER # define CH_LRCORNER '+' #endif #ifndef CH_TTEE # define CH_TTEE '+' #endif #ifndef CH_LTEE # define CH_LTEE '+' #endif #ifndef CH_RTEE # define CH_RTEE '+' #endif #ifndef CH_BTEE # define CH_BTEE '+' #endif #ifndef CH_CROSS # define CH_CROSS '+' #endif /* Defines for opcodes */ #define OPC_BRK 0x00 #define OPC_BPL 0x10 #define OPC_JSR 0x20 #define OPC_BMI 0x30 #define OPC_RTI 0x40 #define OPC_JMP 0x4C #define OPC_BVC 0x50 #define OPC_RTS 0x60 #define OPC_JMPIND 0x6C #define OPC_BVS 0x70 #define OPC_BCC 0x90 #define OPC_BCS 0xB0 #define OPC_BNE 0xD0 #define OPC_BEQ 0xF0 /* Register values that are used also in the assembler stuff */ extern unsigned char DbgSP; /* Stack pointer */ extern unsigned DbgCS; /* C stack pointer */ extern unsigned DbgHI; /* High 16 bit of primary reg */ /* Descriptor for one text line */ typedef struct { unsigned char x; unsigned char y; const char* text; } TextDesc; /* Window descriptor */ typedef struct { unsigned char fd_tl; /* Top left char */ unsigned char fd_tr; /* Top right char */ unsigned char fd_bl; /* Bottom left char */ unsigned char fd_br; /* Bottom right char */ unsigned char fd_x1, fd_y1; /* Upper left corner */ unsigned char fd_x2, fd_y2; /* Lower right corner */ unsigned char fd_width, fd_height; /* Redundant but faster */ unsigned char fd_visible; /* Is the window currently visible? */ char (*fd_func) (void); /* Handler function */ unsigned char fd_textcount; /* Number of text lines to print */ const TextDesc* fd_text; /* Static text in the window */ } FrameDesc; /* Texts for the windows */ static const TextDesc RegText [] = { { 1, 0, "PC" }, { 1, 1, "SR" }, { 1, 2, "A" }, { 1, 3, "X" }, { 1, 4, "Y" }, { 1, 5, "SP" }, { 1, 6, "CS" }, { 1, 7, "HI" } }; static const TextDesc HelpText [] = { { 1, 0, "F1, ? Help" }, { 1, 1, "F2, t Toggle breakpoint" }, { 1, 2, "F3, u Run until subroutine returns" }, { 1, 3, "F4, h Run to cursor" }, { 1, 4, "F7, space Step into" }, { 1, 5, "F8, enter Step over" }, { 1, 6, "1-5 Select active window" }, { 1, 7, "+ Page down" }, { 1, 8, "- Page up" }, { 1, 9, "Cursor Move up/down" }, { 1, 10, "a/z Move up/down" }, { 1, 11, "c Continue" }, { 1, 12, "f Follow instruction" }, { 1, 13, "o Goto origin" }, { 1, 14, "p Use as new PC value" }, { 1, 15, "q Quit" }, { 1, 16, "r Redraw screen" }, { 1, 17, "s Skip next instruction" }, }; /* Window data */ static const FrameDesc AsmFrame = { CH_ULCORNER, CH_TTEE, CH_LTEE, CH_CROSS, 0, 0, MAX_X - 10, 15, MAX_X - 11, 14, 1, AsmHandler, 0, 0 }; static const FrameDesc RegFrame = { CH_TTEE, CH_URCORNER, CH_LTEE, CH_RTEE, MAX_X - 10, 0, MAX_X - 1, 9, 8, 8, 1, RegHandler, sizeof (RegText) / sizeof (RegText [0]), RegText }; static const FrameDesc StackFrame = { CH_LTEE, CH_RTEE, CH_CROSS, CH_RTEE, MAX_X - 10, 9, MAX_X - 1, 15, 8, 5, 1, StackHandler, 0, 0 }; static const FrameDesc CStackFrame = { CH_CROSS, CH_RTEE, CH_BTEE, CH_LRCORNER, MAX_X - 10, 15, MAX_X - 1, MAX_Y - 1, 8, MAX_Y - 17, 1, CStackHandler, 0, 0 }; static const FrameDesc DumpFrame = { CH_LTEE, CH_CROSS, CH_LLCORNER, CH_BTEE, 0, 15, MAX_X - 10, MAX_Y-1, MAX_X - 11, MAX_Y - 17, 1, DumpHandler, 0, 0 }; static const FrameDesc HelpFrame = { CH_ULCORNER, CH_URCORNER, CH_LLCORNER, CH_LRCORNER, 0, 0, MAX_X - 1, MAX_Y-1, MAX_X - 2, MAX_Y - 2, 0, HelpHandler, sizeof (HelpText) / sizeof (HelpText [0]), HelpText }; static const FrameDesc* const Frames [] = { &AsmFrame, &RegFrame, &StackFrame, &CStackFrame, &DumpFrame, &HelpFrame }; /* Number of active frame, -1 = none */ static int ActiveFrame = -1; /* Window names */ #define WIN_ASM 0 #define WIN_REG 1 #define WIN_STACK 2 #define WIN_CSTACK 3 #define WIN_DUMP 4 #define WIN_HELP 5 /* Other window data */ static unsigned AsmAddr; /* Start address of output */ static unsigned DumpAddr; /* Start address of output */ static unsigned CStackAddr; /* Start address of output */ static unsigned char StackAddr; /* Start address of output */ /* Prompt line data */ static const char* ActivePrompt = 0; /* Last prompt line displayed */ static char PromptColor; /* Color behind prompt */ static char PromptLength; /* Length of current prompt string */ /* Values for the bk_use field of struct BreakPoint */ #define BRK_EMPTY 0x00 #define BRK_USER 0x01 #define BRK_TMP 0x80 /* Structure describing a breakpoint */ typedef struct { unsigned bk_addr; /* Address, 0 if unused */ unsigned char bk_opc; /* Opcode */ unsigned char bk_use; /* 1 if in use, 0 otherwise */ } BreakPoint; /* Temporary breakpoints - also accessed from the assembler source */ #define MAX_USERBREAKS 10 unsigned char DbgBreakCount = 0; BreakPoint DbgBreaks [MAX_USERBREAKS+2]; /*****************************************************************************/ /* Forwards for functions in the assembler source */ /*****************************************************************************/ BreakPoint* DbgGetBreakSlot (void); /* Search for a free breakpoint slot. Return a pointer to the slot or 0 */ BreakPoint* DbgIsBreak (unsigned Addr); /* Check if there is a user breakpoint at the given address, if so, return ** a pointer to the slot, else return 0. */ /*****************************************************************************/ /* Frame/window drawing code */ /*****************************************************************************/ static void DrawFrame (register const FrameDesc* F, char Active) /* Draw one window frame */ { const TextDesc* T; unsigned char Count; unsigned char tl, tr, bl, br; unsigned char x1, y1, width; unsigned char OldColor; /* Determine the characters for the corners, set frame color */ if (Active) { OldColor = textcolor (COLOR_FRAMEHIGH); tl = CH_ULCORNER; tr = CH_URCORNER; bl = CH_LLCORNER; br = CH_LRCORNER; } else { OldColor = textcolor (COLOR_FRAMELOW); tl = F->fd_tl; tr = F->fd_tr; bl = F->fd_bl; br = F->fd_br; } /* Get the coordinates into locals for faster access */ x1 = F->fd_x1; y1 = F->fd_y1; width = F->fd_width; /* Top line */ cputcxy (x1, y1, tl); chline (width); cputc (tr); /* Left line */ cvlinexy (x1, ++y1, F->fd_height); /* Bottom line */ cputc (bl); chline (width); cputc (br); /* Right line */ cvlinexy (F->fd_x2, y1, F->fd_height); /* If the window has static text associated, print the text */ (void) textcolor (COLOR_TEXTLOW); Count = F->fd_textcount; T = F->fd_text; while (Count--) { cputsxy (x1 + T->x, y1 + T->y, T->text); ++T; } /* Set the old color */ (void) textcolor (OldColor); } static void DrawFrames (void) /* Draw all frames */ { unsigned char I; const FrameDesc* F; /* Build the frame layout of the screen */ for (I = 0; I < sizeof (Frames) / sizeof (Frames [0]); ++I) { F = Frames [I]; if (F->fd_visible) { DrawFrame (F, 0); } } } static void ActivateFrame (int Num, unsigned char Clear) /* Activate a new frame, deactivate the old one */ { unsigned char y; register const FrameDesc* F; if (ActiveFrame != Num) { /* Deactivate the old one */ if (ActiveFrame >= 0) { DrawFrame (Frames [ActiveFrame], 0); } /* Activate the new one */ if ((ActiveFrame = Num) >= 0) { F = Frames [ActiveFrame]; /* Clear the frame if requested */ if (Clear) { for (y = F->fd_y1+1; y < F->fd_y2; ++y) { cclearxy (F->fd_x1+1, y, F->fd_width); } } DrawFrame (F, 1); } /* Redraw the current prompt line */ DisplayPrompt (ActivePrompt); } } /*****************************************************************************/ /* Prompt line */ /*****************************************************************************/ static void DisplayPrompt (const char* s) /* Display a prompt */ { unsigned char OldColor; /* Remember the current color */ OldColor = textcolor (COLOR_TEXTHIGH); /* Clear the old prompt if there is one */ if (ActivePrompt) { (void) textcolor (PromptColor); chlinexy ((MAX_X - PromptLength) / 2, MAX_Y-1, PromptLength); } /* Get the new prompt data */ ActivePrompt = s; PromptColor = OldColor; PromptLength = strlen (ActivePrompt); /* Display the new prompt */ (void) textcolor (COLOR_TEXTHIGH); cputsxy ((MAX_X - PromptLength) / 2, MAX_Y-1, ActivePrompt); /* Restore the old color */ (void) textcolor (PromptColor); } static void HelpPrompt (void) /* Display a prompt line mentioning the help key */ { DisplayPrompt ("Press F1 for help"); } static void AnyKeyPrompt (void) { DisplayPrompt ("Press any key to continue"); } static char IsAbortKey (char C) /* Return true if C is an abort key */ { #if defined(CH_ESC) if (C == CH_ESC) { return 1; } #endif #if defined(CH_STOP) if (C == CH_STOP) { return 1; } #endif #if !defined(CH_ESC) && !defined(CH_STOP) /* Avoid compiler warning about unused parameter */ (void) C; #endif return 0; } static char Input (char* Prompt, char* Buf, unsigned char Count) /* Read input from the user, return 1 on success, 0 if aborted */ { int Frame; unsigned char OldColor; unsigned char OldCursor; unsigned char x1; unsigned char i; unsigned char done; char c; /* Clear the current prompt line */ cclearxy (0, MAX_Y-1, MAX_X); /* Display the new prompt */ OldColor = textcolor (COLOR_TEXTHIGH); cputsxy (0, MAX_Y-1, Prompt); (void) textcolor (COLOR_TEXTLOW); /* Remember where we are, enable the cursor */ x1 = wherex (); OldCursor = cursor (1); /* Get input and handle it */ i = done = 0; do { c = cgetc (); if (isalnum (c) && i < Count) { Buf [i] = c; cputcxy (x1 + i, MAX_Y-1, c); ++i; } else if (i > 0 && c == CH_DEL) { --i; cputcxy (x1 + i, MAX_Y-1, ' '); gotoxy (x1 + i, MAX_Y-1); } else if (c == '\n') { Buf [i] = '\0'; done = 1; } else if (IsAbortKey (c)) { /* Abort */ done = 2; } } while (!done); /* Reset settings, display old prompt line */ cursor (OldCursor); (void) textcolor (OldColor); DrawFrames (); Frame = ActiveFrame; ActiveFrame = -1; ActivateFrame (Frame, 0); return (done == 1); } static char InputHex (char* Prompt, unsigned* Val) /* Prompt for a hexadecimal value. Return 0 on failure. */ { char Buf [5]; char* P; char C; unsigned V; /* Read input from the user (4 digits max), check input */ if (Input (Prompt, Buf, sizeof (Buf)-1) && isxdigit (Buf [0])) { /* Check the characters and convert to hex */ P = Buf; V = 0; while ((C = *P) && isxdigit (C)) { V <<= 4; if (isdigit (C)) { C -= '0'; } else { C = toupper (C) - ('A' - 10); } V += C; ++P; } /* Assign the value */ *Val = V; /* Success */ return 1; } else { /* Failure */ return 0; } } static void ErrorPrompt (const char* Msg) /* Display an error message and wait for a key */ { /* Save the current prompt */ const char* OldPrompt = ActivePrompt; /* Display the new one */ DisplayPrompt (Msg); /* Wait for a key and discard it */ cgetc (); /* Restore the old prompt */ DisplayPrompt (OldPrompt); } static char InputGoto (unsigned* Addr) /* Prompt "Goto" and read an address. Print an error and return 0 on failure. */ { char Ok; Ok = InputHex ("Goto: ", Addr); if (!Ok) { ErrorPrompt ("Invalid input - press a key"); } return Ok; } static void BreakInRomError (void) /* Print an error message if we cannot set a breakpoint */ { ErrorPrompt ("Cannot set breakpoint - press a key"); } /*****************************************************************************/ /* Breakpoint handling */ /*****************************************************************************/ static void DbgSetTmpBreak (unsigned Addr) /* Set a breakpoint */ { BreakPoint* B = DbgGetBreakSlot (); B->bk_addr = Addr; B->bk_use = BRK_TMP; } static void DbgToggleUserBreak (unsigned Addr) /* Set a breakpoint */ { register BreakPoint* B = DbgIsBreak (Addr); if (B) { /* We have a breakpoint, remove it */ B->bk_use = BRK_EMPTY; --DbgBreakCount; } else { /* We don't have a breakpoint, set one */ if (DbgBreakCount >= MAX_USERBREAKS) { ErrorPrompt ("Too many breakpoints - press a key"); } else { /* Test if we can set a breakpoint at that address */ if (!DbgIsRAM (Addr)) { BreakInRomError (); } else { /* Set the breakpoint */ B = DbgGetBreakSlot (); B->bk_addr = Addr; B->bk_use = BRK_USER; ++DbgBreakCount; } } } } static void DbgResetTmpBreaks (void) /* Reset all temporary breakpoints */ { unsigned char i; BreakPoint* B = DbgBreaks; for (i = 0; i < MAX_USERBREAKS; ++i) { if (B->bk_use == BRK_TMP) { B->bk_use = BRK_EMPTY; } ++B; } } static unsigned char DbgTmpBreaksOk (void) /* Check if the temporary breakpoints can be set, if so, return 1, if not, ** reset them all and return 0. */ { unsigned char i; BreakPoint* B = DbgBreaks; for (i = 0; i < MAX_USERBREAKS; ++i) { if (B->bk_use == BRK_TMP && !DbgIsRAM (B->bk_addr)) { BreakInRomError (); DbgResetTmpBreaks (); return 0; } ++B; } return 1; } /*****************************************************************************/ /* Assembler window stuff */ /*****************************************************************************/ static unsigned AsmBack (unsigned mem, unsigned char lines) /* Go back in the assembler window the given number of lines (calculate ** new start address). */ { unsigned cur; unsigned adr [32]; unsigned char in; unsigned offs = 6; while (1) { in = 0; cur = mem - (lines * 3) - offs; while (1) { cur += DbgDisAsmLen (cur); adr [in] = cur; in = (in + 1) & 0x1F; if (cur >= mem) { if (cur == mem || offs == 12) { /* Found */ return adr [(in - lines - 1) & 0x1F]; } else { /* The requested address is inside an instruction, go back ** one more byte and try again. */ ++offs; break; } } } } } static unsigned UpdateAsm (void) /* Update the assembler window starting at the given address */ { char buf [MAX_X]; unsigned char len; unsigned char y; unsigned char width = AsmFrame.fd_width; unsigned char x = AsmFrame.fd_x1 + 1; unsigned m = AsmBack (AsmAddr, 2); for (y = AsmFrame.fd_y1+1; y < AsmFrame.fd_y2; ++y) { len = DbgDisAsm (m, buf, width); if (m == brk_pc) { buf [4] = '-'; buf [5] = '>'; } if (DbgIsBreak (m)) { buf [5] = '*'; } if (m == AsmAddr) { revers (1); cputsxy (1, y, buf); revers (0); } else { cputsxy (1, y, buf); } m += len; } return m; } static unsigned AsmArg16 (void) /* Return a 16 bit argument */ { return *(unsigned*)(AsmAddr+1); } static void AsmFollow (void) /* Follow the current instruction */ { switch (*(unsigned char*) AsmAddr) { case OPC_JMP: case OPC_JSR: AsmAddr = AsmArg16 (); break; case OPC_JMPIND: AsmAddr = *(unsigned*)AsmArg16 (); break; case OPC_BPL: case OPC_BMI: case OPC_BVC: case OPC_BVS: case OPC_BCC: case OPC_BCS: case OPC_BNE: case OPC_BEQ: AsmAddr = AsmAddr + 2 + *(signed char*)(AsmAddr+1); break; case OPC_RTS: AsmAddr = (*(unsigned*) (DbgSP + 0x101) + 1); break; case OPC_RTI: AsmAddr = *(unsigned*) (DbgSP + 0x102); break; } } static void AsmHome (void) /* Set the cursor to home position */ { AsmAddr = brk_pc; } static void InitAsm (void) /* Initialize the asm window */ { AsmHome (); UpdateAsm (); } static char AsmHandler (void) /* Get characters and handle them */ { char c; unsigned Last; while (1) { /* Update the window contents */ Last = UpdateAsm (); /* Read and handle input */ switch (c = GetKeyUpdate ()) { case '+': AsmAddr = Last; break; case '-': AsmAddr = AsmBack (AsmAddr, AsmFrame.fd_height); break; case 't': #ifdef CH_F2 case CH_F2: #endif DbgToggleUserBreak (AsmAddr); break; case 'f': AsmFollow (); break; case 'g': InputGoto (&AsmAddr); break; case 'o': AsmHome (); break; case 'p': brk_pc = AsmAddr; break; case 'a': #ifdef CH_CURS_UP case CH_CURS_UP: #endif AsmAddr = AsmBack (AsmAddr, 1); break; case 'z': #ifdef CH_CURS_DOWN case CH_CURS_DOWN: #endif AsmAddr += DbgDisAsmLen (AsmAddr); break; default: return c; } } } /*****************************************************************************/ /* Register window stuff */ /*****************************************************************************/ static unsigned UpdateReg (void) /* Update the register window */ { unsigned char x1 = RegFrame.fd_x1 + 5; unsigned char x2 = x1 + 2; unsigned char y = RegFrame.fd_y1; /* Print the register contents */ gotoxy (x1, ++y); cputhex16 (brk_pc); gotoxy (x2, ++y); cputhex8 (brk_sr); gotoxy (x2, ++y); cputhex8 (brk_a); gotoxy (x2, ++y); cputhex8 (brk_x); gotoxy (x2, ++y); cputhex8 (brk_y); gotoxy (x2, ++y); cputhex8 (DbgSP); gotoxy (x1, ++y); cputhex16 (DbgCS); gotoxy (x1, ++y); cputhex16 (DbgHI); /* Not needed */ return 0; } static void InitReg (void) /* Initialize the register window */ { UpdateReg (); } static char RegHandler (void) /* Get characters and handle them */ { return GetKeyUpdate (); } /*****************************************************************************/ /* Stack window stuff */ /*****************************************************************************/ static unsigned UpdateStack (void) /* Update the stack window */ { unsigned char mem = StackAddr; unsigned char x1 = StackFrame.fd_x1 + 1; unsigned char x2 = x1 + 6; unsigned char y; for (y = StackFrame.fd_y2-1; y > StackFrame.fd_y1; --y) { gotoxy (x1, y); cputhex8 (mem); gotoxy (x2, y); cputhex8 (* (unsigned char*) (mem + 0x100)); ++mem; } return mem; } static void StackHome (void) /* Set the cursor to home position */ { StackAddr = DbgSP + 1; } static void InitStack (void) /* Initialize the stack window */ { StackHome (); UpdateStack (); } static char StackHandler (void) /* Get characters and handle them */ { char c; unsigned char BytesPerPage = StackFrame.fd_height; while (1) { /* Read and handle input */ switch (c = GetKeyUpdate ()) { case '+': StackAddr += BytesPerPage; break; case '-': StackAddr -= BytesPerPage; break; case 'o': StackHome (); break; case 'a': #ifdef CH_CURS_UP: case CH_CURS_UP: #endif --StackAddr; break; case 'z': #ifdef CH_CURS_DOWN case CH_CURS_DOWN: #endif ++StackAddr; break; default: return c; } /* Update the window contents */ UpdateStack (); } } /*****************************************************************************/ /* C Stack window stuff */ /*****************************************************************************/ static unsigned UpdateCStack (void) /* Update the C stack window */ { unsigned mem = CStackAddr; unsigned char x = CStackFrame.fd_x1 + 5; unsigned char y; for (y = CStackFrame.fd_y2-1; y > CStackFrame.fd_y1; --y) { gotoxy (x, y); cputhex16 (* (unsigned*)mem); mem += 2; } cputsxy (CStackFrame.fd_x1+1, CStackFrame.fd_y2-1, "->"); return mem; } static void CStackHome (void) /* Set the cursor to home position */ { CStackAddr = DbgCS; } static void InitCStack (void) /* Initialize the C stack window */ { CStackHome (); UpdateCStack (); } static char CStackHandler (void) /* Get characters and handle them */ { char c; unsigned char BytesPerPage = CStackFrame.fd_height * 2; while (1) { /* Read and handle input */ switch (c = GetKeyUpdate ()) { case '+': CStackAddr += BytesPerPage; break; case '-': CStackAddr -= BytesPerPage; break; case 'o': CStackHome (); break; case 'a': #ifdef CH_CURS_UP case CH_CURS_UP: #endif CStackAddr -= 2; break; case 'z': #ifdef CH_CURS_DOWN case CH_CURS_DOWN: #endif CStackAddr += 2; break; default: return c; } /* Update the window contents */ UpdateCStack (); } } /*****************************************************************************/ /* Dump window stuff */ /*****************************************************************************/ static unsigned UpdateDump (void) /* Update the dump window */ { char Buf [MAX_X]; unsigned char y; unsigned mem = DumpAddr; unsigned char x = DumpFrame.fd_x1 + 1; unsigned char* p = (unsigned char*) mem; for (y = DumpFrame.fd_y1+1; y < DumpFrame.fd_y2; ++y) { cputsxy (x, y, DbgMemDump (mem, Buf, DUMP_BYTES)); mem += DUMP_BYTES; } return mem; } static void DumpHome (void) /* Set the cursor to home position */ { DumpAddr = 0; } static char DumpHandler (void) /* Get characters and handle them */ { char c; unsigned BytesPerPage = DumpFrame.fd_height * 8; while (1) { /* Read and handle input */ switch (c = GetKeyUpdate ()) { case '+': DumpAddr += BytesPerPage; break; case '-': DumpAddr -= BytesPerPage; break; case 'g': InputGoto (&DumpAddr); break; case 'o': DumpHome (); break; case 'a': #ifdef CH_CURS_UP case CH_CURS_UP: #endif DumpAddr -= 8; break; case 'z': #ifdef CH_CURS_DOWN case CH_CURS_DOWN: #endif DumpAddr += 8; break; default: return c; } /* Update the window contents */ UpdateDump (); } } /*****************************************************************************/ /* Help window stuff */ /*****************************************************************************/ static char HelpHandler (void) /* Get characters and handle them */ { /* Activate the frame */ int OldActive = ActiveFrame; ActivateFrame (WIN_HELP, 1); /* Say that we're waiting for a key */ AnyKeyPrompt (); /* Get a character and discard it */ cgetc (); /* Redraw the old stuff */ Redraw (OldActive); /* Done, return no char */ return 0; } /*****************************************************************************/ /* Singlestep */ /*****************************************************************************/ static unsigned GetArg16 (void) /* Read an argument */ { return *(unsigned*)(brk_pc+1); } static unsigned GetStack16 (unsigned char Offs) /* Fetch a 16 bit value from stack top */ { return *(unsigned*)(DbgSP+Offs+0x101); } static void SetRTSBreak (void) /* Set a breakpoint at the return target */ { DbgSetTmpBreak (GetStack16 (0) + 1); } static void SingleStep (char StepInto) { signed char Offs; switch (*(unsigned char*) brk_pc) { case OPC_JMP: /* Set breakpoint at target */ DbgSetTmpBreak (GetArg16 ()); return; case OPC_JMPIND: /* Indirect jump, ignore CPU error when crossing page */ DbgSetTmpBreak (*(unsigned*)GetArg16 ()); return; case OPC_BPL: case OPC_BMI: case OPC_BVC: case OPC_BVS: case OPC_BCC: case OPC_BCS: case OPC_BNE: case OPC_BEQ: /* Be sure not to set the breakpoint twice if this is a jump to ** the following instruction. */ Offs = ((signed char*)brk_pc)[1]; if (Offs) { DbgSetTmpBreak (brk_pc + Offs + 2); } break; case OPC_RTS: /* Set a breakpoint at the return target */ SetRTSBreak (); return; case OPC_RTI: /* Set a breakpoint at the return target */ DbgSetTmpBreak (GetStack16 (1)); return; case OPC_JSR: if (StepInto) { /* Set breakpoint at target */ DbgSetTmpBreak (GetArg16 ()); return; } break; } /* Place a breakpoint behind the instruction */ DbgSetTmpBreak (brk_pc + DbgDisAsmLen (brk_pc)); } /*****************************************************************************/ /* High level window handling */ /*****************************************************************************/ static void RedrawStatic (char Frame) /* Redraw static display stuff */ { /* Reset the active frame */ ActiveFrame = -1; /* Clear the screen hide the cursor */ (void) bordercolor (COLOR_BORDER); (void) bgcolor (COLOR_BACKGROUND); clrscr (); cursor (0); /* Build the frame layout of the screen */ (void) textcolor (COLOR_FRAMELOW); DrawFrames (); /* Draw the prompt line */ HelpPrompt (); /* Activate the active frame */ ActivateFrame (Frame, 0); } static void Redraw (char Frame) /* Redraw the display in case it's garbled */ { /* Redraw the static stuff */ RedrawStatic (Frame); /* Init the window contents */ UpdateAsm (); UpdateReg (); UpdateStack (); UpdateCStack (); UpdateDump (); } static char GetKeyUpdate (void) /* Wait for a key updating the windows in the background */ { static unsigned char Win; /* While there are no keys... */ while (!kbhit ()) { switch (Win) { case 0: UpdateAsm (); break; case 1: UpdateStack (); break; case 2: UpdateCStack (); break; case 3: UpdateDump (); break; } Win = (Win + 1) & 0x03; } /* We have a key - return it */ return cgetc (); } /*****************************************************************************/ /* Externally visible functions */ /*****************************************************************************/ void DbgEntry (void) /* Start up the debugger */ { static unsigned char FirstTime = 1; char c; char done; /* If this is the first call, setup the display */ if (FirstTime) { FirstTime = 0; /* Draw the window, default active frame is ASM frame */ RedrawStatic (WIN_ASM); InitAsm (); InitReg (); InitStack (); InitCStack (); UpdateDump (); } /* Only initialize variables here, don't do a display update. The actual ** display update will be done while waiting for user input. */ AsmHome (); UpdateReg (); /* Must update this (static later) */ StackHome (); CStackHome (); /* Wait for user input */ done = 0; while (!done) { c = Frames [ActiveFrame]->fd_func (); switch (c) { case '1': case '2': case '3': case '4': case '5': ActivateFrame (c - '1', 0); break; case '?': #ifdef CH_F1 case CH_F1: #endif HelpHandler (); break; case 'u': #ifdef CH_F3 case CH_F3: #endif /* Go until return */ SetRTSBreak (); done = 1; break; case 'h': #ifdef CH_F4 case CH_F4: #endif /* Go to cursor, only possible if cursor not at current PC */ if (AsmAddr != brk_pc) { DbgSetTmpBreak (AsmAddr); done = 1; } break; case ' ': #ifdef CH_F7 case CH_F7: #endif SingleStep (1); if (DbgTmpBreaksOk ()) { /* Could set breakpoints */ done = 1; } break; case '\n': #ifdef CH_F8 case CH_F8: #endif SingleStep (0); if (DbgTmpBreaksOk ()) { /* Could set breakpoints */ done = 1; } break; case 'c': case 0: done = 1; break; case 's': /* Skip instruction */ brk_pc += DbgDisAsmLen (brk_pc); InitAsm (); break; case 'r': /* Redraw screen */ Redraw (ActiveFrame); break; case 'q': /* Quit program */ clrscr (); exit (1); } } } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/dbg/dbgdasm.s����������������������������������������������������������������������0000664�0000000�0000000�00000017272�13473601511�0016015�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 07.08.1998 ; ; unsigned DbgDisAsm (char* buf, unsigned addr); ; unsigned DbgDisAsm (unsigned addr); ; ; ; Part of this code is taken from the Plus/4 machine language monitor ; (TEDMon). ; .import popax .import __hextab, OffsetTab, AdrFlagTab .import SymbolTab1, SymbolTab2, MnemoTab1, MnemoTab2 ; ------------------------------------------------------------------------- ; Equates for better readability .importzp sreg, tmp1, tmp2, tmp3, tmp4, ptr1, ptr2, ptr3 BufIndex = tmp1 ; Index into output buffer OperandLen = tmp2 ; Length of operand BufLen = tmp3 ; Length of output buffer AdrFlagBuf = tmp4 ; Flag for addressing mode YSave = sreg ; Temp storage XSave = sreg+1 ; Dito BufPtr = ptr1 ; Pointer to output buffer MemPtr = ptr2 ; Pointer to memory to disassemble MnemoBuf = ptr3 ; Buffer for decoding mnemonic ; ------------------------------------------------------------------------- ; Main entries .export _DbgDisAsm, _DbgDisAsmLen .proc _DbgDisAsm sta BufLen ; Save the buffer length jsr popax ; Get the buffer pointer sta BufPtr stx BufPtr+1 jsr popax ; Get the address sta MemPtr stx MemPtr+1 lda #0 sta BufIndex ; Initialize index into buffer jsr DisAssLine ; Disassemble one line into the buffer lda BufLen ; Get requested length sec sbc BufIndex beq L2 tax ; Count into X ldy BufIndex lda #$20 ; Get a space L1: sta (BufPtr),y iny dex bne L1 L2: lda #0 ; Add C string terminator sta (BufPtr),y beq disassret .endproc _DbgDisAsmLen: sta MemPtr ; Save address stx MemPtr+1 ldy #$00 lda (MemPtr),y ; Get the opcode from memory... jsr AnalyzeOPCode ; ...and analyze it disassret: ldx OperandLen ; Get length of operand inx ; Adjust for opcode byte txa ldx #$00 ; Clear high byte rts ; ------------------------------------------------------------------------- ; Helper functions Put3Spaces: jsr PutSpace Put2Spaces: jsr PutSpace PutSpace: lda #$20 PutChar: sty YSave ; Save Y ldy BufIndex ; Get current line pointer cpy BufLen ; Be sure not to overflow the buffer bcs PC9 sta (BufPtr),y ; store character iny ; bump index sty BufIndex PC9: ldy YSave ; get old value rts ; Print the 16 bit hex value in X/Y PutHex16: txa jsr PutHex8 tya ; Print 8 bit value in A, save X and Y PutHex8: stx XSave sty YSave ldy BufIndex pha lsr a lsr a lsr a lsr a tax lda __hextab,x sta (BufPtr),y iny pla and #$0F tax lda __hextab,x sta (BufPtr),y iny sty BufIndex ldy YSave ldx XSave rts ; ------------------------------------------------------------------------- ; Disassemble one line DisAssLine: ldy MemPtr ldx MemPtr+1 jsr PutHex16 ; Print the address jsr Put2Spaces ; Add some space ldy #$00 lda (MemPtr),y ; Get the opcode from memory... jsr AnalyzeOPCode ; ...and analyze it pha ; Save mnemonic ldx OperandLen ; Number of bytes ; Print the bytes that make up the instruction inx L2083: dex bpl L208C ; Print the instruction bytes jsr Put3Spaces ; If none left, print spaces instead jmp L2094 L208C: lda (MemPtr),y ; Get a byte from memory jsr PutHex8 ; ...and print it jsr PutSpace ; Add some space L2094: iny ; Next one... cpy #$03 ; Maximum is three bcc L2083 ; jsr Put2Spaces ; Add some space after bytes ; Print the assembler mnemonic pla ; Get mnemonic code ldx #$03 jsr PutMnemo ; Print the mnemonic ldx #$06 ; Print the operand L20A4: cpx #$03 bne L20BA ldy OperandLen beq L20BA L20AC: lda AdrFlagBuf cmp #$E8 ; Branch? lda (MemPtr),y ; Get branch offset bcs GetBranchAdr ; If branch: Calculate address jsr PutHex8 ; Otherwise print 8bit value dey bne L20AC L20BA: asl AdrFlagBuf bcc L20CC lda SymbolTab1-1,x jsr PutChar lda SymbolTab2-1,x beq L20CC jsr PutChar L20CC: dex bne L20A4 rts ; If the instruction is a branch, calculate the absolute address of the ; branch target and print it. GetBranchAdr: jsr L20DD clc adc #$01 bne L20D9 inx ; Bump high byte L20D9: tay jmp PutHex16 ; Output address L20DD: ldx MemPtr+1 tay bpl L20E3 dex L20E3: adc MemPtr bcc L20E8 inx ; Bump high byte L20E8: rts ; ------------------------------------------------------------------------- ; Subroutine to analyze an opcode byte in A. Will return a byte that ; encodes the mnemonic, and will set the number of bytes needed for this ; instruction in OperandLen AnalyzeOPCode: tay lsr a bcc L20F8 lsr a bcs L2107 cmp #$22 beq L2107 and #$07 ora #$80 L20F8: lsr a tax lda OffsetTab,x bcs L2103 lsr a lsr a lsr a lsr a L2103: and #$0F bne L210B L2107: ldy #$80 lda #$00 L210B: tax lda AdrFlagTab,x sta AdrFlagBuf and #$03 sta OperandLen tya and #$8F tax tya ldy #$03 cpx #$8A beq L212B L2120: lsr a bcc L212B lsr a L2124: lsr a ora #$20 dey bne L2124 iny L212B: dey bne L2120 rts ; ------------------------------------------------------------------------- ; Print the mnemonic with code in A (that code was returned by ; AnalyzeOpcode). PutMnemo: tay lda MnemoTab1,y sta MnemoBuf lda MnemoTab2,y sta MnemoBuf+1 L213A: lda #$00 ldy #$05 ; 3*5 bits in two bytes L213E: asl MnemoBuf+1 rol MnemoBuf rol a dey bne L213E adc #$3F jsr PutChar dex bne L213A jmp PutSpace ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/dbg/dbgdump.s����������������������������������������������������������������������0000664�0000000�0000000�00000003531�13473601511�0016027�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 11.08.1998 ; ; char* __cdecl__ DbgMemDump (unsigend Addr, char* Buf, unsigned char Length); ; .export _DbgMemDump .import addysp1 .import __hextab .importzp sp, tmp2, tmp3, tmp4, ptr3, ptr4 _DbgMemDump: ldy #0 lda (sp),y ; Get length sta tmp4 iny lda (sp),y ; Get the string buffer sta ptr3 iny lda (sp),y sta ptr3+1 iny lda (sp),y ; Get the address sta ptr4 iny lda (sp),y sta ptr4+1 jsr addysp1 ; Drop the parameters lda #0 sta tmp2 ; String index sta tmp3 ; Byte index ; Print the address lda ptr4+1 ; Hi address byte jsr dump ; Print address lda ptr4 ; Lo address byte jsr dump jsr putspace ; Add a space dump1: dec tmp4 ; Bytes left? bmi dump9 ; Jump if no jsr putspace ; Add a space ldy tmp3 inc tmp3 lda (ptr4),y jsr dump jmp dump1 dump9: lda #0 ldy tmp2 sta (ptr3),y ; Add string terminator lda ptr3 ldx ptr3+1 ; We assume this is not zero rts ; Dump one hex byte dump: pha lsr a lsr a lsr a lsr a tax lda __hextab,x jsr putc pla and #$0F tax lda __hextab,x putc: ldy tmp2 inc tmp2 sta (ptr3),y rts putspace: lda #$20 bne putc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/dbg/dbgisram.s���������������������������������������������������������������������0000664�0000000�0000000�00000002151�13473601511�0016172�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 10.08.1998 ; ; int DbgIsRAM (unsigned Addr); ; .export _DbgIsRAM .import popax, return0, return1 .importzp ptr1 _DbgIsRAM: sta ptr1 ; Store the address stx ptr1+1 ldy #0 php ; Save I flag sei ; Disable interrupts lda (ptr1),y ; Get old value pha ; ...and save it ldx #3 L1: lda TestVal,x jsr CheckCell bne L2 dex bpl L1 ; This seems to be RAM pla sta (ptr1),y ; Restore old value plp ; Restore old I flag jmp return1 ; No RAM at this address L2: pla sta (ptr1),y ; Restore old value plp ; Restore old I flag jmp return0 ; Check one memory cell CheckCell: sta (ptr1),y cmp (ptr1),y ; Could we write it? rts .rodata TestVal: .byte $55, $AA, $33, $CC �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/dbg/dbgsupp.s����������������������������������������������������������������������0000664�0000000�0000000�00000011345�13473601511�0016053�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 08.08.1998 ; ; Support routines for the debugger ; .export _DbgInit .export _DbgSP, _DbgCS, _DbgHI .import popptr1, return0, _DbgEntry, _set_brk, _end_brk .import _DbgBreaks .import _brk_pc .import __ZP_START__ ; Linker generated .include "zeropage.inc" ; C callable function, will install the debugger _DbgInit: lda #<DbgBreak ldx #>DbgBreak jmp _set_brk ; Entry for the break vector. DbgBreak: pla sta retsav pla sta retsav+1 cli tsx ; Stack pointer stx _DbgSP jsr DbgSwapZP ; Swap stuff lda #<DbgStack ; Set new stack sta sp lda #>DbgStack sta sp+1 jsr ResetDbgBreaks ; Reset temporary breakpoints jsr _DbgEntry ; Call C code jsr SetDbgBreaks ; Set temporary breakpoints jsr DbgSwapZP ; Swap stuff back lda retsav+1 pha lda retsav pha rts ; Stack used when in debugger mode .bss .res 256 DbgStack: ; Swap space for the the C temporaries CTemp: _DbgCS: .res 2 ; sp _DbgHI: .res 2 ; sreg .res (zpsavespace-4) ; Other stuff _DbgSP: .res 1 retsav: .res 2 ; Save buffer for return address .code ; Swap the C temporaries DbgSwapZP: ldy #zpsavespace-1 Swap1: ldx CTemp,y lda <__ZP_START__,y sta CTemp,y txa sta sp,y dey bpl Swap1 rts ; ---------------------------------------------------------------------------- ; Utility functions ; Set/reset the breakpoints. We must do that here since the breakpoints ; may be in the runtime stuff, causing the C part to fail before it has ; reset the breakpoints. See declaration of struct breakpoint in the C ; source MaxBreaks = 48 ; 4*12 ResetDbgBreaks: ldy #0 ldx #0 L4: lda _DbgBreaks+3,x ; Get bk_use beq L6 ; Jump if not set bpl L5 ; Jump if user breakpoint lda #0 sta _DbgBreaks+3,x ; Clear if temp breakpoint L5: lda _DbgBreaks+1,x ; PC hi sta ptr1+1 lda _DbgBreaks,x ; PC lo sta ptr1 lda _DbgBreaks+2,x ; Old OPC sta (ptr1),y ; Reset the breakpoint L6: inx inx inx inx cpx #MaxBreaks ; Done? bne L4 rts SetDbgBreaks: ldx #0 ldy #0 L7: lda _DbgBreaks+3,x ; Get bk_use beq L8 ; Jump if not set lda _DbgBreaks+1,x ; PC hi sta ptr1+1 lda _DbgBreaks,x ; PC lo sta ptr1 lda (ptr1),y ; Get the breakpoint OPC... sta _DbgBreaks+2,x ; ...and save it lda #$00 ; Load BRK opcode sta (ptr1),y L8: inx inx inx inx cpx #MaxBreaks ; Done? bne L7 rts ; Get a free breakpoint slot or return 0 .export _DbgGetBreakSlot _DbgGetBreakSlot: ldx #0 L10: lda _DbgBreaks+3,x ; Get bk_use beq L11 ; Jump if not set inx inx inx inx cpx #MaxBreaks ; Done? bne L10 jmp return0 ; No free slot L11: stx tmp1 lda #<_DbgBreaks ldx #>_DbgBreaks clc adc tmp1 bcc L12 inx L12: ldy #1 ; Force != 0 rts ; Check if a given address has a user breakpoint set, if found, return the ; slot, otherwise return 0. .export _DbgIsBreak _DbgIsBreak: jsr popptr1 ; Get address ldx #0 L20: lda _DbgBreaks+3,x ; Get bk_use beq L21 ; Jump if not set bmi L21 ; Jump if temp breakpoint lda _DbgBreaks,x ; Low byte of address cmp ptr1 bne L21 lda _DbgBreaks+1,x ; High byte of address cmp ptr1+1 beq L22 L21: inx inx inx inx cpx #MaxBreaks ; Done? bne L20 jmp return0 ; Not found L22: stx tmp1 lda #<_DbgBreaks ldx #>_DbgBreaks clc adc tmp1 bcc L23 inx L23: ldy #1 ; Force != 0 rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/em/��������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014064�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/em/em-kernel.s���������������������������������������������������������������������0000664�0000000�0000000�00000005162�13473601511�0016133�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2002-11-29 ; ; Common functions of the extended memory API. ; .import return0, em_libref .importzp ptr1 .include "em-kernel.inc" .include "em-error.inc" ;---------------------------------------------------------------------------- ; Variables .bss _em_drv: .res 2 ; Pointer to driver ; Jump table for the driver functions. .data emd_vectors: emd_install: jmp return0 emd_uninstall: jmp return0 emd_pagecount: jmp return0 emd_map: jmp return0 emd_use: jmp return0 emd_commit: jmp return0 emd_copyfrom: jmp return0 emd_copyto: jmp return0 ; Driver header signature .rodata emd_sig: .byte $65, $6d, $64, EMD_API_VERSION ; "emd", version ;---------------------------------------------------------------------------- ; unsigned char __fastcall__ em_install (void* driver); ; /* Install the driver once it is loaded */ _em_install: sta _em_drv sta ptr1 stx _em_drv+1 stx ptr1+1 ; Check the driver signature ldy #.sizeof(emd_sig)-1 @L0: lda (ptr1),y cmp emd_sig,y bne inv_drv dey bpl @L0 ; Set the library reference ldy #EMD_HDR::LIBREF lda #<em_libref sta (ptr1),y iny lda #>em_libref sta (ptr1),y ; Copy the jump vectors ldy #EMD_HDR::JUMPTAB ldx #0 @L1: inx ; Skip the JMP opcode jsr copy ; Copy one byte jsr copy ; Copy one byte cpy #(EMD_HDR::JUMPTAB + .sizeof(EMD_HDR::JUMPTAB)) bne @L1 jmp emd_install ; Call driver install routine ; Driver signature invalid inv_drv: lda #EM_ERR_INV_DRIVER ldx #0 rts ; Copy one byte from the jump vectors copy: lda (ptr1),y sta emd_vectors,x iny inx rts ;---------------------------------------------------------------------------- ; unsigned char em_uninstall (void); ; /* Uninstall the currently loaded driver and return an error code. ; ** Note: This call does not free allocated memory. ; */ _em_uninstall: jsr emd_uninstall ; Call driver routine em_clear_ptr: ; External entry point lda #0 sta _em_drv sta _em_drv+1 ; Clear the driver pointer tax rts ; Return zero ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/em/em_commit.s���������������������������������������������������������������������0000664�0000000�0000000�00000001057�13473601511�0016224�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2002-12-01 ; ; void em_commit (void); ; /* Commit changes in the memory window to extended storage. If the contents ; ** of the memory window have been changed, these changes may be lost if ; ** em_map, em_copyfrom or em_copyto are called without calling em_commit ; ** first. Note: Not calling em_commit does not mean that the changes are ; ** discarded, it does just mean that some drivers will discard the changes. ; */ .include "em-kernel.inc" _em_commit = emd_commit ; Use driver entry ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/em/em_copyfrom.s�������������������������������������������������������������������0000664�0000000�0000000�00000000410�13473601511�0016562�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2002-11-29 ; ; void __fastcall__ em_copyfrom (const struct em_copy* copy_data); ; /* Copy from extended into linear memory */ .include "em-kernel.inc" _em_copyfrom = emd_copyfrom ; Use driver entry ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/em/em_copyto.s���������������������������������������������������������������������0000664�0000000�0000000�00000000406�13473601511�0016246�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2002-11-29 ; ; void __fastcall__ em_copyto (const struct em_copy* copy_data); ; /* Copy from linear into extended memory */ .include "em-kernel.inc" _em_copyto = emd_copyto ; Use driver entry ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/em/em_load.s�����������������������������������������������������������������������0000664�0000000�0000000�00000005653�13473601511�0015661�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2012-07-22 ; ; unsigned char __fastcall__ em_load_driver (const char* name) ; /* Load an extended memory driver and return an error code */ .include "em-kernel.inc" .include "em-error.inc" .include "modload.inc" .include "fcntl.inc" .import pushax .import pusha0 .import incsp2 .import _open .import _read .import _close ;---------------------------------------------------------------------------- ; Variables .data ctrl: .addr _read .res 2 ; CALLERDATA .res 2 ; MODULE .res 2 ; MODULE_SIZE .res 2 ; MODULE_ID ;---------------------------------------------------------------------------- ; Code .code .proc _em_load_driver ; Check if we do already have a driver loaded. This is an error. Do not ; touch A/X because they contain the file name. ldy _em_drv bne @L0 ldy _em_drv+1 beq @L1 @L0: lda #EM_ERR_INSTALLED bne @L4 ; Push the name onto the C stack and open the file. The parameter will get ; removed by open(). ; ctrl.callerdata = open (name, O_RDONLY); @L1: jsr pushax lda #<O_RDONLY jsr pusha0 ldy #4 ; Argument size jsr _open sta ctrl + MOD_CTRL::CALLERDATA stx ctrl + MOD_CTRL::CALLERDATA+1 ; if (ctrl.callerdata >= 0) { txa bmi @L3 ; /* Load the module */ ; Res = mod_load (&ctrl); lda #<ctrl ldx #>ctrl jsr _mod_load pha ; /* Close the input file */ ; close (ctrl.callerdata); lda ctrl + MOD_CTRL::CALLERDATA ldx ctrl + MOD_CTRL::CALLERDATA+1 jsr _close ; /* Check the return code */ ; if (Res == MLOAD_OK) { pla bne @L3 ; Check the driver signature, install the driver. ; Res = em_install (ctrl.module); lda ctrl + MOD_CTRL::MODULE ldx ctrl + MOD_CTRL::MODULE+1 jsr _em_install ; If em_install was successful, we're done tax beq @L2 ; The driver didn't install correctly. Remove it from memory and return the ; error code. pha ; Save the error code lda _em_drv ldx _em_drv+1 jsr _mod_free ; Free the driver memory jsr em_clear_ptr ; Clear em_drv pla ; Restore the error code ldx #0 ; We must return an int @L2: rts ; Done ; Open or mod_load failed. Return an error code. @L3: lda #<EM_ERR_CANNOT_LOAD @L4: ldx #0 rts .endproc �������������������������������������������������������������������������������������cc65-2.18/libsrc/em/em_map.s������������������������������������������������������������������������0000664�0000000�0000000�00000000517�13473601511�0015511�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2002-11-29 ; ; void* __fastcall__ em_map (unsigned page); ; /* Unmap the current page from memory and map a new one. The function returns ; ** a pointer to the location of the page in memory. ; */ .include "em-kernel.inc" _em_map = emd_map ; Use driver entry ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/em/em_pagecount.s������������������������������������������������������������������0000664�0000000�0000000�00000000417�13473601511�0016720�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2002-11-29 ; ; unsigned em_pagecount (void); ; /* Return the total number of 256 byte pages available in extended memory. */ .include "em-kernel.inc" _em_pagecount = emd_pagecount ; Use driver entry �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/em/em_unload.s���������������������������������������������������������������������0000664�0000000�0000000�00000001356�13473601511�0016220�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2002-11-29 ; ; unsigned char em_unload (void); ; /* Unload the currently loaded driver. */ .import em_clear_ptr .include "em-kernel.inc" .include "em-error.inc" .include "modload.inc" _em_unload: lda _em_drv ora _em_drv+1 beq no_driver ; No driver jsr emd_uninstall ; Deinstall the driver lda _em_drv ldx _em_drv+1 jsr _mod_free ; Free the driver jmp em_clear_ptr ; Clear the driver pointer, return zero no_driver: tax ; X = 0 lda #EM_ERR_NO_DRIVER rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/em/em_use.s������������������������������������������������������������������������0000664�0000000�0000000�00000001165�13473601511�0015530�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2002-11-29 ; ; void* __fastcall__ em_use (unsigned page); ; /* Tell the driver that the memory window is associated with a given page. ; ** This call is very similar to em_map. The difference is that the driver ; ** does not necessarily transfer the current contents of the extended ; ** memory into the returned window. If you're going to just write to the ; ** window and the current contents of the window are invalid or no longer ; ** use, this call may perform better than em_map. ; */ .include "em-kernel.inc" _em_use = emd_use ; Use driver entry �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/gamate/����������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014721�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/gamate/_scrsize.s������������������������������������������������������������������0000664�0000000�0000000�00000000400�13473601511�0016720�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Screen size variables ; .include "gamate.inc" .export screensize screensize: ldx xsize ldy ysize rts .rodata .export xsize, ysize xsize: .byte charsperline ysize: .byte screenrows ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/gamate/chline.s��������������������������������������������������������������������0000664�0000000�0000000�00000001423�13473601511�0016347�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 gotoxy, cputdirect .importzp tmp1 .include "gamate.inc" _chlinexy: pha ; Save the length 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 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/gamate/clock.s���������������������������������������������������������������������0000664�0000000�0000000�00000001101�13473601511�0016171�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; clock_t clock (void); ; .include "gamate.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 "ONCE" initclock: lda #0 ldx #3 @lp: sta tickcount,x dex bpl @lp rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/gamate/clrscr.s��������������������������������������������������������������������0000664�0000000�0000000�00000001165�13473601511�0016400�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ .include "gamate.inc" .include "extzp.inc" .import plot .export _clrscr _clrscr: ldy #$0 tya rowloop: sty LCD_X sta LCD_Y ldx #$0 colloop: sta LCD_DATA inx bne colloop iny bne rowloop ; Go to the home position. sta CURS_X sta CURS_Y jmp plot ;------------------------------------------------------------------------------- ; force the init constructor to be imported .import initconio conio_init = initconio �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/gamate/color.s���������������������������������������������������������������������0000664�0000000�0000000�00000001470�13473601511�0016225�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 "gamate.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 txa rts _bordercolor: lda #0 tax rts ;------------------------------------------------------------------------------- ; force the init constructor to be imported .import initconio conio_init = initconio ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/gamate/conio.s���������������������������������������������������������������������0000664�0000000�0000000�00000001146�13473601511�0016216�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ .include "gamate.inc" .include "extzp.inc" .import colors .importzp ptr1, tmp1 .constructor initconio .macpack longbranch .segment "ONCE" initconio: lda #0 sta LCD_XPOS sta LCD_YPOS lda #LCD_MODE_INC_Y sta LCD_MODE lda #COLOR_BLACK sta CHARCOLOR lda #COLOR_WHITE sta BGCOLOR rts .segment "RODATA" .export fontdata fontdata: .include "vga.inc" ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/gamate/cputc.s���������������������������������������������������������������������0000664�0000000�0000000�00000005650�13473601511�0016231�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; void cputcxy (unsigned char x, unsigned char y, char c); ; void cputc (char c); ; .export _cputcxy, _cputc, cputdirect, putchar .export newline, plot .import gotoxy .import PLOT .import xsize .import fontdata .import _plotlo .importzp tmp3,tmp4 .importzp ptr3 .include "gamate.inc" .include "extzp.inc" _cputcxy: pha ; Save C jsr gotoxy ; Set cursor, drop x and y pla ; Restore C ; Plot a character - also used as internal function _cputc: cmp #$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: sta ptr3 txa pha lda #0 sta ptr3+1 ; char index * 8 asl ptr3 rol ptr3+1 asl ptr3 rol ptr3+1 asl ptr3 rol ptr3+1 ; plus fontdata base address lda ptr3 clc adc #<(fontdata-$f8) sta ptr3 lda ptr3+1 adc #>(fontdata-$f8) sta ptr3+1 lda CHARCOLOR and #1 beq @skip_plane1 lda #LCD_XPOS_PLANE1 clc adc CURS_X sta LCD_X ldy #$f8 @copylp1: lda (ptr3),y eor RVS sta LCD_DATA iny bne @copylp1 @skip_plane1: lda CHARCOLOR and #2 beq @skip_plane2 lda #LCD_XPOS_PLANE2 clc adc CURS_X sta LCD_X ldx CURS_Y lda _plotlo,x sta LCD_Y ldy #$f8 @copylp2: lda (ptr3),y eor RVS sta LCD_DATA iny bne @copylp2 @skip_plane2: pla tax ldy CURS_X rts ;------------------------------------------------------------------------------- ; force the init constructor to be imported .import initconio conio_init = initconio ����������������������������������������������������������������������������������������cc65-2.18/libsrc/gamate/crt0.s����������������������������������������������������������������������0000664�0000000�0000000�00000003075�13473601511�0015762�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ .export Start, _exit .import initlib, donelib, callmain .import push0, _main, zerobss, copydata ; Linker generated symbols .import __RAM_START__, __RAM_SIZE__ .include "zeropage.inc" .include "gamate.inc" Start: ; setup the CPU and System-IRQ ; Initialize CPU sei cld ldx #0 stx ZP_IRQ_CTRL ; disable calling cartridge IRQ/NMI handler ; Set up stack and memory mapping ;ldx #$FF ; Stack top ($01FF) dex txs ; Clear the BSS data jsr zerobss ; Copy the .data segment to RAM jsr copydata ; Set up the stack lda #<(__RAM_START__+__RAM_SIZE__) ldx #>(__RAM_START__+__RAM_SIZE__) sta sp stx sp + 1 ; Call module constructors jsr initlib lda #1 sta ZP_IRQ_CTRL ; enable calling cartridge IRQ/NMI handler cli ; allow IRQ only after constructors have run ; 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 (start over) jmp Start .export initmainargs initmainargs: rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/gamate/ctype.s���������������������������������������������������������������������0000664�0000000�0000000�00000020775�13473601511�0016244�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 ���cc65-2.18/libsrc/gamate/cvline.s��������������������������������������������������������������������0000664�0000000�0000000�00000001546�13473601511�0016373�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 gotoxy, putchar, newline .importzp tmp1 .include "gamate.inc" _cvlinexy: pha ; Save the length 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 ����������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/gamate/extzp.inc�������������������������������������������������������������������0000664�0000000�0000000�00000000631�13473601511�0016566�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; extzp.inc for the Gamate ; ; Groepaz/Hitmen, 2015-11-27 ; ; Assembler include file that imports the runtime zero page locations used ; by the Gamate runtime, ready for usage in asm code. ; .global CURS_X: zp .global CURS_Y: zp .global CHARCOLOR: zp .global RVS: zp .global BGCOLOR: zp .global tickcount: zp �������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/gamate/extzp.s���������������������������������������������������������������������0000664�0000000�0000000�00000000447�13473601511�0016264�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Groepaz/Hitmen, 2015-11-27 ; ; zeropage locations for exclusive use by the library ; .include "extzp.inc" .segment "EXTZP" : zeropage CURS_X: .res 1 CURS_Y: .res 1 CHARCOLOR: .res 1 RVS: .res 1 BGCOLOR: .res 1 tickcount: .res 4 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/gamate/gotoxy.s��������������������������������������������������������������������0000664�0000000�0000000�00000001132�13473601511�0016433�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; void gotoxy (unsigned char x, unsigned char y); ; .export gotoxy, _gotoxy .import popa, plot .include "gamate.inc" .include "extzp.inc" gotoxy: jsr popa ; Get Y _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 .forceimport initconio ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/gamate/header.s��������������������������������������������������������������������0000664�0000000�0000000�00000001355�13473601511�0016341�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ ; The following symbol is used by linker config to force the module ; to get included into the output file .export __STARTUP__: absolute = 1 .import Start, IRQStub, NMIStub .segment "STARTUP" .word 0 ; +00 checksum from 7000-7fff (simple 8bit adds) .byte 1, 0, 1 ; +02 flags .byte "COPYRIGHT BIT CORPORATION", 0, $ff ; +05 copyright ; system vectors jmp Start ; +20 reset entry jmp NMIStub ; +23 nmi entry jmp IRQStub ; +26 irq entry (135 hz) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/gamate/irq.s�����������������������������������������������������������������������0000664�0000000�0000000�00000001701�13473601511�0015677�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; IRQ handling (Gamate version) ; .export initirq, doneirq, IRQStub .import __INTERRUPTOR_COUNT__, callirq_y .include "gamate.inc" .include "extzp.inc" ; ------------------------------------------------------------------------ .segment "ONCE" ; a constructor ; initirq: rts ; ------------------------------------------------------------------------ .code ; a destructor ; doneirq: rts ; ------------------------------------------------------------------------ ; 256*32 interrupts in about 1minute 60s = 136hz ; -> guess 16384 clock cycles = 135,28hz (might be audio signal 1/512?) IRQStub: ; A and Y are saved by the BIOS ;pha ;tya ;pha ldy #<(__INTERRUPTOR_COUNT__ * 2) beq @L1 txa pha jsr callirq_y pla tax @L1: ;pla ;tay ;pla rts ���������������������������������������������������������������cc65-2.18/libsrc/gamate/joy/������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015522�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/gamate/joy/gamate-stdjoy.s���������������������������������������������������������0000664�0000000�0000000�00000003710�13473601511�0020457�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ ; ; Standard joystick driver for the Gamate ; .include "joy-kernel.inc" .include "joy-error.inc" .include "gamate.inc" .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _gamate_stdjoy_joy ; Driver signature .byte $6A, $6F, $79 ; "joy" .byte JOY_API_VERSION ; Driver API version number ; Library reference .addr $0000 ; Jump table. .addr INSTALL .addr UNINSTALL .addr COUNT .addr READJOY ; ------------------------------------------------------------------------ ; Constants JOY_COUNT = 1 ; 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: lda JOY_DATA eor #$FF ldx #0 rts ��������������������������������������������������������cc65-2.18/libsrc/gamate/joy_stat_stddrv.s�����������������������������������������������������������0000664�0000000�0000000�00000000376�13473601511�0020335�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Address of the static standard joystick driver ; ; Oliver Schmidt, 2012-11-01 ; ; const void joy_static_stddrv[]; ; .export _joy_static_stddrv .import _gamate_stdjoy_joy _joy_static_stddrv := _gamate_stdjoy_joy ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/gamate/kplot.s���������������������������������������������������������������������0000664�0000000�0000000�00000001212�13473601511�0016232�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ .export PLOT .include "gamate.inc" .include "extzp.inc" PLOT: bcs @getpos sty LCD_X ;clc ; already cleared lda _plotlo,x sta LCD_Y @getpos: ldx CURS_Y ldy CURS_X rts .export _plotlo .rodata _plotlo: .repeat screenrows,line .byte <($0000+(line*$8)) .endrepeat ;------------------------------------------------------------------------------- ; force the init constructor to be imported .import initconio conio_init = initconio ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/gamate/libref.s��������������������������������������������������������������������0000664�0000000�0000000�00000000175�13473601511�0016353�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2013-05-31 ; .export joy_libref .import _exit joy_libref := _exit ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/gamate/nmi.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000426�13473601511�0015672�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; NMI handling (Gamate version) ; .export NMIStub .segment "ONCE" NMIStub: ; A is saved by the BIOS ;pha ;txa ;pha ;tya ;pha ;pla ;tay ;pla ;tax ;pla rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/gamate/revers.s��������������������������������������������������������������������0000664�0000000�0000000�00000001604�13473601511�0016414�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ .include "gamate.inc" .include "extzp.inc" .export _revers .proc _revers ldx #$00 ; Assume revers off tay ; Test onoff beq L1 ; Jump if off ldx #$ff ; 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 ����������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/gamate/ticktock.s������������������������������������������������������������������0000664�0000000�0000000�00000000543�13473601511�0016722�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ .interruptor ticktock, 24 .include "gamate.inc" .include "extzp.inc" ticktock: ; Increment the system tick counter. inc tickcount bne @s1 inc tickcount+1 bne @s1 inc tickcount+2 bne @s1 inc tickcount+3 @s1: rts �������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/gamate/vga.inc���������������������������������������������������������������������0000664�0000000�0000000�00000021605�13473601511�0016175�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ ; VGA charset for the Gamate conio implementation .byte $00, $00, $00, $00, $00, $00, $00, $00 ; 1 .byte %00000000 .byte %00000000 .byte %00000000 .byte %11111111 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 ; 2 .byte %00010000 .byte %00010000 .byte %00010000 .byte %00010000 .byte %00010000 .byte %00010000 .byte %00010000 .byte %00010000 ; 3 .byte %00010000 .byte %00010000 .byte %00010000 .byte %11111111 .byte %00010000 .byte %00010000 .byte %00010000 .byte %00010000 ; 4 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00011111 .byte %00010000 .byte %00010000 .byte %00010000 .byte %00010000 ; 5 .byte %00000000 .byte %00000000 .byte %00000000 .byte %11110000 .byte %00010000 .byte %00010000 .byte %00010000 .byte %00010000 ; 6 .byte %00010000 .byte %00010000 .byte %00010000 .byte %00011111 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 ; 7 .byte %00010000 .byte %00010000 .byte %00010000 .byte %11110000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 ; 8 .byte %00000000 .byte %00000000 .byte %00000000 .byte %11111111 .byte %00010000 .byte %00010000 .byte %00010000 .byte %00010000 ; 9 .byte %00010000 .byte %00010000 .byte %00010000 .byte %11111111 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 ; 10 (LF) .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 .byte %00000000 ; 11 .byte %00010000 .byte %00010000 .byte %00010000 .byte %11110000 .byte %00010000 .byte %00010000 .byte %00010000 .byte %00010000 ; 12 .byte %00010000 .byte %00010000 .byte %00010000 .byte %00011111 .byte %00010000 .byte %00010000 .byte %00010000 .byte %00010000 .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 ���������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/gamate/waitvsync.s�����������������������������������������������������������������0000664�0000000�0000000�00000000554�13473601511�0017140�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Written by Groepaz <groepaz@gmx.net> ; ; void waitvsync (void); ; .include "gamate.inc" .include "extzp.inc" .forceimport ticktock .export _waitvsync ; FIXME: is this actually correct? .proc _waitvsync lda tickcount @lp: cmp tickcount beq @lp rts .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/gamate/wherex.s��������������������������������������������������������������������0000664�0000000�0000000�00000000412�13473601511�0016404�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-05-02 ; ; unsigned char wherex (void); ; .export _wherex .include "gamate.inc" .include "extzp.inc" .proc _wherex lda CURS_X ldx #$00 rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/gamate/wherey.s��������������������������������������������������������������������0000664�0000000�0000000�00000000412�13473601511�0016405�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-05-02 ; ; unsigned char wherey (void); ; .export _wherey .include "gamate.inc" .include "extzp.inc" .proc _wherey lda CURS_Y ldx #$00 rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-apple/������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015517�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-apple/Makefile.inc������������������������������������������������������������0000664�0000000�0000000�00000000052�13473601511�0017724�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������CA65FLAGS += -I geos-apple -I geos-common ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-apple/disk/�������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0016451�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-apple/disk/enterturbo.s�������������������������������������������������������0000664�0000000�0000000�00000000244�13473601511�0021026�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt (ol.sc@web.de) ; ; 2012-02-09 ; void EnterTurbo (void); .export _EnterTurbo .import return0 _EnterTurbo = return0 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-apple/disk/exitturbo.s��������������������������������������������������������0000664�0000000�0000000�00000000264�13473601511�0020664�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt (ol.sc@web.de) ; ; 2012-02-09 ; void ExitTurbo (void); .export _ExitTurbo .import return0 _ExitTurbo = return0 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-apple/disk/purgeturbo.s�������������������������������������������������������0000664�0000000�0000000�00000000244�13473601511�0021033�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt (ol.sc@web.de) ; ; 2012-02-09 ; void PurgeTurbo (void); .export _PurgeTurbo .import return0 _PurgeTurbo = return0 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-apple/diskdrv.inc�������������������������������������������������������������0000664�0000000�0000000�00000004423�13473601511�0017663�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ;GEOS Disk Driver JumpTab ;Source: The Hitchhiker's Guide To GEOS ;http://lyonlabs.org/commodore/onrequest/geos-manuals/The_Hitchhikers_Guide_to_GEOS.pdf GetBlock = $0300 PutBlock = $0303 GetFile = $030f LdFile = $0312 ReadFile = $0315 SaveFile = $0318 WriteFile = $031b GetVBM = $031e PutVBM = $0321 CalcBlksFree = $0324 FreeBlock = $032a SetNextFree = $032d AppendRecord = $0330 CloseRecordFile = $0333 DeleteRecord = $0336 NextRecord = $0336 InsertRecord = $0339 OpenRecordFile = $033f PointRecord = $0342 PreviousRecord = $0345 ReadRecord = $0348 UpdateRecordFile = $034b WriteRecord = $034e BlkAlloc = $0351 NxtBlkAlloc = $0354 DeleteFile = $0357 FreeFile = $035a LdDeskAcc = $035d RstrAppl = $0360 FdFTypesInDir = $0363 FindFTypes = $0366 FindFile = $0369 FndFilinDir = $036c BldGDirEntry = $036f GetDirHead = $0372 GetFreeDirBlk = $0375 PutDirHead = $037b SetGDirEntry = $037b DeleteDir = $037e DownDirectory = $0381 GetPathname = $0384 MakeSubDir = $0387 UpDirectory = $038a LdApplic = $038d GetFHdrInfo = $0390 RenameFile = $0393 OpenDisk = $0399 Get1stDirEntry = $039c GetNxtDirEntry = $039c GoDirectory = $039f ReOpenDisk = $03a2 SortAlpha = $03a5 SaveFG = $03ab RecoverFG = $03ae JsrToAux = $03b4 UpdateParent = $03b7 FreeDir = $03ba ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-apple/geossym.inc�������������������������������������������������������������0000664�0000000�0000000�00000015140�13473601511�0017701�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ;GEOS variable memory locations sorted by address ;Source: The Hitchhiker's Guide To GEOS ;http://lyonlabs.org/commodore/onrequest/geos-manuals/The_Hitchhikers_Guide_to_GEOS.pdf r0 = $00 r0L = $00 r0H = $01 r1 = $02 r1L = $02 r1H = $03 r2 = $04 r2L = $04 r2H = $05 r3 = $06 r3L = $06 r3H = $07 r4 = $08 r4L = $08 r4H = $09 r5 = $0a r5L = $0a r5H = $0b r6 = $0c r6L = $0c r6H = $0d r7 = $0e r7L = $0e r7H = $0f r8 = $10 r8L = $10 r8H = $11 r9 = $12 r9L = $12 r9H = $13 r10 = $14 r10L = $14 r10H = $15 r11 = $16 r11L = $16 r11H = $17 r12 = $18 r12L = $18 r12H = $19 r13 = $1a r13L = $1a r13H = $1b r14 = $1c r14L = $1c r14H = $1d r15 = $1e r15L = $1e r15H = $1f string = $53 mouseTop = $57 mouseBottom = $58 mouseLeft = $59 mouseRight = $5b mouseOn = $5d curIndexTable = $5e cardDataPntr = $60 returnAddress = $64 shiftBuf = $70 shiftOutBuf = $78 appMain = $0200 intTopVector = $0202 intBotVector = $0204 mouseVector = $0206 keyVector = $0208 inputVector = $020a mouseFaultVec = $020c otherPressVec = $020e StringFaultVec = $0210 alarmTmtVector = $0212 BRKVector = $0214 RecoverVector = $0216 baselineOffset = $0218 curSetWidth = $0219 curHeight = $021b currentMode = $021c dispBufferOn = $021d windowTop = $021e leftMargin = $0220 rightMargin = $0222 selectionFlash = $0224 alphaFlag = $0225 iconSelFlag = $0226 faultData = $0227 MenuNumber = $0228 mouseXOffset = $0229 mouseYOffset = $022b curPattern = $022c stringX = $022e stringY = $0230 noEraseSprites = $0240 mouseXPos = $0241 mouseYPos = $0243 keyData = $0245 inputData = $0247 random = $024c saveFontTab = $024e dblClickCount = $0258 sysDBData = $0259 offFlag = $027c maxMouseSpeed = $027d minMouseSpeed = $027e mouseAccel = $027f firstBoot = $0281 dataFileName = $02a4 dataDiskName = $02b4 MachineType = $02c4 intSource = $02c6 reqXpos0 = $0800 reqXpos1 = $0802 reqXpos2 = $0804 reqXpos3 = $0806 reqXpos4 = $0808 reqXpos5 = $080a reqXpos6 = $080c reqXpos7 = $080e mobenble = $0818 mobx2 = $0819 moby2 = $081a PrntFileName = $08ac inputDevName = $08cc pressFlag = $08fe curEnable = $0951 sspr1back = $56d0 sspr2back = $5820 sspr3back = $5970 sspr4back = $5ac0 sspr5back = $5c10 sspr6back = $5d60 sspr7back = $5eb0 backBufPtr = $9d7c softOnes = $d000 softZeros = $d0e0 curnoby2 = $d952 curmobx2 = $d953 curXpos0 = $d954 curYpos0 = $d964 backXBufNum = $d98c backYBufNum = $d994 sizeFlags = $db1c doRestFlag = $db1d bootName = $e003 version = $e00c nationality = $e00d mouseSave = $ee53 year = $f200 month = $f201 day = $f202 hour = $f203 minutes = $f204 seconds = $f205 dlgBoxRamBuf = $f381 totNumBlks = $f60b curDrive = $f60d numDrives = $f60e diskOpenFlg = $f617 curRecord = $f618 usedRecords = $f619 fileWritten = $f61a fileSize = $f61b dirBlkno = $f620 dirPtr = $f622 indexBlkno = $f624 diskBlkBuf = $f659 fileHeader = $f859 dirEntryBuf = $fa59 curDirHead = $fa80 DrACurDkNm = $faa7 DrBCurDkNm = $fab7 DrCCurDkNm = $fac7 DrDCurDkNm = $fad7 devTabHi = $fae7 devTabLo = $faeb devUnitTab = $faef driveType = $faf3 drSizeLo = $faf7 drSizeHi = $fafb ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-apple/jumptab.inc�������������������������������������������������������������0000664�0000000�0000000�00000014141�13473601511�0017655�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ;Apple GEOS System Jump Table ;Source: The Hitchhiker's Guide To GEOS ;http://lyonlabs.org/commodore/onrequest/geos-manuals/The_Hitchhikers_Guide_to_GEOS.pdf ReadClock = $0800 ClockInt = $0803 SetTimeDate = $0806 SetAlarm = $0809 ResetAlarm = $080c InitForPrint = $6000 StartPrint = $6003 StartASCII = $6006 PrintBuffer = $6009 PrintASCII = $600c StopPrint = $600f GetMode = $6012 SetMode = $6015 CancelPrint = $6018 InitCard = $6700 OpenCard = $6703 OutputByte = $6706 InputByte = $6709 CloseCard = $670c InfoCard = $670f StatusCard = $6712 ClearCard = $6715 AuxDMain = $efa0 AuxDInt = $efa3 AuxDKeyFilter = $efa6 AuxDExit = $efa9 InitMouse = $f000 SlowMouse = $f003 UpdateMouse = $f006 KeyFilter = $f009 MainLoop = $fe00 InterruptMain = $fe03 StartAppl = $fe06 DoInlineReturn = $fe09 DoIcons = $fe0c DoMenu = $fe0f ReDoMenu = $fe12 DoPreviousMenu = $fe15 GotoFirstMenu = $fe18 RecoverMenu = $fe1b RecoverAllMenus = $fe1e DrawPoint = $fe21 TestPoint = $fe24 HorizontalLine = $fe27 VerticalLine = $fe2a InvertLine = $fe2d RecoverLine = $fe30 DrawLine = $fe33 SetPattern = $fe36 Rectangle = $fe39 i_Rectangle = $fe3c FrameRectangle = $fe3f i_FrameRectangle = $fe42 InvertRectangle = $fe45 RecoverRectangle = $fe48 i_RecoverRectangle = $fe4b ImprintRectangle = $fe4e i_ImprintRectangle = $fe51 BitmapUp = $fe54 i_BitmapUp = $fe57 BitmapClip = $fe5a BitOtherClip = $fe5d GraphicsString = $fe60 i_GraphicsString = $fe63 GetScanLine = $fe66 PutString = $fe69 i_PutString = $fe6c PutDecimal = $fe6f GetString = $fe72 GetNextChar = $fe75 InitTextPrompt = $fe78 PromptOn = $fe7b PromptOff = $fe7e PutChar = $fe81 GetRealSize = $fe84 GetCharWidth = $fe87 LoadCharSet = $fe8a UseSystemFont = $fe8d SmallPutChar = $fe90 StartMouseMode = $fe93 MouseOff = $fe96 MouseUp = $fe99 IsMseInRegion = $fe9c ClearMouseMode = $fe9f DrawSprite = $fea2 PosSprite = $fea5 EnablSprite = $fea8 DisablSprite = $feab InitProcesses = $feae RestartProcess = $feb1 BlockProcess = $feb4 UnblockProcess = $feb7 FreezeProcess = $feba UnfreezeProcess = $febd Sleep = $fec0 EnableProcess = $fec3 DShiftLeft = $fec6 DShiftRight = $fec9 BBMult = $fecc BMult = $fecf DMult = $fed2 Ddiv = $fed5 DSdiv = $fed8 Dabs = $fedb Dnegate = $fede Ddec = $fee1 GetRandom = $fee4 CopyString = $fee7 CopyFString = $feea CmpString = $feed CmpFString = $fef0 Panic = $fef3 MoveData = $fef6 i_MoveData = $fef9 ClearRam = $fefc FillRam = $feff i_FillRam = $ff02 InitRam = $ff05 CallRoutine = $ff08 NewBitOtherClip = $ff0e FirstInit = $ff11 CRC = $ff14 DoDlgBox = $ff17 RstrFrmDialogue = $ff1a NewBitUp = $ff1d IrqMiddle = $ff20 TempHideMouse = $ff29 SoftSprHandler = $ff2c SetMsePic = $ff2f InitSprite = $ff32 SaveFontData = $ff35 RestoreFontData = $ff38 EraseCharacter = $ff3e ReadByte = $ff41 GetLdVars = $ff44 SetLdVars = $ff47 InitForDialog = $ff4a WarmStart = $ff4d RecoverSysRam = $ff53 GetPtrCurDkNm = $ff56 EnterDeskTop = $ff59 CopyScreenBlock = $ff5c CopyLine = $ff5f GetScreenLine = $ff62 PutScreenLine = $ff65 DivideBySeven = $ff68 MoveAuxData = $ff6b GetSpriteData = $ff6e SwapMainAndAux = $ff71 ReadBackLine = $ff74 LoadAuxSet = $ff77 HideOnlyMouse = $ff7a GetPattern = $ff7d SetUserPattern = $ff80 Bell = $ff86 ImprintLine = $ff8f CopyFullScreen = $ff92 NewBitClip = $ff95 ReadScanLine = $ff98 i_NewBitUp = $ff9e �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-apple/targetutil/�������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0017703�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-apple/targetutil/Makefile.inc�������������������������������������������������0000664�0000000�0000000�00000000727�13473601511�0022121�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������DEPS += ../libwrk/$(TARGET)/convert.d ../libwrk/$(TARGET)/convert.o: TARGET = apple2enh ../libwrk/$(TARGET)/convert.o: $(SRCDIR)/targetutil/convert.c | ../libwrk/$(TARGET) $(COMPILE_recipe) ../lib/apple2enh.lib: @$(MAKE) --no-print-directory apple2enh ../target/$(TARGET)/util/convert.system: ../libwrk/$(TARGET)/convert.o ../lib/apple2enh.lib | ../target/$(TARGET)/util $(LD65) -o $@ -C apple2enh-system.cfg $^ $(TARGET): ../target/$(TARGET)/util/convert.system �����������������������������������������cc65-2.18/libsrc/geos-apple/targetutil/convert.c����������������������������������������������������0000664�0000000�0000000�00000025116�13473601511�0021534�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <string.h> #include <stdlib.h> #include <stdio.h> #include <errno.h> #include <dirent.h> #include <device.h> #include <dio.h> unsigned char info_signature[3] = {3, 21, 63 | 0x80}; dhandle_t dhandle; struct dir_entry_t { struct { unsigned name_length :4; unsigned storage_type :4; } storage_length; char file_name[15]; unsigned char file_type; unsigned key_pointer; unsigned blocks_used; unsigned char size[3]; unsigned long creation; unsigned char version; unsigned char min_version; unsigned char access; unsigned aux_type; unsigned long last_mod; unsigned header_pointer; }* dir_entry; union { unsigned char bytes[512]; struct { unsigned prev_block; unsigned next_block; unsigned char entries[1]; } content; } dir_block; union { unsigned char bytes[512]; struct { unsigned char addr_lo[254]; unsigned char size_lo[2]; unsigned char addr_hi[254]; unsigned char size_hi[2]; } content; } index_block, master_block, vlir_block; union { unsigned char bytes[512]; struct { unsigned reserved; unsigned char info_block[254]; unsigned char vlir_records[128]; struct dir_entry_t dir_entry; } content; } header_block; static void err_exit(char *operation, unsigned char oserr) { if (oserr) { fprintf(stderr, "%s - err:%02x - %s", operation, (int)_oserror, _stroserror(_oserror)); } else { fprintf(stderr, "%s", operation); } getchar(); exit(EXIT_FAILURE); } static unsigned get_dir_entry(char* p_name) { char* d_name; char* f_name; size_t f_namelen; DIR* dir; struct dirent* dirent; unsigned cur_addr; unsigned char entry_length; unsigned char entries_per_block; unsigned char cur_entry; /* Split path name into directory name and file name */ f_name = strrchr(p_name, '/'); if (f_name) { d_name = p_name; *f_name++ = '\0'; } else { d_name = "."; f_name = p_name; } f_namelen = strlen(f_name); /* Start with high level functions to get handling of relative path and current drive for free */ dir = opendir(d_name); if (!dir) { err_exit("opendir", 1); } dirent = readdir(dir); if (!dirent) { err_exit("readdir", 1); } /* Field header_pointer directly follows field last_mod */ cur_addr = *(unsigned*)(&dirent->d_mtime.hour + 1); dhandle = dio_open(getcurrentdevice()); if (!dhandle) { err_exit("dio_open", 1); } if (dio_read(dhandle, cur_addr, &dir_block)) { err_exit("dio_read.1", 1); } /* Get directory entry infos from directory header */ entry_length = dir_block.bytes[0x23]; entries_per_block = dir_block.bytes[0x24]; /* Skip directory header entry */ cur_entry = 1; do { /* Search for next active directory entry */ do { /* Check if next directory block is necessary */ if (cur_entry == entries_per_block) { /* Check if another directory block is present */ cur_addr = dir_block.content.next_block; if (!cur_addr) { _mappederrno(0x46); err_exit("dio_read.2", 1); } /* Read next directory block */ if (dio_read(dhandle, cur_addr, &dir_block)) { err_exit("dio_read.3", 1); } /* Start with first entry in next block */ cur_entry = 0; } /* Compute pointer to current entry */ dir_entry = (struct dir_entry_t*)(dir_block.content.entries + cur_entry * entry_length); /* Switch to next entry */ ++cur_entry; } while (!dir_entry->storage_length.storage_type); } while (dir_entry->storage_length.name_length != f_namelen || strncasecmp(dir_entry->file_name, f_name, f_namelen)); return cur_addr; } int main(int argc, char* argv[]) { char input[80]; char* p_name; unsigned dir_addr; unsigned header_addr; unsigned char index; unsigned long size; if (argc > 1) { p_name = argv[1]; } else { printf("\n" "Apple GEOS Convert 1.0\n" "----------------------\n" "\n" "Pathname:"); p_name = gets(input); } dir_addr = get_dir_entry(p_name); /* Read index block */ if (dio_read(dhandle, dir_entry->key_pointer, &index_block)) { err_exit("dio_read.4", 1); } /* First pointer is header block */ header_addr = index_block.content.addr_lo[0] | index_block.content.addr_hi[0] << 8; /* Read header block */ if (dio_read(dhandle, header_addr, &header_block)) { err_exit("dio_read.5", 1); } /* Do some sanity check */ for (index = 0; index < sizeof(info_signature); ++index) { if (header_block.content.info_block[index] != info_signature[index]) { err_exit("file signature mismatch", 0); } } /* Check ProDOS storage type in directory entry template */ if (header_block.content.dir_entry.storage_length.storage_type == 2) { /* ProDOS sapling file means GEOS Sequential file*/ printf("\nSequential file\n"); /* Remove header block pointer from pointer list */ memmove(&index_block.content.addr_lo[0], &index_block.content.addr_lo[1], sizeof(index_block.content.addr_lo) - 1); memmove(&index_block.content.addr_hi[0], &index_block.content.addr_hi[1], sizeof(index_block.content.addr_hi) - 1); /* Get file size from ProDOS directory entry template */ size = (unsigned long)(header_block.content.dir_entry.size[0]) | (unsigned long)(header_block.content.dir_entry.size[1]) << 8 | (unsigned long)(header_block.content.dir_entry.size[2]) << 16; } else { /* ProDOS tree file means GEOS VLIR file */ unsigned vlir_addr; unsigned long vlir_size; unsigned char vlir_blocks; unsigned char record = 0; printf("\nVLIR file\n"); /* Skip header block pointer */ index = 1; size = 0; while (1) { /* Get next VLIR index pointer from index block */ vlir_addr = index_block.content.addr_lo[index] | index_block.content.addr_hi[index] << 8; ++index; /* Check for end of pointer list */ if (vlir_addr == 0) { break; } /* Check for empty VLIRs */ while (header_block.content.vlir_records[record] == 0xFF) { /* Add empty VLIR index pointer to to master index block */ master_block.content.addr_lo[record] = 0xFF; master_block.content.addr_hi[record] = 0xFF; ++record; } /* Add VLIR index pointer to master index block */ master_block.content.addr_lo[record] = (unsigned char)(vlir_addr ); master_block.content.addr_hi[record] = (unsigned char)(vlir_addr >> 8); ++record; /* Read VLIR index block */ if (dio_read(dhandle, vlir_addr, &vlir_block)) { err_exit("dio_read.6", 1); } /* Get VLIR size from VLIR index block */ vlir_size = (unsigned long)(vlir_block.content.size_lo[1]) | (unsigned long)(vlir_block.content.size_hi[1]) << 8 | (unsigned long)(vlir_block.content.size_lo[0]) << 16 | (unsigned long)(vlir_block.content.size_hi[0]) << 24; printf("VLIR %u size %lu bytes\n", record - 1, vlir_size); /* Compute VLIR block size */ vlir_blocks = (unsigned char)((vlir_size + 511) / 512); /* Copy VLIR block pointers from index block to VLIR index block */ memcpy(&vlir_block.content.addr_lo[0], &index_block.content.addr_lo[index], vlir_blocks); memcpy(&vlir_block.content.addr_hi[0], &index_block.content.addr_hi[index], vlir_blocks); index += vlir_blocks; /* Write back VLIR index block */ if (dio_write(dhandle, vlir_addr, &vlir_block)) { err_exit("dio_write.1", 1); } /* Add VLIR size to file size */ size += vlir_size; } /* Replace (by now completely read) index block with (by now completely created) master index block */ index_block = master_block; } printf("File size %lu bytes\n\n", size); /* Set file size in index block */ index_block.content.size_lo[1] = (unsigned char)(size ); index_block.content.size_hi[1] = (unsigned char)(size >> 8); index_block.content.size_lo[0] = (unsigned char)(size >> 16); index_block.content.size_hi[0] = (unsigned char)(size >> 24); /* Write index block */ if (dio_write(dhandle, dir_entry->key_pointer, &index_block)) { err_exit("dio_write.2", 1); } /* Copy selected fields from directory entry template to directory block */ dir_entry->storage_length = header_block.content.dir_entry.storage_length; memcpy(dir_entry->file_name, header_block.content.dir_entry.file_name, 15); dir_entry->file_type = header_block.content.dir_entry.file_type; dir_entry->size[0] = (unsigned char)(size ); dir_entry->size[1] = (unsigned char)(size >> 8); dir_entry->size[2] = (unsigned char)(size >> 16); dir_entry->creation = header_block.content.dir_entry.creation; dir_entry->version = header_block.content.dir_entry.version; dir_entry->min_version = header_block.content.dir_entry.min_version; dir_entry->aux_type = header_addr; dir_entry->last_mod = header_block.content.dir_entry.last_mod; /* Write directory block */ if (dio_write(dhandle, dir_addr, &dir_block)) { err_exit("dio_write.3", 1); } /* We're done */ if (dio_close(dhandle)) { err_exit("dio_close", 1); } printf("Convert to '%.*s' successful", dir_entry->storage_length.name_length, dir_entry->file_name); getchar(); return EXIT_SUCCESS; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/��������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015157�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/Makefile.inc��������������������������������������������������������������0000664�0000000�0000000�00000000050�13473601511�0017362�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������CA65FLAGS += -I geos-cbm -I geos-common ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/dio.inc�������������������������������������������������������������������0000664�0000000�0000000�00000001106�13473601511�0016423�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; offsets into sectsizetab (DIO functions) sst_flag = 0 ; length 1 sst_sectsize = 1 ; 2 sst_driveno = 3 ; 1 (drive #) sst_size = 4 ; size of one entry ; if changed, adapt diopncls.s ; offsets into dio_phys_pos diopp_head = 0 ; head diopp_track = 1 ; track / cylinder diopp_sector = 3 ; sector diopp_size = 5 ; size of structure ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/disk/���������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0016111�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/disk/changediskdevice.s���������������������������������������������������0000664�0000000�0000000�00000000446�13473601511�0021561�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 21.12.1999, 2.1.2003 ; char ChangeDiskDevice (char newDriveNumber); .export _ChangeDiskDevice .import setoserror .include "jumptab.inc" _ChangeDiskDevice: jsr ChangeDiskDevice jmp setoserror ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/disk/chkdkgeos.s����������������������������������������������������������0000664�0000000�0000000�00000000475�13473601511�0020245�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 21.12.1999, 2.1.2003 ; char ChkDkGEOS (void); .export _ChkDkGEOS .import setoserror .include "jumptab.inc" .include "geossym.inc" _ChkDkGEOS: jsr ChkDkGEOS jsr setoserror lda isGEOS rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/disk/dio_cts.s������������������������������������������������������������0000664�0000000�0000000�00000010623�13473601511�0017723�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2001-07-02, Maciej 'YTM/Elysium' Witkowiak ; 2015-08-26, Greg King ; ; ; unsigned char __fastcall__ dio_phys_to_log (dhandle_t handle, ; dio_phys_pos *physpos, /* input */ ; unsigned *sectnum); /* output */ ; .export _dio_phys_to_log .export sectab_1541_l, sectab_1541_h ; for log_to_phys .import popax,__oserror .importzp ptr1,ptr2,ptr3,tmp1,tmp2,tmp3,tmp4 .include "dio.inc" .include "geossym.inc" .include "const.inc" _dio_phys_to_log: sta ptr1 stx ptr1+1 ; pointer to result jsr popax sta ptr2 stx ptr2+1 ; pointer to input structure jsr popax sta ptr3 stx ptr3+1 ; pointer to handle ldy #sst_flag lda (ptr3),y and #128 beq _inv_hand ; handle not open or invalid ldy #diopp_head lda (ptr2),y bne _inv_data ; there is only head 0 ldy #diopp_track lda (ptr2),y beq _inv_data ; there is no track 0 sta tmp1 iny lda (ptr2),y bne _inv_data ; there are no more than 256 tracks dec tmp1 ; normalize track to start from 0 ldy #diopp_sector lda (ptr2),y sta tmp2 iny lda (ptr2),y bne _inv_data ; there are no more than 256 sectors ; tmp1 (int) holds track+sector, translate it using device info ldy #sst_driveno lda (ptr3),y tay lda driveType,y and #%00001111 ; remove ramDisk flags cmp #DRV_1541 beq dio_cts1541 cmp #DRV_1571 beq dio_cts1571 cmp #DRV_1581 beq dio_cts1581 lda #INCOMPATIBLE ; unsupported device ldx #0 beq ret dio_ctsend: ldy #1 lda tmp2 sta (ptr1),y dey lda tmp1 sta (ptr1),y ldx #0 txa ret: sta __oserror rts ; return success ; errors _inv_data: lda #INV_TRACK .byte $2c _inv_hand: lda #DEV_NOT_FOUND ldx #0 beq ret ; device-depended stuff, tmp1=track-1, tmp2=sector dio_cts1541: ldy tmp1 cpy #35 bcs _inv_data lda sectab_1541_l,y clc adc tmp2 sta tmp1 lda sectab_1541_h,y adc #0 sta tmp2 jmp dio_ctsend dio_cts1571: lda tmp1 cmp #70 bcs _inv_data cmp #35 ; last track of one side bcs _sub35 jmp dio_cts1541 ; track <=35 - same as 1541 _sub35: sec sbc #35 sta tmp1 jsr dio_cts1541 ; get offset on second side of disk lda tmp1 ; add second side base clc adc #<683 sta tmp1 lda tmp2 adc #>683 sta tmp2 jmp dio_ctsend dio_cts1581: ; 1581 has 80 tracks, 40 sectors each secnum=track*40+sector ldx #0 stx tmp3 stx tmp4 lda tmp1 beq _nomult cmp #80 bcs _inv_data ; mul40 by Christian Groessler sta tmp4 asl a rol tmp3 asl a rol tmp3 ; val * 4 adc tmp4 bcc L1 inc tmp3 ; val * 5 L1: asl a rol tmp3 ; val * 10 asl a rol tmp3 asl a rol tmp3 ; val * 40 = AX ldx tmp3 sta tmp3 stx tmp4 _nomult: lda tmp2 clc adc tmp3 sta tmp1 lda tmp4 adc #0 sta tmp2 jmp dio_ctsend .rodata sectab_1541_l: .byte $00, $15, $2a, $3f, $54, $69, $7e, $93 .byte $a8, $bd, $d2, $e7, $fc, $11, $26, $3b .byte $50, $65, $78, $8b, $9e, $b1, $c4, $d7 .byte $ea, $fc, $0e, $20, $32, $44, $56, $67 .byte $78, $89, $9a, $ab sectab_1541_h: .byte $00, $00, $00, $00, $00, $00, $00, $00 .byte $00, $00, $00, $00, $00, $01, $01, $01 .byte $01, $01, $01, $01, $01, $01, $01, $01 .byte $01, $01, $02, $02, $02, $02, $02, $02 .byte $02, $02, $02, $02 �������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/disk/dio_openclose.s������������������������������������������������������0000664�0000000�0000000�00000003557�13473601511�0021131�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2001-07-02, Maciej 'YTM/Elysium' Witkowiak ; 2015-08-24, Greg King ; ; based on Atari version by Christian Groessler ; ; dhandle_t __fastcall__ dio_open (unsigned char device); ; unsigned char __fastcall__ dio_close (dhandle_t handle); ; ; dio_open sets given device as current and initializes disk ; dio_close does nothing special .export _dio_open, _dio_close .import __oserror, _OpenDisk .importzp ptr1, tmp1 .include "dio.inc" .include "jumptab.inc" .include "geossym.inc" .include "const.inc" .bss sectsizetab: .res 4 * sst_size ; this is hardcoded .code _dio_open: cmp #4 bcs _inv_drive tax lda driveType,x ; check if there's a device beq _inv_drive txa pha clc adc #8 ; normalize devnum sta curDevice jsr SetDevice jsr _OpenDisk ; take care for errors there pla tay ; drive # asl a ; make index from drive id asl a tax lda #0 sta sectsizetab+sst_sectsize,x lda #128 sta sectsizetab+sst_flag,x ; set flag that drive is "open" lda #1 sta sectsizetab+sst_sectsize+1,x tya sta sectsizetab+sst_driveno,x stx tmp1 lda #<sectsizetab clc adc tmp1 sta tmp1 lda #>sectsizetab adc #0 tax lda tmp1 rts _inv_drive: lda #DEV_NOT_FOUND sta __oserror lda #0 tax rts _dio_close: sta ptr1 stx ptr1+1 lda #0 ldy #sst_flag sta (ptr1),y sta __oserror ; success tax rts ; return no error �������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/disk/dio_params.s���������������������������������������������������������0000664�0000000�0000000�00000002123�13473601511�0020411�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; 2.7.2001 ; ; this function is used by dio_read and dio_write to fix parameters (secnum) ; this function calls SetDevice so that more than one drive can be used at once .export dio_params,dio_secnum .import popax,pushax,_dio_log_to_phys .importzp ptr1 .include "geossym.inc" .include "jumptab.inc" .include "dio.inc" .bss dio_secnum: .res 2 .code dio_params: sta r4L stx r4H jsr popax sta dio_secnum stx dio_secnum+1 jsr popax ; get 3rd parameter pha ; save it txa pha jsr pushax ; put it back pla ; restore it sta ptr1+1 pla sta ptr1 ldy #sst_driveno lda (ptr1),y clc adc #8 jsr SetDevice ; setup device, load driver lda #<dio_secnum ldx #>dio_secnum jsr pushax lda #<r1L ldx #>r1H jmp _dio_log_to_phys ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/disk/dio_qcount.s���������������������������������������������������������0000664�0000000�0000000�00000000427�13473601511�0020444�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2012-10-23 ; ; unsigned __fastcall__ dio_query_sectcount (dhandle_t handle); ; .export _dio_query_sectcount .import __oserror _dio_query_sectcount: lda #0 sta __oserror lda #<683 ldx #>683 rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/disk/dio_qsize.s����������������������������������������������������������0000664�0000000�0000000�00000000405�13473601511�0020262�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2012-10-23 ; ; unsigned __fastcall__ dio_query_sectsize (dhandle_t handle); ; .export _dio_query_sectsize .import __oserror _dio_query_sectsize: lda #<256 ldx #>256 sta __oserror rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/disk/dio_read.s�����������������������������������������������������������0000664�0000000�0000000�00000000747�13473601511�0020053�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2001-07-02, Maciej 'YTM/Elysium' Witkowiak ; 2015-08-27, Greg King ; ; this file provides the _dio_read function ; ; unsigned char __fastcall__ dio_read (dhandle_t handle, unsigned sect_num, void *buffer); ; .export _dio_read .import dio_params, __oserror .include "geossym.inc" .include "jumptab.inc" _dio_read: jsr dio_params tay bne err jsr ReadBlock stx __oserror txa err: rts �������������������������cc65-2.18/libsrc/geos-cbm/disk/dio_stc.s������������������������������������������������������������0000664�0000000�0000000�00000007501�13473601511�0017724�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2001-07-02, Maciej 'YTM/Elysium' Witkowiak ; 2015-08-27, Greg King ; ; unsigned char __fastcall__ dio_log_to_phys (dhandle_t handle, ; unsigned *sectnum, /* input */ ; dio_phys_pos *physpos); /* output */ ; .export _dio_log_to_phys .importzp ptr1,ptr2,ptr3,tmp1,tmp2 .import popax,__oserror .import sectab_1541_l, sectab_1541_h .include "dio.inc" .include "geossym.inc" .include "const.inc" _dio_log_to_phys: ; check device type sta ptr1 stx ptr1+1 ; pointer to result (struct dio_phys_pos) jsr popax sta ptr2 stx ptr2+1 ; pointer to input structure (pointer to int) jsr popax sta ptr3 stx ptr3+1 ; pointer to handle ldy #sst_flag lda (ptr3),y and #128 beq _inv_hand ; handle not open or invalid ; fill in all we have ldy #diopp_head lda #0 ; head 0 sta (ptr1),y ldy #diopp_track+1 sta (ptr1),y ; track <256 ldy #diopp_sector+1 sta (ptr1),y ; sector <256 ldy #0 lda (ptr2),y sta tmp1 iny lda (ptr2),y sta tmp2 ; get drive info ldy #sst_driveno lda (ptr3),y tay lda driveType,y and #%00001111 ; remove ramDisk flags cmp #DRV_1541 beq dio_stc1541 cmp #DRV_1571 beq dio_stc1571 cmp #DRV_1581 beq dio_stc1581 lda #INCOMPATIBLE ; unsupported device ldx #0 beq _ret dio_stcend: ldy #diopp_track lda tmp1 sta (ptr1),y ldy #diopp_sector lda tmp2 sta (ptr1),y ldx #0 txa _ret: sta __oserror rts ; return success ; errors _inv_data: lda #INV_TRACK .byte $2c _inv_hand: lda #DEV_NOT_FOUND ldx #0 beq _ret dio_stc1541: ; if 1541: ; - compare with table to find track ; - subtract and find sector ldx #0 ; index=(track-1) _loop41: lda tmp2 cmp sectab_1541_h+1,x bne _nxt lda tmp1 cmp sectab_1541_l+1,x _nxt: bcc _found inx cpx #35 bne _loop41 beq _inv_data _found: lda tmp1 sec sbc sectab_1541_l,x sta tmp2 _fndend: inx stx tmp1 jmp dio_stcend dio_stc1571: ; if 1571: ; - check size, if too big - subtract and add 35 to track ; - fall down to 1541 lda tmp2 cmp #>683 bne _if71 lda tmp1 cmp #<683 _if71: bcc dio_stc1541 lda tmp1 sec sbc #<683 sta tmp1 lda tmp2 sbc #>683 sta tmp2 jsr dio_stc1541 ; will fall through here tay bne _ret ; result beyond track 70 ldy #diopp_track lda (ptr1),y clc adc #35 sta (ptr1),y lda #0 beq _ret ; if 1581: ; - subtract 40 in loop (at most 80 times) to find track ; - the remainder is sector dio_stc1581: ldx #0 ; index=(track-1) _loop81: lda tmp2 bne _sub81 lda tmp1 cmp #40 bcc _got81 _sub81: lda tmp1 sec sbc #40 sta tmp1 lda tmp2 sbc #0 sta tmp2 inx cpx #80 bne _loop81 beq _inv_data _got81: lda tmp1 sta tmp2 inx stx tmp1 jmp dio_stcend �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/disk/dio_write.s����������������������������������������������������������0000664�0000000�0000000�00000000751�13473601511�0020265�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2001-07-02, Maciej 'YTM/Elysium' Witkowiak ; 2015-08-27, Greg King ; ; this file provides the _dio_write function ; ; unsigned char __fastcall__ dio_write (dhandle_t handle, unsigned sect_num, const void *buffer); ; .export _dio_write .import dio_params, setoserror .include "geossym.inc" .include "jumptab.inc" _dio_write: jsr dio_params tay bne err jsr WriteBlock jmp setoserror err: rts �����������������������cc65-2.18/libsrc/geos-cbm/disk/dio_writev.s���������������������������������������������������������0000664�0000000�0000000�00000001012�13473601511�0020442�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2001-07-02, Maciej 'YTM/Elysium' Witkowiak ; 2015-08-27, Greg King ; ; this file provides the _dio_write function ; ; unsigned char __fastcall__ dio_write_verify (dhandle_t handle, unsigned sect_num, const void *buffer); ; .export _dio_write_verify .import dio_params, __oserror .include "geossym.inc" .include "jumptab.inc" _dio_write_verify: jsr dio_params tay bne err jsr VerWriteBlock stx __oserror txa err: rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/disk/enterturbo.s���������������������������������������������������������0000664�0000000�0000000�00000000267�13473601511�0020473�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 21.12.99 ; void EnterTurbo (void); .export _EnterTurbo .include "jumptab.inc" _EnterTurbo = EnterTurbo �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/disk/exitturbo.s����������������������������������������������������������0000664�0000000�0000000�00000000264�13473601511�0020324�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 21.12.99 ; void ExitTurbo (void); .export _ExitTurbo .include "jumptab.inc" _ExitTurbo = ExitTurbo ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/disk/findbambit.s���������������������������������������������������������0000664�0000000�0000000�00000000726�13473601511�0020401�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 21.12.1999, 2.1.2003 ; char FindBAMBit (struct tr_se *TS); ; (might be called inUSE (if (!inUSE(block)))) .export _FindBAMBit .import gettrse .import return0, return1 .include "jumptab.inc" .include "geossym.inc" _FindBAMBit: jsr gettrse sta r6L stx r6H jsr FindBAMBit bne inUse jmp return0 inUse: jmp return1 ������������������������������������������cc65-2.18/libsrc/geos-cbm/disk/newdisk.s������������������������������������������������������������0000664�0000000�0000000�00000000363�13473601511�0017743�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 21.12.1999, 2.1.2003 ; char NewDisk (void); .export _NewDisk .import setoserror .include "jumptab.inc" _NewDisk: jsr NewDisk jmp setoserror �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/disk/purgeturbo.s���������������������������������������������������������0000664�0000000�0000000�00000000267�13473601511�0020500�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 21.12.99 ; void PurgeTurbo (void); .export _PurgeTurbo .include "jumptab.inc" _PurgeTurbo = PurgeTurbo �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/disk/readblock.s����������������������������������������������������������0000664�0000000�0000000�00000000702�13473601511�0020222�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 21.12.1999, 2.1.2003 ; char ReadBlock (struct tr_se myTS, char *buffer); .export _ReadBlock .import popax, setoserror .import gettrse .include "jumptab.inc" .include "geossym.inc" _ReadBlock: sta r4L stx r4H jsr popax jsr gettrse sta r1L stx r1H jsr ReadBlock jmp setoserror ��������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/disk/readbuff.s�����������������������������������������������������������0000664�0000000�0000000�00000000563�13473601511�0020057�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 26.10.1999, 2.1.2003 ; char ReadBuff (struct tr_se); .export _ReadBuff .import setoserror .import gettrse .include "diskdrv.inc" .include "geossym.inc" _ReadBuff: jsr gettrse sta r1L stx r1H jsr ReadBuff jmp setoserror ���������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/disk/setgeosdisk.s��������������������������������������������������������0000664�0000000�0000000�00000000373�13473601511�0020624�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 21.12.1999, 2.1.2003 ; char SetGEOSDisk (void); .export _SetGEOSDisk .import setoserror .include "jumptab.inc" _SetGEOSDisk: jsr SetGEOSDisk jmp setoserror ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/disk/verwriteblock.s������������������������������������������������������0000664�0000000�0000000�00000000723�13473601511�0021161�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 21.12.1999, 2.1.2003 ; char VerWriteBlock (struct tr_se *myTS, char *buffer); .export _VerWriteBlock .import popax, setoserror .import gettrse .include "jumptab.inc" .include "geossym.inc" _VerWriteBlock: sta r4L stx r4H jsr popax jsr gettrse sta r1L stx r1H jsr VerWriteBlock jmp setoserror ���������������������������������������������cc65-2.18/libsrc/geos-cbm/disk/writeblock.s���������������������������������������������������������0000664�0000000�0000000�00000000707�13473601511�0020446�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 21.12.1999, 2.1.2003 ; char WriteBlock (struct tr_se *myTS, char *buffer); .export _WriteBlock .import popax, setoserror .import gettrse .include "jumptab.inc" .include "geossym.inc" _WriteBlock: sta r4L stx r4H jsr popax jsr gettrse sta r1L stx r1H jsr WriteBlock jmp setoserror ���������������������������������������������������������cc65-2.18/libsrc/geos-cbm/disk/writebuff.s����������������������������������������������������������0000664�0000000�0000000�00000000567�13473601511�0020302�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 26.10.1999, 2.1.2003 ; char WriteBuff (struct tr_se*); .export _WriteBuff .import setoserror .import gettrse .include "diskdrv.inc" .include "geossym.inc" _WriteBuff: jsr gettrse sta r1L stx r1H jsr WriteBuff jmp setoserror �����������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/diskdrv.inc���������������������������������������������������������������0000664�0000000�0000000�00000002506�13473601511�0017323�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ;GEOS Disk Driver JumpTab ;reassembled by Maciej 'YTM/Alliance' Witkowiak ;4-2-99 ;pointers InitForIO_ = $9000 DoneWithIO_ = $9002 ExitTurbo_ = $9004 PurgeTurbo_ = $9006 EnterTurbo_ = $9008 ChangeDiskDevice_ = $900a NewDisk_ = $900c ReadBlock_ = $900e WriteBlock_ = $9010 VerWriteBlock_ = $9012 OpenDisk_ = $9014 GetBlock_ = $9016 PutBlock_ = $9018 GetDirHead_ = $901a PutDirHead_ = $901c GetFreeDirBlk_ = $901e CalcBlksFree_ = $9020 FreeBlock_ = $9022 SetNextFree_ = $9024 FindBAMBit_ = $9026 NxtBlkAlloc_ = $9028 BlkAlloc_ = $902a ChkDkGEOS_ = $902c SetGEOSDisk_ = $902e ;jump table Get1stDirEntry = $9030 GetNxtDirEntry = $9033 GetBorder = $9036 AddDirBlock = $9039 ReadBuff = $903c WriteBuff = $903f ;??? = $9042 ;??? = $9045 AllocateBlock = $9048 ReadLink = $904b ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/emd/����������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015724�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/emd/geos-vdc.s������������������������������������������������������������0000664�0000000�0000000�00000023124�13473601511�0017621�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Extended memory driver for the VDC RAM available on all C128 machines ; version for GEOS enters safe I/O config on C64 (transparent on C128) ; ; Maciej 'YTM/Elysium' Witkowiak <ytm@elysium.pl> ; 06,20,25.12.2002 .include "zeropage.inc" .include "em-kernel.inc" .include "em-error.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _geos_vdc_emd ; Driver signature .byte $65, $6d, $64 ; "emd" .byte EMD_API_VERSION ; EM API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr PAGECOUNT .addr MAP .addr USE .addr COMMIT .addr COPYFROM .addr COPYTO ; ------------------------------------------------------------------------ ; Constants VDC_ADDR_REG = $D600 ; VDC address VDC_DATA_REG = $D601 ; VDC data VDC_DATA_HI = 18 ; used registers VDC_DATA_LO = 19 VDC_CSET = 28 VDC_DATA = 31 ; ------------------------------------------------------------------------ ; Data. .data pagecount: .word 64 ; $0000-$3fff as 16k default curpage: .word $ffff ; currently mapped-in page (invalid) .bss window: .res 256 ; memory window .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present and determine the amount of ; memory available. ; Must return an EM_ERR_xx code in a/x. ; INSTALL: ; do test for VDC presence here??? php sei lda $01 pha lda #$35 sta $01 ldx #VDC_CSET ; determine size of RAM... jsr vdcgetreg sta tmp1 ora #%00010000 jsr vdcputreg ; turn on 64k jsr settestadr1 ; save original value of test byte jsr vdcgetbyte sta tmp2 lda #$55 ; write $55 here ldy #ptr1 jsr test64k ; read it here and there lda #$aa ; write $aa here ldy #ptr2 jsr test64k ; read it here and there jsr settestadr1 lda tmp2 jsr vdcputbyte ; restore original value of test byte lda ptr1 ; do bytes match? cmp ptr1+1 bne @have64k lda ptr2 cmp ptr2+1 bne @have64k ldx #VDC_CSET lda tmp1 jsr vdcputreg ; restore 16/64k flag jmp @endok ; and leave default values for 16k @have64k: lda #<256 ldx #>256 sta pagecount stx pagecount+1 @endok: pla sta $01 plp lda #<EM_ERR_OK ldx #>EM_ERR_OK rts test64k: sta tmp1 sty ptr3 lda #0 sta ptr3+1 jsr settestadr1 lda tmp1 jsr vdcputbyte ; write $55 jsr settestadr1 jsr vdcgetbyte ; read here pha jsr settestadr2 jsr vdcgetbyte ; and there ldy #1 sta (ptr3),y pla dey sta (ptr3),y rts settestadr1: ldy #$02 ; test page 2 (here) .byte $2c settestadr2: ldy #$42 ; or page 64+2 (there) lda #0 jmp vdcsetsrcaddr ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: ;on C128 restore font and clear the screen? rts ; ------------------------------------------------------------------------ ; PAGECOUNT: Return the total number of available pages in a/x. ; PAGECOUNT: lda pagecount ldx pagecount+1 rts ; ------------------------------------------------------------------------ ; MAP: Map the page in a/x into memory and return a pointer to the page in ; a/x. The contents of the currently mapped page (if any) may be discarded ; by the driver. ; MAP: sta curpage stx curpage+1 sta ptr1+1 ldy #0 sty ptr1 lda #<window sta ptr2 lda #>window sta ptr2+1 jsr transferin lda #<window ldx #>window rts ; copy a single page from (ptr1):VDCRAM to (ptr2):RAM transferin: php sei lda $01 pha lda #$35 sta $01 lda ptr1 ldy ptr1+1 jsr vdcsetsrcaddr ; set source address in VDC ldy #0 ldx #VDC_DATA stx VDC_ADDR_REG @L0: bit VDC_ADDR_REG bpl @L0 lda VDC_DATA_REG ; get 2 bytes at a time to speed-up sta (ptr2),y ; (in fact up to 8 bytes could be fetched with special VDC config) iny lda VDC_DATA_REG sta (ptr2),y iny bne @L0 pla sta $01 plp rts ; ------------------------------------------------------------------------ ; USE: Tell the driver that the window is now associated with a given page. USE: sta curpage stx curpage+1 ; Remember the page lda #<window ldx #>window ; Return the window done: rts ; ------------------------------------------------------------------------ ; COMMIT: Commit changes in the memory window to extended storage. COMMIT: lda curpage ; jump if no page mapped ldx curpage+1 bmi done sta ptr1+1 ldy #0 sty ptr1 lda #<window sta ptr2 lda #>window sta ptr2+1 ; fall through to transferout ; copy a single page from (ptr2):RAM to (ptr1):VDCRAM transferout: php sei lda $01 pha lda #$35 sta $01 lda ptr1 ldy ptr1+1 jsr vdcsetsrcaddr ; set source address in VDC ldy #0 ldx #VDC_DATA stx VDC_ADDR_REG @L0: bit VDC_ADDR_REG bpl @L0 lda (ptr2),y ; speedup does not work for writing sta VDC_DATA_REG iny bne @L0 pla sta $01 plp rts ; ------------------------------------------------------------------------ ; COPYFROM: Copy from extended into linear memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYFROM: jsr setup beq @L2 ; Skip if no full pages ; Copy full pages @L1: jsr transferin inc ptr1+1 inc ptr2+1 dec tmp1 bne @L1 ; Copy the remainder of the page @L2: ldy #EM_COPY::COUNT lda (ptr3),y ; Get bytes in last page beq @L4 sta tmp1 ; Transfer the bytes in the last page php sei lda $01 pha lda #$35 sta $01 ldy #0 @L3: jsr vdcgetbyte sta (ptr2),y iny dec tmp1 lda tmp1 bne @L3 pla sta $01 plp @L4: rts ; ------------------------------------------------------------------------ ; COPYTO: Copy from linear into extended memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYTO: jsr setup beq @L2 ; Skip if no full pages ; Copy full pages @L1: jsr transferout inc ptr1+1 inc ptr2+1 dec tmp1 bne @L1 ; Copy the remainder of the page @L2: ldy #EM_COPY::COUNT lda (ptr3),y ; Get bytes in last page beq @L4 sta tmp1 ; Transfer the bytes in the last page php sei lda $01 pha lda #$35 sta $01 ldy #0 @L3: lda (ptr2),y jsr vdcputbyte iny dec tmp1 lda tmp1 bne @L3 pla sta $01 plp @L4: rts ;------------------------------------------------------------------------- ; Helper functions to handle VDC ram ; vdcsetsrcaddr: ldx #VDC_DATA_LO stx VDC_ADDR_REG @L0: bit VDC_ADDR_REG bpl @L0 sta VDC_DATA_REG dex tya stx VDC_ADDR_REG sta VDC_DATA_REG rts vdcgetbyte: ldx #VDC_DATA vdcgetreg: stx VDC_ADDR_REG @L0: bit VDC_ADDR_REG bpl @L0 lda VDC_DATA_REG rts vdcputbyte: ldx #VDC_DATA vdcputreg: stx VDC_ADDR_REG @L0: bit VDC_ADDR_REG bpl @L0 sta VDC_DATA_REG rts ; ------------------------------------------------------------------------ ; Helper function for COPYFROM and COPYTO: Store the pointer to the request ; structure and prepare data for the copy ; setup: sta ptr3 stx ptr3+1 ; Save the passed em_copy pointer ldy #EM_COPY::OFFS lda (ptr3),y sta ptr1 ldy #EM_COPY::PAGE lda (ptr3),y sta ptr1+1 ; From ldy #EM_COPY::BUF lda (ptr3),y sta ptr2 iny lda (ptr3),y sta ptr2+1 ; To ldy #EM_COPY::COUNT+1 lda (ptr3),y ; Get number of pages sta tmp1 rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/file/���������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0016076�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/file/followchain.s��������������������������������������������������������0000664�0000000�0000000�00000000716�13473601511�0020573�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 25.12.1999, 2.1.2003 ; char FollowChain (struct tr_se *myTrSe, char *buffer); .export _FollowChain .import popax, setoserror .import gettrse .include "jumptab.inc" .include "geossym.inc" _FollowChain: sta r3L stx r3H jsr popax jsr gettrse sta r1L stx r1H jsr FollowChain jmp setoserror ��������������������������������������������������cc65-2.18/libsrc/geos-cbm/geossym.inc���������������������������������������������������������������0000664�0000000�0000000�00000025441�13473601511�0017346�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ;GEOS variable memory locations sorted by address ;reassembled by Maciej 'YTM/Elysium' Witkowiak ;4-2-99 zpage = $0000 ; CPU_DDR = $00 CPU_DATA = $01 ; r0 = $02 r0L = $02 r0H = $03 r1 = $04 r1L = $04 r1H = $05 r2 = $06 r2L = $06 r2H = $07 r3 = $08 r3L = $08 r3H = $09 r4 = $0a r4L = $0a r4H = $0b r5 = $0c r5L = $0c r5H = $0d r6 = $0e r6L = $0e r6H = $0f r7 = $10 r7L = $10 r7H = $11 r8 = $12 r8L = $12 r8H = $13 r9 = $14 r9L = $14 r9H = $15 r10 = $16 r10L = $16 r10H = $17 r11 = $18 r11L = $18 r11H = $19 r12 = $1a r12L = $1a r12H = $1b r13 = $1c r13L = $1c r13H = $1d r14 = $1e r14L = $1e r14H = $1f r15 = $20 r15L = $20 r15H = $21 ; a0 = $fb a0L = $fb a0H = $fc a1 = $fd a1L = $fd a1H = $fe a2 = $70 a2L = $70 a2H = $71 a3 = $72 a3L = $72 a3H = $73 a4 = $74 a4L = $74 a4H = $75 a5 = $76 a5L = $76 a5H = $77 a6 = $78 a6L = $78 a6H = $79 a7 = $7a a7L = $7a a7H = $7b a8 = $7c a8L = $7c a8H = $7d a9 = $7e a9L = $7e a9H = $7f ; curPattern = $22 string = $24 baselineOffset = $26 curSetWidth = $27 curHeight = $29 curIndexTable = $2a cardDataPntr = $2c currentMode = $2e dispBufferOn = $2f mouseOn = $30 msePicPtr = $31 windowTop = $33 windowBottom = $34 leftMargin = $35 rightMargin = $37 pressFlag = $39 mouseXPos = $3a mouseYPos = $3c returnAddress = $3d graphMode = $3f TURBO_DD00 = $8e ; from 1541 turbo TURBO_DD00_CPY = $8f ; from 1541 turbo STATUS = $90 curDevice = $ba ; irqvec = $0314 bkvec = $0316 nmivec = $0318 ; APP_RAM = $0400 BACK_SCR_BASE = $6000 PRINTBASE = $7900 OS_VARS = $8000 ; diskBlkBuf = $8000 fileHeader = $8100 curDirHead = $8200 fileTrScTab = $8300 dirEntryBuf = $8400 DrACurDkNm = $841e DrBCurDkNm = $8430 dataFileName = $8442 dataDiskName = $8453 PrntFilename = $8465 PrntDiskName = $8476 curDrive = $8489 diskOpenFlg = $848a isGEOS = $848b interleave = $848c NUMDRV = $848d driveType = $848e _driveType = driveType-8 turboFlags = $8492 _turboFlags = turboFlags-8 curRecord = $8496 usedRecords = $8497 fileWritten = $8498 fileSize = $8499 appMain = $849b intTopVector = $849d intBotVector = $849f mouseVector = $84a1 keyVector = $84a3 inputVector = $84a5 mouseFaultVec = $84a7 otherPressVec = $84a9 StringFaultVec = $84ab alarmTmtVector = $84ad BRKVector = $84af RecoverVector = $84b1 selectionFlash = $84b3 alphaFlag = $84b4 iconSelFlg = $84b5 faultData = $84b6 menuNumber = $84b7 mouseTop = $84b8 mouseBottom = $84b9 mouseLeft = $84ba mouseRight = $84bc stringX = $84be stringY = $84c0 mousePicData = $84c1 maxMouseSpeed = $8501 minMouseSpeed = $8502 mouseAccel = $8503 keyData = $8504 mouseData = $8505 inputData = $8506 mouseSpeed = $8507 random = $850a saveFontTab = $850c dblClickCount = $8515 year = $8516 month = $8517 day = $8518 hour = $8519 minutes = $851a seconds = $851b alarmSetFlag = $851c sysDBData = $851d screencolors = $851e dlgBoxRamBuf = $851f ; to $8697 ; ;$8698 - $8877 - various system data (keyboard queue, VLIR t&s, DBox, Menu, timers) ; savedmoby2 = $88bb scr80polar = $88bc scr80colors = $88bd vdcClrMode = $88be driveData = $88bf ramExpSize = $88c3 sysRAMFlg = $88c4 firstBoot = $88c5 curType = $88c6 ramBase = $88c7 inputDevName = $88cb memBase = $88cf ;??? DrCCurDkNm = $88dc DrDCurDkNm = $88ee dir2Head = $8900 ; SPRITE_PICS = $8a00 spr0pic = $8a00 spr1pic = $8a40 spr2pic = $8a80 spr3pic = $8ac0 spr4pic = $8b00 spr5pic = $8b40 spr6pic = $8b80 spr7pic = $8bc0 COLOR_MATRIX = $8c00 ; obj0Pointer = $8ff8 obj1Pointer = $8ff9 obj2Pointer = $8ffa obj3Pointer = $8ffb obj4Pointer = $8ffc obj5Pointer = $8ffd obj6Pointer = $8ffe obj7Pointer = $8fff ; DISK_BASE = $9000 SCREEN_BASE = $a000 OS_ROM = $c000 OS_JUMPTAB = $c100 RAMC_BASE = $de00 RAMC_WINDOW = $df00 EXP_BASE = $df00 MOUSE_BASE_128 = $fd00 MOUSE_JMP_128 = $fd00 END_MOUSE_128 = $fe80 MOUSE_BASE = $fe80 MOUSE_JMP = $fe80 config = $ff00 END_MOUSE = $fffa NMI_VECTOR = $fffa RESET_VECTOR = $fffc IRQ_VECTOR = $fffe ; vicbase = $d000 sidbase = $d400 mmu = $d500 VDC = $d600 ctab = $d800 cia1base = $dc00 cia2base = $dd00 ; mob0xpos = $d000 mob0ypos = $d001 mob1xpos = $d002 mob1ypos = $d003 mob2xpos = $d004 mob2ypos = $d005 mob3xpos = $d006 mob3ypos = $d007 mob4xpos = $d008 mob4ypos = $d009 mob5xpos = $d00a mob5ypos = $d00b mob6xpos = $d00c mob6ypos = $d00d mob7xpos = $d00e mob7ypos = $d00f msbxpos = $d010 grcntrl1 = $d011 rasreg = $d012 lpxpos = $d013 lpypos = $d014 mobenble = $d015 grcntrl2 = $d016 grmemptr = $d018 grirq = $d019 grirqen = $d01a moby2 = $d017 mobprior = $d01b mobmcm = $d01c mobx2 = $d01d mobmobcol = $d01e mobbakcol = $d01f extclr = $d020 bakclr0 = $d021 bakclr1 = $d022 bakclr2 = $d023 bakclr3 = $d024 mcmclr0 = $d025 mcmclr1 = $d026 mob0clr = $d027 mob1clr = $d028 mob2clr = $d029 mob3clr = $d02a mob4clr = $d02b mob5clr = $d02c mob6clr = $d02d mob7clr = $d02e keyreg = $d02f clkreg = $d030 ; vdcreg = $d600 vdcdata = $d601 ; �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/geossym2.inc��������������������������������������������������������������0000664�0000000�0000000�00000000623�13473601511�0017423�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ;GEOS various variables in OS_ROM area ;reassembled by Maciej 'YTM/Alliance' Witkowiak ;4-2-99 bootName = $c006 gatewayFlag = $c007 version = $c00f nationality = $c010 sysFlgCopy = $c012 c128Flag = $c013 mp3Flag = $c014 dateCopy = $c018 �������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/graph/��������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0016260�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/graph/setnewmode.s��������������������������������������������������������0000664�0000000�0000000�00000000433�13473601511�0020616�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Scott Hutter ; ; 18.12.18 ; void SetNewMode(void); .export _SetNewMode .include "jumptab.inc" .include "geossym.inc" _SetNewMode: lda graphMode eor #$80 sta graphMode jmp SetNewMode �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/inputdrv.inc��������������������������������������������������������������0000664�0000000�0000000�00000000633�13473601511�0017527�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ;GEOS Input Driver Jump Tab ;reassembled by Maciej 'YTM/Alliance' Witkowiak ;4-2-99 ;for C64 ;MOUSE_JMP = $fe80 SlowMouse = $fe83 UpdateMouse = $fe86 SetMouse = $fe89 ;for C128 ;MOUSE_JMP_128 = $fd00 SlowMouse_128 = $fd03 UpdateMouse_128 = $fd06 SetMouse_128 = $fd09 �����������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/joy/����������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015760�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/joy/geos-stdjoy.s���������������������������������������������������������0000664�0000000�0000000�00000005031�13473601511�0020412�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Standard joystick driver for the C64. May be used multiple times when linked ; to the statically application. ; ; Ullrich von Bassewitz, 2002-12-20 ; .include "zeropage.inc" .include "joy-kernel.inc" .include "joy-error.inc" .include "geossym.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _geos_stdjoy_joy ; Driver signature .byte $6A, $6F, $79 ; "joy" .byte JOY_API_VERSION ; Driver API version number ; Library reference .addr $0000 ; Jump table. .word INSTALL .word UNINSTALL .word COUNT .word READ ; ------------------------------------------------------------------------ ; Constants JOY_COUNT = 2 ; Number of joysticks we support ; ------------------------------------------------------------------------ ; Data. .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 ; ------------------------------------------------------------------------ ; UNINSTALL 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. ; COUNT: lda #<JOY_COUNT ldx #>JOY_COUNT rts ; ------------------------------------------------------------------------ ; READ: Read a particular joystick passed in A. ; READ: tax php sei ; disable IRQ lda $01 pha lda #$35 sta $01 ; enable I/O txa ; Joystick number into X bne joy2 ; Read joystick 1 joy1: lda #$7F sta cia1base lda cia1base+1 back: tay pla sta $01 plp tya and #$1F eor #$1F rts ; Read joystick 2 joy2: ldx #0 lda #$E0 ldy #$FF sta cia1base+2 lda cia1base+1 sty cia1base+2 jmp back �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/jumptab.inc���������������������������������������������������������������0000664�0000000�0000000�00000014656�13473601511�0017330�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ;GEOS System Jump Table ;reassembled by Maciej 'YTM/Alliance' Witkowiak ;4-2-99 ;jump table InterruptMain = $c100 InitProcesses = $c103 RestartProcess = $c106 EnableProcess = $c109 BlockProcess = $c10c UnblockProcess = $c10f FreezeProcess = $c112 UnfreezeProcess = $c115 HorizontalLine = $c118 InvertLine = $c11b RecoverLine = $c11e VerticalLine = $c121 Rectangle = $c124 FrameRectangle = $c127 InvertRectangle = $c12a RecoverRectangle = $c12d DrawLine = $c130 DrawPoint = $c133 GraphicsString = $c136 SetPattern = $c139 GetScanLine = $c13c TestPoint = $c13f BitmapUp = $c142 PutChar = $c145 PutString = $c148 UseSystemFont = $c14b StartMouseMode = $c14e DoMenu = $c151 RecoverMenu = $c154 RecoverAllMenus = $c157 DoIcons = $c15a DShiftLeft = $c15d BBMult = $c160 BMult = $c163 DMult = $c166 Ddiv = $c169 DSdiv = $c16c Dabs = $c16f Dnegate = $c172 Ddec = $c175 ClearRam = $c178 FillRam = $c17b MoveData = $c17e InitRam = $c181 PutDecimal = $c184 GetRandom = $c187 MouseUp = $c18a MouseOff = $c18d DoPreviousMenu = $c190 ReDoMenu = $c193 GetSerialNumber = $c196 Sleep = $c199 ClearMouseMode = $c19c i_Rectangle = $c19f i_FrameRectangle = $c1a2 i_RecoverRectangle = $c1a5 i_GraphicsString = $c1a8 i_BitmapUp = $c1ab i_PutString = $c1ae GetRealSize = $c1b1 i_FillRam = $c1b4 i_MoveData = $c1b7 GetString = $c1ba GotoFirstMenu = $c1bd InitTextPrompt = $c1c0 MainLoop = $c1c3 DrawSprite = $c1c6 GetCharWidth = $c1c9 LoadCharSet = $c1cc PosSprite = $c1cf EnablSprite = $c1d2 DisablSprite = $c1d5 CallRoutine = $c1d8 CalcBlksFree = $c1db ChkDkGEOS = $c1de NewDisk = $c1e1 GetBlock = $c1e4 PutBlock = $c1e7 SetGEOSDisk = $c1ea SaveFile = $c1ed SetGDirEntry = $c1f0 BldGDirEntry = $c1f3 GetFreeDirBlk = $c1f6 WriteFile = $c1f9 BlkAlloc = $c1fc ReadFile = $c1ff SmallPutChar = $c202 FollowChain = $c205 GetFile = $c208 FindFile = $c20b CRC = $c20e LdFile = $c211 EnterTurbo = $c214 LdDeskAcc = $c217 ReadBlock = $c21a LdApplic = $c21d WriteBlock = $c220 VerWriteBlock = $c223 FreeFile = $c226 GetFHdrInfo = $c229 EnterDeskTop = $c22c StartAppl = $c22f ExitTurbo = $c232 PurgeTurbo = $c235 DeleteFile = $c238 FindFTypes = $c23b RstrAppl = $c23e ToBASIC = $c241 FastDelFile = $c244 GetDirHead = $c247 PutDirHead = $c24a NxtBlkAlloc = $c24d ImprintRectangle = $c250 i_ImprintRectangle = $c253 DoDlgBox = $c256 RenameFile = $c259 InitForIO = $c25c DoneWithIO = $c25f DShiftRight = $c262 CopyString = $c265 CopyFString = $c268 CmpString = $c26b CmpFString = $c26e FirstInit = $c271 OpenRecordFile = $c274 CloseRecordFile = $c277 NextRecord = $c27a PreviousRecord = $c27d PointRecord = $c280 DeleteRecord = $c283 InsertRecord = $c286 AppendRecord = $c289 ReadRecord = $c28c WriteRecord = $c28f SetNextFree = $c292 UpdateRecordFile = $c295 GetPtrCurDkNm = $c298 PromptOn = $c29b PromptOff = $c29e OpenDisk = $c2a1 DoInlineReturn = $c2a4 GetNextChar = $c2a7 BitmapClip = $c2aa FindBAMBit = $c2ad SetDevice = $c2b0 IsMseInRegion = $c2b3 ReadByte = $c2b6 FreeBlock = $c2b9 ChangeDiskDevice = $c2bc RstrFrmDialogue = $c2bf Panic = $c2c2 BitOtherClip = $c2c5 StashRAM = $c2c8 FetchRAM = $c2cb SwapRAM = $c2ce VerifyRAM = $c2d1 DoRAMOp = $c2d4 ;only in GEOS 128 TempHideMouse = $c2d7 SetMousePicture = $c2da SetNewMode = $c2dd NormalizeX = $c2e0 MoveBData = $c2e3 SwapBData = $c2e6 VerifyBData = $c2e9 DoBOp = $c2ec AccessCache = $c2ef HideOnlyMouse = $c2f2 SetColorMode = $c2f5 ColorCard = $c2f8 ColorRectangle = $c2fb ����������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/memory/�������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0016467�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/memory/fetchram.s���������������������������������������������������������0000664�0000000�0000000�00000000455�13473601511�0020450�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 21.12.99 ; void FetchRAM (char REUBank, int length, char *from, char *dest); .import REURegs .export _FetchRAM .include "jumptab.inc" .include "geossym.inc" _FetchRAM: jsr REURegs jmp FetchRAM �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/memory/reuregs.s����������������������������������������������������������0000664�0000000�0000000�00000000460�13473601511�0020327�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 31.12.99 .import popax, popa .import DoublePop .export REURegs .include "geossym.inc" REURegs: jsr DoublePop jsr popax sta r2L stx r2H jsr popa sta r3L rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/memory/stashram.s���������������������������������������������������������0000664�0000000�0000000�00000000455�13473601511�0020501�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 21.12.99 ; void StashRAM (char REUBank, int length, char *dest, char *from); .import REURegs .export _StashRAM .include "jumptab.inc" .include "geossym.inc" _StashRAM: jsr REURegs jmp StashRAM �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/memory/swapram.s����������������������������������������������������������0000664�0000000�0000000�00000000575�13473601511�0020334�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 21.12.99 ; void SwapRAM (char REUBank, int length, char *reuaddy, char *cpuaddy); ; note that in all REU procs last two pointers are identified like here .import REURegs .export _SwapRAM .include "jumptab.inc" .include "geossym.inc" _SwapRAM: jsr REURegs jmp SwapRAM �����������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/memory/verifyram.s��������������������������������������������������������0000664�0000000�0000000�00000000551�13473601511�0020660�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 21.12.1999, 2.1.2003 ; char VerifyRAM (char REUBank, int length, char *reuaddy, char *cpuaddy); .import REURegs .export _VerifyRAM .include "jumptab.inc" .include "geossym.inc" _VerifyRAM: jsr REURegs jsr VerifyRAM txa ldx #0 rts �������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/printdrv.inc��������������������������������������������������������������0000664�0000000�0000000�00000000626�13473601511�0017526�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ ;GEOS Printer Driver Jump Table ;reassembled by Maciej 'YTM/Alliance' Witkowiak ;4-2-99 ;jump table InitForPrint = $7900 StartPrint = $7903 PrintBuffer = $7906 StopPrint = $7909 GetDimensions = $790c PrinsASCII = $790f StartASCII = $7912 SetNLQ = $7915 ����������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/system/�������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0016503�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/system/get_ostype.s�������������������������������������������������������0000664�0000000�0000000�00000005170�13473601511�0021054�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 10.09.2001 ; ; Plus4, Gateway, MP3 and GEOS 1.1 detection by ; Marco van den Heuvel, 2018-02-07 ; ; unsigned char get_ostype (void); ; unsigned char get_tv (void); .export _get_ostype .export _get_tv .importzp tmp1 .include "const.inc" .include "geossym.inc" .include "geossym2.inc" _get_ostype: ldx #0 lda version cmp #$a9 beq geos11 and #%11110000 cmp #$10 beq geos10 cmp #$13 ; either 1.3 or 1.5 beq geos13check lda gatewayFlag cmp #$41 beq gateway lda mp3Flag cmp #$4d beq megapatch3 lda c128Flag ; we're on at least 2.0 cmp #$18 beq geos_on_plus4 ora version rts geos13: geos10: lda version rts geos11: lda #$11 rts geos_on_plus4: lda #$04 rts gateway: lda #$08 ora c128Flag rts megapatch3: lda #$03 ora c128Flag rts geos13check: lda mp3Flag cmp #$03 bne geos13 geos15: lda #$15 rts _get_tv: jsr _get_ostype cmp #$04 beq plus4_get_tv bpl only40 ; C64 with 40 columns only lda graphMode bpl only40 ; C128 but currently on 40 columns ldx #1 ; COLUMNS80 bne tvmode only40: ldx #0 ; COLUMNS40 tvmode: ; PAL/NTSC check here, result in A php sei ; disable interrupts lda CPU_DATA ; this is for C64 pha lda #IO_IN ; enable access to I/O sta CPU_DATA bit rasreg bpl tvmode ; wait for rasterline 127<x<256 lda #24 ; (rasterline now >=256!) modelp: cmp rasreg ; wait for rasterline = 24 (or 280 on PAL) bne modelp lda grcntrl1 ; 24 or 280 ? bpl ntsc lda #0 ; PAL beq modeend ntsc: lda #$80 ; NTSC modeend: stx tmp1 ora tmp1 sta tmp1 ldx #0 pla sta CPU_DATA ; restore memory config plp ; restore interrupt state lda tmp1 rts plus4_get_tv: ldx #1 ; Assume PAL bit $FF07 ; Test bit 6 bvc plus4pal dex ; NTSC plus4pal: txa ldx #0 rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/system/getserialnumber.s��������������������������������������������������0000664�0000000�0000000�00000000430�13473601511�0022054�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 30.10.99 ; int GetSerialNumber (void); .export _GetSerialNumber .include "jumptab.inc" .include "geossym.inc" _GetSerialNumber: jsr GetSerialNumber lda r0L ldx r0H rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/system/initdoneio.s�������������������������������������������������������0000664�0000000�0000000�00000000375�13473601511�0021035�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 30.10.99 ; void InitForIO (void); ; void DoneWithIO (void); .export _InitForIO, _DoneWithIO .include "jumptab.inc" _InitForIO = InitForIO _DoneWithIO = DoneWithIO�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/system/libref.s�����������������������������������������������������������0000664�0000000�0000000�00000000306�13473601511�0020131�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2013-05-31 ; .export em_libref, joy_libref, tgi_libref .import _exit em_libref := _exit joy_libref := _exit tgi_libref := _exit ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/system/setdevice.s��������������������������������������������������������0000664�0000000�0000000�00000000304�13473601511�0020637�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 21.12.99 ; void SetDevice (char newDeviceNumber); .export _SetDevice .include "jumptab.inc" _SetDevice = SetDevice ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/system/tobasic.s����������������������������������������������������������0000664�0000000�0000000�00000000245�13473601511�0020314�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 30.10.99 ; void ToBASIC (void); .export _ToBASIC .include "jumptab.inc" _ToBASIC = ToBASIC�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/tgi/����������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015742�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-cbm/tgi/geos-tgi.s������������������������������������������������������������0000664�0000000�0000000�00000041067�13473601511�0017654�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Graphics driver for the 320x200x2 and 640x200x2 modes on GEOS 64/128 ; 2010-08-17, Maciej 'YTM/Elysium' Witkowiak <ytm@elysium.pl> ; 2010-08-18, Greg King .include "zeropage.inc" .include "tgi-kernel.inc" .include "tgi-error.inc" .include "const.inc" .include "jumptab.inc" .include "geossym.inc" .include "geossym2.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Constants VDC_ADDR_REG := $D600 ; VDC address VDC_DATA_REG := $D601 ; VDC data VDC_DSP_HI = 12 ; registers used VDC_DSP_LO = 13 VDC_DATA_HI = 18 VDC_DATA_LO = 19 VDC_VSCROLL = 24 VDC_HSCROLL = 25 VDC_COLORS = 26 VDC_CSET = 28 VDC_COUNT = 30 VDC_DATA = 31 ; ------------------------------------------------------------------------ ; Header. Includes jump table and constants. module_header _geos_tgi_tgi ; First part of the header is a structure that has a magic signature, ; and defines the capabilities of the driver. .byte $74, $67, $69 ; "tgi" .byte TGI_API_VERSION ; TGI API version number .addr $0000 ; Library reference xres: .word 320 ; X resolution yres: .word 200 ; Y resolution .byte 2 ; Number of drawing colors pages: .byte 1 ; Number of screens available .byte 8 ; System font X size .byte 8 ; System font Y size aspect: .word $00D4 ; Aspect ratio (based on 4/3 display) .byte 0 ; TGI driver flags ; Next comes the jump table. With the exception of IRQ, all entries must be ; valid, and may point to an RTS for test versions (function not implemented). .addr INSTALL .addr UNINSTALL .addr INIT .addr DONE .addr GETERROR .addr CONTROL .addr CLEAR .addr SETVIEWPAGE .addr SETDRAWPAGE .addr SETCOLOR .addr SETPALETTE .addr GETPALETTE .addr GETDEFPALETTE .addr SETPIXEL .addr GETPIXEL .addr LINE .addr BAR .addr TEXTSTYLE .addr OUTTEXT ; ------------------------------------------------------------------------ ; Data. ; Variables mapped to the zero-page segment variables. Some of these are ; used for passing parameters to the driver. X1 = ptr1 Y1 = ptr2 X2 = ptr3 Y2 = ptr4 ; Absolute variables used in the code .bss SCRBASE: .res 1 ; High byte of screen base (64k VDC only) ERROR: .res 1 ; Error code PALETTE: .res 2 ; The current palette BITMASK: .res 1 ; $00 = clear, $01 = set pixels OLDCOLOR: .res 1 ; colors before entering gfx mode ; Text output stuff TEXTMAGX: .res 1 TEXTMAGY: .res 1 TEXTDIR: .res 1 ; Constants and tables .rodata DEFPALETTE: .byte $00, $0f ; White on black PALETTESIZE = * - DEFPALETTE ; color translation table (indexed by VIC color) COLTRANS: .byte $00, $0f, $08, $06, $0a, $04, $02, $0c .byte $0d, $0b, $09, $01, $0e, $05, $03, $07 ; colors BROWN and GRAY3 are wrong .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. May ; initialize anything that has to be done just once. Is probably empty ; most of the time. ; ; Must set an error code: NO ; INSTALL: lda version ; if GEOS 1.0... and #$f0 cmp #$10 beq @L40 lda c128Flag ; at least GEOS 2.0, but we're on C128? bpl @L40 lda graphMode ; GEOS 2.0, C128, but is 80 column screen enabled? bmi @L80 @L40: rts ; leave default values for 40 column screen ; check for VDC version and update register $19 value @L80: ; double the x resolution and halve the aspect ratio asl xres rol xres+1 lsr aspect+1 ror aspect ; update number of available screens ldx #VDC_CSET ; determine size of RAM... jsr VDCReadReg sta tmp1 ora #%00010000 jsr VDCWriteReg ; turn on 64k jsr settestadr1 ; save original value of test byte jsr VDCReadByte sta tmp2 lda #$55 ; write $55 here ldy #ptr1 jsr test64k ; read it here and there lda #$aa ; write $aa here ldy #ptr2 jsr test64k ; read it here and there jsr settestadr1 lda tmp2 jsr VDCWriteByte ; restore original value of test byte lda ptr1 ; do bytes match? cmp ptr1+1 bne @have64k lda ptr2 cmp ptr2+1 bne @have64k ldx #VDC_CSET lda tmp1 jsr VDCWriteReg ; restore 16/64k flag jmp @endok ; and leave default values for 16k @have64k: lda #4 sta pages @endok: lda #0 sta SCRBASE ; draw page 0 as default rts test64k: sta tmp1 sty ptr3 lda #0 sta ptr3+1 jsr settestadr1 lda tmp1 jsr VDCWriteByte ; write $55 jsr settestadr1 jsr VDCReadByte ; read here pha jsr settestadr2 jsr VDCReadByte ; and there ldy #1 sta (ptr3),y pla dey sta (ptr3),y rts settestadr1: ldy #$02 ; test page 2 (here) .byte $2c settestadr2: ldy #$42 ; or page 64+2 (there) lda #0 jmp VDCSetSourceAddr ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. May ; clean up anything done by INSTALL but is probably empty most of the time. ; ; Must set an error code: NO ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; INIT: Changes an already installed device from text mode to graphics ; mode. ; Note that INIT/DONE may be called multiple times while the driver ; is loaded, while INSTALL is only called once, so any code that is needed ; to initializes variables and so on must go here. Setting palette and ; clearing the screen is not needed because this is called by the graphics ; kernel later. ; The graphics kernel will never call INIT when a graphics mode is already ; active, so there is no need to protect against that. ; ; Must set an error code: YES ; INIT: ldx #$01 stx BITMASK ; solid black as pattern lda #1 jsr SetPattern lda #ST_WR_FORE ; write only on foreground sta dispBufferOn lda graphMode bmi @L80 ; Remember current color value (40 columns) lda screencolors sta OLDCOLOR jmp @L99 ; Remember current color value (80 columns) @L80: lda scr80colors sta OLDCOLOR @L99: lda #0 jsr SETVIEWPAGE ; switch into viewpage 0 ; Done, reset the error code lda #TGI_ERR_OK sta ERROR rts ; ------------------------------------------------------------------------ ; DONE: Will be called to switch the graphics device back into text mode. ; The graphics kernel will never call DONE when no graphics mode is active, ; so there is no need to protect against that. ; ; Must set an error code: NO ; DONE: lda #0 jsr SETVIEWPAGE ; switch into viewpage 0 lda graphMode bmi @L80 lda OLDCOLOR sta screencolors ; restore color for 40 columns ldx #0 @L1: sta COLOR_MATRIX,x sta COLOR_MATRIX+$0100,x sta COLOR_MATRIX+$0200,x sta COLOR_MATRIX+1000-256,x inx bne @L1 rts @L80: lda OLDCOLOR ; restore color for 80 columns ldx #VDC_COLORS jmp VDCWriteReg ; ------------------------------------------------------------------------ ; GETERROR: Return the error code in A and clear it. GETERROR: ldx #TGI_ERR_OK lda ERROR stx ERROR rts ; ------------------------------------------------------------------------ ; CONTROL: Platform/driver specific entry point. ; ; Must set an error code: YES ; CONTROL: lda #TGI_ERR_INV_FUNC sta ERROR rts ; ------------------------------------------------------------------------ ; CLEAR: Clears the screen. ; ; Must set an error code: NO ; CLEAR: lda curPattern pha lda #0 jsr SetPattern ldx #0 stx r3L stx r3H stx r2L lda #199 sta r2H lda graphMode bpl @L40 lda #>639 ; 80 columns ldx #<639 bne @L99 @L40: lda #>319 ; 40 columns ldx #<319 @L99: sta r4H stx r4L jsr Rectangle pla sta curPattern rts ; ------------------------------------------------------------------------ ; SETVIEWPAGE: Set the visible page. Called with the new page in A (0..n). ; The page number is already checked to be valid by the graphics kernel. ; ; Must set an error code: NO (will only be called if page ok) ; SETVIEWPAGE: ldx graphMode bmi @L80 rts @L80: clc ror ror ror ldx #VDC_DSP_HI jmp VDCWriteReg ; ------------------------------------------------------------------------ ; SETDRAWPAGE: Set the drawable page. Called with the new page in A (0..n). ; The page number is already checked to be valid by the graphics kernel. ; ; Must set an error code: NO (will only be called if page ok) ; SETDRAWPAGE: ldx graphMode bmi @L80 rts @L80: clc ror ror ror sta SCRBASE rts ; ------------------------------------------------------------------------ ; SETCOLOR: Set the drawing color (in A). The new color is already checked ; to be in a valid range (0..maxcolor-1). ; ; Must set an error code: NO (will only be called if color ok) ; SETCOLOR: tax beq @L1 lda #1 @L1: sta BITMASK jmp SetPattern ; need to have either 0 or 1 ; ------------------------------------------------------------------------ ; SETPALETTE: Set the palette (not available with all drivers/hardware). ; A pointer to the palette is passed in ptr1. Must set an error if palettes ; are not supported ; ; Must set an error code: YES ; SETPALETTE: jsr GETERROR ; clear error (if any) ldy #PALETTESIZE - 1 @L1: lda (ptr1),y ; Copy the palette and #$0F ; Make a valid color sta PALETTE,y dey bpl @L1 ; Put colors from palette into screen lda graphMode bmi @L80 lda PALETTE+1 ; foreground asl a asl a asl a asl a ora PALETTE ; background ldx #0 @L2: sta COLOR_MATRIX,x sta COLOR_MATRIX+$0100,x sta COLOR_MATRIX+$0200,x sta COLOR_MATRIX+1000-256,x inx bne @L2 rts @L80: ldy PALETTE+1 ; Foreground color lda COLTRANS,y asl a asl a asl a asl a ldy PALETTE ; Background color ora COLTRANS,y ldx #VDC_COLORS jmp VDCWriteReg ; ------------------------------------------------------------------------ ; GETPALETTE: Return the current palette in A/X. Even drivers that cannot ; set the palette should return the default palette here, so there's no ; way for this function to fail. ; ; Must set an error code: NO ; GETPALETTE: lda #<PALETTE ldx #>PALETTE rts ; ------------------------------------------------------------------------ ; GETDEFPALETTE: Return the default palette for the driver in A/X. All ; drivers should return something reasonable here, even drivers that don't ; support palettes, otherwise the caller has no way to determine the colors ; of the (not changeable) palette. ; ; Must set an error code: NO (all drivers must have a default palette) ; GETDEFPALETTE: lda #<DEFPALETTE ldx #>DEFPALETTE rts ; ------------------------------------------------------------------------ ; SETPIXEL: Draw one pixel at X1/Y1 = ptr1/ptr2 with the current drawing ; color. The coordinates passed to this function are never outside the ; visible screen area, so there is no need for clipping inside this function. ; ; Must set an error code: NO ; SETPIXEL: lda X1 ldx X1+1 ldy Y1 sta r3L stx r3H sty r11L sec lda BITMASK ; set or clear C flag bne @L1 clc @L1: lda #0 jmp DrawPoint ; ------------------------------------------------------------------------ ; GETPIXEL: Read the color value of a pixel and return it in A/X. The ; coordinates passed to this function are never outside the visible screen ; area, so there is no need for clipping inside this function. GETPIXEL: lda X1 ldx X1+1 ldy Y1 sta r3L stx r3H sty r11L jsr TestPoint ldx #0 bcc @L1 inx @L1: txa ldx #0 rts ; ------------------------------------------------------------------------ ; LINE: Draw a line from X1/Y1 to X2/Y2, where X1/Y1 = ptr1/ptr2 and ; X2/Y2 = ptr3/ptr4 using the current drawing color. ; ; Must set an error code: NO ; LINE: lda X1 ldx X1+1 ldy Y1 sta r3L stx r3H sty r11L lda X2 ldx X2+1 ldy Y2 sta r4L stx r4H sty r11H sec lda BITMASK ; set or clear C flag bne @L1 clc @L1: lda #0 jmp DrawLine ; ------------------------------------------------------------------------ ; BAR: Draw a filled rectangle with the corners X1/Y1, X2/Y2, where ; X1/Y1 = ptr1/ptr2 and X2/Y2 = ptr3/ptr4 using the current drawing color. ; Contrary to most other functions, the graphics kernel will sort and clip ; the coordinates before calling the driver, so on entry the following ; conditions are valid: ; X1 <= X2 ; Y1 <= Y2 ; (X1 >= 0) && (X1 < XRES) ; (X2 >= 0) && (X2 < XRES) ; (Y1 >= 0) && (Y1 < YRES) ; (Y2 >= 0) && (Y2 < YRES) ; ; Must set an error code: NO ; BAR: lda X1 ldx X1+1 ldy Y1 sta r3L stx r3H sty r2L lda X2 ldx X2+1 ldy Y2 sta r4L stx r4H sty r2H jmp Rectangle ; ------------------------------------------------------------------------ ; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in X and Y ; direction is passend in X/Y, the text direction is passed in A. ; ; Must set an error code: NO ; TEXTSTYLE: stx TEXTMAGX sty TEXTMAGY sta TEXTDIR rts ; ------------------------------------------------------------------------ ; OUTTEXT: Output text at X/Y = ptr1/ptr2 using the current color and the ; current text style. The text to output is given as a zero terminated ; string with address in ptr3. ; ; Must set an error code: NO ; OUTTEXT: lda TEXTDIR ; cmp #TGI_TEXT_HORIZONTAL ; this is equal 0 bne @vertical lda X1 ; horizontal text output ldx X1+1 ldy Y1 sta r11L stx r11H sty r1H lda ptr3 ldx ptr3+1 sta r0L stx r0H jmp PutString @vertical: lda X1 ; vertical text output ldx X1+1 ldy Y1 sta r11L stx r11H sty r1H ldy #0 lda (ptr3),y beq @end jsr PutChar inc ptr3 bne @L1 inc ptr3+1 @L1: lda Y1 clc adc #8 sta Y1 bne @vertical @end: rts ;------------- ; VDC helpers VDCSetSourceAddr: pha tya ldx #VDC_DATA_HI jsr VDCWriteReg pla ldx #VDC_DATA_LO bne VDCWriteReg VDCReadByte: ldx #VDC_DATA VDCReadReg: stx VDC_ADDR_REG @L0: bit VDC_ADDR_REG bpl @L0 lda VDC_DATA_REG rts VDCWriteByte: ldx #VDC_DATA VDCWriteReg: stx VDC_ADDR_REG @L0: bit VDC_ADDR_REG bpl @L0 sta VDC_DATA_REG rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/�����������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015706�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/common/����������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0017176�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/common/_afailed.c������������������������������������������������������0000664�0000000�0000000�00000001176�13473601511�0021073�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** _afailed.c ** ** Maciej 'YTM/Elysium' Witkowiak 28.10.2001 */ #include <stdio.h> #include <stdlib.h> #include <geos.h> void _afailed (char* file, unsigned line) { ExitTurbo(); drawWindow.top = 0; drawWindow.left = 0; drawWindow.bot = 15; drawWindow.right = 150; dispBufferOn = ST_WR_FORE|ST_WR_BACK; SetPattern(0); Rectangle(); FrameRectangle(0xff); PutString(CBOLDON "file: ", 10, 10); PutString(file, 10, r11); PutString(CBOLDON " line: ", 10, r11); PutDecimal(0, line, 10, r11); DlgBoxOk(CBOLDON "ASSERTION FAILED", "PROGRAM TERMINATED" CPLAINTEXT); exit (2); } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/common/_poserror.c�����������������������������������������������������0000664�0000000�0000000�00000000557�13473601511�0021363�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** _poserror.c ** ** Maciej 'YTM/Elysium' Witkowiak, 25.04.2003 */ #include <stdio.h> #include <string.h> #include <errno.h> #include <geos.h> void __fastcall__ _poserror (const char* msg) { const char *errmsg = _stroserror(_oserror); ExitTurbo(); if (msg && *msg) { DlgBoxOk(msg, errmsg); } else { DlgBoxOk("", errmsg); } } �������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/common/abort.c���������������������������������������������������������0000664�0000000�0000000�00000000341�13473601511�0020447�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** abort.c ** ** Maciej 'YTM/Elysium' Witkowiak 15.7.2001 */ #include <stdlib.h> #include <geos.h> void abort (void) { ExitTurbo(); DlgBoxOk(CBOLDON "ABNORMAL PROGRAM", "TERMINATION." CPLAINTEXT); exit(3); } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/common/copydata.s������������������������������������������������������0000664�0000000�0000000�00000001135�13473601511�0021166�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak 15.07.2001 ; ; Copy the data segment from the LOAD to the RUN location ; .export copydata .import __DATA_LOAD__, __DATA_RUN__, __DATA_SIZE__ .include "geossym.inc" .include "jumptab.inc" copydata: lda #<__DATA_SIZE__ ; no need to check if it is == 0 ldx #>__DATA_SIZE__ sta r2L stx r2H lda #<__DATA_RUN__ ldx #>__DATA_RUN__ sta r1L stx r1H lda #<__DATA_LOAD__ ldx #>__DATA_LOAD__ sta r0L stx r0H jmp MoveData �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/common/memcpy.s��������������������������������������������������������0000664�0000000�0000000�00000000320�13473601511�0020647�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; void* __fastcall__ memcpy (void* dest, const void* src, size_t n); ; ; Maciej 'YTM/Elysium' Witkowiak, 15.07.2001 ; .export _memcpy .import _MoveData _memcpy = _MoveData ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/common/memmove.s�������������������������������������������������������0000664�0000000�0000000�00000000322�13473601511�0021024�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; void* __fastcall__ memmove (void* dest, const void* src, size_t n); ; ; Maciej 'YTM/Elysium' Witkowiak, 15.07.2001 ; .export _memmove .import _MoveData _memmove = _MoveData ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/common/memset.s��������������������������������������������������������0000664�0000000�0000000�00000000524�13473601511�0020655�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; void* memset (void* ptr, int c, size_t n); ; void* _bzero (void* ptr, size_t n); ; void bzero (void* ptr, size_t n); ; ; Maciej 'YTM/Elysium' Witkowiak, 20.08.2003 ; .export _memset, _bzero, __bzero .import _ClearRam, _FillRam _bzero = _ClearRam __bzero = _ClearRam _memset = _FillRam ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/common/perror.c��������������������������������������������������������0000664�0000000�0000000�00000000542�13473601511�0020654�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** perror.c ** ** Maciej 'YTM/Elysium' Witkowiak, 15.07.2001 */ #include <stdio.h> #include <string.h> #include <errno.h> #include <geos.h> void __fastcall__ perror(const char* msg) { const char *errmsg = strerror(errno); ExitTurbo(); if (msg && *msg) { DlgBoxOk(msg, errmsg); } else { DlgBoxOk("", errmsg); } } ��������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/common/sleep.c���������������������������������������������������������0000664�0000000�0000000�00000000426�13473601511�0020454�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** sleep.c ** ** Maciej 'YTM/Elysium' Witkowiak, 16.08.2003 ** */ #include <geos.h> unsigned __fastcall__ sleep (unsigned wait) { char typ; if ( (get_tv()) & TV_NTSC ) { typ = 60; } else { typ = 50; } Sleep(wait*typ); return 0; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/common/zerobss.s�������������������������������������������������������0000664�0000000�0000000�00000000704�13473601511�0021052�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak <ytm@elysium.pl> ; 23.12.2002 ; ; Zero the bss segment. ; .export zerobss .import __BSS_RUN__, __BSS_SIZE__ .include "jumptab.inc" .include "geossym.inc" zerobss: lda #<__BSS_SIZE__ ldx #>__BSS_SIZE__ sta r0L stx r0H lda #<__BSS_RUN__ ldx #>__BSS_RUN__ sta r1L stx r1H jmp ClearRam ������������������������������������������������������������cc65-2.18/libsrc/geos-common/conio/�����������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0017015�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/conio/_scrsize.s�������������������������������������������������������0000664�0000000�0000000�00000002011�13473601511�0021014�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; Screen size variables ; ; 6.3.2001, 17.4.2003 .export xsize, ysize .export screensize .importzp cursor_r, cursor_c .import _cursor .constructor initscrsize .include "geossym.inc" .segment "ONCE" initscrsize: .ifdef __GEOS_CBM__ lda graphMode bpl L1 lda #80 ; 80 columns (more or less) .byte $2c L1: lda #40 ; 40 columns (more or less) sta xsize lda #25 ; something like that for Y size .else lda #70 ; 70 columns (more or less) sta xsize lda #24 ; something like that for Y size .endif sta ysize lda #0 sta cursor_c sta cursor_r jmp _cursor ; home and update cursor .code screensize: ldx xsize ldy ysize rts .segment "INIT" xsize: .res 1 ysize: .res 1 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/conio/cclear.s���������������������������������������������������������0000664�0000000�0000000�00000002646�13473601511�0020442�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 06.03.2002 ; void cclearxy (unsigned char x, unsigned char y, unsigned char length); ; void cclear (unsigned char length); .export _cclearxy, _cclear .import gotoxy, fixcursor .importzp cursor_x, cursor_y, cursor_c .include "jumptab.inc" .include "geossym.inc" _cclearxy: pha ; Save the length jsr gotoxy ; Call this one, will pop params pla ; Restore the length _cclear: cmp #0 ; Is the length zero? beq L9 ; Jump if done tax lda cursor_x ; left start sta r3L lda cursor_x+1 sta r3L+1 lda cursor_y ; level sta r2L clc adc #7 sta r2H txa ; right end clc adc cursor_c sta cursor_c sta r4L ldx #r4 ldy #3 jsr DShiftLeft clc ; one pixel less lda r4L sbc #0 sta r4L lda r4L+1 sbc #0 sta r4L+1 lda curPattern ; store current pattern pha lda #0 ; set pattern to clear jsr SetPattern jsr Rectangle pla jsr SetPattern ; restore pattern jsr fixcursor L9: rts ������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/conio/cgetc.s����������������������������������������������������������0000664�0000000�0000000�00000001242�13473601511�0020265�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 27.10.2001 ; 06.03.2002 ; unsigned char cgetc (void); .export _cgetc .import cursor, _PromptOff .importzp cursor_x, cursor_y .include "jumptab.inc" .include "geossym.inc" _cgetc: ; show cursor if needed lda cursor beq L0 ; prepare cursor lda #7 jsr InitTextPrompt lda cursor_x ldx cursor_x+1 sta stringX stx stringX+1 lda cursor_y sta stringY jsr PromptOn L0: jsr GetNextChar tax beq L0 pha jsr _PromptOff pla ldx #0 rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/conio/chline.s���������������������������������������������������������0000664�0000000�0000000�00000002502�13473601511�0020442�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 06.03.2002 ; void chlinexy (unsigned char x, unsigned char y, unsigned char length); ; void chline (unsigned char length); .export _chlinexy, _chline .import gotoxy, fixcursor .importzp cursor_x, cursor_y, cursor_c .include "jumptab.inc" .include "geossym.inc" _chlinexy: pha ; Save the length jsr gotoxy ; Call this one, will pop params pla ; Restore the length _chline: cmp #0 ; Is the length zero? beq L9 ; Jump if done tax lda cursor_x ; left start sta r3L lda cursor_x+1 sta r3L+1 lda cursor_y ; level clc adc #4 ; in the middle of a cell sta r11L txa ; right end clc adc cursor_c sta cursor_c sta r4L lda #0 sta r4L+1 ldx #r4 ldy #3 jsr DShiftLeft clc ; one pixel less lda r4L sbc #0 sta r4L lda r4L+1 sbc #0 sta r4L+1 lda #%11111111 ; pattern jsr HorizontalLine jsr fixcursor L9: rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/conio/clrscr.s���������������������������������������������������������0000664�0000000�0000000�00000002007�13473601511�0020470�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 27.10.2001, 23.12.2002 ; void clrscr (void); .export _clrscr .import fixcursor .importzp cursor_c, cursor_r .include "jumptab.inc" .include "geossym.inc" .include "const.inc" _clrscr: lda curPattern ; save current pattern pha lda #0 ; set pattern to clear jsr SetPattern ldx #0 stx r3L stx r3H stx r2L stx cursor_c stx cursor_r jsr fixcursor ; home cursor .ifdef __GEOS_CBM__ lda #199 sta r2H lda graphMode bpl L40 lda #>639 ; 80 columns ldx #<639 bne L99 L40: lda #>319 ; 40 columns ldx #<319 L99: .else lda #191 sta r2H lda #>559 ldx #<559 .endif sta r4H stx r4L jsr Rectangle pla jmp SetPattern ; restore pattern �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/conio/cputc.s����������������������������������������������������������0000664�0000000�0000000�00000004257�13473601511�0020327�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 27.10.2001 ; 06.03.2002 ; 25.07.2005 ; void cputcxy (unsigned char x, unsigned char y, char c); ; void cputc (char c); ; TODO: ; TAB (should be implemented) ; other special characters directly from keyboard are unsafe, though some might be ; implemented: ; HOME, UPLINE, ULINEON, ULINEOFF, REV_ON, REV_OFF, BOLDON, ITALICON, OUTLINEON, PLAINTEXT ; and cursor movement, maybe stuff like INSERT too ; ; these must be ignored: ; ESC_GRAPHICS, ESC_RULER, GOTOX, GOTOY, GOTOXY, NEWCARDSET, all 1..8 ; ; note that there are conflicts between control characters and keyboard: ; HOME = KEY_ENTER, KEY_HOME = REV_ON, ; UPLINE = ?, KEY_UPARROW = GOTOY, ... .export _cputcxy, _cputc .import gotoxy, fixcursor .import xsize,ysize .importzp cursor_x, cursor_y, cursor_c, cursor_r .include "const.inc" .include "geossym.inc" .include "jumptab.inc" _cputcxy: pha ; Save C jsr gotoxy ; Set cursor, drop x and y pla ; Restore C ; Plot a character - also used as internal function _cputc: tax ; save character ; some characters 0-31 are not safe for PutChar cmp #$20 bcs L1 cmp #CR beq do_cr cmp #LF beq do_lf cmp #KEY_DELETE bne L0 ldx #BACKSPACE sec bcs L2 L0: rts L1: clc L2: php lda cursor_x sta r11L lda cursor_x+1 sta r11H lda cursor_y clc adc #6 ; 6 pixels down to the baseline sta r1H txa jsr PutChar plp bcs fix_cursor inc cursor_c lda cursor_c cmp xsize ; hit right margin? bne fix_cursor lda #0 ; yes - do cr+lf sta cursor_c do_lf: inc cursor_r lda cursor_r cmp ysize ; hit bottom margin? bne fix_cursor dec cursor_r ; yes - stay in the last line fix_cursor: jmp fixcursor do_cr: lda #0 sta cursor_c beq fix_cursor �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/conio/cvline.s���������������������������������������������������������0000664�0000000�0000000�00000002325�13473601511�0020463�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 06.03.2002 ; void cvlinexy (unsigned char x, unsigned char y, unsigned char length); ; void cvline (unsigned char length); .export _cvlinexy, _cvline .import gotoxy, fixcursor .importzp cursor_x, cursor_y, cursor_r .include "jumptab.inc" .include "geossym.inc" _cvlinexy: pha ; Save the length jsr gotoxy ; Call this one, will pop params pla ; Restore the length _cvline: cmp #0 ; Is the length zero? beq L9 ; Jump if done tax lda cursor_x ; x position clc adc #3 ; in the middle of cell sta r4L lda cursor_x+1 adc #0 sta r4L+1 lda cursor_y ; top start sta r3L txa ; bottom end clc adc cursor_r sta cursor_r asl a asl a asl a clc ; one pixel less sbc #0 sta r3H lda #%11111111 ; pattern jsr VerticalLine jsr fixcursor L9: rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/conio/dummies.s��������������������������������������������������������0000664�0000000�0000000�00000000760�13473601511�0020647�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 27.10.2001 ; unsigned char __fastcall__ textcolor (unsigned char color); ; unsigned char __fastcall__ bgcolor (unsigned char color); ; unsigned char __fastcall__ bordercolor (unsigned char color); ; unsigned char __fastcall__ revers (unsigned char onoff); ; .export _textcolor, _bgcolor, _bordercolor, _revers .import return0 _textcolor = return0 _bgcolor = return0 _bordercolor = return0 _revers = return0 ����������������cc65-2.18/libsrc/geos-common/conio/gotoxy.s���������������������������������������������������������0000664�0000000�0000000�00000001527�13473601511�0020537�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 27.10.2001 ; 06.03.2002 ; void gotox (unsigned char x); ; void gotoy (unsigned char y); ; void gotoxy (unsigned char x, unsigned char y); .export _gotox, _gotoy, gotoxy, _gotoxy, fixcursor .import popa .importzp cursor_x, cursor_y, cursor_c, cursor_r .include "jumptab.inc" _gotox: sta cursor_c jmp fixcursor _gotoy: sta cursor_r jmp fixcursor gotoxy: jsr popa _gotoxy: sta cursor_r jsr popa sta cursor_c ; convert 8x8 x/y coordinates to GEOS hires fixcursor: lda cursor_c sta cursor_x lda #0 sta cursor_x+1 ldx #cursor_x ldy #3 jsr DShiftLeft lda cursor_r asl a asl a asl a sta cursor_y rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/conio/kbhit.s����������������������������������������������������������0000664�0000000�0000000�00000000536�13473601511�0020306�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 27.10.2001 ; unsigned char kbhit (void); .export _kbhit .include "geossym.inc" _kbhit: ldx #0 ; High byte of result lda pressFlag rol ; Bit 7 is new key flag txa ; A = 0 rol rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/conio/where.s����������������������������������������������������������0000664�0000000�0000000�00000000516�13473601511�0020315�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 27.10.2001 ; 06.03.2002 ; 02.01.2003 ; unsigned char wherex (void); ; unsigned char wherey (void); .export _wherex, _wherey .importzp cursor_c, cursor_r _wherex: lda cursor_c ldx #0 rts _wherey: lda cursor_r ldx #0 rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/const.inc��������������������������������������������������������������0000664�0000000�0000000�00000032606�13473601511�0017536�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ;GeosConst - various system constans sorted by function ;reassembled by Maciej 'YTM/Elysium' Witkowiak ;4-2-99, 18-3-99 NULL = 0 FALSE = NULL TRUE = $ff MOUSE_SPRNUM = 0 DISK_DRV_LGH = $0d80 ; ;filetypes ; GEOS NOT_GEOS = 0 BASIC = 1 ASSEMBLY = 2 DATA = 3 SYSTEM = 4 DESK_ACC = 5 APPLICATION = 6 APPL_DATA = 7 FONT = 8 PRINTER = 9 INPUT_DEVICE = 10 DISK_DEVICE = 11 SYSTEM_BOOT = 12 TEMPORARY = 13 AUTO_EXEC = 14 INPUT_128 = 15 NUMFILETYPES = 16 ; structure SEQUENTIAL = 0 VLIR = 1 ; DOS DEL = 0 SEQ = 1 PRG = 2 USR = 3 REL = 4 CBM = 5 ;drivetypes DRV_NULL = 0 DRV_1541 = 1 DRV_1571 = 2 DRV_1581 = 3 DRV_NETWORK = 15 ;various disk REL_FILE_NUM = 9 CMND_FILE_NUM = 15 MAX_CMND_STR = 32 DIR_1581_TRACK = 40 DIR_ACC_CHAN = 13 DIR_TRACK = 18 N_TRACKS = 35 DK_NM_ID_LEN = 18 TRACK = 9 SECTOR = 12 TOTAL_BLOCKS = 664 ;colours BLACK = 0 WHITE = 1 RED = 2 CYAN = 3 PURPLE = 4 GREEN = 5 BLUE = 6 YELLOW = 7 ORANGE = 8 BROWN = 9 LTRED = 10 DKGREY = 11 GREY = 12 MEDGREY = 12 LTGREEN = 13 LTBLUE = 14 LTGREY = 15 ;vic memory banks GRBANK0 = %11 GRBANK1 = %10 GRBANK2 = %01 GRBANK3 = %00 ;screen VIC_X_POS_OFF = 24 VIC_Y_POS_OFF = 50 SC_BYTE_WIDTH = 40 .ifdef __GEOS_CBM__ SC_PIX_HEIGHT = 200 SC_PIX_WIDTH = 320 .else SC_PIX_HEIGHT = 192 SC_PIX_WIDTH = 560 .endif SC_SIZE = 8000 ;128 screen size constants SCREENBYTEWIDTH = 80 SCREENPIXELWIDTH = 640 ;control characters EOF = 0 BACKSPACE = 8 FORWARDSPACE = 9 TAB = 9 LF = 10 HOME = 11 PAGE_BREAK = 12 UPLINE = 12 CR = 13 ULINEON = 14 ULINEOFF = 15 ESC_GRAPHICS = 16 ESC_RULER = 17 REV_ON = 18 REV_OFF = 19 GOTOX = 20 GOTOY = 21 GOTOXY = 22 NEWCARDSET = 23 BOLDON = 24 ITALICON = 25 OUTLINEON = 26 PLAINTEXT = 27 ;keyboard KEY_F1 = 1 KEY_F2 = 2 KEY_F3 = 3 KEY_F4 = 4 KEY_F5 = 5 KEY_F6 = 6 KEY_NOSCRL = 7 KEY_ENTER = 11 KEY_F7 = 14 KEY_F8 = 15 KEY_UP = 16 KEY_DOWN = 17 KEY_HOME = 18 KEY_CLEAR = 19 KEY_LARROW = 20 KEY_UPARROR = 21 KEY_STOP = 22 KEY_RUN = 23 KEY_BPS = 24 KEY_HELP = 25 KEY_ALT = 26 KEY_ESC = 27 KEY_INSERT = 28 KEY_DELETE = 29 KEY_RIGHT = 30 KEY_INVALID = 31 KEY_LEFT = BACKSPACE ;DialogBox ; icons OK = 1 CANCEL = 2 YES = 3 NO = 4 OPEN = 5 DISK = 6 ; commands DBTXTSTR = 11 DBVARSTR = 12 DBGETSTRING = 13 DBSYSOPV = 14 DBGRPHSTR = 15 DBGETFILES = 16 DBOPVEC = 17 DBUSRICON = 18 DB_USR_ROUT = 19 ; tabulation in standard window DBI_X_0 = 1 DBI_X_1 = 9 DBI_X_2 = 17 DBI_Y_0 = 8 DBI_Y_1 = 40 DBI_Y_2 = 72 ; standard window SET_DB_POS = 0 DEF_DB_POS = $80 DEF_DB_TOP = 32 DEF_DB_BOT = 127 DEF_DB_LEFT = 64 DEF_DB_RIGHT = 255 ; text tabulation TXT_LN_1_Y = 16 TXT_LN_2_Y = 32 TXT_LN_3_Y = 48 TXT_LN_4_Y = 64 TXT_LN_5_Y = 80 TXT_LN_X = 16 ; ??? SYSDBI_HEIGHT = 16 SYSDBI_WIDTH = 6 ;GraphicsString - commands MOVEPENTO = 1 LINETO = 2 RECTANGLETO = 3 NEWPATTERN = 5 ESC_PUTSTRING = 6 FRAME_RECTO = 7 PEN_X_DELTA = 8 PEN_Y_DELTA = 9 PEN_XY_DELTA = 10 ;DoMenu - menutypes MENU_ACTION = $00 DYN_SUB_MENU = $40 SUB_MENU = $80 HORIZONTAL = %00000000 VERTICAL = %10000000 ;Errors ANY_FAULT = %11110000 NO_BLOCKS = 1 INV_TRACK = 2 INSUFF_SPACE = 3 FULL_DIRECTORY = 4 FILE_NOT_FOUND = 5 BAD_BAM = 6 UNOPENED_VLIR = 7 INV_RECORD = 8 OUT_OF_RECORDS = 9 STRUCT_MISMAT = 10 BFR_OVERFLOW = 11 CANCEL_ERR = 12 DEV_NOT_FOUND = 13 INCOMPATIBLE = 14 HDR_NOT_THERE = $20 NO_SYNC = $21 DBLK_NOT_THERE = $22 DAT_CHKSUM_ERR = $23 WR_VER_ERR = $25 WR_PR_ON = $26 HDR_CHKSUM_ERR = $27 DSK_ID_MISMAT = $29 BYTE_DEC_ERR = $2e DOS_MISMATCH = $73 ;Offsets ; ??? OFF_INDEX_PTR = 1 ; icons OFF_NM_ICNS = 0 OFF_IC_XMOUSE = 1 OFF_IC_YMOUSE = 3 OFF_PIC_ICON = 0 OFF_X_ICON_POS = 2 OFF_Y_ICON_POS = 3 OFF_WDTH_ICON = 4 OFF_HEIGHT_ICON = 5 OFF_SRV_RT_ICON = 6 OFF_NX_ICON = 8 ; menu OFF_MY_TOP = 0 OFF_MY_BOT = 1 OFF_MX_LEFT = 2 OFF_MX_RIGHT = 4 OFF_NUM_M_ITEMS = 6 OFF_1ST_M_ITEM = 7 ; dialog box OFF_DB_FORM = 0 OFF_DB_TOP = 1 OFF_DB_BOT = 2 OFF_DB_LEFT = 3 OFF_DB_RIGHT = 5 OFF_DB_1STCMD = 7 ; directory ; disk header OFF_TO_BAM = 4 OFF_DISK_NAME = 144 OFF_GS_DTYPE = 189 OFF_OP_TR_SC = 171 OFF_GS_ID = 173 ; dir entry .ifdef __GEOS_CBM__ FRST_FILE_ENTRY = 2 OFF_CFILE_TYPE = 0 OFF_DE_TR_SC = 1 OFF_FNAME = 3 OFF_GHDR_PTR = 19 OFF_GSTRUC_TYPE = 21 OFF_GFILE_TYPE = 22 OFF_YEAR = 23 OFF_SIZE = 28 OFF_NXT_FILE = 32 .else FRST_FILE_ENTRY = 43 OFF_GSTRUC_TYPE = 0 OFF_FNAME = 1 OFF_GFILE_TYPE = 16 OFF_DE_TR_SC = 17 OFF_SIZE = 21 OFF_YEAR = 25 OFF_GHDR_PTR = 31 OFF_NXT_FILE = 39 .endif ; file header O_GHIC_WIDTH = 2 O_GHIC_HEIGHT = 3 O_GHIC_PIC = 4 O_GHCMDR_TYPE = 68 O_GHGEOS_TYPE = 69 O_GHSTR_TYPE = 70 O_GHST_ADDR = 71 O_GHEND_ADDR = 73 O_GHST_VEC = 75 O_GHFNAME = 77 O_128_FLAGS = 96 O_GH_AUTHOR = 97 O_GHP_DISK = 97 O_GHP_FNAME = 117 O_GHINFO_TXT = $a0 ; values for CPU_DATA - C64 memory config RAM_64K = $30 ;64K RAM IO_IN = $35 ;60K RAM, 4K I/O space in KRNL_IO_IN = $36 ;kernal and I/O mapped into memory KRNL_BAS_IO_IN = $37 ;kernal, I/O and basic mapped into memory ;values for config - C128 mmu CIOIN = $7E ;60K RAM, 4K I/O space in CRAM64K = $7F ;64K RAM CKRNLBASIOIN = $40 ;kernal, I/O and basic ROM's mapped into memory CKRNLIOIN = $4E ;Kernal ROM and I/O space mapped in ;values of faultData - pointer position vs. mouseTop/Bottom/Left/Right ; bit numbers OFFTOP_BIT = 7 OFFBOTTOM_BIT = 6 OFFLEFT_BIT = 5 OFFRIGHT_BIT = 4 OFFMENU_BIT = 3 ; masks SET_OFFTOP = %10000000 SET_OFFBOTTOM = %01000000 SET_OFFLEFT = %00100000 SET_OFFRIGHT = %00010000 SET_OFFMENU = %00001000 ;values of currentMode ; bit numbers UNDERLINE_BIT = 7 BOLD_BIT = 6 REVERSE_BIT = 5 ITALIC_BIT = 4 OUTLINE_BIT = 3 SUPERSCRIPT_BIT = 2 SUBSCRIPT_BIT = 1 ; masks SET_UNDERLINE = %10000000 SET_BOLD = %01000000 SET_REVERSE = %00100000 SET_ITALIC = %00010000 SET_OUTLINE = %00001000 SET_SUPERSCRIPT = %00000100 SET_SUBSCRIPT = %00000010 SET_PLAINTEXT = %00000000 ;Process control variable ; bit numbers RUNABLE_BIT = 7 BLOCKED_BIT = 6 FROZEN_BIT = 5 NOTIMER_BIT = 4 ; masks SET_RUNABLE = %10000000 SET_BLOCKED = %01000000 SET_FROZEN = %00100000 SET_NOTIMER = %00010000 ;mouseOn ; bit numbers MOUSEON_BIT = 7 MENUON_BIT = 6 ICONSON_BIT = 5 ; masks SET_MSE_ON = %10000000 SET_MENUON = %01000000 SET_ICONSON = %00100000 ;pressFlag ; bit numbers KEYPRESS_BIT = 7 INPUT_BIT = 6 MOUSE_BIT = 5 ; masks SET_KEYPRESS = %10000000 SET_INPUTCHG = %01000000 SET_MOUSE = %00100000 ;dispBufferOn ST_WRGS_FORE = $20 ST_WR_BACK = $40 ST_WR_FORE = $80 ;alarmSetFlag ALARMMASK = %00000100 ;PutDecimal ;leading zeroes SET_NOSURPRESS = %00000000 SET_SURPRESS = %01000000 ;justification SET_RIGHTJUST = %00000000 SET_LEFTJUST = %10000000 ;icons, menus status flags ST_FLASH = $80 ST_INVERT = $40 ST_LD_AT_ADDR = $01 ST_LD_DATA = $80 ST_PR_DATA = $40 ST_WR_PR = $40 ;??? ADD1_W = $2000 DOUBLE_B = $80 DOUBLE_W = $8000 CLR_SAVE = %01000000 CONSTRAINED = %01000000 UN_CONSTRAINED = %00000000 FG_SAVE = %10000000 FUTURE1 = 7 FUTURE2 = 8 FUTURE3 = 9 FUTURE4 = 10 USELAST = 127 SHORTCUT = 128 ��������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/disk/������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0016640�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/disk/blkalloc.s��������������������������������������������������������0000664�0000000�0000000�00000000663�13473601511�0020614�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 21.12.1999, 2.1.2003 ; char BlkAlloc (struct tr_se output[], int length); .import popax, setoserror .export _BlkAlloc .include "jumptab.inc" .include "diskdrv.inc" .include "geossym.inc" _BlkAlloc: sta r2L stx r2H jsr popax sta r4L stx r4H jsr BlkAlloc jmp setoserror �����������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/disk/calcblksfree.s����������������������������������������������������0000664�0000000�0000000�00000000553�13473601511�0021447�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 21.12.99 ; int CalcBlksFree (void); .import __oserror .export _CalcBlksFree .include "jumptab.inc" .include "diskdrv.inc" .include "geossym.inc" _CalcBlksFree: jsr CalcBlksFree stx __oserror lda r4L ldx r4H rts �����������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/disk/freeblock.s�������������������������������������������������������0000664�0000000�0000000�00000000612�13473601511�0020757�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 21.12.1999, 2.1.2003 ; char FreeBlock (struct tr_se *TS); .import gettrse, setoserror .export _FreeBlock .include "jumptab.inc" .include "diskdrv.inc" .include "geossym.inc" _FreeBlock: jsr gettrse sta r6L stx r6H jsr FreeBlock jmp setoserror ����������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/disk/getblock.s��������������������������������������������������������0000664�0000000�0000000�00000000742�13473601511�0020621�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 21.12.1999, 2.1.2003 ; char GetBlock (struct tr_se *myTS, char *buffer); .import popax, setoserror .import gettrse .export _GetBlock .include "jumptab.inc" .include "diskdrv.inc" .include "geossym.inc" _GetBlock: sta r4L stx r4H jsr popax jsr gettrse sta r1L stx r1H jsr GetBlock jmp setoserror ������������������������������cc65-2.18/libsrc/geos-common/disk/getdirhead.s������������������������������������������������������0000664�0000000�0000000�00000000432�13473601511�0021123�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 21.12.1999, 2.1.2003 ; char GetDirHead (void); .import setoserror .export _GetDirHead .include "jumptab.inc" .include "diskdrv.inc" _GetDirHead: jsr GetDirHead jmp setoserror ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/disk/getptrcurdknm.s���������������������������������������������������0000664�0000000�0000000�00000001267�13473601511�0021723�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 21.12.99 ; void GetPtrCurDkNm (char *curName); ; (fills curName[17] with current disk's name) .importzp ptr4, ptr3 .import __oserror .export _GetPtrCurDkNm .include "jumptab.inc" .include "geossym.inc" _GetPtrCurDkNm: sta ptr3 stx ptr3+1 ldx #ptr4 jsr GetPtrCurDkNm ldy #0 txa bne fin namelp: lda (ptr4),y .ifdef __GEOS_CBM__ cmp #$a0 .else cmp #0 .endif beq fin sta (ptr3),y iny cpy #16 bne namelp fin: lda #0 sta (ptr3),y stx __oserror rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/disk/gettrse.s���������������������������������������������������������0000664�0000000�0000000�00000000363�13473601511�0020503�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 29.1.00 .export gettrse .importzp ptr4 gettrse: sta ptr4 stx ptr4+1 ldy #1 lda (ptr4),y tax dey lda (ptr4),y rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/disk/nxtblkalloc.s�����������������������������������������������������0000664�0000000�0000000�00000001124�13473601511�0021337�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 21.12.1999, 2.1.2003 ; char NxtBlkAlloc (struct tr_se *startTS, struct tr_se output[], int length ); .import popax, setoserror .import gettrse .importzp ptr4 .export _NxtBlkAlloc .include "jumptab.inc" .include "diskdrv.inc" .include "geossym.inc" _NxtBlkAlloc: sta r2L stx r2H jsr popax sta r4L stx r4H jsr popax jsr gettrse sta r3L stx r3H jsr NxtBlkAlloc jmp setoserror ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/disk/opendisk.s��������������������������������������������������������0000664�0000000�0000000�00000000432�13473601511�0020637�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 21.12.1999, 2.1.2003 ; char OpenDisk (void); .import setoserror .export _OpenDisk .include "jumptab.inc" .include "diskdrv.inc" _OpenDisk: jsr OpenDisk jmp setoserror ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/disk/putblock.s��������������������������������������������������������0000664�0000000�0000000�00000000742�13473601511�0020652�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 21.12.1999, 2.1.2003 ; char PutBlock (struct tr_se *myTS, char *buffer); .import popax, setoserror .import gettrse .export _PutBlock .include "jumptab.inc" .include "diskdrv.inc" .include "geossym.inc" _PutBlock: sta r4L stx r4H jsr popax jsr gettrse sta r1L stx r1H jsr PutBlock jmp setoserror ������������������������������cc65-2.18/libsrc/geos-common/disk/putdirhead.s������������������������������������������������������0000664�0000000�0000000�00000000440�13473601511�0021153�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 21.12.99, 2.1.2003 ; char PutDirHead (void); .import setoserror .export _PutDirHead .include "jumptab.inc" .include "diskdrv.inc" _PutDirHead: jsr PutDirHead jmp setoserror ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/disk/setnextfree.s�����������������������������������������������������0000664�0000000�0000000�00000000721�13473601511�0021360�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 21.12.99 ; struct tr_se SetNextFree (struct tr_se *startTS); .import __oserror .import gettrse .export _SetNextFree .include "jumptab.inc" .include "diskdrv.inc" .include "geossym.inc" _SetNextFree: jsr gettrse sta r3L stx r3H jsr SetNextFree stx __oserror lda r3L ldx r3H rts �����������������������������������������������cc65-2.18/libsrc/geos-common/dlgbox/����������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0017165�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/dlgbox/dbget2lines.s���������������������������������������������������0000664�0000000�0000000�00000001110�13473601511�0021544�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 25.12.99 .export DB_get2lines .importzp ptr3,ptr4 .import popax DB_get2lines: sta ptr4 ; fetch line 2 stx ptr4+1 jsr popax sta ptr3 ; fetch line 1 stx ptr3+1 ldx #ptr3 jsr checknull ldx #ptr4 jmp checknull checknull: lda $0,x ora $1,x bne cn_end lda #<nullstring sta $0,x lda #>nullstring sta $1,x cn_end: rts .rodata nullstring: .byte 0 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/dlgbox/dlgboxfileselect.s����������������������������������������������0000664�0000000�0000000�00000002220�13473601511�0022664�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 25.12.99 ; char DlgBoxFileSelect (char *class, char ftype, char *fname); .export _DlgBoxFileSelect .import popa, popax .import _DoDlgBox .include "jumptab.inc" .include "diskdrv.inc" .include "geossym.inc" .include "geosmac.inc" .include "const.inc" _DlgBoxFileSelect: sta tmp_r5 stx tmp_r5+1 jsr popa sta tmp_r7L jsr popax sta tmp_r10 stx tmp_r10+1 DB_FS_reload: MoveW tmp_r5, r5 MoveW tmp_r10, r10 MoveB tmp_r7L, r7L lda #<paramStrFileSelect ldx #>paramStrFileSelect jsr _DoDlgBox cmp #DISK bne DB_FS_Fin jsr OpenDisk txa beq DB_FS_reload DB_FS_Fin: rts .rodata paramStrFileSelect: .byte DEF_DB_POS | 1 .byte DBGETFILES, 4, 4 .byte OPEN, DBI_X_2, DBI_Y_0+16 .byte DISK, DBI_X_2, DBI_Y_0+32+1 .byte CANCEL, DBI_X_2, DBI_Y_0+64+3 .byte NULL .bss tmp_r5: .res 2 tmp_r7L: .res 1 tmp_r10: .res 2 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/dlgbox/dlgboxgetstring.s�����������������������������������������������0000664�0000000�0000000�00000001553�13473601511�0022563�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 25.12.99 ; char DlgBoxGetString (char *string, char strlen, char *line1,char *line2); .export _DlgBoxGetString .import DB_get2lines, _DoDlgBox .importzp ptr2, ptr3, ptr4 .import popa, popax .include "geossym.inc" .include "const.inc" _DlgBoxGetString: jsr DB_get2lines jsr popa sta DB_strlen jsr popax sta ptr2 stx ptr2+1 lda #<paramStrGetString ldx #>paramStrGetString jmp _DoDlgBox .data paramStrGetString: .byte DEF_DB_POS | 1 .byte DBVARSTR, TXT_LN_X, TXT_LN_1_Y, ptr3 .byte DBVARSTR, TXT_LN_X, TXT_LN_2_Y, ptr4 .byte DBGETSTRING, TXT_LN_X, TXT_LN_3_Y, ptr2 DB_strlen: .byte 17 .byte CANCEL, DBI_X_2, DBI_Y_2 .byte NULL �����������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/dlgbox/dlgboxok.s������������������������������������������������������0000664�0000000�0000000�00000001117�13473601511�0021162�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 25.12.99 ; char DlgBoxOk (char *line1,char *line2); .export _DlgBoxOk .import DB_get2lines, _DoDlgBox .importzp ptr3, ptr4 .include "geossym.inc" .include "const.inc" _DlgBoxOk: jsr DB_get2lines lda #<paramStrOk ldx #>paramStrOk jmp _DoDlgBox .rodata paramStrOk: .byte DEF_DB_POS | 1 .byte DBVARSTR, TXT_LN_X, TXT_LN_2_Y, ptr3 .byte DBVARSTR, TXT_LN_X, TXT_LN_3_Y, ptr4 .byte OK, DBI_X_0, DBI_Y_2 .byte NULL �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/dlgbox/dlgboxokcancel.s������������������������������������������������0000664�0000000�0000000�00000001232�13473601511�0022326�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 25.12.99 ; char DlgBoxOkCancel (char *line1,char *line2); .export _DlgBoxOkCancel .import DB_get2lines, _DoDlgBox .importzp ptr3, ptr4 .include "geossym.inc" .include "const.inc" _DlgBoxOkCancel: jsr DB_get2lines lda #<paramStrOkCancel ldx #>paramStrOkCancel jmp _DoDlgBox .rodata paramStrOkCancel: .byte DEF_DB_POS | 1 .byte DBVARSTR, TXT_LN_X, TXT_LN_2_Y, ptr3 .byte DBVARSTR, TXT_LN_X, TXT_LN_3_Y, ptr4 .byte OK, DBI_X_0, DBI_Y_2 .byte CANCEL, DBI_X_2, DBI_Y_2 .byte NULL ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/dlgbox/dlgboxyesno.s���������������������������������������������������0000664�0000000�0000000�00000001205�13473601511�0021704�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 25.12.99 ; char DlgBoxYesNo (char *line1,char *line2); .export _DlgBoxYesNo .import DB_get2lines, _DoDlgBox .importzp ptr3, ptr4 .include "geossym.inc" .include "const.inc" _DlgBoxYesNo: jsr DB_get2lines lda #<paramStrYesNo ldx #>paramStrYesNo jmp _DoDlgBox .rodata paramStrYesNo: .byte DEF_DB_POS | 1 .byte DBVARSTR, TXT_LN_X, TXT_LN_2_Y, ptr3 .byte DBVARSTR, TXT_LN_X, TXT_LN_3_Y, ptr4 .byte YES, DBI_X_0, DBI_Y_2 .byte NO, DBI_X_2, DBI_Y_2 .byte NULL �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/dlgbox/dodlgbox.s������������������������������������������������������0000664�0000000�0000000�00000000476�13473601511�0021162�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 25.12.1999, 2.1.2003 ; char DoDlgBox (char *myParamString); .export _DoDlgBox .include "jumptab.inc" .include "geossym.inc" _DoDlgBox: sta r0L stx r0H jsr DoDlgBox ldx #0 lda r0L rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/dlgbox/messagebox.c����������������������������������������������������0000664�0000000�0000000�00000003341�13473601511�0021467�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** char MessageBox (char mode, const char *format, ...) ** ** Maciej 'YTM/Elysium' Witkowiak, 17.08.2003 ** */ #include <geos.h> #include <stdio.h> void _mbprintout(void); static const dlgBoxStr _mbdlg_EMPTY = { DB_DEFPOS(1), DB_OPVEC(&RstrFrmDialogue), DB_USRROUT(&_mbprintout), DB_END, }; static const dlgBoxStr _mbdlg_OK = { DB_DEFPOS(1), DB_USRROUT(&_mbprintout), DB_ICON(OK, DBI_X_1, DBI_Y_2), DB_END, }; static const dlgBoxStr _mbdlg_OKCANCEL = { DB_DEFPOS(1), DB_USRROUT(&_mbprintout), DB_ICON(OK, DBI_X_0, DBI_Y_2), DB_ICON(CANCEL, DBI_X_2, DBI_Y_2), DB_END, }; static const dlgBoxStr _mbdlg_YESNO = { DB_DEFPOS(1), DB_USRROUT(&_mbprintout), DB_ICON(YES, DBI_X_0, DBI_Y_2), DB_ICON(NO, DBI_X_2, DBI_Y_2), DB_END, }; static const dlgBoxStr * const _mbboxes[] = { &_mbdlg_EMPTY, &_mbdlg_OK, &_mbdlg_OKCANCEL, &_mbdlg_YESNO }; static char _mbbuffer[256]; char MessageBox(char mode, const char *format, ...) { register char *buf; va_list ap; /* first format out things */ va_start(ap, format); vsprintf(_mbbuffer, format, ap); va_end(ap); /* replace LFs by CRs */ buf = &_mbbuffer[0]; while (*buf) { if (*buf==LF) *buf=CR; ++buf; } /* validate mode */ if (mode>=MB_LAST) mode = MB_EMPTY; return DoDlgBox(_mbboxes[mode]); } void _mbprintout(void) { UseSystemFont(); curWindow.top = DEF_DB_TOP; curWindow.left = DEF_DB_LEFT+10; curWindow.right = DEF_DB_RIGHT-10; curWindow.bot = DEF_DB_BOT; PutString(_mbbuffer, DEF_DB_TOP+10+curFontDesc.height, DEF_DB_LEFT+10 ); } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/dlgbox/rstrfrmdialogue.s�����������������������������������������������0000664�0000000�0000000�00000000310�13473601511�0022554�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 25.12.99 ; char RstrFrmDialogue (void); .export _RstrFrmDialogue .include "jumptab.inc" _RstrFrmDialogue = RstrFrmDialogue ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/drivers/���������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0017364�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/drivers/fio_module.s���������������������������������������������������0000664�0000000�0000000�00000012157�13473601511�0021700�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Low level file I/O routines, ONLY for module loading OR sth similar ; ; Maciej 'YTM/Elysium' Witkowiak <ytm@elysium.pl> ; 25.12.2002 ; ; only ONE opened file at a time, only O_RDONLY flag ; int open (const char* name, int flags, ...); /* May take a mode argument */ ; int __fastcall__ close (int fd); ; int __fastcall__ read (int fd, void* buf, unsigned count); FILEDES = 3 ; first free to use file descriptor .importzp ptr1, ptr2, ptr3, tmp1 .import addysp, popax, popptr1 .import __oserror .import _FindFile, _ReadByte .export _open, _close, _read .include "geossym.inc" .include "const.inc" .include "errno.inc" .include "fcntl.inc" _open: cpy #4 ; correct # of arguments (bytes)? beq @parmok ; parameter count ok tya ; parm count < 4 shouldn't be needed to be... sec ; ...checked (it generates a c compiler warning) sbc #4 tay jsr addysp ; fix stack, throw away unused parameters ; Parameters ok. Pop the flags and save them into tmp3 @parmok: jsr popax ; Get flags sta tmp1 jsr popptr1 ; Get name lda filedesc ; is there a file already open? bne @alreadyopen lda tmp1 ; check open mode and #(O_RDWR | O_CREAT) cmp #O_RDONLY ; only O_RDONLY is valid bne @badmode lda ptr1 ldx ptr1+1 jsr _FindFile ; try to find the file tax bne @oserror lda dirEntryBuf + OFF_DE_TR_SC ; tr&se for ReadByte (r1) sta f_track lda dirEntryBuf + OFF_DE_TR_SC + 1 sta f_sector lda #<diskBlkBuf ; buffer for ReadByte (r4) sta f_buffer lda #>diskBlkBuf sta f_buffer+1 ldx #0 ; offset for ReadByte (r5) stx f_offset stx f_offset+1 lda #0 ; clear errors sta __oserror jsr __seterrno lda #FILEDES ; return fd sta filedesc rts @badmode: lda #EINVAL ; invalid parameters - invalid open mode .byte $2c ; skip @alreadyopen: lda #EMFILE ; too many opened files (there can be only one) jmp __directerrno ; set errno, clear oserror, return -1 @oserror: jmp __mappederrno ; set platform error code, return -1 _close: lda #0 sta __oserror jsr __seterrno ; clear errors lda #0 ; clear fd sta filedesc tax rts _read: ; a/x - number of bytes ; popax - buffer ptr ; popax - fd, must be == to the above one ; return -1+__oserror or number of bytes read eor #$ff sta ptr1 txa eor #$ff sta ptr1+1 ; -(# of bytes to read)-1 jsr popax sta ptr2 stx ptr2+1 ; buffer ptr jsr popax cmp #FILEDES ; lo-byte == FILEDES bne @filenotopen txa ; hi-byte == 0 beq @fileok ; fd must be == FILEDES @filenotopen: lda #EBADF jmp __directerrno ; Sets _errno, clears _oserror, returns -1 @fileok: lda #0 sta ptr3 sta ptr3+1 ; put 0 into ptr3 (number of bytes read) sta __oserror ; clear error flags jsr __seterrno lda f_track ; restore stuff for ReadByte ldx f_sector sta r1L stx r1H lda f_buffer ldx f_buffer+1 sta r4L stx r4H lda f_offset ldx f_offset+1 sta r5L stx r5H clc bcc @L3 ; branch always @L0: jsr _ReadByte ldy #0 ; store the byte sta (ptr2),y inc ptr2 ; increment target address bne @L1 inc ptr2+1 @L1: inc ptr3 ; increment byte count bne @L2 inc ptr3+1 @L2: lda __oserror ; was there error ? beq @L3 cmp #BFR_OVERFLOW ; EOF? beq @done ; yes, we're done jmp __mappederrno ; no, we're screwed @L3: inc ptr1 ; decrement the count bne @L0 inc ptr1+1 bne @L0 @done: lda r1L ; preserve data for ReadByte ldx r1H sta f_track stx f_sector lda r4L ldx r4H sta f_buffer stx f_buffer+1 lda r5L ldx r5H sta f_offset stx f_offset+1 lda ptr3 ; return byte count ldx ptr3+1 rts .bss filedesc: .res 1 ; file open flag - 0 (no file opened) or 1 f_track: .res 1 ; values preserved for ReadByte f_sector: .res 1 f_offset: .res 2 f_buffer: .res 2 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/drivers/geos-stdmou.s��������������������������������������������������0000664�0000000�0000000�00000010346�13473601511�0022022�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 2.7.2001 ; ; Driver for GEOS standard input device interface ; .export _mouse_init, _mouse_done .export _mouse_hide, _mouse_show .export _mouse_box .export _mouse_pos, _mouse_info .export _mouse_move, _mouse_buttons .import popsreg, addysp1 .importzp sp, sreg, ptr1 .include "const.inc" .include "jumptab.inc" .include "geossym.inc" ; -------------------------------------------------------------------------- ; ; unsigned char __fastcall__ mouse_init (unsigned char type); ; _mouse_init: jsr StartMouseMode jsr MouseOff lda #0 sta mouseTop sta mouseLeft sta mouseLeft+1 .ifdef __GEOS_CBM__ lda #199 sta mouseBottom lda graphMode bpl _mse_screen320 lda #<639 ; 80 columns on C128 ldx #>639 bne _mse_storex _mse_screen320: lda #<319 ; 40 columns on C64/C128 ldx #>319 _mse_storex: .else lda #191 sta mouseBottom lda #<559 ldx #>559 .endif sta mouseRight stx mouseRight+1 _mse_initend: lda #0 tax ; -------------------------------------------------------------------------- ; ; void mouse_done (void); ; _mouse_done: rts ; -------------------------------------------------------------------------- ; ; void mouse_hide (void); ; _mouse_hide = MouseOff ; -------------------------------------------------------------------------- ; ; void mouse_show (void); ; _mouse_show = MouseUp ; -------------------------------------------------------------------------- ; ; void __fastcall__ mouse_box (int minx, int miny, int maxx, int maxy); ; _mouse_box: ldy #0 ; Stack offset sta mouseBottom lda (sp),y sta mouseRight iny lda (sp),y sta mouseRight+1 ; maxx iny lda (sp),y sta mouseTop iny ; Skip high byte iny lda (sp),y sta mouseLeft iny lda (sp),y sta mouseLeft+1 ; minx jmp addysp1 ; Drop params, return ; -------------------------------------------------------------------------- ; ; void __fastcall__ mouse_pos (struct mouse_pos* pos); ; /* Return the current mouse position */ ; _mouse_pos: sta ptr1 stx ptr1+1 ; Remember the argument pointer ldy #0 ; Structure offset php sei ; Disable interrupts lda mouseXPos ; Transfer the position sta (ptr1),y lda mouseXPos+1 iny sta (ptr1),y lda mouseYPos iny sta (ptr1),y lda #$00 iny sta (ptr1),y plp ; Reenable interrupts rts ; Done ; -------------------------------------------------------------------------- ; ; void __fastcall__ mouse_info (struct mouse_info* info); ; /* Return the state of the mouse buttons and the position of the mouse */ ; _mouse_info: ; We're cheating here to keep the code smaller: The first fields of the ; mouse_info struct are identical to the mouse_pos struct, so we will just ; call _mouse_pos to initialize the struct pointer and fill the position ; fields. jsr _mouse_pos ; Fill in the button state jsr _mouse_buttons ; Will not touch ptr1 iny sta (ptr1),y rts ; -------------------------------------------------------------------------- ; ; void __fastcall__ mouse_move (int x, int y); ; _mouse_move: jsr popsreg ; Get X php sei ; Disable interrupts sta mouseYPos lda sreg ldx sreg+1 sta mouseXPos stx mouseXPos+1 plp ; Enable interrupts rts ; -------------------------------------------------------------------------- ; ; unsigned char mouse_buttons (void); ; _mouse_buttons: ldx #0 lda pressFlag and #SET_MOUSE lsr rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/drivers/mcbdefault.s���������������������������������������������������0000664�0000000�0000000�00000003722�13473601511�0021662�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Mouse callbacks for GEOS. ; ; GEOS has a built-in mouse architecture. Half of this file does nothing ; -- it exists merely to allow portable programs to link and run. ; ; 2.7.2001, Maciej 'YTM/Elysium' Witkowiak ; 2004-03-20, Ullrich von Bassewitz ; 2004-09-24, Greg King ; ; .constructor init_pointer .export _mouse_def_callbacks ; .include "mouse-kernel.inc" ; .include "const.inc" ; .include "geossym.inc" .include "jumptab.inc" ; .macpack generic ; The functions below must be interrupt-safe, ; because they might be called from an interrupt-handler. ; -------------------------------------------------------------------------- ; Hide the mouse pointer. Always called with interrupts disabled. hide := MouseOff ; -------------------------------------------------------------------------- ; Show the mouse pointer. Always called with interrupts disabled. show := MouseUp ; -------------------------------------------------------------------------- ; Prepare to move the mouse pointer. Always called with interrupts disabled. prep: ; Fall through ; -------------------------------------------------------------------------- ; Draw the mouse pointer. Always called with interrupts disabled. draw: ; Fall through ; -------------------------------------------------------------------------- ; Move the mouse pointer X position to the value in .XA. Always called with ; interrupts disabled. movex: ; Fall through ; -------------------------------------------------------------------------- ; Move the mouse pointer Y position to the value in .XA. Always called with ; interrupts disabled. movey: rts ; -------------------------------------------------------------------------- ; Callback structure .rodata _mouse_def_callbacks: .addr hide .addr show .addr prep .addr draw .addr movex .addr movey ����������������������������������������������cc65-2.18/libsrc/geos-common/drivers/mouse_stddrv.s�������������������������������������������������0000664�0000000�0000000�00000000277�13473601511�0022274�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Name of the standard mouse driver ; ; 2010-01-25, Greg King ; ; const char mouse_stddrv[]; ; .export _mouse_stddrv .rodata _mouse_stddrv: .asciiz "geos-stdmou.mou" ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/file/������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0016625�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/file/appendrecord.s����������������������������������������������������0000664�0000000�0000000�00000000454�13473601511�0021462�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 25.12.1999, 2.1.2003 ; char AppendRecord (void); .import setoserror .export _AppendRecord .include "jumptab.inc" .include "diskdrv.inc" _AppendRecord: jsr AppendRecord jmp setoserror ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/file/closerecordfile.s�������������������������������������������������0000664�0000000�0000000�00000000467�13473601511�0022164�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 25.12.1999, 2.1.2003 ; char CloseRecordFile (void); .import setoserror .export _CloseRecordFile .include "jumptab.inc" .include "diskdrv.inc" _CloseRecordFile: jsr CloseRecordFile jmp setoserror ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/file/deletefile.s������������������������������������������������������0000664�0000000�0000000�00000000556�13473601511�0021121�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 25.12.1999, 2.1.2003 ; char DeleteFile (char *myName); .import setoserror .export _DeleteFile .include "jumptab.inc" .include "diskdrv.inc" .include "geossym.inc" _DeleteFile: sta r0L stx r0H jsr DeleteFile jmp setoserror ��������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/file/deleterecord.s����������������������������������������������������0000664�0000000�0000000�00000000516�13473601511�0021454�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 25.12.1999, 2.1.2003 ; char DeleteRecord (void); .import setoserror .export _DeleteRecord .include "jumptab.inc" .include "diskdrv.inc" .include "geossym.inc" _DeleteRecord: jsr DeleteRecord jmp setoserror ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/file/findfile.s��������������������������������������������������������0000664�0000000�0000000�00000000546�13473601511�0020576�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 25.12.1999, 2.1.2003 ; char FindFile (char *myName); .import setoserror .export _FindFile .include "jumptab.inc" .include "diskdrv.inc" .include "geossym.inc" _FindFile: sta r6L stx r6H jsr FindFile jmp setoserror ����������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/file/findftypes.s������������������������������������������������������0000664�0000000�0000000�00000001244�13473601511�0021165�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 25.12.1999, 2.1.2003 ; char FindFTypes (char *buffer, char fileType, char fileMax, char *Class); .export _FindFTypes .import popax, popa, setoserror .include "jumptab.inc" .include "diskdrv.inc" .include "geossym.inc" _FindFTypes: sta r10L stx r10H jsr popa sta r7H sta tmpFileMax jsr popa sta r7L jsr popax sta r6L stx r6H jsr FindFTypes jsr setoserror ; return (fileMax - r7H) lda tmpFileMax sec sbc r7H rts .bss tmpFileMax: .res 1 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/file/freefile.s��������������������������������������������������������0000664�0000000�0000000�00000000556�13473601511�0020600�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 25.12.1999, 2.1.2003 ; char FreeFile (struct trse myTrSe[]); .import setoserror .export _FreeFile .include "jumptab.inc" .include "diskdrv.inc" .include "geossym.inc" _FreeFile: sta r9L stx r9H jsr FreeFile jmp setoserror ��������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/file/get1stdirentry.s��������������������������������������������������0000664�0000000�0000000�00000000527�13473601511�0022005�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 26.10.99 ; struct filehandle* Get1stDirEntry (void); .import __oserror .export _Get1stDirEntry .include "diskdrv.inc" .include "geossym.inc" _Get1stDirEntry: jsr Get1stDirEntry stx __oserror lda r5L ldx r5H rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/file/getfhdrinfo.s�����������������������������������������������������0000664�0000000�0000000�00000000577�13473601511�0021321�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 25.12.1999, 2.1.2003 ; char GetFHdrInfo (struct filehandle *myFile); .import setoserror .export _GetFHdrInfo .include "jumptab.inc" .include "diskdrv.inc" .include "geossym.inc" _GetFHdrInfo: sta r9L stx r9H jsr GetFHdrInfo jmp setoserror ���������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/file/getfile.s���������������������������������������������������������0000664�0000000�0000000�00000001223�13473601511�0020426�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 4.4.2003 ; char __fastcall__ GetFile(char flag, const char *fname, const char *loadaddr, const char *datadname, char *datafname); .export _GetFile .import popa, popax, setoserror .include "jumptab.inc" .include "diskdrv.inc" .include "geossym.inc" _GetFile: sta r3L stx r3H jsr popax sta r2L stx r2H jsr popax sta r7L stx r7H jsr popax sta r6L stx r6H jsr popa sta r0L lda #0 sta r10L jsr GetFile jmp setoserror �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/file/getnxtdirentry.s��������������������������������������������������0000664�0000000�0000000�00000000527�13473601511�0022107�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 26.10.99 ; struct filehandle* GetNxtDirEntry (void); .import __oserror .export _GetNxtDirEntry .include "diskdrv.inc" .include "geossym.inc" _GetNxtDirEntry: jsr GetNxtDirEntry stx __oserror lda r5L ldx r5H rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/file/insertrecord.s����������������������������������������������������0000664�0000000�0000000�00000000443�13473601511�0021515�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 25.12.1999, 2.1.2003 ; char InsertRecord (void); .import setoserror .export _InsertRecord .include "jumptab.inc" .include "diskdrv.inc" _InsertRecord: jsr InsertRecord jmp setoserror �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/file/nextrecord.s������������������������������������������������������0000664�0000000�0000000�00000000433�13473601511�0021166�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 25.12.1999, 2.1.2003 ; char NextRecord (void); .import setoserror .export _NextRecord .include "jumptab.inc" .include "diskdrv.inc" _NextRecord: jsr NextRecord jmp setoserror �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/file/openrecordfile.s��������������������������������������������������0000664�0000000�0000000�00000000576�13473601511�0022021�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 25.12.1999, 2.1.2003 ; char OpenRecordFile (char *myName); .import setoserror .export _OpenRecordFile .include "jumptab.inc" .include "diskdrv.inc" .include "geossym.inc" _OpenRecordFile: sta r0L stx r0H jsr OpenRecordFile jmp setoserror ����������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/file/pointrecord.s�����������������������������������������������������0000664�0000000�0000000�00000000461�13473601511�0021342�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 25.12.1999, 2.1.2003 ; char PointRecord (char recordNum); .import setoserror .export _PointRecord .include "jumptab.inc" .include "diskdrv.inc" _PointRecord: jsr PointRecord jmp setoserror ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/file/previousrecord.s��������������������������������������������������0000664�0000000�0000000�00000000453�13473601511�0022066�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 25.12.1999, 2.1.2003 ; char PreviousRecord (void); .import setoserror .export _PreviousRecord .include "jumptab.inc" .include "diskdrv.inc" _PreviousRecord: jsr PreviousRecord jmp setoserror ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/file/readbyte.s��������������������������������������������������������0000664�0000000�0000000�00000000411�13473601511�0020604�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 25.12.1999, 2.1.2003 ; char ReadByte (void); .import __oserror .export _ReadByte .include "jumptab.inc" _ReadByte: jsr ReadByte stx __oserror ldx #0 rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/file/readfile.s��������������������������������������������������������0000664�0000000�0000000�00000001041�13473601511�0020560�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 25.12.1999, 2.1.2003 ; char ReadFile (struct tr_se *myTS, char *buffer, int length); .export _ReadFile .import popax, setoserror .import gettrse .include "jumptab.inc" .include "diskdrv.inc" .include "geossym.inc" _ReadFile: sta r2L stx r2H jsr popax sta r7L stx r7H jsr popax jsr gettrse sta r1L stx r1H jsr ReadFile jmp setoserror �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/file/readrecord.s������������������������������������������������������0000664�0000000�0000000�00000000663�13473601511�0021130�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 25.12.1999, 2.1.2003 ; char ReadRecord (char *buffer, int length); .export _ReadRecord .import popax, setoserror .include "jumptab.inc" .include "diskdrv.inc" .include "geossym.inc" _ReadRecord: sta r2L stx r2H jsr popax sta r7L stx r7H jsr ReadRecord jmp setoserror �����������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/file/renamefile.s������������������������������������������������������0000664�0000000�0000000�00000000647�13473601511�0021127�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 25.12.1999, 2.1.2003 ; char RenameFile (char *old, char *new); .export _RenameFile .import popax, setoserror .include "jumptab.inc" .include "diskdrv.inc" .include "geossym.inc" _RenameFile: sta r0L stx r0H jsr popax sta r6L stx r6H jsr RenameFile jmp setoserror �����������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/file/savefile.s��������������������������������������������������������0000664�0000000�0000000�00000000663�13473601511�0020614�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 25.12.1999, 2.1.2003 ; char SaveFile (char skip, struct fileheader *myHeader); .import setoserror .import popa .export _SaveFile .include "jumptab.inc" .include "diskdrv.inc" .include "geossym.inc" _SaveFile: sta r9L stx r9H jsr popa sta r10L jsr SaveFile jmp setoserror �����������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/file/sysremove.s�������������������������������������������������������0000664�0000000�0000000�00000000547�13473601511�0021053�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 19.07.2005 ; unsigned char __fastcall__ _sysremove (const char* name); .export __sysremove .include "jumptab.inc" .include "diskdrv.inc" .include "geossym.inc" __sysremove: sta r0L stx r0H jsr DeleteFile txa ldx #0 rts ���������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/file/sysrename.s�������������������������������������������������������0000664�0000000�0000000�00000000712�13473601511�0021017�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 19.07.2005 ; unsigned char __fastcall__ _sysrename (const char* oldname, const char* newname); .export __sysrename .import popax .include "jumptab.inc" .include "diskdrv.inc" .include "geossym.inc" __sysrename: sta r0L stx r0H jsr popax sta r6L stx r6H jsr RenameFile txa ldx #0 rts ������������������������������������������������������cc65-2.18/libsrc/geos-common/file/updaterecordfile.s������������������������������������������������0000664�0000000�0000000�00000000463�13473601511�0022335�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 25.12.1999, 2.1.2003 ; char UpdateRecordFile (void); .import setoserror .export _UpdateRecordFile .include "jumptab.inc" .include "diskdrv.inc" _UpdateRecordFile: jsr UpdateRecordFile jmp setoserror �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/file/writerecord.s�����������������������������������������������������0000664�0000000�0000000�00000000667�13473601511�0021353�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 25.12.1999, 2.1.2003 ; char WriteRecord (char *buffer, int length); .export _WriteRecord .import popax, setoserror .include "jumptab.inc" .include "diskdrv.inc" .include "geossym.inc" _WriteRecord: sta r2L stx r2H jsr popax sta r7L stx r7H jsr WriteRecord jmp setoserror �������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/geosmac.inc������������������������������������������������������������0000664�0000000�0000000�00000015403�13473601511�0020022�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ;GEOS macros ;reassembled for 6502TASM/MMS by Maciej 'YTM/Elysium' Witkowiak ;4-2-99 ;28-6-99 - ca65 port ;macro 'sub' renamed to 'ssub' due to 65816 mnemonics ;------------------------------------------------------------------------- .macro LoadB dest, value lda #value sta dest .endmacro ;------------------------------------------------------------------------- .macro LoadW dest, value LoadB dest+1, >(value) LoadB dest+0, <(value) .endmacro ;------------------------------------------------------------------------- .macro MoveB source, dest lda source sta dest .endmacro ;------------------------------------------------------------------------- .macro MoveW source, dest MoveB source+1, dest+1 MoveB source+0, dest+0 .endmacro ;------------------------------------------------------------------------- .macro add source clc adc source .endmacro ;------------------------------------------------------------------------- .macro AddB source, dest lda source add dest sta dest .endmacro ;------------------------------------------------------------------------- .macro AddW source, dest AddB source+0, dest+0 lda source+1 adc dest+1 sta dest+1 .endmacro ;------------------------------------------------------------------------- .macro AddVB value, dest lda dest clc adc #(value) sta dest .endmacro ;------------------------------------------------------------------------- .macro AddVW value, dest .local Skip AddVB <(value), dest+0 .if (>(value))=0 bcc Skip inc dest+1 .else lda #>(value) adc dest+1 sta dest+1 .endif Skip: .endmacro ;------------------------------------------------------------------------- .macro ssub source sec sbc source .endmacro ;------------------------------------------------------------------------- .macro SubB source, dest lda dest ssub source sta dest .endmacro ;------------------------------------------------------------------------- .macro SubW source, dest SubB source+0, dest+0 lda dest+1 sbc source+1 sta dest+1 .endmacro ;------------------------------------------------------------------------- .macro SubVW value, dest sec lda dest+0 sbc #<(value) sta dest+0 lda dest+1 sbc #>(value) sta dest+1 .endmacro ;------------------------------------------------------------------------- .macro CmpB source, dest lda source cmp dest .endmacro ;------------------------------------------------------------------------- .macro CmpBI source, immed lda source cmp #(immed) .endmacro ;------------------------------------------------------------------------- .macro CmpW source, dest .local Skip CmpB source+1, dest+1 bne Skip CmpB source+0, dest+0 Skip: .endmacro ;------------------------------------------------------------------------- .macro CmpWI source, immed .local Skip CmpBI source+1, >(immed) bne Skip CmpBI source+0, <(immed) Skip: .endmacro ;------------------------------------------------------------------------- .macro PushB source lda source pha .endmacro ;------------------------------------------------------------------------- .macro PushW source PushB source+1 PushB source+0 .endmacro ;------------------------------------------------------------------------- .macro PopB dest pla sta dest .endmacro ;------------------------------------------------------------------------- .macro PopW dest PopB dest+0 PopB dest+1 .endmacro ;------------------------------------------------------------------------- .macro smb bitNumber, dest pha lda #(1 << bitNumber) ora dest sta dest pla .endmacro ;------------------------------------------------------------------------- .macro smbf bitNumber, dest lda #(1 << bitNumber) ora dest sta dest .endmacro ;------------------------------------------------------------------------- .macro rmb bitNumber, dest pha lda #(1 << bitNumber) ^ $ff and dest sta dest pla .endmacro ;------------------------------------------------------------------------- .macro rmbf bitNumber, dest lda #(1 << bitNumber) ^ $ff and dest sta dest .endmacro ;------------------------------------------------------------------------- .macro bbs bitNumber, source, addr .local Skip php pha lda source and #(1 << bitNumber) beq Skip pla plp bra addr Skip: pla plp .endmacro ;------------------------------------------------------------------------- .macro bbsf bitNumber, source, addr .if bitNumber=7 bit source bmi addr .else .if bitNumber=6 bit source bvs addr .else lda source and #(1 << bitNumber) bne addr .endif .endif .endmacro ;------------------------------------------------------------------------- .macro bbr bitNumber, source, addr .local Skip php pha lda source and #(1 << bitNumber) bne Skip pla plp bra addr Skip: pla plp .endmacro ;------------------------------------------------------------------------- .macro bbrf bitNumber, source, addr .if bitNumber=7 bit source bpl addr .else .if bitNumber=6 bit source bvc addr .else lda source and #(1 << bitNumber) beq addr .endif .endif .endmacro ;------------------------------------------------------------------------- ;03.03.99 by Maciej Witkowiak ;------------------------------------------------------------------------- .macro addv value clc adc #(value) .endmacro ;------------------------------------------------------------------------- .macro subv value sec sbc #(value) .endmacro ;------------------------------------------------------------------------- .macro bnex addr txa bne addr .endmacro ;------------------------------------------------------------------------- .macro beqx addr txa beq addr .endmacro ;------------------------------------------------------------------------- �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/graph/�����������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0017007�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/graph/bitmapclip.s�����������������������������������������������������0000664�0000000�0000000�00000000741�13473601511�0021321�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 21.12.99 ; void BitmapClip (char skipl, char skipr, int skipy, struct iconpic *myGfx); .import popa, popax .import BitmapRegs .export _BitmapClip .include "jumptab.inc" .include "geossym.inc" _BitmapClip: jsr BitmapRegs jsr popax sta r12L stx r12H jsr popa sta r11H jsr popa sta r11L jmp BitmapClip �������������������������������cc65-2.18/libsrc/geos-common/graph/bitmapregs.s�����������������������������������������������������0000664�0000000�0000000�00000000537�13473601511�0021335�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 21.12.99 .importzp ptr4 .export BitmapRegs .include "geossym.inc" BitmapRegs: ; a/x is a struct iconpic* sta ptr4 stx ptr4+1 ldy #0 bmpLp: lda (ptr4),y sta r0L,y iny cpy #6 bne bmpLp rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/graph/bitmapup.s�������������������������������������������������������0000664�0000000�0000000�00000000365�13473601511�0021020�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 21.12.99 ; void BitmapUp (struct iconpic *myGfx); .import BitmapRegs .export _BitmapUp .include "jumptab.inc" _BitmapUp: jsr BitmapRegs jmp BitmapUp ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/graph/bitotherclip.s���������������������������������������������������0000664�0000000�0000000�00000001550�13473601511�0021664�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 21.12.99 ; void BitOtherClip (void *proc1, void* proc2, char skipl, char skipr, int skipy, ; struct iconpic *myGfx); ; both proc1, proc2 should be: char __fastcall something (void); ; proc1 is called before reading a byte (.A returns next data) ; proc2 is called before reading each byte which is not pattern (code >219) .import popa, popax .import BitOtherRegs .export _BitOtherClip .include "jumptab.inc" .include "geossym.inc" _BitOtherClip: jsr BitOtherRegs jsr popax sta r12L stx r12H jsr popa sta r11H jsr popa sta r11L jsr popax sta r14L stx r14H jsr popax sta r13L stx r13H jmp BitOtherClip ��������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/graph/drawline.s�������������������������������������������������������0000664�0000000�0000000�00000001101�13473601511�0020771�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 29.10.99, 5.03.2003 ; void DrawLine (char mode, struct window *mywindow); .import _InitDrawWindow .import popa .importzp tmp1 .export _DrawLine .include "jumptab.inc" .include "geossym.inc" .include "geosmac.inc" _DrawLine: tay PushW r2 tya jsr _InitDrawWindow MoveW r2, r11 PopW r2 jsr popa sta tmp1 clc bit tmp1 bvc @1 sec @1: jmp DrawLine ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/graph/drawpoint.s������������������������������������������������������0000664�0000000�0000000�00000000641�13473601511�0021203�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 29.10.99, 05.3.2003 ; void DrawPoint (char mode, struct pixel *mypixel); .import PointRegs .import popa .importzp tmp1 .export _DrawPoint .include "jumptab.inc" _DrawPoint: jsr PointRegs jsr popa sta tmp1 clc bit tmp1 bvc @1 sec @1: jmp DrawPoint �����������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/graph/framerectangle.s�������������������������������������������������0000664�0000000�0000000�00000000321�13473601511�0022146�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 29.10.99 ; void FrameRectangle (char pattern); .export _FrameRectangle .include "jumptab.inc" _FrameRectangle = FrameRectangle ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/graph/getcharwidth.s���������������������������������������������������0000664�0000000�0000000�00000000356�13473601511�0021654�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 21.12.1999, 2.1.2003 ; char GetCharWidth (char character); .export _GetCharWidth .include "jumptab.inc" _GetCharWidth: jsr GetCharWidth ldx #0 rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/graph/getintcharint.s��������������������������������������������������0000664�0000000�0000000�00000000454�13473601511�0022041�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 11.03.2000 .import popa, popax .export getintcharint .include "geossym.inc" getintcharint: sta r11L stx r11H jsr popa sta r1H jsr popax sta r0L stx r0H rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/graph/graphicsstring.s�������������������������������������������������0000664�0000000�0000000�00000000433�13473601511�0022222�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 25.12.99 ; void GraphicsString (char *myString); .export _GraphicsString .include "jumptab.inc" .include "geossym.inc" _GraphicsString: sta r0L stx r0H jmp GraphicsString �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/graph/hlineregs.s������������������������������������������������������0000664�0000000�0000000�00000000441�13473601511�0021152�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 29.10.99 .import popax, popa .export HLineRegs .include "geossym.inc" HLineRegs: stx r4H sta r4L jsr popax stx r3H sta r3L jsr popa sta r11L rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/graph/horizontalline.s�������������������������������������������������0000664�0000000�0000000�00000000512�13473601511�0022232�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 29.10.99 ; void HorizontalLine (char pattern, char y, int xstart, int xend); .import popa .import HLineRegs .export _HorizontalLine .include "jumptab.inc" _HorizontalLine: jsr HLineRegs jsr popa jmp HorizontalLine ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/graph/imprintrectangle.s�����������������������������������������������0000664�0000000�0000000�00000000334�13473601511�0022542�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 21.12.99 ; void ImprintRectangle (void); .export _ImprintRectangle .include "jumptab.inc" _ImprintRectangle = ImprintRectangle ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/graph/initdrawwindow.s�������������������������������������������������0000664�0000000�0000000�00000000644�13473601511�0022250�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 29.10.99 ; 11.03.2000 ; void InitDrawWindow (struct window *myWindow); .importzp ptr4 .export _InitDrawWindow .include "geossym.inc" _InitDrawWindow: ; a/x is a struct window* sta ptr4 stx ptr4+1 ldy #0 copyWin:lda (ptr4),y sta r2L,y iny cpy #6 bne copyWin rts ��������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/graph/invertline.s�����������������������������������������������������0000664�0000000�0000000�00000000422�13473601511�0021350�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 29.10.99 ; void InvertLine (char y, int xstart, int xend); .import HLineRegs .export _InvertLine .include "jumptab.inc" _InvertLine: jsr HLineRegs jmp InvertLine ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/graph/invertrectangle.s������������������������������������������������0000664�0000000�0000000�00000000315�13473601511�0022366�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 29.10.99 ; void InvertRectangle (void); .export _InvertRectangle .include "jumptab.inc" _InvertRectangle = InvertRectangle �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/graph/loadcharset.s����������������������������������������������������0000664�0000000�0000000�00000000420�13473601511�0021460�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 21.12.99 ; void LoadCharSet (struct fontdesc *myFont); .export _LoadCharSet .include "jumptab.inc" .include "geossym.inc" _LoadCharSet: sta r0L stx r0H jmp LoadCharSet ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/graph/pointregs.s������������������������������������������������������0000664�0000000�0000000�00000000620�13473601511�0021203�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 29.10.99 .importzp ptr4 .export PointRegs .include "geossym.inc" PointRegs: ; a/x is a struct pixel* sta ptr4 stx ptr4+1 ldy #0 lda (ptr4),y sta r3L iny lda (ptr4),y sta r3H iny lda (ptr4),y sta r11L rts ����������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/graph/put_char.s�������������������������������������������������������0000664�0000000�0000000�00000000533�13473601511�0021001�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 30.10.99 ; void PutChar (char character, char y, int x); .import popa .export _PutChar .include "jumptab.inc" .include "geossym.inc" _PutChar: sta r11L stx r11H jsr popa sta r1H jsr popa jmp PutChar ���������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/graph/putdecimal.s�����������������������������������������������������0000664�0000000�0000000�00000000532�13473601511�0021322�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 30.10.99, 17.8.2003 ; void PutDecimal (char style, unsigned value, char y, int x); .import popa, popax .import getintcharint .export _PutDecimal .include "jumptab.inc" _PutDecimal: jsr getintcharint jsr popa jmp PutDecimal ����������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/graph/putstring.s������������������������������������������������������0000664�0000000�0000000�00000000453�13473601511�0021234�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 30.10.99 ; void PutString (char *mytxt, char y, int x); .import popax, popa .import getintcharint .export _PutString .include "jumptab.inc" _PutString: jsr getintcharint jmp PutString ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/graph/recoverline.s����������������������������������������������������0000664�0000000�0000000�00000000426�13473601511�0021512�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 29.10.99 ; void RecoverLine (char y, int xstart, int xend); .import HLineRegs .export _RecoverLine .include "jumptab.inc" _RecoverLine: jsr HLineRegs jmp RecoverLine ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/graph/recoverrectangle.s�����������������������������������������������0000664�0000000�0000000�00000000334�13473601511�0022525�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 29.10.99 ; void RecoverRectangle (void); .export _RecoverRectangle .include "jumptab.inc" _RecoverRectangle = RecoverRectangle ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/graph/rectangle.s������������������������������������������������������0000664�0000000�0000000�00000000277�13473601511�0021145�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 29.10.99 ; void Rectangle (void); .export _Rectangle .include "jumptab.inc" _Rectangle = Rectangle ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/graph/setpattern.s�����������������������������������������������������0000664�0000000�0000000�00000000273�13473601511�0021366�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 29.10.99 ; void SetPattern (char pattern); .export _SetPattern .include "jumptab.inc" _SetPattern = SetPattern �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/graph/testpoint.s������������������������������������������������������0000664�0000000�0000000�00000000566�13473601511�0021233�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 29.10.1999, 2.1.2003 ; char TestPoint (struct pixel *mypixel); .import PointRegs .import return0, return1 .export _TestPoint .include "jumptab.inc" _TestPoint: jsr PointRegs jsr TestPoint bcc goFalse jmp return1 goFalse:jmp return0 ������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/graph/usesystemfont.s��������������������������������������������������0000664�0000000�0000000�00000000270�13473601511�0022122�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 30.10.99 ; void UseSystemFont (void); .export _UseSystemFont .include "jumptab.inc" _UseSystemFont = UseSystemFont ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/graph/verticalline.s���������������������������������������������������0000664�0000000�0000000�00000000643�13473601511�0021657�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 29.10.99 ; void VerticalLine (char pattern, char ystart, char yend, int x); .import popa .export _VerticalLine .include "jumptab.inc" .include "geossym.inc" _VerticalLine: stx r4H sta r4L jsr popa sta r3H jsr popa sta r3L jsr popa jmp VerticalLine ���������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/memory/����������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0017216�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/memory/clearram.s������������������������������������������������������0000664�0000000�0000000�00000000601�13473601511�0021165�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 30.10.99, 20.08.2003 ; void * ClearRam (char *dest, int length); .import DoublePop .export _ClearRam .include "jumptab.inc" .include "geossym.inc" _ClearRam: jsr DoublePop pha txa pha jsr ClearRam pla tax pla rts �������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/memory/cmpfstring.s����������������������������������������������������0000664�0000000�0000000�00000000652�13473601511�0021561�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 22.12.99, 29.07.2000 ; char CmpFString (char length, char *dest, char* source); .import DoubleSPop, SetPtrXY .import popa, return0, return1 .export _CmpFString .include "jumptab.inc" _CmpFString: jsr DoubleSPop jsr popa jsr SetPtrXY jsr CmpFString bne L1 jmp return0 L1: jmp return1 ��������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/memory/cmpstring.s�����������������������������������������������������0000664�0000000�0000000�00000000543�13473601511�0021412�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 22.12.1999, 2.1.2003 ; char CmpString (char *dest, char* source); .import DoubleSPop .import return0, return1 .export _CmpString .include "jumptab.inc" _CmpString: jsr DoubleSPop jsr CmpString bne L1 jmp return0 L1: jmp return1 �������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/memory/copyfstring.s���������������������������������������������������0000664�0000000�0000000�00000000545�13473601511�0021755�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 22.12.99, 29.07.2000 ; void CopyFString (char length, char *dest, char* source); .import DoubleSPop, SetPtrXY .import popa .export _CopyFString .include "jumptab.inc" _CopyFString: jsr DoubleSPop jsr popa jsr SetPtrXY jmp CopyFString �����������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/memory/copystring.s����������������������������������������������������0000664�0000000�0000000�00000000400�13473601511�0021575�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 22.12.99 ; void CopyString (char *dest, char* source); .import DoubleSPop .export _CopyString .include "jumptab.inc" _CopyString: jsr DoubleSPop jmp CopyString ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/memory/crc.s�����������������������������������������������������������0000664�0000000�0000000�00000000504�13473601511�0020150�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 22.12.99 ; int CRC (char *memory, int length); .import DoublePop .export _CRC .include "jumptab.inc" .include "geossym.inc" _CRC: jsr DoublePop jsr CRC lda r2L ldx r2H rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/memory/doublepop.s�����������������������������������������������������0000664�0000000�0000000�00000000370�13473601511�0021373�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 31.12.99 .import popax .export DoublePop .include "geossym.inc" DoublePop: sta r0L stx r0H jsr popax sta r1L stx r1H rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/memory/doublespop.s����������������������������������������������������0000664�0000000�0000000�00000000743�13473601511�0021562�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 22.12.99, 29.07.2000 .import popax .importzp ptr3, ptr4 .export DoubleSPop .export SetPtrXY .include "geossym.inc" DoubleSPop: sta ptr4 stx ptr4+1 jsr popax sta ptr3 stx ptr3+1 ; rts ; ; SetPtrXY can be sometimes executed twice, but even this way it is few cycles ; faster... SetPtrXY: ldx #ptr4 ldy #ptr3 rts �����������������������������cc65-2.18/libsrc/geos-common/memory/fillram.s�������������������������������������������������������0000664�0000000�0000000�00000000746�13473601511�0021037�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 30.10.99, 15.07.2001 ; void * FillRam (char *dest, char what, int length); .import popa, popax .export _FillRam .include "jumptab.inc" .include "geossym.inc" _FillRam: sta r0L stx r0H jsr popa sta r2L jsr popax sta r1L stx r1H pha txa pha jsr FillRam pla tax pla rts ��������������������������cc65-2.18/libsrc/geos-common/memory/initram.s�������������������������������������������������������0000664�0000000�0000000�00000000400�13473601511�0021037�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 30.10.99 ; void InitRam (struct inittab*); .export _InitRam .include "jumptab.inc" .include "geossym.inc" _InitRam: sta r0L stx r0H jmp InitRam ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/memory/movedata.s������������������������������������������������������0000664�0000000�0000000�00000001032�13473601511�0021176�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 30.10.99, 15.07.2001 ; void* MoveData (char* dest, char *source, int length); .import popax .export _MoveData .include "jumptab.inc" .include "geossym.inc" _MoveData: sta r2L stx r2H jsr popax sta r0L stx r0H jsr popax sta r1L stx r1H jsr MoveData lda r1L ; return dest ptr to be compatible with memmove and memcpy ldx r1H rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/menuicon/��������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0017523�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/menuicon/doicons.s�����������������������������������������������������0000664�0000000�0000000�00000000407�13473601511�0021346�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 30.10.99 ; void DoIcons (struct icontab *myicons); .export _DoIcons .include "jumptab.inc" .include "geossym.inc" _DoIcons: sta r0L stx r0H jmp DoIcons���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/menuicon/domenu.s������������������������������������������������������0000664�0000000�0000000�00000000416�13473601511�0021177�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 30.10.99 ; void DoMenu (struct menu *mymenu); .export _DoMenu .include "jumptab.inc" .include "geossym.inc" _DoMenu: sta r0L stx r0H lda #0 jmp DoMenu��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/menuicon/dopreviousmenu.s����������������������������������������������0000664�0000000�0000000�00000000272�13473601511�0022774�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 30.10.99 ; void DoPreviousMenu (void); .export _DoPreviousMenu .include "jumptab.inc" _DoPreviousMenu = DoPreviousMenu��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/menuicon/gotofirstmenu.s�����������������������������������������������0000664�0000000�0000000�00000000267�13473601511�0022621�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 30.10.99 ; void GotoFirstMenu (void); .export _GotoFirstMenu .include "jumptab.inc" _GotoFirstMenu = GotoFirstMenu�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/menuicon/recoverallmenus.s���������������������������������������������0000664�0000000�0000000�00000000276�13473601511�0023122�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 30.10.99 ; void RecoverAllMenus (void); .export _RecoverAllMenus .include "jumptab.inc" _RecoverAllMenus = RecoverAllMenus����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/menuicon/recovermenu.s�������������������������������������������������0000664�0000000�0000000�00000000261�13473601511�0022240�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 30.10.99 ; void RecoverMenu (void); .export _RecoverMenu .include "jumptab.inc" _RecoverMenu = RecoverMenu�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/menuicon/redomenu.s����������������������������������������������������0000664�0000000�0000000�00000000250�13473601511�0021522�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 30.10.99 ; void ReDoMenu (void); .export _ReDoMenu .include "jumptab.inc" _ReDoMenu = ReDoMenu��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/mousesprite/�����������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0020265�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/mousesprite/clearmousemode.s�������������������������������������������0000664�0000000�0000000�00000000272�13473601511�0023456�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 30.10.99 ; void ClearMouseMode (void); .export _ClearMouseMode .include "jumptab.inc" _ClearMouseMode = ClearMouseMode��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/mousesprite/disablsprite.s���������������������������������������������0000664�0000000�0000000�00000000372�13473601511�0023140�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 30.10.99 ; void DisablSprite (char spritenum); .export _DisablSprite .include "jumptab.inc" .include "geossym.inc" _DisablSprite: sta r3L jmp DisablSprite����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/mousesprite/drawsprite.s�����������������������������������������������0000664�0000000�0000000�00000000512�13473601511�0022633�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 30.10.99 ; void DrawSprite (char spritenum, char *tab63 ); .import popa .export _DrawSprite .include "jumptab.inc" .include "geossym.inc" _DrawSprite: sta r4L stx r4H jsr popa sta r3L jmp DrawSprite��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/mousesprite/enablsprite.s����������������������������������������������0000664�0000000�0000000�00000000366�13473601511�0022766�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 30.10.99 ; void EnablSprite (char spritenum); .export _EnablSprite .include "jumptab.inc" .include "geossym.inc" _EnablSprite: sta r3L jmp EnablSprite��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/mousesprite/getnextchar.s����������������������������������������������0000664�0000000�0000000�00000000535�13473601511�0022770�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 21.12.1999, 2.1.2003 ; char GetNextChar (void); ; note that if it returns 0 (FALSE) then no characters are available .export _GetNextChar .include "jumptab.inc" _GetNextChar: jsr GetNextChar ldx #0 tay ; preserve Z flag rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/mousesprite/inittextprompt.s�������������������������������������������0000664�0000000�0000000�00000000301�13473601511�0023555�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 21.12.99 ; void InitTextPrompt (char height); .export _InitTextPrompt .include "jumptab.inc" _InitTextPrompt = InitTextPrompt�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/mousesprite/ismseinregion.s��������������������������������������������0000664�0000000�0000000�00000000507�13473601511�0023326�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 21.12.1999, 2.1.2003 ; char IsMseInRegion (struct window *mywindow); .import _InitDrawWindow .export _IsMseInRegion .include "jumptab.inc" _IsMseInRegion: jsr _InitDrawWindow jsr IsMseInRegion ldx #0 rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/mousesprite/mouseoff.s�������������������������������������������������0000664�0000000�0000000�00000000250�13473601511�0022271�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 30.10.99 ; void MouseOff (void); .export _MouseOff .include "jumptab.inc" _MouseOff = MouseOff��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/mousesprite/mouseup.s��������������������������������������������������0000664�0000000�0000000�00000000245�13473601511�0022147�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 30.10.99 ; void MouseUp (void); .export _MouseUp .include "jumptab.inc" _MouseUp = MouseUp�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/mousesprite/possprite.s������������������������������������������������0000664�0000000�0000000�00000001006�13473601511�0022476�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 30.10.99 ; void PosSprite (char spritenum, struct pixel *position ); .importzp ptr4 .import popa .export _PosSprite .include "jumptab.inc" .include "geossym.inc" _PosSprite: sta ptr4 stx ptr4+1 ldy #0 lda (ptr4),y sta r4L iny lda (ptr4),y sta r4H iny lda (ptr4),y sta r5L jsr popa sta r3L jmp PosSprite��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/mousesprite/promptoff.s������������������������������������������������0000664�0000000�0000000�00000000522�13473601511�0022464�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 21.12.99 ; void PromptOff (void); .export _PromptOff .include "jumptab.inc" .include "geossym.inc" _PromptOff: ; from 'The Hitchhiker's Guide To GEOS' php sei jsr PromptOff lda #0 sta alphaFlag plp rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/mousesprite/prompton.s�������������������������������������������������0000664�0000000�0000000�00000000616�13473601511�0022332�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 21.12.99 ; void PromptOn (struct pixel *); .importzp ptr4 .export _PromptOn .include "jumptab.inc" .include "geossym.inc" _PromptOn: sta ptr4 stx ptr4+1 ldy #0 promptLp: lda (ptr4),y sta stringX,y iny cpy #3 bne promptLp jmp PromptOn ������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/mousesprite/startmousemode.s�������������������������������������������0000664�0000000�0000000�00000000321�13473601511�0023520�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 30.10.99 ; void StartMouseMode (void); .export _StartMouseMode .include "jumptab.inc" _StartMouseMode: clc jmp StartMouseMode���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/process/���������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0017364�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/process/processblock.s�������������������������������������������������0000664�0000000�0000000�00000000672�13473601511�0022246�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 27.10.99 ; void InitProcesses (char number, struct process* proctab); ; (rest) ; void BlockProcess (char number); ; void UnblockProcess (char number); .export _BlockProcess .export _UnblockProcess .include "jumptab.inc" _BlockProcess: tax jmp BlockProcess _UnblockProcess: tax jmp UnblockProcess ����������������������������������������������������������������������cc65-2.18/libsrc/geos-common/process/processfreeze.s������������������������������������������������0000664�0000000�0000000�00000000567�13473601511�0022437�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 27.10.99 ; void FreezeProcess (char number); ; void UnfreezeProcess (char number); .export _FreezeProcess .export _UnfreezeProcess .include "jumptab.inc" _FreezeProcess: tax jmp FreezeProcess _UnfreezeProcess: tax jmp UnfreezeProcess �����������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/process/processinitrestartenable.s�������������������������������������0000664�0000000�0000000�00000001157�13473601511�0024672�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 27.10.99 ; void InitProcesses (char number, struct process* proctab); ; void RestartProcess (char number); ; void EnableProcess (char number); .import popa .export _InitProcesses .export _RestartProcess .export _EnableProcess .include "jumptab.inc" .include "geossym.inc" _InitProcesses: sta r0L stx r0H jsr popa jmp InitProcesses _RestartProcess: tax jmp RestartProcess _EnableProcess: tax jmp EnableProcess �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/process/processsleep.s�������������������������������������������������0000664�0000000�0000000�00000001567�13473601511�0022270�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 30.10.99, 15.8.2003 ; void Sleep (int jiffies); .importzp ptr1 .importzp tmp1 .export _Sleep .include "jumptab.inc" .include "geossym.inc" _SleepExit: jsr Sleep ; call Sleep ldx tmp1 txs ; restore stack pointer jmp (ptr1) ; when timeouts control will reach here _Sleep: sta r0L ; store data stx r0H pla sta ptr1 pla sta ptr1+1 ; preserve return address inc ptr1 bne @L0 inc ptr1+1 ; fix return address @L0: tsx stx tmp1 ; preserve stack pointer jsr _SleepExit ; call Sleep jmp MainLoop ; immediate return here - go to idle loop �����������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/runtime/���������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0017371�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/runtime/call.s���������������������������������������������������������0000664�0000000�0000000�00000000314�13473601511�0020466�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak <ytm@elysium.pl> ; 23.12.2002 ; ; CC65 runtime: call function via pointer in ax ; .export callax .include "jumptab.inc" callax = CallRoutine ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/symbols.txt������������������������������������������������������������0000664�0000000�0000000�00000104164�13473601511�0020145�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������Source: The Hitchhiker's Guide To GEOS https://archive.org/details/The_Hitchhikers_Guide_to_GEOS GEOS Variables ============== Name C64 C128 Apple Size Description ------------------------------------------------------------------- alarmSetFlag $851c $851c n/a Byte TRUE if the alarm is set for GEOS to monitor, else FALSE. alarmTmtVector $84ad $84ad $0212 Word Address of a service routine for the alarm clock time-out ... alphaFlag $84b4 $84b4 $0225 Byte Flag for alphanumeric string input ... appMain $849b $849b $0200 Word Vector that allows applications to include their own main loop ... backBufPtr n/a $131b $9d7c 16 Bytes Screen pointer where the back buffer came from. backXBufNum n/a $132b $d98c 8 Bytes For each sprite, there is one byte here for how many bytes ... backYBufNum n/a $1333 $d994 8 Bytes For each sprite, there is one byte here for how many scanlines ... bakclr0 $d021 $d021 n/a Byte Background color 0. bakclr1 $d022 $d022 n/a Byte Background color 1. bakclr2 $d023 $d023 n/a Byte Background color 2. bakclr3 $d024 $d024 n/a Byte Background color 3. baselineOffset $26 $26 $0218 Byte Offset from top line to baseline in character set. bkvec $0316 $0316 n/a Word BRK instruction vector for when ROMs are switched in. bootName $c006 $c006 $e003 9 Bytes This is the start of the "GEOS BOOT" string. BRKVector $84af $84af $0214 Word Vector to the routine that is called when a BRK instruction is ... cardDataPntr $2c $2c $60 Word This is a pointer to the actual card graphics data for the ... CPU_DATA $01 n/a n/a Word Address of 6510 data register that controls the hardware memory ... CPU_DDR $00 n/a n/a Byte Address of 6510 data direction register. curDevice $ba $ba n/a Byte This holds the current serial device number. curDirHead $8200 $8200 $fa80 256 | 39 Bytes For CBM, it is the buffer containing header infomation ... curDrive $8489 $8489 $f60d Byte Holds the device number of the currently active disk drive. curEnable n/a $1300 $0951 Byte This is an image of the C64 mobenble register. curHeight $29 $29 $021b Byte Used to hold the card height in pixels of the current font in ... curIndexTable $2a $2a $005e Word curIndexTable points to the table of sizes, in bytes, of each ... curmobx2 n/a $1302 $d953 Byte Image of the C64 mobx2 register. curnoby2 n/a $1301 $d952 Byte Image of the C64 moby2 register. curPattern $22 $22 $022c Word curPattern points to the first byte of the graphics data for the ... curRecord $8496 $8496 $f618 Byte Holds the current record number for an open VLIR file. currentMode $2e $2e $021c Byte Holds the current text drawing node. curSetWidth $27 $27 $0219 Word Holds the card width in pixels for the current font. curType $88c6 $88c6 n/a Byte Holds the current disk type. curXpos0 n/a $1303 $d954 16 Bytes The current X positions of the C128 and Apple soft sprites. curYpos0 n/a $1313 $d964 8 Bytes The current Y positions for the C128 and Apple soft sprites. dataDiskName $8453 $8453 $02b4 18 | 16 Bytes Holds the disk name that an application's data file is on. dataFileName $8442 $8442 $02a4 17 | 16 Bytes This is the name of a data file to open. dateCopy $c018 $c018 n/a 3 Bytes This is a copy of the system variables for year, month, and day. day $8518 $8518 $f202 Byte Holds the value for current day. dblClickCount $8515 $8515 $0258 Byte Used to determine when an icon is double clicked on. devTabHi n/a n/a $fae7 4 Bytes For the Apple, these are the high and low bytes of the four ... devTabLo n/a n/a $faeb 4 Bytes For the Apple, these are the high and low bytes of the four ... devUnitTab n/a n/a $faef 4 Bytes The ProDos unit numbers of the four possible devices are kept ... dir2Head $8900 $8900 n/a 256 Bytes This is the 2nd directory header block used for larger cpacity ... dirBlkno n/a n/a $f620 Word Block number of the key block of the directory containing ... dirEntryBuf $8400 $8400 $fa59 256 | 39 Bytes Buffer used to build a file's directory entry. dirPtr n/a n/a $f622 Word Pointer into diskBlkBuf for this file's entry. diskBlkBuf $8000 $8000 $f659 256 | 512 Bytes General disk block buffer. Initialized to all zeros. diskOpenFlg $848a $848a $f617 Byte Set to TRUE or FALSE to indicate whether a disk is currently ... dispBufferOn $2f $2f $021d Byte Routes graphic and text operations to either the foreground ... dlgBoxRamBuf $851f $B51f $f381 417 | 649 Bytes This is the buffer for variables that are saved when desk ... doRestFlag n/a $1b54 $db1d Byte Flag needed because of ouerlapping soft sprite problems on C128 ... DrACurDkNm $841e $841e $faa7 18 | 16 Bytes This is the disk name of the current disk in drive A. DrBCurDkNm $8430 $8430 $fab7 18 | 16 Bytes This is the disk name of the current disk in drive B. DrCCurDkNm $88dc $88dc $fac7 18 | 16 Bytes This is the disk name of the current disk in drive C. DrDCurDkNm $88ee $88ee $fad7 18 | 16 Bytes This is the disk name of the current disk in drive D. driveData $88bf $88bf n/a 4 Bytes One byte is reserved for each disk drive, to be used by the ... driveType $848e $848e $faf3 4 Bytes There are 4 bytes at location driveType, one for each of four ... drSizeHi n/a n/a $fafb 4 Bytes The high bytes of the sizes of the four possible ... drSizeLo n/a n/a $faf7 4 Bytes The low bytes of the sizes of the four possible ... extclr $20 $20 n/a Byte Holds value for exterior (border) color. faultData $84b6 $84b6 $0227 Byte Holds information about mouse faults. fileHeader $8100 $8100 $f859 256 | 512 Bytes Buffer used to hold the header block for a GEOS file. fileSize $8499 $8499 $f61b Word This is the current size (in blocks) of a file. fileTrScTab $8300 $8300 n/a 256 Bytes For Commodore, it is the buffer used to hold the track and ... fileWritten $8498 $8498 $f61a Byte Flag indicating if a if the currently open file has been written ... firstBoot $88c5 $88c5 $0281 Byte This flag is changed from 0 to $FF when the deskTop comes up ... fontData $850c $850c n/a(?) 9 Bytes Buffer for saving the user active font table when going into ... fontTable $26 $26 n/a(?) 8 Bytes fontTable is a label for the beginning of variables for the ... grcntr12 $d016 $d016 n/a Byte Graphics control reqister #2. grcntrl1 $d011 $d011 n/a Byte Graphics control register #1. grirq $d019 $d019 n/a Byte Graphics chip interrupt register. grirqen $d01a $d01a n/a Byte Graphics chip interrupt enable register. grmemptr $d018 $d018 n/a Byte Graphics memory pointer VM3-VttlO|CB13-CBll. hour $8519 $8519 $f203 Byte Variable for hour. iconSelFlag $84b5 $84b5 $0226 Byte This RAM variable contains flag bits in b7 and b6 to specify ... indexBlkno n/a n/a $f624 Word Block number of the VLIR index table. inputData $8506 $8506 $0247 4 Bytes This is where input drivers pass device specific information to ... inputDevName $88cb $88cb $08cc 17 | 16 Bytes String that holds the name of the current input device. inputVector $84a5 $84a5 $020a Word Pointer to routine to call on input device change. intBotVector $849f $849f $0204 Word Vector to routine to call after the operating system interrupt ... interleave $848c $848c n/a Byte Variable used by BlkAlloc routine as the desired interleave when ... intSource n/a n/a $02c6 Byte Byte to indicate where interrupts are coming from on the Apple. intTopVector $849d $849d $0202 Word Vector to routine to call before the operating system interrupt ... invertBuffer n/a $1ced n/a 80 Bytes Buffer area used to speed up the 80 colunn InvertLine routine. irqvec $0314 $0314 n/a Word IRQ vector. isGEOS $848b $848b n/a Byte Flag to indicate whether the current disk is a GEOS disk. keyData $8504 $8504 $0245 Byte Holds the ASCII value of the current last key that was pressed. keyVector $84a3 $84a3 $0208 Word Vector to routine to call on keypress. leftMargin $35 $35 $0220 Word Leftmost point for writing characters. MachineType n/a n/a $02c4 Byte Type of Apple machine. maxMouseSpeed $8501 $8501 $027d Byte Maximum speed for mouse cursor. mcmclr0 $d025 $d025 n/a Byte This is the variable for multi-color mode colors 0. mcmclr1 $d026 $d026 n/a Byte This is the variable for multi-color mode colors 1. MenuNumber $84b7 $84b7 $0228 Byte Number of currently working menu. minMouseSpeed $8502 $8502 $027e Byte Minimum speed for mouse cursor. minutes $851a $851a $f204 Byte Variable for minutes for time of day clock. mob0clr $d027 $d027 n/a Byte This is the color of the 1. object (sprite) on Commodore. mob0xpos $d000 $d000 n/a(!) Byte This is the x position of sprite #0 mob0ypos $d001 $d001 n/a(!) Byte This is the y position of sprite #0 mob1clr $d028 $d028 n/a Byte This is the color of the 2. object (sprite) on Commodore. mob1xpos $d002 $d002 n/a(!) Byte This is the x position of sprite #1 mob1ypos $d003 $d003 n/a(!) Byte This is the y position of sprite #1 mob2clr $d029 $d029 n/a Byte This is the color of the 3. object (sprite) on Commodore. mob2xpos $d004 $d004 n/a(!) Byte This is the x position of sprite #2 mob2ypos $d005 $d005 n/a(!) Byte This is the y position of sprite #2 mob3clr $d02a $d02a n/a Byte This is the color of the 4. object (sprite) on Commodore. mob3xpos $d006 $d006 n/a(!) Byte This is the x position of sprite #3 mob3ypos $d007 $d007 n/a(!) Byte This is the y position of sprite #3 mob4clr $d02b $d02b n/a Byte This is the color of the 5. object (sprite) on Commodore. mob4xpos $d008 $d008 n/a(!) Byte This is the x position of sprite #4 mob4ypos $d009 $d009 n/a(!) Byte This is the y position of sprite #4 mob5clr $d02c $d02c n/a Byte This is the color of the 6. object (sprite) on Commodore. mob5xpos $d00a $d00a n/a(!) Byte This is the x position of sprite #5 mob5ypos $d00b $d00b n/a(!) Byte This is the y position of sprite #5 mob6clr $d02d $d02d n/a Byte This is the color of the 7. object (sprite) on Commodore. mob6xpos $d00c $d00c n/a(!) Byte This is the x position of sprite #6 mob6ypos $d00d $d00d n/a(!) Byte This is the y position of sprite #6 mob7clr $d02e $d02e n/a Byte This is the color of the 8. object (sprite) on Commodore. mob7xpos $d00e $d00e n/a(!) Byte This is the x position of sprite #7 mob7ypos $d00f $d00f n/a(!) Byte This is the y position of sprite #7 mobbakcol $d01f $d01f n/a Byte Sprite to background collision register for Commodore. mobenble $d015 $d015 $0818 Byte Sprite enable bits. mobmcm $d01c $d01c n/a Byte Sprite multi-color mode select. mobmobcol $d01e $d01e n/a Byte Object to object collision register. mobprior $d01b $d01b n/a Byte Object to background priority. mobx2 $d01d $d01d $0819 Byte Double object size in x. moby2 $d017 $d017 $081a Byte Double object size in y. month $8517 $8517 $f201 Byte Holds month for time of day clock. mouseAccel $8503 $8503 $027f Byte Acceleration of mouse cursor. mouseBottom $84b9 $84b9 $58 Byte Bottom most position for mouse cursor. mouseFaultVec $84a7 $84a7 $020c Word Vector to routine to call when mouse goes outside region ... mouseLeft $84ba $84ba $59 Word Left most position for mouse. mouseOn $30 $30 $5d Byte Flag indicating that the mouse is mode is on. mousePicData $84c1 $84c1 n/a 64 Bytes 64 byte array for the mouse sprite picture on Commodore. mouseRight $84bc $84bc $5b Word Right most position for mouse. mouseSave n/a $1b55 $ee53 24 Bytes Screen data for what is beneath mouse soft sprite. mouseTop $84b8 $84b8 $57 Byte Top most position for mouse. mouseVector $84a1 $84a1 $0206 Word Routine to call on a mouse key press. mouseXOffset n/a n/a $0229 Word Offset from mouseXPos to draw the mouse sprite. mouseXPos $3a $3a $0241 Word Mouse X position. mouseYOffset n/a n/a $022b Byte Offset from mouseYPos to draw the mouse sprite. mouseYPos $3c $3c $0243 Byte Mouse Y position. msbxpos $d010 $d010 n/a Byte Most significant bits for x positions of sprites. msePicPtr $31 $31 n/a Word Pointer to the mouse graphics data. nationality $c010 $c010 $e00d Byte Byte to hold nationality of Kernal. nmivec $0318 $0318 n/a Word NMI vector. noEraseSprites n/a n/a $0240 Byte Flag to stop routine TempHideMouse fron erasing sprites #2 ... numDrives $848d $848d $f60e Byte Set to number of drives on the system. obj0Pointer $8ff8 $8ff8 n/a Byte Pointer to the picture data for sprite 0. obj1Pointer $8ff9 $8ff9 n/a Byte Pointer to the picture data for sprite 1. obj2Pointer $8ffa $8ffa n/a Byte Pointer to the picture data for sprite 2. obj3Pointer $8ffb $8ffb n/a Byte Pointer to the picture data for sprite 3. obj4Pointer $8ffc $8ffc n/a Byte Pointer to the picture data for sprite 4. obj5Pointer $8ffd $8ffd n/a Byte Pointer to the picture data for sprite 5. obj6Pointer $8ffe $8ffe n/a Byte Pointer to the picture data for sprite 6. obj7Pointer $8fff $8fff n/a Byte Pointer to the picture data for sprite 7. offFlag n/a n/a $027c Byte Flag telling whether the mouse needs to be redrawn. otherPressVec $84a9 $84a9 $020e Word Vector to routine that is called when the mouse button is ... pressFlag $39 $39 $08fe Byte Flag to indicate that a new key has been pressed. PrntDiskName $8476 $8476 n/a 18 Bytes Disk name that current printer driver is on. PrntFileName $8465 $8465 $08ac 17 | 16 Bytes Name of the current printer driver. ramBase $88c7 $88c7 n/a 4 Bytes RAM bank for each disk drive to use if the drive type is either ... ramExpSize $88c3 $88c3 n/a Byte Byte for number or RAM banks available in RAM expansion unit. random $850a $850a $024c Word Variable incremented each interrupt to generate a randon nunber. rasreg $d012 $d012 n/a Byte Raster register. RecoverVector $84b1 $84b1 $0216 Word Pointer to routine that is called to recover the background ... reqXpos0 n/a n/a $0800 Word This variable corresponds to the Commodore VIC chip register ... reqXpos1 n/a n/a $0802 Word This variable corresponds to the Commodore VIC chip register ... reqXpos2 n/a n/a $0804 Word This variable corresponds to the Commodore VIC chip register ... reqXpos3 n/a n/a $0806 Word This variable corresponds to the Commodore VIC chip register ... reqXpos4 n/a n/a $0808 Word This variable corresponds to the Commodore VIC chip register ... reqXpos5 n/a n/a $080a Word This variable corresponds to the Commodore VIC chip register ... reqXpos6 n/a n/a $080c Word This variable corresponds to the Commodore VIC chip register ... reqXpos7 n/a n/a $080e Word This variable corresponds to the Commodore VIC chip register ... returnAddress $3d $3d $64 Word Address to return to from in-line call. rightMargin $37 $37 $0222 Word The rightmost point for writing characters. savedmoby2 $88bb $88bb n/a Byte Saved value of moby2 for context saving done when dialogue boxes ... saveFontTab $850c $850c $024e 9 | 10 Bytes When a menu is selected, the users active font table is saved ... scr80colors n/a $88bd n/a Byte Screen colors for 80 column node on the C128. scr80polar n/a $88bc n/a Byte Copy of reg 24 in the VDC for the C128. screencolors $851e $851e n/a Byte Default screen colors. seconds $851b $851b $f205 Byte Seconds variable for the time of day clock. selectionFlash $84b3 $84b3 $0224 Byte Variable for the speed at which menu items and icons are ... shiftBuf n/a $1b45 $70 7 Bytes Buffer for shifting/doubling sprites. Located in back RAM. shiftOutBuf n/a $1b4c $78 7 Bytes Buffer for shifting/doubling/oring sprites. Located in back ... sizeFlags n/a $1b53 $db1c Byte Height of sprite. softOnes n/a $1c2d $d000 192 Bytes Buffer used for putting sprite bitmaps up on screen without ... softZeros n/a $1b6d $d0e0 192 Bytes Buffer used for putting sprite bitnaps up on screen without ... spr0pic $8a00 $8a00 n/a 64 Bytes This is where the graphics data for sprite 0 is kept on ... spr1pic $8a40 $8a40 n/a 64 Bytes This is where the graphics data for sprite 1 is kept on ... spr2pic $8a80 $8a80 n/a 64 Bytes This is where the graphics data for sprite 2 is kept on ... spr3pic $8ac0 $8ac0 n/a 64 Bytes This is where the graphics data for sprite 3 is kept on ... spr4pic $8b00 $8b00 n/a 64 Bytes This is where the graphics data for sprite 4 is kept on ... spr5pic $8b40 $8b40 n/a 64 Bytes This is where the graphics data for sprite 5 is kept on ... spr6pic $8b80 $8b80 n/a 64 Bytes This is where the graphics data for sprite 6 is kept on ... spr7pic $8bc0 $8bc0 n/a 64 Bytes This is where the graphics data for sprite 7 is kept on ... sspr1back n/a $133b $56d0 294 | 336 Bytes For the soft sprites #1, there is a buffer in the ... sspr2back n/a $1461 $5820 294 | 336 Bytes For the soft sprites #2, there is a buffer in the ... sspr3back n/a $1587 $5970 294 | 336 Bytes For the soft sprites #3, there is a buffer in the ... sspr4back n/a $16ad $5ac0 294 | 336 Bytes For the soft sprites #4, there is a buffer in the ... sspr5back n/a $17d3 $5c10 294 | 336 Bytes For the soft sprites #5, there is a buffer in the ... sspr6back n/a $18f9 $5d60 294 | 336 Bytes For the soft sprites #6, there is a buffer in the ... sspr7back n/a $1a1f $5eb0 294 | 336 Bytes For the soft sprites #7, there is a buffer in the ... string $24 $24 $53 Word Used by GEOS as a pointer to string destinations for routines ... StringFaultVec $84ab $84ab $0210 Word Vector called when an attempt is made to write a character ... stringX $84be $84be $022e Word The X position for string input. stringY $84c0 $84c0 $0230 Byte The Y position for string input. sysDBData $851d $851d $0259 Byte Variable that is used internally to indicate which icon caused ... sysFlgCopy $c012 $c012 n/a Byte This is a copy of the sysRAMFlg that is saved here when going ... sysRAMFlg $88c4 $88c4 n/a Byte If RAM expansion in, Bank 0 is reserved for the Kernal's use. totNumBlks n/a n/a $f60b Word Total number of blocks in current volume. turboFlags $8492 $8492 n/a 4 Bytes The turbo state flags for drives 8 through 11 on Commodore. usedRecords $8497 $8497 $f619 Byte Holds the number of records in an open VLIR file. vdcClrMode n/a $88be n/a Byte Holds the current color mode for C128 color routines. version $c00f $c00f $e00c Byte Holds byte indicating what version of GEOS is running. windowTop $33 $33 $021e Byte Top line of window for text clipping. year $8516 $8516 $f200 Byte Holds the year for the time of day clock. GEOS Routines ============= Name C64 C128 Apple Description ----------------------------------------------------------- AllocateBlock $9048 $9048 $0300 Mark a disk block as in-use. AppendRecord $c289 $c289 $0330 Insert a new VLIR record after the current record. AuxDExit n/a n/a $efa9 Aux-driver deinstall and exit routine. AuxDInt n/a n/a $efa3 Aux-driver interrupt level routine. AuxDKeyFilter n/a n/a $efa6 Aux-driver keypress filter. AuxDMain n/a n/a $efa0 Aux-driver MainLoop level routine. BBMult $c160 $c160 $fecc Byte by byte (single-precision) unsigned multiply. Bell n/a n/a $ff86 1000 Hz Bell sound. BitmapClip $c2aa $c2aa $fe5a Display a compacted bitmap, clipping to a sub-window. BitmapUp $c142 $c142 $fe54 Display a compacted bitmap without clipping. BitOtherClip $c2c5 $c2c5 $fe5d BitmapClip with data coming from elsewhere (e.g., disk). BldGDirEntry $c1f3 $c1f3 $036f Build a GEOS directory entry in memory. BlkAlloc $c1fc $c1fc $0351 Allocate space on disk. BlockProcess $c10c $c10c $feb4 Block process from running. Does not freeze timer. BMult $c163 $c163 $fecf Byte by word unsigned multiply. BootGEOS $c000 $c000 n/a Reboot GEOS. Requires only 128 bytes at $c000. CalcBlksFree $c1db $c1db $0324 Calculate total number of free disk blocks. CallRoutine $c1d8 $c1d8 $ff08 Pseudo-subroutine call. $0000 aborts call. CancelPrint n/a n/a $6018 Cancel printing, clearing printer and I/O card buffers. ChangeDiskDevice $c2bc $c2bc n/a Instruct CBM drive to change its serial device address. ChkDkGEOS $c1de $c1de n/a Check CBM disk for GEOS format. ClearCard n/a n/a $6715 Clear any buffered I/O operations. ClearMouseMode $c19c $c19c $fe9f Stop input device monitoring. ClearRam $c178 $c178 $fefc Clear memory to $00. ClockInt n/a n/a $0803 Clock driver interrupt level routine. CloseCard n/a n/a $670c Close access to I/O card. CloseRecordFile $c277 $c277 $0333 Close currently open VLIR file. CmpFString $c26e $c26e $fef0 Compare two fixed-length strings. CmpString $c26b $c26b $feed Compare two null-terminated strings. CopyFString $c268 $c268 $feea Copy a fixed-length string. CopyFullScreen n/a n/a $ff92 Fast vertical screen copy. CopyLine n/a n/a $ff5f Bit-boundary horizontal line copy. CopyScreenBlock n/a n/a $ff5c Bit-boundary rectangle copy. CopyString $c256 $c256 $fee7 Copy a null-terminated string. CRC $c20e $c20e $ff14 Cyclic Reduncancy Check calculation. Dabs $c16f $c16f $fedb Double-precision signed absolute value. Ddec $c175 $c175 $fee1 Double-precison unsigned decrement. Ddiv $c169 $c169 $fed5 Double-precision unsigned division. DeleteDir n/a n/a $037e Delete directory. DeleteFile $c238 $c238 $0357 Delete file. DeleteRecord $c283 $c283 $0336 Delete current VLIR record. DisablSprite $c1d5 $c1d5 $feab Disable sprite. DivideBySeven n/a n/a $ff68 Quick division by seven for direct screen access. DMult $c166 $c166 $fed2 Double-precision unsigned multiply. Dnegate $c172 $c172 $fede Double-precision signed negation. DoBOp n/a $c2ec n/a C128-backram memory primitive. DoDlgBox $c256 $c256 $ff17 Display and begin interaction with dialog box. DoIcons $c15a $c15a $fe0c Display and begin interaction with icons. DoInlineReturn $c2a4 $c2a4 $fe09 Return from inline subroutine. DoMenu $c151 $c151 $fe0f Display and begin interaction with menus. DoneWithIO $c25f $c25f n/a Restore system after I/O across CBM serial bus. DoPreviousMenu $c190 $c190 $fe15 Retract sub-menu and reactivate menus up one level. DoRAMOp $c2d4 $c2d4 n/a CBM RAM-expansion unit access primitive. DownDirectory n/a n/a $0381 Open subdirectory. DrawLine $c130 $c130 $fe33 Draw, clear, or recover line between two endpoints. DrawPoint $c133 $c133 $fe21 Draw, clear, or recover a single screen point. DrawSprite $c1c6 $c1c6 $fea2 Define sprite image. DSdiv $c16c $c16c $fed8 Double-precision signed division. DShiftLeft $c15d $c15d $fec6 Double-precision left shift (zeros shifted in). DShiftRight $c262 $c262 $fec9 Double-precision right shift (zeros shifted in). EnableProcess $c109 $c109 $fec3 Make a process runable immediately. EnablSprite $c1d2 $c1d2 $fea8 Enable sprite. EnterDeskTop $c22c $c22c $ff59 Leave application and return to GEOS deskTop. EnterTurbo $c214 $c214 n/a Activate CBM disk turbo on current drive. EraseCharacter n/a n/a $ff3e Erase text character from screen. ExitTurbo $c232 $c232 n/a Deactivate CBM disk turbo on current drive. FastDelFile $c244 $c244 n/a Quick file delete (requires full track/sector list). FdFTypesInDir n/a n/a $0363 Find files in directory other than current directory. FetchRAM $c2cb $c2cb n/a Transfer data from CBM RAM-expansion unit. FillRam $c17b $c17b $feff Fill memory with a particular byte. FindBAMBit $c2ad $c2ad n/a Get allocation status of particular CBM disk block. FindFile $c20b $c20b $0369 Search for a particular file. FindFTypes $c23b $c23b $0366 Find all files of a particular GEOS type. FindVBMBit n/a n/a $036c Get allocation status of particular ProDOS disk block. FirstInit $c271 $c271 $ff11 GEOS startup entry point. FndFilinDir n/a n/a $036c Find a file in a directory other than current directory. FollowChain $c205 $c205 n/a Follow chain of CBM sectors, building track/sector table. FrameRectangle $c127 $c127 $fe3f Draw a rectangular frame (outline). FreeBlock $c2b9 $c2b9 $032a Mark a disk block as not-in-use. FreeDir n/a n/a $03ba Free all blocks associated with a subdirectory. FreeFile $c226 $c226 $035a Free all blocks assocatiated with a file. FreezeProcess $c112 $c112 $feba Pause a process countdown timer. Get1stDirEntry $9030 $9030 $039c Get first directory entry. GetBlock $c1e4 $c1e4 $0300 Read single disk block into memory. GetCharWidth $c1c9 $c1c9 $fe87 Calculate width of character without style attributes. GetDimensions $790c $790c n/a Get CBM printer page dimensions. GetDirHead $c247 $c247 $0372 Read directory header into memory. GetFHdrInfo $c229 $c229 $0390 Read a GEOS file header into memory. GetFile $c208 $c208 $030f Load GEOS file. GetFreeDirBlk $c1f6 $c1f6 $0375 Find an empty directory slot. GetLdVars n/a n/a $ff44 Transfer internal Ld variables to GEOS pseudoregisters. GetMode n/a n/a $6012 Return current printer resolution and setable attributes. GetNextChar $c2a7 $c2a7 $fe75 Get next character from character queue. GetNxtDirEntry $9033 $9033 $039c Get directory entry other than first. GetPathname n/a n/a $0384 Return current path string. GetPattern n/a n/a $ff7d Get eight-byte GEOS pattern definition. GetPtrCurDkNm $c298 $c298 $ff56 Return pointer to current disk name. GetRandom $c187 $c187 $fee4 Calculate new random number. GetRealSize $c1b1 $c1b1 $fe84 Calculate actual character size with attributes. GetScanLine $c13c $c13c $fe66 Calculate scanline address. GetScreenLine n/a n/a $ff62 Copy Apple screen data to buffer. GetSerialNumber $c196 $c196 $4b38 Return GEOS serial number or pointer to name string. GetSpriteData n/a n/a $ff6e Get sprite image data. GetString $c1ba $c1ba $fe72 Get string input from user. GetVBM n/a n/a $031e Read first VBM block into VBM cache. GoDirectory n/a n/a $039f Go directory to a specific subdirectory. GotoFirstMenu $c1bd $c1bd $fe18 Retract all sub-menus and reactivate at main level. GraphicsString $c136 $c136 $fe60 Execute a string of graphics commands. HideOnlyMouse n/a $c2f2 $ff7a Temporarily remove soft-sprite mouse pointer. HorizontalLine $c118 $c118 $fe27 Draw a patterned horizontal line. i_BitmapUp $c1ab $c1ab $fe57 Inline BitmapUp. i_FillRam $c1b4 $c1b4 $ff02 Inline FillRam. i_FrameRectangle $c1a2 $c1a2 $fe42 Inline FrameRectangle. i_GraphicsString $c1a8 $c1a8 $fe63 Inline GraphicsString. i_ImprintRectangle $c253 $c253 $fe51 Inline ImprintRectangle. i_MoveData $c1b7 $c1b7 $fef9 Inline MoveData. i_NewBitUp n/a n/a $ff9e Inline NewBitUp. i_PutString $c1ae $c1ae $fe6c Inline PutString. i_RecoverRectangle $c1a5 $c1a5 $fe4b Inline RecoverRectangle. i_Rectangle $c19f $c19f $fe3c Inline Rectangle. ImprintLine n/a n/a $ff8f Imprint horizontal line to background buffer. ImprintRectangle $c250 $c250 $fe4e Imprint rectangular area to background buffer. InfoCard n/a n/a $670f Get I/O card attributes. InitCard n/a n/a $6700 Intialize I/O card. InitForDialog n/a n/a $ff4a Internal pre-dialog box intialization. InitForIO $c25c $c25c n/a Prepare CBM system for I/O across serial bus. InitForPrint $7900 $7900 $6000 Initialize printer (once per document). InitMouse $fe80 $fe80 $f000 Initialize input device. InitProcesses $c103 $c103 $feae Initialize processes. InitRam $c181 $c181 $ff05 Initialize memory areas from table. InitSprite n/a n/a $ff32 Initialize software sprites. InitTextPrompt $c1c0 $c1c0 $fe78 Initialize text prompt. InputByte n/a n/a $6709 Read byte from I/O card. InsertRecord $c286 $c286 $0339 Insert new VLIR record in front of current record. InterruptMain $c100 $c100 $fe03 Main interrupt level processing. InvertLine $c11b $c11b $fe2d Invert the pixels on a horizontal screen line. InvertRectangle $c12a $c12a $fe45 Invert the pixels in a rectangular screen area. IrqMiddle n/a n/a $ff20 Software interrupts entry point. IsMseInRegion $c2b3 $c2b3 $fe9c Check if mouse is within a screen region. JsrToAux n/a n/a $03b4 Call aux-memory subroutine. KeyFilter n/a n/a $f009 Input driver keypress filter. LdApplic $c21d $c21d $038d Load GEOS application. LdDeskAcc $c217 $c217 $035d Load GEOS desk accessory. LdFile $c211 $c211 $0312 Load GEOS data file. LoadAuxSet n/a n/a $ff77 Use aux-memory character set. LoadCharSet $c1cc $c1cc $fe8a Use main-memory character set. MainLoop $c1c3 $c1c3 $fe00 GEOS MainLoop processing. MakeSubDir n/a n/a $0387 Create ProDOS subdirectory. MouseOff $c18d $c18d $fe96 Disable mouse pointer and GEOS mouse tracking. MouseUp $c18a $c18a $fe99 Enable mouse pointer and GEOS mouse tracking. MoveAuxData n/a n/a $ff6b Apple aux-memory memory move routine. MoveBData n/a $c2e3 n/a C128 backram memory move routine. MoveData $c17c $c17e $fef6 Memory move routine. NewBitClip n/a n/a $ff95 Bit-boundary BitmapClip. NewBitOtherClip n/a n/a $ff0e Bit-boundary BitOtherClip. NewBitUp n/a n/a $ff1d Bit-boundary BitmapUp. NewDisk $c1e1 $c1e1 n/a Tell CBM disk turbo software that a new disk is in drive. NextRecord $c27a $c27a $0336 Make next VLIR the current record. NormalizeX n/a $c2e0 n/a Normalize C128 X-coordinates for 40/80 modes. NxtBlkAlloc $c24d $c24d $0354 Version of BlkAlloc that starts at a specific block. OpenCard n/a n/a $6703 Open I/O card for access. OpenDisk $c2a1 $c2a1 $0399 Open disk in current drive. OpenRecordFile $c274 $c274 $033f Open VLIR file on current disk. OutputByte n/a n/a $6706 Write byte to I/O card. Panic $c2c2 $c2c2 $fef3 System-error dialog box. PointRecord $c280 $c280 $0342 Make specific VLIR record the current record. PosSprite $c1cf $c1cf $fea5 Position sprite. PreviousRecord $c27d $c27d $0345 Make previous VLIR record the current record. PrintASCII $790f $790f $600c Send ASCII data to printer. PrintBuffer $7906 $7906 $6009 Send graphics data to printer. PromptOff $c29e $c29e $fe7e Turn off text prompt. PromptOn $c29b $c29b $fe7b Turn on text prompt. PurgeTurbo $c235 $c235 n/a Remove CBM disk turbo software from drive. PutBlock $c1e7 $c1e7 $0303 Write single disk block from memory. PutChar $c145 $c145 $fe81 Display a single character to screen. PutDecimal $c184 $c184 $fe6f Format and display an unsigned double-precison number. PutDirHead $c24a $c24a $037b Write directory header to disk. PutScreenLine n/a n/a $ff65 Copy buffer data to Apple screen memory. PutString $c148 $c148 $fe69 Print string of characters to screen. PutVBM n/a n/a $0321 Flush VBM cache; write currently cached block to disk. ReadBackLine n/a n/a $ff74 Get data from background screen in linear bitmap format. ReadBlock $c21a $c21a n/a CBM get disk block primitive. ReadByte $c2b6 $c2b6 $ff41 Read disk file a byte at a time. ReadClock n/a n/a $0800 Update GEOS time/date variables from clock hardware. ReadFile $c1ff $c1ff $0315 Read chained list of blocks into memory. ReadLink $904b $904b n/a Read CBM track/sector link. ReadRecord $c28c $c28c $0348 Read current VLIR record into memory. ReadScanLine n/a n/a $ff98 Get data from foreground screen in linear bitmap format. RecoverAllMenus $c157 $c157 $fe1e Recover all menus from background buffer. RecoverFG n/a n/a $03ae Restores foreground screen from data created with SaveFG. RecoverLine $c11e $c11e $fe30 Recover horizontal screen line from background buffer. RecoverMenu $c154 $c154 $fe1b Recover single menu from background buffer. RecoverRectangle $c12d $c12d $fe48 Recover rectangular screen area from background buffer. RecoverSysRam n/a n/a $ff53 Restore system after dialog box or desk accessory. Rectangle $c124 $c124 $fe39 Draw a filled rectangle. ReDoMenu $c193 $c193 $fe12 Reactivate menus at the current level. RenameFile $c259 $c259 $0393 Rename GEOS disk file. ReOpenDisk n/a n/a $03a2 Reopen disk to previous directory. ResetAlarm n/a n/a $080c Disable clock driver alarm. ResetHandle $c003 $c003 n/a Internal bootstrap entry point. RestartProcess $c106 $c106 $feb1 Unblock, unfreeze, and restart process. RestoreFontData n/a n/a $ff38 Restore font variables from saveFontTab. RstrAppl $c23e $c23e $0360 Leave desk accessory and return to calling application. RstrFrmDialog $c2bf $c2bf $ff1a Exit dialog box. SaveFG n/a n/a $03ab Save foreground screen data for RestoreFG. SaveFile $c1ed $c1ed $0318 Save/create a GEOS file. SaveFontData n/a n/a $ff35 Copy font variables to saveFontTab. SetAlarm n/a n/a $0809 Set clock driver alarm. SetDevice $c2b0 $c2b0 n/a Establish communication with a new serial device. SetGDirEntry $c1f0 $c1f0 $037b Create and save a new GEOS directory entry. SetGEOSDisk $c1ea $c1ea n/a Convert normal CBM disk into GEOS format disk. SetLdVars n/a n/a $ff47 Set internal Ld variables from GEOS pseudoregisters. SetMode n/a n/a $6015 Set print mode. SetMouse n/a $fe89 n/a Reset input device scanning circutry. SetMsePic n/a $c2da $ff2f Set and preshift new soft-sprite mouse picture. SetNewMode n/a $c2dd n/a Change GEOS 128 graphics mode (40/80 switch). SetNextFree $c292 $c292 $032d Search for nearby free disk block and allocate it. SetNLQ $7915 $7915 n/a Begin near-letter quality printing. SetPattern $c139 $c139 $fe36 Set current fill pattern. SetTimeDate n/a n/a $0806 Set clock driver time and date. SetUserPattern n/a n/a $ff80 Define new GEOS pattern image. Sleep $c199 $c199 $fec0 Put current subroutine to sleep for a specified time. SlowMouse $fe83 $fe83 $f003 Reset mouse velocity variables. SmallPutChar $c202 $c202 $fe90 Fast character print routine. SoftSprHandler n/a n/a $ff2c Apple soft-sprite drawing routine. SortAlpha n/a n/a $03a5 Insertion sort. StartAppl $c22f $c22f $fe06 Warmstart GEOS and start application in memory. StartASCII $7912 $7912 $6006 Begin ASCII mode printing. StartMouseMode $c14e $c14e $fe93 Start monitoring input device. StartPrint $7903 $7903 $6003 Begin graphics mode printing. StashRAM $c2c8 $c2c8 n/a Transfer memory to CBM RAM-expansion unit. StatusCard n/a n/a $6712 Get current status of I/O card. StopPrint $7909 $7909 $600f End page of printer output. SwapBData n/a $c2e6 n/a C128 memory swap between front/back ram. SwapMainAndAux n/a n/a $ff71 Apple memory swap between main and aux. SwapRAM $c2ce $c2ce n/a CBM RAM-expansion unit memory swap. TempHideMouse n/a $c2d7 $ff29 Hide soft-sprites before direct screen access. TestPoint $c13f $c13f $fe24 Test status of single screen point (on or off?). ToBasic $c241 $c241 n/a Call Commodore BASIC. UnblockProcess $c10f $c10f $feb7 Unblock a blocked process, allowing it to run again. UnfreezeProcess $c115 $c115 $febd Unpause a frozen process timer. UpdateMouse $fe86 $fe86 $f006 Update mouse variables from input device. UpdateParent n/a n/a $03b7 Update parent directory to reflect any changes. UpdateRecordFile $c295 $c295 $034b Update currently open VLIR file without closing it. UpDirectory n/a n/a $038a Close current directory and move up one level. UseSystemFont $c14b $c14b $fe8d Use default system font (BSW 9). VerifyBData n/a $c2e9 n/a C128 backram verify. VerifyRAM $c2d1 $c2d1 n/a CBM RAM-expansion unit verify. VerticalLine $c121 $c121 $fe2a Draw a patterned vertical line. VerWriteBlock $c223 $c223 n/a CBM disk block verify primitive. WarmStart n/a n/a $ff4d Bring GEOS to a warmstart state. WriteBlock $c220 $c220 n/a CBM write disk block primitive. WriteFile $c1f9 $c1f9 $031b Write chained list of blocks to disk. WriteRecord $c28f $c28f $034e Write current VLIR record to disk. ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/system/����������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0017232�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/system/callroutine.s���������������������������������������������������0000664�0000000�0000000�00000000266�13473601511�0021743�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 21.12.99 ; void CallRoutine (myRoutine); .export _CallRoutine .include "jumptab.inc" _CallRoutine = CallRoutine������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/system/crt0.s����������������������������������������������������������0000664�0000000�0000000�00000003413�13473601511�0020267�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Startup code for GEOS ; ; Maciej 'YTM/Elysium' Witkowiak ; 26.10.99, 10.3.2000, 15.8.2001, 23.12.2002 .export _exit .export __STARTUP__ : absolute = 1 ; Mark as startup .import __STACKADDR__, __STACKSIZE__ ; Linker generated .import __BACKBUFSIZE__ ; Linker generated .import initlib, donelib .import callmain .import zerobss .importzp sp .include "jumptab.inc" .include "geossym.inc" .include "const.inc" ; ------------------------------------------------------------------------ ; Place the startup code in a special segment. .segment "STARTUP" ; GEOS 64/128 initializes the screen before starting an application while ; Apple GEOS does not. In order to provide identical startup conditions, ; we initialize the screen here, on Apple GEOS. For the same reason, we set ; the pattern and dispBufferOn, even on GEOS 64/128, although we don't use ; them here. lda #2 ; Checkerboard pattern jsr SetPattern lda #<(ST_WR_FORE | .MIN (ST_WR_BACK, __BACKBUFSIZE__)) sta dispBufferOn .ifdef __GEOS_APPLE__ jsr i_Rectangle .byte 0 .byte SC_PIX_HEIGHT-1 .word 0 .word SC_PIX_WIDTH-1 .endif ; Clear the BSS data. jsr zerobss ; Set up the stack. lda #<(__STACKADDR__ + __STACKSIZE__) ldx #>(__STACKADDR__ + __STACKSIZE__) sta sp stx sp+1 ; Call the module constructors. jsr initlib ; Push the command-line arguments; and, call main(). cli jsr callmain ; Call the module destructors. _exit: jsr donelib jmp EnterDeskTop ; Return control to the system �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/system/ctype.s���������������������������������������������������������0000664�0000000�0000000�00000046757�13473601511�0020565�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Source: The Hitchhiker's Guide To GEOS ; http://lyonlabs.org/commodore/onrequest/geos-manuals/The_Hitchhikers_Guide_to_GEOS.pdf ; ; Character specification table. ; .include "ctype.inc" .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: .byte CT_CTRL ; 0/00 ____NULL___ .byte CT_CTRL ; 1/01 ____N/A____ .byte CT_CTRL ; 2/02 ____N/A____ .byte CT_CTRL ; 3/03 ____N/A____ .byte CT_CTRL ; 4/04 ____N/A____ .byte CT_CTRL ; 5/05 ____N/A____ .byte CT_CTRL ; 6/06 ____N/A____ .byte CT_CTRL ; 7/07 ____N/A____ .byte CT_CTRL ; 8/08 __BAKSPACE_ .byte CT_CTRL | CT_OTHER_WS | CT_SPACE_TAB ; 9/09 __FWDSPACE_ .byte CT_CTRL | CT_OTHER_WS ; 10/0a _____LF____ .byte CT_CTRL ; 11/0b ____HOME___ .byte CT_CTRL ; 12/0c ___UPLINE__ .byte CT_CTRL | CT_OTHER_WS ; 13/0d _____CR____ .byte CT_CTRL ; 14/0e __ULINEON__ .byte CT_CTRL ; 15/0f __ULINEOFF_ .byte CT_CTRL ; 16/10 _ESC_GRAPH_ .byte CT_CTRL ; 17/11 ____N/A____ .byte CT_CTRL ; 18/12 ___REVON___ .byte CT_CTRL ; 19/13 ___REVOFF__ .byte CT_CTRL ; 20/14 ___GOTOX___ .byte CT_CTRL ; 21/15 ___GOTOY___ .byte CT_CTRL ; 22/16 ___GOTOXY__ .byte CT_CTRL ; 23/17 _NEWCRDSET_ .byte CT_CTRL ; 24/18 ___BOLDON__ .byte CT_CTRL ; 25/19 __ITALICON_ .byte CT_CTRL ; 26/1a _OUTLINEON_ .byte CT_CTRL ; 27/1b _PLAINTEXT_ .byte CT_CTRL ; 28/1c ____N/A____ .byte CT_CTRL ; 29/1d ____N/A____ .byte CT_CTRL ; 30/1e ____N/A____ .byte CT_CTRL ; 31/1f ____N/A____ .byte CT_SPACE_TAB | CT_SPACE ; 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 _____`_____ .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_CTRL ; 127/7f __USELAST__ .byte CT_NONE ; 128/80 __SHORTCUT_ .byte CT_NONE ; 129/81 ____N/A____ .byte CT_NONE ; 130/82 ____N/A____ .byte CT_NONE ; 131/83 ____N/A____ .byte CT_NONE ; 132/84 ____N/A____ .byte CT_NONE ; 133/85 ____N/A____ .byte CT_NONE ; 134/86 ____N/A____ .byte CT_NONE ; 135/87 ____N/A____ .byte CT_NONE ; 136/88 ____N/A____ .byte CT_NONE ; 137/89 ____N/A____ .byte CT_NONE ; 138/8a ____N/A____ .byte CT_NONE ; 139/8b ____N/A____ .byte CT_NONE ; 140/8c ____N/A____ .byte CT_NONE ; 141/8d ____N/A____ .byte CT_NONE ; 142/8e ____N/A____ .byte CT_NONE ; 143/8f ____N/A____ .byte CT_NONE ; 144/90 ____N/A____ .byte CT_NONE ; 145/91 ____N/A____ .byte CT_NONE ; 146/92 ____N/A____ .byte CT_NONE ; 147/93 ____N/A____ .byte CT_NONE ; 148/94 ____N/A____ .byte CT_NONE ; 149/95 ____N/A____ .byte CT_NONE ; 150/96 ____N/A____ .byte CT_NONE ; 151/97 ____N/A____ .byte CT_NONE ; 152/98 ____N/A____ .byte CT_NONE ; 153/99 ____N/A____ .byte CT_NONE ; 154/9a ____N/A____ .byte CT_NONE ; 155/9b ____N/A____ .byte CT_NONE ; 156/9c ____N/A____ .byte CT_NONE ; 157/9d ____N/A____ .byte CT_NONE ; 158/9e ____N/A____ .byte CT_NONE ; 159/9f ____N/A____ .byte CT_NONE ; 160/a0 ____N/A____ .byte CT_NONE ; 161/a1 ____N/A____ .byte CT_NONE ; 162/a2 ____N/A____ .byte CT_NONE ; 163/a3 ____N/A____ .byte CT_NONE ; 164/a4 ____N/A____ .byte CT_NONE ; 165/a5 ____N/A____ .byte CT_NONE ; 166/a6 ____N/A____ .byte CT_NONE ; 167/a7 ____N/A____ .byte CT_NONE ; 168/a8 ____N/A____ .byte CT_NONE ; 169/a9 ____N/A____ .byte CT_NONE ; 170/aa ____N/A____ .byte CT_NONE ; 171/ab ____N/A____ .byte CT_NONE ; 172/ac ____N/A____ .byte CT_NONE ; 173/ad ____N/A____ .byte CT_NONE ; 174/ae ____N/A____ .byte CT_NONE ; 175/af ____N/A____ .byte CT_NONE ; 176/b0 ____N/A____ .byte CT_NONE ; 177/b1 ____N/A____ .byte CT_NONE ; 178/b2 ____N/A____ .byte CT_NONE ; 179/b3 ____N/A____ .byte CT_NONE ; 180/b4 ____N/A____ .byte CT_NONE ; 181/b5 ____N/A____ .byte CT_NONE ; 182/b6 ____N/A____ .byte CT_NONE ; 183/b7 ____N/A____ .byte CT_NONE ; 184/b8 ____N/A____ .byte CT_NONE ; 185/b9 ____N/A____ .byte CT_NONE ; 186/ba ____N/A____ .byte CT_NONE ; 187/bb ____N/A____ .byte CT_NONE ; 188/bc ____N/A____ .byte CT_NONE ; 189/bd ____N/A____ .byte CT_NONE ; 190/be ____N/A____ .byte CT_NONE ; 191/bf ____N/A____ .byte CT_NONE ; 192/c0 ____N/A____ .byte CT_NONE ; 193/c1 ____N/A____ .byte CT_NONE ; 194/c2 ____N/A____ .byte CT_NONE ; 195/c3 ____N/A____ .byte CT_NONE ; 196/c4 ____N/A____ .byte CT_NONE ; 197/c5 ____N/A____ .byte CT_NONE ; 198/c6 ____N/A____ .byte CT_NONE ; 199/c7 ____N/A____ .byte CT_NONE ; 200/c8 ____N/A____ .byte CT_NONE ; 201/c9 ____N/A____ .byte CT_NONE ; 202/ca ____N/A____ .byte CT_NONE ; 203/cb ____N/A____ .byte CT_NONE ; 204/cc ____N/A____ .byte CT_NONE ; 205/cd ____N/A____ .byte CT_NONE ; 206/ce ____N/A____ .byte CT_NONE ; 207/cf ____N/A____ .byte CT_NONE ; 208/d0 ____N/A____ .byte CT_NONE ; 209/d1 ____N/A____ .byte CT_NONE ; 210/d2 ____N/A____ .byte CT_NONE ; 211/d3 ____N/A____ .byte CT_NONE ; 212/d4 ____N/A____ .byte CT_NONE ; 213/d5 ____N/A____ .byte CT_NONE ; 214/d6 ____N/A____ .byte CT_NONE ; 215/d7 ____N/A____ .byte CT_NONE ; 216/d8 ____N/A____ .byte CT_NONE ; 217/d9 ____N/A____ .byte CT_NONE ; 218/da ____N/A____ .byte CT_NONE ; 219/db ____N/A____ .byte CT_NONE ; 220/dc ____N/A____ .byte CT_NONE ; 221/dd ____N/A____ .byte CT_NONE ; 222/de ____N/A____ .byte CT_NONE ; 223/df ____N/A____ .byte CT_NONE ; 224/e0 ____N/A____ .byte CT_NONE ; 225/e1 ____N/A____ .byte CT_NONE ; 226/e2 ____N/A____ .byte CT_NONE ; 227/e3 ____N/A____ .byte CT_NONE ; 228/e4 ____N/A____ .byte CT_NONE ; 229/e5 ____N/A____ .byte CT_NONE ; 230/e6 ____N/A____ .byte CT_NONE ; 231/e7 ____N/A____ .byte CT_NONE ; 232/e8 ____N/A____ .byte CT_NONE ; 233/e9 ____N/A____ .byte CT_NONE ; 234/ea ____N/A____ .byte CT_NONE ; 235/eb ____N/A____ .byte CT_NONE ; 236/ec ____N/A____ .byte CT_NONE ; 237/ed ____N/A____ .byte CT_NONE ; 238/ee ____N/A____ .byte CT_NONE ; 239/ef ____N/A____ .byte CT_NONE ; 240/f0 ____N/A____ .byte CT_NONE ; 241/f1 ____N/A____ .byte CT_NONE ; 242/f2 ____N/A____ .byte CT_NONE ; 243/f3 ____N/A____ .byte CT_NONE ; 244/f4 ____N/A____ .byte CT_NONE ; 245/f5 ____N/A____ .byte CT_NONE ; 246/f6 ____N/A____ .byte CT_NONE ; 247/f7 ____N/A____ .byte CT_NONE ; 248/f8 ____N/A____ .byte CT_NONE ; 249/f9 ____N/A____ .byte CT_NONE ; 250/fa ____N/A____ .byte CT_NONE ; 251/fb ____N/A____ .byte CT_NONE ; 252/fc ____N/A____ .byte CT_NONE ; 253/fd ____N/A____ .byte CT_NONE ; 254/fe ____N/A____ .byte CT_NONE ; 255/ff ____N/A____ �����������������cc65-2.18/libsrc/geos-common/system/enterdesktop.s��������������������������������������������������0000664�0000000�0000000�00000000323�13473601511�0022123�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 30.10.99, 17.04.2003 ; void EnterDeskTop (void); .import _exit .export _EnterDeskTop _EnterDeskTop: lda #0 tax jmp _exit �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/system/extzp.s���������������������������������������������������������0000664�0000000�0000000�00000001001�13473601511�0020560�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak <ytm@elysium.pl> ; 31.12.2002 ; ; zeropage locations for exclusive use by the library ; .exportzp cursor_x, cursor_y .exportzp cursor_c, cursor_r .segment "EXTZP" : zeropage cursor_x: .res 2 ; Cursor column (0-319/639) cursor_y: .res 1 ; Cursor row (0-199) cursor_c: .res 1 ; Cursor column (0-39/79) cursor_r: .res 1 ; Cursor row (0-24) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/system/firstinit.s�����������������������������������������������������0000664�0000000�0000000�00000000253�13473601511�0021431�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 30.10.99 ; void FirstInit (void); .export _FirstInit .include "jumptab.inc" _FirstInit = FirstInit�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/system/getrandom.s�����������������������������������������������������0000664�0000000�0000000�00000000330�13473601511�0021372�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 30.10.1999, 2.1.2003 ; char GetRandom (void); .export _GetRandom .include "jumptab.inc" _GetRandom: jsr GetRandom ldx #0 rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/system/gettime.c�������������������������������������������������������0000664�0000000�0000000�00000001303�13473601511�0021031�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** gettime.c ** ** Maciej 'YTM/Elysium' Witkowiak, 22.11.2002 */ #include <time.h> #include <geos.h> clock_t clock(void) { struct tm currentTime; currentTime.tm_sec = system_date.s_seconds; currentTime.tm_min = system_date.s_minutes; currentTime.tm_hour = system_date.s_hour; currentTime.tm_mday = system_date.s_day; currentTime.tm_mon = system_date.s_month; currentTime.tm_year = system_date.s_year; if (system_date.s_year < 87) { currentTime.tm_year+=100; } currentTime.tm_isdst = -1; return mktime(¤tTime); } int __fastcall__ clock_gettime(clockid_t, struct timespec *tp) { tp->tv_sec = clock(); tp->tv_nsec = 0; return 0; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/system/joy_stddrv.s����������������������������������������������������0000664�0000000�0000000�00000000311�13473601511�0021600�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Name of the standard joystick driver ; ; Ullrich von Bassewitz, 2002-12-21 ; ; const char joy_stddrv[]; ; .export _joy_stddrv .rodata _joy_stddrv: .asciiz "geos-stdjoy.joy" �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/system/mainargs.s������������������������������������������������������0000664�0000000�0000000�00000003225�13473601511�0021221�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-03-07 ; Maciej Witkowiak, 2003-05-02 ; ; Setup arguments for main ; ; There is always either 1 or 3 arguments: ; <program name>, 0 ; or ; <program name>, <data file name>, <data disk name>, 0 ; the 2nd case is when using DeskTop user drags an icon of a file and drops it ; on icon of your application ; .constructor initmainargs, 24 .import __argc, __argv .include "const.inc" .include "geossym.inc" .segment "ONCE" ; Setup arguments for main initmainargs: ; Setup a pointer to our argv vector lda #<argv sta __argv lda #>argv sta __argv+1 ; Copy program name ldy #0 @fn_loop: lda dirEntryBuf+OFF_FNAME,y .ifdef __GEOS_CBM__ cmp #$a0 .else cmp #0 .endif beq @fn_end sta argv0,y iny cpy #16+1 bne @fn_loop @fn_end: lda #0 sta argv0,y sta __argc+1 ; Check if there are any more arguments lda dataFileName bne @threeargs ldx #0 ; no dataFileName - NULL the 2nd argument stx argv+2 stx argv+3 inx ; there is only one argument bne @setargc @threeargs: ldx #3 ; there are three arguments @setargc: stx __argc rts .data argv: .word argv0 ; Pointer to program name .word dataFileName ; dataFileName or NULL if last one .word dataDiskName ; dataDiskName .word $0000 ; last one must be NULL .segment "INIT" argv0: .res 17 ; Program name ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/system/mainloop.s������������������������������������������������������0000664�0000000�0000000�00000000266�13473601511�0021240�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 30.10.1999, 10.01.2003 ; void MainLoop (void); .export _MainLoop .include "jumptab.inc" _MainLoop = MainLoop ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/system/oserrlist.s�����������������������������������������������������0000664�0000000�0000000�00000006421�13473601511�0021447�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak <ytm@elysium.pl> ; 25.12.2002 ; ; Defines the platform specific error list. ; ; The table is built as a list of entries ; ; .byte entrylen ; .byte errorcode ; .asciiz errormsg ; ; and terminated by an entry with length zero that is returned if the ; error code could not be found. ; .export __sys_oserrlist .include "const.inc" ;---------------------------------------------------------------------------- ; Macros used to generate the list (may get moved to an include file?) ; Regular entry .macro sys_oserr_entry code, msg .local Start, End Start: .byte End - Start .byte code .asciiz msg End: .endmacro ; Sentinel entry .macro sys_oserr_sentinel msg .byte 0 ; Length is always zero .byte 0 ; Code is unused .asciiz msg .endmacro ;---------------------------------------------------------------------------- ; The error message table .rodata __sys_oserrlist: sys_oserr_entry NO_BLOCKS, "No free blocks" sys_oserr_entry INV_TRACK, "Illegal track or sector" sys_oserr_entry INSUFF_SPACE, "Disk full" sys_oserr_entry FULL_DIRECTORY, "Directory full" sys_oserr_entry FILE_NOT_FOUND, "File not found" sys_oserr_entry BAD_BAM, "Inconsistent BAM" sys_oserr_entry UNOPENED_VLIR, "VLIR file not opened" sys_oserr_entry INV_RECORD, "Invalid VLIR record" sys_oserr_entry OUT_OF_RECORDS, "Out of VLIR records" sys_oserr_entry STRUCT_MISMAT, "Structure mismatch" sys_oserr_entry BFR_OVERFLOW, "Buffer overflow" sys_oserr_entry CANCEL_ERR, "Operation cancelled" sys_oserr_entry DEV_NOT_FOUND, "Device not found" sys_oserr_entry INCOMPATIBLE, "Incompatible device" sys_oserr_entry 20, "Read error" sys_oserr_entry 21, "Read error" sys_oserr_entry 22, "Read error" sys_oserr_entry 23, "Read error" sys_oserr_entry 24, "Read error" sys_oserr_entry 25, "Write error" sys_oserr_entry 26, "Write protect on" sys_oserr_entry 27, "Read error" sys_oserr_entry 28, "Write error" sys_oserr_entry 29, "Disk ID mismatch" sys_oserr_entry 30, "Syntax error" sys_oserr_entry 31, "Syntax error" sys_oserr_entry 32, "Syntax error" sys_oserr_entry 33, "Syntax error (invalid file name)" sys_oserr_entry 34, "Syntax error (no file given)" sys_oserr_entry 39, "Syntax error" sys_oserr_entry 50, "Record not present" sys_oserr_entry 51, "Overflow in record" sys_oserr_entry 52, "File too large" sys_oserr_entry 60, "Write file open" sys_oserr_entry 61, "File not open" sys_oserr_entry 62, "File not found" sys_oserr_entry 63, "File exists" sys_oserr_entry 64, "File type mismatch" sys_oserr_entry 65, "No block" sys_oserr_entry 66, "Illegal track or sector" sys_oserr_entry 67, "Illegal system track or sector" sys_oserr_entry 70, "No channel" sys_oserr_entry 71, "Directory error" sys_oserr_entry 72, "Disk full" sys_oserr_entry 73, "DOS version mismatch" sys_oserr_entry 74, "Drive not ready" sys_oserr_sentinel "Unknown error" �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/system/oserror.s�������������������������������������������������������0000664�0000000�0000000�00000006135�13473601511�0021116�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 17.05.2000 ; GEOS port: Maciej 'YTM/Elysium' Witkowiak ; 2.7.2001 ; ; int __fastcall__ _osmaperrno (unsigned char oserror); ; /* Map a system specific error into a system independent code */ ; .export __osmaperrno .include "errno.inc" .include "const.inc" __osmaperrno: ldx #ErrTabSize @L1: cmp ErrTab-2,x ; Search for the error code beq @L2 ; Jump if found dex dex bne @L1 ; Next entry ; Code not found, return EINVAL lda #<EINVAL ldx #>EINVAL rts ; Found the code @L2: lda ErrTab-1,x ldx #$00 ; High byte always zero rts .rodata ErrTab: .byte NO_BLOCKS, EINVAL ; ??? .byte INV_TRACK, EINVAL ; invalid track§or pair .byte INSUFF_SPACE, ENOSPC ; out of space .byte FULL_DIRECTORY, ENOSPC ; directory is full .byte FILE_NOT_FOUND, ENOENT ; file not found .byte BAD_BAM, EIO ; bam inconsistent .byte UNOPENED_VLIR, EINVAL ; using VLIR file without opening .byte INV_RECORD, EINVAL ; using >128 VLIR record number .byte OUT_OF_RECORDS, ENOSPC ; cannot insert/add record .byte STRUCT_MISMAT, EINVAL ; ??? .byte BFR_OVERFLOW, ENOMEM ; file longer than buffer or end of file .byte CANCEL_ERR, EIO ; ??? .byte DEV_NOT_FOUND, ENODEV ; device not found .byte INCOMPATIBLE, EINVAL ; ??? ; .byte 20, ; Read error ; .byte 21, ; Read error ; .byte 22, ; Read error ; .byte 23, ; Read error ; .byte 24, ; Read error ; .byte 25, ; Write error .byte 26, EACCES ; Write protect on ; .byte 27, ; Read error ; .byte 28, ; Write error ; .byte 29, ; Disk ID mismatch ; .byte 30, ; Syntax error ; .byte 31, ; Syntax error ; .byte 32, ; Syntax error .byte 33, EINVAL ; Syntax error (invalid file name) .byte 34, EINVAL ; Syntax error (no file given) ; .byte 39, ; Syntax error ; .byte 50, ; Record not present ; .byte 51, ; Overflow in record ; .byte 52, ; File too large .byte 60, EINVAL ; Write file open .byte 61, EINVAL ; File not open .byte 62, ENOENT ; File not found .byte 63, EEXIST ; File exists .byte 64, EINVAL ; File type mismatch ; .byte 65, ; No block ; .byte 66, ; Illegal track or sector ; .byte 67, ; Illegal system track or sector .byte 70, EBUSY ; No channel ; .byte 71, ; Directory error ; .byte 72, ; Disk full ; .byte 73, ; DOS version mismatch ErrTabSize = (* - ErrTab) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/system/panic.s���������������������������������������������������������0000664�0000000�0000000�00000000237�13473601511�0020512�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Alliance' Witkowiak ; ; 30.10.99 ; void Panic (void); .export _Panic .include "jumptab.inc" _Panic = Panic�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/system/randomize.s�����������������������������������������������������0000664�0000000�0000000�00000000566�13473601511�0021415�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 05.11.2002 ; ; void _randomize (void); ; /* Initialize the random number generator */ ; .export __randomize .import _srand .include "geossym.inc" __randomize: lda random ; get random value from internal generator ldx random+1 jmp _srand ; and use it as seed ������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/system/setoserror.s����������������������������������������������������0000664�0000000�0000000�00000000516�13473601511�0021627�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Maciej 'YTM/Elysium' Witkowiak ; ; 2.1.2003 ; .export setoserror .import __oserror setoserror: stx __oserror txa ldx #0 ; X is cleared (high byte for promoting char to int) tay ; Y register is used just to save flags state rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/system/sysuname.s������������������������������������������������������0000664�0000000�0000000�00000001276�13473601511�0021270�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-08-12 ; ; unsigned char __fastcall__ _sysuname (struct utsname* buf); ; .import utscopy .export __sysuname, utsdata __sysuname = utscopy ;-------------------------------------------------------------------------- ; Data. We define a fixed utsname struct here and just copy it. .rodata utsdata: ; sysname .asciiz "cc65" ; nodename .asciiz "" ; release .byte ((.VERSION >> 8) & $0F) + '0' .byte '.' .byte ((.VERSION >> 4) & $0F) + '0' .byte $00 ; version .byte (.VERSION & $0F) + '0' .byte $00 ; machine .asciiz "GEOS" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/geos-common/system/tgi_stddrv.s����������������������������������������������������0000664�0000000�0000000�00000000271�13473601511�0021567�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Name of the standard tgi driver ; ; Oliver Schmidt, 2011-05-02 ; ; const char tgi_stddrv[]; ; .export _tgi_stddrv .rodata _tgi_stddrv: .asciiz "geos-tgi.tgi" ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/joystick/��������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015322�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/joystick/joy-kernel.s��������������������������������������������������������������0000664�0000000�0000000�00000004730�13473601511�0017571�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2002-12-20 ; ; Common functions of the joystick API. ; .import joy_libref .importzp ptr1 .include "joy-kernel.inc" .include "joy-error.inc" ;---------------------------------------------------------------------------- ; Variables .bss _joy_drv: .res 2 ; Pointer to driver ; Jump table for the driver functions. .data joy_vectors: joy_install: jmp $0000 joy_uninstall: jmp $0000 joy_count: jmp $0000 joy_read: jmp $0000 ; Driver header signature .rodata joy_sig: .byte $6A, $6F, $79, JOY_API_VERSION ; "joy", version .code ;---------------------------------------------------------------------------- ; unsigned char __fastcall__ joy_install (void* driver); ; /* Install the driver once it is loaded */ _joy_install: sta _joy_drv sta ptr1 stx _joy_drv+1 stx ptr1+1 ; Check the driver signature ldy #.sizeof(joy_sig)-1 @L0: lda (ptr1),y cmp joy_sig,y bne inv_drv dey bpl @L0 ; Set the library reference ldy #JOY_HDR::LIBREF lda #<joy_libref sta (ptr1),y iny lda #>joy_libref sta (ptr1),y ; Copy the jump vectors ldy #JOY_HDR::JUMPTAB ldx #0 @L1: inx ; Skip the JMP opcode jsr copy ; Copy one byte jsr copy ; Copy one byte cpy #(JOY_HDR::JUMPTAB + .sizeof(JOY_HDR::JUMPTAB)) bne @L1 jmp joy_install ; Call driver install routine ; Driver signature invalid inv_drv: lda #JOY_ERR_INV_DRIVER ldx #0 rts ; Copy one byte from the jump vectors copy: lda (ptr1),y iny sta joy_vectors,x inx rts ;---------------------------------------------------------------------------- ; unsigned char joy_uninstall (void); ; /* Uninstall the currently loaded driver. Note: This call does not free ; ** allocated memory. ; */ _joy_uninstall: jsr joy_uninstall ; Call the driver routine _joy_clear_ptr: ; External entry point lda #0 sta _joy_drv sta _joy_drv+1 ; Clear the driver pointer tax ; Return zero rts ����������������������������������������cc65-2.18/libsrc/joystick/joy_count.s���������������������������������������������������������������0000664�0000000�0000000�00000000371�13473601511�0017520�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2002-12-20 ; ; unsigned char joy_count (void); ; /* Return the number of joysticks supported by the driver */ ; .include "joy-kernel.inc" _joy_count = joy_count ; Use driver entry �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/joystick/joy_load.s����������������������������������������������������������������0000664�0000000�0000000�00000005750�13473601511�0017315�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2006-06-05 ; ; unsigned char __fastcall__ joy_load_driver (const char* driver); ; /* Load and install a joystick driver. Return an error code. */ .include "joy-kernel.inc" .include "joy-error.inc" .include "modload.inc" .include "fcntl.inc" .import pushax .import pusha0 .import incsp2 .import _open .import _read .import _close ;---------------------------------------------------------------------------- ; Variables .data ctrl: .addr _read .res 2 ; CALLERDATA .res 2 ; MODULE .res 2 ; MODULE_SIZE .res 2 ; MODULE_ID ;---------------------------------------------------------------------------- ; Code .code .proc _joy_load_driver ; Save name on the C stack. We will need it later as parameter passed to open() jsr pushax ; Check if we do already have a driver loaded. If so, remove it. lda _joy_drv ora _joy_drv+1 beq @L1 jsr _joy_uninstall ; Open the file. The name parameter is already on stack and will get removed ; by open(). ; ctrl.callerdata = open (name, O_RDONLY); @L1: lda #<O_RDONLY jsr pusha0 ldy #4 ; Argument size jsr _open sta ctrl + MOD_CTRL::CALLERDATA stx ctrl + MOD_CTRL::CALLERDATA+1 ; if (ctrl.callerdata >= 0) { txa bmi @L3 ; /* Load the module */ ; Res = mod_load (&ctrl); lda #<ctrl ldx #>ctrl jsr _mod_load pha ; /* Close the input file */ ; close (ctrl.callerdata); lda ctrl + MOD_CTRL::CALLERDATA ldx ctrl + MOD_CTRL::CALLERDATA+1 jsr _close ; /* Check the return code */ ; if (Res == MLOAD_OK) { pla bne @L3 ; Check the driver signature, install the driver. c is already on stack and ; will get removed by joy_install(). ; Res = joy_install (ctrl.module); lda ctrl + MOD_CTRL::MODULE ldx ctrl + MOD_CTRL::MODULE+1 jsr _joy_install ; If joy_install was successful, we're done tax beq @L2 ; The driver didn't install correctly. Remove it from memory and return the ; error code. pha ; Save the error code lda _joy_drv ldx _joy_drv+1 jsr _mod_free ; Free the driver memory jsr _joy_clear_ptr ; Clear joy_drv pla ; Restore the error code ldx #0 ; We must return an int @L2: rts ; Done ; Open or mod_load failed. Return an error code. @L3: lda #<JOY_ERR_CANNOT_LOAD ldx #>JOY_ERR_CANNOT_LOAD rts .endproc ������������������������cc65-2.18/libsrc/joystick/joy_read.s����������������������������������������������������������������0000664�0000000�0000000�00000000373�13473601511�0017305�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2002-12-20 ; ; unsigned char __fastcall__ joy_read (unsigned char joystick); ; /* Read a particular joystick */ ; .include "joy-kernel.inc" _joy_read = joy_read ; Use driver entry ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/joystick/joy_unload.s��������������������������������������������������������������0000664�0000000�0000000�00000001716�13473601511�0017656�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2002-11-29 ; ; unsigned char joy_unload (void); ; /* Unload the currently loaded driver. */ .include "joy-kernel.inc" .include "joy-error.inc" .include "modload.inc" .import joy_clear_ptr .import return0 _joy_unload: lda _joy_drv pha ; Save pointer to driver ora _joy_drv+1 beq no_driver ; No driver lda _joy_drv+1 pha jsr _joy_uninstall ; Uninstall the driver pla tax pla ; Get pointer to driver jsr _mod_free ; Free the driver jmp return0 ; Return JOY_ERR_OK no_driver: tax ; X = 0 pla ; Remove pushed junk lda #JOY_ERR_NO_DRIVER rts ��������������������������������������������������cc65-2.18/libsrc/lynx/������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014455�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/bllhdr.s����������������������������������������������������������������������0000664�0000000�0000000�00000000736�13473601511�0016116�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Karri Kaksonen, 2011 ; ; This header is required for BLL builds. ; .import __BSS_LOAD__ .import __MAIN_START__ .export __BLLHDR__: absolute = 1 ; ------------------------------------------------------------------------ ; BLL header (BLL header) .segment "BLLHDR" .word $0880 .dbyt __MAIN_START__ .dbyt __BSS_LOAD__ - __MAIN_START__ + 10 .byte $42,$53 .byte $39,$33 ����������������������������������cc65-2.18/libsrc/lynx/bootldr.s���������������������������������������������������������������������0000664�0000000�0000000�00000010717�13473601511�0016314�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Karri Kaksonen, 2011 ; ; This bootloader creates a signed binary so that the Lynx will accept it. ; .include "lynx.inc" .include "extzp.inc" .import __BANK0BLOCKSIZE__ .export __BOOTLDR__: absolute = 1 ; ------------------------------------------------------------------------ ; Bootloader .segment "BOOTLDR" ;********************************** ; Here is the bootloader in plaintext ; The idea is to make the smalles possible encrypted loader as decryption ; is very slow. The minimum size is 49 bytes plus a zero byte. ;********************************** ; EXE = $fb68 ; ; .org $0200 ; ; ; 1. force Mikey to be in memory ; stz MAPCTL ; ; ; 3. set ComLynx to open collector ; lda #4 ; a = 00000100 ; sta SERCTL ; set the ComLynx to open collector ; ; ; 4. make sure the ROM is powered on ; lda #8 ; a = 00001000 ; sta IODAT ; set the ROM power to on ; ; ; 5. read in secondary exe + 8 bytes from the cart and store it in $f000 ; ldx #0 ; x = 0 ; ldy #$97 ; y = secondary loader size (151 bytes) ;rloop1: lda RCART0 ; read a byte from the cart ; sta EXE,X ; EXE[X] = a ; inx ; x++ ; dey ; y-- ; bne rloop1 ; loops until y wraps ; ; ; 6. jump to secondary loader ; jmp EXE ; run the secondary loader ; ; .reloc ;********************************** ; After compilation, encryption and obfuscation it turns into this. ;********************************** .byte $ff, $81, $ca, $33, $be, $80, $a2, $c4 .byte $6d, $98, $fe, $8d, $bc, $66, $c0, $7a .byte $09, $50, $23, $28, $18, $c8, $06, $70 .byte $58, $4f, $1b, $e1, $c7, $90, $08, $cd .byte $1a, $6e, $5a, $45, $32, $d7, $6d, $c6 .byte $8a, $e5, $d8, $5c, $a0, $e8, $4f, $7a .byte $5f, $73, $8d, $22 ;********************************** ; Now we have the secondary loader ;********************************** .org $fb68 ; 1. Read in the 1st File-entry (main exe) in FileEntry ldx #$00 ldy #8 rloop: lda RCART0 ; read a byte from the cart sta _FileEntry,X ; EXE[X] = a inx dey bne rloop ; 2. Set the block hardware to the main exe start lda _FileStartBlock sta _FileCurrBlock jsr seclynxblock ; 3. Skip over the block offset lda _FileBlockOffset+1 eor #$FF tay lda _FileBlockOffset eor #$FF tax jsr seclynxskip0 ; 4. Read in the main exe to RAM lda _FileDestAddr ldx _FileDestAddr+1 sta _FileDestPtr stx _FileDestPtr+1 lda _FileFileLen+1 eor #$FF tay lda _FileFileLen eor #$FF tax jsr seclynxread0 ; 5. Jump to start of the main exe code jmp (_FileDestAddr) ;********************************** ; Skip bytes on bank 0 ; X:Y count (EOR $FFFF) ;********************************** seclynxskip0: inx bne @0 iny beq exit @0: jsr secreadbyte0 bra seclynxskip0 ;********************************** ; Read bytes from bank 0 ; X:Y count (EOR $ffff) ;********************************** seclynxread0: inx bne @1 iny beq exit @1: jsr secreadbyte0 sta (_FileDestPtr) inc _FileDestPtr bne seclynxread0 inc _FileDestPtr+1 bra seclynxread0 ;********************************** ; Read one byte from cartridge ;********************************** secreadbyte0: lda RCART0 inc _FileBlockByte bne exit inc _FileBlockByte+1 bne exit ;********************************** ; Select a block ;********************************** seclynxblock: pha phx phy lda __iodat and #$fc tay ora #2 tax lda _FileCurrBlock inc _FileCurrBlock sec bra @2 @0: bcc @1 stx IODAT clc @1: inx stx SYSCTL1 dex @2: stx SYSCTL1 rol sty IODAT bne @0 lda __iodat sta IODAT stz _FileBlockByte lda #<($100-(>__BANK0BLOCKSIZE__)) sta _FileBlockByte+1 ply plx pla exit: rts .reloc �������������������������������������������������cc65-2.18/libsrc/lynx/cgetc.s�����������������������������������������������������������������������0000664�0000000�0000000�00000003737�13473601511�0015740�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Karri Kaksonen, Harry Dodgson 2006-01-07 ; ; char cgetc (void); ; .export _cgetc .import _kbhit .import KBEDG .import KBSTL ; -------------------------------------------------------------------------- ; The Atari Lynx has a very small keyboard - only 3 keys ; Opt1, Opt2 and Pause. ; But the designers have decided that pressing Pause and Opt1 at the ; same time means Restart and pressing Pause and Opt2 means Flip screen. ; For "easter egg" use I have also included all three keys pressed '?' ; and Opt1 + Opt2 pressed '3'. ; So the keyboard returns '1', '2', '3', 'P', 'R', 'F' or '?'. _cgetc: lda KBSTL ora KBEDG bne @L1 jsr _kbhit ; Check for char available tax ; Test result bra _cgetc @L1: ldx #0 and #1 beq @L6 lda KBEDG ; Pause button is pressed and #$0c beq @L3 ora KBSTL @L2: bit #$04 beq @L4 ; Pause + Opt 1 = Reset bit #$08 beq @L5 ; Pause + Opt 2 = Flip lda #'?' ; All buttons pressed rts @L3: lda KBSTL ; Pause alone was the last placed button and #$0c bne @L2 lda #'P' ; Pause pressed rts @L4: lda #'R' ; Reset pressed rts @L5: lda #'F' ; Flip pressed rts @L6: lda KBEDG ; No Pause pressed ora KBSTL bit #$08 beq @L8 bit #$04 beq @L7 lda #'3' ; opt 1 + opt 2 pressed rts @L7: lda #'1' ; opt 1 pressed rts @L8: lda #'2' ; opt 2 pressed rts ���������������������������������cc65-2.18/libsrc/lynx/clock.s�����������������������������������������������������������������������0000664�0000000�0000000�00000004440�13473601511�0015736�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2003-04-13, Ullrich von Bassewitz ; 2012-02-06, Greg King ; ; #include <time.h> ; ; typedef unsigned long int clock_t; ; clock_t _clk_tck(void); ; #define CLOCKS_PER_SEC _clk_tck() ; clock_t clock(void); ; ; clk_tck()'s test-values are based on the numbers in "set_tv.s". ; If you change the numbers there, then change them here, too. ; .export _clock, __clk_tck, clock_count .interruptor update_clock, 2 ; (low priority) .constructor init_clock .import sreg: zp .include "lynx.inc" .macpack generic .proc _clock php sei ; Disable interrupts ; Read the clock counter. lda clock_count ldx clock_count+1 ldy clock_count+2 plp ; Re-enable interrupts sty sreg stz sreg+1 ; Promote 24 bits up to 32 bits rts .endproc ;----------------------------------------------------------------------------- ; Return the number of clock ticks in one second. ; __clk_tck: ldx #$00 ; >50, >60, >75 ldy PBKUP lda #<75 cpy #$20 + 1 blt @ok lda #<60 cpy #$29 + 1 blt @ok lda #<50 @ok: stz sreg ; return 32 bits stz sreg+1 rts ;----------------------------------------------------------------------------- ; This interrupt handler increments a 24-bit counter at every video ; vertical-blanking time. ; .segment "LOWCODE" update_clock: lda INTSET and #%00000100 beq @NotVBlank ; Not vertical-blank interrupt inc clock_count bne @L1 inc clock_count+1 bne @L1 inc clock_count+2 @L1: ;clc ; General interrupt was not reset @NotVBlank: rts ;----------------------------------------------------------------------------- ; Enable the interrupt that update_clock needs. ; .segment "ONCE" init_clock: lda #%10000000 tsb VTIMCTLA rts ;----------------------------------------------------------------------------- ; .bss clock_count: .res 3 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/crt0.s������������������������������������������������������������������������0000664�0000000�0000000�00000006100�13473601511�0015506�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; *** ; CC65 Lynx Library ; ; Originally by Bastian Schick ; http://www.geocities.com/SiliconValley/Byte/4242/lynx/ ; ; Ported to cc65 (http://www.cc65.org) by ; Shawn Jefferson, June 2004 ; ; *** ; ; Startup code for cc65 (Lynx version). Based on the Atari 8-bit startup ; code structure. The C stack is located at the end of the RAM memory ; segment, and grows downward. Bastian Schick's executable header is put ; on the front of the fully linked binary (see EXEHDR segment.) ; .export _exit .export __STARTUP__ : absolute = 1 ; Mark as startup .import initlib, donelib .import zerobss .import callmain .import _main .import __MAIN_START__, __MAIN_SIZE__, __STACKSIZE__ .include "zeropage.inc" .include "extzp.inc" .include "lynx.inc" ; ------------------------------------------------------------------------ ; Mikey and Suzy init data, reg offsets and data .rodata SuzyInitReg: .byte $28,$2a,$04,$06,$92,$83,$90 SuzyInitData: .byte $7f,$7f,$00,$00,$24,$f3,$01 MikeyInitReg: .byte $00,$01,$08,$09,$20,$28,$30,$38,$44,$50,$8a,$8b,$8c,$92,$93 MikeyInitData: .byte $9e,$18,$68,$1f,$00,$00,$00,$00,$00,$ff,$1a,$1b,$04,$0d,$29 ; ------------------------------------------------------------------------ ; Actual code .segment "STARTUP" ; Set up the system. sei ldx #$FF txs ; Init the bank switching. lda #$C sta MAPCTL ; $FFF9 ; Disable all timer interrupts. lda #$80 trb TIM0CTLA trb TIM1CTLA trb TIM2CTLA trb TIM3CTLA trb TIM5CTLA trb TIM6CTLA trb TIM7CTLA ; Disable the TX/RX IRQ; set to 8E1. lda #%11101 sta SERCTL ; Clear all pending interrupts. lda INTSET sta INTRST ; Set up the stack. lda #<(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__) ldx #>(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__) sta sp stx sp+1 ; Init Mickey. ldx #.sizeof(MikeyInitReg)-1 mloop: ldy MikeyInitReg,x lda MikeyInitData,x sta $fd00,y dex bpl mloop ; These are RAM-shadows of read-only regs. ldx #$1b stx __iodat dex ; $1A stx __iodir ldx #$d stx __viddma ; Init Suzy. ldx #.sizeof(SuzyInitReg)-1 sloop: ldy SuzyInitReg,x lda SuzyInitData,x sta $fc00,y dex bpl sloop lda #$24 sta __sprsys cli ; Clear the BSS data. jsr zerobss ; Call the module constructors. jsr initlib ; Push the command-line arguments; and, call main(). jsr callmain ; Call the module destructors. This is also the exit() entry. _exit: jsr donelib ; Run module destructors ; Endless loop noret: bra noret ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/ctype.s�����������������������������������������������������������������������0000664�0000000�0000000�00000015333�13473601511�0015772�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 02.06.1998 ; ; Character specification table. ; ; 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. ; ; ; Bit assignments: ; ; 0 - Lower case char ; 1 - Upper case char ; 2 - Numeric digit ; 3 - Hex digit (both, lower and upper) ; 4 - Control character ; 5 - The space character itself ; 6 - Other whitespace (that is: '\f', '\n', '\r', '\t' and '\v') ; 7 - Space or tab character .export __ctype __ctype: .repeat 2 ; 2 times for normal and inverted .byte $10 ; 0/00 ___ctrl_@___ .byte $10 ; 1/01 ___ctrl_A___ .byte $10 ; 2/02 ___ctrl_B___ .byte $10 ; 3/03 ___ctrl_C___ .byte $10 ; 4/04 ___ctrl_D___ .byte $10 ; 5/05 ___ctrl_E___ .byte $10 ; 6/06 ___ctrl_F___ .byte $10 ; 7/07 ___ctrl_G___ .byte $10 ; 8/08 ___ctrl_H___ .byte $D0 ; 9/09 ___ctrl_I___ .byte $50 ; 10/0a ___ctrl_J___ .byte $50 ; 11/0b ___ctrl_K___ .byte $50 ; 12/0c ___ctrl_L___ .byte $50 ; 13/0d ___ctrl_M___ .byte $10 ; 14/0e ___ctrl_N___ .byte $10 ; 15/0f ___ctrl_O___ .byte $10 ; 16/10 ___ctrl_P___ .byte $10 ; 17/11 ___ctrl_Q___ .byte $10 ; 18/12 ___ctrl_R___ .byte $10 ; 19/13 ___ctrl_S___ .byte $10 ; 20/14 ___ctrl_T___ .byte $10 ; 21/15 ___ctrl_U___ .byte $10 ; 22/16 ___ctrl_V___ .byte $10 ; 23/17 ___ctrl_W___ .byte $10 ; 24/18 ___ctrl_X___ .byte $10 ; 25/19 ___ctrl_Y___ .byte $10 ; 26/1a ___ctrl_Z___ .byte $10 ; 27/1b ___ctrl_[___ .byte $10 ; 28/1c ___ctrl_\___ .byte $10 ; 29/1d ___ctrl_]___ .byte $10 ; 30/1e ___ctrl_^___ .byte $10 ; 31/1f ___ctrl_____ .byte $A0 ; 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 $0C ; 48/30 _____0_____ .byte $0C ; 49/31 _____1_____ .byte $0C ; 50/32 _____2_____ .byte $0C ; 51/33 _____3_____ .byte $0C ; 52/34 _____4_____ .byte $0C ; 53/35 _____5_____ .byte $0C ; 54/36 _____6_____ .byte $0C ; 55/37 _____7_____ .byte $0C ; 56/38 _____8_____ .byte $0C ; 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 $0A ; 65/41 _____A_____ .byte $0A ; 66/42 _____B_____ .byte $0A ; 67/43 _____C_____ .byte $0A ; 68/44 _____D_____ .byte $0A ; 69/45 _____E_____ .byte $0A ; 70/46 _____F_____ .byte $02 ; 71/47 _____G_____ .byte $02 ; 72/48 _____H_____ .byte $02 ; 73/49 _____I_____ .byte $02 ; 74/4a _____J_____ .byte $02 ; 75/4b _____K_____ .byte $02 ; 76/4c _____L_____ .byte $02 ; 77/4d _____M_____ .byte $02 ; 78/4e _____N_____ .byte $02 ; 79/4f _____O_____ .byte $02 ; 80/50 _____P_____ .byte $02 ; 81/51 _____Q_____ .byte $02 ; 82/52 _____R_____ .byte $02 ; 83/53 _____S_____ .byte $02 ; 84/54 _____T_____ .byte $02 ; 85/55 _____U_____ .byte $02 ; 86/56 _____V_____ .byte $02 ; 87/57 _____W_____ .byte $02 ; 88/58 _____X_____ .byte $02 ; 89/59 _____Y_____ .byte $02 ; 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 ___grave___ .byte $09 ; 97/61 _____a_____ .byte $09 ; 98/62 _____b_____ .byte $09 ; 99/63 _____c_____ .byte $09 ; 100/64 _____d_____ .byte $09 ; 101/65 _____e_____ .byte $09 ; 102/66 _____f_____ .byte $01 ; 103/67 _____g_____ .byte $01 ; 104/68 _____h_____ .byte $01 ; 105/69 _____i_____ .byte $01 ; 106/6a _____j_____ .byte $01 ; 107/6b _____k_____ .byte $01 ; 108/6c _____l_____ .byte $01 ; 109/6d _____m_____ .byte $01 ; 110/6e _____n_____ .byte $01 ; 111/6f _____o_____ .byte $01 ; 112/70 _____p_____ .byte $01 ; 113/71 _____q_____ .byte $01 ; 114/72 _____r_____ .byte $01 ; 115/73 _____s_____ .byte $01 ; 116/74 _____t_____ .byte $01 ; 117/75 _____u_____ .byte $01 ; 118/76 _____v_____ .byte $01 ; 119/77 _____w_____ .byte $01 ; 120/78 _____x_____ .byte $01 ; 121/79 _____y_____ .byte $01 ; 122/7a _____z_____ .byte $00 ; 123/7b _____{_____ .byte $00 ; 124/7c _____|_____ .byte $00 ; 125/7d _____}_____ .byte $00 ; 126/7e _____~_____ .byte $40 ; 127/7f ____DEL____ .endrepeat �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/defdir.s����������������������������������������������������������������������0000664�0000000�0000000�00000001772�13473601511�0016105�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Karri Kaksonen, 2011 ; ; A default directory with just the main executable. ; .include "lynx.inc" .import __STARTOFDIRECTORY__ .import __MAIN_START__ .import __CODE_SIZE__, __DATA_SIZE__, __RODATA_SIZE__ .import __STARTUP_SIZE__, __ONCE_SIZE__, __LOWCODE_SIZE__ .import __BANK0BLOCKSIZE__ .export __DEFDIR__: absolute = 1 ; ------------------------------------------------------------------------ ; Lynx directory .segment "DIRECTORY" __DIRECTORY_START__: off0 = __STARTOFDIRECTORY__ + (__DIRECTORY_END__ - __DIRECTORY_START__) blocka = off0 / __BANK0BLOCKSIZE__ ; Entry 0 - first executable block0 = off0 / __BANK0BLOCKSIZE__ len0 = __STARTUP_SIZE__ + __ONCE_SIZE__ + __CODE_SIZE__ + __DATA_SIZE__ + __RODATA_SIZE__ + __LOWCODE_SIZE__ .byte <block0 .word off0 & (__BANK0BLOCKSIZE__ - 1) .byte $88 .word __MAIN_START__ .word len0 __DIRECTORY_END__: ������cc65-2.18/libsrc/lynx/eeprom.s����������������������������������������������������������������������0000664�0000000�0000000�00000013172�13473601511�0016134�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������;**************** ; CC65 Lynx Library ; ; Originally by Bastian Schick ; http://www.geocities.com/SiliconValley/Byte/4242/lynx/ ; ; Ported to cc65 (http://www.cc65.org) by ; Shawn Jefferson, June 2004 ; ; Several changes, ; Ullrich von Bassewitz, 1004-10-14 ; ; ;**************** ;* EEPROM-routs ;* for 93C46 (1024bit => 64 16-bit words) ;* ;* created : 11.05.95 ;* last modified : ;* ;* 16.02.96 leaner (thanks to Harry) ;* 12.03.96 test for busy after write and erase (well, Harry ;)) ) ;* 22.08.97 ported to ra65 for use with cc65 ;* 02.12.97 added xref for the new ra65 ;* ;* ;* (c) 1995..97 Bastian Schick ;* CS = A7 (18) ;* CLK = A1 (11) ;* DI/DO = AUDIN (32) ;* ;* And now how to contact the EEPROM : ;* ;* CARD ;* PORT ----\/---- 93C46(SMD too) ;* (18) A7 --------| CS |- +5V ;* (11) A1 --------| CLK |- NC ;* +---| DI |- NC ;* (32) AUDIN ----+---| DO |- GND ;* ---------- ;* ;**************** .export _lynx_eeprom_read .export _lynx_eeprom_write .export _lynx_eeprom_erase .import popa .importzp ptr1 .include "lynx.inc" ; ------------------------------------------------------------------------ ; EEPROM command list EE_C_WRITE = $40 EE_C_READ = $80 EE_C_ERASE = $C0 EE_C_EWEN = $30 EE_C_EWDS = $00 ; ------------------------------------------------------------------------ ; unsigned __fastcall__ lynx_eeprom_read (unsigned char cell); ; /* Read a 16 bit word from the given address */ ; _lynx_eeprom_read: and #$3f ora #EE_C_READ jsr EE_Send9Bit lda #$a sta IODIR ; set AUDIN to Input clc stz ptr1 stz ptr1+1 ; Clear result ldy #16-1 ; Initialize bit counter @L1: ; CLK = 1 stz RCART0 stz RCART0 ; CLK = 0 stz RCART0 stz RCART0 lda IODAT and #$10 ; mask bit adc #$f0 ; C=1 if A=$10 rol ptr1 rol ptr1+1 ; shifts 0 to Carry dey bpl @L1 ldx #$1a stx IODIR ; set AUDIN for output ;EE_SET_CS_LOW ldx #3 stx SYSCTL1 dex stx SYSCTL1 lda ptr1 ldy ptr1+1 ; Load result rts ; ------------------------------------------------------------------------ ; unsigned __fastcall__ lynx_eeprom_erase (unsigned char cell); ; /* Clear the word at the given address */ ; _lynx_eeprom_erase: pha ; Save argument lda #EE_C_EWEN ; EWEN jsr EE_Send9Bit pla ; Restore cell and #$3f ora #EE_C_ERASE ; clear cell A jsr EE_Send9Bit bra EE_wait ; ------------------------------------------------------------------------ ; unsigned __fastcall__ lynx_eeprom_write (unsigned char cell, unsigned val); ; /* Write the word at the given address */ ; _lynx_eeprom_write: sta ptr1 stx ptr1+1 ; Save val into ptr1 lda #EE_C_EWEN ; EWEN jsr EE_Send9Bit jsr popa ; Get cell and #$3f ; Make valid range 0..63 ora #EE_C_WRITE ; WRITE jsr EE_Send9Bit jsr EE_Send16Bit ; Send value in ptr1 EE_wait: ; EE_SET_CS_HIGH ldx #63 EEloop: stz RCART0 stz RCART0 dex bpl EEloop lda #$0A sta IODIR ; AUDIN to input lda #$10 EE_wait1: bit IODAT ; 'til ready :D0-read is /D0-written beq EE_wait1 lda #$1a ; AUDIN to output sta IODIR lda #EE_C_EWDS ; EWDS ; bra EE_Send9Bit ; fall into ; ------------------------------------------------------------------------ ; Send 8 bit value in A to eeprom EE_Send9Bit: ; EE_SET_CS_LOW ldx #3 stx SYSCTL1 dex stx SYSCTL1 ; EE_SET_CS_HIGH ldx #63 EEloop2: stz RCART0 stz RCART0 dex bpl EEloop2 ldy #8 sec ; start bit ror A ror A ror A ror A ; bit 8 at pos. 4 EEloop3: tax and #$10 ora #$b sta IODAT ; CLK = 1 stz RCART0 stz RCART0 ; CLK = 0 stz RCART0 stz RCART0 txa rol A dey bpl EEloop3 lda #$b ; fnr neue EEPROMs sta IODAT rts ; ------------------------------------------------------------------------ ; Send 16 bit value in ptr1 to eeprom EE_Send16Bit: lda ptr1+1 ror A ror ptr1 ror A ror ptr1 ror A ror ptr1 ldy #15 EEloop4: tax and #$10 ora #$b sta IODAT ; CLK = 1 stz RCART0 stz RCART0 ; CLK = 0 stz RCART0 stz RCART0 txa rol ptr1 rol A dey bpl EEloop4 ; EE_SET_CS_LOW ldx #3 stx SYSCTL1 dex stx SYSCTL1 lda #$b ; fnr neue EEPROMs sta IODAT rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/eeprom46.s��������������������������������������������������������������������0000664�0000000�0000000�00000007627�13473601511�0016316�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������;*************** ; EEPROM-routines ; for 93C46 (128 bytes as 64 16-bit words) ; ; created : 11.05.95 ; last modified : ; ; 16.02.96 leaner (thanks to Harry) ; 12.03.96 test for busy after write and erase (well, Harry ;)) ) ; 22.08.97 ported to ra65 for use with cc65 ; 02.12.97 added xref for the new ra65 ; ; ; (c) 1995..97 Bastian Schick ; CS = A7 (18) ; CLK = A1 (11) ; DI/DO = AUDIN (32) ; ;And now how to contact the EEPROM : ; ;CARD ;PORT ----\/---- 93C46(SMD too) ;(18) A7 --------| CS |- +5V ;(11) A1 --------| CLK |- NC ; +---| DI |- NC ;(32) AUDIN ----+---| DO |- GND ; ---------- .export _lynx_eeread_93c46 .export _lynx_eewrite_93c46 .import popax .importzp ptr1 .include "lynx.inc" ; ------------------- ; EEPROM command list EE_C_WRITE = $40 EE_C_READ = $80 EE_C_ERASE = $C0 EE_C_EWEN = $30 EE_C_EWDS = $00 ; ------------------------------------------------------------------------ ; unsigned __fastcall__ lynx_eeread_93c46(unsigned char cell); ; /* Read a 16 bit word from the given address */ ; _lynx_eeread_93c46: and #$3f ora #EE_C_READ jsr EE_Send9Bit jsr EE_Read16Bit lda ptr1 ldx ptr1+1 rts ;*************** ; reads EEPROM-word to ptr1 ; A,Y destroyed EE_Read16Bit: lda #$a sta IODIR ; set AUDIN to Input clc stz ptr1 stz ptr1+1 ldy #15 EEloop1: ; CLK = 1 stz RCART0 stz RCART0 ; CLK = 0 stz RCART0 stz RCART0 lda IODAT and #$10 ; mask bit adc #$f0 ; C=1 if A=$10 rol ptr1 rol ptr1+1 ; shifts 0 to Carry dey bpl EEloop1 ldx #$1a stx IODIR ; set AUDIN for output ;EE_SET_CS_LOW ldx #3 stx SYSCTL1 dex stx SYSCTL1 rts ;*************** ; write word to EEPROM ; void __fastcall__ lynx_eewrite_93c46(unsigned int addr, unsigned int val); _lynx_eewrite_93c46: sta ptr1 stx ptr1+1 lda #EE_C_EWEN jsr EE_Send9Bit jsr popax and #$3f ora #EE_C_WRITE jsr EE_Send9Bit jsr EE_Send16Bit ; Sends ptr1 that contains val EE_wait: ; EE_SET_CS_HIGH ldx #63 EEloop: stz RCART0 stz RCART0 dex bpl EEloop lda #$0A sta IODIR ; AUDIN to input lda #$10 EE_wait1: bit IODAT ; 'til ready :D0-read is /D0-written beq EE_wait1 lda #$1a ; AUDIN to output sta IODIR lda #EE_C_EWDS ; bra EE_Send9Bit ; fall into ;*************** ; send A via I2C ; A,Y destroyed ;*************** EE_Send9Bit: ; EE_SET_CS_LOW ldy #3 sty SYSCTL1 dey sty SYSCTL1 ; EE_SET_CS_HIGH ldy #63 EEloop2: stz RCART0 stz RCART0 dey bpl EEloop2 ldy #8 sec ; start bit ror A ror A ror A ror A ; bit 8 at pos. 4 EEloop3: tax and #$10 ora #$b sta IODAT ; CLK = 1 stz RCART0 stz RCART0 ; CLK = 0 stz RCART0 stz RCART0 txa rol A dey bpl EEloop3 rts ;*************** ; send ptr1 to EEPROM EE_Send16Bit: lda ptr1+1 ror A ror ptr1 ror A ror ptr1 ror A ror ptr1 ldy #15 EEloop5: tax and #$10 ora #$b sta IODAT ; CLK = 1 stz RCART0 stz RCART0 ; CLK = 0 stz RCART0 stz RCART0 txa rol ptr1 rol A dey bpl EEloop5 ; EE_SET_CS_LOW ldx #3 stx SYSCTL1 dex stx SYSCTL1 rts ���������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/eeprom66.s��������������������������������������������������������������������0000664�0000000�0000000�00000010522�13473601511�0016304�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������;*************** ; EEPROM-routines ; for 93C66 (512 bytes as 256 16-bit words) ; ; created : 11.05.95 ; last modified : ; ; 16.02.96 leaner (thanks to Harry) ; 12.03.96 test for busy after write and erase (well, Harry ;)) ) ; 22.08.97 ported to ra65 for use with cc65 ; 02.12.97 added xref for the new ra65 ; 2010 93c66 support B. Spruck ; 2011 modified to suit cc65 environment Karri Kaksonen ; ; (c) 1995..97 Bastian Schick ; CS = A7 (18) ; CLK = A1 (11) ; DI/DO = AUDIN (32) ; ;And now how to contact the EEPROM : ; ;CARD ;PORT ----\/---- 93C66(SMD too) ;(18) A7 --------| CS |- +5V ;(11) A1 --------| CLK |- NC ; +---| DI |- NC ;(32) AUDIN ----+---| DO |- GND ; ---------- .export _lynx_eeread_93c66 .export _lynx_eewrite_93c66 .import popax .importzp ptr1 .include "lynx.inc" ; ------------------- ; EEPROM command list EE_C_WRITE = $14 EE_C_READ = $18 EE_C_ERASE = $1C EE_C_EWEN = $13 EE_C_EWEN2 = $FF ;; C0 schould be enough EE_C_EWDS = $10 EE_C_EWDS2 = $00 ;************** ; Only lower byte in A is used for address ; unsigned int __fastcall__ lynx_eeread_93c66(unsigned int addr); _lynx_eeread_93c66: ldx #EE_C_READ jsr EE_Send11Bit jsr EE_Read16Bit lda ptr1 ldx ptr1+1 rts ;*************** ; reads EEPROM-word to ptr1 ; A,Y destroyed EE_Read16Bit: lda #$a sta IODIR ; set AUDIN to Input clc stz ptr1 stz ptr1+1 ldy #15 EEloop1: ; CLK = 1 stz RCART0 stz RCART0 ; CLK = 0 stz RCART0 stz RCART0 lda IODAT and #$10 ; mask bit adc #$f0 ; C=1 if A=$10 rol ptr1 rol ptr1+1 ; shifts 0 to Carry dey bpl EEloop1 ldx #$1a stx IODIR ; set AUDIN for output ;EE_SET_CS_LOW ldx #3 stx SYSCTL1 dex stx SYSCTL1 rts ;*************** ; write word to EEPROM ; void __fastcall__ lynx_eewrite_93c66(unsigned int addr, unsigned int val); _lynx_eewrite_93c66: sta ptr1 stx ptr1+1 ldx #EE_C_EWEN lda #EE_C_EWEN2 jsr EE_Send11Bit jsr popax ldx #EE_C_WRITE jsr EE_Send11Bit jsr EE_Send16Bit ; Sends ptr1 that contains val EE_wait: ; EE_SET_CS_HIGH ldx #63 EEloop: stz RCART0 stz RCART0 dex bpl EEloop lda #$0A sta IODIR ; AUDIN to input lda #$10 EE_wait1: bit IODAT ; 'til ready :D0-read is /D0-written beq EE_wait1 lda #$1a ; AUDIN to output sta IODIR ldx #EE_C_EWDS lda #EE_C_EWDS2 ; bra EE_Send11Bit ; fall into ;*************** ; send A via I2C ; A,Y destroyed EE_Send11Bit: ; EE_SET_CS_LOW ldy #3 sty SYSCTL1 dey sty SYSCTL1 ; EE_SET_CS_HIGH ldy #63 EEloop2: stz RCART0 stz RCART0 dey bpl EEloop2 pha txa ;; Ok erstmal x abarbeiten und A sichern ldy #2 ; 3 times EEloop3: tax and #$10 ora #$b sta IODAT ; CLK = 1 stz RCART0 stz RCART0 ; CLK = 0 stz RCART0 stz RCART0 txa rol A dey bpl EEloop3 ldy #7 ; 8 times pla ;; jetzt kommt a an die reihe ror A ror A ror A ; bit 7 at pos. 4 EEloop4: tax and #$10 ora #$b sta IODAT ; CLK = 1 stz RCART0 stz RCART0 ; CLK = 0 stz RCART0 stz RCART0 txa rol A dey bpl EEloop4 rts ;*************** ; send ptr1 to EEPROM EE_Send16Bit: lda ptr1+1 ror A ror ptr1 ror A ror ptr1 ror A ror ptr1 ldy #15 EEloop5: tax and #$10 ora #$b sta IODAT ; CLK = 1 stz RCART0 stz RCART0 ; CLK = 0 stz RCART0 stz RCART0 txa rol ptr1 rol A dey bpl EEloop5 ; EE_SET_CS_LOW ldx #3 stx SYSCTL1 dex stx SYSCTL1 rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/eeprom86.s��������������������������������������������������������������������0000664�0000000�0000000�00000010717�13473601511�0016314�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������;*************** ; EEPROM-routs ; for 93C86 (2048 bytes as 1024 16-bit words) ; ; created : 11.05.95 ; last modified : ; ; 16.02.96 leaner (thanks to Harry) ; 12.03.96 test for busy after write and erase (well, Harry ;)) ) ; 22.08.97 ported to ra65 for use with cc65 ; 02.12.97 added xref for the new ra65 ; 2010 93c66 support B. Spruck ; 2010 93c86 support B. Spruck ; 2011 modified to suit cc65 environment Karri Kaksonen ; ; (c) 1995..97 Bastian Schick ; CS = A7 (18) ; CLK = A1 (11) ; DI/DO = AUDIN (32) ; ;And now how to contact the EEPROM : ; ;CARD ;PORT ----\/---- 93C86(SMD too) ;(18) A7 --------| CS |- +5V ;(11) A1 --------| CLK |- NC ; +---| DI |- NC ;(32) AUDIN ----+---| DO |- GND ; ---------- .export _lynx_eeread_93c86 .export _lynx_eewrite_93c86 .import popax .importzp ptr1 .include "lynx.inc" ; ------------------- ; EEPROM command list EE_C_WRITE = $14 EE_C_READ = $18 EE_C_ERASE = $1C EE_C_EWEN = $13 EE_C_EWEN2 = $FF ;; C0 schould be enough EE_C_EWDS = $10 EE_C_EWDS2 = $00 ;************** ; Only lower byte in A is used for address ; unsigned int __fastcall__ lynx_eeread_93c86(unsigned int addr); _lynx_eeread_93c86: pha txa ora #EE_C_READ tax pla jsr EE_Send13Bit jsr EE_Read16Bit lda ptr1 ldx ptr1+1 rts ;*************** ; reads EEPROM-word to ptr1 ; A,Y destroyed EE_Read16Bit: lda #$a sta IODIR ; set AUDIN to Input clc stz ptr1 stz ptr1+1 ldy #15 EEloop1: ; CLK = 1 stz RCART0 stz RCART0 ; CLK = 0 stz RCART0 stz RCART0 lda IODAT and #$10 ; mask bit adc #$f0 ; C=1 if A=$10 rol ptr1 rol ptr1+1 ; shifts 0 to Carry dey bpl EEloop1 ldx #$1a stx IODIR ; set AUDIN for output ;EE_SET_CS_LOW ldx #3 stx SYSCTL1 dex stx SYSCTL1 rts ;*************** ; write word to EEPROM ; void __fastcall__ lynx_eewrite_93c86(unsigned int addr, unsigned int val); _lynx_eewrite_93c86: sta ptr1 stx ptr1+1 ldx #EE_C_EWEN lda #EE_C_EWEN2 jsr EE_Send13Bit jsr popax pha txa ora #EE_C_WRITE tax pla jsr EE_Send13Bit jsr EE_Send16Bit ; Sends ptr1 that contains val EE_wait: ; EE_SET_CS_HIGH ldx #63 EEloop: stz RCART0 stz RCART0 dex bpl EEloop lda #$0A sta IODIR ; AUDIN to input lda #$10 EE_wait1: bit IODAT ; 'til ready :D0-read is /D0-written beq EE_wait1 lda #$1a ; AUDIN to output sta IODIR ldx #EE_C_EWDS lda #EE_C_EWDS2 ; bra EE_Send13Bit ; fall into ;*************** ; send A via I2C ; A,Y destroyed EE_Send13Bit: ; EE_SET_CS_LOW ldy #3 sty SYSCTL1 dey sty SYSCTL1 ; EE_SET_CS_HIGH ldy #63 EEloop2: stz RCART0 stz RCART0 dey bpl EEloop2 pha txa ;; Ok erstmal x abarbeiten und A sichern ldy #4 ; 5 times EEloop3: tax and #$10 ora #$b sta IODAT ; CLK = 1 stz RCART0 stz RCART0 ; CLK = 0 stz RCART0 stz RCART0 txa rol A dey bpl EEloop3 ldy #7 ; 8 times pla ;; jetzt kommt a an die reihe ror A ror A ror A ; bit 7 at pos. 4 EEloop4: tax and #$10 ora #$b sta IODAT ; CLK = 1 stz RCART0 stz RCART0 ; CLK = 0 stz RCART0 stz RCART0 txa rol A dey bpl EEloop4 rts ;*************** ; send ptr1 to EEPROM EE_Send16Bit: lda ptr1+1 ror A ror ptr1 ror A ror ptr1 ror A ror ptr1 ldy #15 EEloop5: tax and #$10 ora #$b sta IODAT ; CLK = 1 stz RCART0 stz RCART0 ; CLK = 0 stz RCART0 stz RCART0 txa rol ptr1 rol A dey bpl EEloop5 ; EE_SET_CS_LOW ldx #3 stx SYSCTL1 dex stx SYSCTL1 rts �������������������������������������������������cc65-2.18/libsrc/lynx/exec.s������������������������������������������������������������������������0000664�0000000�0000000�00000001514�13473601511�0015566�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Karri Kaksonen, 2010 ; ; lynx_exec(fileno) loads a file into memory but after the read the CPU ; does a jump into the loaded start address. ; ; lynx_exec is often used in compilation carts when you run small demos ; created with various (non-cc65) compilers. ; ; void lynx_exec(int fileno) ; .importzp _FileDestAddr .import pushax,ldax0sp,incsp2 .import _lynx_load .export _lynx_exec ; --------------------------------------------------------------- ; void __near__ __fastcall__ lynx_exec (int) ; --------------------------------------------------------------- .segment "CODE" .proc _lynx_exec: near .segment "CODE" jsr pushax jsr ldax0sp jsr _lynx_load jsr incsp2 jmp (_FileDestAddr) .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/exehdr.s����������������������������������������������������������������������0000664�0000000�0000000�00000001754�13473601511�0016127�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Karri Kaksonen, 2011 ; ; This header contains data for emulators like Handy and Mednafen ; .import __BANK0BLOCKSIZE__ .import __BANK1BLOCKSIZE__ .export __EXEHDR__: absolute = 1 ; ------------------------------------------------------------------------ ; EXE header .segment "EXEHDR" .byte 'L','Y','N','X' ; magic .word __BANK0BLOCKSIZE__ ; bank 0 page size .word __BANK1BLOCKSIZE__ ; bank 1 page size .word 1 ; version number .asciiz "Cart name " ; 32 bytes cart name .asciiz "Manufacturer " ; 16 bytes manufacturer .byte 0 ; rotation 1=left ; rotation 2=right .byte 0,0,0,0,0 ; spare ��������������������cc65-2.18/libsrc/lynx/extzp.inc���������������������������������������������������������������������0000664�0000000�0000000�00000001607�13473601511�0016326�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; extzp.inc for the Lynx ; ; Ullrich von Bassewitz, 2004-11-06 ; ; Assembler include file that imports the runtime zero page locations used ; by the Lynx runtime, ready for usage in asm code. ; .global __iodat: zp .global __iodir: zp .global __viddma: zp .global __sprsys: zp .global _abc_score_ptr0: zp .global _abc_score_ptr1: zp .global _abc_score_ptr2: zp .global _abc_score_ptr3: zp .global _FileEntry: zp .global _FileStartBlock: zp .global _FileBlockOffset: zp .global _FileExecFlag: zp .global _FileDestAddr: zp .global _FileFileLen: zp .global _FileCurrBlock: zp .global _FileBlockByte: zp .global _FileDestPtr: zp �������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/extzp.s�����������������������������������������������������������������������0000664�0000000�0000000�00000002022�13473601511�0016007�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2004-11-06 ; ; zeropage locations for exclusive use by the library ; .include "extzp.inc" .segment "EXTZP" : zeropage ; ------------------------------------------------------------------------ ; mikey and suzy shadow registers __iodat: .res 1 __iodir: .res 1 __viddma: .res 1 __sprsys: .res 1 ; ------------------------------------------------------------------------ ; sound effect pointers for multitimbral Lynx music hardware _abc_score_ptr0: .res 2 _abc_score_ptr1: .res 2 _abc_score_ptr2: .res 2 _abc_score_ptr3: .res 2 ; ------------------------------------------------------------------------ ; Filesystem variables needed for reading stuff from the Lynx cart _FileEntry: ; The file directory entry is 8 bytes _FileStartBlock: .res 1 _FileBlockOffset: .res 2 _FileExecFlag: .res 1 _FileDestAddr: .res 2 _FileFileLen: .res 2 _FileCurrBlock: .res 1 _FileBlockByte: .res 2 _FileDestPtr: .res 2 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/irq.s�������������������������������������������������������������������������0000664�0000000�0000000�00000001510�13473601511�0015431�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; IRQ handling (Lynx version) ; .export initirq, doneirq .import callirq .include "lynx.inc" ; ------------------------------------------------------------------------ .segment "ONCE" initirq: lda #<IRQStub ldx #>IRQStub sei sta INTVECTL stx INTVECTH cli rts ; ------------------------------------------------------------------------ .code doneirq: ; as Lynx is a console there is not much point in releasing the IRQ rts ; ------------------------------------------------------------------------ .segment "LOWCODE" IRQStub: phy phx pha jsr callirq lda INTSET sta INTRST pla plx ply rti ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/joy/��������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015256�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/joy/lynx-stdjoy.s�������������������������������������������������������������0000664�0000000�0000000�00000004356�13473601511�0017756�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Standard joystick driver for the Atari Lynx. ; The Lynx has two fire buttons. So it is not quite "standard". ; ; Modified by Karri Kaksonen, 2004-09-16 ; Ullrich von Bassewitz, 2002-12-20 ; Using code from Steve Schmidtke ; .include "zeropage.inc" .include "joy-kernel.inc" .include "joy-error.inc" .include "lynx.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _lynx_stdjoy_joy ; Driver signature .byte $6A, $6F, $79 ; "joy" .byte JOY_API_VERSION ; Driver API version number ; Library reference .addr $0000 ; Jump table. .addr INSTALL .addr UNINSTALL .addr COUNT .addr READ ; ------------------------------------------------------------------------ ; Constants JOY_COUNT = 1 ; Number of joysticks we support ; ------------------------------------------------------------------------ ; Data. .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 ; ------------------------------------------------------------------------ ; UNINSTALL 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. ; COUNT: lda #<JOY_COUNT ldx #>JOY_COUNT rts ; ------------------------------------------------------------------------ ; READ: Read a particular joystick passed in A. READ: ldx #$00 ; Clear high byte lda JOYSTICK ; Read joystick and #$F3 ; Mask relevant keys rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/joy_stat_stddrv.s�������������������������������������������������������������0000664�0000000�0000000�00000000356�13473601511�0020067�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Address of the static standard joystick driver ; ; Oliver Schmidt, 2012-11-01 ; ; const void joy_static_stddrv[]; ; .export _joy_static_stddrv .import _lynx_stdjoy_joy .rodata _joy_static_stddrv := _lynx_stdjoy_joy ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/kbhit.s�����������������������������������������������������������������������0000664�0000000�0000000�00000003066�13473601511�0015747�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Karri Kaksonen, Harry Dodgson 2006-01-06 ; ; unsigned char kbhit (void); ; .export _kbhit .export KBEDG .export KBSTL .import return1 ; -------------------------------------------------------------------------- ; The Atari Lynx has a very small keyboard - only 3 keys ; Opt1, Opt2 and Pause. ; But the designers have decided that pressing Pause and Opt1 at the ; same time means Restart and pressing Pause and Opt2 means Flip screen. ; For "easter egg" use I have also included all three keys pressed '?' ; and Opt1 + Opt2 pressed '3'. ; So the keyboard returns '1', '2', '3', 'P', 'R', 'F' or '?'. .data KBTMP: .byte 0 KBPRV: .byte 0 KBEDG: .byte 0 KBSTL: .byte 0 KBDEB: .byte 0 KBNPR: .byte 0 .code _kbhit: lda $FCB0 ; Read the Opt buttons and #$0c sta KBTMP lda $FCB1 ; Read Pause and #1 ora KBTMP ; 0000210P tax and KBPRV sta KBSTL ; for multibutton txa and KBDEB sta KBEDG ; for just depressed txa and KBNPR sta KBDEB ; for debouncing txa eor #$ff sta KBNPR ; inverted previous ones pressed stx KBPRV lda KBEDG beq @L1 jmp return1 ; Key hit @L1: tax ; No new keys hit rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/libref.s����������������������������������������������������������������������0000664�0000000�0000000�00000000242�13473601511�0016102�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2013-05-31 ; .export joy_libref, ser_libref .import _exit joy_libref := _exit ser_libref := _exit ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/load.s������������������������������������������������������������������������0000664�0000000�0000000�00000002016�13473601511�0015557�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Karri Kaksonen, 2010 ; ; lynx_load(fileno) is a convenience function that is widely used on the Lynx. ; Basically this opens directory entry fileno and reads the content of the ; file this points to into RAM. ; ; void lynx_load(int fileno) ; .importzp _FileFileLen .importzp _FileDestAddr .import pushax,ldax0sp,pusha0,incsp2 .import _openn .import _read .export _lynx_load ; --------------------------------------------------------------- ; void __near__ __fastcall__ lynx_load (int) ; --------------------------------------------------------------- .segment "CODE" .proc _lynx_load: near .segment "CODE" jsr pushax jsr ldax0sp jsr _openn lda #$01 jsr pusha0 lda _FileDestAddr ldx _FileDestAddr+1 jsr pushax lda _FileFileLen ldx _FileFileLen+1 jsr _read jmp incsp2 .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/lseek.s�����������������������������������������������������������������������0000664�0000000�0000000�00000002754�13473601511�0015754�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Karri Kaksonen, 2010 ; ; This function is used to place the Lynx hardware to point to any byte in ; the Lynx cart. ; ; This function supports all available block sizes (512, 1024 and 2048 bytes). ; No other block sizes have been used afaik. ; ; Only SEEK_SET operation mode is implemented. ; ; off_t __fastcall__ lseek(int fd, off_t offset, int whence); .importzp sp, sreg, regsave, regbank, tmp1, ptr1, ptr2 .macpack longbranch .export _lseek .import addysp, stax0sp, tosand0ax, pusheax, asreax2 .import ldeaxysp, decsp2, pushax, incsp8 .import tosandeax,decax1,tosdiveax,axlong,ldaxysp .import lynxskip0, lynxblock,tosasreax .import __BLOCKSIZE__ .importzp _FileCurrBlock .segment "CODE" .proc _lseek: near .segment "CODE" jsr pushax ldy #$05 jsr ldeaxysp jsr pusheax ldx #$00 lda #<(__BLOCKSIZE__/1024 + 9) jsr tosasreax sta _FileCurrBlock jsr lynxblock ldy #$05 jsr ldeaxysp jsr pusheax lda #<(__BLOCKSIZE__-1) ldx #>(__BLOCKSIZE__-1) jsr axlong jsr tosandeax eor #$FF pha txa eor #$FF tay plx jsr lynxskip0 ldy #$05 jsr ldeaxysp jmp incsp8 .endproc ��������������������cc65-2.18/libsrc/lynx/lynx-cart.s�������������������������������������������������������������������0000664�0000000�0000000�00000003772�13473601511�0016573�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; *** ; CC65 Lynx Library ; ; Originally by Bastian Schick ; http://www.geocities.com/SiliconValley/Byte/4242/lynx/ ; ; Ported to cc65 (http://www.cc65.org) by ; Shawn Jefferson, June 2004 ; ; This version by Karri Kaksonen, December 2010 ; ; Helper stuff for the cartridge file functions. This version can deal ; with 1024 bytes/block carts that are using CART0 as a read strobe. ; Also the default crt0.s supports this most common Lynx cart format. .include "lynx.inc" .include "extzp.inc" .export lynxskip0, lynxread0 .export lynxblock .import __BLOCKSIZE__ .code ;********************************** ; Skip bytes on bank 0 ; X:Y count (EOR $FFFF) ;********************************** lynxskip0: inx bne @0 iny beq exit @0: jsr readbyte0 bra lynxskip0 ;********************************** ; Read bytes from bank 0 ; X:Y count (EOR $ffff) ;********************************** lynxread0: inx bne @1 iny beq exit @1: jsr readbyte0 sta (_FileDestPtr) inc _FileDestPtr bne lynxread0 inc _FileDestPtr+1 bra lynxread0 ;********************************** ; Read one byte from cartridge ;********************************** readbyte0: lda RCART0 inc _FileBlockByte bne exit inc _FileBlockByte+1 bne exit ;********************************** ; Select a block ;********************************** lynxblock: pha phx phy lda __iodat and #$fc tay ora #2 tax lda _FileCurrBlock inc _FileCurrBlock sec bra @2 @0: bcc @1 stx IODAT clc @1: inx stx SYSCTL1 dex @2: stx SYSCTL1 rol sty IODAT bne @0 lda __iodat sta IODAT stz _FileBlockByte lda #<($100-(>__BLOCKSIZE__)) sta _FileBlockByte+1 ply plx pla exit: rts ������cc65-2.18/libsrc/lynx/lynx-snd.s��������������������������������������������������������������������0000664�0000000�0000000�00000100273�13473601511�0016420�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Sound driver for the Atari Lynx. ; ; Karri Kaksonen and Bjoern Spruck, 11.12.2012 ; .include "lynx.inc" .include "zeropage.inc" .export _lynx_snd_init .export _lynx_snd_active .export _lynx_snd_play .export _lynx_snd_stop .export _lynx_snd_stop_channel .export _lynx_snd_pause .export _lynx_snd_continue .interruptor lynx_snd_handler .import popa .importzp ptr1 ;---------------------------------------------------------------------------- ; ZP variables that go into APPZP ; .segment "APPZP" : zeropage SndSema: .res 1 SndPtrTmp: .res 2 SndTmp: .res 2 SndEnvPtr: .res 2 ;---------------------------------------------------------------------------- ; Global variables ; .bss SndRetAFlag2: .res 1 SndRetAFlag: .res 1 SndPtrLo: .res 4 SndPtrHi: .res 4 SndDelay: .res 4 SndLoopCnt: .res 4 SndLoopPtrLo: .res 4 SndLoopPtrHi: .res 4 SndVolume: .res 4 SndMaxVolume: .res 4 SndNotePlaying: .res 4 SndRetAddr: .res 8 SndActive: .res 4 SndReqStop: .res 4 SndEnvVol: .res 4 SndEnvFrq: .res 4 SndEnvWave: .res 4 SndChannel: .res 32 SndEnvVolCnt: .res 4 SndEnvVolInc: .res 4 SndEnvVolOff: .res 4 SndEnvVolLoop: .res 4 SndEnvVolParts: .res 4 SndEnvVolParts2: .res 4 SndEnvFrqCnt: .res 4 SndEnvFrqInc: .res 4 SndEnvFrqOff: .res 4 SndEnvFrqLoop: .res 4 SndEnvFrqParts: .res 4 SndEnvFrqParts2: .res 4 SndEnvWaveCnt: .res 4 SndEnvWaveOff: .res 4 SndEnvWaveLoop: .res 4 SndEnvWaveParts: .res 4 SndEnvWaveParts2: .res 4 MAX_INSTRUMENTS .set 64 SndEnvVolPtrLo: .res MAX_INSTRUMENTS SndEnvVolPtrHi: .res MAX_INSTRUMENTS SndEnvFrqPtrLo: .res MAX_INSTRUMENTS SndEnvFrqPtrHi: .res MAX_INSTRUMENTS SndEnvWavePtrLo: .res MAX_INSTRUMENTS SndEnvWavePtrHi: .res MAX_INSTRUMENTS .rodata SndOffsets: .byte $00,$08,$10,$18 ;---------------------------------------------------------------------------- ; Macros ; if_count .set 0 nest_count .set 0 .macro _IFNE if_count .set if_count +1 nest_count .set nest_count +1 beq .ident (.sprintf ("else%04d", if_count)) .ident (.sprintf ("push%04d", nest_count)) .set if_count .endmacro .macro _IFEQ if_count .set if_count +1 nest_count .set nest_count +1 bne .ident (.sprintf ("else%04d", if_count)) .ident (.sprintf ("push%04d", nest_count)) .set if_count .endmacro .macro _IFMI if_count .set if_count +1 nest_count .set nest_count +1 bpl .ident (.sprintf ("else%04d", if_count)) .ident (.sprintf ("push%04d", nest_count)) .set if_count .endmacro .macro _IFPL if_count .set if_count +1 nest_count .set nest_count +1 bmi .ident (.sprintf ("else%04d", if_count)) .ident (.sprintf ("push%04d", nest_count)) .set if_count .endmacro .macro _IFGE if_count .set if_count +1 nest_count .set nest_count +1 bcc .ident (.sprintf ("else%04d", if_count)) .ident (.sprintf ("push%04d", nest_count)) .set if_count .endmacro .macro _IFCS if_count .set if_count +1 nest_count .set nest_count +1 bcc .ident (.sprintf ("else%04d", if_count)) .ident (.sprintf ("push%04d", nest_count)) .set if_count .endmacro .macro _IFCC if_count .set if_count +1 nest_count .set nest_count +1 bcs .ident (.sprintf ("else%04d", if_count)) .ident (.sprintf ("push%04d", nest_count)) .set if_count .endmacro .macro _ELSE bra .ident (.sprintf ("endif%04d", .ident (.sprintf ("push%04d", nest_count)))) .ident (.sprintf ("else%04d", .ident (.sprintf ("push%04d", nest_count)))) := * .endmacro .macro _ENDIF .if .not .defined( .ident (.sprintf ("else%04d", .ident (.sprintf ("push%04d", nest_count))))) .ident (.sprintf ("else%04d", .ident (.sprintf ("push%04d", nest_count)))) := * .endif .ident (.sprintf ("endif%04d", .ident (.sprintf ("push%04d", nest_count)))) := * nest_count .set nest_count -1 .endmacro .code ;---------------------------------------------------------------------------- ; void lynx_snd_init() will initialize the sound engine. ; _31250Hz .set %101 _lynx_snd_init: php sei lda #%10011000|_31250Hz sta STIMCTLA lda #129 sta STIMBKUP ; set up a 240Hz IRQ stz AUD0VOL stz AUD1VOL stz AUD2VOL stz AUD3VOL stz $fd44 ; all channels full volume / no attenuation lda #$ff stz MSTEREO lda #0 sta AUD0CTLA sta AUD1CTLA sta AUD2CTLA sta AUD3CTLA ldx #3 lda #0 init0: stz SndActive,x stz SndReqStop,x stz SndEnvVol,x stz SndEnvFrq,x stz SndEnvWave,x ldy SndOffsets,x sta SndChannel+2,y dex bpl init0 stz SndRetAFlag stz SndRetAFlag2 stz SndSema plp rts ;---------------------------------------------------------------------------- ; lynx_snd_handler is run at every sound interrupt ; lynx_snd_handler: lda INTSET and #SND_INTERRUPT bne @L0 clc rts @L0: lda #$ff tsb SndSema bne endirq phy ; *NOW* set all values which were "pre-set" in last interrupt jsr SndSetValues cli lda SndRetAFlag ; reset the return flag, but save it first _IFNE lda #$0F ; MASK sta SndRetAFlag2 stz SndRetAFlag _ENDIF ldx #3 irq0: phx lda SndActive,x _IFNE lda SndEnvVol,x _IFNE phx jsr SndChangeVol plx _ENDIF lda SndEnvFrq,x _IFNE phx jsr SndChangeFrq plx _ENDIF lda SndEnvWave,x _IFNE phx jsr SndChangeWave plx _ENDIF jsr SndGetCmd _ENDIF plx dex bpl irq0 sei ply stz SndSema endirq: clc rts ;---------------------------------------------------------------------------- ; A process table with addresses to sound functions ; SndCmdsLo: .byte <((SndLoop)-1) .byte <((SndDo)-1) .byte <((SndPause)-1) .byte <((SndNoteOff)-1) .byte <((SndSetInstr)-1) .byte <((SndNewNote2)-1) .byte <((SndCallPattern)-1) .byte <((SndRetToSong)-1) .byte <((SndDefEnvVol)-1) .byte <((SndSetEnvVol)-1) .byte <((SndDefEnvFrq)-1) .byte <((SndSetEnvFrq)-1) .byte <((SndDefEnvWave)-1) .byte <((SndSetEnvWave)-1) .byte <((SndSetStereo)-1) .byte <((SndSetAttenuationOn)-1) .byte <((SndSetChnAttenution)-1) .byte <((SndPlayerFreq)-1) .byte <((SndReturnAll)-1) SndCmdsHi: .byte >((SndLoop)-1) .byte >((SndDo)-1) .byte >((SndPause)-1) .byte >((SndNoteOff)-1) .byte >((SndSetInstr)-1) .byte >((SndNewNote2)-1) .byte >((SndCallPattern)-1) .byte >((SndRetToSong)-1) .byte >((SndDefEnvVol)-1) .byte >((SndSetEnvVol)-1) .byte >((SndDefEnvFrq)-1) .byte >((SndSetEnvFrq)-1) .byte >((SndDefEnvWave)-1) .byte >((SndSetEnvWave)-1) .byte >((SndSetStereo)-1) .byte >((SndSetAttenuationOn)-1) .byte >((SndSetChnAttenution)-1) .byte >((SndPlayerFreq)-1) .byte >((SndReturnAll)-1) ;---------------------------------------------------------------------------- ; Get next sound command from stream ; SndGetCmd: lda SndReqStop,x bne SndStop lda SndRetAFlag2 and SndMask,x _IFNE eor SndRetAFlag2 sta SndRetAFlag2 lda SndRetAddr,x sta SndPtrLo,x lda SndRetAddr+4,x sta SndPtrHi,x ;;; force the direct continue return _ELSE dec SndDelay,x bne cmd991 ;; check special case _ENDIF lda SndPtrLo,x sta SndPtrTmp lda SndPtrHi,x sta SndPtrTmp+1 cmd0: lda (SndPtrTmp) beq SndStop _IFMI and #$7f tay jsr SndCallCmd _ELSE jsr SndNewNote _ENDIF clc tya and #$7f adc SndPtrTmp sta SndPtrLo,x sta SndPtrTmp lda #0 adc SndPtrTmp+1 sta SndPtrHi,x sta SndPtrTmp+1 tya bmi cmd0 cmd991: ;; now check if delay is only 1 AND next one is return all. lda #1 cmp SndDelay,x bne cmd99 ;; NOW read ahead ONE lda SndPtrLo,x sta SndPtrTmp lda SndPtrHi,x sta SndPtrTmp+1 lda (SndPtrTmp) cmp #$92 ;; Return all _IFEQ sta SndRetAFlag ; just set !=0 _ENDIF cmd99: rts ;---------------------------------------------------------------------------- ; Call function pointed to by y ; SndCallCmd: lda SndCmdsHi,y pha lda SndCmdsLo,y pha ldy #1 rts ;---------------------------------------------------------------------------- ; Stop sound on one channel ; SndStop: stz SndReqStop,x stz SndActive,x ldy SndOffsets,x lda #0 sta SndChannel,y ina ;lda #1 sta SndChannel+2,y tay ;ldy #1 rts ;---------------------------------------------------------------------------- ; Send a new note, length, volume triplet ; SndNewNote: phx sta SndNotePlaying,x pha ldy #1 lda (SndPtrTmp),y sta SndDelay,x ldy SndOffsets,x lda SndVolume,x sta SndChannel,y plx lda SndPrescaler,x sta SndChannel+5,y lda SndReload,x sta SndChannel+4,y lda #$FF ; = -1 sta SndChannel+2,y plx lda SndEnvVol,x _IFNE jsr SndSetEnvVol1 _ENDIF lda SndEnvFrq,x _IFNE jsr SndSetEnvFrq1 _ENDIF lda SndEnvWave,x _IFNE jsr SndSetEnvWave1 _ENDIF lda #$2 ldy SndDelay,x _IFNE ora #$80 _ENDIF tay rts ;---------------------------------------------------------------------------- ; Start a loop with count ; SndLoop: lda (SndPtrTmp),y sta SndLoopCnt,x lda SndPtrTmp sta SndLoopPtrLo,x lda SndPtrTmp+1 sta SndLoopPtrHi,x ldy #$82 rts SndDo: dec SndLoopCnt,x _IFNE lda SndLoopPtrLo,x sta SndPtrTmp lda SndLoopPtrHi,x sta SndPtrTmp+1 ldy #$82 _ELSE ldy #$81 _ENDIF rts ;---------------------------------------------------------------------------- ; Sound volume envelope ; SndDefEnvVol: phx lda (SndPtrTmp),y ; env # tax iny lda (SndPtrTmp),y sta SndEnvVolPtrLo,x iny lda (SndPtrTmp),y sta SndEnvVolPtrHi,x ; Ptr to [cnt,inc] ldy #$84 plx rts SndSetEnvVol: lda (SndPtrTmp),y ; # env SndSetEnvVol1: and #$7f sta SndEnvVol,x ; save _IFEQ ldy #$82 rts _ENDIF tay lda SndEnvVolPtrLo,y sta SndEnvPtr lda SndEnvVolPtrHi,y sta SndEnvPtr+1 lda (SndEnvPtr) sta SndTmp asl sta SndEnvVolLoop,x ; here is the loop-start ldy #1 lda (SndEnvPtr),y sta SndEnvVolParts,x sec sbc SndTmp sta SndEnvVolParts2,x stz SndEnvVolCnt,x lda #2 sta SndEnvVolOff,x ldy #$82 rts ;---------------------------------------------------------------------------- ; Sound frequency envelope ; SndDefEnvFrq: phx lda (SndPtrTmp),y ; env # tax iny lda (SndPtrTmp),y sta SndEnvFrqPtrLo,x iny lda (SndPtrTmp),y sta SndEnvFrqPtrHi,x ; Ptr to [inc,cnt] plx ldy #$84 rts SndSetEnvFrq: lda (SndPtrTmp),y ; # env SndSetEnvFrq1: and #$7f sta SndEnvFrq,x ; save _IFEQ ldy #$82 rts _ENDIF tay lda SndEnvFrqPtrLo,y sta SndEnvPtr lda SndEnvFrqPtrHi,y sta SndEnvPtr+1 lda (SndEnvPtr) sta SndTmp asl sta SndEnvFrqLoop,x ldy #1 lda (SndEnvPtr),y sta SndEnvFrqParts,x sec sbc SndTmp sta SndEnvFrqParts2,x stz SndEnvFrqCnt,x lda #2 sta SndEnvFrqOff,x ldy #$82 rts ;---------------------------------------------------------------------------- ; Sound frequency envelope ; SndDefEnvWave: phx lda (SndPtrTmp),y ; env # tax iny lda (SndPtrTmp),y sta SndEnvWavePtrLo,x iny lda (SndPtrTmp),y sta SndEnvWavePtrHi,x ; Ptr to [inc,cnt] plx ldy #$84 rts SndSetEnvWave: lda (SndPtrTmp),y ; # env SndSetEnvWave1: and #$7f sta SndEnvWave,x ; save _IFEQ ldy #$82 rts _ENDIF tay lda SndEnvWavePtrLo,y sta SndEnvPtr lda SndEnvWavePtrHi,y sta SndEnvPtr+1 lda (SndEnvPtr) sta SndTmp asl ; *4 -2 dea asl sta SndEnvWaveLoop,x ldy #1 lda (SndEnvPtr),y sta SndEnvWaveParts,x sec sbc SndTmp sta SndEnvWaveParts2,x stz SndEnvWaveCnt,x lda #2 sta SndEnvWaveOff,x ldy #$82 rts ;---------------------------------------------------------------------------- ; Pause sound ; SndPause: lda (SndPtrTmp),y sta SndDelay,x iny SndDummy: rts ;;;* This set the new Player Freq instantanious!!! SndPlayerFreq: lda (SndPtrTmp),y sta STIMCTLA iny lda (SndPtrTmp),y sta STIMBKUP ldy #$83 rts SndNoteOff: ldy SndOffsets,x stz SndNotePlaying,x lda SndEnvVol,x ora #$80 sta SndEnvVol,x lda SndEnvFrq,x ora #$80 sta SndEnvFrq,x lda SndEnvWave,x ora #$80 sta SndEnvWave,x lda #0 sta SndChannel,y sta SndChannel+4,y sta SndChannel+5,y dea sta SndChannel+2,y ldy #$81 rts SndSetInstr: phx lda SndOffsets,x tax lda (SndPtrTmp),y sta SndChannel+3,x iny lda (SndPtrTmp),y sta SndChannel+7,x iny lda (SndPtrTmp),y sta SndChannel+1,x plx iny lda (SndPtrTmp),y sta SndVolume,x iny lda (SndPtrTmp),y sta SndMaxVolume,x ldy #$86 rts SndCallPattern: clc lda SndPtrTmp adc #3 sta SndRetAddr,x lda SndPtrTmp+1 adc #0 sta SndRetAddr+4,x ldy #1 lda (SndPtrTmp),y pha iny lda (SndPtrTmp),y sta SndPtrTmp+1 pla sta SndPtrTmp ldy #$80 rts SndRetToSong: lda SndRetAddr,x sta SndPtrTmp lda SndRetAddr+4,x sta SndPtrTmp+1 ldy #$80 rts SndReturnAll: lda #1 sta SndRetAFlag sta SndDelay,x ldy #$0 rts SndNewNote2: ;;; Note,length,volume phx sta SndNotePlaying,x ldy #1 lda (SndPtrTmp),y ; reload pha iny lda (SndPtrTmp),y ; prescale pha iny lda (SndPtrTmp),y ; laenge sta SndDelay,x ldy SndOffsets,x lda SndVolume,x sta SndChannel,y pla sta SndChannel+5,y pla sta SndChannel+4,y lda #$FF ; = -1 sta SndChannel+2,y plx lda SndEnvVol,x _IFNE jsr SndSetEnvVol1 _ENDIF lda SndEnvFrq,x _IFNE jsr SndSetEnvFrq1 _ENDIF lda SndEnvWave,x _IFNE jsr SndSetEnvWave1 _ENDIF ldy #4 rts SndSetStereo: ldy #1 lda (SndPtrTmp),y sta MSTEREO ldy #$82 rts SndSetAttenuationOn: ldy #1 lda (SndPtrTmp),y sta $FD44 ldy #$82 rts SndSetChnAttenution: ldy #1 lda (SndPtrTmp),y sta $FD40,x ldy #$82 rts SndChangeVol: tay _IFMI vol99: rts _ENDIF lda SndNotePlaying,x beq vol99 lda SndEnvVolPtrLo,y sta SndEnvPtr lda SndEnvVolPtrHi,y sta SndEnvPtr+1 dec SndEnvVolCnt,x _IFMI dec SndEnvVolParts,x _IFMI lda SndEnvVolLoop,x _IFNE tay lda SndEnvVolParts2,x sta SndEnvVolParts,x bra vol1v _ELSE tya ora #$80 sta SndEnvVol,x _ENDIF _ELSE ldy SndEnvVolOff,x vol1v: lda (SndEnvPtr),y sta SndEnvVolCnt,x iny lda (SndEnvPtr),y sta SndEnvVolInc,x iny tya sta SndEnvVolOff,x _ENDIF rts _ENDIF ldy SndOffsets,x clc lda SndEnvVolInc,x _IFEQ rts _ENDIF _IFPL adc SndChannel,y cmp SndMaxVolume,x _IFCS lda SndMaxVolume,x stz SndEnvVolInc,x _ENDIF cmp #$80 _IFGE lda #$7f stz SndEnvVolInc,x _ENDIF _ELSE adc SndChannel,y _IFCC lda #0 sta SndEnvVolInc,x ;; NEU: switch Tremolo off sta SndNotePlaying,x _ENDIF cmp #$80 _IFGE lda #0 sta SndEnvVolInc,x ;; NEU: switch Tremolo off sta SndNotePlaying,x _ENDIF _ENDIF sta SndChannel,y lda SndChannel+2,y ora #1 ;; if already -1 ... no effect sta SndChannel+2,y rts SndChangeFrq: tay _IFMI frq99: rts _ENDIF lda SndNotePlaying,x beq frq99 lda SndEnvFrqPtrLo,y sta SndEnvPtr lda SndEnvFrqPtrHi,y sta SndEnvPtr+1 dec SndEnvFrqCnt,x _IFMI dec SndEnvFrqParts,x _IFMI lda SndEnvFrqLoop,x _IFNE tay lda SndEnvFrqParts2,x sta SndEnvFrqParts,x bra frq1f _ELSE tya ora #$80 sta SndEnvFrq,x _ENDIF _ELSE ldy SndEnvFrqOff,x frq1f: lda (SndEnvPtr),y sta SndEnvFrqCnt,x iny lda (SndEnvPtr),y eor #$ff ina sta SndEnvFrqInc,x iny tya sta SndEnvFrqOff,x _ENDIF rts _ENDIF ldy SndOffsets,x clc lda SndEnvFrqInc,x _IFEQ rts _ENDIF _IFMI adc SndChannel+4,y _IFPL pha lda SndChannel+5,y _IFNE dea sta SndChannel+5,y pla eor #128 _ELSE pla pha clc adc SndEnvFrqInc,x pla _ENDIF _ELSE pha lda SndChannel+5,y _IFEQ pla sta SndChannel+4,y rts _ENDIF pla _ENDIF _ELSE adc SndChannel+4,y _IFPL pha lda SndChannel+5,y cmp #6 _IFNE ina sta SndChannel+5,y pla eor #128 _ELSE lda SndChannel+4,y _IFMI pla rts _ENDIF pla _ENDIF _ELSE pha lda SndChannel+5,y cmp #6 _IFEQ lda SndChannel+4,y _IFPL pla rts _ENDIF _ENDIF pla _ENDIF _ENDIF sta SndChannel+4,y ora #1 ;; if already -1 -> no effect rts SndChangeWave: tay ;; Ab hier x Kanal 0-3, y Environment _IFMI wav99: rts _ENDIF lda SndNotePlaying,x beq wav99 lda SndEnvWavePtrLo,y sta SndEnvPtr lda SndEnvWavePtrHi,y sta SndEnvPtr+1 dec SndEnvWaveCnt,x _IFMI dec SndEnvWaveParts,x _IFMI lda SndEnvWaveLoop,x _IFNE tay ;; Ab hier x Kanal 0-3, y Offset im Environment lda SndEnvWaveParts2,x sta SndEnvWaveParts,x bra wav1v _ELSE tya ora #$80 ;; beende Env sta SndEnvWave,x _ENDIF _ELSE ldy SndEnvWaveOff,x ;; Ab hier x Kanal 0-3, y Offset im Environment wav1v: lda (SndEnvPtr),y sta SndEnvWaveCnt,x phx lda SndOffsets,x tax ;; Ab hier x Kanal (0-3)*8, y Offset im Environment iny lda (SndEnvPtr),y sta SndChannel+3,x ; Shift LO iny lda (SndEnvPtr),y sta SndChannel+7,x ; Shift HI iny lda (SndEnvPtr),y sta SndChannel+1,x ; Feedback iny tya ply ;; Ab hier x Kanal (0-3)*8, y Kanal 0-3 sta SndEnvWaveOff,y lda #$FF ; =-1 ;; stop timer to set new values... sta SndChannel+2,x _ENDIF _ENDIF rts SndSetValues: ldx #4-1 set0: ldy SndOffsets,x lda SndChannel+2,y _IFNE ; flag == 0 => don't set bit #$80 _IFNE ; lda #0 sta $fd25,y ; stop sound timer lda SndChannel+3,y sta $fd23,y ; shifter 1 ;;lda $fd27,y ;;and #$0F ;;ora SndChannel+7,y ; shifter 2 lda SndChannel+7,y ; shifter 2 sta $fd27,y lda SndChannel+1,y sta $fd21,y ; feedback _ENDIF lda SndChannel,y sta $fd20,y ; volume lda SndChannel+2,y bit #$80 _IFNE ; lda SndChannel+4,y sta $fd24,y ; reload lda SndChannel+5,y ora #%00011000 ;;; #%01011000 ;; and #%00111111 sta $fd25,y ; re-enable timer _ENDIF lda #0 sta SndChannel+2,y ; clear flag _ENDIF dex _IFPL jmp set0 _ENDIF rts _lynx_snd_play: sta ptr1 stx ptr1+1 jsr popa tax lda ptr1 ldy ptr1+1 php pha lda SndActive,x _IFNE dec SndReqStop,x lda #1 sta SndDelay,x start0: lda SndActive,x bne start0 _ENDIF bra start1 SndStartSoundx: php pha start1: sei pla sta SndPtrLo,x tya sta SndPtrHi,x lda #1 sta SndDelay,x stz SndEnvVol,x stz SndEnvFrq,x stz SndEnvWave,x sta SndActive,x stz SndReqStop,x plp rts SndStartSound2: pha lda SndActive,x ; check default beq start20 ; inactive => ok phx ldx #3 ; search free channel start21: lda SndActive,x beq start22 ; found => dex bpl start21 plx ; not found dec SndReqStop,x ; stop default-channel lda #1 sta SndDelay,x start23: lda SndActive,x bne start23 bra start20 start22: pla ; clear stack start20: pla phx jsr SndStartSoundx ; launch new sound plx rts _lynx_snd_stop: ldx #3 lda SndActive,x _IFNE stop0: dec SndReqStop,x lda #1 sta SndDelay,x stop1: lda SndActive,x bne stop1 _ENDIF dex bpl stop0 rts _lynx_snd_stop_channel: tax lda SndActive,x _IFNE dec SndReqStop,x lda #1 sta SndDelay,x stopc1: lda SndActive,x bne stopc1 _ENDIF rts _lynx_snd_active: ldx #3 lda #0 act0: ldy SndActive,x _IFNE ora SndMask,x _ENDIF dex bpl act0 rts _lynx_snd_pause: php sei lda STIMCTLA sta SndPauseOff1+1 stz STIMCTLA lda MSTEREO sta SndPauseOff2+1 lda #$ff sta MSTEREO lda #$18 trb AUD0CTLA trb AUD1CTLA trb AUD2CTLA trb AUD3CTLA plp rts _lynx_snd_continue: php sei SndPauseOff1: lda #0 ; Selbsmodifizierter Code!!! sta STIMCTLA SndPauseOff2: lda #0 ; Selbsmodifizierter Code!!! sta MSTEREO lda #$18 tsb AUD0CTLA tsb AUD1CTLA tsb AUD2CTLA tsb AUD3CTLA plp rts .rodata SndMask: .byte 1,2,4,8 SndPrescaler: .byte $00,$06,$06,$06,$06,$05,$05,$05,$05,$05,$05,$05,$04,$04,$04,$04 .byte $04,$04,$04,$04,$03,$03,$03,$03,$03,$03,$03,$03,$03,$03,$02,$02 .byte $02,$02,$02,$02,$02,$02,$02,$02,$02,$02,$02,$01,$01,$01,$01,$01 .byte $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$00,$00 .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 .byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 SndReload: .byte $00,$9A,$96,$8F,$86,$FA,$E5,$D1,$BE,$AC,$9C,$8D,$00,$E8,$D3,$C0 .byte $AF,$A0,$93,$87,$FA,$E7,$D6,$C6,$B8,$AC,$A1,$96,$8D,$84,$FA,$EB .byte $DE,$D2,$C7,$BC,$B3,$AA,$A1,$9A,$93,$8C,$86,$00,$F5,$EB,$E1,$D8 .byte $CF,$C7,$C0,$B9,$B2,$AB,$A5,$A0,$9A,$95,$90,$8B,$87,$82,$FD,$F5 .byte $EE,$E7,$E0,$D9,$D3,$CD,$C8,$C2,$BD,$B8,$B3,$AE,$AA,$A5,$A1,$9D .byte $99,$96,$92,$8F,$8B,$88,$85,$82,$7F,$7C,$79,$77,$74,$72,$6F,$6D .byte $6B,$69,$67,$64,$63,$61,$5F,$5D,$5B,$59,$58,$56,$55,$53,$51,$50 .byte $4F,$4D,$4C,$4B,$49,$48,$47,$46,$44,$43,$42,$41,$40,$3F,$3E,$3D �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/mainargs.s��������������������������������������������������������������������0000664�0000000�0000000�00000000654�13473601511�0016447�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2004-10-08 ; ; Setup arguments for main ; .constructor initmainargs, 24 .import __argc, __argv ;--------------------------------------------------------------------------- ; Get possible command-line arguments. Goes into the special ONCE segment, ; which may be reused after the startup code is run .segment "ONCE" .proc initmainargs rts .endproc ������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/open.s������������������������������������������������������������������������0000664�0000000�0000000�00000006454�13473601511�0015613�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Karri Kaksonen, 2010 ; ; This function reads the directory entry for file "name". ; ; The name is actually plain ASCII string starting from ; "0", "1", up to "4095" which is the largest file number we can handle. ; ; open() does not take part in what kind of cart we have. If it is RAM ; you may also be able to write into it. Therefore we allow both reads ; and writes in this routine. ; ; int open(const char *name, int flags, ...) ; ; As helper functions we also provide. ; void openn(int fileno) ; .importzp sreg, tmp3 .macpack longbranch .import _atoi .import _read .import _lseek .import addysp,popax,pushax,decsp6,pusha0,pusheax,ldaxysp .import aslax3,axlong,tosaddeax,steaxysp,stax0sp,incsp8 .import ldax0sp .import lynxskip0, lynxblock .importzp _FileEntry .importzp _FileStartBlock .importzp _FileCurrBlock .importzp _FileBlockOffset .import __STARTOFDIRECTORY__ .export _open .export _openn .include "errno.inc" .include "fcntl.inc" .segment "DATA" _startofdirectory: .dword __STARTOFDIRECTORY__ ; --------------------------------------------------------------- ; int __near__ open (__near__ const unsigned char*, int) ; --------------------------------------------------------------- .segment "CODE" .proc _open .segment "CODE" dey dey dey dey beq parmok jsr addysp parmok: jsr popax sta tmp3 and #(O_RDWR | O_CREAT) cmp #O_RDONLY beq flagsok cmp #(O_WRONLY | O_CREAT) beq flagsok jsr popax lda #EINVAL jmp __directerrno flagsok: jsr popax jsr _atoi jsr _openn ldx #$00 lda #$01 stx __oserror rts .endproc ; --------------------------------------------------------------- ; void __near__ __fastcall__ openn (int) ; --------------------------------------------------------------- .segment "CODE" .proc _openn: near .segment "CODE" jsr pushax jsr decsp6 lda #$01 jsr pusha0 lda _startofdirectory+3 sta sreg+1 lda _startofdirectory+2 sta sreg ldx _startofdirectory+1 lda _startofdirectory jsr pusheax ldy #$0D jsr ldaxysp jsr aslax3 jsr axlong jsr tosaddeax jsr pusheax ldx #$00 txa jsr _lseek ldy #$02 jsr steaxysp lda #$01 jsr pusha0 lda #<_FileEntry ldx #>_FileEntry jsr pushax ldx #$00 lda #$08 jsr _read lda _FileStartBlock sta _FileCurrBlock jsr lynxblock lda _FileBlockOffset+1 eor #$FF tay lda _FileBlockOffset eor #$FF tax jsr lynxskip0 jsr stax0sp jmp incsp8 .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/oserror.s���������������������������������������������������������������������0000664�0000000�0000000�00000000340�13473601511�0016331�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Karri Kaksonen, 2010 ; ; int __fastcall__ _osmaperrno (unsigned char oserror); ; /* Map a system specific error into a system independent code */ ; .include "errno.inc" .code __osmaperrno: rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/read.s������������������������������������������������������������������������0000664�0000000�0000000�00000002057�13473601511�0015560�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Karri Kaksonen, 2010 ; ; This function reads count bytes from the place where the address counter is. ; Use lseek to place the address counter where you want to read from. ; ; The file descriptor is ignored in this implementation. The read operation ; reads bytes from a raw cart and does not understand the concept of files. ; So if you read over the end of file you get data from the next file. ; ; The count-parameter is positive (Atari style). ; ; int __fastcall__ read(int fd,void *buf,int count) ; .importzp _FileDestPtr .import lynxread0 .import pushax,ldaxysp,ldax0sp,incsp6 .export _read .segment "CODE" .proc _read: near .segment "CODE" jsr pushax ldy #$03 jsr ldaxysp sta _FileDestPtr stx _FileDestPtr+1 jsr ldax0sp pha txa eor #$FF tay pla eor #$FF tax jsr lynxread0 jsr ldax0sp jmp incsp6 .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/ser/��������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015246�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/ser/lynx-comlynx.s������������������������������������������������������������0000664�0000000�0000000�00000024516�13473601511�0020123�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Serial driver for the Atari Lynx ComLynx port. ; ; Karri Kaksonen, 17.09.2009 ; .include "lynx.inc" .include "zeropage.inc" .include "ser-kernel.inc" .include "ser-error.inc" .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _lynx_comlynx_ser ; Driver signature .byte $73, $65, $72 ; "ser" .byte SER_API_VERSION ; Serial API version number ; Library reference .addr $0000 ; Jump table .addr SER_INSTALL .addr SER_UNINSTALL .addr SER_OPEN .addr SER_CLOSE .addr SER_GET .addr SER_PUT .addr SER_STATUS .addr SER_IOCTL .addr SER_IRQ ;---------------------------------------------------------------------------- ; Global variables ; .bss TxBuffer: .res 256 RxBuffer: .res 256 RxPtrIn: .res 1 RxPtrOut: .res 1 TxPtrIn: .res 1 TxPtrOut: .res 1 contrl: .res 1 SerialStat: .res 1 TxDone: .res 1 .code ;---------------------------------------------------------------------------- ; SER_INSTALL: Is called after the driver is loaded into memory. ; ; Must return an SER_ERR_xx code in a/x. SER_INSTALL: ; Set up IRQ vector ? ;---------------------------------------------------------------------------- ; SER_UNINSTALL: Is called before the driver is removed from memory. ; No return code required (the driver is removed from memory on return). ; SER_UNINSTALL: ;---------------------------------------------------------------------------- ; SER_CLOSE: Close the port and disable interrupts. Called without parameters. ; Must return an SER_ERR_xx code in a/x. SER_CLOSE: ; Disable interrupts ; Done, return an error code lda #<SER_ERR_OK ldx #>SER_ERR_OK rts ;---------------------------------------------------------------------------- ; SER_OPEN: A pointer to a ser_params structure is passed in ptr1. ; ; The Lynx has only two correct serial data formats: ; 8 bits, parity mark, 1 stop bit ; 8 bits, parity space, 1 stop bit ; ; It also has two wrong formats; ; 8 bits, even parity, 1 stop bit ; 8 bits, odd parity, 1 stop bit ; ; Unfortunately the parity bit includes itself in the calculation making ; parity not compatible with the rest of the world. ; ; We can only specify a few baud rates. ; Lynx has two non-standard speeds 31250 and 62500 which are ; frequently used in games. ; ; The receiver will always read the parity and report parity errors. ; ; Must return an SER_ERR_xx code in a/x. SER_OPEN: stz RxPtrIn stz RxPtrOut stz TxPtrIn stz TxPtrOut ; clock = 8 * 15625 lda #%00011000 sta TIM4CTLA ldy #SER_PARAMS::BAUDRATE lda (ptr1),y ldx #1 cmp #SER_BAUD_62500 beq setbaudrate ldx #2 cmp #SER_BAUD_31250 beq setbaudrate ldx #12 cmp #SER_BAUD_9600 beq setbaudrate ldx #25 cmp #SER_BAUD_4800 beq setbaudrate ldx #51 cmp #SER_BAUD_2400 beq setbaudrate ldx #103 cmp #SER_BAUD_1200 beq setbaudrate ldx #207 cmp #SER_BAUD_600 beq setbaudrate ; clock = 6 * 15625 ldx #%00011010 stx TIM4CTLA ldx #12 cmp #SER_BAUD_7200 beq setbaudrate ldx #25 cmp #SER_BAUD_3600 beq setbaudrate ldx #207 stx TIM4BKUP ; clock = 4 * 15625 ldx #%00011100 cmp #SER_BAUD_300 beq setprescaler ; clock = 6 * 15625 ldx #%00011110 cmp #SER_BAUD_150 beq setprescaler ; clock = 1 * 15625 ldx #%00011111 stx TIM4CTLA cmp #SER_BAUD_75 beq baudsuccess ldx #141 cmp #SER_BAUD_110 beq setbaudrate ; clock = 2 * 15625 ldx #%00011010 stx TIM4CTLA ldx #68 cmp #SER_BAUD_1800 beq setbaudrate ; clock = 6 * 15625 ldx #%00011110 stx TIM4CTLA ldx #231 cmp #SER_BAUD_134_5 beq setbaudrate lda #<SER_ERR_BAUD_UNAVAIL ldx #>SER_ERR_BAUD_UNAVAIL rts setprescaler: stx TIM4CTLA bra baudsuccess setbaudrate: stx TIM4BKUP baudsuccess: ldx #TxOpenColl|ParEven stx contrl ldy #SER_PARAMS::DATABITS ; Databits lda (ptr1),y cmp #SER_BITS_8 bne invparameter ldy #SER_PARAMS::STOPBITS ; Stopbits lda (ptr1),y cmp #SER_STOP_1 bne invparameter ldy #SER_PARAMS::PARITY ; Parity lda (ptr1),y cmp #SER_PAR_NONE beq invparameter cmp #SER_PAR_MARK beq checkhs cmp #SER_PAR_SPACE bne @L0 ldx #TxOpenColl stx contrl bra checkhs @L0: ldx #TxParEnable|TxOpenColl|ParEven stx contrl cmp #SER_PAR_EVEN beq checkhs ldx #TxParEnable|TxOpenColl stx contrl checkhs: ldx contrl stx SERCTL ldy #SER_PARAMS::HANDSHAKE ; Handshake lda (ptr1),y cmp #SER_HS_NONE bne invparameter lda SERDAT lda contrl ora #RxIntEnable|ResetErr sta SERCTL lda #<SER_ERR_OK ldx #>SER_ERR_OK rts invparameter: lda #<SER_ERR_INIT_FAILED ldx #>SER_ERR_INIT_FAILED rts ;---------------------------------------------------------------------------- ; SER_GET: Will fetch a character from the receive buffer and store it into the ; variable pointed to by ptr1. If no data is available, SER_ERR_NO_DATA is ; returned. SER_GET: lda RxPtrIn cmp RxPtrOut bne GetByte lda #<SER_ERR_NO_DATA ldx #>SER_ERR_NO_DATA rts GetByte: ldy RxPtrOut lda RxBuffer,y inc RxPtrOut ldx #$00 sta (ptr1,x) txa ; Return code = 0 rts ;---------------------------------------------------------------------------- ; SER_PUT: Output character in A. ; Must return an SER_ERR_xx code in a/x. SER_PUT: tax lda TxPtrIn ina cmp TxPtrOut bne PutByte lda #<SER_ERR_OVERFLOW ldx #>SER_ERR_OVERFLOW rts PutByte: ldy TxPtrIn txa sta TxBuffer,y inc TxPtrIn bit TxDone bmi @L1 php sei lda contrl ora #TxIntEnable|ResetErr sta SERCTL ; Allow TX-IRQ to hang RX-IRQ sta TxDone plp @L1: lda #<SER_ERR_OK tax rts ;---------------------------------------------------------------------------- ; SER_STATUS: Return the status in the variable pointed to by ptr1. ; Must return an SER_ERR_xx code in a/x. SER_STATUS: ldy SerialStat ldx #$00 sta (ptr1,x) txa ; Return code = 0 rts ;---------------------------------------------------------------------------- ; SER_IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl ; specific data in ptr1, and the ioctl code in A. ; Must return an SER_ERR_xx code in a/x. SER_IOCTL: lda #<SER_ERR_INV_IOCTL ldx #>SER_ERR_INV_IOCTL rts ;---------------------------------------------------------------------------- ; SER_IRQ: Called from the builtin runtime IRQ handler as a subroutine. All ; registers are already saved, no parameters are passed, but the carry flag ; is clear on entry. The routine must return with carry set if the interrupt ; was handled, otherwise with carry clear. ; ; Both the Tx and Rx interrupts are level sensitive instead of edge sensitive. ; Due to this bug you have to disable the interrupt before clearing it. SER_IRQ: lda INTSET ; Poll all pending interrupts and #SERIAL_INTERRUPT bne @L0 clc rts @L0: bit TxDone bmi @tx_irq ; Transmit in progress ldx SERDAT lda SERCTL and #RxParityErr|RxOverrun|RxFrameErr|RxBreak beq @rx_irq tsb SerialStat ; Save error condition bit #RxBreak beq @noBreak stz TxPtrIn ; Break received - drop buffers stz TxPtrOut stz RxPtrIn stz RxPtrOut @noBreak: lda contrl ora #RxIntEnable|ResetErr sta SERCTL lda #$10 sta INTRST bra @IRQexit @rx_irq: lda contrl ora #RxIntEnable|ResetErr sta SERCTL txa ldx RxPtrIn sta RxBuffer,x txa inx @cont0: cpx RxPtrOut beq @1 stx RxPtrIn lda #SERIAL_INTERRUPT sta INTRST bra @IRQexit @1: sta RxPtrIn lda #$80 tsb SerialStat @tx_irq: ldx TxPtrOut ; Has all bytes been sent? cpx TxPtrIn beq @allSent lda TxBuffer,x ; Send next byte sta SERDAT inc TxPtrOut @exit1: lda contrl ora #TxIntEnable|ResetErr sta SERCTL lda #SERIAL_INTERRUPT sta INTRST bra @IRQexit @allSent: lda SERCTL ; All bytes sent bit #TxEmpty beq @exit1 bvs @exit1 stz TxDone lda contrl ora #RxIntEnable|ResetErr sta SERCTL lda #SERIAL_INTERRUPT sta INTRST @IRQexit: clc rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/sysuname.s��������������������������������������������������������������������0000664�0000000�0000000�00000001436�13473601511�0016511�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2004-10-08 ; ; unsigned char __fastcall__ _sysuname (struct utsname* buf); ; .export __sysuname, utsdata .import utscopy __sysuname = utscopy ;-------------------------------------------------------------------------- ; Data. We define a fixed utsname struct here and just copy it. .rodata utsdata: ; sysname .asciiz "cc65" ; nodename .asciiz "" ; release .byte ((.VERSION >> 8) & $0F) + '0' .byte '.' .byte ((.VERSION >> 4) & $0F) + '0' .byte $00 ; version .byte (.VERSION & $0F) + '0' .byte $00 ; machine .asciiz "LYNX" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/tgi/��������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015240�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/tgi/lynx-160-102-16.s���������������������������������������������������������0000664�0000000�0000000�00000073104�13473601511�0017453�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Graphics driver for the 160x102x16 mode on the Lynx. ; ; All the drawing functions are simply done by sprites as the sprite ; engine is the only way to do fast graphics on a Lynx. ; ; This code is written by Karri Kaksonen, 2004 for the cc65 compiler. ; .include "zeropage.inc" .include "../extzp.inc" .include "tgi-kernel.inc" .include "tgi-error.inc" .include "lynx.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table and constants. module_header _lynx_160_102_16_tgi ; First part of the header is a structure that has a magic and defines the ; capabilities of the driver .byte $74, $67, $69 ; "tgi" .byte TGI_API_VERSION ; TGI API version number libref: .addr $0000 ; Library reference .word 160 ; X resolution .word 102 ; Y resolution .byte 16 ; Number of drawing colors .byte 2 ; Number of screens available .byte 8 ; System font X size .byte 8 ; System font Y size .word $0100 ; Aspect ratio (square pixel LCD) .byte TGI_BM_FONT_FINESCALE ; TGI driver flags ; Next comes the jump table. Currently all entries must be valid and may point ; to an RTS for test versions (function not implemented). A future version may ; allow for emulation: In this case the vector will be zero. Emulation means ; that the graphics kernel will emulate the function by using lower level ; primitives - for example ploting a line by using calls to SETPIXEL. .addr INSTALL .addr UNINSTALL .addr INIT .addr DONE .addr GETERROR .addr CONTROL .addr CLEAR .addr SETVIEWPAGE .addr SETDRAWPAGE .addr SETCOLOR .addr SETPALETTE .addr GETPALETTE .addr GETDEFPALETTE .addr SETPIXEL .addr GETPIXEL .addr LINE .addr BAR .addr TEXTSTYLE .addr OUTTEXT ; ------------------------------------------------------------------------ ; Data. ; Variables mapped to the zero page segment variables. Some of these are ; used for passing parameters to the driver. X1 := ptr1 Y1 := ptr2 X2 := ptr3 Y2 := ptr4 STRPTR := ptr3 FONTOFF := ptr4 STROFF := tmp3 STRLEN := tmp4 ; Absolute variables used in the code .bss ERROR: .res 1 ; Error code DRAWINDEX: .res 1 ; Pen to use for drawing VIEWPAGEL: .res 1 VIEWPAGEH: .res 1 DRAWPAGEL: .res 1 DRAWPAGEH: .res 1 ; Text output stuff TEXTMAGX: .res 1 TEXTMAGY: .res 1 TEXTDIR: .res 1 BGINDEX: .res 1 ; Pen to use for text background ; Double buffer IRQ stuff DRAWPAGE: .res 1 SWAPREQUEST: .res 1 text_bitmap: .res 8*(1+20+1)+1 ; 8 rows with (one offset-byte plus 20 character bytes plus one fill-byte) plus one 0-offset-byte ; Constants and tables .rodata DEFPALETTE: .byte >$011 .byte >$34d .byte >$9af .byte >$9b8 .byte >$777 .byte >$335 .byte >$448 .byte >$75e .byte >$d5f .byte >$c53 .byte >$822 .byte >$223 .byte >$484 .byte >$8e5 .byte >$cf5 .byte >$fff .byte <$011 .byte <$34d .byte <$9af .byte <$9b8 .byte <$777 .byte <$335 .byte <$448 .byte <$75e .byte <$d5f .byte <$c53 .byte <$822 .byte <$223 .byte <$484 .byte <$8e5 .byte <$cf5 .byte <$fff PALETTESIZE = * - DEFPALETTE .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. May ; initialize anything that has to be done just once. Is probably empty ; most of the time. ; ; Must set an error code: NO ; INSTALL: lda #1 sta TEXTMAGX sta TEXTMAGY stz BGINDEX stz DRAWPAGE stz SWAPREQUEST lda libref ldx libref+1 sta ptr1 stx ptr1+1 ldy #1 lda #<irq sta (ptr1),y iny lda #>irq sta (ptr1),y lda #$4C ; Jump opcode sta (ptr1) ; Activate IRQ routine rts ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. May ; clean up anything done by INSTALL but is probably empty most of the time. ; ; Must set an error code: NO ; UNINSTALL: lda libref ldx libref+1 sta ptr1 stx ptr1+1 lda #$60 ; RTS opcode sta (ptr1) ; Disable IRQ routine rts ; ------------------------------------------------------------------------ ; INIT: Changes an already installed device from text mode to graphics ; mode. ; Note that INIT/DONE may be called multiple times while the driver ; is loaded, while INSTALL is only called once, so any code that is needed ; to initializes variables and so on must go here. Setting palette and ; clearing the screen is not needed because this is called by the graphics ; kernel later. ; The graphics kernel will never call INIT when a graphics mode is already ; active, so there is no need to protect against that. ; ; Must set an error code: YES ; INIT: ; Enable interrupts for VBL lda #$80 tsb VTIMCTLA ; Set up collision buffer to $A058 lda #$58 sta COLLBASL lda #$A0 sta COLLBASH ; Put collision index before sprite data lda #$FF sta COLLOFFL lda #$FF sta COLLOFFH ; Done, reset the error code lda #TGI_ERR_OK sta ERROR rts ; ------------------------------------------------------------------------ ; DONE: Will be called to switch the graphics device back into text mode. ; The graphics kernel will never call DONE when no graphics mode is active, ; so there is no need to protect against that. ; ; Must set an error code: NO ; DONE: rts ; ------------------------------------------------------------------------ ; GETERROR: Return the error code in A and clear it. GETERROR: ldx #TGI_ERR_OK lda ERROR stx ERROR rts ; ------------------------------------------------------------------------ ; CONTROL: Platform/driver specific entry point. ; ; Must set an error code: YES ; ; The TGI lacks a way to draw sprites. As that functionality is vital to ; Lynx games we borrow this CONTROL function to implement the still ; missing tgi_draw_sprite funtion. To use this in your C-program ; do a #define tgi_draw_sprite(spr) tgi_ioctl(0, spr) ; ; To do a flip-screen call tgi_ioctl(1, 0) ; ; To set the background index for text outputs call tgi_ioctl(2, bgindex) ; ; To set the frame rate for the display hardware call tgi_ioctl(3, rate) ; ; To check if the drawing engine is busy with the previous swap you can ; call tgi_ioctl(4, 0). It returns 0 if idle and 1 if busy ; ; To update displays you can call tgi_ioctl(4, 1) it will wait for the ; next VBL interrupt and swap draw and view buffers. ; ; Activate or deactivate collision detection by calling tgi_ioctl(5, 0/1). CONTROL: pha ; Almost all control routines succeed lda #TGI_ERR_OK sta ERROR pla cmp #5 bne ControlSwap lda ptr1 ; Activate/deactivate collision detection bne @L0 lda #%00000001 ; tgi_clear does not erase collision buffer sta cls_sprite lda #%00100000 sta cls_sprite+2 lda __sprsys ora #$20 bra @L1 @L0: lda #%00000000 ; tgi_clear erases collision buffer sta cls_sprite sta cls_sprite+2 lda __sprsys and #$df @L1: sta __sprsys sta SPRSYS rts ControlSwap: cmp #4 bne ControlFramerate lda ptr1 ; Swap request bne @L0 lda SWAPREQUEST rts @L0: sta SWAPREQUEST rts ControlFramerate: cmp #3 bne ControlTextBG lda ptr1 cmp #75 ; Set framerate beq rate75 cmp #60 beq rate60 cmp #50 beq rate50 lda #TGI_ERR_INV_ARG sta ERROR rts rate50: lda #$bd ; 50 Hz ldx #$31 bra setRate rate60: lda #$9e ; 60 Hz ldx #$29 bra setRate rate75: lda #$7e ; 75 Hz ldx #$20 setRate: sta HTIMBKUP stx PBKUP rts ControlTextBG: cmp #2 bne ControlFlipScreen lda ptr1 ; Set text background color sta BGINDEX rts ControlFlipScreen: cmp #1 bne ControlDrawSprite lda __sprsys ; Flip screen eor #8 sta __sprsys sta SPRSYS lda __viddma eor #2 sta __viddma sta DISPCTL ldy VIEWPAGEL ldx VIEWPAGEH and #2 beq NotFlipped clc tya adc #<8159 tay txa adc #>8159 tax NotFlipped: sty DISPADRL stx DISPADRH rts ControlDrawSprite: lda ptr1 ; Get the sprite address ldx ptr1+1 draw_sprite: ; Draw it in render buffer sta SCBNEXTL stx SCBNEXTH lda DRAWPAGEL ldx DRAWPAGEH sta VIDBASL stx VIDBASH lda #1 sta SPRGO stz SDONEACK @L0: stz CPUSLEEP lda SPRSYS lsr bcs @L0 stz SDONEACK lda #TGI_ERR_OK sta ERROR rts ; ------------------------------------------------------------------------ ; CLEAR: Clears the screen. ; ; Must set an error code: NO ; .rodata pixel_bitmap: .byte 3,%10000100,%00000000, $0 ; A pixel bitmap .data cls_coll: .byte 0 cls_sprite: .byte %00000001 ; A pixel sprite .byte %00010000 .byte %00100000 .addr 0,pixel_bitmap .word 0 .word 0 .word $a000 ; 160 .word $6600 ; 102 .byte $00 .code CLEAR: lda #<cls_sprite ldx #>cls_sprite bra draw_sprite ; ------------------------------------------------------------------------ ; SETVIEWPAGE: Set the visible page. Called with the new page in A (0..n). ; The page number is already checked to be valid by the graphics kernel. ; ; Must set an error code: NO (will only be called if page ok) ; ; It is a good idea to call this function during the vertical blanking ; period. If you call it in the middle of the screen update then half of ; the drawn frame will be from the old buffer and the other half is ; from the new buffer. This is usually noticed by the user. SETVIEWPAGE: cmp #1 beq @L1 ; page == maxpages-1 ldy #<$e018 ; page 0 ldx #>$e018 bra @L2 @L1: ldy #<$c038 ; page 1 ldx #>$c038 @L2: sty VIEWPAGEL ; Save viewpage for getpixel stx VIEWPAGEH lda __viddma ; Process flipped displays and #2 beq @L3 clc tya adc #<8159 tay txa adc #>8159 tax @L3: sty DISPADRL ; $FD94 stx DISPADRH ; $FD95 rts ; ------------------------------------------------------------------------ ; SETDRAWPAGE: Set the drawable page. Called with the new page in A (0..n). ; The page number is already checked to be valid by the graphics kernel. ; ; Must set an error code: NO (will only be called if page ok) ; SETDRAWPAGE: cmp #1 beq @L1 ; page == maxpages-1 lda #<$e018 ; page 0 ldx #>$e018 bra @L2 @L1: lda #<$c038 ; page 1 ldx #>$c038 @L2: sta DRAWPAGEL stx DRAWPAGEH rts irq: lda INTSET ; Poll all pending interrupts and #VBL_INTERRUPT beq @L0 ; Exit if not a VBL interrupt lda SWAPREQUEST beq @L0 lda DRAWPAGE jsr SETVIEWPAGE lda DRAWPAGE eor #1 sta DRAWPAGE jsr SETDRAWPAGE stz SWAPREQUEST @L0: clc rts ; ------------------------------------------------------------------------ ; SETCOLOR: Set the drawing color (in A). The new color is already checked ; to be in a valid range (0..maxcolor-1). ; ; Must set an error code: NO (will only be called if color ok) ; SETCOLOR: sta DRAWINDEX rts ; ------------------------------------------------------------------------ ; SETPALETTE: Set the palette (not available with all drivers/hardware). ; A pointer to the palette is passed in ptr1. Must set an error if palettes ; are not supported ; ; Must set an error code: YES ; SETPALETTE: ldy #31 @L1: lda (ptr1),y sta GCOLMAP,y ; $FDA0 dey bpl @L1 ; Done, reset the error code lda #TGI_ERR_OK sta ERROR rts ; ------------------------------------------------------------------------ ; GETPALETTE: Return the current palette in A/X. Even drivers that cannot ; set the palette should return the default palette here, so there's no ; way for this function to fail. ; ; Must set an error code: NO ; GETPALETTE: lda #<GCOLMAP ; $FDA0 ldx #>GCOLMAP rts ; ------------------------------------------------------------------------ ; GETDEFPALETTE: Return the default palette for the driver in A/X. All ; drivers should return something reasonable here, even drivers that don't ; support palettes, otherwise the caller has no way to determine the colors ; of the (not changeable) palette. ; ; Must set an error code: NO (all drivers must have a default palette) ; GETDEFPALETTE: lda #<DEFPALETTE ldx #>DEFPALETTE rts ; ------------------------------------------------------------------------ ; SETPIXEL: Draw one pixel at X1/Y1 = ptr1/ptr2 with the current drawing ; color. The coordinates passed to this function are never outside the ; visible screen area, so there is no need for clipping inside this function. ; ; Must set an error code: NO ; .data pixel_coll: .byte 0 pixel_sprite: .byte %00000001 ; A pixel sprite .byte %00010000 .byte %00100000 .addr 0,pixel_bitmap pix_x: .word 0 pix_y: .word 0 .word $100 .word $100 pix_c: .byte $00 .code SETPIXEL: lda X1 sta pix_x lda Y1 sta pix_y lda DRAWINDEX sta pix_c lda #<pixel_sprite ldx #>pixel_sprite jmp draw_sprite ; ------------------------------------------------------------------------ ; GETPIXEL: Read the color value of a pixel and return it in A/X. The ; coordinates passed to this function are never outside the visible screen ; area, so there is no need for clipping inside this function. GETPIXEL: lda Y1 sta MATHD ; Hardware multiply stz MATHC lda #80 sta MATHB stz MATHA lda X1 lsr A php tay clc lda VIEWPAGEL adc MATHH sta ptr1 lda VIEWPAGEH adc MATHG sta ptr1+1 ldx #0 lda #15 sta MAPCTL lda (ptr1),y tay lda #$0c sta MAPCTL tya plp bcc @L1 and #$f rts @L1: lsr A lsr A lsr A lsr A rts ; ------------------------------------------------------------------------ ; LINE: Draw a line from X1/Y1 to X2/Y2, where X1/Y1 = ptr1/ptr2 and ; X2/Y2 = ptr3/ptr4 using the current drawing color. ; ; Must set an error code: NO ; .data line_coll: .byte 0 line_sprite: .byte 0 ; Will be replaced by the code .byte %00110000 .byte %00100000 .word 0,pixel_bitmap line_x: .word 0 line_y: .word 0 line_sx: .word $100 line_sy: .word $100 .word 0 line_tilt: .word 0 line_c: .byte $e .code LINE: lda DRAWINDEX sta line_c stz line_sx stz line_sy sec lda X2 sbc X1 lda X2+1 sbc X1+1 bpl @L1 lda X1 ldx X2 sta X2 stx X1 lda X1+1 ldx X2+1 sta X2+1 stx X1+1 lda Y1 ldx Y2 sta Y2 stx Y1 lda Y1+1 ldx Y2+1 sta Y2+1 stx Y1+1 @L1: lda #%00000000 ; Not flipped sta line_sprite sec lda Y2 sbc Y1 sta Y2 lda Y2+1 sbc Y1+1 sta Y2+1 bpl @L2 sec lda #0 sbc Y2 sta Y2 lda #0 sbc Y2+1 sta Y2+1 lda #%00010000 ; Vertical flip sta line_sprite @L2: lda X1 sta line_x lda X1+1 sta line_x+1 lda Y1 sta line_y lda Y1+1 sta line_y+1 lda Y2 ina sta line_sy+1 sta MATHP ; hardware divide stz MATHN stz MATHH stz MATHG sec lda X2 sbc X1 ina sta MATHF stz MATHE @L3: lda SPRSYS bmi @L3 ; wait for math done (bit 7 of sprsys) lda MATHC sta line_tilt lda MATHB sta line_tilt+1 bne @L4 lda #1 sta line_sx+1 bra @L6 @L4: bit line_tilt bpl @L5 ina @L5: sta line_sx+1 @L6: lda #<line_sprite ldx #>line_sprite jmp draw_sprite ; ------------------------------------------------------------------------ ; BAR: Draw a filled rectangle with the corners X1/Y1, X2/Y2, where ; X1/Y1 = ptr1/ptr2 and X2/Y2 = ptr3/ptr4 using the current drawing color. ; Contrary to most other functions, the graphics kernel will sort and clip ; the coordinates before calling the driver, so on entry the following ; conditions are valid: ; X1 <= X2 ; Y1 <= Y2 ; (X1 >= 0) && (X1 < XRES) ; (X2 >= 0) && (X2 < XRES) ; (Y1 >= 0) && (Y1 < YRES) ; (Y2 >= 0) && (Y2 < YRES) ; ; Must set an error code: NO ; .data bar_coll: .byte 0 bar_sprite: .byte %00000001 ; A pixel sprite .byte %00010000 .byte %00100000 .addr 0,pixel_bitmap bar_x: .word 0 bar_y: .word 0 bar_sx: .word $0100 bar_sy: .word $0100 bar_c: .byte $00 .code BAR: lda X1 sta bar_x lda Y1 sta bar_y lda X2 sec sbc X1 ina sta bar_sx+1 lda Y2 sec sbc Y1 ina sta bar_sy+1 lda DRAWINDEX sta bar_c lda #<bar_sprite ldx #>bar_sprite jmp draw_sprite ; ------------------------------------------------------------------------ ; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in X and Y ; direction is passend in X/Y, the text direction is passed in A. ; ; Must set an error code: NO ; TEXTSTYLE: stx TEXTMAGX sty TEXTMAGY sta TEXTDIR rts ; ------------------------------------------------------------------------ ; OUTTEXT: Output text at X/Y = ptr1/ptr2 using the current color and the ; current text style. The text to output is given as a zero terminated ; string with address in ptr3. ; ; Must set an error code: NO ; OUTTEXT: lda TEXTMAGX ; Scale sprite sta text_sx+1 lda TEXTMAGY sta text_sy+1 stz text_sprite ; Set normal sprite lda BGINDEX bne @L1 lda #4 sta text_sprite ; Set opaque sprite @L1: lda DRAWINDEX ; Set color asl asl asl asl ora BGINDEX sta text_c lda X1 ; Set start position sta text_x lda X1+1 sta text_x+1 lda Y1 sta text_y lda Y1+1 sta text_y+1 ldy #<-1 ; Calculate string length @L2: iny lda (STRPTR),y bne @L2 cpy #20 bmi @L3 ldy #20 @L3: sty STRLEN bne @L4 rts ; Zero length string @L4: iny ; Prepare text_bitmap iny sty STROFF ldy #8-1 ; 8 pixel lines per character ldx #0 clc @L5: lda STROFF sta text_bitmap,x txa adc STROFF tax lda #$ff sta text_bitmap-1,x dey bpl @L5 stz text_bitmap,x stz tmp2 iny @L6: lda (STRPTR),y sty tmp1 sec ; (ch-' ') * 8 sbc #32 stz FONTOFF stz FONTOFF+1 asl asl rol FONTOFF+1 asl rol FONTOFF+1 clc ; Choose font adc #<font sta FONTOFF lda FONTOFF+1 adc #>font sta FONTOFF+1 ; and now copy the 8 bytes of that char ldx tmp2 inx stx tmp2 ; draw char from top to bottom, reading char-data from offset 8-1 to offset 0 ldy #8-1 @L7: lda (FONTOFF),y ; *chptr sta text_bitmap,x ;textbuf[y*(1+len+1)+1+x] txa adc STROFF tax dey bpl @L7 ; goto next char ldy tmp1 iny dec STRLEN bne @L6 lda #<text_sprite ldx #>text_sprite jmp draw_sprite .data text_coll: .byte 0 text_sprite: .byte $00,$90,$20 .addr 0, text_bitmap text_x: .word 0 text_y: .word 0 text_sx: .word $100 text_sy: .word $100 text_c: .byte 0 .rodata ; The Font ; 96 characters from ASCII 32 to 127 ; 8 pixels wide, 8 pixels high ; bit value 0 = foreground, bit value 1 = background / transparent font: ; VERSAIL .byte $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF ;32 .byte $FF, $E7, $FF, $FF, $E7, $E7, $E7, $E7 ;33 .byte $FF, $FF, $FF, $FF, $FF, $99, $99, $99 ;34 .byte $FF, $99, $99, $00, $99, $00, $99, $99 ;35 .byte $FF, $E7, $83, $F9, $C3, $9F, $C1, $E7 ;36 .byte $FF, $B9, $99, $CF, $E7, $F3, $99, $9D ;37 .byte $FF, $C0, $99, $98, $C7, $C3, $99, $C3 ;38 .byte $FF, $FF, $FF, $FF, $FF, $E7, $F3, $F9 ;39 .byte $FF, $F3, $E7, $CF, $CF, $CF, $E7, $F3 ;40 .byte $FF, $CF, $E7, $F3, $F3, $F3, $E7, $CF ;41 .byte $FF, $FF, $99, $C3, $00, $C3, $99, $FF ;42 .byte $FF, $FF, $E7, $E7, $81, $E7, $E7, $FF ;43 .byte $CF, $E7, $E7, $FF, $FF, $FF, $FF, $FF ;44 .byte $FF, $FF, $FF, $FF, $81, $FF, $FF, $FF ;45 .byte $FF, $E7, $E7, $FF, $FF, $FF, $FF, $FF ;46 .byte $FF, $9F, $CF, $E7, $F3, $F9, $FC, $FF ;47 .byte $FF, $C3, $99, $99, $89, $91, $99, $C3 ;48 .byte $FF, $81, $E7, $E7, $E7, $C7, $E7, $E7 ;49 .byte $FF, $81, $9F, $CF, $F3, $F9, $99, $C3 ;50 .byte $FF, $C3, $99, $F9, $E3, $F9, $99, $C3 ;51 .byte $FF, $F9, $F9, $80, $99, $E1, $F1, $F9 ;52 .byte $FF, $C3, $99, $F9, $F9, $83, $9F, $81 ;53 .byte $FF, $C3, $99, $99, $83, $9F, $99, $C3 ;54 .byte $FF, $E7, $E7, $E7, $E7, $F3, $99, $81 ;55 .byte $FF, $C3, $99, $99, $C3, $99, $99, $C3 ;56 .byte $FF, $C3, $99, $F9, $C1, $99, $99, $C3 ;57 .byte $FF, $FF, $E7, $FF, $FF, $E7, $FF, $FF ;58 .byte $CF, $E7, $E7, $FF, $FF, $E7, $FF, $FF ;59 .byte $FF, $F1, $E7, $CF, $9F, $CF, $E7, $F1 ;60 .byte $FF, $FF, $FF, $81, $FF, $81, $FF, $FF ;61 .byte $FF, $8F, $E7, $F3, $F9, $F3, $E7, $8F ;62 .byte $FF, $E7, $FF, $E7, $F3, $F9, $99, $C3 ;63 .byte $FF, $C3, $9D, $9F, $91, $91, $99, $C3 ;0 .byte $FF, $99, $99, $99, $81, $99, $C3, $E7 ;1 .byte $FF, $83, $99, $99, $83, $99, $99, $83 ;2 .byte $FF, $C3, $99, $9F, $9F, $9F, $99, $C3 ;3 .byte $FF, $87, $93, $99, $99, $99, $93, $87 ;4 .byte $FF, $81, $9F, $9F, $87, $9F, $9F, $81 ;5 .byte $FF, $9F, $9F, $9F, $87, $9F, $9F, $81 ;6 .byte $FF, $C3, $99, $99, $91, $9F, $99, $C3 ;7 .byte $FF, $99, $99, $99, $81, $99, $99, $99 ;8 .byte $FF, $C3, $E7, $E7, $E7, $E7, $E7, $C3 ;9 .byte $FF, $C7, $93, $F3, $F3, $F3, $F3, $E1 ;10 .byte $FF, $99, $93, $87, $8F, $87, $93, $99 ;11 .byte $FF, $81, $9F, $9F, $9F, $9F, $9F, $9F ;12 .byte $FF, $9C, $9C, $9C, $94, $80, $88, $9C ;13 .byte $FF, $99, $99, $91, $81, $81, $89, $99 ;14 .byte $FF, $C3, $99, $99, $99, $99, $99, $C3 ;15 .byte $FF, $9F, $9F, $9F, $83, $99, $99, $83 ;16 .byte $FF, $F1, $C3, $99, $99, $99, $99, $C3 ;17 .byte $FF, $99, $93, $87, $83, $99, $99, $83 ;18 .byte $FF, $C3, $99, $F9, $C3, $9F, $99, $C3 ;19 .byte $FF, $E7, $E7, $E7, $E7, $E7, $E7, $81 ;20 .byte $FF, $C3, $99, $99, $99, $99, $99, $99 ;21 .byte $FF, $E7, $C3, $99, $99, $99, $99, $99 ;22 .byte $FF, $9C, $88, $80, $94, $9C, $9C, $9C ;23 .byte $FF, $99, $99, $C3, $E7, $C3, $99, $99 ;24 .byte $FF, $E7, $E7, $E7, $C3, $99, $99, $99 ;25 .byte $FF, $81, $9F, $CF, $E7, $F3, $F9, $81 ;26 .byte $FF, $C3, $CF, $CF, $CF, $CF, $CF, $C3 ;27 .byte $FF, $03, $9D, $CF, $83, $CF, $ED, $F3 ;28 .byte $FF, $C3, $F3, $F3, $F3, $F3, $F3, $C3 ;29 .byte $E7, $E7, $E7, $E7, $81, $C3, $E7, $FF ;30 .byte $FF, $EF, $CF, $80, $80, $CF, $EF, $FF ;31 ; gemena .byte $FF, $C3, $9D, $9F, $91, $91, $99, $C3 ;224 .byte $FF, $C1, $99, $C1, $F9, $C3, $FF, $FF ;225 .byte $FF, $83, $99, $99, $83, $9F, $9F, $FF ;226 .byte $FF, $C3, $9F, $9F, $9F, $C3, $FF, $FF ;227 .byte $FF, $C1, $99, $99, $C1, $F9, $F9, $FF ;228 .byte $FF, $C3, $9F, $81, $99, $C3, $FF, $FF ;229 .byte $FF, $E7, $E7, $E7, $C1, $E7, $F1, $FF ;230 .byte $83, $F9, $C1, $99, $99, $C1, $FF, $FF ;231 .byte $FF, $99, $99, $99, $83, $9F, $9F, $FF ;232 .byte $FF, $C3, $E7, $E7, $C7, $FF, $E7, $FF ;233 .byte $C3, $F9, $F9, $F9, $F9, $FF, $F9, $FF ;234 .byte $FF, $99, $93, $87, $93, $9F, $9F, $FF ;235 .byte $FF, $C3, $E7, $E7, $E7, $E7, $C7, $FF ;236 .byte $FF, $9C, $94, $80, $80, $99, $FF, $FF ;237 .byte $FF, $99, $99, $99, $99, $83, $FF, $FF ;238 .byte $FF, $C3, $99, $99, $99, $C3, $FF, $FF ;239 .byte $9F, $9F, $83, $99, $99, $83, $FF, $FF ;240 .byte $F9, $F9, $C1, $99, $99, $C1, $FF, $FF ;241 .byte $FF, $9F, $9F, $9F, $99, $83, $FF, $FF ;242 .byte $FF, $83, $F9, $C3, $9F, $C1, $FF, $FF ;243 .byte $FF, $F1, $E7, $E7, $E7, $81, $E7, $FF ;244 .byte $FF, $C1, $99, $99, $99, $99, $FF, $FF ;245 .byte $FF, $E7, $C3, $99, $99, $99, $FF, $FF ;246 .byte $FF, $C9, $C1, $80, $94, $9C, $FF, $FF ;247 .byte $FF, $99, $C3, $E7, $C3, $99, $FF, $FF ;248 .byte $87, $F3, $C1, $99, $99, $99, $FF, $FF ;249 .byte $FF, $81, $CF, $E7, $F3, $81, $FF, $FF ;250 .byte $FF, $C3, $CF, $CF, $CF, $CF, $CF, $C3 ;251 .byte $FF, $03, $9D, $CF, $83, $CF, $ED, $F3 ;252 .byte $FF, $C3, $F3, $F3, $F3, $F3, $F3, $C3 ;253 .byte $E7, $E7, $E7, $E7, $81, $C3, $E7, $FF ;254 .byte $FF, $EF, $CF, $80, $80, $CF, $EF, $FF ;255 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/tgi_colors.s������������������������������������������������������������������0000664�0000000�0000000�00000000340�13473601511�0017002�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Target-specific black & white values for use by the target-shared TGI kernel ; .include "tgi-kernel.inc" .export tgi_color_black:zp = $00 .export tgi_color_white:zp = $0F ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/tgi_irq.s���������������������������������������������������������������������0000664�0000000�0000000�00000000344�13473601511�0016300�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2018-02-02 ; .export tgi_libref .interruptor tgi_irq ; Export as IRQ handler .data tgi_libref: tgi_irq: .byte $60, $00, $00 ; RTS plus two dummy bytes ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/tgi_stat_stddrv.s�������������������������������������������������������������0000664�0000000�0000000�00000000361�13473601511�0020045�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Address of the static standard tgi driver ; ; Oliver Schmidt, 2012-11-01 ; ; const void tgi_static_stddrv[]; ; .export _tgi_static_stddrv .import _lynx_160_102_16_tgi .rodata _tgi_static_stddrv := _lynx_160_102_16_tgi �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/tgi_stddrv.s������������������������������������������������������������������0000664�0000000�0000000�00000000267�13473601511�0017017�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Name of the standard tgi driver ; ; Oliver Schmidt, 2012-11-01 ; ; const char tgi_stddrv[]; ; .export _tgi_stddrv .rodata _tgi_stddrv: .asciiz "lynx-160-102-16.tgi" �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/lynx/uploader.s��������������������������������������������������������������������0000664�0000000�0000000�00000003103�13473601511�0016451�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ .include "lynx.inc" .include "extzp.inc" .interruptor _UpLoaderIRQ .export __UPLOADER__: absolute = 1 load_len=_FileDestAddr load_ptr=_FileFileLen load_ptr2=_FileCurrBlock .segment "UPCODE" ComLynxReadAndExec: ldy #4 loop0: jsr read_byte sta load_len-1,y dey bne loop0 ; get destination and length tax ; lowbyte of length lda load_ptr sta load_ptr2 lda load_ptr+1 sta load_ptr2+1 loop1: inx bne cont1 inc load_len+1 bne cont1 jmp (load_ptr) cont1: jsr read_byte sta (load_ptr2),y sta PALETTE ; feedback ;-) iny bne loop1 inc load_ptr2+1 bra loop1 read_byte: bit SERCTL bvc read_byte lda SERDAT rts _UpLoaderIRQ: lda INTSET and #$10 bne @L0 clc rts @L0: lda SERDAT ; wait for the start sequence bit flag ; already seen $81 ? bpl again ; >= 0 => no cmp #$50 ; "P" ? bne again ; not correct, so clear flag sei jmp ComLynxReadAndExec again: stz flag cmp #$81 bne exit sta flag ; ; last action : clear interrupt ; exit: clc rts .segment "UPDATA" flag: .byte 0 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/mouse/�����������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014613�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/mouse/mouse-kernel.s���������������������������������������������������������������0000664�0000000�0000000�00000013041�13473601511�0017404�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-28, 2009-09-26 ; ; Common functions of the mouse driver API. ; .import return0, popsreg, incsp2, mouse_libref .importzp sreg, ptr1, tmp1, tmp2 .interruptor mouse_irq ; Export as IRQ handler .include "mouse-kernel.inc" ;---------------------------------------------------------------------------- ; Variables .bss _mouse_drv: .res 2 ; Pointer to driver _mouse_hidden: .res 1 ; Mouse visibility flag ; Jump table for the driver functions. .data mouse_vectors: mouse_install: jmp return0 mouse_uninstall:jmp return0 mouse_hide: jmp return0 mouse_show: jmp return0 mouse_setbox: jmp return0 mouse_getbox: jmp return0 mouse_move: jmp return0 mouse_buttons: jmp return0 mouse_pos: jmp return0 mouse_info: jmp return0 mouse_ioctl: jmp return0 mouse_irq: .byte $60, $00, $00 ; RTS plus two dummy bytes mouse_flags: .byte $00 ; Driver header signature .rodata mouse_sig: .byte $6d, $6f, $75, MOUSE_API_VERSION ; "mou", version .code ;---------------------------------------------------------------------------- ; unsigned char __fastcall__ mouse_install (const struct mouse_callbacks* c, ; void* driver); ; /* Install an already loaded driver. Returns an error code. */ _mouse_install: sta _mouse_drv sta ptr1 stx _mouse_drv+1 stx ptr1+1 ; Check the driver signature ldy #.sizeof(mouse_sig)-1 @L0: lda (ptr1),y cmp mouse_sig,y bne inv_drv dey bpl @L0 ; Set the library reference ldy #MOUSE_HDR::LIBREF lda #<mouse_libref sta (ptr1),y iny lda #>mouse_libref sta (ptr1),y ; Reset flags lda #1 sta _mouse_hidden ; Copy the jump vectors ldy #MOUSE_HDR::JUMPTAB ldx #0 @L1: inx ; Skip the JMP opcode jsr copyjv ; Copy one byte jsr copyjv ; Copy one byte cpy #(MOUSE_HDR::JUMPTAB + .sizeof(MOUSE_HDR::JUMPTAB)) bne @L1 ; Copy the flags byte. It is located directly behind the jump vectors, so Y ; is already correct when we come here. To save code, we use copyjv - crude ; but effective. jsr copyjv ; Copy the callback vectors into the driver space jsr popsreg ldy #(MOUSE_HDR::CALLBACKS + .sizeof(MOUSE_HDR::CALLBACKS) - 1) sty tmp2 ldy #.sizeof(MOUSE_CALLBACKS)-1 sty tmp1 @L2: jsr copycb ldy tmp1 jsr copycb dec tmp2 ; Skip opcode byte ldy tmp1 bpl @L2 ; Install the IRQ vector if the driver needs it bit mouse_flags ; Test MOUSE_FLAG_EARLY_IRQ bvc @L3 ; Jump if no interrupts at this time jsr install_irq ; Activate IRQ routine ; Call driver install routine and check for errors @L3: jsr mouse_install tay ; Test error code bne uninstall_irq ; Jump on error ; No errors on INSTALL. If the driver needs late IRQs, enable them now. Be ; careful not to use A/X since these registers contain the error code from ; INSTALL. bit mouse_flags ; Test MOUSE_FLAG_LATE_IRQ bpl Exit ; Jump if vector not needed install_irq: ldy #$4C ; Jump opcode sty mouse_irq ; Activate IRQ routine Exit: rts ; Uninstall IRQ vector if install routine had errors. A/X may contain the ; error code from mouse_install, so don't use it. uninstall_irq: ldy #$60 ; RTS opcode sty mouse_irq ; Disable IRQ entry point rts ; Driver signature invalid. One word is still on the stack inv_drv: lda #MOUSE_ERR_INV_DRIVER ldx #0 jmp incsp2 ; Copy one byte from the jump vectors copyjv: lda (ptr1),y sta mouse_vectors,x iny inx rts ; Copy one byte from the callback vectors copycb: lda (sreg),y dec tmp1 ldy tmp2 sta (ptr1),y dec tmp2 rts ;---------------------------------------------------------------------------- ; unsigned char mouse_uninstall (void); ; /* Uninstall the currently loaded driver. Returns an error code. */ _mouse_uninstall: ; Depending on the late/early IRQ flag, we will disable IRQs before or after ; calling the driver mouse_uninstall routine. bit mouse_flags ; Test MOUSE_FLAG_LATE_IRQ bpl @L1 ; Don't disable interrupts now jsr uninstall_irq ; Disable driver interrupts @L1: jsr mouse_uninstall ; Call driver routine ; We don't check the flag a second time here, since disabling IRQs twice, ; or disabling them if they weren't enabled will do no harm, and the missing ; check will save a few bytes. jsr uninstall_irq ; Disable driver interrupts _mouse_clear_ptr: ; External entry point lda #0 sta _mouse_drv sta _mouse_drv+1 ; Clear the driver pointer tax rts ; Return zero �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/mouse/mouse_buttons.s��������������������������������������������������������������0000664�0000000�0000000�00000000500�13473601511�0017700�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-30 ; ; unsigned char mouse_buttons (void); ; /* Return a bit mask encoding the states of the mouse buttons. Use the ; ** MOUSE_BTN_XXX flags to decode a specific button. ; */ ; .include "mouse-kernel.inc" _mouse_buttons = mouse_buttons ; Call driver directly ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/mouse/mouse_getbox.s���������������������������������������������������������������0000664�0000000�0000000�00000000441�13473601511�0017476�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2009-09-26 ; ; void __fastcall__ mouse_getbox (struct mouse_box* box); ; /* Get the current bounding box for the mouse pointer movement. */ ; ; .include "mouse-kernel.inc" _mouse_getbox := mouse_getbox ; Call driver directly �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/mouse/mouse_geterrormsg.s����������������������������������������������������������0000664�0000000�0000000�00000002253�13473601511�0020551�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2004-11-07 ; ; const char* __fastcall__ mouse_geterrormsg (unsigned char code); ; /* Get an error message describing the error in code. */ ; .include "mouse-kernel.inc" .proc _mouse_geterrormsg cmp #MOUSE_ERR_COUNT bcc L1 lda #MOUSE_ERR_COUNT ; "Unknown error" L1: tay ldx #>msgtab lda #<msgtab clc adc offs,y bcc L2 inx L2: rts .endproc ;---------------------------------------------------------------------------- ; Error messages. The messages are currently limited to 256 bytes total. .rodata offs: .byte <(msg0-msgtab) .byte <(msg1-msgtab) .byte <(msg2-msgtab) .byte <(msg3-msgtab) .byte <(msg4-msgtab) .byte <(msg5-msgtab) .byte <(msg6-msgtab) msgtab: msg0: .asciiz "No error" msg1: .asciiz "No driver available" msg2: .asciiz "Cannot load driver" msg3: .asciiz "Invalid driver" msg4: .asciiz "Mouse hardware not found" msg5: .asciiz "Invalid ioctl code" msg6: .asciiz "Unknown error" �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/mouse/mouse_hide.s�����������������������������������������������������������������0000664�0000000�0000000�00000001132�13473601511�0017115�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-30 ; ; void mouse_hide (void); ; /* Hide the mouse. The function manages a counter and may be called more than ; ** once. For each call to mouse_hide there must be a call to mouse_show to make ; ** the mouse visible again. ; */ ; .include "mouse-kernel.inc" .proc _mouse_hide lda _mouse_hidden ; Get the flag bne @L1 ; Jump if already invisible jsr mouse_hide ; Call the driver @L1: inc _mouse_hidden ; Set the flag to invisible rts .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/mouse/mouse_info.s�����������������������������������������������������������������0000664�0000000�0000000�00000000661�13473601511�0017145�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-30 ; ; void __fastcall__ mouse_info (struct mouse_info* info); ; /* Return the state of the mouse buttons and the position of the mouse */ ; .import ptr1: zp .include "mouse-kernel.inc" .proc _mouse_info sta ptr1 stx ptr1+1 ; Store info into ptr1 jmp mouse_info ; Call the driver .endproc �������������������������������������������������������������������������������cc65-2.18/libsrc/mouse/mouse_ioctl.s����������������������������������������������������������������0000664�0000000�0000000�00000001057�13473601511�0017324�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-30 ; ; unsigned char __fastcall__ mouse_ioctl (unsigned char code, void* data); ; /* Call the driver specific ioctl function. NON PORTABLE! Returns an error ; ** code. ; */ ; .import popa .import ptr1: zp .include "mouse-kernel.inc" .proc _mouse_ioctl sta ptr1 stx ptr1+1 ; Store data into ptr1 jsr popa ; Get code from stack jmp mouse_ioctl ; Call the driver .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/mouse/mouse_load.s�����������������������������������������������������������������0000664�0000000�0000000�00000006171�13473601511�0017133�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2006-06-05 ; ; unsigned char __fastcall__ mouse_load_driver (const struct mouse_callbacks* c, ; const char* name) ; /* Load a mouse driver and return an error code */ .include "mouse-kernel.inc" .include "modload.inc" .include "fcntl.inc" .import pushax .import pusha0 .import incsp2 .import _open .import _read .import _close ;---------------------------------------------------------------------------- ; Variables .data ctrl: .addr _read .res 2 ; CALLERDATA .res 2 ; MODULE .res 2 ; MODULE_SIZE .res 2 ; MODULE_ID ;---------------------------------------------------------------------------- ; Code .code .proc _mouse_load_driver ; Save name on the C stack. We will need it later as parameter passed to open() jsr pushax ; Check if we do already have a driver loaded. If so, remove it. lda _mouse_drv ora _mouse_drv+1 beq @L1 jsr _mouse_uninstall ; Open the file. The name parameter is already on stack and will get removed ; by open(). ; ctrl.callerdata = open (name, O_RDONLY); @L1: lda #<O_RDONLY jsr pusha0 ldy #4 ; Argument size jsr _open sta ctrl + MOD_CTRL::CALLERDATA stx ctrl + MOD_CTRL::CALLERDATA+1 ; if (ctrl.callerdata >= 0) { txa bmi @L3 ; /* Load the module */ ; Res = mod_load (&ctrl); lda #<ctrl ldx #>ctrl jsr _mod_load pha ; /* Close the input file */ ; close (ctrl.callerdata); lda ctrl + MOD_CTRL::CALLERDATA ldx ctrl + MOD_CTRL::CALLERDATA+1 jsr _close ; /* Check the return code */ ; if (Res == MLOAD_OK) { pla bne @L3 ; Check the driver signature, install the driver. c is already on stack and ; will get removed by mouse_install(). ; Res = mouse_install (c, ctrl.module); lda ctrl + MOD_CTRL::MODULE ldx ctrl + MOD_CTRL::MODULE+1 jsr _mouse_install ; If mouse_install was successful, we're done tax beq @L2 ; The driver didn't install correctly. Remove it from memory and return the ; error code. pha ; Save the error code lda _mouse_drv ldx _mouse_drv+1 jsr _mod_free ; Free the driver memory jsr _mouse_clear_ptr ; Clear mouse_drv pla ; Restore the error code ldx #0 ; We must return an int @L2: rts ; Done ; Open or mod_load failed. Remove excess arguments from stack and return an ; error code. @L3: jsr incsp2 lda #<MOUSE_ERR_CANNOT_LOAD ldx #>MOUSE_ERR_CANNOT_LOAD rts .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/mouse/mouse_move.s�����������������������������������������������������������������0000664�0000000�0000000�00000001166�13473601511�0017161�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-30 ; ; void __fastcall__ mouse_move (int x, int y); ; /* Set the mouse cursor to the given position. If a mouse cursor is defined ; ** and currently visible, the mouse cursor is also moved. ; ** NOTE: This function does not check if the given position is valid and ; ** inside the bounding box. ; */ ; .import incsp2 .import ptr1: zp .include "mouse-kernel.inc" .proc _mouse_move jsr mouse_move ; Call the driver jmp incsp2 ; Drop the parameter .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/mouse/mouse_pos.s������������������������������������������������������������������0000664�0000000�0000000�00000000612�13473601511�0017007�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-30 ; ; void __fastcall__ mouse_pos (struct mouse_pos* pos); ; /* Return the current mouse position */ ; .import ptr1: zp .include "mouse-kernel.inc" .proc _mouse_pos sta ptr1 stx ptr1+1 ; Store pos into ptr1 jmp mouse_pos ; Call the driver .endproc ����������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/mouse/mouse_setbox.s���������������������������������������������������������������0000664�0000000�0000000�00000001562�13473601511�0017517�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2009-09-26 ; ; void __fastcall__ mouse_setbox (const struct mouse_box* box); ; /* Set the bounding box for the mouse pointer movement. The mouse X and Y ; ** coordinates will never go outside the given box. ; ** NOTE: The function does *not* check if the mouse is currently inside the ; ** given margins. The proper way to use this function therefore is: ; ** ; ** - Hide the mouse ; ** - Set the bounding box ; ** - Place the mouse at the desired position ; ** - Show the mouse again. ; ** ; ** NOTE2: When setting the box to something that is larger than the actual ; ** screen, the positioning of the mouse cursor can fail. If such margins ; ** are really what you want, you have to use your own cursor routines. ; */ ; ; .include "mouse-kernel.inc" _mouse_setbox := mouse_setbox ; Call driver directly ����������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/mouse/mouse_show.s�����������������������������������������������������������������0000664�0000000�0000000�00000000773�13473601511�0017176�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-12-30 ; ; void mouse_show (void); ; /* Show the mouse. See mouse_hide for more information. */ ; .include "mouse-kernel.inc" .proc _mouse_show lda _mouse_hidden ; Mouse visible? beq @L1 ; Jump if yes dec _mouse_hidden ; Set the flag bne @L1 ; Jump if still invisible jmp mouse_show ; Call the driver @L1: rts .endproc �����cc65-2.18/libsrc/mouse/mouse_unload.s���������������������������������������������������������������0000664�0000000�0000000�00000001641�13473601511�0017473�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2004-03-21 ; ; unsigned char mouse_unload (void); ; /* Uninstall, then unload the currently loaded driver. */ .include "mouse-kernel.inc" .include "modload.inc" .import return0 _mouse_unload: lda _mouse_drv pha ; Save pointer to driver ora _mouse_drv+1 beq no_driver ; No driver lda _mouse_drv+1 pha jsr _mouse_uninstall ; Uninstall the driver pla tax pla ; Get pointer to driver jsr _mod_free ; Free the driver jmp return0 ; Return MOUSE_ERR_OK no_driver: tax ; X = 0 pla ; Remove pushed junk lda #<MOUSE_ERR_NO_DRIVER rts �����������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/�������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014250�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/Makefile.inc�������������������������������������������������������������������0000664�0000000�0000000�00000000572�13473601511�0016464�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������../target/nes/drv/tgi/nes-64-56-2.tgi: \ ../libwrk/nes/clrscr.o \ ../libwrk/nes/cputc.o \ ../libwrk/nes/get_tv.o \ ../libwrk/nes/gotoxy.o \ ../libwrk/nes/popa.o \ ../libwrk/nes/ppu.o \ ../libwrk/nes/ppubuf.o \ ../libwrk/nes/setcursor.o ��������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/_scrsize.s���������������������������������������������������������������������0000664�0000000�0000000�00000000634�13473601511�0016260�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-04-14 ; Stefan Haubenthal, 2011-05-11 ; ; Screen size function ; .export screensize .include "nes.inc" .include "get_tv.inc" .proc screensize jsr _get_tv ldx #charsperline ldy #screenrows cmp #TV::PAL beq pal dey ; NTSC rows pal: rts .endproc ����������������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/cclear.s�����������������������������������������������������������������������0000664�0000000�0000000�00000001432�13473601511�0015665�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 gotoxy, cputdirect .importzp tmp1 _cclearxy: pha ; Save the length 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 #$20 ; Blank - screen code jsr cputdirect ; Direct output dec tmp1 bne L1 L9: rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/chline.s�����������������������������������������������������������������������0000664�0000000�0000000�00000001461�13473601511�0015700�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 gotoxy, cputdirect .importzp tmp1 .include "nes.inc" _chlinexy: pha ; Save the length 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 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/clock.s������������������������������������������������������������������������0000664�0000000�0000000�00000001124�13473601511�0015525�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; clock.s ; ; Written by Groepaz/Hitmen <groepaz@gmx.net> ; Cleanup by Ullrich von Bassewitz <uz@cc65.org> ; 2003-05-02, Greg King <gngking@erols.com> ; ; #include <time.h> ; ; clock_t clock (void); ; .include "nes.inc" .export _clock .importzp sreg .proc _clock ldy #0 ; High word is always zero sty sreg+1 sty sreg L1: ldx tickcount+1 lda tickcount cpx tickcount+1 ; Did tickcount change? bne L1 ; Yes, re-read it rts .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/clrscr.s�����������������������������������������������������������������������0000664�0000000�0000000�00000002577�13473601511�0015737�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Written by Groepaz/Hitmen <groepaz@gmx.net> ; Cleanup by Ullrich von Bassewitz <uz@cc65.org> ; ; void clrscr (void); ; .export _clrscr .import ppubuf_waitempty .include "nes.inc" .proc _clrscr ; wait until all console data has been written jsr ppubuf_waitempty ; wait for vblank lda #0 sta VBLANK_FLAG @w2: lda VBLANK_FLAG beq @w2 ; switch screen off lda #%00000000 sta PPU_CTRL2 ; Set start address to Name Table #1 lda #$20 sta PPU_VRAM_ADDR2 lda #$00 sta PPU_VRAM_ADDR2 ; Clear Name Table #1 lda #' ' ldx #$f0 ; 4*$f0=$03c0 beg: sta PPU_VRAM_IO sta PPU_VRAM_IO sta PPU_VRAM_IO sta PPU_VRAM_IO dex bne beg lda #$23 ; sta PPU_VRAM_ADDR2 ; Set start address to PPU address $23C0 lda #$C0 ; (1st attribute table) sta PPU_VRAM_ADDR2 ldx #$00 lll: lda #$00 ; Write attribute table value and auto increment sta PPU_VRAM_IO ; to next address inx cpx #$40 bne lll ; switch screen on again lda #%00011110 sta PPU_CTRL2 rts .endproc ���������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/color.s������������������������������������������������������������������������0000664�0000000�0000000�00000003106�13473601511�0015552�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Written by Groepaz/Hitmen <groepaz@gmx.net> ; Cleanup by Ullrich von Bassewitz <uz@cc65.org> ; ; 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 .import return0, ppubuf_put .include "nes.inc" _textcolor = return0 _bordercolor = return0 .proc _bgcolor tax lda BGCOLOR ; get old value stx BGCOLOR ; set new value pha lda colors,x pha ldy #$3F ldx #0 jsr ppubuf_put pla pha ldy #$3F ldx #4 jsr ppubuf_put pla pha ldy #$3F ldx #8 jsr ppubuf_put pla ldy #$3F ldx #12 jsr ppubuf_put pla rts .endproc .rodata colors: .byte $0f ; 0 black .byte $3d ; 1 white .byte $04 ; 2 red .byte $3b ; 3 cyan .byte $14 ; 4 violett .byte $1a ; 5 green .byte $01 ; 6 blue .byte $38 ; 7 yellow .byte $18 ; 8 orange .byte $08 ; 9 brown .byte $35 ; a light red .byte $2d ; b dark grey .byte $10 ; c middle grey .byte $2b ; d light green .byte $22 ; e light blue .byte $3d ; f light gray ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/cputc.s������������������������������������������������������������������������0000664�0000000�0000000�00000004260�13473601511�0015554�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Written by Groepaz/Hitmen <groepaz@gmx.net> ; Cleanup by Ullrich von Bassewitz <uz@cc65.org> ; ; void cputcxy (unsigned char x, unsigned char y, char c); ; void cputc (char c); ; .export _cputcxy, _cputc, cputdirect, putchar .export newline .constructor initconio .import gotoxy .import ppuinit, paletteinit, ppubuf_put .import setcursor .importzp tmp3,tmp4 .include "nes.inc" ;----------------------------------------------------------------------------- .code _cputcxy: pha ; Save C jsr gotoxy ; Set cursor, drop x and y pla ; Restore C ; Plot a character - also used as internal function _cputc: cmp #$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 inc CURS_Y ; 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 jmp setcursor ; 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 ldy SCREEN_PTR+1 ldx SCREEN_PTR jmp ppubuf_put ;----------------------------------------------------------------------------- ; Initialize the conio subsystem. Code goes into the ONCE segment, which may ; be reused after startup. .segment "ONCE" initconio: jsr ppuinit jsr paletteinit lda #0 sta RVS sta CURS_X sta CURS_Y jmp plot ; Set the cursor ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/crt0.s�������������������������������������������������������������������������0000664�0000000�0000000�00000012644�13473601511�0015313�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Start-up code for cc65 (NES version) ; ; by Groepaz/Hitmen <groepaz@gmx.net> ; based on code by Ullrich von Bassewitz <uz@cc65.org> ; .export _exit .export __STARTUP__ : absolute = 1 ; Mark as startup .import initlib, donelib, callmain .import push0, _main, zerobss, copydata .import ppubuf_flush ; Linker-generated symbols .import __RAM_START__, __RAM_SIZE__ .import __SRAM_START__, __SRAM_SIZE__ .import __ROM0_START__, __ROM0_SIZE__ .import __STARTUP_LOAD__,__STARTUP_RUN__, __STARTUP_SIZE__ .import __CODE_LOAD__,__CODE_RUN__, __CODE_SIZE__ .import __RODATA_LOAD__,__RODATA_RUN__, __RODATA_SIZE__ ; ------------------------------------------------------------------------ ; Character data ; ------------------------------------------------------------------------ .forceimport NESfont .include "zeropage.inc" .include "nes.inc" ; ------------------------------------------------------------------------ ; 16-byte INES header .segment "HEADER" ; +--------+------+------------------------------------------+ ; | Offset | Size | Content(s) | ; +--------+------+------------------------------------------+ ; | 0 | 3 | 'NES' | ; | 3 | 1 | $1A | ; | 4 | 1 | 16K PRG-ROM page count | ; | 5 | 1 | 8K CHR-ROM page count | ; | 6 | 1 | ROM Control Byte #1 | ; | | | %####vTsM | ; | | | | ||||+- 0=Horizontal mirroring | ; | | | | |||| 1=Vertical mirroring | ; | | | | |||+-- 1=SRAM enabled | ; | | | | ||+--- 1=512-byte trainer present | ; | | | | |+---- 1=Four-screen mirroring | ; | | | | | | ; | | | +--+----- Mapper # (lower 4-bits) | ; | 7 | 1 | ROM Control Byte #2 | ; | | | %####0000 | ; | | | | | | ; | | | +--+----- Mapper # (upper 4-bits) | ; | 8-15 | 8 | $00 | ; | 16-.. | | Actual 16K PRG-ROM pages (in linear | ; | ... | | order). If a trainer exists, it precedes | ; | ... | | the first PRG-ROM page. | ; | ..-EOF | | CHR-ROM pages (in ascending order). | ; +--------+------+------------------------------------------+ .byte $4e,$45,$53,$1a ; "NES"^Z .byte 2 ; ines prg - Specifies the number of 16k prg banks. .byte 1 ; ines chr - Specifies the number of 8k chr banks. .byte %00000011 ; ines mir - Specifies VRAM mirroring of the banks. .byte %00000000 ; ines map - Specifies the NES mapper used. .byte 0,0,0,0,0,0,0,0 ; 8 zeroes ; ------------------------------------------------------------------------ ; Place the startup code in a special segment. .segment "STARTUP" start: ; Set up the CPU and System-IRQ. sei cld ldx #0 stx VBLANK_FLAG stx ringread stx ringwrite stx ringcount txs lda #$20 @l: sta ringbuff,x sta ringbuff+$0100,x sta ringbuff+$0200,x inx bne @l ; Clear the BSS data. jsr zerobss ; Initialize the data. jsr copydata ; Set up the stack. lda #<(__SRAM_START__ + __SRAM_SIZE__) ldx #>(__SRAM_START__ + __SRAM_SIZE__) sta sp stx sp+1 ; Set argument stack ptr ; Call the module constructors. jsr initlib ; Push the command-line arguments; and, call main(). jsr callmain ; Call the module destructors. This is also the exit() entry. _exit: jsr donelib ; Run module destructors ; Reset the NES. jmp start ; ------------------------------------------------------------------------ ; System V-Blank Interrupt ; Updates PPU Memory (buffered). ; Updates VBLANK_FLAG and tickcount. ; ------------------------------------------------------------------------ nmi: pha tya pha txa pha lda #1 sta VBLANK_FLAG inc tickcount bne @s inc tickcount+1 @s: jsr ppubuf_flush ; Reset the video counter. lda #$20 sta PPU_VRAM_ADDR2 lda #$00 sta PPU_VRAM_ADDR2 ; Reset scrolling. sta PPU_VRAM_ADDR1 sta PPU_VRAM_ADDR1 pla tax pla tay pla ; Interrupt exit irq: rti ; ------------------------------------------------------------------------ ; Hardware vectors ; ------------------------------------------------------------------------ .segment "VECTORS" .word nmi ; $fffa vblank nmi .word start ; $fffc reset .word irq ; $fffe irq / brk ��������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/ctype.s������������������������������������������������������������������������0000664�0000000�0000000�00000015333�13473601511�0015565�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 02.06.1998 ; ; Character specification table. ; ; 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. ; ; ; Bit assignments: ; ; 0 - Lower case char ; 1 - Upper case char ; 2 - Numeric digit ; 3 - Hex digit (both, lower and upper) ; 4 - Control character ; 5 - The space character itself ; 6 - Other whitespace (that is: '\f', '\n', '\r', '\t' and '\v') ; 7 - Space or tab character .export __ctype __ctype: .repeat 2 ; 2 times for normal and inverted .byte $10 ; 0/00 ___ctrl_@___ .byte $10 ; 1/01 ___ctrl_A___ .byte $10 ; 2/02 ___ctrl_B___ .byte $10 ; 3/03 ___ctrl_C___ .byte $10 ; 4/04 ___ctrl_D___ .byte $10 ; 5/05 ___ctrl_E___ .byte $10 ; 6/06 ___ctrl_F___ .byte $10 ; 7/07 ___ctrl_G___ .byte $10 ; 8/08 ___ctrl_H___ .byte $D0 ; 9/09 ___ctrl_I___ .byte $50 ; 10/0a ___ctrl_J___ .byte $50 ; 11/0b ___ctrl_K___ .byte $50 ; 12/0c ___ctrl_L___ .byte $50 ; 13/0d ___ctrl_M___ .byte $10 ; 14/0e ___ctrl_N___ .byte $10 ; 15/0f ___ctrl_O___ .byte $10 ; 16/10 ___ctrl_P___ .byte $10 ; 17/11 ___ctrl_Q___ .byte $10 ; 18/12 ___ctrl_R___ .byte $10 ; 19/13 ___ctrl_S___ .byte $10 ; 20/14 ___ctrl_T___ .byte $10 ; 21/15 ___ctrl_U___ .byte $10 ; 22/16 ___ctrl_V___ .byte $10 ; 23/17 ___ctrl_W___ .byte $10 ; 24/18 ___ctrl_X___ .byte $10 ; 25/19 ___ctrl_Y___ .byte $10 ; 26/1a ___ctrl_Z___ .byte $10 ; 27/1b ___ctrl_[___ .byte $10 ; 28/1c ___ctrl_\___ .byte $10 ; 29/1d ___ctrl_]___ .byte $10 ; 30/1e ___ctrl_^___ .byte $10 ; 31/1f ___ctrl_____ .byte $A0 ; 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 $0C ; 48/30 _____0_____ .byte $0C ; 49/31 _____1_____ .byte $0C ; 50/32 _____2_____ .byte $0C ; 51/33 _____3_____ .byte $0C ; 52/34 _____4_____ .byte $0C ; 53/35 _____5_____ .byte $0C ; 54/36 _____6_____ .byte $0C ; 55/37 _____7_____ .byte $0C ; 56/38 _____8_____ .byte $0C ; 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 $0A ; 65/41 _____A_____ .byte $0A ; 66/42 _____B_____ .byte $0A ; 67/43 _____C_____ .byte $0A ; 68/44 _____D_____ .byte $0A ; 69/45 _____E_____ .byte $0A ; 70/46 _____F_____ .byte $02 ; 71/47 _____G_____ .byte $02 ; 72/48 _____H_____ .byte $02 ; 73/49 _____I_____ .byte $02 ; 74/4a _____J_____ .byte $02 ; 75/4b _____K_____ .byte $02 ; 76/4c _____L_____ .byte $02 ; 77/4d _____M_____ .byte $02 ; 78/4e _____N_____ .byte $02 ; 79/4f _____O_____ .byte $02 ; 80/50 _____P_____ .byte $02 ; 81/51 _____Q_____ .byte $02 ; 82/52 _____R_____ .byte $02 ; 83/53 _____S_____ .byte $02 ; 84/54 _____T_____ .byte $02 ; 85/55 _____U_____ .byte $02 ; 86/56 _____V_____ .byte $02 ; 87/57 _____W_____ .byte $02 ; 88/58 _____X_____ .byte $02 ; 89/59 _____Y_____ .byte $02 ; 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 ___grave___ .byte $09 ; 97/61 _____a_____ .byte $09 ; 98/62 _____b_____ .byte $09 ; 99/63 _____c_____ .byte $09 ; 100/64 _____d_____ .byte $09 ; 101/65 _____e_____ .byte $09 ; 102/66 _____f_____ .byte $01 ; 103/67 _____g_____ .byte $01 ; 104/68 _____h_____ .byte $01 ; 105/69 _____i_____ .byte $01 ; 106/6a _____j_____ .byte $01 ; 107/6b _____k_____ .byte $01 ; 108/6c _____l_____ .byte $01 ; 109/6d _____m_____ .byte $01 ; 110/6e _____n_____ .byte $01 ; 111/6f _____o_____ .byte $01 ; 112/70 _____p_____ .byte $01 ; 113/71 _____q_____ .byte $01 ; 114/72 _____r_____ .byte $01 ; 115/73 _____s_____ .byte $01 ; 116/74 _____t_____ .byte $01 ; 117/75 _____u_____ .byte $01 ; 118/76 _____v_____ .byte $01 ; 119/77 _____w_____ .byte $01 ; 120/78 _____x_____ .byte $01 ; 121/79 _____y_____ .byte $01 ; 122/7a _____z_____ .byte $00 ; 123/7b _____{_____ .byte $00 ; 124/7c _____|_____ .byte $00 ; 125/7d _____}_____ .byte $00 ; 126/7e _____~_____ .byte $40 ; 127/7f ____DEL____ .endrepeat �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/cvline.s�����������������������������������������������������������������������0000664�0000000�0000000�00000001543�13473601511�0015717�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 gotoxy, putchar, newline .importzp tmp1 .include "nes.inc" _cvlinexy: pha ; Save the length 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 �������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/get_tv.s�����������������������������������������������������������������������0000664�0000000�0000000�00000001505�13473601511�0015725�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Stefan Haubenthal, 2007-01-21 ; ; unsigned char get_tv (void); ; /* Return the video mode the machine is using */ ; .include "nes.inc" .include "get_tv.inc" .importzp tmp1, tmp2 ;-------------------------------------------------------------------------- ; _get_tv .proc _get_tv lda #TV::NTSC ; assume NTSC tax ; clear sta tmp1 sta tmp2 ldy tickcount wait: cpy tickcount beq wait iny ; next tick loop: cpy tickcount bne over inc tmp1 bne loop inc tmp2 bne loop over: ldy tmp2 cpy #9 bcc nopal lda #TV::PAL ; choose PAL nopal: rts .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/gotox.s������������������������������������������������������������������������0000664�0000000�0000000�00000000547�13473601511�0015602�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-05-02 ; ; void gotox (unsigned char x); ; .export _gotox .import setcursor .include "nes.inc" .proc _gotox sta CURS_X ; Set new position tay ldx CURS_Y jmp setcursor ; Set the cursor to the new position .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/gotoxy.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000767�13473601511�0015777�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; void gotoxy (unsigned char x, unsigned char y); ; .export gotoxy, _gotoxy .import setcursor .import popa .include "nes.inc" gotoxy: jsr popa ; Get Y _gotoxy: sta CURS_Y ; Set Y jsr popa ; Get X sta CURS_X ; Set X tay ldx CURS_Y jmp setcursor ; Set the cursor position ���������cc65-2.18/libsrc/nes/gotoy.s������������������������������������������������������������������������0000664�0000000�0000000�00000000566�13473601511�0015604�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-05-02 ; ; void gotoy (unsigned char y); ; .export _gotoy .import setcursor .include "nes.inc" .proc _gotoy sta CURS_Y ; Set new position tax ldy CURS_X jmp setcursor ; Set the cursor to the new position .endproc ������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/irq.s��������������������������������������������������������������������������0000664�0000000�0000000�00000000456�13473601511�0015234�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; IRQ handling (NES version) ; .export initirq, doneirq ; ------------------------------------------------------------------------ .segment "ONCE" initirq: rts ; ------------------------------------------------------------------------ .code doneirq: rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/joy/���������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015051�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/joy/nes-stdjoy.s���������������������������������������������������������������0000664�0000000�0000000�00000004517�13473601511�0017343�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Standard joypad driver for the NES. May be used multiple times when ; linked to the statically application. ; ; Ullrich von Bassewitz, 2003-05-02 ; Stefan Haubenthal, 2004-10-05 ; .include "zeropage.inc" .include "joy-kernel.inc" .include "joy-error.inc" .include "nes.inc" .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _nes_stdjoy_joy ; Driver signature .byte $6A, $6F, $79 ; "joy" .byte JOY_API_VERSION ; Driver API version number ; Library reference .addr $0000 ; Jump table. .addr INSTALL .addr UNINSTALL .addr COUNT .addr READJOY ; ------------------------------------------------------------------------ ; Constants JOY_COUNT = 2 ; 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 #0 ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; COUNT: Return the total number of available joysticks in a/x. ; COUNT: lda #JOY_COUNT ldx #0 rts ; ------------------------------------------------------------------------ ; READ: Read a particular joystick passed in A. ; READJOY: and #$01 ; Fix joystick number tay ; Joystick number (0,1) into Y lda #1 sta APU_PAD1 lda #0 sta APU_PAD1 ; Read joystick ldx #8 @Loop: lda APU_PAD1,y ror a ror tmp1 dex bne @Loop lda tmp1 ; ldx #$00 ; X implicitly fixed rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/joy_stat_stddrv.s��������������������������������������������������������������0000664�0000000�0000000�00000000354�13473601511�0017660�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Address of the static standard joystick driver ; ; Oliver Schmidt, 2012-11-01 ; ; const void joy_static_stddrv[]; ; .export _joy_static_stddrv .import _nes_stdjoy_joy .rodata _joy_static_stddrv := _nes_stdjoy_joy ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/libref.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000242�13473601511�0015675�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2013-05-31 ; .export joy_libref, tgi_libref .import _exit joy_libref := _exit tgi_libref := _exit ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/mainargs.s���������������������������������������������������������������������0000664�0000000�0000000�00000000654�13473601511�0016242�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-03-07 ; ; Setup arguments for main ; .constructor initmainargs, 24 .import __argc, __argv ;--------------------------------------------------------------------------- ; Get possible command-line arguments. Goes into the special ONCE segment, ; which may be reused after the startup code is run .segment "ONCE" .proc initmainargs rts .endproc ������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/neschar.s����������������������������������������������������������������������0000664�0000000�0000000�00000637600�13473601511�0016073�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ------------------------------------------------------------------------ ; Character data ; ------------------------------------------------------------------------ .export NESfont .segment "CHARS" NESfont: .byte %00000000 ; 0000 1-00: .byte %00000000 ; 0001 1-00: .byte %00000000 ; 0002 1-00: .byte %00000000 ; 0003 1-00: .byte %00000000 ; 0004 1-00: .byte %00000000 ; 0005 1-00: .byte %00000000 ; 0006 1-00: .byte %00000000 ; 0007 1-00: .byte %00000000 ; 0008 1-01: .byte %00000000 ; 0009 1-01: .byte %00000000 ; 000A 1-01: .byte %00000000 ; 000B 1-01: .byte %00000000 ; 000C 1-01: .byte %00000000 ; 000D 1-01: .byte %00000000 ; 000E 1-01: .byte %00000000 ; 000F 1-01: .byte %11001100 ; 0010 1-02: ** ** .byte %11001100 ; 0011 1-02: ** ** .byte %00110011 ; 0012 1-02: ** ** .byte %00110011 ; 0013 1-02: ** ** .byte %11001100 ; 0014 1-02: ** ** .byte %11001100 ; 0015 1-02: ** ** .byte %00110011 ; 0016 1-02: ** ** .byte %00110011 ; 0017 1-02: ** ** .byte %11001100 ; 0018 1-03: ** ** .byte %11001100 ; 0019 1-03: ** ** .byte %00110011 ; 001A 1-03: ** ** .byte %00110011 ; 001B 1-03: ** ** .byte %11001100 ; 001C 1-03: ** ** .byte %11001100 ; 001D 1-03: ** ** .byte %00110011 ; 001E 1-03: ** ** .byte %00110011 ; 001F 1-03: ** ** .byte %00000000 ; 0020 1-04: .byte %00011000 ; 0021 1-04: ** .byte %00111100 ; 0022 1-04: **** .byte %01111110 ; 0023 1-04: ****** .byte %00011000 ; 0024 1-04: ** .byte %00011000 ; 0025 1-04: ** .byte %00011000 ; 0026 1-04: ** .byte %00011000 ; 0027 1-04: ** .byte %00000000 ; 0028 1-05: .byte %00011000 ; 0029 1-05: ** .byte %00111100 ; 002A 1-05: **** .byte %01111110 ; 002B 1-05: ****** .byte %00011000 ; 002C 1-05: ** .byte %00011000 ; 002D 1-05: ** .byte %00011000 ; 002E 1-05: ** .byte %00011000 ; 002F 1-05: ** .byte %00000000 ; 0030 1-06: .byte %00010000 ; 0031 1-06: * .byte %00110000 ; 0032 1-06: ** .byte %01111111 ; 0033 1-06: ******* .byte %01111111 ; 0034 1-06: ******* .byte %00110000 ; 0035 1-06: ** .byte %00010000 ; 0036 1-06: * .byte %00000000 ; 0037 1-06: .byte %00000000 ; 0038 1-07: .byte %00010000 ; 0039 1-07: * .byte %00110000 ; 003A 1-07: ** .byte %01111111 ; 003B 1-07: ******* .byte %01111111 ; 003C 1-07: ******* .byte %00110000 ; 003D 1-07: ** .byte %00010000 ; 003E 1-07: * .byte %00000000 ; 003F 1-07: .byte %00001100 ; 0040 1-08: ** .byte %00010010 ; 0041 1-08: * * .byte %00110000 ; 0042 1-08: ** .byte %01111100 ; 0043 1-08: ***** .byte %00110000 ; 0044 1-08: ** .byte %01100010 ; 0045 1-08: ** * .byte %11111100 ; 0046 1-08: ****** .byte %00000000 ; 0047 1-08: .byte %00001100 ; 0048 1-09: ** .byte %00010010 ; 0049 1-09: * * .byte %00110000 ; 004A 1-09: ** .byte %01111100 ; 004B 1-09: ***** .byte %00110000 ; 004C 1-09: ** .byte %01100010 ; 004D 1-09: ** * .byte %11111100 ; 004E 1-09: ****** .byte %00000000 ; 004F 1-09: .byte %00000000 ; 0050 1-0a: .byte %00000000 ; 0051 1-0a: .byte %00000011 ; 0052 1-0a: ** .byte %00111110 ; 0053 1-0a: ***** .byte %01110110 ; 0054 1-0a: *** ** .byte %00110110 ; 0055 1-0a: ** ** .byte %00110110 ; 0056 1-0a: ** ** .byte %00000000 ; 0057 1-0a: .byte %00000000 ; 0058 1-0b: .byte %00000000 ; 0059 1-0b: .byte %00000011 ; 005A 1-0b: ** .byte %00111110 ; 005B 1-0b: ***** .byte %01110110 ; 005C 1-0b: *** ** .byte %00110110 ; 005D 1-0b: ** ** .byte %00110110 ; 005E 1-0b: ** ** .byte %00000000 ; 005F 1-0b: .byte %01111111 ; 0060 1-0c: ******* .byte %01111111 ; 0061 1-0c: ******* .byte %00000000 ; 0062 1-0c: .byte %00000000 ; 0063 1-0c: .byte %00000000 ; 0064 1-0c: .byte %00000000 ; 0065 1-0c: .byte %00000000 ; 0066 1-0c: .byte %00000000 ; 0067 1-0c: .byte %01111111 ; 0068 1-0d: ******* .byte %01111111 ; 0069 1-0d: ******* .byte %00000000 ; 006A 1-0d: .byte %00000000 ; 006B 1-0d: .byte %00000000 ; 006C 1-0d: .byte %00000000 ; 006D 1-0d: .byte %00000000 ; 006E 1-0d: .byte %00000000 ; 006F 1-0d: .byte %11100000 ; 0070 1-0e: *** .byte %11100000 ; 0071 1-0e: *** .byte %01100000 ; 0072 1-0e: ** .byte %01100000 ; 0073 1-0e: ** .byte %01100000 ; 0074 1-0e: ** .byte %01100000 ; 0075 1-0e: ** .byte %01100000 ; 0076 1-0e: ** .byte %01100000 ; 0077 1-0e: ** .byte %11100000 ; 0078 1-0f: *** .byte %11100000 ; 0079 1-0f: *** .byte %01100000 ; 007A 1-0f: ** .byte %01100000 ; 007B 1-0f: ** .byte %01100000 ; 007C 1-0f: ** .byte %01100000 ; 007D 1-0f: ** .byte %01100000 ; 007E 1-0f: ** .byte %01100000 ; 007F 1-0f: ** .byte %00011000 ; 0080 1-10: ** .byte %00011000 ; 0081 1-10: ** .byte %00011000 ; 0082 1-10: ** .byte %11111000 ; 0083 1-10: ***** .byte %11111000 ; 0084 1-10: ***** .byte %00000000 ; 0085 1-10: .byte %00000000 ; 0086 1-10: .byte %00000000 ; 0087 1-10: .byte %00011000 ; 0088 1-11: ** .byte %00011000 ; 0089 1-11: ** .byte %00011000 ; 008A 1-11: ** .byte %11111000 ; 008B 1-11: ***** .byte %11111000 ; 008C 1-11: ***** .byte %00000000 ; 008D 1-11: .byte %00000000 ; 008E 1-11: .byte %00000000 ; 008F 1-11: .byte %11001100 ; 0090 1-12: ** ** .byte %10011001 ; 0091 1-12: * ** * .byte %00110011 ; 0092 1-12: ** ** .byte %01100110 ; 0093 1-12: ** ** .byte %11001100 ; 0094 1-12: ** ** .byte %10011001 ; 0095 1-12: * ** * .byte %00110011 ; 0096 1-12: ** ** .byte %01100110 ; 0097 1-12: ** ** .byte %11001100 ; 0098 1-13: ** ** .byte %10011001 ; 0099 1-13: * ** * .byte %00110011 ; 009A 1-13: ** ** .byte %01100110 ; 009B 1-13: ** ** .byte %11001100 ; 009C 1-13: ** ** .byte %10011001 ; 009D 1-13: * ** * .byte %00110011 ; 009E 1-13: ** ** .byte %01100110 ; 009F 1-13: ** ** .byte %00110011 ; 00A0 1-14: ** ** .byte %10011001 ; 00A1 1-14: * ** * .byte %11001100 ; 00A2 1-14: ** ** .byte %01100110 ; 00A3 1-14: ** ** .byte %00110011 ; 00A4 1-14: ** ** .byte %10011001 ; 00A5 1-14: * ** * .byte %11001100 ; 00A6 1-14: ** ** .byte %01100110 ; 00A7 1-14: ** ** .byte %00110011 ; 00A8 1-15: ** ** .byte %10011001 ; 00A9 1-15: * ** * .byte %11001100 ; 00AA 1-15: ** ** .byte %01100110 ; 00AB 1-15: ** ** .byte %00110011 ; 00AC 1-15: ** ** .byte %10011001 ; 00AD 1-15: * ** * .byte %11001100 ; 00AE 1-15: ** ** .byte %01100110 ; 00AF 1-15: ** ** .byte %00000000 ; 00B0 1-16: .byte %00000000 ; 00B1 1-16: .byte %00000000 ; 00B2 1-16: .byte %11111111 ; 00B3 1-16: ******** .byte %11111111 ; 00B4 1-16: ******** .byte %00000000 ; 00B5 1-16: .byte %00000000 ; 00B6 1-16: .byte %00000000 ; 00B7 1-16: .byte %00000000 ; 00B8 1-17: .byte %00000000 ; 00B9 1-17: .byte %00000000 ; 00BA 1-17: .byte %11111111 ; 00BB 1-17: ******** .byte %11111111 ; 00BC 1-17: ******** .byte %00000000 ; 00BD 1-17: .byte %00000000 ; 00BE 1-17: .byte %00000000 ; 00BF 1-17: .byte %00000011 ; 00C0 1-18: ** .byte %00000011 ; 00C1 1-18: ** .byte %00000011 ; 00C2 1-18: ** .byte %00000011 ; 00C3 1-18: ** .byte %00000011 ; 00C4 1-18: ** .byte %00000011 ; 00C5 1-18: ** .byte %00000011 ; 00C6 1-18: ** .byte %00000011 ; 00C7 1-18: ** .byte %00000011 ; 00C8 1-19: ** .byte %00000011 ; 00C9 1-19: ** .byte %00000011 ; 00CA 1-19: ** .byte %00000011 ; 00CB 1-19: ** .byte %00000011 ; 00CC 1-19: ** .byte %00000011 ; 00CD 1-19: ** .byte %00000011 ; 00CE 1-19: ** .byte %00000011 ; 00CF 1-19: ** .byte %00000000 ; 00D0 1-1a: .byte %00000000 ; 00D1 1-1a: .byte %00000000 ; 00D2 1-1a: .byte %00000000 ; 00D3 1-1a: .byte %11001100 ; 00D4 1-1a: ** ** .byte %11001100 ; 00D5 1-1a: ** ** .byte %00110011 ; 00D6 1-1a: ** ** .byte %00110011 ; 00D7 1-1a: ** ** .byte %00000000 ; 00D8 1-1b: .byte %00000000 ; 00D9 1-1b: .byte %00000000 ; 00DA 1-1b: .byte %00000000 ; 00DB 1-1b: .byte %11001100 ; 00DC 1-1b: ** ** .byte %11001100 ; 00DD 1-1b: ** ** .byte %00110011 ; 00DE 1-1b: ** ** .byte %00110011 ; 00DF 1-1b: ** ** .byte %00011000 ; 00E0 1-1c: ** .byte %00011000 ; 00E1 1-1c: ** .byte %00011000 ; 00E2 1-1c: ** .byte %00011000 ; 00E3 1-1c: ** .byte %00011000 ; 00E4 1-1c: ** .byte %00011000 ; 00E5 1-1c: ** .byte %00011000 ; 00E6 1-1c: ** .byte %00011000 ; 00E7 1-1c: ** .byte %00011000 ; 00E8 1-1d: ** .byte %00011000 ; 00E9 1-1d: ** .byte %00011000 ; 00EA 1-1d: ** .byte %00011000 ; 00EB 1-1d: ** .byte %00011000 ; 00EC 1-1d: ** .byte %00011000 ; 00ED 1-1d: ** .byte %00011000 ; 00EE 1-1d: ** .byte %00011000 ; 00EF 1-1d: ** .byte %00011000 ; 00F0 1-1e: ** .byte %00011000 ; 00F1 1-1e: ** .byte %00011000 ; 00F2 1-1e: ** .byte %00011111 ; 00F3 1-1e: ***** .byte %00011111 ; 00F4 1-1e: ***** .byte %00011000 ; 00F5 1-1e: ** .byte %00011000 ; 00F6 1-1e: ** .byte %00011000 ; 00F7 1-1e: ** .byte %00011000 ; 00F8 1-1f: ** .byte %00011000 ; 00F9 1-1f: ** .byte %00011000 ; 00FA 1-1f: ** .byte %00011111 ; 00FB 1-1f: ***** .byte %00011111 ; 00FC 1-1f: ***** .byte %00011000 ; 00FD 1-1f: ** .byte %00011000 ; 00FE 1-1f: ** .byte %00011000 ; 00FF 1-1f: ** .byte %00011000 ; 0100 1-20: ** .byte %00011000 ; 0101 1-20: ** .byte %00011000 ; 0102 1-20: ** .byte %11111111 ; 0103 1-20: ******** .byte %11111111 ; 0104 1-20: ******** .byte %00011000 ; 0105 1-20: ** .byte %00011000 ; 0106 1-20: ** .byte %00011000 ; 0107 1-20: ** .byte %00011000 ; 0108 1-21: ** .byte %00011000 ; 0109 1-21: ** .byte %00011000 ; 010A 1-21: ** .byte %11111111 ; 010B 1-21: ******** .byte %11111111 ; 010C 1-21: ******** .byte %00011000 ; 010D 1-21: ** .byte %00011000 ; 010E 1-21: ** .byte %00011000 ; 010F 1-21: ** .byte %00011000 ; 0110 1-22: ** .byte %00011000 ; 0111 1-22: ** .byte %00011000 ; 0112 1-22: ** .byte %00011111 ; 0113 1-22: ***** .byte %00011111 ; 0114 1-22: ***** .byte %00000000 ; 0115 1-22: .byte %00000000 ; 0116 1-22: .byte %00000000 ; 0117 1-22: .byte %00011000 ; 0118 1-23: ** .byte %00011000 ; 0119 1-23: ** .byte %00011000 ; 011A 1-23: ** .byte %00011111 ; 011B 1-23: ***** .byte %00011111 ; 011C 1-23: ***** .byte %00000000 ; 011D 1-23: .byte %00000000 ; 011E 1-23: .byte %00000000 ; 011F 1-23: .byte %00000000 ; 0120 1-24: .byte %00000000 ; 0121 1-24: .byte %00000000 ; 0122 1-24: .byte %11111000 ; 0123 1-24: ***** .byte %11111000 ; 0124 1-24: ***** .byte %00011000 ; 0125 1-24: ** .byte %00011000 ; 0126 1-24: ** .byte %00011000 ; 0127 1-24: ** .byte %00000000 ; 0128 1-25: .byte %00000000 ; 0129 1-25: .byte %00000000 ; 012A 1-25: .byte %11111000 ; 012B 1-25: ***** .byte %11111000 ; 012C 1-25: ***** .byte %00011000 ; 012D 1-25: ** .byte %00011000 ; 012E 1-25: ** .byte %00011000 ; 012F 1-25: ** .byte %00000000 ; 0130 1-26: .byte %00000000 ; 0131 1-26: .byte %00000000 ; 0132 1-26: .byte %00000000 ; 0133 1-26: .byte %00000000 ; 0134 1-26: .byte %00000000 ; 0135 1-26: .byte %11111111 ; 0136 1-26: ******** .byte %11111111 ; 0137 1-26: ******** .byte %00000000 ; 0138 1-27: .byte %00000000 ; 0139 1-27: .byte %00000000 ; 013A 1-27: .byte %00000000 ; 013B 1-27: .byte %00000000 ; 013C 1-27: .byte %00000000 ; 013D 1-27: .byte %11111111 ; 013E 1-27: ******** .byte %11111111 ; 013F 1-27: ******** .byte %00000000 ; 0140 1-28: .byte %00000000 ; 0141 1-28: .byte %00000000 ; 0142 1-28: .byte %00011111 ; 0143 1-28: ***** .byte %00011111 ; 0144 1-28: ***** .byte %00011000 ; 0145 1-28: ** .byte %00011000 ; 0146 1-28: ** .byte %00011000 ; 0147 1-28: ** .byte %00000000 ; 0148 1-29: .byte %00000000 ; 0149 1-29: .byte %00000000 ; 014A 1-29: .byte %00011111 ; 014B 1-29: ***** .byte %00011111 ; 014C 1-29: ***** .byte %00011000 ; 014D 1-29: ** .byte %00011000 ; 014E 1-29: ** .byte %00011000 ; 014F 1-29: ** .byte %00011000 ; 0150 1-2a: ** .byte %00011000 ; 0151 1-2a: ** .byte %00011000 ; 0152 1-2a: ** .byte %11111111 ; 0153 1-2a: ******** .byte %11111111 ; 0154 1-2a: ******** .byte %00000000 ; 0155 1-2a: .byte %00000000 ; 0156 1-2a: .byte %00000000 ; 0157 1-2a: .byte %00011000 ; 0158 1-2b: ** .byte %00011000 ; 0159 1-2b: ** .byte %00011000 ; 015A 1-2b: ** .byte %11111111 ; 015B 1-2b: ******** .byte %11111111 ; 015C 1-2b: ******** .byte %00000000 ; 015D 1-2b: .byte %00000000 ; 015E 1-2b: .byte %00000000 ; 015F 1-2b: .byte %00000000 ; 0160 1-2c: .byte %00000000 ; 0161 1-2c: .byte %00000000 ; 0162 1-2c: .byte %11111111 ; 0163 1-2c: ******** .byte %11111111 ; 0164 1-2c: ******** .byte %00011000 ; 0165 1-2c: ** .byte %00011000 ; 0166 1-2c: ** .byte %00011000 ; 0167 1-2c: ** .byte %00000000 ; 0168 1-2d: .byte %00000000 ; 0169 1-2d: .byte %00000000 ; 016A 1-2d: .byte %11111111 ; 016B 1-2d: ******** .byte %11111111 ; 016C 1-2d: ******** .byte %00011000 ; 016D 1-2d: ** .byte %00011000 ; 016E 1-2d: ** .byte %00011000 ; 016F 1-2d: ** .byte %00011000 ; 0170 1-2e: ** .byte %00011000 ; 0171 1-2e: ** .byte %00011000 ; 0172 1-2e: ** .byte %11111000 ; 0173 1-2e: ***** .byte %11111000 ; 0174 1-2e: ***** .byte %00011000 ; 0175 1-2e: ** .byte %00011000 ; 0176 1-2e: ** .byte %00011000 ; 0177 1-2e: ** .byte %00011000 ; 0178 1-2f: ** .byte %00011000 ; 0179 1-2f: ** .byte %00011000 ; 017A 1-2f: ** .byte %11111000 ; 017B 1-2f: ***** .byte %11111000 ; 017C 1-2f: ***** .byte %00011000 ; 017D 1-2f: ** .byte %00011000 ; 017E 1-2f: ** .byte %00011000 ; 017F 1-2f: ** .byte %11110000 ; 0180 1-30: **** .byte %11110000 ; 0181 1-30: **** .byte %11110000 ; 0182 1-30: **** .byte %11110000 ; 0183 1-30: **** .byte %11110000 ; 0184 1-30: **** .byte %11110000 ; 0185 1-30: **** .byte %11110000 ; 0186 1-30: **** .byte %11110000 ; 0187 1-30: **** .byte %11110000 ; 0188 1-31: **** .byte %11110000 ; 0189 1-31: **** .byte %11110000 ; 018A 1-31: **** .byte %11110000 ; 018B 1-31: **** .byte %11110000 ; 018C 1-31: **** .byte %11110000 ; 018D 1-31: **** .byte %11110000 ; 018E 1-31: **** .byte %11110000 ; 018F 1-31: **** .byte %00000000 ; 0190 1-32: .byte %00000000 ; 0191 1-32: .byte %00000000 ; 0192 1-32: .byte %00000000 ; 0193 1-32: .byte %11111111 ; 0194 1-32: ******** .byte %11111111 ; 0195 1-32: ******** .byte %11111111 ; 0196 1-32: ******** .byte %11111111 ; 0197 1-32: ******** .byte %00000000 ; 0198 1-33: .byte %00000000 ; 0199 1-33: .byte %00000000 ; 019A 1-33: .byte %00000000 ; 019B 1-33: .byte %11111111 ; 019C 1-33: ******** .byte %11111111 ; 019D 1-33: ******** .byte %11111111 ; 019E 1-33: ******** .byte %11111111 ; 019F 1-33: ******** .byte %00000000 ; 01A0 1-34: .byte %00000000 ; 01A1 1-34: .byte %00000000 ; 01A2 1-34: .byte %00000000 ; 01A3 1-34: .byte %11110000 ; 01A4 1-34: **** .byte %11110000 ; 01A5 1-34: **** .byte %11110000 ; 01A6 1-34: **** .byte %11110000 ; 01A7 1-34: **** .byte %00000000 ; 01A8 1-35: .byte %00000000 ; 01A9 1-35: .byte %00000000 ; 01AA 1-35: .byte %00000000 ; 01AB 1-35: .byte %11110000 ; 01AC 1-35: **** .byte %11110000 ; 01AD 1-35: **** .byte %11110000 ; 01AE 1-35: **** .byte %11110000 ; 01AF 1-35: **** .byte %11000000 ; 01B0 1-36: ** .byte %11000000 ; 01B1 1-36: ** .byte %00110000 ; 01B2 1-36: ** .byte %00110000 ; 01B3 1-36: ** .byte %11000000 ; 01B4 1-36: ** .byte %11000000 ; 01B5 1-36: ** .byte %00110000 ; 01B6 1-36: ** .byte %00110000 ; 01B7 1-36: ** .byte %11000000 ; 01B8 1-37: ** .byte %11000000 ; 01B9 1-37: ** .byte %00110000 ; 01BA 1-37: ** .byte %00110000 ; 01BB 1-37: ** .byte %11000000 ; 01BC 1-37: ** .byte %11000000 ; 01BD 1-37: ** .byte %00110000 ; 01BE 1-37: ** .byte %00110000 ; 01BF 1-37: ** .byte %00001111 ; 01C0 1-38: **** .byte %00001111 ; 01C1 1-38: **** .byte %00001111 ; 01C2 1-38: **** .byte %00001111 ; 01C3 1-38: **** .byte %00000000 ; 01C4 1-38: .byte %00000000 ; 01C5 1-38: .byte %00000000 ; 01C6 1-38: .byte %00000000 ; 01C7 1-38: .byte %00001111 ; 01C8 1-39: **** .byte %00001111 ; 01C9 1-39: **** .byte %00001111 ; 01CA 1-39: **** .byte %00001111 ; 01CB 1-39: **** .byte %00000000 ; 01CC 1-39: .byte %00000000 ; 01CD 1-39: .byte %00000000 ; 01CE 1-39: .byte %00000000 ; 01CF 1-39: .byte %00000000 ; 01D0 1-3a: .byte %00000000 ; 01D1 1-3a: .byte %00000000 ; 01D2 1-3a: .byte %00000000 ; 01D3 1-3a: .byte %00001111 ; 01D4 1-3a: **** .byte %00001111 ; 01D5 1-3a: **** .byte %00001111 ; 01D6 1-3a: **** .byte %00001111 ; 01D7 1-3a: **** .byte %00000000 ; 01D8 1-3b: .byte %00000000 ; 01D9 1-3b: .byte %00000000 ; 01DA 1-3b: .byte %00000000 ; 01DB 1-3b: .byte %00001111 ; 01DC 1-3b: **** .byte %00001111 ; 01DD 1-3b: **** .byte %00001111 ; 01DE 1-3b: **** .byte %00001111 ; 01DF 1-3b: **** .byte %11110000 ; 01E0 1-3c: **** .byte %11110000 ; 01E1 1-3c: **** .byte %11110000 ; 01E2 1-3c: **** .byte %11110000 ; 01E3 1-3c: **** .byte %00000000 ; 01E4 1-3c: .byte %00000000 ; 01E5 1-3c: .byte %00000000 ; 01E6 1-3c: .byte %00000000 ; 01E7 1-3c: .byte %11110000 ; 01E8 1-3d: **** .byte %11110000 ; 01E9 1-3d: **** .byte %11110000 ; 01EA 1-3d: **** .byte %11110000 ; 01EB 1-3d: **** .byte %00000000 ; 01EC 1-3d: .byte %00000000 ; 01ED 1-3d: .byte %00000000 ; 01EE 1-3d: .byte %00000000 ; 01EF 1-3d: .byte %11110000 ; 01F0 1-3e: **** .byte %11110000 ; 01F1 1-3e: **** .byte %11110000 ; 01F2 1-3e: **** .byte %11110000 ; 01F3 1-3e: **** .byte %00001111 ; 01F4 1-3e: **** .byte %00001111 ; 01F5 1-3e: **** .byte %00001111 ; 01F6 1-3e: **** .byte %00001111 ; 01F7 1-3e: **** .byte %11110000 ; 01F8 1-3f: **** .byte %11110000 ; 01F9 1-3f: **** .byte %11110000 ; 01FA 1-3f: **** .byte %11110000 ; 01FB 1-3f: **** .byte %00001111 ; 01FC 1-3f: **** .byte %00001111 ; 01FD 1-3f: **** .byte %00001111 ; 01FE 1-3f: **** .byte %00001111 ; 01FF 1-3f: **** .byte %00000000 ; 0200 1-40: .byte %00000000 ; 0201 1-40: .byte %00000000 ; 0202 1-40: .byte %00000000 ; 0203 1-40: .byte %00000000 ; 0204 1-40: .byte %00000000 ; 0205 1-40: .byte %00000000 ; 0206 1-40: .byte %00000000 ; 0207 1-40: .byte %00000000 ; 0208 1-41: .byte %00000000 ; 0209 1-41: .byte %00000000 ; 020A 1-41: .byte %00000000 ; 020B 1-41: .byte %00000000 ; 020C 1-41: .byte %00000000 ; 020D 1-41: .byte %00000000 ; 020E 1-41: .byte %00000000 ; 020F 1-41: .byte %00011000 ; 0210 1-42: ** .byte %00011000 ; 0211 1-42: ** .byte %00011000 ; 0212 1-42: ** .byte %00011000 ; 0213 1-42: ** .byte %00000000 ; 0214 1-42: .byte %00000000 ; 0215 1-42: .byte %00011000 ; 0216 1-42: ** .byte %00000000 ; 0217 1-42: .byte %00011000 ; 0218 1-43: ** .byte %00011000 ; 0219 1-43: ** .byte %00011000 ; 021A 1-43: ** .byte %00011000 ; 021B 1-43: ** .byte %00000000 ; 021C 1-43: .byte %00000000 ; 021D 1-43: .byte %00011000 ; 021E 1-43: ** .byte %00000000 ; 021F 1-43: .byte %01100110 ; 0220 1-44: ** ** .byte %01100110 ; 0221 1-44: ** ** .byte %01100110 ; 0222 1-44: ** ** .byte %00000000 ; 0223 1-44: .byte %00000000 ; 0224 1-44: .byte %00000000 ; 0225 1-44: .byte %00000000 ; 0226 1-44: .byte %00000000 ; 0227 1-44: .byte %01100110 ; 0228 1-45: ** ** .byte %01100110 ; 0229 1-45: ** ** .byte %01100110 ; 022A 1-45: ** ** .byte %00000000 ; 022B 1-45: .byte %00000000 ; 022C 1-45: .byte %00000000 ; 022D 1-45: .byte %00000000 ; 022E 1-45: .byte %00000000 ; 022F 1-45: .byte %01100110 ; 0230 1-46: ** ** .byte %01100110 ; 0231 1-46: ** ** .byte %11111111 ; 0232 1-46: ******** .byte %01100110 ; 0233 1-46: ** ** .byte %11111111 ; 0234 1-46: ******** .byte %01100110 ; 0235 1-46: ** ** .byte %01100110 ; 0236 1-46: ** ** .byte %00000000 ; 0237 1-46: .byte %01100110 ; 0238 1-47: ** ** .byte %01100110 ; 0239 1-47: ** ** .byte %11111111 ; 023A 1-47: ******** .byte %01100110 ; 023B 1-47: ** ** .byte %11111111 ; 023C 1-47: ******** .byte %01100110 ; 023D 1-47: ** ** .byte %01100110 ; 023E 1-47: ** ** .byte %00000000 ; 023F 1-47: .byte %00011000 ; 0240 1-48: ** .byte %00111110 ; 0241 1-48: ***** .byte %01100000 ; 0242 1-48: ** .byte %00111100 ; 0243 1-48: **** .byte %00000110 ; 0244 1-48: ** .byte %01111100 ; 0245 1-48: ***** .byte %00011000 ; 0246 1-48: ** .byte %00000000 ; 0247 1-48: .byte %00011000 ; 0248 1-49: ** .byte %00111110 ; 0249 1-49: ***** .byte %01100000 ; 024A 1-49: ** .byte %00111100 ; 024B 1-49: **** .byte %00000110 ; 024C 1-49: ** .byte %01111100 ; 024D 1-49: ***** .byte %00011000 ; 024E 1-49: ** .byte %00000000 ; 024F 1-49: .byte %00000000 ; 0250 1-4a: .byte %01100110 ; 0251 1-4a: ** ** .byte %00001100 ; 0252 1-4a: ** .byte %00011000 ; 0253 1-4a: ** .byte %00110000 ; 0254 1-4a: ** .byte %01100110 ; 0255 1-4a: ** ** .byte %01000110 ; 0256 1-4a: * ** .byte %00000000 ; 0257 1-4a: .byte %00000000 ; 0258 1-4b: .byte %01100110 ; 0259 1-4b: ** ** .byte %00001100 ; 025A 1-4b: ** .byte %00011000 ; 025B 1-4b: ** .byte %00110000 ; 025C 1-4b: ** .byte %01100110 ; 025D 1-4b: ** ** .byte %01000110 ; 025E 1-4b: * ** .byte %00000000 ; 025F 1-4b: .byte %00111100 ; 0260 1-4c: **** .byte %01100110 ; 0261 1-4c: ** ** .byte %00111100 ; 0262 1-4c: **** .byte %00111000 ; 0263 1-4c: *** .byte %01100111 ; 0264 1-4c: ** *** .byte %01100110 ; 0265 1-4c: ** ** .byte %00111111 ; 0266 1-4c: ****** .byte %00000000 ; 0267 1-4c: .byte %00111100 ; 0268 1-4d: **** .byte %01100110 ; 0269 1-4d: ** ** .byte %00111100 ; 026A 1-4d: **** .byte %00111000 ; 026B 1-4d: *** .byte %01100111 ; 026C 1-4d: ** *** .byte %01100110 ; 026D 1-4d: ** ** .byte %00111111 ; 026E 1-4d: ****** .byte %00000000 ; 026F 1-4d: .byte %00000110 ; 0270 1-4e: ** .byte %00001100 ; 0271 1-4e: ** .byte %00011000 ; 0272 1-4e: ** .byte %00000000 ; 0273 1-4e: .byte %00000000 ; 0274 1-4e: .byte %00000000 ; 0275 1-4e: .byte %00000000 ; 0276 1-4e: .byte %00000000 ; 0277 1-4e: .byte %00000110 ; 0278 1-4f: ** .byte %00001100 ; 0279 1-4f: ** .byte %00011000 ; 027A 1-4f: ** .byte %00000000 ; 027B 1-4f: .byte %00000000 ; 027C 1-4f: .byte %00000000 ; 027D 1-4f: .byte %00000000 ; 027E 1-4f: .byte %00000000 ; 027F 1-4f: .byte %00001100 ; 0280 1-50: ** .byte %00011000 ; 0281 1-50: ** .byte %00110000 ; 0282 1-50: ** .byte %00110000 ; 0283 1-50: ** .byte %00110000 ; 0284 1-50: ** .byte %00011000 ; 0285 1-50: ** .byte %00001100 ; 0286 1-50: ** .byte %00000000 ; 0287 1-50: .byte %00001100 ; 0288 1-51: ** .byte %00011000 ; 0289 1-51: ** .byte %00110000 ; 028A 1-51: ** .byte %00110000 ; 028B 1-51: ** .byte %00110000 ; 028C 1-51: ** .byte %00011000 ; 028D 1-51: ** .byte %00001100 ; 028E 1-51: ** .byte %00000000 ; 028F 1-51: .byte %00110000 ; 0290 1-52: ** .byte %00011000 ; 0291 1-52: ** .byte %00001100 ; 0292 1-52: ** .byte %00001100 ; 0293 1-52: ** .byte %00001100 ; 0294 1-52: ** .byte %00011000 ; 0295 1-52: ** .byte %00110000 ; 0296 1-52: ** .byte %00000000 ; 0297 1-52: .byte %00110000 ; 0298 1-53: ** .byte %00011000 ; 0299 1-53: ** .byte %00001100 ; 029A 1-53: ** .byte %00001100 ; 029B 1-53: ** .byte %00001100 ; 029C 1-53: ** .byte %00011000 ; 029D 1-53: ** .byte %00110000 ; 029E 1-53: ** .byte %00000000 ; 029F 1-53: .byte %00000000 ; 02A0 1-54: .byte %01100110 ; 02A1 1-54: ** ** .byte %00111100 ; 02A2 1-54: **** .byte %11111111 ; 02A3 1-54: ******** .byte %00111100 ; 02A4 1-54: **** .byte %01100110 ; 02A5 1-54: ** ** .byte %00000000 ; 02A6 1-54: .byte %00000000 ; 02A7 1-54: .byte %00000000 ; 02A8 1-55: .byte %01100110 ; 02A9 1-55: ** ** .byte %00111100 ; 02AA 1-55: **** .byte %11111111 ; 02AB 1-55: ******** .byte %00111100 ; 02AC 1-55: **** .byte %01100110 ; 02AD 1-55: ** ** .byte %00000000 ; 02AE 1-55: .byte %00000000 ; 02AF 1-55: .byte %00000000 ; 02B0 1-56: .byte %00011000 ; 02B1 1-56: ** .byte %00011000 ; 02B2 1-56: ** .byte %01111110 ; 02B3 1-56: ****** .byte %00011000 ; 02B4 1-56: ** .byte %00011000 ; 02B5 1-56: ** .byte %00000000 ; 02B6 1-56: .byte %00000000 ; 02B7 1-56: .byte %00000000 ; 02B8 1-57: .byte %00011000 ; 02B9 1-57: ** .byte %00011000 ; 02BA 1-57: ** .byte %01111110 ; 02BB 1-57: ****** .byte %00011000 ; 02BC 1-57: ** .byte %00011000 ; 02BD 1-57: ** .byte %00000000 ; 02BE 1-57: .byte %00000000 ; 02BF 1-57: .byte %00000000 ; 02C0 1-58: .byte %00000000 ; 02C1 1-58: .byte %00000000 ; 02C2 1-58: .byte %00000000 ; 02C3 1-58: .byte %00000000 ; 02C4 1-58: .byte %00011000 ; 02C5 1-58: ** .byte %00011000 ; 02C6 1-58: ** .byte %00110000 ; 02C7 1-58: ** .byte %00000000 ; 02C8 1-59: .byte %00000000 ; 02C9 1-59: .byte %00000000 ; 02CA 1-59: .byte %00000000 ; 02CB 1-59: .byte %00000000 ; 02CC 1-59: .byte %00011000 ; 02CD 1-59: ** .byte %00011000 ; 02CE 1-59: ** .byte %00110000 ; 02CF 1-59: ** .byte %00000000 ; 02D0 1-5a: .byte %00000000 ; 02D1 1-5a: .byte %00000000 ; 02D2 1-5a: .byte %01111110 ; 02D3 1-5a: ****** .byte %00000000 ; 02D4 1-5a: .byte %00000000 ; 02D5 1-5a: .byte %00000000 ; 02D6 1-5a: .byte %00000000 ; 02D7 1-5a: .byte %00000000 ; 02D8 1-5b: .byte %00000000 ; 02D9 1-5b: .byte %00000000 ; 02DA 1-5b: .byte %01111110 ; 02DB 1-5b: ****** .byte %00000000 ; 02DC 1-5b: .byte %00000000 ; 02DD 1-5b: .byte %00000000 ; 02DE 1-5b: .byte %00000000 ; 02DF 1-5b: .byte %00000000 ; 02E0 1-5c: .byte %00000000 ; 02E1 1-5c: .byte %00000000 ; 02E2 1-5c: .byte %00000000 ; 02E3 1-5c: .byte %00000000 ; 02E4 1-5c: .byte %00011000 ; 02E5 1-5c: ** .byte %00011000 ; 02E6 1-5c: ** .byte %00000000 ; 02E7 1-5c: .byte %00000000 ; 02E8 1-5d: .byte %00000000 ; 02E9 1-5d: .byte %00000000 ; 02EA 1-5d: .byte %00000000 ; 02EB 1-5d: .byte %00000000 ; 02EC 1-5d: .byte %00011000 ; 02ED 1-5d: ** .byte %00011000 ; 02EE 1-5d: ** .byte %00000000 ; 02EF 1-5d: .byte %00000000 ; 02F0 1-5e: .byte %00000011 ; 02F1 1-5e: ** .byte %00000110 ; 02F2 1-5e: ** .byte %00001100 ; 02F3 1-5e: ** .byte %00011000 ; 02F4 1-5e: ** .byte %00110000 ; 02F5 1-5e: ** .byte %01100000 ; 02F6 1-5e: ** .byte %00000000 ; 02F7 1-5e: .byte %00000000 ; 02F8 1-5f: .byte %00000011 ; 02F9 1-5f: ** .byte %00000110 ; 02FA 1-5f: ** .byte %00001100 ; 02FB 1-5f: ** .byte %00011000 ; 02FC 1-5f: ** .byte %00110000 ; 02FD 1-5f: ** .byte %01100000 ; 02FE 1-5f: ** .byte %00000000 ; 02FF 1-5f: .byte %00111100 ; 0300 1-60: **** .byte %01100110 ; 0301 1-60: ** ** .byte %01101110 ; 0302 1-60: ** *** .byte %01110110 ; 0303 1-60: *** ** .byte %01100110 ; 0304 1-60: ** ** .byte %01100110 ; 0305 1-60: ** ** .byte %00111100 ; 0306 1-60: **** .byte %00000000 ; 0307 1-60: .byte %00111100 ; 0308 1-61: **** .byte %01100110 ; 0309 1-61: ** ** .byte %01101110 ; 030A 1-61: ** *** .byte %01110110 ; 030B 1-61: *** ** .byte %01100110 ; 030C 1-61: ** ** .byte %01100110 ; 030D 1-61: ** ** .byte %00111100 ; 030E 1-61: **** .byte %00000000 ; 030F 1-61: .byte %00011000 ; 0310 1-62: ** .byte %00011000 ; 0311 1-62: ** .byte %00111000 ; 0312 1-62: *** .byte %00011000 ; 0313 1-62: ** .byte %00011000 ; 0314 1-62: ** .byte %00011000 ; 0315 1-62: ** .byte %01111110 ; 0316 1-62: ****** .byte %00000000 ; 0317 1-62: .byte %00011000 ; 0318 1-63: ** .byte %00011000 ; 0319 1-63: ** .byte %00111000 ; 031A 1-63: *** .byte %00011000 ; 031B 1-63: ** .byte %00011000 ; 031C 1-63: ** .byte %00011000 ; 031D 1-63: ** .byte %01111110 ; 031E 1-63: ****** .byte %00000000 ; 031F 1-63: .byte %00111100 ; 0320 1-64: **** .byte %01100110 ; 0321 1-64: ** ** .byte %00000110 ; 0322 1-64: ** .byte %00001100 ; 0323 1-64: ** .byte %00110000 ; 0324 1-64: ** .byte %01100000 ; 0325 1-64: ** .byte %01111110 ; 0326 1-64: ****** .byte %00000000 ; 0327 1-64: .byte %00111100 ; 0328 1-65: **** .byte %01100110 ; 0329 1-65: ** ** .byte %00000110 ; 032A 1-65: ** .byte %00001100 ; 032B 1-65: ** .byte %00110000 ; 032C 1-65: ** .byte %01100000 ; 032D 1-65: ** .byte %01111110 ; 032E 1-65: ****** .byte %00000000 ; 032F 1-65: .byte %00111100 ; 0330 1-66: **** .byte %01100110 ; 0331 1-66: ** ** .byte %00000110 ; 0332 1-66: ** .byte %00011100 ; 0333 1-66: *** .byte %00000110 ; 0334 1-66: ** .byte %01100110 ; 0335 1-66: ** ** .byte %00111100 ; 0336 1-66: **** .byte %00000000 ; 0337 1-66: .byte %00111100 ; 0338 1-67: **** .byte %01100110 ; 0339 1-67: ** ** .byte %00000110 ; 033A 1-67: ** .byte %00011100 ; 033B 1-67: *** .byte %00000110 ; 033C 1-67: ** .byte %01100110 ; 033D 1-67: ** ** .byte %00111100 ; 033E 1-67: **** .byte %00000000 ; 033F 1-67: .byte %00000110 ; 0340 1-68: ** .byte %00001110 ; 0341 1-68: *** .byte %00011110 ; 0342 1-68: **** .byte %01100110 ; 0343 1-68: ** ** .byte %01111111 ; 0344 1-68: ******* .byte %00000110 ; 0345 1-68: ** .byte %00000110 ; 0346 1-68: ** .byte %00000000 ; 0347 1-68: .byte %00000110 ; 0348 1-69: ** .byte %00001110 ; 0349 1-69: *** .byte %00011110 ; 034A 1-69: **** .byte %01100110 ; 034B 1-69: ** ** .byte %01111111 ; 034C 1-69: ******* .byte %00000110 ; 034D 1-69: ** .byte %00000110 ; 034E 1-69: ** .byte %00000000 ; 034F 1-69: .byte %01111110 ; 0350 1-6a: ****** .byte %01100000 ; 0351 1-6a: ** .byte %01111100 ; 0352 1-6a: ***** .byte %00000110 ; 0353 1-6a: ** .byte %00000110 ; 0354 1-6a: ** .byte %01100110 ; 0355 1-6a: ** ** .byte %00111100 ; 0356 1-6a: **** .byte %00000000 ; 0357 1-6a: .byte %01111110 ; 0358 1-6b: ****** .byte %01100000 ; 0359 1-6b: ** .byte %01111100 ; 035A 1-6b: ***** .byte %00000110 ; 035B 1-6b: ** .byte %00000110 ; 035C 1-6b: ** .byte %01100110 ; 035D 1-6b: ** ** .byte %00111100 ; 035E 1-6b: **** .byte %00000000 ; 035F 1-6b: .byte %00111100 ; 0360 1-6c: **** .byte %01100110 ; 0361 1-6c: ** ** .byte %01100000 ; 0362 1-6c: ** .byte %01111100 ; 0363 1-6c: ***** .byte %01100110 ; 0364 1-6c: ** ** .byte %01100110 ; 0365 1-6c: ** ** .byte %00111100 ; 0366 1-6c: **** .byte %00000000 ; 0367 1-6c: .byte %00111100 ; 0368 1-6d: **** .byte %01100110 ; 0369 1-6d: ** ** .byte %01100000 ; 036A 1-6d: ** .byte %01111100 ; 036B 1-6d: ***** .byte %01100110 ; 036C 1-6d: ** ** .byte %01100110 ; 036D 1-6d: ** ** .byte %00111100 ; 036E 1-6d: **** .byte %00000000 ; 036F 1-6d: .byte %01111110 ; 0370 1-6e: ****** .byte %01100110 ; 0371 1-6e: ** ** .byte %00001100 ; 0372 1-6e: ** .byte %00011000 ; 0373 1-6e: ** .byte %00011000 ; 0374 1-6e: ** .byte %00011000 ; 0375 1-6e: ** .byte %00011000 ; 0376 1-6e: ** .byte %00000000 ; 0377 1-6e: .byte %01111110 ; 0378 1-6f: ****** .byte %01100110 ; 0379 1-6f: ** ** .byte %00001100 ; 037A 1-6f: ** .byte %00011000 ; 037B 1-6f: ** .byte %00011000 ; 037C 1-6f: ** .byte %00011000 ; 037D 1-6f: ** .byte %00011000 ; 037E 1-6f: ** .byte %00000000 ; 037F 1-6f: .byte %00111100 ; 0380 1-70: **** .byte %01100110 ; 0381 1-70: ** ** .byte %01100110 ; 0382 1-70: ** ** .byte %00111100 ; 0383 1-70: **** .byte %01100110 ; 0384 1-70: ** ** .byte %01100110 ; 0385 1-70: ** ** .byte %00111100 ; 0386 1-70: **** .byte %00000000 ; 0387 1-70: .byte %00111100 ; 0388 1-71: **** .byte %01100110 ; 0389 1-71: ** ** .byte %01100110 ; 038A 1-71: ** ** .byte %00111100 ; 038B 1-71: **** .byte %01100110 ; 038C 1-71: ** ** .byte %01100110 ; 038D 1-71: ** ** .byte %00111100 ; 038E 1-71: **** .byte %00000000 ; 038F 1-71: .byte %00111100 ; 0390 1-72: **** .byte %01100110 ; 0391 1-72: ** ** .byte %01100110 ; 0392 1-72: ** ** .byte %00111110 ; 0393 1-72: ***** .byte %00000110 ; 0394 1-72: ** .byte %01100110 ; 0395 1-72: ** ** .byte %00111100 ; 0396 1-72: **** .byte %00000000 ; 0397 1-72: .byte %00111100 ; 0398 1-73: **** .byte %01100110 ; 0399 1-73: ** ** .byte %01100110 ; 039A 1-73: ** ** .byte %00111110 ; 039B 1-73: ***** .byte %00000110 ; 039C 1-73: ** .byte %01100110 ; 039D 1-73: ** ** .byte %00111100 ; 039E 1-73: **** .byte %00000000 ; 039F 1-73: .byte %00000000 ; 03A0 1-74: .byte %00000000 ; 03A1 1-74: .byte %00011000 ; 03A2 1-74: ** .byte %00000000 ; 03A3 1-74: .byte %00000000 ; 03A4 1-74: .byte %00011000 ; 03A5 1-74: ** .byte %00000000 ; 03A6 1-74: .byte %00000000 ; 03A7 1-74: .byte %00000000 ; 03A8 1-75: .byte %00000000 ; 03A9 1-75: .byte %00011000 ; 03AA 1-75: ** .byte %00000000 ; 03AB 1-75: .byte %00000000 ; 03AC 1-75: .byte %00011000 ; 03AD 1-75: ** .byte %00000000 ; 03AE 1-75: .byte %00000000 ; 03AF 1-75: .byte %00000000 ; 03B0 1-76: .byte %00000000 ; 03B1 1-76: .byte %00011000 ; 03B2 1-76: ** .byte %00000000 ; 03B3 1-76: .byte %00000000 ; 03B4 1-76: .byte %00011000 ; 03B5 1-76: ** .byte %00011000 ; 03B6 1-76: ** .byte %00110000 ; 03B7 1-76: ** .byte %00000000 ; 03B8 1-77: .byte %00000000 ; 03B9 1-77: .byte %00011000 ; 03BA 1-77: ** .byte %00000000 ; 03BB 1-77: .byte %00000000 ; 03BC 1-77: .byte %00011000 ; 03BD 1-77: ** .byte %00011000 ; 03BE 1-77: ** .byte %00110000 ; 03BF 1-77: ** .byte %00001110 ; 03C0 1-78: *** .byte %00011000 ; 03C1 1-78: ** .byte %00110000 ; 03C2 1-78: ** .byte %01100000 ; 03C3 1-78: ** .byte %00110000 ; 03C4 1-78: ** .byte %00011000 ; 03C5 1-78: ** .byte %00001110 ; 03C6 1-78: *** .byte %00000000 ; 03C7 1-78: .byte %00001110 ; 03C8 1-79: *** .byte %00011000 ; 03C9 1-79: ** .byte %00110000 ; 03CA 1-79: ** .byte %01100000 ; 03CB 1-79: ** .byte %00110000 ; 03CC 1-79: ** .byte %00011000 ; 03CD 1-79: ** .byte %00001110 ; 03CE 1-79: *** .byte %00000000 ; 03CF 1-79: .byte %00000000 ; 03D0 1-7a: .byte %00000000 ; 03D1 1-7a: .byte %01111110 ; 03D2 1-7a: ****** .byte %00000000 ; 03D3 1-7a: .byte %01111110 ; 03D4 1-7a: ****** .byte %00000000 ; 03D5 1-7a: .byte %00000000 ; 03D6 1-7a: .byte %00000000 ; 03D7 1-7a: .byte %00000000 ; 03D8 1-7b: .byte %00000000 ; 03D9 1-7b: .byte %01111110 ; 03DA 1-7b: ****** .byte %00000000 ; 03DB 1-7b: .byte %01111110 ; 03DC 1-7b: ****** .byte %00000000 ; 03DD 1-7b: .byte %00000000 ; 03DE 1-7b: .byte %00000000 ; 03DF 1-7b: .byte %01110000 ; 03E0 1-7c: *** .byte %00011000 ; 03E1 1-7c: ** .byte %00001100 ; 03E2 1-7c: ** .byte %00000110 ; 03E3 1-7c: ** .byte %00001100 ; 03E4 1-7c: ** .byte %00011000 ; 03E5 1-7c: ** .byte %01110000 ; 03E6 1-7c: *** .byte %00000000 ; 03E7 1-7c: .byte %01110000 ; 03E8 1-7d: *** .byte %00011000 ; 03E9 1-7d: ** .byte %00001100 ; 03EA 1-7d: ** .byte %00000110 ; 03EB 1-7d: ** .byte %00001100 ; 03EC 1-7d: ** .byte %00011000 ; 03ED 1-7d: ** .byte %01110000 ; 03EE 1-7d: *** .byte %00000000 ; 03EF 1-7d: .byte %00111100 ; 03F0 1-7e: **** .byte %01100110 ; 03F1 1-7e: ** ** .byte %00000110 ; 03F2 1-7e: ** .byte %00001100 ; 03F3 1-7e: ** .byte %00011000 ; 03F4 1-7e: ** .byte %00000000 ; 03F5 1-7e: .byte %00011000 ; 03F6 1-7e: ** .byte %00000000 ; 03F7 1-7e: .byte %00111100 ; 03F8 1-7f: **** .byte %01100110 ; 03F9 1-7f: ** ** .byte %00000110 ; 03FA 1-7f: ** .byte %00001100 ; 03FB 1-7f: ** .byte %00011000 ; 03FC 1-7f: ** .byte %00000000 ; 03FD 1-7f: .byte %00011000 ; 03FE 1-7f: ** .byte %00000000 ; 03FF 1-7f: .byte %00111100 ; 0400 1-80: **** .byte %01100110 ; 0401 1-80: ** ** .byte %01101110 ; 0402 1-80: ** *** .byte %01101110 ; 0403 1-80: ** *** .byte %01100000 ; 0404 1-80: ** .byte %01100010 ; 0405 1-80: ** * .byte %00111100 ; 0406 1-80: **** .byte %00000000 ; 0407 1-80: .byte %00111100 ; 0408 1-81: **** .byte %01100110 ; 0409 1-81: ** ** .byte %01101110 ; 040A 1-81: ** *** .byte %01101110 ; 040B 1-81: ** *** .byte %01100000 ; 040C 1-81: ** .byte %01100010 ; 040D 1-81: ** * .byte %00111100 ; 040E 1-81: **** .byte %00000000 ; 040F 1-81: .byte %00011000 ; 0410 1-82: ** .byte %00111100 ; 0411 1-82: **** .byte %01100110 ; 0412 1-82: ** ** .byte %01111110 ; 0413 1-82: ****** .byte %01100110 ; 0414 1-82: ** ** .byte %01100110 ; 0415 1-82: ** ** .byte %01100110 ; 0416 1-82: ** ** .byte %00000000 ; 0417 1-82: .byte %00011000 ; 0418 1-83: ** .byte %00111100 ; 0419 1-83: **** .byte %01100110 ; 041A 1-83: ** ** .byte %01111110 ; 041B 1-83: ****** .byte %01100110 ; 041C 1-83: ** ** .byte %01100110 ; 041D 1-83: ** ** .byte %01100110 ; 041E 1-83: ** ** .byte %00000000 ; 041F 1-83: .byte %01111100 ; 0420 1-84: ***** .byte %01100110 ; 0421 1-84: ** ** .byte %01100110 ; 0422 1-84: ** ** .byte %01111100 ; 0423 1-84: ***** .byte %01100110 ; 0424 1-84: ** ** .byte %01100110 ; 0425 1-84: ** ** .byte %01111100 ; 0426 1-84: ***** .byte %00000000 ; 0427 1-84: .byte %01111100 ; 0428 1-85: ***** .byte %01100110 ; 0429 1-85: ** ** .byte %01100110 ; 042A 1-85: ** ** .byte %01111100 ; 042B 1-85: ***** .byte %01100110 ; 042C 1-85: ** ** .byte %01100110 ; 042D 1-85: ** ** .byte %01111100 ; 042E 1-85: ***** .byte %00000000 ; 042F 1-85: .byte %00111100 ; 0430 1-86: **** .byte %01100110 ; 0431 1-86: ** ** .byte %01100000 ; 0432 1-86: ** .byte %01100000 ; 0433 1-86: ** .byte %01100000 ; 0434 1-86: ** .byte %01100110 ; 0435 1-86: ** ** .byte %00111100 ; 0436 1-86: **** .byte %00000000 ; 0437 1-86: .byte %00111100 ; 0438 1-87: **** .byte %01100110 ; 0439 1-87: ** ** .byte %01100000 ; 043A 1-87: ** .byte %01100000 ; 043B 1-87: ** .byte %01100000 ; 043C 1-87: ** .byte %01100110 ; 043D 1-87: ** ** .byte %00111100 ; 043E 1-87: **** .byte %00000000 ; 043F 1-87: .byte %01111000 ; 0440 1-88: **** .byte %01101100 ; 0441 1-88: ** ** .byte %01100110 ; 0442 1-88: ** ** .byte %01100110 ; 0443 1-88: ** ** .byte %01100110 ; 0444 1-88: ** ** .byte %01101100 ; 0445 1-88: ** ** .byte %01111000 ; 0446 1-88: **** .byte %00000000 ; 0447 1-88: .byte %01111000 ; 0448 1-89: **** .byte %01101100 ; 0449 1-89: ** ** .byte %01100110 ; 044A 1-89: ** ** .byte %01100110 ; 044B 1-89: ** ** .byte %01100110 ; 044C 1-89: ** ** .byte %01101100 ; 044D 1-89: ** ** .byte %01111000 ; 044E 1-89: **** .byte %00000000 ; 044F 1-89: .byte %01111110 ; 0450 1-8a: ****** .byte %01100000 ; 0451 1-8a: ** .byte %01100000 ; 0452 1-8a: ** .byte %01111000 ; 0453 1-8a: **** .byte %01100000 ; 0454 1-8a: ** .byte %01100000 ; 0455 1-8a: ** .byte %01111110 ; 0456 1-8a: ****** .byte %00000000 ; 0457 1-8a: .byte %01111110 ; 0458 1-8b: ****** .byte %01100000 ; 0459 1-8b: ** .byte %01100000 ; 045A 1-8b: ** .byte %01111000 ; 045B 1-8b: **** .byte %01100000 ; 045C 1-8b: ** .byte %01100000 ; 045D 1-8b: ** .byte %01111110 ; 045E 1-8b: ****** .byte %00000000 ; 045F 1-8b: .byte %01111110 ; 0460 1-8c: ****** .byte %01100000 ; 0461 1-8c: ** .byte %01100000 ; 0462 1-8c: ** .byte %01111000 ; 0463 1-8c: **** .byte %01100000 ; 0464 1-8c: ** .byte %01100000 ; 0465 1-8c: ** .byte %01100000 ; 0466 1-8c: ** .byte %00000000 ; 0467 1-8c: .byte %01111110 ; 0468 1-8d: ****** .byte %01100000 ; 0469 1-8d: ** .byte %01100000 ; 046A 1-8d: ** .byte %01111000 ; 046B 1-8d: **** .byte %01100000 ; 046C 1-8d: ** .byte %01100000 ; 046D 1-8d: ** .byte %01100000 ; 046E 1-8d: ** .byte %00000000 ; 046F 1-8d: .byte %00111100 ; 0470 1-8e: **** .byte %01100110 ; 0471 1-8e: ** ** .byte %01100000 ; 0472 1-8e: ** .byte %01101110 ; 0473 1-8e: ** *** .byte %01100110 ; 0474 1-8e: ** ** .byte %01100110 ; 0475 1-8e: ** ** .byte %00111100 ; 0476 1-8e: **** .byte %00000000 ; 0477 1-8e: .byte %00111100 ; 0478 1-8f: **** .byte %01100110 ; 0479 1-8f: ** ** .byte %01100000 ; 047A 1-8f: ** .byte %01101110 ; 047B 1-8f: ** *** .byte %01100110 ; 047C 1-8f: ** ** .byte %01100110 ; 047D 1-8f: ** ** .byte %00111100 ; 047E 1-8f: **** .byte %00000000 ; 047F 1-8f: .byte %01100110 ; 0480 1-90: ** ** .byte %01100110 ; 0481 1-90: ** ** .byte %01100110 ; 0482 1-90: ** ** .byte %01111110 ; 0483 1-90: ****** .byte %01100110 ; 0484 1-90: ** ** .byte %01100110 ; 0485 1-90: ** ** .byte %01100110 ; 0486 1-90: ** ** .byte %00000000 ; 0487 1-90: .byte %01100110 ; 0488 1-91: ** ** .byte %01100110 ; 0489 1-91: ** ** .byte %01100110 ; 048A 1-91: ** ** .byte %01111110 ; 048B 1-91: ****** .byte %01100110 ; 048C 1-91: ** ** .byte %01100110 ; 048D 1-91: ** ** .byte %01100110 ; 048E 1-91: ** ** .byte %00000000 ; 048F 1-91: .byte %00111100 ; 0490 1-92: **** .byte %00011000 ; 0491 1-92: ** .byte %00011000 ; 0492 1-92: ** .byte %00011000 ; 0493 1-92: ** .byte %00011000 ; 0494 1-92: ** .byte %00011000 ; 0495 1-92: ** .byte %00111100 ; 0496 1-92: **** .byte %00000000 ; 0497 1-92: .byte %00111100 ; 0498 1-93: **** .byte %00011000 ; 0499 1-93: ** .byte %00011000 ; 049A 1-93: ** .byte %00011000 ; 049B 1-93: ** .byte %00011000 ; 049C 1-93: ** .byte %00011000 ; 049D 1-93: ** .byte %00111100 ; 049E 1-93: **** .byte %00000000 ; 049F 1-93: .byte %00011110 ; 04A0 1-94: **** .byte %00001100 ; 04A1 1-94: ** .byte %00001100 ; 04A2 1-94: ** .byte %00001100 ; 04A3 1-94: ** .byte %00001100 ; 04A4 1-94: ** .byte %01101100 ; 04A5 1-94: ** ** .byte %00111000 ; 04A6 1-94: *** .byte %00000000 ; 04A7 1-94: .byte %00011110 ; 04A8 1-95: **** .byte %00001100 ; 04A9 1-95: ** .byte %00001100 ; 04AA 1-95: ** .byte %00001100 ; 04AB 1-95: ** .byte %00001100 ; 04AC 1-95: ** .byte %01101100 ; 04AD 1-95: ** ** .byte %00111000 ; 04AE 1-95: *** .byte %00000000 ; 04AF 1-95: .byte %01100110 ; 04B0 1-96: ** ** .byte %01101100 ; 04B1 1-96: ** ** .byte %01111000 ; 04B2 1-96: **** .byte %01110000 ; 04B3 1-96: *** .byte %01111000 ; 04B4 1-96: **** .byte %01101100 ; 04B5 1-96: ** ** .byte %01100110 ; 04B6 1-96: ** ** .byte %00000000 ; 04B7 1-96: .byte %01100110 ; 04B8 1-97: ** ** .byte %01101100 ; 04B9 1-97: ** ** .byte %01111000 ; 04BA 1-97: **** .byte %01110000 ; 04BB 1-97: *** .byte %01111000 ; 04BC 1-97: **** .byte %01101100 ; 04BD 1-97: ** ** .byte %01100110 ; 04BE 1-97: ** ** .byte %00000000 ; 04BF 1-97: .byte %01100000 ; 04C0 1-98: ** .byte %01100000 ; 04C1 1-98: ** .byte %01100000 ; 04C2 1-98: ** .byte %01100000 ; 04C3 1-98: ** .byte %01100000 ; 04C4 1-98: ** .byte %01100000 ; 04C5 1-98: ** .byte %01111110 ; 04C6 1-98: ****** .byte %00000000 ; 04C7 1-98: .byte %01100000 ; 04C8 1-99: ** .byte %01100000 ; 04C9 1-99: ** .byte %01100000 ; 04CA 1-99: ** .byte %01100000 ; 04CB 1-99: ** .byte %01100000 ; 04CC 1-99: ** .byte %01100000 ; 04CD 1-99: ** .byte %01111110 ; 04CE 1-99: ****** .byte %00000000 ; 04CF 1-99: .byte %01100011 ; 04D0 1-9a: ** ** .byte %01110111 ; 04D1 1-9a: *** *** .byte %01111111 ; 04D2 1-9a: ******* .byte %01101011 ; 04D3 1-9a: ** * ** .byte %01100011 ; 04D4 1-9a: ** ** .byte %01100011 ; 04D5 1-9a: ** ** .byte %01100011 ; 04D6 1-9a: ** ** .byte %00000000 ; 04D7 1-9a: .byte %01100011 ; 04D8 1-9b: ** ** .byte %01110111 ; 04D9 1-9b: *** *** .byte %01111111 ; 04DA 1-9b: ******* .byte %01101011 ; 04DB 1-9b: ** * ** .byte %01100011 ; 04DC 1-9b: ** ** .byte %01100011 ; 04DD 1-9b: ** ** .byte %01100011 ; 04DE 1-9b: ** ** .byte %00000000 ; 04DF 1-9b: .byte %01100110 ; 04E0 1-9c: ** ** .byte %01110110 ; 04E1 1-9c: *** ** .byte %01111110 ; 04E2 1-9c: ****** .byte %01111110 ; 04E3 1-9c: ****** .byte %01101110 ; 04E4 1-9c: ** *** .byte %01100110 ; 04E5 1-9c: ** ** .byte %01100110 ; 04E6 1-9c: ** ** .byte %00000000 ; 04E7 1-9c: .byte %01100110 ; 04E8 1-9d: ** ** .byte %01110110 ; 04E9 1-9d: *** ** .byte %01111110 ; 04EA 1-9d: ****** .byte %01111110 ; 04EB 1-9d: ****** .byte %01101110 ; 04EC 1-9d: ** *** .byte %01100110 ; 04ED 1-9d: ** ** .byte %01100110 ; 04EE 1-9d: ** ** .byte %00000000 ; 04EF 1-9d: .byte %00111100 ; 04F0 1-9e: **** .byte %01100110 ; 04F1 1-9e: ** ** .byte %01100110 ; 04F2 1-9e: ** ** .byte %01100110 ; 04F3 1-9e: ** ** .byte %01100110 ; 04F4 1-9e: ** ** .byte %01100110 ; 04F5 1-9e: ** ** .byte %00111100 ; 04F6 1-9e: **** .byte %00000000 ; 04F7 1-9e: .byte %00111100 ; 04F8 1-9f: **** .byte %01100110 ; 04F9 1-9f: ** ** .byte %01100110 ; 04FA 1-9f: ** ** .byte %01100110 ; 04FB 1-9f: ** ** .byte %01100110 ; 04FC 1-9f: ** ** .byte %01100110 ; 04FD 1-9f: ** ** .byte %00111100 ; 04FE 1-9f: **** .byte %00000000 ; 04FF 1-9f: .byte %01111100 ; 0500 1-a0: ***** .byte %01100110 ; 0501 1-a0: ** ** .byte %01100110 ; 0502 1-a0: ** ** .byte %01111100 ; 0503 1-a0: ***** .byte %01100000 ; 0504 1-a0: ** .byte %01100000 ; 0505 1-a0: ** .byte %01100000 ; 0506 1-a0: ** .byte %00000000 ; 0507 1-a0: .byte %01111100 ; 0508 1-a1: ***** .byte %01100110 ; 0509 1-a1: ** ** .byte %01100110 ; 050A 1-a1: ** ** .byte %01111100 ; 050B 1-a1: ***** .byte %01100000 ; 050C 1-a1: ** .byte %01100000 ; 050D 1-a1: ** .byte %01100000 ; 050E 1-a1: ** .byte %00000000 ; 050F 1-a1: .byte %00111100 ; 0510 1-a2: **** .byte %01100110 ; 0511 1-a2: ** ** .byte %01100110 ; 0512 1-a2: ** ** .byte %01100110 ; 0513 1-a2: ** ** .byte %01100110 ; 0514 1-a2: ** ** .byte %00111100 ; 0515 1-a2: **** .byte %00001110 ; 0516 1-a2: *** .byte %00000000 ; 0517 1-a2: .byte %00111100 ; 0518 1-a3: **** .byte %01100110 ; 0519 1-a3: ** ** .byte %01100110 ; 051A 1-a3: ** ** .byte %01100110 ; 051B 1-a3: ** ** .byte %01100110 ; 051C 1-a3: ** ** .byte %00111100 ; 051D 1-a3: **** .byte %00001110 ; 051E 1-a3: *** .byte %00000000 ; 051F 1-a3: .byte %01111100 ; 0520 1-a4: ***** .byte %01100110 ; 0521 1-a4: ** ** .byte %01100110 ; 0522 1-a4: ** ** .byte %01111100 ; 0523 1-a4: ***** .byte %01111000 ; 0524 1-a4: **** .byte %01101100 ; 0525 1-a4: ** ** .byte %01100110 ; 0526 1-a4: ** ** .byte %00000000 ; 0527 1-a4: .byte %01111100 ; 0528 1-a5: ***** .byte %01100110 ; 0529 1-a5: ** ** .byte %01100110 ; 052A 1-a5: ** ** .byte %01111100 ; 052B 1-a5: ***** .byte %01111000 ; 052C 1-a5: **** .byte %01101100 ; 052D 1-a5: ** ** .byte %01100110 ; 052E 1-a5: ** ** .byte %00000000 ; 052F 1-a5: .byte %00111100 ; 0530 1-a6: **** .byte %01100110 ; 0531 1-a6: ** ** .byte %01100000 ; 0532 1-a6: ** .byte %00111100 ; 0533 1-a6: **** .byte %00000110 ; 0534 1-a6: ** .byte %01100110 ; 0535 1-a6: ** ** .byte %00111100 ; 0536 1-a6: **** .byte %00000000 ; 0537 1-a6: .byte %00111100 ; 0538 1-a7: **** .byte %01100110 ; 0539 1-a7: ** ** .byte %01100000 ; 053A 1-a7: ** .byte %00111100 ; 053B 1-a7: **** .byte %00000110 ; 053C 1-a7: ** .byte %01100110 ; 053D 1-a7: ** ** .byte %00111100 ; 053E 1-a7: **** .byte %00000000 ; 053F 1-a7: .byte %01111110 ; 0540 1-a8: ****** .byte %00011000 ; 0541 1-a8: ** .byte %00011000 ; 0542 1-a8: ** .byte %00011000 ; 0543 1-a8: ** .byte %00011000 ; 0544 1-a8: ** .byte %00011000 ; 0545 1-a8: ** .byte %00011000 ; 0546 1-a8: ** .byte %00000000 ; 0547 1-a8: .byte %01111110 ; 0548 1-a9: ****** .byte %00011000 ; 0549 1-a9: ** .byte %00011000 ; 054A 1-a9: ** .byte %00011000 ; 054B 1-a9: ** .byte %00011000 ; 054C 1-a9: ** .byte %00011000 ; 054D 1-a9: ** .byte %00011000 ; 054E 1-a9: ** .byte %00000000 ; 054F 1-a9: .byte %01100110 ; 0550 1-aa: ** ** .byte %01100110 ; 0551 1-aa: ** ** .byte %01100110 ; 0552 1-aa: ** ** .byte %01100110 ; 0553 1-aa: ** ** .byte %01100110 ; 0554 1-aa: ** ** .byte %01100110 ; 0555 1-aa: ** ** .byte %00111100 ; 0556 1-aa: **** .byte %00000000 ; 0557 1-aa: .byte %01100110 ; 0558 1-ab: ** ** .byte %01100110 ; 0559 1-ab: ** ** .byte %01100110 ; 055A 1-ab: ** ** .byte %01100110 ; 055B 1-ab: ** ** .byte %01100110 ; 055C 1-ab: ** ** .byte %01100110 ; 055D 1-ab: ** ** .byte %00111100 ; 055E 1-ab: **** .byte %00000000 ; 055F 1-ab: .byte %01100110 ; 0560 1-ac: ** ** .byte %01100110 ; 0561 1-ac: ** ** .byte %01100110 ; 0562 1-ac: ** ** .byte %01100110 ; 0563 1-ac: ** ** .byte %01100110 ; 0564 1-ac: ** ** .byte %00111100 ; 0565 1-ac: **** .byte %00011000 ; 0566 1-ac: ** .byte %00000000 ; 0567 1-ac: .byte %01100110 ; 0568 1-ad: ** ** .byte %01100110 ; 0569 1-ad: ** ** .byte %01100110 ; 056A 1-ad: ** ** .byte %01100110 ; 056B 1-ad: ** ** .byte %01100110 ; 056C 1-ad: ** ** .byte %00111100 ; 056D 1-ad: **** .byte %00011000 ; 056E 1-ad: ** .byte %00000000 ; 056F 1-ad: .byte %01100011 ; 0570 1-ae: ** ** .byte %01100011 ; 0571 1-ae: ** ** .byte %01100011 ; 0572 1-ae: ** ** .byte %01101011 ; 0573 1-ae: ** * ** .byte %01111111 ; 0574 1-ae: ******* .byte %01110111 ; 0575 1-ae: *** *** .byte %01100011 ; 0576 1-ae: ** ** .byte %00000000 ; 0577 1-ae: .byte %01100011 ; 0578 1-af: ** ** .byte %01100011 ; 0579 1-af: ** ** .byte %01100011 ; 057A 1-af: ** ** .byte %01101011 ; 057B 1-af: ** * ** .byte %01111111 ; 057C 1-af: ******* .byte %01110111 ; 057D 1-af: *** *** .byte %01100011 ; 057E 1-af: ** ** .byte %00000000 ; 057F 1-af: .byte %01100110 ; 0580 1-b0: ** ** .byte %01100110 ; 0581 1-b0: ** ** .byte %00111100 ; 0582 1-b0: **** .byte %00011000 ; 0583 1-b0: ** .byte %00111100 ; 0584 1-b0: **** .byte %01100110 ; 0585 1-b0: ** ** .byte %01100110 ; 0586 1-b0: ** ** .byte %00000000 ; 0587 1-b0: .byte %01100110 ; 0588 1-b1: ** ** .byte %01100110 ; 0589 1-b1: ** ** .byte %00111100 ; 058A 1-b1: **** .byte %00011000 ; 058B 1-b1: ** .byte %00111100 ; 058C 1-b1: **** .byte %01100110 ; 058D 1-b1: ** ** .byte %01100110 ; 058E 1-b1: ** ** .byte %00000000 ; 058F 1-b1: .byte %01100110 ; 0590 1-b2: ** ** .byte %01100110 ; 0591 1-b2: ** ** .byte %01100110 ; 0592 1-b2: ** ** .byte %00111100 ; 0593 1-b2: **** .byte %00011000 ; 0594 1-b2: ** .byte %00011000 ; 0595 1-b2: ** .byte %00011000 ; 0596 1-b2: ** .byte %00000000 ; 0597 1-b2: .byte %01100110 ; 0598 1-b3: ** ** .byte %01100110 ; 0599 1-b3: ** ** .byte %01100110 ; 059A 1-b3: ** ** .byte %00111100 ; 059B 1-b3: **** .byte %00011000 ; 059C 1-b3: ** .byte %00011000 ; 059D 1-b3: ** .byte %00011000 ; 059E 1-b3: ** .byte %00000000 ; 059F 1-b3: .byte %01111110 ; 05A0 1-b4: ****** .byte %00000110 ; 05A1 1-b4: ** .byte %00001100 ; 05A2 1-b4: ** .byte %00011000 ; 05A3 1-b4: ** .byte %00110000 ; 05A4 1-b4: ** .byte %01100000 ; 05A5 1-b4: ** .byte %01111110 ; 05A6 1-b4: ****** .byte %00000000 ; 05A7 1-b4: .byte %01111110 ; 05A8 1-b5: ****** .byte %00000110 ; 05A9 1-b5: ** .byte %00001100 ; 05AA 1-b5: ** .byte %00011000 ; 05AB 1-b5: ** .byte %00110000 ; 05AC 1-b5: ** .byte %01100000 ; 05AD 1-b5: ** .byte %01111110 ; 05AE 1-b5: ****** .byte %00000000 ; 05AF 1-b5: .byte %00111100 ; 05B0 1-b6: **** .byte %00110000 ; 05B1 1-b6: ** .byte %00110000 ; 05B2 1-b6: ** .byte %00110000 ; 05B3 1-b6: ** .byte %00110000 ; 05B4 1-b6: ** .byte %00110000 ; 05B5 1-b6: ** .byte %00111100 ; 05B6 1-b6: **** .byte %00000000 ; 05B7 1-b6: .byte %00111100 ; 05B8 1-b7: **** .byte %00110000 ; 05B9 1-b7: ** .byte %00110000 ; 05BA 1-b7: ** .byte %00110000 ; 05BB 1-b7: ** .byte %00110000 ; 05BC 1-b7: ** .byte %00110000 ; 05BD 1-b7: ** .byte %00111100 ; 05BE 1-b7: **** .byte %00000000 ; 05BF 1-b7: .byte %01100000 ; 05C0 1-b8: ** .byte %00110000 ; 05C1 1-b8: ** .byte %00011000 ; 05C2 1-b8: ** .byte %00001100 ; 05C3 1-b8: ** .byte %00000110 ; 05C4 1-b8: ** .byte %00000011 ; 05C5 1-b8: ** .byte %00000000 ; 05C6 1-b8: .byte %00000000 ; 05C7 1-b8: .byte %01100000 ; 05C8 1-b9: ** .byte %00110000 ; 05C9 1-b9: ** .byte %00011000 ; 05CA 1-b9: ** .byte %00001100 ; 05CB 1-b9: ** .byte %00000110 ; 05CC 1-b9: ** .byte %00000011 ; 05CD 1-b9: ** .byte %00000000 ; 05CE 1-b9: .byte %00000000 ; 05CF 1-b9: .byte %00111100 ; 05D0 1-ba: **** .byte %00001100 ; 05D1 1-ba: ** .byte %00001100 ; 05D2 1-ba: ** .byte %00001100 ; 05D3 1-ba: ** .byte %00001100 ; 05D4 1-ba: ** .byte %00001100 ; 05D5 1-ba: ** .byte %00111100 ; 05D6 1-ba: **** .byte %00000000 ; 05D7 1-ba: .byte %00111100 ; 05D8 1-bb: **** .byte %00001100 ; 05D9 1-bb: ** .byte %00001100 ; 05DA 1-bb: ** .byte %00001100 ; 05DB 1-bb: ** .byte %00001100 ; 05DC 1-bb: ** .byte %00001100 ; 05DD 1-bb: ** .byte %00111100 ; 05DE 1-bb: **** .byte %00000000 ; 05DF 1-bb: .byte %00000000 ; 05E0 1-bc: .byte %00011000 ; 05E1 1-bc: ** .byte %00111100 ; 05E2 1-bc: **** .byte %01100110 ; 05E3 1-bc: ** ** .byte %00000000 ; 05E4 1-bc: .byte %00000000 ; 05E5 1-bc: .byte %00000000 ; 05E6 1-bc: .byte %00000000 ; 05E7 1-bc: .byte %00000000 ; 05E8 1-bd: .byte %00011000 ; 05E9 1-bd: ** .byte %00111100 ; 05EA 1-bd: **** .byte %01100110 ; 05EB 1-bd: ** ** .byte %00000000 ; 05EC 1-bd: .byte %00000000 ; 05ED 1-bd: .byte %00000000 ; 05EE 1-bd: .byte %00000000 ; 05EF 1-bd: .byte %00000000 ; 05F0 1-be: .byte %00000000 ; 05F1 1-be: .byte %00000000 ; 05F2 1-be: .byte %00000000 ; 05F3 1-be: .byte %00000000 ; 05F4 1-be: .byte %00000000 ; 05F5 1-be: .byte %01111111 ; 05F6 1-be: ******* .byte %00000000 ; 05F7 1-be: .byte %00000000 ; 05F8 1-bf: .byte %00000000 ; 05F9 1-bf: .byte %00000000 ; 05FA 1-bf: .byte %00000000 ; 05FB 1-bf: .byte %00000000 ; 05FC 1-bf: .byte %00000000 ; 05FD 1-bf: .byte %01111111 ; 05FE 1-bf: ******* .byte %00000000 ; 05FF 1-bf: .byte %00011000 ; 0600 1-c0: ** .byte %00011000 ; 0601 1-c0: ** .byte %00011000 ; 0602 1-c0: ** .byte %00000000 ; 0603 1-c0: .byte %00000000 ; 0604 1-c0: .byte %00000000 ; 0605 1-c0: .byte %00000000 ; 0606 1-c0: .byte %00000000 ; 0607 1-c0: .byte %00011000 ; 0608 1-c1: ** .byte %00011000 ; 0609 1-c1: ** .byte %00011000 ; 060A 1-c1: ** .byte %00000000 ; 060B 1-c1: .byte %00000000 ; 060C 1-c1: .byte %00000000 ; 060D 1-c1: .byte %00000000 ; 060E 1-c1: .byte %00000000 ; 060F 1-c1: .byte %00000000 ; 0610 1-c2: .byte %00000000 ; 0611 1-c2: .byte %00111100 ; 0612 1-c2: **** .byte %00000110 ; 0613 1-c2: ** .byte %00111110 ; 0614 1-c2: ***** .byte %01100110 ; 0615 1-c2: ** ** .byte %00111110 ; 0616 1-c2: ***** .byte %00000000 ; 0617 1-c2: .byte %00000000 ; 0618 1-c3: .byte %00000000 ; 0619 1-c3: .byte %00111100 ; 061A 1-c3: **** .byte %00000110 ; 061B 1-c3: ** .byte %00111110 ; 061C 1-c3: ***** .byte %01100110 ; 061D 1-c3: ** ** .byte %00111110 ; 061E 1-c3: ***** .byte %00000000 ; 061F 1-c3: .byte %00000000 ; 0620 1-c4: .byte %01100000 ; 0621 1-c4: ** .byte %01100000 ; 0622 1-c4: ** .byte %01111100 ; 0623 1-c4: ***** .byte %01100110 ; 0624 1-c4: ** ** .byte %01100110 ; 0625 1-c4: ** ** .byte %01111100 ; 0626 1-c4: ***** .byte %00000000 ; 0627 1-c4: .byte %00000000 ; 0628 1-c5: .byte %01100000 ; 0629 1-c5: ** .byte %01100000 ; 062A 1-c5: ** .byte %01111100 ; 062B 1-c5: ***** .byte %01100110 ; 062C 1-c5: ** ** .byte %01100110 ; 062D 1-c5: ** ** .byte %01111100 ; 062E 1-c5: ***** .byte %00000000 ; 062F 1-c5: .byte %00000000 ; 0630 1-c6: .byte %00000000 ; 0631 1-c6: .byte %00111100 ; 0632 1-c6: **** .byte %01100000 ; 0633 1-c6: ** .byte %01100000 ; 0634 1-c6: ** .byte %01100000 ; 0635 1-c6: ** .byte %00111100 ; 0636 1-c6: **** .byte %00000000 ; 0637 1-c6: .byte %00000000 ; 0638 1-c7: .byte %00000000 ; 0639 1-c7: .byte %00111100 ; 063A 1-c7: **** .byte %01100000 ; 063B 1-c7: ** .byte %01100000 ; 063C 1-c7: ** .byte %01100000 ; 063D 1-c7: ** .byte %00111100 ; 063E 1-c7: **** .byte %00000000 ; 063F 1-c7: .byte %00000000 ; 0640 1-c8: .byte %00000110 ; 0641 1-c8: ** .byte %00000110 ; 0642 1-c8: ** .byte %00111110 ; 0643 1-c8: ***** .byte %01100110 ; 0644 1-c8: ** ** .byte %01100110 ; 0645 1-c8: ** ** .byte %00111110 ; 0646 1-c8: ***** .byte %00000000 ; 0647 1-c8: .byte %00000000 ; 0648 1-c9: .byte %00000110 ; 0649 1-c9: ** .byte %00000110 ; 064A 1-c9: ** .byte %00111110 ; 064B 1-c9: ***** .byte %01100110 ; 064C 1-c9: ** ** .byte %01100110 ; 064D 1-c9: ** ** .byte %00111110 ; 064E 1-c9: ***** .byte %00000000 ; 064F 1-c9: .byte %00000000 ; 0650 1-ca: .byte %00000000 ; 0651 1-ca: .byte %00111100 ; 0652 1-ca: **** .byte %01100110 ; 0653 1-ca: ** ** .byte %01111110 ; 0654 1-ca: ****** .byte %01100000 ; 0655 1-ca: ** .byte %00111100 ; 0656 1-ca: **** .byte %00000000 ; 0657 1-ca: .byte %00000000 ; 0658 1-cb: .byte %00000000 ; 0659 1-cb: .byte %00111100 ; 065A 1-cb: **** .byte %01100110 ; 065B 1-cb: ** ** .byte %01111110 ; 065C 1-cb: ****** .byte %01100000 ; 065D 1-cb: ** .byte %00111100 ; 065E 1-cb: **** .byte %00000000 ; 065F 1-cb: .byte %00000000 ; 0660 1-cc: .byte %00001110 ; 0661 1-cc: *** .byte %00011000 ; 0662 1-cc: ** .byte %00111110 ; 0663 1-cc: ***** .byte %00011000 ; 0664 1-cc: ** .byte %00011000 ; 0665 1-cc: ** .byte %00011000 ; 0666 1-cc: ** .byte %00000000 ; 0667 1-cc: .byte %00000000 ; 0668 1-cd: .byte %00001110 ; 0669 1-cd: *** .byte %00011000 ; 066A 1-cd: ** .byte %00111110 ; 066B 1-cd: ***** .byte %00011000 ; 066C 1-cd: ** .byte %00011000 ; 066D 1-cd: ** .byte %00011000 ; 066E 1-cd: ** .byte %00000000 ; 066F 1-cd: .byte %00000000 ; 0670 1-ce: .byte %00000000 ; 0671 1-ce: .byte %00111110 ; 0672 1-ce: ***** .byte %01100110 ; 0673 1-ce: ** ** .byte %01100110 ; 0674 1-ce: ** ** .byte %00111110 ; 0675 1-ce: ***** .byte %00000110 ; 0676 1-ce: ** .byte %01111100 ; 0677 1-ce: ***** .byte %00000000 ; 0678 1-cf: .byte %00000000 ; 0679 1-cf: .byte %00111110 ; 067A 1-cf: ***** .byte %01100110 ; 067B 1-cf: ** ** .byte %01100110 ; 067C 1-cf: ** ** .byte %00111110 ; 067D 1-cf: ***** .byte %00000110 ; 067E 1-cf: ** .byte %01111100 ; 067F 1-cf: ***** .byte %00000000 ; 0680 1-d0: .byte %01100000 ; 0681 1-d0: ** .byte %01100000 ; 0682 1-d0: ** .byte %01111100 ; 0683 1-d0: ***** .byte %01100110 ; 0684 1-d0: ** ** .byte %01100110 ; 0685 1-d0: ** ** .byte %01100110 ; 0686 1-d0: ** ** .byte %00000000 ; 0687 1-d0: .byte %00000000 ; 0688 1-d1: .byte %01100000 ; 0689 1-d1: ** .byte %01100000 ; 068A 1-d1: ** .byte %01111100 ; 068B 1-d1: ***** .byte %01100110 ; 068C 1-d1: ** ** .byte %01100110 ; 068D 1-d1: ** ** .byte %01100110 ; 068E 1-d1: ** ** .byte %00000000 ; 068F 1-d1: .byte %00000000 ; 0690 1-d2: .byte %00011000 ; 0691 1-d2: ** .byte %00000000 ; 0692 1-d2: .byte %00111000 ; 0693 1-d2: *** .byte %00011000 ; 0694 1-d2: ** .byte %00011000 ; 0695 1-d2: ** .byte %00111100 ; 0696 1-d2: **** .byte %00000000 ; 0697 1-d2: .byte %00000000 ; 0698 1-d3: .byte %00011000 ; 0699 1-d3: ** .byte %00000000 ; 069A 1-d3: .byte %00111000 ; 069B 1-d3: *** .byte %00011000 ; 069C 1-d3: ** .byte %00011000 ; 069D 1-d3: ** .byte %00111100 ; 069E 1-d3: **** .byte %00000000 ; 069F 1-d3: .byte %00000000 ; 06A0 1-d4: .byte %00000110 ; 06A1 1-d4: ** .byte %00000000 ; 06A2 1-d4: .byte %00000110 ; 06A3 1-d4: ** .byte %00000110 ; 06A4 1-d4: ** .byte %00000110 ; 06A5 1-d4: ** .byte %00000110 ; 06A6 1-d4: ** .byte %00111100 ; 06A7 1-d4: **** .byte %00000000 ; 06A8 1-d5: .byte %00000110 ; 06A9 1-d5: ** .byte %00000000 ; 06AA 1-d5: .byte %00000110 ; 06AB 1-d5: ** .byte %00000110 ; 06AC 1-d5: ** .byte %00000110 ; 06AD 1-d5: ** .byte %00000110 ; 06AE 1-d5: ** .byte %00111100 ; 06AF 1-d5: **** .byte %00000000 ; 06B0 1-d6: .byte %01100000 ; 06B1 1-d6: ** .byte %01100000 ; 06B2 1-d6: ** .byte %01101100 ; 06B3 1-d6: ** ** .byte %01111000 ; 06B4 1-d6: **** .byte %01101100 ; 06B5 1-d6: ** ** .byte %01100110 ; 06B6 1-d6: ** ** .byte %00000000 ; 06B7 1-d6: .byte %00000000 ; 06B8 1-d7: .byte %01100000 ; 06B9 1-d7: ** .byte %01100000 ; 06BA 1-d7: ** .byte %01101100 ; 06BB 1-d7: ** ** .byte %01111000 ; 06BC 1-d7: **** .byte %01101100 ; 06BD 1-d7: ** ** .byte %01100110 ; 06BE 1-d7: ** ** .byte %00000000 ; 06BF 1-d7: .byte %00000000 ; 06C0 1-d8: .byte %00111000 ; 06C1 1-d8: *** .byte %00011000 ; 06C2 1-d8: ** .byte %00011000 ; 06C3 1-d8: ** .byte %00011000 ; 06C4 1-d8: ** .byte %00011000 ; 06C5 1-d8: ** .byte %00111100 ; 06C6 1-d8: **** .byte %00000000 ; 06C7 1-d8: .byte %00000000 ; 06C8 1-d9: .byte %00111000 ; 06C9 1-d9: *** .byte %00011000 ; 06CA 1-d9: ** .byte %00011000 ; 06CB 1-d9: ** .byte %00011000 ; 06CC 1-d9: ** .byte %00011000 ; 06CD 1-d9: ** .byte %00111100 ; 06CE 1-d9: **** .byte %00000000 ; 06CF 1-d9: .byte %00000000 ; 06D0 1-da: .byte %00000000 ; 06D1 1-da: .byte %01100110 ; 06D2 1-da: ** ** .byte %01111111 ; 06D3 1-da: ******* .byte %01111111 ; 06D4 1-da: ******* .byte %01101011 ; 06D5 1-da: ** * ** .byte %01100011 ; 06D6 1-da: ** ** .byte %00000000 ; 06D7 1-da: .byte %00000000 ; 06D8 1-db: .byte %00000000 ; 06D9 1-db: .byte %01100110 ; 06DA 1-db: ** ** .byte %01111111 ; 06DB 1-db: ******* .byte %01111111 ; 06DC 1-db: ******* .byte %01101011 ; 06DD 1-db: ** * ** .byte %01100011 ; 06DE 1-db: ** ** .byte %00000000 ; 06DF 1-db: .byte %00000000 ; 06E0 1-dc: .byte %00000000 ; 06E1 1-dc: .byte %01111100 ; 06E2 1-dc: ***** .byte %01100110 ; 06E3 1-dc: ** ** .byte %01100110 ; 06E4 1-dc: ** ** .byte %01100110 ; 06E5 1-dc: ** ** .byte %01100110 ; 06E6 1-dc: ** ** .byte %00000000 ; 06E7 1-dc: .byte %00000000 ; 06E8 1-dd: .byte %00000000 ; 06E9 1-dd: .byte %01111100 ; 06EA 1-dd: ***** .byte %01100110 ; 06EB 1-dd: ** ** .byte %01100110 ; 06EC 1-dd: ** ** .byte %01100110 ; 06ED 1-dd: ** ** .byte %01100110 ; 06EE 1-dd: ** ** .byte %00000000 ; 06EF 1-dd: .byte %00000000 ; 06F0 1-de: .byte %00000000 ; 06F1 1-de: .byte %00111100 ; 06F2 1-de: **** .byte %01100110 ; 06F3 1-de: ** ** .byte %01100110 ; 06F4 1-de: ** ** .byte %01100110 ; 06F5 1-de: ** ** .byte %00111100 ; 06F6 1-de: **** .byte %00000000 ; 06F7 1-de: .byte %00000000 ; 06F8 1-df: .byte %00000000 ; 06F9 1-df: .byte %00111100 ; 06FA 1-df: **** .byte %01100110 ; 06FB 1-df: ** ** .byte %01100110 ; 06FC 1-df: ** ** .byte %01100110 ; 06FD 1-df: ** ** .byte %00111100 ; 06FE 1-df: **** .byte %00000000 ; 06FF 1-df: .byte %00000000 ; 0700 1-e0: .byte %00000000 ; 0701 1-e0: .byte %01111100 ; 0702 1-e0: ***** .byte %01100110 ; 0703 1-e0: ** ** .byte %01100110 ; 0704 1-e0: ** ** .byte %01111100 ; 0705 1-e0: ***** .byte %01100000 ; 0706 1-e0: ** .byte %01100000 ; 0707 1-e0: ** .byte %00000000 ; 0708 1-e1: .byte %00000000 ; 0709 1-e1: .byte %01111100 ; 070A 1-e1: ***** .byte %01100110 ; 070B 1-e1: ** ** .byte %01100110 ; 070C 1-e1: ** ** .byte %01111100 ; 070D 1-e1: ***** .byte %01100000 ; 070E 1-e1: ** .byte %01100000 ; 070F 1-e1: ** .byte %00000000 ; 0710 1-e2: .byte %00000000 ; 0711 1-e2: .byte %00111110 ; 0712 1-e2: ***** .byte %01100110 ; 0713 1-e2: ** ** .byte %01100110 ; 0714 1-e2: ** ** .byte %00111110 ; 0715 1-e2: ***** .byte %00000110 ; 0716 1-e2: ** .byte %00000110 ; 0717 1-e2: ** .byte %00000000 ; 0718 1-e3: .byte %00000000 ; 0719 1-e3: .byte %00111110 ; 071A 1-e3: ***** .byte %01100110 ; 071B 1-e3: ** ** .byte %01100110 ; 071C 1-e3: ** ** .byte %00111110 ; 071D 1-e3: ***** .byte %00000110 ; 071E 1-e3: ** .byte %00000110 ; 071F 1-e3: ** .byte %00000000 ; 0720 1-e4: .byte %00000000 ; 0721 1-e4: .byte %01111100 ; 0722 1-e4: ***** .byte %01100110 ; 0723 1-e4: ** ** .byte %01100000 ; 0724 1-e4: ** .byte %01100000 ; 0725 1-e4: ** .byte %01100000 ; 0726 1-e4: ** .byte %00000000 ; 0727 1-e4: .byte %00000000 ; 0728 1-e5: .byte %00000000 ; 0729 1-e5: .byte %01111100 ; 072A 1-e5: ***** .byte %01100110 ; 072B 1-e5: ** ** .byte %01100000 ; 072C 1-e5: ** .byte %01100000 ; 072D 1-e5: ** .byte %01100000 ; 072E 1-e5: ** .byte %00000000 ; 072F 1-e5: .byte %00000000 ; 0730 1-e6: .byte %00000000 ; 0731 1-e6: .byte %00111110 ; 0732 1-e6: ***** .byte %01100000 ; 0733 1-e6: ** .byte %00111100 ; 0734 1-e6: **** .byte %00000110 ; 0735 1-e6: ** .byte %01111100 ; 0736 1-e6: ***** .byte %00000000 ; 0737 1-e6: .byte %00000000 ; 0738 1-e7: .byte %00000000 ; 0739 1-e7: .byte %00111110 ; 073A 1-e7: ***** .byte %01100000 ; 073B 1-e7: ** .byte %00111100 ; 073C 1-e7: **** .byte %00000110 ; 073D 1-e7: ** .byte %01111100 ; 073E 1-e7: ***** .byte %00000000 ; 073F 1-e7: .byte %00000000 ; 0740 1-e8: .byte %00011000 ; 0741 1-e8: ** .byte %01111110 ; 0742 1-e8: ****** .byte %00011000 ; 0743 1-e8: ** .byte %00011000 ; 0744 1-e8: ** .byte %00011000 ; 0745 1-e8: ** .byte %00001110 ; 0746 1-e8: *** .byte %00000000 ; 0747 1-e8: .byte %00000000 ; 0748 1-e9: .byte %00011000 ; 0749 1-e9: ** .byte %01111110 ; 074A 1-e9: ****** .byte %00011000 ; 074B 1-e9: ** .byte %00011000 ; 074C 1-e9: ** .byte %00011000 ; 074D 1-e9: ** .byte %00001110 ; 074E 1-e9: *** .byte %00000000 ; 074F 1-e9: .byte %00000000 ; 0750 1-ea: .byte %00000000 ; 0751 1-ea: .byte %01100110 ; 0752 1-ea: ** ** .byte %01100110 ; 0753 1-ea: ** ** .byte %01100110 ; 0754 1-ea: ** ** .byte %01100110 ; 0755 1-ea: ** ** .byte %00111110 ; 0756 1-ea: ***** .byte %00000000 ; 0757 1-ea: .byte %00000000 ; 0758 1-eb: .byte %00000000 ; 0759 1-eb: .byte %01100110 ; 075A 1-eb: ** ** .byte %01100110 ; 075B 1-eb: ** ** .byte %01100110 ; 075C 1-eb: ** ** .byte %01100110 ; 075D 1-eb: ** ** .byte %00111110 ; 075E 1-eb: ***** .byte %00000000 ; 075F 1-eb: .byte %00000000 ; 0760 1-ec: .byte %00000000 ; 0761 1-ec: .byte %01100110 ; 0762 1-ec: ** ** .byte %01100110 ; 0763 1-ec: ** ** .byte %01100110 ; 0764 1-ec: ** ** .byte %00111100 ; 0765 1-ec: **** .byte %00011000 ; 0766 1-ec: ** .byte %00000000 ; 0767 1-ec: .byte %00000000 ; 0768 1-ed: .byte %00000000 ; 0769 1-ed: .byte %01100110 ; 076A 1-ed: ** ** .byte %01100110 ; 076B 1-ed: ** ** .byte %01100110 ; 076C 1-ed: ** ** .byte %00111100 ; 076D 1-ed: **** .byte %00011000 ; 076E 1-ed: ** .byte %00000000 ; 076F 1-ed: .byte %00000000 ; 0770 1-ee: .byte %00000000 ; 0771 1-ee: .byte %01100011 ; 0772 1-ee: ** ** .byte %01101011 ; 0773 1-ee: ** * ** .byte %01111111 ; 0774 1-ee: ******* .byte %00111110 ; 0775 1-ee: ***** .byte %00110110 ; 0776 1-ee: ** ** .byte %00000000 ; 0777 1-ee: .byte %00000000 ; 0778 1-ef: .byte %00000000 ; 0779 1-ef: .byte %01100011 ; 077A 1-ef: ** ** .byte %01101011 ; 077B 1-ef: ** * ** .byte %01111111 ; 077C 1-ef: ******* .byte %00111110 ; 077D 1-ef: ***** .byte %00110110 ; 077E 1-ef: ** ** .byte %00000000 ; 077F 1-ef: .byte %00000000 ; 0780 1-f0: .byte %00000000 ; 0781 1-f0: .byte %01100110 ; 0782 1-f0: ** ** .byte %00111100 ; 0783 1-f0: **** .byte %00011000 ; 0784 1-f0: ** .byte %00111100 ; 0785 1-f0: **** .byte %01100110 ; 0786 1-f0: ** ** .byte %00000000 ; 0787 1-f0: .byte %00000000 ; 0788 1-f1: .byte %00000000 ; 0789 1-f1: .byte %01100110 ; 078A 1-f1: ** ** .byte %00111100 ; 078B 1-f1: **** .byte %00011000 ; 078C 1-f1: ** .byte %00111100 ; 078D 1-f1: **** .byte %01100110 ; 078E 1-f1: ** ** .byte %00000000 ; 078F 1-f1: .byte %00000000 ; 0790 1-f2: .byte %00000000 ; 0791 1-f2: .byte %01100110 ; 0792 1-f2: ** ** .byte %01100110 ; 0793 1-f2: ** ** .byte %01100110 ; 0794 1-f2: ** ** .byte %00111110 ; 0795 1-f2: ***** .byte %00001100 ; 0796 1-f2: ** .byte %01111000 ; 0797 1-f2: **** .byte %00000000 ; 0798 1-f3: .byte %00000000 ; 0799 1-f3: .byte %01100110 ; 079A 1-f3: ** ** .byte %01100110 ; 079B 1-f3: ** ** .byte %01100110 ; 079C 1-f3: ** ** .byte %00111110 ; 079D 1-f3: ***** .byte %00001100 ; 079E 1-f3: ** .byte %01111000 ; 079F 1-f3: **** .byte %00000000 ; 07A0 1-f4: .byte %00000000 ; 07A1 1-f4: .byte %01111110 ; 07A2 1-f4: ****** .byte %00001100 ; 07A3 1-f4: ** .byte %00011000 ; 07A4 1-f4: ** .byte %00110000 ; 07A5 1-f4: ** .byte %01111110 ; 07A6 1-f4: ****** .byte %00000000 ; 07A7 1-f4: .byte %00000000 ; 07A8 1-f5: .byte %00000000 ; 07A9 1-f5: .byte %01111110 ; 07AA 1-f5: ****** .byte %00001100 ; 07AB 1-f5: ** .byte %00011000 ; 07AC 1-f5: ** .byte %00110000 ; 07AD 1-f5: ** .byte %01111110 ; 07AE 1-f5: ****** .byte %00000000 ; 07AF 1-f5: .byte %00011100 ; 07B0 1-f6: *** .byte %00110000 ; 07B1 1-f6: ** .byte %00011000 ; 07B2 1-f6: ** .byte %01110000 ; 07B3 1-f6: *** .byte %00011000 ; 07B4 1-f6: ** .byte %00110000 ; 07B5 1-f6: ** .byte %00011100 ; 07B6 1-f6: *** .byte %00000000 ; 07B7 1-f6: .byte %00011100 ; 07B8 1-f7: *** .byte %00110000 ; 07B9 1-f7: ** .byte %00011000 ; 07BA 1-f7: ** .byte %01110000 ; 07BB 1-f7: *** .byte %00011000 ; 07BC 1-f7: ** .byte %00110000 ; 07BD 1-f7: ** .byte %00011100 ; 07BE 1-f7: *** .byte %00000000 ; 07BF 1-f7: .byte %00011000 ; 07C0 1-f8: ** .byte %00011000 ; 07C1 1-f8: ** .byte %00011000 ; 07C2 1-f8: ** .byte %00000000 ; 07C3 1-f8: .byte %00000000 ; 07C4 1-f8: .byte %00011000 ; 07C5 1-f8: ** .byte %00011000 ; 07C6 1-f8: ** .byte %00011000 ; 07C7 1-f8: ** .byte %00011000 ; 07C8 1-f9: ** .byte %00011000 ; 07C9 1-f9: ** .byte %00011000 ; 07CA 1-f9: ** .byte %00000000 ; 07CB 1-f9: .byte %00000000 ; 07CC 1-f9: .byte %00011000 ; 07CD 1-f9: ** .byte %00011000 ; 07CE 1-f9: ** .byte %00011000 ; 07CF 1-f9: ** .byte %00111000 ; 07D0 1-fa: *** .byte %00001100 ; 07D1 1-fa: ** .byte %00011000 ; 07D2 1-fa: ** .byte %00001110 ; 07D3 1-fa: *** .byte %00011000 ; 07D4 1-fa: ** .byte %00001100 ; 07D5 1-fa: ** .byte %00111000 ; 07D6 1-fa: *** .byte %00000000 ; 07D7 1-fa: .byte %00111000 ; 07D8 1-fb: *** .byte %00001100 ; 07D9 1-fb: ** .byte %00011000 ; 07DA 1-fb: ** .byte %00001110 ; 07DB 1-fb: *** .byte %00011000 ; 07DC 1-fb: ** .byte %00001100 ; 07DD 1-fb: ** .byte %00111000 ; 07DE 1-fb: *** .byte %00000000 ; 07DF 1-fb: .byte %00110011 ; 07E0 1-fc: ** ** .byte %11111111 ; 07E1 1-fc: ******** .byte %11001100 ; 07E2 1-fc: ** ** .byte %00000000 ; 07E3 1-fc: .byte %00000000 ; 07E4 1-fc: .byte %00000000 ; 07E5 1-fc: .byte %00000000 ; 07E6 1-fc: .byte %00000000 ; 07E7 1-fc: .byte %00110011 ; 07E8 1-fd: ** ** .byte %11111111 ; 07E9 1-fd: ******** .byte %11001100 ; 07EA 1-fd: ** ** .byte %00000000 ; 07EB 1-fd: .byte %00000000 ; 07EC 1-fd: .byte %00000000 ; 07ED 1-fd: .byte %00000000 ; 07EE 1-fd: .byte %00000000 ; 07EF 1-fd: .byte %00000000 ; 07F0 1-fe: .byte %00000000 ; 07F1 1-fe: .byte %00000000 ; 07F2 1-fe: .byte %00000000 ; 07F3 1-fe: .byte %00000000 ; 07F4 1-fe: .byte %00000000 ; 07F5 1-fe: .byte %00000000 ; 07F6 1-fe: .byte %00000000 ; 07F7 1-fe: .byte %00000000 ; 07F8 1-ff: .byte %00000000 ; 07F9 1-ff: .byte %00000000 ; 07FA 1-ff: .byte %00000000 ; 07FB 1-ff: .byte %00000000 ; 07FC 1-ff: .byte %00000000 ; 07FD 1-ff: .byte %00000000 ; 07FE 1-ff: .byte %00000000 ; 07FF 1-ff: .byte %11111111 ; 0800 2-00: ******** .byte %11111111 ; 0801 2-00: ******** .byte %11111111 ; 0802 2-00: ******** .byte %11111111 ; 0803 2-00: ******** .byte %11111111 ; 0804 2-00: ******** .byte %11111111 ; 0805 2-00: ******** .byte %11111111 ; 0806 2-00: ******** .byte %11111111 ; 0807 2-00: ******** .byte %11111111 ; 0808 2-01: ******** .byte %11111111 ; 0809 2-01: ******** .byte %11111111 ; 080A 2-01: ******** .byte %11111111 ; 080B 2-01: ******** .byte %11111111 ; 080C 2-01: ******** .byte %11111111 ; 080D 2-01: ******** .byte %11111111 ; 080E 2-01: ******** .byte %11111111 ; 080F 2-01: ******** .byte %00110011 ; 0810 2-02: ** ** .byte %00110011 ; 0811 2-02: ** ** .byte %11001100 ; 0812 2-02: ** ** .byte %11001100 ; 0813 2-02: ** ** .byte %00110011 ; 0814 2-02: ** ** .byte %00110011 ; 0815 2-02: ** ** .byte %11001100 ; 0816 2-02: ** ** .byte %11001100 ; 0817 2-02: ** ** .byte %00110011 ; 0818 2-03: ** ** .byte %00110011 ; 0819 2-03: ** ** .byte %11001100 ; 081A 2-03: ** ** .byte %11001100 ; 081B 2-03: ** ** .byte %00110011 ; 081C 2-03: ** ** .byte %00110011 ; 081D 2-03: ** ** .byte %11001100 ; 081E 2-03: ** ** .byte %11001100 ; 081F 2-03: ** ** .byte %11111111 ; 0820 2-04: ******** .byte %11100111 ; 0821 2-04: *** *** .byte %11000011 ; 0822 2-04: ** ** .byte %10000001 ; 0823 2-04: * * .byte %11100111 ; 0824 2-04: *** *** .byte %11100111 ; 0825 2-04: *** *** .byte %11100111 ; 0826 2-04: *** *** .byte %11100111 ; 0827 2-04: *** *** .byte %11111111 ; 0828 2-05: ******** .byte %11100111 ; 0829 2-05: *** *** .byte %11000011 ; 082A 2-05: ** ** .byte %10000001 ; 082B 2-05: * * .byte %11100111 ; 082C 2-05: *** *** .byte %11100111 ; 082D 2-05: *** *** .byte %11100111 ; 082E 2-05: *** *** .byte %11100111 ; 082F 2-05: *** *** .byte %11111111 ; 0830 2-06: ******** .byte %11101111 ; 0831 2-06: *** **** .byte %11001111 ; 0832 2-06: ** **** .byte %10000000 ; 0833 2-06: * .byte %10000000 ; 0834 2-06: * .byte %11001111 ; 0835 2-06: ** **** .byte %11101111 ; 0836 2-06: *** **** .byte %11111111 ; 0837 2-06: ******** .byte %11111111 ; 0838 2-07: ******** .byte %11101111 ; 0839 2-07: *** **** .byte %11001111 ; 083A 2-07: ** **** .byte %10000000 ; 083B 2-07: * .byte %10000000 ; 083C 2-07: * .byte %11001111 ; 083D 2-07: ** **** .byte %11101111 ; 083E 2-07: *** **** .byte %11111111 ; 083F 2-07: ******** .byte %11110011 ; 0840 2-08: **** ** .byte %11101101 ; 0841 2-08: *** ** * .byte %11001111 ; 0842 2-08: ** **** .byte %10000011 ; 0843 2-08: * ** .byte %11001111 ; 0844 2-08: ** **** .byte %10011101 ; 0845 2-08: * *** * .byte %00000011 ; 0846 2-08: ** .byte %11111111 ; 0847 2-08: ******** .byte %11110011 ; 0848 2-09: **** ** .byte %11101101 ; 0849 2-09: *** ** * .byte %11001111 ; 084A 2-09: ** **** .byte %10000011 ; 084B 2-09: * ** .byte %11001111 ; 084C 2-09: ** **** .byte %10011101 ; 084D 2-09: * *** * .byte %00000011 ; 084E 2-09: ** .byte %11111111 ; 084F 2-09: ******** .byte %11111111 ; 0850 2-0a: ******** .byte %11111111 ; 0851 2-0a: ******** .byte %11111100 ; 0852 2-0a: ****** .byte %11000001 ; 0853 2-0a: ** * .byte %10001001 ; 0854 2-0a: * * * .byte %11001001 ; 0855 2-0a: ** * * .byte %11001001 ; 0856 2-0a: ** * * .byte %11111111 ; 0857 2-0a: ******** .byte %11111111 ; 0858 2-0b: ******** .byte %11111111 ; 0859 2-0b: ******** .byte %11111100 ; 085A 2-0b: ****** .byte %11000001 ; 085B 2-0b: ** * .byte %10001001 ; 085C 2-0b: * * * .byte %11001001 ; 085D 2-0b: ** * * .byte %11001001 ; 085E 2-0b: ** * * .byte %11111111 ; 085F 2-0b: ******** .byte %10000000 ; 0860 2-0c: * .byte %10000000 ; 0861 2-0c: * .byte %11111111 ; 0862 2-0c: ******** .byte %11111111 ; 0863 2-0c: ******** .byte %11111111 ; 0864 2-0c: ******** .byte %11111111 ; 0865 2-0c: ******** .byte %11111111 ; 0866 2-0c: ******** .byte %11111111 ; 0867 2-0c: ******** .byte %10000000 ; 0868 2-0d: * .byte %10000000 ; 0869 2-0d: * .byte %11111111 ; 086A 2-0d: ******** .byte %11111111 ; 086B 2-0d: ******** .byte %11111111 ; 086C 2-0d: ******** .byte %11111111 ; 086D 2-0d: ******** .byte %11111111 ; 086E 2-0d: ******** .byte %11111111 ; 086F 2-0d: ******** .byte %00011111 ; 0870 2-0e: ***** .byte %00011111 ; 0871 2-0e: ***** .byte %10011111 ; 0872 2-0e: * ***** .byte %10011111 ; 0873 2-0e: * ***** .byte %10011111 ; 0874 2-0e: * ***** .byte %10011111 ; 0875 2-0e: * ***** .byte %10011111 ; 0876 2-0e: * ***** .byte %10011111 ; 0877 2-0e: * ***** .byte %00011111 ; 0878 2-0f: ***** .byte %00011111 ; 0879 2-0f: ***** .byte %10011111 ; 087A 2-0f: * ***** .byte %10011111 ; 087B 2-0f: * ***** .byte %10011111 ; 087C 2-0f: * ***** .byte %10011111 ; 087D 2-0f: * ***** .byte %10011111 ; 087E 2-0f: * ***** .byte %10011111 ; 087F 2-0f: * ***** .byte %11100111 ; 0880 2-10: *** *** .byte %11100111 ; 0881 2-10: *** *** .byte %11100111 ; 0882 2-10: *** *** .byte %00000111 ; 0883 2-10: *** .byte %00000111 ; 0884 2-10: *** .byte %11111111 ; 0885 2-10: ******** .byte %11111111 ; 0886 2-10: ******** .byte %11111111 ; 0887 2-10: ******** .byte %11100111 ; 0888 2-11: *** *** .byte %11100111 ; 0889 2-11: *** *** .byte %11100111 ; 088A 2-11: *** *** .byte %00000111 ; 088B 2-11: *** .byte %00000111 ; 088C 2-11: *** .byte %11111111 ; 088D 2-11: ******** .byte %11111111 ; 088E 2-11: ******** .byte %11111111 ; 088F 2-11: ******** .byte %00110011 ; 0890 2-12: ** ** .byte %01100110 ; 0891 2-12: ** ** .byte %11001100 ; 0892 2-12: ** ** .byte %10011001 ; 0893 2-12: * ** * .byte %00110011 ; 0894 2-12: ** ** .byte %01100110 ; 0895 2-12: ** ** .byte %11001100 ; 0896 2-12: ** ** .byte %10011001 ; 0897 2-12: * ** * .byte %00110011 ; 0898 2-13: ** ** .byte %01100110 ; 0899 2-13: ** ** .byte %11001100 ; 089A 2-13: ** ** .byte %10011001 ; 089B 2-13: * ** * .byte %00110011 ; 089C 2-13: ** ** .byte %01100110 ; 089D 2-13: ** ** .byte %11001100 ; 089E 2-13: ** ** .byte %10011001 ; 089F 2-13: * ** * .byte %11001100 ; 08A0 2-14: ** ** .byte %01100110 ; 08A1 2-14: ** ** .byte %00110011 ; 08A2 2-14: ** ** .byte %10011001 ; 08A3 2-14: * ** * .byte %11001100 ; 08A4 2-14: ** ** .byte %01100110 ; 08A5 2-14: ** ** .byte %00110011 ; 08A6 2-14: ** ** .byte %10011001 ; 08A7 2-14: * ** * .byte %11001100 ; 08A8 2-15: ** ** .byte %01100110 ; 08A9 2-15: ** ** .byte %00110011 ; 08AA 2-15: ** ** .byte %10011001 ; 08AB 2-15: * ** * .byte %11001100 ; 08AC 2-15: ** ** .byte %01100110 ; 08AD 2-15: ** ** .byte %00110011 ; 08AE 2-15: ** ** .byte %10011001 ; 08AF 2-15: * ** * .byte %11111111 ; 08B0 2-16: ******** .byte %11111111 ; 08B1 2-16: ******** .byte %11111111 ; 08B2 2-16: ******** .byte %00000000 ; 08B3 2-16: .byte %00000000 ; 08B4 2-16: .byte %11111111 ; 08B5 2-16: ******** .byte %11111111 ; 08B6 2-16: ******** .byte %11111111 ; 08B7 2-16: ******** .byte %11111111 ; 08B8 2-17: ******** .byte %11111111 ; 08B9 2-17: ******** .byte %11111111 ; 08BA 2-17: ******** .byte %00000000 ; 08BB 2-17: .byte %00000000 ; 08BC 2-17: .byte %11111111 ; 08BD 2-17: ******** .byte %11111111 ; 08BE 2-17: ******** .byte %11111111 ; 08BF 2-17: ******** .byte %11111100 ; 08C0 2-18: ****** .byte %11111100 ; 08C1 2-18: ****** .byte %11111100 ; 08C2 2-18: ****** .byte %11111100 ; 08C3 2-18: ****** .byte %11111100 ; 08C4 2-18: ****** .byte %11111100 ; 08C5 2-18: ****** .byte %11111100 ; 08C6 2-18: ****** .byte %11111100 ; 08C7 2-18: ****** .byte %11111100 ; 08C8 2-19: ****** .byte %11111100 ; 08C9 2-19: ****** .byte %11111100 ; 08CA 2-19: ****** .byte %11111100 ; 08CB 2-19: ****** .byte %11111100 ; 08CC 2-19: ****** .byte %11111100 ; 08CD 2-19: ****** .byte %11111100 ; 08CE 2-19: ****** .byte %11111100 ; 08CF 2-19: ****** .byte %11111111 ; 08D0 2-1a: ******** .byte %11111111 ; 08D1 2-1a: ******** .byte %11111111 ; 08D2 2-1a: ******** .byte %11111111 ; 08D3 2-1a: ******** .byte %00110011 ; 08D4 2-1a: ** ** .byte %00110011 ; 08D5 2-1a: ** ** .byte %11001100 ; 08D6 2-1a: ** ** .byte %11001100 ; 08D7 2-1a: ** ** .byte %11111111 ; 08D8 2-1b: ******** .byte %11111111 ; 08D9 2-1b: ******** .byte %11111111 ; 08DA 2-1b: ******** .byte %11111111 ; 08DB 2-1b: ******** .byte %00110011 ; 08DC 2-1b: ** ** .byte %00110011 ; 08DD 2-1b: ** ** .byte %11001100 ; 08DE 2-1b: ** ** .byte %11001100 ; 08DF 2-1b: ** ** .byte %11100111 ; 08E0 2-1c: *** *** .byte %11100111 ; 08E1 2-1c: *** *** .byte %11100111 ; 08E2 2-1c: *** *** .byte %11100111 ; 08E3 2-1c: *** *** .byte %11100111 ; 08E4 2-1c: *** *** .byte %11100111 ; 08E5 2-1c: *** *** .byte %11100111 ; 08E6 2-1c: *** *** .byte %11100111 ; 08E7 2-1c: *** *** .byte %11100111 ; 08E8 2-1d: *** *** .byte %11100111 ; 08E9 2-1d: *** *** .byte %11100111 ; 08EA 2-1d: *** *** .byte %11100111 ; 08EB 2-1d: *** *** .byte %11100111 ; 08EC 2-1d: *** *** .byte %11100111 ; 08ED 2-1d: *** *** .byte %11100111 ; 08EE 2-1d: *** *** .byte %11100111 ; 08EF 2-1d: *** *** .byte %11100111 ; 08F0 2-1e: *** *** .byte %11100111 ; 08F1 2-1e: *** *** .byte %11100111 ; 08F2 2-1e: *** *** .byte %11100000 ; 08F3 2-1e: *** .byte %11100000 ; 08F4 2-1e: *** .byte %11100111 ; 08F5 2-1e: *** *** .byte %11100111 ; 08F6 2-1e: *** *** .byte %11100111 ; 08F7 2-1e: *** *** .byte %11100111 ; 08F8 2-1f: *** *** .byte %11100111 ; 08F9 2-1f: *** *** .byte %11100111 ; 08FA 2-1f: *** *** .byte %11100000 ; 08FB 2-1f: *** .byte %11100000 ; 08FC 2-1f: *** .byte %11100111 ; 08FD 2-1f: *** *** .byte %11100111 ; 08FE 2-1f: *** *** .byte %11100111 ; 08FF 2-1f: *** *** .byte %11100111 ; 0900 2-20: *** *** .byte %11100111 ; 0901 2-20: *** *** .byte %11100111 ; 0902 2-20: *** *** .byte %00000000 ; 0903 2-20: .byte %00000000 ; 0904 2-20: .byte %11100111 ; 0905 2-20: *** *** .byte %11100111 ; 0906 2-20: *** *** .byte %11100111 ; 0907 2-20: *** *** .byte %11100111 ; 0908 2-21: *** *** .byte %11100111 ; 0909 2-21: *** *** .byte %11100111 ; 090A 2-21: *** *** .byte %00000000 ; 090B 2-21: .byte %00000000 ; 090C 2-21: .byte %11100111 ; 090D 2-21: *** *** .byte %11100111 ; 090E 2-21: *** *** .byte %11100111 ; 090F 2-21: *** *** .byte %11100111 ; 0910 2-22: *** *** .byte %11100111 ; 0911 2-22: *** *** .byte %11100111 ; 0912 2-22: *** *** .byte %11100000 ; 0913 2-22: *** .byte %11100000 ; 0914 2-22: *** .byte %11111111 ; 0915 2-22: ******** .byte %11111111 ; 0916 2-22: ******** .byte %11111111 ; 0917 2-22: ******** .byte %11100111 ; 0918 2-23: *** *** .byte %11100111 ; 0919 2-23: *** *** .byte %11100111 ; 091A 2-23: *** *** .byte %11100000 ; 091B 2-23: *** .byte %11100000 ; 091C 2-23: *** .byte %11111111 ; 091D 2-23: ******** .byte %11111111 ; 091E 2-23: ******** .byte %11111111 ; 091F 2-23: ******** .byte %11111111 ; 0920 2-24: ******** .byte %11111111 ; 0921 2-24: ******** .byte %11111111 ; 0922 2-24: ******** .byte %00000111 ; 0923 2-24: *** .byte %00000111 ; 0924 2-24: *** .byte %11100111 ; 0925 2-24: *** *** .byte %11100111 ; 0926 2-24: *** *** .byte %11100111 ; 0927 2-24: *** *** .byte %11111111 ; 0928 2-25: ******** .byte %11111111 ; 0929 2-25: ******** .byte %11111111 ; 092A 2-25: ******** .byte %00000111 ; 092B 2-25: *** .byte %00000111 ; 092C 2-25: *** .byte %11100111 ; 092D 2-25: *** *** .byte %11100111 ; 092E 2-25: *** *** .byte %11100111 ; 092F 2-25: *** *** .byte %11111111 ; 0930 2-26: ******** .byte %11111111 ; 0931 2-26: ******** .byte %11111111 ; 0932 2-26: ******** .byte %11111111 ; 0933 2-26: ******** .byte %11111111 ; 0934 2-26: ******** .byte %11111111 ; 0935 2-26: ******** .byte %00000000 ; 0936 2-26: .byte %00000000 ; 0937 2-26: .byte %11111111 ; 0938 2-27: ******** .byte %11111111 ; 0939 2-27: ******** .byte %11111111 ; 093A 2-27: ******** .byte %11111111 ; 093B 2-27: ******** .byte %11111111 ; 093C 2-27: ******** .byte %11111111 ; 093D 2-27: ******** .byte %00000000 ; 093E 2-27: .byte %00000000 ; 093F 2-27: .byte %11111111 ; 0940 2-28: ******** .byte %11111111 ; 0941 2-28: ******** .byte %11111111 ; 0942 2-28: ******** .byte %11100000 ; 0943 2-28: *** .byte %11100000 ; 0944 2-28: *** .byte %11100111 ; 0945 2-28: *** *** .byte %11100111 ; 0946 2-28: *** *** .byte %11100111 ; 0947 2-28: *** *** .byte %11111111 ; 0948 2-29: ******** .byte %11111111 ; 0949 2-29: ******** .byte %11111111 ; 094A 2-29: ******** .byte %11100000 ; 094B 2-29: *** .byte %11100000 ; 094C 2-29: *** .byte %11100111 ; 094D 2-29: *** *** .byte %11100111 ; 094E 2-29: *** *** .byte %11100111 ; 094F 2-29: *** *** .byte %11100111 ; 0950 2-2a: *** *** .byte %11100111 ; 0951 2-2a: *** *** .byte %11100111 ; 0952 2-2a: *** *** .byte %00000000 ; 0953 2-2a: .byte %00000000 ; 0954 2-2a: .byte %11111111 ; 0955 2-2a: ******** .byte %11111111 ; 0956 2-2a: ******** .byte %11111111 ; 0957 2-2a: ******** .byte %11100111 ; 0958 2-2b: *** *** .byte %11100111 ; 0959 2-2b: *** *** .byte %11100111 ; 095A 2-2b: *** *** .byte %00000000 ; 095B 2-2b: .byte %00000000 ; 095C 2-2b: .byte %11111111 ; 095D 2-2b: ******** .byte %11111111 ; 095E 2-2b: ******** .byte %11111111 ; 095F 2-2b: ******** .byte %11111111 ; 0960 2-2c: ******** .byte %11111111 ; 0961 2-2c: ******** .byte %11111111 ; 0962 2-2c: ******** .byte %00000000 ; 0963 2-2c: .byte %00000000 ; 0964 2-2c: .byte %11100111 ; 0965 2-2c: *** *** .byte %11100111 ; 0966 2-2c: *** *** .byte %11100111 ; 0967 2-2c: *** *** .byte %11111111 ; 0968 2-2d: ******** .byte %11111111 ; 0969 2-2d: ******** .byte %11111111 ; 096A 2-2d: ******** .byte %00000000 ; 096B 2-2d: .byte %00000000 ; 096C 2-2d: .byte %11100111 ; 096D 2-2d: *** *** .byte %11100111 ; 096E 2-2d: *** *** .byte %11100111 ; 096F 2-2d: *** *** .byte %11100111 ; 0970 2-2e: *** *** .byte %11100111 ; 0971 2-2e: *** *** .byte %11100111 ; 0972 2-2e: *** *** .byte %00000111 ; 0973 2-2e: *** .byte %00000111 ; 0974 2-2e: *** .byte %11100111 ; 0975 2-2e: *** *** .byte %11100111 ; 0976 2-2e: *** *** .byte %11100111 ; 0977 2-2e: *** *** .byte %11100111 ; 0978 2-2f: *** *** .byte %11100111 ; 0979 2-2f: *** *** .byte %11100111 ; 097A 2-2f: *** *** .byte %00000111 ; 097B 2-2f: *** .byte %00000111 ; 097C 2-2f: *** .byte %11100111 ; 097D 2-2f: *** *** .byte %11100111 ; 097E 2-2f: *** *** .byte %11100111 ; 097F 2-2f: *** *** .byte %00001111 ; 0980 2-30: **** .byte %00001111 ; 0981 2-30: **** .byte %00001111 ; 0982 2-30: **** .byte %00001111 ; 0983 2-30: **** .byte %00001111 ; 0984 2-30: **** .byte %00001111 ; 0985 2-30: **** .byte %00001111 ; 0986 2-30: **** .byte %00001111 ; 0987 2-30: **** .byte %00001111 ; 0988 2-31: **** .byte %00001111 ; 0989 2-31: **** .byte %00001111 ; 098A 2-31: **** .byte %00001111 ; 098B 2-31: **** .byte %00001111 ; 098C 2-31: **** .byte %00001111 ; 098D 2-31: **** .byte %00001111 ; 098E 2-31: **** .byte %00001111 ; 098F 2-31: **** .byte %11111111 ; 0990 2-32: ******** .byte %11111111 ; 0991 2-32: ******** .byte %11111111 ; 0992 2-32: ******** .byte %11111111 ; 0993 2-32: ******** .byte %00000000 ; 0994 2-32: .byte %00000000 ; 0995 2-32: .byte %00000000 ; 0996 2-32: .byte %00000000 ; 0997 2-32: .byte %11111111 ; 0998 2-33: ******** .byte %11111111 ; 0999 2-33: ******** .byte %11111111 ; 099A 2-33: ******** .byte %11111111 ; 099B 2-33: ******** .byte %00000000 ; 099C 2-33: .byte %00000000 ; 099D 2-33: .byte %00000000 ; 099E 2-33: .byte %00000000 ; 099F 2-33: .byte %11111111 ; 09A0 2-34: ******** .byte %11111111 ; 09A1 2-34: ******** .byte %11111111 ; 09A2 2-34: ******** .byte %11111111 ; 09A3 2-34: ******** .byte %00001111 ; 09A4 2-34: **** .byte %00001111 ; 09A5 2-34: **** .byte %00001111 ; 09A6 2-34: **** .byte %00001111 ; 09A7 2-34: **** .byte %11111111 ; 09A8 2-35: ******** .byte %11111111 ; 09A9 2-35: ******** .byte %11111111 ; 09AA 2-35: ******** .byte %11111111 ; 09AB 2-35: ******** .byte %00001111 ; 09AC 2-35: **** .byte %00001111 ; 09AD 2-35: **** .byte %00001111 ; 09AE 2-35: **** .byte %00001111 ; 09AF 2-35: **** .byte %00111111 ; 09B0 2-36: ****** .byte %00111111 ; 09B1 2-36: ****** .byte %11001111 ; 09B2 2-36: ** **** .byte %11001111 ; 09B3 2-36: ** **** .byte %00111111 ; 09B4 2-36: ****** .byte %00111111 ; 09B5 2-36: ****** .byte %11001111 ; 09B6 2-36: ** **** .byte %11001111 ; 09B7 2-36: ** **** .byte %00111111 ; 09B8 2-37: ****** .byte %00111111 ; 09B9 2-37: ****** .byte %11001111 ; 09BA 2-37: ** **** .byte %11001111 ; 09BB 2-37: ** **** .byte %00111111 ; 09BC 2-37: ****** .byte %00111111 ; 09BD 2-37: ****** .byte %11001111 ; 09BE 2-37: ** **** .byte %11001111 ; 09BF 2-37: ** **** .byte %11110000 ; 09C0 2-38: **** .byte %11110000 ; 09C1 2-38: **** .byte %11110000 ; 09C2 2-38: **** .byte %11110000 ; 09C3 2-38: **** .byte %11111111 ; 09C4 2-38: ******** .byte %11111111 ; 09C5 2-38: ******** .byte %11111111 ; 09C6 2-38: ******** .byte %11111111 ; 09C7 2-38: ******** .byte %11110000 ; 09C8 2-39: **** .byte %11110000 ; 09C9 2-39: **** .byte %11110000 ; 09CA 2-39: **** .byte %11110000 ; 09CB 2-39: **** .byte %11111111 ; 09CC 2-39: ******** .byte %11111111 ; 09CD 2-39: ******** .byte %11111111 ; 09CE 2-39: ******** .byte %11111111 ; 09CF 2-39: ******** .byte %11111111 ; 09D0 2-3a: ******** .byte %11111111 ; 09D1 2-3a: ******** .byte %11111111 ; 09D2 2-3a: ******** .byte %11111111 ; 09D3 2-3a: ******** .byte %11110000 ; 09D4 2-3a: **** .byte %11110000 ; 09D5 2-3a: **** .byte %11110000 ; 09D6 2-3a: **** .byte %11110000 ; 09D7 2-3a: **** .byte %11111111 ; 09D8 2-3b: ******** .byte %11111111 ; 09D9 2-3b: ******** .byte %11111111 ; 09DA 2-3b: ******** .byte %11111111 ; 09DB 2-3b: ******** .byte %11110000 ; 09DC 2-3b: **** .byte %11110000 ; 09DD 2-3b: **** .byte %11110000 ; 09DE 2-3b: **** .byte %11110000 ; 09DF 2-3b: **** .byte %00001111 ; 09E0 2-3c: **** .byte %00001111 ; 09E1 2-3c: **** .byte %00001111 ; 09E2 2-3c: **** .byte %00001111 ; 09E3 2-3c: **** .byte %11111111 ; 09E4 2-3c: ******** .byte %11111111 ; 09E5 2-3c: ******** .byte %11111111 ; 09E6 2-3c: ******** .byte %11111111 ; 09E7 2-3c: ******** .byte %00001111 ; 09E8 2-3d: **** .byte %00001111 ; 09E9 2-3d: **** .byte %00001111 ; 09EA 2-3d: **** .byte %00001111 ; 09EB 2-3d: **** .byte %11111111 ; 09EC 2-3d: ******** .byte %11111111 ; 09ED 2-3d: ******** .byte %11111111 ; 09EE 2-3d: ******** .byte %11111111 ; 09EF 2-3d: ******** .byte %00001111 ; 09F0 2-3e: **** .byte %00001111 ; 09F1 2-3e: **** .byte %00001111 ; 09F2 2-3e: **** .byte %00001111 ; 09F3 2-3e: **** .byte %11110000 ; 09F4 2-3e: **** .byte %11110000 ; 09F5 2-3e: **** .byte %11110000 ; 09F6 2-3e: **** .byte %11110000 ; 09F7 2-3e: **** .byte %00001111 ; 09F8 2-3f: **** .byte %00001111 ; 09F9 2-3f: **** .byte %00001111 ; 09FA 2-3f: **** .byte %00001111 ; 09FB 2-3f: **** .byte %11110000 ; 09FC 2-3f: **** .byte %11110000 ; 09FD 2-3f: **** .byte %11110000 ; 09FE 2-3f: **** .byte %11110000 ; 09FF 2-3f: **** .byte %11111111 ; 0A00 2-40: ******** .byte %11111111 ; 0A01 2-40: ******** .byte %11111111 ; 0A02 2-40: ******** .byte %11111111 ; 0A03 2-40: ******** .byte %11111111 ; 0A04 2-40: ******** .byte %11111111 ; 0A05 2-40: ******** .byte %11111111 ; 0A06 2-40: ******** .byte %11111111 ; 0A07 2-40: ******** .byte %11111111 ; 0A08 2-41: ******** .byte %11111111 ; 0A09 2-41: ******** .byte %11111111 ; 0A0A 2-41: ******** .byte %11111111 ; 0A0B 2-41: ******** .byte %11111111 ; 0A0C 2-41: ******** .byte %11111111 ; 0A0D 2-41: ******** .byte %11111111 ; 0A0E 2-41: ******** .byte %11111111 ; 0A0F 2-41: ******** .byte %11100111 ; 0A10 2-42: *** *** .byte %11100111 ; 0A11 2-42: *** *** .byte %11100111 ; 0A12 2-42: *** *** .byte %11100111 ; 0A13 2-42: *** *** .byte %11111111 ; 0A14 2-42: ******** .byte %11111111 ; 0A15 2-42: ******** .byte %11100111 ; 0A16 2-42: *** *** .byte %11111111 ; 0A17 2-42: ******** .byte %11100111 ; 0A18 2-43: *** *** .byte %11100111 ; 0A19 2-43: *** *** .byte %11100111 ; 0A1A 2-43: *** *** .byte %11100111 ; 0A1B 2-43: *** *** .byte %11111111 ; 0A1C 2-43: ******** .byte %11111111 ; 0A1D 2-43: ******** .byte %11100111 ; 0A1E 2-43: *** *** .byte %11111111 ; 0A1F 2-43: ******** .byte %10011001 ; 0A20 2-44: * ** * .byte %10011001 ; 0A21 2-44: * ** * .byte %10011001 ; 0A22 2-44: * ** * .byte %11111111 ; 0A23 2-44: ******** .byte %11111111 ; 0A24 2-44: ******** .byte %11111111 ; 0A25 2-44: ******** .byte %11111111 ; 0A26 2-44: ******** .byte %11111111 ; 0A27 2-44: ******** .byte %10011001 ; 0A28 2-45: * ** * .byte %10011001 ; 0A29 2-45: * ** * .byte %10011001 ; 0A2A 2-45: * ** * .byte %11111111 ; 0A2B 2-45: ******** .byte %11111111 ; 0A2C 2-45: ******** .byte %11111111 ; 0A2D 2-45: ******** .byte %11111111 ; 0A2E 2-45: ******** .byte %11111111 ; 0A2F 2-45: ******** .byte %10011001 ; 0A30 2-46: * ** * .byte %10011001 ; 0A31 2-46: * ** * .byte %00000000 ; 0A32 2-46: .byte %10011001 ; 0A33 2-46: * ** * .byte %00000000 ; 0A34 2-46: .byte %10011001 ; 0A35 2-46: * ** * .byte %10011001 ; 0A36 2-46: * ** * .byte %11111111 ; 0A37 2-46: ******** .byte %10011001 ; 0A38 2-47: * ** * .byte %10011001 ; 0A39 2-47: * ** * .byte %00000000 ; 0A3A 2-47: .byte %10011001 ; 0A3B 2-47: * ** * .byte %00000000 ; 0A3C 2-47: .byte %10011001 ; 0A3D 2-47: * ** * .byte %10011001 ; 0A3E 2-47: * ** * .byte %11111111 ; 0A3F 2-47: ******** .byte %11100111 ; 0A40 2-48: *** *** .byte %11000001 ; 0A41 2-48: ** * .byte %10011111 ; 0A42 2-48: * ***** .byte %11000011 ; 0A43 2-48: ** ** .byte %11111001 ; 0A44 2-48: ***** * .byte %10000011 ; 0A45 2-48: * ** .byte %11100111 ; 0A46 2-48: *** *** .byte %11111111 ; 0A47 2-48: ******** .byte %11100111 ; 0A48 2-49: *** *** .byte %11000001 ; 0A49 2-49: ** * .byte %10011111 ; 0A4A 2-49: * ***** .byte %11000011 ; 0A4B 2-49: ** ** .byte %11111001 ; 0A4C 2-49: ***** * .byte %10000011 ; 0A4D 2-49: * ** .byte %11100111 ; 0A4E 2-49: *** *** .byte %11111111 ; 0A4F 2-49: ******** .byte %11111111 ; 0A50 2-4a: ******** .byte %10011001 ; 0A51 2-4a: * ** * .byte %11110011 ; 0A52 2-4a: **** ** .byte %11100111 ; 0A53 2-4a: *** *** .byte %11001111 ; 0A54 2-4a: ** **** .byte %10011001 ; 0A55 2-4a: * ** * .byte %10111001 ; 0A56 2-4a: * *** * .byte %11111111 ; 0A57 2-4a: ******** .byte %11111111 ; 0A58 2-4b: ******** .byte %10011001 ; 0A59 2-4b: * ** * .byte %11110011 ; 0A5A 2-4b: **** ** .byte %11100111 ; 0A5B 2-4b: *** *** .byte %11001111 ; 0A5C 2-4b: ** **** .byte %10011001 ; 0A5D 2-4b: * ** * .byte %10111001 ; 0A5E 2-4b: * *** * .byte %11111111 ; 0A5F 2-4b: ******** .byte %11000011 ; 0A60 2-4c: ** ** .byte %10011001 ; 0A61 2-4c: * ** * .byte %11000011 ; 0A62 2-4c: ** ** .byte %11000111 ; 0A63 2-4c: ** *** .byte %10011000 ; 0A64 2-4c: * ** .byte %10011001 ; 0A65 2-4c: * ** * .byte %11000000 ; 0A66 2-4c: ** .byte %11111111 ; 0A67 2-4c: ******** .byte %11000011 ; 0A68 2-4d: ** ** .byte %10011001 ; 0A69 2-4d: * ** * .byte %11000011 ; 0A6A 2-4d: ** ** .byte %11000111 ; 0A6B 2-4d: ** *** .byte %10011000 ; 0A6C 2-4d: * ** .byte %10011001 ; 0A6D 2-4d: * ** * .byte %11000000 ; 0A6E 2-4d: ** .byte %11111111 ; 0A6F 2-4d: ******** .byte %11111001 ; 0A70 2-4e: ***** * .byte %11110011 ; 0A71 2-4e: **** ** .byte %11100111 ; 0A72 2-4e: *** *** .byte %11111111 ; 0A73 2-4e: ******** .byte %11111111 ; 0A74 2-4e: ******** .byte %11111111 ; 0A75 2-4e: ******** .byte %11111111 ; 0A76 2-4e: ******** .byte %11111111 ; 0A77 2-4e: ******** .byte %11111001 ; 0A78 2-4f: ***** * .byte %11110011 ; 0A79 2-4f: **** ** .byte %11100111 ; 0A7A 2-4f: *** *** .byte %11111111 ; 0A7B 2-4f: ******** .byte %11111111 ; 0A7C 2-4f: ******** .byte %11111111 ; 0A7D 2-4f: ******** .byte %11111111 ; 0A7E 2-4f: ******** .byte %11111111 ; 0A7F 2-4f: ******** .byte %11110011 ; 0A80 2-50: **** ** .byte %11100111 ; 0A81 2-50: *** *** .byte %11001111 ; 0A82 2-50: ** **** .byte %11001111 ; 0A83 2-50: ** **** .byte %11001111 ; 0A84 2-50: ** **** .byte %11100111 ; 0A85 2-50: *** *** .byte %11110011 ; 0A86 2-50: **** ** .byte %11111111 ; 0A87 2-50: ******** .byte %11110011 ; 0A88 2-51: **** ** .byte %11100111 ; 0A89 2-51: *** *** .byte %11001111 ; 0A8A 2-51: ** **** .byte %11001111 ; 0A8B 2-51: ** **** .byte %11001111 ; 0A8C 2-51: ** **** .byte %11100111 ; 0A8D 2-51: *** *** .byte %11110011 ; 0A8E 2-51: **** ** .byte %11111111 ; 0A8F 2-51: ******** .byte %11001111 ; 0A90 2-52: ** **** .byte %11100111 ; 0A91 2-52: *** *** .byte %11110011 ; 0A92 2-52: **** ** .byte %11110011 ; 0A93 2-52: **** ** .byte %11110011 ; 0A94 2-52: **** ** .byte %11100111 ; 0A95 2-52: *** *** .byte %11001111 ; 0A96 2-52: ** **** .byte %11111111 ; 0A97 2-52: ******** .byte %11001111 ; 0A98 2-53: ** **** .byte %11100111 ; 0A99 2-53: *** *** .byte %11110011 ; 0A9A 2-53: **** ** .byte %11110011 ; 0A9B 2-53: **** ** .byte %11110011 ; 0A9C 2-53: **** ** .byte %11100111 ; 0A9D 2-53: *** *** .byte %11001111 ; 0A9E 2-53: ** **** .byte %11111111 ; 0A9F 2-53: ******** .byte %11111111 ; 0AA0 2-54: ******** .byte %10011001 ; 0AA1 2-54: * ** * .byte %11000011 ; 0AA2 2-54: ** ** .byte %00000000 ; 0AA3 2-54: .byte %11000011 ; 0AA4 2-54: ** ** .byte %10011001 ; 0AA5 2-54: * ** * .byte %11111111 ; 0AA6 2-54: ******** .byte %11111111 ; 0AA7 2-54: ******** .byte %11111111 ; 0AA8 2-55: ******** .byte %10011001 ; 0AA9 2-55: * ** * .byte %11000011 ; 0AAA 2-55: ** ** .byte %00000000 ; 0AAB 2-55: .byte %11000011 ; 0AAC 2-55: ** ** .byte %10011001 ; 0AAD 2-55: * ** * .byte %11111111 ; 0AAE 2-55: ******** .byte %11111111 ; 0AAF 2-55: ******** .byte %11111111 ; 0AB0 2-56: ******** .byte %11100111 ; 0AB1 2-56: *** *** .byte %11100111 ; 0AB2 2-56: *** *** .byte %10000001 ; 0AB3 2-56: * * .byte %11100111 ; 0AB4 2-56: *** *** .byte %11100111 ; 0AB5 2-56: *** *** .byte %11111111 ; 0AB6 2-56: ******** .byte %11111111 ; 0AB7 2-56: ******** .byte %11111111 ; 0AB8 2-57: ******** .byte %11100111 ; 0AB9 2-57: *** *** .byte %11100111 ; 0ABA 2-57: *** *** .byte %10000001 ; 0ABB 2-57: * * .byte %11100111 ; 0ABC 2-57: *** *** .byte %11100111 ; 0ABD 2-57: *** *** .byte %11111111 ; 0ABE 2-57: ******** .byte %11111111 ; 0ABF 2-57: ******** .byte %11111111 ; 0AC0 2-58: ******** .byte %11111111 ; 0AC1 2-58: ******** .byte %11111111 ; 0AC2 2-58: ******** .byte %11111111 ; 0AC3 2-58: ******** .byte %11111111 ; 0AC4 2-58: ******** .byte %11100111 ; 0AC5 2-58: *** *** .byte %11100111 ; 0AC6 2-58: *** *** .byte %11001111 ; 0AC7 2-58: ** **** .byte %11111111 ; 0AC8 2-59: ******** .byte %11111111 ; 0AC9 2-59: ******** .byte %11111111 ; 0ACA 2-59: ******** .byte %11111111 ; 0ACB 2-59: ******** .byte %11111111 ; 0ACC 2-59: ******** .byte %11100111 ; 0ACD 2-59: *** *** .byte %11100111 ; 0ACE 2-59: *** *** .byte %11001111 ; 0ACF 2-59: ** **** .byte %11111111 ; 0AD0 2-5a: ******** .byte %11111111 ; 0AD1 2-5a: ******** .byte %11111111 ; 0AD2 2-5a: ******** .byte %10000001 ; 0AD3 2-5a: * * .byte %11111111 ; 0AD4 2-5a: ******** .byte %11111111 ; 0AD5 2-5a: ******** .byte %11111111 ; 0AD6 2-5a: ******** .byte %11111111 ; 0AD7 2-5a: ******** .byte %11111111 ; 0AD8 2-5b: ******** .byte %11111111 ; 0AD9 2-5b: ******** .byte %11111111 ; 0ADA 2-5b: ******** .byte %10000001 ; 0ADB 2-5b: * * .byte %11111111 ; 0ADC 2-5b: ******** .byte %11111111 ; 0ADD 2-5b: ******** .byte %11111111 ; 0ADE 2-5b: ******** .byte %11111111 ; 0ADF 2-5b: ******** .byte %11111111 ; 0AE0 2-5c: ******** .byte %11111111 ; 0AE1 2-5c: ******** .byte %11111111 ; 0AE2 2-5c: ******** .byte %11111111 ; 0AE3 2-5c: ******** .byte %11111111 ; 0AE4 2-5c: ******** .byte %11100111 ; 0AE5 2-5c: *** *** .byte %11100111 ; 0AE6 2-5c: *** *** .byte %11111111 ; 0AE7 2-5c: ******** .byte %11111111 ; 0AE8 2-5d: ******** .byte %11111111 ; 0AE9 2-5d: ******** .byte %11111111 ; 0AEA 2-5d: ******** .byte %11111111 ; 0AEB 2-5d: ******** .byte %11111111 ; 0AEC 2-5d: ******** .byte %11100111 ; 0AED 2-5d: *** *** .byte %11100111 ; 0AEE 2-5d: *** *** .byte %11111111 ; 0AEF 2-5d: ******** .byte %11111111 ; 0AF0 2-5e: ******** .byte %11111100 ; 0AF1 2-5e: ****** .byte %11111001 ; 0AF2 2-5e: ***** * .byte %11110011 ; 0AF3 2-5e: **** ** .byte %11100111 ; 0AF4 2-5e: *** *** .byte %11001111 ; 0AF5 2-5e: ** **** .byte %10011111 ; 0AF6 2-5e: * ***** .byte %11111111 ; 0AF7 2-5e: ******** .byte %11111111 ; 0AF8 2-5f: ******** .byte %11111100 ; 0AF9 2-5f: ****** .byte %11111001 ; 0AFA 2-5f: ***** * .byte %11110011 ; 0AFB 2-5f: **** ** .byte %11100111 ; 0AFC 2-5f: *** *** .byte %11001111 ; 0AFD 2-5f: ** **** .byte %10011111 ; 0AFE 2-5f: * ***** .byte %11111111 ; 0AFF 2-5f: ******** .byte %11000011 ; 0B00 2-60: ** ** .byte %10011001 ; 0B01 2-60: * ** * .byte %10010001 ; 0B02 2-60: * * * .byte %10001001 ; 0B03 2-60: * * * .byte %10011001 ; 0B04 2-60: * ** * .byte %10011001 ; 0B05 2-60: * ** * .byte %11000011 ; 0B06 2-60: ** ** .byte %11111111 ; 0B07 2-60: ******** .byte %11000011 ; 0B08 2-61: ** ** .byte %10011001 ; 0B09 2-61: * ** * .byte %10010001 ; 0B0A 2-61: * * * .byte %10001001 ; 0B0B 2-61: * * * .byte %10011001 ; 0B0C 2-61: * ** * .byte %10011001 ; 0B0D 2-61: * ** * .byte %11000011 ; 0B0E 2-61: ** ** .byte %11111111 ; 0B0F 2-61: ******** .byte %11100111 ; 0B10 2-62: *** *** .byte %11100111 ; 0B11 2-62: *** *** .byte %11000111 ; 0B12 2-62: ** *** .byte %11100111 ; 0B13 2-62: *** *** .byte %11100111 ; 0B14 2-62: *** *** .byte %11100111 ; 0B15 2-62: *** *** .byte %10000001 ; 0B16 2-62: * * .byte %11111111 ; 0B17 2-62: ******** .byte %11100111 ; 0B18 2-63: *** *** .byte %11100111 ; 0B19 2-63: *** *** .byte %11000111 ; 0B1A 2-63: ** *** .byte %11100111 ; 0B1B 2-63: *** *** .byte %11100111 ; 0B1C 2-63: *** *** .byte %11100111 ; 0B1D 2-63: *** *** .byte %10000001 ; 0B1E 2-63: * * .byte %11111111 ; 0B1F 2-63: ******** .byte %11000011 ; 0B20 2-64: ** ** .byte %10011001 ; 0B21 2-64: * ** * .byte %11111001 ; 0B22 2-64: ***** * .byte %11110011 ; 0B23 2-64: **** ** .byte %11001111 ; 0B24 2-64: ** **** .byte %10011111 ; 0B25 2-64: * ***** .byte %10000001 ; 0B26 2-64: * * .byte %11111111 ; 0B27 2-64: ******** .byte %11000011 ; 0B28 2-65: ** ** .byte %10011001 ; 0B29 2-65: * ** * .byte %11111001 ; 0B2A 2-65: ***** * .byte %11110011 ; 0B2B 2-65: **** ** .byte %11001111 ; 0B2C 2-65: ** **** .byte %10011111 ; 0B2D 2-65: * ***** .byte %10000001 ; 0B2E 2-65: * * .byte %11111111 ; 0B2F 2-65: ******** .byte %11000011 ; 0B30 2-66: ** ** .byte %10011001 ; 0B31 2-66: * ** * .byte %11111001 ; 0B32 2-66: ***** * .byte %11100011 ; 0B33 2-66: *** ** .byte %11111001 ; 0B34 2-66: ***** * .byte %10011001 ; 0B35 2-66: * ** * .byte %11000011 ; 0B36 2-66: ** ** .byte %11111111 ; 0B37 2-66: ******** .byte %11000011 ; 0B38 2-67: ** ** .byte %10011001 ; 0B39 2-67: * ** * .byte %11111001 ; 0B3A 2-67: ***** * .byte %11100011 ; 0B3B 2-67: *** ** .byte %11111001 ; 0B3C 2-67: ***** * .byte %10011001 ; 0B3D 2-67: * ** * .byte %11000011 ; 0B3E 2-67: ** ** .byte %11111111 ; 0B3F 2-67: ******** .byte %11111001 ; 0B40 2-68: ***** * .byte %11110001 ; 0B41 2-68: **** * .byte %11100001 ; 0B42 2-68: *** * .byte %10011001 ; 0B43 2-68: * ** * .byte %10000000 ; 0B44 2-68: * .byte %11111001 ; 0B45 2-68: ***** * .byte %11111001 ; 0B46 2-68: ***** * .byte %11111111 ; 0B47 2-68: ******** .byte %11111001 ; 0B48 2-69: ***** * .byte %11110001 ; 0B49 2-69: **** * .byte %11100001 ; 0B4A 2-69: *** * .byte %10011001 ; 0B4B 2-69: * ** * .byte %10000000 ; 0B4C 2-69: * .byte %11111001 ; 0B4D 2-69: ***** * .byte %11111001 ; 0B4E 2-69: ***** * .byte %11111111 ; 0B4F 2-69: ******** .byte %10000001 ; 0B50 2-6a: * * .byte %10011111 ; 0B51 2-6a: * ***** .byte %10000011 ; 0B52 2-6a: * ** .byte %11111001 ; 0B53 2-6a: ***** * .byte %11111001 ; 0B54 2-6a: ***** * .byte %10011001 ; 0B55 2-6a: * ** * .byte %11000011 ; 0B56 2-6a: ** ** .byte %11111111 ; 0B57 2-6a: ******** .byte %10000001 ; 0B58 2-6b: * * .byte %10011111 ; 0B59 2-6b: * ***** .byte %10000011 ; 0B5A 2-6b: * ** .byte %11111001 ; 0B5B 2-6b: ***** * .byte %11111001 ; 0B5C 2-6b: ***** * .byte %10011001 ; 0B5D 2-6b: * ** * .byte %11000011 ; 0B5E 2-6b: ** ** .byte %11111111 ; 0B5F 2-6b: ******** .byte %11000011 ; 0B60 2-6c: ** ** .byte %10011001 ; 0B61 2-6c: * ** * .byte %10011111 ; 0B62 2-6c: * ***** .byte %10000011 ; 0B63 2-6c: * ** .byte %10011001 ; 0B64 2-6c: * ** * .byte %10011001 ; 0B65 2-6c: * ** * .byte %11000011 ; 0B66 2-6c: ** ** .byte %11111111 ; 0B67 2-6c: ******** .byte %11000011 ; 0B68 2-6d: ** ** .byte %10011001 ; 0B69 2-6d: * ** * .byte %10011111 ; 0B6A 2-6d: * ***** .byte %10000011 ; 0B6B 2-6d: * ** .byte %10011001 ; 0B6C 2-6d: * ** * .byte %10011001 ; 0B6D 2-6d: * ** * .byte %11000011 ; 0B6E 2-6d: ** ** .byte %11111111 ; 0B6F 2-6d: ******** .byte %10000001 ; 0B70 2-6e: * * .byte %10011001 ; 0B71 2-6e: * ** * .byte %11110011 ; 0B72 2-6e: **** ** .byte %11100111 ; 0B73 2-6e: *** *** .byte %11100111 ; 0B74 2-6e: *** *** .byte %11100111 ; 0B75 2-6e: *** *** .byte %11100111 ; 0B76 2-6e: *** *** .byte %11111111 ; 0B77 2-6e: ******** .byte %10000001 ; 0B78 2-6f: * * .byte %10011001 ; 0B79 2-6f: * ** * .byte %11110011 ; 0B7A 2-6f: **** ** .byte %11100111 ; 0B7B 2-6f: *** *** .byte %11100111 ; 0B7C 2-6f: *** *** .byte %11100111 ; 0B7D 2-6f: *** *** .byte %11100111 ; 0B7E 2-6f: *** *** .byte %11111111 ; 0B7F 2-6f: ******** .byte %11000011 ; 0B80 2-70: ** ** .byte %10011001 ; 0B81 2-70: * ** * .byte %10011001 ; 0B82 2-70: * ** * .byte %11000011 ; 0B83 2-70: ** ** .byte %10011001 ; 0B84 2-70: * ** * .byte %10011001 ; 0B85 2-70: * ** * .byte %11000011 ; 0B86 2-70: ** ** .byte %11111111 ; 0B87 2-70: ******** .byte %11000011 ; 0B88 2-71: ** ** .byte %10011001 ; 0B89 2-71: * ** * .byte %10011001 ; 0B8A 2-71: * ** * .byte %11000011 ; 0B8B 2-71: ** ** .byte %10011001 ; 0B8C 2-71: * ** * .byte %10011001 ; 0B8D 2-71: * ** * .byte %11000011 ; 0B8E 2-71: ** ** .byte %11111111 ; 0B8F 2-71: ******** .byte %11000011 ; 0B90 2-72: ** ** .byte %10011001 ; 0B91 2-72: * ** * .byte %10011001 ; 0B92 2-72: * ** * .byte %11000001 ; 0B93 2-72: ** * .byte %11111001 ; 0B94 2-72: ***** * .byte %10011001 ; 0B95 2-72: * ** * .byte %11000011 ; 0B96 2-72: ** ** .byte %11111111 ; 0B97 2-72: ******** .byte %11000011 ; 0B98 2-73: ** ** .byte %10011001 ; 0B99 2-73: * ** * .byte %10011001 ; 0B9A 2-73: * ** * .byte %11000001 ; 0B9B 2-73: ** * .byte %11111001 ; 0B9C 2-73: ***** * .byte %10011001 ; 0B9D 2-73: * ** * .byte %11000011 ; 0B9E 2-73: ** ** .byte %11111111 ; 0B9F 2-73: ******** .byte %11111111 ; 0BA0 2-74: ******** .byte %11111111 ; 0BA1 2-74: ******** .byte %11100111 ; 0BA2 2-74: *** *** .byte %11111111 ; 0BA3 2-74: ******** .byte %11111111 ; 0BA4 2-74: ******** .byte %11100111 ; 0BA5 2-74: *** *** .byte %11111111 ; 0BA6 2-74: ******** .byte %11111111 ; 0BA7 2-74: ******** .byte %11111111 ; 0BA8 2-75: ******** .byte %11111111 ; 0BA9 2-75: ******** .byte %11100111 ; 0BAA 2-75: *** *** .byte %11111111 ; 0BAB 2-75: ******** .byte %11111111 ; 0BAC 2-75: ******** .byte %11100111 ; 0BAD 2-75: *** *** .byte %11111111 ; 0BAE 2-75: ******** .byte %11111111 ; 0BAF 2-75: ******** .byte %11111111 ; 0BB0 2-76: ******** .byte %11111111 ; 0BB1 2-76: ******** .byte %11100111 ; 0BB2 2-76: *** *** .byte %11111111 ; 0BB3 2-76: ******** .byte %11111111 ; 0BB4 2-76: ******** .byte %11100111 ; 0BB5 2-76: *** *** .byte %11100111 ; 0BB6 2-76: *** *** .byte %11001111 ; 0BB7 2-76: ** **** .byte %11111111 ; 0BB8 2-77: ******** .byte %11111111 ; 0BB9 2-77: ******** .byte %11100111 ; 0BBA 2-77: *** *** .byte %11111111 ; 0BBB 2-77: ******** .byte %11111111 ; 0BBC 2-77: ******** .byte %11100111 ; 0BBD 2-77: *** *** .byte %11100111 ; 0BBE 2-77: *** *** .byte %11001111 ; 0BBF 2-77: ** **** .byte %11110001 ; 0BC0 2-78: **** * .byte %11100111 ; 0BC1 2-78: *** *** .byte %11001111 ; 0BC2 2-78: ** **** .byte %10011111 ; 0BC3 2-78: * ***** .byte %11001111 ; 0BC4 2-78: ** **** .byte %11100111 ; 0BC5 2-78: *** *** .byte %11110001 ; 0BC6 2-78: **** * .byte %11111111 ; 0BC7 2-78: ******** .byte %11110001 ; 0BC8 2-79: **** * .byte %11100111 ; 0BC9 2-79: *** *** .byte %11001111 ; 0BCA 2-79: ** **** .byte %10011111 ; 0BCB 2-79: * ***** .byte %11001111 ; 0BCC 2-79: ** **** .byte %11100111 ; 0BCD 2-79: *** *** .byte %11110001 ; 0BCE 2-79: **** * .byte %11111111 ; 0BCF 2-79: ******** .byte %11111111 ; 0BD0 2-7a: ******** .byte %11111111 ; 0BD1 2-7a: ******** .byte %10000001 ; 0BD2 2-7a: * * .byte %11111111 ; 0BD3 2-7a: ******** .byte %10000001 ; 0BD4 2-7a: * * .byte %11111111 ; 0BD5 2-7a: ******** .byte %11111111 ; 0BD6 2-7a: ******** .byte %11111111 ; 0BD7 2-7a: ******** .byte %11111111 ; 0BD8 2-7b: ******** .byte %11111111 ; 0BD9 2-7b: ******** .byte %10000001 ; 0BDA 2-7b: * * .byte %11111111 ; 0BDB 2-7b: ******** .byte %10000001 ; 0BDC 2-7b: * * .byte %11111111 ; 0BDD 2-7b: ******** .byte %11111111 ; 0BDE 2-7b: ******** .byte %11111111 ; 0BDF 2-7b: ******** .byte %10001111 ; 0BE0 2-7c: * **** .byte %11100111 ; 0BE1 2-7c: *** *** .byte %11110011 ; 0BE2 2-7c: **** ** .byte %11111001 ; 0BE3 2-7c: ***** * .byte %11110011 ; 0BE4 2-7c: **** ** .byte %11100111 ; 0BE5 2-7c: *** *** .byte %10001111 ; 0BE6 2-7c: * **** .byte %11111111 ; 0BE7 2-7c: ******** .byte %10001111 ; 0BE8 2-7d: * **** .byte %11100111 ; 0BE9 2-7d: *** *** .byte %11110011 ; 0BEA 2-7d: **** ** .byte %11111001 ; 0BEB 2-7d: ***** * .byte %11110011 ; 0BEC 2-7d: **** ** .byte %11100111 ; 0BED 2-7d: *** *** .byte %10001111 ; 0BEE 2-7d: * **** .byte %11111111 ; 0BEF 2-7d: ******** .byte %11000011 ; 0BF0 2-7e: ** ** .byte %10011001 ; 0BF1 2-7e: * ** * .byte %11111001 ; 0BF2 2-7e: ***** * .byte %11110011 ; 0BF3 2-7e: **** ** .byte %11100111 ; 0BF4 2-7e: *** *** .byte %11111111 ; 0BF5 2-7e: ******** .byte %11100111 ; 0BF6 2-7e: *** *** .byte %11111111 ; 0BF7 2-7e: ******** .byte %11000011 ; 0BF8 2-7f: ** ** .byte %10011001 ; 0BF9 2-7f: * ** * .byte %11111001 ; 0BFA 2-7f: ***** * .byte %11110011 ; 0BFB 2-7f: **** ** .byte %11100111 ; 0BFC 2-7f: *** *** .byte %11111111 ; 0BFD 2-7f: ******** .byte %11100111 ; 0BFE 2-7f: *** *** .byte %11111111 ; 0BFF 2-7f: ******** .byte %11000011 ; 0C00 2-80: ** ** .byte %10011001 ; 0C01 2-80: * ** * .byte %10010001 ; 0C02 2-80: * * * .byte %10010001 ; 0C03 2-80: * * * .byte %10011111 ; 0C04 2-80: * ***** .byte %10011101 ; 0C05 2-80: * *** * .byte %11000011 ; 0C06 2-80: ** ** .byte %11111111 ; 0C07 2-80: ******** .byte %11000011 ; 0C08 2-81: ** ** .byte %10011001 ; 0C09 2-81: * ** * .byte %10010001 ; 0C0A 2-81: * * * .byte %10010001 ; 0C0B 2-81: * * * .byte %10011111 ; 0C0C 2-81: * ***** .byte %10011101 ; 0C0D 2-81: * *** * .byte %11000011 ; 0C0E 2-81: ** ** .byte %11111111 ; 0C0F 2-81: ******** .byte %11100111 ; 0C10 2-82: *** *** .byte %11000011 ; 0C11 2-82: ** ** .byte %10011001 ; 0C12 2-82: * ** * .byte %10000001 ; 0C13 2-82: * * .byte %10011001 ; 0C14 2-82: * ** * .byte %10011001 ; 0C15 2-82: * ** * .byte %10011001 ; 0C16 2-82: * ** * .byte %11111111 ; 0C17 2-82: ******** .byte %11100111 ; 0C18 2-83: *** *** .byte %11000011 ; 0C19 2-83: ** ** .byte %10011001 ; 0C1A 2-83: * ** * .byte %10000001 ; 0C1B 2-83: * * .byte %10011001 ; 0C1C 2-83: * ** * .byte %10011001 ; 0C1D 2-83: * ** * .byte %10011001 ; 0C1E 2-83: * ** * .byte %11111111 ; 0C1F 2-83: ******** .byte %10000011 ; 0C20 2-84: * ** .byte %10011001 ; 0C21 2-84: * ** * .byte %10011001 ; 0C22 2-84: * ** * .byte %10000011 ; 0C23 2-84: * ** .byte %10011001 ; 0C24 2-84: * ** * .byte %10011001 ; 0C25 2-84: * ** * .byte %10000011 ; 0C26 2-84: * ** .byte %11111111 ; 0C27 2-84: ******** .byte %10000011 ; 0C28 2-85: * ** .byte %10011001 ; 0C29 2-85: * ** * .byte %10011001 ; 0C2A 2-85: * ** * .byte %10000011 ; 0C2B 2-85: * ** .byte %10011001 ; 0C2C 2-85: * ** * .byte %10011001 ; 0C2D 2-85: * ** * .byte %10000011 ; 0C2E 2-85: * ** .byte %11111111 ; 0C2F 2-85: ******** .byte %11000011 ; 0C30 2-86: ** ** .byte %10011001 ; 0C31 2-86: * ** * .byte %10011111 ; 0C32 2-86: * ***** .byte %10011111 ; 0C33 2-86: * ***** .byte %10011111 ; 0C34 2-86: * ***** .byte %10011001 ; 0C35 2-86: * ** * .byte %11000011 ; 0C36 2-86: ** ** .byte %11111111 ; 0C37 2-86: ******** .byte %11000011 ; 0C38 2-87: ** ** .byte %10011001 ; 0C39 2-87: * ** * .byte %10011111 ; 0C3A 2-87: * ***** .byte %10011111 ; 0C3B 2-87: * ***** .byte %10011111 ; 0C3C 2-87: * ***** .byte %10011001 ; 0C3D 2-87: * ** * .byte %11000011 ; 0C3E 2-87: ** ** .byte %11111111 ; 0C3F 2-87: ******** .byte %10000111 ; 0C40 2-88: * *** .byte %10010011 ; 0C41 2-88: * * ** .byte %10011001 ; 0C42 2-88: * ** * .byte %10011001 ; 0C43 2-88: * ** * .byte %10011001 ; 0C44 2-88: * ** * .byte %10010011 ; 0C45 2-88: * * ** .byte %10000111 ; 0C46 2-88: * *** .byte %11111111 ; 0C47 2-88: ******** .byte %10000111 ; 0C48 2-89: * *** .byte %10010011 ; 0C49 2-89: * * ** .byte %10011001 ; 0C4A 2-89: * ** * .byte %10011001 ; 0C4B 2-89: * ** * .byte %10011001 ; 0C4C 2-89: * ** * .byte %10010011 ; 0C4D 2-89: * * ** .byte %10000111 ; 0C4E 2-89: * *** .byte %11111111 ; 0C4F 2-89: ******** .byte %10000001 ; 0C50 2-8a: * * .byte %10011111 ; 0C51 2-8a: * ***** .byte %10011111 ; 0C52 2-8a: * ***** .byte %10000111 ; 0C53 2-8a: * *** .byte %10011111 ; 0C54 2-8a: * ***** .byte %10011111 ; 0C55 2-8a: * ***** .byte %10000001 ; 0C56 2-8a: * * .byte %11111111 ; 0C57 2-8a: ******** .byte %10000001 ; 0C58 2-8b: * * .byte %10011111 ; 0C59 2-8b: * ***** .byte %10011111 ; 0C5A 2-8b: * ***** .byte %10000111 ; 0C5B 2-8b: * *** .byte %10011111 ; 0C5C 2-8b: * ***** .byte %10011111 ; 0C5D 2-8b: * ***** .byte %10000001 ; 0C5E 2-8b: * * .byte %11111111 ; 0C5F 2-8b: ******** .byte %10000001 ; 0C60 2-8c: * * .byte %10011111 ; 0C61 2-8c: * ***** .byte %10011111 ; 0C62 2-8c: * ***** .byte %10000111 ; 0C63 2-8c: * *** .byte %10011111 ; 0C64 2-8c: * ***** .byte %10011111 ; 0C65 2-8c: * ***** .byte %10011111 ; 0C66 2-8c: * ***** .byte %11111111 ; 0C67 2-8c: ******** .byte %10000001 ; 0C68 2-8d: * * .byte %10011111 ; 0C69 2-8d: * ***** .byte %10011111 ; 0C6A 2-8d: * ***** .byte %10000111 ; 0C6B 2-8d: * *** .byte %10011111 ; 0C6C 2-8d: * ***** .byte %10011111 ; 0C6D 2-8d: * ***** .byte %10011111 ; 0C6E 2-8d: * ***** .byte %11111111 ; 0C6F 2-8d: ******** .byte %11000011 ; 0C70 2-8e: ** ** .byte %10011001 ; 0C71 2-8e: * ** * .byte %10011111 ; 0C72 2-8e: * ***** .byte %10010001 ; 0C73 2-8e: * * * .byte %10011001 ; 0C74 2-8e: * ** * .byte %10011001 ; 0C75 2-8e: * ** * .byte %11000011 ; 0C76 2-8e: ** ** .byte %11111111 ; 0C77 2-8e: ******** .byte %11000011 ; 0C78 2-8f: ** ** .byte %10011001 ; 0C79 2-8f: * ** * .byte %10011111 ; 0C7A 2-8f: * ***** .byte %10010001 ; 0C7B 2-8f: * * * .byte %10011001 ; 0C7C 2-8f: * ** * .byte %10011001 ; 0C7D 2-8f: * ** * .byte %11000011 ; 0C7E 2-8f: ** ** .byte %11111111 ; 0C7F 2-8f: ******** .byte %10011001 ; 0C80 2-90: * ** * .byte %10011001 ; 0C81 2-90: * ** * .byte %10011001 ; 0C82 2-90: * ** * .byte %10000001 ; 0C83 2-90: * * .byte %10011001 ; 0C84 2-90: * ** * .byte %10011001 ; 0C85 2-90: * ** * .byte %10011001 ; 0C86 2-90: * ** * .byte %11111111 ; 0C87 2-90: ******** .byte %10011001 ; 0C88 2-91: * ** * .byte %10011001 ; 0C89 2-91: * ** * .byte %10011001 ; 0C8A 2-91: * ** * .byte %10000001 ; 0C8B 2-91: * * .byte %10011001 ; 0C8C 2-91: * ** * .byte %10011001 ; 0C8D 2-91: * ** * .byte %10011001 ; 0C8E 2-91: * ** * .byte %11111111 ; 0C8F 2-91: ******** .byte %11000011 ; 0C90 2-92: ** ** .byte %11100111 ; 0C91 2-92: *** *** .byte %11100111 ; 0C92 2-92: *** *** .byte %11100111 ; 0C93 2-92: *** *** .byte %11100111 ; 0C94 2-92: *** *** .byte %11100111 ; 0C95 2-92: *** *** .byte %11000011 ; 0C96 2-92: ** ** .byte %11111111 ; 0C97 2-92: ******** .byte %11000011 ; 0C98 2-93: ** ** .byte %11100111 ; 0C99 2-93: *** *** .byte %11100111 ; 0C9A 2-93: *** *** .byte %11100111 ; 0C9B 2-93: *** *** .byte %11100111 ; 0C9C 2-93: *** *** .byte %11100111 ; 0C9D 2-93: *** *** .byte %11000011 ; 0C9E 2-93: ** ** .byte %11111111 ; 0C9F 2-93: ******** .byte %11100001 ; 0CA0 2-94: *** * .byte %11110011 ; 0CA1 2-94: **** ** .byte %11110011 ; 0CA2 2-94: **** ** .byte %11110011 ; 0CA3 2-94: **** ** .byte %11110011 ; 0CA4 2-94: **** ** .byte %10010011 ; 0CA5 2-94: * * ** .byte %11000111 ; 0CA6 2-94: ** *** .byte %11111111 ; 0CA7 2-94: ******** .byte %11100001 ; 0CA8 2-95: *** * .byte %11110011 ; 0CA9 2-95: **** ** .byte %11110011 ; 0CAA 2-95: **** ** .byte %11110011 ; 0CAB 2-95: **** ** .byte %11110011 ; 0CAC 2-95: **** ** .byte %10010011 ; 0CAD 2-95: * * ** .byte %11000111 ; 0CAE 2-95: ** *** .byte %11111111 ; 0CAF 2-95: ******** .byte %10011001 ; 0CB0 2-96: * ** * .byte %10010011 ; 0CB1 2-96: * * ** .byte %10000111 ; 0CB2 2-96: * *** .byte %10001111 ; 0CB3 2-96: * **** .byte %10000111 ; 0CB4 2-96: * *** .byte %10010011 ; 0CB5 2-96: * * ** .byte %10011001 ; 0CB6 2-96: * ** * .byte %11111111 ; 0CB7 2-96: ******** .byte %10011001 ; 0CB8 2-97: * ** * .byte %10010011 ; 0CB9 2-97: * * ** .byte %10000111 ; 0CBA 2-97: * *** .byte %10001111 ; 0CBB 2-97: * **** .byte %10000111 ; 0CBC 2-97: * *** .byte %10010011 ; 0CBD 2-97: * * ** .byte %10011001 ; 0CBE 2-97: * ** * .byte %11111111 ; 0CBF 2-97: ******** .byte %10011111 ; 0CC0 2-98: * ***** .byte %10011111 ; 0CC1 2-98: * ***** .byte %10011111 ; 0CC2 2-98: * ***** .byte %10011111 ; 0CC3 2-98: * ***** .byte %10011111 ; 0CC4 2-98: * ***** .byte %10011111 ; 0CC5 2-98: * ***** .byte %10000001 ; 0CC6 2-98: * * .byte %11111111 ; 0CC7 2-98: ******** .byte %10011111 ; 0CC8 2-99: * ***** .byte %10011111 ; 0CC9 2-99: * ***** .byte %10011111 ; 0CCA 2-99: * ***** .byte %10011111 ; 0CCB 2-99: * ***** .byte %10011111 ; 0CCC 2-99: * ***** .byte %10011111 ; 0CCD 2-99: * ***** .byte %10000001 ; 0CCE 2-99: * * .byte %11111111 ; 0CCF 2-99: ******** .byte %10011100 ; 0CD0 2-9a: * *** .byte %10001000 ; 0CD1 2-9a: * * .byte %10000000 ; 0CD2 2-9a: * .byte %10010100 ; 0CD3 2-9a: * * * .byte %10011100 ; 0CD4 2-9a: * *** .byte %10011100 ; 0CD5 2-9a: * *** .byte %10011100 ; 0CD6 2-9a: * *** .byte %11111111 ; 0CD7 2-9a: ******** .byte %10011100 ; 0CD8 2-9b: * *** .byte %10001000 ; 0CD9 2-9b: * * .byte %10000000 ; 0CDA 2-9b: * .byte %10010100 ; 0CDB 2-9b: * * * .byte %10011100 ; 0CDC 2-9b: * *** .byte %10011100 ; 0CDD 2-9b: * *** .byte %10011100 ; 0CDE 2-9b: * *** .byte %11111111 ; 0CDF 2-9b: ******** .byte %10011001 ; 0CE0 2-9c: * ** * .byte %10001001 ; 0CE1 2-9c: * * * .byte %10000001 ; 0CE2 2-9c: * * .byte %10000001 ; 0CE3 2-9c: * * .byte %10010001 ; 0CE4 2-9c: * * * .byte %10011001 ; 0CE5 2-9c: * ** * .byte %10011001 ; 0CE6 2-9c: * ** * .byte %11111111 ; 0CE7 2-9c: ******** .byte %10011001 ; 0CE8 2-9d: * ** * .byte %10001001 ; 0CE9 2-9d: * * * .byte %10000001 ; 0CEA 2-9d: * * .byte %10000001 ; 0CEB 2-9d: * * .byte %10010001 ; 0CEC 2-9d: * * * .byte %10011001 ; 0CED 2-9d: * ** * .byte %10011001 ; 0CEE 2-9d: * ** * .byte %11111111 ; 0CEF 2-9d: ******** .byte %11000011 ; 0CF0 2-9e: ** ** .byte %10011001 ; 0CF1 2-9e: * ** * .byte %10011001 ; 0CF2 2-9e: * ** * .byte %10011001 ; 0CF3 2-9e: * ** * .byte %10011001 ; 0CF4 2-9e: * ** * .byte %10011001 ; 0CF5 2-9e: * ** * .byte %11000011 ; 0CF6 2-9e: ** ** .byte %11111111 ; 0CF7 2-9e: ******** .byte %11000011 ; 0CF8 2-9f: ** ** .byte %10011001 ; 0CF9 2-9f: * ** * .byte %10011001 ; 0CFA 2-9f: * ** * .byte %10011001 ; 0CFB 2-9f: * ** * .byte %10011001 ; 0CFC 2-9f: * ** * .byte %10011001 ; 0CFD 2-9f: * ** * .byte %11000011 ; 0CFE 2-9f: ** ** .byte %11111111 ; 0CFF 2-9f: ******** .byte %10000011 ; 0D00 2-a0: * ** .byte %10011001 ; 0D01 2-a0: * ** * .byte %10011001 ; 0D02 2-a0: * ** * .byte %10000011 ; 0D03 2-a0: * ** .byte %10011111 ; 0D04 2-a0: * ***** .byte %10011111 ; 0D05 2-a0: * ***** .byte %10011111 ; 0D06 2-a0: * ***** .byte %11111111 ; 0D07 2-a0: ******** .byte %10000011 ; 0D08 2-a1: * ** .byte %10011001 ; 0D09 2-a1: * ** * .byte %10011001 ; 0D0A 2-a1: * ** * .byte %10000011 ; 0D0B 2-a1: * ** .byte %10011111 ; 0D0C 2-a1: * ***** .byte %10011111 ; 0D0D 2-a1: * ***** .byte %10011111 ; 0D0E 2-a1: * ***** .byte %11111111 ; 0D0F 2-a1: ******** .byte %11000011 ; 0D10 2-a2: ** ** .byte %10011001 ; 0D11 2-a2: * ** * .byte %10011001 ; 0D12 2-a2: * ** * .byte %10011001 ; 0D13 2-a2: * ** * .byte %10011001 ; 0D14 2-a2: * ** * .byte %11000011 ; 0D15 2-a2: ** ** .byte %11110001 ; 0D16 2-a2: **** * .byte %11111111 ; 0D17 2-a2: ******** .byte %11000011 ; 0D18 2-a3: ** ** .byte %10011001 ; 0D19 2-a3: * ** * .byte %10011001 ; 0D1A 2-a3: * ** * .byte %10011001 ; 0D1B 2-a3: * ** * .byte %10011001 ; 0D1C 2-a3: * ** * .byte %11000011 ; 0D1D 2-a3: ** ** .byte %11110001 ; 0D1E 2-a3: **** * .byte %11111111 ; 0D1F 2-a3: ******** .byte %10000011 ; 0D20 2-a4: * ** .byte %10011001 ; 0D21 2-a4: * ** * .byte %10011001 ; 0D22 2-a4: * ** * .byte %10000011 ; 0D23 2-a4: * ** .byte %10000111 ; 0D24 2-a4: * *** .byte %10010011 ; 0D25 2-a4: * * ** .byte %10011001 ; 0D26 2-a4: * ** * .byte %11111111 ; 0D27 2-a4: ******** .byte %10000011 ; 0D28 2-a5: * ** .byte %10011001 ; 0D29 2-a5: * ** * .byte %10011001 ; 0D2A 2-a5: * ** * .byte %10000011 ; 0D2B 2-a5: * ** .byte %10000111 ; 0D2C 2-a5: * *** .byte %10010011 ; 0D2D 2-a5: * * ** .byte %10011001 ; 0D2E 2-a5: * ** * .byte %11111111 ; 0D2F 2-a5: ******** .byte %11000011 ; 0D30 2-a6: ** ** .byte %10011001 ; 0D31 2-a6: * ** * .byte %10011111 ; 0D32 2-a6: * ***** .byte %11000011 ; 0D33 2-a6: ** ** .byte %11111001 ; 0D34 2-a6: ***** * .byte %10011001 ; 0D35 2-a6: * ** * .byte %11000011 ; 0D36 2-a6: ** ** .byte %11111111 ; 0D37 2-a6: ******** .byte %11000011 ; 0D38 2-a7: ** ** .byte %10011001 ; 0D39 2-a7: * ** * .byte %10011111 ; 0D3A 2-a7: * ***** .byte %11000011 ; 0D3B 2-a7: ** ** .byte %11111001 ; 0D3C 2-a7: ***** * .byte %10011001 ; 0D3D 2-a7: * ** * .byte %11000011 ; 0D3E 2-a7: ** ** .byte %11111111 ; 0D3F 2-a7: ******** .byte %10000001 ; 0D40 2-a8: * * .byte %11100111 ; 0D41 2-a8: *** *** .byte %11100111 ; 0D42 2-a8: *** *** .byte %11100111 ; 0D43 2-a8: *** *** .byte %11100111 ; 0D44 2-a8: *** *** .byte %11100111 ; 0D45 2-a8: *** *** .byte %11100111 ; 0D46 2-a8: *** *** .byte %11111111 ; 0D47 2-a8: ******** .byte %10000001 ; 0D48 2-a9: * * .byte %11100111 ; 0D49 2-a9: *** *** .byte %11100111 ; 0D4A 2-a9: *** *** .byte %11100111 ; 0D4B 2-a9: *** *** .byte %11100111 ; 0D4C 2-a9: *** *** .byte %11100111 ; 0D4D 2-a9: *** *** .byte %11100111 ; 0D4E 2-a9: *** *** .byte %11111111 ; 0D4F 2-a9: ******** .byte %10011001 ; 0D50 2-aa: * ** * .byte %10011001 ; 0D51 2-aa: * ** * .byte %10011001 ; 0D52 2-aa: * ** * .byte %10011001 ; 0D53 2-aa: * ** * .byte %10011001 ; 0D54 2-aa: * ** * .byte %10011001 ; 0D55 2-aa: * ** * .byte %11000011 ; 0D56 2-aa: ** ** .byte %11111111 ; 0D57 2-aa: ******** .byte %10011001 ; 0D58 2-ab: * ** * .byte %10011001 ; 0D59 2-ab: * ** * .byte %10011001 ; 0D5A 2-ab: * ** * .byte %10011001 ; 0D5B 2-ab: * ** * .byte %10011001 ; 0D5C 2-ab: * ** * .byte %10011001 ; 0D5D 2-ab: * ** * .byte %11000011 ; 0D5E 2-ab: ** ** .byte %11111111 ; 0D5F 2-ab: ******** .byte %10011001 ; 0D60 2-ac: * ** * .byte %10011001 ; 0D61 2-ac: * ** * .byte %10011001 ; 0D62 2-ac: * ** * .byte %10011001 ; 0D63 2-ac: * ** * .byte %10011001 ; 0D64 2-ac: * ** * .byte %11000011 ; 0D65 2-ac: ** ** .byte %11100111 ; 0D66 2-ac: *** *** .byte %11111111 ; 0D67 2-ac: ******** .byte %10011001 ; 0D68 2-ad: * ** * .byte %10011001 ; 0D69 2-ad: * ** * .byte %10011001 ; 0D6A 2-ad: * ** * .byte %10011001 ; 0D6B 2-ad: * ** * .byte %10011001 ; 0D6C 2-ad: * ** * .byte %11000011 ; 0D6D 2-ad: ** ** .byte %11100111 ; 0D6E 2-ad: *** *** .byte %11111111 ; 0D6F 2-ad: ******** .byte %10011100 ; 0D70 2-ae: * *** .byte %10011100 ; 0D71 2-ae: * *** .byte %10011100 ; 0D72 2-ae: * *** .byte %10010100 ; 0D73 2-ae: * * * .byte %10000000 ; 0D74 2-ae: * .byte %10001000 ; 0D75 2-ae: * * .byte %10011100 ; 0D76 2-ae: * *** .byte %11111111 ; 0D77 2-ae: ******** .byte %10011100 ; 0D78 2-af: * *** .byte %10011100 ; 0D79 2-af: * *** .byte %10011100 ; 0D7A 2-af: * *** .byte %10010100 ; 0D7B 2-af: * * * .byte %10000000 ; 0D7C 2-af: * .byte %10001000 ; 0D7D 2-af: * * .byte %10011100 ; 0D7E 2-af: * *** .byte %11111111 ; 0D7F 2-af: ******** .byte %10011001 ; 0D80 2-b0: * ** * .byte %10011001 ; 0D81 2-b0: * ** * .byte %11000011 ; 0D82 2-b0: ** ** .byte %11100111 ; 0D83 2-b0: *** *** .byte %11000011 ; 0D84 2-b0: ** ** .byte %10011001 ; 0D85 2-b0: * ** * .byte %10011001 ; 0D86 2-b0: * ** * .byte %11111111 ; 0D87 2-b0: ******** .byte %10011001 ; 0D88 2-b1: * ** * .byte %10011001 ; 0D89 2-b1: * ** * .byte %11000011 ; 0D8A 2-b1: ** ** .byte %11100111 ; 0D8B 2-b1: *** *** .byte %11000011 ; 0D8C 2-b1: ** ** .byte %10011001 ; 0D8D 2-b1: * ** * .byte %10011001 ; 0D8E 2-b1: * ** * .byte %11111111 ; 0D8F 2-b1: ******** .byte %10011001 ; 0D90 2-b2: * ** * .byte %10011001 ; 0D91 2-b2: * ** * .byte %10011001 ; 0D92 2-b2: * ** * .byte %11000011 ; 0D93 2-b2: ** ** .byte %11100111 ; 0D94 2-b2: *** *** .byte %11100111 ; 0D95 2-b2: *** *** .byte %11100111 ; 0D96 2-b2: *** *** .byte %11111111 ; 0D97 2-b2: ******** .byte %10011001 ; 0D98 2-b3: * ** * .byte %10011001 ; 0D99 2-b3: * ** * .byte %10011001 ; 0D9A 2-b3: * ** * .byte %11000011 ; 0D9B 2-b3: ** ** .byte %11100111 ; 0D9C 2-b3: *** *** .byte %11100111 ; 0D9D 2-b3: *** *** .byte %11100111 ; 0D9E 2-b3: *** *** .byte %11111111 ; 0D9F 2-b3: ******** .byte %10000001 ; 0DA0 2-b4: * * .byte %11111001 ; 0DA1 2-b4: ***** * .byte %11110011 ; 0DA2 2-b4: **** ** .byte %11100111 ; 0DA3 2-b4: *** *** .byte %11001111 ; 0DA4 2-b4: ** **** .byte %10011111 ; 0DA5 2-b4: * ***** .byte %10000001 ; 0DA6 2-b4: * * .byte %11111111 ; 0DA7 2-b4: ******** .byte %10000001 ; 0DA8 2-b5: * * .byte %11111001 ; 0DA9 2-b5: ***** * .byte %11110011 ; 0DAA 2-b5: **** ** .byte %11100111 ; 0DAB 2-b5: *** *** .byte %11001111 ; 0DAC 2-b5: ** **** .byte %10011111 ; 0DAD 2-b5: * ***** .byte %10000001 ; 0DAE 2-b5: * * .byte %11111111 ; 0DAF 2-b5: ******** .byte %11000011 ; 0DB0 2-b6: ** ** .byte %11001111 ; 0DB1 2-b6: ** **** .byte %11001111 ; 0DB2 2-b6: ** **** .byte %11001111 ; 0DB3 2-b6: ** **** .byte %11001111 ; 0DB4 2-b6: ** **** .byte %11001111 ; 0DB5 2-b6: ** **** .byte %11000011 ; 0DB6 2-b6: ** ** .byte %11111111 ; 0DB7 2-b6: ******** .byte %11000011 ; 0DB8 2-b7: ** ** .byte %11001111 ; 0DB9 2-b7: ** **** .byte %11001111 ; 0DBA 2-b7: ** **** .byte %11001111 ; 0DBB 2-b7: ** **** .byte %11001111 ; 0DBC 2-b7: ** **** .byte %11001111 ; 0DBD 2-b7: ** **** .byte %11000011 ; 0DBE 2-b7: ** ** .byte %11111111 ; 0DBF 2-b7: ******** .byte %10011111 ; 0DC0 2-b8: * ***** .byte %11001111 ; 0DC1 2-b8: ** **** .byte %11100111 ; 0DC2 2-b8: *** *** .byte %11110011 ; 0DC3 2-b8: **** ** .byte %11111001 ; 0DC4 2-b8: ***** * .byte %11111100 ; 0DC5 2-b8: ****** .byte %11111111 ; 0DC6 2-b8: ******** .byte %11111111 ; 0DC7 2-b8: ******** .byte %10011111 ; 0DC8 2-b9: * ***** .byte %11001111 ; 0DC9 2-b9: ** **** .byte %11100111 ; 0DCA 2-b9: *** *** .byte %11110011 ; 0DCB 2-b9: **** ** .byte %11111001 ; 0DCC 2-b9: ***** * .byte %11111100 ; 0DCD 2-b9: ****** .byte %11111111 ; 0DCE 2-b9: ******** .byte %11111111 ; 0DCF 2-b9: ******** .byte %11000011 ; 0DD0 2-ba: ** ** .byte %11110011 ; 0DD1 2-ba: **** ** .byte %11110011 ; 0DD2 2-ba: **** ** .byte %11110011 ; 0DD3 2-ba: **** ** .byte %11110011 ; 0DD4 2-ba: **** ** .byte %11110011 ; 0DD5 2-ba: **** ** .byte %11000011 ; 0DD6 2-ba: ** ** .byte %11111111 ; 0DD7 2-ba: ******** .byte %11000011 ; 0DD8 2-bb: ** ** .byte %11110011 ; 0DD9 2-bb: **** ** .byte %11110011 ; 0DDA 2-bb: **** ** .byte %11110011 ; 0DDB 2-bb: **** ** .byte %11110011 ; 0DDC 2-bb: **** ** .byte %11110011 ; 0DDD 2-bb: **** ** .byte %11000011 ; 0DDE 2-bb: ** ** .byte %11111111 ; 0DDF 2-bb: ******** .byte %11111111 ; 0DE0 2-bc: ******** .byte %11100111 ; 0DE1 2-bc: *** *** .byte %11000011 ; 0DE2 2-bc: ** ** .byte %10011001 ; 0DE3 2-bc: * ** * .byte %11111111 ; 0DE4 2-bc: ******** .byte %11111111 ; 0DE5 2-bc: ******** .byte %11111111 ; 0DE6 2-bc: ******** .byte %11111111 ; 0DE7 2-bc: ******** .byte %11111111 ; 0DE8 2-bd: ******** .byte %11100111 ; 0DE9 2-bd: *** *** .byte %11000011 ; 0DEA 2-bd: ** ** .byte %10011001 ; 0DEB 2-bd: * ** * .byte %11111111 ; 0DEC 2-bd: ******** .byte %11111111 ; 0DED 2-bd: ******** .byte %11111111 ; 0DEE 2-bd: ******** .byte %11111111 ; 0DEF 2-bd: ******** .byte %11111111 ; 0DF0 2-be: ******** .byte %11111111 ; 0DF1 2-be: ******** .byte %11111111 ; 0DF2 2-be: ******** .byte %11111111 ; 0DF3 2-be: ******** .byte %11111111 ; 0DF4 2-be: ******** .byte %11111111 ; 0DF5 2-be: ******** .byte %10000000 ; 0DF6 2-be: * .byte %11111111 ; 0DF7 2-be: ******** .byte %11111111 ; 0DF8 2-bf: ******** .byte %11111111 ; 0DF9 2-bf: ******** .byte %11111111 ; 0DFA 2-bf: ******** .byte %11111111 ; 0DFB 2-bf: ******** .byte %11111111 ; 0DFC 2-bf: ******** .byte %11111111 ; 0DFD 2-bf: ******** .byte %10000000 ; 0DFE 2-bf: * .byte %11111111 ; 0DFF 2-bf: ******** .byte %11100111 ; 0E00 2-c0: *** *** .byte %11100111 ; 0E01 2-c0: *** *** .byte %11100111 ; 0E02 2-c0: *** *** .byte %11111111 ; 0E03 2-c0: ******** .byte %11111111 ; 0E04 2-c0: ******** .byte %11111111 ; 0E05 2-c0: ******** .byte %11111111 ; 0E06 2-c0: ******** .byte %11111111 ; 0E07 2-c0: ******** .byte %11100111 ; 0E08 2-c1: *** *** .byte %11100111 ; 0E09 2-c1: *** *** .byte %11100111 ; 0E0A 2-c1: *** *** .byte %11111111 ; 0E0B 2-c1: ******** .byte %11111111 ; 0E0C 2-c1: ******** .byte %11111111 ; 0E0D 2-c1: ******** .byte %11111111 ; 0E0E 2-c1: ******** .byte %11111111 ; 0E0F 2-c1: ******** .byte %11111111 ; 0E10 2-c2: ******** .byte %11111111 ; 0E11 2-c2: ******** .byte %11000011 ; 0E12 2-c2: ** ** .byte %11111001 ; 0E13 2-c2: ***** * .byte %11000001 ; 0E14 2-c2: ** * .byte %10011001 ; 0E15 2-c2: * ** * .byte %11000001 ; 0E16 2-c2: ** * .byte %11111111 ; 0E17 2-c2: ******** .byte %11111111 ; 0E18 2-c3: ******** .byte %11111111 ; 0E19 2-c3: ******** .byte %11000011 ; 0E1A 2-c3: ** ** .byte %11111001 ; 0E1B 2-c3: ***** * .byte %11000001 ; 0E1C 2-c3: ** * .byte %10011001 ; 0E1D 2-c3: * ** * .byte %11000001 ; 0E1E 2-c3: ** * .byte %11111111 ; 0E1F 2-c3: ******** .byte %11111111 ; 0E20 2-c4: ******** .byte %10011111 ; 0E21 2-c4: * ***** .byte %10011111 ; 0E22 2-c4: * ***** .byte %10000011 ; 0E23 2-c4: * ** .byte %10011001 ; 0E24 2-c4: * ** * .byte %10011001 ; 0E25 2-c4: * ** * .byte %10000011 ; 0E26 2-c4: * ** .byte %11111111 ; 0E27 2-c4: ******** .byte %11111111 ; 0E28 2-c5: ******** .byte %10011111 ; 0E29 2-c5: * ***** .byte %10011111 ; 0E2A 2-c5: * ***** .byte %10000011 ; 0E2B 2-c5: * ** .byte %10011001 ; 0E2C 2-c5: * ** * .byte %10011001 ; 0E2D 2-c5: * ** * .byte %10000011 ; 0E2E 2-c5: * ** .byte %11111111 ; 0E2F 2-c5: ******** .byte %11111111 ; 0E30 2-c6: ******** .byte %11111111 ; 0E31 2-c6: ******** .byte %11000011 ; 0E32 2-c6: ** ** .byte %10011111 ; 0E33 2-c6: * ***** .byte %10011111 ; 0E34 2-c6: * ***** .byte %10011111 ; 0E35 2-c6: * ***** .byte %11000011 ; 0E36 2-c6: ** ** .byte %11111111 ; 0E37 2-c6: ******** .byte %11111111 ; 0E38 2-c7: ******** .byte %11111111 ; 0E39 2-c7: ******** .byte %11000011 ; 0E3A 2-c7: ** ** .byte %10011111 ; 0E3B 2-c7: * ***** .byte %10011111 ; 0E3C 2-c7: * ***** .byte %10011111 ; 0E3D 2-c7: * ***** .byte %11000011 ; 0E3E 2-c7: ** ** .byte %11111111 ; 0E3F 2-c7: ******** .byte %11111111 ; 0E40 2-c8: ******** .byte %11111001 ; 0E41 2-c8: ***** * .byte %11111001 ; 0E42 2-c8: ***** * .byte %11000001 ; 0E43 2-c8: ** * .byte %10011001 ; 0E44 2-c8: * ** * .byte %10011001 ; 0E45 2-c8: * ** * .byte %11000001 ; 0E46 2-c8: ** * .byte %11111111 ; 0E47 2-c8: ******** .byte %11111111 ; 0E48 2-c9: ******** .byte %11111001 ; 0E49 2-c9: ***** * .byte %11111001 ; 0E4A 2-c9: ***** * .byte %11000001 ; 0E4B 2-c9: ** * .byte %10011001 ; 0E4C 2-c9: * ** * .byte %10011001 ; 0E4D 2-c9: * ** * .byte %11000001 ; 0E4E 2-c9: ** * .byte %11111111 ; 0E4F 2-c9: ******** .byte %11111111 ; 0E50 2-ca: ******** .byte %11111111 ; 0E51 2-ca: ******** .byte %11000011 ; 0E52 2-ca: ** ** .byte %10011001 ; 0E53 2-ca: * ** * .byte %10000001 ; 0E54 2-ca: * * .byte %10011111 ; 0E55 2-ca: * ***** .byte %11000011 ; 0E56 2-ca: ** ** .byte %11111111 ; 0E57 2-ca: ******** .byte %11111111 ; 0E58 2-cb: ******** .byte %11111111 ; 0E59 2-cb: ******** .byte %11000011 ; 0E5A 2-cb: ** ** .byte %10011001 ; 0E5B 2-cb: * ** * .byte %10000001 ; 0E5C 2-cb: * * .byte %10011111 ; 0E5D 2-cb: * ***** .byte %11000011 ; 0E5E 2-cb: ** ** .byte %11111111 ; 0E5F 2-cb: ******** .byte %11111111 ; 0E60 2-cc: ******** .byte %11110001 ; 0E61 2-cc: **** * .byte %11100111 ; 0E62 2-cc: *** *** .byte %11000001 ; 0E63 2-cc: ** * .byte %11100111 ; 0E64 2-cc: *** *** .byte %11100111 ; 0E65 2-cc: *** *** .byte %11100111 ; 0E66 2-cc: *** *** .byte %11111111 ; 0E67 2-cc: ******** .byte %11111111 ; 0E68 2-cd: ******** .byte %11110001 ; 0E69 2-cd: **** * .byte %11100111 ; 0E6A 2-cd: *** *** .byte %11000001 ; 0E6B 2-cd: ** * .byte %11100111 ; 0E6C 2-cd: *** *** .byte %11100111 ; 0E6D 2-cd: *** *** .byte %11100111 ; 0E6E 2-cd: *** *** .byte %11111111 ; 0E6F 2-cd: ******** .byte %11111111 ; 0E70 2-ce: ******** .byte %11111111 ; 0E71 2-ce: ******** .byte %11000001 ; 0E72 2-ce: ** * .byte %10011001 ; 0E73 2-ce: * ** * .byte %10011001 ; 0E74 2-ce: * ** * .byte %11000001 ; 0E75 2-ce: ** * .byte %11111001 ; 0E76 2-ce: ***** * .byte %10000011 ; 0E77 2-ce: * ** .byte %11111111 ; 0E78 2-cf: ******** .byte %11111111 ; 0E79 2-cf: ******** .byte %11000001 ; 0E7A 2-cf: ** * .byte %10011001 ; 0E7B 2-cf: * ** * .byte %10011001 ; 0E7C 2-cf: * ** * .byte %11000001 ; 0E7D 2-cf: ** * .byte %11111001 ; 0E7E 2-cf: ***** * .byte %10000011 ; 0E7F 2-cf: * ** .byte %11111111 ; 0E80 2-d0: ******** .byte %10011111 ; 0E81 2-d0: * ***** .byte %10011111 ; 0E82 2-d0: * ***** .byte %10000011 ; 0E83 2-d0: * ** .byte %10011001 ; 0E84 2-d0: * ** * .byte %10011001 ; 0E85 2-d0: * ** * .byte %10011001 ; 0E86 2-d0: * ** * .byte %11111111 ; 0E87 2-d0: ******** .byte %11111111 ; 0E88 2-d1: ******** .byte %10011111 ; 0E89 2-d1: * ***** .byte %10011111 ; 0E8A 2-d1: * ***** .byte %10000011 ; 0E8B 2-d1: * ** .byte %10011001 ; 0E8C 2-d1: * ** * .byte %10011001 ; 0E8D 2-d1: * ** * .byte %10011001 ; 0E8E 2-d1: * ** * .byte %11111111 ; 0E8F 2-d1: ******** .byte %11111111 ; 0E90 2-d2: ******** .byte %11100111 ; 0E91 2-d2: *** *** .byte %11111111 ; 0E92 2-d2: ******** .byte %11000111 ; 0E93 2-d2: ** *** .byte %11100111 ; 0E94 2-d2: *** *** .byte %11100111 ; 0E95 2-d2: *** *** .byte %11000011 ; 0E96 2-d2: ** ** .byte %11111111 ; 0E97 2-d2: ******** .byte %11111111 ; 0E98 2-d3: ******** .byte %11100111 ; 0E99 2-d3: *** *** .byte %11111111 ; 0E9A 2-d3: ******** .byte %11000111 ; 0E9B 2-d3: ** *** .byte %11100111 ; 0E9C 2-d3: *** *** .byte %11100111 ; 0E9D 2-d3: *** *** .byte %11000011 ; 0E9E 2-d3: ** ** .byte %11111111 ; 0E9F 2-d3: ******** .byte %11111111 ; 0EA0 2-d4: ******** .byte %11111001 ; 0EA1 2-d4: ***** * .byte %11111111 ; 0EA2 2-d4: ******** .byte %11111001 ; 0EA3 2-d4: ***** * .byte %11111001 ; 0EA4 2-d4: ***** * .byte %11111001 ; 0EA5 2-d4: ***** * .byte %11111001 ; 0EA6 2-d4: ***** * .byte %11000011 ; 0EA7 2-d4: ** ** .byte %11111111 ; 0EA8 2-d5: ******** .byte %11111001 ; 0EA9 2-d5: ***** * .byte %11111111 ; 0EAA 2-d5: ******** .byte %11111001 ; 0EAB 2-d5: ***** * .byte %11111001 ; 0EAC 2-d5: ***** * .byte %11111001 ; 0EAD 2-d5: ***** * .byte %11111001 ; 0EAE 2-d5: ***** * .byte %11000011 ; 0EAF 2-d5: ** ** .byte %11111111 ; 0EB0 2-d6: ******** .byte %10011111 ; 0EB1 2-d6: * ***** .byte %10011111 ; 0EB2 2-d6: * ***** .byte %10010011 ; 0EB3 2-d6: * * ** .byte %10000111 ; 0EB4 2-d6: * *** .byte %10010011 ; 0EB5 2-d6: * * ** .byte %10011001 ; 0EB6 2-d6: * ** * .byte %11111111 ; 0EB7 2-d6: ******** .byte %11111111 ; 0EB8 2-d7: ******** .byte %10011111 ; 0EB9 2-d7: * ***** .byte %10011111 ; 0EBA 2-d7: * ***** .byte %10010011 ; 0EBB 2-d7: * * ** .byte %10000111 ; 0EBC 2-d7: * *** .byte %10010011 ; 0EBD 2-d7: * * ** .byte %10011001 ; 0EBE 2-d7: * ** * .byte %11111111 ; 0EBF 2-d7: ******** .byte %11111111 ; 0EC0 2-d8: ******** .byte %11000111 ; 0EC1 2-d8: ** *** .byte %11100111 ; 0EC2 2-d8: *** *** .byte %11100111 ; 0EC3 2-d8: *** *** .byte %11100111 ; 0EC4 2-d8: *** *** .byte %11100111 ; 0EC5 2-d8: *** *** .byte %11000011 ; 0EC6 2-d8: ** ** .byte %11111111 ; 0EC7 2-d8: ******** .byte %11111111 ; 0EC8 2-d9: ******** .byte %11000111 ; 0EC9 2-d9: ** *** .byte %11100111 ; 0ECA 2-d9: *** *** .byte %11100111 ; 0ECB 2-d9: *** *** .byte %11100111 ; 0ECC 2-d9: *** *** .byte %11100111 ; 0ECD 2-d9: *** *** .byte %11000011 ; 0ECE 2-d9: ** ** .byte %11111111 ; 0ECF 2-d9: ******** .byte %11111111 ; 0ED0 2-da: ******** .byte %11111111 ; 0ED1 2-da: ******** .byte %10011001 ; 0ED2 2-da: * ** * .byte %10000000 ; 0ED3 2-da: * .byte %10000000 ; 0ED4 2-da: * .byte %10010100 ; 0ED5 2-da: * * * .byte %10011100 ; 0ED6 2-da: * *** .byte %11111111 ; 0ED7 2-da: ******** .byte %11111111 ; 0ED8 2-db: ******** .byte %11111111 ; 0ED9 2-db: ******** .byte %10011001 ; 0EDA 2-db: * ** * .byte %10000000 ; 0EDB 2-db: * .byte %10000000 ; 0EDC 2-db: * .byte %10010100 ; 0EDD 2-db: * * * .byte %10011100 ; 0EDE 2-db: * *** .byte %11111111 ; 0EDF 2-db: ******** .byte %11111111 ; 0EE0 2-dc: ******** .byte %11111111 ; 0EE1 2-dc: ******** .byte %10000011 ; 0EE2 2-dc: * ** .byte %10011001 ; 0EE3 2-dc: * ** * .byte %10011001 ; 0EE4 2-dc: * ** * .byte %10011001 ; 0EE5 2-dc: * ** * .byte %10011001 ; 0EE6 2-dc: * ** * .byte %11111111 ; 0EE7 2-dc: ******** .byte %11111111 ; 0EE8 2-dd: ******** .byte %11111111 ; 0EE9 2-dd: ******** .byte %10000011 ; 0EEA 2-dd: * ** .byte %10011001 ; 0EEB 2-dd: * ** * .byte %10011001 ; 0EEC 2-dd: * ** * .byte %10011001 ; 0EED 2-dd: * ** * .byte %10011001 ; 0EEE 2-dd: * ** * .byte %11111111 ; 0EEF 2-dd: ******** .byte %11111111 ; 0EF0 2-de: ******** .byte %11111111 ; 0EF1 2-de: ******** .byte %11000011 ; 0EF2 2-de: ** ** .byte %10011001 ; 0EF3 2-de: * ** * .byte %10011001 ; 0EF4 2-de: * ** * .byte %10011001 ; 0EF5 2-de: * ** * .byte %11000011 ; 0EF6 2-de: ** ** .byte %11111111 ; 0EF7 2-de: ******** .byte %11111111 ; 0EF8 2-df: ******** .byte %11111111 ; 0EF9 2-df: ******** .byte %11000011 ; 0EFA 2-df: ** ** .byte %10011001 ; 0EFB 2-df: * ** * .byte %10011001 ; 0EFC 2-df: * ** * .byte %10011001 ; 0EFD 2-df: * ** * .byte %11000011 ; 0EFE 2-df: ** ** .byte %11111111 ; 0EFF 2-df: ******** .byte %11111111 ; 0F00 2-e0: ******** .byte %11111111 ; 0F01 2-e0: ******** .byte %10000011 ; 0F02 2-e0: * ** .byte %10011001 ; 0F03 2-e0: * ** * .byte %10011001 ; 0F04 2-e0: * ** * .byte %10000011 ; 0F05 2-e0: * ** .byte %10011111 ; 0F06 2-e0: * ***** .byte %10011111 ; 0F07 2-e0: * ***** .byte %11111111 ; 0F08 2-e1: ******** .byte %11111111 ; 0F09 2-e1: ******** .byte %10000011 ; 0F0A 2-e1: * ** .byte %10011001 ; 0F0B 2-e1: * ** * .byte %10011001 ; 0F0C 2-e1: * ** * .byte %10000011 ; 0F0D 2-e1: * ** .byte %10011111 ; 0F0E 2-e1: * ***** .byte %10011111 ; 0F0F 2-e1: * ***** .byte %11111111 ; 0F10 2-e2: ******** .byte %11111111 ; 0F11 2-e2: ******** .byte %11000001 ; 0F12 2-e2: ** * .byte %10011001 ; 0F13 2-e2: * ** * .byte %10011001 ; 0F14 2-e2: * ** * .byte %11000001 ; 0F15 2-e2: ** * .byte %11111001 ; 0F16 2-e2: ***** * .byte %11111001 ; 0F17 2-e2: ***** * .byte %11111111 ; 0F18 2-e3: ******** .byte %11111111 ; 0F19 2-e3: ******** .byte %11000001 ; 0F1A 2-e3: ** * .byte %10011001 ; 0F1B 2-e3: * ** * .byte %10011001 ; 0F1C 2-e3: * ** * .byte %11000001 ; 0F1D 2-e3: ** * .byte %11111001 ; 0F1E 2-e3: ***** * .byte %11111001 ; 0F1F 2-e3: ***** * .byte %11111111 ; 0F20 2-e4: ******** .byte %11111111 ; 0F21 2-e4: ******** .byte %10000011 ; 0F22 2-e4: * ** .byte %10011001 ; 0F23 2-e4: * ** * .byte %10011111 ; 0F24 2-e4: * ***** .byte %10011111 ; 0F25 2-e4: * ***** .byte %10011111 ; 0F26 2-e4: * ***** .byte %11111111 ; 0F27 2-e4: ******** .byte %11111111 ; 0F28 2-e5: ******** .byte %11111111 ; 0F29 2-e5: ******** .byte %10000011 ; 0F2A 2-e5: * ** .byte %10011001 ; 0F2B 2-e5: * ** * .byte %10011111 ; 0F2C 2-e5: * ***** .byte %10011111 ; 0F2D 2-e5: * ***** .byte %10011111 ; 0F2E 2-e5: * ***** .byte %11111111 ; 0F2F 2-e5: ******** .byte %11111111 ; 0F30 2-e6: ******** .byte %11111111 ; 0F31 2-e6: ******** .byte %11000001 ; 0F32 2-e6: ** * .byte %10011111 ; 0F33 2-e6: * ***** .byte %11000011 ; 0F34 2-e6: ** ** .byte %11111001 ; 0F35 2-e6: ***** * .byte %10000011 ; 0F36 2-e6: * ** .byte %11111111 ; 0F37 2-e6: ******** .byte %11111111 ; 0F38 2-e7: ******** .byte %11111111 ; 0F39 2-e7: ******** .byte %11000001 ; 0F3A 2-e7: ** * .byte %10011111 ; 0F3B 2-e7: * ***** .byte %11000011 ; 0F3C 2-e7: ** ** .byte %11111001 ; 0F3D 2-e7: ***** * .byte %10000011 ; 0F3E 2-e7: * ** .byte %11111111 ; 0F3F 2-e7: ******** .byte %11111111 ; 0F40 2-e8: ******** .byte %11100111 ; 0F41 2-e8: *** *** .byte %10000001 ; 0F42 2-e8: * * .byte %11100111 ; 0F43 2-e8: *** *** .byte %11100111 ; 0F44 2-e8: *** *** .byte %11100111 ; 0F45 2-e8: *** *** .byte %11110001 ; 0F46 2-e8: **** * .byte %11111111 ; 0F47 2-e8: ******** .byte %11111111 ; 0F48 2-e9: ******** .byte %11100111 ; 0F49 2-e9: *** *** .byte %10000001 ; 0F4A 2-e9: * * .byte %11100111 ; 0F4B 2-e9: *** *** .byte %11100111 ; 0F4C 2-e9: *** *** .byte %11100111 ; 0F4D 2-e9: *** *** .byte %11110001 ; 0F4E 2-e9: **** * .byte %11111111 ; 0F4F 2-e9: ******** .byte %11111111 ; 0F50 2-ea: ******** .byte %11111111 ; 0F51 2-ea: ******** .byte %10011001 ; 0F52 2-ea: * ** * .byte %10011001 ; 0F53 2-ea: * ** * .byte %10011001 ; 0F54 2-ea: * ** * .byte %10011001 ; 0F55 2-ea: * ** * .byte %11000001 ; 0F56 2-ea: ** * .byte %11111111 ; 0F57 2-ea: ******** .byte %11111111 ; 0F58 2-eb: ******** .byte %11111111 ; 0F59 2-eb: ******** .byte %10011001 ; 0F5A 2-eb: * ** * .byte %10011001 ; 0F5B 2-eb: * ** * .byte %10011001 ; 0F5C 2-eb: * ** * .byte %10011001 ; 0F5D 2-eb: * ** * .byte %11000001 ; 0F5E 2-eb: ** * .byte %11111111 ; 0F5F 2-eb: ******** .byte %11111111 ; 0F60 2-ec: ******** .byte %11111111 ; 0F61 2-ec: ******** .byte %10011001 ; 0F62 2-ec: * ** * .byte %10011001 ; 0F63 2-ec: * ** * .byte %10011001 ; 0F64 2-ec: * ** * .byte %11000011 ; 0F65 2-ec: ** ** .byte %11100111 ; 0F66 2-ec: *** *** .byte %11111111 ; 0F67 2-ec: ******** .byte %11111111 ; 0F68 2-ed: ******** .byte %11111111 ; 0F69 2-ed: ******** .byte %10011001 ; 0F6A 2-ed: * ** * .byte %10011001 ; 0F6B 2-ed: * ** * .byte %10011001 ; 0F6C 2-ed: * ** * .byte %11000011 ; 0F6D 2-ed: ** ** .byte %11100111 ; 0F6E 2-ed: *** *** .byte %11111111 ; 0F6F 2-ed: ******** .byte %11111111 ; 0F70 2-ee: ******** .byte %11111111 ; 0F71 2-ee: ******** .byte %10011100 ; 0F72 2-ee: * *** .byte %10010100 ; 0F73 2-ee: * * * .byte %10000000 ; 0F74 2-ee: * .byte %11000001 ; 0F75 2-ee: ** * .byte %11001001 ; 0F76 2-ee: ** * * .byte %11111111 ; 0F77 2-ee: ******** .byte %11111111 ; 0F78 2-ef: ******** .byte %11111111 ; 0F79 2-ef: ******** .byte %10011100 ; 0F7A 2-ef: * *** .byte %10010100 ; 0F7B 2-ef: * * * .byte %10000000 ; 0F7C 2-ef: * .byte %11000001 ; 0F7D 2-ef: ** * .byte %11001001 ; 0F7E 2-ef: ** * * .byte %11111111 ; 0F7F 2-ef: ******** .byte %11111111 ; 0F80 2-f0: ******** .byte %11111111 ; 0F81 2-f0: ******** .byte %10011001 ; 0F82 2-f0: * ** * .byte %11000011 ; 0F83 2-f0: ** ** .byte %11100111 ; 0F84 2-f0: *** *** .byte %11000011 ; 0F85 2-f0: ** ** .byte %10011001 ; 0F86 2-f0: * ** * .byte %11111111 ; 0F87 2-f0: ******** .byte %11111111 ; 0F88 2-f1: ******** .byte %11111111 ; 0F89 2-f1: ******** .byte %10011001 ; 0F8A 2-f1: * ** * .byte %11000011 ; 0F8B 2-f1: ** ** .byte %11100111 ; 0F8C 2-f1: *** *** .byte %11000011 ; 0F8D 2-f1: ** ** .byte %10011001 ; 0F8E 2-f1: * ** * .byte %11111111 ; 0F8F 2-f1: ******** .byte %11111111 ; 0F90 2-f2: ******** .byte %11111111 ; 0F91 2-f2: ******** .byte %10011001 ; 0F92 2-f2: * ** * .byte %10011001 ; 0F93 2-f2: * ** * .byte %10011001 ; 0F94 2-f2: * ** * .byte %11000001 ; 0F95 2-f2: ** * .byte %11110011 ; 0F96 2-f2: **** ** .byte %10000111 ; 0F97 2-f2: * *** .byte %11111111 ; 0F98 2-f3: ******** .byte %11111111 ; 0F99 2-f3: ******** .byte %10011001 ; 0F9A 2-f3: * ** * .byte %10011001 ; 0F9B 2-f3: * ** * .byte %10011001 ; 0F9C 2-f3: * ** * .byte %11000001 ; 0F9D 2-f3: ** * .byte %11110011 ; 0F9E 2-f3: **** ** .byte %10000111 ; 0F9F 2-f3: * *** .byte %11111111 ; 0FA0 2-f4: ******** .byte %11111111 ; 0FA1 2-f4: ******** .byte %10000001 ; 0FA2 2-f4: * * .byte %11110011 ; 0FA3 2-f4: **** ** .byte %11100111 ; 0FA4 2-f4: *** *** .byte %11001111 ; 0FA5 2-f4: ** **** .byte %10000001 ; 0FA6 2-f4: * * .byte %11111111 ; 0FA7 2-f4: ******** .byte %11111111 ; 0FA8 2-f5: ******** .byte %11111111 ; 0FA9 2-f5: ******** .byte %10000001 ; 0FAA 2-f5: * * .byte %11110011 ; 0FAB 2-f5: **** ** .byte %11100111 ; 0FAC 2-f5: *** *** .byte %11001111 ; 0FAD 2-f5: ** **** .byte %10000001 ; 0FAE 2-f5: * * .byte %11111111 ; 0FAF 2-f5: ******** .byte %11100011 ; 0FB0 2-f6: *** ** .byte %11001111 ; 0FB1 2-f6: ** **** .byte %11100111 ; 0FB2 2-f6: *** *** .byte %10001111 ; 0FB3 2-f6: * **** .byte %11100111 ; 0FB4 2-f6: *** *** .byte %11001111 ; 0FB5 2-f6: ** **** .byte %11100011 ; 0FB6 2-f6: *** ** .byte %11111111 ; 0FB7 2-f6: ******** .byte %11100011 ; 0FB8 2-f7: *** ** .byte %11001111 ; 0FB9 2-f7: ** **** .byte %11100111 ; 0FBA 2-f7: *** *** .byte %10001111 ; 0FBB 2-f7: * **** .byte %11100111 ; 0FBC 2-f7: *** *** .byte %11001111 ; 0FBD 2-f7: ** **** .byte %11100011 ; 0FBE 2-f7: *** ** .byte %11111111 ; 0FBF 2-f7: ******** .byte %11100111 ; 0FC0 2-f8: *** *** .byte %11100111 ; 0FC1 2-f8: *** *** .byte %11100111 ; 0FC2 2-f8: *** *** .byte %11111111 ; 0FC3 2-f8: ******** .byte %11111111 ; 0FC4 2-f8: ******** .byte %11100111 ; 0FC5 2-f8: *** *** .byte %11100111 ; 0FC6 2-f8: *** *** .byte %11100111 ; 0FC7 2-f8: *** *** .byte %11100111 ; 0FC8 2-f9: *** *** .byte %11100111 ; 0FC9 2-f9: *** *** .byte %11100111 ; 0FCA 2-f9: *** *** .byte %11111111 ; 0FCB 2-f9: ******** .byte %11111111 ; 0FCC 2-f9: ******** .byte %11100111 ; 0FCD 2-f9: *** *** .byte %11100111 ; 0FCE 2-f9: *** *** .byte %11100111 ; 0FCF 2-f9: *** *** .byte %11000111 ; 0FD0 2-fa: ** *** .byte %11110011 ; 0FD1 2-fa: **** ** .byte %11100111 ; 0FD2 2-fa: *** *** .byte %11110001 ; 0FD3 2-fa: **** * .byte %11100111 ; 0FD4 2-fa: *** *** .byte %11110011 ; 0FD5 2-fa: **** ** .byte %11000111 ; 0FD6 2-fa: ** *** .byte %11111111 ; 0FD7 2-fa: ******** .byte %11000111 ; 0FD8 2-fb: ** *** .byte %11110011 ; 0FD9 2-fb: **** ** .byte %11100111 ; 0FDA 2-fb: *** *** .byte %11110001 ; 0FDB 2-fb: **** * .byte %11100111 ; 0FDC 2-fb: *** *** .byte %11110011 ; 0FDD 2-fb: **** ** .byte %11000111 ; 0FDE 2-fb: ** *** .byte %11111111 ; 0FDF 2-fb: ******** .byte %11001100 ; 0FE0 2-fc: ** ** .byte %00000000 ; 0FE1 2-fc: .byte %00110011 ; 0FE2 2-fc: ** ** .byte %11111111 ; 0FE3 2-fc: ******** .byte %11111111 ; 0FE4 2-fc: ******** .byte %11111111 ; 0FE5 2-fc: ******** .byte %11111111 ; 0FE6 2-fc: ******** .byte %11111111 ; 0FE7 2-fc: ******** .byte %11001100 ; 0FE8 2-fd: ** ** .byte %00000000 ; 0FE9 2-fd: .byte %00110011 ; 0FEA 2-fd: ** ** .byte %11111111 ; 0FEB 2-fd: ******** .byte %11111111 ; 0FEC 2-fd: ******** .byte %11111111 ; 0FED 2-fd: ******** .byte %11111111 ; 0FEE 2-fd: ******** .byte %11111111 ; 0FEF 2-fd: ******** .byte %11111111 ; 0FF0 2-fe: ******** .byte %11111111 ; 0FF1 2-fe: ******** .byte %11111111 ; 0FF2 2-fe: ******** .byte %11111111 ; 0FF3 2-fe: ******** .byte %11111111 ; 0FF4 2-fe: ******** .byte %11111111 ; 0FF5 2-fe: ******** .byte %11111111 ; 0FF6 2-fe: ******** .byte %11111111 ; 0FF7 2-fe: ******** .byte %11111111 ; 0FF8 2-ff: ******** .byte %11111111 ; 0FF9 2-ff: ******** .byte %11111111 ; 0FFA 2-ff: ******** .byte %11111111 ; 0FFB 2-ff: ******** .byte %11111111 ; 0FFC 2-ff: ******** .byte %11111111 ; 0FFD 2-ff: ******** .byte %11111111 ; 0FFE 2-ff: ******** .byte %11111111 ; 0FFF 2-ff: ******** ��������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/ppu.s��������������������������������������������������������������������������0000664�0000000�0000000�00000013645�13473601511�0015251�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Written by Groepaz/Hitmen <groepaz@gmx.net> ; Cleanup by Ullrich von Bassewitz <uz@cc65.org> ; .export ppuinit .export paletteinit, paldata .include "nes.inc" ;+---------+----------------------------------------------------------+ ;| $2000 | PPU Control Register #1 (W) | ;| | | ;| | D7: Execute NMI on VBlank | ;| | 0 = Disabled | ;| | 1 = Enabled | ;| | D6: PPU Master/Slave Selection --+ | ;| | 0 = Master +-- UNUSED | ;| | 1 = Slave --+ | ;| | D5: Sprite Size | ;| | 0 = 8x8 | ;| | 1 = 8x16 | ;| | D4: Background Pattern Table Address | ;| | 0 = $0000 (VRAM) | ;| | 1 = $1000 (VRAM) | ;| | D3: Sprite Pattern Table Address | ;| | 0 = $0000 (VRAM) | ;| | 1 = $1000 (VRAM) | ;| | D2: PPU Address Increment | ;| | 0 = Increment by 1 | ;| | 1 = Increment by 32 | ;| | D1-D0: Name Table Address | ;| | 00 = $2000 (VRAM) | ;| | 01 = $2400 (VRAM) | ;| | 10 = $2800 (VRAM) | ;| | 11 = $2C00 (VRAM) | ;+---------+----------------------------------------------------------+ ;+---------+----------------------------------------------------------+ ;| $2001 | PPU Control Register #2 (W) | ;| | | ;| | D7-D5: Full Background Colour (when D0 == 1) | ;| | 000 = None +------------+ | ;| | 001 = Green | NOTE: Do not use more | ;| | 010 = Blue | than one type | ;| | 100 = Red +------------+ | ;| | D7-D5: Colour Intensity (when D0 == 0) | ;| | 000 = None +--+ | ;| | 001 = Intensify green | NOTE: Do not use more | ;| | 010 = Intensify blue | than one type | ;| | 100 = Intensify red +--+ | ;| | D4: Sprite Visibility | ;| | 0 = Sprites not displayed | ;| | 1 = Sprites visible | ;| | D3: Background Visibility | ;| | 0 = Background not displayed | ;| | 1 = Background visible | ;| | D2: Sprite Clipping | ;| | 0 = Sprites invisible in left 8-pixel column | ;| | 1 = No clipping | ;| | D1: Background Clipping | ;| | 0 = BG invisible in left 8-pixel column | ;| | 1 = No clipping | ;| | D0: Display Type | ;| | 0 = Colour display | ;| | 1 = Monochrome display | ;+---------+----------------------------------------------------------+ ;----------------------------------------------------------------------------- .segment "ONCE" .proc ppuinit lda #%10101000 sta PPU_CTRL1 lda #%00011110 sta PPU_CTRL2 ; Wait for vblank @wait: lda PPU_STATUS bpl @wait ; reset scrolling lda #0 sta PPU_VRAM_ADDR1 sta PPU_VRAM_ADDR1 ; Make all sprites invisible lda #$00 ldy #$f0 sta PPU_SPR_ADDR ldx #$40 @loop: sty PPU_SPR_IO sta PPU_SPR_IO sta PPU_SPR_IO sty PPU_SPR_IO dex bne @loop rts .endproc ;----------------------------------------------------------------------------- .proc paletteinit ; Wait for v-blank @wait: lda PPU_STATUS bpl @wait lda #$3F sta PPU_VRAM_ADDR2 lda #$00 sta PPU_VRAM_ADDR2 ldx #0 @loop: lda paldata,x sta PPU_VRAM_IO inx cpx #(16*2) bne @loop rts .endproc ;----------------------------------------------------------------------------- .rodata paldata: .repeat 2 .byte $0f ; 0 black .byte $14 ; 4 violett .byte $3b ; 3 cyan .byte $3d ; 1 white .byte $38 ; 7 yellow .byte $2d ; b dark grey .byte $22 ; e light blue .byte $04 ; 2 red .byte $18 ; 8 orange .byte $08 ; 9 brown .byte $35 ; a light red .byte $01 ; 6 blue .byte $10 ; c middle grey .byte $2b ; d light green .byte $3d ; f light gray .byte $1a ; 5 green .endrepeat �������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/ppubuf.s�����������������������������������������������������������������������0000664�0000000�0000000�00000004135�13473601511�0015740�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Written by Groepaz/Hitmen <groepaz@gmx.net> ; Cleanup by Ullrich von Bassewitz <uz@cc65.org> ; .export ppubuf_waitempty .export ppubuf_wait .export ppubuf_put .export ppubuf_flush .include "nes.inc" .code ; ------------------------------------------------------------------------ ; ppubuf_waitempty ; Wait until buffer is empty .proc ppubuf_waitempty @wait: lda ringcount bne @wait rts .endproc ; ------------------------------------------------------------------------ ; ppubuf_wait ; Wait until buffer is full .proc ppubuf_wait lda #$ff ; (($0100/3)*1) @wait: cmp ringcount beq @wait rts .endproc ; ------------------------------------------------------------------------ ; Put a PPU-Memory write to buffer ; called from main program (not necessary when in vblank irq) .proc ppubuf_put sta ppuval sty ppuhi stx ppulo jsr ppubuf_wait ; wait if buffer is full ldy ringwrite lda ppuhi sta ringbuff,y lda ppulo sta ringbuff+$0100,y lda ppuval sta ringbuff+$0200,y iny sty ringwrite inc ringcount rts .endproc ; ------------------------------------------------------------------------ ; Flush PPU-Memory write buffer ; called from vblank interupt .proc ppubuf_flush ldy ringcount bne @doloop rts @doloop: ldx ringread lda #$0e sta temp @loop: .repeat 5 lda ringbuff,x sta $2006 lda ringbuff+$0100,x sta $2006 lda ringbuff+$0200,x sta $2007 inx dey beq @end .endrepeat dec temp bne @loop @end: stx ringread sty ringcount rts .endproc ; ------------------------------------------------------------------------ ; Data .bss temp: .res 1 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/randomize.s��������������������������������������������������������������������0000664�0000000�0000000�00000000556�13473601511�0016432�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-05-02 ; ; void _randomize (void); ; /* Initialize the random number generator */ ; .export __randomize .import _srand .include "nes.inc" __randomize: ldx tickcount ; Use tick clock lda tickcount+1 jmp _srand ; Initialize generator ��������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/revers.s�����������������������������������������������������������������������0000664�0000000�0000000�00000001401�13473601511�0015736�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 07.08.1998 ; ; unsigned char revers (unsigned char onoff); ; .export _revers .include "nes.inc" .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 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/setcursor.s��������������������������������������������������������������������0000664�0000000�0000000�00000001423�13473601511�0016465�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Written by Groepaz/Hitmen <groepaz@gmx.net> ; Cleanup by Ullrich von Bassewitz <uz@cc65.org> ; ; Set the cursor position .export setcursor .include "nes.inc" ;----------------------------------------------------------------------------- .proc setcursor tya clc adc addrlo,x sta SCREEN_PTR lda addrhi,x adc #0 sta SCREEN_PTR+1 rts .endproc ;----------------------------------------------------------------------------- ; Tables with screen addresses addrlo: .repeat screenrows,line .byte <($2000+((1*32))+(line*charsperline)) .endrepeat addrhi: .repeat screenrows,line .byte >($2000+((1*32))+(line*charsperline)) .endrepeat ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/sysuname.s���������������������������������������������������������������������0000664�0000000�0000000�00000001471�13473601511�0016303�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-08-12 ; ; unsigned char __fastcall__ _sysuname (struct utsname* buf); ; .export __sysuname, utsdata .import utscopy __sysuname = utscopy ;-------------------------------------------------------------------------- ; Data. We define a fixed utsname struct here and just copy it. .rodata utsdata: ; sysname .asciiz "cc65" ; nodename .asciiz "" ; release .byte ((.VERSION >> 8) & $0F) + '0' .byte '.' .byte ((.VERSION >> 4) & $0F) + '0' .byte $00 ; version .byte (.VERSION & $0F) + '0' .byte $00 ; machine .asciiz "NES" �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/tgi/���������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015033�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/tgi/nes-64-56-2.s��������������������������������������������������������������0000664�0000000�0000000�00000030731�13473601511�0016626�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Graphics driver for the lores 64x56x2 mode on the NES ; ; Stefan Haubenthal, 2009-03-10 ; Based on Maciej Witkowiak's line routine. ; .include "zeropage.inc" .include "tgi-kernel.inc" .include "tgi-error.inc" .include "nes.inc" .include "get_tv.inc" .import _clrscr, setcursor, putchar .import paldata .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table and constants. module_header _nes_64_56_2_tgi ; First part of the header is a structure that has a magic and defines the ; capabilities of the driver .byte $74, $67, $69 ; "tgi" .byte TGI_API_VERSION ; TGI API version number .addr $0000 ; Library reference xres: .word charsperline*2 ; Max X resolution yres: .word 56 ; Max Y resolution .byte 2 ; Number of drawing colors .byte 1 ; Number of screens available .byte 2 ; System font X size .byte 2 ; System font Y size .word $0100 ; Aspect ratio .byte 0 ; TGI driver flags ; Next comes the jump table. Currently all entries must be valid and may point ; to an RTS for test versions (function not implemented). .addr INSTALL .addr UNINSTALL .addr INIT .addr DONE .addr GETERROR .addr CONTROL .addr CLEAR .addr SETVIEWPAGE .addr SETDRAWPAGE .addr SETCOLOR .addr SETPALETTE .addr GETPALETTE .addr GETDEFPALETTE .addr SETPIXEL .addr GETPIXEL .addr LINE .addr BAR .addr TEXTSTYLE .addr OUTTEXT ; ------------------------------------------------------------------------ ; Data. ; Variables mapped to the zero page segment variables. Some of these are ; used for passing parameters to the driver. X1 = ptr1 Y1 = ptr2 X2 = ptr3 Y2 = ptr4 RADIUS = tmp1 ADDR = tmp1 TEMP = tmp3 TEMP2 = tmp4 TEMP3 = sreg TEMP4 = sreg+1 ; Absolute variables used in the code .bss MEM: .res charsperline*2*56/4 MEMEND: ERROR: .res 1 ; Error code COLOR: .res 1 ; Current color PALETTE: .res 2 ; The current palette ; Constants and tables .rodata DEFPALETTE: .byte $0, $1 OFFSET: .byte 8, 4, 2, 1 ; 00 00 00 00 01 01 01 01 ; 00 01 10 11 00 01 10 11 CODE: .byte 32, 29, 26, 25, 28, 24+128, 31+128, 30+128 ; 10 10 10 10 11 11 11 11 ; 00 01 10 11 00 01 10 11 .byte 30, 31, 24, 28+128, 25+128, 26+128, 29+128, 32+128 .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. May ; initialize anything that has to be done just once. Is probably empty ; most of the time. ; ; Must set an error code: NO ; INSTALL: jsr _get_tv cmp #TV::NTSC beq ntsc ; TODO ROM! inc yres inc yres ntsc:; rts ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. May ; clean up anything done by INSTALL but is probably empty most of the time. ; ; Must set an error code: NO ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; INIT: Changes an already installed device from text mode to graphics ; mode. ; Note that INIT/DONE may be called multiple times while the driver ; is loaded, while INSTALL is only called once, so any code that is needed ; to initializes variables and so on must go here. Setting palette and ; clearing the screen is not needed because this is called by the graphics ; kernel later. ; The graphics kernel will never call INIT when a graphics mode is already ; active, so there is no need to protect against that. ; ; Must set an error code: YES ; INIT: ; Done, reset the error code lda #TGI_ERR_OK sta ERROR ; rts ; ------------------------------------------------------------------------ ; DONE: Will be called to switch the graphics device back into text mode. ; The graphics kernel will never call DONE when no graphics mode is active, ; so there is no need to protect against that. ; ; Must set an error code: NO ; DONE: rts ; ------------------------------------------------------------------------ ; GETERROR: Return the error code in A and clear it. GETERROR: lda ERROR ldx #TGI_ERR_OK stx ERROR rts ; ------------------------------------------------------------------------ ; CONTROL: Platform/driver specific entry point. ; ; Must set an error code: YES ; CONTROL: lda #TGI_ERR_INV_FUNC sta ERROR rts ; ------------------------------------------------------------------------ ; CLEAR: Clears the screen. ; ; Must set an error code: NO ; CLEAR: ldx #<MEM stx TEMP ldx #>MEM stx TEMP+1 lda #0 tay @L1: sta (TEMP),y iny bne @L1 inc TEMP+1 inx cpx #>MEMEND bne @L1 jmp _clrscr ; ------------------------------------------------------------------------ ; SETCOLOR: Set the drawing color (in A). The new color is already checked ; to be in a valid range (0..maxcolor-1). ; ; Must set an error code: NO (will only be called if color ok) ; SETCOLOR: sta COLOR ; rts ; ------------------------------------------------------------------------ ; SETVIEWPAGE: Set the visible page. Called with the new page in A (0..n). ; The page number is already checked to be valid by the graphics kernel. ; ; Must set an error code: NO (will only be called if page ok) ; SETVIEWPAGE: ; rts ; ------------------------------------------------------------------------ ; SETDRAWPAGE: Set the drawable page. Called with the new page in A (0..n). ; The page number is already checked to be valid by the graphics kernel. ; ; Must set an error code: NO (will only be called if page ok) ; SETDRAWPAGE: rts ; ------------------------------------------------------------------------ ; SETPALETTE: Set the palette (not available with all drivers/hardware). ; A pointer to the palette is passed in ptr1. Must set an error if palettes ; are not supported ; ; Must set an error code: YES ; SETPALETTE: ; Wait for v-blank @wait: lda PPU_STATUS bpl @wait lda #$3F sta PPU_VRAM_ADDR2 lda #$00 sta PPU_VRAM_ADDR2 ldy #0 lda (ptr1),y sta PALETTE tax lda paldata,x ; sta PPU_VRAM_IO iny lda (ptr1),y sta PALETTE+1 tax lda paldata,x sta PPU_VRAM_IO lda #TGI_ERR_OK sta ERROR rts ; ------------------------------------------------------------------------ ; GETPALETTE: Return the current palette in A/X. Even drivers that cannot ; set the palette should return the default palette here, so there's no ; way for this function to fail. ; ; Must set an error code: NO ; GETPALETTE: lda #<PALETTE ldx #>PALETTE rts ; ------------------------------------------------------------------------ ; GETDEFPALETTE: Return the default palette for the driver in A/X. All ; drivers should return something reasonable here, even drivers that don't ; support palettes, otherwise the caller has no way to determine the colors ; of the (not changeable) palette. ; ; Must set an error code: NO (all drivers must have a default palette) ; GETDEFPALETTE: lda #<DEFPALETTE ldx #>DEFPALETTE rts ; ------------------------------------------------------------------------ ; SETPIXEL: Draw one pixel at X1/Y1 = ptr1/ptr2 with the current drawing ; color. The coordinates passed to this function are never outside the ; visible screen area, so there is no need for clipping inside this function. ; ; Must set an error code: NO ; SETPIXEL: ldx Y1 ; y+2<yres inx inx cpx yres bcc @L2 ldx X1 ; x+2<xres inx inx cpx xres bcc @L2 rts @L2: lda X1 lsr tay lda Y1 lsr tax clc jsr setcursor jsr CALC ldx COLOR bne @set2 eor #%00001111 @set2: sta TEMP3 lda (TEMP),y ldx COLOR bne @set and TEMP3 .byte $2c @set: ora TEMP3 sta (TEMP),y tax lda CODE,x @normal:jmp putchar ; ------------------------------------------------------------------------ ; GETPIXEL: Read the color value of a pixel and return it in A/X. The ; coordinates passed to this function are never outside the visible screen ; area, so there is no need for clipping inside this function. GETPIXEL: jsr CALC sta TEMP3 lda (TEMP),y and TEMP3 beq @L1 lda #1 @L1: ldx #0 rts ; ------------------------------------------------------------------------ ; BAR: Draw a filled rectangle with the corners X1/Y1, X2/Y2, where ; X1/Y1 = ptr1/ptr2 and X2/Y2 = ptr3/ptr4 using the current drawing color. ; Contrary to most other functions, the graphics kernel will sort and clip ; the coordinates before calling the driver, so on entry the following ; conditions are valid: ; X1 <= X2 ; Y1 <= Y2 ; (X1 >= 0) && (X1 < XRES) ; (X2 >= 0) && (X2 < XRES) ; (Y1 >= 0) && (Y1 < YRES) ; (Y2 >= 0) && (Y2 < YRES) ; ; Must set an error code: NO ; BAR: inc Y2 @L1: lda X1 pha @L2: jsr SETPIXEL inc X1 lda X2 cmp X1 bne @L2 pla sta X1 inc Y1 lda Y2 cmp Y1 bne @L1 rts ; ------------------------------------------------------------------------ ; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in X and Y ; direction is passend in X/Y, the text direction is passed in A. ; ; Must set an error code: NO ; TEXTSTYLE: rts ; ------------------------------------------------------------------------ ; OUTTEXT: Output text at X/Y = ptr1/ptr2 using the current color and the ; current text style. The text to output is given as a zero terminated ; string with address in ptr3. ; ; Must set an error code: NO ; OUTTEXT: lda ptr1 lsr tay lda ptr2 lsr tax clc jsr setcursor ldy #0 @L1: lda (ptr3),y jsr putchar iny cmp #$0 bne @L1 rts ; ------------------------------------------------------------------------ ; Calculate all variables to plot the pixel at X1/Y1. If the point is out ; of range, a carry is returned and INRANGE is set to a value !0 zero. If ; the coordinates are valid, INRANGE is zero and the carry clear. CALC: lda xres sta TEMP lda #0 sta TEMP+1 ldy Y1 @L1: lda TEMP add xres lsr sta TEMP lda TEMP+1 adc #0 lsr sta TEMP+1 dey bne @L1 lda TEMP add X1 lsr sta TEMP lda TEMP+1 adc #0 lsr sta TEMP+1 lda TEMP add #<MEM sta TEMP lda TEMP+1 adc #>MEM sta TEMP+1 lda X1 and #%00000001 sta TEMP3 lda Y1 asl and #%00000010 ora TEMP3 tax lda OFFSET,x rts ; ------------------------------------------------------------------------ .include "../../tgi/tgidrv_line.inc" ���������������������������������������cc65-2.18/libsrc/nes/tgi_stat_stddrv.s��������������������������������������������������������������0000664�0000000�0000000�00000000351�13473601511�0017637�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Address of the static standard tgi driver ; ; Oliver Schmidt, 2012-11-01 ; ; const void tgi_static_stddrv[]; ; .export _tgi_static_stddrv .import _nes_64_56_2_tgi .rodata _tgi_static_stddrv := _nes_64_56_2_tgi ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/tgi_stddrv.s�������������������������������������������������������������������0000664�0000000�0000000�00000000263�13473601511�0016606�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Name of the standard tgi driver ; ; Oliver Schmidt, 2012-11-01 ; ; const char tgi_stddrv[]; ; .export _tgi_stddrv .rodata _tgi_stddrv: .asciiz "nes-64-56-2.tgi" ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/waitvsync.s��������������������������������������������������������������������0000664�0000000�0000000�00000000411�13473601511�0016457�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Written by Groepaz <groepaz@gmx.net> ; Cleanup by Ullrich von Bassewitz <uz@cc65.org> ; ; void waitvsync(void); ; .export _waitvsync .include "nes.inc" .proc _waitvsync wait: lda PPU_STATUS bpl wait rts .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/wherex.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000343�13473601511�0015736�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-05-02 ; ; unsigned char wherex (void); ; .export _wherex .include "nes.inc" .proc _wherex lda CURS_X ldx #$00 rts .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/nes/wherey.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000343�13473601511�0015737�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-05-02 ; ; unsigned char wherey (void); ; .export _wherey .include "nes.inc" .proc _wherey lda CURS_Y ldx #$00 rts .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/none/������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014422�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/none/crt0.s������������������������������������������������������������������������0000664�0000000�0000000�00000000773�13473601511�0015465�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ .export _exit .export __STARTUP__ : absolute = 1 ; Mark as startup .import zerobss, _main .import initlib, donelib .import __STACKSTART__ ; Linker generated .include "zeropage.inc" .segment "STARTUP" lda #<__STACKSTART__ ldx #>__STACKSTART__ sta sp stx sp+1 jsr zerobss jsr initlib jsr _main _exit: pha jsr donelib pla rts �����cc65-2.18/libsrc/none/ctype.s�����������������������������������������������������������������������0000664�0000000�0000000�00000020737�13473601511�0015743�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-10-10 ; ; Character specification table. ; .include "ctype.inc" ; The tables are readonly, put them into the rodata segment .rodata ; The following 256 byte wide table specifies attributes for the isxxx type ; of functions. Doing it by a table means some overhead in space, but it ; has major advantages: ; ; * It is fast. If it weren't for the slow parameter passing of cc65, one ; could even define macros for the isxxx functions (this is usually ; done on other platforms). ; ; * It is highly portable. The only unportable part is the table itself, ; all real code goes into the common library. ; ; * We save some code in the isxxx functions. __ctype: .byte CT_CTRL ; 0/00 ___ctrl_@___ .byte CT_CTRL ; 1/01 ___ctrl_A___ .byte CT_CTRL ; 2/02 ___ctrl_B___ .byte CT_CTRL ; 3/03 ___ctrl_C___ .byte CT_CTRL ; 4/04 ___ctrl_D___ .byte CT_CTRL ; 5/05 ___ctrl_E___ .byte CT_CTRL ; 6/06 ___ctrl_F___ .byte CT_CTRL ; 7/07 ___ctrl_G___ .byte CT_CTRL ; 8/08 ___ctrl_H___ .byte CT_CTRL | CT_OTHER_WS | CT_SPACE_TAB ; 9/09 ___ctrl_I___ .byte CT_CTRL | CT_OTHER_WS ; 10/0a ___ctrl_J___ .byte CT_CTRL | CT_OTHER_WS ; 11/0b ___ctrl_K___ .byte CT_CTRL | CT_OTHER_WS ; 12/0c ___ctrl_L___ .byte CT_CTRL | CT_OTHER_WS ; 13/0d ___ctrl_M___ .byte CT_CTRL ; 14/0e ___ctrl_N___ .byte CT_CTRL ; 15/0f ___ctrl_O___ .byte CT_CTRL ; 16/10 ___ctrl_P___ .byte CT_CTRL ; 17/11 ___ctrl_Q___ .byte CT_CTRL ; 18/12 ___ctrl_R___ .byte CT_CTRL ; 19/13 ___ctrl_S___ .byte CT_CTRL ; 20/14 ___ctrl_T___ .byte CT_CTRL ; 21/15 ___ctrl_U___ .byte CT_CTRL ; 22/16 ___ctrl_V___ .byte CT_CTRL ; 23/17 ___ctrl_W___ .byte CT_CTRL ; 24/18 ___ctrl_X___ .byte CT_CTRL ; 25/19 ___ctrl_Y___ .byte CT_CTRL ; 26/1a ___ctrl_Z___ .byte CT_CTRL ; 27/1b ___ctrl_[___ .byte CT_CTRL ; 28/1c ___ctrl_\___ .byte CT_CTRL ; 29/1d ___ctrl_]___ .byte CT_CTRL ; 30/1e ___ctrl_^___ .byte CT_CTRL ; 31/1f ___ctrl_____ .byte CT_SPACE | CT_SPACE_TAB ; 32/20 ___SPACE___ .byte CT_NONE ; 33/21 _____!_____ .byte CT_NONE ; 34/22 _____"_____ .byte CT_NONE ; 35/23 _____#_____ .byte CT_NONE ; 36/24 _____$_____ .byte CT_NONE ; 37/25 _____%_____ .byte CT_NONE ; 38/26 _____&_____ .byte CT_NONE ; 39/27 _____'_____ .byte CT_NONE ; 40/28 _____(_____ .byte CT_NONE ; 41/29 _____)_____ .byte CT_NONE ; 42/2a _____*_____ .byte CT_NONE ; 43/2b _____+_____ .byte CT_NONE ; 44/2c _____,_____ .byte CT_NONE ; 45/2d _____-_____ .byte CT_NONE ; 46/2e _____._____ .byte CT_NONE ; 47/2f _____/_____ .byte CT_DIGIT | CT_XDIGIT ; 48/30 _____0_____ .byte CT_DIGIT | CT_XDIGIT ; 49/31 _____1_____ .byte CT_DIGIT | CT_XDIGIT ; 50/32 _____2_____ .byte CT_DIGIT | CT_XDIGIT ; 51/33 _____3_____ .byte CT_DIGIT | CT_XDIGIT ; 52/34 _____4_____ .byte CT_DIGIT | CT_XDIGIT ; 53/35 _____5_____ .byte CT_DIGIT | CT_XDIGIT ; 54/36 _____6_____ .byte CT_DIGIT | CT_XDIGIT ; 55/37 _____7_____ .byte CT_DIGIT | CT_XDIGIT ; 56/38 _____8_____ .byte CT_DIGIT | CT_XDIGIT ; 57/39 _____9_____ .byte CT_NONE ; 58/3a _____:_____ .byte CT_NONE ; 59/3b _____;_____ .byte CT_NONE ; 60/3c _____<_____ .byte CT_NONE ; 61/3d _____=_____ .byte CT_NONE ; 62/3e _____>_____ .byte CT_NONE ; 63/3f _____?_____ .byte CT_NONE ; 64/40 _____@_____ .byte CT_UPPER | CT_XDIGIT ; 65/41 _____A_____ .byte CT_UPPER | CT_XDIGIT ; 66/42 _____B_____ .byte CT_UPPER | CT_XDIGIT ; 67/43 _____C_____ .byte CT_UPPER | CT_XDIGIT ; 68/44 _____D_____ .byte CT_UPPER | CT_XDIGIT ; 69/45 _____E_____ .byte CT_UPPER | CT_XDIGIT ; 70/46 _____F_____ .byte CT_UPPER ; 71/47 _____G_____ .byte CT_UPPER ; 72/48 _____H_____ .byte CT_UPPER ; 73/49 _____I_____ .byte CT_UPPER ; 74/4a _____J_____ .byte CT_UPPER ; 75/4b _____K_____ .byte CT_UPPER ; 76/4c _____L_____ .byte CT_UPPER ; 77/4d _____M_____ .byte CT_UPPER ; 78/4e _____N_____ .byte CT_UPPER ; 79/4f _____O_____ .byte CT_UPPER ; 80/50 _____P_____ .byte CT_UPPER ; 81/51 _____Q_____ .byte CT_UPPER ; 82/52 _____R_____ .byte CT_UPPER ; 83/53 _____S_____ .byte CT_UPPER ; 84/54 _____T_____ .byte CT_UPPER ; 85/55 _____U_____ .byte CT_UPPER ; 86/56 _____V_____ .byte CT_UPPER ; 87/57 _____W_____ .byte CT_UPPER ; 88/58 _____X_____ .byte CT_UPPER ; 89/59 _____Y_____ .byte CT_UPPER ; 90/5a _____Z_____ .byte CT_NONE ; 91/5b _____[_____ .byte CT_NONE ; 92/5c _____\_____ .byte CT_NONE ; 93/5d _____]_____ .byte CT_NONE ; 94/5e _____^_____ .byte CT_NONE ; 95/5f _UNDERLINE_ .byte CT_NONE ; 96/60 ___grave___ .byte CT_LOWER | CT_XDIGIT ; 97/61 _____a_____ .byte CT_LOWER | CT_XDIGIT ; 98/62 _____b_____ .byte CT_LOWER | CT_XDIGIT ; 99/63 _____c_____ .byte CT_LOWER | CT_XDIGIT ; 100/64 _____d_____ .byte CT_LOWER | CT_XDIGIT ; 101/65 _____e_____ .byte CT_LOWER | CT_XDIGIT ; 102/66 _____f_____ .byte CT_LOWER ; 103/67 _____g_____ .byte CT_LOWER ; 104/68 _____h_____ .byte CT_LOWER ; 105/69 _____i_____ .byte CT_LOWER ; 106/6a _____j_____ .byte CT_LOWER ; 107/6b _____k_____ .byte CT_LOWER ; 108/6c _____l_____ .byte CT_LOWER ; 109/6d _____m_____ .byte CT_LOWER ; 110/6e _____n_____ .byte CT_LOWER ; 111/6f _____o_____ .byte CT_LOWER ; 112/70 _____p_____ .byte CT_LOWER ; 113/71 _____q_____ .byte CT_LOWER ; 114/72 _____r_____ .byte CT_LOWER ; 115/73 _____s_____ .byte CT_LOWER ; 116/74 _____t_____ .byte CT_LOWER ; 117/75 _____u_____ .byte CT_LOWER ; 118/76 _____v_____ .byte CT_LOWER ; 119/77 _____w_____ .byte CT_LOWER ; 120/78 _____x_____ .byte CT_LOWER ; 121/79 _____y_____ .byte CT_LOWER ; 122/7a _____z_____ .byte CT_NONE ; 123/7b _____{_____ .byte CT_NONE ; 124/7c _____|_____ .byte CT_NONE ; 125/7d _____}_____ .byte CT_NONE ; 126/7e _____~_____ .byte CT_OTHER_WS ; 127/7f ____DEL____ .res 128, CT_NONE ; 128-255 ���������������������������������cc65-2.18/libsrc/osic1p/����������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014661�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/osic1p/bootstrap.s�����������������������������������������������������������������0000664�0000000�0000000�00000010427�13473601511�0017066�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 __MAIN_START__, __MAIN_SIZE__, __BSS_RUN__ ; ------------------------------------------------------------------------ load_addr := __MAIN_START__ load_size = __BSS_RUN__ - __MAIN_START__ ram_top := __MAIN_START__ + __MAIN_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 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/osic1p/cclear.s��������������������������������������������������������������������0000664�0000000�0000000�00000001451�13473601511�0016277�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 gotoxy, cputdirect .importzp tmp1 _cclearxy: pha ; Save the length 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 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/osic1p/cgetc.s���������������������������������������������������������������������0000664�0000000�0000000�00000003065�13473601511�0016136�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; char cgetc (void); ; .constructor initcgetc .export _cgetc .import cursor .include "osic1p.inc" .include "extzp.inc" .include "zeropage.inc" ; Initialize one-character buffer that is filled by kbhit() .segment "ONCE" initcgetc: lda #$00 sta CHARBUF ; No character in buffer initially rts ; Input routine from 65V PROM MONITOR, show cursor if enabled .code _cgetc: lda CHARBUF ; character in buffer available? beq nobuffer tax ; save character in X lda #$00 sta CHARBUF ; empty buffer beq restorex ; restore X and return nobuffer: lda cursor ; show cursor? beq nocursor ldy CURS_X lda (SCREEN_PTR),y ; fetch current character sta tmp1 ; save it lda #$A1 ; full white square sta (SCREEN_PTR),y ; store at cursor position nocursor: jsr INPUTC ; get input character in A ldx cursor beq done ; was cursor on? tax ; save A in X lda tmp1 ; fetch saved character ldy CURS_X sta (SCREEN_PTR),y ; store at cursor position restorex: txa ; restore saved character from X done: ldx #$00 ; high byte of int return value rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/osic1p/chline.s��������������������������������������������������������������������0000664�0000000�0000000�00000001432�13473601511�0016307�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 gotoxy, cputdirect .importzp tmp1 _chlinexy: pha ; Save the length 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 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/osic1p/crt0.s����������������������������������������������������������������������0000664�0000000�0000000�00000003364�13473601511�0015723�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; --------------------------------------------------------------------------- ; crt0.s ; --------------------------------------------------------------------------- ; ; Startup code for Ohio Scientific Challenger 1P .export _init, _exit .import _main .export __STARTUP__ : absolute = 1 ; Mark as startup .import __MAIN_START__, __MAIN_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 #<(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__) ldx #>(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__) sta sp stx 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 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/osic1p/ctype.s���������������������������������������������������������������������0000664�0000000�0000000�00000020737�13473601511�0016202�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-10-10 ; ; Character specification table. ; .include "ctype.inc" ; The tables are readonly, put them into the rodata segment .rodata ; The following 256 byte wide table specifies attributes for the isxxx type ; of functions. Doing it by a table means some overhead in space, but it ; has major advantages: ; ; * It is fast. If it weren't for the slow parameter passing of cc65, one ; could even define macros for the isxxx functions (this is usually ; done on other platforms). ; ; * It is highly portable. The only unportable part is the table itself, ; all real code goes into the common library. ; ; * We save some code in the isxxx functions. __ctype: .byte CT_CTRL ; 0/00 ___ctrl_@___ .byte CT_CTRL ; 1/01 ___ctrl_A___ .byte CT_CTRL ; 2/02 ___ctrl_B___ .byte CT_CTRL ; 3/03 ___ctrl_C___ .byte CT_CTRL ; 4/04 ___ctrl_D___ .byte CT_CTRL ; 5/05 ___ctrl_E___ .byte CT_CTRL ; 6/06 ___ctrl_F___ .byte CT_CTRL ; 7/07 ___ctrl_G___ .byte CT_CTRL ; 8/08 ___ctrl_H___ .byte CT_CTRL | CT_OTHER_WS | CT_SPACE_TAB ; 9/09 ___ctrl_I___ .byte CT_CTRL | CT_OTHER_WS ; 10/0a ___ctrl_J___ .byte CT_CTRL | CT_OTHER_WS ; 11/0b ___ctrl_K___ .byte CT_CTRL | CT_OTHER_WS ; 12/0c ___ctrl_L___ .byte CT_CTRL | CT_OTHER_WS ; 13/0d ___ctrl_M___ .byte CT_CTRL ; 14/0e ___ctrl_N___ .byte CT_CTRL ; 15/0f ___ctrl_O___ .byte CT_CTRL ; 16/10 ___ctrl_P___ .byte CT_CTRL ; 17/11 ___ctrl_Q___ .byte CT_CTRL ; 18/12 ___ctrl_R___ .byte CT_CTRL ; 19/13 ___ctrl_S___ .byte CT_CTRL ; 20/14 ___ctrl_T___ .byte CT_CTRL ; 21/15 ___ctrl_U___ .byte CT_CTRL ; 22/16 ___ctrl_V___ .byte CT_CTRL ; 23/17 ___ctrl_W___ .byte CT_CTRL ; 24/18 ___ctrl_X___ .byte CT_CTRL ; 25/19 ___ctrl_Y___ .byte CT_CTRL ; 26/1a ___ctrl_Z___ .byte CT_CTRL ; 27/1b ___ctrl_[___ .byte CT_CTRL ; 28/1c ___ctrl_\___ .byte CT_CTRL ; 29/1d ___ctrl_]___ .byte CT_CTRL ; 30/1e ___ctrl_^___ .byte CT_CTRL ; 31/1f ___ctrl_____ .byte CT_SPACE | CT_SPACE_TAB ; 32/20 ___SPACE___ .byte CT_NONE ; 33/21 _____!_____ .byte CT_NONE ; 34/22 _____"_____ .byte CT_NONE ; 35/23 _____#_____ .byte CT_NONE ; 36/24 _____$_____ .byte CT_NONE ; 37/25 _____%_____ .byte CT_NONE ; 38/26 _____&_____ .byte CT_NONE ; 39/27 _____'_____ .byte CT_NONE ; 40/28 _____(_____ .byte CT_NONE ; 41/29 _____)_____ .byte CT_NONE ; 42/2a _____*_____ .byte CT_NONE ; 43/2b _____+_____ .byte CT_NONE ; 44/2c _____,_____ .byte CT_NONE ; 45/2d _____-_____ .byte CT_NONE ; 46/2e _____._____ .byte CT_NONE ; 47/2f _____/_____ .byte CT_DIGIT | CT_XDIGIT ; 48/30 _____0_____ .byte CT_DIGIT | CT_XDIGIT ; 49/31 _____1_____ .byte CT_DIGIT | CT_XDIGIT ; 50/32 _____2_____ .byte CT_DIGIT | CT_XDIGIT ; 51/33 _____3_____ .byte CT_DIGIT | CT_XDIGIT ; 52/34 _____4_____ .byte CT_DIGIT | CT_XDIGIT ; 53/35 _____5_____ .byte CT_DIGIT | CT_XDIGIT ; 54/36 _____6_____ .byte CT_DIGIT | CT_XDIGIT ; 55/37 _____7_____ .byte CT_DIGIT | CT_XDIGIT ; 56/38 _____8_____ .byte CT_DIGIT | CT_XDIGIT ; 57/39 _____9_____ .byte CT_NONE ; 58/3a _____:_____ .byte CT_NONE ; 59/3b _____;_____ .byte CT_NONE ; 60/3c _____<_____ .byte CT_NONE ; 61/3d _____=_____ .byte CT_NONE ; 62/3e _____>_____ .byte CT_NONE ; 63/3f _____?_____ .byte CT_NONE ; 64/40 _____@_____ .byte CT_UPPER | CT_XDIGIT ; 65/41 _____A_____ .byte CT_UPPER | CT_XDIGIT ; 66/42 _____B_____ .byte CT_UPPER | CT_XDIGIT ; 67/43 _____C_____ .byte CT_UPPER | CT_XDIGIT ; 68/44 _____D_____ .byte CT_UPPER | CT_XDIGIT ; 69/45 _____E_____ .byte CT_UPPER | CT_XDIGIT ; 70/46 _____F_____ .byte CT_UPPER ; 71/47 _____G_____ .byte CT_UPPER ; 72/48 _____H_____ .byte CT_UPPER ; 73/49 _____I_____ .byte CT_UPPER ; 74/4a _____J_____ .byte CT_UPPER ; 75/4b _____K_____ .byte CT_UPPER ; 76/4c _____L_____ .byte CT_UPPER ; 77/4d _____M_____ .byte CT_UPPER ; 78/4e _____N_____ .byte CT_UPPER ; 79/4f _____O_____ .byte CT_UPPER ; 80/50 _____P_____ .byte CT_UPPER ; 81/51 _____Q_____ .byte CT_UPPER ; 82/52 _____R_____ .byte CT_UPPER ; 83/53 _____S_____ .byte CT_UPPER ; 84/54 _____T_____ .byte CT_UPPER ; 85/55 _____U_____ .byte CT_UPPER ; 86/56 _____V_____ .byte CT_UPPER ; 87/57 _____W_____ .byte CT_UPPER ; 88/58 _____X_____ .byte CT_UPPER ; 89/59 _____Y_____ .byte CT_UPPER ; 90/5a _____Z_____ .byte CT_NONE ; 91/5b _____[_____ .byte CT_NONE ; 92/5c _____\_____ .byte CT_NONE ; 93/5d _____]_____ .byte CT_NONE ; 94/5e _____^_____ .byte CT_NONE ; 95/5f _UNDERLINE_ .byte CT_NONE ; 96/60 ___grave___ .byte CT_LOWER | CT_XDIGIT ; 97/61 _____a_____ .byte CT_LOWER | CT_XDIGIT ; 98/62 _____b_____ .byte CT_LOWER | CT_XDIGIT ; 99/63 _____c_____ .byte CT_LOWER | CT_XDIGIT ; 100/64 _____d_____ .byte CT_LOWER | CT_XDIGIT ; 101/65 _____e_____ .byte CT_LOWER | CT_XDIGIT ; 102/66 _____f_____ .byte CT_LOWER ; 103/67 _____g_____ .byte CT_LOWER ; 104/68 _____h_____ .byte CT_LOWER ; 105/69 _____i_____ .byte CT_LOWER ; 106/6a _____j_____ .byte CT_LOWER ; 107/6b _____k_____ .byte CT_LOWER ; 108/6c _____l_____ .byte CT_LOWER ; 109/6d _____m_____ .byte CT_LOWER ; 110/6e _____n_____ .byte CT_LOWER ; 111/6f _____o_____ .byte CT_LOWER ; 112/70 _____p_____ .byte CT_LOWER ; 113/71 _____q_____ .byte CT_LOWER ; 114/72 _____r_____ .byte CT_LOWER ; 115/73 _____s_____ .byte CT_LOWER ; 116/74 _____t_____ .byte CT_LOWER ; 117/75 _____u_____ .byte CT_LOWER ; 118/76 _____v_____ .byte CT_LOWER ; 119/77 _____w_____ .byte CT_LOWER ; 120/78 _____x_____ .byte CT_LOWER ; 121/79 _____y_____ .byte CT_LOWER ; 122/7a _____z_____ .byte CT_NONE ; 123/7b _____{_____ .byte CT_NONE ; 124/7c _____|_____ .byte CT_NONE ; 125/7d _____}_____ .byte CT_NONE ; 126/7e _____~_____ .byte CT_OTHER_WS ; 127/7f ____DEL____ .res 128, CT_NONE ; 128-255 ���������������������������������cc65-2.18/libsrc/osic1p/cvline.s��������������������������������������������������������������������0000664�0000000�0000000�00000001545�13473601511�0016332�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 gotoxy, putchar, newline .importzp tmp1 _cvlinexy: pha ; Save the length 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 �����������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/osic1p/doesclrscr.s����������������������������������������������������������������0000664�0000000�0000000�00000000531�13473601511�0017207�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2016-06, Christian Groessler ; 2017-06-26, Greg King ; ; unsigned char doesclrscrafterexit (void); ; ; Returns 0/1 if, after program termination, the screen isn't/is cleared. ; .import return1 ; cc65's OSI programs return to the monitor ROM which clears the screen. .export _doesclrscrafterexit := return1 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/osic1p/extra/����������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0016004�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/osic1p/extra/screen-s3-32x28.s�����������������������������������������������������0000664�0000000�0000000�00000001261�13473601511�0020556�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/osic1p/extzp.inc�������������������������������������������������������������������0000664�0000000�0000000�00000000305�13473601511�0016524�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Additional zero page locations for the Challenger 1P. ; ; ------------------------------------------------------------------------ .globalzp CURS_X, CURS_Y, SCREEN_PTR, CHARBUF ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/osic1p/extzp.s���������������������������������������������������������������������0000664�0000000�0000000�00000001115�13473601511�0016215�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/osic1p/gotox.s���������������������������������������������������������������������0000664�0000000�0000000�00000000502�13473601511�0016202�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/osic1p/gotoxy.s��������������������������������������������������������������������0000664�0000000�0000000�00000000754�13473601511�0016404�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; copied from CBM implementation ; ; originally by: ; Ullrich von Bassewitz, 06.08.1998 ; ; void gotoxy (unsigned char x, unsigned char y); ; .export gotoxy, _gotoxy .import popa, plot .include "extzp.inc" gotoxy: jsr popa ; Get Y _gotoxy: sta CURS_Y ; Set Y jsr popa ; Get X sta CURS_X ; Set X jmp plot ; Set the cursor position ��������������������cc65-2.18/libsrc/osic1p/gotoy.s���������������������������������������������������������������������0000664�0000000�0000000�00000000505�13473601511�0016206�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/osic1p/kbhit.s���������������������������������������������������������������������0000664�0000000�0000000�00000003655�13473601511�0016157�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 �����������������������������������������������������������������������������������cc65-2.18/libsrc/osic1p/oserror.s�������������������������������������������������������������������0000664�0000000�0000000�00000000645�13473601511�0016545�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 �������������������������������������������������������������������������������������������cc65-2.18/libsrc/osic1p/osic1p.inc������������������������������������������������������������������0000664�0000000�0000000�00000000311�13473601511�0016545�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; Addresses INPUTC := $FD00 ; Input character from keyboard RESET := $FF00 ; Reset address, show boot prompt KBD := $DF00 ; Polled keyboard register �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/osic1p/osiscreen.inc���������������������������������������������������������������0000664�0000000�0000000�00000011302�13473601511�0017343�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Macro definitions for screen layout modules ; .include "extzp.inc" .linecont + ; ; Internal function for screensize() ; .macro osi_screensize ScrWidth, ScrHeight ; Macro implementation of internal screensize ; function for given width and height in ; characters .export screensize .proc screensize ldx #ScrWidth ldy #ScrHeight rts .endproc .endmacro ; ; void clrscr (void); ; .macro osi_clrscr ScrBase, ScrRamSize .export _clrscr .proc _clrscr lda #<ScrBase ; Fill whole video RAM with blanks by calling ldx #>ScrBase ; memset appropriately jsr pushax lda #' ' ldx #$00 jsr pushax lda #<ScrRamSize ldx #>ScrRamSize jsr _memset lda #$00 ; Cursor in upper left corner sta CURS_X sta CURS_Y jmp plot ; Set the cursor position .endproc .endmacro ; ; cputc/cputcxy for Challenger 1P ; Based on PET/CBM implementation ; .macro osi_cputfuncs ScrBase, ScrFirstChar, ScrWidth, ScrHeight, \ ScrollDist, ScrLo, ScrHi ; Number of characters to move for scrolling ; by one line ScrollLength = (ScrHeight - 1) * ScrollDist ; ; void cputcxy (unsigned char x, unsigned char y, char c); ; void cputc (char c); ; .export _cputcxy, _cputc, cputdirect, putchar .export newline, plot _cputcxy: pha ; Save C jsr gotoxy ; Set cursor, drop x and y pla ; Restore C ; Plot a character - also used as internal function _cputc: cmp #$0A ; CR? bne L1 lda #0 sta CURS_X beq plot ; Recalculate pointers L1: cmp #$0D ; LF? beq newline ; Recalculate pointers cputdirect: jsr putchar ; Write the character to the screen ; Advance cursor position, register Y contains horizontal position after ; putchar cpy #(ScrWidth - 1) ; Check whether line is full bne L3 jsr newline ; New line ldy #$FF ; + cr L3: iny sty CURS_X rts newline: inc CURS_Y lda CURS_Y cmp #ScrHeight ; Screen height bne plot dec CURS_Y ; Bottom of screen reached, scroll ; Scroll destination address lda #<(ScrBase + ScrFirstChar) ldx #>(ScrBase + ScrFirstChar) jsr pushax ; Scroll source address lda #<(ScrBase + ScrFirstChar + ScrollDist) ldx #>(ScrBase + ScrFirstChar + ScrollDist) jsr pushax ; Number of characters to move lda #<ScrollLength ldx #>ScrollLength jsr _memmove ; Address of first character in last line ; of screen lda #<(ScrBase + ScrFirstChar + ScrollLength) sta ptr1 lda #>(ScrBase + ScrFirstChar + ScrollLength) sta ptr1+1 ldy #ScrWidth ; Fill last line with blanks lda #' ' clrln: sta (ptr1),y dey bpl clrln plot: ldy CURS_Y lda ScrLo,y sta SCREEN_PTR lda ScrHi,y sta SCREEN_PTR+1 rts ; Write one character to the screen without doing anything else, return X ; position in register Y putchar: ldy CURS_X sta (SCREEN_PTR),y ; Set char rts .endmacro .macro osi_screen_funcs ScrBase, ScrRamSize, ScrFirstChar, \ ScrWidth, ScrHeight, ScrollDist .import gotoxy .import _memmove, _memset, pushax .importzp ptr1 .rodata ; Screen address tables - offset to real screen ScrTabLo: .repeat ScrHeight, I .byte <(ScrBase + ScrFirstChar + I * ScrollDist) .endrep ScrTabHi: .repeat ScrHeight, I .byte >(ScrBase + ScrFirstChar + I * ScrollDist) .endrep .code osi_cputfuncs ScrBase, ScrFirstChar, ScrWidth, ScrHeight, \ ScrollDist, ScrTabLo, ScrTabHi osi_screensize ScrWidth, ScrHeight osi_clrscr ScrBase, ScrRamSize .endmacro������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/osic1p/revers.s��������������������������������������������������������������������0000664�0000000�0000000�00000000271�13473601511�0016353�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2017-06-26, Greg King ; ; unsigned char __fastcall__ revers (unsigned char onoff) ; .import return0 .export _revers := return0 ; no attribute ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/osic1p/screen-c1p-24x24.s����������������������������������������������������������0000664�0000000�0000000�00000001235�13473601511�0017567�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/osic1p/wherex.s��������������������������������������������������������������������0000664�0000000�0000000�00000000371�13473601511�0016350�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/osic1p/wherey.s��������������������������������������������������������������������0000664�0000000�0000000�00000000372�13473601511�0016352�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pce/�������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014232�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pce/_scrsize.s���������������������������������������������������������������������0000664�0000000�0000000�00000000522�13473601511�0016236�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Screen size variables ; .export screensize .export xsize, ysize .include "pce.inc" screensize: ldx xsize ldy ysize rts ; FIXME: changing the video mode allows for different screen sizes .rodata xsize: .byte charsperline ysize: .byte screenrows ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pce/call.s�������������������������������������������������������������������������0000664�0000000�0000000�00000000466�13473601511�0015337�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; CC65 runtime: call function via pointer in ax ; ; 1998-08-06, Ullrich von Bassewitz ; 2018-02-28, Greg King ; .export callax .importzp ptr1 callax: sta ptr1 stx ptr1+1 ; The PC-Engine puts the zero-page at $2000. jmp (ptr1 + $2000) ; go there ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pce/callptr4.s���������������������������������������������������������������������0000664�0000000�0000000�00000000350�13473601511�0016141�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; CC65 runtime: call function via pointer in ptr4 ; ; 2018-02-28, Greg King ; .export callptr4 .importzp ptr4 callptr4: ; The PC-Engine puts the zero-page at $2000. jmp (ptr4 + $2000) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pce/cclear.s�����������������������������������������������������������������������0000664�0000000�0000000�00000001426�13473601511�0015652�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 gotoxy, cputdirect .importzp tmp1 _cclearxy: pha ; Save the length 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 #$20 ; Blank - screen code jsr cputdirect ; Direct output dec tmp1 bne L1 L9: rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pce/chline.s�����������������������������������������������������������������������0000664�0000000�0000000�00000001415�13473601511�0015661�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 gotoxy, cputdirect .importzp tmp1 .include "pce.inc" _chlinexy: pha ; Save the length 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 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pce/clock.s������������������������������������������������������������������������0000664�0000000�0000000�00000001751�13473601511�0015515�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; clock_t clock (void); ; .constructor initclock .export _clock .forceimport ticktock ; make sure that tickcount changes .importzp tickcount, sreg ; Make the process clock start at zero. .segment "ONCE" initclock: ldx #4 - 1 @lp: stz tickcount,x dex bpl @lp rts ; ------------------------------------------------------------------------ .code ; This function might be interrupted while it is reading the several bytes of ; the clock. They are read again if that happens. (We do not want to stop ; interrupts because that might cause glitches in interrupt-driven graphics ; and sound.) .proc _clock lda tickcount ldy tickcount+3 sty sreg+1 ldy tickcount+2 sty sreg ldx tickcount+1 cmp tickcount bne _clock ; clock changed; reread it rts .endproc �����������������������cc65-2.18/libsrc/pce/clrscr.s�����������������������������������������������������������������������0000664�0000000�0000000�00000001504�13473601511�0015706�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Clear (erase) the screen. ; ; Support the full 128- x 64-tile background. ; .export _clrscr .import plot .include "pce.inc" .include "extzp.inc" _clrscr: VREG VDC_MAWR, $0000 st0 #VDC_VWR ldy #$40 rowloop: ldx #$80 colloop: st1 #' ' ; low byte of char. index st2 #$02 ; background color, high nybble of char. index 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 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pce/color.s������������������������������������������������������������������������0000664�0000000�0000000�00000003750�13473601511�0015541�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 colors .import return0 .include "pce.inc" .include "extzp.inc" _bordercolor := return0 ; always black _textcolor: ldx CHARCOLOR ; get old value sta CHARCOLOR ; set new value txa rts _bgcolor: and #$0F 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 .rodata ; G R B colors: .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 violet .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 ������������������������cc65-2.18/libsrc/pce/conio.s������������������������������������������������������������������������0000664�0000000�0000000�00000004066�13473601511�0015533�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ .constructor initconio, 24 .import vdc_init .import psg_init .import colors .importzp ptr1, tmp1 .include "pce.inc" .include "extzp.inc" .segment "ONCE" initconio: jsr vdc_init jsr psg_init jsr load_font set_palette: stz VCE_ADDR_LO stz VCE_ADDR_HI clx @lp: ldy #16 ; size of a palette @lp1: lda colors,x sta VCE_DATA_LO lda colors+1,x sta VCE_DATA_HI dey bne @lp1 inx inx cpx #16 * 2 ; 16 palettes bne @lp sty BGCOLOR ; white on black iny sty CHARCOLOR VREG VDC_CR, $0088 ; enable background and vertical-blank interrupt rts ; Load the conio font into the VDC. load_font: VREG VDC_MAWR, $2000 st0 #VDC_VWR stz tmp1 ; #%00000000 bsr copy ; make normal characters dec tmp1 ; #%11111111 ; bsr copy ; make reversed characters ; rts ; (fall through) ; Point to the font data. copy: lda #<font ldx #>font sta ptr1 stx ptr1+1 ldy #$80 ; 128 chars charloop: ldx #$08 ; 8 bytes/char lineloop: lda (ptr1) eor tmp1 sta VDC_DATA_LO ; bitplane 0 st2 #>$0000 ; bitplane 1 inc ptr1 ; increment font pointer bne @noC inc ptr1+1 @noC: dex bne lineloop ; next bitplane-0 byte ldx #$08 ; fill bitplanes 2 and 3 with 0 fillloop: st1 #<$0000 st2 #>$0000 dex bne fillloop ; next byte dey bne charloop ; next character rts .rodata font: .include "vga.inc" ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pce/cputc.s������������������������������������������������������������������������0000664�0000000�0000000�00000003775�13473601511�0015550�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; void cputcxy (unsigned char x, unsigned char y, char c); ; void cputc (char c); ; .export _cputcxy, _cputc, cputdirect, putchar .export newline, plot .forceimport initconio ; force conio initiation .import gotoxy .import PLOT .import xsize .importzp tmp3, tmp4 .include "pce.inc" .include "extzp.inc" _cputcxy: pha ; Save C jsr gotoxy ; Set cursor, drop x and y pla ; Restore C ; Plot a character - also used as internal function _cputc: cmp #$0D ; CR? bne L1 stz CURS_X bra plot ; Recalculate pointer L1: cmp #$0A ; LF? beq newline ; Recalculate pointer ; Printable char of some sort cputdirect: jsr putchar ; Write the character to the screen ; Move the cursor (rightwards) to the next position. advance: ldy CURS_X iny cpy xsize bne L3 inc CURS_Y ; new line cly ; + CR L3: sty CURS_X ; Set cursor position; calculate VRAM pointer. plot: ldy CURS_X ldx CURS_Y clc jmp PLOT ; Set the new cursor newline: inc CURS_Y bra plot ; Write one character to the screen without doing anything else. putchar: ora RVS ; Set reverse bit st0 #VDC_MAWR ; Memory-Address Write ldy SCREEN_PTR ldx SCREEN_PTR+1 sty VDC_DATA_LO stx VDC_DATA_HI st0 #VDC_VWR sta VDC_DATA_LO ; character lda CHARCOLOR ; pallette number asl a asl a asl a asl a ora #>$0200 ; high nybble of char. index sta VDC_DATA_HI rts ���cc65-2.18/libsrc/pce/crt0.s�������������������������������������������������������������������������0000664�0000000�0000000�00000007667�13473601511�0015306�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Start-up code for cc65 (PC-Engine version) ; ; by Groepaz/Hitmen <groepaz@gmx.net>, ; based on code by Ullrich von Bassewitz <uz@cc65.org> ; ; 2018-02-24, Greg King ; .export _exit .export __STARTUP__ : absolute = 1 ; Mark as start-up .import initlib, donelib .import push0, _main .import IRQStub, __nmi .importzp sp ; Linker-generated .import __CARTSIZE__ .import __DATA_LOAD__, __DATA_RUN__, __DATA_SIZE__ .import __BSS_RUN__, __BSS_SIZE__ .import __MAIN_START__, __MAIN_SIZE__, __STACKSIZE__ .include "pce.inc" .include "extzp.inc" ; ------------------------------------------------------------------------ ; Place the start-up code in a special segment. .segment "STARTUP" ; Initialize the CPU. start: sei nop csh ; Set high-speed CPU mode nop ; Set up the stack and the memory mapping. ldx #$FF ; Stack top ($21FF) txs ; At power-on, most MPRs have random values; so, initiate them. lda #$FF tam #%00000001 ; $0000-$1FFF = Hardware bank lda #$F8 tam #%00000010 ; $2000-$3FFF = Work RAM ;lda #$F7 ;tam #%00000100 ; $4000-$47FF = 2K Battery-backed RAM ;lda #4 ;tam #%00001000 ; $6000-$7FFF lda #$01 ldx #>$8000 cpx #>__CARTSIZE__ bcc @L1 ;(blt) tam #%00010000 ; $8000-$9FFF = ROM bank 1 (32K block of ROM) inc a tam #%00100000 ; $A000-$BFFF = ROM bank 2 inc a @L1: tam #%01000000 ; $C000-$DFFF = ROM bank 3 (32K) or 1 (16K) ;lda #$00 ; (The reset default) ;tam #%10000000 ; $E000-$FFFF Hucard/Syscard bank 0 ; Initialize the hardware. stz TIMER_CTRL ; Timer off lda #%00000111 sta IRQ_MASK ; Interrupts off ; FIXME; I don't know why the heck this one doesn't work when called from a constructor. -Groepaz :-/ .if 0 ; It now seems to work (at least, in Mednafen). -Greg King .import vdc_init jsr vdc_init .endif ; Allow interrupts from the VDC. lda #%00000101 sta IRQ_MASK ; IRQ1 = on ; Copy the .data segment to RAM tii __DATA_LOAD__, __DATA_RUN__, __DATA_SIZE__ ; Clear the .bss segment stz __BSS_RUN__ tii __BSS_RUN__, __BSS_RUN__ + 1, __BSS_SIZE__ - 1 ; Set up the stack lda #<(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__) ldx #>(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__) sta sp stx sp+1 ; Call the module constructors. jsr initlib stz IRQ_STATUS ; Clear IRQs 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 user's code ; Call the module destructors. This is also the exit() entry. _exit: jsr donelib ; Reset the PCEngine (start over). jmp start .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 �������������������������������������������������������������������������cc65-2.18/libsrc/pce/ctype.s������������������������������������������������������������������������0000664�0000000�0000000�00000020774�13473601511�0015554�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Stefan Haubenthal with minor changes from Ullrich von Bassewitz, 2003-05-02 ; ; Character specification table. ; .include "ctype.inc" ; The tables are read-only; put them into the RODATA segment. .rodata ; The following 256-byte-wide table specifies attributes for the isxxx type ; of functions. Doing it by a table means some overhead in space, but it ; has major advantages: ; ; * It is fast. If it weren't for the slow parameter passing of cc65, one ; could even define macros for the isxxx functions (this is usually ; done on other platforms). ; ; * It is highly portable. The only unportable part is the table itself, ; all real code goes into the common library. ; ; * We save some code in the isxxx functions. __ctype: .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 ����cc65-2.18/libsrc/pce/cvline.s�����������������������������������������������������������������������0000664�0000000�0000000�00000001541�13473601511�0015677�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 gotoxy, putchar, newline .importzp tmp1 .include "pce.inc" _cvlinexy: pha ; Save the length 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 ���������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pce/extzp.inc����������������������������������������������������������������������0000664�0000000�0000000�00000000754�13473601511�0016105�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 ��������������������cc65-2.18/libsrc/pce/extzp.s������������������������������������������������������������������������0000664�0000000�0000000�00000000563�13473601511�0015574�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 ���������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pce/gotoxy.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000704�13473601511�0015750�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; void __fastcall__ gotoxy (unsigned char x, unsigned char y); ; .export gotoxy, _gotoxy .import popa, plot .include "pce.inc" .include "extzp.inc" gotoxy: jsr popa ; Get Y _gotoxy: sta CURS_Y ; Set Y jsr popa ; Get X sta CURS_X ; Set X jmp plot ; Set the cursor position ������������������������������������������������������������cc65-2.18/libsrc/pce/irq.s��������������������������������������������������������������������������0000664�0000000�0000000�00000001535�13473601511�0015215�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; IRQ handling (PCE version) ; .export initirq, doneirq, IRQStub, __nmi .import __INTERRUPTOR_COUNT__, callirq_y .include "pce.inc" .include "extzp.inc" ; ------------------------------------------------------------------------ .segment "ONCE" ; a constructor ; initirq: rts ; ------------------------------------------------------------------------ .code ; a destructor ; doneirq: rts ; ------------------------------------------------------------------------ IRQStub: phy ; Save the display-source flags (and, release the interrupt). ; ldy VDC_CTRL sty vdc_flags ldy #<(__INTERRUPTOR_COUNT__ * 2) beq @L1 phx pha jsr callirq_y pla plx @L1: ply __nmi: rti �������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pce/joy/���������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015033�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pce/joy/pce-stdjoy.s���������������������������������������������������������������0000664�0000000�0000000�00000006016�13473601511�0017303�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 ; Jump table. .addr INSTALL .addr UNINSTALL .addr COUNT .addr READJOY ; ------------------------------------------------------------------------ ; Constants JOY_COUNT = 4 ; Number of joysticks we support .bss padbuffer: .res JOY_COUNT .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 a 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 clx ; 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 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 #.sizeof(padbuffer) bcc nextpad rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pce/joy_stat_stddrv.s��������������������������������������������������������������0000664�0000000�0000000�00000000371�13473601511�0017641�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 _joy_static_stddrv := _pce_stdjoy_joy �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pce/kplot.s������������������������������������������������������������������������0000664�0000000�0000000�00000001060�13473601511�0015544�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ .export PLOT .include "pce.inc" .include "extzp.inc" PLOT: bcs @getpos tya ;clc ; already cleared adc plotlo,x sta SCREEN_PTR cla adc plothi,x 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 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pce/libref.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000175�13473601511�0015664�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2013-05-31 ; .export joy_libref .import _exit joy_libref := _exit ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pce/memcpy.s�����������������������������������������������������������������������0000664�0000000�0000000�00000006075�13473601511�0015720�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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, popptr1 .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 popptr1 ; save src ; (Direct stack access is six cycles faster [total cycle count].) iny ; (Y=0 by popptr1, need '1' here) 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 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pce/memmove.s����������������������������������������������������������������������0000664�0000000�0000000�00000003322�13473601511�0016063�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pce/memset.s�����������������������������������������������������������������������0000664�0000000�0000000�00000004510�13473601511�0015710�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 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 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pce/psg.s��������������������������������������������������������������������������0000664�0000000�0000000�00000001602�13473601511�0015206�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ .export psg_init .include "pce.inc" .segment "ONCE" psg_init: stz PSG_GLOBAL_PAN ; Silence global balance ldx #6 - 1 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 ldy #$20 psg_clear_waveform: stz PSG_CHAN_DATA ; Clear waveform byte dey bne psg_clear_waveform dex bpl psg_clear_loop rts ������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pce/revers.s�����������������������������������������������������������������������0000664�0000000�0000000�00000001021�13473601511�0015716�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 1998-08-07, Ullrich von Bassewitz ; 2015-11-23, Greg King ; ; unsigned char __fastcall__ revers (unsigned char onoff); ; .export _revers .importzp RVS .proc _revers cmp #$01 ; False or true? cla ror a ; Either $00 or $80 ldy RVS ; Load old value sta RVS ; Set new value tya asl a rol a ; Either $00 or $01 clx rts .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pce/ticktock.s���������������������������������������������������������������������0000664�0000000�0000000�00000000575�13473601511�0016240�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ .interruptor ticktock .include "extzp.inc" ticktock: bbr5 vdc_flags,@s1 ; skip if 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 �����������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pce/vce.s��������������������������������������������������������������������������0000664�0000000�0000000�00000001043�13473601511�0015171�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ .export vce_init .include "pce.inc" .segment "ONCE" vce_init: ; Set CTA to zero stz VCE_ADDR_LO stz VCE_ADDR_HI ldy #$01 ; Only background palettes vce_clear_bank: clx ; ldx #<$0100 ; <(16 * 16) 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 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pce/vdc.s��������������������������������������������������������������������������0000664�0000000�0000000�00000001531�13473601511�0015172�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ .export vdc_init .include "pce.inc" ; FIXME: implement selection of different video modes at runtime HIRES = 1 vdc_init: lda VDC_CTRL VREG VDC_CR , $0000 ; disable display and interrupts VREG VDC_BXR, $0000 ; no scrolling VREG VDC_BYR, $0000 VREG VDC_MWR, $0070 ; 128 x 64 tiles (1024 x 512 pixels) VREG VDC_VSR, $1702 ; CRTC VREG VDC_VDR, $00DF ; CRTC - VDS VREG VDC_VCR, $000C ; CRTC - VDE VREG VDC_DCR, $0000 .if HIRES VREG VDC_HSR, $0C02 ; CRTC VREG VDC_HDR, $043C ; CRTC - HDS lda #$06 .else VREG VDC_HSR, $0202 ; CRTC VREG VDC_HDR, $041F ; CRTC - HDS lda #$04 .endif sta VCE_CTRL lda VDC_CTRL rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pce/vga.inc������������������������������������������������������������������������0000664�0000000�0000000�00000021570�13473601511�0015507�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������;---------------------------------------------------------------------------- ; VGA font for the PC-Engine conio implementation ; The character tiles use only two colors from each pallette. Color zero ; comes from pallette zero; color one is different in each pallette. The ; color of a character is set by choosing one of the 16 pallettes. .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 ����������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pce/waitvsync.s��������������������������������������������������������������������0000664�0000000�0000000�00000000514�13473601511�0016445�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Written by Groepaz <groepaz@gmx.net> ; ; void waitvsync (void); ; .export _waitvsync .forceimport ticktock ; make sure that tickcount changes .include "extzp.inc" .proc _waitvsync lda tickcount @lp: cmp tickcount beq @lp rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pce/wherex.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000672�13473601511�0015725�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-05-02 ; ; unsigned char wherex (void); ; .export _wherex .include "pce.inc" .include "extzp.inc" .proc _wherex lda CURS_X ldx #$00 rts .endproc ;------------------------------------------------------------------------------- ; force the init constructor to be imported .import initconio conio_init = initconio ����������������������������������������������������������������������cc65-2.18/libsrc/pce/wherey.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000672�13473601511�0015726�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-05-02 ; ; unsigned char wherey (void); ; .export _wherey .include "pce.inc" .include "extzp.inc" .proc _wherey lda CURS_Y ldx #$00 rts .endproc ;------------------------------------------------------------------------------- ; force the init constructor to be imported .import initconio conio_init = initconio ����������������������������������������������������������������������cc65-2.18/libsrc/pet/�������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014253�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/_scrsize.s���������������������������������������������������������������������0000664�0000000�0000000�00000000434�13473601511�0016261�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.10.2000 ; ; Screen size variables ; .export screensize .include "pet.inc" .proc screensize ldx SCR_LINELEN inx ; Variable is one less ldy #25 rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/break.s������������������������������������������������������������������������0000664�0000000�0000000�00000004313�13473601511�0015524�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.11.1998 ; ; void __fastcall__ set_brk (unsigned Addr); ; void reset_brk (void); ; .export _set_brk, _reset_brk .destructor _reset_brk .export _brk_a, _brk_x, _brk_y, _brk_sr, _brk_pc .include "pet.inc" .bss _brk_a: .res 1 _brk_x: .res 1 _brk_y: .res 1 _brk_sr: .res 1 _brk_pc: .res 2 oldvec: .res 2 ; Old vector .data uservec: jmp $FFFF ; Patched at runtime .code ; Set the break vector .proc _set_brk sta uservec+1 stx uservec+2 ; Set the user vector lda oldvec ora oldvec+1 ; Did we save the vector already? bne L1 ; Jump if we installed the handler already lda BRKVec sta oldvec lda BRKVec+1 sta oldvec+1 ; Save the old vector L1: lda #<brk_handler ; Set the break vector to our routine ldx #>brk_handler sta BRKVec stx BRKVec+1 rts .endproc ; Reset the break vector .proc _reset_brk lda oldvec ldx oldvec+1 beq @L9 ; Jump if vector not installed sta BRKVec stx BRKVec+1 lda #$00 sta oldvec ; Clear the old vector stx oldvec+1 @L9: rts .endproc ; Break handler, called if a break occurs .proc brk_handler pla sta _brk_y pla sta _brk_x pla sta _brk_a pla and #$EF ; Clear break bit sta _brk_sr pla ; PC low sec sbc #2 ; Point to start of brk sta _brk_pc pla ; PC high sbc #0 sta _brk_pc+1 jsr uservec ; Call the user's routine lda _brk_pc+1 pha lda _brk_pc pha lda _brk_sr pha ldx _brk_x ldy _brk_y lda _brk_a rti ; Jump back... .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/cgetc.s������������������������������������������������������������������������0000664�0000000�0000000�00000003146�13473601511�0015530�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; char cgetc (void); ; .export _cgetc .import cursor .include "pet.inc" _cgetc: lda KEY_COUNT ; Get number of characters bne L3 ; Jump if there are already chars waiting ; Switch on the cursor if needed lda CURS_FLAG pha lda cursor jsr setcursor L1: lda KEY_COUNT beq L1 ldx #0 pla bne L2 inx L2: txa jsr setcursor ; Fetch the character from the keyboard buffer L3: sei ldy KEY_BUF ldx #$00 L4: lda KEY_BUF+1,x sta KEY_BUF,x inx cpx KEY_COUNT bne L4 dec KEY_COUNT cli ldx #$00 ; Clear high byte tya rts ; Switch the cursor on or off setcursor: tax ; On or off? bne seton ; Go set it on lda CURS_FLAG ; Is the cursor currently off? bne crs9 ; Jump if yes lda #1 sta CURS_FLAG ; Mark it as off lda CURS_STATE ; Cursor currently displayed? beq crs8 ; Jump if no ldy CURS_X ; Get the character column lda (SCREEN_PTR),y ; Get character eor #$80 sta (SCREEN_PTR),y ; Store character back crs8: lda #0 sta CURS_STATE ; Cursor not displayed crs9: rts seton: lda #0 sta CURS_FLAG rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/checkst.s����������������������������������������������������������������������0000664�0000000�0000000�00000000605�13473601511�0016064�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 19.11.2002 ; ; The kernal open routines do not return a carry on error, so check the IEEE ; status, set carry flag and return ; .export checkst .importzp ST .proc checkst lda ST beq @L1 lda #5 ; ### Device not present sec rts @L1: clc rts .endproc ���������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/clrscr.s�����������������������������������������������������������������������0000664�0000000�0000000�00000001474�13473601511�0015735�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.11.1998 ; ; void clrscr (void); ; .export _clrscr .import plot .importzp ptr1 .include "pet.inc" _clrscr: ; Set the screen base address lda #$00 sta ptr1 lda #$80 sta ptr1+1 ; Determine, how many pages to fill ldx #4 lda SCR_LINELEN ; Check length of one line cmp #40+1 bcc L1 ldx #8 ; Clear the screen L1: lda #$20 ; Screen code for blank ldy #$00 L2: sta (ptr1),y iny bne L2 inc ptr1+1 dex bne L2 ; Set the cursor to 0/0 lda #0 sta CURS_X sta CURS_Y jmp plot rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/color.s������������������������������������������������������������������������0000664�0000000�0000000�00000000634�13473601511�0015560�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; 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 .import return0, return1 _textcolor = return1 _bgcolor = return0 _bordercolor = return0 ����������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/conio.s������������������������������������������������������������������������0000664�0000000�0000000�00000000250�13473601511�0015543�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.11.1998 ; ; Low level stuff for screen output/console input ; .exportzp CURS_X, CURS_Y .include "pet.inc" ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/cpeekcolor.s�������������������������������������������������������������������0000664�0000000�0000000�00000000247�13473601511�0016570�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2017-06-03, Greg King ; ; unsigned char cpeekcolor (void); ; .import return1 .export _cpeekcolor := return1 ; always COLOR_WHITE ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/cputc.s������������������������������������������������������������������������0000664�0000000�0000000�00000005466�13473601511�0015570�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; void cputcxy (unsigned char x, unsigned char y, char c); ; void cputc (char c); ; .export _cputcxy, _cputc, cputdirect, putchar .export newline, plot .import gotoxy .include "pet.inc" _cputcxy: pha ; Save C jsr gotoxy ; Set cursor, drop x and y pla ; Restore C ; Plot a character - also used as internal function _cputc: cmp #$0A ; CR? bne L1 lda #0 sta CURS_X beq plot ; Recalculate pointers L1: cmp #$0D ; LF? beq newline ; Recalculate pointers ; Printable char of some sort cmp #' ' bcc cputdirect ; Other control char tay bmi L10 cmp #$60 bcc L2 and #$DF bne cputdirect ; Branch always L2: and #$3F cputdirect: jsr putchar ; Write the character to the screen ; Advance cursor position advance: cpy SCR_LINELEN ; xsize-1 bne L3 jsr newline ; new line ldy #$FF ; + cr L3: iny sty CURS_X rts newline: lda SCR_LINELEN ; xsize-1 sec ; Account for -1 above adc SCREEN_PTR sta SCREEN_PTR bcc L4 inc SCREEN_PTR+1 L4: inc CURS_Y rts ; Handle character if high bit set L10: and #$7F cmp #$7E ; PI? bne L11 lda #$5E ; Load screen code for PI bne cputdirect L11: ora #$40 bne cputdirect ; Set cursor position, calculate RAM pointers plot: ldy CURS_Y lda ScrLo,y sta SCREEN_PTR lda ScrHi,y ldy SCR_LINELEN cpy #40+1 bcc @L1 asl SCREEN_PTR ; 80 column mode rol a @L1: ora #$80 ; Screen at $8000 sta SCREEN_PTR+1 rts ; Write one character to the screen without doing anything else, return X ; position in Y putchar: ora RVS ; Set revers bit ldy CURS_X sta (SCREEN_PTR),y ; Set char rts ; Screen address tables - offset to real screen .rodata ScrLo: .byte $00, $28, $50, $78, $A0, $C8, $F0, $18 .byte $40, $68, $90, $B8, $E0, $08, $30, $58 .byte $80, $A8, $D0, $F8, $20, $48, $70, $98 .byte $C0 ScrHi: .byte $00, $00, $00, $00, $00, $00, $00, $01 .byte $01, $01, $01, $01, $01, $02, $02, $02 .byte $02, $02, $02, $02, $03, $03, $03, $03 .byte $03 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/crt0.s�������������������������������������������������������������������������0000664�0000000�0000000�00000004655�13473601511�0015321�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Startup code for cc65 (PET version) ; .export _exit .export __STARTUP__ : absolute = 1 ; Mark as startup .import initlib, donelib .import zerobss, push0 .import callmain .import CLRCH, BSOUT .importzp ST .include "zeropage.inc" .include "pet.inc" .include "../cbm/cbm.inc" ; ------------------------------------------------------------------------ ; Startup code .segment "STARTUP" 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. The routine that is called by BSOUT to switch the ; character set will use FNLEN as temporary storage -- YUCK! Since the ; initmainargs routine, which parses the command line for arguments, needs that ; information, we need to save and restore it here. ; Thanks to Stefan Haubenthal for this information! lda FNLEN pha ; Save FNLEN lda #14 ; sta $E84C ; See PET FAQ jsr BSOUT pla sta FNLEN ; Restore FNLEN ; Clear the BSS data. jsr zerobss ; Save some system stuff; and, set up the stack. tsx stx spsave ; Save the system stack ptr lda MEMSIZE sta sp lda MEMSIZE+1 sta sp+1 ; Set argument stack ptr ; Call the module constructors. jsr initlib ; Push the command-line arguments; and, call main(). jsr callmain ; Call the module destructors. This is also the exit() entry. _exit: pha ; Save the return code on stack jsr donelib ; Copy back the zero-page stuff. ldx #zpspace-1 L2: lda zpsave,x sta sp,x dex bpl L2 ; Store the program return code into BASIC's status variable. pla sta ST ; Restore the stack pointer. ldx spsave txs ; Restore stack pointer ; Back to BASIC. rts ; ------------------------------------------------------------------------ .segment "INIT" zpsave: .res zpspace ; ------------------------------------------------------------------------ .bss spsave: .res 1 mmusave:.res 1 �����������������������������������������������������������������������������������cc65-2.18/libsrc/pet/devnum.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000156�13473601511�0015737�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2010-02-14 ; .include "pet.inc" .exportzp devnum := DEVNUM ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/get_tv.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000561�13473601511�0015731�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2004-10-26 ; ; unsigned char get_tv (void); ; /* Return the video mode the machine is using */ ; .include "pet.inc" .include "get_tv.inc" ;-------------------------------------------------------------------------- ; _get_tv .proc _get_tv lda #TV::OTHER ldx #0 rts .endproc �����������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/irq.s��������������������������������������������������������������������������0000664�0000000�0000000�00000002045�13473601511�0015233�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; IRQ handling (PET version) ; .export initirq, doneirq .import callirq .include "pet.inc" ; ------------------------------------------------------------------------ .segment "ONCE" initirq: lda IRQVec ldx IRQVec+1 sta IRQInd+1 stx IRQInd+2 lda #<IRQStub ldx #>IRQStub jmp setvec ; ------------------------------------------------------------------------ .code doneirq: lda IRQInd+1 ldx IRQInd+2 setvec: sei sta IRQVec stx IRQVec+1 cli rts ; ------------------------------------------------------------------------ .segment "LOWCODE" IRQStub: cld ; Just to be sure jsr callirq ; Call the functions jmp IRQInd ; Jump to the saved IRQ vector ; ------------------------------------------------------------------------ .data IRQInd: jmp $0000 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/joy/���������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015054�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/joy/pet-ptvjoy.s���������������������������������������������������������������0000664�0000000�0000000�00000005437�13473601511�0017372�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; PTV-2 Player joystick driver for the PET ; ; Stefan Haubenthal, 2005-05-25 ; Groepaz/Hitmen, 2002-12-23 ; obviously based on Ullrichs driver :) ; .include "zeropage.inc" .include "joy-kernel.inc" .include "joy-error.inc" .include "pet.inc" .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _pet_ptvjoy_joy ; Driver signature .byte $6A, $6F, $79 ; "joy" .byte JOY_API_VERSION ; Driver API version number ; Library reference .addr $0000 ; Jump table. .addr INSTALL .addr UNINSTALL .addr COUNT .addr READ ; ------------------------------------------------------------------------ ; Constants JOY_COUNT = 2 ; 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 ; ------------------------------------------------------------------------ ; UNINSTALL 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. ; COUNT: lda #<JOY_COUNT ldx #>JOY_COUNT rts ; ------------------------------------------------------------------------ ; READ: Read a particular joystick passed in A. ; READ: lda #%10000000 ; via port A Data-Direction sta VIA_DDRA ; bit 7: out bit 6-0: in tax ; Joystick number into X bne joy2 ; Read joystick 1 joy1: lda #$80 ; via port A read/write sta VIA_PA1 ; (output one at PA7) lda VIA_PA1 ; via port A read/write and #$1f ; get bit 4-0 (PA4-PA0) eor #$1f rts ; Read joystick 2 joy2: lda #$00 ; via port A read/write sta VIA_PA1 ; (output zero at PA7) lda VIA_PA1 ; via port A read/write and #$0f ; get bit 3-0 (PA3-PA0) sta tmp1 ; joy 4 directions lda VIA_PA1 ; via port A read/write and #%00100000 ; get bit 5 (PA5) lsr ora tmp1 eor #$1f ldx #0 rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/joy/pet-stdjoy.s���������������������������������������������������������������0000664�0000000�0000000�00000004757�13473601511�0017357�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Standard PET userport joystick driver for the PET ; ; Marco van den Heuvel, 2010-01-23 ; .include "zeropage.inc" .include "joy-kernel.inc" .include "joy-error.inc" .include "pet.inc" .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _pet_stdjoy_joy ; Driver signature .byte $6A, $6F, $79 ; "joy" .byte JOY_API_VERSION ; Driver API version number ; Library reference .addr $0000 ; Jump table. .addr INSTALL .addr UNINSTALL .addr COUNT .addr READ ; ------------------------------------------------------------------------ ; Constants JOY_COUNT = 2 ; 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 ; ------------------------------------------------------------------------ ; UNINSTALL 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. ; COUNT: lda #<JOY_COUNT ldx #>JOY_COUNT rts ; ------------------------------------------------------------------------ ; READ: Read a particular joystick passed in A. ; READ: tax ; Joystick number into X bne joy2 ; Read joystick 1 joy1: lda #0 sta VIA_DDRA lda VIA_PA1 and #$0f cmp #$0c bne @notc1 lda #$0f bne @end1 @notc1: ora #$10 @end1: eor #$1f rts ; Read joystick 2 joy2: lda #0 sta VIA_DDRA lda VIA_PA1 lsr lsr lsr lsr cmp #$0c bne @notc2 lda #$0f bne @end2 @notc2: ora #$10 @end2: eor #$1f ldx #0 rts �����������������cc65-2.18/libsrc/pet/joy_stat_stddrv.s��������������������������������������������������������������0000664�0000000�0000000�00000000354�13473601511�0017663�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Address of the static standard joystick driver ; ; Oliver Schmidt, 2012-11-01 ; ; const void joy_static_stddrv[]; ; .export _joy_static_stddrv .import _pet_stdjoy_joy .rodata _joy_static_stddrv := _pet_stdjoy_joy ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/joy_stddrv.s�������������������������������������������������������������������0000664�0000000�0000000�00000000277�13473601511�0016634�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Name of the standard joystick driver ; ; Ullrich von Bassewitz, 2002-12-21 ; ; const char joy_stddrv[]; ; .export _joy_stddrv .rodata _joy_stddrv: .asciiz "pet-stdjoy.joy" ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/kbhit.s������������������������������������������������������������������������0000664�0000000�0000000�00000000533�13473601511�0015541�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.11.1998 ; ; unsigned char kbhit (void); ; .export _kbhit .include "pet.inc" .proc _kbhit ldx #0 ; High byte of return is always zero lda KEY_COUNT ; Get number of characters beq L9 lda #1 L9: rts .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/kbrepeat.s���������������������������������������������������������������������0000664�0000000�0000000�00000001412�13473601511�0016232�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; unsigned char __fastcall__ kbrepeat (unsigned char mode); ; ; 2017-06-16, Groepaz ; 2017-09-05, Greg King ; .export _kbrepeat .include "pet.inc" _kbrepeat: ldx #>$0000 ldy SCR_LINELEN cpy #40 + 1 bcc L1 ; branch if screen is 40 columns wide ldy KBDREPEAT80 ; get old value sta KBDREPEAT80 ; store new value tya ; return old value rts L1: tay lda KBDREPEAT40B ; get REPEAT-key flag (used by some editor ROMs) lsr a ; move bit 0 into bit 7 ror a ora KBDREPEAT40 ; combine with old key-REPEAT flags sty KBDREPEAT40 rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/kbsout.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000454�13473601511�0015751�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 19.11.2002 ; ; BSOUT replacement function for the PETs ; .export BSOUT .import checkst .proc BSOUT jsr $FFD2 ; Call kernal function jmp checkst ; Check status, return carry on error .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/kchkin.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000455�13473601511�0015712�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 19.11.2002 ; ; CHKIN replacement function for the PETs ; .export CHKIN .import checkst .proc CHKIN jsr $FFC6 ; Call kernal function jmp checkst ; Check status, return carry on error .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/kckout.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000454�13473601511�0015742�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 19.11.2002 ; ; CKOUT replacement function for the PETs ; .export CKOUT .import checkst .proc CKOUT jsr $FFC9 ; Call kernal function jmp checkst ; Check status, return carry on error .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/kclose.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000521�13473601511�0015715�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 19.11.2002 ; ; CLOSE replacement function for the PETs ; .export CLOSE .include "pet.inc" .proc CLOSE ldx PET_DETECT cpx #PET_4000 bne @L1 jmp $F2E2 ; BASIC 4 @L1: jmp $F2AE ; BASIC 2&3 .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/kernal.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000430�13473601511�0015710�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 19.11.2002 ; ; PET kernal functions ; .include "cbm_kernal.inc" .export CLRCH .export BASIN .export STOP .export GETIN .export CLALL .export UDTIM ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/kopen.s������������������������������������������������������������������������0000664�0000000�0000000�00000000640�13473601511�0015553�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 19.11.2002 ; ; OPEN replacement function for the PETs ; .export OPEN .import checkst .include "pet.inc" .proc OPEN lda PET_DETECT cmp #PET_4000 bne @L1 jsr $F563 ; BASIC 4 jmp checkst @L1: jsr $F524 ; BASIC 2&3 jmp checkst .endproc ������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/kplot.s������������������������������������������������������������������������0000664�0000000�0000000�00000000650�13473601511�0015571�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2002-12-12 ; ; PLOT replacement function for the PETs ; .export PLOT .import plot ; from cputc.s .include "pet.inc" .proc PLOT bcs @L1 ; Fetch values if carry set sty CURS_X stx CURS_Y jsr plot @L1: ldy CURS_X ldx CURS_Y rts .endproc ����������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/krdtim.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000431�13473601511�0015727�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 19.11.2002 ; ; RDTIM replacement function for the PETs ; .export RDTIM .include "pet.inc" .proc RDTIM sei lda TIME+2 ldx TIME+1 ldy TIME cli rts .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/kreadst.s����������������������������������������������������������������������0000664�0000000�0000000�00000000315�13473601511�0016073�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 19.11.2002 ; ; READST replacement function for the PETs ; .export READST .importzp ST .proc READST lda ST rts .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/ksetlfs.s����������������������������������������������������������������������0000664�0000000�0000000�00000000514�13473601511�0016112�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 19.11.2002 ; ; SETLFS replacement function for the PETs ; .export SETLFS .include "pet.inc" .proc SETLFS sta LFN ; LFN stx DEVNUM ; Device address sty SECADR ; Secondary address rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/ksetnam.s����������������������������������������������������������������������0000664�0000000�0000000�00000000405�13473601511�0016100�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 19.11.2002 ; ; SETNAM replacement function for the PETs ; .export SETNAM .include "pet.inc" .proc SETNAM sta FNLEN stx FNADR sty FNADR+1 rts .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/libref.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000175�13473601511�0015705�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2013-05-31 ; .export joy_libref .import _exit joy_libref := _exit ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/mainargs.s���������������������������������������������������������������������0000664�0000000�0000000�00000006723�13473601511�0016250�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-03-07 ; Stefan Haubenthal, 2008-08-11 ; ; Setup arguments for main ; .constructor initmainargs, 24 .import __argc, __argv .include "pet.inc" MAXARGS = 10 ; Maximum number of arguments allowed REM = $8f ; BASIC token-code NAME_LEN = 16 ; Maximum length of command-name ;--------------------------------------------------------------------------- ; Get possible command-line arguments. Goes into the special ONCE segment, ; which may be reused after the startup code is run .segment "ONCE" .proc initmainargs ; Assume that the program was loaded, a moment ago, by the traditional LOAD ; statement. Save the "most-recent filename" as argument #0. lda #0 ; The terminating NUL character ldy FNLEN cpy #NAME_LEN + 1 bcc L1 ldy #NAME_LEN ; Limit the length bne L1 ; Branch always L0: lda (FNADR),y L1: sta name,y dey bpl L0 inc __argc ; argc always is equal to, at least, 1 ; Find the "rem" token. ldx #0 L2: lda BASIC_BUF,x beq done ; No "rem," no args. inx cmp #REM bne L2 ldy #1 * 2 ; Find the next argument next: lda BASIC_BUF,x beq done ; End of line reached inx cmp #' ' ; Skip leading spaces 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 ; will check now for a quoted argument, in which case we will have to skip this ; first character. found: cmp #'"' ; Is the argument quoted? beq setterm ; Jump if so dex ; Reset pointer to first argument character lda #' ' ; A space ends the argument setterm:sta term ; Set end of argument marker ; Now store a pointer to the argument into the next slot. Since the BASIC ; input buffer is located at the start of a RAM page, no calculations are ; necessary. txa ; Get low byte sta argv,y ; argv[y]= &arg iny lda #>BASIC_BUF sta argv,y iny inc __argc ; Found another arg ; Search for the end of the argument argloop:lda BASIC_BUF,x beq done inx cmp term bne argloop ; 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 #0 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? bcc 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 .endproc .segment "INIT" term: .res 1 name: .res NAME_LEN + 1 .data ; char* argv[MAXARGS+1]={name}; argv: .addr name .res MAXARGS * 2 ���������������������������������������������cc65-2.18/libsrc/pet/randomize.s��������������������������������������������������������������������0000664�0000000�0000000�00000000600�13473601511�0016423�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2002-11-05, Ullrich von Bassewitz ; 2015-09-11, Greg King ; ; void _randomize (void); ; /* Initialize the random number generator */ ; .export __randomize .import _srand .include "pet.inc" __randomize: ldx TIME+2 lda TIME+1 ; Use 60HZ clock jmp _srand ; Initialize generator ��������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/revers.s�����������������������������������������������������������������������0000664�0000000�0000000�00000001401�13473601511�0015741�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 07.08.1998 ; ; unsigned char revers (unsigned char onoff); ; .export _revers .include "pet.inc" .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 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/status.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000134�13473601511�0015760�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2012-09-30 ; .exportzp ST := $96 ; IEC status byte ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/pet/sysuname.s���������������������������������������������������������������������0000664�0000000�0000000�00000001447�13473601511�0016311�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-08-12 ; ; unsigned char __fastcall__ _sysuname (struct utsname* buf); ; .export __sysuname, utsdata .import utscopy __sysuname = utscopy ;-------------------------------------------------------------------------- ; Data. We define a fixed utsname struct here and just copy it. .rodata utsdata: ; sysname .asciiz "cc65" ; nodename .asciiz "" ; release .byte ((.VERSION >> 8) & $0F) + '0' .byte '.' .byte ((.VERSION >> 4) & $0F) + '0' .byte $00 ; version .byte (.VERSION & $0F) + '0' .byte $00 ; machine .asciiz "Commodore PET" �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/plus4/�����������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014532�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/plus4/_scrsize.s�������������������������������������������������������������������0000664�0000000�0000000�00000000517�13473601511�0016542�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.10.2000 ; ; Screen size variables ; .export screensize ; We will return the values directly instead of banking in the ROM and calling ; SCREEN which is a lot more overhead in code size and CPU cycles. .proc screensize ldx #40 ldy #25 rts .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/plus4/break.s����������������������������������������������������������������������0000664�0000000�0000000�00000003410�13473601511�0016000�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 27.09.1998 ; ; void __fastcall__ set_brk (unsigned Addr); ; void reset_brk (void); ; .export _set_brk, _reset_brk .export _brk_a, _brk_x, _brk_y, _brk_sr, _brk_pc .import brk_jmp .include "plus4.inc" .bss _brk_a: .res 1 _brk_x: .res 1 _brk_y: .res 1 _brk_sr: .res 1 _brk_pc: .res 2 oldvec: .res 2 ; Old vector .data uservec: jmp $FFFF ; Patched at runtime .code ; Set the break vector .proc _set_brk sta uservec+1 stx uservec+2 ; Set the user vector lda #<brk_handler ; Set the break vector to our routine sta brk_jmp+1 lda #>brk_handler sta brk_jmp+2 rts .endproc ; Reset the break vector .proc _reset_brk lda #$00 sta brk_jmp+1 sta brk_jmp+2 ; Reset the vector rts .endproc ; Break handler, called if a break occurs. .proc brk_handler pla sta _brk_y pla sta _brk_x pla sta _brk_a pla and #$EF ; Clear break bit sta _brk_sr pla ; PC low sec sbc #2 ; Point to start of brk sta _brk_pc pla ; PC high sbc #0 sta _brk_pc+1 jsr uservec ; Call the user's routine lda _brk_pc+1 pha lda _brk_pc pha lda _brk_sr pha ldx _brk_x ldy _brk_y lda _brk_a rti ; Jump back... .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/plus4/cgetc.s����������������������������������������������������������������������0000664�0000000�0000000�00000004756�13473601511�0016017�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; char cgetc (void); ; .export _cgetc .import cursor .include "cbm_kernal.inc" .include "plus4.inc" ; -------------------------------------------------------------------------- .segment "LOWCODE" ; Accesses the ROM - must go into low mem _cgetc: lda KEY_COUNT ; Get number of characters ora FKEY_COUNT ; Or with number of function key chars bne L2 ; Jump if there are already chars waiting ; Switch on the cursor if needed ldy CURS_X lda (CRAM_PTR),y ; Get current char pha ; And save it lda CHARCOLOR sta (CRAM_PTR),y lda cursor beq L1 ; Jump if no cursor tya clc adc SCREEN_PTR sta TED_CURSLO lda SCREEN_PTR+1 adc #$00 sbc #$0B ; + carry = $C00 (screen address) sta TED_CURSHI L1: lda KEY_COUNT ora FKEY_COUNT beq L1 pla sta (CRAM_PTR),y lda #$ff sta TED_CURSLO ; Cursor off sta TED_CURSHI L2: sta ENABLE_ROM ; Bank in the ROM jsr KBDREAD ; Read char and return in A (ROM routine) sta ENABLE_RAM ; Reenable the RAM ldx #0 rts ; -------------------------------------------------------------------------- ; Make the function keys return function key codes instead of the current ; strings so the program will see and may handle them. ; Undo this change when the program ends .constructor initkbd .destructor donekbd .segment "ONCE" ; Special init code segment may get overwritten .proc initkbd ldy #7 @L1: lda fnkeys,y sta FKEY_SPACE+8,y lda #$01 ; Lower 8 places are all $01 sta FKEY_SPACE,y dey bpl @L1 rts .endproc fnkeys: .byte 133, 137, 134, 138, 135, 139, 136, 140 .segment "LOWCODE" ; Accesses the ROM - must go into low mem .proc donekbd ldx #$39 ; Copy the original function keys sta ENABLE_ROM ; Bank in the ROM @L1: lda FKEY_ORIG,x sta FKEY_SPACE,x dex bpl @L1 sta ENABLE_RAM ; Bank out the ROM rts .endproc ������������������cc65-2.18/libsrc/plus4/clrscr.s���������������������������������������������������������������������0000664�0000000�0000000�00000000774�13473601511�0016216�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; void clrscr (void); ; .export _clrscr .include "cbm_kernal.inc" .include "plus4.inc" .segment "LOWCODE" ; Must go into low memory .proc _clrscr sta ENABLE_ROM ; Enable the ROM jsr CLRSCR ; Call the ROM routine sta ENABLE_RAM ; Switch back to RAM rts ; Return to caller .endproc ����cc65-2.18/libsrc/plus4/color.s����������������������������������������������������������������������0000664�0000000�0000000�00000001330�13473601511�0016031�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; 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 "plus4.inc" _textcolor: ldx CHARCOLOR ; get old value sta CHARCOLOR ; set new value txa rts _bgcolor: ldx TED_BGCOLOR ; get old value sta TED_BGCOLOR ; set new value txa rts _bordercolor: ldx TED_BORDERCOLOR ; get old value sta TED_BORDERCOLOR ; set new value txa rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/plus4/conio.s����������������������������������������������������������������������0000664�0000000�0000000�00000000252�13473601511�0016024�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; Low level stuff for screen output/console input ; .exportzp CURS_X, CURS_Y .include "plus4.inc" ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/plus4/cputc.s����������������������������������������������������������������������0000664�0000000�0000000�00000004470�13473601511�0016041�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; void cputcxy (unsigned char x, unsigned char y, char c); ; void cputc (char c); ; .export _cputcxy, _cputc, cputdirect, putchar .export newline, plot .import gotoxy .import PLOT .include "plus4.inc" _cputcxy: pha ; Save C jsr gotoxy ; Set cursor, drop x and y pla ; Restore C ; Plot a character - also used as internal function _cputc: cmp #$0A ; CR? bne L1 lda #0 sta CURS_X beq plot ; Recalculate pointers L1: cmp #$0D ; LF? beq newline ; Recalculate pointers ; Printable char of some sort cmp #' ' bcc cputdirect ; Other control char tay bmi L10 cmp #$60 bcc L2 and #$DF bne cputdirect ; Branch always L2: and #$3F cputdirect: jsr putchar ; Write the character to the screen ; Advance cursor position advance: iny cpy #XSIZE bne L3 jsr newline ; new line ldy #0 ; + cr L3: sty CURS_X rts newline: clc lda #XSIZE adc SCREEN_PTR sta SCREEN_PTR bcc L4 inc SCREEN_PTR+1 clc L4: lda #XSIZE adc CRAM_PTR sta CRAM_PTR bcc L5 inc CRAM_PTR+1 L5: inc CURS_Y rts ; Handle character if high bit set L10: and #$7F cmp #$7E ; PI? bne L11 lda #$5E ; Load screen code for PI bne cputdirect L11: ora #$40 bne cputdirect ; 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 ldy CURS_X sta (SCREEN_PTR),y ; Set char lda CHARCOLOR sta (CRAM_PTR),y ; Set color rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/plus4/crt0.s�����������������������������������������������������������������������0000664�0000000�0000000�00000012576�13473601511�0015601�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Startup code for cc65 (Plus/4 version) ; .export _exit .export brk_jmp .export __STARTUP__ : absolute = 1 ; Mark as startup .import callirq_y, initlib, donelib .import callmain, zerobss .import __INTERRUPTOR_COUNT__ .import __MAIN_START__, __MAIN_SIZE__ ; Linker generated .import __STACKSIZE__ ; Linker generated .importzp ST .include "zeropage.inc" .include "plus4.inc" ; ------------------------------------------------------------------------ ; Constants IRQInd = $500 ; JMP $0000 - used as indirect IRQ vector ; ------------------------------------------------------------------------ ; Startup code .segment "STARTUP" Start: ; Save the zero-page locations that we need. sei ; No interrupts since we're banking out the ROM sta ENABLE_RAM ldx #zpspace-1 L1: lda sp,x sta zpsave,x dex bpl L1 sta ENABLE_ROM cli ; Switch to the second charset. lda #14 jsr $FFD2 ; BSOUT ; Save some system stuff; and, set up the stack. The stack starts at the top ; of the usable RAM. tsx stx spsave ; Save system stk ptr lda #<(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__) ldx #>(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__) sta sp stx sp+1 ; Set up the IRQ vector in the banked RAM; and, switch off the ROM. ldx #<IRQ ldy #>IRQ sei ; No ints, handler not yet in place sta ENABLE_RAM stx $FFFE ; Install interrupt handler sty $FFFF cli ; Allow interrupts ; Clear the BSS data. jsr zerobss ; Initialize irqcount, which means that, from now on, custom linked-in IRQ ; handlers will be called (via condes). lda #.lobyte(__INTERRUPTOR_COUNT__*2) sta irqcount ; Call the module constructors. jsr initlib ; Push the command-line arguments; and, call main(). jsr callmain ; Back from main() [this is also the exit() entry]. Run the module destructors. _exit: pha ; Save the return code jsr donelib ; Run module destructors ; Disable the chained IRQ handlers. lda #0 sta irqcount ; Disable custom IRQ handlers ; Copy back the zero-page stuff. ldx #zpspace-1 L2: lda zpsave,x sta sp,x dex bpl L2 ; Place the program return code into BASIC's status variable. pla sta ST ; Restore the stack pointer. ldx spsave txs ; Enable the ROM; and, return to BASIC. sta ENABLE_ROM rts ; ------------------------------------------------------------------------ ; IRQ handler. The handler in the ROM enables the Kernal, and jumps to ; $CE00, where the ROM code checks for a BRK or IRQ, and branches via the ; indirect vectors at $314/$316. ; To make our stub as fast as possible, we skip the whole part of the ROM ; handler, and jump to the indirect vectors directly. We do also call our ; own interrupt handlers if we have any; so, they need not use $314. .segment "LOWCODE" IRQ: cld ; Just to be sure pha txa pha tya pha tsx ; Get the stack pointer lda $0104,x ; Get the saved status register and #$10 ; Test for BRK bit bne dobreak ; It's an IRQ; and, RAM is enabled. If we have handlers, call them. We will use ; a flag here instead of loading __INTERRUPTOR_COUNT__ directly, since the ; condes function is not reentrant. The irqcount flag will be set/reset from ; the main code, to avoid races. ldy irqcount beq @L1 jsr callirq_y ; Call the IRQ functions ; Since the ROM handler will end with an RTI, we have to fake an IRQ return ; on the stack, so that we get control of the CPU after the ROM handler, ; and can switch back to RAM. @L1: lda #>irq_ret ; Push new return address pha lda #<irq_ret pha php ; Push faked IRQ frame on stack pha ; Push faked A register pha ; Push faked X register pha ; Push faked Y register sta ENABLE_ROM ; Switch to ROM jmp (IRQVec) ; Jump indirect to Kernal IRQ handler irq_ret: sta ENABLE_RAM ; Switch back to RAM pla tay pla tax pla rti dobreak: lda brk_jmp+2 ; Check high byte of address beq nohandler jmp brk_jmp ; Jump to the handler ; No break handler installed, jump to ROM. nohandler: sta ENABLE_ROM jmp (BRKVec) ; Jump indirect to the break vector ; ------------------------------------------------------------------------ ; Data .data ; BRK handling brk_jmp: jmp $0000 spsave: .res 1 irqcount: .byte 0 .segment "INIT" zpsave: .res zpspace ����������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/plus4/devnum.s���������������������������������������������������������������������0000664�0000000�0000000�00000000160�13473601511�0016211�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2010-02-14 ; .include "plus4.inc" .exportzp devnum := DEVNUM ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/plus4/fast.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000444�13473601511�0015655�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Marco van den Heuvel, 2018-03-20 ; ; void fast (void); ; /* Switch the CPU into double clock mode. */ ; .export _fast .include "plus4.inc" .proc _fast lda TED_CLK and #%11111101 sta TED_CLK rts .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/plus4/get_tv.s���������������������������������������������������������������������0000664�0000000�0000000�00000000772�13473601511�0016214�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2002-12-03 ; ; unsigned char get_tv (void); ; /* Return the video mode the machine is using */ ; .include "plus4.inc" .include "get_tv.inc" ;-------------------------------------------------------------------------- ; _get_tv .proc _get_tv ldx #TV::PAL ; Assume PAL bit TED_MULTI1 ; Test bit 6 bvc pal dex ; NTSC pal: txa ldx #0 rts .endproc ������cc65-2.18/libsrc/plus4/irq.s������������������������������������������������������������������������0000664�0000000�0000000�00000000155�13473601511�0015512�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; IRQ handling (Plus/4 version) ; .export initirq, doneirq initirq: doneirq: rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/plus4/isfast.s���������������������������������������������������������������������0000664�0000000�0000000�00000000474�13473601511�0016214�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Marco van den Heuvel, 2018-03-20 ; ; unsigned char isfast (void); ; /* Returns 1 if the CPU is in double clock mode. */ ; .export _isfast .include "plus4.inc" .proc _isfast lda TED_CLK lsr and #$01 ldx #$00 rts .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/plus4/joy/�������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015333�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/plus4/joy/plus4-stdjoy.s�����������������������������������������������������������0000664�0000000�0000000�00000005300�13473601511�0020076�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Standard joystick driver for the Plus/4 and C16. ; May be used multiple times when linked statically to an application. ; ; 2002-12-21, Ullrich von Bassewitz ; 2016-06-18, Greg King ; .include "joy-kernel.inc" .include "joy-error.inc" .include "plus4.inc" .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table .if .xmatch ("MODULE_LABEL", .string(MODULE_LABEL)) module_header _plus4_stdjoy_joy .else module_header MODULE_LABEL .endif ; Driver signature .byte $6A, $6F, $79 ; ASCII "joy" .byte JOY_API_VERSION ; Driver API version number ; Library reference .addr $0000 ; Jump table. .addr INSTALL .addr UNINSTALL .addr COUNT .addr READ ; ------------------------------------------------------------------------ ; Constants JOY_COUNT = 2 ; Number of joysticks we support ; ------------------------------------------------------------------------ ; Data. .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 ; ------------------------------------------------------------------------ ; UNINSTALL 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. ; COUNT: lda #<JOY_COUNT ldx #>JOY_COUNT rts ; ------------------------------------------------------------------------ ; READ: Read a particular joystick passed in A. ; READ: ldy #%11111011 ; Load index for joystick #1 tax ; Test joystick number beq @L1 ldy #%11111101 ; Load index for joystick #2 ldx #>$0000 ; (Return unsigned int) @L1: sei sty TED_KBD ; Read a joystick ... lda TED_KBD ; ... and some keys -- it's unavoidable cli eor #%11111111 ; The push buttons are in bits 6 and 7. Both of them cannot be %1 together. ; Therefore, bit 6 can be merged with bit 7. clc adc #%01000000 rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/plus4/joy_stat_stddrv.s������������������������������������������������������������0000664�0000000�0000000�00000000360�13473601511�0020137�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Address of the static standard joystick driver ; ; Oliver Schmidt, 2012-11-01 ; ; const void joy_static_stddrv[]; ; .export _joy_static_stddrv .import _plus4_stdjoy_joy .rodata _joy_static_stddrv := _plus4_stdjoy_joy ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/plus4/joy_stddrv.s�����������������������������������������������������������������0000664�0000000�0000000�00000000301�13473601511�0017077�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Name of the standard joystick driver ; ; Ullrich von Bassewitz, 2002-12-21 ; ; const char joy_stddrv[]; ; .export _joy_stddrv .rodata _joy_stddrv: .asciiz "plus4-stdjoy.joy" �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/plus4/kacptr.s���������������������������������������������������������������������0000664�0000000�0000000�00000000730�13473601511�0016202�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.11.2002 ; ; ACPTR replacement function ; .export ACPTR .include "plus4.inc" .segment "LOWCODE" ; Must go into low memory .proc ACPTR sta ENABLE_ROM ; Enable the ROM jsr $FFA5 ; Call the ROM routine sta ENABLE_RAM ; Switch back to RAM rts ; Return to caller .endproc ����������������������������������������cc65-2.18/libsrc/plus4/kbasin.s���������������������������������������������������������������������0000664�0000000�0000000�00000000745�13473601511�0016173�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.11.2002 ; ; BASIN replacement function ; .export BASIN .include "plus4.inc" .segment "LOWCODE" ; Must go into low memory .proc BASIN sta ENABLE_ROM ; Enable the ROM jsr $FFCF ; Call the ROM routine sta ENABLE_RAM ; Switch back to RAM rts ; Return to caller .endproc ���������������������������cc65-2.18/libsrc/plus4/kbhit.s����������������������������������������������������������������������0000664�0000000�0000000�00000000653�13473601511�0016023�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; unsigned char kbhit (void); ; .export _kbhit .include "plus4.inc" .proc _kbhit ldx #0 ; High byte of return is always zero lda KEY_COUNT ; Get number of characters ora FKEY_COUNT ; Or with number of chars from function keys beq L9 lda #1 L9: rts .endproc �������������������������������������������������������������������������������������cc65-2.18/libsrc/plus4/kbrepeat.s�������������������������������������������������������������������0000664�0000000�0000000�00000000474�13473601511�0016520�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; unsigned char __fastcall__ kbrepeat (unsigned char mode); ; .export _kbrepeat .include "plus4.inc" _kbrepeat: ldx KBDREPEAT ; get old value sta KBDREPEAT ; store new value txa ; return old value ldx #0 rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/plus4/kbsout.s���������������������������������������������������������������������0000664�0000000�0000000�00000000730�13473601511�0016225�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.11.2002 ; ; BSOUT replacement function ; .export BSOUT .include "plus4.inc" .segment "LOWCODE" ; Must go into low memory .proc BSOUT sta ENABLE_ROM ; Enable the ROM jsr $FFD2 ; Call the ROM routine sta ENABLE_RAM ; Switch back to RAM rts ; Return to caller .endproc ����������������������������������������cc65-2.18/libsrc/plus4/kchkin.s���������������������������������������������������������������������0000664�0000000�0000000�00000000730�13473601511�0016165�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.11.2002 ; ; CHKIN replacement function ; .export CHKIN .include "plus4.inc" .segment "LOWCODE" ; Must go into low memory .proc CHKIN sta ENABLE_ROM ; Enable the ROM jsr $FFC6 ; Call the ROM routine sta ENABLE_RAM ; Switch back to RAM rts ; Return to caller .endproc ����������������������������������������cc65-2.18/libsrc/plus4/kciout.s���������������������������������������������������������������������0000664�0000000�0000000�00000000730�13473601511�0016214�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.11.2002 ; ; CIOUT replacement function ; .export CIOUT .include "plus4.inc" .segment "LOWCODE" ; Must go into low memory .proc CIOUT sta ENABLE_ROM ; Enable the ROM jsr $FFA8 ; Call the ROM routine sta ENABLE_RAM ; Switch back to RAM rts ; Return to caller .endproc ����������������������������������������cc65-2.18/libsrc/plus4/kckout.s���������������������������������������������������������������������0000664�0000000�0000000�00000000730�13473601511�0016216�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.11.2002 ; ; CKOUT replacement function ; .export CKOUT .include "plus4.inc" .segment "LOWCODE" ; Must go into low memory .proc CKOUT sta ENABLE_ROM ; Enable the ROM jsr $FFC9 ; Call the ROM routine sta ENABLE_RAM ; Switch back to RAM rts ; Return to caller .endproc ����������������������������������������cc65-2.18/libsrc/plus4/kclall.s���������������������������������������������������������������������0000664�0000000�0000000�00000000730�13473601511�0016160�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.11.2002 ; ; CLALL replacement function ; .export CLALL .include "plus4.inc" .segment "LOWCODE" ; Must go into low memory .proc CLALL sta ENABLE_ROM ; Enable the ROM jsr $FFE7 ; Call the ROM routine sta ENABLE_RAM ; Switch back to RAM rts ; Return to caller .endproc ����������������������������������������cc65-2.18/libsrc/plus4/kclose.s���������������������������������������������������������������������0000664�0000000�0000000�00000001041�13473601511�0016172�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.11.2002 ; ; CLOSE replacement function ; .export CLOSE .include "plus4.inc" .segment "LOWCODE" ; Must go into low memory .proc CLOSE sta ENABLE_ROM ; Enable the ROM clc ; Force C64 compatible behaviour jsr $FFC3 ; Call the ROM routine sta ENABLE_RAM ; Switch back to RAM rts ; Return to caller .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/plus4/kclrch.s���������������������������������������������������������������������0000664�0000000�0000000�00000000730�13473601511�0016164�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.11.2002 ; ; CLRCH replacement function ; .export CLRCH .include "plus4.inc" .segment "LOWCODE" ; Must go into low memory .proc CLRCH sta ENABLE_ROM ; Enable the ROM jsr $FFCC ; Call the ROM routine sta ENABLE_RAM ; Switch back to RAM rts ; Return to caller .endproc ����������������������������������������cc65-2.18/libsrc/plus4/kiobase.s��������������������������������������������������������������������0000664�0000000�0000000�00000000733�13473601511�0016336�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.11.2002 ; ; IOBASE replacement function ; .export IOBASE .include "plus4.inc" .segment "LOWCODE" ; Must go into low memory .proc IOBASE sta ENABLE_ROM ; Enable the ROM jsr $FFF3 ; Call the ROM routine sta ENABLE_RAM ; Switch back to RAM rts ; Return to caller .endproc �������������������������������������cc65-2.18/libsrc/plus4/klisten.s��������������������������������������������������������������������0000664�0000000�0000000�00000000733�13473601511�0016372�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.11.2002 ; ; LISTEN replacement function ; .export LISTEN .include "plus4.inc" .segment "LOWCODE" ; Must go into low memory .proc LISTEN sta ENABLE_ROM ; Enable the ROM jsr $FFB1 ; Call the ROM routine sta ENABLE_RAM ; Switch back to RAM rts ; Return to caller .endproc �������������������������������������cc65-2.18/libsrc/plus4/kload.s����������������������������������������������������������������������0000664�0000000�0000000�00000000725�13473601511�0016014�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.11.2002 ; ; LOAD replacement function ; .export LOAD .include "plus4.inc" .segment "LOWCODE" ; Must go into low memory .proc LOAD sta ENABLE_ROM ; Enable the ROM jsr $FFD5 ; Call the ROM routine sta ENABLE_RAM ; Switch back to RAM rts ; Return to caller .endproc �������������������������������������������cc65-2.18/libsrc/plus4/kopen.s����������������������������������������������������������������������0000664�0000000�0000000�00000000725�13473601511�0016036�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.11.2002 ; ; OPEN replacement function ; .export OPEN .include "plus4.inc" .segment "LOWCODE" ; Must go into low memory .proc OPEN sta ENABLE_ROM ; Enable the ROM jsr $FFC0 ; Call the ROM routine sta ENABLE_RAM ; Switch back to RAM rts ; Return to caller .endproc �������������������������������������������cc65-2.18/libsrc/plus4/kplot.s����������������������������������������������������������������������0000664�0000000�0000000�00000000752�13473601511�0016053�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.11.2002 ; ; PLOT replacement function ; .export PLOT .include "plus4.inc" .segment "LOWCODE" ; Must go into low memory .proc PLOT sta ENABLE_ROM ; Enable the ROM jsr $FFF0 ; Call the ROM routine sta ENABLE_RAM ; Switch back to RAM rts ; Return to caller .endproc ����������������������cc65-2.18/libsrc/plus4/krdtim.s���������������������������������������������������������������������0000664�0000000�0000000�00000000772�13473601511�0016216�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.11.2002 ; ; RDTIM replacement function ; .export RDTIM .include "plus4.inc" ; Read the clock from the zero page to avoid banking in the ROM .proc RDTIM sei ; No interrupts lda TIME+2 ldx TIME+1 ldy TIME ; Read the time cli ; Allow interrupts rts ; Return to caller .endproc ������cc65-2.18/libsrc/plus4/kreadst.s��������������������������������������������������������������������0000664�0000000�0000000�00000000575�13473601511�0016362�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.11.2002 ; ; READST replacement function ; .export READST .include "plus4.inc" .importzp ST ; Read the status byte from the zero page instead of banking in the ROM .proc READST lda ST ; Load status rts ; Return to caller .endproc �����������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/plus4/ksave.s����������������������������������������������������������������������0000664�0000000�0000000�00000000725�13473601511�0016033�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.11.2002 ; ; SAVE replacement function ; .export SAVE .include "plus4.inc" .segment "LOWCODE" ; Must go into low memory .proc SAVE sta ENABLE_ROM ; Enable the ROM jsr $FFD8 ; Call the ROM routine sta ENABLE_RAM ; Switch back to RAM rts ; Return to caller .endproc �������������������������������������������cc65-2.18/libsrc/plus4/kscnkey.s��������������������������������������������������������������������0000664�0000000�0000000�00000000761�13473601511�0016371�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2002-11-22, Ullrich von Bassewitz ; 2016-08-07, Greg King ; ; SCNKEY replacement function ; .export SCNKEY .include "plus4.inc" .segment "LOWCODE" ; Must go into low memory .proc SCNKEY sta ENABLE_ROM ; Enable the ROM jsr $FF9F ; Call the ROM routine sta ENABLE_RAM ; Switch back to RAM rts ; Return to caller .endproc ���������������cc65-2.18/libsrc/plus4/ksetlfs.s��������������������������������������������������������������������0000664�0000000�0000000�00000000544�13473601511�0016374�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.11.2002 ; ; SETLFS replacement function ; .export SETLFS .include "plus4.inc" ; Write directly to the zero page to avoid banking in the ROM .proc SETLFS sta LFN stx DEVNUM sty SECADR rts ; Return to caller .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/plus4/ksetnam.s��������������������������������������������������������������������0000664�0000000�0000000�00000002440�13473601511�0016360�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.11.2002 ; ; SETNAM replacement function ; .export SETNAM .include "plus4.inc" ; This function is special in that the name must reside in low memory, ; otherwise it is not accessible by the ROM code. .segment "LOWCODE" ; Must go into low memory .proc SETNAM ; Store the length of the name into the zero page sta FNAM_LEN ; Check if we have to copy the name to low memory cmp #$00 ; Length zero? beq @L3 ; Yes: Copying not needed cpy #$00 ; Is the name in low memory? bpl @L3 ; Yes: Copying not needed ; Store the length and the pointer to the name stx TMPPTR sty TMPPTR+1 ; Store pointer to name in TMPPTR ; Copy the given name into FNBUF. ldy #$00 @L2: lda (TMPPTR),y sta FNBUF,y iny cpy FNAM_LEN bne @L2 ; Load the new parameters for the low memory buffer ldx #<FNBUF ldy #>FNBUF ; Instead of banking in the ROM, store the values directly into the zeropage @L3: stx FNAM sty FNAM+1 ; Return to caller rts .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/plus4/ksettim.s��������������������������������������������������������������������0000664�0000000�0000000�00000001011�13473601511�0016367�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.11.2002 ; ; SETTIM replacement function ; .export SETTIM .include "plus4.inc" ; Set the clock by writing directly to zero page to avoid banking in the ROM .proc SETTIM sei ; No interrupts sta TIME+2 stx TIME+1 sty TIME ; Set the time cli ; Allow interrupts rts ; Return to caller .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/plus4/ktalk.s����������������������������������������������������������������������0000664�0000000�0000000�00000000725�13473601511�0016030�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.11.2002 ; ; TALK replacement function ; .export TALK .include "plus4.inc" .segment "LOWCODE" ; Must go into low memory .proc TALK sta ENABLE_ROM ; Enable the ROM jsr $FFB4 ; Call the ROM routine sta ENABLE_RAM ; Switch back to RAM rts ; Return to caller .endproc �������������������������������������������cc65-2.18/libsrc/plus4/kudtim.s���������������������������������������������������������������������0000664�0000000�0000000�00000000756�13473601511�0016223�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2002-11-22, Ullrich von Bassewitz ; 2016-08-07, Greg King ; ; UDTIM replacement function ; .export UDTIM .include "plus4.inc" .segment "LOWCODE" ; Must go into low memory .proc UDTIM sta ENABLE_ROM ; Enable the ROM jsr $FFEA ; Call the ROM routine sta ENABLE_RAM ; Switch back to RAM rts ; Return to caller .endproc ������������������cc65-2.18/libsrc/plus4/kunlsn.s���������������������������������������������������������������������0000664�0000000�0000000�00000000730�13473601511�0016230�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.11.2002 ; ; UNLSN replacement function ; .export UNLSN .include "plus4.inc" .segment "LOWCODE" ; Must go into low memory .proc UNLSN sta ENABLE_ROM ; Enable the ROM jsr $FFAE ; Call the ROM routine sta ENABLE_RAM ; Switch back to RAM rts ; Return to caller .endproc ����������������������������������������cc65-2.18/libsrc/plus4/kuntlk.s���������������������������������������������������������������������0000664�0000000�0000000�00000000730�13473601511�0016226�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.11.2002 ; ; UNTLK replacement function ; .export UNTLK .include "plus4.inc" .segment "LOWCODE" ; Must go into low memory .proc UNTLK sta ENABLE_ROM ; Enable the ROM jsr $FFAB ; Call the ROM routine sta ENABLE_RAM ; Switch back to RAM rts ; Return to caller .endproc ����������������������������������������cc65-2.18/libsrc/plus4/libref.s���������������������������������������������������������������������0000664�0000000�0000000�00000000242�13473601511�0016157�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2013-05-31 ; .export joy_libref, ser_libref .import _exit joy_libref := _exit ser_libref := _exit ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/plus4/mainargs.s�������������������������������������������������������������������0000664�0000000�0000000�00000007765�13473601511�0016536�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; mainargs.s ; ; Ullrich von Bassewitz, 2003-03-07 ; Based on code from Stefan A. Haubenthal, <polluks@web.de> ; 2003-05-18, Greg King ; 2004-04-28, 2005-02-26, Ullrich von Bassewitz ; ; Scan a group of arguments that are in BASIC's input-buffer. ; Build an array that points to the beginning of each argument. ; Send, to main(), that array and the count of the arguments. ; ; Command-lines look like these lines: ; ; run ; run : rem ; run:rem arg1 " arg 2 is quoted " arg3 "" arg5 ; ; "run" and "rem" are entokenned; the args. are not. Leading and trailing ; spaces outside of quotes are ignored. ; ; TO-DO: ; - The "file-name" might be a path-name; don't copy the directory-components. ; - Add a control-character quoting mechanism. .constructor initmainargs, 24 .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 ; Get possible command-line arguments. Goes into the special ONCE segment, ; which may be reused after the startup code is run .segment "ONCE" initmainargs: ; Assume that the program was loaded, a moment ago, by the traditional LOAD ; statement. Save the "most-recent filename" as argument #0. lda #0 ; The terminating NUL character ldy FNAM_LEN cpy #NAME_LEN + 1 bcc L1 ldy #NAME_LEN ; Limit the length bne L1 ; Branch always L0: lda (FNAM),y L1: sta name,y dey bpl L0 inc __argc ; argc always is equal to, at least, 1 ; Find the "rem" token. ldx #0 L2: lda BASIC_BUF,x beq done ; No "rem," no args. inx cmp #REM bne L2 ldy #1 * 2 ; Find the next argument next: lda BASIC_BUF,x beq done ; End of line reached inx cmp #' ' ; Skip leading spaces 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 ; will check now for a quoted argument, in which case we will have to skip this ; first character. found: cmp #'"' ; Is the argument quoted? beq setterm ; Jump if so dex ; Reset pointer to first argument character lda #' ' ; A space ends the argument setterm:sta term ; Set end of argument marker ; Now store a pointer to the argument into the next slot. Since the BASIC ; input buffer is located at the start of a RAM page, no calculations are ; necessary. txa ; Get low byte sta argv,y ; argv[y]= &arg iny lda #>BASIC_BUF sta argv,y iny inc __argc ; Found another arg ; Search for the end of the argument argloop:lda BASIC_BUF,x beq done inx cmp term bne argloop ; 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 #0 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? bcc 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 .segment "INIT" term: .res 1 name: .res NAME_LEN + 1 .data ; char* argv[MAXARGS+1]={name}; argv: .addr name .res MAXARGS * 2 �����������cc65-2.18/libsrc/plus4/randomize.s������������������������������������������������������������������0000664�0000000�0000000�00000000707�13473601511�0016712�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2002-11-05, Ullrich von Bassewitz ; 2015-09-11, Greg King ; ; void _randomize (void); ; /* Initialize the random number generator */ ; .export __randomize .import _srand .include "plus4.inc" __randomize: ldx TED_VLINELO ; Use TED rasterline as high byte lda TIME+2 ; Use 60HZ clock as low byte jmp _srand ; Initialize generator ���������������������������������������������������������cc65-2.18/libsrc/plus4/revers.s���������������������������������������������������������������������0000664�0000000�0000000�00000001403�13473601511�0016222�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 07.08.1998 ; ; unsigned char revers (unsigned char onoff); ; .export _revers .include "plus4.inc" .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 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/plus4/ser/�������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015323�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/plus4/ser/plus4-stdser.s�����������������������������������������������������������0000664�0000000�0000000�00000030013�13473601511�0020055�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Serial driver for the built-in 6551 ACIA of the Plus/4. ; ; Ullrich von Bassewitz, 2003-12-13 ; ; The driver is based on the cc65 rs232 module, which in turn is based on ; Craig Bruce's device driver for the Switftlink/Turbo-232. ; ; SwiftLink/Turbo-232 v0.90 device driver, by Craig Bruce, 14-Apr-1998. ; ; This (C. Bruce) software is Public Domain. It is in Buddy assembler format. ; ; This device driver uses the SwiftLink RS-232 Serial Cartridge, available from ; Creative Micro Designs, Inc, and also supports the extensions of the Turbo232 ; Serial Cartridge. Both devices are based on the 6551 ACIA chip. It also ; supports the "hacked" SwiftLink with a 1.8432 MHz crystal. ; ; The code assumes that the kernal + I/O are in context. On the C128, call ; it from Bank 15. On the C64, don't flip out the Kernal unless a suitable ; NMI catcher is put into the RAM under the Kernal. For the SuperCPU, the ; interrupt handling assumes that the 65816 is in 6502-emulation mode. ; .include "zeropage.inc" .include "ser-kernel.inc" .include "ser-error.inc" .include "plus4.inc" .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _plus4_stdser_ser ; Driver signature .byte $73, $65, $72 ; ASCII "ser" .byte SER_API_VERSION ; Serial API version number ; Library reference .addr $0000 ; Jump table .word SER_INSTALL .word SER_UNINSTALL .word SER_OPEN .word SER_CLOSE .word SER_GET .word SER_PUT .word SER_STATUS .word SER_IOCTL .word SER_IRQ ;---------------------------------------------------------------------------- ; I/O definitions ACIA := $FD00 ACIA_DATA := ACIA+0 ; Data register ACIA_STATUS := ACIA+1 ; Status register ACIA_CMD := ACIA+2 ; Command register ACIA_CTRL := ACIA+3 ; Control register ;---------------------------------------------------------------------------- ; ; Global variables ; .bss RecvHead: .res 1 ; Head of receive buffer RecvTail: .res 1 ; Tail of receive buffer RecvFreeCnt: .res 1 ; Number of bytes in receive buffer SendHead: .res 1 ; Head of send buffer SendTail: .res 1 ; Tail of send buffer SendFreeCnt: .res 1 ; Number of bytes in send buffer Stopped: .res 1 ; Flow-stopped flag RtsOff: .res 1 ; ; Send and receive buffers: 256 bytes each RecvBuf: .res 256 SendBuf: .res 256 .rodata ; Tables used to translate RS232 params into register values BaudTable: ; bit7 = 1 means setting is invalid .byte $FF ; SER_BAUD_45_5 .byte $01 ; SER_BAUD_50 .byte $02 ; SER_BAUD_75 .byte $03 ; SER_BAUD_110 .byte $04 ; SER_BAUD_134_5 .byte $05 ; SER_BAUD_150 .byte $06 ; SER_BAUD_300 .byte $07 ; SER_BAUD_600 .byte $08 ; SER_BAUD_1200 .byte $09 ; SER_BAUD_1800 .byte $0A ; SER_BAUD_2400 .byte $0B ; SER_BAUD_3600 .byte $0C ; SER_BAUD_4800 .byte $0D ; SER_BAUD_7200 .byte $0E ; SER_BAUD_9600 .byte $0F ; SER_BAUD_19200 .byte $FF ; SER_BAUD_38400 .byte $FF ; SER_BAUD_57600 .byte $FF ; SER_BAUD_115200 .byte $FF ; SER_BAUD_230400 BitTable: .byte $60 ; SER_BITS_5 .byte $40 ; SER_BITS_6 .byte $20 ; SER_BITS_7 .byte $00 ; SER_BITS_8 StopTable: .byte $00 ; SER_STOP_1 .byte $80 ; SER_STOP_2 ParityTable: .byte $00 ; SER_PAR_NONE .byte $20 ; SER_PAR_ODD .byte $60 ; SER_PAR_EVEN .byte $A0 ; SER_PAR_MARK .byte $E0 ; SER_PAR_SPACE .code ;---------------------------------------------------------------------------- ; SER_INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present. ; Must return an SER_ERR_xx code in a/x. ; ; Since we don't have to manage the IRQ vector on the Plus/4, this is actually ; the same as: ; ; SER_UNINSTALL routine. Is called before the driver is removed from memory. ; Must return an SER_ERR_xx code in a/x. ; ; and: ; ; SER_CLOSE: Close the port, disable interrupts and flush the buffer. Called ; without parameters. Must return an error code in a/x. ; SER_INSTALL: SER_UNINSTALL: SER_CLOSE: ; Deactivate DTR and disable 6551 interrupts lda #%00001010 sta ACIA_CMD ; Done, return an error code lda #<SER_ERR_OK tax ; A is zero rts ;---------------------------------------------------------------------------- ; PARAMS routine. A pointer to a ser_params structure is passed in ptr1. ; Must return an SER_ERR_xx code in a/x. SER_OPEN: ; Check if the handshake setting is valid ldy #SER_PARAMS::HANDSHAKE ; Handshake lda (ptr1),y cmp #SER_HS_HW ; This is all we support bne InvParam ; Initialize buffers ldx #0 stx Stopped stx RecvHead stx RecvTail stx SendHead stx SendTail dex ; X = 255 stx RecvFreeCnt stx SendFreeCnt ; Set the value for the control register, which contains stop bits, word ; length and the baud rate. ldy #SER_PARAMS::BAUDRATE lda (ptr1),y ; Baudrate index tay lda BaudTable,y ; Get 6551 value bmi InvBaud ; Branch if rate not supported sta tmp1 ldy #SER_PARAMS::DATABITS ; Databits lda (ptr1),y tay lda BitTable,y ora tmp1 sta tmp1 ldy #SER_PARAMS::STOPBITS ; Stopbits lda (ptr1),y tay lda StopTable,y ora tmp1 ora #%00010000 ; Receiver clock source = baudrate sta ACIA_CTRL ; Set the value for the command register. We remember the base value in ; RtsOff, since we will have to manipulate ACIA_CMD often. ldy #SER_PARAMS::PARITY ; Parity lda (ptr1),y tay lda ParityTable,y ora #%00000001 ; DTR active sta RtsOff ora #%00001000 ; Enable receive interrupts sta ACIA_CMD ; Done lda #<SER_ERR_OK tax ; A is zero rts ; Invalid parameter InvParam: lda #<SER_ERR_INIT_FAILED ldx #>SER_ERR_INIT_FAILED rts ; Baud rate not available InvBaud: lda #<SER_ERR_BAUD_UNAVAIL ldx #>SER_ERR_BAUD_UNAVAIL rts ;---------------------------------------------------------------------------- ; SER_GET: Will fetch a character from the receive buffer and store it into the ; variable pointer to by ptr1. If no data is available, SER_ERR_NO_DATA is ; return. ; SER_GET: ldx SendFreeCnt ; Send data if necessary inx ; X == $FF? beq @L1 lda #$00 jsr TryToSend ; Check for buffer empty @L1: lda RecvFreeCnt ; (25) cmp #$ff bne @L2 lda #<SER_ERR_NO_DATA ldx #>SER_ERR_NO_DATA rts ; Check for flow stopped & enough free: release flow control @L2: ldx Stopped ; (34) beq @L3 cmp #63 bcc @L3 lda #$00 sta Stopped lda RtsOff ora #%00001000 sta ACIA_CMD ; Get byte from buffer @L3: ldx RecvHead ; (41) lda RecvBuf,x inc RecvHead inc RecvFreeCnt ldx #$00 ; (59) sta (ptr1,x) txa ; Return code = 0 rts ;---------------------------------------------------------------------------- ; SER_PUT: Output character in A. ; Must return an error code in a/x. ; SER_PUT: ; Try to send ldx SendFreeCnt inx ; X = $ff? beq @L2 pha lda #$00 jsr TryToSend pla ; Put byte into send buffer & send @L2: ldx SendFreeCnt bne @L3 lda #<SER_ERR_OVERFLOW ; X is already zero rts @L3: ldx SendTail sta SendBuf,x inc SendTail dec SendFreeCnt lda #$ff jsr TryToSend lda #<SER_ERR_OK tax rts ;---------------------------------------------------------------------------- ; SER_STATUS: Return the status in the variable pointed to by ptr1. ; Must return an error code in a/x. ; SER_STATUS: lda ACIA_STATUS ldx #0 sta (ptr1,x) txa ; SER_ERR_OK rts ;---------------------------------------------------------------------------- ; SER_IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl ; specific data in ptr1, and the ioctl code in A. ; Must return an error code in a/x. ; SER_IOCTL: lda #<SER_ERR_INV_IOCTL ; We don't support ioclts for now ldx #>SER_ERR_INV_IOCTL rts ; Run into IRQ instead ;---------------------------------------------------------------------------- ; SER_IRQ: Called from the builtin runtime IRQ handler as a subroutine. All ; registers are already save, no parameters are passed, but the carry flag ; is clear on entry. The routine must return with carry set if the interrupt ; was handled, otherwise with carry clear. ; SER_IRQ: lda ACIA_STATUS ; Check ACIA status for receive interrupt and #$08 beq @L9 ; Jump if no ACIA interrupt (carry still clear) lda ACIA_DATA ; Get byte from ACIA ldx RecvFreeCnt ; Check if we have free space left beq @L1 ; Jump if no space in receive buffer ldy RecvTail ; Load buffer pointer sta RecvBuf,y ; Store received byte in buffer inc RecvTail ; Increment buffer pointer dec RecvFreeCnt ; Decrement free space counter cpx #33 ; Check for buffer space low bcc @L1 ; Assert flow control if buffer space low rts ; Return with carry set (interrupt handled) ; Assert flow control if buffer space too low @L1: lda RtsOff sta ACIA_CMD sta Stopped sec ; Interrupt handled @L9: rts ;---------------------------------------------------------------------------- ; Try to send a byte. Internal routine. A = TryHard .proc TryToSend sta tmp1 ; Remember tryHard flag @L0: lda SendFreeCnt cmp #$ff beq @L3 ; Bail out ; Check for flow stopped @L1: lda Stopped bne @L3 ; Bail out ; Check that swiftlink is ready to send @L2: lda ACIA_STATUS and #$10 bne @L4 bit tmp1 ;keep trying if must try hard bmi @L0 @L3: rts ; Send byte and try again @L4: ldx SendHead lda SendBuf,x sta ACIA_DATA inc SendHead inc SendFreeCnt jmp @L0 .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/plus4/slow.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000444�13473601511�0015704�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Marco van den Heuvel, 2018-03-28 ; ; void slow (void); ; /* Switch the CPU into single clock mode. */ ; .export _slow .include "plus4.inc" .proc _slow lda TED_CLK ora #%00000010 sta TED_CLK rts .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/plus4/status.s���������������������������������������������������������������������0000664�0000000�0000000�00000000134�13473601511�0016237�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2012-09-30 ; .exportzp ST := $90 ; IEC status byte ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/plus4/sysuname.s�������������������������������������������������������������������0000664�0000000�0000000�00000001452�13473601511�0016564�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-08-12 ; ; unsigned char __fastcall__ _sysuname (struct utsname* buf); ; .export __sysuname, utsdata .import utscopy __sysuname = utscopy ;-------------------------------------------------------------------------- ; Data. We define a fixed utsname struct here and just copy it. .rodata utsdata: ; sysname .asciiz "cc65" ; nodename .asciiz "" ; release .byte ((.VERSION >> 8) & $0F) + '0' .byte '.' .byte ((.VERSION >> 4) & $0F) + '0' .byte $00 ; version .byte (.VERSION & $0F) + '0' .byte $00 ; machine .asciiz "Commodore Plus/4" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/plus4/waitvsync.s������������������������������������������������������������������0000664�0000000�0000000�00000000416�13473601511�0016746�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Written by Groepaz <groepaz@gmx.net> ; ; void waitvsync (void); ; .export _waitvsync .include "plus4.inc" _waitvsync: @l1: lda TED_VLINEHI and #$01 ora TED_VLINELO bne @l1 rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/���������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015146�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/add.s����������������������������������������������������������������������0000664�0000000�0000000�00000003162�13473601511�0016064�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 05.08.1998 ; Christian Krueger, 11-Mar-2017, spend two bytes for one cycle, improved 65SC02 optimization ; ; CC65 runtime: add ints ; ; Make this as fast as possible, even if it needs more space since it's ; called a lot! .export tosadda0, tosaddax .importzp sp, tmp1 .macpack cpu tosadda0: ldx #0 tosaddax: clc ; (2) .if (.cpu .bitand ::CPU_ISET_65SC02) adc (sp) ; (7) tay ; (9) inc sp ; (14) bne hiadd ; (17) inc sp+1 ; (-1+5) hiadd: txa ; (19) adc (sp) ; (24) tax ; (26) inc sp ; (31) bne done ; (34) inc sp+1 ; (-1+5) done: tya ; (36) .else ldy #0 ; (4) adc (sp),y ; (9) lo byte iny ; (11) sta tmp1 ; (14) save it txa ; (16) adc (sp),y ; (21) hi byte tax ; (23) clc ; (25) lda sp ; (28) adc #2 ; (30) sta sp ; (33) bcc L1 ; (36) inc sp+1 ; (-1+5) L1: lda tmp1 ; (39) restore low byte .endif rts ; (6502: 45 cycles, 26 bytes <-> 65SC02: 42 cycles, 22 bytes ) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/addeqsp.s������������������������������������������������������������������0000664�0000000�0000000�00000000574�13473601511�0016761�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 08.10.1998 ; ; CC65 runtime: += operator for ints on the stack ; .export addeq0sp, addeqysp .importzp sp addeq0sp: ldy #0 addeqysp: clc adc (sp),y sta (sp),y pha iny txa adc (sp),y sta (sp),y tax pla rts ������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/addysp.s�������������������������������������������������������������������0000664�0000000�0000000�00000001042�13473601511�0016613�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.10.2000 ; ; CC65 runtime: Increment the stackpointer by value in y ; .export addysp1, addysp .importzp sp addysp1: iny addysp: pha ; Save A clc tya ; Get the value adc sp ; Add low byte sta sp ; Put it back bcc @L1 ; If no carry, we're done inc sp+1 ; Inc high byte @L1: pla ; Restore A rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/along.s��������������������������������������������������������������������0000664�0000000�0000000�00000000661�13473601511�0016435�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 23.11.2002 ; Christian Krueger, 11-Mar-2017, saved 5 bytes ; ; CC65 runtime: Convert char in ax into a long ; .export aulong, along .importzp sreg ; Convert A from char to long in EAX along: ldx #$ff cmp #$80 ; Positive? bcs store ; no, apply $FF aulong: ldx #0 store: stx sreg stx sreg+1 rts �������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/and.s����������������������������������������������������������������������0000664�0000000�0000000�00000001107�13473601511�0016073�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 05.08.1998 ; ; CC65 runtime: and on ints ; .export tosanda0, tosandax .import addysp1 .importzp sp, ptr4 .macpack cpu tosanda0: ldx #$00 tosandax: .if (.cpu .bitand CPU_ISET_65SC02) and (sp) ; 65SC02 version, saves 2 cycles and 1 byte ldy #1 .else ldy #0 and (sp),y iny .endif pha txa and (sp),y tax pla jmp addysp1 ; drop TOS, set condition codes ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/aslax1.s�������������������������������������������������������������������0000664�0000000�0000000�00000000436�13473601511�0016526�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: Scale the primary register ; .export aslax1, shlax1 .importzp tmp1 aslax1: shlax1: stx tmp1 asl A rol tmp1 ldx tmp1 rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/aslax2.s�������������������������������������������������������������������0000664�0000000�0000000�00000000455�13473601511�0016530�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: Scale the primary register by 4 ; .export aslax2, shlax2 .importzp tmp1 aslax2: shlax2: stx tmp1 asl a rol tmp1 asl a rol tmp1 ldx tmp1 rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/aslax3.s�������������������������������������������������������������������0000664�0000000�0000000�00000000524�13473601511�0016526�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: Scale the primary register by 8 ; .export aslax3, shlax3 .importzp tmp1 aslax3: shlax3: stx tmp1 asl a rol tmp1 asl a rol tmp1 asl a rol tmp1 ldx tmp1 rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/aslax4.s�������������������������������������������������������������������0000664�0000000�0000000�00000000574�13473601511�0016534�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.07.2001 ; ; CC65 runtime: Scale the primary register by 16 ; .export aslax4, shlax4 .importzp tmp1 aslax4: shlax4: stx tmp1 asl a rol tmp1 asl a rol tmp1 asl a rol tmp1 asl a rol tmp1 ldx tmp1 rts ������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/asleax1.s������������������������������������������������������������������0000664�0000000�0000000�00000000513�13473601511�0016667�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: Scale the 32 bit primary register by 2 ; .export asleax1, shleax1 .importzp sreg, tmp1 asleax1: shleax1: stx tmp1 asl a rol tmp1 rol sreg rol sreg+1 ldx tmp1 rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/asleax2.s������������������������������������������������������������������0000664�0000000�0000000�00000000636�13473601511�0016676�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: Scale the 32 bit primary register by 4 ; .export asleax2, shleax2 .importzp sreg, tmp1 asleax2: shleax2: stx tmp1 asl a rol tmp1 rol sreg rol sreg+1 asl a rol tmp1 rol sreg rol sreg+1 ldx tmp1 rts ��������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/asleax3.s������������������������������������������������������������������0000664�0000000�0000000�00000000761�13473601511�0016676�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: Scale the 32 bit primary register by 8 ; .export asleax3, shleax3 .importzp sreg, tmp1 asleax3: shleax3: stx tmp1 asl a rol tmp1 rol sreg rol sreg+1 asl a rol tmp1 rol sreg rol sreg+1 asl a rol tmp1 rol sreg rol sreg+1 ldx tmp1 rts ���������������cc65-2.18/libsrc/runtime/asleax4.s������������������������������������������������������������������0000664�0000000�0000000�00000000577�13473601511�0016704�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.07.2001 ; ; CC65 runtime: Scale the 32 bit primary register by 16 ; .export asleax4, shleax4 .importzp sreg, tmp1 asleax4: shleax4: stx tmp1 ldx #4 @L1: asl a rol tmp1 rol sreg rol sreg+1 dex bne @L1 ldx tmp1 rts ���������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/asr.s����������������������������������������������������������������������0000664�0000000�0000000�00000004031�13473601511�0016115�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2004-06-30 ; ; CC65 runtime: right shift support for ints ; ; Note: The standard declares a shift count that is negative or >= the ; bitcount of the shifted type for undefined behaviour. ; ; Note^2: The compiler knowns about the register/zero page usage of this ; function, so you need to change the compiler source if you change it! ; .export tosasrax, asraxy .import popax .importzp tmp1 tosasrax: sta tmp1 ; Save shift count jsr popax ; Get the left hand operand ldy tmp1 ; Get shift count ; Run into asraxy asraxy: pha tya and #$0F beq L2 ; Nothing to shift sec sbc #8 ; Shift count 8 or greater? beq L3 ; Jump if exactly 8 bcc L6 ; Jump if less than 8 ; Shift count is greater than 8. tay ; Shift count into Y pla ; Discard low byte txa ; Get high byte L1: cmp #$80 ; Sign bit into carry ror a ; Carry into A dey bne L1 beq L4 ; Sign extend and return ; Shift count is zero L2: pla rts ; Shift count is exactly 8 L3: pla ; Drop low byte from stack ... txa ; Move high byte to low L4: ldx #$00 ; Clear high byte cmp #$80 ; Check sign bit bcc L5 dex L5: rts ; Shift count is less than 8 L6: adc #8 ; Correct counter tay ; Shift count into Y pla ; Restore low byte stx tmp1 ; Save high byte of lhs L7: cpx #$80 ; Sign bit into carry ror tmp1 ror a dey bne L7 ; Done with shift ldx tmp1 rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/asrax1.s�������������������������������������������������������������������0000664�0000000�0000000�00000000450�13473601511�0016530�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: Scale the primary register ; .export asrax1 .importzp tmp1 asrax1: stx tmp1 cpx #$80 ; Put bit 7 into carry ror tmp1 ror a ldx tmp1 rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/asrax2.s�������������������������������������������������������������������0000664�0000000�0000000�00000000551�13473601511�0016533�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: Scale the primary register by 4 ; .export asrax2 .importzp tmp1 asrax2: stx tmp1 cpx #$80 ; Put bit 7 into carry ror tmp1 ror a cpx #$80 ror tmp1 ror a ldx tmp1 rts �������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/asrax3.s�������������������������������������������������������������������0000664�0000000�0000000�00000000701�13473601511�0016531�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Piotr Fusik, 24.10.2003 ; originally by Ullrich von Bassewitz ; ; CC65 runtime: Scale the primary register by 8 ; .export asrax3 .importzp tmp1 asrax3: stx tmp1 cpx #$80 ; Put bit 7 into carry ror tmp1 ror a cpx #$80 ror tmp1 ror a cpx #$80 ror tmp1 ror a ldx tmp1 rts ���������������������������������������������������������������cc65-2.18/libsrc/runtime/asrax4.s�������������������������������������������������������������������0000664�0000000�0000000�00000000776�13473601511�0016546�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Piotr Fusik, 24.10.2003 ; originally by Ullrich von Bassewitz ; ; CC65 runtime: Scale the primary register by 16 ; .export asrax4 .importzp tmp1 asrax4: stx tmp1 cpx #$80 ; Put bit 7 into carry ror tmp1 ror a cpx #$80 ror tmp1 ror a cpx #$80 ror tmp1 ror a cpx #$80 ror tmp1 ror a ldx tmp1 rts ��cc65-2.18/libsrc/runtime/asreax1.s������������������������������������������������������������������0000664�0000000�0000000�00000000573�13473601511�0016703�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: Scale the primary register ; .export asreax1 .importzp sreg, tmp1 asreax1: stx tmp1 ldx sreg+1 cpx #$80 ; Get bit 7 into carry ror sreg+1 ror sreg ror tmp1 ror a ldx tmp1 rts �������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/asreax2.s������������������������������������������������������������������0000664�0000000�0000000�00000001021�13473601511�0016671�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: Scale the 32 bit primary register by 4 ; .export asreax2 .importzp sreg, tmp1 asreax2: stx tmp1 ldx sreg+1 cpx #$80 ; Get bit 7 into carry ror sreg+1 ror sreg ror tmp1 ror a cpx #$80 ; Get bit 7 into carry ror sreg+1 ror sreg ror tmp1 ror a ldx tmp1 rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/asreax3.s������������������������������������������������������������������0000664�0000000�0000000�00000001233�13473601511�0016677�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: Scale the 32 bit primary register by 8 ; .export asreax3 .importzp sreg, tmp1 asreax3: stx tmp1 ldx sreg+1 cpx #$80 ; Get bit 7 into carry ror sreg+1 ror sreg ror tmp1 ror a cpx #$80 ; Get bit 7 into carry ror sreg+1 ror sreg ror tmp1 ror a cpx #$80 ; Get bit 7 into carry ror sreg+1 ror sreg ror tmp1 ror a ldx tmp1 rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/asreax4.s������������������������������������������������������������������0000664�0000000�0000000�00000000673�13473601511�0016707�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.07.2001 ; ; CC65 runtime: Scale the 32 bit primary register by 16 ; .export asreax4 .importzp sreg, tmp1 asreax4: stx tmp1 ldx sreg+1 ldy #4 @L1: cpx #$80 ; Get bit 7 into carry ror sreg+1 ror sreg ror tmp1 ror a dey bne @L1 ldx tmp1 rts ���������������������������������������������������������������������cc65-2.18/libsrc/runtime/axlong.s�������������������������������������������������������������������0000664�0000000�0000000�00000000676�13473601511�0016633�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.10.2000 ; Christian Krueger, 02-Mar-2017, some bytes saved ; ; CC65 runtime: Convert int in ax into a long ; .export axulong, axlong .importzp sreg ; Convert AX from int to long in EAX axlong: ldy #$ff cpx #$80 ; Positive? bcs store ; No, apply $FF axulong: ldy #0 store: sty sreg sty sreg+1 rts ������������������������������������������������������������������cc65-2.18/libsrc/runtime/bneg.s���������������������������������������������������������������������0000664�0000000�0000000�00000000516�13473601511�0016247�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 05.08.1998 ; ; CC65 runtime: boolean negation ; .export bnega, bnegax .import return0, return1 bnegax: cpx #0 bne L0 bnega: tax bne L0 L1: lda #1 ; Zero already in X rts L0: ldx #0 txa rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/bpushbsp.s�����������������������������������������������������������������0000664�0000000�0000000�00000000441�13473601511�0017157�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 31.08.1998 ; ; CC65 runtime: Load a from stack slot and push as byte ; .export bpushbsp, bpushbysp .import pusha .importzp sp bpushbsp: ldy #0 bpushbysp: lda (sp),y jmp pusha �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/call.s���������������������������������������������������������������������0000664�0000000�0000000�00000000362�13473601511�0016246�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: call function via pointer in ax ; .export callax .importzp ptr1 callax: sta ptr1 stx ptr1+1 jmp (ptr1) ; jump there ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/callirq.s������������������������������������������������������������������0000664�0000000�0000000�00000005141�13473601511�0016762�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2004-04-04 ; ; CC65 runtime: Support for calling special irq routines declared as condes ; type 2. ; ; There are two reasons, why this is a separate routine, and the generic ; condes routine in condes.s is not used: ; ; 1. Speed. Having several things hardcoded makes it faster. This is ; important if it is called in each interrupt. ; ; 2. Reentrancy. The condes routines must use self modyfiying code, which ; means it is not reentrant. An IRQ using condes, that interrupts ; another use of condes will cause unpredicatble behaviour. The current ; code avoids this by using locking mechanisms, but it's complex and ; has a size and performance penalty. ; ; 3. Special semantics: An interruptor called by callirq must tell by ; setting or resetting the carry flag if the interrupt has been handled ; (which means that the interrupt is no longer active at the interrupt ; source). callirq will call no other interruptors if this happens. To ; simplify code, all interrupt routines will be called with carry clear ; on entry. ; ; As the normal condes routine, this one has the limitation of 127 table ; entries. ; .export callirq .export callirq_y ; Same but with Y preloaded .export __CALLIRQ__ : absolute = 1 .constructor irq_init, 10 .destructor irq_done, 10 .import __INTERRUPTOR_TABLE__, __INTERRUPTOR_COUNT__ .import initirq .import doneirq irq_init := initirq irq_done := doneirq ; -------------------------------------------------------------------------- ; Call all IRQ routines. The function needs to use self modifying code and ; is thereforce placed in the data segment. It will return carry set if the ; interrupt was handled and carry clear if not. The caller may choose to ; ignore this at will. ; NOTE: The routine must not be called if the table is empty! .data callirq: ldy #.lobyte(__INTERRUPTOR_COUNT__*2) callirq_y: clc ; Preset carry flag loop: dey lda __INTERRUPTOR_TABLE__,y sta jmpvec+2 ; Modify code below dey lda __INTERRUPTOR_TABLE__,y sta jmpvec+1 ; Modify code below sty index+1 ; Modify code below jmpvec: jsr $FFFF ; Patched at runtime bcs done ; Bail out if interrupt handled index: ldy #$FF ; Patched at runtime bne loop done: rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/callmain.s�����������������������������������������������������������������0000664�0000000�0000000�00000001351�13473601511�0017112�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-03-07 ; ; Push arguments and call main() ; .export callmain .export __argc, __argv .import _main, pushax ;--------------------------------------------------------------------------- ; Setup the stack for main(), then jump to it .proc callmain lda __argc ldx __argc+1 jsr pushax ; Push argc lda __argv ldx __argv+1 jsr pushax ; Push argv ldy #4 ; Argument size jmp _main .endproc ;--------------------------------------------------------------------------- ; Data .data __argc: .word 0 __argv: .addr 0 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/callptr4.s�����������������������������������������������������������������0000664�0000000�0000000�00000000256�13473601511�0017062�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; CC65 runtime: call function via pointer in ptr4 ; .export callptr4 .importzp ptr4 callptr4: jmp (ptr4) ; jump there ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/compl.s��������������������������������������������������������������������0000664�0000000�0000000�00000000405�13473601511�0016443�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: integer complement ; .export complax complax: eor #$FF ; Not A pha txa eor #$FF ; Not X tax pla rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/condes.s�������������������������������������������������������������������0000664�0000000�0000000�00000004156�13473601511�0016613�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 20.11.2000 ; ; CC65 runtime: Support for calling module constructors/destructors ; ; The condes routine must be called with the table address in a/x and the ; size of the table (which must not be zero!) in y. The current implementation ; limits the table size to 254 bytes (127 vectors) but this shouldn't be ; problem for now and may be changed later. ; ; libinit and libdone call condes with the predefined module constructor and ; destructor tables, they must be called from the platform specific startup ; code. .export initlib, donelib, condes .import __CONSTRUCTOR_TABLE__, __CONSTRUCTOR_COUNT__ .import __DESTRUCTOR_TABLE__, __DESTRUCTOR_COUNT__ .macpack cpu ; -------------------------------------------------------------------------- ; Initialize library modules .segment "ONCE" .proc initlib ldy #<(__CONSTRUCTOR_COUNT__*2) beq exit lda #<__CONSTRUCTOR_TABLE__ ldx #>__CONSTRUCTOR_TABLE__ jmp condes exit: rts .endproc ; -------------------------------------------------------------------------- ; Cleanup library modules .code .proc donelib ldy #<(__DESTRUCTOR_COUNT__*2) beq exit lda #<__DESTRUCTOR_TABLE__ ldx #>__DESTRUCTOR_TABLE__ jmp condes exit: rts .endproc ; -------------------------------------------------------------------------- ; Generic table call handler. The code uses self modifying code and goes ; into the data segment for this reason. ; NOTE: The routine must not be called if the table is empty! .data .proc condes sta fetch1+1 stx fetch1+2 sta fetch2+1 stx fetch2+2 loop: dey fetch1: lda $FFFF,y ; Patched at runtime sta jmpvec+2 dey fetch2: lda $FFFF,y ; Patched at runtime sta jmpvec+1 sty index+1 jmpvec: jsr $FFFF ; Patched at runtime index: ldy #$FF ; Patched at runtime bne loop rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/decax1.s�������������������������������������������������������������������0000664�0000000�0000000�00000000347�13473601511�0016503�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 29.12.1999 ; ; CC65 runtime: Decrement ax by 1 ; .export decax1 .macpack generic .proc decax1 sub #1 bcs @L9 dex @L9: rts .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/decax2.s�������������������������������������������������������������������0000664�0000000�0000000�00000000347�13473601511�0016504�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 29.12.1999 ; ; CC65 runtime: Decrement ax by 2 ; .export decax2 .macpack generic .proc decax2 sub #2 bcs @L9 dex @L9: rts .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/decax3.s�������������������������������������������������������������������0000664�0000000�0000000�00000000347�13473601511�0016505�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.03.2001 ; ; CC65 runtime: Decrement ax by 3 ; .export decax3 .macpack generic .proc decax3 sub #3 bcs @L9 dex @L9: rts .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/decax4.s�������������������������������������������������������������������0000664�0000000�0000000�00000000347�13473601511�0016506�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.03.2001 ; ; CC65 runtime: Decrement ax by 4 ; .export decax4 .macpack generic .proc decax4 sub #4 bcs @L9 dex @L9: rts .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/decax5.s�������������������������������������������������������������������0000664�0000000�0000000�00000000347�13473601511�0016507�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.03.2001 ; ; CC65 runtime: Decrement ax by 5 ; .export decax5 .macpack generic .proc decax5 sub #5 bcs @L9 dex @L9: rts .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/decax6.s�������������������������������������������������������������������0000664�0000000�0000000�00000000347�13473601511�0016510�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.03.2001 ; ; CC65 runtime: Decrement ax by 6 ; .export decax6 .macpack generic .proc decax6 sub #6 bcs @L9 dex @L9: rts .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/decax7.s�������������������������������������������������������������������0000664�0000000�0000000�00000000347�13473601511�0016511�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.03.2001 ; ; CC65 runtime: Decrement ax by 7 ; .export decax7 .macpack generic .proc decax7 sub #7 bcs @L9 dex @L9: rts .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/decax8.s�������������������������������������������������������������������0000664�0000000�0000000�00000000347�13473601511�0016512�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.03.2001 ; ; CC65 runtime: Decrement ax by 8 ; .export decax8 .macpack generic .proc decax8 sub #8 bcs @L9 dex @L9: rts .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/decaxy.s�������������������������������������������������������������������0000664�0000000�0000000�00000000445�13473601511�0016612�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 29.12.1999 ; ; CC65 runtime: Decrement ax by value in Y ; .export decaxy .importzp tmp1 .macpack generic .proc decaxy sty tmp1 sub tmp1 bcs @L9 dex @L9: rts .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/decsp1.s�������������������������������������������������������������������0000664�0000000�0000000�00000000430�13473601511�0016506�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.10.2000 ; ; CC65 runtime: Decrement the stackpointer by 1 ; .export decsp1 .importzp sp .proc decsp1 ldy sp bne @L1 dec sp+1 @L1: dec sp rts .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/decsp2.s�������������������������������������������������������������������0000664�0000000�0000000�00000000474�13473601511�0016517�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.10.2000 ; ; CC65 runtime: Decrement the stackpointer by 2 ; .export decsp2 .importzp sp .proc decsp2 lda sp sec sbc #2 sta sp bcc @L1 rts @L1: dec sp+1 rts .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/decsp3.s�������������������������������������������������������������������0000664�0000000�0000000�00000000474�13473601511�0016520�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.10.2000 ; ; CC65 runtime: Decrement the stackpointer by 3 ; .export decsp3 .importzp sp .proc decsp3 lda sp sec sbc #3 sta sp bcc @L1 rts @L1: dec sp+1 rts .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/decsp4.s�������������������������������������������������������������������0000664�0000000�0000000�00000000474�13473601511�0016521�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.10.2000 ; ; CC65 runtime: Decrement the stackpointer by 4 ; .export decsp4 .importzp sp .proc decsp4 lda sp sec sbc #4 sta sp bcc @L1 rts @L1: dec sp+1 rts .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/decsp5.s�������������������������������������������������������������������0000664�0000000�0000000�00000000474�13473601511�0016522�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.10.2000 ; ; CC65 runtime: Decrement the stackpointer by 5 ; .export decsp5 .importzp sp .proc decsp5 lda sp sec sbc #5 sta sp bcc @L1 rts @L1: dec sp+1 rts .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/decsp6.s�������������������������������������������������������������������0000664�0000000�0000000�00000000474�13473601511�0016523�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.10.2000 ; ; CC65 runtime: Decrement the stackpointer by 6 ; .export decsp6 .importzp sp .proc decsp6 lda sp sec sbc #6 sta sp bcc @L1 rts @L1: dec sp+1 rts .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/decsp7.s�������������������������������������������������������������������0000664�0000000�0000000�00000000472�13473601511�0016522�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.10.2000 ; ; CC65 runtime: Decrement the stackpointer by 7 ; .export decsp7 .importzp sp .proc decsp7 lda sp sec sbc #7 sta sp bcc @L1 rts @L1: dec sp+1 rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/decsp8.s�������������������������������������������������������������������0000664�0000000�0000000�00000000474�13473601511�0016525�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.10.2000 ; ; CC65 runtime: Decrement the stackpointer by 8 ; .export decsp8 .importzp sp .proc decsp8 lda sp sec sbc #8 sta sp bcc @L1 rts @L1: dec sp+1 rts .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/div.s����������������������������������������������������������������������0000664�0000000�0000000�00000002021�13473601511�0016107�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 07.08.1998 ; ; CC65 runtime: division for signed ints ; ; When negating values, we will ignore the possibility here, that one of the ; values is $8000, in which case the negate will fail. .export tosdiva0, tosdivax .import popsargsudiv16, negax .importzp ptr1, tmp1, tmp2 tosdiva0: ldx #0 tosdivax: jsr popsargsudiv16 ; Get arguments from stack, adjust sign ; and do the division ldx ptr1+1 ; Load high byte of result ; Adjust the sign of the result. tmp1 contains the high byte of the left ; operand, tmp2 contains the high byte of the right operand. lda tmp1 eor tmp2 bpl Pos ; Jump if sign of result positive ; Result is negative lda ptr1 ; Load low byte of result jmp negax ; Adjust the sign ; Result is positive Pos: lda ptr1 ; Load low byte of result rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/enter.s��������������������������������������������������������������������0000664�0000000�0000000�00000000532�13473601511�0016447�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: function prologue ; .export enter .importzp sp enter: tya ; get arg size ldy sp bne L1 dec sp+1 L1: dec sp ldy #0 sta (sp),y ; Store the arg count rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/eq.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000561�13473601511�0015741�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: Compare == for ints ; .export toseq00, toseqa0, toseqax .import tosicmp, booleq .importzp sp, tmp1 toseq00: lda #$00 toseqa0: ldx #$00 toseqax: jsr tosicmp ; Set flags jmp booleq ; Convert to boolean �����������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/ge.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000530�13473601511�0015723�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: Compare >= for signed ints ; .export tosge00, tosgea0, tosgeax .import tosicmp, boolge tosge00: lda #$00 tosgea0: ldx #$00 tosgeax: jsr tosicmp ; Set flags jmp boolge ; Convert to boolean ������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/gt.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000534�13473601511�0015746�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: Compare > for signed ints ; .export tosgt00, tosgta0, tosgtax .import tosicmp, boolgt tosgt00: lda #$00 tosgta0: ldx #$00 tosgtax: jsr tosicmp ; Set the flags jmp boolgt ; Convert to boolean ��������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/icmp.s���������������������������������������������������������������������0000664�0000000�0000000�00000002152�13473601511�0016262�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Piotr Fusik, 15.04.2002 ; originally by Ullrich von Bassewitz ; ; Integer compare function - used by the compare operators ; .export tosicmp, tosicmp0 .importzp sp, sreg tosicmp0: ldx #$00 tosicmp: sta sreg stx sreg+1 ; Save ax ldy #$00 lda (sp),y ; Get low byte tax inc sp ; 5 bne @L1 ; 3 inc sp+1 ; (5) @L1: lda (sp),y ; Get high byte inc sp ; 5 bne @L2 ; 3 inc sp+1 ; (5) ; Do the compare. @L2: sec sbc sreg+1 ; Compare high byte bne @L4 cpx sreg ; Compare low byte beq @L3 adc #$FF ; If the C flag is set then clear the N flag ora #$01 ; else set the N flag @L3: rts @L4: bvc @L3 eor #$FF ; Fix the N flag if overflow ora #$01 ; Clear the Z flag rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/idiv32by16r16.s������������������������������������������������������������0000664�0000000�0000000�00000002451�13473601511�0017467�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2009-11-04 ; ; CC65 runtime: 32by16 => 16 signed division ; .export idiv32by16r16 .import negax, udiv32by16r16m .include "zeropage.inc" ;--------------------------------------------------------------------------- ; 32by16 division. Divide ptr1:ptr2 by ptr3. Result is in ptr1, remainder ; in sreg. ; ; lhs rhs result result also in remainder ; ----------------------------------------------------------------------- ; ptr1:ptr2 ptr3 ax ptr1 sreg ; idiv32by16r16: stx tmp1 cpx #0 bpl @L1 jsr negax @L1: sta ptr3 stx ptr3+1 lda ptr2+1 eor tmp1 sta tmp1 bit ptr2+1 bpl @L3 ; Negate the value in ptr1:ptr2 ldx #0 ldy #4 sec @L2: lda ptr1,x eor #$FF adc #$00 sta ptr1,x inx dey bne @L2 ; Call the unsigned division routine @L3: jsr udiv32by16r16m ; Check the sign of the result bit tmp1 bmi @L4 rts ; Negate the result. We do this here only for the result, not for the ; remainder! @L4: jmp negax �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/imul16x16r32.s�������������������������������������������������������������0000664�0000000�0000000�00000001755�13473601511�0017345�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2010-11-03 ; ; CC65 runtime: 16x16 => 32 signed multiplication ; .export imul16x16r32 .import negax, umul16x16r32m, negeax .include "zeropage.inc" ;--------------------------------------------------------------------------- ; 16x16 => 32 signed multiplication routine. ; ; LHS RHS result result also in ; ------------------------------------------------------------- ; ax ptr1 ax:sreg ; ; There is probably a faster way to do this. ; imul16x16r32: stx tmp1 cpx #0 bpl @L1 jsr negax @L1: sta ptr3 stx ptr3+1 lda ptr1+1 eor tmp1 sta tmp1 lda ptr1 ldx ptr1+1 bpl @L2 jsr negax sta ptr1 stx ptr1+1 @L2: jsr umul16x16r32m ldy tmp1 bpl @L3 jmp negeax @L3: rts �������������������cc65-2.18/libsrc/runtime/imul8x8r16.s���������������������������������������������������������������0000664�0000000�0000000�00000003712�13473601511�0017204�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2010-11-02, Ullrich von Bassewitz ; 2014-09-10, Greg King ; ; CC65 runtime: 8x8 => 16 signed multiplication ; .export imul8x8r16, imul8x8r16m .importzp ptr1, ptr3, tmp1 .macpack generic ;--------------------------------------------------------------------------- ; 8x8 => 16 signed multiplication routine. ; ; multiplicand multiplier product ; LHS RHS result ; ------------------------------------------------------------- ; .A (ptr3-low) ptr1-low .XA ; imul8x8r16: sta ptr3 imul8x8r16m: ldx #>$0000 bit ptr3 bpl @L7 dex @L7: stx ptr3+1 ; Extend sign of Left-Hand Side ldy #<$0000 ; Clear .XY accumulator ldx #>$0000 lda ptr1 bmi NegMult bpl @L2 ; Branch always @L0: tya ; Add current multiplicand add ptr3 tay txa adc ptr3+1 tax @L1: asl ptr3 rol ptr3+1 @L2: lsr ptr1 ; Get next bit of Right-Hand Side into carry bcs @L0 bnz @L1 ; Loop if more one-bits in multiplier tya ; Put result into cc65's accumulator rts ; The multiplier is negative. ; Therefore, make it positive; and, subtract when multiplying. NegMult: eor #%11111111 sta ptr1 inc ptr1 bnz @L2 ; Branch always @L0: tya ; Subtract current multiplicand sub ptr3 tay txa sbc ptr3+1 tax @L1: asl ptr3 rol ptr3+1 @L2: lsr ptr1 ; Get next bit of Right-Hand Side into carry bcs @L0 bnz @L1 ; Loop if more one-bits in multiplier tya ; Put result into cc65's accumulator rts ������������������������������������������������������cc65-2.18/libsrc/runtime/incax1.s�������������������������������������������������������������������0000664�0000000�0000000�00000000571�13473601511�0016520�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 05.08.1998 ; ; CC65 runtime: Increment ax by 1 ; .export incax1 .macpack generic .macpack cpu .proc incax1 .if (.cpu .bitand ::CPU_ISET_65SC02) ina ; 65C02 version bne @L9 .else add #1 bcc @L9 .endif inx @L9: rts .endproc ���������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/incax2.s�������������������������������������������������������������������0000664�0000000�0000000�00000000347�13473601511�0016522�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 05.08.1998 ; ; CC65 runtime: Increment ax by 2 ; .export incax2 .macpack generic .proc incax2 add #2 bcc @L9 inx @L9: rts .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/incax3.s�������������������������������������������������������������������0000664�0000000�0000000�00000000321�13473601511�0016513�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 05.08.1998 ; ; CC65 runtime: Increment ax by 3 ; .export incax3 .import incaxy .proc incax3 ldy #3 jmp incaxy .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/incax5.s�������������������������������������������������������������������0000664�0000000�0000000�00000000321�13473601511�0016515�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 05.08.1998 ; ; CC65 runtime: Increment ax by 5 ; .export incax5 .import incaxy .proc incax5 ldy #5 jmp incaxy .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/incax6.s�������������������������������������������������������������������0000664�0000000�0000000�00000000321�13473601511�0016516�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 05.08.1998 ; ; CC65 runtime: Increment ax by 6 ; .export incax6 .import incaxy .proc incax6 ldy #6 jmp incaxy .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/incax7.s�������������������������������������������������������������������0000664�0000000�0000000�00000000321�13473601511�0016517�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 05.08.1998 ; ; CC65 runtime: Increment ax by 7 ; .export incax7 .import incaxy .proc incax7 ldy #7 jmp incaxy .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/incax8.s�������������������������������������������������������������������0000664�0000000�0000000�00000000321�13473601511�0016520�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 05.08.1998 ; ; CC65 runtime: Increment ax by 8 ; .export incax8 .import incaxy .proc incax8 ldy #8 jmp incaxy .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/incaxy.s�������������������������������������������������������������������0000664�0000000�0000000�00000000445�13473601511�0016630�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 05.08.1998 ; ; CC65 runtime: Increment ax by value in y ; .export incaxy, incax4 .importzp tmp1 .macpack generic incax4: ldy #4 incaxy: sty tmp1 add tmp1 bcc @L9 inx @L9: rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/incsp1.s�������������������������������������������������������������������0000664�0000000�0000000�00000000405�13473601511�0016526�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.10.2000 ; ; CC65 runtime: Increment the stackpointer by 1 ; .export incsp1 .importzp sp .proc incsp1 inc sp bne @L1 inc sp+1 @L1: rts .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/incsp2.s�������������������������������������������������������������������0000664�0000000�0000000�00000001603�13473601511�0016530�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.10.2000 ; ; CC65 runtime: Increment the stackpointer by 2. For performance reasons, ; this module also contains the popax function. .export popax, incsp2 .importzp sp .macpack cpu ; Pop a/x from stack. This function will run directly into incsp2 .proc popax ldy #1 lda (sp),y ; get hi byte tax ; into x .if (.cpu .bitand ::CPU_ISET_65SC02) lda (sp) ; get lo byte .else dey lda (sp),y ; get lo byte .endif .endproc .proc incsp2 inc sp ; 5 beq @L1 ; 2 inc sp ; 5 beq @L2 ; 2 rts @L1: inc sp ; 5 @L2: inc sp+1 ; 5 rts .endproc �����������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/incsp3.s�������������������������������������������������������������������0000664�0000000�0000000�00000000353�13473601511�0016532�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.10.2000 ; ; CC65 runtime: Increment the stackpointer by 3 ; .export incsp3 .import addysp .proc incsp3 ldy #3 jmp addysp .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/incsp4.s�������������������������������������������������������������������0000664�0000000�0000000�00000000353�13473601511�0016533�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.10.2000 ; ; CC65 runtime: Increment the stackpointer by 4 ; .export incsp4 .import addysp .proc incsp4 ldy #4 jmp addysp .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/incsp5.s�������������������������������������������������������������������0000664�0000000�0000000�00000000353�13473601511�0016534�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.10.2000 ; ; CC65 runtime: Increment the stackpointer by 5 ; .export incsp5 .import addysp .proc incsp5 ldy #5 jmp addysp .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/incsp6.s�������������������������������������������������������������������0000664�0000000�0000000�00000000353�13473601511�0016535�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.10.2000 ; ; CC65 runtime: Increment the stackpointer by 6 ; .export incsp6 .import addysp .proc incsp6 ldy #6 jmp addysp .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/incsp7.s�������������������������������������������������������������������0000664�0000000�0000000�00000000353�13473601511�0016536�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.10.2000 ; ; CC65 runtime: Increment the stackpointer by 7 ; .export incsp7 .import addysp .proc incsp7 ldy #7 jmp addysp .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/incsp8.s�������������������������������������������������������������������0000664�0000000�0000000�00000000340�13473601511�0016533�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.10.2000 ; ; CC65 runtime: Increment the stackpointer by 8 ; .export incsp8 .import addysp .proc incsp8 ldy #8 jmp addysp .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/jmpvec.s�������������������������������������������������������������������0000664�0000000�0000000�00000000313�13473601511�0016613�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2002-12-26 ; ; CC65 runtime: Jump vector that resides in the data segment so its address ; may be patched at runtime. ; .export jmpvec .data jmpvec: jmp $FFFF ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/ladd.s���������������������������������������������������������������������0000664�0000000�0000000�00000001656�13473601511�0016246�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 05.08.1998 ; ; CC65 runtime: long add ; .export tosadd0ax, tosaddeax .import addysp1 .importzp sp, sreg, tmp1 .macpack cpu ; EAX = TOS + EAX tosadd0ax: ldy #$00 sty sreg sty sreg+1 tosaddeax: clc .if (.cpu .bitand CPU_ISET_65SC02) adc (sp) ; 65SC02 version - saves 2 cycles ldy #1 .else ldy #0 adc (sp),y ; lo byte iny .endif sta tmp1 ; use as temp storage txa adc (sp),y ; byte 1 tax iny lda sreg adc (sp),y ; byte 2 sta sreg iny lda sreg+1 adc (sp),y ; byte 3 sta sreg+1 lda tmp1 ; load byte 0 jmp addysp1 ; drop TOS ����������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/laddeq.s�������������������������������������������������������������������0000664�0000000�0000000�00000002731�13473601511�0016567�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 07.04.2000 ; Christian Krueger, 12-Mar-2017, added 65SC02 optimization ; ; CC65 runtime: += operator ; ; On entry, the low byte of the address of the variable to increment is ; in ptr1, the high byte is in Y, and the increment is in eax. ; .export laddeq1, laddeqa, laddeq .importzp sreg, ptr1, tmp1 .macpack cpu laddeq1: lda #$01 laddeqa: ldx #$00 stx sreg stx sreg+1 laddeq: sty ptr1+1 ; Store high byte of address clc .if (.cpu .bitand ::CPU_ISET_65SC02) adc (ptr1) sta (ptr1) ldy #$01 ; Address byte 1 .else ldy #$00 ; Address low byte adc (ptr1),y sta (ptr1),y iny ; Address byte 1 .endif pha ; Save byte 0 of result for later txa adc (ptr1),y ; Load byte 1 sta (ptr1),y tax iny ; Address byte 2 lda sreg adc (ptr1),y sta (ptr1),y sta sreg iny ; Address byte 3 lda sreg+1 adc (ptr1),y sta (ptr1),y sta sreg+1 pla ; Retrieve byte 0 of result rts ; Done ���������������������������������������cc65-2.18/libsrc/runtime/laddeqsp.s�����������������������������������������������������������������0000664�0000000�0000000�00000001123�13473601511�0017124�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 08.10.1998 ; ; CC65 runtime: += operator for longs on the stack ; .export laddeq0sp, laddeqysp .importzp sp, sreg laddeq0sp: ldy #0 laddeqysp: clc adc (sp),y sta (sp),y pha iny txa adc (sp),y sta (sp),y tax iny lda sreg adc (sp),y sta (sp),y sta sreg iny lda sreg+1 adc (sp),y sta (sp),y sta sreg+1 pla rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/land.s���������������������������������������������������������������������0000664�0000000�0000000�00000001766�13473601511�0016262�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; Christian Krueger, 11-Mar-2017, added 65SC02 optimization ; ; CC65 runtime: and on longs ; .export tosand0ax, tosandeax .import addysp1 .importzp sp, sreg, tmp1 .macpack cpu tosand0ax: .if (.cpu .bitand ::CPU_ISET_65SC02) stz sreg stz sreg+1 .else ldy #$00 sty sreg sty sreg+1 .endif tosandeax: .if (.cpu .bitand ::CPU_ISET_65SC02) and (sp) ; byte 0 ldy #1 .else ldy #0 and (sp),y ; byte 0 iny .endif sta tmp1 txa and (sp),y ; byte 1 tax iny lda sreg and (sp),y ; byte 2 sta sreg iny lda sreg+1 and (sp),y ; byte 3 sta sreg+1 lda tmp1 jmp addysp1 ����������cc65-2.18/libsrc/runtime/lasr.s���������������������������������������������������������������������0000664�0000000�0000000�00000002220�13473601511�0016267�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2004-06-30 ; ; CC65 runtime: right shift support for longs ; ; Note: The standard declares a shift count that is negative or >= the ; bitcount of the shifted type for undefined behaviour. ; ; Note^2: The compiler knowns about the register/zero page usage of this ; function, so you need to change the compiler source if you change it! ; .export tosasreax .import popeax .importzp sreg, tmp1 tosasreax: and #$1F ; Bring the shift count into a valid range sta tmp1 ; Save it jsr popeax ; Get the left hand operand ldy tmp1 ; Get shift count beq L9 ; Bail out if shift count zero stx tmp1 ; Save byte 1 ldx sreg+1 ; Load byte 3 ; Do the actual shift. Faster solutions are possible but need a lot more code. L2: cpx #$80 ; Copy bit 31 into the carry ror sreg+1 ror sreg ror tmp1 ror a dey bne L2 ; Shift done ldx tmp1 L9: rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/lbneg.s��������������������������������������������������������������������0000664�0000000�0000000�00000000634�13473601511�0016424�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: boolean negation for longs ; .export bnegeax .importzp sreg, tmp1 bnegeax: stx tmp1 ldx #0 ; High byte of result ora tmp1 ora sreg ora sreg+1 bne @L0 lda #1 rts @L0: txa ; X is zero rts ����������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/lcmp.s���������������������������������������������������������������������0000664�0000000�0000000�00000002300�13473601511�0016260�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Piotr Fusik, 15.04.2002 ; originally by Ullrich von Bassewitz ; ; Long int compare function - used by the compare operators ; .export toslcmp .import incsp4 .importzp sp, sreg, ptr1 toslcmp: sta ptr1 stx ptr1+1 ; EAX now in sreg:ptr1 ldy #$03 lda (sp),y sec sbc sreg+1 bne L4 dey lda (sp),y cmp sreg bne L1 dey lda (sp),y cmp ptr1+1 bne L1 dey lda (sp),y cmp ptr1 L1: php ; Save flags jsr incsp4 ; Drop TOS plp ; Restore the flags beq L2 bcs L3 lda #$FF ; Set the N flag L2: rts L3: lda #$01 ; Clear the N flag rts L4: bvc L5 eor #$FF ; Fix the N flag if overflow ora #$01 ; Clear the Z flag L5: php ; Save flags jsr incsp4 ; Drop TOS plp ; Restore flags rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/lcompl.s�������������������������������������������������������������������0000664�0000000�0000000�00000000613�13473601511�0016620�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: long complement ; .export compleax .importzp sreg ; eax = ~eax compleax: eor #$FF pha txa eor #$FF tax lda sreg eor #$FF sta sreg lda sreg+1 eor #$FF sta sreg+1 pla rts ���������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/ldai.s���������������������������������������������������������������������0000664�0000000�0000000�00000000472�13473601511�0016246�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 31.08.1998 ; ; CC65 runtime: Load a indirect from address in ax ; .export ldaidx .importzp ptr1 .proc ldaidx sta ptr1 stx ptr1+1 ldx #$00 lda (ptr1),y bpl @L1 dex @L1: rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/ldau0sp.s������������������������������������������������������������������0000664�0000000�0000000�00000001027�13473601511�0016702�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 11.04.1999 ; ; CC65 runtime: Load an unsigned char indirect from pointer somewhere in stack ; .export ldau00sp, ldau0ysp .importzp sp, ptr1 .macpack cpu ldau00sp: ldy #1 ldau0ysp: lda (sp),y sta ptr1+1 dey lda (sp),y sta ptr1 ldx #0 .if (.cpu .bitand CPU_ISET_65SC02) lda (ptr1) ; Save one cycle for the C02 .else lda (ptr1,x) .endif rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/ldaui.s��������������������������������������������������������������������0000664�0000000�0000000�00000000442�13473601511�0016430�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 31.08.1998 ; ; CC65 runtime: Load a unsigned indirect from address in ax ; .export ldauidx .importzp ptr1 .proc ldauidx sta ptr1 stx ptr1+1 ldx #0 lda (ptr1),y rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/ldauisp.s������������������������������������������������������������������0000664�0000000�0000000�00000000711�13473601511�0016772�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 11.04.1999 ; ; CC65 runtime: Load an unsigned char indirect from pointer somewhere in stack ; .export ldaui0sp, ldauiysp .importzp sp, ptr1 ldaui0sp: ldy #1 ldauiysp: lda (sp),y sta ptr1+1 dey lda (sp),y sta ptr1 txa tay ldx #0 lda (ptr1),y rts �������������������������������������������������������cc65-2.18/libsrc/runtime/ldaxi.s��������������������������������������������������������������������0000664�0000000�0000000�00000000503�13473601511�0016431�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 31.08.1998 ; ; CC65 runtime: Load ax indirect from address in ax ; .export ldaxi, ldaxidx .importzp ptr1 ldaxi: ldy #1 ldaxidx: sta ptr1 stx ptr1+1 lda (ptr1),y tax dey lda (ptr1),y rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/ldaxsp.s�������������������������������������������������������������������0000664�0000000�0000000�00000000722�13473601511�0016626�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 31.08.1998 ; ; CC65 runtime: Load ax from offset in stack ; .export ldax0sp, ldaxysp .importzp sp ; Beware: The optimizer knows about the value in Y after return! ldax0sp: ldy #1 ldaxysp: lda (sp),y ; get high byte tax ; and save it dey ; point to lo byte lda (sp),y ; load low byte rts ����������������������������������������������cc65-2.18/libsrc/runtime/ldeaxi.s�������������������������������������������������������������������0000664�0000000�0000000�00000000703�13473601511�0016600�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 31.08.1998 ; ; CC65 runtime: Load eax indirect from address in ax ; .export ldeaxidx, ldeaxi .importzp sreg, ptr1 ldeaxi: ldy #3 ldeaxidx: sta ptr1 stx ptr1+1 lda (ptr1),y dey sta sreg+1 lda (ptr1),y dey sta sreg lda (ptr1),y dey tax lda (ptr1),y rts �������������������������������������������������������������cc65-2.18/libsrc/runtime/ldeaxysp.s�����������������������������������������������������������������0000664�0000000�0000000�00000001000�13473601511�0017152�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.06.1998 ; ; CC65 runtime: Load a long from somewhere in the stack ; ; Beware: The optimizer knows about the register contents after calling ; this function! ; .export ldeax0sp, ldeaxysp .importzp sreg, sp ldeax0sp: ldy #3 ldeaxysp: lda (sp),y sta sreg+1 dey lda (sp),y sta sreg dey lda (sp),y tax dey lda (sp),y rts cc65-2.18/libsrc/runtime/ldec.s���������������������������������������������������������������������0000664�0000000�0000000�00000001047�13473601511�0016243�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Piotr Fusik, 09.03.2018 ; originally by Ullrich von Bassewitz ; ; CC65 runtime: Decrement eax by value in Y ; .export deceaxy .importzp sreg, tmp1 deceaxy: sty tmp1 sec sbc tmp1 bcs @L9 ; Borrow from X. dex cpx #$FF bne @L9 ; X wrapped from zero to $FF, borrow from sreg. dec sreg cpx sreg bne @L9 ; sreg wrapped from zero to $FF, borrow from sreg+1. dec sreg+1 ; Done. @L9: rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/ldiv.s���������������������������������������������������������������������0000664�0000000�0000000�00000002025�13473601511�0016267�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 17.08.1998 ; ; CC65 runtime: division for signed long ints ; ; When negating values, we will ignore the possibility here, that one of the ; values if $80000000, in which case the negate will fail. .export tosdiv0ax, tosdiveax .import poplsargs, udiv32, negeax .importzp sreg, ptr1, tmp1, tmp2 tosdiv0ax: ldy #$00 sty sreg sty sreg+1 tosdiveax: jsr poplsargs ; Get arguments from stack, adjust sign jsr udiv32 ; Do the division, result is in (ptr1:sreg) ldx ptr1+1 ; Load byte 1 of result ; Adjust the sign of the result lda tmp1 ; Get sign of left operand eor tmp2 ; Calculate sign of result bpl Pos ; Jump if result positive ; Result is negative lda ptr1 ; Load byte 0 jmp negeax ; Negate value ; Result is positive Pos: lda ptr1 rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/le.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000530�13473601511�0015730�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: Compare <= for signed ints ; .export tosle00, toslea0, tosleax .import tosicmp, boolle tosle00: lda #$00 toslea0: ldx #$00 tosleax: jsr tosicmp ; Set flags jmp boolle ; Convert to boolean ������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/leaaxsp.s������������������������������������������������������������������0000664�0000000�0000000�00000000523�13473601511�0016767�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2009-08-31 ; ; CC65 runtime: Load effective address with offset in A/X relative to SP ; .export leaaxsp, leaa0sp .importzp sp leaa0sp: ldx #$00 leaaxsp: clc adc sp pha txa adc sp+1 tax pla rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/leave.s��������������������������������������������������������������������0000664�0000000�0000000�00000002660�13473601511�0016432�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; Christian Krueger, 11-Mar-2017, added 65SC02 optimization ; ; CC65 runtime: function epilogue ; ; exit a function. pop stack and rts. The function comes in different ; flavours that provide default values for the return val, or drop a local ; stack frame with size in y. .export leave00, leave0, leavey00, leavey0, leavey .export leave .import addysp .importzp sp .macpack cpu leave00: lda #0 leave0: ldx #0 beq leave leavey00: lda #0 ; "return 0" leavey0: ldx #0 ; return < 256 leavey: jsr addysp ; drop stack frame .if (.cpu .bitand ::CPU_ISET_65SC02) leave: tay ; save A a sec lda (sp) ; that's the pushed arg size sec ; Count the byte, the count's stored in adc sp sta sp bcc L1 inc sp+1 L1: tya ; Get return value back .else leave: pha ; save A a sec ldy #0 lda (sp),y ; that's the pushed arg size sec ; Count the byte, the count's stored in adc sp sta sp bcc L1 inc sp+1 L1: pla ; Get return value back .endif rts ��������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/leq.s����������������������������������������������������������������������0000664�0000000�0000000�00000000425�13473601511�0016114�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 05.08.1998 ; ; CC65 runtime: long equal ; .export toseqeax .import toslcmp, booleq toseqeax: jsr toslcmp ; Set flags jmp booleq ; Convert to boolean �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/lge.s����������������������������������������������������������������������0000664�0000000�0000000�00000000416�13473601511�0016102�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 07.08.1998 ; ; CC65 runtime: Compare >= for long ints ; .export tosgeeax .import toslcmp, boolge tosgeeax: jsr toslcmp ; Set the flags jmp boolge ; Convert to boolean ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/lgt.s����������������������������������������������������������������������0000664�0000000�0000000�00000000416�13473601511�0016121�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 07.08.1998 ; ; CC65 runtime: Compare > for long ints ; .export tosgteax .import toslcmp, boolgt tosgteax: jsr toslcmp ; Set the flags jmp boolgt ; Convert to boolean ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/linc.s���������������������������������������������������������������������0000664�0000000�0000000�00000000555�13473601511�0016264�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 29.12.1999 ; ; CC65 runtime: Increment eax by value in Y ; .export inceaxy .importzp ptr4, sreg .proc inceaxy sty ptr4 clc adc ptr4 bcc @L9 inx bne @L9 inc sreg bne @L9 inc sreg+1 @L9: rts .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/lle.s����������������������������������������������������������������������0000664�0000000�0000000�00000000416�13473601511�0016107�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 07.08.1998 ; ; CC65 runtime: Compare <= for long ints ; .export tosleeax .import toslcmp, boolle tosleeax: jsr toslcmp ; Set the flags jmp boolle ; Convert to boolean ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/llt.s����������������������������������������������������������������������0000664�0000000�0000000�00000000414�13473601511�0016124�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 07.08.1998 ; ; CC65 runtime: Compare < for long ints ; .export toslteax .import toslcmp, boollt toslteax: jsr toslcmp ; Set the flags jmp boollt ; Convert to boolean ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/lmod.s���������������������������������������������������������������������0000664�0000000�0000000�00000002437�13473601511�0016273�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 07.08.1998 ; Christian Krueger, 11-Mar-2017, added 65SC02 optimization ; CC65 runtime: modulo operation for long signed ints ; ; When negating values, we will ignore the possibility here, that one of the ; values if $8000, in which case the negate will fail. .export tosmod0ax, tosmodeax .import poplsargs, udiv32, negeax .importzp sreg, ptr1, ptr2, tmp1, tmp3, tmp4 .macpack cpu tosmod0ax: .if (.cpu .bitand ::CPU_ISET_65SC02) stz sreg stz sreg+1 .else ldy #$00 sty sreg sty sreg+1 .endif tosmodeax: jsr poplsargs ; Get arguments from stack, adjust sign jsr udiv32 ; Do the division, remainder is in (ptr2:tmp3:tmp4) ; Load the result lda ptr2 ldx ptr2+1 ldy tmp3 sty sreg ldy tmp4 sty sreg+1 ; Check the sign of the result. It is the sign of the left operand. bit tmp1 ; Check sign of left operand bpl Pos ; Jump if result is positive ; Result is negative jmp negeax ; Negate result ; Result is positive Pos: rts ; Done ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/lmul.s���������������������������������������������������������������������0000664�0000000�0000000�00000003351�13473601511�0016305�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 13.08.1998 ; Christian Krueger, 11-Mar-2017, added 65SC02 optimization ; ; CC65 runtime: multiplication for long (unsigned) ints ; .export tosumul0ax, tosumuleax, tosmul0ax, tosmuleax .import addysp1 .importzp sp, sreg, tmp1, tmp2, tmp3, tmp4, ptr1, ptr3, ptr4 .macpack cpu tosmul0ax: tosumul0ax: .if (.cpu .bitand ::CPU_ISET_65SC02) stz sreg stz sreg+1 .else ldy #$00 sty sreg sty sreg+1 .endif tosmuleax: tosumuleax: mul32: sta ptr1 stx ptr1+1 ; op2 now in ptr1/sreg .if (.cpu .bitand ::CPU_ISET_65SC02) lda (sp) ldy #1 .else ldy #0 lda (sp),y iny .endif sta ptr3 lda (sp),y sta ptr3+1 iny lda (sp),y sta ptr4 iny lda (sp),y sta ptr4+1 ; op1 in pre3/ptr4 jsr addysp1 ; Drop TOS ; Do (ptr1:sreg)*(ptr3:ptr4) --> EAX. lda #0 sta tmp4 sta tmp3 sta tmp2 ldy #32 L0: lsr tmp4 ror tmp3 ror tmp2 ror a ror sreg+1 ror sreg ror ptr1+1 ror ptr1 bcc L1 clc adc ptr3 pha lda ptr3+1 adc tmp2 sta tmp2 lda ptr4 adc tmp3 sta tmp3 lda ptr4+1 adc tmp4 sta tmp4 pla L1: dey bpl L0 lda ptr1 ; Load the low result word ldx ptr1+1 rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/lne.s����������������������������������������������������������������������0000664�0000000�0000000�00000000401�13473601511�0016103�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 05.08.1998 ; ; CC65 runtime: long not equal ; .export tosneeax .import toslcmp, boolne tosneeax: jsr toslcmp ; Set flags jmp boolne ; Convert to boolean ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/lneg.s���������������������������������������������������������������������0000664�0000000�0000000�00000000734�13473601511�0016263�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: negation on longs ; ; ; eax = -eax ; .export negeax .importzp sreg negeax: clc eor #$FF adc #1 pha txa eor #$FF adc #0 tax lda sreg eor #$FF adc #0 sta sreg lda sreg+1 eor #$FF adc #0 sta sreg+1 pla rts ������������������������������������cc65-2.18/libsrc/runtime/lor.s����������������������������������������������������������������������0000664�0000000�0000000�00000001734�13473601511�0016133�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; Christian Krueger, 11-Mar-2017, added 65SC02 optimization ; ; CC65 runtime: or on longs ; .export tosor0ax, tosoreax .import addysp1 .importzp sp, sreg, tmp1 .macpack cpu tosor0ax: .if (.cpu .bitand ::CPU_ISET_65SC02) stz sreg stz sreg+1 .else ldy #$00 sty sreg sty sreg+1 .endif tosoreax: .if (.cpu .bitand ::CPU_ISET_65SC02) ora (sp) ldy #1 .else ldy #0 ora (sp),y ; byte 0 iny .endif sta tmp1 txa ora (sp),y ; byte 1 tax iny lda sreg ora (sp),y ; byte 2 sta sreg iny lda sreg+1 ora (sp),y ; byte 3 sta sreg+1 lda tmp1 jmp addysp1 ������������������������������������cc65-2.18/libsrc/runtime/lpop.s���������������������������������������������������������������������0000664�0000000�0000000�00000001060�13473601511�0016301�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 29.12.1999 ; Christian Krueger, 11-Mar-2017, added 65SC02 optimization ; ; CC65 runtime: long pop ; .export popeax .import incsp4 .importzp sp, sreg .macpack cpu popeax: ldy #3 lda (sp),y sta sreg+1 dey lda (sp),y sta sreg dey lda (sp),y tax .if (.cpu .bitand ::CPU_ISET_65SC02) lda (sp) .else dey lda (sp),y .endif jmp incsp4 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/lpush.s��������������������������������������������������������������������0000664�0000000�0000000�00000001625�13473601511�0016471�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; Christian Krueger, 11-Mar-2017, added 65SC02 optimization ; ; CC65 runtime: long push ; ; ; push eax on stack ; .export pushl0, push0ax, pusheax .import decsp4 .importzp sp, sreg .macpack cpu pushl0: lda #0 tax push0ax: .if (.cpu .bitand ::CPU_ISET_65SC02) stz sreg stz sreg+1 .else ldy #$00 sty sreg sty sreg+1 .endif pusheax: pha ; decsp will destroy A (but not X) jsr decsp4 ldy #3 lda sreg+1 sta (sp),y dey lda sreg sta (sp),y dey txa sta (sp),y pla .if (.cpu .bitand ::CPU_ISET_65SC02) sta (sp) .else dey sta (sp),y .endif rts �����������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/lrsub.s��������������������������������������������������������������������0000664�0000000�0000000�00000002054�13473601511�0016462�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 05.08.1998 ; Christian Krueger, 11-Mar-2017, added 65SC02 optimization ; ; CC65 runtime: long sub reversed ; ; ; EAX = EAX - TOS ; .export tosrsub0ax, tosrsubeax .import addysp1 .importzp sp, sreg, tmp1 .macpack cpu tosrsub0ax: .if (.cpu .bitand ::CPU_ISET_65SC02) stz sreg stz sreg+1 .else ldy #$00 sty sreg sty sreg+1 .endif tosrsubeax: sec .if (.cpu .bitand ::CPU_ISET_65SC02) sbc (sp) ldy #1 .else ldy #0 sbc (sp),y ; byte 0 iny .endif sta tmp1 ; use as temp storage txa sbc (sp),y ; byte 1 tax iny lda sreg sbc (sp),y ; byte 2 sta sreg iny lda sreg+1 sbc (sp),y ; byte 3 sta sreg+1 lda tmp1 jmp addysp1 ; drop TOS ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/lsave.s��������������������������������������������������������������������0000664�0000000�0000000�00000001102�13473601511�0016436�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 08.08.1998 ; Christian Krueger, 11-Mar-2017, optimization ; ; CC65 runtime: save eax into temp storage/restore eax from temp storage ; .export saveeax, resteax .importzp sreg, regsave saveeax: sta regsave stx regsave+1 ldy sreg sty regsave+2 ldy sreg+1 sty regsave+3 rts resteax: lda regsave+3 sta sreg+1 lda regsave+2 sta sreg ldx regsave+1 lda regsave rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/lshelp.s�������������������������������������������������������������������0000664�0000000�0000000�00000003244�13473601511�0016624�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 13.08.1998 ; ; CC65 runtime: helper stuff for mod/div/mul with long signed ints ; ; When negating values, we will ignore the possibility here, that one of the ; values if $80000000, in which case the negate will fail. .export poplsargs .import getlop .importzp sreg, tmp1, tmp2, ptr1, ptr3, ptr4 poplsargs: jsr getlop ; Get the operands ; Remember the signs of the operands (that is, the high bytes) in tmp1 and ; tmp2. Make both operands positive. lda sreg+1 ; Is the left operand negative? sta tmp1 ; Remember the sign for later bpl L1 ; Jump if not clc ; Make it positive lda ptr1 eor #$FF adc #$01 sta ptr1 lda ptr1+1 eor #$FF adc #$00 sta ptr1+1 lda sreg eor #$FF adc #$00 sta sreg lda sreg+1 eor #$FF adc #$00 sta sreg+1 L1: lda ptr4+1 ; Is the right operand nagative? sta tmp2 ; Remember the sign for later bpl L2 ; Jump if not clc ; Make it positive lda ptr3 eor #$FF adc #$01 sta ptr3 lda ptr3+1 eor #$FF adc #$00 sta ptr3+1 lda ptr4 eor #$FF adc #$00 sta ptr4 lda ptr4+1 eor #$FF adc #$00 sta ptr4+1 L2: rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/lshl.s���������������������������������������������������������������������0000664�0000000�0000000�00000002114�13473601511�0016272�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2004-06-30 ; ; CC65 runtime: left shift support for long and unsigned long ; ; Note: The standard declares a shift count that is negative or >= the ; bitcount of the shifted type for undefined behaviour. ; ; Note^2: The compiler knowns about the register/zero page usage of this ; function, so you need to change the compiler source if you change it! ; .export tosasleax, tosshleax .import popeax .importzp sreg, tmp1 tosshleax: tosasleax: and #$1F ; Bring the shift count into a valid range sta tmp1 ; Save it jsr popeax ; Get the left hand operand ldy tmp1 ; Get shift count beq L9 ; Bail out if shift count zero stx tmp1 ; Save byte 1 ; Do the actual shift. Faster solutions are possible but need a lot more code. L2: asl a rol tmp1 rol sreg rol sreg+1 dey bne L2 ; Shift done ldx tmp1 L9: rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/lshr.s���������������������������������������������������������������������0000664�0000000�0000000�00000002064�13473601511�0016304�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2004-06-30 ; ; CC65 runtime: right shift support for unsigned longs ; ; Note: The standard declares a shift count that is negative or >= the ; bitcount of the shifted type for undefined behaviour. ; ; Note^2: The compiler knowns about the register/zero page usage of this ; function, so you need to change the compiler source if you change it! ; .export tosshreax .import popeax .importzp sreg, tmp1 tosshreax: and #$1F ; Bring the shift count into a valid range sta tmp1 ; Save it jsr popeax ; Get the left hand operand ldy tmp1 ; Get shift count beq L9 ; Bail out if shift count zero stx tmp1 ; Save byte 1 ; Do the actual shift. Faster solutions are possible but need a lot more code. L2: lsr sreg+1 ror sreg ror tmp1 ror a dey bne L2 ; Shift done ldx tmp1 L9: rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/lsub.s���������������������������������������������������������������������0000664�0000000�0000000�00000002165�13473601511�0016303�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 05.08.1998 ; Christian Krueger, 11-Mar-2017, ímproved 65SC02 optimization ; CC65 runtime: long sub ; ; ; EAX = TOS - EAX ; .export tossub0ax, tossubeax .import addysp1 .importzp sp, sreg .macpack cpu tossub0ax: .if (.cpu .bitand ::CPU_ISET_65SC02) stz sreg stz sreg+1 .else ldy #$00 sty sreg sty sreg+1 .endif tossubeax: sec eor #$FF .if (.cpu .bitand ::CPU_ISET_65SC02) adc (sp) ; 65SC02 version - saves 2 cycles ldy #1 .else ldy #0 adc (sp),y ; lo byte iny .endif pha ; Save low byte txa eor #$FF adc (sp),y ; byte 1 tax iny lda (sp),y sbc sreg ; byte 2 sta sreg iny lda (sp),y sbc sreg+1 ; byte 3 sta sreg+1 pla ; Restore byte 0 jmp addysp1 ; Drop TOS �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/lsubeq.s�������������������������������������������������������������������0000664�0000000�0000000�00000003205�13473601511�0016625�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 07.04.2000 ; Christian Krueger, 12-Mar-2017, added 65SC02 optimization ; ; CC65 runtime: -= operator ; ; On entry, the low byte of the address of the variable to decrement is ; in ptr1, the high byte is in Y, and the decrement is in eax. ; .export lsubeq1, lsubeqa, lsubeq .importzp sreg, ptr1 .macpack cpu lsubeq1: lda #$01 lsubeqa: ldx #$00 stx sreg stx sreg+1 lsubeq: sty ptr1+1 ; Store high byte of address sec eor #$FF .if (.cpu .bitand ::CPU_ISET_65SC02) adc (ptr1) ; Subtract byte 0 sta (ptr1) ldy #$01 ; Address byte 1 .else ldy #$00 ; Address low byte adc (ptr1),y ; Subtract byte 0 sta (ptr1),y iny ; Address byte 1 .endif pha ; Save byte 0 of result for later txa eor #$FF adc (ptr1),y ; Subtract byte 1 sta (ptr1),y tax iny ; Address byte 2 lda (ptr1),y sbc sreg sta (ptr1),y sta sreg iny ; Address byte 3 lda (ptr1),y sbc sreg+1 sta (ptr1),y sta sreg+1 pla ; Retrieve byte 0 of result rts ; Done �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/lsubeqsp.s�����������������������������������������������������������������0000664�0000000�0000000�00000001241�13473601511�0017166�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 08.10.1998 ; ; CC65 runtime: -= operator for longs on the stack ; .export lsubeq0sp, lsubeqysp .importzp sp, sreg lsubeq0sp: ldy #0 lsubeqysp: sec eor #$FF adc (sp),y sta (sp),y pha ; Save low byte iny txa eor #$FF adc (sp),y sta (sp),y tax iny lda (sp),y sbc sreg sta (sp),y sta sreg iny lda (sp),y sbc sreg+1 sta (sp),y sta sreg+1 pla rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/lt.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000527�13473601511�0015755�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: Compare < for signed ints ; .export toslt00, toslta0, tosltax .import tosicmp, boollt toslt00: lda #$00 toslta0: ldx #$00 tosltax: jsr tosicmp ; Set flags jmp boollt ; Convert to boolean �������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/ltest.s��������������������������������������������������������������������0000664�0000000�0000000�00000000643�13473601511�0016470�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 07.08.1998 ; ; CC65 runtime: test long in eax ; .export utsteax, tsteax .importzp sreg, tmp1 tsteax: utsteax: tay ; Save value stx tmp1 ora tmp1 ora sreg ora sreg+1 beq L9 tya ldy #1 ; Force NE L9: rts ���������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/ludiv.s��������������������������������������������������������������������0000664�0000000�0000000�00000005226�13473601511�0016462�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 17.08.1998 ; Christian Krueger, 11-Mar-2017, added 65SC02 optimization ; ; CC65 runtime: division for long unsigned ints ; .export tosudiv0ax, tosudiveax, getlop, udiv32 .import addysp1 .importzp sp, sreg, tmp3, tmp4, ptr1, ptr2, ptr3, ptr4 .macpack cpu tosudiv0ax: .if (.cpu .bitand ::CPU_ISET_65SC02) stz sreg stz sreg+1 .else ldy #$00 sty sreg sty sreg+1 .endif tosudiveax: jsr getlop ; Get the paramameters jsr udiv32 ; Do the division lda ptr1 ; Result is in ptr1:sreg ldx ptr1+1 rts ; Pop the parameters for the long division and put it into the relevant ; memory cells. Called from the signed divisions also. getlop: sta ptr3 ; Put right operand in place stx ptr3+1 lda sreg sta ptr4 lda sreg+1 sta ptr4+1 .if (.cpu .bitand ::CPU_ISET_65SC02) lda (sp) ldy #1 .else ldy #0 ; Put left operand in place lda (sp),y iny .endif sta ptr1 lda (sp),y sta ptr1+1 iny lda (sp),y sta sreg iny lda (sp),y sta sreg+1 jmp addysp1 ; Drop parameters ; Do (ptr1:sreg) / (ptr3:ptr4) --> (ptr1:sreg), remainder in (ptr2:tmp3:tmp4) ; This is also the entry point for the signed division udiv32: lda #0 sta ptr2+1 sta tmp3 sta tmp4 ; sta ptr1+1 ldy #32 L0: asl ptr1 rol ptr1+1 rol sreg rol sreg+1 rol a rol ptr2+1 rol tmp3 rol tmp4 ; Do a subtraction. we do not have enough space to store the intermediate ; result, so we may have to do the subtraction twice. tax cmp ptr3 lda ptr2+1 sbc ptr3+1 lda tmp3 sbc ptr4 lda tmp4 sbc ptr4+1 bcc L1 ; Overflow, do the subtraction again, this time store the result sta tmp4 ; We have the high byte already txa sbc ptr3 ; byte 0 tax lda ptr2+1 sbc ptr3+1 sta ptr2+1 ; byte 1 lda tmp3 sbc ptr4 sta tmp3 ; byte 2 inc ptr1 ; Set result bit L1: txa dey bne L0 sta ptr2 rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/luge.s���������������������������������������������������������������������0000664�0000000�0000000�00000000426�13473601511�0016270�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 10.12.1998 ; ; CC65 runtime: Compare >= for long unsigneds ; .export tosugeeax .import toslcmp, booluge tosugeeax: jsr toslcmp ; Set the flags jmp booluge ; Convert to boolean ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/lugt.s���������������������������������������������������������������������0000664�0000000�0000000�00000000426�13473601511�0016307�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 10.12.1998 ; ; CC65 runtime: Compare > for long unsigneds ; .export tosugteax .import toslcmp, boolugt tosugteax: jsr toslcmp ; Set the flags jmp boolugt ; Convert to boolean ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/lule.s���������������������������������������������������������������������0000664�0000000�0000000�00000000426�13473601511�0016275�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 10.12.1998 ; ; CC65 runtime: Compare <= for long unsigneds ; .export tosuleeax .import toslcmp, boolule tosuleeax: jsr toslcmp ; Set the flags jmp boolule ; Convert to boolean ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/lult.s���������������������������������������������������������������������0000664�0000000�0000000�00000000424�13473601511�0016312�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 10.12.1998 ; ; CC65 runtime: Compare < for long unsigneds ; .export tosulteax .import toslcmp, boolult tosulteax: jsr toslcmp ; Set the flags jmp boolult ; Convert to boolean ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/lumod.s��������������������������������������������������������������������0000664�0000000�0000000�00000001470�13473601511�0016454�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 27.09.1998 ; Christian Krueger, 11-Mar-2017, added 65SC02 optimization ; ; CC65 runtime: modulo operation for long unsigned ints ; .export tosumod0ax, tosumodeax .import getlop, udiv32 .importzp sreg, tmp3, tmp4, ptr2 .macpack cpu tosumod0ax: .if (.cpu .bitand ::CPU_ISET_65SC02) stz sreg stz sreg+1 .else ldy #$00 sty sreg sty sreg+1 .endif tosumodeax: jsr getlop ; Get the paramameters jsr udiv32 ; Do the division lda tmp3 ; Remainder is in ptr2:tmp3:tmp4 sta sreg lda tmp4 sta sreg+1 lda ptr2 ldx ptr2+1 rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/lxor.s���������������������������������������������������������������������0000664�0000000�0000000�00000001744�13473601511�0016324�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; Christian Krueger, 11-Mar-2017, added 65SC02 optimization ; ; CC65 runtime: xor on longs ; .export tosxor0ax, tosxoreax .import addysp1 .importzp sp, sreg, tmp1 .macpack cpu tosxor0ax: .if (.cpu .bitand ::CPU_ISET_65SC02) stz sreg stz sreg+1 .else ldy #$00 sty sreg sty sreg+1 .endif tosxoreax: .if (.cpu .bitand ::CPU_ISET_65SC02) eor (sp) ; byte 0 ldy #1 .else ldy #0 eor (sp),y ; byte 0 iny .endif sta tmp1 txa eor (sp),y ; byte 1 tax iny lda sreg eor (sp),y ; byte 2 sta sreg iny lda sreg+1 eor (sp),y ; byte 3 sta sreg+1 lda tmp1 jmp addysp1 ����������������������������cc65-2.18/libsrc/runtime/makebool.s�����������������������������������������������������������������0000664�0000000�0000000�00000001440�13473601511�0017122�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 05.10.1998 ; Christian Krueger, 11-Mar-2017, optimization ; ; CC65 runtime: Make boolean according to flags ; .export boolne, booleq, boollt, boolle, boolgt, boolge .export boolult, boolule, boolugt, booluge boolne: bne ret1 ret0: ldx #$00 txa rts booleq: bne ret0 ret1: ldx #$00 lda #$01 rts boolle: beq ret1 boollt: bmi ret1 ldx #$00 txa rts boolgt: beq L0 boolge: bpl ret1 L0: ldx #$00 txa rts boolule: beq ret1 boolult: bcc ret1 ldx #$00 txa rts boolugt: beq ret0 booluge: ldx #$00 txa rol a rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/mod.s����������������������������������������������������������������������0000664�0000000�0000000�00000002037�13473601511�0016113�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 07.08.1998 ; ; CC65 runtime: modulo operation for signed ints ; ; When negating values, we will ignore the possibility here, that one of the ; values is $8000, in which case the negate will fail. .export tosmoda0, tosmodax .import popsargsudiv16, negax .importzp sreg, tmp1 tosmoda0: ldx #0 tosmodax: jsr popsargsudiv16 ; Get arguments from stack, adjust sign ; and do the division lda sreg ; Load low byte of result ldx sreg+1 ; Load high byte of result ; Adjust the sign of the result. tmp1 contains the high byte of the left ; operand, tmp2 contains the high byte of the right operand. The sign of ; the result of the modulo operation is the same as that of the left ; operand bit tmp1 bpl Pos ; Jump if sign of result positive ; Result is negative jmp negax ; Adjust the sign ; Result is positive Pos: rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/mul.s����������������������������������������������������������������������0000664�0000000�0000000�00000004004�13473601511�0016125�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2009-08-17 ; ; CC65 runtime: multiplication for ints ; .export tosumulax, tosmulax .import mul8x16, mul8x16a ; in mul8.s .import popptr1 .importzp tmp1, ptr1, ptr4 ;--------------------------------------------------------------------------- ; 16x16 multiplication routine tosmulax: tosumulax: sta ptr4 txa ; High byte zero beq @L3 ; Do 8x16 multiplication if high byte zero stx ptr4+1 ; Save right operand jsr popptr1 ; Get left operand (Y=0, X untouched by popptr1) ; Do ptr4:ptr4+1 * ptr1:ptr1+1 --> AX tya ; A = 0 ldy ptr1+1 ; check if lhs is 8 bit only beq @L4 ; -> we can do 8x16 after swap sta tmp1 ldy #16 ; Number of bits lsr ptr4+1 ror ptr4 ; Get first bit into carry @L0: bcc @L1 clc adc ptr1 tax lda ptr1+1 ; Hi byte of left op adc tmp1 sta tmp1 txa @L1: ror tmp1 ror a ror ptr4+1 ror ptr4 dey bne @L0 lda ptr4 ; Load the result ldx ptr4+1 rts ; Done ; High byte of rhs is zero, jump to the 8x16 routine instead @L3: jmp mul8x16 ; If the high byte of lhs is zero, swap the operands in ptr1/4 and ; use the 8x16 routine. On entry, A and Y are zero and X has the value ; of ptr4+1 @L4: stx ptr1+1 ; Store hi-byte from ptr4 ldy ptr1 ; Save right operand (8 bit) ldx ptr4 ; Copy left 16 bit operand to right stx ptr1 sty ptr4 ; Copy low 8 bit of right op to left ldy #8 jmp mul8x16a ; There, ptr4+1 will be also cleared ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/mul8.s���������������������������������������������������������������������0000664�0000000�0000000�00000003112�13473601511�0016214�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2009-08-17 ; ; CC65 runtime: multiplication for ints. Short versions. ; .export tosumula0, tosmula0 .export mul8x16, mul8x16a .import popptr1 .importzp ptr1, ptr4 ;--------------------------------------------------------------------------- ; 8x16 routine with external entry points used by the 16x16 routine in mul.s tosmula0: tosumula0: sta ptr4 mul8x16:jsr popptr1 ; Get left operand (Y=0 by popptr1) tya ; Clear byte 1 ldy #8 ; Number of bits ldx ptr1+1 ; check if lhs is 8 bit only beq mul8x8 ; Do 8x8 multiplication if high byte zero mul8x16a: sta ptr4+1 ; Clear byte 2 lsr ptr4 ; Get first bit into carry @L0: bcc @L1 clc adc ptr1 tax lda ptr1+1 ; hi byte of left op adc ptr4+1 sta ptr4+1 txa @L1: ror ptr4+1 ror a ror ptr4 dey bne @L0 tax lda ptr4 ; Load the result rts ;--------------------------------------------------------------------------- ; 8x8 multiplication routine mul8x8: lsr ptr4 ; Get first bit into carry @L0: bcc @L1 clc adc ptr1 @L1: ror ror ptr4 dey bne @L0 tax lda ptr4 ; Load the result rts ; Done ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/mulax10.s������������������������������������������������������������������0000664�0000000�0000000�00000001001�13473601511�0016611�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Piotr Fusik, 24.10.2003 ; originally by Ullrich von Bassewitz ; ; CC65 runtime: Multiply the primary register by 10 ; .export mulax10 .importzp ptr1 .proc mulax10 sta ptr1 stx ptr1+1 asl a rol ptr1+1 asl a rol ptr1+1 clc adc ptr1 sta ptr1 txa adc ptr1+1 asl ptr1 rol a tax lda ptr1 rts .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/mulax3.s�������������������������������������������������������������������0000664�0000000�0000000�00000000717�13473601511�0016550�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 04.10.2001 ; ; CC65 runtime: Multiply the primary register by 3 ; ; Don't touch the Y-register here, the optimizer relies on it! .export mulax3 .importzp ptr1 .proc mulax3 sta ptr1 stx ptr1+1 asl a rol ptr1+1 clc adc ptr1 pha txa adc ptr1+1 tax pla rts .endproc �������������������������������������������������cc65-2.18/libsrc/runtime/mulax5.s�������������������������������������������������������������������0000664�0000000�0000000�00000000750�13473601511�0016547�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 04.10.2001 ; ; CC65 runtime: Multiply the primary register by 5 ; ; Don't touch the Y-register here, the optimizer relies on it! .export mulax5 .importzp ptr1 .proc mulax5 sta ptr1 stx ptr1+1 asl a rol ptr1+1 asl a rol ptr1+1 clc adc ptr1 pha txa adc ptr1+1 tax pla rts .endproc ������������������������cc65-2.18/libsrc/runtime/mulax6.s�������������������������������������������������������������������0000664�0000000�0000000�00000000725�13473601511�0016552�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Piotr Fusik, 24.10.2003 ; originally by Ullrich von Bassewitz ; ; CC65 runtime: Multiply the primary register by 6 ; .export mulax6 .importzp ptr1 .proc mulax6 sta ptr1 stx ptr1+1 asl a rol ptr1+1 clc adc ptr1 sta ptr1 txa adc ptr1+1 asl ptr1 rol a tax lda ptr1 rts .endproc �������������������������������������������cc65-2.18/libsrc/runtime/mulax7.s�������������������������������������������������������������������0000664�0000000�0000000�00000001244�13473601511�0016550�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Piotr Fusik, 24.10.2003 ; originally by Ullrich von Bassewitz ; ; CC65 runtime: Multiply the primary register by 7 ; ; Don't touch the Y-register here, the optimizer relies on it! .export mulax7 .importzp ptr1 .proc mulax7 sta ptr1 stx ptr1+1 asl a rol ptr1+1 ; * 2 asl a rol ptr1+1 ; * 4 asl a rol ptr1+1 ; * 8 sec sbc ptr1 pha txa eor #$ff adc ptr1+1 ; * (8 - 1) tax pla rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/mulax9.s�������������������������������������������������������������������0000664�0000000�0000000�00000001217�13473601511�0016552�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Piotr Fusik, 24.10.2003 ; originally by Ullrich von Bassewitz ; ; CC65 runtime: Multiply the primary register by 9 ; ; Don't touch the Y-register here, the optimizer relies on it! .export mulax9 .importzp ptr1 .proc mulax9 sta ptr1 stx ptr1+1 asl a rol ptr1+1 ; * 2 asl a rol ptr1+1 ; * 4 asl a rol ptr1+1 ; * 8 clc adc ptr1 ; * (8+1) pha txa adc ptr1+1 tax pla rts .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/ne.s�����������������������������������������������������������������������0000664�0000000�0000000�00000000522�13473601511�0015733�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: Compare != for ints ; .export tosne00, tosnea0, tosneax .import tosicmp, boolne tosne00: lda #$00 tosnea0: ldx #$00 tosneax: jsr tosicmp ; Set flags jmp boolne ; Convert to boolean ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/negabs.s�������������������������������������������������������������������0000664�0000000�0000000�00000000645�13473601511�0016576�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 05.08.1998 ; ; int abs (int x); ; and ; CC65 runtime: negation on ints ; .export negax .export _abs _abs: cpx #$00 ; Test hi byte bpl L1 ; Don't touch if positive negax: clc eor #$FF adc #1 pha txa eor #$FF adc #0 tax pla L1: rts �������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/or.s�����������������������������������������������������������������������0000664�0000000�0000000�00000001143�13473601511�0015751�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 05.08.1998 ; Christian Krueger, 11-Mar-2017, added 65SC02 optimization ; ; CC65 runtime: or on ints ; .export tosora0, tosorax .import addysp1 .importzp sp, tmp1 .macpack cpu tosora0: ldx #$00 tosorax: .if (.cpu .bitand ::CPU_ISET_65SC02) ora (sp) ldy #1 .else ldy #0 ora (sp),y iny .endif sta tmp1 txa ora (sp),y tax lda tmp1 jmp addysp1 ; drop TOS, set condition codes �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/popa.s���������������������������������������������������������������������0000664�0000000�0000000�00000000760�13473601511�0016274�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.10.2000 ; ; CC65 runtime: Pop a from stack ; .export popa .importzp sp .macpack cpu .proc popa .if (.cpu .bitand ::CPU_ISET_65SC02) lda (sp) .else ldy #0 ; (2) lda (sp),y ; (7) Read byte .endif inc sp ; (12) beq @L1 ; (14) rts ; (20) @L1: inc sp+1 rts .endproc ����������������cc65-2.18/libsrc/runtime/popptr1.s������������������������������������������������������������������0000664�0000000�0000000�00000001176�13473601511�0016744�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Christian Kruger, 20-May-2018 ; ; CC65 runtime: Pop 2 bytes from stack to ptr1. ; X is untouched, low byte in A, Y is defined to be 0! .export popptr1 .import incsp2 .importzp sp, ptr1 .proc popptr1 ; 14 bytes (four usages = at least 2 bytes saved) ldy #1 lda (sp),y ; get hi byte sta ptr1+1 ; into ptr hi dey ; no optimization for 65C02 here to have Y=0 at exit! lda (sp),y ; get lo byte sta ptr1 ; to ptr lo jmp incsp2 .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/popsreg.s������������������������������������������������������������������0000664�0000000�0000000�00000001240�13473601511�0017006�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 1998-08-21, 2009-02-22 ; ; CC65 runtime: Pop TOS into sreg ; .export popsreg .import incsp2 .importzp sp, sreg .macpack cpu popsreg: pha ; save A ldy #1 lda (sp),y ; get hi byte sta sreg+1 ; store it .if (.cpu .bitand ::CPU_ISET_65SC02) lda (sp) ; get lo byte .else dey lda (sp),y ; get lo byte .endif sta sreg ; store it pla ; get A back jmp incsp2 ; bump stack and return ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/push1.s��������������������������������������������������������������������0000664�0000000�0000000�00000000415�13473601511�0016372�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.10.2000 ; ; CC65 runtime: Push (int)1 onto the stack ; .export push1 .import pusha0 ; Beware: The optimizer knows about this function! .proc push1 lda #1 jmp pusha0 .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/push2.s��������������������������������������������������������������������0000664�0000000�0000000�00000000415�13473601511�0016373�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.10.2000 ; ; CC65 runtime: Push (int)2 onto the stack ; .export push2 .import pusha0 ; Beware: The optimizer knows about this function! .proc push2 lda #2 jmp pusha0 .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/push3.s��������������������������������������������������������������������0000664�0000000�0000000�00000000415�13473601511�0016374�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.10.2000 ; ; CC65 runtime: Push (int)3 onto the stack ; .export push3 .import pusha0 ; Beware: The optimizer knows about this function! .proc push3 lda #3 jmp pusha0 .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/push4.s��������������������������������������������������������������������0000664�0000000�0000000�00000000415�13473601511�0016375�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.10.2000 ; ; CC65 runtime: Push (int)4 onto the stack ; .export push4 .import pusha0 ; Beware: The optimizer knows about this function! .proc push4 lda #4 jmp pusha0 .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/push5.s��������������������������������������������������������������������0000664�0000000�0000000�00000000415�13473601511�0016376�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.10.2000 ; ; CC65 runtime: Push (int)5 onto the stack ; .export push5 .import pusha0 ; Beware: The optimizer knows about this function! .proc push5 lda #5 jmp pusha0 .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/push6.s��������������������������������������������������������������������0000664�0000000�0000000�00000000415�13473601511�0016377�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.10.2000 ; ; CC65 runtime: Push (int)6 onto the stack ; .export push6 .import pusha0 ; Beware: The optimizer knows about this function! .proc push6 lda #6 jmp pusha0 .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/push7.s��������������������������������������������������������������������0000664�0000000�0000000�00000000415�13473601511�0016400�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.10.2000 ; ; CC65 runtime: Push (int)7 onto the stack ; .export push7 .import pusha0 ; Beware: The optimizer knows about this function! .proc push7 lda #7 jmp pusha0 .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/pusha.s��������������������������������������������������������������������0000664�0000000�0000000�00000001277�13473601511�0016461�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.10.2000 ; ; CC65 runtime: Push value in a onto the stack ; .export pusha0sp, pushaysp, pusha .importzp sp .macpack cpu ; Beware: The optimizer knows about this function! pusha0sp: ldy #$00 pushaysp: lda (sp),y pusha: ldy sp ; (3) beq @L1 ; (6) dec sp ; (11) ldy #0 ; (13) sta (sp),y ; (19) rts ; (25) @L1: dec sp+1 ; (11) dec sp ; (16) sta (sp),y ; (22) rts ; (28) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/pushaff.s������������������������������������������������������������������0000664�0000000�0000000�00000000466�13473601511�0016774�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.10.2000 ; ; CC65 runtime: Push a extended with FF onto the stack ; .export pushaFF .import pushax ; Beware: The optimizer knows about this function! .proc pushaFF ldx #$FF jmp pushax .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/pushax.s�������������������������������������������������������������������0000664�0000000�0000000�00000001756�13473601511�0016653�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.10.2000 ; ; CC65 runtime: Push value in a/x onto the stack ; .export push0, pusha0, pushax .importzp sp push0: lda #0 pusha0: ldx #0 ; This function is used *a lot*, so don't call any subroutines here. ; Beware: The value in ax must not be changed by this function! ; Beware^2: The optimizer knows about the value of Y after the function ; returns! .proc pushax pha ; (3) lda sp ; (6) sec ; (8) sbc #2 ; (10) sta sp ; (13) bcs @L1 ; (17) dec sp+1 ; (+5) @L1: ldy #1 ; (19) txa ; (21) sta (sp),y ; (27) pla ; (31) dey ; (33) sta (sp),y ; (38) rts ; (44) .endproc ������������������cc65-2.18/libsrc/runtime/pushb.s��������������������������������������������������������������������0000664�0000000�0000000�00000001174�13473601511�0016456�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 31.08.1998 ; ; CC65 runtime: Push word from stack ; .export pushb, pushbidx .import pushax .importzp ptr1 .macpack cpu pushbidx: sty ptr1 clc adc ptr1 bcc pushb inx pushb: sta ptr1 stx ptr1+1 ldx #0 ; Load index/high byte .if (.cpu .bitand CPU_ISET_65SC02) lda (ptr1) ; Save one cycle for the C02 .else lda (ptr1,x) .endif bpl L1 dex ; Make high byte FF L1: jmp pushax ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/pushbsp.s������������������������������������������������������������������0000664�0000000�0000000�00000000535�13473601511�0017021�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 31.08.1998 ; ; CC65 runtime: Load a from stack slot and push as word ; .export pushbsp, pushbysp .import pusha0 .importzp sp pushbsp: ldy #0 pushbysp: lda (sp),y ; get lo byte jmp pusha0 ; promote to unsigned and push �������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/pushc0.s�������������������������������������������������������������������0000664�0000000�0000000�00000000416�13473601511�0016535�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.10.2000 ; ; CC65 runtime: Push (char)0 onto the stack ; .export pushc0 .import pusha ; Beware: The optimizer knows about this function! .proc pushc0 lda #0 jmp pusha .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/pushc1.s�������������������������������������������������������������������0000664�0000000�0000000�00000000416�13473601511�0016536�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.10.2000 ; ; CC65 runtime: Push (char)1 onto the stack ; .export pushc1 .import pusha ; Beware: The optimizer knows about this function! .proc pushc1 lda #1 jmp pusha .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/pushc2.s�������������������������������������������������������������������0000664�0000000�0000000�00000000416�13473601511�0016537�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.10.2000 ; ; CC65 runtime: Push (char)2 onto the stack ; .export pushc2 .import pusha ; Beware: The optimizer knows about this function! .proc pushc2 lda #2 jmp pusha .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/pushlysp.s�����������������������������������������������������������������0000664�0000000�0000000�00000000731�13473601511�0017222�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.06.1998 ; ; CC65 runtime: Push a long from somewhere in the stack ; .export pushlysp .import pusheax .importzp sreg, sp .proc pushlysp iny iny lda (sp),y iny sta sreg lda (sp),y sta sreg+1 dey dey lda (sp),y dey tax lda (sp),y jmp pusheax .endproc ���������������������������������������cc65-2.18/libsrc/runtime/pushw.s��������������������������������������������������������������������0000664�0000000�0000000�00000000603�13473601511�0016477�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 31.08.1998 ; ; CC65 runtime: Fetch word indirect and push ; .export pushw, pushwidx, pushptr1idx .import pushax .importzp ptr1 pushw: ldy #1 pushwidx: sta ptr1 stx ptr1+1 pushptr1idx: lda (ptr1),y tax dey lda (ptr1),y jmp pushax �����������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/pushwsp.s������������������������������������������������������������������0000664�0000000�0000000�00000001375�13473601511�0017051�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 24.10.2001 ; ; CC65 runtime: Load word from stack slot and push ; .export pushwysp, pushw0sp .importzp sp .macpack generic pushw0sp: ldy #3 pushwysp: lda sp ; 3 sub #2 ; 4 sta sp ; 3 bcs @L1 ; 3(+1) dec sp+1 ; (5) @L1: lda (sp),y ; 5 =16 tax ; 2 dey ; 2 lda (sp),y ; 5 ldy #$00 ; 2 sta (sp),y ; 5 iny ; 2 txa ; 2 sta (sp),y ; 5 rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/regswap.s������������������������������������������������������������������0000664�0000000�0000000�00000001161�13473601511�0017001�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.11.2002 ; ; CC65 runtime: Swap x bytes of register variable space ; .export regswap .importzp sp, regbank, tmp1 .proc regswap sta tmp1 ; Store count @L1: lda regbank,x ; Get old value pha ; Save it lda (sp),y ; Get stack loc sta regbank,x ; Store new value pla sta (sp),y ; Store old value inx iny dec tmp1 bne @L1 rts .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/regswap1.s�����������������������������������������������������������������0000664�0000000�0000000�00000000764�13473601511�0017072�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.11.2002 ; ; CC65 runtime: Swap 1 byte of register variable space ; .export regswap1 .importzp sp, regbank .proc regswap1 lda regbank,x ; Get old value pha ; Save it lda (sp),y ; Get stack loc sta regbank,x ; Store new value pla sta (sp),y ; Store old value rts .endproc ������������cc65-2.18/libsrc/runtime/regswap2.s�����������������������������������������������������������������0000664�0000000�0000000�00000001502�13473601511�0017062�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.11.2002 ; ; CC65 runtime: Swap 2 bytes of register variable space ; .export regswap2 .importzp sp, regbank .proc regswap2 ; First byte lda regbank,x ; Get old value pha ; Save it lda (sp),y ; Get stack loc sta regbank,x ; Store new value pla sta (sp),y ; Store old value ; Second byte iny lda regbank+1,x ; Get old value pha ; Save it lda (sp),y ; Get stack loc sta regbank+1,x ; Store new value pla sta (sp),y ; Store old value rts .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/return0.s������������������������������������������������������������������0000664�0000000�0000000�00000000277�13473601511�0016737�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.10.2000 ; ; CC65 runtime: Return 0 in a/x ; .export return0 .proc return0 lda #0 tax rts .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/return1.s������������������������������������������������������������������0000664�0000000�0000000�00000000306�13473601511�0016731�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.10.2000 ; ; CC65 runtime: Return 1 in a/x ; .export return1 .proc return1 ldx #0 lda #1 rts .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/rsub.s���������������������������������������������������������������������0000664�0000000�0000000�00000001310�13473601511�0016300�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 05.08.1998 ; Christian Krueger, 11-Mar-2017, added 65SC02 optimization ; ; CC65 runtime: sub ints reversed ; .export tosrsuba0, tosrsubax .import addysp1 .importzp sp, tmp1 .macpack cpu ; ; AX = AX - TOS ; tosrsuba0: ldx #0 tosrsubax: sec .if (.cpu .bitand CPU_ISET_65SC02) sbc (sp) ldy #1 .else ldy #0 sbc (sp),y ; lo byte iny .endif sta tmp1 ; save lo byte txa sbc (sp),y ; hi byte tax lda tmp1 jmp addysp1 ; drop TOS, set condition codes ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/shelp.s��������������������������������������������������������������������0000664�0000000�0000000�00000001470�13473601511�0016447�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 07.08.1998 ; ; CC65 runtime: helper stuff for mod/div with signed ints ; ; When negating values, we will ignore the possibility here, that one of the ; values is $8000, in which case the negate will fail. .export popsargsudiv16 .import negax, popax, udiv16 .importzp tmp1, tmp2, ptr1, ptr4 popsargsudiv16: stx tmp2 ; Remember sign cpx #0 bpl L1 jsr negax ; Negate accumulator L1: sta ptr4 stx ptr4+1 ; Save right operand jsr popax stx tmp1 ; Remember sign cpx #0 bpl L2 jsr negax L2: sta ptr1 stx ptr1+1 jmp udiv16 ; Call the division ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/shl.s����������������������������������������������������������������������0000664�0000000�0000000�00000004000�13473601511�0016112�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 1998-08-05, 2004-06-25 ; ; CC65 runtime: left shift support for ints and unsigneds ; ; Note: The standard declares a shift count that is negative or >= the ; bitcount of the shifted type for undefined behaviour. ; ; Note^2: The compiler knowns about the register/zero page usage of this ; function, so you need to change the compiler source if you change it! ; .export tosaslax, tosshlax, aslaxy, shlaxy .import popax .importzp tmp1 .macpack cpu tosshlax: tosaslax: sta tmp1 ; Save shift count jsr popax ; Get the left hand operand ldy tmp1 ; Get shift count ; Run into shlaxy shlaxy: aslaxy: pha tya and #$0F beq L2 ; Nothing to shift sec sbc #8 ; Shift count 8 or greater? beq L3 ; Jump if exactly 8 bcc L4 ; Jump if less than 8 ; Shift count is greater than 8. tay ; Shift count into Y pla ; Get low byte L1: asl a dey bne L1 tax tya ; A = 0 rts ; Shift count is zero L2: pla rts ; Shift count is exactly 8 .if (.cpu .bitand CPU_ISET_65SC02) L3: plx ; Low byte from stack into X rts ; A is already zero .else L3: pla ; Low byte from stack ... tax ; ... into X lda #$00 ; Clear low byte rts .endif ; Shift count is less than 8 L4: adc #8 ; Correct counter tay ; Shift count into Y pla ; Restore low byte stx tmp1 ; Save high byte of lhs L5: asl a rol tmp1 dey bne L5 ; Done with shift ldx tmp1 L9: rts cc65-2.18/libsrc/runtime/shr.s����������������������������������������������������������������������0000664�0000000�0000000�00000003515�13473601511�0016132�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2004-06-30 ; ; CC65 runtime: right shift support for unsigneds ; ; Note: The standard declares a shift count that is negative or >= the ; bitcount of the shifted type for undefined behaviour. ; ; Note^2: The compiler knowns about the register/zero page usage of this ; function, so you need to change the compiler source if you change it! ; .export tosshrax, shraxy .import popax .importzp tmp1 tosshrax: sta tmp1 ; Save shift count jsr popax ; Get the left hand operand ldy tmp1 ; Get shift count ; Run into shraxy shraxy: pha tya and #$0F beq L2 ; Nothing to shift sec sbc #8 ; Shift count 8 or greater? beq L3 ; Jump if exactly 8 bcc L4 ; Jump if less than 8 ; Shift count is greater than 8. tay ; Shift count into Y pla ; Discard low byte txa ; Get high byte L1: lsr a dey bne L1 ldx #$00 ; High byte is zero rts ; Shift count is zero L2: pla rts ; Shift count is exactly 8 L3: pla ; Drop low byte from stack ... txa ; Move high byte to low ldx #$00 ; Clear high byte rts ; Shift count is less than 8 L4: adc #8 ; Correct counter tay ; Shift count into Y pla ; Restore low byte stx tmp1 ; Save high byte of lhs L5: lsr tmp1 ror a dey bne L5 ; Done with shift ldx tmp1 rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/shrax1.s�������������������������������������������������������������������0000664�0000000�0000000�00000000361�13473601511�0016540�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: Scale the primary register ; .export shrax1 .importzp tmp1 shrax1: stx tmp1 lsr tmp1 ror a ldx tmp1 rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/shrax2.s�������������������������������������������������������������������0000664�0000000�0000000�00000000436�13473601511�0016544�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: Scale the primary register by 4 ; .export shrax2 .importzp tmp1 shrax2: stx tmp1 lsr tmp1 ror a lsr tmp1 ror a ldx tmp1 rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/shrax3.s�������������������������������������������������������������������0000664�0000000�0000000�00000000505�13473601511�0016542�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: Scale the primary register by 8 ; .export shrax3 .importzp tmp1 shrax3: stx tmp1 lsr tmp1 ror a lsr tmp1 ror a lsr tmp1 ror a ldx tmp1 rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/shrax4.s�������������������������������������������������������������������0000664�0000000�0000000�00000000555�13473601511�0016550�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.07.2001 ; ; CC65 runtime: Scale the primary register by 16 ; .export shrax4 .importzp tmp1 shrax4: stx tmp1 lsr tmp1 ror a lsr tmp1 ror a lsr tmp1 ror a lsr tmp1 ror a ldx tmp1 rts ���������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/shreax1.s������������������������������������������������������������������0000664�0000000�0000000�00000000471�13473601511�0016707�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: Scale the 32 bit primary register by 2 ; .export shreax1 .importzp sreg, tmp1 shreax1: stx tmp1 lsr sreg+1 ror sreg ror tmp1 ror a ldx tmp1 rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/shreax2.s������������������������������������������������������������������0000664�0000000�0000000�00000000614�13473601511�0016707�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: Scale the 32 bit primary register by 4 ; .export shreax2 .importzp sreg, tmp1 shreax2: stx tmp1 lsr sreg+1 ror sreg ror tmp1 ror a lsr sreg+1 ror sreg ror tmp1 ror a ldx tmp1 rts ��������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/shreax3.s������������������������������������������������������������������0000664�0000000�0000000�00000000737�13473601511�0016716�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: Scale the 32 bit primary register by 8 ; .export shreax3 .importzp sreg, tmp1 shreax3: stx tmp1 lsr sreg+1 ror sreg ror tmp1 ror a lsr sreg+1 ror sreg ror tmp1 ror a lsr sreg+1 ror sreg ror tmp1 ror a ldx tmp1 rts ���������������������������������cc65-2.18/libsrc/runtime/shreax4.s������������������������������������������������������������������0000664�0000000�0000000�00000000555�13473601511�0016715�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.07.2001 ; ; CC65 runtime: Scale the 32 bit primary register by 16 ; .export shreax4 .importzp sreg, tmp1 shreax4: stx tmp1 ldx #4 @L1: lsr sreg+1 ror sreg ror tmp1 ror a dex bne @L1 ldx tmp1 rts ���������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/staspidx.s�����������������������������������������������������������������0000664�0000000�0000000�00000001205�13473601511�0017167�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.10.2000 ; ; CC65 runtime: Store a indirect into address at top of stack with index ; .export staspidx .import incsp2 .importzp sp, tmp1, ptr1 .proc staspidx pha sty tmp1 ; Save Index ldy #1 lda (sp),y sta ptr1+1 dey lda (sp),y sta ptr1 ; Pointer now in ptr1 ldy tmp1 ; Restore offset pla ; Restore value sta (ptr1),y ; Store jmp incsp2 ; Drop address .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/staxsp.s�������������������������������������������������������������������0000664�0000000�0000000�00000000443�13473601511�0016655�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 31.08.1998 ; ; CC65 runtime: Store ax at (sp),y ; .export staxysp, stax0sp .importzp sp stax0sp: ldy #0 staxysp: sta (sp),y iny pha txa sta (sp),y pla rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/staxspi.s������������������������������������������������������������������0000664�0000000�0000000�00000002031�13473601511�0017021�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.10.2000 ; Christian Krueger, 12-Mar-2017, added 65SC02 optimization ; ; CC65 runtime: Store a/x indirect into address at top of stack with index ; .export staxspidx .import incsp2 .importzp sp, tmp1, ptr1 .macpack cpu .proc staxspidx sty tmp1 ; Save Y pha ; Save A ldy #1 lda (sp),y sta ptr1+1 .if (.cpu .bitand ::CPU_ISET_65SC02) lda (sp) .else dey lda (sp),y .endif sta ptr1 ; Address now in ptr1 ldy tmp1 ; Restore Y iny ; Address high byte txa ; Get high byte sta (ptr1),y ; Store high byte dey ; Address low byte pla ; Restore low byte into A sta (ptr1),y ; Store low byte jmp incsp2 ; Drop address .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/steaxsp.s������������������������������������������������������������������0000664�0000000�0000000�00000000641�13473601511�0017022�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 31.08.1998 ; ; CC65 runtime: Store eax at (sp),y ; .export steaxysp, steax0sp .importzp sp, sreg steax0sp: ldy #0 steaxysp: sta (sp),y iny pha txa sta (sp),y iny lda sreg sta (sp),y iny lda sreg+1 sta (sp),y pla rts �����������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/steaxspi.s�����������������������������������������������������������������0000664�0000000�0000000�00000001234�13473601511�0017172�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.06.1998 ; ; CC65 runtime: Store eax at the address on top of stack with index ; .export steaxspidx .import popptr1 .importzp sreg, ptr1, tmp1, tmp2, tmp3 .proc steaxspidx sta tmp1 stx tmp2 sty tmp3 jsr popptr1 ; get the pointer ldy tmp3 lda tmp1 sta (ptr1),y iny lda tmp2 sta (ptr1),y iny tax lda sreg sta (ptr1),y iny lda sreg+1 sta (ptr1),y lda tmp1 rts .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/stkchk.s�������������������������������������������������������������������0000664�0000000�0000000�00000006215�13473601511�0016625�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 19.03.2001 ; ; Stack checking code. These are actually two routines, one to check the C ; stack, and the other one to check the 6502 hardware stack. ; For performance reasons (to avoid having to pass a parameter), the compiler ; calls the cstkchk routine *after* allocating space on the stack. So the ; stackpointer may already be invalid if this routine is called. In addition ; to that, pushs and pops that are needed for expression evaluation are not ; checked (this would be way too much overhead). As a consequence we will ; operate using a safety area at the stack bottom. Once the stack reaches this ; safety area, we consider it an overflow, even if the stack is still inside ; its' bounds. ; .export stkchk, cstkchk .constructor initstkchk, 25 .import __STACKSIZE__ ; Linker defined .import pusha0, _exit .importzp sp ; Use macros for better readability .macpack generic .macpack cpu ; ---------------------------------------------------------------------------- ; Initialization code. This is a constructor, so it is called on startup if ; the linker has detected references to this module. .segment "ONCE" .proc initstkchk lda sp sta initialsp sub #<__STACKSIZE__ sta lowwater lda sp+1 sta initialsp+1 sbc #>__STACKSIZE__ .if (.cpu .bitand ::CPU_ISET_65SC02) ina ; Add 256 bytes safety area .else add #1 ; Add 256 bytes safety area .endif sta lowwater+1 rts .endproc ; ---------------------------------------------------------------------------- ; 6502 stack checking routine. Does not need to save any registers. ; Safety zone for the hardware stack is 12 bytes. .code stkchk: tsx cpx #12 bcc Fail ; Jump on stack overflow rts ; Return if ok ; ---------------------------------------------------------------------------- ; C stack checking routine. Does not need to save any registers. .code cstkchk: ; Check the high byte of the software stack @L0: lda lowwater+1 cmp sp+1 bcs @L1 rts ; Check low byte @L1: bne CStackOverflow lda lowwater cmp sp bcs CStackOverflow Done: rts ; We have a C stack overflow. Set the stack pointer to the initial value, so ; we can continue without worrying about stack issues. CStackOverflow: lda initialsp sta sp lda initialsp+1 sta sp+1 ; Generic abort entry. We should output a diagnostic here, but this is ; difficult, since we're operating at a lower level here. Fail: lda #4 ldx #0 jmp _exit ; ---------------------------------------------------------------------------- ; Data .segment "INIT" ; Initial stack pointer value. Stack is reset to this in case of overflows to ; allow program exit processing. initialsp: .res 2 ; Stack low water mark. lowwater: .res 2 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/sub.s����������������������������������������������������������������������0000664�0000000�0000000�00000001345�13473601511�0016126�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 05.08.1998 ; ; CC65 runtime: sub ints ; .export tossuba0, tossubax .import addysp1 .importzp sp .macpack cpu ; AX = TOS - AX tossuba0: ldx #0 tossubax: sec eor #$FF .if (.cpu .bitand CPU_ISET_65SC02) adc (sp) ldy #1 .else ldy #0 adc (sp),y ; Subtract low byte iny .endif pha ; Save high byte txa eor #$FF adc (sp),y ; Subtract high byte tax ; High byte into X pla ; Restore low byte jmp addysp1 ; drop TOS �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/subeqsp.s������������������������������������������������������������������0000664�0000000�0000000�00000000761�13473601511�0017020�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 08.10.1998 ; ; CC65 runtime: -= operator for ints on the stack ; .export subeq0sp, subeqysp .importzp sp subeq0sp: ldy #0 subeqysp: sec eor #$FF adc (sp),y sta (sp),y pha ; Save low byte iny txa eor #$FF adc (sp),y sta (sp),y tax pla ; Restore low byte rts ���������������cc65-2.18/libsrc/runtime/subysp.s�������������������������������������������������������������������0000664�0000000�0000000�00000000537�13473601511�0016664�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Piotr Fusik, 24.10.2003 ; originally by Ullrich von Bassewitz ; ; CC65 runtime: Decrement the stackpointer by value in y ; .export subysp .importzp sp .proc subysp tya eor #$ff sec adc sp sta sp bcs @L1 dec sp+1 @L1: rts .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/swap.s���������������������������������������������������������������������0000664�0000000�0000000�00000001301�13473601511�0016277�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; Christian Krueger, 11-Mar-2017, added 65SC02 optimization ; ; CC65 runtime: swap ax with TOS ; .export swapstk .importzp sp, ptr4 .macpack cpu swapstk: sta ptr4 stx ptr4+1 ldy #1 ; index lda (sp),y tax lda ptr4+1 sta (sp),y .if (.cpu .bitand ::CPU_ISET_65SC02) lda (sp) tay lda ptr4 sta (sp) tya .else dey lda (sp),y pha lda ptr4 sta (sp),y pla .endif rts ; whew! �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/tosint.s�������������������������������������������������������������������0000664�0000000�0000000�00000001144�13473601511�0016652�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.10.2000 ; ; CC65 runtime: Convert tos from long to int ; .export tosint .import incsp2 .importzp sp .macpack cpu ; Convert TOS from long to int by cutting of the high 16bit .proc tosint pha .if (.cpu .bitand ::CPU_ISET_65SC02) lda (sp) .else ldy #0 lda (sp),y ; sp+1 .endif ldy #2 sta (sp),y dey lda (sp),y ldy #3 sta (sp),y pla jmp incsp2 ; Drop 16 bit .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/toslong.s������������������������������������������������������������������0000664�0000000�0000000�00000002412�13473601511�0017016�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 25.10.2000 ; ; CC65 runtime: Convert tos from int to long ; .export tosulong, toslong .import decsp2 .importzp sp .macpack cpu ; Convert TOS from int to long tosulong: pha jsr decsp2 ; Make room ldy #2 lda (sp),y .if (.cpu .bitand CPU_ISET_65SC02) sta (sp) ; 65C02 version iny ; Y = 3 .else ldy #0 sta (sp),y ldy #3 .endif lda (sp),y toslong1: ldy #1 sta (sp),y lda #0 ; Zero extend toslong2: iny sta (sp),y iny sta (sp),y pla rts toslong: pha jsr decsp2 ; Make room ldy #2 lda (sp),y .if (.cpu .bitand CPU_ISET_65SC02) sta (sp) ; 65C02 version iny ; Y = 3 .else ldy #0 sta (sp),y ldy #3 .endif lda (sp),y bpl toslong1 ; Jump if positive, high word is zero ldy #1 sta (sp),y lda #$FF bne toslong2 ; Branch always ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/udiv.s���������������������������������������������������������������������0000664�0000000�0000000�00000003207�13473601511�0016303�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 07.08.1998 ; ; CC65 runtime: division for unsigned ints ; ; Don't use tmp1 here, the signed division tunnels data with it! .export tosudiva0, tosudivax, udiv16 .import popptr1 .importzp sreg, ptr1, ptr4 tosudiva0: ldx #$00 ; Clear high byte tosudivax: sta ptr4 stx ptr4+1 ; Save right operand jsr popptr1 ; Get left operand ; Do the division jsr udiv16 ; Result is in ptr1, remainder in sreg lda ptr1 ldx ptr1+1 rts ;--------------------------------------------------------------------------- ; 16by16 division. Divide ptr1 by ptr4. Result is in ptr1, remainder in sreg ; (see mult-div.s from "The Fridge"). ; This is also the entry point for the signed division udiv16: lda #0 sta sreg+1 ldy #16 ldx ptr4+1 beq udiv16by8a L0: asl ptr1 rol ptr1+1 rol a rol sreg+1 tax cmp ptr4 lda sreg+1 sbc ptr4+1 bcc L1 sta sreg+1 txa sbc ptr4 tax inc ptr1 L1: txa dey bne L0 sta sreg rts ;--------------------------------------------------------------------------- ; 16by8 division udiv16by8a: @L0: asl ptr1 rol ptr1+1 rol a bcs @L1 cmp ptr4 bcc @L2 @L1: sbc ptr4 inc ptr1 @L2: dey bne @L0 sta sreg rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/udiv32by16r16.s������������������������������������������������������������0000664�0000000�0000000�00000002165�13473601511�0017505�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2009-11-04 ; ; CC65 runtime: 32by16 => 16 unsigned division ; .export udiv32by16r16, udiv32by16r16m .include "zeropage.inc" ;--------------------------------------------------------------------------- ; 32by16 division. Divide ptr1:ptr2 by ptr3. Result is in ptr1, remainder ; in sreg. ; ; lhs rhs result result also in remainder ; ----------------------------------------------------------------------- ; ptr1:ptr2 ptr3 ax ptr1 sreg ; udiv32by16r16: sta ptr3 stx ptr3+1 udiv32by16r16m: lda #0 sta sreg+1 ldy #32 L0: asl ptr1 rol ptr1+1 rol ptr2 rol ptr2+1 rol a rol sreg+1 tax cmp ptr3 lda sreg+1 sbc ptr3+1 bcc L1 sta sreg+1 txa sbc ptr3 tax inc ptr1 L1: txa dey bne L0 sta sreg lda ptr1 ldx ptr1+1 rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/uge.s����������������������������������������������������������������������0000664�0000000�0000000�00000000544�13473601511�0016115�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: Compare >= for unsigned ints ; .export tosuge00, tosugea0, tosugeax .import tosicmp, booluge tosuge00: lda #$00 tosugea0: ldx #$00 tosugeax: jsr tosicmp ; Set flags jmp booluge ; Convert to boolean ������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/ugt.s����������������������������������������������������������������������0000664�0000000�0000000�00000000541�13473601511�0016131�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: Compare > for unsigned ints ; .export tosugt00, tosugta0, tosugtax .import tosicmp, boolugt tosugt00: lda #$00 tosugta0: ldx #$00 tosugtax: jsr tosicmp ; Set flags jmp boolugt ; Convert to boolean ���������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/ule.s����������������������������������������������������������������������0000664�0000000�0000000�00000000542�13473601511�0016120�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: Compare <= for unsigned ints ; .export tosule00, tosulea0, tosuleax .import tosicmp, boolule tosule00: lda #$00 tosulea0: ldx #$00 tosuleax: jsr tosicmp ; Set flags jmp boolule ; Convert to boolean ��������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/ult.s����������������������������������������������������������������������0000664�0000000�0000000�00000000603�13473601511�0016135�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; CC65 runtime: Compare < for unsigned ints ; .export tosult00, tosulta0, tosultax .import tosicmp, boolult, return0 tosult00 = return0 ; This is always false tosulta0: ldx #$00 tosultax: jsr tosicmp ; Set flags jmp boolult ; Convert to boolean �����������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/umod.s���������������������������������������������������������������������0000664�0000000�0000000�00000001027�13473601511�0016276�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 07.08.1998 ; ; CC65 runtime: modulo operation for unsigned ints ; .export tosumoda0, tosumodax .import popptr1, udiv16 .importzp sreg, ptr4 tosumoda0: ldx #0 tosumodax: sta ptr4 stx ptr4+1 ; Save right operand jsr popptr1 ; Get right operand ; Do the division jsr udiv16 ; Result is in ptr1, remainder in sreg lda sreg ldx sreg+1 rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/umul16x16r32.s�������������������������������������������������������������0000664�0000000�0000000�00000003176�13473601511�0017360�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2010-11-03 ; ; CC65 runtime: 16x16 => 32 unsigned multiplication ; .export umul16x16r32, umul16x16r32m .export umul16x16r16, umul16x16r16m .include "zeropage.inc" ;--------------------------------------------------------------------------- ; 16x16 => 32 unsigned multiplication routine. Because the overhead for a ; 16x16 => 16 unsigned multiplication routine is small, we will tag it with ; the matching labels, as well. ; ; routine LHS RHS result result also in ; ----------------------------------------------------------------------- ; umul16x16r32 ax ptr1 ax:sreg ptr1:sreg ; umul16x16r32m ptr3 ptr1 ax:sreg ptr1:sreg ; umul16x16r16 ax ptr1 ax ptr1 ; umul16x16r16m ptr3 ptr1 ax ptr1 ; ; ptr3 is left intact by the routine. ; umul16x16r32: umul16x16r16: sta ptr3 stx ptr3+1 umul16x16r32m: umul16x16r16m: lda #0 sta sreg+1 ldy #16 ; Number of bits lsr ptr1+1 ror ptr1 ; Get first bit into carry @L0: bcc @L1 clc adc ptr3 tax lda ptr3+1 adc sreg+1 sta sreg+1 txa @L1: ror sreg+1 ror a ror ptr1+1 ror ptr1 dey bne @L0 sta sreg ; Save byte 3 lda ptr1 ; Load the result ldx ptr1+1 rts ; Done ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/umul8x16r24.s��������������������������������������������������������������0000664�0000000�0000000�00000003312�13473601511�0017272�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2011-07-10 ; ; CC65 runtime: 8x16 => 24 unsigned multiplication ; .export umul8x16r24, umul8x16r24m .export umul8x16r16, umul8x16r16m .include "zeropage.inc" .macpack cpu ;--------------------------------------------------------------------------- ; 8x16 => 24 unsigned multiplication routine. Because the overhead for a ; 8x16 => 16 unsigned multiplication routine is small, we will tag it with ; the matching labels, as well. ; ; routine LHS RHS result result also in ; ----------------------------------------------------------------------- ; umul8x16r24 ax ptr1-low ax:sreg-low ptr1:sreg-low ; umul8x16r24m ptr3 ptr1-low ax:sreg-low ptr1:sreg-low ; ; ptr3 is left intact by the routine. ; umul8x16r24: umul8x16r16: sta ptr3 stx ptr3+1 umul8x16r24m: umul8x16r16m: .if (.cpu .bitand ::CPU_ISET_65SC02) stz ptr1+1 stz sreg .else ldx #0 stx ptr1+1 stx sreg .endif ldy #8 ; Number of bits ldx ptr3 ; Get into register for speed lda ptr1 ror a ; Get next bit into carry @L0: bcc @L1 clc pha txa adc ptr1+1 sta ptr1+1 lda ptr3+1 adc sreg sta sreg pla @L1: ror sreg ror ptr1+1 ror a dey bne @L0 sta ptr1 ; Save low byte of result ldx ptr1+1 ; Load high byte of result rts ; Done ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/umul8x8r16.s���������������������������������������������������������������0000664�0000000�0000000�00000001705�13473601511�0017220�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2010-11-02 ; ; CC65 runtime: 8x8 => 16 unsigned multiplication ; .export umul8x8r16, umul8x8r16m .importzp ptr1, ptr3 ;--------------------------------------------------------------------------- ; 8x8 => 16 unsigned multiplication routine. ; ; LHS RHS result result in also ; ------------------------------------------------------------- ; .A (ptr3-low) ptr1-low .XA ptr1 ; umul8x8r16: sta ptr3 umul8x8r16m: lda #0 ; Clear byte 1 ldy #8 ; Number of bits lsr ptr1 ; Get first bit of RHS into carry @L0: bcc @L1 clc adc ptr3 @L1: ror ror ptr1 dey bne @L0 tax stx ptr1+1 ; Result in .XA and ptr1 lda ptr1 ; Load the result rts ; Done �����������������������������������������������������������cc65-2.18/libsrc/runtime/xor.s����������������������������������������������������������������������0000664�0000000�0000000�00000001136�13473601511�0016143�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 05.08.1998 ; Christian Krueger, 11-Mar-2017, added 65SC02 optimization ; ; CC65 runtime: xor on ints ; .export tosxora0, tosxorax .import addysp1 .importzp sp, tmp1 .macpack cpu tosxora0: ldx #$00 tosxorax: .if (.cpu .bitand CPU_ISET_65SC02) eor (sp) ldy #1 .else ldy #0 eor (sp),y iny .endif sta tmp1 txa eor (sp),y tax lda tmp1 jmp addysp1 ; drop TOS, set condition codes ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/runtime/zeropage.s�����������������������������������������������������������������0000664�0000000�0000000�00000001206�13473601511�0017145�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.05.2002 ; ; CC65 runtime: zeropage usage ; .include "zeropage.inc" ; ------------------------------------------------------------------------ .zeropage sp: .res 2 ; Stack pointer sreg: .res 2 ; Secondary register/high 16 bit for longs regsave: .res 4 ; Slot to save/restore (E)AX into ptr1: .res 2 ptr2: .res 2 ptr3: .res 2 ptr4: .res 2 tmp1: .res 1 tmp2: .res 1 tmp3: .res 1 tmp4: .res 1 regbank: .res regbanksize ; Register bank ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/serial/����������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014742�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/serial/ser-kernel.s����������������������������������������������������������������0000664�0000000�0000000�00000006223�13473601511�0017200�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-04-15 ; ; Common functions of the serial drivers ; .import return0, ser_libref .importzp ptr1 .interruptor ser_irq, 29 ; Export as high priority IRQ handler .include "ser-kernel.inc" .include "ser-error.inc" ;---------------------------------------------------------------------------- ; Variables .bss _ser_drv: .res 2 ; Pointer to driver ; Jump table for the driver functions. .data ser_vectors: ser_install: jmp return0 ser_uninstall: jmp return0 ser_open: jmp return0 ser_close: jmp return0 ser_get: jmp return0 ser_put: jmp return0 ser_status: jmp return0 ser_ioctl: jmp return0 ser_irq: .byte $60, $00, $00 ; RTS plus two dummy bytes ; Driver header signature .rodata ser_sig: .byte $73, $65, $72, SER_API_VERSION ; "ser", version .code ;---------------------------------------------------------------------------- ; unsigned char __fastcall__ ser_install (void* driver); ; /* Install the driver once it is loaded */ _ser_install: sta _ser_drv sta ptr1 stx _ser_drv+1 stx ptr1+1 ; Check the driver signature ldy #.sizeof(ser_sig)-1 @L0: lda (ptr1),y cmp ser_sig,y bne inv_drv dey bpl @L0 ; Set the library reference ldy #SER_HDR::LIBREF lda #<ser_libref sta (ptr1),y iny lda #>ser_libref sta (ptr1),y ; Copy the jump vectors ldy #SER_HDR::JUMPTAB ldx #0 @L1: inx ; Skip the JMP opcode jsr copy ; Copy one byte jsr copy ; Copy one byte cpy #(SER_HDR::JUMPTAB + .sizeof(SER_HDR::JUMPTAB)) bne @L1 jsr ser_install ; Call driver install routine ldy ser_irq+2 ; Check high byte of IRQ vector beq @L2 ; Jump if vector invalid ldy #$4C ; Jump opcode sty ser_irq ; Activate IRQ routine @L2: rts ; Driver signature invalid inv_drv: lda #SER_ERR_INV_DRIVER ldx #0 rts ; Copy one byte from the jump vectors copy: lda (ptr1),y sta ser_vectors,x iny inx rts ;---------------------------------------------------------------------------- ; unsigned char ser_uninstall (void); ; /* Uninstall the currently loaded driver and return an error code. ; ** Note: This call does not free allocated memory. ; */ _ser_uninstall: jsr ser_uninstall ; Call driver routine lda #$60 ; RTS opcode sta ser_irq ; Disable IRQ entry point _ser_clear_ptr: ; External entry point lda #0 sta _ser_drv sta _ser_drv+1 ; Clear the driver pointer tax rts ; Return zero �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/serial/ser_close.s�����������������������������������������������������������������0000664�0000000�0000000�00000000336�13473601511�0017106�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-08-22 ; ; unsigned char ser_close (void); ; /* "Close" the port. Clear buffers and and disable interrupts. */ .include "ser-kernel.inc" _ser_close = ser_close ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/serial/ser_get.s�������������������������������������������������������������������0000664�0000000�0000000�00000000756�13473601511�0016566�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-04-18 ; ; unsigned char __fastcall__ ser_get (char* b); ; /* 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. ; */ .importzp ptr1 .include "ser-kernel.inc" .proc _ser_get sta ptr1 stx ptr1+1 ; Save pointer to char jmp ser_get ; Call the driver .endproc ������������������cc65-2.18/libsrc/serial/ser_ioctl.s�����������������������������������������������������������������0000664�0000000�0000000�00000000722�13473601511�0017112�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2005-09-02 ; ; unsigned char __fastcall__ ser_ioctl (unsigned char code, void* data); ; /* Driver specific entry. */ .import popa .importzp ptr1 .include "ser-kernel.inc" .proc _ser_ioctl sta ptr1 stx ptr1+1 ; Save pointer to data jsr popa ; Get code jmp ser_ioctl ; Call the driver .endproc ����������������������������������������������cc65-2.18/libsrc/serial/ser_load.s������������������������������������������������������������������0000664�0000000�0000000�00000005733�13473601511�0016726�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2006-06-05 ; ; unsigned char __fastcall__ ser_load_driver (const char* name) ; /* Load a serial driver and return an error code */ .include "ser-kernel.inc" .include "ser-error.inc" .include "modload.inc" .include "fcntl.inc" .import pushax .import pusha0 .import incsp2 .import _open .import _read .import _close ;---------------------------------------------------------------------------- ; Variables .data ctrl: .addr _read .res 2 ; CALLERDATA .res 2 ; MODULE .res 2 ; MODULE_SIZE .res 2 ; MODULE_ID ;---------------------------------------------------------------------------- ; Code .code .proc _ser_load_driver ; Check if we do already have a driver loaded. This is an error. Do not ; touch A/X because they contain the file name. ldy _ser_drv bne @L0 ldy _ser_drv+1 beq @L1 @L0: lda #SER_ERR_INSTALLED bne @L4 ; Push the name onto the C stack and open the file. The parameter will get ; removed by open(). ; ctrl.callerdata = open (name, O_RDONLY); @L1: jsr pushax lda #<O_RDONLY jsr pusha0 ldy #4 ; Argument size jsr _open sta ctrl + MOD_CTRL::CALLERDATA stx ctrl + MOD_CTRL::CALLERDATA+1 ; if (ctrl.callerdata >= 0) { txa bmi @L3 ; /* Load the module */ ; Res = mod_load (&ctrl); lda #<ctrl ldx #>ctrl jsr _mod_load pha ; /* Close the input file */ ; close (ctrl.callerdata); lda ctrl + MOD_CTRL::CALLERDATA ldx ctrl + MOD_CTRL::CALLERDATA+1 jsr _close ; /* Check the return code */ ; if (Res == MLOAD_OK) { pla bne @L3 ; Check the driver signature, install the driver. c is already on stack and ; will get removed by ser_install(). ; Res = ser_install (ctrl.module); lda ctrl + MOD_CTRL::MODULE ldx ctrl + MOD_CTRL::MODULE+1 jsr _ser_install ; If ser_install was successful, we're done tax beq @L2 ; The driver didn't install correctly. Remove it from memory and return the ; error code. pha ; Save the error code lda _ser_drv ldx _ser_drv+1 jsr _mod_free ; Free the driver memory jsr _ser_clear_ptr ; Clear ser_drv pla ; Restore the error code ldx #0 ; We must return an int @L2: rts ; Done ; Open or mod_load failed. Return an error code. @L3: lda #<SER_ERR_CANNOT_LOAD @L4: ldx #0 rts .endproc �������������������������������������cc65-2.18/libsrc/serial/ser_open.s������������������������������������������������������������������0000664�0000000�0000000�00000000674�13473601511�0016747�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-08-22 ; ; unsigned char __fastcall__ ser_open (const struct ser_params* params); ; /* "Open" the port by setting the port parameters and enable interrupts. */ .importzp ptr1 .include "ser-kernel.inc" .proc _ser_open sta ptr1 stx ptr1+1 ; Save pointer to params jmp ser_open ; Call the driver .endproc ��������������������������������������������������������������������cc65-2.18/libsrc/serial/ser_put.s�������������������������������������������������������������������0000664�0000000�0000000�00000000600�13473601511�0016603�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-04-18 ; ; unsigned char __fastcall__ ser_put (char b); ; /* 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. ; */ .include "ser-kernel.inc" _ser_put = ser_put ��������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/serial/ser_status.s����������������������������������������������������������������0000664�0000000�0000000�00000000614�13473601511�0017323�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-04-18 ; ; unsigned char __fastcall__ ser_status (unsigned char* status); ; /* Return the serial port status. */ .importzp ptr1 .include "ser-kernel.inc" .proc _ser_status sta ptr1 stx ptr1+1 ; Save pointer to status jmp ser_status ; Call the driver .endproc ��������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/serial/ser_unload.s����������������������������������������������������������������0000664�0000000�0000000�00000001717�13473601511�0017267�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-04-15 ; ; unsigned char ser_unload (void); ; /* Unload the currently loaded driver. */ .include "ser-kernel.inc" .include "ser-error.inc" .include "modload.inc" .import ser_clear_ptr .import return0 _ser_unload: lda _ser_drv pha ; Save pointer to driver ora _ser_drv+1 beq no_driver ; No driver lda _ser_drv+1 pha jsr _ser_uninstall ; Uninstall the driver pla tax pla ; Get pointer to driver jsr _mod_free ; Free the driver jmp return0 ; Return SER_ERR_OK no_driver: tax ; X = 0 pla ; Remove pushed junk lda #<SER_ERR_NO_DRIVER rts �������������������������������������������������cc65-2.18/libsrc/sim6502/���������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014570�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/sim6502/crt0.s���������������������������������������������������������������������0000664�0000000�0000000�00000001621�13473601511�0015624�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2013-05-16 ; ; Startup code for cc65 (sim6502 version) ; .export _exit .export startup .export __STARTUP__ : absolute = 1 ; Mark as startup .import zerobss, callmain .import initlib, donelib .import exit .import __MAIN_START__, __MAIN_SIZE__ ; Linker generated .import __STACKSIZE__ ; Linker generated .include "zeropage.inc" .segment "STARTUP" startup:cld ldx #$FF txs lda #<(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__) ldx #>(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__) sta sp stx sp+1 jsr zerobss jsr initlib jsr callmain _exit: pha jsr donelib pla jmp exit ���������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/sim6502/ctype.s��������������������������������������������������������������������0000664�0000000�0000000�00000020737�13473601511�0016111�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-10-10 ; ; Character specification table. ; .include "ctype.inc" ; The tables are readonly, put them into the rodata segment .rodata ; The following 256 byte wide table specifies attributes for the isxxx type ; of functions. Doing it by a table means some overhead in space, but it ; has major advantages: ; ; * It is fast. If it weren't for the slow parameter passing of cc65, one ; could even define macros for the isxxx functions (this is usually ; done on other platforms). ; ; * It is highly portable. The only unportable part is the table itself, ; all real code goes into the common library. ; ; * We save some code in the isxxx functions. __ctype: .byte CT_CTRL ; 0/00 ___ctrl_@___ .byte CT_CTRL ; 1/01 ___ctrl_A___ .byte CT_CTRL ; 2/02 ___ctrl_B___ .byte CT_CTRL ; 3/03 ___ctrl_C___ .byte CT_CTRL ; 4/04 ___ctrl_D___ .byte CT_CTRL ; 5/05 ___ctrl_E___ .byte CT_CTRL ; 6/06 ___ctrl_F___ .byte CT_CTRL ; 7/07 ___ctrl_G___ .byte CT_CTRL ; 8/08 ___ctrl_H___ .byte CT_CTRL | CT_OTHER_WS | CT_SPACE_TAB ; 9/09 ___ctrl_I___ .byte CT_CTRL | CT_OTHER_WS ; 10/0a ___ctrl_J___ .byte CT_CTRL | CT_OTHER_WS ; 11/0b ___ctrl_K___ .byte CT_CTRL | CT_OTHER_WS ; 12/0c ___ctrl_L___ .byte CT_CTRL | CT_OTHER_WS ; 13/0d ___ctrl_M___ .byte CT_CTRL ; 14/0e ___ctrl_N___ .byte CT_CTRL ; 15/0f ___ctrl_O___ .byte CT_CTRL ; 16/10 ___ctrl_P___ .byte CT_CTRL ; 17/11 ___ctrl_Q___ .byte CT_CTRL ; 18/12 ___ctrl_R___ .byte CT_CTRL ; 19/13 ___ctrl_S___ .byte CT_CTRL ; 20/14 ___ctrl_T___ .byte CT_CTRL ; 21/15 ___ctrl_U___ .byte CT_CTRL ; 22/16 ___ctrl_V___ .byte CT_CTRL ; 23/17 ___ctrl_W___ .byte CT_CTRL ; 24/18 ___ctrl_X___ .byte CT_CTRL ; 25/19 ___ctrl_Y___ .byte CT_CTRL ; 26/1a ___ctrl_Z___ .byte CT_CTRL ; 27/1b ___ctrl_[___ .byte CT_CTRL ; 28/1c ___ctrl_\___ .byte CT_CTRL ; 29/1d ___ctrl_]___ .byte CT_CTRL ; 30/1e ___ctrl_^___ .byte CT_CTRL ; 31/1f ___ctrl_____ .byte CT_SPACE | CT_SPACE_TAB ; 32/20 ___SPACE___ .byte CT_NONE ; 33/21 _____!_____ .byte CT_NONE ; 34/22 _____"_____ .byte CT_NONE ; 35/23 _____#_____ .byte CT_NONE ; 36/24 _____$_____ .byte CT_NONE ; 37/25 _____%_____ .byte CT_NONE ; 38/26 _____&_____ .byte CT_NONE ; 39/27 _____'_____ .byte CT_NONE ; 40/28 _____(_____ .byte CT_NONE ; 41/29 _____)_____ .byte CT_NONE ; 42/2a _____*_____ .byte CT_NONE ; 43/2b _____+_____ .byte CT_NONE ; 44/2c _____,_____ .byte CT_NONE ; 45/2d _____-_____ .byte CT_NONE ; 46/2e _____._____ .byte CT_NONE ; 47/2f _____/_____ .byte CT_DIGIT | CT_XDIGIT ; 48/30 _____0_____ .byte CT_DIGIT | CT_XDIGIT ; 49/31 _____1_____ .byte CT_DIGIT | CT_XDIGIT ; 50/32 _____2_____ .byte CT_DIGIT | CT_XDIGIT ; 51/33 _____3_____ .byte CT_DIGIT | CT_XDIGIT ; 52/34 _____4_____ .byte CT_DIGIT | CT_XDIGIT ; 53/35 _____5_____ .byte CT_DIGIT | CT_XDIGIT ; 54/36 _____6_____ .byte CT_DIGIT | CT_XDIGIT ; 55/37 _____7_____ .byte CT_DIGIT | CT_XDIGIT ; 56/38 _____8_____ .byte CT_DIGIT | CT_XDIGIT ; 57/39 _____9_____ .byte CT_NONE ; 58/3a _____:_____ .byte CT_NONE ; 59/3b _____;_____ .byte CT_NONE ; 60/3c _____<_____ .byte CT_NONE ; 61/3d _____=_____ .byte CT_NONE ; 62/3e _____>_____ .byte CT_NONE ; 63/3f _____?_____ .byte CT_NONE ; 64/40 _____@_____ .byte CT_UPPER | CT_XDIGIT ; 65/41 _____A_____ .byte CT_UPPER | CT_XDIGIT ; 66/42 _____B_____ .byte CT_UPPER | CT_XDIGIT ; 67/43 _____C_____ .byte CT_UPPER | CT_XDIGIT ; 68/44 _____D_____ .byte CT_UPPER | CT_XDIGIT ; 69/45 _____E_____ .byte CT_UPPER | CT_XDIGIT ; 70/46 _____F_____ .byte CT_UPPER ; 71/47 _____G_____ .byte CT_UPPER ; 72/48 _____H_____ .byte CT_UPPER ; 73/49 _____I_____ .byte CT_UPPER ; 74/4a _____J_____ .byte CT_UPPER ; 75/4b _____K_____ .byte CT_UPPER ; 76/4c _____L_____ .byte CT_UPPER ; 77/4d _____M_____ .byte CT_UPPER ; 78/4e _____N_____ .byte CT_UPPER ; 79/4f _____O_____ .byte CT_UPPER ; 80/50 _____P_____ .byte CT_UPPER ; 81/51 _____Q_____ .byte CT_UPPER ; 82/52 _____R_____ .byte CT_UPPER ; 83/53 _____S_____ .byte CT_UPPER ; 84/54 _____T_____ .byte CT_UPPER ; 85/55 _____U_____ .byte CT_UPPER ; 86/56 _____V_____ .byte CT_UPPER ; 87/57 _____W_____ .byte CT_UPPER ; 88/58 _____X_____ .byte CT_UPPER ; 89/59 _____Y_____ .byte CT_UPPER ; 90/5a _____Z_____ .byte CT_NONE ; 91/5b _____[_____ .byte CT_NONE ; 92/5c _____\_____ .byte CT_NONE ; 93/5d _____]_____ .byte CT_NONE ; 94/5e _____^_____ .byte CT_NONE ; 95/5f _UNDERLINE_ .byte CT_NONE ; 96/60 ___grave___ .byte CT_LOWER | CT_XDIGIT ; 97/61 _____a_____ .byte CT_LOWER | CT_XDIGIT ; 98/62 _____b_____ .byte CT_LOWER | CT_XDIGIT ; 99/63 _____c_____ .byte CT_LOWER | CT_XDIGIT ; 100/64 _____d_____ .byte CT_LOWER | CT_XDIGIT ; 101/65 _____e_____ .byte CT_LOWER | CT_XDIGIT ; 102/66 _____f_____ .byte CT_LOWER ; 103/67 _____g_____ .byte CT_LOWER ; 104/68 _____h_____ .byte CT_LOWER ; 105/69 _____i_____ .byte CT_LOWER ; 106/6a _____j_____ .byte CT_LOWER ; 107/6b _____k_____ .byte CT_LOWER ; 108/6c _____l_____ .byte CT_LOWER ; 109/6d _____m_____ .byte CT_LOWER ; 110/6e _____n_____ .byte CT_LOWER ; 111/6f _____o_____ .byte CT_LOWER ; 112/70 _____p_____ .byte CT_LOWER ; 113/71 _____q_____ .byte CT_LOWER ; 114/72 _____r_____ .byte CT_LOWER ; 115/73 _____s_____ .byte CT_LOWER ; 116/74 _____t_____ .byte CT_LOWER ; 117/75 _____u_____ .byte CT_LOWER ; 118/76 _____v_____ .byte CT_LOWER ; 119/77 _____w_____ .byte CT_LOWER ; 120/78 _____x_____ .byte CT_LOWER ; 121/79 _____y_____ .byte CT_LOWER ; 122/7a _____z_____ .byte CT_NONE ; 123/7b _____{_____ .byte CT_NONE ; 124/7c _____|_____ .byte CT_NONE ; 125/7d _____}_____ .byte CT_NONE ; 126/7e _____~_____ .byte CT_OTHER_WS ; 127/7f ____DEL____ .res 128, CT_NONE ; 128-255 ���������������������������������cc65-2.18/libsrc/sim6502/exehdr.s�������������������������������������������������������������������0000664�0000000�0000000�00000001220�13473601511�0016226�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2013-05-16 ; ; This module supplies a header used by sim65. ; .export __EXEHDR__ : absolute = 1 ; Linker referenced .importzp sp .import __MAIN_START__ .import startup .segment "EXEHDR" .byte $73, $69, $6D, $36, $35 ; 'sim65' .byte 2 ; header version .byte .defined(__SIM65C02__) ; CPU type .byte sp ; sp address .addr __MAIN_START__ ; load address .addr startup ; reset address ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/sim6502/mainargs.s�����������������������������������������������������������������0000664�0000000�0000000�00000000452�13473601511�0016556�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2013-05-16 ; .constructor initmainargs, 24 .import __argc, __argv, args .segment "ONCE" initmainargs: lda #<__argv ldx #>__argv jsr args sta __argc stx __argc+1 rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/sim6502/paravirt.s�����������������������������������������������������������������0000664�0000000�0000000�00000000717�13473601511�0016611�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2013-05-16 ; ; int open (const char* name, int flags, ...); ; int __fastcall__ close (int fd); ; int __fastcall__ read (int fd, void* buf, unsigned count); ; int __fastcall__ write (int fd, const void* buf, unsigned count); ; .export exit, args, _open, _close, _read, _write _open := $FFF4 _close := $FFF5 _read := $FFF6 _write := $FFF7 args := $FFF8 exit := $FFF9 �������������������������������������������������cc65-2.18/libsrc/supervision/�����������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0016051�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/supervision/crt0.s�����������������������������������������������������������������0000664�0000000�0000000�00000003476�13473601511�0017117�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Startup code for cc65 (supervision version) ; .export _exit .export __STARTUP__ : absolute = 1 ; Mark as startup .import _main .import initlib, donelib, copydata .import zerobss .import __RAM_START__, __RAM_SIZE__ ; Linker generated .import __STACKSIZE__ ; Linker generated .include "zeropage.inc" .include "supervision.inc" .export _sv_irq_timer_counter, _sv_irq_dma_counter .export _sv_nmi_counter .bss _sv_irq_dma_counter: .byte 0 _sv_irq_timer_counter: .byte 0 _sv_nmi_counter: .byte 0 .code reset: jsr zerobss ; Initialize data. jsr copydata lda #<(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__) ldx #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__) sta sp stx sp+1 ; Set argument stack ptr jsr initlib jsr _main _exit: jsr donelib exit: jmp exit .proc irq pha lda sv_irq_source and #SV_IRQ_REQUEST_TIMER beq not_timer lda sv_timer_quit inc _sv_irq_timer_counter not_timer: lda sv_irq_source and #SV_IRQ_REQUEST_DMA beq not_dma lda sv_dma_quit inc _sv_irq_dma_counter not_dma: pla rti .endproc .proc nmi inc _sv_nmi_counter rti .endproc ; Removing this segment gives only a warning. .segment "FFF0" .proc reset32kcode lda #(6<<5) sta sv_bank ; Now, the 32Kbyte image can reside in the top of 64Kbyte and 128Kbyte ROMs. jmp reset .endproc .segment "VECTOR" .word nmi .word reset32kcode .word irq ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/supervision/ctype.s����������������������������������������������������������������0000664�0000000�0000000�00000020742�13473601511�0017366�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-10-10 ; ; Character specification table. ; .include "ctype.inc" ; The tables are readonly, put them into the rodata segment .rodata ; The following 256 byte wide table specifies attributes for the isxxx type ; of functions. Doing it by a table means some overhead in space, but it ; has major advantages: ; ; * It is fast. If it weren't for the slow parameter passing of cc65, one ; could even define macros for the isxxx functions (this is usually ; done on other platforms). ; ; * It is highly portable. The only unportable part is the table itself, ; all real code goes into the common library. ; ; * We save some code in the isxxx functions. __ctype: .byte CT_CTRL ; 0/00 ___ctrl_@___ .byte CT_CTRL ; 1/01 ___ctrl_A___ .byte CT_CTRL ; 2/02 ___ctrl_B___ .byte CT_CTRL ; 3/03 ___ctrl_C___ .byte CT_CTRL ; 4/04 ___ctrl_D___ .byte CT_CTRL ; 5/05 ___ctrl_E___ .byte CT_CTRL ; 6/06 ___ctrl_F___ .byte CT_CTRL ; 7/07 ___ctrl_G___ .byte CT_CTRL ; 8/08 ___ctrl_H___ .byte CT_CTRL | CT_OTHER_WS | CT_SPACE_TAB ; 9/09 ___ctrl_I___ .byte CT_CTRL | CT_OTHER_WS ; 10/0a ___ctrl_J___ .byte CT_CTRL | CT_OTHER_WS ; 11/0b ___ctrl_K___ .byte CT_CTRL | CT_OTHER_WS ; 12/0c ___ctrl_L___ .byte CT_CTRL | CT_OTHER_WS ; 13/0d ___ctrl_M___ .byte CT_CTRL ; 14/0e ___ctrl_N___ .byte CT_CTRL ; 15/0f ___ctrl_O___ .byte CT_CTRL ; 16/10 ___ctrl_P___ .byte CT_CTRL ; 17/11 ___ctrl_Q___ .byte CT_CTRL ; 18/12 ___ctrl_R___ .byte CT_CTRL ; 19/13 ___ctrl_S___ .byte CT_CTRL ; 20/14 ___ctrl_T___ .byte CT_CTRL ; 21/15 ___ctrl_U___ .byte CT_CTRL ; 22/16 ___ctrl_V___ .byte CT_CTRL ; 23/17 ___ctrl_W___ .byte CT_CTRL ; 24/18 ___ctrl_X___ .byte CT_CTRL ; 25/19 ___ctrl_Y___ .byte CT_CTRL ; 26/1a ___ctrl_Z___ .byte CT_CTRL ; 27/1b ___ctrl_[___ .byte CT_CTRL ; 28/1c ___ctrl_\___ .byte CT_CTRL ; 29/1d ___ctrl_]___ .byte CT_CTRL ; 30/1e ___ctrl_^___ .byte CT_CTRL ; 31/1f ___ctrl_____ .byte CT_SPACE | CT_SPACE_TAB ; 32/20 ___SPACE___ .byte CT_NONE ; 33/21 _____!_____ .byte CT_NONE ; 34/22 _____"_____ .byte CT_NONE ; 35/23 _____#_____ .byte CT_NONE ; 36/24 _____$_____ .byte CT_NONE ; 37/25 _____%_____ .byte CT_NONE ; 38/26 _____&_____ .byte CT_NONE ; 39/27 _____'_____ .byte CT_NONE ; 40/28 _____(_____ .byte CT_NONE ; 41/29 _____)_____ .byte CT_NONE ; 42/2a _____*_____ .byte CT_NONE ; 43/2b _____+_____ .byte CT_NONE ; 44/2c _____,_____ .byte CT_NONE ; 45/2d _____-_____ .byte CT_NONE ; 46/2e _____._____ .byte CT_NONE ; 47/2f _____/_____ .byte CT_DIGIT | CT_XDIGIT ; 48/30 _____0_____ .byte CT_DIGIT | CT_XDIGIT ; 49/31 _____1_____ .byte CT_DIGIT | CT_XDIGIT ; 50/32 _____2_____ .byte CT_DIGIT | CT_XDIGIT ; 51/33 _____3_____ .byte CT_DIGIT | CT_XDIGIT ; 52/34 _____4_____ .byte CT_DIGIT | CT_XDIGIT ; 53/35 _____5_____ .byte CT_DIGIT | CT_XDIGIT ; 54/36 _____6_____ .byte CT_DIGIT | CT_XDIGIT ; 55/37 _____7_____ .byte CT_DIGIT | CT_XDIGIT ; 56/38 _____8_____ .byte CT_DIGIT | CT_XDIGIT ; 57/39 _____9_____ .byte CT_NONE ; 58/3a _____:_____ .byte CT_NONE ; 59/3b _____;_____ .byte CT_NONE ; 60/3c _____<_____ .byte CT_NONE ; 61/3d _____=_____ .byte CT_NONE ; 62/3e _____>_____ .byte CT_NONE ; 63/3f _____?_____ .byte CT_NONE ; 64/40 _____@_____ .byte CT_UPPER | CT_XDIGIT ; 65/41 _____A_____ .byte CT_UPPER | CT_XDIGIT ; 66/42 _____B_____ .byte CT_UPPER | CT_XDIGIT ; 67/43 _____C_____ .byte CT_UPPER | CT_XDIGIT ; 68/44 _____D_____ .byte CT_UPPER | CT_XDIGIT ; 69/45 _____E_____ .byte CT_UPPER | CT_XDIGIT ; 70/46 _____F_____ .byte CT_UPPER ; 71/47 _____G_____ .byte CT_UPPER ; 72/48 _____H_____ .byte CT_UPPER ; 73/49 _____I_____ .byte CT_UPPER ; 74/4a _____J_____ .byte CT_UPPER ; 75/4b _____K_____ .byte CT_UPPER ; 76/4c _____L_____ .byte CT_UPPER ; 77/4d _____M_____ .byte CT_UPPER ; 78/4e _____N_____ .byte CT_UPPER ; 79/4f _____O_____ .byte CT_UPPER ; 80/50 _____P_____ .byte CT_UPPER ; 81/51 _____Q_____ .byte CT_UPPER ; 82/52 _____R_____ .byte CT_UPPER ; 83/53 _____S_____ .byte CT_UPPER ; 84/54 _____T_____ .byte CT_UPPER ; 85/55 _____U_____ .byte CT_UPPER ; 86/56 _____V_____ .byte CT_UPPER ; 87/57 _____W_____ .byte CT_UPPER ; 88/58 _____X_____ .byte CT_UPPER ; 89/59 _____Y_____ .byte CT_UPPER ; 90/5a _____Z_____ .byte CT_NONE ; 91/5b _____[_____ .byte CT_NONE ; 92/5c _____\_____ .byte CT_NONE ; 93/5d _____]_____ .byte CT_NONE ; 94/5e _____^_____ .byte CT_NONE ; 95/5f _UNDERLINE_ .byte CT_NONE ; 96/60 ___grave___ .byte CT_LOWER | CT_XDIGIT ; 97/61 _____a_____ .byte CT_LOWER | CT_XDIGIT ; 98/62 _____b_____ .byte CT_LOWER | CT_XDIGIT ; 99/63 _____c_____ .byte CT_LOWER | CT_XDIGIT ; 100/64 _____d_____ .byte CT_LOWER | CT_XDIGIT ; 101/65 _____e_____ .byte CT_LOWER | CT_XDIGIT ; 102/66 _____f_____ .byte CT_LOWER ; 103/67 _____g_____ .byte CT_LOWER ; 104/68 _____h_____ .byte CT_LOWER ; 105/69 _____i_____ .byte CT_LOWER ; 106/6a _____j_____ .byte CT_LOWER ; 107/6b _____k_____ .byte CT_LOWER ; 108/6c _____l_____ .byte CT_LOWER ; 109/6d _____m_____ .byte CT_LOWER ; 110/6e _____n_____ .byte CT_LOWER ; 111/6f _____o_____ .byte CT_LOWER ; 112/70 _____p_____ .byte CT_LOWER ; 113/71 _____q_____ .byte CT_LOWER ; 114/72 _____r_____ .byte CT_LOWER ; 115/73 _____s_____ .byte CT_LOWER ; 116/74 _____t_____ .byte CT_LOWER ; 117/75 _____u_____ .byte CT_LOWER ; 118/76 _____v_____ .byte CT_LOWER ; 119/77 _____w_____ .byte CT_LOWER ; 120/78 _____x_____ .byte CT_LOWER ; 121/79 _____y_____ .byte CT_LOWER ; 122/7a _____z_____ .byte CT_NONE ; 123/7b _____{_____ .byte CT_NONE ; 124/7c _____|_____ .byte CT_NONE ; 125/7d _____}_____ .byte CT_NONE ; 126/7e _____~_____ .byte CT_OTHER_WS ; 127/7f ____DEL____ .res 128, CT_NONE ; 128-255 ������������������������������cc65-2.18/libsrc/supervision/joy/�������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0016652�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/supervision/joy/supervision-stdjoy.s�����������������������������������������������0000664�0000000�0000000�00000003727�13473601511�0022747�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Standard joystick driver for the Supervision ; .include "joy-kernel.inc" .include "joy-error.inc" .include "supervision.inc" .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _supervision_stdjoy_joy ; Driver signature .byte $6A, $6F, $79 ; "joy" .byte JOY_API_VERSION ; Driver API version number ; Library reference .addr $0000 ; Jump table. .addr INSTALL .addr UNINSTALL .addr COUNT .addr READJOY ; ------------------------------------------------------------------------ ; Constants JOY_COUNT = 1 ; 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: lda sv_control eor #$FF ldx #0 rts �����������������������������������������cc65-2.18/libsrc/supervision/joy_stat_stddrv.s������������������������������������������������������0000664�0000000�0000000�00000000410�13473601511�0021452�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Address of the static standard joystick driver ; ; Oliver Schmidt, 2012-11-01 ; ; const void joy_static_stddrv[]; ; .export _joy_static_stddrv .import _supervision_stdjoy_joy _joy_static_stddrv := _supervision_stdjoy_joy ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/supervision/libref.s���������������������������������������������������������������0000664�0000000�0000000�00000000175�13473601511�0017503�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2013-05-31 ; .export joy_libref .import _exit joy_libref := _exit ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/telestrat/�������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015472�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/telestrat/_scrsize.s���������������������������������������������������������������0000664�0000000�0000000�00000000417�13473601511�0017501�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2003-04-13, Ullrich von Bassewitz ; 2013-07-16, Greg King ; ; Screen size variables ; .export screensize .include "telestrat.inc" .proc screensize ldx #SCREEN_XSIZE ldy #SCREEN_YSIZE rts .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/telestrat/cgetc.s������������������������������������������������������������������0000664�0000000�0000000�00000001656�13473601511�0016753�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; jede jede@oric.org 2017-10-01 ; .export _cgetc .import cursor .include "telestrat.inc" .proc _cgetc ; this routine could be quicker if we wrote in page 2 variables, ; but it's better to use telemon routine in that case, because telemon can manage 4 I/O ldx cursor ; if cursor equal to 0, then switch off cursor beq switchoff_cursor ldx #$00 ; x is the first screen BRK_TELEMON(XCSSCR) ; display cursor jmp loop ; could be replaced by a bne/beq but 'jmp' is cleaner than a bne/beq which could expect some matters switchoff_cursor: ; at this step X is equal to $00, X must be set, because it's the id of the screen (telestrat can handle 4 virtuals screen) BRK_TELEMON(XCOSCR) ; switch off cursor loop: BRK_TELEMON XRD0 ; waits until key is pressed bcs loop rts .endproc ����������������������������������������������������������������������������������cc65-2.18/libsrc/telestrat/chline.s�����������������������������������������������������������������0000664�0000000�0000000�00000000661�13473601511�0017123�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; jede jede@oric.org 2018-04-17 ; ; void chline (unsigned char length); ; .export _chline .include "telestrat.inc" .include "zeropage.inc" .proc _chline sta tmp1 @loop: lda #'-' ; horizontal line screen code BRK_TELEMON XWR0 ; macro send char to screen (channel 0 in telemon terms) dec tmp1 bne @loop rts .endproc �������������������������������������������������������������������������������cc65-2.18/libsrc/telestrat/close.s������������������������������������������������������������������0000664�0000000�0000000�00000000605�13473601511�0016764�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; jede jede@oric.org 2017-01-22 .export _close .import addysp,popax .include "zeropage.inc" .include "telestrat.inc" .include "errno.inc" .include "fcntl.inc" ; int open (const char* name, int flags, ...); /* May take a mode argument */ .proc _close BRK_TELEMON XCLOSE ; launch primitive ROM rts .endproc ���������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/telestrat/clrscr.s�����������������������������������������������������������������0000664�0000000�0000000�00000001162�13473601511�0017146�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; jede jede@oric.org 2017-02-25 ; .export _clrscr .importzp sp .include "telestrat.inc" .proc _clrscr ; Switch to text mode BRK_TELEMON(XTEXT) lda #<SCREEN ldy #>SCREEN sta RES sty RES+1 ldy #<(SCREEN+SCREEN_XSIZE*SCREEN_YSIZE) ldx #>(SCREEN+SCREEN_XSIZE*SCREEN_YSIZE) lda #' ' BRK_TELEMON XFILLM ; reset prompt position lda #<(SCREEN+40) sta ADSCRL lda #>(SCREEN+40) sta ADSCRH ; reset display position lda #$01 sta SCRY lda #$00 sta SCRX rts .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/telestrat/cputc.s������������������������������������������������������������������0000664�0000000�0000000�00000000375�13473601511�0017001�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; 2018-04-13, Jede (jede@oric.org) ; ; void cputc (char c); ; .export _cputc .include "telestrat.inc" .proc _cputc BRK_TELEMON XWR0 ; macro send char to screen (channel 0 in telemon terms) rts .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/telestrat/crt0.s�������������������������������������������������������������������0000664�0000000�0000000�00000003762�13473601511�0016536�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Startup code for cc65 (Oric version) ; ; By Debrune Jérôme <jede@oric.org> and Ullrich von Bassewitz <uz@cc65.org> ; .export _exit .export __STARTUP__ : absolute = 1 ; Mark as startup .import initlib, donelib .import callmain, zerobss .import __MAIN_START__, __MAIN_SIZE__ .include "zeropage.inc" .include "telestrat.inc" ; ------------------------------------------------------------------------ ; Place the startup code in a special segment. .segment "STARTUP" tsx stx spsave ; Save system stk ptr ; Save space by putting some of the start-up code in a segment ; that will be re-used. jsr init ; Clear the BSS variables (after the constructors have been run). jsr zerobss ; Push the command-line arguments; and, call main(). jsr callmain ; Call the module destructors. This is also the exit() entry. _exit: jsr donelib ; Restore the system stuff. ldx spsave txs ; Copy back the zero-page stuff. ldx #zpspace - 1 L2: lda zpsave,x sta sp,x dex bpl L2 ; Back to BASIC. rts ; ------------------------------------------------------------------------ ; Put this code in a place that will be re-used by BSS, the heap, ; and the C stack. .segment "ONCE" ; Save the zero-page area that we're about to use. init: ldx #zpspace - 1 L1: lda sp,x sta zpsave,x dex bpl L1 ; Set up the C stack. lda #<(__MAIN_START__ + __MAIN_SIZE__) ldx #>(__MAIN_START__ + __MAIN_SIZE__) sta sp stx sp+1 ; Set argument stack ptr ; Call the module constructors. jmp initlib ; ------------------------------------------------------------------------ .segment "INIT" spsave: .res 1 stsave: .res 1 zpsave: .res zpspace ��������������cc65-2.18/libsrc/telestrat/ctype.s������������������������������������������������������������������0000664�0000000�0000000�00000030437�13473601511�0017011�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-04-13 ; ; Character specification table. ; ; 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. ; ; ; Bit assignments: ; ; 0 - Lower case char ; 1 - Upper case char ; 2 - Numeric digit ; 3 - Hex digit (both, lower and upper) ; 4 - Control character ; 5 - The space character itself ; 6 - Other whitespace (that is: '\f', '\n', '\r', '\t' and '\v') ; 7 - Space or tab character .export __ctype __ctype: .byte $10 ; 0/00 ___ctrl_@___ .byte $10 ; 1/01 ___ctrl_A___ .byte $10 ; 2/02 ___ctrl_B___ .byte $10 ; 3/03 ___ctrl_C___ .byte $10 ; 4/04 ___ctrl_D___ .byte $10 ; 5/05 ___ctrl_E___ .byte $10 ; 6/06 ___ctrl_F___ .byte $10 ; 7/07 ___ctrl_G___ .byte $10 ; 8/08 ___ctrl_H___ .byte $D0 ; 9/09 ___ctrl_I___ .byte $50 ; 10/0a ___ctrl_J___ .byte $50 ; 11/0b ___ctrl_K___ .byte $50 ; 12/0c ___ctrl_L___ .byte $50 ; 13/0d ___ctrl_M___ .byte $10 ; 14/0e ___ctrl_N___ .byte $10 ; 15/0f ___ctrl_O___ .byte $10 ; 16/10 ___ctrl_P___ .byte $10 ; 17/11 ___ctrl_Q___ .byte $10 ; 18/12 ___ctrl_R___ .byte $10 ; 19/13 ___ctrl_S___ .byte $10 ; 20/14 ___ctrl_T___ .byte $10 ; 21/15 ___ctrl_U___ .byte $10 ; 22/16 ___ctrl_V___ .byte $10 ; 23/17 ___ctrl_W___ .byte $10 ; 24/18 ___ctrl_X___ .byte $10 ; 25/19 ___ctrl_Y___ .byte $10 ; 26/1a ___ctrl_Z___ .byte $10 ; 27/1b ___ctrl_[___ .byte $10 ; 28/1c ___ctrl_\___ .byte $10 ; 29/1d ___ctrl_]___ .byte $10 ; 30/1e ___ctrl_^___ .byte $10 ; 31/1f ___ctrl_____ .byte $A0 ; 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 $0C ; 48/30 _____0_____ .byte $0C ; 49/31 _____1_____ .byte $0C ; 50/32 _____2_____ .byte $0C ; 51/33 _____3_____ .byte $0C ; 52/34 _____4_____ .byte $0C ; 53/35 _____5_____ .byte $0C ; 54/36 _____6_____ .byte $0C ; 55/37 _____7_____ .byte $0C ; 56/38 _____8_____ .byte $0C ; 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 $0A ; 65/41 _____A_____ .byte $0A ; 66/42 _____B_____ .byte $0A ; 67/43 _____C_____ .byte $0A ; 68/44 _____D_____ .byte $0A ; 69/45 _____E_____ .byte $0A ; 70/46 _____F_____ .byte $02 ; 71/47 _____G_____ .byte $02 ; 72/48 _____H_____ .byte $02 ; 73/49 _____I_____ .byte $02 ; 74/4a _____J_____ .byte $02 ; 75/4b _____K_____ .byte $02 ; 76/4c _____L_____ .byte $02 ; 77/4d _____M_____ .byte $02 ; 78/4e _____N_____ .byte $02 ; 79/4f _____O_____ .byte $02 ; 80/50 _____P_____ .byte $02 ; 81/51 _____Q_____ .byte $02 ; 82/52 _____R_____ .byte $02 ; 83/53 _____S_____ .byte $02 ; 84/54 _____T_____ .byte $02 ; 85/55 _____U_____ .byte $02 ; 86/56 _____V_____ .byte $02 ; 87/57 _____W_____ .byte $02 ; 88/58 _____X_____ .byte $02 ; 89/59 _____Y_____ .byte $02 ; 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 ___grave___ .byte $09 ; 97/61 _____a_____ .byte $09 ; 98/62 _____b_____ .byte $09 ; 99/63 _____c_____ .byte $09 ; 100/64 _____d_____ .byte $09 ; 101/65 _____e_____ .byte $09 ; 102/66 _____f_____ .byte $01 ; 103/67 _____g_____ .byte $01 ; 104/68 _____h_____ .byte $01 ; 105/69 _____i_____ .byte $01 ; 106/6a _____j_____ .byte $01 ; 107/6b _____k_____ .byte $01 ; 108/6c _____l_____ .byte $01 ; 109/6d _____m_____ .byte $01 ; 110/6e _____n_____ .byte $01 ; 111/6f _____o_____ .byte $01 ; 112/70 _____p_____ .byte $01 ; 113/71 _____q_____ .byte $01 ; 114/72 _____r_____ .byte $01 ; 115/73 _____s_____ .byte $01 ; 116/74 _____t_____ .byte $01 ; 117/75 _____u_____ .byte $01 ; 118/76 _____v_____ .byte $01 ; 119/77 _____w_____ .byte $01 ; 120/78 _____x_____ .byte $01 ; 121/79 _____y_____ .byte $01 ; 122/7a _____z_____ .byte $00 ; 123/7b _____{_____ .byte $00 ; 124/7c _____|_____ .byte $00 ; 125/7d _____}_____ .byte $00 ; 126/7e _____~_____ .byte $40 ; 127/7f ____DEL____ .byte $00 ; 128/80 ___________ .byte $00 ; 129/81 ___________ .byte $00 ; 130/82 ___________ .byte $00 ; 131/83 ___________ .byte $00 ; 132/84 ___________ .byte $00 ; 133/85 ___________ .byte $00 ; 134/86 ___________ .byte $00 ; 135/87 ___________ .byte $00 ; 136/88 ___________ .byte $00 ; 137/89 ___________ .byte $00 ; 138/8a ___________ .byte $00 ; 139/8b ___________ .byte $00 ; 140/8c ___________ .byte $00 ; 141/8d ___________ .byte $00 ; 142/8e ___________ .byte $00 ; 143/8f ___________ .byte $00 ; 144/90 ___________ .byte $00 ; 145/91 ___________ .byte $00 ; 146/92 ___________ .byte $10 ; 147/93 ___________ .byte $00 ; 148/94 ___________ .byte $00 ; 149/95 ___________ .byte $00 ; 150/96 ___________ .byte $00 ; 151/97 ___________ .byte $00 ; 152/98 ___________ .byte $00 ; 153/99 ___________ .byte $00 ; 154/9a ___________ .byte $00 ; 155/9b ___________ .byte $00 ; 156/9c ___________ .byte $00 ; 157/9d ___________ .byte $00 ; 158/9e ___________ .byte $00 ; 159/9f ___________ .byte $00 ; 160/a0 ___________ .byte $00 ; 161/a1 ___________ .byte $00 ; 162/a2 ___________ .byte $00 ; 163/a3 ___________ .byte $00 ; 164/a4 ___________ .byte $00 ; 165/a5 ___________ .byte $00 ; 166/a6 ___________ .byte $00 ; 167/a7 ___________ .byte $00 ; 168/a8 ___________ .byte $00 ; 169/a9 ___________ .byte $00 ; 170/aa ___________ .byte $00 ; 171/ab ___________ .byte $00 ; 172/ac ___________ .byte $00 ; 173/ad ___________ .byte $00 ; 174/ae ___________ .byte $00 ; 175/af ___________ .byte $00 ; 176/b0 ___________ .byte $00 ; 177/b1 ___________ .byte $00 ; 178/b2 ___________ .byte $00 ; 179/b3 ___________ .byte $00 ; 180/b4 ___________ .byte $00 ; 181/b5 ___________ .byte $00 ; 182/b6 ___________ .byte $00 ; 183/b7 ___________ .byte $00 ; 184/b8 ___________ .byte $00 ; 185/b9 ___________ .byte $00 ; 186/ba ___________ .byte $00 ; 187/bb ___________ .byte $00 ; 188/bc ___________ .byte $00 ; 189/bd ___________ .byte $00 ; 190/be ___________ .byte $00 ; 191/bf ___________ .byte $02 ; 192/c0 ___________ .byte $02 ; 193/c1 ___________ .byte $02 ; 194/c2 ___________ .byte $02 ; 195/c3 ___________ .byte $02 ; 196/c4 ___________ .byte $02 ; 197/c5 ___________ .byte $02 ; 198/c6 ___________ .byte $02 ; 199/c7 ___________ .byte $02 ; 200/c8 ___________ .byte $02 ; 201/c9 ___________ .byte $02 ; 202/ca ___________ .byte $02 ; 203/cb ___________ .byte $02 ; 204/cc ___________ .byte $02 ; 205/cd ___________ .byte $02 ; 206/ce ___________ .byte $02 ; 207/cf ___________ .byte $02 ; 208/d0 ___________ .byte $02 ; 209/d1 ___________ .byte $02 ; 210/d2 ___________ .byte $02 ; 211/d3 ___________ .byte $02 ; 212/d4 ___________ .byte $02 ; 213/d5 ___________ .byte $02 ; 214/d6 ___________ .byte $02 ; 215/d7 ___________ .byte $02 ; 216/d8 ___________ .byte $02 ; 217/d9 ___________ .byte $02 ; 218/da ___________ .byte $02 ; 219/db ___________ .byte $02 ; 220/dc ___________ .byte $02 ; 221/dd ___________ .byte $02 ; 222/de ___________ .byte $00 ; 223/df ___________ .byte $01 ; 224/e0 ___________ .byte $01 ; 225/e1 ___________ .byte $01 ; 226/e2 ___________ .byte $01 ; 227/e3 ___________ .byte $01 ; 228/e4 ___________ .byte $01 ; 229/e5 ___________ .byte $01 ; 230/e6 ___________ .byte $01 ; 231/e7 ___________ .byte $01 ; 232/e8 ___________ .byte $01 ; 233/e9 ___________ .byte $01 ; 234/ea ___________ .byte $01 ; 235/eb ___________ .byte $01 ; 236/ec ___________ .byte $01 ; 237/ed ___________ .byte $01 ; 238/ee ___________ .byte $01 ; 239/ef ___________ .byte $01 ; 240/f0 ___________ .byte $01 ; 241/f1 ___________ .byte $01 ; 242/f2 ___________ .byte $01 ; 243/f3 ___________ .byte $01 ; 244/f4 ___________ .byte $01 ; 245/f5 ___________ .byte $01 ; 246/f6 ___________ .byte $01 ; 247/f7 ___________ .byte $01 ; 248/f8 ___________ .byte $01 ; 249/f9 ___________ .byte $01 ; 250/fa ___________ .byte $01 ; 251/fb ___________ .byte $01 ; 252/fc ___________ .byte $01 ; 253/fd ___________ .byte $01 ; 254/fe ___________ .byte $00 ; 255/ff ___________ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/telestrat/gotox.s������������������������������������������������������������������0000664�0000000�0000000�00000000260�13473601511�0017014�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; jede jede@oric.org 2017-02-25 ; .export _gotox .import popa .importzp sp .include "telestrat.inc" .proc _gotox sta SCRX rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/telestrat/gotoxy.s�����������������������������������������������������������������0000664�0000000�0000000�00000001057�13473601511�0017212�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2017-02-25, jede <jede@oric.org> ; 2017-06-15, Greg King ; ; void gotoxy (unsigned char x, unsigned char y); ; .export gotoxy, _gotoxy .import popa .importzp sp .include "telestrat.inc" gotoxy: jsr popa ; Get Y .proc _gotoxy ; This function moves only the display cursor; it does not move the prompt position. ; In telemon, there is a position for the prompt, and another for the cursor. sta SCRY jsr popa sta SCRX rts .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/telestrat/gotoy.s������������������������������������������������������������������0000664�0000000�0000000�00000000233�13473601511�0017015�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; jede jede@oric.org 2017-02-25 ; .export _gotoy .importzp sp .include "telestrat.inc" .proc _gotoy sta SCRY rts .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/telestrat/initcwd.s����������������������������������������������������������������0000664�0000000�0000000�00000000666�13473601511�0017327�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Jede (jede@oric.org) 24.09.2017 ; .export initcwd .import __cwd .include "zeropage.inc" .include "telestrat.inc" initcwd: ldx #PWD_PTR BRK_TELEMON XVARS sta ptr1 sty ptr1+1 ldy #$00 loop: lda (ptr1),y sta __cwd,y beq done iny bne loop done: rts ��������������������������������������������������������������������������cc65-2.18/libsrc/telestrat/irq.s��������������������������������������������������������������������0000664�0000000�0000000�00000002244�13473601511�0016453�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; IRQ handling (Oric version) ; .export initirq, doneirq .import callirq .include "telestrat.inc" ; ------------------------------------------------------------------------ .segment "ONCE" initirq: lda IRQVec ldx IRQVec+1 sta IRQInd+1 stx IRQInd+2 lda #<IRQStub ldx #>IRQStub jmp setvec ; ------------------------------------------------------------------------ .code doneirq: lda IRQInd+1 ldx IRQInd+2 setvec: sei sta IRQVec stx IRQVec+1 cli rts ; ------------------------------------------------------------------------ .segment "LOWCODE" IRQStub: cld ; Just to be sure pha txa pha tya pha jsr callirq ; Call the functions pla tay pla tax pla jmp IRQInd ; Jump to the saved IRQ vector ; ------------------------------------------------------------------------ .data IRQInd: jmp $0000 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/telestrat/libref.s�����������������������������������������������������������������0000664�0000000�0000000�00000000203�13473601511�0017114�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Jede (jede@oric.org), 2017-10-16 ; .export tgi_libref .import _exit tgi_libref := _exit ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/telestrat/mainargs.s���������������������������������������������������������������0000664�0000000�0000000�00000005440�13473601511�0017462�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2003-03-07, Ullrich von Bassewitz ; 2011-01-28, Stefan Haubenthal ; 2014-09-10, Greg King ; ; Set up arguments for main ; .constructor initmainargs, 24 .import __argc, __argv .import ptr1 .include "telestrat.inc" .macpack generic MAXARGS = 10 ; Maximum number of arguments allowed ; Assume that the program was loaded, a moment ago, by the traditional LOAD ; statement. Save the "most-recent filename" as argument #0. initmainargs: ldx #0 ; Limit the length L0: lda BUFEDT,x beq L3 cmp #' ' bne L1 lda #0 beq L3 L1: sta name,x inx cpx #FNAME_LEN bne L0 lda #0 L3: sta name,x inc __argc ; argc always is equal to, at least, 1 ldy #1 * 2 ; Point to second argv slot next: lda BUFEDT,x beq done ; End of line reached inx cmp #' ' ; Skip leading spaces beq next found: cmp #'"' ; Is the argument quoted? beq setterm ; Jump if so dex ; Reset pointer to first argument character lda #' ' ; A space ends the argument setterm:sta term ; Set end of argument marker ; Now, store a pointer, to the argument, into the next slot. txa ; Get low byte clc adc #<BUFEDT bcc L4 inc L5+1 L4: sta argv,y ; argv[y]=&arg L5: lda #>BUFEDT sta argv+1,y iny iny inc __argc ; Found another arg ; Search for the end of the argument argloop:lda BUFEDT,x beq done inx cmp term bne argloop ; 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 #0 sta BUFEDT-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? bcc next ; Parse next one if not done: lda #<argv ldx #>argv sta __argv stx __argv + 1 rts .segment "INIT" term: .res 1 .data name: .res FNAME_LEN + 1 args: .res SCREEN_XSIZE * 2 - 1 param_found: .res 1 ; char* argv[MAXARGS+1]={name}; argv: .addr name .res MAXARGS * 2 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/telestrat/open.s�������������������������������������������������������������������0000664�0000000�0000000�00000001743�13473601511�0016624�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ .export _open .import addysp,popax .importzp sp,tmp2,tmp3,tmp1 .include "telestrat.inc" .include "errno.inc" .include "fcntl.inc" ; int open (const char* name, int flags, ...); /* May take a mode argument */ .proc _open ; Throw away any additional parameters passed through the ellipsis dey ; Parm count < 4 shouldn't be needed to be... dey ; ...checked (it generates a c compiler warning) dey dey beq parmok ; Branch if parameter count ok jsr addysp ; Fix stack, throw away unused parameters ; Parameters ok. Pop the flags and save them into tmp3 parmok: jsr popax ; Get flagss sta tmp3 ; save flags ; Get the filename from stack and parse it. Bail out if is not ok jsr popax ; Get name ldy tmp3 ; Get flags again BRK_TELEMON XOPEN ; launch primitive ROM rts .endproc �����������������������������cc65-2.18/libsrc/telestrat/orixhdr.s����������������������������������������������������������������0000664�0000000�0000000�00000002175�13473601511�0017342�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; By Debrune Jérôme <jede@oric.org> ; ; The following symbol is used by the linker config. file ; to force this module to be included into the output file. .export __ORIXHDR__:abs = 1 ; These symbols, also, come from the configuration file. .import __AUTORUN__, __PROGFLAG__ .import __MAIN_START__, __MAIN_LAST__ ; ------------------------------------------------------------------------ ; Orix header see http://orix.oric.org/doku.php?id=orix:header for specs .segment "ORIXHDR" .byte $01, $00 ; Non C64 marker (same as o65 format) .byte "ori" ; Magic number .byte $01 ; Version of the header .byte $00,%00000000 ; 6502 only .byte $00,$00 ; Type of language .byte $00,$00 ; OS version .byte $00 ; Reserved .byte $00 ; Auto or not .word __MAIN_START__ ; Address of start of file .word __MAIN_LAST__ - 1 ; Address of end of file .word __MAIN_START__ ; Address of start of file ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/telestrat/oserror.s����������������������������������������������������������������0000664�0000000�0000000�00000000501�13473601511�0017345�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Jede, 2017-10-27 ; ; 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 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/telestrat/read.s�������������������������������������������������������������������0000664�0000000�0000000�00000001442�13473601511�0016572�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; jede jede@oric.org 2017-01-22 ; .export _read .import popax .include "zeropage.inc" .include "telestrat.inc" ;int read (int fd, void* buf, unsigned count); .proc _read sta ptr1 ; count stx ptr1+1 ; count jsr popax ; get buf sta PTR_READ_DEST stx PTR_READ_DEST+1 sta ptr2 ; in order to calculate nb of bytes read stx ptr2+1 ; ; jsr popax ; fp pointer don't care in this version lda ptr1 ; ldy ptr1+1 ; BRK_TELEMON XFREAD ; calls telemon30 routine ; compute nb of bytes read lda PTR_READ_DEST+1 sec sbc ptr2+1 tax lda PTR_READ_DEST sec sbc ptr2 ; Here A and X contains number of bytes read rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/telestrat/sound.s������������������������������������������������������������������0000664�0000000�0000000�00000001135�13473601511�0017006�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; jede jede@oric.org 2017-01-22 .export _kbdclick1,_oups,_ping,_explode,_shoot,_zap .include "telestrat.inc" .proc _kbdclick1 ldx #<sound_bip_keyboard ldy #>sound_bip_keyboard BRK_TELEMON XSONPS rts sound_bip_keyboard: .byte $1f,$00,$00,$00,$00,$00,$00,$3e,$10,$00,$00,$1f,$00,$00 .endproc .proc _explode BRK_TELEMON XEXPLO rts .endproc .proc _oups BRK_TELEMON XOUPS rts .endproc .proc _ping BRK_TELEMON XPING rts .endproc .proc _shoot BRK_TELEMON XSHOOT rts .endproc .proc _zap BRK_TELEMON XZAP rts .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/telestrat/sysmkdir.s���������������������������������������������������������������0000664�0000000�0000000�00000001000�13473601511�0017512�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Jede (jede@oric.org), 2017-10-27 ; ; unsigned char _sysmkdir (const char* name, ...); ; .export __sysmkdir .import addysp, popax .include "telestrat.inc" .include "zeropage.inc" __sysmkdir: ; Throw away all parameters except the name dey dey jsr addysp ; Get name jsr popax ; Call telemon primitive BRK_TELEMON(XMKDIR) rts cc65-2.18/libsrc/telestrat/sysremove.s��������������������������������������������������������������0000664�0000000�0000000�00000000422�13473601511�0017710�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Jede, 10.11.2017 ; ; unsigned char __fastcall__ _sysremove (const char* name); ; .export __sysremove .include "zeropage.inc" .include "telestrat.inc" __sysremove: ; Push name BRK_TELEMON(XRM) rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/telestrat/sysuname.s���������������������������������������������������������������0000664�0000000�0000000�00000002244�13473601511�0017524�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-08-12 ; ; unsigned char __fastcall__ _sysuname (struct utsname* buf); ; .export __sysuname, utsdata .import utscopy __sysuname = utscopy ;-------------------------------------------------------------------------- ; Data. We define a fixed utsname struct here and just copy it. .rodata utsdata: ; sysname .asciiz "cc65" ; nodename .asciiz "" ; release .byte ((.VERSION >> 8) & $0F) + '0' .byte '.' .if ((.VERSION >> 4) & $0F) > 9 .byte ((.VERSION >> 4) & $0F) / 10 + '0' .byte ((.VERSION >> 4) & $0F) .MOD 10 + '0' .else .byte ((.VERSION >> 4) & $0F) + '0' .endif .byte $00 ; version .if (.VERSION & $0F) > 9 .byte (.VERSION & $0F) / 10 + '0' .byte (.VERSION & $0F) .MOD 10 + '0' .else .byte (.VERSION & $0F) + '0' .endif .byte $00 ; machine .asciiz "Oric Telestrat" ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/telestrat/tgi/���������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0016255�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/telestrat/tgi/telestrat-228-200-3.s������������������������������������������������0000664�0000000�0000000�00000024103�13473601511�0021420�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Graphics driver for the 228x200x3 palette mode on the Telestrat ; ; Jede (jede@oric.org), 2017-10-15 .include "zeropage.inc" .include "tgi-kernel.inc" .include "tgi-error.inc" .include "telestrat.inc" .macpack generic .macpack module XSIZE = 6 ; System font width YSIZE = 8 ; System font height ; ------------------------------------------------------------------------ ; Header. Includes jump table and constants. module_header _telestrat_228_200_3_tgi ; The first part of the header is a structure that has a signature, ; and defines the capabilities of the driver. .byte "tgi" .byte TGI_API_VERSION ; TGI API version number .addr $0000 ; Library reference .word 228 ; x resolution .word 200 ; y resolution .byte 3 ; Number of drawing colors .byte 1 ; Number of screens available .byte XSIZE ; System font x size .byte YSIZE ; System font y size .word $011C ; Aspect ratio (based on 4/3 display) .byte 0 ; TGI driver flags ; Next comes the jump table. Currently, all entries must be valid; ; and, may point to an RTS, for test versions (function not implemented). .addr INSTALL .addr UNINSTALL .addr INIT .addr DONE .addr GETERROR .addr CONTROL .addr CLEAR .addr SETVIEWPAGE .addr SETDRAWPAGE .addr SETCOLOR .addr SETPALETTE .addr GETPALETTE .addr GETDEFPALETTE .addr SETPIXEL .addr GETPIXEL .addr LINE .addr BAR .addr CIRCLE .addr TEXTSTYLE .addr OUTTEXT ; ------------------------------------------------------------------------ ; Data. ; Variables mapped to the zero-page segment variables. These are ; used for passing parameters to the driver. X1 := ptr1 Y1 := ptr2 X2 := ptr3 Y2 := ptr4 ; Absolute variables used in the code .bss ERROR: .res 1 ; Error code MODE: .res 1 ; Graphics mode PALETTE: .res 2 ; Constant table .rodata ; Default colors: black background, white foreground ; (The third "color" actually flips a pixel ; between the foreground and background colors.) ; DEFPALETTE: .byte 0, 1 .code ; ------------------------------------------------------------------------ ; INIT: Changes an already installed device from text mode to graphics mode. ; Note that INIT/DONE may be called multiple times while the driver ; is loaded, while INSTALL is called only once. So, any code that is needed ; to initialize variables and so on must go here. Setting palette and ; clearing the screen are not needed because they are called by the graphics ; kernel later. ; The graphics kernel never will call INIT when a graphics mode is already ; active, so there is no need to protect against that. ; ; Must set an error code: YES ; INIT: ; Switch into graphics mode. BRK_TELEMON(XHIRES) ; Done, reset the error code. lda #TGI_ERR_OK sta ERROR rts ; ------------------------------------------------------------------------ ; GETERROR: Return the error code in A, and clear it. GETERROR: ldx #TGI_ERR_OK lda ERROR stx ERROR rts ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. May ; initialize anything that has to be done just once. Is probably empty ; most of the time. ; ; Must set an error code: NO ; INSTALL: ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. May ; clean up anything done by INSTALL, but probably is empty most of the time. ; ; Must set an error code: NO ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; DONE: Will be called to switch the graphics device back into text mode. ; The graphics kernel never will call DONE when no graphics mode is active, ; so there is no need to protect against that. ; ; Must set an error code: NO ; DONE: BRK_TELEMON(XTEXT) rts ; ------------------------------------------------------------------------ ; CONTROL: Platform-/driver-specific entry point. ; ; Must set an error code: YES ; CONTROL: ; not done yet rts ; ------------------------------------------------------------------------ ; CLEAR: Clears the screen. ; ; Must set an error code: NO ; CLEAR: BRK_TELEMON(XEFFHI) rts ; ------------------------------------------------------------------------ ; SETVIEWPAGE: Set the visible page. Called with the new page in A (0..n). ; The page number already is checked to be valid, by the graphics kernel. ; ; Must set an error code: NO (will be called only if page OK) ; SETVIEWPAGE: ; ------------------------------------------------------------------------ ; SETDRAWPAGE: Set the drawable page. Called with the new page in A (0..n). ; The page number already is checked to be valid, by the graphics kernel. ; ; Must set an error code: NO (will be called only if page OK) ; SETDRAWPAGE: rts ; ------------------------------------------------------------------------ ; SETCOLOR: Set the drawing color (in A). The new color already is checked ; to be in a valid range (0..maxcolor-1). ; ; Must set an error code: NO (will be called only if color OK) ; SETCOLOR: ; not done yet rts ; ------------------------------------------------------------------------ ; SETPALETTE: Set the palette (not available with all drivers/hardware). ; A pointer to the palette is passed in ptr1. Must set an error if palettes ; are not supported. ; ; Must set an error code: YES ; SETPALETTE: ; not done yet rts flipcolor: ; not done yet rts ; ------------------------------------------------------------------------ ; GETPALETTE: Return the current palette in A/X. Even drivers that cannot ; set the palette should return the default palette here, so there's no ; way for this function to fail. ; ; Must set an error code: NO ; GETPALETTE: ; not done yet rts ; ------------------------------------------------------------------------ ; GETDEFPALETTE: Return the default palette for the driver in A/X. All ; drivers should return something reasonable here, even drivers that don't ; support palettes; otherwise, the caller has no way to determine the colors ; of the (not changeable) palette. ; ; Must set an error code: NO (all drivers must have a default palette) ; GETDEFPALETTE: lda #<DEFPALETTE ldx #>DEFPALETTE rts ; ------------------------------------------------------------------------ ; SETPIXEL: Draw one pixel at X1/Y1 = ptr1/ptr2 with the current drawing ; color. The co-ordinates passed to this function are never outside the ; visible screen area, so there is no need for clipping inside this function. ; ; Must set an error code: NO ; SETPIXEL: lda #$80 SETPIXELSETMODE: sta HRSFB lda X1 sta HRS1 lda Y1 sta HRS2 BRK_TELEMON(XCURSE) rts ; ------------------------------------------------------------------------ ; GETPIXEL: Read the color value of a pixel, and return it in A/X. The ; co-ordinates passed to this function are never outside the visible screen ; area, so there is no need for clipping inside this function. GETPIXEL: ; not done yet rts ; ------------------------------------------------------------------------ ; LINE: Draw a line from X1/Y1 to X2/Y2, where X1/Y1 = ptr1/ptr2 and ; X2/Y2 = ptr3/ptr4, using the current drawing color. ; ; Must set an error code: NO ; LINE: ; not done yet lda X1 sta HRS1 lda Y1 sta HRS2 lda X2 sta HRS3 lda Y2 sta HRS4 lda #$ff sta HRSPAT BRK_TELEMON(XDRAWA) rts CIRCLE: ; not done yet rts ; ------------------------------------------------------------------------ ; BAR: Draw a filled rectangle with the corners X1/Y1, X2/Y2, where ; X1/Y1 = ptr1/ptr2 and X2/Y2 = ptr3/ptr4, using the current drawing color. ; Contrary to most other functions, the graphics kernel will sort and clip ; the co-ordinates before calling the driver; so, on entry, the following ; conditions are valid: ; X1 <= X2 ; Y1 <= Y2 ; (X1 >= 0) && (X1 < XRES) ; (X2 >= 0) && (X2 < XRES) ; (Y1 >= 0) && (Y1 < YRES) ; (Y2 >= 0) && (Y2 < YRES) ; ; Must set an error code: NO ; BAR: ; not done yet rts ; ------------------------------------------------------------------------ ; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in the x ; and y directions is passed in X/Y, the text direction is passed in A. ; ; Must set an error code: NO ; TEXTSTYLE: rts ; ------------------------------------------------------------------------ ; OUTTEXT: Output text at x/y = ptr1/ptr2, using the current color and the ; current text style. The text to output is given as a zero-terminated ; string with its address in ptr3. ; ; Must set an error code: NO ; OUTTEXT: ; put hires cursor in X & Y lda #$00 jsr SETPIXELSETMODE ; count the length of the string ldy #$00 loop: lda (ptr3),y beq out iny bne loop out: ; XSCHAR routine from telemon needs to have the length of the string in X register ; copy Y register to X register. It could be optimized in 65C02 with TYX tya tax lda ptr3 ; XSCHAR needs in A and Y the adress of the string ldy ptr3+1 BRK_TELEMON(XSCHAR) rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/telestrat/tgi/telestrat-240-200-2.s������������������������������������������������0000664�0000000�0000000�00000023667�13473601511�0021427�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Graphics driver for the 240x200x2 monochrome mode on the Atmos ; ; Jede (jede@oric.org), 2017-10-15 .include "zeropage.inc" .include "tgi-kernel.inc" .include "tgi-error.inc" .include "telestrat.inc" .macpack generic .macpack module XSIZE = 6 ; System font width YSIZE = 8 ; System font height ; ------------------------------------------------------------------------ ; Header. Includes jump table and constants. module_header _telestrat_240_200_2_tgi ; First part of the header is a structure that has a magic and defines the ; capabilities of the driver .byte $74, $67, $69 ; "tgi" .byte TGI_API_VERSION ; TGI API version number .addr $0000 ; Library reference .word 240 ; X resolution .word 200 ; Y resolution .byte 2 ; Number of drawing colors .byte 1 ; Number of screens available .byte XSIZE ; System font X size .byte YSIZE ; System font Y size .word $011C ; Aspect ratio (based on 4/3 display) .byte 0 ; TGI driver flags ; Next comes the jump table. Currently all entries must be valid and may point ; to an RTS for test versions (function not implemented). .addr INSTALL .addr UNINSTALL .addr INIT .addr DONE .addr GETERROR .addr CONTROL .addr CLEAR .addr SETVIEWPAGE .addr SETDRAWPAGE .addr SETCOLOR .addr SETPALETTE .addr GETPALETTE .addr GETDEFPALETTE .addr SETPIXEL .addr GETPIXEL .addr LINE .addr BAR .addr TEXTSTYLE .addr OUTTEXT ; ------------------------------------------------------------------------ ; Data. ; Variables mapped to the zero page segment variables. Some of these are ; used for passing parameters to the driver. X1 := ptr1 Y1 := ptr2 X2 := ptr3 Y2 := ptr4 ; Absolute variables used in the code .bss ERROR: .res 1 ; Error code MODE: .res 1 ; Graphics mode ; Constant table .rodata DEFPALETTE: .byte 0, 1 .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. May ; initialize anything that has to be done just once. Is probably empty ; most of the time. ; ; Must set an error code: NO ; INSTALL: ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. May ; clean up anything done by INSTALL but is probably empty most of the time. ; ; Must set an error code: NO ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; INIT: Changes an already installed device from text mode to graphics ; mode. ; Note that INIT/DONE may be called multiple times while the driver ; is loaded, while INSTALL is only called once, so any code that is needed ; to initializes variables and so on must go here. Setting palette and ; clearing the screen is not needed because this is called by the graphics ; kernel later. ; The graphics kernel will never call INIT when a graphics mode is already ; active, so there is no need to protect against that. ; ; Must set an error code: YES ; INIT: ; Switch into graphics mode BRK_TELEMON(XHIRES) ; Done, reset the error code lda #TGI_ERR_OK sta ERROR rts ; ------------------------------------------------------------------------ ; DONE: Will be called to switch the graphics device back into text mode. ; The graphics kernel will never call DONE when no graphics mode is active, ; so there is no need to protect against that. ; ; Must set an error code: NO ; DONE: BRK_TELEMON(XTEXT) rts ; ------------------------------------------------------------------------ ; GETERROR: Return the error code in A and clear it. GETERROR: ldx #TGI_ERR_OK lda ERROR stx ERROR rts ; ------------------------------------------------------------------------ ; CONTROL: Platform/driver specific entry point. ; ; Must set an error code: YES ; CONTROL: ; not done yet rts ; ------------------------------------------------------------------------ ; CLEAR: Clears the screen. ; ; Must set an error code: NO ; CLEAR: BRK_TELEMON(XEFFHI) rts ; ------------------------------------------------------------------------ ; SETVIEWPAGE: Set the visible page. Called with the new page in A (0..n). ; The page number is already checked to be valid by the graphics kernel. ; ; Must set an error code: NO (will only be called if page ok) ; SETVIEWPAGE: ; ------------------------------------------------------------------------ ; SETDRAWPAGE: Set the drawable page. Called with the new page in A (0..n). ; The page number is already checked to be valid by the graphics kernel. ; ; Must set an error code: NO (will only be called if page ok) ; SETDRAWPAGE: rts ; ------------------------------------------------------------------------ ; SETCOLOR: Set the drawing color (in A). The new color is already checked ; to be in a valid range (0..maxcolor-1). ; ; Must set an error code: NO (will only be called if color ok) ; SETCOLOR: ;not done yet rts ; ------------------------------------------------------------------------ ; SETPALETTE: Set the palette (not available with all drivers/hardware). ; A pointer to the palette is passed in ptr1. Must set an error if palettes ; are not supported ; ; Must set an error code: YES ; SETPALETTE: lda #TGI_ERR_INV_FUNC ; This resolution has no palette sta ERROR rts ; ------------------------------------------------------------------------ ; GETPALETTE: Return the current palette in A/X. Even drivers that cannot ; set the palette should return the default palette here, so there's no ; way for this function to fail. ; ; Must set an error code: NO ; GETPALETTE: ; ------------------------------------------------------------------------ ; GETDEFPALETTE: Return the default palette for the driver in A/X. All ; drivers should return something reasonable here, even drivers that don't ; support palettes, otherwise the caller has no way to determine the colors ; of the (not changeable) palette. ; ; Must set an error code: NO (all drivers must have a default palette) ; GETDEFPALETTE: ; not done yet rts ; ------------------------------------------------------------------------ ; SETPIXEL: Draw one pixel at X1/Y1 = ptr1/ptr2 with the current drawing ; color. The coordinates passed to this function are never outside the ; visible screen area, so there is no need for clipping inside this function. ; ; Must set an error code: NO ; SETPIXEL: lda #$80 ; curset on SETPIXELSETMODE: sta HRSFB lda X1 sta HRS1 lda Y1 sta HRS2 BRK_TELEMON(XCURSE) rts ; ------------------------------------------------------------------------ ; GETPIXEL: Read the color value of a pixel and return it in A/X. The ; coordinates passed to this function are never outside the visible screen ; area, so there is no need for clipping inside this function. GETPIXEL: ; not done yet rts ; ------------------------------------------------------------------------ ; LINE: Draw a line from X1/Y1 to X2/Y2, where X1/Y1 = ptr1/ptr2 and ; X2/Y2 = ptr3/ptr4 using the current drawing color. ; ; Must set an error code: NO ; LINE: lda X1 sta HRS1 lda Y1 sta HRS2 lda X2 sta HRS3 lda Y2 sta HRS4 lda #$ff sta HRSPAT BRK_TELEMON(XDRAWA) rts CIRCLE: ; not done yet rts ; ------------------------------------------------------------------------ ; BAR: Draw a filled rectangle with the corners X1/Y1, X2/Y2, where ; X1/Y1 = ptr1/ptr2 and X2/Y2 = ptr3/ptr4 using the current drawing color. ; Contrary to most other functions, the graphics kernel will sort and clip ; the coordinates before calling the driver, so on entry the following ; conditions are valid: ; X1 <= X2 ; Y1 <= Y2 ; (X1 >= 0) && (X1 < XRES) ; (X2 >= 0) && (X2 < XRES) ; (Y1 >= 0) && (Y1 < YRES) ; (Y2 >= 0) && (Y2 < YRES) ; ; Must set an error code: NO ; BAR: ; not done yet rts ; ------------------------------------------------------------------------ ; TEXTSTYLE: Set the style used when calling OUTTEXT. Text scaling in X and Y ; direction is passend in X/Y, the text direction is passed in A. ; ; Must set an error code: NO ; TEXTSTYLE: rts ; ------------------------------------------------------------------------ ; OUTTEXT: Output text at X/Y = ptr1/ptr2 using the current color and the ; current text style. The text to output is given as a zero terminated ; string with address in ptr3. ; ; Must set an error code: NO ; OUTTEXT: ; put hires cursor in X & Y lda #$00 jsr SETPIXELSETMODE ; count the length of the string ldy #$00 loop: lda (ptr3),y beq out iny bne loop out: ; XSCHAR routine from telemon needs to have the length of the string in X register ; copy Y register to X register. It could be optimized in 65C02 with TYX tya tax lda ptr3 ; XSCHAR needs in A and Y the adress of the string ldy ptr3+1 BRK_TELEMON(XSCHAR) rts �������������������������������������������������������������������������cc65-2.18/libsrc/telestrat/tgi_stat_stddrv.s��������������������������������������������������������0000664�0000000�0000000�00000000377�13473601511�0021071�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Address of the static standard tgi driver ; ; Jede (jede@oric.org), 2017-10-15 ; ; const void tgi_static_stddrv[]; ; .export _tgi_static_stddrv .import _telestrat_240_200_2_tgi .rodata _tgi_static_stddrv := _telestrat_240_200_2_tgi �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/telestrat/wherex.s�����������������������������������������������������������������0000664�0000000�0000000�00000000256�13473601511�0017163�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; jede jede@oric.org 2017-02-25 ; .export _wherex .importzp sp .include "telestrat.inc" .proc _wherex ldx #$00 lda SCRX rts .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/telestrat/wherey.s�����������������������������������������������������������������0000664�0000000�0000000�00000000233�13473601511�0017157�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; jede jede@oric.org 2017-02-25 ; .export _wherey .include "telestrat.inc" .proc _wherey ldx #$00 lda SCRY rts .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/telestrat/write.s������������������������������������������������������������������0000664�0000000�0000000�00000003345�13473601511�0017015�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; jede jede@oric.org 2017-01-22 .export _write .import popax, popptr1 .importzp ptr1, ptr2, ptr3, tmp1 .include "telestrat.inc" ; int write (int fd, const void* buf, int count); .proc _write sta ptr3 stx ptr3+1 ; save count as result eor #$FF sta ptr2 txa eor #$FF sta ptr2+1 ; remember -count-1 jsr popptr1 ; get buf jsr popax ; get fd and discard ; if fd=0001 then it stdout cpx #0 beq next jmp L1 next: cmp #1 beq L1 ; here it's a file opened lda ptr1 sta PTR_READ_DEST lda ptr1+1 sta PTR_READ_DEST+1 lda ptr3 ldy ptr3+1 BRK_TELEMON XFWRITE ; compute nb of bytes written lda PTR_READ_DEST+1 sec sbc ptr1+1 tax lda PTR_READ_DEST sec sbc ptr1 rts L1: inc ptr2 bne L2 inc ptr2+1 beq L9 L2: ldy #0 lda (ptr1),y tax cpx #$0A ; check for \n bne L3 BRK_TELEMON XWR0 ; macro send char to screen (channel 0 in telemon terms) lda #$0D ; return to the beggining of the line BRK_TELEMON XWR0 ; macro ldx #$0D L3: BRK_TELEMON XWR0 ; macro inc ptr1 bne L1 inc ptr1+1 jmp L1 ; No error, return count L9: lda ptr3 ldx ptr3+1 rts .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/�������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014246�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi-kernel.s�������������������������������������������������������������������0000664�0000000�0000000�00000014131�13473601511�0016473�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 21.06.2002 ; ; Common functions of the tgi graphics kernel. ; .import tgi_libref .importzp ptr1 .include "tgi-kernel.inc" .include "tgi-error.inc" ;---------------------------------------------------------------------------- ; Variables .bss _tgi_drv: .res 2 ; Pointer to driver ; From here on, variables get cleared when a new driver is loaded cstart: _tgi_error: .res 1 ; Last error code _tgi_gmode: .res 1 ; Flag: Graphics mode active _tgi_curx: .res 2 ; Current drawing cursor X _tgi_cury: .res 2 ; Current drawing cursor Y _tgi_color: .res 1 ; Current drawing color _tgi_font: .res 1 ; Which font to use _tgi_textdir: .res 1 ; Current text direction _tgi_vectorfont: .res 2 ; Pointer to vector font ; The following are character scale/size variables in 8.8 fixed point ; format. They are required to be in this order and adjacent. _tgi_textscalew: .res 2 ; Vector font width scale .res 2 ; Bitmap font width scale _tgi_charwidth: .res 2 ; Full width of one bitmap char _tgi_textscaleh: .res 2 ; Vector font height scale .res 2 ; Bitmap font height scale _tgi_charheight: .res 2 ; Full height of one bitmap char ; End of section that gets cleared when a new driver is loaded csize = * - cstart ; Maximum X and Y coordinate (that is, xres-1 and yres-1) _tgi_xmax: .res 2 _tgi_ymax: .res 2 ; The following variables are copied from the driver header for faster access. ; fontwidth and fontheight are expected to be in order and adjacent. tgi_driver_vars: _tgi_xres: .res 2 ; X resolution of the current mode _tgi_yres: .res 2 ; Y resolution of the current mode _tgi_colorcount: .res 1 ; Number of available colors _tgi_pagecount: .res 1 ; Number of available screen pages _tgi_fontwidth: .res 1 ; System font width in pixels _tgi_fontheight: .res 1 ; System font height in pixels _tgi_aspectratio: .res 2 ; Aspect ratio in 8.8 fixed point _tgi_flags: .res 1 ; TGI driver flags .data ; Jump table for the driver functions. jumpvectors: tgi_install: jmp $0000 tgi_uninstall: jmp $0000 tgi_init: jmp $0000 tgi_done: jmp $0000 tgi_geterror: jmp $0000 tgi_control: jmp $0000 tgi_clear: jmp $0000 tgi_setviewpage: jmp $0000 tgi_setdrawpage: jmp $0000 tgi_setcolor: jmp $0000 tgi_setpalette: jmp $0000 tgi_getpalette: jmp $0000 tgi_getdefpalette: jmp $0000 tgi_setpixel: jmp $0000 tgi_getpixel: jmp $0000 tgi_line: jmp $0000 tgi_bar: jmp $0000 tgi_textstyle: jmp $0000 tgi_outtext: jmp $0000 ; Driver header signature .rodata tgi_sig: .byte $74, $67, $69, TGI_API_VERSION ; "tgi", version .code ;---------------------------------------------------------------------------- ; void __fastcall__ tgi_install (void* driver); ; /* Install an already loaded driver. */ _tgi_install: sta _tgi_drv sta ptr1 stx _tgi_drv+1 stx ptr1+1 ; Check the driver signature ldy #.sizeof(tgi_sig)-1 @L0: lda (ptr1),y cmp tgi_sig,y bne tgi_inv_drv dey bpl @L0 ; Set the library reference ldy #TGI_HDR::LIBREF lda #<tgi_libref sta (ptr1),y iny lda #>tgi_libref sta (ptr1),y ; Copy the jump vectors ldy #TGI_HDR::JUMPTAB ldx #0 @L1: inx ; Skip JMP opcode jsr copy ; Copy one byte jsr copy ; Copy one byte cpy #(TGI_HDR::JUMPTAB + .sizeof(TGI_HDR::JUMPTAB)) bne @L1 ; Call the driver install routine. It may update header variables, so we copy ; them after this call. jsr tgi_install ; Copy variables from the driver header for faster access. jsr tgi_set_ptr ; Set ptr1 to tgi_drv ldy #(TGI_HDR::VARS + .sizeof(TGI_HDR::VARS) - 1) ldx #.sizeof(TGI_HDR::VARS)-1 @L3: lda (ptr1),y sta tgi_driver_vars,x dey dex bpl @L3 ; Initialize some other variables lda #$00 ldx #csize-1 @L4: sta cstart,x ; Clear error/mode/curx/cury/... dex bpl @L4 rts ; Copy one byte to the jump vectors copy: lda (ptr1),y sta jumpvectors,x iny inx rts ;---------------------------------------------------------------------------- ; Set an invalid argument error tgi_inv_arg: lda #TGI_ERR_INV_ARG sta _tgi_error rts ;---------------------------------------------------------------------------- ; Set an invalid driver error tgi_inv_drv: lda #TGI_ERR_INV_DRIVER sta _tgi_error rts ;---------------------------------------------------------------------------- ; Load the pointer to the tgi driver into ptr1. tgi_set_ptr: lda _tgi_drv sta ptr1 lda _tgi_drv+1 sta ptr1+1 rts ;---------------------------------------------------------------------------- ; void tgi_uninstall (void); ; /* Uninstall the currently loaded driver but do not unload it. Will call ; ** tgi_done if necessary. ; */ _tgi_uninstall: jsr _tgi_done ; Switch off graphics jsr tgi_uninstall ; Allow the driver to clean up ; Clear driver pointer and error code tgi_clear_ptr: lda #$00 sta _tgi_drv sta _tgi_drv+1 sta _tgi_error rts ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_arc.c����������������������������������������������������������������������0000664�0000000�0000000�00000007640�13473601511�0016031�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* tgi_arc.c */ /* */ /* Draw an ellipse arc */ /* */ /* */ /* */ /* (C) 2002-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <tgi.h> #include <tgi/tgi-kernel.h> #include <cc65.h> /*****************************************************************************/ /* Code */ /*****************************************************************************/ void __fastcall__ tgi_arc (int x, int y, unsigned char rx, unsigned char ry, unsigned sa, unsigned ea) /* Draw an ellipse arc with center at x/y and 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 (otherwise the function may ** bevave unextectedly). */ { int x1, y1, x2, y2; unsigned char inc; unsigned char done = 0; /* Bail out if there's nothing to do */ if (sa > ea) { return; } /* Determine the number of segments to use. This may be refined ... */ if (rx + ry >= 25) { inc = 12; } else { inc = 24; } /* Calculate the start coords */ x1 = x + tgi_imulround (rx, _cos (sa)); y1 = y - tgi_imulround (ry, _sin (sa)); do { sa += inc; if (sa >= ea) { sa = ea; done = 1; } x2 = x + tgi_imulround (rx, _cos (sa)); y2 = y - tgi_imulround (ry, _sin (sa)); tgi_line (x1, y1, x2, y2); x1 = x2; y1 = y2; } while (!done); } ������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_bar.s����������������������������������������������������������������������0000664�0000000�0000000�00000005666�13473601511�0016056�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 21.06.2002 ; ; void __fastcall__ tgi_bar (int x1, int y1, int x2, int y2); ; /* Draw a bar (a filled rectangle) using the current color */ .include "tgi-kernel.inc" .importzp ptr1, ptr2, ptr3, ptr4 .import popax, popptr1 .proc _tgi_bar sta ptr4 ; Y2 stx ptr4+1 jsr popax sta ptr3 ; X2 stx ptr3+1 jsr popax sta ptr2 ; Y1 stx ptr2+1 jsr popptr1 ; X1 ; Make sure X1 is less than X2. Swap both if not. lda ptr3 cmp ptr1 lda ptr3+1 sbc ptr1+1 bpl @L1 lda ptr3 ldy ptr1 sta ptr1 sty ptr3 lda ptr3+1 ldy ptr1+1 sta ptr1+1 sty ptr3+1 ; Make sure Y1 is less than Y2. Swap both if not. @L1: lda ptr4 cmp ptr2 lda ptr4+1 sbc ptr2+1 bpl @L2 lda ptr4 ldy ptr2 sta ptr2 sty ptr4 lda ptr4+1 ldy ptr2+1 sta ptr2+1 sty ptr4+1 ; Check if X2 or Y2 are negative. If so, the bar is completely out of screen. @L2: lda ptr4+1 ora ptr3+1 bmi @L9 ; Bail out ; Check if X1 is negative. If so, clip it to the left border (zero). bit ptr1+1 bpl @L3 lda #$00 sta ptr1 sta ptr1+1 beq @L4 ; Branch always, skip following test ; Check if X1 is beyond the right border. If so, the bar is invisible. @L3: lda ptr1 cmp _tgi_xres lda ptr1+1 sbc _tgi_xres bcs @L9 ; Bail out if invisible ; Check if Y1 is negative. If so, clip it to the top border (zero). @L4: bit ptr2+1 bpl @L5 lda #$00 sta ptr2 sta ptr2+1 beq @L6 ; Branch always, skip following test ; Check if Y1 is beyond the bottom border. If so, the bar is invisible. @L5: lda ptr2 cmp _tgi_yres lda ptr2+1 sbc _tgi_yres bcs @L9 ; Bail out if invisible ; Check if X2 is larger than the maximum x coord. If so, clip it. @L6: lda ptr3 cmp _tgi_xres lda ptr3+1 sbc _tgi_xres+1 bcc @L7 jsr _tgi_getmaxx sta ptr3 stx ptr3+1 ; Check if Y2 is larger than the maximum y coord. If so, clip it. @L7: lda ptr4 cmp _tgi_yres lda ptr4+1 sbc _tgi_yres+1 bcc @L8 jsr _tgi_getmaxy sta ptr4 stx ptr4+1 ; The coordinates are now valid. Call the driver. @L8: jmp tgi_bar ; Error exit @L9: rts .endproc ��������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_circle.s�������������������������������������������������������������������0000664�0000000�0000000�00000000733�13473601511�0016541�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2009-11-05 ; ; void __fastcall__ tgi_circle (int x, int y, unsigned char radius); ; /* Draw a circle in the current drawing color */ .include "tgi-kernel.inc" .import pusha ;---------------------------------------------------------------------------- ; .code .proc _tgi_circle jsr pusha ; Push as rx jmp _tgi_ellipse ; Draw an ellipse with rx=ry .endproc �������������������������������������cc65-2.18/libsrc/tgi/tgi_clear.s��������������������������������������������������������������������0000664�0000000�0000000�00000000303�13473601511�0016357�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 21.06.2002 ; ; void tgi_clear (void); ; /* Clear the drawpage */ .include "tgi-kernel.inc" _tgi_clear = tgi_clear ; Call the driver �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_clippedline.s��������������������������������������������������������������0000664�0000000�0000000�00000023117�13473601511�0017571�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2009-10-25 ; ; Clips line coordinates to the screen coordinates and calls tgi_line ; .import umul16x16r32, udiv32by16r16 .import negax .include "tgi-kernel.inc" .include "zeropage.inc" .macpack longbranch ;---------------------------------------------------------------------------- ; Data .bss ; Outcodes for both ends tgi_clip_o1: .res 1 tgi_clip_o2: .res 1 ; Line deltas tgi_clip_d: .res 1 tgi_clip_dx: .res 2 tgi_clip_dy: .res 2 tgi_clip_sign: .res 1 ;---------------------------------------------------------------------------- ; Calculate outcodes for both ends of the line ; .code .proc outcode1 ldy #0 jsr tgi_outcode sta tgi_clip_o1 rts .endproc .code .proc outcode2 ldy #<(tgi_clip_y2 - tgi_clip_y1) jsr tgi_outcode sta tgi_clip_o2 rts .endproc ;---------------------------------------------------------------------------- ; Negate tgi_clip_dxy ; .code .proc negate lda tgi_clip_dx,y eor #$FF clc adc #1 sta tgi_clip_dx,y lda tgi_clip_dx+1,y eor #$FF adc #$00 sta tgi_clip_dx+1,y rts .endproc ;---------------------------------------------------------------------------- ; Calculate the absolute values of dx and dy and store the combined sign in ; tgi_clip_sign ; .code .proc calcdeltas lda tgi_clip_x2 sec sbc tgi_clip_x1 sta tgi_clip_dx lda tgi_clip_x2+1 sbc tgi_clip_x1+1 sta tgi_clip_dx+1 sta tgi_clip_sign bpl @L1 ldy #0 jsr negate @L1: lda tgi_clip_y2 sec sbc tgi_clip_y1 sta tgi_clip_dy lda tgi_clip_y2+1 sbc tgi_clip_y1+1 sta tgi_clip_dy+1 eor tgi_clip_sign sta tgi_clip_sign bit tgi_clip_dy+1 bpl @L9 ldy #(tgi_clip_dy - tgi_clip_dx) jmp negate @L9: rts .endproc ;---------------------------------------------------------------------------- ; Helper routine. Generate the absolute value of y/a and calculate the sign ; of the final result ; .code .proc prepare_coord tax ; Remember high byte eor tgi_clip_sign sta tmp1 ; Sign of result tya cpx #0 ; Check sign bpl @L1 jsr negax @L1: sta ptr1 stx ptr1+1 rts .endproc ;---------------------------------------------------------------------------- ; Helper routine. Move the value in eax to ptr1:ptr2 ; .code .proc move_intermediate_result sta ptr1 stx ptr1+1 ldy sreg sty ptr2 ldy sreg+1 sty ptr2+1 rts .endproc ;---------------------------------------------------------------------------- ; Multiplicate value in y/a by dy, then divide by dx. ; .code .proc muldiv_dydx ; Generate the absolute value of y/a and calculate the sign of the final ; result jsr prepare_coord ; All values are positive now (dx/dy have been made positive in calcdeltas) ; and the sign of the final result is on tmp1, so we can use unsigned ; operations and apply the final result later, after rounding. lda tgi_clip_dy ldx tgi_clip_dy+1 ; rhs jsr umul16x16r32 ; Multiplicate ; Move the result of the multiplication into ptr1:ptr2 jsr move_intermediate_result ; Load divisor and divide lda tgi_clip_dx ldx tgi_clip_dx+1 jsr udiv32by16r16 ; Check the sign of the final result and negate it if nessary done: bit tmp1 jmi negax rts .endproc ;---------------------------------------------------------------------------- ; Multiplicate value in y/a by dx, then divide by dy. ; .code .proc muldiv_dxdy ; Generate the absolute value of y/a and calculate the sign of the final ; result jsr prepare_coord ; All values are positive now (dx/dy have been made positive in calcdeltas) ; and the sign of the final result is on tmp1, so we can use unsigned ; operations and apply the final result later, after rounding. lda tgi_clip_dx ldx tgi_clip_dx+1 ; rhs jsr umul16x16r32 ; Multiplicate ; Move the result of the multiplication into ptr1:ptr2 jsr move_intermediate_result ; Load divisor and divide lda tgi_clip_dy ldx tgi_clip_dy+1 jsr udiv32by16r16 ; Check the sign of the final result and negate it if nessary jmp muldiv_dydx::done .endproc ;---------------------------------------------------------------------------- ; Clip a line using Cohen Sutherland ; .code .proc tgi_clippedline ; Set a flag that we have no deltas calculated lda #0 sta tgi_clip_d ; Generate outcodes jsr outcode1 jsr outcode2 ; if ((tgi_clip_o1 | tgi_clip_o2) == 0) { ; tgi_line (x1, y1, x2, y2); ; } Loop: lda tgi_clip_o1 ora tgi_clip_o2 bne L1 ; Copy the coordinates into ptr1-4 and draw the line ldx #7 L0: lda tgi_clip_x1,x sta ptr1,x dex bpl L0 jmp tgi_line ; if ((tgi_clip_o1 & tgi_clip_o2) != 0) reject; L1: lda tgi_clip_o1 and tgi_clip_o2 beq L2 rts ; Nothing to draw ; We must clip. If we haven't already done so, calculate dx/dy. L2: lda tgi_clip_d ; Deltas alreay calculated? bne HaveDeltas ; Jump if yes inc tgi_clip_d jsr calcdeltas ; Check if X1/Y1 needs clipping HaveDeltas: lda tgi_clip_o1 jeq L10 ; Need to clip X1/Y1 lsr a ; Check for TGI_CLIP_LEFT bcc L3 ; tgi_clip_y1 += (0 - tgi_clip_x1) * tgi_clip_dy / tgi_clip_dx; ; tgi_clip_x1 = 0; lda #$00 tax beq L4 L3: lsr a ; Check for TGI_CLIP_RIGHT bcc L5 ; tgi_clip_y1 += (tgi_xmax - tgi_clip_x1) * tgi_clip_dy / tgi_clip_dx; ; tgi_clip_x1 = tgi_xmax; lda _tgi_xmax ldx _tgi_xmax+1 L4: tay sec sbc tgi_clip_x1 sty tgi_clip_x1 tay txa sbc tgi_clip_x1+1 stx tgi_clip_x1+1 jsr muldiv_dydx clc adc tgi_clip_y1 sta tgi_clip_y1 txa adc tgi_clip_y1+1 sta tgi_clip_y1+1 ; lda tgi_clip_o1 lsr a lsr a L5: lsr a ; Check for TGI_CLIP_BOTTOM bcc L6 ; tgi_clip_x1 = (0 - tgi_clip_y1) * tgi_clip_dx / tgi_clip_dy; ; tgi_clip_y1 = 0; lda #$00 tax beq L7 L6: lsr a ; Check for TGI_CLIP_TOP bcc L8 ; tgi_clip_x1 += (tgi_ymax - tgi_clip_y1) * tgi_clip_dx / tgi_clip_dy; ; tgi_clip_y1 = ymax; lda _tgi_ymax ldx _tgi_ymax+1 L7: tay sec sbc tgi_clip_y1 sty tgi_clip_y1 tay txa sbc tgi_clip_y1+1 stx tgi_clip_y1+1 jsr muldiv_dxdy clc adc tgi_clip_x1 sta tgi_clip_x1 txa adc tgi_clip_x1+1 sta tgi_clip_x1+1 ; We need to recalculate outcode1 in this case L8: jsr outcode1 ; Check if X2/Y2 needs clipping L10: lda tgi_clip_o2 jeq Loop ; Need to clip X2/Y2 lsr a ; Check for TGI_CLIP_LEFT bcc L11 ; tgi_clip_y2 += (0 - tgi_clip_x2) * tgi_clip_dy / tgi_clip_dx; ; tgi_clip_x2 = 0; lda #$00 tax beq L12 L11: lsr a ; Check for TGI_CLIP_RIGHT bcc L13 ; tgi_clip_y2 += (tgi_xmax - tgi_clip_x2) * tgi_clip_dy / tgi_clip_dx; ; tgi_clip_x2 = tgi_xmax; lda _tgi_xmax ldx _tgi_xmax+1 L12: tay sec sbc tgi_clip_x2 sty tgi_clip_x2 tay txa sbc tgi_clip_x2+1 stx tgi_clip_x2+1 jsr muldiv_dydx clc adc tgi_clip_y2 sta tgi_clip_y2 txa adc tgi_clip_y2+1 sta tgi_clip_y2+1 ; lda tgi_clip_o2 lsr a lsr a L13: lsr a ; Check for TGI_CLIP_BOTTOM bcc L14 ; tgi_clip_x2 += (0 - tgi_clip_y2) * tgi_clip_dx / tgi_clip_dy; ; tgi_clip_y2 = 0; lda #$00 tax beq L15 L14: lsr a ; Check for TGI_CLIP_TOP bcc L16 ; tgi_clip_x2 += (tgi_ymax - tgi_clip_y2) * tgi_clip_dx / tgi_clip_dy; ; tgi_clip_y2 = tgi_ymax; lda _tgi_ymax ldx _tgi_ymax+1 L15: tay sec sbc tgi_clip_y2 sty tgi_clip_y2 tay txa sbc tgi_clip_y2+1 stx tgi_clip_y2+1 jsr muldiv_dxdy clc adc tgi_clip_x2 sta tgi_clip_x2 txa adc tgi_clip_x2+1 sta tgi_clip_x2+1 ; We need to recalculate outcode2 in this case L16: jsr outcode2 ; Try again jmp Loop .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_curtoxy.s������������������������������������������������������������������0000664�0000000�0000000�00000000672�13473601511�0017017�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 02.10.2002 ; ; Helper function for tgi functions. Moves the current X/Y pos to ptr1/ptr2 ; .include "tgi-kernel.inc" .importzp ptr1, ptr2 tgi_curtoxy: ldy _tgi_curx ; X1 sty ptr1 ldy _tgi_curx+1 sty ptr1+1 ldy _tgi_cury ; Y1 sty ptr2 ldy _tgi_cury+1 sty ptr2+1 rts ����������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_done.s���������������������������������������������������������������������0000664�0000000�0000000�00000001043�13473601511�0016220�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 21.06.2002 ; ; void tgi_done (void); ; /* End graphics mode, switch back to text mode. Will NOT unload the driver! */ .include "tgi-kernel.inc" .include "tgi-error.inc" .proc _tgi_done lda _tgi_gmode ; Is a graphics mode active? beq @L1 ; Jump if not jsr tgi_done ; Call the driver routine lda #$00 sta _tgi_gmode ; Reset the graph mode flag @L1: rts .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_ellipse.s������������������������������������������������������������������0000664�0000000�0000000�00000001206�13473601511�0016731�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2009-11-05 ; ; void __fastcall__ tgi_ellipse (int x, int y, unsigned char rx, unsigned char ry); ; /* Draw a full ellipse with center at x/y and radii rx/ry using the current ; ** drawing color. ; */ ; .include "tgi-kernel.inc" .import pusha, push0 ;---------------------------------------------------------------------------- ; .code .proc _tgi_ellipse jsr pusha ; Push ry jsr push0 ; Start angle is 0 lda #<360 ldx #>360 ; End angle is 360 jmp _tgi_arc .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_free_vectorfont.s����������������������������������������������������������0000664�0000000�0000000�00000000432�13473601511�0020466�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2009-11-01 ; ; void tgi_free_vectorfont (const tgi_vectorfont* font); ; /* Free a vector font that was previously loaded into memory. */ ; ; This function is identical to free(void*) ; .import _free .export _tgi_free_vectorfont := _free ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_getaspectratio.s�����������������������������������������������������������0000664�0000000�0000000�00000000537�13473601511�0020320�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2011-05-01 ; ; unsigned tgi_getaspectratio (void); ; /* Returns the aspect ratio for the loaded driver. The aspect ratio is an ; ** 8.8 fixed point value. ; */ ; .include "tgi-kernel.inc" .proc _tgi_getaspectratio lda _tgi_aspectratio ldx _tgi_aspectratio+1 rts .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_getcolor.s�����������������������������������������������������������������0000664�0000000�0000000�00000000501�13473601511�0017107�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.06.2002 ; ; unsigned char tgi_getcolor (void); ; /* Return the current drawing color */ .include "tgi-kernel.inc" .proc _tgi_getcolor lda _tgi_color ; Get the current drawing color ldx #0 ; Clear high byte rts .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_getcolorcount.s������������������������������������������������������������0000664�0000000�0000000�00000000415�13473601511�0020164�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.06.2002 ; ; unsigned char tgi_getcolorcount (void); ; /* Get the number of available colors */ .include "tgi-kernel.inc" .proc _tgi_getcolorcount lda _tgi_colorcount ldx #0 rts .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_getdefpalette.s������������������������������������������������������������0000664�0000000�0000000�00000000466�13473601511�0020120�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 23.06.2002 ; ; const unsigned char* tgi_getdefpalette (void); ; /* Return the default palette. Will return NULL for drivers that do not ; ** support palettes. ; */ ; .include "tgi-kernel.inc" _tgi_getdefpalette = tgi_getdefpalette ; Call the driver ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_geterror.s�����������������������������������������������������������������0000664�0000000�0000000�00000001420�13473601511�0017123�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 21.06.2002 ; ; unsigned char tgi_geterror (void); ; /* Return the error code for the last operation. This will also clear the ; ** error. ; */ .include "tgi-kernel.inc" .proc _tgi_geterror lda _tgi_drv ; Check if we have a driver ora _tgi_drv+1 beq @L1 jsr tgi_geterror ; First call driver @L1: ldx #$00 ; Clear high byte ldy _tgi_error ; Test high level error code beq @L2 ; Branch if no high level error code tya ; Use high level code if we have one stx _tgi_error ; Clear high level error code @L2: rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_geterrormsg.s��������������������������������������������������������������0000664�0000000�0000000�00000003116�13473601511�0017636�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2004-06-15 ; ; const char* __fastcall__ tgi_geterrormsg (unsigned char code); ; /* Get an error message describing the error in code. */ ; .include "tgi-kernel.inc" .include "tgi-error.inc" .proc _tgi_geterrormsg cmp #TGI_ERR_COUNT bcc L1 lda #TGI_ERR_COUNT ; "Unknown error" L1: tay ldx #>msgtab lda #<msgtab clc adc offs,y bcc L2 inx L2: rts .endproc ;---------------------------------------------------------------------------- ; Error messages. The messages are currently limited to 256 bytes total. .rodata offs: .byte <(msg0-msgtab) .byte <(msg1-msgtab) .byte <(msg2-msgtab) .byte <(msg3-msgtab) .byte <(msg4-msgtab) .byte <(msg5-msgtab) .byte <(msg6-msgtab) .byte <(msg7-msgtab) .byte <(msg8-msgtab) .byte <(msg9-msgtab) .byte <(msg10-msgtab) msgtab: msg0: .asciiz "No error" msg1: .asciiz "No driver available" msg2: .asciiz "Cannot load driver" msg3: .asciiz "Invalid driver" msg4: .asciiz "Mode not supported by driver" msg5: .asciiz "Invalid function argument" msg6: .asciiz "Function not supported" msg7: .asciiz "Invalid font file" msg8: .asciiz "Out of resources" msg9: .asciiz "Unknown error" msg10: .asciiz "A driver is already installed" .assert (*-msgtab) < 256, error, "Message table too large" ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_getmaxcolor.s��������������������������������������������������������������0000664�0000000�0000000�00000000547�13473601511�0017627�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.06.2002 ; ; unsigned char tgi_getmaxcolor (void); ; /* Return the maximum supported color number (the number of colors would ; ** then be getmaxcolor()+1). ; */ ; .include "tgi-kernel.inc" .proc _tgi_getmaxcolor ldx _tgi_colorcount dex txa ldx #0 rts .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_getmaxx.s������������������������������������������������������������������0000664�0000000�0000000�00000000464�13473601511�0016756�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 21.06.2002 ; ; unsigned tgi_getmaxx (void); ; /* Return the maximum x coordinate. The resolution in x direction is ; ** getmaxx() + 1 ; */ .include "tgi-kernel.inc" .proc _tgi_getmaxx lda _tgi_xmax ldx _tgi_xmax+1 rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_getmaxy.s������������������������������������������������������������������0000664�0000000�0000000�00000000463�13473601511�0016756�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 21.06.2002 ; ; unsigned tgi_getmaxy (void); ; /* Return the maximum y coordinate. The resolution in y direction is ; ** getmaxy() + 1 ; */ .include "tgi-kernel.inc" .proc _tgi_getmaxy lda _tgi_ymax ldx _tgi_ymax+1 rts .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_getpagecount.s�������������������������������������������������������������0000664�0000000�0000000�00000000422�13473601511�0017760�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 23.06.2002 ; ; unsigned tgi_getpagecount (void); ; /* Returns the number of screen pages available. */ ; .include "tgi-kernel.inc" .proc _tgi_getpagecount lda _tgi_pagecount ldx #0 rts .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_getpalette.s���������������������������������������������������������������0000664�0000000�0000000�00000000463�13473601511�0017436�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 23.06.2002 ; ; const unsigned char* tgi_getpalette (void); ; /* Return the current palette. Will return NULL for drivers that do not ; ** support palettes. ; */ ; .include "tgi-kernel.inc" _tgi_getpalette = tgi_getpalette ; Call the driver �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_getpixel.s�����������������������������������������������������������������0000664�0000000�0000000�00000000650�13473601511�0017117�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 21.06.2002 ; ; unsigned char __fastcall__ tgi_getpixel (int x, int y); ; /* Get the color value of a pixel */ .include "tgi-kernel.inc" .import return0 .proc _tgi_getpixel jsr tgi_getset ; Pop args, check range bcs @L9 jmp tgi_getpixel ; Call the driver @L9: jmp return0 ; Assume bg color .endproc ����������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_getset.s�������������������������������������������������������������������0000664�0000000�0000000�00000002003�13473601511�0016563�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2002-06-22, Ullrich von Bassewitz ; 2018-07-27, Greg King ; ; Helper function for getpixel/setpixel. Load X/Y from arguments; ; and, check if the co-ordinates are valid. Return carry clear if so. ; .include "tgi-kernel.inc" .import popax .importzp ptr1, ptr2 .proc tgi_getset jsr tgi_popxy ; Pop X/Y into ptr1/ptr2 ; Are the co-ordinates out of range? First, check if any coord is negative. txa ; (.X = ptr2+1 from tgi_popxy) ora ptr1+1 sec ; Return carry set if number is negative bmi @L9 ; Bail out if negative ; Check if X is larger than the maximum x coord. If so, bail out. lda ptr1 cmp _tgi_xres txa sbc _tgi_xres+1 bcs @L9 ; Check if Y is larger than the maximum y coord. lda ptr2 cmp _tgi_yres lda ptr2+1 sbc _tgi_yres+1 @L9: rts .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_gettextheight.s������������������������������������������������������������0000664�0000000�0000000�00000002406�13473601511�0020154�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2009-10-30 ; .include "tgi-kernel.inc" .include "tgi-vectorfont.inc" .include "zeropage.inc" ;----------------------------------------------------------------------------- ; unsigned __fastcall__ tgi_gettextheight (const char* s); ; /* Calculate the height of the text in pixels according to the current text ; ** style. ; */ ; .proc _tgi_gettextheight ldy _tgi_font bne @L2 ; Jump if vector font ; Return the height for the bitmap font lda _tgi_charheight ldx #0 @L1: rts ; Return the height for the vector font @L2: lda _tgi_vectorfont tax ora _tgi_vectorfont+1 beq @L1 ; Return zero if no font stx ptr1 lda _tgi_vectorfont+1 sta ptr1+1 ldy #TGI_VECTORFONT::HEIGHT lda (ptr1),y ; Get height of font sta ptr1 lda #0 sta ptr1+1 ; Save base height in ptr1 lda _tgi_textscaleh ldx _tgi_textscaleh+1 ; Get scale factor ... jmp tgi_imulround ; ... and return scaled result .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_gettextwidth.s�������������������������������������������������������������0000664�0000000�0000000�00000004740�13473601511�0020026�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2009-10-30 ; .include "tgi-kernel.inc" .include "tgi-vectorfont.inc" .include "zeropage.inc" .import _strlen, _toascii .import umul8x16r16 ;----------------------------------------------------------------------------- ; Aliases for zero page locations Width := ptr1 WTab := ptr2 Text := ptr3 ;----------------------------------------------------------------------------- ; unsigned __fastcall__ tgi_gettextwidth (const char* s); ; /* Calculate the width of the text in pixels according to the current text ; ** style. ; */ ; ; Result is strlen (s) * tgi_textmagw * tgi_fontsizex ; .code .proc _tgi_gettextwidth ldy _tgi_font bne @L1 ; Jump if vector font ; Return the width of the string for the bitmap font jsr _strlen ldy _tgi_charwidth+1 sty ptr1 jmp umul8x16r16 ; Return the width of the string for the vector font. To save some code, we ; will add up all the character widths and then multiply by the scale factor. ; Since the output routine will scale each single character, the result may ; be slightly different. @L1: sta Text stx Text+1 ; Save pointer to string lda _tgi_vectorfont+1 tax ora _tgi_vectorfont beq @L9 ; Return zero if no font lda _tgi_vectorfont clc adc #<(TGI_VECTORFONT::WIDTHS - TGI_VF_FIRSTCHAR) sta WTab txa adc #>(TGI_VECTORFONT::WIDTHS - TGI_VF_FIRSTCHAR) sta WTab+1 ldy #0 sty Width sty Width+1 ; Zero the total width ; Sum up the widths of the single characters @L2: ldy #0 lda (Text),y ; Get next char beq @L4 ; Bail out if end of text reached jsr _toascii ; Convert to ascii tay lda (WTab),y ; Get width of this char clc adc Width sta Width bcc @L3 inc Width+1 @L3: inc Text bne @L2 inc Text+1 bne @L2 ; We have the total width now, scale and return it @L4: lda _tgi_textscalew ldx _tgi_textscalew+1 jmp tgi_imulround ; Exit point if no font installed @L9: rts .endproc ��������������������������������cc65-2.18/libsrc/tgi/tgi_getxres.s������������������������������������������������������������������0000664�0000000�0000000�00000000402�13473601511�0016752�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 21.06.2002 ; ; unsigned tgi_getxres (void); ; /* Return the resolution in X direction */ .include "tgi-kernel.inc" .proc _tgi_getxres lda _tgi_xres ldx _tgi_xres+1 rts .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_getyres.s������������������������������������������������������������������0000664�0000000�0000000�00000000402�13473601511�0016753�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 21.06.2002 ; ; unsigned tgi_getyres (void); ; /* Return the resolution in Y direction */ .include "tgi-kernel.inc" .proc _tgi_getyres lda _tgi_yres ldx _tgi_yres+1 rts .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_gotoxy.s�������������������������������������������������������������������0000664�0000000�0000000�00000000664�13473601511�0016634�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.06.2002 ; ; void __fastcall__ tgi_gotoxy (int x, int y); ; /* Set the current drawing pointer to the given position. */ ; .include "tgi-kernel.inc" .import popax .proc _tgi_gotoxy sta _tgi_cury ; Y stx _tgi_cury+1 jsr popax sta _tgi_curx ; X stx _tgi_curx+1 rts .endproc ����������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_imulround.s����������������������������������������������������������������0000664�0000000�0000000�00000002355�13473601511�0017320�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2009-11-05 ; ; Helper function for graphics functions: Multiply two values, one being ; an 8.8 fixed point one, and return the rounded and scaled result. ; ; The module has two entry points: One is C callable and expects the ; parameters in ax and the stack, the second is assembler callable and ; expects the parameters in ax and ptr1 ; .export _tgi_imulround, tgi_imulround .import popax, imul16x16r32 .include "zeropage.inc" ;---------------------------------------------------------------------------- ; .code ; C callable entry point _tgi_imulround: ; Get arguments sta ptr1 stx ptr1+1 ; Save lhs jsr popax ; Get rhs ; ASM callable entry point tgi_imulround: ; Multiplicate jsr imul16x16r32 ; Round the result cmp #$80 ; Frac(x) >= 0.5? txa ldy sreg+1 ; Check sign bmi @L1 adc #$00 tay lda sreg adc #$00 tax tya rts @L1: sbc #$00 tay lda sreg sbc #$00 tax tya rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_init.s���������������������������������������������������������������������0000664�0000000�0000000�00000003776�13473601511�0016255�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 21.06.2002 ; ; void tgi_init (void); ; /* Initialize the already loaded graphics driver */ .include "tgi-kernel.inc" .include "tgi-error.inc" .import pushax, pusha, decax1 .importzp ptr1 ;---------------------------------------------------------------------------- .code .proc _tgi_init jsr _tgi_done ; Switch off graphics if needed jsr tgi_init ; Go into graphics mode jsr tgi_geterror ; Get the error code sta _tgi_error ; Save for later reference cmp #TGI_ERR_OK bne @L9 ; Jump on error inc _tgi_gmode ; Remember that graph mode is active ; Get the maximum X and Y coordinate jsr _tgi_getxres jsr decax1 sta _tgi_xmax stx _tgi_xmax+1 jsr _tgi_getyres jsr decax1 sta _tgi_ymax stx _tgi_ymax+1 ; Do driver initialization. Set draw and view pages. lda #0 jsr tgi_setviewpage lda #0 jsr tgi_setdrawpage ; Set the default palette. jsr tgi_getdefpalette ; Get the default palette into A/X sta ptr1 stx ptr1+1 ; Save it jsr tgi_setpalette ; Set the default palette. jsr tgi_geterror ; Clear a possible error code ; Set the drawing color to white @L1: lda #tgi_color_white jsr _tgi_setcolor ; tgi_setcolor (TGI_COLOR_WHITE); ; Set the text style lda #<$100 ldx #>$100 jsr pushax ; Width scale = 1.0 jsr pushax ; Heigh scale = 1.0 jsr pusha ; Text direction = TGI_TEXT_HORIZONTAL jmp _tgi_settextstyle ; A = Font = TGI_FONT_BITMAP ; Error exit @L9: rts .endproc ��cc65-2.18/libsrc/tgi/tgi_install_vectorfont.s�������������������������������������������������������0000664�0000000�0000000�00000001124�13473601511�0021212�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2009-11-06 ; .include "tgi-kernel.inc" ;----------------------------------------------------------------------------- ; void __fastcall__ tgi_install_vectorfont (const tgi_vectorfont* font); ; /* 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. ; */ ; .code .proc _tgi_install_vectorfont sta _tgi_vectorfont stx _tgi_vectorfont+1 rts .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_ioctl.s��������������������������������������������������������������������0000664�0000000�0000000�00000001123�13473601511�0016404�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2004-10-14 ; ; unsigned __fastcall__ tgi_ioctl (unsigned char code, void* data); ; /* Call the driver specific control function. What this function does for ; ** a specific code depends on the driver. The driver will set an error ; ** for unknown codes or values. ; */ ; .include "tgi-kernel.inc" .import popa .importzp ptr1 .proc _tgi_ioctl sta ptr1 stx ptr1+1 ; Save val jsr popa ; Retrieve code jmp tgi_control ; Call the driver .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_line.s���������������������������������������������������������������������0000664�0000000�0000000�00000001112�13473601511�0016217�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 21.06.2002 ; ; void __fastcall__ tgi_line (int x1, int y1, int x2, int y2); ; /* Draw a line in the current drawing color */ .include "tgi-kernel.inc" .import popax .proc _tgi_line jsr tgi_linepop ; Pop/store Y2/X2 jsr popax ; Y1 sta tgi_clip_y1 stx tgi_clip_y1+1 jsr popax ; X1 sta tgi_clip_x1 stx tgi_clip_x1+1 jmp tgi_clippedline ; Call the line clipper .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_linepop.s������������������������������������������������������������������0000664�0000000�0000000�00000000754�13473601511�0016751�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.06.2002 ; ; Helper function for tgi_line and tgi_lineto. Pops/stores X2/Y2. ; .include "tgi-kernel.inc" .import popax .proc tgi_linepop sta tgi_clip_y2 ; Y2 stx tgi_clip_y2+1 sta _tgi_cury stx _tgi_cury+1 jsr popax sta tgi_clip_x2 ; X2 stx tgi_clip_x2+1 sta _tgi_curx stx _tgi_curx+1 rts .endproc ��������������������cc65-2.18/libsrc/tgi/tgi_lineto.s�������������������������������������������������������������������0000664�0000000�0000000�00000001116�13473601511�0016566�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.06.2002 ; ; void __fastcall__ tgi_lineto (int x2, int y2); ; /* Draw a line in the current drawing color from the graphics cursor to the ; ** new end point. ; */ .include "tgi-kernel.inc" .import popax .proc _tgi_lineto pha ldy #3 ; Copy curx/cury to tgi_clip_x1/tgi_clip_y1 @L1: lda _tgi_curx,y sta tgi_clip_x1,y dey bpl @L1 pla jsr tgi_linepop ; Pop x2/y2 jmp tgi_clippedline ; Call the line clipper .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_load.s���������������������������������������������������������������������0000664�0000000�0000000�00000005245�13473601511�0016222�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2012-07-22 ; ; void __fastcall__ tgi_load_driver (const char* name); ; /* Load and install the given driver. */ .include "tgi-kernel.inc" .include "tgi-error.inc" .include "modload.inc" .include "fcntl.inc" .import pushax .import pusha0 .import incsp2 .import _open .import _read .import _close ;---------------------------------------------------------------------------- ; Variables .data ctrl: .addr _read .res 2 ; CALLERDATA .res 2 ; MODULE .res 2 ; MODULE_SIZE .res 2 ; MODULE_ID ;---------------------------------------------------------------------------- ; Code .code .proc _tgi_load_driver ; Check if we do already have a driver loaded. This is an error. Do not ; touch A/X because they contain the file name. ldy _tgi_drv bne @L0 ldy _tgi_drv+1 beq @L1 @L0: lda #TGI_ERR_INSTALLED bne @L3 ; Push the name onto the C stack and open the file. The parameter will get ; removed by open(). ; ctrl.callerdata = open (name, O_RDONLY); @L1: jsr pushax lda #<O_RDONLY jsr pusha0 ldy #4 ; Argument size jsr _open sta ctrl + MOD_CTRL::CALLERDATA stx ctrl + MOD_CTRL::CALLERDATA+1 ; if (ctrl.callerdata >= 0) { txa bmi @L2 ; /* Load the module */ ; Res = mod_load (&ctrl); lda #<ctrl ldx #>ctrl jsr _mod_load pha ; /* Close the input file */ ; close (ctrl.callerdata); lda ctrl + MOD_CTRL::CALLERDATA ldx ctrl + MOD_CTRL::CALLERDATA+1 jsr _close ; /* Check the return code */ ; if (Res == MLOAD_OK) { pla beq @L5 @L2: lda #TGI_ERR_CANNOT_LOAD ; Set an error and exit @L3: sta _tgi_error @L4: rts ; Check the driver signature, install the driver. ; tgi_install (ctrl.module); @L5: lda ctrl + MOD_CTRL::MODULE ldx ctrl + MOD_CTRL::MODULE+1 jsr _tgi_install ; If tgi_install was successful, we're done lda _tgi_error beq @L4 ; The driver didn't install correctly. Remove it from memory. The error code ; will be retained. lda _tgi_drv ldx _tgi_drv+1 jsr _mod_free ; Free the driver memory jmp tgi_clear_ptr ; Clear tgi_drv and return .endproc �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_load_vectorfont.c����������������������������������������������������������0000664�0000000�0000000�00000011772�13473601511�0020455�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* tgi_load_vectorfont.c */ /* */ /* Loader module for TGI vector font files */ /* */ /* */ /* */ /* (C) 2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <tgi.h> #include <tgi/tgi-kernel.h> #include <tgi/tgi-vectorfont.h> /*****************************************************************************/ /* Code */ /*****************************************************************************/ const tgi_vectorfont* __fastcall__ tgi_load_vectorfont (const char* name) /* 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. */ { static const char Magic[4] = { 0x54, 0x43, 0x48, TGI_VF_VERSION }; tgi_vectorfont_header H; int F; tgi_vectorfont* Font = 0; unsigned V; unsigned char I; /* Assume we have an error loading the font */ tgi_error = TGI_ERR_CANNOT_LOAD; /* Open the file */ F = open (name, O_RDONLY); if (F < 0) { /* Cannot open file */ goto LoadError; } /* Read the header */ if (read (F, &H, sizeof (H)) != sizeof (H)) { /* Cannot read header bytes */ goto LoadError; } /* Check the header */ if (memcmp (&H, Magic, sizeof (Magic)) != 0) { /* Header magic not ok */ goto LoadError; } /* Allocate memory for the data */ Font = malloc (H.size); if (Font == 0) { /* Out of memory */ tgi_error = TGI_ERR_NO_RES; goto LoadError; } /* Read the whole font file into the buffer */ if (read (F, Font, H.size) != H.size) { /* Problem reading font data */ free (Font); goto LoadError; } /* Close the file */ close (F); /* Fix the offset pointers. When loaded, they contain numeric offsets ** into the VectorOps, with the start of the VectorOps at offset zero. ** We will add a pointer to the VectorOps to make them actual pointers ** that may be used independently from anything else. */ V = (unsigned) &Font->vec_ops; for (I = 0; I < TGI_VF_CCOUNT; ++I) { Font->chars[I] += V; } /* Clear the error */ tgi_error = TGI_ERR_OK; /* Return the vector font loaded */ return Font; LoadError: /* Some sort of load problem. If the file is still open, be sure to ** close it */ if (F >= 0) { close (F); } return 0; } ������cc65-2.18/libsrc/tgi/tgi_outcode.s������������������������������������������������������������������0000664�0000000�0000000�00000004046�13473601511�0016743�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2009-10-25 ; ; Generates clipping outcodes for Cohen Sutherland and others. ; .include "tgi-kernel.inc" .include "zeropage.inc" ;---------------------------------------------------------------------------- ; Data .bss ; Clipping coordinates. They must be in this order! tgi_clip_x1: .res 2 tgi_clip_y1: .res 2 tgi_clip_x2: .res 2 tgi_clip_y2: .res 2 ;---------------------------------------------------------------------------- ; Generate a Cohen Sutherland outcode ; ; void outcode () ; { ; unsigned char o = 0; ; if (Y < 0) { ; o = TGI_CLIP_BOTTOM; ; } else if (Y >= yres) { ; o = TGI_CLIP_TOP; ; } ; if (X < 0) { ; o |= TGI_CLIP_LEFT; ; } else if (X >= xres) { ; o |= TGI_CLIP_RIGHT; ; } ; return o; ; } ; ; The function return the outcode in A and the flags for the outcode are ; correctly set. ; .code .proc tgi_outcode lda #TGI_CLIP_NONE sta tmp1 ; Check Y coordinate lda tgi_clip_y1+1,y ; High byte of Y1 bmi L2 ; Jump if bottom clip ldx tgi_clip_y1,y ; Low byte of Y1 cpx _tgi_yres sbc _tgi_yres+1 bvs L1 eor #$80 L1: bpl L4 lda #TGI_CLIP_TOP ; Top clipping necessary bne L3 L2: lda #TGI_CLIP_BOTTOM L3: sta tmp1 ; Save temp outcode ; Check X coordinate L4: lda tgi_clip_x1+1,y ; High byte of X1 bmi L7 ; Jump if left clip ldx tgi_clip_x1,y ; Low byte of X1 cpx _tgi_xres sbc _tgi_xres+1 bvs L5 eor #$80 L5: bmi L6 ; No right or left clipping necessary lda tmp1 rts ; Need right clipping L6: lda #TGI_CLIP_RIGHT ora tmp1 rts ; Need left clipping L7: lda #TGI_CLIP_LEFT ora tmp1 rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_outtext.s������������������������������������������������������������������0000664�0000000�0000000�00000007406�13473601511�0017020�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 21.06.2002 ; ; void __fastcall__ tgi_outtext (const char* s); ; /* Output text at the current graphics cursor position. */ .include "tgi-kernel.inc" .include "tgi-vectorfont.inc" .include "zeropage.inc" .import _toascii .import popax, negax ;---------------------------------------------------------------------------- ; Data text := regbank font := regbank ; Same as text widths := regbank+2 ;---------------------------------------------------------------------------- ; .proc _tgi_outtext ldy _tgi_font ; Bit or vectorfont? bne VectorFont ; Handle bitmapped font output sta ptr3 stx ptr3+1 ; Pass s in ptr3 to driver pha txa pha ; Save s on stack for later jsr tgi_curtoxy ; Copy curx/cury into ptr1/ptr2 jsr tgi_outtext ; Call the driver pla tax pla ; Restore s jsr _tgi_gettextwidth ; Get width of text string ; Move the graphics cursor by the amount in a/x MoveCursor: ldy _tgi_textdir ; Horizontal or vertical text? beq @L1 ; Jump if horizontal ; Move graphics cursor for vertical text jsr negax ldy #2 ; Point to _tgi_cury ; Move graphics cursor for horizontal text @L1: clc adc _tgi_curx,y sta _tgi_curx,y txa adc _tgi_curx+1,y sta _tgi_curx+1,y Done: rts ; Handle vector font output. First, check if we really have a registered ; vector font. Bail out if this is not the case. VectorFont: tay lda _tgi_vectorfont ; Do we have a vector font? ora _tgi_vectorfont+1 beq Done ; Bail out if not ; Check if the font in the given size is partially out of the screen. We ; do this in vertical direction here, and in horizontal direction before ; outputting a character. ; (todo) ; Save zero page variable on stack and save lda text pha lda text+1 pha lda widths pha lda widths+1 pha sty text stx text+1 ; Store pointer to string lda _tgi_vectorfont clc adc #<(TGI_VECTORFONT::WIDTHS - TGI_VF_FIRSTCHAR) sta widths lda _tgi_vectorfont+1 adc #>(TGI_VECTORFONT::WIDTHS - TGI_VF_FIRSTCHAR) sta widths+1 ; Output the text string @L1: ldy #0 lda (text),y ; Get next character from string beq EndOfText jsr _toascii ; Convert to ascii pha ; Save char in A jsr _tgi_vectorchar ; Output it pla ; Move the graphics cursor by the width of the char tay lda (widths),y ; Get width of this char sta ptr1 lda #0 sta ptr1+1 lda _tgi_textscalew ldx _tgi_textscalew+1 ; Get scale factor jsr tgi_imulround ; Multiplcate and round jsr MoveCursor ; Move the graphics cursor ; Next char in string inc text bne @L1 inc text+1 bne @L1 ; Done. Restore registers and return EndOfText: pla sta widths+1 pla sta widths pla sta text+1 pla sta text rts .endproc ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_outtextxy.s����������������������������������������������������������������0000664�0000000�0000000�00000001432�13473601511�0017372�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 21.06.2002 ; ; void __fastcall__ tgi_outtextxy (int x, int y, const char* s); ; /* Output text at the given position. */ .include "tgi-kernel.inc" .import addysp1 .importzp sp .proc _tgi_outtextxy ; Get the X/Y parameters and store them into curx/cury. This enables us ; to use tgi_outtext for the actual output pha ; ldy #0 lda (sp),y sta _tgi_cury iny lda (sp),y sta _tgi_cury+1 iny lda (sp),y sta _tgi_curx iny lda (sp),y sta _tgi_curx+1 pla jsr addysp1 ; Drop arguments from stack jmp _tgi_outtext .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_pieslice.c�����������������������������������������������������������������0000664�0000000�0000000�00000006750�13473601511�0017062�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* tgi_pieslice.c */ /* */ /* Draw an ellipic pie slice */ /* */ /* */ /* */ /* (C) 2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <tgi.h> #include <tgi/tgi-kernel.h> #include <cc65.h> /*****************************************************************************/ /* Code */ /*****************************************************************************/ void __fastcall__ tgi_pieslice (int x, int y, unsigned char rx, unsigned char ry, unsigned sa, unsigned ea) /* Draw an ellipse pie slice with center at x/y 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 (otherwise the ** function may behave unexpectedly). */ { /* Draw an arc ... */ tgi_arc (x, y, rx, ry, sa, ea); /* ... and close it */ tgi_line (x, y, x + tgi_imulround (rx, _cos (sa)), y - tgi_imulround (ry, _sin (sa))); tgi_line (x, y, x + tgi_imulround (rx, _cos (ea)), y - tgi_imulround (ry, _sin (ea))); } ������������������������cc65-2.18/libsrc/tgi/tgi_popxy.s��������������������������������������������������������������������0000664�0000000�0000000�00000000573�13473601511�0016461�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2002-10-02, Ullrich von Bassewitz ; 2018-05-20, Christian Kruger ; ; Helper function for TGI functions. Pops X/Y from arguments into ptr1/ptr2. ; .include "tgi-kernel.inc" .import popptr1 .importzp ptr2 .proc tgi_popxy sta ptr2 ; Y stx ptr2+1 jmp popptr1 ; X .endproc �������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_popxy2.s�������������������������������������������������������������������0000664�0000000�0000000�00000000627�13473601511�0016543�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 02.10.2002 ; ; Helper function for tgi functions. Pops X/Y from stack into ptr3/ptr4 ; .include "tgi-kernel.inc" .import popax .importzp ptr3, ptr4 .proc tgi_popxy2 sta ptr4 ; Y stx ptr4+1 jsr popax sta ptr3 ; X stx ptr3+1 rts .endproc ���������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_setaspectratio.s�����������������������������������������������������������0000664�0000000�0000000�00000000567�13473601511�0020337�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2011-05-01 ; ; void __fastcall__ tgi_setaspectratio (unsigned aspectratio); ; /* Set a new aspect ratio for the loaded driver. The aspect ratio is an ; ** 8.8 fixed point value. ; */ ; .include "tgi-kernel.inc" .proc _tgi_setaspectratio sta _tgi_aspectratio stx _tgi_aspectratio+1 rts .endproc �����������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_setcolor.s�����������������������������������������������������������������0000664�0000000�0000000�00000000710�13473601511�0017125�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 21.06.2002 ; ; void __fastcall__ tgi_setcolor (unsigned char color); ; /* Set the current drawing color */ .include "tgi-kernel.inc" .proc _tgi_setcolor cmp _tgi_colorcount ; Compare to available colors bcs @L1 sta _tgi_color ; Remember the drawing color jmp tgi_setcolor ; Call the driver @L1: jmp tgi_inv_arg ; Invalid argument .endproc ��������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_setdrawpage.s��������������������������������������������������������������0000664�0000000�0000000�00000000607�13473601511�0017606�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.06.2002 ; ; void __fastcall__ tgi_setdrawpage (unsigned char page); ; /* Set the drawable page */ .include "tgi-kernel.inc" .proc _tgi_setdrawpage cmp _tgi_pagecount ; Compare to available pages bcs @L1 jmp tgi_setdrawpage ; Call the driver @L1: jmp tgi_inv_arg ; Invalid argument .endproc �������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_setpalette.s���������������������������������������������������������������0000664�0000000�0000000�00000000707�13473601511�0017453�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 23.06.2002 ; ; void __fastcall__ tgi_setpalette (const unsigned char* palette); ; /* Set the palette (not available with all drivers/hardware). palette is ; ** a pointer to as many entries as there are colors. ; */ ; .include "tgi-kernel.inc" .importzp ptr1 .proc _tgi_setpalette sta ptr1 stx ptr1+1 jmp tgi_setpalette ; Call the driver .endproc ���������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_setpixel.s�����������������������������������������������������������������0000664�0000000�0000000�00000000544�13473601511�0017135�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 21.06.2002 ; ; void __fastcall__ tgi_setpixel (int x, int y); ; /* Plot a point in the current drawing color */ .include "tgi-kernel.inc" .proc _tgi_setpixel jsr tgi_getset ; Pop args, check range bcs @L9 jmp tgi_setpixel ; Call the driver @L9: rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_settextdir.s���������������������������������������������������������������0000664�0000000�0000000�00000000653�13473601511�0017500�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2011-07-17 ; .include "tgi-kernel.inc" ;----------------------------------------------------------------------------- ; void __fastcall__ tgi_settextdir (unsigned char dir); ; /* Set the direction for text output. dir is one of the TGI_TEXT_XXX ; ** constants. ; */ ; .proc _tgi_settextdir sta _tgi_textdir ; Remember the direction rts .endproc �������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_settextstyle.s�������������������������������������������������������������0000664�0000000�0000000�00000006401�13473601511�0020057�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2009-10-30 ; .include "zeropage.inc" .include "tgi-kernel.inc" .import umul8x16r24 .import popa, popax .macpack cpu ;----------------------------------------------------------------------------- ; void __fastcall__ tgi_settextstyle (unsigned width, unsigned height, ; unsigned char dir, unsigned char font); ; /* Set the style for text output. The scaling factors for width and height ; ** are 8.8 fixed point values. This means that $100 = 1 $200 = 2 etc. ; ** dir is one of the TGI_TEXT_XXX constants. font is one of the TGI_FONT_XXX ; ** constants. ; */ ; .proc _tgi_settextstyle sta _tgi_font ; Remember the font to use jsr popa sta _tgi_textdir ; Remember the direction ; Pop the height and run directly into tgi_textscale jsr popax .endproc ;----------------------------------------------------------------------------- ; void __fastcall__ tgi_settextscale (unsigned width, unsigned height); ; /* 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. ; */ .proc _tgi_settextscale ; Setup the height ldy _tgi_fontheight ; Get height of bitmap font in pixels sty ptr1 ; Save for later ldy #6 ; Address the height jsr process_onedim ; Process height ; Setup the width jsr popax ; Get width scale into a/x ldy _tgi_fontwidth ; Get width of bitmap font in pixels sty ptr1 ; Save for later ldy #0 ; Address the width ; Process one character dimension. That means: ; ; - Store the vector font dimension in 8.8 format ; - If necessary, round up/down to next integer ; - Store the bitmap font dimension in 8.8 format ; - Multiply by size of bitmap char in pixels ; - Store the bitmap font size in 8.8 format ; process_onedim: jsr store ; Store vector font scale factor bit _tgi_flags ; Fine grained scaling support avail? bmi @L2 ; Jump if yes asl a ; Round to nearest full integer bcc @L1 inx @L1: lda #0 @L2: jsr store ; Store bitmap font scale factor ; The size of the font in pixels in the selected dimension is already in ptr1 ; So if we call umul8x16r24 we get the size in pixels in 16.8 fixed point. ; Disallowing characters larger than 256 pixels, we just drop the high byte ; and remember the low 16 bit as size in 8.8 format. .if (.cpu .bitand ::CPU_ISET_65SC02) phy ; Save Y jsr umul8x16r24 ply ; Restore Y .else sty tmp1 ; Save Y jsr umul8x16r24 ldy tmp1 ; Restore Y .endif store: sta _tgi_textscalew,y iny pha txa sta _tgi_textscalew,y iny pla rts .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_setviewpage.s��������������������������������������������������������������0000664�0000000�0000000�00000000610�13473601511�0017615�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 22.06.2002 ; ; void __fastcall__ tgi_setviewpage (unsigned char page); ; /* Set the visible page. */ .include "tgi-kernel.inc" .proc _tgi_setviewpage cmp _tgi_pagecount ; Compare to available pages bcs @L1 jmp tgi_setviewpage ; Call the driver @L1: jmp tgi_inv_arg ; Invalid argument .endproc ������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_unload.s�������������������������������������������������������������������0000664�0000000�0000000�00000001325�13473601511�0016560�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 21.06.2002 ; ; void tgi_unload (void); ; /* Unload the currently loaded driver. */ .include "tgi-kernel.inc" .include "tgi-error.inc" .include "modload.inc" _tgi_unload: lda _tgi_drv ora _tgi_drv beq no_driver ; No driver lda _tgi_drv pha lda _tgi_drv+1 pha ; Save pointer to driver jsr _tgi_uninstall ; Uninstall the driver pla tax pla jmp _mod_free ; Free the driver no_driver: lda #<TGI_ERR_NO_DRIVER sta _tgi_error rts �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgi_vectorchar.s���������������������������������������������������������������0000664�0000000�0000000�00000013604�13473601511�0017441�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2009-11-02 ; ; void __fastcall__ tgi_vectorchar (const unsigned char* Ops); ; /* Draw one character of the vector font at the current graphics cursor ; ** position using the current font magnification. ; */ ; .import imul16x16r32, umul16x16r32, negax, negeax .include "tgi-kernel.inc" .include "tgi-vectorfont.inc" .include "zeropage.inc" .macpack longbranch ;---------------------------------------------------------------------------- ; Data Ops = regbank Flag = regbank+2 .bss X1: .res 2 Y1: .res 2 X2: .res 2 Y2: .res 2 ;---------------------------------------------------------------------------- ; Get the next operation from the Ops pointer, remove the flag bit and sign ; extend the 8 bit value to 16 bits. .code .proc GetOp ; Load delta value ldy #0 lda (Ops),y inc Ops bne :+ inc Ops+1 ; Move bit 7 into Flag, then sign extend the value in A and extend the sign ; into X. : asl a ; Flag into carry ror Flag ldx #0 cmp #$80 ; Sign bit into carry ror a ; Sign extend the value bpl :+ dex ; Value is negative ; Done : rts .endproc ;---------------------------------------------------------------------------- ; Get and process one coordinate value. The scale factor is passed in a/x .code GetProcessedYCoord: lda _tgi_textscaleh+0 ldx _tgi_textscaleh+1 GetProcessedCoord: ; Save scale factor as left operand for multiplication sta ptr1 stx ptr1+1 ; Load next operation value. jsr GetOp ; Multiplicate with the scale factor. jmp tgi_imulround ; Multiplicate, round and scale ;---------------------------------------------------------------------------- ; Add the base coordinate with offset in Y to the value in A/X .code .proc AddBaseCoord clc adc _tgi_curx+0,y pha txa adc _tgi_curx+1,y tax pla rts .endproc ;---------------------------------------------------------------------------- ; Subtract the value in a/x from the base coordinate with offset in Y ; This is ; ; ax = _tgi_cur[xy] - ax ; ; which can be transformed to ; ; ax = _tgi_cur[xy] + (~ax + 1); .code .proc SubBaseCoord eor #$FF sec ; + 1 adc _tgi_curx+0,y pha txa eor #$FF adc _tgi_curx+1,y tax pla rts .endproc ;---------------------------------------------------------------------------- ; .code .proc _tgi_vectorchar ; Multiplicate the char value by two and save into Y asl a tay ; Since we will call tgi_lineto, which uses the zero page, and we do also ; need the zero page, make room in the register bank. lda Ops pha lda Ops+1 pha lda Flag pha ; Calculate a pointer to the vector ops for the given char (now in Y). We ; definitely expect a font here, that has to be checked by the caller. lda _tgi_vectorfont clc adc #<(TGI_VECTORFONT::CHARS - 2*TGI_VF_FIRSTCHAR) sta Ops lda _tgi_vectorfont+1 adc #>(TGI_VECTORFONT::CHARS - 2*TGI_VF_FIRSTCHAR) sta Ops+1 iny lda (Ops),y tax dey lda (Ops),y sta Ops stx Ops+1 ; Main loop executing vector operations Loop: lda _tgi_textscalew+0 ldx _tgi_textscalew+1 jsr GetProcessedCoord ; Get X vector ; Depending on the text direction, the X vector is either applied to X as ; ; X2 = _tgi_curx + XMag * XDelta ; ; or applied to Y as ; ; Y2 = _tgi_cury - XMag * XDelta ; ; which can be transformed to ; ; Y2 = _tgi_cury + (~(XMag * XDelta) + 1); ; ; ; For the Y component we have ; ; Y2 = _tgi_cury - YMag * YDelta ; ; which can be transformed to ; ; Y2 = _tgi_cury + (~(YMag * YDelta) + 1); ; ; or applied to X as ; ; X2 = _tgi_curx - YMag * YDelta ; ; which can be transformed to ; ; X2 = _tgi_curx + (~(YMag * YDelta) + 1); ; ldy _tgi_textdir ; Horizontal or vertical text? bne @Vertical ; Jump if vertical ; Process horizontal text ldy #0 jsr AddBaseCoord sta X2 stx X2+1 ; Get Y vector jsr GetProcessedYCoord ; Apply to Y ldy #2 jsr SubBaseCoord sta Y2 stx Y2+1 jmp @DrawMove ; Process vertical text @Vertical: ldy #2 jsr SubBaseCoord sta Y2 stx Y2+1 ; Get Y vector jsr GetProcessedYCoord ; Apply to X ldy #0 jsr SubBaseCoord sta X2 stx X2+1 ; Draw, then move - or just move @DrawMove: bit Flag bpl @Move ; Jump if move only .if 0 ldy #7 ; Copy start coords into zp : lda X1,y sta ptr1,y dey bpl :- jsr tgi_line ; Call the driver .else ldy #7 ; Copy start coords : lda X1,y sta tgi_clip_x1,y dey bpl :- jsr tgi_clippedline ; Call line clipper .endif ; Move the start position @Move: ldy #3 : lda X2,y sta X1,y dey bpl :- ; Loop if not done bit Flag bvc Loop ; Done. Restore zp and return. pla sta Flag pla sta Ops+1 pla sta Ops rts .endproc ����������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/tgi/tgidrv_line.inc����������������������������������������������������������������0000664�0000000�0000000�00000013116�13473601511�0017251�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt <ol.sc@web.de> ; ; Generic LINE implementation based on SETPIXEL for TGI driver inclusion ; Code previously present in a2.lo.tgi, c128-vdc.tgi and c128-vdc2.tgi ; ; ------------------------------------------------------------------------ ; LINE: Draw a line from X1/Y1 to X2/Y2, where X1/Y1 = ptr1/ptr2 and ; X2/Y2 = ptr3/ptr4 using the current drawing color. ; Must set an error code: NO .proc LINE ; Used for passing parameters to the driver. X1 := ptr1 Y1 := ptr2 X2 := ptr3 Y2 := ptr4 ; These ones must be on zpage. TEMP1 := tmp3 TEMP2 := tmp4 TEMP3 := sreg TEMP4 := sreg+1 PB := ptr3 UB := ptr4 ERR := regsave NX := regsave+2 ; ------------------------------------------------------------------------ .bss COUNT: .res 2 NY: .res 2 DX: .res 1 DY: .res 1 AX: .res 1 AY: .res 1 ; ------------------------------------------------------------------------ .code ; nx = abs (x2 - x1) sec lda X2 sbc X1 sta NX lda X2+1 sbc X1+1 tay lda NX jsr abs sta NX sty NX+1 ; ny = abs (y2 - y1) sec lda Y2 sbc Y1 sta NY lda Y2+1 sbc Y1+1 tay lda NY jsr abs sta NY sty NY+1 ; if (x2 >= x1) ldx #X2 lda X1 ldy X1+1 jsr icmp bcc :+ ; dx = 1 lda #$01 bne :++ ; else ; dx = -1 : lda #$FF : sta DX ; if (y2 >= y1) ldx #Y2 lda Y1 ldy Y1+1 jsr icmp bcc :+ ; dy = 1 lda #$01 bne :++ ; else ; dy = -1 : lda #$FF : sta DY ; err = ax = ay = 0 lda #$00 sta ERR sta ERR+1 sta AX sta AY ; if (nx < ny) { ldx #NX lda NY ldy NY+1 jsr icmp bcs :+ ; nx <-> ny lda NX ldx NY sta NY stx NX lda NX+1 ldx NY+1 sta NY+1 stx NX+1 ; ax = dx lda DX sta AX ; ay = dy lda DY sta AY ; dx = dy = 0 } lda #$00 sta DX sta DY ; ny = - ny : lda NY ldy NY+1 jsr neg sta NY sty NY+1 ; for (count = nx; count > 0; --count) { lda NX ldx NX+1 sta COUNT stx COUNT+1 for: lda COUNT ; count > 0 ora COUNT+1 bne :+ rts ; setpixel (X1, Y1) : jsr SETPIXEL ; pb = err + ny clc lda ERR adc NY sta PB lda ERR+1 adc NY+1 sta PB+1 tax ; ub = pb + nx clc lda PB adc NX sta UB txa adc NX+1 sta UB+1 ; x1 = x1 + dx ldx #$00 lda DX bpl :+ dex : clc adc X1 sta X1 txa adc X1+1 sta X1+1 ; y1 = y1 + ay ldx #$00 lda AY bpl :+ dex : clc adc Y1 sta Y1 txa adc Y1+1 sta Y1+1 ; if (abs (pb) < abs (ub)) { lda PB ldy PB+1 jsr abs sta TEMP3 sty TEMP4 lda UB ldy UB+1 jsr abs ldx #TEMP3 jsr icmp bpl :+ ; err = pb } lda PB ldx PB+1 jmp next ; else { x1 = x1 + ax : ldx #$00 lda AX bpl :+ dex : clc adc X1 sta X1 txa adc X1+1 sta X1+1 ; y1 = y1 + dy ldx #$00 lda DY bpl :+ dex : clc adc Y1 sta Y1 txa adc Y1+1 sta Y1+1 ; err = ub } lda UB ldx UB+1 next: sta ERR stx ERR+1 ; } (--count) lda COUNT sec sbc #$01 sta COUNT bcc :+ jmp for : dec COUNT+1 jmp for ; Copies of some runtime routines abs: ; A/Y := abs (A/Y) cpy #$00 bpl :+ ; A/Y := neg (A/Y) neg: clc eor #$FF adc #$01 pha tya eor #$FF adc #$00 tay pla : rts icmp: ; Compare A/Y to zp,X sta TEMP1 ; TEMP1/TEMP2 - arg2 sty TEMP2 lda $00,x pha lda $01,x tay pla tax tya ; X/A - arg1 (a = high) sec sbc TEMP2 bne :++ cpx TEMP1 beq :+ adc #$FF ora #$01 : rts : bvc :+ eor #$FF ora #$01 : rts .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/vic20/�����������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014406�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/vic20/_scrsize.s�������������������������������������������������������������������0000664�0000000�0000000�00000000241�13473601511�0016410�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 26.10.2000 ; ; Screen size variables ; .export screensize .import SCREEN screensize = SCREEN ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/vic20/break.s����������������������������������������������������������������������0000664�0000000�0000000�00000004314�13473601511�0015660�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 27.09.1998 ; ; void __fastcall__ set_brk (unsigned Addr); ; void reset_brk (void); ; .export _set_brk, _reset_brk .destructor _reset_brk .export _brk_a, _brk_x, _brk_y, _brk_sr, _brk_pc .include "vic20.inc" .bss _brk_a: .res 1 _brk_x: .res 1 _brk_y: .res 1 _brk_sr: .res 1 _brk_pc: .res 2 oldvec: .res 2 ; Old vector .data uservec: jmp $FFFF ; Patched at runtime .code ; Set the break vector .proc _set_brk sta uservec+1 stx uservec+2 ; Set the user vector lda oldvec ora oldvec+1 ; Did we save the vector already? bne L1 ; Jump if we installed the handler already lda BRKVec sta oldvec lda BRKVec+1 sta oldvec+1 ; Save the old vector L1: lda #<brk_handler ; Set the break vector to our routine ldx #>brk_handler sta BRKVec stx BRKVec+1 rts .endproc ; Reset the break vector .proc _reset_brk lda oldvec ldx oldvec+1 beq @L9 ; Jump if vector not installed sta BRKVec stx BRKVec+1 lda #$00 sta oldvec ; Clear the old vector stx oldvec+1 @L9: rts .endproc ; Break handler, called if a break occurs .proc brk_handler pla sta _brk_y pla sta _brk_x pla sta _brk_a pla and #$EF ; Clear break bit sta _brk_sr pla ; PC low sec sbc #2 ; Point to start of brk sta _brk_pc pla ; PC high sbc #0 sta _brk_pc+1 jsr uservec ; Call the user's routine lda _brk_pc+1 pha lda _brk_pc pha lda _brk_sr pha ldx _brk_x ldy _brk_y lda _brk_a rti ; Jump back... .endproc ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/vic20/cgetc.s����������������������������������������������������������������������0000664�0000000�0000000�00000002761�13473601511�0015665�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; char cgetc (void); ; .export _cgetc .import cursor .include "cbm_kernal.inc" .include "vic20.inc" _cgetc: lda KEY_COUNT ; Get number of characters bne L3 ; Jump if there are already chars waiting ; Switch on the cursor if needed lda CURS_FLAG pha lda cursor jsr setcursor L1: lda KEY_COUNT beq L1 ldx #0 pla bne L2 inx L2: txa jsr setcursor L3: jsr KBDREAD ; Read char and return in A ldx #0 rts ; Switch the cursor on or off .proc setcursor tax ; On or off? bne seton ; Go set it on lda CURS_FLAG ; Is the cursor currently off? bne crs9 ; Jump if yes inc CURS_FLAG ; Mark it as off lda CURS_STATE ; Cursor currently displayed? beq crs8 ; Jump if no ldy CURS_X ; Get the character column lda (SCREEN_PTR),y ; Get character eor #$80 sta (SCREEN_PTR),y ; Store character back lda CURS_COLOR sta (CRAM_PTR),y ; Store color back crs8: lda #0 sta CURS_STATE ; Cursor not displayed crs9: rts seton: lda #0 sta CURS_FLAG rts .endproc ���������������cc65-2.18/libsrc/vic20/clrscr.s���������������������������������������������������������������������0000664�0000000�0000000�00000000235�13473601511�0016062�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; void clrscr (void); ; .export _clrscr .include "cbm_kernal.inc" _clrscr = CLRSCR �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/vic20/color.s����������������������������������������������������������������������0000664�0000000�0000000�00000002375�13473601511�0015717�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; Adapted for Vic20 by Steve Schmidtke 05.08.2002 ; ; 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 .importzp tmp1 .include "vic20.inc" .code _textcolor: ldx CHARCOLOR ; get old value sta CHARCOLOR ; set new value txa rts _bgcolor: asl asl asl asl sta tmp1 sei ; don't want anything messing around while we update lda VIC_COLOR ; get old value and #$0F tax ora tmp1 sta VIC_COLOR ; set new value cli txa lsr lsr lsr lsr rts _bordercolor: and #$07 sta tmp1 sei ; don't want anything messing around while we update lda VIC_COLOR ; get old value and #$F8 tax ora tmp1 sta VIC_COLOR ; set new value cli txa rts �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/vic20/conio.s����������������������������������������������������������������������0000664�0000000�0000000�00000000252�13473601511�0015700�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; Low level stuff for screen output/console input ; .exportzp CURS_X, CURS_Y .include "vic20.inc" ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/vic20/cputc.s����������������������������������������������������������������������0000664�0000000�0000000�00000004470�13473601511�0015715�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; void cputcxy (unsigned char x, unsigned char y, char c); ; void cputc (char c); ; .export _cputcxy, _cputc, cputdirect, putchar .export newline, plot .import gotoxy .import PLOT .include "vic20.inc" _cputcxy: pha ; Save C jsr gotoxy ; Set cursor, drop x and y pla ; Restore C ; Plot a character - also used as internal function _cputc: cmp #$0A ; CR? bne L1 lda #0 sta CURS_X beq plot ; Recalculate pointers L1: cmp #$0D ; LF? beq newline ; Recalculate pointers ; Printable char of some sort cmp #' ' bcc cputdirect ; Other control char tay bmi L10 cmp #$60 bcc L2 and #$DF bne cputdirect ; Branch always L2: and #$3F cputdirect: jsr putchar ; Write the character to the screen ; Advance cursor position advance: iny cpy #XSIZE bne L3 jsr newline ; new line ldy #0 ; + cr L3: sty CURS_X rts newline: clc lda #XSIZE adc SCREEN_PTR sta SCREEN_PTR bcc L4 inc SCREEN_PTR+1 clc L4: lda #XSIZE adc CRAM_PTR sta CRAM_PTR bcc L5 inc CRAM_PTR+1 L5: inc CURS_Y rts ; Handle character if high bit set L10: and #$7F cmp #$7E ; PI? bne L11 lda #$5E ; Load screen code for PI bne cputdirect L11: ora #$40 bne cputdirect ; 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 ldy CURS_X sta (SCREEN_PTR),y ; Set char lda CHARCOLOR sta (CRAM_PTR),y ; Set color rts ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/vic20/crt0.s�����������������������������������������������������������������������0000664�0000000�0000000�00000004160�13473601511�0015443�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Startup code for cc65 (Vic20 version) ; .export _exit .export __STARTUP__ : absolute = 1 ; Mark as startup .import initlib, donelib .import zerobss, push0 .import callmain .import RESTOR, BSOUT, CLRCH .import __MAIN_START__, __MAIN_SIZE__ ; Linker generated .import __STACKSIZE__ ; Linker generated .importzp ST .include "zeropage.inc" .include "vic20.inc" ; ------------------------------------------------------------------------ ; Startup code .segment "STARTUP" 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 jsr BSOUT ; Clear the BSS data. jsr zerobss ; Save some system stuff; and, set up the stack. tsx stx spsave ; Save the system stack ptr 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. jsr initlib ; Push the command-line arguments; and, call main(). jsr callmain ; Back from main() [this is also the exit() entry]. Run the module destructors. _exit: pha ; Save the return code on stack jsr donelib ; Copy back the zero-page stuff. ldx #zpspace-1 L2: lda zpsave,x sta sp,x dex bpl L2 ; Place the program return code into BASIC's status variable. pla sta ST ; Restore the stack pointer. ldx spsave txs ; Back to BASIC. rts ; ------------------------------------------------------------------------ .segment "INIT" zpsave: .res zpspace ; ------------------------------------------------------------------------ .bss spsave: .res 1 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/vic20/devnum.s���������������������������������������������������������������������0000664�0000000�0000000�00000000160�13473601511�0016065�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2010-02-14 ; .include "vic20.inc" .exportzp devnum := DEVNUM ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/vic20/emd/�������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015153�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/vic20/emd/vic20-georam.s�����������������������������������������������������������0000775�0000000�0000000�00000020172�13473601511�0017537�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Extended memory driver for the GEORAM cartridge through the masC=erade ; c64 cartridge adapter. Driver works without problems when statically ; linked. ; ; Marco van den Heuvel, 2018-03-18 ; .include "zeropage.inc" .include "em-kernel.inc" .include "em-error.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _vic20_georam_emd ; Driver signature .byte $65, $6d, $64 ; "emd" .byte EMD_API_VERSION ; EM API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr PAGECOUNT .addr MAP .addr USE .addr COMMIT .addr COPYFROM .addr COPYTO ; ------------------------------------------------------------------------ ; Constants GR_WINDOW = $9800 ; Address of GEORAM window GR_PAGE_LO = $9CFE ; Page register low GR_PAGE_HI = $9CFF ; Page register high ; ------------------------------------------------------------------------ ; Data. .data pagecount: .res 2 ; Number of available pages .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present and determine the amount of ; memory available. ; Must return an EM_ERR_xx code in a/x. ; INSTALL: ldx GR_WINDOW cpx GR_WINDOW bne @notpresent inc GR_WINDOW cpx GR_WINDOW beq @notpresent lda #4 jsr check cpy GR_WINDOW beq @has64k lda #8 jsr check cpy GR_WINDOW beq @has128k lda #16 jsr check cpy GR_WINDOW beq @has256k lda #32 jsr check cpy GR_WINDOW beq @has512k lda #64 jsr check cpy GR_WINDOW beq @has1024k lda #128 jsr check cpy GR_WINDOW beq @has2048k ldx #>16384 bne @setok @has64k: ldx #>256 bne @setok @has128k: ldx #>512 bne @setok @has256k: ldx #>1024 bne @setok @has512k: ldx #>2048 bne @setok @has1024k: ldx #>4096 bne @setok @has2048k: ldx #>8192 bne @setok @notpresent: lda #<EM_ERR_NO_DEVICE ldx #>EM_ERR_NO_DEVICE rts @setok: lda #0 sta pagecount stx pagecount+1 lda #<EM_ERR_OK ldx #>EM_ERR_OK rts check: ldx #0 stx GR_PAGE_LO stx GR_PAGE_HI ldy GR_WINDOW iny sta GR_PAGE_HI sty GR_WINDOW ldx #0 stx GR_PAGE_HI ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; PAGECOUNT: Return the total number of available pages in a/x. ; PAGECOUNT: lda pagecount ldx pagecount+1 rts ; ------------------------------------------------------------------------ ; USE: Tell the driver that the window is now associated with a given page. ; The GeoRAM cartridge does not copy but actually map the window, so USE is ; identical to MAP. USE = MAP ; ------------------------------------------------------------------------ ; MAP: Map the page in a/x into memory and return a pointer to the page in ; a/x. The contents of the currently mapped page (if any) may be discarded ; by the driver. ; MAP: sta tmp1 txa asl tmp1 rol a asl tmp1 rol a sta GR_PAGE_HI lda tmp1 lsr a lsr a sta GR_PAGE_LO lda #<GR_WINDOW ldx #>GR_WINDOW ; Use the RTS from COMMIT below to save a precious byte of storage ; ------------------------------------------------------------------------ ; COMMIT: Commit changes in the memory window to extended storage. COMMIT: rts ; ------------------------------------------------------------------------ ; COPYFROM: Copy from extended into linear memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYFROM: jsr setup ; Setup is: ; ; - ptr1 contains the struct pointer ; - ptr2 contains the linear memory buffer ; - ptr3 contains -(count-1) ; - tmp1 contains the low page register value ; - tmp2 contains the high page register value ; - X contains the page offset ; - Y contains zero jmp @L5 @L1: lda GR_WINDOW,x sta (ptr2),y iny bne @L2 inc ptr2+1 @L2: inx beq @L4 ; Bump count and repeat @L3: inc ptr3 bne @L1 inc ptr3+1 bne @L1 rts ; Bump page register @L4: inc tmp1 ; Bump low page register bit tmp1 ; Check for overflow in bit 6 bvc @L6 ; Jump if no overflow inc tmp2 @L5: lda tmp2 sta GR_PAGE_HI @L6: lda tmp1 sta GR_PAGE_LO jmp @L3 ; ------------------------------------------------------------------------ ; COPYTO: Copy from linear into extended memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYTO: jsr setup ; Setup is: ; ; - ptr1 contains the struct pointer ; - ptr2 contains the linear memory buffer ; - ptr3 contains -(count-1) ; - tmp1 contains the low page register value ; - tmp2 contains the high page register value ; - X contains the page offset ; - Y contains zero jmp @L5 @L1: lda (ptr2),y sta GR_WINDOW,x iny bne @L2 inc ptr2+1 @L2: inx beq @L4 ; Bump count and repeat @L3: inc ptr3 bne @L1 inc ptr3+1 bne @L1 rts ; Bump page register @L4: inc tmp1 ; Bump low page register bit tmp1 ; Check for overflow in bit 6 bvc @L6 ; Jump if no overflow inc tmp2 @L5: lda tmp2 sta GR_PAGE_HI @L6: lda tmp1 sta GR_PAGE_LO jmp @L3 ; ------------------------------------------------------------------------ ; Helper function for COPYFROM and COPYTO: Store the pointer to the request ; structure and prepare data for the copy setup: sta ptr1 stx ptr1+1 ; Save passed pointer ; Get the page number from the struct and adjust it so that it may be used ; with the hardware. That is: lower 6 bits in tmp1, high bits in tmp2. ldy #EM_COPY::PAGE+1 lda (ptr1),y sta tmp2 dey lda (ptr1),y asl a rol tmp2 asl a rol tmp2 lsr a lsr a sta tmp1 ; Get the buffer pointer into ptr2 ldy #EM_COPY::BUF lda (ptr1),y sta ptr2 iny lda (ptr1),y sta ptr2+1 ; Get the count, calculate -(count-1) and store it into ptr3 ldy #EM_COPY::COUNT lda (ptr1),y eor #$FF sta ptr3 iny lda (ptr1),y eor #$FF sta ptr3+1 ; Get the page offset into X and clear Y ldy #EM_COPY::OFFS lda (ptr1),y tax ldy #$00 ; Done rts ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/vic20/emd/vic20-rama.s�������������������������������������������������������������0000664�0000000�0000000�00000014456�13473601511�0017212�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Extended memory driver for the VIC20 $A000-$BFFF RAM. Driver works without ; problems when statically linked. ; ; Marco van den Heuvel, 2018-03-16 ; .include "zeropage.inc" .include "em-kernel.inc" .include "em-error.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _vic20_rama_emd ; Driver signature .byte $65, $6d, $64 ; "emd" .byte EMD_API_VERSION ; EM API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr PAGECOUNT .addr MAP .addr USE .addr COMMIT .addr COPYFROM .addr COPYTO ; ------------------------------------------------------------------------ ; Constants BASE = $A000 PAGES = ($C000 - BASE) / 256 ; ------------------------------------------------------------------------ ; Data. .bss curpage: .res 1 ; Current page number window: .res 256 ; Memory "window" .code ; ------------------------------------------------------------------------ ; INSTALL routine. Is called after the driver is loaded into memory. If ; possible, check if the hardware is present and determine the amount of ; memory available. ; Must return an EM_ERR_xx code in a/x. ; INSTALL: lda $A000 ; see what is at address $A000 inc $A000 ; see if it can be changed cmp $A000 ; did it stick ? beq nomem dec $A000 ldx #$FF stx curpage ; Invalidate the current page inx ; X = 0 txa ; A = X = EM_ERR_OK rts nomem: ldx #>EM_ERR_NO_DEVICE lda #<EM_ERR_NO_DEVICE ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; PAGECOUNT: Return the total number of available pages in a/x. ; PAGECOUNT: lda #<PAGES ldx #>PAGES rts ; ------------------------------------------------------------------------ ; MAP: Map the page in a/x into memory and return a pointer to the page in ; a/x. The contents of the currently mapped page (if any) may be discarded ; by the driver. ; MAP: sta curpage ; Remember the new page clc adc #>BASE sta ptr1+1 ldy #$00 sty ptr1 lda #<window sta ptr2 lda #>window sta ptr2+1 ; Transfer one page jsr transfer ; Transfer one page ; Return the memory window lda #<window ldx #>window ; Return the window address rts ; ------------------------------------------------------------------------ ; USE: Tell the driver that the window is now associated with a given page. USE: sta curpage ; Remember the page lda #<window ldx #>window ; Return the window rts ; ------------------------------------------------------------------------ ; COMMIT: Commit changes in the memory window to extended storage. COMMIT: lda curpage ; Get the current page bmi done ; Jump if no page mapped clc adc #>BASE sta ptr2+1 ldy #$00 sty ptr2 lda #<window sta ptr1 lda #>window sta ptr1+1 ; Transfer one page. Y must be zero on entry transfer: ; Unroll the following loop loop: .repeat 8 lda (ptr1),y sta (ptr2),y iny .endrepeat bne loop ; Done done: rts ; ------------------------------------------------------------------------ ; COPYFROM: Copy from extended into linear memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYFROM: sta ptr3 stx ptr3+1 ; Save the passed em_copy pointer ldy #EM_COPY::OFFS lda (ptr3),y sta ptr1 ldy #EM_COPY::PAGE lda (ptr3),y clc adc #>BASE sta ptr1+1 ; From ldy #EM_COPY::BUF lda (ptr3),y sta ptr2 iny lda (ptr3),y sta ptr2+1 ; To common: ldy #EM_COPY::COUNT+1 lda (ptr3),y ; Get number of pages beq @L2 ; Skip if no full pages sta tmp1 ; Copy full pages allowing interrupts after each page copied ldy #$00 @L1: jsr transfer inc ptr1+1 inc ptr2+1 dec tmp1 bne @L1 ; Copy the remainder of the page @L2: ldy #EM_COPY::COUNT lda (ptr3),y ; Get bytes in last page beq @L4 tax ; Transfer the bytes in the last page ldy #$00 @L3: lda (ptr1),y sta (ptr2),y iny dex bne @L3 ; Done @L4: rts ; ------------------------------------------------------------------------ ; COPYTO: Copy from linear into extended memory. A pointer to a structure ; describing the request is passed in a/x. ; The function must not return anything. ; COPYTO: sta ptr3 stx ptr3+1 ; Save the passed em_copy pointer ldy #EM_COPY::OFFS lda (ptr3),y sta ptr2 ldy #EM_COPY::PAGE lda (ptr3),y clc adc #>BASE sta ptr2+1 ; To ldy #EM_COPY::BUF lda (ptr3),y sta ptr1 iny lda (ptr3),y sta ptr1+1 ; From jmp common ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/vic20/get_tv.s���������������������������������������������������������������������0000664�0000000�0000000�00000001045�13473601511�0016062�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Stefan Haubenthal, 2018-04-10 ; Based on code by Mike ; ; unsigned char get_tv (void); ; /* Return the video mode the machine is using */ ; .include "get_tv.inc" ;-------------------------------------------------------------------------- ; _get_tv .proc _get_tv ; detect the system lda #TV::NTSC tax ldy $EDE4 ; VIC init table cpy #5 beq @L0 lda #TV::PAL @L0: rts ; system detected: 0 for NTSC, 1 for PAL .endproc �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/vic20/irq.s������������������������������������������������������������������������0000664�0000000�0000000�00000002051�13473601511�0015363�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; IRQ handling (Vic20 version) ; .export initirq, doneirq .import callirq .include "vic20.inc" ; ------------------------------------------------------------------------ .segment "ONCE" initirq: lda IRQVec ldx IRQVec+1 sta IRQInd+1 stx IRQInd+2 lda #<IRQStub ldx #>IRQStub jmp setvec ; ------------------------------------------------------------------------ .code doneirq: lda IRQInd+1 ldx IRQInd+2 setvec: sei sta IRQVec stx IRQVec+1 cli rts ; ------------------------------------------------------------------------ .segment "LOWCODE" IRQStub: cld ; Just to be sure jsr callirq ; Call the functions jmp IRQInd ; Jump to the saved IRQ vector ; ------------------------------------------------------------------------ .data IRQInd: jmp $0000 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/vic20/joy/�������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015207�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/vic20/joy/vic20-ptvjoy.s�����������������������������������������������������������0000664�0000000�0000000�00000010550�13473601511�0017650�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; PTV-3 Player joystick driver for the VIC20 ; ; Stefan Haubenthal, 2005-05-25 ; Groepaz/Hitmen, 2002-12-23 ; obviously based on Ullrichs driver :) ; Using code from Steve Schmidtke ; .include "zeropage.inc" .include "joy-kernel.inc" .include "joy-error.inc" .include "vic20.inc" .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _vic20_ptvjoy_joy ; Driver signature .byte $6A, $6F, $79 ; "joy" .byte JOY_API_VERSION ; Driver API version number ; Library reference .addr $0000 ; Jump table. .addr INSTALL .addr UNINSTALL .addr COUNT .addr READ ; ------------------------------------------------------------------------ ; Constants JOY_COUNT = 3 ; 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 ; ------------------------------------------------------------------------ ; UNINSTALL 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. ; COUNT: lda #<JOY_COUNT ldx #>JOY_COUNT rts ; ------------------------------------------------------------------------ ; READ: Read a particular joystick passed in A. ; READ: tax ; Joystick number into X bne joy2 ; Read joystick 1 joy1: lda #$7F ; mask for VIA2 JOYBIT: sw3 ldx #$C3 ; mask for VIA1 JOYBITS: sw0,sw1,sw2,sw4 sei ; necessary? ldy VIA2_DDRB ; remember the date of DDRB sta VIA2_DDRB ; set JOYBITS on this VIA for input lda VIA2_PB ; read JOYBIT: sw3 sty VIA2_DDRB ; restore the state of DDRB asl ; Shift sw3 into carry ldy VIA1_DDRA ; remember the state of DDRA stx VIA1_DDRA ; set JOYBITS on this VIA for input lda VIA1_PA1 ; read JOYBITS: sw0,sw1,sw2,sw4 sty VIA1_DDRA ; restore the state of DDRA cli ; necessary? php ; Save sw3 in carry lsr ; Shift sw0,sw1,sw2,sw4 into bits 1-4 tax ; Save sw0,sw1,sw2 and #$10 ; Extract sw4 in bit 4 sta tmp1 ; Save sw4 in bit 4 txa ; Restore sw0,sw1,sw2 lsr ; Shift sw0,sw1,sw2 into bits 0-2 and #$07 ; Mask bits 0-2 plp ; Restore sw3 in carry bcc @L0 ; Is sw3 set? ora #$08 ; Yes: Add sw3 in bit 3 @L0: ora tmp1 ; Add sw4 in bit 4 eor #$1F ; Active states are inverted ldx #0 rts ; Read joystick 2 joy2: lda #%10000000 ; via port B Data-Direction sta VIA1_DDRB ; bit 7: out bit 6-0: in dex bne joy3 lda #$80 ; via port B read/write sta VIA1_PB ; (output one at PB7) lda VIA1_PB ; via port B read/write and #$1F ; get bit 4-0 (PB4-PB0) eor #$1F rts ; Read joystick 3 joy3: lda #$00 ; via port B read/write sta VIA1_PB ; (output zero at PB7) lda VIA1_PB ; via port B read/write and #$0F ; get bit 3-0 (PB3-PB0) sta tmp1 ; joy 4 directions lda VIA1_PB ; via port B read/write and #%00100000 ; get bit 5 (PB5) lsr ora tmp1 eor #$1F ldx #0 rts ��������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/vic20/joy/vic20-stdjoy.s�����������������������������������������������������������0000664�0000000�0000000�00000007174�13473601511�0017641�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Standard joystick driver for the VIC20. May be used multiple times when linked ; to the statically application. ; ; Ullrich von Bassewitz, 2002-12-20 ; Using code from Steve Schmidtke ; .include "zeropage.inc" .include "joy-kernel.inc" .include "joy-error.inc" .include "vic20.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _vic20_stdjoy_joy ; Driver signature .byte $6A, $6F, $79 ; "joy" .byte JOY_API_VERSION ; Driver API version number ; Library reference .addr $0000 ; Jump table. .addr INSTALL .addr UNINSTALL .addr COUNT .addr READ ; ------------------------------------------------------------------------ ; Constants JOY_COUNT = 1 ; Number of joysticks we support ; ------------------------------------------------------------------------ ; Data. .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 ; ------------------------------------------------------------------------ ; UNINSTALL 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. ; COUNT: lda #<JOY_COUNT ldx #>JOY_COUNT rts ; ------------------------------------------------------------------------ ; READ: Read a particular joystick passed in A. ; The current implemenation will ignore the joystick number because we do only ; have one joystick READ: lda #$7F ; mask for VIA2 JOYBIT: sw3 ldx #$C3 ; mask for VIA1 JOYBITS: sw0,sw1,sw2,sw4 sei ; necessary? ldy VIA2_DDRB ; remember the date of DDRB sta VIA2_DDRB ; set JOYBITS on this VIA for input lda VIA2_PB ; read JOYBIT: sw3 sty VIA2_DDRB ; restore the state of DDRB asl ; Shift sw3 into carry ldy VIA1_DDRA ; remember the state of DDRA stx VIA1_DDRA ; set JOYBITS on this VIA for input lda VIA1_PA1 ; read JOYBITS: sw0,sw1,sw2,sw4 sty VIA1_DDRA ; restore the state of DDRA cli ; necessary? php ; Save sw3 in carry lsr ; Shift sw0,sw1,sw2,sw4 into bits 1-4 tax ; Save sw0,sw1,sw2 and #$10 ; Extract sw4 in bit 4 sta tmp1 ; Save sw4 in bit 4 txa ; Restore sw0,sw1,sw2 lsr ; Shift sw0,sw1,sw2 into bits 0-2 and #$07 ; Mask bits 0-2 plp ; Restore sw3 in carry bcc @L0 ; Is sw3 set? ora #$08 ; Yes: Add sw3 in bit 3 @L0: ora tmp1 ; Add sw4 in bit 4 eor #$1F ; Active states are inverted ldx #0 rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/vic20/joy_stat_stddrv.s������������������������������������������������������������0000664�0000000�0000000�00000000360�13473601511�0020013�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Address of the static standard joystick driver ; ; Oliver Schmidt, 2012-11-01 ; ; const void joy_static_stddrv[]; ; .export _joy_static_stddrv .import _vic20_stdjoy_joy .rodata _joy_static_stddrv := _vic20_stdjoy_joy ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/vic20/joy_stddrv.s�����������������������������������������������������������������0000664�0000000�0000000�00000000301�13473601511�0016753�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Name of the standard joystick driver ; ; Ullrich von Bassewitz, 2002-12-21 ; ; const char joy_stddrv[]; ; .export _joy_stddrv .rodata _joy_stddrv: .asciiz "vic20-stdjoy.joy" �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/vic20/kbhit.s����������������������������������������������������������������������0000664�0000000�0000000�00000000536�13473601511�0015677�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 06.08.1998 ; ; unsigned char kbhit (void); ; .export _kbhit .include "vic20.inc" .proc _kbhit ldx #0 ; High byte of return is always zero lda KEY_COUNT ; Get number of characters beq L9 lda #1 L9: rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/vic20/kbrepeat.s�������������������������������������������������������������������0000664�0000000�0000000�00000000474�13473601511�0016374�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; unsigned char __fastcall__ kbrepeat (unsigned char mode); ; .export _kbrepeat .include "vic20.inc" _kbrepeat: ldx KBDREPEAT ; get old value sta KBDREPEAT ; store new value txa ; return old value ldx #0 rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/vic20/kernal.s���������������������������������������������������������������������0000664�0000000�0000000�00000002345�13473601511�0016052�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 19.11.2002 ; ; VIC20 kernal functions ; .include "cbm_kernal.inc" .export CINT .export IOINIT .export RAMTAS .export RESTOR .export VECTOR .export SETMSG .export SECOND .export TKSA .export MEMTOP .export MEMBOT .export SCNKEY .export SETTMO .export ACPTR .export CIOUT .export UNTLK .export UNLSN .export LISTEN .export TALK .export READST .export SETLFS .export SETNAM .export OPEN .export CLOSE .export CHKIN .export CKOUT .export CLRCH .export BASIN .export BSOUT .export LOAD .export SAVE .export SETTIM .export RDTIM .export STOP .export GETIN .export CLALL .export UDTIM .export SCREEN .export IOBASE �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/vic20/kplot.s����������������������������������������������������������������������0000664�0000000�0000000�00000000655�13473601511�0015731�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2002-12-09 ; ; PLOT replacement function for the VIC20. The kernal function does not set ; the pointer to the color RAM correctly. ; .export PLOT .proc PLOT bcs @L1 jsr $FFF0 ; Set cursor position jmp $EAB2 ; Set pointer to color RAM @L1: jmp $FFF0 ; Get cursor position .endproc �����������������������������������������������������������������������������������cc65-2.18/libsrc/vic20/libref.s���������������������������������������������������������������������0000664�0000000�0000000�00000000270�13473601511�0016034�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2013-05-31 ; .export joy_libref .export em_libref .import _exit joy_libref := _exit em_libref := _exit ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/vic20/mainargs.s�������������������������������������������������������������������0000664�0000000�0000000�00000007765�13473601511�0016412�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; mainargs.s ; ; Ullrich von Bassewitz, 2003-03-07 ; Based on code from Stefan A. Haubenthal, <polluks@web.de> ; 2003-05-18, Greg King ; 2004-04-28, 2005-02-26, Ullrich von Bassewitz ; ; Scan a group of arguments that are in BASIC's input-buffer. ; Build an array that points to the beginning of each argument. ; Send, to main(), that array and the count of the arguments. ; ; Command-lines look like these lines: ; ; run ; run : rem ; run:rem arg1 " arg 2 is quoted " arg3 "" arg5 ; ; "run" and "rem" are entokenned; the args. are not. Leading and trailing ; spaces outside of quotes are ignored. ; ; TO-DO: ; - The "file-name" might be a path-name; don't copy the directory-components. ; - Add a control-character quoting mechanism. .constructor initmainargs, 24 .import __argc, __argv .include "vic20.inc" MAXARGS = 10 ; Maximum number of arguments allowed REM = $8f ; BASIC token-code NAME_LEN = 16 ; Maximum length of command-name ; Get possible command-line arguments. Goes into the special ONCE segment, ; which may be reused after the startup code is run .segment "ONCE" initmainargs: ; Assume that the program was loaded, a moment ago, by the traditional LOAD ; statement. Save the "most-recent filename" as argument #0. lda #0 ; The terminating NUL character ldy FNAM_LEN cpy #NAME_LEN + 1 bcc L1 ldy #NAME_LEN ; Limit the length bne L1 ; Branch always L0: lda (FNAM),y L1: sta name,y dey bpl L0 inc __argc ; argc always is equal to, at least, 1 ; Find the "rem" token. ldx #0 L2: lda BASIC_BUF,x beq done ; No "rem," no args. inx cmp #REM bne L2 ldy #1 * 2 ; Find the next argument next: lda BASIC_BUF,x beq done ; End of line reached inx cmp #' ' ; Skip leading spaces 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 ; will check now for a quoted argument, in which case we will have to skip this ; first character. found: cmp #'"' ; Is the argument quoted? beq setterm ; Jump if so dex ; Reset pointer to first argument character lda #' ' ; A space ends the argument setterm:sta term ; Set end of argument marker ; Now store a pointer to the argument into the next slot. Since the BASIC ; input buffer is located at the start of a RAM page, no calculations are ; necessary. txa ; Get low byte sta argv,y ; argv[y]= &arg iny lda #>BASIC_BUF sta argv,y iny inc __argc ; Found another arg ; Search for the end of the argument argloop:lda BASIC_BUF,x beq done inx cmp term bne argloop ; 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 #0 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? bcc 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 .segment "INIT" term: .res 1 name: .res NAME_LEN + 1 .data ; char* argv[MAXARGS+1]={name}; argv: .addr name .res MAXARGS * 2 �����������cc65-2.18/libsrc/vic20/randomize.s������������������������������������������������������������������0000664�0000000�0000000�00000001217�13473601511�0016563�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2002-11-05, Ullrich von Bassewitz ; 2015-09-11, Greg King ; ; void _randomize (void); ; /* Initialize the random number generator */ ; .export __randomize .import _srand .include "vic20.inc" __randomize: lda VIC_LINES ; Get overflow bit asl a ; Shift bit 7 into carry lda VIC_HLINE ; Get bit 1-8 of rasterline rol a ; Use bit 0-7 tax ; Use VIC rasterline as high byte lda TIME+2 ; Use 60HZ clock as low byte jmp _srand ; Initialize generator ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/vic20/revers.s���������������������������������������������������������������������0000664�0000000�0000000�00000001403�13473601511�0016076�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 07.08.1998 ; ; unsigned char revers (unsigned char onoff); ; .export _revers .include "vic20.inc" .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 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/vic20/status.s���������������������������������������������������������������������0000664�0000000�0000000�00000000134�13473601511�0016113�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Oliver Schmidt, 2012-09-30 ; .exportzp ST := $90 ; IEC status byte ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/vic20/sysuname.s�������������������������������������������������������������������0000664�0000000�0000000�00000001451�13473601511�0016437�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Ullrich von Bassewitz, 2003-08-12 ; ; unsigned char __fastcall__ _sysuname (struct utsname* buf); ; .export __sysuname, utsdata .import utscopy __sysuname = utscopy ;-------------------------------------------------------------------------- ; Data. We define a fixed utsname struct here and just copy it. .rodata utsdata: ; sysname .asciiz "cc65" ; nodename .asciiz "" ; release .byte ((.VERSION >> 8) & $0F) + '0' .byte '.' .byte ((.VERSION >> 4) & $0F) + '0' .byte $00 ; version .byte (.VERSION & $0F) + '0' .byte $00 ; machine .asciiz "Commodore VIC20" �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/vic20/waitvsync.s������������������������������������������������������������������0000664�0000000�0000000�00000000334�13473601511�0016621�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; Written by Groepaz <groepaz@gmx.net> ; ; void waitvsync (void); ; .export _waitvsync .include "vic20.inc" _waitvsync: @l2: lda VIC_HLINE bne @l2 rts ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/zlib/������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014423�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/zlib/adler32.s���������������������������������������������������������������������0000664�0000000�0000000�00000003703�13473601511�0016046�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2001-11-18, Piotr Fusik ; 2018-05-20, Christian Kruger ; ; unsigned long __fastcall__ adler32 (unsigned long adler, unsigned char* buf, ; unsigned len); ; .export _adler32 .import incsp2, incsp4, popptr1, popeax .importzp sreg, ptr1, ptr2, tmp1 BASE = 65521 ; largest prime smaller than 65536 _adler32: ; ptr2 = (len & 0xff) == 0 ? len : len + 0x100; tay beq @L1 inx @L1: sta ptr2 stx ptr2+1 ; ptr1 = buf jsr popptr1 ; if (buf == NULL) return 1L; ora ptr1+1 beq @L0 ; s1 = adler & 0xFFFF; s2 = adler >> 16; jsr popeax ; if (len == 0) return adler; ldy ptr2 bne @L2 ldy ptr2+1 beq @RET @L2: ldy #0 ; s1 += *ptr++; if (s1 >= BASE) s1 -= BASE; @L3: clc adc (ptr1),y bcc @L4 inx beq @L5 ; C flag is set @L4: cpx #>BASE bcc @L6 cmp #<BASE bcc @L6 inx ; ldx #0 @L5: sbc #<BASE ; C flag is set clc @L6: sta tmp1 ; s2 += s1; if (s2 >= BASE) s2 -= BASE; adc sreg ; C flag is clear sta sreg txa adc sreg+1 sta sreg+1 bcs @L7 cmp #>BASE bcc @L8 lda sreg cmp #<BASE bcc @L8 @L7: lda sreg sbc #<BASE ; C flag is set sta sreg lda sreg+1 sbc #>BASE sta sreg+1 @L8: lda tmp1 iny bne @L9 inc ptr1+1 @L9: dec ptr2 bne @L3 dec ptr2+1 bne @L3 ; return (s2 << 16) | s1; @RET: rts ; return 1L @L0: sta sreg sta sreg+1 tax ; (popptr1 doesn't set .X) lda #1 ; ignore adler jmp incsp4 �������������������������������������������������������������cc65-2.18/libsrc/zlib/crc32.s�����������������������������������������������������������������������0000664�0000000�0000000�00000005506�13473601511�0015531�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2001-11-14, Piotr Fusik ; 2018-05-20, Christian Kruger ; ; unsigned long __fastcall__ crc32 (unsigned long crc, unsigned char* buf, ; unsigned len); ; .export _crc32 .import compleax, incsp2, incsp4, popptr1, popeax .importzp sreg, ptr1, ptr2, tmp1, tmp2 POLYNOMIAL = $EDB88320 make_table: ldx #0 @L1: lda #0 sta tmp2 sta sreg sta sreg+1 ldy #8 txa @L2: sta tmp1 lsr a bcc @L3 lda sreg+1 lsr a eor #(POLYNOMIAL>>24)&$FF sta sreg+1 lda sreg ror a eor #(POLYNOMIAL>>16)&$FF sta sreg lda tmp2 ror a eor #(POLYNOMIAL>>8)&$FF sta tmp2 lda tmp1 ror a eor #POLYNOMIAL&$FF bcs @L4 ; branch always @L3: rol a lsr sreg+1 ror sreg ror tmp2 ror a @L4: dey bne @L2 sta table_0,x lda tmp2 sta table_1,x lda sreg sta table_2,x lda sreg+1 sta table_3,x inx bne @L1 inc table_initialised RET: rts _crc32: ; ptr2 = (len & 0xff) == 0 ? len : len + 0x100; tay beq @L1 inx @L1: sta ptr2 stx ptr2+1 ; ptr1 = buf jsr popptr1 ; if (buf == NULL) return 0; ora ptr1+1 beq @L0 ; if (!tables_initialised) make_tables(); lda table_initialised bne @dont_make jsr make_table @dont_make: ; eax = crc jsr popeax ; if (len == 0) return crc; ldy ptr2 bne @L2 ldy ptr2+1 beq RET @L2: ; eax = ~crc jsr compleax stx tmp2 ldy #0 ; crc = (crc >> 8) ^ table[(crc & 0xff) ^ *p++]; @L3: eor (ptr1),y tax lda table_0,x eor tmp2 sta tmp1 lda table_1,x eor sreg sta tmp2 lda table_2,x eor sreg+1 sta sreg lda table_3,x sta sreg+1 lda tmp1 iny bne @L4 inc ptr1+1 @L4: dec ptr2 bne @L3 dec ptr2+1 bne @L3 ldx tmp2 jmp compleax ; return 0L @L0: sta sreg sta sreg+1 tax ; (popptr1 doesn't set .X) ; ignore crc jmp incsp4 .data table_initialised: .byte 0 .bss table_0: .res 256 table_1: .res 256 table_2: .res 256 table_3: .res 256 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/zlib/inflatemem.s������������������������������������������������������������������0000664�0000000�0000000�00000035106�13473601511�0016735�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; 2017-11-07, Piotr Fusik ; ; unsigned __fastcall__ inflatemem (char* dest, const char* source); ; ; NOTE: Be extremely careful with modifications, because this code is heavily ; optimized for size (for example assumes certain register and flag values ; when its internal routines return). Test with the gunzip65 sample. ; .export _inflatemem .import incsp2 .importzp sp, sreg, ptr1, ptr2, ptr3, ptr4 ; -------------------------------------------------------------------------- ; ; Constants ; ; Argument values for getBits. GET_1_BIT = $81 GET_2_BITS = $82 GET_3_BITS = $84 GET_4_BITS = $88 GET_5_BITS = $90 GET_6_BITS = $a0 GET_7_BITS = $c0 ; Huffman trees. TREE_SIZE = 16 PRIMARY_TREE = 0 DISTANCE_TREE = TREE_SIZE ; Alphabet. LENGTH_SYMBOLS = 1+29+2 ; EOF, 29 length symbols, two unused symbols DISTANCE_SYMBOLS = 30 CONTROL_SYMBOLS = LENGTH_SYMBOLS+DISTANCE_SYMBOLS ; -------------------------------------------------------------------------- ; ; Page zero ; ; Pointer to the compressed data. inputPointer := ptr1 ; 2 bytes ; Pointer to the uncompressed data. outputPointer := ptr2 ; 2 bytes ; Local variables. ; As far as there is no conflict, same memory locations are used ; for different variables. inflateStored_pageCounter := ptr3 ; 1 byte inflateDynamic_symbol := ptr3 ; 1 byte inflateDynamic_lastLength := ptr3+1 ; 1 byte .assert ptr4 = ptr3 + 2, error, "Need three bytes for inflateDynamic_tempCodes" inflateDynamic_tempCodes := ptr3+1 ; 3 bytes inflateDynamic_allCodes := inflateDynamic_tempCodes+1 ; 1 byte inflateDynamic_primaryCodes := inflateDynamic_tempCodes+2 ; 1 byte inflateCodes_sourcePointer := ptr3 ; 2 bytes inflateCodes_lengthMinus2 := ptr4 ; 1 byte getBits_base := sreg ; 1 byte getBit_buffer := sreg+1 ; 1 byte ; -------------------------------------------------------------------------- ; ; Code ; _inflatemem: ; inputPointer = source sta inputPointer stx inputPointer+1 ; outputPointer = dest ldy #1 lda (sp),y sta outputPointer+1 dey lda (sp),y sta outputPointer ; ldy #0 sty getBit_buffer inflate_blockLoop: ; Get a bit of EOF and two bits of block type ; ldy #0 sty getBits_base lda #GET_3_BITS jsr getBits lsr a ; A and Z contain block type, C contains EOF flag ; Save EOF flag php bne inflateCompressed ; Decompress a 'stored' data block. ; ldy #0 sty getBit_buffer ; ignore bits until byte boundary jsr getWord ; skip the length we don't need jsr getWord ; get the one's complement length sta inflateStored_pageCounter bcs inflateStored_firstByte ; jmp inflateStored_copyByte: jsr getByte ; sec inflateStoreByte: jsr storeByte bcc inflateCodes_loop inflateStored_firstByte: inx bne inflateStored_copyByte inc inflateStored_pageCounter bne inflateStored_copyByte ; Block decompressed. inflate_nextBlock: plp bcc inflate_blockLoop ; Decompression complete. ; return outputPointer - dest lda outputPointer ; ldy #0 ; sec sbc (sp),y iny pha lda outputPointer+1 sbc (sp),y tax pla ; pop dest jmp incsp2 inflateCompressed: ; Decompress a Huffman-coded data block ; A=1: fixed block, initialize with fixed codes ; A=2: dynamic block, start by clearing all code lengths ; A=3: invalid compressed data, not handled in this routine eor #2 ; ldy #0 inflateCompressed_setCodeLengths: tax beq inflateCompressed_setLiteralCodeLength ; fixed Huffman literal codes: ; 144 8-bit codes ; 112 9-bit codes lda #4 cpy #144 rol a inflateCompressed_setLiteralCodeLength: sta literalSymbolCodeLength,y beq inflateCompressed_setControlCodeLength ; fixed Huffman control codes: ; 24 7-bit codes ; 6 8-bit codes ; 2 meaningless 8-bit codes ; 30 5-bit distance codes lda #5+DISTANCE_TREE cpy #LENGTH_SYMBOLS bcs inflateCompressed_setControlCodeLength cpy #24 adc #$100+2-DISTANCE_TREE inflateCompressed_setControlCodeLength: cpy #CONTROL_SYMBOLS bcs inflateCompressed_noControlSymbol sta controlSymbolCodeLength,y inflateCompressed_noControlSymbol: iny bne inflateCompressed_setCodeLengths tax beq inflateDynamic ; Decompress a block inflateCodes: jsr buildHuffmanTree inflateCodes_loop: jsr fetchPrimaryCode bcc inflateStoreByte beq inflate_nextBlock ; Copy sequence from look-behind buffer ; ldy #0 sty getBits_base cmp #9 bcc inflateCodes_setSequenceLength tya ; lda #0 cpx #1+28 bcs inflateCodes_setSequenceLength dex txa lsr a ror getBits_base inc getBits_base lsr a rol getBits_base jsr getAMinus1BitsMax8 ; sec adc #0 inflateCodes_setSequenceLength: sta inflateCodes_lengthMinus2 ldx #DISTANCE_TREE jsr fetchCode cmp #4 bcc inflateCodes_setOffsetLowByte inc getBits_base lsr a jsr getAMinus1BitsMax8 inflateCodes_setOffsetLowByte: eor #$ff sta inflateCodes_sourcePointer lda getBits_base cpx #10 bcc inflateCodes_setOffsetHighByte lda getNPlus1Bits_mask-10,x jsr getBits clc inflateCodes_setOffsetHighByte: eor #$ff ; clc adc outputPointer+1 sta inflateCodes_sourcePointer+1 jsr copyByte jsr copyByte inflateCodes_copyByte: jsr copyByte dec inflateCodes_lengthMinus2 bne inflateCodes_copyByte beq inflateCodes_loop ; jmp inflateDynamic: ; Decompress a block reading Huffman trees first ; ldy #0 ; numberOfPrimaryCodes = 257 + getBits(5) ; numberOfDistanceCodes = 1 + getBits(5) ; numberOfTemporaryCodes = 4 + getBits(4) ldx #3 inflateDynamic_getHeader: lda inflateDynamic_headerBits-1,x jsr getBits ; sec adc inflateDynamic_headerBase-1,x sta inflateDynamic_tempCodes-1,x dex bne inflateDynamic_getHeader ; Get lengths of temporary codes in the order stored in inflateDynamic_tempSymbols ; ldx #0 inflateDynamic_getTempCodeLengths: lda #GET_3_BITS jsr getBits ldy inflateDynamic_tempSymbols,x sta literalSymbolCodeLength,y ldy #0 inx cpx inflateDynamic_tempCodes bcc inflateDynamic_getTempCodeLengths ; Build the tree for temporary codes jsr buildHuffmanTree ; Use temporary codes to get lengths of literal/length and distance codes ; ldx #0 ; sec inflateDynamic_decodeLength: ; C=1: literal codes ; C=0: control codes stx inflateDynamic_symbol php ; Fetch a temporary code jsr fetchPrimaryCode ; Temporary code 0..15: put this length bpl inflateDynamic_storeLengths ; Temporary code 16: repeat last length 3 + getBits(2) times ; Temporary code 17: put zero length 3 + getBits(3) times ; Temporary code 18: put zero length 11 + getBits(7) times tax jsr getBits cpx #GET_3_BITS bcc inflateDynamic_code16 beq inflateDynamic_code17 ; sec adc #7 inflateDynamic_code17: ; ldy #0 sty inflateDynamic_lastLength inflateDynamic_code16: tay lda inflateDynamic_lastLength iny iny inflateDynamic_storeLengths: iny plp ldx inflateDynamic_symbol inflateDynamic_storeLength: bcc inflateDynamic_controlSymbolCodeLength sta literalSymbolCodeLength,x inx cpx #1 inflateDynamic_storeNext: dey bne inflateDynamic_storeLength sta inflateDynamic_lastLength beq inflateDynamic_decodeLength ; jmp inflateDynamic_controlSymbolCodeLength: cpx inflateDynamic_primaryCodes bcc inflateDynamic_storeControl ; the code lengths we skip here were zero-initialized ; in inflateCompressed_setControlCodeLength bne inflateDynamic_noStartDistanceTree ldx #LENGTH_SYMBOLS inflateDynamic_noStartDistanceTree: ora #DISTANCE_TREE inflateDynamic_storeControl: sta controlSymbolCodeLength,x inx cpx inflateDynamic_allCodes bcc inflateDynamic_storeNext dey ; ldy #0 jmp inflateCodes ; Build Huffman trees basing on code lengths (in bits) ; stored in the *SymbolCodeLength arrays buildHuffmanTree: ; Clear nBitCode_literalCount, nBitCode_controlCount tya ; lda #0 buildHuffmanTree_clear: sta nBitCode_clearFrom,y iny bne buildHuffmanTree_clear ; Count number of codes of each length ; ldy #0 buildHuffmanTree_countCodeLengths: ldx literalSymbolCodeLength,y inc nBitCode_literalCount,x bne buildHuffmanTree_notAllLiterals stx allLiteralsCodeLength buildHuffmanTree_notAllLiterals: cpy #CONTROL_SYMBOLS bcs buildHuffmanTree_noControlSymbol ldx controlSymbolCodeLength,y inc nBitCode_controlCount,x buildHuffmanTree_noControlSymbol: iny bne buildHuffmanTree_countCodeLengths ; Calculate offsets of symbols sorted by code length ; lda #0 ldx #$100-4*TREE_SIZE buildHuffmanTree_calculateOffsets: sta nBitCode_literalOffset+4*TREE_SIZE-$100,x clc adc nBitCode_literalCount+4*TREE_SIZE-$100,x inx bne buildHuffmanTree_calculateOffsets ; Put symbols in their place in the sorted array ; ldy #0 buildHuffmanTree_assignCode: tya ldx literalSymbolCodeLength,y ldy nBitCode_literalOffset,x inc nBitCode_literalOffset,x sta codeToLiteralSymbol,y tay cpy #CONTROL_SYMBOLS bcs buildHuffmanTree_noControlSymbol2 ldx controlSymbolCodeLength,y ldy nBitCode_controlOffset,x inc nBitCode_controlOffset,x sta codeToControlSymbol,y tay buildHuffmanTree_noControlSymbol2: iny bne buildHuffmanTree_assignCode rts ; Read Huffman code using the primary tree fetchPrimaryCode: ldx #PRIMARY_TREE ; Read a code from input using the tree specified in X. ; Return low byte of this code in A. ; Return C flag reset for literal code, set for length code. fetchCode: ; ldy #0 tya fetchCode_nextBit: jsr getBit rol a inx bcs fetchCode_ge256 ; are all 256 literal codes of this length? cpx allLiteralsCodeLength beq fetchCode_allLiterals ; is it literal code of length X? sec sbc nBitCode_literalCount,x bcs fetchCode_notLiteral ; literal code ; clc adc nBitCode_literalOffset,x tax lda codeToLiteralSymbol,x fetchCode_allLiterals: clc rts ; code >= 256, must be control fetchCode_ge256: ; sec sbc nBitCode_literalCount,x sec ; is it control code of length X? fetchCode_notLiteral: ; sec sbc nBitCode_controlCount,x bcs fetchCode_nextBit ; control code ; clc adc nBitCode_controlOffset,x tax lda codeToControlSymbol,x and #$1f ; make distance symbols zero-based tax ; sec rts ; Read A minus 1 bits, but no more than 8 getAMinus1BitsMax8: rol getBits_base tax cmp #9 bcs getByte lda getNPlus1Bits_mask-2,x getBits: jsr getBits_loop getBits_normalizeLoop: lsr getBits_base ror a bcc getBits_normalizeLoop rts ; Read 16 bits getWord: jsr getByte tax ; Read 8 bits getByte: lda #$80 getBits_loop: jsr getBit ror a bcc getBits_loop rts ; Read one bit, return in the C flag getBit: lsr getBit_buffer bne getBit_return pha ; ldy #0 lda (inputPointer),y inc inputPointer bne getBit_samePage inc inputPointer+1 getBit_samePage: sec ror a sta getBit_buffer pla getBit_return: rts ; Copy a previously written byte copyByte: ldy outputPointer lda (inflateCodes_sourcePointer),y ldy #0 ; Write a byte storeByte: ; ldy #0 sta (outputPointer),y inc outputPointer bne storeByte_return inc outputPointer+1 inc inflateCodes_sourcePointer+1 storeByte_return: rts ; -------------------------------------------------------------------------- ; ; Constant data ; .rodata getNPlus1Bits_mask: .byte GET_1_BIT,GET_2_BITS,GET_3_BITS,GET_4_BITS,GET_5_BITS,GET_6_BITS,GET_7_BITS inflateDynamic_tempSymbols: .byte GET_2_BITS,GET_3_BITS,GET_7_BITS,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 inflateDynamic_headerBits: .byte GET_4_BITS,GET_5_BITS,GET_5_BITS inflateDynamic_headerBase: .byte 3,LENGTH_SYMBOLS,0 ; -------------------------------------------------------------------------- ; ; Uninitialised data ; .bss ; Data for building trees. literalSymbolCodeLength: .res 256 controlSymbolCodeLength: .res CONTROL_SYMBOLS ; Huffman trees. nBitCode_clearFrom: nBitCode_literalCount: .res 2*TREE_SIZE nBitCode_controlCount: .res 2*TREE_SIZE nBitCode_literalOffset: .res 2*TREE_SIZE nBitCode_controlOffset: .res 2*TREE_SIZE allLiteralsCodeLength: .res 1 codeToLiteralSymbol: .res 256 codeToControlSymbol: .res CONTROL_SYMBOLS ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/libsrc/zlib/uncompress.c������������������������������������������������������������������0000664�0000000�0000000�00000002377�13473601511�0016776�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** uncompress.c ** ** Piotr Fusik, 18.11.2001 */ #include <zlib.h> int __fastcall__ uncompress (char* dest, unsigned* destLen, const char* source, unsigned sourceLen) { unsigned len; unsigned char* ptr; unsigned long csum; /* source[0]: Compression method and flags bits 0 to 3: Compression method (must be Z_DEFLATED) bits 4 to 7: Compression info (must be <= 7) source[1]: Flags bits 0 to 4: Check bits bit 5: Preset dictionary (not supported, sorry) bits 6 to 7: Compression level */ if ((source[0] & 0x8f) != Z_DEFLATED || source[1] & 0x20) return Z_DATA_ERROR; if ((((unsigned) source[0] << 8) | (unsigned char) source[1]) % 31) return Z_DATA_ERROR; *destLen = len = inflatemem(dest, source + 2); ptr = (unsigned char*) source + sourceLen - 4; csum = adler32(adler32(0L, Z_NULL, 0), dest, len); if ((unsigned char) csum != ptr[3] || (unsigned char) (csum >> 8) != ptr[2] || (unsigned char) (csum >> 16) != ptr[1] || (unsigned char) (csum >> 24) != ptr[0]) return Z_DATA_ERROR; return Z_OK; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/����������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0013651�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/Makefile��������������������������������������������������������������������������0000664�0000000�0000000�00000024222�13473601511�0015313�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# # Makefile for cc65 samples # # This Makefile requires GNU make # # Run 'make SYS=<target>'; or, set a SYS env. # var. to build for another target system. SYS ?= c64 # Just the usual way to define a variable # containing a single space character. SPACE := SPACE += # Just the usual way to find out if we're # using cmd.exe to execute make rules. ifneq ($(shell echo),) CMD_EXE = 1 endif ifdef CMD_EXE NULLDEV = nul: DEL = -del /f RMDIR = rmdir /s /q else NULLDEV = /dev/null DEL = $(RM) RMDIR = $(RM) -r endif ifdef CC65_HOME AS = $(CC65_HOME)/bin/ca65 CC = $(CC65_HOME)/bin/cc65 CL = $(CC65_HOME)/bin/cl65 LD = $(CC65_HOME)/bin/ld65 else AS := $(if $(wildcard ../bin/ca65*),../bin/ca65,ca65) CC := $(if $(wildcard ../bin/cc65*),../bin/cc65,cc65) CL := $(if $(wildcard ../bin/cl65*),../bin/cl65,cl65) LD := $(if $(wildcard ../bin/ld65*),../bin/ld65,ld65) endif ifneq ($(filter disk samples.%,$(MAKECMDGOALS)),) ifdef CC65_HOME TARGET_PATH = $(CC65_HOME)/target else TARGET_PATH := $(if $(wildcard ../target),../target,$(shell $(CL) --print-target-path)) endif # If TARGET_PATH contains spaces then it is presumed to contain escaped spaces. GNU make # has very limited support for paths containing spaces. $(wildcard) is the only function # that is aware of escaped spaces. However, $(wildcard) never returns paths with escaped # spaces !!! So if it e.g. finds 4 files in a path with 2 spaces then one ends up with a # return value consisting of 12 plain words :-(( # # Fortunately we can work around that behaviour here because we know that the files we # are looking for have known extensions. So we can $(filter) the in our example above 12 # words for file extensions so we come up with 4 path fragments. Then we remove those # path fragments with $(notdir) from the file names. # # So far so good. But here we want to process files from different paths in a single # recipe further down below and therefore want to prepend the paths to the files with # $(addprefix). However, $(foreach) isn't aware of escaped spaces (only $(wildcard) is). # Therefore, we need to replace the spaces with some other character temporarily in order # to have $(foreach) generate one invocation per file. We use the character '?' for that # purpose here, just because it is known to not be part of file names. # # Inside the recipe generated per file we then replace the '?' again with a space. As we # want to be compatible with cmd.exe for execution we're not using an escaped space but # rather double-quote the whole path. # # Note: The "strange" $(wildcard) further down below just serves the purpose to unescape # spaces for cmd.exe. This could have as well been done with another $(subst). SUBST_TARGET_PATH := $(subst \$(SPACE),?,$(TARGET_PATH)) EMD := $(wildcard $(TARGET_PATH)/$(SYS)/drv/emd/*) MOU := $(wildcard $(TARGET_PATH)/$(SYS)/drv/mou/*) TGI := $(wildcard $(TARGET_PATH)/$(SYS)/drv/tgi/*) EMD := $(addprefix $(SUBST_TARGET_PATH)/$(SYS)/drv/emd/,$(notdir $(filter %.emd,$(EMD)))) MOU := $(addprefix $(SUBST_TARGET_PATH)/$(SYS)/drv/mou/,$(notdir $(filter %.mou,$(MOU)))) TGI := $(addprefix $(SUBST_TARGET_PATH)/$(SYS)/drv/tgi/,$(notdir $(filter %.tgi,$(TGI)))) # This one comes with the VICE emulator. # See http://vice-emu.sourceforge.net/ C1541 ?= c1541 # For this one, see https://applecommander.github.io/ AC ?= ac.jar # For this one, see http://www.horus.com/~hias/atari/ DIR2ATR ?= dir2atr DISK_c64 = samples.d64 DISK_apple2 = samples.dsk DISK_apple2enh = samples.dsk DISK_atari = samples.atr DISK_atarixl = samples.atr endif # -------------------------------------------------------------------------- # System-dependent settings # For convenience, these groups and lines are sorted alphabetically, first # by target-machine group, then by mission, then by program and sub-target. # The Apple machines need the start address adjusted when using TGI LDFLAGS_mandelbrot_apple2 = --start-addr 0x4000 LDFLAGS_mandelbrot_apple2enh = --start-addr 0x4000 LDFLAGS_tgidemo_apple2 = --start-addr 0x4000 LDFLAGS_tgidemo_apple2enh = --start-addr 0x4000 # The Apple ][ needs the start address adjusted for the mousedemo LDFLAGS_mousedemo_apple2 = --start-addr 0x4000 # The Apple machines need the end address adjusted for large programs LDFLAGS_gunzip65_apple2 = -D __HIMEM__=0xBF00 LDFLAGS_gunzip65_apple2enh = -D __HIMEM__=0xBF00 # The atari target needs to reserve some memory when using TGI LDFLAGS_mandelbrot_atari = -D __RESERVED_MEMORY__=0x2000 LDFLAGS_tgidemo_atari = -D __RESERVED_MEMORY__=0x2000 # The atarixl target needs the start address adjusted when using TGI LDFLAGS_mandelbrot_atarixl = --start-addr 0x4000 LDFLAGS_tgidemo_atarixl = --start-addr 0x4000 # -------------------------------------------------------------------------- # Generic rules .PHONY: all mostlyclean clean install zip samples disk %: %.c %: %.s .c.o: $(CC) $(CFLAGS) -Ors --codesize 500 -T -g -t $(SYS) $< $(AS) $(<:.c=.s) .s.o: $(AS) $(ASFLAGS) -t $(SYS) $< .PRECIOUS: %.o .o: ifeq ($(SYS),vic20) $(LD) $(LDFLAGS_$(@F)_$(SYS)) $(LDFLAGS) -o $@ -C vic20-32k.cfg -m $@.map $^ $(SYS).lib else $(LD) $(LDFLAGS_$(@F)_$(SYS)) $(LDFLAGS) -o $@ -t $(SYS) -m $@.map $^ $(SYS).lib endif # -------------------------------------------------------------------------- # Lists of executables EXELIST_c64 = \ ascii \ enumdevdir \ fire \ gunzip65 \ hello \ mandelbrot \ mousedemo \ multdemo \ nachtm \ ovrldemo \ plasma \ sieve \ tgidemo EXELIST_apple2 = \ ascii \ diodemo \ enumdevdir \ gunzip65 \ hello \ mandelbrot \ mousedemo \ multdemo \ ovrldemo \ sieve \ tgidemo EXELIST_apple2enh = $(EXELIST_apple2) EXELIST_atari = \ ascii \ gunzip65 \ hello \ mandelbrot \ mousedemo \ multdemo \ ovrldemo \ sieve \ tgidemo EXELIST_atarixl = $(EXELIST_atari) EXELIST_atari2600 = \ atari2600hello # Unlisted targets will try to build everything. # That lets us learn what they cannot build, and what settings # we need to use for programs that can be built and run. ifndef EXELIST_$(SYS) EXELIST_$(SYS) := ${patsubst %.c,%,$(wildcard *.c)} endif # -------------------------------------------------------------------------- # Rules to make the binaries and the disk samples: $(EXELIST_$(SYS)) disk: $(DISK_$(SYS)) all: # -------------------------------------------------------------------------- # Overlay rules. Overlays need special ld65 configuration files. Also, the # overlay file-names are shortenned to fit the Atari's 8.3-character limit. multdemo: multidemo.o $(LD) $(LDFLAGS) -o $@ -C $(SYS)-overlay.cfg -m $@.map $^ $(SYS).lib ovrldemo: overlaydemo.o $(LD) $(LDFLAGS) -o $@ -C $(SYS)-overlay.cfg -m $@.map $^ $(SYS).lib OVERLAYLIST := $(foreach I,1 2 3,multdemo.$I ovrldemo.$I) # -------------------------------------------------------------------------- # Rule to make a CBM disk with all samples. Needs the c1541 program that comes # with the VICE emulator. define D64_WRITE_recipe $(C1541) -attach $@ -write "$(subst ?,$(SPACE),$(file))" $(notdir $(file)) >$(NULLDEV) endef # D64_WRITE_recipe samples.d64: samples @$(C1541) -format samples,AA d64 $@ >$(NULLDEV) $(foreach file,$(EXELIST_$(SYS)),$(D64_WRITE_recipe)) $(foreach file,$(OVERLAYLIST),$(D64_WRITE_recipe)) $(foreach file,$(EMD) $(MOU) $(TGI),$(D64_WRITE_recipe)) # -------------------------------------------------------------------------- # Rule to make an Apple II disk with all samples. Needs the AppleCommander # program, available at https://applecommander.github.io/, and a template disk # named 'prodos.dsk'. define DSK_WRITE_BIN_recipe $(if $(findstring BF00,$(LDFLAGS_$(notdir $(file))_$(SYS))), \ java -jar $(AC) -p $@ $(notdir $(file)).system sys <"$(wildcard $(TARGET_PATH)/$(SYS)/util/loader.system)") java -jar $(AC) -as $@ $(notdir $(file)) <"$(file)" endef # DSK_WRITE_BIN_recipe define DSK_WRITE_REL_recipe java -jar $(AC) -p $@ $(notdir $(file)) rel 0 <"$(subst ?,$(SPACE),$(file))" endef # DSK_WRITE_REL_recipe samples.dsk: samples cp prodos.dsk $@ $(foreach file,$(EXELIST_$(SYS)),$(DSK_WRITE_BIN_recipe)) $(foreach file,$(OVERLAYLIST),$(DSK_WRITE_REL_recipe)) $(foreach file,$(EMD) $(MOU) $(TGI),$(DSK_WRITE_REL_recipe)) # -------------------------------------------------------------------------- # Rule to make an Atari disk with all samples. Needs the dir2atr program # available at http://www.horus.com/~hias/atari/ and the MyDos4534 variant # of dos.sys and dup.sys. define ATR_WRITE_recipe cp "$(subst ?,$(SPACE),$(file))" atr/$(notdir $(file)) endef # ATR_WRITE_recipe samples.atr: samples @mkdir atr cp "dos.sys" atr/dos.sys cp "dup.sys" atr/dup.sys @$(foreach file,$(EXELIST_$(SYS)),$(ATR_WRITE_recipe)) @$(foreach file,$(OVERLAYLIST),$(ATR_WRITE_recipe)) @$(foreach file,$(EMD) $(MOU) $(TGI),$(ATR_WRITE_recipe)) $(DIR2ATR) -d -b MyDos4534 3200 $@ atr @$(RMDIR) atr # -------------------------------------------------------------------------- # Installation rules INSTALL = install samplesdir = $(PREFIX)/share/cc65/samples install: $(if $(PREFIX),,$(error variable "PREFIX" must be set)) $(INSTALL) -d $(DESTDIR)$(samplesdir) $(INSTALL) -d $(DESTDIR)$(samplesdir)/geos $(INSTALL) -d $(DESTDIR)$(samplesdir)/tutorial $(INSTALL) -m0644 *.* $(DESTDIR)$(samplesdir) $(INSTALL) -m0644 README $(DESTDIR)$(samplesdir) $(INSTALL) -m0644 Makefile $(DESTDIR)$(samplesdir) $(INSTALL) -m0644 geos/*.* $(DESTDIR)$(samplesdir)/geos $(INSTALL) -m0644 tutorial/*.* $(DESTDIR)$(samplesdir)/tutorial # -------------------------------------------------------------------------- # Packaging rules zip: @cd .. && zip -r cc65 samples/ # -------------------------------------------------------------------------- # Clean-up rules mostlyclean: @$(DEL) *.lbl *.map *.o *.s 2>$(NULLDEV) clean: mostlyclean @$(DEL) $(EXELIST_$(SYS)) $(DISK_$(SYS)) 2>$(NULLDEV) @$(DEL) multdemo.? ovrldemo.? 2>$(NULLDEV) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/README����������������������������������������������������������������������������0000664�0000000�0000000�00000013427�13473601511�0014540�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ This directory contains sample programs for the cc65 compiler. Below is a short description for each of the programs together with a list of the supported platforms. Please note: * The supplied makefile needs GNU make. It works out of the box on Linux and similar systems. If you're using Windows, consider installing Cygwin. * The makefile specifies the C64 as the default target system, because all but one of the programs run on this platform. When compiling for another system, you will have to change the line that specifies the target system at the top of the makefile, specify the system with SYS=<target> on the make command line or set a SYS env var. List of supplied sample programs: ----------------------------------------------------------------------------- Name: ascii Description: Shows the ASCII (or ATASCII, PETSCII) codes of typed characters. Written and contributed by Greg King <gngking@erols.com>. Platforms: All platforms with conio or stdio (compile time configurable). ----------------------------------------------------------------------------- Name: diodemo Description: A disc copy program written and contributed by Oliver Schmidt, <ol.sc@web.de>. Supports single or dual disc copy. Platforms: The program does depend on conio and dio (direct disk i/o), so it does currently compile for the Atari and Apple ][ machines. ----------------------------------------------------------------------------- Name: enumdevdir Description: Enumerates all devices, directories and files. Written and contributed by Oliver Schmidt, <ol.sc@web.de>. Platforms: All systems with device enumeration and directory access (currently the C64, the C128 and the Apple ][). ----------------------------------------------------------------------------- Name: fire Description: Another graphics demo written by groepaz/hitmen. Platforms: The program is currently only running on the C64, but should be portable to the C128 and CBM510 (and maybe more machines). ----------------------------------------------------------------------------- Name: gunzip65 Description: A gunzip utility for 6502 based machines written by Piotr Fusik <fox@scene.pl>. Platforms: Runs on all platforms with file I/O (currently the Atari, the Apple ][ and most Commodore machines). ----------------------------------------------------------------------------- Name: hello Description: A nice "Hello world" type program that uses the conio console I/O library for output. Platforms: Runs on all platforms that support conio, which means: Apple ][, Atari, C16, C64, C128, CBM510, CBM610, PET, Plus/4 ----------------------------------------------------------------------------- Name: mandelbrot Description: A mandelbrot demo using integer arithmetic. The demo was written by groepaz/hitmen and converted to cc65 using TGI graphics by Stephan Haubenthal. Platforms: Runs on all platforms that have TGI support: Apple ][, C64, C128, Oric Atmos, Geos and Lynx. ----------------------------------------------------------------------------- Name: mousedemo Description: Shows how to use the mouse. Platforms: All systems with mouse and conio support: C64, C128, CBM510, Atari, Apple ][ ----------------------------------------------------------------------------- Name: multidemo Description: Shows how to combine multiple cc65 features incl. overlays and extended memory drivers. Written and contributed by Oliver Schmidt, <ol.sc@web.de>. Platforms: All systems with an overlay linker config, disk directory access and EMD support (currently the C64, the C128, the Atari and the Apple ][). ----------------------------------------------------------------------------- Name: nachtm Description: Plays "Eine kleine Nachtmusik" by Wolfgang Amadeus Mozart Platforms: All systems that have the Commodore SID (Sound Interface Device): C64, C128, CBM510, CBM610 ----------------------------------------------------------------------------- Name: overlaydemo Description: Shows how to load overlay files from disk. Written and contributed by Oliver Schmidt, <ol.sc@web.de>. Platforms: All systems with an overlay linker config (currently the C64, the C128, the Atari and the Apple ][). ----------------------------------------------------------------------------- Name: plasma Description: A fancy graphics demo written by groepaz/hitmen. Platforms: The program needs a VIC, or a TED, so it runs on the following systems: C64, C128, CBM510, Plus/4 ----------------------------------------------------------------------------- Name: sieve Description: Implements the "Sieve of Eratosthenes" as a way to find all prime numbers in a specific number interval. Often used as a benchmark program. Platforms: All systems with conio and clock support: Atari, C16, C64, C128, CBM510, CBM610, PET, Plus/4, Apple ][ (without timing due to missing clock support) ----------------------------------------------------------------------------- Name: tgidemo Description: Shows some of the graphics capabilities of the "tiny graphics interface". Platforms: Runs on all platforms that have TGI support: Apple ][, C64, C128, Oric Atmos, Geos and Lynx. �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/ascii.c���������������������������������������������������������������������������0000664�0000000�0000000�00000004410�13473601511�0015104�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ascii.c ** ** Shows the ASCII (or ATASCII, PETSCII) codes of typed characters. ** ** 2003-03-09, Greg King <gngking@erols.com> */ /* Define USE_STDIO, when you want to use the stdio functions. ** Do not define it, when you want to use the conio functions. ** NOTE: stdin on some targets is line-bufferred. You might need to type ** a key, then tap the return(enter)-key, in order to see each code. */ /* #define USE_STDIO */ #include <conio.h> #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #define QUIT 'Q' /* r -- row. t -- table-column. */ static unsigned char height, width, r, t; static int c; #ifndef USE_STDIO # define PRINT cprintf # define PUT(c) cputc((char)(c)) /* conio doesn't echo typed characters. ** So, this function does it. */ static int GET(void) { PUT(c = (int)cgetc()); return c; } #else # define PRINT printf # define GET getchar #endif int main(void) { # ifndef USE_STDIO /* conio doesn't scroll! Avoid trouble by starting at the top ** of the screen, and never going "below" the bottom of the screen. */ clrscr(); r = 7; /* allow for prompt */ # endif /* This prompt fits on the VIC-20's narrow screen. */ PRINT("Type characters to see\r\ntheir hexadecimal code\r\nnumbers - 'Q' quits:\r\n\n"); screensize(&width, &height); /* get the screen's dimensions */ width /= 6; /* get number of codes on a line */ cursor(true); t = 0; while ((c = GET()) != EOF) { # ifndef USE_STDIO if (r == height) { clrscr(); t = 0; PUT(c); /* echo char. again because screen was erased */ r = 1; } if (c == '\n') ++r; # endif PRINT("=$%02x ", c); if (c == QUIT) break; if (++t == width) { PRINT("\r\n"); ++r; t = 0; } } PRINT("\r\n"); return EXIT_SUCCESS; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/atari2600hello.c������������������������������������������������������������������0000664�0000000�0000000�00000003602�13473601511�0016452�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* Atari VCS 2600 sample C program */ /* */ /* Florent Flament (contact@florentflament.com), 2017 */ /* */ /*****************************************************************************/ #include <atari2600.h> // PAL Timings // Roughly computed based on Stella Programmer's guide (Steve Wright) // scanlines count per section. #define VBLANK_TIM64 51 // 45 lines * 76 cycles/line / 64 cycles/tick #define KERNAL_T1024 17 // 228 lines * 76 cycles/line / 1024 cycles/tick #define OVERSCAN_TIM64 42 // 36 lines * 76 cycles/line / 64 cycles/tick // Testing memory zones const unsigned char rodata_v[] = "Hello!"; unsigned char data_v = 0x77; unsigned char bss_v; void main(void) { unsigned char color = 0x79; // Stack variable bss_v = 0x88; // Testing BSS variable for/*ever*/(;;) { // Vertical Sync signal TIA.vsync = 0x02; TIA.wsync = 0x00; TIA.wsync = 0x00; TIA.wsync = 0x00; TIA.vsync = 0x00; // Vertical Blank timer setting RIOT.tim64t = VBLANK_TIM64; // Doing frame computation during blank TIA.colubk = color++; // Update color // Wait for end of Vertical Blank while (RIOT.timint == 0) {} TIA.wsync = 0x00; TIA.vblank = 0x00; // Turn on beam // Display frame RIOT.t1024t = KERNAL_T1024; while (RIOT.timint == 0) {} TIA.wsync = 0x00; TIA.vblank = 0x02; // Turn off beam // Overscan RIOT.tim64t = OVERSCAN_TIM64; while (RIOT.timint == 0) {} } } ������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/diodemo.c�������������������������������������������������������������������������0000664�0000000�0000000�00000020015�13473601511�0015433�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* diodemo.c */ /* */ /* Direct Disk I/O Demo Program */ /* */ /* */ /* */ /* (C) Copyright 2005, Oliver Schmidt, <ol.sc@web.de> */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stddef.h> #include <stdlib.h> #include <limits.h> #include <conio.h> #include <ctype.h> #include <errno.h> #include <cc65.h> #include <dio.h> #define MAX_CHUNKS 10 /* Maximum acceptable number of chunks */ static unsigned char ScreenX; static unsigned char ScreenY; static void ClearLine (void) /* Clear the screen line the cursor is on */ { cputc ('\r'); cclear (ScreenX); } static unsigned char AskForDrive (const char* Name) /* Ask for a drive id and return it */ { unsigned char Drive = 0; char Char; cprintf ("\r\n%s Drive ID ? ", Name); cursor (1); do { Char = cgetc (); if (isdigit (Char)) { cputc (Char); Drive = Drive * 10 + Char - '0'; } } while (Char != CH_ENTER); cursor (0); return Drive; } static void AskForDisk (const char* Name, unsigned char Drive) /* Ask the user to insert a specific disk */ { ClearLine (); cprintf ("\rInsert %s Disk into Drive %d !", Name, Drive); cgetc (); } static char* AllocBuffer (unsigned int SectSize, unsigned int SectCount, unsigned int* ChunkCount) /* Allocate a copy buffer on the heap and return a pointer to it */ { char* Buffer = NULL; unsigned long BufferSize; unsigned int Chunks = 1; /* Increase number of chunks resp. decrease size */ /* of one chunk until buffer allocation succeeds */ do { *ChunkCount = (unsigned int) ((SectCount + Chunks - 1) / Chunks); BufferSize = *ChunkCount * (unsigned long) SectSize; if (BufferSize < UINT_MAX) { Buffer = malloc ((size_t) BufferSize); } } while (Buffer == NULL && ++Chunks <= MAX_CHUNKS); return Buffer; } int main (int argc, const char* argv[]) { unsigned char SourceId; unsigned char TargetId; dhandle_t Source = NULL; dhandle_t Target = NULL; unsigned int SectSize; unsigned int SectCount; char* Buffer; unsigned int Sector; unsigned int ChunkCount; unsigned int ChunkOffset = 0; clrscr (); screensize (&ScreenX, &ScreenY); /* Allow user to read exit messages */ if (doesclrscrafterexit ()) { atexit ((void (*)) cgetc); } cputs ("Floppy Disk Copy\r\n"); chline (16); cputs ("\r\n"); /* Get source and target drive id (which may very well be identical) */ switch (argc) { case 1: SourceId = AskForDrive ("Source"); TargetId = AskForDrive ("Target"); cputs ("\r\n"); break; case 2: SourceId = TargetId = atoi (argv[1]); break; case 3: SourceId = atoi (argv[1]); TargetId = atoi (argv[2]); break; default: cprintf ("\r\nToo many arguments\r\n"); return EXIT_FAILURE; } cputs ("\r\n"); do { /* Check for single drive copy or inital iteration */ if (SourceId == TargetId || Source == NULL) { AskForDisk ("Source", SourceId); } /* Check for initial iteration */ if (Source == NULL) { /* Open source drive */ Source = dio_open (SourceId); if (Source == NULL) { cprintf ("\r\n\nError %d on opening Drive %d\r\n", (int) _oserror, SourceId); return EXIT_FAILURE; } SectSize = dio_query_sectsize (Source); SectCount = dio_query_sectcount (Source); /* Allocate buffer */ Buffer = AllocBuffer (SectSize, SectCount, &ChunkCount); if (Buffer == NULL) { cputs ("\r\n\nError on allocating Buffer\r\n"); return EXIT_FAILURE; } } ClearLine (); /* Read one chunk of sectors into buffer */ for (Sector = ChunkOffset; Sector < SectCount && (Sector - ChunkOffset) < ChunkCount; ++Sector) { cprintf ("\rReading Sector %d of %d", Sector + 1, SectCount); /* Read one sector */ if (dio_read (Source, Sector, Buffer + (Sector - ChunkOffset) * SectSize) != 0) { cprintf ("\r\n\nError %d on reading from Drive %d\r\n", (int) _oserror, SourceId); return EXIT_FAILURE; } } /* Check for single drive copy or inital iteration */ if (TargetId == SourceId || Target == NULL) { AskForDisk ("Target", TargetId); } /* Open target drive on initial iteration */ if (Target == NULL) { Target = dio_open (TargetId); if (Target == NULL) { cprintf ("\r\n\nError %d on opening Drive %d\r\n", (int) _oserror, TargetId); return EXIT_FAILURE; } /* Check for compatible drives */ if (dio_query_sectsize (Target) != SectSize || dio_query_sectcount (Target) != SectCount) { cputs ("\r\n\nFormat mismatch between Drives\r\n"); return EXIT_FAILURE; } } ClearLine (); /* Write one chunk of sectors from buffer */ for (Sector = ChunkOffset; Sector < SectCount && (Sector - ChunkOffset) < ChunkCount; ++Sector) { cprintf ("\rWriting Sector %d of %d", Sector + 1, SectCount); /* Write one sector */ if (dio_write (Target, Sector, Buffer + (Sector - ChunkOffset) * SectSize) != 0) { cprintf ("\r\n\nError %d on writing to Drive %d\r\n", (int) _oserror, TargetId); return EXIT_FAILURE; } } /* Advance to next chunk */ ChunkOffset += ChunkCount; } while (Sector < SectCount); ClearLine (); cprintf ("\rSuccessfully copied %d Sectors\r\n", SectCount); free (Buffer); dio_close (Source); dio_close (Target); return EXIT_SUCCESS; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/enumdevdir.c����������������������������������������������������������������������0000664�0000000�0000000�00000004704�13473601511�0016164�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** Enumerate devices, directories and files. ** ** 2012-10-15, Oliver Schmidt (ol.sc@web.de) ** */ #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <device.h> #include <dirent.h> #include <cc65.h> void printdir (char *newdir) { char olddir[FILENAME_MAX]; char curdir[FILENAME_MAX]; DIR *dir; struct dirent *ent; char *subdirs = NULL; unsigned dirnum = 0; unsigned num; getcwd (olddir, sizeof (olddir)); if (chdir (newdir)) { /* If chdir() fails we just print the ** directory name - as done for files. */ printf (" Dir %s\n", newdir); return; } /* We call getcwd() in order to print the ** absolute pathname for a subdirectory. */ getcwd (curdir, sizeof (curdir)); printf (" Dir %s:\n", curdir); /* Calling opendir() always with "." avoids ** fiddling around with pathname separators. */ dir = opendir ("."); while (ent = readdir (dir)) { if (_DE_ISREG (ent->d_type)) { printf (" File %s\n", ent->d_name); continue; } /* We defer handling of subdirectories until we're done with the ** current one as several targets don't support other disk i/o ** while reading a directory (see cc65 readdir() doc for more). */ if (_DE_ISDIR (ent->d_type)) { subdirs = realloc (subdirs, FILENAME_MAX * (dirnum + 1)); strcpy (subdirs + FILENAME_MAX * dirnum++, ent->d_name); } } closedir (dir); for (num = 0; num < dirnum; ++num) { printdir (subdirs + FILENAME_MAX * num); } free (subdirs); chdir (olddir); } void main (void) { unsigned char device; char devicedir[FILENAME_MAX]; /* Calling getfirstdevice()/getnextdevice() does _not_ turn on the motor ** of a drive-type device and does _not_ check for a disk in the drive. */ device = getfirstdevice (); while (device != INVALID_DEVICE) { printf ("Device %d:\n", device); /* Calling getdevicedir() _does_ check for a (formatted) disk in a ** floppy-disk-type device and returns NULL if that check fails. */ if (getdevicedir (device, devicedir, sizeof (devicedir))) { printdir (devicedir); } else { printf (" N/A\n"); } device = getnextdevice (device); } if (doesclrscrafterexit ()) { getchar (); } } ������������������������������������������������������������cc65-2.18/samples/fire.c����������������������������������������������������������������������������0000664�0000000�0000000�00000015411�13473601511�0014744�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************\ ** fire test program for cc65. ** ** ** ** (w)2002 by groepaz/hitmen ** ** ** ** Cleanup and porting by Ullrich von Bassewitz. ** ** 2004-06-08, Greg King ** ** ** \*****************************************************************************/ /* sync page-flipping to vertical blank */ /* #define DOVSYNC */ #include <stdlib.h> #include <string.h> /* for memset */ #include <time.h> #include <conio.h> #include <cbm.h> #if defined(__C64__) # define BUFFER 0x0400 # define SCREEN1 0xE000 # define SCREEN2 0xE400 # define CHARSET 0xE800 # define COLORRAM 0xD800 # define outb(addr,val) (*(addr) = (val)) # define inb(addr) (*(addr)) #elif defined(__C128__) # define BUFFER 0x0400 # define SCREEN1 0xE000 # define SCREEN2 0xE400 # define CHARSET 0xE800 # define COLORRAM 0xD800 # define outb(addr,val) (*(addr) = (val)) # define inb(addr) (*(addr)) #elif defined(__CBM510__) # define BUFFER 0xF800 # define SCREEN1 0xF000 # define SCREEN2 0xF400 # define CHARSET 0xE000 # define COLORRAM 0xD400 # define outb(addr,val) pokebsys ((unsigned)(addr), val) # define inb(addr) peekbsys ((unsigned)(addr)) #endif /* Values for the VIC address register to switch between the two pages */ #define PAGE1 ((SCREEN1 >> 6) & 0xF0) | ((CHARSET >> 10) & 0x0E) #define PAGE2 ((SCREEN2 >> 6) & 0xF0) | ((CHARSET >> 10) & 0x0E) /* Use static local variables for speed */ #pragma static-locals (1); #ifdef DOVSYNC # define WAITVSYNC() waitvsync() #else # define WAITVSYNC() #endif static void makechar (void) { static const unsigned char bittab[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; register char *font; register unsigned char i, ii, b, bc; unsigned char c; gotoxy (0, 1); for (font = (char*)CHARSET; font != (char*)(CHARSET+(1*8)); ++font) { *font = 0x00; } for (font = (char*)(CHARSET+(64*8)); font != (char*)(CHARSET+(256*8)); ++font) { *font = 0xff; } for (c = 0; c < 0x40; ++c) { bc = 0; for (i = 0; i < 8; i++){ b = 0; for (ii = 0; ii < 8; ii++) { bc += c; if (bc > 0x3f) { bc = bc - 0x40; b += bittab[(ii + (i & 1)) & 0x7]; } } ((unsigned char*)CHARSET + (1 * 8)) [(c * 8) + i] = b; } if ((c & 0x07) == 0) { cputc ('.'); } } } static void fire (unsigned screenbase) { register char* screen; register char* buffer; register char c; screen = (char*) screenbase; buffer = (char*) BUFFER; while (buffer != (char*) (BUFFER + (24 * 40))) { c = (buffer[40-1] + buffer[40-1] + buffer[40] + buffer[41]) / 4; if (c > 2) { c -= 3; } *screen = *buffer = c; ++screen; ++buffer; } screen = (char*) (screenbase + (23 * 40)); buffer = (char*) (BUFFER + (23 * 40)); for(; buffer != (char*)(BUFFER+(25*40)); ++screen, ++buffer) { *screen = *buffer = 0x30 + (inb (&SID.noise) >> 4); } } int main (void) { unsigned char border; unsigned char background; unsigned char text; unsigned char v; clock_t t; unsigned long f = 0; unsigned long sec; unsigned sec10; unsigned long fps; unsigned fps10; int i; #if defined(__C64__) unsigned char block; #endif #if defined(__C128__) unsigned char block; unsigned char initflag; unsigned char graphflag; #endif /* Noise on channel 3 for random numbers */ outb (&SID.v3.freq, 0xffff); outb (&SID.v3.ctrl, 0x80); clrscr (); cprintf ("Making charset, mompls"); makechar (); /* Set the border and background colors */ border = bordercolor (COLOR_BLACK); background = bgcolor (COLOR_BLACK); text = textcolor (COLOR_BLACK); clrscr (); for(i = 0; i != 0x400; i++) { *((char *)(i + BUFFER)) = 0; *((char *)(i + SCREEN1)) = 0; *((char *)(i + SCREEN2)) = 0; outb ((char*)(i + COLORRAM), COLOR_YELLOW); } #if defined(__C64__) || defined(__C128__) /* Move the VIC 16K block */ block = inb (&CIA2.pra); outb (&CIA2.pra, (block & 0xFC) | ((SCREEN1 >> 14) ^ 0x03)); #endif #if defined(__C128__) /* Save and change some flags, so that kernal/basic interrupt handler will ** not interfere with our routine. */ initflag = *(unsigned char*) 0xA04; *(unsigned char*) 0xA04 &= 0xFE; graphflag = *(unsigned char*) 0xD8; *(unsigned char*) 0xD8 = 0xFF; #endif /* Remember the VIC address register */ v = inb (&VIC.addr); /* Run the demo until a key was hit */ t = clock (); while (!kbhit()) { /* Build page 1, then make it visible */ fire (SCREEN1); WAITVSYNC (); outb (&VIC.addr, PAGE1); /* Build page 2, then make it visible */ fire (SCREEN2); WAITVSYNC (); outb (&VIC.addr, PAGE2); /* Count frames */ f += 2; } t = clock() - t; /* Switch back the VIC screen */ outb (&VIC.addr, v); #if defined(__C64__) || defined(__C128__) /* Move back the VIC 16K block */ outb (&CIA2.pra, block); #endif #if defined(__C128__) /* Restore the flags */ *(unsigned char*) 0xA04 = initflag; *(unsigned char*) 0xD8 = graphflag; #endif /* Fetch the character from the keyboard buffer and discard it */ (void) cgetc(); /* Reset screen colors */ bordercolor (border); bgcolor (background); textcolor (text); clrscr (); /* Calculate stats */ sec = (t * 10) / CLK_TCK; sec10 = sec % 10; sec /= 10; fps = (f * (CLK_TCK * 10)) / t; fps10 = fps % 10; fps /= 10; /* Output stats */ gotoxy (0, 0); cprintf ("time : %lu.%us", sec, sec10); gotoxy (0, 1); cprintf ("frames: %lu", f); gotoxy (0, 2); cprintf ("fps : %lu.%u", fps, fps10); /* Wait for a key, then end */ cputsxy (0, 4, "Press any key when done..."); (void) cgetc (); /* Done */ return EXIT_SUCCESS; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/geos/�����������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014606�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/geos/bitmap-demo.c����������������������������������������������������������������0000664�0000000�0000000�00000001167�13473601511�0017155�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** Minimalistic GEOSLib bitmap demo program ** ** 2012-06-10, Oliver Schmidt (ol.sc@web.de) ** ** To create bitmap.c use the sp65 sprite and bitmap utility: ** sp65 -r logo.pcx -c geos-bitmap -w bitmap.c,ident=bitmap ** */ #include <conio.h> #include <geos.h> #include "bitmap.c" #if (!(bitmap_COLORS == 2 && \ bitmap_WIDTH%8 == 0 && \ bitmap_WIDTH <= SC_PIX_WIDTH && \ bitmap_HEIGHT <= SC_PIX_HEIGHT)) #error Incompatible Bitmap #endif struct iconpic picture = {(char*)bitmap, 0, 0, bitmap_WIDTH/8, bitmap_HEIGHT}; void main(void) { BitmapUp(&picture); cgetc(); } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/geos/bitmap-demores.grc�����������������������������������������������������������0000664�0000000�0000000�00000000314�13473601511�0020211�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������HEADER APPLICATION "Bitmap Demo" "Bitmap Demo" "V1.0" { author "Oliver Schmidt" info "This is a minimalistic cc65 GEOSLib bitmap demo program written in C." date 12 06 10 12 00 } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/geos/dialog.c���������������������������������������������������������������������0000664�0000000�0000000�00000001331�13473601511�0016207�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Note: ** This is just a sample piece of code that shows how to use some structs - ** it may not even run. */ #include <geos.h> void sysopvfunc (void); void opvecfunc (void); void usrfunc (void); static const dlgBoxStr myDialog = { DB_SETPOS (1, 0, 150, 0, 319), DB_TXTSTR (10, 20, "test"), DB_VARSTR (10, 20, &r0L), DB_GETSTR (10, 20, &r0L, 9), DB_SYSOPV (sysopvfunc), DB_GRPHSTR (&r0L), DB_GETFILES (10, 10), DB_OPVEC (opvecfunc), DB_USRICON (0, 0, &r0L), DB_USRROUT (usrfunc), DB_ICON (OK, DBI_X_0, DBI_Y_0 ), DB_ICON (CANCEL, DBI_X_1, DBI_Y_1), DB_END }; void main (void) { DoDlgBox (&myDialog); } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/geos/filesel.c��������������������������������������������������������������������0000664�0000000�0000000�00000000617�13473601511�0016401�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* GEOSLib example using DlgBoxFileSelect Maciej 'YTM/Elysium' Witkowiak <ytm@elysium.pl> 26.12.1999 */ #include <geos.h> char fName[17] = ""; void main (void) { r0=(int)fName; DlgBoxOk(CBOLDON "You now will be presented", "with an apps list" CPLAINTEXT); DlgBoxFileSelect("", APPLICATION, fName); DlgBoxOk("You've chosen:" CBOLDON, fName); } �����������������������������������������������������������������������������������������������������������������cc65-2.18/samples/geos/fileselres.grc���������������������������������������������������������������0000664�0000000�0000000�00000000330�13473601511�0017434�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ ; this is the resource file for filesel.c, a GEOS application example HEADER APPLICATION "filesel" "FileSel" "V1.0" { dostype USR author "Maciej Witkowiak" info "This is a C prog compiled with cc65 and GEOSLib." } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/geos/geosconio.c������������������������������������������������������������������0000664�0000000�0000000�00000002603�13473601511�0016740�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ #include <geos.h> #include <conio.h> #include <mouse.h> void main(void) { struct mouse_info info; char ch; DlgBoxOk("Now the screen will be", "cleared."); clrscr(); DlgBoxOk("Now a character will be", "written at 20,20"); gotoxy(20, 20); cputc('A'); DlgBoxOk("Now a string will be", "written at 0,1"); cputsxy(0, 1, CBOLDON "Just" COUTLINEON "a " CITALICON "string." CPLAINTEXT ); DlgBoxOk("Write text and finish it", "with a dot."); cursor(1); do { ch = cgetc(); cputc(ch); } while (ch!='.'); cursor(0); DlgBoxOk("Seems that it is all for conio.", "Let's test mouse routines."); mouse_init(1); cputsxy(0, 2, CBOLDON "Now you can't see mouse (press any key)" CPLAINTEXT); mouse_hide(); while (!kbhit()) { }; cputc(cgetc()); cputsxy(0, 3, CBOLDON "Now you see the mouse (press any key)" CPLAINTEXT); mouse_show(); while (!kbhit()) { }; cputc(cgetc()); // Get the current mouse coordinates and button states and print them mouse_info(&info); gotoxy(0, 4); cprintf("X = %3d", info.pos.x); gotoxy(0, 5); cprintf("Y = %3d", info.pos.y); gotoxy(0, 6); cprintf("LB = %c", (info.buttons & MOUSE_BTN_LEFT)? '1' : '0'); gotoxy(0, 7); cprintf("RB = %c", (info.buttons & MOUSE_BTN_RIGHT)? '1' : '0'); DlgBoxOk("Bye,", "Bye."); } �����������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/geos/geosconiores.grc�������������������������������������������������������������0000664�0000000�0000000�00000000310�13473601511�0017774�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; this is the resource file for geosconio.c, a GEOS application example HEADER APPLICATION "conio" "ConIO" "V0.1" { dostype USR author "Maciej Witkowiak" info "This is an example for a conio app." } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/geos/geosver.c��������������������������������������������������������������������0000664�0000000�0000000�00000003041�13473601511�0016422�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <geos.h> #include <conio.h> // Let's define the window we're operating struct window wholeScreen = {0, SC_PIX_HEIGHT-1, 0, SC_PIX_WIDTH-1}; void main (void) { unsigned char os = get_ostype(); unsigned char *machine = NULL; unsigned char *version = NULL; unsigned char good = 1; SetPattern(0); InitDrawWindow(&wholeScreen); Rectangle(); gotoxy(0, 4); if (os == GEOS4) { machine = "plus4"; version = "GEOS v3.5"; } else { if ((os & GEOS128) == GEOS128) { machine = "c128"; } else { machine = "c64"; } os &= 0x7f; if (os == GEOS_V10) { version = "GEOS v1.0"; } else if (os == GEOS_V11) { version = "GEOS v1.1"; } else if (os == GEOS_V12) { version = "GEOS v1.2"; } else if (os == GEOS_V13) { version = "GEOS v1.3"; } else if (os == GEOS_V15) { version = "GEOS v1.5"; } else if (os == GEOS_V20) { version = "GEOS v2.0"; } else if (os == MEGAPATCH3) { version = "MegaPatch 3"; } else if (os == GATEWAY) { version = "GateWay"; } else if ((os & WHEELS) == WHEELS) { version = "Wheels"; } else { version = "Unknown GEOS version"; good = 0; } } if (good) { cprintf("%s (%s)", version, machine); } else { cprintf("%s (%s) (%d)", version, machine, os); } Sleep(10*50); return; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/geos/geosverres.grc���������������������������������������������������������������0000664�0000000�0000000�00000000334�13473601511�0017467�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ ; this is the resource file for geosver.c, a GEOS application example HEADER APPLICATION "geosver" "GEOSver" "V1.0" { dostype USR author "Marco van den Heuvel" info "This is a C prog compiled with cc65 and GEOSLib." } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/geos/getid.c����������������������������������������������������������������������0000664�0000000�0000000�00000001355�13473601511�0016052�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* This is an example program for GEOS. It reads GEOS serial number and prints it on the screen. Maciej 'YTM/Elysium' Witkowiak <ytm@elysium.pl> 05.03.2004 */ #include <stdlib.h> #include <geos.h> #include <conio.h> const graphicStr Table = { NEWPATTERN(0), MOVEPENTO(0, 0), RECTANGLETO(320, 199), GSTR_END }; void Exit(void) { exit(0); } void Menu = { (char)0, (char)14, (int)0, (int)28, (char)(HORIZONTAL|1), CBOLDON "quit", (char)MENU_ACTION, &Exit }; int main(void) { dispBufferOn = ST_WR_FORE; GraphicsString(&Table); cputsxy(0, 3, CBOLDON "Your Serial Number is:"); cputhex16(GetSerialNumber()); DoMenu(&Menu); MainLoop(); // will never reach this point... return 0; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/geos/getidres.grc�����������������������������������������������������������������0000664�0000000�0000000�00000000170�13473601511�0017107�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������HEADER APPLICATION "getid" "GetId" "V1.0" { mode any dostype USR author "Maciej Witkowiak" info "This is an example." } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/geos/grphstr.c��������������������������������������������������������������������0000664�0000000�0000000�00000000720�13473601511�0016442�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Note: ** This is just a sample piece of code that shows how to use some structs - ** it may not even run. */ #include <geos.h> static const graphicStr myString = { MOVEPENTO (0, 0), LINETO(100, 100), RECTANGLETO(50, 50), NEWPATTERN(3), FRAME_RECTO(50, 50), PEN_X_DELTA(10), PEN_Y_DELTA(10), PEN_XY_DELTA(10, 10), GSTR_END }; int main (void) { GraphicsString(&myString); } ������������������������������������������������cc65-2.18/samples/geos/hello1.c���������������������������������������������������������������������0000664�0000000�0000000�00000001214�13473601511�0016134�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* GEOSLib example Hello, world example - with DBox Maciej 'YTM/Elysium' Witkowiak <ytm@elysium.pl> 26.12.1999 */ #include <geos.h> void main (void) { // Let's show what we've got... DlgBoxOk(CBOLDON "Hello, world" CPLAINTEXT, "This is written in C!"); // Normal apps exit from main into system's mainloop, and app finish // when user selects it from icons or menu, but here we want to exit // immediately. // So instead: // MainLoop(); // we can do: // (nothing as this is the end of main function) // exit(0); // return; return; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/geos/hello1res.grc����������������������������������������������������������������0000664�0000000�0000000�00000000326�13473601511�0017202�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ ; this is the resource file for hello1.c, a GEOS application example HEADER APPLICATION "hello1" "Hello 1" "V1.0" { dostype USR author "Maciej Witkowiak" info "This is a C prog compiled with cc65 and GEOSLib." } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/geos/hello2.c���������������������������������������������������������������������0000664�0000000�0000000�00000002512�13473601511�0016137�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* GEOSLib example Hello, world example - using graphic functions Maciej 'YTM/Alliance' Witkowiak <ytm@friko.onet.pl> 26.12.1999 */ #include <geos.h> // Let's define the window we're operating struct window wholeScreen = {0, SC_PIX_HEIGHT-1, 0, SC_PIX_WIDTH-1}; void main (void) { // Let's show what we've got... // Let's clear the screen - with different pattern, because apps have cleared screen upon // start SetPattern(0); InitDrawWindow(&wholeScreen); Rectangle(); // Now some texts PutString(COUTLINEON "This is compiled using cc65!" CPLAINTEXT, 20, 10); PutString(CBOLDON "This is bold", 30, 10); PutString(CULINEON "and this is bold and underline!", 40, 10); PutString(CPLAINTEXT "This is plain text", 50, 10); // Wait for 5 secs... // Note that this is multitasking sleep, and if there are any icons/menus onscreen, // they would be usable, in this case you have only pointer usable Sleep(5*50); // Normal apps exit from main into system's mainloop, and app finish // when user selects it from icons or menu, but here we want to exit // immediately. // So instead: // MainLoop(); // we can do: // (nothing as this is the end of main function) // exit(0); // return; return; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/geos/hello2res.grc����������������������������������������������������������������0000664�0000000�0000000�00000000326�13473601511�0017203�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ ; this is the resource file for hello2.c, a GEOS application example HEADER APPLICATION "hello2" "Hello 2" "V1.0" { dostype USR author "Maciej Witkowiak" info "This is a C prog compiled with cc65 and GEOSLib." } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/geos/inittab.c��������������������������������������������������������������������0000664�0000000�0000000�00000000550�13473601511�0016404�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Note: ** This is just a sample piece of code that shows how to use some structs - ** it may not even run. */ #include <geos.h> static const void myTab = { 0xd020, (char)2, (char)0, (char)2, 0x4000, (char)5, (char)0, (char)1, (char)2, (char)3, (char)4, 0x0000 }; int main (void) { InitRam(&myTab); } ��������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/geos/logo.pcx���������������������������������������������������������������������0000664�0000000�0000000�00000040766�13473601511�0016277�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ ����‹�,,������������������������������������������������������������������������������������������������������������ÿ�ÿ�ÿ�ÿ�Ü�ÿ�ÿ�ÿ�ÿ�Ü�ÿ�ÿ�ÿ�ÿ�Ü�ÿ�ÿ�ÿ�ÿ�Ü�ÿ�ÿ�ÿ�ÿ�Ü�ÿ�ÿ�ÿ�ÿ�Ü�ÿ�ÿ�ÿ�ÿ�Ü�ÿ�ÿ�ÿ�ÿ�Ü�ÿ�ÿ�ÿ�ÿ�Ü�ÿ�ÿ�ÿ�ÿ�Ü�ÿ�ÿ�ÿ�ÿ�Ü�ÿ�ÿ�ÿ�ÿ�Ü�ÿ�ÿ�ÿ�ÿ�Ü�ÿ�ÿ�ÿ�ÿ�Ü�ÿ�ÿ�ÿ�ÿ�Ü�ÿ�ÿ�ÿ�ÿ�Ü�ÿ�ÿ�ÿ�ÿ�Ü�ÿ�ÿ�é���È�Â��ÿ�ß�ÿ�ÿ�ä��Â���Ä������Â�Ú����Â��Â��Â��Â��Â��Â��Â��Â��Â��Ì�ÿ�ÿ�à��������Â��������ÂÙ��������������������������Í�ÿ�ÿ�ß�����������������Â�Ö��������������������������Â�Ë�ÿ�ÿ�Ü�������������������Â�Õ��������������������������ÂÃ�É�ÿ�ÿ�Ú�������Â�������������Ã�Ó����������������������������Ê�ÿ�ÿ�Ù����������������������Õ�����������������������������È�ÿ�ÿ�×����Â������������������Â�Ò����������������������������Ë�ÿ�ÿ�Ö������Â�����Â�����Â����Â�ÂÕ��Â��Â��Â���Â��Â���Â��Â���Â�����Â�Ç�ÿ�ÿ�Ô��������������Â���������Â��Ñ���������Â�����������������Ã�Ê�ÿ�ÿ�Ô����������Â������������Ã�Ô��������Â���������������������È�ÿ�ÿ�Ò�Â���������������Â���������Ò���������Â�����������������Ã�Ë�ÿ�ÿ�Ñ����Â�����������������Â��ÄÂ�Ò��������������������Â�����Â�Ã��Ç�ÿ�ÿ�Ð���������������Â�Â�Â������Â�Ô���������������Â�����������Â��Ê�ÿ�ÿ�Ð�������������Ã�Ã�Â�Ç���Ã��Ñ��Â������������������������Â��Ê�ÿ�ÿ�Î���������Â���Ä�Â��Â�Ã�Â��Â�ÂÂ�Ó�����Â����Ë�É�Ë�Â��Â�È�ÿ�ÿ�Í������������Â��Â�Â���Â������Â��Ò��������������Â�Â�Â�Â��Â�Â��Â���Ë�ì�Â�÷�Â�à�������Â����Æ���Â�Ã�Â����Ã�Ô����������Ã�����Â�Â����Â�Â���ÂÄ�É�æ��Ã���Ã�Â�è���Â���Â�Ã�Ø����Â������Â�����Â�Â�Ã�Ç��Â�Â�Ð������Â���Â�Ã���Â�Â������Â���Â�ÂÌ�á��Ã�Â��������Â�à����������Â��Â�Ò�����������Â�Â���Ã�Å�Ä��Ã�Â�Ô���������Â���Â�Â�Â�Ä�Ç�Ã�Â�Ï�Þ���Â��Â�����������Û���������������Â�Ï�����������Ã�Â�Ã�Ð�Ú��������Â�Ã�Â�Ä�Ã��Ã���Â�Æ�Â�Ë�Ü������Â������������×�������������������Ì�����������Â�Â�Â�Æ�Ï�Ã�Ò���������Ã���Â�Ê�Ê�Ó�Ú�������Â������������Ã�Ñ��������������������Â�É���Â�������Ã���Â�ì���Â�����Â�Â�É�Ó�Ñ�Ø�����Â���������������Ô��������������������Ì����������Â��ÂÂ�ï���������Ã�Â�Õ�Ø�Ø���������������������Â��Ì�����������Â��Â�������Ã��Æ�������Â���Ã��Â�î�������Â�Â�Â���ì�Õ�Ã��������������������Â�Í�������Â��������������Â�É����������Ã�Â�Å���é���������Â�ñ�Ô�Â���������������������Â���Ê���������������������Â�Ä�Ä���������Â�Â��������Å�á����������Ä��ì�Ó��Â���������Â������Â������Ë�Ã��������Â������Â�����Â�É����������Ã�Â�������Ã���Þ����������Ã����Â�ç�Ó�Â���Â����������Â���������Â��Ç����Â�����������������Â�Å�Ã�����Â�����Â���������Â���Â�Û����������Ã������Â��á�Ð�Â�Â������������������Â���Ã�È�Â������������������Â����Â�Æ�������������������������Â�Ú���Â������Â��������Â�à�Ñ���������Â����Æ�������Â�Â��Å��������������Æ�������Â�Â�ÃÃ�������������������������Â�Â�Ö����������Â��������Â�Â�Ý�Ï��������Â���Æ���Ä������Â�ÂÇ������������Å���Ä������Â�ÂÆ���Â���������������������Â�Ú�����Â��������������Â�Â�Û�Î���������������Â��Â��Â�������Â�Ã���������Â��Â��Â��Â��Â�Â����Â���Â��������Â����������������Â�Ã�Â�Ò��������������������Â�Â�Â�Ø�Î�����������Ç����Â����Â��Ã�Æ�����������Ã�Ã�Â�����������ÂÅ����������Â����Â�Â������������Ö�������������������Â���Û�Í�����������Â�Â���Â�Ã�Â������Â��Ä����Â��Â���Â�Â��Â��Â�Â�Â�����Â��ÂÃ������Â�����������������������Â�Ñ������Â�������������Â���Â��Õ�Ì�����������Â�Ã��Â�Ã�Ã�Â�Â����ÂÅ�����������Ã�Â��Ä�Ã�Â�Â�����ÂÆ������������Â�����Â�����������Ó�Â�����������������������Ù�Ì������Â����Ä��Â�Ç�Æ����Â�Â�Ã�����������Ã����Ì����Â�Â�Â���������������������Â����������Ð�����������Â�������������Â��Ó�Ì���Â������Ã���Å�È�Å����Â�Â����������Ä���Ç�Å�Æ����Æ������������������������������Ñ��������������Â����������Â�Ö�Ë�����������Ã���Î�Å�Â��Ä���������Â��Â�Â�Â�Î�Ã�Â����Â���Â��������Â�Æ�Â���������������Í���Â�����������������������Â�Ò�Ê����������Ã��Ú�Â�Â�Â���������Å��Ù�Â�Æ�Â���������Ã�Â�Â��Â�Â������������Ñ���������������������������Ô�Ë����������Â���Â�Ñ�Ã�Â�Å���Â�����Â��Â���Ö�Ä�Ä�����������Ã�Ã�Â���������������Ã�Í������Í�����Â�����������Ñ�É��������Â��Â�Âã����������Ä��Ü�Ç������Â����Â�ÂÂ���������Â��������Ð�����Ã���Â�Â��Ã���������Â����Ô�É�����Â�����Ã�Â�Ü�Ä������Â����Â�Â�Ý�Å��������Â��Â�Â�Â�Ã�Â�������������Ã��Ï���Â���Â�Â����Ã����Â���������Ð�Ê���������Â��ä����������Â��å�����������Ã��Ä�Ç�����Â�Â�����Ò�Â�������Â����Â�������������Ó�É����������Ã���à����������Ã���â����������Â��Â��Ä�Â�Ä�����������Â�Ó�Â���Å�Ä�Â�������������Â�Â�Ï�È����������Â��ä�����������Âè����������Â��Î��������Â���Â�Ð��Â�Æ��Ä�Ä�Ã������������ÂÓ�È���Â�������Â��ã����Â�����Â��Âæ���Â�������ÃÂ�Ð�������������Ò���Å�Ä�Å�Ã������������Â�Ï�É���������Â��å��Â����Â���Â�ç�Â���������ÂÂ�Ñ�Â���������Â�Ó�Ø�������Â�����Ó�È����������Â��Â�á����������Â��Â�â�����������Â�Â�Ï����������Â��í�������Â���Å�Î�È�����Â����Â��ä����������Â�é����������Â�Ò�����������Âï�����������Ô�È����������Â��ã����������Â�Â�å�����Â�����Â��Ð������������Â�ì��Â��������Ä�Ï�È����������Â�æ����������ÂÂ�æ�����������ÂÓ������Â���Ã�ï������������Ò�È����������Â���â�������Â���Âè�������Â����Â��Î���Â����Â�Â�Ä�í���������Â�Â�Â�Î�È������Â����Âæ����������Â��ç����������ÂÂ�Ð����������Â�ð�����������Â�Ñ�É�����������Âä������������Â�å����������Â�Ò�����������Â��ë������������Â�Ï�È�Â��������Â�Â�ã���Â�������ÂÂ�æ�����������Â�Ð����������Ã�È��â����Â�������Ã�Ñ�É��Â��������ÂÃ�×�É�����������ÂÛ�Í��Â�����Â�����Í�����������Â��Æ���à�������Â�������Ï�È����������ÂÂ�×�Â�Ê������������Ö�Â�Í����������Â�Ð����������Â��È����Â�Ú����������Â�Ã�Ò�É������������×��Ê�����������Â�Â�Ó��Í������������Â�Ì����������Â�Â��Æ����Ä�Ö�������������Â��Ï�È������������Â�Ñ�Ã�Ä�Ç���Â��Â�Â����Í�Æ��Â�Â�Ì���Â��������Í�Â����������ÂÂ�Ç������×������������Ä�Ó�Ê�����������Ò�Â���ÂË������������Ñ����Â�Â�È�������������Ì���Â�Â�����Â�Â�Ç������Ã��Â�Ê��������Â�����Â�Â��Ñ�É����Â�Â���Â���Â�Ë�����Ã��Æ����������Â�Â�Í������Î�����������Ä�Ç�Â������Â���ÄÂ�É�����Â����Â����Â�����Â��������Ã��Ã�Ï�É�������������Ë�������Ä�Ç�������Â���Â��Â�Æ������Â��Â�È����Â�������ÂÊ������������Â�Â�Æ�Â��������������������������Â�Ã��Ò�Ê�������������Â�Ã�Ã��������É�������Â���Â���Â��Â��������Â�Ë���������������Ã����������Ã��Â�Ç���Â���������������������Â���Â��Õ�Ê����������������Â���������ÂÂ�Ç������Â���Â���������������Ì��������������Â������������Â�Â�Ê����������������Â�����������Ä�Â�Ò�Ë����������������Â��������Â�È�������������������������Â�Ë�����Â�Â�������Â�����������Â�Â�É�Â��������������������������Â���Õ�Í��������������������Â��Â�Ì�����������������������Â��Ì�����Â��Â�����������������Å�Â�Æ�����Â����������������������Ã�ÂÂ��Ò�Ì����������������������Â���È������������Â��������Â�Â��Ð�����Â������������������Ã�Î���������������������������Â�Â��Õ�Í����Â���Â���������������ÂÃ�É��Â���������������Â����Â�Ã�Î���Â������Â�����Â������Â�Ã�Ã�É������������������Â��Â������Ã��×�Î�����Â�����������Â����Ã��Í���������������������Â�Ð����Â�������������Â����Â�Â��Ì��������Â�Â��Â����������Â���Ã���Â�Õ�Ð���Â�����������������Â�Ñ�����������Â�Â�������Â��Ð���������������������Ä��Â�Ë�������������Â�����������Â�Ä��Ø�Î����Â����������������Â���Ì�����Â������������������Ó������Â������������Ã��Â�Â�Ë������������������������Ã�ÂÂ��Ú�Ó�������������������Â�Ã�Í������Â������������ÆÂ��Ñ����������������Â��Ã���Ð����������������������Â�Ã�Â�Ã�Â�Õ�Ð�����������Â������Æ�Ã�Ñ����������������Ã��Â�Ò�Ã����������Â������Ã���Ä�Ð��Â�����������������Ã�Â���Â�Û�Ô���Â�Â��Â�������Â����ÂÒ�Ã��������������Â�Â�Â��×��Â�����Â������Ä�Â����Ó�Â��Â���������Â�����Â�Â�Â��Â�Â�Ú�Ò�Â�����Â����Â�Ç�Â��Ã�Ó�Â��Â�Â�Â����Â�Å�Â�Â��Ã�Ó�Ã���Ã������Æ��Â���Ø����Ã�Â�������Â�Æ�Â�Â����Þ�Ø�����Â�Ã�Â���Â��Â��Ø�Ã��Â�Ã�Ä�Â��Â����Â�×�Ä�Â��Ã�Â�Ã����Â���Â�Â�Õ�Â�����Å�Ç�Â���Â�����â�Ô��Â�����Â���Â�����Â�Ã�Ô�Ã��Â���Â������Â��Ã�Ü�Â��������Â��Â���Â�×�Ä�Ã���Â��ÂÂ�Â���Â������Å�Â�Ý�Ý��Â���Â�����Â�â�Â�Â��������Â��Ã�â�������Â���Â�à�Ä���Â�Â�Â��������Ã��ã�×���Ã��Â����Â�Å�Â�Ú�Â�Ã�Â�Â�����Ä�ä���Ä�������Æ�Ã�ß�Ç�Ã�Â�����Â�Ä�è�Ü�Å�Ã�Ã�Ã��ë�É��Ä�Â�å�Ð��á�Å���Ã�Ã�Ê�Ã�Ã�ç�ß�Ä�Ã�ì�Ã�Ä���Ç�í�Â�����ó�Ç����ò�ë�ø�ÿ�ö�Î�í�ÿ�è�ÿ�ÿ�Ì�å�é�ÅÃ�ß��Ã�Å�����É�Ã�É�Ä�Ó�Åÿ�Í�ÄÃ�Äæ�ß�ÄÅ�Äã�ÉÄ�ÌÄ�ÉÃ��ÊÎ�Ëÿ�Ê�ÅÃ�Äæ�ß�ÄÆ�Äâ�ÉÄ�ÌÃ�ËÄ�Ë�Ë�Ë�ÿ�É��Ä�Ä�Â�á�ß�ÄÅ�ÄÂ�Ã�Ú�ÅÄ�Å�Å�Ã�Ã�ÅÂ�ÅÃ�ÃÂ��ÅË�ÆÃ�Äÿ�Ð��Ãç�ß�Ä�ÂÂ�ÄÂ�ÃÃ�Å�Ä�Ì�ÅÆ��Â�ÄÇ�Â�ÅÃ�ÄÃ�Ç�ÄÂ��Æ�ÄÃ�Ã�ÂÂ��È�ÅÃ�Ã�ÅÇ��Â�ÃÅ�ÃÆ��Â�ÄÅ�ÄÃ�Å�Â��ÅÆ��Ã�Î�Ý�ÉÂ�ËÄ�É�Ê�ÄÂ�Â�Å�ÄÂ���Ã�ÅÃ�Å�Ã�Â��ÅÊ�ÄÃ�Â�Ã�É�ÉÃ�ÉÄ�Ë�ÇÄ�ÊÅ�ÄÃ�ÄÄ�ÉÄ�Ä�ÄÍ�Ý�É�ÌÄ�Ä�ÅÃ�Ç�Ë�Â�É��Â�Ã�Ã�ÄÂ�Ç�Å��Æ�ÅÃ�Â�Ã�Ã�Ã�ÊÂ�ËÄ�ÓÃ�ÌÃ�Ã�Â�Ä��Å�ÅÃ�ÉÍ�Ì����Ë�ÄÄ��Ä�Æ��ÄÄ�ÄÉ�ÌÂ��Ê�Â�ÄÂ��Å�Â�Ã��Ä�Ä�Ã�ÄÃ�Â�Â�Ä�Ä�ÅÄ�Â�ÅÃ�Ä��ÅÂ�Æ�ÅÂ��ÃÄ�ÄÂ�ÅÃ�ÅÂ�ÄÄ�ÅÂ�ÈÂ�Ë�Ë�ÉÊ�Ä���ÅÃ�ÄÂ�ÄÂ�Â�ÅÂ�Å�Ä��ÆÃ�Ë��ÄÂ�Â�Å�Â�Â�ÅÂ��Æ�ÅÂ�Â�Â��Ç�ÄÃ�Ä�ÄÄ�ÄÃ�ÄÄ�ÄÃ�ÅÂ�Ä�Â�ÅÂ�ÅÂ�Ä��Ä�Ã�ÄÂ�ÄÃ�Î�Ë�ÈÊ�Ä���Å��Å�ÎÈ�ÅÂ��Å�Ç�ÅÂ�Å�Â�ÅÂ�Ä�ÅÂ��Â�Ä�ÄÂ�Â�Ì�ÄÆ��Å�Â�ÅÂ�Ä��Ä�Â�ÄÂ��ÃÃ��ÃÂ�ÅÂ�Å��Ì�ÅÂ�Ã��Ê�Ë��Â�ÃÂ��Å�ÄÃ�Â�Ä��Ä��Ì���Ä�ÄÂ��ÅÂ�Ä�Â�Ä��ÄÂ��Ä����ÄÂ�Ã�Ç�ÄÃ�Ã�Å�Ä�Å��Ä�ÄÂ��Å�Å��Å��Ä��Å��ÅÂ�ÄÃ�ÄÂ�ÍÂ�Å��Ä�É�Ó�É�Ä�Â�ÅÂ��Å�ÅÂ�Â���È�Ä��Å�Â��Â��Ä��Ä��Å�Ã�ÅÄ��Â�Å�Å��Ã�É�ÄÃ���Å�Â�ÅÂ�ÄÃ�Å��ÅÂ�ÅÃ�Å�Å��Å�ÅÂ�Â�Â��ÅÃ���Ë�Ô�È�ÄÂ�Â�ÄÂ��Ä��Å������Å�Ä�Â�Å�ÂÆ�Æ�Å��ÅÂ��ÅÂ�Â�Â�Ç�ÆÂ��Â�È�Ä�Ã�Â�Å��Æ�Ä�Â�Ä��Æ�Å��ÅÂ�ÅÂ�ÅÂ�Æ���ÂÂ�Ä�Â�Î�Ï��Ä�Æ�Ä���Ä��Å��Å�Â�ÃÂ�Ã�Ã�Å�ÅÂ�ÍÂ��Å�Å��ÍÄ�Æ�ËÊ�Æ�ÃÃ�Å�ÅÂ�Å��Ä�Â�ÄÂ��Ã�Ç��ÄÂ�Å��Æ�Å�Æ��Â�Â�É�Ó�Ã�Å�Ç�ÅÄ�ÄÂ��Ê�Â�Ç�ËÂ�Ì�Â�ÊÂ��Í�É�ËË�ÊÂ�Ê�Â�Ä��ÄÂ��ÄÂ�ÍÂ�ÆÂ�ÄÄ�ËÂ�ÄÂ�Â�Î�Ñ�Ë�Ç�Ä��Å���Ê��È�ÈÃ�ÌÂ��Â�È�Â�Í�Ã�È�ÈÂ��È�ÇÂ�Â�Ç�Â�ÅÃ�Å��Å��ÉÃ��ÄÂ��Ä���É��Ä�Â�Â�Ì�Ô�Ì��Æ�Ä�Ã�Å���Â�Å�È����Ç��Â�Ã��Ã��Â�Â�Ê�Â�Â�Í��Ã�Ï���Æ�����Ä��Æ�Â�Æ�ÄÂ��Â��Å�Â�Å�Ç����Ä�Â�Ñ�ß�Ã����Â�Ä�Â��Â����Â��Ë�Â�����Å�Â�Â�Â�Ã���Â�����Â���Ï���Â�Â�È�Â��Â�Â�Ã�Ã�Â��Â����Â�Â����ÅÂ�Â�Â���Â�Â���Â���Â�Ã�Â��Â���Î�à�Ã�Ä�Â��Â�Ä�Æ�Â�Ï�Â�Â�Â�Â��Ã��Â�Ä�Å�Â�È���Â��É�Æ�Â�Ð�Â�Ã�Â����Â�Ä�Æ�È�Ä����Â�Â�Â�Â�Å�Ä�Â��Â�Ä�Ô�â�Ã�Ä�Ç�Ä��Ã�Â�Ë�Ä�Â�Â�Æ�Å�Ä�Ã��Â�Ã�Â��Æ�Ï��Ä�Í��Ã�Î�Ã�Ä��Ä����ÅÂ��Â�Í��Ã�Ä�Ã�Â�Å��Ð�ã�Ã�Å�Æ�Æ�Æ�Â�Õ�Ä��Ã�É�Ã�É��Ã�Â�Í��Ã�Â�Ì�Å�Ä���Ç�Õ��Â�Â���Â�Â�Î�Æ��Æ�Î�ð�Ì�Â�Ï�Â�Â�æ�Ä�ê�Æ�Ç�Ì�Ì�Ä�Ô�Ê�Ü�ä�Ã�õ�Ä�Ñ�â�Õ�Î�Æ�Ó�Â���Ó�É�Ú�ÿ�î�Ã�ÿ�ÿ�è�ÿ�ÿ�ÿ�Î�Ë�Â�ý�ÿ�ÿ�ÿ�ÿ�Ü�ÿ�ÿ�ÿ�ÿ�Ü�ÿ�ÿ�ÿ�ÿ�Ü�ÿ�ÿ�ÿ�ÿ�Ü�ÿ�ÿ�ÿ�ÿ�Ü�ÿ�ÿ�ÿ�ÿ�Ü�ÿ�ÿ�ÿ�ÿ�Ü�ÿ�ÿ�ÿ�ÿ�Ü�ÿ�ÿ�ÿ�ÿ�Ü�ÿ�ÿ�ÿ�ÿ�Ü�ÿ�ÿ�ÿ�ÿ�Ü�ÿ�ÿ�ÿ�ÿ�Ü�ÿ�ÿ�ÿ�ÿ�Ü�ÿ�ÿ�ÿ�ÿ�Ü� ÿÿÿ�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/geos/menu.c�����������������������������������������������������������������������0000664�0000000�0000000�00000001735�13473601511�0015724�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Note: ** This is just a sample piece of code that shows how to use some structs - ** it may not even run. */ #include <geos.h> /* prototypes are necessary */ void smenu1 (void); void smenu2 (void); void smenu3 (void); typedef void menuString; /* you can declare a menu using cc65 non-ANSI extensions */ static const menuString subMenu1 = { (char)0, (char)(3*15), (unsigned)0, (unsigned)50, (char)(3 | VERTICAL), "subitem1", (char)MENU_ACTION, (unsigned)smenu1, "subitem2", (char)MENU_ACTION, (unsigned)smenu2, "subitem3", (char)MENU_ACTION, (unsigned)smenu3 }; /* or by using initialized structures */ static struct menu subMenu2 = { { 0, 3*15, 0, 50 }, 3 | VERTICAL, { { "subitem1", MENU_ACTION, smenu1 }, { "subitem2", MENU_ACTION, smenu2 }, { "subitem3", MENU_ACTION, smenu3 }, } }; void main (void) { DoMenu(&subMenu1); DoMenu(&subMenu2); } �����������������������������������cc65-2.18/samples/geos/overlay-demo.c���������������������������������������������������������������0000664�0000000�0000000�00000006026�13473601511�0017361�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** Minimalistic GEOSLib overlay demo program ** ** 2012-01-01, Oliver Schmidt (ol.sc@web.de) ** */ #include <stdio.h> #include <geos.h> #include "overlay-demores.h" /* Functions resident in an overlay can call back functions resident in the ** main program at any time without any precautions. The function show() is ** an example for such a function resident in the main program. */ void show(char *name) { char line1[40]; sprintf(line1, CBOLDON "Overlay Demo - Overlay %s" CPLAINTEXT, name); DlgBoxOk(line1, "Click OK to return to Main."); } /* In a real-world overlay program one would probably not use a #pragma but ** rather place the all the code of certain source files into the overlay by ** compiling them with --code-name OVERLAY1. */ #pragma code-name(push, "OVERLAY1"); void foo(void) { /* Functions resident in an overlay can access all program variables and ** constants at any time without any precautions because those are never ** placed in overlays. The string constant "One" is an example for such ** a constant resident in the main program. */ show("One"); } #pragma code-name(pop); #pragma code-name(push, "OVERLAY2"); void bar(void) { show("Two"); } #pragma code-name(pop); #pragma code-name(push, "OVERLAY3"); void foobar (void) { show("Three"); } #pragma code-name(pop); void main(int /*argc*/, char *argv[]) { if (OpenRecordFile(argv[0])) { _poserror("OpenRecordFile"); return; } DlgBoxOk(CBOLDON "Overlay Demo - Main" CPLAINTEXT, "Click OK to call Overlay One."); if (PointRecord(1)) { _poserror("PointRecord.1"); return; } /* The macro definitions OVERLAY_ADDR and OVERLAY_SIZE were generated in ** overlay-demores.h by grc65. They contain the overlay area address and ** size specific to a certain program. */ if (ReadRecord(OVERLAY_ADDR, OVERLAY_SIZE)) { _poserror("ReadRecord.1"); return; } /* The linker makes sure that the call to foo() ends up at the right mem ** addr. However, it's up to user to make sure that the -- right -- overlay ** actually is loaded before making the call. */ foo(); DlgBoxOk(CBOLDON "Overlay Demo - Main" CPLAINTEXT, "Click OK to call Overlay Two."); if (PointRecord(2)) { _poserror("PointRecord.2"); return; } /* Replacing one overlay with another one can only happen from the main ** program. This implies that an overlay can never load another overlay. */ if (ReadRecord(OVERLAY_ADDR, OVERLAY_SIZE)) { _poserror("ReadRecord.2"); return; } bar(); DlgBoxOk(CBOLDON "Overlay Demo - Main" CPLAINTEXT, "Click OK to call Overlay Three."); if (PointRecord(3)) { _poserror("PointRecord.3"); return; } if (ReadRecord(OVERLAY_ADDR, OVERLAY_SIZE)) { _poserror("ReadRecord.3"); return; } foobar(); if (CloseRecordFile()) { _poserror("CloseRecordFile"); return; } } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/geos/overlay-demores.grc����������������������������������������������������������0000664�0000000�0000000�00000000435�13473601511�0020422�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������HEADER APPLICATION "Overlay Demo" "Overlay Demo" "V1.0" { author "Oliver Schmidt" info "This is a minimalistic cc65 GEOSLib overlay demo program written in C." date 12 01 01 12 00 structure VLIR } MEMORY { overlaysize 0x1000 overlaynums 0 1 2 3 } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/geos/rmvprot.c��������������������������������������������������������������������0000664�0000000�0000000�00000004170�13473601511�0016465�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* GEOSLib example This small application removes GEOS disk write protection tag. e.g. boot disk is always protected after boot-up Maciej 'YTM/Elysium' Witkowiak <ytm@elysium.pl> 21.03.2000 */ #include <geos.h> char diskName[17] = ""; static const graphicStr clearScreen = { MOVEPENTO(0, 0), NEWPATTERN(2), RECTANGLETO(SC_PIX_WIDTH-1, SC_PIX_HEIGHT-1), GSTR_END }; static const dlgBoxStr mainDialog = { DB_DEFPOS(1), DB_TXTSTR(TXT_LN_X, TXT_LN_2_Y, CBOLDON "Remove protection on:" CPLAINTEXT), DB_TXTSTR(TXT_LN_X, TXT_LN_3_Y, diskName), DB_ICON(OK, DBI_X_0, DBI_Y_2), DB_ICON(DISK, DBI_X_1, DBI_Y_2), DB_ICON(CANCEL, DBI_X_2, DBI_Y_2), DB_END }; static const dlgBoxStr changeDiskDlg = { DB_DEFPOS(1), DB_TXTSTR(TXT_LN_X, TXT_LN_2_Y, CBOLDON "Insert new disk"), DB_TXTSTR(TXT_LN_X, TXT_LN_3_Y, "into drive." CPLAINTEXT), DB_ICON(OK, DBI_X_0, DBI_Y_2), DB_ICON(CANCEL, DBI_X_2, DBI_Y_2), DB_END }; static const dlgBoxStr errorDialog = { DB_DEFPOS(1), DB_TXTSTR(TXT_LN_X, TXT_LN_2_Y, CBOLDON "Error happened..."), DB_TXTSTR(TXT_LN_X, TXT_LN_3_Y, "exiting..." CPLAINTEXT), DB_ICON(OK, DBI_X_0, DBI_Y_2), DB_END }; void Error(void) { DoDlgBox(&errorDialog); EnterDeskTop(); } void main(void) { // Here we clear the screen. Not really needed anyway... GraphicsString(&clearScreen); // Get the name of current disk to show it in dialog box GetPtrCurDkNm(diskName); while (1) { switch (DoDlgBox(&mainDialog)) { // What's the result of dialog box? which icon was pressed? case OK: if (GetDirHead()) Error(); curDirHead[OFF_GS_DTYPE] = 0; if (PutDirHead()) Error(); break; case DISK: DoDlgBox(&changeDiskDlg); GetPtrCurDkNm(diskName); break; default: // CANCEL is the third option return; break; } } } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/geos/rmvprotres.grc���������������������������������������������������������������0000664�0000000�0000000�00000000341�13473601511�0017524�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ ; this is the resource file for rmvprot.c, a GEOS application example HEADER APPLICATION "rmvprot" "RmvProt" "V1.0" { dostype USR author "Maciej Witkowiak" info "This will remove the write protection from your bootdisk." } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/geos/vector-demo.c����������������������������������������������������������������0000664�0000000�0000000�00000002522�13473601511�0017177�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <geos.h> #include <conio.h> #include <stdlib.h> unsigned char x,y; void_func oldMouseVector, oldKeyVector; void foo1 (void) { // do something on mouse press/release gotoxy(x,y); ++x; cputc('A'); // call previous routine oldMouseVector(); } void foo2 (void) { // do something on key press/release gotoxy(x,y); ++y; cputc('B'); // call previous routine oldKeyVector(); } void hook_into_system(void) { // hook into system vectors - preserve old value oldMouseVector = mouseVector; mouseVector = foo1; oldKeyVector = keyVector; keyVector = foo2; } void remove_hooks(void) { mouseVector = oldMouseVector; keyVector = oldKeyVector; } int main(void) { x = 0; y = 0; // To make cc65 do something for you before exiting you might register // a function to be called using atexit call. #include <stdlib.h> then and // write: atexit(&remove_hooks); clrscr(); cputsxy(0,1, CBOLDON "Just" COUTLINEON "a " CITALICON "string." CPLAINTEXT ); hook_into_system(); // This program will loop forever though MainLoop(); // If not using atexit() you have to remember about restoring system vectors // right before exiting your application. Otherwise the system will most // likely crash. // remove_hooks(); return 0; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/geos/vector-demores.grc�����������������������������������������������������������0000664�0000000�0000000�00000000342�13473601511�0020240�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ ; this is the resource file for vector-demo.c, a GEOS application example HEADER APPLICATION "vectordemo" "VectorDemo" "V1.0" { dostype USR author "Maciej Witkowiak" info "This is a C prog compiled with cc65 and GEOSLib." } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/geos/yesno.c����������������������������������������������������������������������0000664�0000000�0000000�00000001014�13473601511�0016103�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* GEOSLib example example of using DlgBoxYesNo, DlgBoxOkCancel and DlgBoxOk functions Maciej 'YTM/Elysium' Witkowiak <ytm@elysium.pl> 26.12.1999 */ #include <geos.h> void main(void) { do { if (DlgBoxYesNo("Are you female?", "(don't lie ;-)") == YES) { DlgBoxOk("You claim to be woman!", "You wanna dance?"); } else { DlgBoxOk("Ergh, another man...", "Let's go for a beer."); }; } while (DlgBoxOkCancel("Do you want to try again?", "") == OK); } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/geos/yesnores.grc�����������������������������������������������������������������0000664�0000000�0000000�00000000322�13473601511�0017147�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ ; this is the resource file for yesno.c, a GEOS application example HEADER APPLICATION "yesno" "YesNo" "V1.0" { dostype USR author "Maciej Witkowiak" info "This is a C prog compiled with cc65 and GEOSLib." } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/gunzip65.c������������������������������������������������������������������������0000664�0000000�0000000�00000015257�13473601511�0015516�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** gunzip65 - a gunzip utility for 6502-based machines. ** ** Piotr Fusik <fox@scene.pl> ** ** This should be considered as a test of my zlib-compatible library ** rather than a real application. ** It's not user-friendly, fault-tolerant, whatever. ** However, it really works for real GZIP files, provided they are small ** enough to fit in buffer[] (after decompression!). */ #include <stdio.h> #include <string.h> #include <zlib.h> #ifdef __CC65__ #include <stdlib.h> #include <cc65.h> #endif #ifndef __CC65__ /* ** Emulate inflatemem() if using original zlib. ** As you can see, this program is quite portable. */ unsigned inflatemem(char* dest, const char* source) { z_stream stream; stream.next_in = (Bytef*) source; stream.avail_in = 65535; stream.next_out = dest; stream.avail_out = 65535; stream.zalloc = (alloc_func) 0; stream.zfree = (free_func) 0; inflateInit2(&stream, -MAX_WBITS); inflate(&stream, Z_FINISH); inflateEnd(&stream); return stream.total_out; } #endif /* __CC65__ */ /* ** Structure of a GZIP file: ** ** 1. GZIP header: ** Offset 0: Signature (2 bytes: 0x1f, 0x8b) ** Offset 2: Compression method (1 byte: 8 == "deflate") ** Offset 3: Flags (1 byte: see below) ** Offset 4: File date and time (4 bytes) ** Offset 8: Extra flags (1 byte) ** Offset 9: Target OS (1 byte: DOS, Amiga, Unix, etc.) ** if (flags & FEXTRA) { 2 bytes of length, then length bytes } ** if (flags & FNAME) { ASCIIZ filename } ** if (flags & FCOMMENT) { ASCIIZ comment } ** if (flags & FHCRC) { 2 bytes of CRC } ** ** 2. Deflate compressed data. ** ** 3. GZIP trailer: ** Offset 0: CRC-32 (4 bytes) ** Offset 4: uncompressed file length (4 bytes) */ /* Flags in the GZIP header. */ #define FTEXT 1 /* Extra text */ #define FHCRC 2 /* Header CRC */ #define FEXTRA 4 /* Extra field */ #define FNAME 8 /* File name */ #define FCOMMENT 16 /* File comment */ /* ** We read whole GZIP file into this buffer. ** Then we use this buffer for the decompressed data. */ static unsigned char buffer[26000]; /* ** Get a 16-bit little-endian unsigned number, using unsigned char* p. ** On many machines this could be (*(unsigned short*) p), ** but I really like portability. :-) */ #define GET_WORD(p) (*(p) + ((unsigned) (p)[1] << 8)) /* Likewise, for a 32-bit number. */ #define GET_LONG(p) (GET_WORD(p) + ((unsigned long) GET_WORD(p + 2) << 16)) /* ** Uncompress a GZIP file. ** On entry, buffer[] should contain the whole GZIP file contents, ** and the argument complen should be equal to the length of the GZIP file. ** On return, buffer[] contains the uncompressed data, and the returned ** value is the length of the uncompressed data. */ unsigned uncompress_buffer(unsigned complen) { unsigned char* ptr; unsigned long crc; unsigned long unclen; void* ptr2; unsigned unclen2; /* check GZIP signature */ if (buffer[0] != 0x1f || buffer[1] != 0x8b) { puts("Not GZIP format"); return 0; } /* check compression method (it is always (?) "deflate") */ if (buffer[2] != 8) { puts("Unsupported compression method"); return 0; } /* get CRC from GZIP trailer */ crc = GET_LONG(buffer + complen - 8); /* get uncompressed length from GZIP trailer */ unclen = GET_LONG(buffer + complen - 4); if (unclen > sizeof(buffer)) { puts("Uncompressed size too big"); return 0; } /* skip extra field, file name, comment and crc */ ptr = buffer + 10; if (buffer[3] & FEXTRA) ptr = buffer + 12 + GET_WORD(buffer + 10); if (buffer[3] & FNAME) while (*ptr++ != 0); if (buffer[3] & FCOMMENT) while (*ptr++ != 0); if (buffer[3] & FHCRC) ptr += 2; /* ** calculate length of raw "deflate" data ** (without the GZIP header and 8-byte trailer) */ complen -= (ptr - buffer) + 8; /* ** We will move the compressed data to the end of buffer[]. ** Thus the compressed data and the decompressed data (written from ** the beginning of buffer[]) may overlap, as long as the decompressed ** data doesn't go further than unread compressed data. ** ptr2 points to the beginning of compressed data at the end ** of buffer[]. */ ptr2 = buffer + sizeof(buffer) - complen; /* move the compressed data to end of buffer[] */ memmove(ptr2, ptr, complen); /* uncompress */ puts("Inflating..."); unclen2 = inflatemem(buffer, ptr2); /* verify uncompressed length */ if (unclen2 != (unsigned) unclen) { puts("Uncompressed size does not match"); return 0; } /* verify CRC */ puts("Calculating CRC..."); if (crc32(crc32(0L, Z_NULL, 0), buffer, unclen2) != crc) { puts("CRC mismatch"); return 0; } /* return number of uncompressed bytes */ return unclen2; } /* ** Get a filename from standard input. */ char* get_fname(void) { static char filename[100]; unsigned len; fgets(filename, sizeof(filename), stdin); len = strlen(filename); if (len >= 1 && filename[len - 1] == '\n') filename[len - 1] = '\0'; return filename; } int main(void) { FILE* fp; unsigned length; #ifdef __CC65__ /* allow user to read exit messages */ if (doesclrscrafterexit()) { atexit((void (*)) getchar); } #endif /* __CC65__ */ /* read GZIP file */ puts("GZIP file name:"); fp = fopen(get_fname(), "rb"); if (!fp) { puts("Can't open GZIP file"); return 1; } length = fread(buffer, 1, sizeof(buffer), fp); fclose(fp); if (length == sizeof(buffer)) { puts("File is too long"); return 1; } /* decompress */ length = uncompress_buffer(length); if (length == 0) return 1; /* write uncompressed file */ puts("Uncompressed file name:"); fp = fopen(get_fname(), "wb"); if (!fp) { puts("Can't create output file"); return 1; } if (fwrite(buffer, 1, length, fp) != length) { puts("Error while writing output file"); return 1; } fclose(fp); puts("Ok."); return 0; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/hello.c���������������������������������������������������������������������������0000664�0000000�0000000�00000003653�13473601511�0015127�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** Fancy hello world program using cc65. ** ** Ullrich von Bassewitz (ullrich@von-bassewitz.de) ** */ #include <stdlib.h> #include <string.h> #include <conio.h> #include <joystick.h> /*****************************************************************************/ /* Data */ /*****************************************************************************/ static const char Text [] = "Hello world!"; /*****************************************************************************/ /* Code */ /*****************************************************************************/ int main (void) { unsigned char XSize, YSize; /* Set screen colors */ (void) textcolor (COLOR_WHITE); (void) bordercolor (COLOR_BLACK); (void) bgcolor (COLOR_BLACK); /* Clear the screen, put cursor in upper left corner */ clrscr (); /* Ask for the screen size */ screensize (&XSize, &YSize); /* Draw a border around the screen */ /* Top line */ cputc (CH_ULCORNER); chline (XSize - 2); cputc (CH_URCORNER); /* Vertical line, left side */ cvlinexy (0, 1, YSize - 2); /* Bottom line */ cputc (CH_LLCORNER); chline (XSize - 2); cputc (CH_LRCORNER); /* Vertical line, right side */ cvlinexy (XSize - 1, 1, YSize - 2); /* Write the greeting in the mid of the screen */ gotoxy ((XSize - strlen (Text)) / 2, YSize / 2); cprintf ("%s", Text); #if defined(__NES__) || defined(__PCE__) || defined(__GAMATE__) || defined(__ATARI5200__) /* 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 */ cgetc (); #endif /* Clear the screen again */ clrscr (); /* Done */ return EXIT_SUCCESS; } �������������������������������������������������������������������������������������cc65-2.18/samples/mandelbrot.c����������������������������������������������������������������������0000664�0000000�0000000�00000007425�13473601511�0016154�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************\ ** mandelbrot sample program for cc65. ** ** ** ** (w) 2002 by groepaz/hitmen, TGI support by Stefan Haubenthal ** \*****************************************************************************/ #include <stdlib.h> #include <time.h> #include <conio.h> #include <tgi.h> #include <cc65.h> /* Graphics definitions */ #define SCREEN_X (tgi_getxres()) #define SCREEN_Y (tgi_getyres()) #define MAXCOL (tgi_getcolorcount()) #define maxiterations 32 #define fpshift (10) #define tofp(_x) ((_x)<<fpshift) #define fromfp(_x) ((_x)>>fpshift) #define fpabs(_x) (abs(_x)) #define mulfp(_a,_b) ((((signed long)_a)*(_b))>>fpshift) #define divfp(_a,_b) ((((signed long)_a)<<fpshift)/(_b)) /* Workaround missing clock stuff */ #ifdef __APPLE2__ # define clock() 0 # define CLK_TCK 1 #endif /* Use dynamically loaded driver by default */ #ifndef DYN_DRV # define DYN_DRV 1 #endif /* Use static local variables for speed */ #pragma static-locals (1); void mandelbrot (signed short x1, signed short y1, signed short x2, signed short y2) { register unsigned char count; register signed short r, r1, i; register signed short xs, ys, xx, yy; register signed short x, y; /* Calc stepwidth */ xs = ((x2 - x1) / (SCREEN_X)); ys = ((y2 - y1) / (SCREEN_Y)); yy = y1; for (y = 0; y < (SCREEN_Y); y++) { yy += ys; xx = x1; for (x = 0; x < (SCREEN_X); x++) { xx += xs; /* Do iterations */ r = 0; i = 0; for (count = 0; (count < maxiterations) && (fpabs (r) < tofp (2)) && (fpabs (i) < tofp (2)); ++count) { r1 = (mulfp (r, r) - mulfp (i, i)) + xx; /* i = (mulfp(mulfp(r,i),tofp(2)))+yy; */ i = (((signed long) r * i) >> (fpshift - 1)) + yy; r = r1; } if (count == maxiterations) { tgi_setcolor (0); } else { if (MAXCOL == 2) { tgi_setcolor (1); } else { tgi_setcolor (count % MAXCOL); } } /* Set pixel */ tgi_setpixel (x, y); } } } int main (void) { clock_t t; unsigned long sec; unsigned sec10; unsigned char err; clrscr (); #if DYN_DRV /* Load the graphics driver */ cprintf ("initializing... mompls\r\n"); tgi_load_driver (tgi_stddrv); #else /* Install the graphics driver */ tgi_install (tgi_static_stddrv); #endif err = tgi_geterror (); if (err != TGI_ERR_OK) { cprintf ("Error #%d initializing graphics.\r\n%s\r\n", err, tgi_geterrormsg (err)); if (doesclrscrafterexit ()) { cgetc (); } exit (EXIT_FAILURE); }; cprintf ("ok.\n\r"); /* Initialize graphics */ tgi_init (); tgi_clear (); t = clock (); /* Calc mandelbrot set */ mandelbrot (tofp (-2), tofp (-2), tofp (2), tofp (2)); t = clock () - t; /* Fetch the character from the keyboard buffer and discard it */ cgetc (); /* Shut down gfx mode and return to textmode */ tgi_done (); /* Calculate stats */ sec = (t * 10) / CLK_TCK; sec10 = sec % 10; sec /= 10; /* Output stats */ cprintf ("time : %lu.%us\n\r", sec, sec10); if (doesclrscrafterexit ()) { /* Wait for a key, then end */ cputs ("Press any key when done...\n\r"); cgetc (); } /* Done */ return EXIT_SUCCESS; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/mousedemo.c�����������������������������������������������������������������������0000664�0000000�0000000�00000016356�13473601511�0016025�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** Demo program for mouse usage. ** Supports the C64/C128/CBM510/Atari/Apple2. ** ** 2001-09-13, Ullrich von Bassewitz ** 2013-09-05, Greg King ** */ #include <stdbool.h> #include <stdlib.h> #include <string.h> #include <mouse.h> #include <pen.h> #include <conio.h> #include <ctype.h> #include <dbg.h> #include <cc65.h> #define max(a,b) (((a) > (b)) ? (a) : (b)) #define min(a,b) (((a) < (b)) ? (a) : (b)) #ifdef MOUSE_DRIVER /* A statically linked driver was named on the compiler's command line. ** Make sure that it is used instead of a dynamic one. */ # undef DYN_DRV # define DYN_DRV 0 #else /* Use a dynamically loaded driver, by default. */ # ifndef DYN_DRV # define DYN_DRV 1 # endif #endif #ifdef __CBM__ /* Set dark-on-light colors. */ const unsigned char mouse_def_pointercolor = COLOR_BLACK; #endif static void __fastcall__ CheckError (const char* S, unsigned char Error) { if (Error != MOUSE_ERR_OK) { cprintf ("\n%s: %s(%u)\r\n", S, mouse_geterrormsg (Error), Error); /* Wait for a key-press, so that some platforms can show the error ** message before they remove the current screen. */ if (doesclrscrafterexit ()) { cgetc (); } exit (EXIT_FAILURE); } } #if DYN_DRV /* Points to the dynamic driver's name. */ static const char *mouse_name; static void DoWarning (void) /* Warn the user that a driver is needed for this program. */ { cprintf ("Warning: This program needs\r\n" "the driver with the name\r\n" " %s\r\n" "on a disk! Press 'y' if you have it;\r\n" "or, any other key to exit.\r\n", mouse_stddrv); if (tolower (cgetc ()) != 'y') { exit (EXIT_SUCCESS); } cprintf ("OK. Please wait patiently...\r\n"); } #endif static void __fastcall__ ShowState (unsigned char Jailed, unsigned char Invisible) /* Display jail and cursor states. */ { cclearxy (0, 7, 32); gotoxy (0, 7); cprintf ("Pointer is %svisible%s.", Invisible? "in" : "", Jailed? " and jailed" : ""); } #if DYN_DRV int main (int argc, char *argv[]) #else int main (void) #endif { struct mouse_info info; struct mouse_box full_box, small_box; unsigned char width, height; char C; bool Invisible = true, Done = false, Jailed = false; /* Initialize the debugger */ DbgInit (0); /* Set dark-on-light colors. Clear the screen. */ #ifdef __CBM__ (void) bordercolor (COLOR_GRAY2); (void) bgcolor (COLOR_WHITE); (void) textcolor (COLOR_GRAY1); #else (void) bordercolor (COLOR_BLUE); (void) bgcolor (COLOR_WHITE); (void) textcolor (COLOR_BLACK); #endif cursor (0); clrscr (); /* 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. ** (Other drivers will ignore this.) */ #if defined(__C64__) || defined(__C128__) || defined(__CBM510__) pen_adjust ("pen.dat"); #endif #if DYN_DRV /* If a dynamically loadable driver is named on the command line, ** then use that driver instead of the standard one. */ if (argc > 1) { mouse_name = argv[1]; } else { /* Output a warning about the standard driver that is needed. */ DoWarning (); mouse_name = mouse_stddrv; } /* Load and install the driver. */ CheckError ("mouse_load_driver", mouse_load_driver (&mouse_def_callbacks, mouse_name)); #else /* Install the driver. */ CheckError ("mouse_install", mouse_install (&mouse_def_callbacks, # ifdef MOUSE_DRIVER MOUSE_DRIVER # else mouse_static_stddrv # endif )); #endif /* Get the initial bounding box. */ mouse_getbox (&full_box); screensize (&width, &height); top: clrscr (); /* Print a help line */ cputs (" d)ebug h)ide q)uit s)how j)ail"); /* Put a cross at the center of the screen. */ gotoxy (width / 2 - 3, height / 2 - 1); #if defined(__CBM__) cprintf ("%3u,%3u\r\n%*s\xDB", width / 2 * 8 + 4, height / 2 * 8 + 4, width / 2, ""); #else cprintf ("%3u,%3u\r\n%*s+", width / 2 * 8 + 4, height / 2 * 8 + 4, width / 2, ""); #endif /* Test loop */ ShowState (Jailed, Invisible); do { /* Get the current co-ordinates and button states; and, print them. */ mouse_info (&info); gotoxy (0, 2); cprintf (" X = %3d\r\n", info.pos.x); cprintf (" Y = %3d\r\n", info.pos.y); cprintf (" B1 = %c\r\n", (info.buttons & MOUSE_BTN_LEFT) ? #ifdef __CBM__ 0x5F #else 'v' #endif : '^'); cprintf (" B2 = %c", (info.buttons & MOUSE_BTN_RIGHT) ? #ifdef __CBM__ 0x5F #else 'v' #endif : '^'); /* Handle user input */ if (kbhit ()) { cclearxy (1, 9, 23); switch (tolower (C = cgetc ())) { case 'd': BREAK(); /* The debugger might have changed the colors. ** Restore them. */ #ifdef __CBM__ (void) bordercolor (COLOR_GRAY2); (void) bgcolor (COLOR_WHITE); (void) textcolor (COLOR_GRAY1); #else (void) bordercolor (COLOR_BLUE); (void) bgcolor (COLOR_WHITE); (void) textcolor (COLOR_BLACK); #endif /* The debugger changed the screen; restore it. */ goto top; case 'h': mouse_hide (); ShowState (Jailed, ++Invisible); break; case 'j': if (Jailed) { mouse_setbox (&full_box); Jailed = false; } else { small_box.minx = max (info.pos.x - 10, full_box.minx); small_box.miny = max (info.pos.y - 10, full_box.miny); small_box.maxx = min (info.pos.x + 10, full_box.maxx); small_box.maxy = min (info.pos.y + 10, full_box.maxy); mouse_setbox (&small_box); Jailed = true; } ShowState (Jailed, Invisible); break; case 's': mouse_show (); if (Invisible) { ShowState (Jailed, --Invisible); } break; case 'q': Done = true; break; default: gotoxy (1, 9); cprintf ("Spurious character: $%02X", C); } } } while (!Done); #if DYN_DRV /* Uninstall and unload the driver. */ CheckError ("mouse_unload", mouse_unload ()); #else /* Uninstall the static driver. */ CheckError ("mouse_uninstall", mouse_uninstall ()); #endif /* Say goodbye */ cputsxy (0, height / 2 + 3, "Goodbye!"); return EXIT_SUCCESS; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/multidemo.c�����������������������������������������������������������������������0000664�0000000�0000000�00000014240�13473601511�0016015�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** Extended memory overlay demo program. ** ** Shows how to combine multiple cc65 features ** incl. overlays and extended memory drivers. ** ** 2012-17-07, Oliver Schmidt (ol.sc@web.de) ** */ #include <string.h> #include <stdio.h> #include <stdlib.h> #include <dirent.h> #include <em.h> #include <cc65.h> #ifndef __CBM__ #include <fcntl.h> #include <unistd.h> #else #include <cbm.h> #include <device.h> #endif /* The symbols _OVERLAY?_LOAD__ and _OVERLAY?_SIZE__ were generated by the ** linker. They contain the overlay area address and size specific to a ** certain program. */ extern void _OVERLAY1_LOAD__[], _OVERLAY1_SIZE__[]; extern void _OVERLAY2_LOAD__[], _OVERLAY2_SIZE__[]; extern void _OVERLAY3_LOAD__[], _OVERLAY3_SIZE__[]; struct { char *name; int page; void *addr; unsigned size; } overlay[] = {{"multdemo.1", -1, _OVERLAY1_LOAD__, (unsigned)_OVERLAY1_SIZE__}, {"multdemo.2", -1, _OVERLAY2_LOAD__, (unsigned)_OVERLAY2_SIZE__}, {"multdemo.3", -1, _OVERLAY3_LOAD__, (unsigned)_OVERLAY3_SIZE__}}; /* Functions resident in an overlay can call back functions resident in the ** main program at any time without any precautions. The function log() is ** an example for such a function resident in the main program. */ void log (char *msg) { /* Functions resident in an overlay can access all program variables and ** constants at any time without any precautions because those are never ** placed in overlays. The string constant below is an example for such ** a constant resident in the main program. */ printf ("Log: %s\n", msg); } /* In a real-world overlay program one would probably not use a #pragma but ** rather place all the code of certain source files into the overlay by ** compiling them with --code-name OVERLAY1. */ #pragma code-name (push, "OVERLAY1"); void foo (void) { log ("Calling main from overlay 1"); } #pragma code-name (pop); #pragma code-name (push, "OVERLAY2"); void bar (void) { log ("Calling main from overlay 2"); } #pragma code-name (pop); #pragma code-name (push, "OVERLAY3"); void foobar (void) { log ("Calling main from overlay 3"); } #pragma code-name(pop); unsigned char loademdriver (void) { DIR *dir; struct dirent *ent; char *emd = NULL; unsigned char max = 0; unsigned char num; printf ("Dbg: Searching for emdrivers\n"); dir = opendir ("."); if (!dir) { log ("Opening directory failed"); return 0; } while (ent = readdir (dir)) { char *ext; if (!_DE_ISREG (ent->d_type)) { continue; } ext = strrchr (ent->d_name, '.'); if (!ext || strcasecmp (ext, ".emd")) { printf ("Dbg: Skipping file %s\n", ent->d_name); continue; } printf ("Dbg: Memorizing file %s\n", ent->d_name); emd = realloc (emd, FILENAME_MAX * (max + 1)); strcpy (emd + FILENAME_MAX * max++, ent->d_name); } closedir (dir); for (num = 0; num < max; ++num) { char *drv; drv = emd + FILENAME_MAX * num; printf ("Dbg: Trying emdriver %s\n", drv); if (em_load_driver (drv) == EM_ERR_OK) { printf ("Dbg: Loaded emdriver %s\n", drv); free (emd); return 1; } printf ("Dbg: Emdriver %s failed\n", drv); } free (emd); return 0; } unsigned char loadoverlay (unsigned char num) { if (overlay[num - 1].page < 0) { #ifndef __CBM__ int file; printf ("Dbg: Loading overlay %u from file\n", num); file = open (overlay[num - 1].name, O_RDONLY); if (file == -1) { log ("Opening overlay file failed"); return 0; } read (file, overlay[num - 1].addr, overlay[num - 1].size); close (file); #else if (cbm_load (overlay[num - 1].name, getcurrentdevice (), NULL) == 0) { log ("Loading overlay file failed"); return 0; } #endif return 1; } else { struct em_copy copyinfo; printf ("Dbg: Loading overlay %u from memory\n", num); copyinfo.offs = 0; copyinfo.page = overlay[num - 1].page; copyinfo.buf = overlay[num - 1].addr; copyinfo.count = overlay[num - 1].size; em_copyfrom (©info); return 1; } } void copyoverlays (void) { unsigned page = 0; unsigned char num; for (num = 0; num < sizeof (overlay) / sizeof (overlay[0]); ++num) { struct em_copy copyinfo; unsigned size = (overlay[num].size + EM_PAGE_SIZE - 1) / EM_PAGE_SIZE; if (size > em_pagecount () - page) { printf ("Dbg: Not enough memory for overlay %u\n", num + 1); continue; } if (loadoverlay (num + 1) == 0) continue; copyinfo.offs = 0; copyinfo.page = page; copyinfo.buf = overlay[num].addr; copyinfo.count = overlay[num].size; em_copyto (©info); overlay[num].page = page; page += size; printf ("Dbg: Stored overlay %u in pages %u-%u\n", num + 1, overlay[num].page, page - 1); } } void main (void) { log ("Loading extended memory driver"); if (loademdriver ()) { log ("Copying overlays into ext. memory"); copyoverlays (); } else { log ("No extended memory driver found"); } log ("Press any key..."); getchar (); if (loadoverlay (1)) { log ("Calling overlay 1 from main"); /* The linker makes sure that the call to foo() ends up at the right mem ** addr. However it's up to user to make sure that the - right - overlay ** is actually loaded before making the the call. */ foo (); } /* Replacing one overlay with another one can only happen from the main ** program. This implies that an overlay can never load another overlay. */ if (loadoverlay (2)) { log ("Calling overlay 2 from main"); bar (); } if (loadoverlay (3)) { log ("Calling overlay 3 from main"); foobar (); } if (doesclrscrafterexit ()) { log ("Press any key..."); getchar (); } } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/nachtm.c��������������������������������������������������������������������������0000664�0000000�0000000�00000210206�13473601511�0015270�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** "Eine kleine Nachtmusik" by Wolfgang Amadeus Mozart, KV 525 ** ** First version in 1987 by ** Joachim von Bassewitz (joachim@von-bassewitz.de) and ** Ullrich von Bassewitz (ullrich@von-bassewitz.de). ** ** C conversion in 1998 by ** Ullrich von Bassewitz (ullrich@von-bassewitz.de) ** */ #include <stdio.h> #include <string.h> #include <time.h> #include <conio.h> #include <cbm.h> #include <dbg.h> /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Tables with voice data. ** ** Bit Description ** ------------------------------------------- ** 15 Pause bit. ** 12-14 Octave ** 8-11 Tone (index into frequency table) ** 7 Unused. Was thought as a control bit in the original version to ** change SID parameters, but this was never implemented. ** 0-6 Length of the tone in ticks. ** */ static unsigned Voice1 [] = { 0x5708,0x8004,0x5204,0x5708,0x8004,0x5204,0x5704,0x5204,0x5704,0x5B04, 0x6208,0x8008,0x6008,0x8004,0x5904,0x6008,0x8004,0x5904,0x6004,0x5904, 0x5604,0x5904,0x5208,0x8008,0x5704,0x8004,0x570C,0x5B01,0x5B01,0x5B01, 0x5B01,0x5904,0x5704,0x5704,0x5604,0x560C,0x5901,0x5901,0x5901,0x5901, 0x6004,0x5604,0x5901,0x5901,0x5901,0x5901,0x5704,0x570C,0x5B01,0x5B01, 0x5B01,0x5B01,0x5904,0x5704,0x5701,0x5701,0x5701,0x5701,0x5604,0x560C, 0x5901,0x5901,0x5901,0x5901,0x6004,0x5604,0x5704,0x5704,0x5601,0x5601, 0x5601,0x5601,0x5401,0x5401,0x5602,0x5704,0x5704,0x5901,0x5901,0x5901, 0x5901,0x5701,0x5701,0x5902,0x5B04,0x5B04,0x6001,0x6001,0x6001,0x6001, 0x5B01,0x5B01,0x6001,0x6001,0x6208,0x8008,0x5201,0x5201,0x5201,0x5201, 0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201, 0x5201,0x5201,0x5410,0x5008,0x5008,0x4B08,0x4B08,0x4908,0x4908,0x4701, 0x4701,0x4701,0x4701,0x4604,0x4404,0x4604,0x4704,0x8004,0x4904,0x8004, 0x4B04,0x800C,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201, 0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5410,0x5201, 0x5201,0x5201,0x5201,0x5004,0x5004,0x5004,0x5001,0x5001,0x5001,0x5001, 0x4B04,0x4B04,0x4B04,0x4B01,0x4B01,0x4B01,0x4B01,0x4904,0x4904,0x4904, 0x4701,0x4701,0x4701,0x4701,0x4601,0x4601,0x4601,0x4601,0x4401,0x4401, 0x4401,0x4401,0x4604,0x4701,0x4701,0x4701,0x4701,0x4701,0x4701,0x4701, 0x4701,0x4701,0x4701,0x4701,0x4701,0x4701,0x4701,0x4701,0x4701,0x4704, 0x4701,0x4701,0x4601,0x4701,0x4901,0x4901,0x4901,0x4901,0x4604,0x4B01, 0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01, 0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B04,0x4B01,0x4B01,0x4901,0x4B01, 0x5001,0x5001,0x5001,0x5001,0x4904,0x5210,0x5408,0x5608,0x5708,0x5908, 0x5B08,0x6108,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201, 0x6201,0x6201,0x6201,0x6201,0x5904,0x6101,0x6101,0x6101,0x6101,0x6101, 0x6101,0x5902,0x6101,0x6101,0x6101,0x6101,0x6101,0x6101,0x5902,0x6201, 0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201, 0x6201,0x5904,0x6101,0x6101,0x6101,0x6101,0x6101,0x6101,0x5902,0x6101, 0x6101,0x6101,0x6101,0x6101,0x6101,0x5902,0x6204,0x6208,0x6208,0x6208, 0x6201,0x6201,0x6201,0x6201,0x6204,0x6208,0x6208,0x6208,0x6204,0x6104, 0x5904,0x6204,0x5904,0x6004,0x5904,0x6204,0x5904,0x6104,0x4904,0x4904, 0x4904,0x4908,0x8008,0x590A,0x5702,0x5602,0x5402,0x5204,0x8004,0x5B04, 0x8004,0x5704,0x8004,0x5404,0x8004,0x5B04,0x800C,0x5601,0x5601,0x5601, 0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5401,0x5401,0x5201, 0x5201,0x5101,0x5101,0x4B04,0x8004,0x5704,0x8004,0x5601,0x5601,0x5601, 0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601, 0x5601,0x5601,0x5601,0x5408,0x8008,0x5901,0x5901,0x5901,0x5901,0x5901, 0x5901,0x5901,0x5901,0x5901,0x5901,0x5701,0x5701,0x5601,0x5601,0x5401, 0x5401,0x5204,0x8004,0x5B04,0x8004,0x5704,0x8004,0x5404,0x8004,0x5908, 0x8004,0x5704,0x6104,0x6204,0x8004,0x5B04,0x5B01,0x5B01,0x5B01,0x5B01, 0x5904,0x8004,0x5104,0x5208,0x8004,0x5904,0x6201,0x6201,0x6201,0x6201, 0x6101,0x6101,0x6101,0x6101,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x5B01, 0x5B01,0x5B01,0x5B01,0x5904,0x8004,0x5904,0x5904,0x5904,0x5904,0x5904, 0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x8004,0x5904,0x6204,0x6104,0x5B04, 0x5904,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x8004,0x5904,0x5904,0x5904, 0x5904,0x5904,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x8008,0x5B0A,0x5901, 0x5901,0x5701,0x5701,0x5601,0x5601,0x5708,0x8008,0x590A,0x5701,0x5701, 0x5601,0x5601,0x5401,0x5401,0x5608,0x8008,0x5B01,0x5B01,0x5B01,0x5B01, 0x6101,0x6101,0x6201,0x6201,0x6104,0x5B04,0x5B01,0x5B01,0x5B01,0x5B01, 0x5904,0x5604,0x5904,0x5901,0x5901,0x5901,0x5901,0x5704,0x5604,0x5404, 0x5208,0x8004,0x5904,0x6201,0x6201,0x6201,0x6201,0x6101,0x6101,0x6101, 0x6101,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x5B01,0x5B01,0x5B01,0x5B01, 0x5904,0x8004,0x5904,0x5904,0x5904,0x5904,0x5904,0x5B01,0x5B01,0x5B01, 0x5B01,0x5904,0x8004,0x5904,0x6201,0x6201,0x6201,0x6201,0x6101,0x6101, 0x6101,0x6101,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x5B01,0x5B01,0x5B01, 0x5B01,0x5904,0x8004,0x5904,0x5904,0x5904,0x5904,0x5904,0x5B01,0x5B01, 0x5B01,0x5B01,0x5904,0x8008,0x5B0A,0x5901,0x5901,0x5701,0x5701,0x5601, 0x5601,0x5708,0x8008,0x590A,0x5701,0x5701,0x5601,0x5601,0x5401,0x5401, 0x5608,0x8008,0x5B01,0x5B01,0x5B01,0x5B01,0x6101,0x6101,0x6201,0x6201, 0x6104,0x5B04,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x5604,0x5904,0x5901, 0x5901,0x5901,0x5901,0x5704,0x5604,0x5404,0x5204,0x4904,0x4B04,0x5104, 0x5204,0x5204,0x5401,0x5401,0x5401,0x5401,0x5201,0x5201,0x5401,0x5401, 0x5604,0x5104,0x5204,0x5404,0x5604,0x5604,0x5701,0x5701,0x5701,0x5701, 0x5601,0x5601,0x5701,0x5701,0x5904,0x5904,0x5A04,0x5802,0x5A02,0x5B08, 0x8008,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01, 0x4B01,0x4B01,0x4B01,0x5404,0x5201,0x5201,0x5201,0x5201,0x5101,0x5101, 0x5101,0x5101,0x5B01,0x5B01,0x5B01,0x5B01,0x5901,0x5901,0x5901,0x5901, 0x6204,0x8004,0x6604,0x8004,0x6204,0x800C,0x5708,0x8004,0x5204,0x5708, 0x8004,0x5204,0x5704,0x5204,0x5704,0x5B04,0x6208,0x8008,0x6008,0x8004, 0x5904,0x6008,0x8004,0x5904,0x6004,0x5904,0x5604,0x5904,0x5208,0x8008, 0x5704,0x8004,0x570C,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x5704,0x5704, 0x5604,0x560C,0x5901,0x5901,0x5901,0x5901,0x6004,0x5604,0x5901,0x5901, 0x5901,0x5901,0x5704,0x570C,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x5704, 0x5701,0x5701,0x5701,0x5701,0x5604,0x560C,0x5901,0x5901,0x5901,0x5901, 0x6004,0x5604,0x5704,0x5704,0x5601,0x5601,0x5601,0x5601,0x5401,0x5401, 0x5602,0x5704,0x5704,0x5901,0x5901,0x5901,0x5901,0x5701,0x5701,0x5902, 0x5B04,0x5B04,0x6001,0x6001,0x6001,0x6001,0x5B01,0x5B01,0x6001,0x6001, 0x6208,0x8008,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201, 0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5410,0x5008, 0x5008,0x4B08,0x4B08,0x4908,0x4908,0x4701,0x4701,0x4701,0x4701,0x4604, 0x4404,0x4604,0x4704,0x8004,0x4904,0x8004,0x4B04,0x800C,0x5201,0x5201, 0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201, 0x5201,0x5201,0x5201,0x5201,0x5410,0x5201,0x5201,0x5201,0x5201,0x5004, 0x5004,0x5004,0x5001,0x5001,0x5001,0x5001,0x4B04,0x4B04,0x4B04,0x4B01, 0x4B01,0x4B01,0x4B01,0x4904,0x4904,0x4904,0x4701,0x4701,0x4701,0x4701, 0x4601,0x4601,0x4601,0x4601,0x4401,0x4401,0x4401,0x4401,0x4604,0x4701, 0x4701,0x4701,0x4701,0x4701,0x4701,0x4701,0x4701,0x4701,0x4701,0x4701, 0x4701,0x4701,0x4701,0x4701,0x4701,0x4704,0x4701,0x4701,0x4601,0x4701, 0x4901,0x4901,0x4901,0x4901,0x4604,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01, 0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01, 0x4B01,0x4B04,0x4B01,0x4B01,0x4901,0x4B01,0x5001,0x5001,0x5001,0x5001, 0x4904,0x5210,0x5408,0x5608,0x5708,0x5908,0x5B08,0x6108,0x6201,0x6201, 0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201, 0x5904,0x6101,0x6101,0x6101,0x6101,0x6101,0x6101,0x5902,0x6101,0x6101, 0x6101,0x6101,0x6101,0x6101,0x5902,0x6201,0x6201,0x6201,0x6201,0x6201, 0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x5904,0x6101,0x6101, 0x6101,0x6101,0x6101,0x6101,0x5902,0x6101,0x6101,0x6101,0x6101,0x6101, 0x6101,0x5902,0x6204,0x6208,0x6208,0x6208,0x6201,0x6201,0x6201,0x6201, 0x6204,0x6208,0x6208,0x6208,0x6204,0x6104,0x5904,0x6204,0x5904,0x6004, 0x5904,0x6204,0x5904,0x6104,0x4904,0x4904,0x4904,0x4908,0x8008,0x590A, 0x5702,0x5602,0x5402,0x5204,0x8004,0x5B04,0x8004,0x5704,0x8004,0x5404, 0x8004,0x5B04,0x800C,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601, 0x5601,0x5601,0x5601,0x5401,0x5401,0x5201,0x5201,0x5101,0x5101,0x4B04, 0x8004,0x5704,0x8004,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601, 0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5408, 0x8008,0x5901,0x5901,0x5901,0x5901,0x5901,0x5901,0x5901,0x5901,0x5901, 0x5901,0x5701,0x5701,0x5601,0x5601,0x5401,0x5401,0x5204,0x8004,0x5B04, 0x8004,0x5704,0x8004,0x5404,0x8004,0x5908,0x8004,0x5704,0x6104,0x6204, 0x8004,0x5B04,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x8004,0x5104,0x5208, 0x8004,0x5904,0x6201,0x6201,0x6201,0x6201,0x6101,0x6101,0x6101,0x6101, 0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x5B01,0x5B01,0x5B01,0x5B01,0x5904, 0x8004,0x5904,0x5904,0x5904,0x5904,0x5904,0x5B01,0x5B01,0x5B01,0x5B01, 0x5904,0x8004,0x5904,0x6204,0x6104,0x5B04,0x5904,0x5B01,0x5B01,0x5B01, 0x5B01,0x5904,0x8004,0x5904,0x5904,0x5904,0x5904,0x5904,0x5B01,0x5B01, 0x5B01,0x5B01,0x5904,0x8008,0x5B0A,0x5901,0x5901,0x5701,0x5701,0x5601, 0x5601,0x5708,0x8008,0x590A,0x5701,0x5701,0x5601,0x5601,0x5401,0x5401, 0x5608,0x8008,0x5B01,0x5B01,0x5B01,0x5B01,0x6101,0x6101,0x6201,0x6201, 0x6104,0x5B04,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x5604,0x5904,0x5901, 0x5901,0x5901,0x5901,0x5704,0x5604,0x5404,0x5208,0x8004,0x5904,0x6201, 0x6201,0x6201,0x6201,0x6101,0x6101,0x6101,0x6101,0x5B01,0x5B01,0x5B01, 0x5B01,0x5904,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x8004,0x5904,0x5904, 0x5904,0x5904,0x5904,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x8004,0x5904, 0x6201,0x6201,0x6201,0x6201,0x6101,0x6101,0x6101,0x6101,0x5B01,0x5B01, 0x5B01,0x5B01,0x5904,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x8004,0x5904, 0x5904,0x5904,0x5904,0x5904,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x8008, 0x5B0A,0x5901,0x5901,0x5701,0x5701,0x5601,0x5601,0x5708,0x8008,0x590A, 0x5701,0x5701,0x5601,0x5601,0x5401,0x5401,0x5608,0x8008,0x5B01,0x5B01, 0x5B01,0x5B01,0x6101,0x6101,0x6201,0x6201,0x6104,0x5B04,0x5B01,0x5B01, 0x5B01,0x5B01,0x5904,0x5604,0x5904,0x5901,0x5901,0x5901,0x5901,0x5704, 0x5604,0x5404,0x5204,0x4904,0x4B04,0x5104,0x5204,0x5204,0x5401,0x5401, 0x5401,0x5401,0x5201,0x5201,0x5401,0x5401,0x5604,0x5104,0x5204,0x5404, 0x5604,0x5604,0x5701,0x5701,0x5701,0x5701,0x5601,0x5601,0x5701,0x5701, 0x5904,0x5904,0x5A04,0x5802,0x5A02,0x5B08,0x8008,0x4B01,0x4B01,0x4B01, 0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x5404, 0x5201,0x5201,0x5201,0x5201,0x5101,0x5101,0x5101,0x5101,0x5B01,0x5B01, 0x5B01,0x5B01,0x5901,0x5901,0x5901,0x5901,0x6204,0x8004,0x6604,0x8004, 0x6204,0x800C,0x5208,0x8004,0x4904,0x5208,0x8004,0x4904,0x5204,0x4904, 0x5204,0x5604,0x5908,0x8008,0x5908,0x8004,0x5604,0x5908,0x8004,0x5604, 0x5904,0x5604,0x5304,0x5604,0x4B08,0x8014,0x5704,0x6001,0x6001,0x6001, 0x6001,0x5B01,0x5B01,0x5B01,0x5B01,0x5901,0x5901,0x5901,0x5901,0x5704, 0x5901,0x5901,0x5901,0x5901,0x5704,0x8004,0x5704,0x5704,0x5704,0x5704, 0x5704,0x5901,0x5901,0x5901,0x5901,0x5704,0x8004,0x5704,0x6001,0x6001, 0x6001,0x6001,0x5B01,0x5B01,0x5B01,0x5B01,0x5901,0x5901,0x5901,0x5901, 0x5704,0x5901,0x5901,0x5901,0x5901,0x5704,0x8004,0x5704,0x5704,0x5704, 0x5704,0x5704,0x5901,0x5901,0x5901,0x5901,0x5704,0x8004,0x5704,0x6001, 0x6001,0x6001,0x6001,0x5B01,0x5B01,0x5B01,0x5B01,0x5901,0x5901,0x5901, 0x5901,0x5704,0x5901,0x5901,0x5901,0x5901,0x5804,0x8004,0x5804,0x5804, 0x5804,0x5804,0x5804,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x8004,0x5904, 0x6001,0x6001,0x6001,0x6001,0x5A01,0x5A01,0x5A01,0x5A01,0x5901,0x5901, 0x5901,0x5901,0x5704,0x5701,0x5701,0x5701,0x5701,0x5604,0x8004,0x5604, 0x5604,0x5604,0x5604,0x5604,0x5901,0x5901,0x5901,0x5901,0x5704,0x8004, 0x5304,0x5704,0x5504,0x5304,0x5204,0x5201,0x5201,0x5201,0x5201,0x5104, 0x8004,0x5104,0x5104,0x5104,0x5104,0x5104,0x5401,0x5401,0x5401,0x5401, 0x5204,0x8004,0x4201,0x4201,0x4201,0x4201,0x4401,0x4401,0x4401,0x4401, 0x4601,0x4601,0x4601,0x4601,0x4701,0x4701,0x4701,0x4701,0x4901,0x4901, 0x4901,0x4901,0x5001,0x5001,0x5001,0x5001,0x4A04,0x8004,0x4601,0x4601, 0x4601,0x4601,0x4701,0x4701,0x4701,0x4701,0x4901,0x4901,0x4901,0x4901, 0x4A01,0x4A01,0x4A01,0x4A01,0x5101,0x5101,0x5101,0x5101,0x5401,0x5401, 0x5401,0x5401,0x5204,0x8004,0x5201,0x5201,0x5201,0x5201,0x5401,0x5401, 0x5401,0x5401,0x5601,0x5601,0x5601,0x5601,0x5701,0x5701,0x5701,0x5701, 0x5901,0x5901,0x5901,0x5901,0x5A01,0x5A01,0x5A01,0x5A01,0x5A01,0x5A01, 0x5A01,0x5A01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01, 0x6001,0x6001,0x6001,0x6001,0x6001,0x6001,0x6001,0x6001,0x6108,0x6201, 0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201, 0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201, 0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201, 0x6201,0x6210,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601, 0x5601,0x5601,0x5601,0x5601,0x5401,0x5401,0x5602,0x5708,0x8004,0x5204, 0x5708,0x8004,0x5204,0x5704,0x5204,0x5704,0x5B04,0x6208,0x8008,0x6008, 0x8004,0x5904,0x6008,0x8004,0x5904,0x6004,0x5904,0x5604,0x5904,0x5208, 0x8008,0x5704,0x8004,0x570C,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x5704, 0x5701,0x5701,0x5701,0x5701,0x5604,0x560C,0x5901,0x5901,0x5901,0x5901, 0x6004,0x5604,0x5901,0x5901,0x5901,0x5901,0x5704,0x570C,0x5B01,0x5B01, 0x5B01,0x5B01,0x5904,0x5704,0x5701,0x5701,0x5701,0x5701,0x5604,0x560C, 0x5901,0x5901,0x5901,0x5901,0x6004,0x5604,0x5704,0x5704,0x5601,0x5601, 0x5601,0x5601,0x5401,0x5401,0x5602,0x5704,0x5704,0x5901,0x5901,0x5901, 0x5901,0x5701,0x5701,0x5902,0x5B04,0x5B04,0x6001,0x6001,0x6001,0x6001, 0x5B01,0x5B01,0x6001,0x6001,0x6208,0x8008,0x5201,0x5201,0x5201,0x5201, 0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201, 0x5201,0x5201,0x5410,0x5008,0x5008,0x4B08,0x4B08,0x4908,0x4908,0x4701, 0x4701,0x4701,0x4701,0x4604,0x4404,0x4604,0x4704,0x8004,0x4904,0x8004, 0x4B04,0x800C,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201, 0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5410,0x5201, 0x5201,0x5201,0x5201,0x5004,0x5004,0x5004,0x5001,0x5001,0x5001,0x5001, 0x4B04,0x4B04,0x4B04,0x4B01,0x4B01,0x4B01,0x4B01,0x4904,0x4904,0x4904, 0x4701,0x4701,0x4701,0x4701,0x4604,0x4404,0x4604,0x4714,0x4701,0x4701, 0x4601,0x4701,0x4901,0x4901,0x4901,0x4901,0x4604,0x4B14,0x4B01,0x4B01, 0x4901,0x4B01,0x5001,0x5001,0x5001,0x5001,0x4904,0x5210,0x5408,0x5608, 0x5708,0x5908,0x5B08,0x5108,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201, 0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x5904,0x6101,0x6101,0x6101, 0x6101,0x6101,0x6101,0x5902,0x5101,0x5101,0x5101,0x5101,0x5101,0x5101, 0x5902,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201, 0x6201,0x6201,0x6201,0x5904,0x6101,0x6101,0x6101,0x6101,0x6101,0x6101, 0x5902,0x5101,0x5101,0x5101,0x5101,0x5101,0x5101,0x5902,0x6204,0x5904, 0x6104,0x5904,0x6204,0x5904,0x6104,0x5904,0x6204,0x4204,0x4204,0x4204, 0x4208,0x8008,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201, 0x5201,0x5201,0x5001,0x5001,0x4B01,0x4B01,0x4901,0x4901,0x4704,0x8004, 0x5404,0x8004,0x5004,0x8004,0x4904,0x8004,0x5204,0x800C,0x5B01,0x5B01, 0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5901,0x5901, 0x5701,0x5701,0x5601,0x5601,0x5404,0x8004,0x6004,0x8004,0x5B01,0x5B01, 0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01, 0x5B01,0x5B01,0x5B01,0x5B01,0x5908,0x8008,0x8004,0x6204,0x6204,0x6204, 0x6204,0x6204,0x6204,0x6204,0x6204,0x6204,0x6204,0x6204,0x6201,0x6201, 0x6201,0x6201,0x6001,0x6001,0x6001,0x6001,0x5901,0x5901,0x5901,0x5901, 0x5604,0x5601,0x5601,0x5601,0x5601,0x5704,0x8004,0x5404,0x5401,0x5401, 0x5401,0x5401,0x5204,0x8004,0x4604,0x4708,0x8004,0x5204,0x5701,0x5701, 0x5701,0x5701,0x5601,0x5601,0x5601,0x5601,0x5401,0x5401,0x5401,0x5401, 0x5204,0x5401,0x5401,0x5401,0x5401,0x5204,0x8004,0x5204,0x5204,0x5204, 0x5204,0x5204,0x5401,0x5401,0x5401,0x5401,0x5204,0x8004,0x5204,0x5704, 0x5604,0x5404,0x5204,0x5401,0x5401,0x5401,0x5401,0x5204,0x8004,0x5204, 0x5204,0x5204,0x5204,0x5204,0x5401,0x5401,0x5401,0x5401,0x5204,0x8008, 0x540A,0x5201,0x5201,0x5001,0x5001,0x4B01,0x4B01,0x5008,0x8008,0x520A, 0x5001,0x5001,0x4B01,0x4B01,0x4901,0x4901,0x4B08,0x8008,0x5401,0x5401, 0x5401,0x5401,0x5601,0x5601,0x5701,0x5701,0x5604,0x5404,0x5401,0x5401, 0x5401,0x5401,0x5204,0x4B04,0x5204,0x5201,0x5201,0x5201,0x5201,0x5004, 0x4B04,0x4904,0x4708,0x8004,0x5204,0x5701,0x5701,0x5701,0x5701,0x5601, 0x5601,0x5601,0x5601,0x5401,0x5401,0x5401,0x5401,0x5204,0x5401,0x5401, 0x5401,0x5401,0x5204,0x8004,0x5204,0x5204,0x5204,0x5204,0x5204,0x5401, 0x5401,0x5401,0x5401,0x5204,0x8004,0x5204,0x5701,0x5701,0x5701,0x5701, 0x5601,0x5601,0x5601,0x5601,0x5401,0x5401,0x5401,0x5401,0x5204,0x5401, 0x5401,0x5401,0x5401,0x5204,0x8004,0x5204,0x5204,0x5204,0x5204,0x5204, 0x5401,0x5401,0x5401,0x5401,0x5204,0x8008,0x640A,0x6201,0x6201,0x6001, 0x6001,0x5B01,0x5B01,0x6008,0x8008,0x620A,0x6001,0x6001,0x5B01,0x5B01, 0x5901,0x5901,0x5B08,0x8008,0x5401,0x5401,0x5401,0x5401,0x5601,0x5601, 0x5701,0x5701,0x5604,0x5404,0x5204,0x5704,0x5B04,0x6204,0x6201,0x6201, 0x6201,0x6201,0x6004,0x5B04,0x5904,0x5704,0x4204,0x4404,0x4604,0x4704, 0x4704,0x4901,0x4901,0x4901,0x4901,0x4701,0x4701,0x4901,0x4901,0x4B04, 0x4604,0x4704,0x4904,0x4B04,0x4B04,0x5001,0x5001,0x5001,0x5001,0x4B01, 0x4B01,0x5001,0x5001,0x5204,0x5204,0x5301,0x5301,0x5301,0x5301,0x5101, 0x5101,0x5301,0x5301,0x5408,0x8008,0x440C,0x4904,0x4704,0x4604,0x4404, 0x4204,0x5201,0x5201,0x5201,0x5201,0x5101,0x5101,0x5101,0x5101,0x5001, 0x5001,0x5001,0x5001,0x4B01,0x4B01,0x4B01,0x4B01,0x5201,0x5201,0x5201, 0x5201,0x5101,0x5101,0x5101,0x5101,0x5001,0x5001,0x5001,0x5001,0x4B04, 0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401, 0x4401,0x4401,0x4904,0x4701,0x4701,0x4701,0x4701,0x4601,0x4601,0x4601, 0x4601,0x4401,0x4401,0x4401,0x4401,0x4204,0x5201,0x5201,0x5201,0x5201, 0x5401,0x5401,0x5401,0x5401,0x5601,0x5601,0x5601,0x5601,0x5701,0x5701, 0x5701,0x5701,0x5201,0x5201,0x5201,0x5201,0x5401,0x5401,0x5401,0x5401, 0x5601,0x5601,0x5601,0x5601,0x5704,0x5908,0x8008,0x6208,0x8008,0x5708, 0x8004,0x5204,0x4B04,0x4704,0x4B04,0x5204,0x5704,0x5204,0x5704,0x5B04, 0x6208,0x5608,0x5708,0x8004,0x5204,0x4B04,0x4704,0x4B04,0x5204,0x5704, 0x5204,0x5704,0x5B04,0x6208,0x5608,0x5708,0x8008,0x5708,0x8008,0x5708, 0x4706,0x4702,0x4708,0x8008,0x5208,0x8004,0x4904,0x5208,0x8004,0x4904, 0x5204,0x4904,0x5204,0x5604,0x5908,0x8008,0x5908,0x8004,0x5604,0x5908, 0x8004,0x5604,0x5904,0x5604,0x5304,0x5604,0x4B08,0x8014,0x5704,0x6001, 0x6001,0x6001,0x6001,0x5B01,0x5B01,0x5B01,0x5B01,0x5901,0x5901,0x5901, 0x5901,0x5704,0x5901,0x5901,0x5901,0x5901,0x5704,0x8004,0x5704,0x5704, 0x5704,0x5704,0x5704,0x5901,0x5901,0x5901,0x5901,0x5704,0x8004,0x5704, 0x6001,0x6001,0x6001,0x6001,0x5B01,0x5B01,0x5B01,0x5B01,0x5901,0x5901, 0x5901,0x5901,0x5704,0x5901,0x5901,0x5901,0x5901,0x5704,0x8004,0x5704, 0x5704,0x5704,0x5704,0x5704,0x5901,0x5901,0x5901,0x5901,0x5704,0x8004, 0x5704,0x6001,0x6001,0x6001,0x6001,0x5B01,0x5B01,0x5B01,0x5B01,0x5901, 0x5901,0x5901,0x5901,0x5704,0x5901,0x5901,0x5901,0x5901,0x5804,0x8004, 0x5804,0x5804,0x5804,0x5804,0x5804,0x5B01,0x5B01,0x5B01,0x5B01,0x5904, 0x8004,0x5904,0x6001,0x6001,0x6001,0x6001,0x5A01,0x5A01,0x5A01,0x5A01, 0x5901,0x5901,0x5901,0x5901,0x5704,0x5701,0x5701,0x5701,0x5701,0x5604, 0x8004,0x5604,0x5604,0x5604,0x5604,0x5604,0x5901,0x5901,0x5901,0x5901, 0x5704,0x8004,0x5304,0x5704,0x5504,0x5304,0x5204,0x5201,0x5201,0x5201, 0x5201,0x5104,0x8004,0x5104,0x5104,0x5104,0x5104,0x5104,0x5401,0x5401, 0x5401,0x5401,0x5204,0x8004,0x4201,0x4201,0x4201,0x4201,0x4401,0x4401, 0x4401,0x4401,0x4601,0x4601,0x4601,0x4601,0x4701,0x4701,0x4701,0x4701, 0x4901,0x4901,0x4901,0x4901,0x5001,0x5001,0x5001,0x5001,0x4A04,0x8004, 0x4601,0x4601,0x4601,0x4601,0x4701,0x4701,0x4701,0x4701,0x4901,0x4901, 0x4901,0x4901,0x4A01,0x4A01,0x4A01,0x4A01,0x5101,0x5101,0x5101,0x5101, 0x5401,0x5401,0x5401,0x5401,0x5204,0x8004,0x5201,0x5201,0x5201,0x5201, 0x5401,0x5401,0x5401,0x5401,0x5601,0x5601,0x5601,0x5601,0x5701,0x5701, 0x5701,0x5701,0x5901,0x5901,0x5901,0x5901,0x5A01,0x5A01,0x5A01,0x5A01, 0x5A01,0x5A01,0x5A01,0x5A01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01, 0x5B01,0x5B01,0x6001,0x6001,0x6001,0x6001,0x6001,0x6001,0x6001,0x6001, 0x6108,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201, 0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201, 0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201, 0x6201,0x6201,0x6201,0x6210,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601, 0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5401,0x5401,0x5602,0x5708, 0x8004,0x5204,0x5708,0x8004,0x5204,0x5704,0x5204,0x5704,0x5B04,0x6208, 0x8008,0x6008,0x8004,0x5904,0x6008,0x8004,0x5904,0x6004,0x5904,0x5604, 0x5904,0x5208,0x8008,0x5704,0x8004,0x570C,0x5B01,0x5B01,0x5B01,0x5B01, 0x5904,0x5704,0x5701,0x5701,0x5701,0x5701,0x5604,0x560C,0x5901,0x5901, 0x5901,0x5901,0x6004,0x5604,0x5901,0x5901,0x5901,0x5901,0x5704,0x570C, 0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x5704,0x5701,0x5701,0x5701,0x5701, 0x5604,0x560C,0x5901,0x5901,0x5901,0x5901,0x6004,0x5604,0x5704,0x5704, 0x5601,0x5601,0x5601,0x5601,0x5401,0x5401,0x5602,0x5704,0x5704,0x5901, 0x5901,0x5901,0x5901,0x5701,0x5701,0x5902,0x5B04,0x5B04,0x6001,0x6001, 0x6001,0x6001,0x5B01,0x5B01,0x6001,0x6001,0x6208,0x8008,0x5201,0x5201, 0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201, 0x5201,0x5201,0x5201,0x5201,0x5410,0x5008,0x5008,0x4B08,0x4B08,0x4908, 0x4908,0x4701,0x4701,0x4701,0x4701,0x4604,0x4404,0x4604,0x4704,0x8004, 0x4904,0x8004,0x4B04,0x800C,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201, 0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201, 0x5410,0x5201,0x5201,0x5201,0x5201,0x5004,0x5004,0x5004,0x5001,0x5001, 0x5001,0x5001,0x4B04,0x4B04,0x4B04,0x4B01,0x4B01,0x4B01,0x4B01,0x4904, 0x4904,0x4904,0x4701,0x4701,0x4701,0x4701,0x4604,0x4404,0x4604,0x4714, 0x4701,0x4701,0x4601,0x4701,0x4901,0x4901,0x4901,0x4901,0x4604,0x4B14, 0x4B01,0x4B01,0x4901,0x4B01,0x5001,0x5001,0x5001,0x5001,0x4904,0x5210, 0x5408,0x5608,0x5708,0x5908,0x5B08,0x5108,0x6201,0x6201,0x6201,0x6201, 0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x5904,0x6101, 0x6101,0x6101,0x6101,0x6101,0x6101,0x5902,0x5101,0x5101,0x5101,0x5101, 0x5101,0x5101,0x5902,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201, 0x6201,0x6201,0x6201,0x6201,0x6201,0x5904,0x6101,0x6101,0x6101,0x6101, 0x6101,0x6101,0x5902,0x5101,0x5101,0x5101,0x5101,0x5101,0x5101,0x5902, 0x6204,0x5904,0x6104,0x5904,0x6204,0x5904,0x6104,0x5904,0x6204,0x4204, 0x4204,0x4204,0x4208,0x8008,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201, 0x5201,0x5201,0x5201,0x5201,0x5001,0x5001,0x4B01,0x4B01,0x4901,0x4901, 0x4704,0x8004,0x5404,0x8004,0x5004,0x8004,0x4904,0x8004,0x5204,0x800C, 0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01, 0x5901,0x5901,0x5701,0x5701,0x5601,0x5601,0x5404,0x8004,0x6004,0x8004, 0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01, 0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5908,0x8008,0x8004,0x6204, 0x6204,0x6204,0x6204,0x6204,0x6204,0x6204,0x6204,0x6204,0x6204,0x6204, 0x6201,0x6201,0x6201,0x6201,0x6001,0x6001,0x6001,0x6001,0x5901,0x5901, 0x5901,0x5901,0x5604,0x5601,0x5601,0x5601,0x5601,0x5704,0x8004,0x5404, 0x5401,0x5401,0x5401,0x5401,0x5204,0x8004,0x4604,0x4708,0x8004,0x5204, 0x5701,0x5701,0x5701,0x5701,0x5601,0x5601,0x5601,0x5601,0x5401,0x5401, 0x5401,0x5401,0x5204,0x5401,0x5401,0x5401,0x5401,0x5204,0x8004,0x5204, 0x5204,0x5204,0x5204,0x5204,0x5401,0x5401,0x5401,0x5401,0x5204,0x8004, 0x5204,0x5704,0x5604,0x5404,0x5204,0x5401,0x5401,0x5401,0x5401,0x5204, 0x8004,0x5204,0x5204,0x5204,0x5204,0x5204,0x5401,0x5401,0x5401,0x5401, 0x5204,0x8008,0x540A,0x5201,0x5201,0x5001,0x5001,0x4B01,0x4B01,0x5008, 0x8008,0x520A,0x5001,0x5001,0x4B01,0x4B01,0x4901,0x4901,0x4B08,0x8008, 0x5401,0x5401,0x5401,0x5401,0x5601,0x5601,0x5701,0x5701,0x5604,0x5404, 0x5401,0x5401,0x5401,0x5401,0x5204,0x4B04,0x5204,0x5201,0x5201,0x5201, 0x5201,0x5004,0x4B04,0x4904,0x4708,0x8004,0x5204,0x5701,0x5701,0x5701, 0x5701,0x5601,0x5601,0x5601,0x5601,0x5401,0x5401,0x5401,0x5401,0x5204, 0x5401,0x5401,0x5401,0x5401,0x5204,0x8004,0x5204,0x5204,0x5204,0x5204, 0x5204,0x5401,0x5401,0x5401,0x5401,0x5204,0x8004,0x5204,0x5701,0x5701, 0x5701,0x5701,0x5601,0x5601,0x5601,0x5601,0x5401,0x5401,0x5401,0x5401, 0x5204,0x5401,0x5401,0x5401,0x5401,0x5204,0x8004,0x5204,0x5204,0x5204, 0x5204,0x5204,0x5401,0x5401,0x5401,0x5401,0x5204,0x8008,0x640A,0x6201, 0x6201,0x6001,0x6001,0x5B01,0x5B01,0x6008,0x8008,0x620A,0x6001,0x6001, 0x5B01,0x5B01,0x5901,0x5901,0x5B08,0x8008,0x5401,0x5401,0x5401,0x5401, 0x5601,0x5601,0x5701,0x5701,0x5604,0x5404,0x5204,0x5704,0x5B04,0x6204, 0x6201,0x6201,0x6201,0x6201,0x6004,0x5B04,0x5904,0x5704,0x4204,0x4404, 0x4604,0x4704,0x4704,0x4901,0x4901,0x4901,0x4901,0x4701,0x4701,0x4901, 0x4901,0x4B04,0x4604,0x4704,0x4904,0x4B04,0x4B04,0x5001,0x5001,0x5001, 0x5001,0x4B01,0x4B01,0x5001,0x5001,0x5204,0x5204,0x5301,0x5301,0x5301, 0x5301,0x5101,0x5101,0x5301,0x5301,0x5408,0x8008,0x440C,0x4904,0x4704, 0x4604,0x4404,0x4204,0x5201,0x5201,0x5201,0x5201,0x5101,0x5101,0x5101, 0x5101,0x5001,0x5001,0x5001,0x5001,0x4B01,0x4B01,0x4B01,0x4B01,0x5201, 0x5201,0x5201,0x5201,0x5101,0x5101,0x5101,0x5101,0x5001,0x5001,0x5001, 0x5001,0x4B04,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401, 0x4401,0x4401,0x4401,0x4401,0x4904,0x4701,0x4701,0x4701,0x4701,0x4601, 0x4601,0x4601,0x4601,0x4401,0x4401,0x4401,0x4401,0x4204,0x5201,0x5201, 0x5201,0x5201,0x5401,0x5401,0x5401,0x5401,0x5601,0x5601,0x5601,0x5601, 0x5701,0x5701,0x5701,0x5701,0x5201,0x5201,0x5201,0x5201,0x5401,0x5401, 0x5401,0x5401,0x5601,0x5601,0x5601,0x5601,0x5704,0x5908,0x8008,0x6208, 0x8008,0x5708,0x8004,0x5204,0x4B04,0x4704,0x4B04,0x5204,0x5704,0x5204, 0x5704,0x5B04,0x6208,0x5608,0x5708,0x8004,0x5204,0x4B04,0x4704,0x4B04, 0x5204,0x5704,0x5204,0x5704,0x5B04,0x6208,0x5608,0x5708,0x8008,0x5708, 0x8008,0x5708,0x4706,0x4702,0x4708,0x8008, 0x0000 }; static unsigned Voice2 [] = { 0x4708,0x8004,0x4204,0x4708,0x8004,0x4204,0x4704,0x4204,0x4704,0x4B04, 0x5208,0x8008,0x5008,0x8004,0x4904,0x5008,0x8004,0x4904,0x5004,0x4904, 0x4604,0x4904,0x4208,0x8008,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704, 0x4704,0x4704,0x4904,0x4904,0x4904,0x4904,0x4901,0x4901,0x4901,0x4901, 0x5004,0x4601,0x4601,0x4601,0x4601,0x4904,0x4704,0x4704,0x4704,0x4704, 0x4704,0x4704,0x4704,0x4704,0x4904,0x4904,0x4904,0x4904,0x4901,0x4901, 0x4901,0x4901,0x5004,0x4601,0x4601,0x4601,0x4601,0x4904,0x4210,0x4210, 0x4210,0x4208,0x8028,0x3610,0x3710,0x4008,0x4008,0x3908,0x3208,0x3204, 0x8004,0x4204,0x8004,0x4208,0x8028,0x4601,0x4601,0x4601,0x4601,0x4601, 0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601, 0x4601,0x4710,0x4008,0x4004,0x4004,0x3908,0x3904,0x3904,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x4704,0x4704,0x4704,0x4704,0x4704, 0x4904,0x4904,0x4704,0x4704,0x4604,0x4604,0x4704,0x4704,0x4404,0x4404, 0x4210,0x4410,0x4210,0x4410,0x4604,0x4704,0x4904,0x4704,0x4604,0x4704, 0x4904,0x4604,0x4B04,0x4904,0x4704,0x4904,0x4B04,0x4904,0x4804,0x4B04, 0x4904,0x4904,0x4904,0x4904,0x4904,0x4904,0x4904,0x4904,0x4904,0x3904, 0x3904,0x3904,0x3908,0x8020,0x4604,0x8004,0x3B04,0x8004,0x4704,0x8004, 0x4404,0x8004,0x4104,0x800C,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401, 0x4401,0x4401,0x4204,0x8004,0x4404,0x8004,0x4201,0x4201,0x4201,0x4201, 0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201, 0x4201,0x4201,0x4108,0x8010,0x4101,0x4101,0x4101,0x4101,0x4101,0x4101, 0x4101,0x4101,0x4204,0x8004,0x4604,0x8004,0x3B04,0x8004,0x3704,0x8004, 0x3408,0x8004,0x4404,0x4704,0x4604,0x8004,0x5704,0x5701,0x5701,0x5701, 0x5701,0x5604,0x8004,0x4704,0x4204,0x4204,0x4404,0x4404,0x4604,0x4604, 0x4204,0x4204,0x4104,0x4104,0x4204,0x4204,0x4404,0x4404,0x4104,0x4104, 0x4204,0x4204,0x4404,0x4404,0x4604,0x4604,0x4204,0x4204,0x4104,0x4104, 0x4204,0x4204,0x4404,0x4404,0x4104,0x4104,0x4204,0x4204,0x4604,0x4404, 0x4304,0x3B04,0x4104,0x4304,0x4404,0x4704,0x4404,0x4204,0x4104,0x3904, 0x3B04,0x4104,0x5204,0x5204,0x5204,0x5204,0x5204,0x5204,0x5204,0x5204, 0x5204,0x4904,0x4904,0x4904,0x4904,0x4904,0x4904,0x4704,0x4604,0x4204, 0x4404,0x4404,0x4604,0x4604,0x4204,0x4204,0x4104,0x4104,0x4204,0x4204, 0x4404,0x4404,0x4104,0x4104,0x4204,0x4204,0x4404,0x4404,0x4604,0x4604, 0x4204,0x4204,0x4104,0x4104,0x4204,0x4204,0x4404,0x4404,0x4104,0x4104, 0x4204,0x4204,0x4604,0x4404,0x4304,0x3B04,0x4104,0x4304,0x4404,0x4704, 0x4404,0x4204,0x4104,0x3904,0x3B04,0x4104,0x4204,0x5204,0x5204,0x5204, 0x5204,0x5204,0x5204,0x5204,0x5204,0x4904,0x4904,0x4904,0x4904,0x4904, 0x4904,0x4704,0x4604,0x3904,0x3B04,0x4104,0x4204,0x4204,0x4404,0x4404, 0x4604,0x4104,0x4204,0x4404,0x4604,0x4604,0x4704,0x4704,0x4904,0x4904, 0x4A04,0x4A04,0x4B08,0x8008,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401, 0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401, 0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4201,0x4201, 0x4201,0x4201,0x4104,0x5204,0x8004,0x5204,0x8004,0x5204,0x800C,0x4708, 0x8004,0x4204,0x4708,0x8004,0x4204,0x4704,0x4204,0x4704,0x4B04,0x5208, 0x8008,0x5008,0x8004,0x4904,0x5008,0x8004,0x4904,0x5004,0x4904,0x4604, 0x4904,0x4208,0x8008,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704, 0x4704,0x4904,0x4904,0x4904,0x4904,0x4901,0x4901,0x4901,0x4901,0x5004, 0x4601,0x4601,0x4601,0x4601,0x4904,0x4704,0x4704,0x4704,0x4704,0x4704, 0x4704,0x4704,0x4704,0x4904,0x4904,0x4904,0x4904,0x4901,0x4901,0x4901, 0x4901,0x5004,0x4601,0x4601,0x4601,0x4601,0x4904,0x4210,0x4210,0x4210, 0x4208,0x8028,0x3610,0x3710,0x4008,0x4008,0x3908,0x3208,0x3204,0x8004, 0x4204,0x8004,0x4208,0x8028,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601, 0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601, 0x4710,0x4008,0x4004,0x4004,0x3908,0x3904,0x3904,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4904, 0x4904,0x4704,0x4704,0x4604,0x4604,0x4704,0x4704,0x4404,0x4404,0x4210, 0x4410,0x4210,0x4410,0x4604,0x4704,0x4904,0x4704,0x4604,0x4704,0x4904, 0x4604,0x4B04,0x4904,0x4704,0x4904,0x4B04,0x4904,0x4804,0x4B04,0x4904, 0x4904,0x4904,0x4904,0x4904,0x4904,0x4904,0x4904,0x4904,0x3904,0x3904, 0x3904,0x3908,0x8020,0x4604,0x8004,0x3B04,0x8004,0x4704,0x8004,0x4404, 0x8004,0x4104,0x800C,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401, 0x4401,0x4204,0x8004,0x4404,0x8004,0x4201,0x4201,0x4201,0x4201,0x4201, 0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201, 0x4201,0x4108,0x8010,0x4101,0x4101,0x4101,0x4101,0x4101,0x4101,0x4101, 0x4101,0x4204,0x8004,0x4604,0x8004,0x3B04,0x8004,0x3704,0x8004,0x3408, 0x8004,0x4404,0x4704,0x4604,0x8004,0x5704,0x5701,0x5701,0x5701,0x5701, 0x5604,0x8004,0x4704,0x4204,0x4204,0x4404,0x4404,0x4604,0x4604,0x4204, 0x4204,0x4104,0x4104,0x4204,0x4204,0x4404,0x4404,0x4104,0x4104,0x4204, 0x4204,0x4404,0x4404,0x4604,0x4604,0x4204,0x4204,0x4104,0x4104,0x4204, 0x4204,0x4404,0x4404,0x4104,0x4104,0x4204,0x4204,0x4604,0x4404,0x4304, 0x3B04,0x4104,0x4304,0x4404,0x4704,0x4404,0x4204,0x4104,0x3904,0x3B04, 0x4104,0x5204,0x5204,0x5204,0x5204,0x5204,0x5204,0x5204,0x5204,0x5204, 0x4904,0x4904,0x4904,0x4904,0x4904,0x4904,0x4704,0x4604,0x4204,0x4404, 0x4404,0x4604,0x4604,0x4204,0x4204,0x4104,0x4104,0x4204,0x4204,0x4404, 0x4404,0x4104,0x4104,0x4204,0x4204,0x4404,0x4404,0x4604,0x4604,0x4204, 0x4204,0x4104,0x4104,0x4204,0x4204,0x4404,0x4404,0x4104,0x4104,0x4204, 0x4204,0x4604,0x4404,0x4304,0x3B04,0x4104,0x4304,0x4404,0x4704,0x4404, 0x4204,0x4104,0x3904,0x3B04,0x4104,0x4204,0x5204,0x5204,0x5204,0x5204, 0x5204,0x5204,0x5204,0x5204,0x4904,0x4904,0x4904,0x4904,0x4904,0x4904, 0x4704,0x4604,0x3904,0x3B04,0x4104,0x4204,0x4204,0x4404,0x4404,0x4604, 0x4104,0x4204,0x4404,0x4604,0x4604,0x4704,0x4704,0x4904,0x4904,0x4A04, 0x4A04,0x4B08,0x8008,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401, 0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401, 0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4201,0x4201,0x4201, 0x4201,0x4104,0x5204,0x8004,0x5204,0x8004,0x5204,0x800C,0x4208,0x8004, 0x3904,0x4208,0x8004,0x3904,0x4204,0x3904,0x4204,0x4604,0x4908,0x8008, 0x4908,0x8004,0x4604,0x4908,0x8004,0x4604,0x4904,0x4604,0x4304,0x4604, 0x3B08,0x8008,0x4004,0x4004,0x4204,0x4204,0x4404,0x4404,0x4004,0x4004, 0x3B04,0x3B04,0x4004,0x4004,0x4204,0x4204,0x3B04,0x3B04,0x4004,0x4004, 0x4204,0x4204,0x4404,0x4404,0x4004,0x4004,0x3B04,0x3B04,0x4004,0x4004, 0x4204,0x4204,0x3B04,0x3B04,0x4004,0x4004,0x4204,0x4204,0x4404,0x4404, 0x4004,0x4004,0x3B04,0x3B04,0x4004,0x4004,0x4204,0x4204,0x3B04,0x3B04, 0x3904,0x3904,0x3B04,0x3B04,0x4004,0x4004,0x3904,0x3904,0x3904,0x3904, 0x3A04,0x3A04,0x4004,0x4004,0x3904,0x3904,0x3704,0x3704,0x3604,0x3604, 0x3704,0x3704,0x4604,0x4604,0x4704,0x4704,0x4604,0x4604,0x4704,0x3704, 0x3604,0x3704,0x3908,0x8004,0x3201,0x3201,0x3201,0x3201,0x3401,0x3401, 0x3401,0x3401,0x3601,0x3601,0x3601,0x3601,0x3701,0x3701,0x3701,0x3701, 0x3901,0x3901,0x3901,0x3901,0x4001,0x4001,0x4001,0x4001,0x3A04,0x8004, 0x3601,0x3601,0x3601,0x3601,0x3701,0x3701,0x3701,0x3701,0x3901,0x3901, 0x3901,0x3901,0x3A01,0x3A01,0x3A01,0x3A01,0x4101,0x4101,0x4101,0x4101, 0x4401,0x4401,0x4401,0x4401,0x4204,0x8038,0x4B04,0x4B04,0x4B01,0x4B01, 0x4B01,0x4B01,0x5004,0x4904,0x4904,0x4901,0x4901,0x4901,0x4901,0x4B04, 0x4704,0x4704,0x4701,0x4701,0x4701,0x4701,0x4B04,0x4B01,0x4B01,0x4B01, 0x4B01,0x4904,0x4704,0x4204,0x3B08,0x8004,0x4204,0x4708,0x8004,0x4204, 0x4704,0x4204,0x4704,0x4B04,0x5208,0x8008,0x5008,0x8004,0x4904,0x5008, 0x8004,0x4904,0x5004,0x4904,0x4604,0x4904,0x4208,0x8008,0x4704,0x4704, 0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704, 0x4701,0x4701,0x4701,0x4701,0x4B04,0x4401,0x4401,0x4401,0x4401,0x4704, 0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704, 0x4704,0x4704,0x4701,0x4701,0x4701,0x4701,0x4B04,0x4401,0x4401,0x4401, 0x4401,0x4704,0x4210,0x4210,0x4210,0x4208,0x8028,0x3610,0x3710,0x4008, 0x4008,0x3908,0x3908,0x3204,0x8004,0x4204,0x8004,0x4208,0x8028,0x4601, 0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601, 0x4601,0x4601,0x4601,0x4601,0x4601,0x4710,0x4008,0x4004,0x4004,0x3908, 0x3904,0x3904,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x4704, 0x4704,0x4704,0x4704,0x4704,0x4904,0x4904,0x4704,0x4704,0x4604,0x4604, 0x4704,0x4704,0x4404,0x4404,0x4210,0x4410,0x4210,0x4410,0x4208,0x4408, 0x4208,0x4408,0x4204,0x3204,0x3204,0x3204,0x3208,0x8020,0x3B04,0x8004, 0x3404,0x8004,0x4004,0x8004,0x3904,0x8004,0x3604,0x800C,0x4901,0x4901, 0x4901,0x4901,0x4901,0x4901,0x4901,0x4901,0x4704,0x8004,0x4904,0x8004, 0x4B10,0x4908,0x8008,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201, 0x5201,0x5201,0x5201,0x5001,0x5001,0x4B01,0x4B01,0x4901,0x4901,0x4704, 0x8004,0x5404,0x8004,0x5004,0x8004,0x4904,0x8004,0x5208,0x8004,0x5004, 0x5001,0x5001,0x5001,0x5001,0x4B04,0x8004,0x5004,0x5001,0x5001,0x5001, 0x5001,0x4B04,0x8004,0x4004,0x3704,0x3704,0x3904,0x3904,0x3B04,0x3B04, 0x3704,0x3704,0x3604,0x3604,0x3704,0x3704,0x3904,0x3904,0x3604,0x3604, 0x3704,0x3704,0x3904,0x3904,0x3B04,0x3B04,0x3704,0x3704,0x3604,0x3604, 0x3704,0x3704,0x3904,0x3904,0x3604,0x3604,0x3704,0x4704,0x4B04,0x4904, 0x4804,0x4404,0x4604,0x4804,0x4904,0x5004,0x4904,0x4704,0x4604,0x4204, 0x4404,0x4604,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704, 0x4704,0x4204,0x4204,0x4204,0x4204,0x4204,0x4204,0x4004,0x3B04,0x3704, 0x3904,0x3904,0x3B04,0x3B04,0x3704,0x3704,0x3604,0x3604,0x3704,0x3704, 0x3904,0x3904,0x3604,0x3604,0x3704,0x4704,0x4904,0x4904,0x4B04,0x4B04, 0x4704,0x4704,0x4604,0x4604,0x4704,0x4704,0x4904,0x4904,0x4604,0x4604, 0x4704,0x4704,0x4B04,0x4904,0x4804,0x4404,0x4604,0x4804,0x4904,0x5004, 0x4904,0x4704,0x4604,0x4204,0x4404,0x4604,0x4704,0x4704,0x4704,0x4704, 0x4704,0x4704,0x4704,0x4704,0x4701,0x4701,0x4701,0x4701,0x4904,0x5004, 0x5004,0x5004,0x5004,0x5004,0x4B04,0x4904,0x4204,0x4404,0x4604,0x4704, 0x4704,0x4904,0x4904,0x4B04,0x3604,0x3704,0x3904,0x3B04,0x3B04,0x4004, 0x4004,0x4004,0x4004,0x4104,0x4104,0x4208,0x8008,0x3901,0x3901,0x3901, 0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901, 0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901, 0x3901,0x3701,0x3701,0x3701,0x3701,0x3604,0x3708,0x8018,0x3901,0x3901, 0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901, 0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901, 0x3901,0x3901,0x3701,0x3701,0x3701,0x3701,0x3604,0x3708,0x8008,0x4708, 0x8008,0x4408,0x8008,0x4708,0x8008,0x3710,0x3710,0x3710,0x3708,0x3908, 0x3710,0x3710,0x3710,0x3708,0x3908,0x3704,0x3B04,0x4204,0x4704,0x4B04, 0x4704,0x5204,0x4B04,0x4708,0x3706,0x3702,0x3708,0x8008,0x4208,0x8004, 0x3904,0x4208,0x8004,0x3904,0x4204,0x3904,0x4204,0x4604,0x4908,0x8008, 0x4908,0x8004,0x4604,0x4908,0x8004,0x4604,0x4904,0x4604,0x4304,0x4604, 0x3B08,0x8008,0x4004,0x4004,0x4204,0x4204,0x4404,0x4404,0x4004,0x4004, 0x3B04,0x3B04,0x4004,0x4004,0x4204,0x4204,0x3B04,0x3B04,0x4004,0x4004, 0x4204,0x4204,0x4404,0x4404,0x4004,0x4004,0x3B04,0x3B04,0x4004,0x4004, 0x4204,0x4204,0x3B04,0x3B04,0x4004,0x4004,0x4204,0x4204,0x4404,0x4404, 0x4004,0x4004,0x3B04,0x3B04,0x4004,0x4004,0x4204,0x4204,0x3B04,0x3B04, 0x3904,0x3904,0x3B04,0x3B04,0x4004,0x4004,0x3904,0x3904,0x3904,0x3904, 0x3A04,0x3A04,0x4004,0x4004,0x3904,0x3904,0x3704,0x3704,0x3604,0x3604, 0x3704,0x3704,0x4604,0x4604,0x4704,0x4704,0x4604,0x4604,0x4704,0x3704, 0x3604,0x3704,0x3908,0x8004,0x3201,0x3201,0x3201,0x3201,0x3401,0x3401, 0x3401,0x3401,0x3601,0x3601,0x3601,0x3601,0x3701,0x3701,0x3701,0x3701, 0x3901,0x3901,0x3901,0x3901,0x4001,0x4001,0x4001,0x4001,0x3A04,0x8004, 0x3601,0x3601,0x3601,0x3601,0x3701,0x3701,0x3701,0x3701,0x3901,0x3901, 0x3901,0x3901,0x3A01,0x3A01,0x3A01,0x3A01,0x4101,0x4101,0x4101,0x4101, 0x4401,0x4401,0x4401,0x4401,0x4204,0x8038,0x4B04,0x4B04,0x4B01,0x4B01, 0x4B01,0x4B01,0x5004,0x4904,0x4904,0x4901,0x4901,0x4901,0x4901,0x4B04, 0x4704,0x4704,0x4701,0x4701,0x4701,0x4701,0x4B04,0x4B01,0x4B01,0x4B01, 0x4B01,0x4904,0x4704,0x4204,0x3B08,0x8004,0x4204,0x4708,0x8004,0x4204, 0x4704,0x4204,0x4704,0x4B04,0x5208,0x8008,0x5008,0x8004,0x4904,0x5008, 0x8004,0x4904,0x5004,0x4904,0x4604,0x4904,0x4208,0x8008,0x4704,0x4704, 0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704, 0x4701,0x4701,0x4701,0x4701,0x4B04,0x4401,0x4401,0x4401,0x4401,0x4704, 0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704, 0x4704,0x4704,0x4701,0x4701,0x4701,0x4701,0x4B04,0x4401,0x4401,0x4401, 0x4401,0x4704,0x4210,0x4210,0x4210,0x4208,0x8028,0x3610,0x3710,0x4008, 0x4008,0x3908,0x3908,0x3204,0x8004,0x4204,0x8004,0x4208,0x8028,0x4601, 0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601, 0x4601,0x4601,0x4601,0x4601,0x4601,0x4710,0x4008,0x4004,0x4004,0x3908, 0x3904,0x3904,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x4704, 0x4704,0x4704,0x4704,0x4704,0x4904,0x4904,0x4704,0x4704,0x4604,0x4604, 0x4704,0x4704,0x4404,0x4404,0x4210,0x4410,0x4210,0x4410,0x4208,0x4408, 0x4208,0x4408,0x4204,0x3204,0x3204,0x3204,0x3208,0x8020,0x3B04,0x8004, 0x3404,0x8004,0x4004,0x8004,0x3904,0x8004,0x3604,0x800C,0x4901,0x4901, 0x4901,0x4901,0x4901,0x4901,0x4901,0x4901,0x4704,0x8004,0x4904,0x8004, 0x4B10,0x4908,0x8008,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201, 0x5201,0x5201,0x5201,0x5001,0x5001,0x4B01,0x4B01,0x4901,0x4901,0x4704, 0x8004,0x5404,0x8004,0x5004,0x8004,0x4904,0x8004,0x5208,0x8004,0x5004, 0x5001,0x5001,0x5001,0x5001,0x4B04,0x8004,0x5004,0x5001,0x5001,0x5001, 0x5001,0x4B04,0x8004,0x4004,0x3704,0x3704,0x3904,0x3904,0x3B04,0x3B04, 0x3704,0x3704,0x3604,0x3604,0x3704,0x3704,0x3904,0x3904,0x3604,0x3604, 0x3704,0x3704,0x3904,0x3904,0x3B04,0x3B04,0x3704,0x3704,0x3604,0x3604, 0x3704,0x3704,0x3904,0x3904,0x3604,0x3604,0x3704,0x4704,0x4B04,0x4904, 0x4804,0x4404,0x4604,0x4804,0x4904,0x5004,0x4904,0x4704,0x4604,0x4204, 0x4404,0x4604,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704, 0x4704,0x4204,0x4204,0x4204,0x4204,0x4204,0x4204,0x4004,0x3B04,0x3704, 0x3904,0x3904,0x3B04,0x3B04,0x3704,0x3704,0x3604,0x3604,0x3704,0x3704, 0x3904,0x3904,0x3604,0x3604,0x3704,0x4704,0x4904,0x4904,0x4B04,0x4B04, 0x4704,0x4704,0x4604,0x4604,0x4704,0x4704,0x4904,0x4904,0x4604,0x4604, 0x4704,0x4704,0x4B04,0x4904,0x4804,0x4404,0x4604,0x4804,0x4904,0x5004, 0x4904,0x4704,0x4604,0x4204,0x4404,0x4604,0x4704,0x4704,0x4704,0x4704, 0x4704,0x4704,0x4704,0x4704,0x4701,0x4701,0x4701,0x4701,0x4904,0x5004, 0x5004,0x5004,0x5004,0x5004,0x4B04,0x4904,0x4204,0x4404,0x4604,0x4704, 0x4704,0x4904,0x4904,0x4B04,0x3604,0x3704,0x3904,0x3B04,0x3B04,0x4004, 0x4004,0x4004,0x4004,0x4104,0x4104,0x4208,0x8008,0x3901,0x3901,0x3901, 0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901, 0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901, 0x3901,0x3701,0x3701,0x3701,0x3701,0x3604,0x3708,0x8018,0x3901,0x3901, 0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901, 0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901, 0x3901,0x3901,0x3701,0x3701,0x3701,0x3701,0x3604,0x3708,0x8008,0x4708, 0x8008,0x4408,0x8008,0x4708,0x8008,0x3710,0x3710,0x3710,0x3708,0x3908, 0x3710,0x3710,0x3710,0x3708,0x3908,0x3704,0x3B04,0x4204,0x4704,0x4B04, 0x4704,0x5204,0x4B04,0x4708,0x3706,0x3702,0x3708,0x8008, 0x0000 }; static unsigned Voice3 [] = { 0x3708,0x8004,0x3204,0x3708,0x8004,0x3204,0x3704,0x3204,0x3704,0x3B04, 0x3208,0x8008,0x4008,0x8004,0x3904,0x4008,0x8004,0x3904,0x4004,0x3904, 0x3604,0x4904,0x4208,0x8008,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3904,0x3904, 0x3B04,0x3B04,0x3604,0x3604,0x3704,0x3704,0x3904,0x3904,0x3B08,0x8028, 0x3210,0x3410,0x3008,0x3008,0x3208,0x3208,0x2B04,0x8004,0x3204,0x8004, 0x3708,0x8008,0x4B10,0x5010,0x3201,0x3201,0x3201,0x3201,0x3201,0x3201, 0x3201,0x3201,0x3201,0x3201,0x3201,0x3201,0x3201,0x3201,0x3201,0x3201, 0x3410,0x3008,0x3008,0x3208,0x3208,0x3B14,0x3B02,0x3901,0x3B01,0x4004, 0x3904,0x4714,0x4702,0x4601,0x4701,0x4904,0x4604,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3604,0x3604,0x3704, 0x3704,0x3404,0x3404,0x3204,0x3204,0x3204,0x3204,0x3204,0x3204,0x3204, 0x3204,0x3204,0x3204,0x3204,0x3204,0x3204,0x3204,0x3204,0x3204,0x3204, 0x3404,0x3604,0x3404,0x3204,0x3404,0x3604,0x3204,0x3704,0x3904,0x3B04, 0x3904,0x3704,0x3904,0x3B04,0x3804,0x3904,0x3904,0x3904,0x3904,0x3904, 0x3904,0x3904,0x3904,0x3904,0x2904,0x2904,0x2904,0x2908,0x8008,0x490A, 0x4702,0x4602,0x4402,0x4204,0x8004,0x3304,0x8004,0x3404,0x8004,0x3204, 0x8004,0x3104,0x8004,0x2904,0x800C,0x2A01,0x2A01,0x2A01,0x2A01,0x2A01, 0x2A01,0x2A01,0x2A01,0x2B04,0x8004,0x2704,0x8004,0x2908,0x3901,0x3901, 0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901, 0x3801,0x3801,0x3801,0x3801,0x3701,0x3701,0x3701,0x3701,0x3401,0x3401, 0x3401,0x3401,0x3204,0x8004,0x3404,0x8004,0x3604,0x8004,0x3304,0x8004, 0x3404,0x8004,0x3204,0x8004,0x3104,0x8004,0x2904,0x8004,0x2B04,0x8004, 0x3704,0x8004,0x3904,0x8004,0x2904,0x8004,0x4604,0x4604,0x4704,0x4704, 0x4904,0x4904,0x4604,0x4604,0x4404,0x4404,0x4604,0x4604,0x4704,0x4704, 0x4404,0x4404,0x4604,0x4604,0x4704,0x4704,0x4904,0x4904,0x4604,0x4604, 0x4404,0x4404,0x4604,0x4604,0x4704,0x4704,0x4404,0x4404,0x4608,0x8008, 0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601, 0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5408,0x8008,0x5401,0x5401, 0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401, 0x5401,0x5401,0x5401,0x5401,0x5204,0x5604,0x5704,0x5904,0x5701,0x5701, 0x5701,0x5701,0x5901,0x5901,0x5B01,0x5B01,0x5904,0x5704,0x5701,0x5701, 0x5701,0x5701,0x5604,0x5204,0x5604,0x5601,0x5601,0x5601,0x5601,0x5404, 0x5204,0x5104,0x5204,0x4604,0x4704,0x4704,0x4904,0x4904,0x4604,0x4604, 0x4404,0x4404,0x4604,0x4604,0x4704,0x4704,0x4404,0x4404,0x4604,0x4604, 0x4704,0x4704,0x4904,0x4904,0x4604,0x4604,0x4404,0x4404,0x4604,0x4604, 0x4704,0x4704,0x4404,0x4404,0x4608,0x8008,0x5601,0x5601,0x5601,0x5601, 0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601, 0x5601,0x5601,0x5408,0x8008,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401, 0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401, 0x5204,0x5504,0x5704,0x5904,0x5701,0x5701,0x5701,0x5701,0x5901,0x5901, 0x5B01,0x5B01,0x5904,0x5704,0x5701,0x5701,0x5701,0x5701,0x5604,0x5204, 0x5604,0x5601,0x5601,0x5601,0x5601,0x5404,0x5204,0x5104,0x3204,0x2904, 0x2B04,0x3104,0x3204,0x3204,0x3404,0x3404,0x3604,0x3104,0x3204,0x3404, 0x3604,0x3604,0x3704,0x3704,0x3904,0x3904,0x3A04,0x3A04,0x3B08,0x8008, 0x3710,0x3910,0x4204,0x8004,0x4204,0x8004,0x4204,0x800C,0x3708,0x8004, 0x3204,0x3708,0x8004,0x3204,0x3704,0x3204,0x3704,0x3B04,0x3208,0x8008, 0x4008,0x8004,0x3904,0x4008,0x8004,0x3904,0x4004,0x3904,0x3604,0x4904, 0x4208,0x8008,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3904,0x3904,0x3B04,0x3B04, 0x3604,0x3604,0x3704,0x3704,0x3904,0x3904,0x3B08,0x8028,0x3210,0x3410, 0x3008,0x3008,0x3208,0x3208,0x2B04,0x8004,0x3204,0x8004,0x3708,0x8008, 0x4B10,0x5010,0x3201,0x3201,0x3201,0x3201,0x3201,0x3201,0x3201,0x3201, 0x3201,0x3201,0x3201,0x3201,0x3201,0x3201,0x3201,0x3201,0x3410,0x3008, 0x3008,0x3208,0x3208,0x3B14,0x3B02,0x3901,0x3B01,0x4004,0x3904,0x4714, 0x4702,0x4601,0x4701,0x4904,0x4604,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3604,0x3604,0x3704,0x3704,0x3404, 0x3404,0x3204,0x3204,0x3204,0x3204,0x3204,0x3204,0x3204,0x3204,0x3204, 0x3204,0x3204,0x3204,0x3204,0x3204,0x3204,0x3204,0x3204,0x3404,0x3604, 0x3404,0x3204,0x3404,0x3604,0x3204,0x3704,0x3904,0x3B04,0x3904,0x3704, 0x3904,0x3B04,0x3804,0x3904,0x3904,0x3904,0x3904,0x3904,0x3904,0x3904, 0x3904,0x3904,0x2904,0x2904,0x2904,0x2908,0x8008,0x490A,0x4702,0x4602, 0x4402,0x4204,0x8004,0x3304,0x8004,0x3404,0x8004,0x3204,0x8004,0x3104, 0x8004,0x2904,0x800C,0x2A01,0x2A01,0x2A01,0x2A01,0x2A01,0x2A01,0x2A01, 0x2A01,0x2B04,0x8004,0x2704,0x8004,0x2908,0x3901,0x3901,0x3901,0x3901, 0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3801,0x3801, 0x3801,0x3801,0x3701,0x3701,0x3701,0x3701,0x3401,0x3401,0x3401,0x3401, 0x3204,0x8004,0x3404,0x8004,0x3604,0x8004,0x3304,0x8004,0x3404,0x8004, 0x3204,0x8004,0x3104,0x8004,0x2904,0x8004,0x2B04,0x8004,0x3704,0x8004, 0x3904,0x8004,0x2904,0x8004,0x4604,0x4604,0x4704,0x4704,0x4904,0x4904, 0x4604,0x4604,0x4404,0x4404,0x4604,0x4604,0x4704,0x4704,0x4404,0x4404, 0x4604,0x4604,0x4704,0x4704,0x4904,0x4904,0x4604,0x4604,0x4404,0x4404, 0x4604,0x4604,0x4704,0x4704,0x4404,0x4404,0x4608,0x8008,0x5601,0x5601, 0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601, 0x5601,0x5601,0x5601,0x5601,0x5408,0x8008,0x5401,0x5401,0x5401,0x5401, 0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401, 0x5401,0x5401,0x5204,0x5604,0x5704,0x5904,0x5701,0x5701,0x5701,0x5701, 0x5901,0x5901,0x5B01,0x5B01,0x5904,0x5704,0x5701,0x5701,0x5701,0x5701, 0x5604,0x5204,0x5604,0x5601,0x5601,0x5601,0x5601,0x5404,0x5204,0x5104, 0x5204,0x4604,0x4704,0x4704,0x4904,0x4904,0x4604,0x4604,0x4404,0x4404, 0x4604,0x4604,0x4704,0x4704,0x4404,0x4404,0x4604,0x4604,0x4704,0x4704, 0x4904,0x4904,0x4604,0x4604,0x4404,0x4404,0x4604,0x4604,0x4704,0x4704, 0x4404,0x4404,0x4608,0x8008,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601, 0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601, 0x5408,0x8008,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401, 0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5204,0x5504, 0x5704,0x5904,0x5701,0x5701,0x5701,0x5701,0x5901,0x5901,0x5B01,0x5B01, 0x5904,0x5704,0x5701,0x5701,0x5701,0x5701,0x5604,0x5204,0x5604,0x5601, 0x5601,0x5601,0x5601,0x5404,0x5204,0x5104,0x3204,0x2904,0x2B04,0x3104, 0x3204,0x3204,0x3404,0x3404,0x3604,0x3104,0x3204,0x3404,0x3604,0x3604, 0x3704,0x3704,0x3904,0x3904,0x3A04,0x3A04,0x3B08,0x8008,0x3710,0x3910, 0x4204,0x8004,0x4204,0x8004,0x4204,0x800C,0x3208,0x8004,0x2904,0x3208, 0x8004,0x2904,0x3204,0x2904,0x3204,0x3604,0x4908,0x8008,0x3908,0x8004, 0x3604,0x3908,0x8004,0x3604,0x3904,0x3604,0x3304,0x3604,0x2B08,0x8008, 0x4404,0x4404,0x4504,0x4504,0x4704,0x4704,0x4404,0x4404,0x4204,0x4204, 0x4404,0x4404,0x4504,0x4504,0x4204,0x4204,0x4404,0x4404,0x4504,0x4504, 0x4704,0x4704,0x4404,0x4404,0x4204,0x4204,0x4404,0x4404,0x4504,0x4504, 0x4204,0x4204,0x4404,0x4404,0x4504,0x4504,0x4704,0x4704,0x4404,0x4404, 0x4204,0x4204,0x4404,0x4404,0x4504,0x4504,0x4204,0x4204,0x4004,0x4004, 0x4204,0x4204,0x4404,0x4404,0x4004,0x4004,0x4004,0x4004,0x4204,0x4204, 0x4304,0x4304,0x4004,0x4004,0x3A04,0x3A04,0x3904,0x3904,0x3A04,0x3A04, 0x4904,0x4904,0x4A04,0x4A04,0x4904,0x4904,0x4A04,0x4A04,0x4904,0x4704, 0x4608,0x8004,0x2201,0x2201,0x2201,0x2201,0x2401,0x2401,0x2401,0x2401, 0x2601,0x2601,0x2601,0x2601,0x2701,0x2701,0x2701,0x2701,0x2901,0x2901, 0x2901,0x2901,0x3001,0x3001,0x3001,0x3001,0x2A04,0x8004,0x2601,0x2601, 0x2601,0x2601,0x2701,0x2701,0x2701,0x2701,0x2901,0x2901,0x2901,0x2901, 0x2A01,0x2A01,0x2A01,0x2A01,0x2101,0x2101,0x2101,0x2101,0x3401,0x3401, 0x3401,0x3401,0x3204,0x8004,0x4204,0x4404,0x4504,0x4704,0x4904,0x4A08, 0x4B08,0x5008,0x5108,0x5204,0x5204,0x5201,0x5201,0x5201,0x5201,0x5404, 0x5004,0x5004,0x5001,0x5001,0x5001,0x5001,0x5204,0x4B04,0x4B04,0x4B01, 0x4B01,0x4B01,0x4B01,0x5204,0x5201,0x5201,0x5201,0x5201,0x5004,0x4B04, 0x4904,0x4708,0x8004,0x3204,0x3708,0x8004,0x3204,0x3704,0x3204,0x3704, 0x3B04,0x4208,0x8008,0x4008,0x8004,0x3904,0x4008,0x8004,0x3904,0x4004, 0x3904,0x3604,0x3904,0x3208,0x8008,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3904, 0x3904,0x3B04,0x3B04,0x3704,0x3704,0x3904,0x3904,0x3B04,0x3B04,0x4008, 0x8008,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01, 0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x5010,0x4908,0x4908, 0x4708,0x4708,0x4408,0x4408,0x4008,0x3908,0x4204,0x8004,0x4604,0x8004, 0x4704,0x800C,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01, 0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x5010,0x4B01, 0x4B01,0x4B01,0x4B01,0x4904,0x4904,0x4904,0x4901,0x4901,0x4901,0x4901, 0x4704,0x4704,0x4704,0x4408,0x4404,0x4404,0x4008,0x4004,0x4004,0x3B14, 0x3B01,0x3B01,0x3901,0x3B01,0x4001,0x4001,0x4001,0x4001,0x3904,0x4714, 0x4701,0x4701,0x4601,0x4701,0x4901,0x4901,0x4901,0x4901,0x4604,0x4B10, 0x5010,0x4B08,0x5210,0x5708,0x5610,0x5710,0x5610,0x5710,0x5608,0x5708, 0x5608,0x5708,0x5604,0x4204,0x4204,0x4204,0x4208,0x8008,0x4201,0x4201, 0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4001,0x4001, 0x3B01,0x3B01,0x3901,0x3901,0x3704,0x8004,0x4404,0x8004,0x4004,0x8004, 0x3904,0x8004,0x4204,0x800C,0x4B0A,0x4902,0x4702,0x4602,0x5404,0x8004, 0x5004,0x8004,0x3208,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201, 0x4201,0x4201,0x4201,0x4201,0x4201,0x4101,0x4101,0x4101,0x4101,0x4001, 0x4001,0x4001,0x4001,0x3901,0x3901,0x3901,0x3901,0x3704,0x8004,0x3904, 0x8004,0x3B04,0x8004,0x3804,0x8004,0x3904,0x8004,0x3704,0x8004,0x3604, 0x8004,0x3204,0x8004,0x3404,0x8004,0x3004,0x8004,0x3204,0x8004,0x3204, 0x8004,0x2708,0x8018,0x3208,0x8018,0x2708,0x8018,0x3208,0x8018,0x3B08, 0x8008,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01, 0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4908,0x8008,0x4901, 0x4901,0x4901,0x4901,0x4901,0x4901,0x4901,0x4901,0x4901,0x4901,0x4901, 0x4901,0x4901,0x4901,0x4901,0x4901,0x4704,0x4B04,0x5004,0x5204,0x5001, 0x5001,0x5001,0x5001,0x5201,0x5201,0x5401,0x5401,0x5204,0x5004,0x5001, 0x5001,0x5001,0x5001,0x4B04,0x4704,0x4B04,0x4B01,0x4B01,0x4B01,0x4B01, 0x4904,0x4704,0x4604,0x4704,0x3B04,0x4004,0x4004,0x4204,0x4204,0x3B04, 0x3B04,0x3904,0x3904,0x3B04,0x3B04,0x4004,0x4004,0x3904,0x3904,0x3B04, 0x4B04,0x5004,0x5004,0x5204,0x5204,0x4B04,0x4B04,0x4904,0x4904,0x4B04, 0x4B04,0x5004,0x5004,0x4904,0x4904,0x8004,0x3704,0x3B04,0x3904,0x3804, 0x3404,0x3604,0x3804,0x3904,0x4004,0x3904,0x3704,0x3604,0x3204,0x3404, 0x3604,0x3704,0x3704,0x3904,0x3B04,0x4004,0x4004,0x4004,0x4004,0x4204, 0x4204,0x4204,0x4204,0x3204,0x3204,0x3204,0x3204,0x3704,0x3204,0x3404, 0x3604,0x3704,0x3704,0x3904,0x3904,0x3B04,0x3604,0x3704,0x3904,0x3B04, 0x3B04,0x4004,0x4004,0x4204,0x4204,0x4304,0x4304,0x4408,0x8008,0x3001, 0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001, 0x3001,0x3001,0x3001,0x3001,0x3001,0x3210,0x2708,0x8018,0x3001,0x3001, 0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001, 0x3001,0x3001,0x3001,0x3001,0x3210,0x2708,0x8018,0x3008,0x8008,0x3208, 0x8008,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704, 0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704, 0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704, 0x2704,0x2704,0x2704,0x2704,0x2B04,0x3204,0x3704,0x3B04,0x3704,0x4204, 0x3B04,0x3708,0x2706,0x2702,0x2708,0x8008,0x3208,0x8004,0x2904,0x3208, 0x8004,0x2904,0x3204,0x2904,0x3204,0x3604,0x4908,0x8008,0x3908,0x8004, 0x3604,0x3908,0x8004,0x3604,0x3904,0x3604,0x3304,0x3604,0x2B08,0x8008, 0x4404,0x4404,0x4504,0x4504,0x4704,0x4704,0x4404,0x4404,0x4204,0x4204, 0x4404,0x4404,0x4504,0x4504,0x4204,0x4204,0x4404,0x4404,0x4504,0x4504, 0x4704,0x4704,0x4404,0x4404,0x4204,0x4204,0x4404,0x4404,0x4504,0x4504, 0x4204,0x4204,0x4404,0x4404,0x4504,0x4504,0x4704,0x4704,0x4404,0x4404, 0x4204,0x4204,0x4404,0x4404,0x4504,0x4504,0x4204,0x4204,0x4004,0x4004, 0x4204,0x4204,0x4404,0x4404,0x4004,0x4004,0x4004,0x4004,0x4204,0x4204, 0x4304,0x4304,0x4004,0x4004,0x3A04,0x3A04,0x3904,0x3904,0x3A04,0x3A04, 0x4904,0x4904,0x4A04,0x4A04,0x4904,0x4904,0x4A04,0x4A04,0x4904,0x4704, 0x4608,0x8004,0x2201,0x2201,0x2201,0x2201,0x2401,0x2401,0x2401,0x2401, 0x2601,0x2601,0x2601,0x2601,0x2701,0x2701,0x2701,0x2701,0x2901,0x2901, 0x2901,0x2901,0x3001,0x3001,0x3001,0x3001,0x2A04,0x8004,0x2601,0x2601, 0x2601,0x2601,0x2701,0x2701,0x2701,0x2701,0x2901,0x2901,0x2901,0x2901, 0x2A01,0x2A01,0x2A01,0x2A01,0x2101,0x2101,0x2101,0x2101,0x3401,0x3401, 0x3401,0x3401,0x3204,0x8004,0x4204,0x4404,0x4504,0x4704,0x4904,0x4A08, 0x4B08,0x5008,0x5108,0x5204,0x5204,0x5201,0x5201,0x5201,0x5201,0x5404, 0x5004,0x5004,0x5001,0x5001,0x5001,0x5001,0x5204,0x4B04,0x4B04,0x4B01, 0x4B01,0x4B01,0x4B01,0x5204,0x5201,0x5201,0x5201,0x5201,0x5004,0x4B04, 0x4904,0x4708,0x8004,0x3204,0x3708,0x8004,0x3204,0x3704,0x3204,0x3704, 0x3B04,0x4208,0x8008,0x4008,0x8004,0x3904,0x4008,0x8004,0x3904,0x4004, 0x3904,0x3604,0x3904,0x3208,0x8008,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3904, 0x3904,0x3B04,0x3B04,0x3704,0x3704,0x3904,0x3904,0x3B04,0x3B04,0x4008, 0x8008,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01, 0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x5010,0x4908,0x4908, 0x4708,0x4708,0x4408,0x4408,0x4008,0x3908,0x4204,0x8004,0x4604,0x8004, 0x4704,0x800C,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01, 0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x5010,0x4B01, 0x4B01,0x4B01,0x4B01,0x4904,0x4904,0x4904,0x4901,0x4901,0x4901,0x4901, 0x4704,0x4704,0x4704,0x4408,0x4404,0x4404,0x4008,0x4004,0x4004,0x3B14, 0x3B01,0x3B01,0x3901,0x3B01,0x4001,0x4001,0x4001,0x4001,0x3904,0x4714, 0x4701,0x4701,0x4601,0x4701,0x4901,0x4901,0x4901,0x4901,0x4604,0x4B10, 0x5010,0x4B08,0x5210,0x5708,0x5610,0x5710,0x5610,0x5710,0x5608,0x5708, 0x5608,0x5708,0x5604,0x4204,0x4204,0x4204,0x4208,0x8008,0x4201,0x4201, 0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4001,0x4001, 0x3B01,0x3B01,0x3901,0x3901,0x3704,0x8004,0x4404,0x8004,0x4004,0x8004, 0x3904,0x8004,0x4204,0x800C,0x4B0A,0x4902,0x4702,0x4602,0x5404,0x8004, 0x5004,0x8004,0x3208,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201, 0x4201,0x4201,0x4201,0x4201,0x4201,0x4101,0x4101,0x4101,0x4101,0x4001, 0x4001,0x4001,0x4001,0x3901,0x3901,0x3901,0x3901,0x3704,0x8004,0x3904, 0x8004,0x3B04,0x8004,0x3804,0x8004,0x3904,0x8004,0x3704,0x8004,0x3604, 0x8004,0x3204,0x8004,0x3404,0x8004,0x3004,0x8004,0x3204,0x8004,0x3204, 0x8004,0x2708,0x8018,0x3208,0x8018,0x2708,0x8018,0x3208,0x8018,0x3B08, 0x8008,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01, 0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4908,0x8008,0x4901, 0x4901,0x4901,0x4901,0x4901,0x4901,0x4901,0x4901,0x4901,0x4901,0x4901, 0x4901,0x4901,0x4901,0x4901,0x4901,0x4704,0x4B04,0x5004,0x5204,0x5001, 0x5001,0x5001,0x5001,0x5201,0x5201,0x5401,0x5401,0x5204,0x5004,0x5001, 0x5001,0x5001,0x5001,0x4B04,0x4704,0x4B04,0x4B01,0x4B01,0x4B01,0x4B01, 0x4904,0x4704,0x4604,0x4704,0x3B04,0x4004,0x4004,0x4204,0x4204,0x3B04, 0x3B04,0x3904,0x3904,0x3B04,0x3B04,0x4004,0x4004,0x3904,0x3904,0x3B04, 0x4B04,0x5004,0x5004,0x5204,0x5204,0x4B04,0x4B04,0x4904,0x4904,0x4B04, 0x4B04,0x5004,0x5004,0x4904,0x4904,0x8004,0x3704,0x3B04,0x3904,0x3804, 0x3404,0x3604,0x3804,0x3904,0x4004,0x3904,0x3704,0x3604,0x3204,0x3404, 0x3604,0x3704,0x3704,0x3904,0x3B04,0x4004,0x4004,0x4004,0x4004,0x4204, 0x4204,0x4204,0x4204,0x3204,0x3204,0x3204,0x3204,0x3704,0x3204,0x3404, 0x3604,0x3704,0x3704,0x3904,0x3904,0x3B04,0x3604,0x3704,0x3904,0x3B04, 0x3B04,0x4004,0x4004,0x4204,0x4204,0x4304,0x4304,0x4408,0x8008,0x3001, 0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001, 0x3001,0x3001,0x3001,0x3001,0x3001,0x3210,0x2708,0x8018,0x3001,0x3001, 0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001, 0x3001,0x3001,0x3001,0x3001,0x3210,0x2708,0x8018,0x3008,0x8008,0x3208, 0x8008,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704, 0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704, 0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704, 0x2704,0x2704,0x2704,0x2704,0x2B04,0x3204,0x3704,0x3B04,0x3704,0x4204, 0x3B04,0x3708,0x2706,0x2702,0x2708,0x8008, 0x0000 }; #if defined(__C64__) || defined(__CBM510__) static unsigned long FreqTab [12] = { #ifndef NTSC /* PAL */ 0x008B38, 0x009381, 0x009C45, 0x00A590, 0x00AF68, 0x00B9D6, 0x00C4E4, 0x00D099, 0x00DCFF, 0x00EA24, 0x00F810, 0x0106D1, #else /* NTSC */ 0x00861E, 0x008E19, 0x00968B, 0x009F7F, 0x00A8FA, 0x00B307, 0x00BDAD, 0x00C8F4, 0x00D4E6, 0x00E18F, 0x00EEF9, 0x00FD2F, #endif }; #elif defined(__C128__) static unsigned long FreqTab [12] = { 0x00892B, 0x009153, 0x0099F7, 0x00A31E, 0x00ACD2, 0x00B718, 0x00C1FD, 0x00CD85, 0x00D9BD, 0x00E6B0, 0x00F467, 0x0102F0, }; #elif defined(__CBM610__) static unsigned long FreqTab [12] = { 0x004495, 0x0048AA, 0x004CFB, 0x00518F, 0x005669, 0x005B8C, 0x0060FE, 0x0066C3, 0x006CDE, 0x007358, 0x007A34, 0x008178, }; #endif typedef struct { unsigned char DoneMask; /* Set this if we're done */ unsigned char Trigger; /* Trigger value */ unsigned char Ticks; /* Ticks for this tone */ unsigned Freq; /* Actual frequency value */ unsigned* Data; /* Pointer to data */ struct __sid_voice* Voice; /* Pointer to sid registers */ } VoiceCtrl; /* Control structs for all three voices */ static VoiceCtrl V1 = { 0x01, 0x11, 0, 0, Voice1, &SID.v1 }; static VoiceCtrl V2 = { 0x02, 0x41, 0, 0, Voice2, &SID.v2 }; static VoiceCtrl V3 = { 0x04, 0x11, 0, 0, Voice3, &SID.v3 }; /* Pointers to the structs for easy reference */ static VoiceCtrl* V [3] = { &V1, &V2, &V3 }; /* Screen dimensions */ static unsigned char XSize, YSize; /* Variable that contains the time of the next clock tick to play a note */ static unsigned char NextClock; /* Start- and runtime */ static clock_t StartTime; /* Number of ticks for each tone */ #define TICKS_PER_TONE 4 /* Done flag. Contains one bit for each voice. Will contain 0x07 if all ** voices have finished playing. */ static unsigned char Done; /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void MakeTeeLine (unsigned char Y) /* Make a divider line */ { cputcxy (0, Y, CH_LTEE); chline (XSize - 2); cputc (CH_RTEE); } static void MakeNiceScreen (void) /* Make a nice screen */ { typedef struct { unsigned char Y; char* Msg; } TextDesc; static TextDesc Text [] = { { 2, "Wolfgang Amadeus Mozart" }, { 4, "\"Eine kleine Nachtmusik\"" }, { 5, "(KV 525)" }, { 9, "Ported to the SID in 1987 by" }, { 11, "Joachim von Bassewitz" }, { 12, "(joachim@von-bassewitz.de)" }, { 13, "and" }, { 14, "Ullrich von Bassewitz" }, { 15, "(ullrich@von-bassewitz.de)" }, { 18, "C Implementation by" }, { 19, "Ullrich von Bassewitz" }, { 23, "Press any key to quit..." }, }; register const TextDesc* T; unsigned char I; unsigned char X; /* Clear the screen hide the cursor, set colors */ #ifdef __CBM610__ textcolor (COLOR_WHITE); #else textcolor (COLOR_GRAY3); #endif bordercolor (COLOR_BLACK); bgcolor (COLOR_BLACK); clrscr (); cursor (0); /* Top line */ cputcxy (0, 0, CH_ULCORNER); chline (XSize - 2); cputc (CH_URCORNER); /* Left line */ cvlinexy (0, 1, 23); /* Bottom line */ cputc (CH_LLCORNER); chline (XSize - 2); cputc (CH_LRCORNER); /* Right line */ cvlinexy (XSize - 1, 1, 23); /* Several divider lines */ MakeTeeLine (7); MakeTeeLine (22); /* Write something into the frame */ for (I = 0, T = Text; I < sizeof (Text) / sizeof (Text [0]); ++I) { X = (XSize - strlen (T->Msg)) / 2; cputsxy (X, T->Y, T->Msg); ++T; } } static void TimeSync (void) /* Sync the time for the next tone */ { static unsigned char Clock; do { Clock = clock (); } while (Clock != NextClock); NextClock = Clock + TICKS_PER_TONE; } static void DisplayTime (void) /* Display the running time */ { clock_t Time = (clock () - StartTime) / CLOCKS_PER_SEC; unsigned Sec = Time % 60; unsigned Min = Time / 60; gotoxy (1, 0); cprintf ("%02d:%02d", Min, Sec); } /* On the 510/610, the SID is in another bank (the system bank), so we cannot ** just write to the memory space. */ #if defined(__CBM510__) || defined(__CBM610__) # define outb(addr,val) pokebsys ((unsigned)(addr), val) # define outw(addr,val) pokewsys ((unsigned)(addr), val) #else # define outb(addr,val) (*(addr)) = (val) # define outw(addr,val) (*(addr)) = (val) #endif int main (void) { unsigned char I; unsigned char Tone; unsigned char Octave; unsigned Val; struct __sid_voice* Voice; register VoiceCtrl* VC; /* Initialize the debugger */ DbgInit (0); /* Get the screen dimensions */ screensize (&XSize, &YSize); /* Make a nice screen */ MakeNiceScreen (); /* Initialize the SID */ outw (&SID.v1.pw, 0x0800); outb (&SID.v1.ad, 0x33); outb (&SID.v1.sr, 0xF0); outw (&SID.v2.pw, 0x0800); outb (&SID.v2.ad, 0x77); outb (&SID.v2.sr, 0x74); outw (&SID.v3.pw, 0x0800); outb (&SID.v3.ad, 0x77); outb (&SID.v3.sr, 0xD2); outw (&SID.flt_freq, 0xF0F0); outb (&SID.flt_ctrl, 0xF2); outb (&SID.amp, 0x5F); /* Sync the clock */ NextClock = StartTime = clock (); NextClock += TICKS_PER_TONE; /* Play each voice until all three are done */ while (Done != 0x07) { /* Display the time in the lower left corner */ DisplayTime (); /* Wait for the next run */ TimeSync (); /* Check for a key */ if (kbhit ()) { if (cgetc () == 'd') { /* Start the debugger */ BREAK (); } else { /* Stop playing music */ break; } } /* Play all three voices */ for (I = 0; I < 3; ++I) { /* Get a pointer to this voice */ VC = V [I]; Voice = VC->Voice; /* Is this voice done? */ if (Done & VC->DoneMask) { /* Voice already done */ continue; } /* Do we have any more ticks to play? */ if (VC->Ticks == 0) { /* We need new data */ if ((Val = *VC->Data) == 0) { /* End of data. Mark the voice as done */ Done |= VC->DoneMask; continue; } ++VC->Data; /* Get the ticks from the data */ VC->Ticks = (Val & 0x7F) - 1; /* Check if this is a tone or a pause */ if (Val & 0x8000) { /* This is a pause. Remember it and shut off the SID */ outb (&Voice->ctrl, VC->Trigger & 0xFE); } else { /* This is a tone. Extract the attributes. */ Tone = (Val >> 8) & 0x0F; Octave = ((Val >> 12) & 0x07) ^ 0x07; /* Calculate the frequency */ VC->Freq = FreqTab [Tone] >> Octave; /* Set the frequency */ outw (&Voice->freq, VC->Freq); /* Start the tone */ outb (&Voice->ctrl, VC->Trigger); } } else { /* Decrement the ticks. If this is the last tick of a tone, ** reset bit 0 of the trigger value and write it back to the ** SID to start the release phase. */ if (--(VC->Ticks) == 0) { outb (&Voice->ctrl, VC->Trigger & 0xFE); } } } } /* Reset the SID */ outb (&SID.v1.ctrl, 0x00); outb (&SID.v2.ctrl, 0x00); outb (&SID.v3.ctrl, 0x00); /* Clear the screen */ clrscr (); /* If we have a character, remove it from the buffer */ if (kbhit ()) { cgetc (); } /* Done */ return 0; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/overlaydemo.c���������������������������������������������������������������������0000664�0000000�0000000�00000006153�13473601511�0016350�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** Minimalistic overlay demo program. ** ** Shows how to load overlay files from disk. ** ** 2009-10-02, Oliver Schmidt (ol.sc@web.de) ** */ #include <stdio.h> #include <cc65.h> #ifndef __CBM__ #include <fcntl.h> #include <unistd.h> #else #include <cbm.h> #include <device.h> #endif extern void _OVERLAY1_LOAD__[], _OVERLAY1_SIZE__[]; extern void _OVERLAY2_LOAD__[], _OVERLAY2_SIZE__[]; extern void _OVERLAY3_LOAD__[], _OVERLAY3_SIZE__[]; /* Functions resident in an overlay can call back functions resident in the ** main program at any time without any precautions. The function log() is ** an example for such a function resident in the main program. */ void log (char *msg) { printf ("Log: %s\n", msg); } /* In a real-world overlay program one would probably not use a #pragma but ** rather place all the code of certain source files into the overlay by ** compiling them with --code-name OVERLAY1. */ #pragma code-name (push, "OVERLAY1"); void foo (void) { /* Functions resident in an overlay can access all program variables and ** constants at any time without any precautions because those are never ** placed in overlays. The string constant below is an example for such ** a constant resident in the main program. */ log ("Calling main from overlay 1"); } #pragma code-name (pop); #pragma code-name (push, "OVERLAY2"); void bar (void) { log ("Calling main from overlay 2"); } #pragma code-name (pop); #pragma code-name (push, "OVERLAY3"); void foobar (void) { log ("Calling main from overlay 3"); } #pragma code-name(pop); unsigned char loadfile (char *name, void *addr, void *size) { #ifndef __CBM__ int file = open (name, O_RDONLY); if (file == -1) { log ("Opening overlay file failed"); return 0; } read (file, addr, (unsigned) size); close (file); #else /* Avoid compiler warnings about unused parameters. */ (void) addr; (void) size; if (cbm_load (name, getcurrentdevice (), NULL) == 0) { log ("Loading overlay file failed"); return 0; } #endif return 1; } void main (void) { log ("Calling overlay 1 from main"); /* The symbols _OVERLAY1_LOAD__ and _OVERLAY1_SIZE__ were generated by the ** linker. They contain the overlay area address and size specific to a ** certain program. */ if (loadfile ("ovrldemo.1", _OVERLAY1_LOAD__, _OVERLAY1_SIZE__)) { /* The linker makes sure that the call to foo() ends up at the right mem ** addr. However it's up to user to make sure that the - right - overlay ** is actually loaded before making the the call. */ foo (); } log ("Calling overlay 2 from main"); /* Replacing one overlay with another one can only happen from the main ** program. This implies that an overlay can never load another overlay. */ if (loadfile ("ovrldemo.2", _OVERLAY2_LOAD__, _OVERLAY2_SIZE__)) { bar (); } log ("Calling overlay 3 from main"); if (loadfile ("ovrldemo.3", _OVERLAY3_LOAD__, _OVERLAY3_SIZE__)) { foobar (); } if (doesclrscrafterexit ()) { getchar (); } } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/plasma.c��������������������������������������������������������������������������0000664�0000000�0000000�00000020632�13473601511�0015275�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************\ ** plasma test program for cc65. ** ** ** ** (w)2001 by groepaz/hitmen ** ** ** ** Cleanup and porting by Ullrich von Bassewitz. ** ** ** \*****************************************************************************/ #include <stdlib.h> #include <time.h> #include <conio.h> #include <cc65.h> #if defined(__C64__) || defined(__C128__) # define SCREEN1 0xE000 # define SCREEN2 0xE400 # define CHARSET 0xE800 # define outb(addr,val) (*(addr)) = (val) # define inb(addr) (*(addr)) #elif defined(__CBM510__) # define SCREEN1 0xF000 # define SCREEN2 0xF400 # define CHARSET 0xE000 # define outb(addr,val) pokebsys ((unsigned)(addr), val) # define inb(addr) peekbsys ((unsigned)(addr)) #elif defined(__PLUS4__) # define SCREEN1 0x6400 # define SCREEN2 0x6C00 # define CHARSET 0x7000 # define outb(addr,val) (*(addr)) = (val) # define inb(addr) (*(addr)) #endif /* Values for the VIC address register to switch between the two pages */ #if defined(__PLUS4__) #define PAGE1 ((SCREEN1 >> 8) & 0xF8) #define PAGE2 ((SCREEN2 >> 8) & 0xF8) #define CHARADR ((CHARSET >> 8) & 0xFC) #else #define PAGE1 ((SCREEN1 >> 6) & 0xF0) | ((CHARSET >> 10) & 0x0E) #define PAGE2 ((SCREEN2 >> 6) & 0xF0) | ((CHARSET >> 10) & 0x0E) #endif /* Use static local variables for speed */ #pragma static-locals (1); static const unsigned char sinustable[0x100] = { 0x80, 0x7d, 0x7a, 0x77, 0x74, 0x70, 0x6d, 0x6a, 0x67, 0x64, 0x61, 0x5e, 0x5b, 0x58, 0x55, 0x52, 0x4f, 0x4d, 0x4a, 0x47, 0x44, 0x41, 0x3f, 0x3c, 0x39, 0x37, 0x34, 0x32, 0x2f, 0x2d, 0x2b, 0x28, 0x26, 0x24, 0x22, 0x20, 0x1e, 0x1c, 0x1a, 0x18, 0x16, 0x15, 0x13, 0x11, 0x10, 0x0f, 0x0d, 0x0c, 0x0b, 0x0a, 0x08, 0x07, 0x06, 0x06, 0x05, 0x04, 0x03, 0x03, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x04, 0x05, 0x06, 0x06, 0x07, 0x08, 0x0a, 0x0b, 0x0c, 0x0d, 0x0f, 0x10, 0x11, 0x13, 0x15, 0x16, 0x18, 0x1a, 0x1c, 0x1e, 0x20, 0x22, 0x24, 0x26, 0x28, 0x2b, 0x2d, 0x2f, 0x32, 0x34, 0x37, 0x39, 0x3c, 0x3f, 0x41, 0x44, 0x47, 0x4a, 0x4d, 0x4f, 0x52, 0x55, 0x58, 0x5b, 0x5e, 0x61, 0x64, 0x67, 0x6a, 0x6d, 0x70, 0x74, 0x77, 0x7a, 0x7d, 0x80, 0x83, 0x86, 0x89, 0x8c, 0x90, 0x93, 0x96, 0x99, 0x9c, 0x9f, 0xa2, 0xa5, 0xa8, 0xab, 0xae, 0xb1, 0xb3, 0xb6, 0xb9, 0xbc, 0xbf, 0xc1, 0xc4, 0xc7, 0xc9, 0xcc, 0xce, 0xd1, 0xd3, 0xd5, 0xd8, 0xda, 0xdc, 0xde, 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xeb, 0xed, 0xef, 0xf0, 0xf1, 0xf3, 0xf4, 0xf5, 0xf6, 0xf8, 0xf9, 0xfa, 0xfa, 0xfb, 0xfc, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfd, 0xfd, 0xfc, 0xfb, 0xfa, 0xfa, 0xf9, 0xf8, 0xf6, 0xf5, 0xf4, 0xf3, 0xf1, 0xf0, 0xef, 0xed, 0xeb, 0xea, 0xe8, 0xe6, 0xe4, 0xe2, 0xe0, 0xde, 0xdc, 0xda, 0xd8, 0xd5, 0xd3, 0xd1, 0xce, 0xcc, 0xc9, 0xc7, 0xc4, 0xc1, 0xbf, 0xbc, 0xb9, 0xb6, 0xb3, 0xb1, 0xae, 0xab, 0xa8, 0xa5, 0xa2, 0x9f, 0x9c, 0x99, 0x96, 0x93, 0x90, 0x8c, 0x89, 0x86, 0x83 }; static void doplasma (register unsigned char* scrn) { unsigned char xbuf[40]; unsigned char ybuf[25]; unsigned char c1a,c1b; unsigned char c2a,c2b; unsigned char c1A,c1B; unsigned char c2A,c2B; register unsigned char i, ii; c1a = c1A; c1b = c1B; for (ii = 0; ii < 25; ++ii) { ybuf[ii] = (sinustable[c1a] + sinustable[c1b]); c1a += 4; c1b += 9; } c1A += 3; c1B -= 5; c2a = c2A; c2b = c2B; for (i = 0; i < 40; ++i) { xbuf[i] = (sinustable[c2a] + sinustable[c2b]); c2a += 3; c2b += 7; } c2A += 2; c2B -= 3; for (ii = 0; ii < 25; ++ii) { /* Unrolling the following loop will give a speed increase of ** nearly 100% (~24fps), but it will also increase the code ** size a lot. */ for (i = 0; i < 40; ++i, ++scrn) { *scrn = (xbuf[i] + ybuf[ii]); } } } static void makechar (void) { static const unsigned char bittab[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; unsigned char i, ii, b, s; unsigned c; gotoxy (0, 1); for (c = 0; c < 0x100; ++c) { s = sinustable[c]; for (i = 0; i < 8; ++i){ b = 0; for (ii = 0; ii < 8; ++ii) { if ((rand() & 0xFF) > s) { b |= bittab[ii]; } } ((unsigned char*)CHARSET) [(c*8) + i] = b; } if ((c & 0x07) == 0) { cputc ('.'); } } } int main (void) { unsigned char border; unsigned char background; unsigned char text; unsigned char v; clock_t t; unsigned long f = 0; unsigned long sec; unsigned sec10; unsigned long fps; unsigned fps10; #if defined(__C64__) unsigned char block; #endif #if defined(__C128__) unsigned char block; unsigned char initflag; unsigned char graphflag; #endif #if defined(__PLUS4__) unsigned int i; unsigned char v2; #endif clrscr (); cprintf ("Making charset, mompls"); makechar(); /* Set the border and background colors */ border = bordercolor (COLOR_BLUE); background = bgcolor (COLOR_BLUE); text = textcolor (COLOR_BLACK); clrscr (); #if defined(__C64__) || defined(__C128__) /* Move the VIC 16K block */ block = inb (&CIA2.pra); outb (&CIA2.pra, (block & 0xFC) | ((SCREEN1 >> 14) ^ 0x03)); #endif #if defined(__C128__) /* Save and change some flags, so that kernal/basic interrupt handler will ** not interfere with our routine. */ initflag = *(unsigned char*) 0xA04; *(unsigned char*) 0xA04 &= 0xFE; graphflag = *(unsigned char*) 0xD8; *(unsigned char*) 0xD8 = 0xFF; #endif /* Remember the VIC address register */ #if defined(__PLUS4__) v = inb (&TED.char_addr); v2 = inb (&TED.video_addr); #else v = inb (&VIC.addr); #endif #if defined(__PLUS4__) for (i=0;i<1000;i++) { ((unsigned char *) (SCREEN1-0x0400))[i] = 0; ((unsigned char *) (SCREEN2-0x0400))[i] = 0; } outb (&TED.char_addr, CHARADR); #endif /* Run the demo until a key was hit */ t = clock (); while (!kbhit()) { /* Build page 1, then make it visible */ doplasma ((unsigned char*)SCREEN1); #if defined(__PLUS4__) outb (&TED.video_addr, PAGE1); #else outb (&VIC.addr, PAGE1); #endif /* Build page 2, then make it visible */ doplasma ((unsigned char*)SCREEN2); #if defined(__PLUS4__) outb (&TED.video_addr, PAGE2); #else outb (&VIC.addr, PAGE2); #endif /* Count frames */ f += 2; } t = clock() - t; /* Switch back the VIC screen */ #if defined(__PLUS4__) outb (&TED.video_addr, v2); outb (&TED.char_addr, v); #else outb (&VIC.addr, v); #endif #if defined(__C64__) || defined(__C128__) /* Move back the VIC 16K block */ outb (&CIA2.pra, block); #endif #if defined(__C128__) /* Restore the flags */ *(unsigned char*) 0xA04 = initflag; *(unsigned char*) 0xD8 = graphflag; #endif /* Fetch the character from the keyboard buffer and discard it */ (void) cgetc(); /* Reset screen colors */ bordercolor (border); bgcolor (background); textcolor (text); clrscr (); /* Calculate stats */ sec = (t * 10) / CLK_TCK; sec10 = sec % 10; sec /= 10; fps = (f * (CLK_TCK * 10)) / t; fps10 = fps % 10; fps /= 10; /* Output stats */ gotoxy (0, 0); cprintf ("time : %lu.%us", sec, sec10); gotoxy (0, 1); cprintf ("frames: %lu", f); gotoxy (0, 2); cprintf ("fps : %lu.%u", fps, fps10); if (doesclrscrafterexit ()) { cputsxy (0, 4, "Press any key when done..."); (void) cgetc (); } /* Done */ return EXIT_SUCCESS; } ������������������������������������������������������������������������������������������������������cc65-2.18/samples/sieve.c���������������������������������������������������������������������������0000664�0000000�0000000�00000005474�13473601511�0015142�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** Calculate all primes up to a specific number. */ #include <stdlib.h> #include <stdio.h> #include <ctype.h> #include <time.h> #include <conio.h> /* Workaround missing clock stuff */ #ifdef __APPLE2__ # define clock() 0 # define CLOCKS_PER_SEC 1 #endif /*****************************************************************************/ /* Data */ /*****************************************************************************/ #define COUNT 16384 /* Up to what number? */ #define SQRT_COUNT 128 /* Sqrt of COUNT */ static unsigned char Sieve[COUNT]; /*****************************************************************************/ /* Code */ /*****************************************************************************/ #pragma static-locals(1); static char ReadUpperKey (void) /* Read a key from console, convert to upper case and return */ { return toupper (cgetc ()); } int main (void) { /* Clock variable */ clock_t Ticks; unsigned Sec; unsigned Milli; /* This is an example where register variables make sense */ register unsigned char* S; register unsigned I; register unsigned J; /* Output a header */ printf ("Sieve benchmark - calculating primes\n"); printf ("between 2 and %u\n", COUNT); printf ("Please wait patiently ...\n"); /* Read the clock */ Ticks = clock(); /* Execute the sieve */ I = 2; while (I < SQRT_COUNT) { if (Sieve[I] == 0) { /* Prime number - mark multiples */ J = I*2; S = &Sieve[J]; while (J < COUNT) { *S = 1; S += I; J += I; } } ++I; } /* Calculate the time used */ Ticks = clock() - Ticks; Sec = (unsigned) (Ticks / CLOCKS_PER_SEC); Milli = ((Ticks % CLOCKS_PER_SEC) * 1000) / CLOCKS_PER_SEC; /* Print the time used */ printf ("Time used: %u.%03u seconds\n", Sec, Milli); printf ("Q to quit, any other key for list\n"); /* Wait for a key and print the list if not 'Q' */ if (ReadUpperKey () != 'Q') { /* Print the result */ J = 0; for (I = 2; I < COUNT; ++I) { if (Sieve[I] == 0) { printf ("%4d\n", I); if (++J == 23) { printf ("Q to quit, any other key continues\n"); if (ReadUpperKey () == 'Q') { break; } J = 0; } } if (kbhit() && ReadUpperKey () == 'Q') { break; } } } return EXIT_SUCCESS; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/tgidemo.c�������������������������������������������������������������������������0000664�0000000�0000000�00000012362�13473601511�0015451�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <stdio.h> #include <stdlib.h> #include <cc65.h> #include <conio.h> #include <ctype.h> #include <modload.h> #include <tgi.h> #ifndef DYN_DRV # define DYN_DRV 1 #endif #define COLOR_BACK TGI_COLOR_BLACK #define COLOR_FORE TGI_COLOR_WHITE /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Driver stuff */ static unsigned MaxX; static unsigned MaxY; static unsigned AspectRatio; /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void CheckError (const char* S) { unsigned char Error = tgi_geterror (); if (Error != TGI_ERR_OK) { printf ("%s: %d\n", S, Error); if (doesclrscrafterexit ()) { cgetc (); } exit (EXIT_FAILURE); } } #if DYN_DRV static void DoWarning (void) /* Warn the user that the dynamic TGI driver is needed for this program */ { printf ("Warning: This program needs the TGI\n" "driver on disk! Press 'y' if you have\n" "it - any other key exits.\n"); if (tolower (cgetc ()) != 'y') { exit (EXIT_SUCCESS); } printf ("OK. Please wait patiently...\n"); } #endif static void DoCircles (void) { static const unsigned char Palette[2] = { TGI_COLOR_WHITE, TGI_COLOR_ORANGE }; unsigned char I; unsigned char Color = COLOR_FORE; unsigned X = MaxX / 2; unsigned Y = MaxY / 2; tgi_setpalette (Palette); while (!kbhit ()) { tgi_setcolor (COLOR_FORE); tgi_line (0, 0, MaxX, MaxY); tgi_line (0, MaxY, MaxX, 0); tgi_setcolor (Color); for (I = 10; I < 240; I += 10) { tgi_ellipse (X, Y, I, tgi_imulround (I, AspectRatio)); } Color = Color == COLOR_FORE ? COLOR_BACK : COLOR_FORE; } cgetc (); tgi_clear (); } static void DoCheckerboard (void) { static const unsigned char Palette[2] = { TGI_COLOR_WHITE, TGI_COLOR_BLACK }; unsigned X, Y; unsigned char Color; tgi_setpalette (Palette); Color = COLOR_BACK; while (1) { for (Y = 0; Y <= MaxY; Y += 10) { for (X = 0; X <= MaxX; X += 10) { tgi_setcolor (Color); tgi_bar (X, Y, X+9, Y+9); Color = Color == COLOR_FORE ? COLOR_BACK : COLOR_FORE; if (kbhit ()) { cgetc (); tgi_clear (); return; } } Color = Color == COLOR_FORE ? COLOR_BACK : COLOR_FORE; } Color = Color == COLOR_FORE ? COLOR_BACK : COLOR_FORE; } } static void DoDiagram (void) { static const unsigned char Palette[2] = { TGI_COLOR_WHITE, TGI_COLOR_BLACK }; int XOrigin, YOrigin; int Amp; int X, Y; unsigned I; tgi_setpalette (Palette); tgi_setcolor (COLOR_FORE); /* Determine zero and aplitude */ YOrigin = MaxY / 2; XOrigin = 10; Amp = (MaxY - 19) / 2; /* Y axis */ tgi_line (XOrigin, 10, XOrigin, MaxY-10); tgi_line (XOrigin-2, 12, XOrigin, 10); tgi_lineto (XOrigin+2, 12); /* X axis */ tgi_line (XOrigin, YOrigin, MaxX-10, YOrigin); tgi_line (MaxX-12, YOrigin-2, MaxX-10, YOrigin); tgi_lineto (MaxX-12, YOrigin+2); /* Sine */ tgi_gotoxy (XOrigin, YOrigin); for (I = 0; I <= 360; I += 5) { /* Calculate the next points */ X = (int) (((long) (MaxX - 19) * I) / 360); Y = (int) (((long) Amp * -_sin (I)) / 256); /* Draw the line */ tgi_lineto (XOrigin + X, YOrigin + Y); } cgetc (); tgi_clear (); } static void DoLines (void) { static const unsigned char Palette[2] = { TGI_COLOR_WHITE, TGI_COLOR_BLACK }; unsigned X; tgi_setpalette (Palette); tgi_setcolor (COLOR_FORE); for (X = 0; X <= MaxY; X += 10) { tgi_line (0, 0, MaxY, X); tgi_line (0, 0, X, MaxY); tgi_line (MaxY, MaxY, 0, MaxY-X); tgi_line (MaxY, MaxY, MaxY-X, 0); } cgetc (); tgi_clear (); } int main (void) { unsigned char Border; #if DYN_DRV /* Warn the user that the tgi driver is needed */ DoWarning (); /* Load and initialize the driver */ tgi_load_driver (tgi_stddrv); CheckError ("tgi_load_driver"); #else /* Install the driver */ tgi_install (tgi_static_stddrv); CheckError ("tgi_install"); #endif tgi_init (); CheckError ("tgi_init"); tgi_clear (); /* Get stuff from the driver */ MaxX = tgi_getmaxx (); MaxY = tgi_getmaxy (); AspectRatio = tgi_getaspectratio (); /* Set the palette, set the border color */ Border = bordercolor (COLOR_BLACK); /* Do graphics stuff */ DoCircles (); DoCheckerboard (); DoDiagram (); DoLines (); #if DYN_DRV /* Unload the driver */ tgi_unload (); #else /* Uninstall the driver */ tgi_uninstall (); #endif /* Reset the border */ (void) bordercolor (Border); /* Done */ printf ("Done\n"); return EXIT_SUCCESS; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/tutorial/�������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015514�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/tutorial/hello.c������������������������������������������������������������������0000664�0000000�0000000�00000000243�13473601511�0016762�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <stdio.h> #include <stdlib.h> extern const char text[]; /* In text.s */ int main (void) { printf ("%s\n", text); return EXIT_SUCCESS; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/samples/tutorial/text.s�������������������������������������������������������������������0000664�0000000�0000000�00000000077�13473601511�0016670�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ .export _text _text: .asciiz "Hello world!" �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/��������������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0012774�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/.gitignore����������������������������������������������������������������������������0000664�0000000�0000000�00000000124�13473601511�0014761�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ipch/ *.suo *.sdf *.opensdf *.VC.db *.VC.VC.opendb *.vcxproj.filters *.vcxproj.user ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/Makefile������������������������������������������������������������������������������0000664�0000000�0000000�00000005651�13473601511�0014443�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ifneq ($(shell echo),) CMD_EXE = 1 endif PROGS = ar65 \ ca65 \ cc65 \ chrcvt65 \ cl65 \ co65 \ da65 \ grc65 \ ld65 \ od65 \ sim65 \ sp65 .PHONY: all mostlyclean clean install zip avail unavail bin $(PROGS) .SUFFIXES: bindir := $(PREFIX)/bin datadir := $(if $(PREFIX),$(PREFIX)/share/cc65,$(abspath ..)) CA65_INC = $(datadir)/asminc CC65_INC = $(datadir)/include CL65_TGT = $(datadir)/target LD65_LIB = $(datadir)/lib LD65_OBJ = $(datadir)/lib LD65_CFG = $(datadir)/cfg ifdef CMD_EXE NULLDEV = nul: DIRLIST = $(strip $(foreach dir,$1,$(wildcard $(dir)))) MKDIR = mkdir $(subst /,\,$1) RMDIR = $(if $(DIRLIST),rmdir /s /q $(subst /,\,$(DIRLIST))) else NULLDEV = /dev/null MKDIR = mkdir -p $1 RMDIR = $(RM) -r $1 endif CC = $(CROSS_COMPILE)gcc AR = $(CROSS_COMPILE)ar ifdef CROSS_COMPILE $(info CC: $(CC)) $(info AR: $(AR)) endif ifdef USER_CFLAGS $(info USER_CFLAGS: $(USER_CFLAGS)) endif ifdef GIT_SHA $(info GIT_SHA: $(GIT_SHA)) else GIT_SHA := $(shell git rev-parse --short HEAD 2>$(NULLDEV) || svnversion 2>$(NULLDEV)) ifneq ($(words $(GIT_SHA)),1) GIT_SHA := N/A $(info GIT_SHA: N/A) endif endif CFLAGS += -MMD -MP -O3 -I common \ -Wall -Wextra -Wno-char-subscripts $(USER_CFLAGS) \ -DCA65_INC="$(CA65_INC)" -DCC65_INC="$(CC65_INC)" -DCL65_TGT="$(CL65_TGT)" \ -DLD65_LIB="$(LD65_LIB)" -DLD65_OBJ="$(LD65_OBJ)" -DLD65_CFG="$(LD65_CFG)" \ -DGIT_SHA=$(GIT_SHA) LDLIBS += -lm ifdef CMD_EXE EXE_SUFFIX=.exe endif ifdef CROSS_COMPILE EXE_SUFFIX=.exe endif all bin: $(PROGS) mostlyclean: $(call RMDIR,../wrk) clean: $(call RMDIR,../wrk ../bin) ifdef CMD_EXE install avail unavail: else # CMD_EXE INSTALL = install define AVAIL_recipe ln -s $(abspath ../bin/$(prog)) /usr/local/bin/$(prog) endef # AVAIL_recipe define UNAVAIL_recipe $(RM) /usr/local/bin/$(prog) endef # UNAVAIL_recipe install: $(if $(PREFIX),,$(error variable "PREFIX" must be set)) $(INSTALL) -d $(DESTDIR)$(bindir) $(INSTALL) ../bin/* $(DESTDIR)$(bindir) avail: $(foreach prog,$(PROGS),$(AVAIL_recipe)) unavail: $(foreach prog,$(PROGS),$(UNAVAIL_recipe)) endif # CMD_EXE zip: @cd .. && zip cc65 bin/* define OBJS_template $1_OBJS := $$(patsubst %.c,../wrk/%.o,$$(wildcard $1/*.c)) $$($1_OBJS): | ../wrk/$1 ../wrk/$1: @$$(call MKDIR,$$@) DEPS += $$($1_OBJS:.o=.d) endef # OBJS_template define PROG_template $$(eval $$(call OBJS_template,$1)) ../bin/$1$(EXE_SUFFIX): $$($1_OBJS) ../wrk/common/common.a | ../bin $$(CC) $$(LDFLAGS) -o $$@ $$^ $$(LDLIBS) $1: ../bin/$1$(EXE_SUFFIX) endef # PROG_template ../wrk/%.o: %.c @echo $< @$(CC) -c $(CFLAGS) -o $@ $< ../bin: @$(call MKDIR,$@) $(eval $(call OBJS_template,common)) ../wrk/common/common.a: $(common_OBJS) $(AR) r $@ $? $(foreach prog,$(PROGS),$(eval $(call PROG_template,$(prog)))) -include $(DEPS) ���������������������������������������������������������������������������������������cc65-2.18/src/ar65.vcxproj��������������������������������������������������������������������������0000664�0000000�0000000�00000012030�13473601511�0015162�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> <ProjectConfiguration Include="Release|Win32"> <Configuration>Release</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> </ItemGroup> <PropertyGroup Label="Globals"> <ProjectGuid>{5E8C19C6-B167-440C-8BEF-3CBF109CDB49}</ProjectGuid> <Keyword>Win32Proj</Keyword> <RootNamespace>ar65</RootNamespace> <WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <UseDebugLibraries>true</UseDebugLibraries> <PlatformToolset>v141</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <UseDebugLibraries>false</UseDebugLibraries> <WholeProgramOptimization>true</WholeProgramOptimization> <PlatformToolset>v141</PlatformToolset> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <PropertyGroup Label="UserMacros" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <LinkIncremental>true</LinkIncremental> <OutDir>$(SolutionDir)..\bin\</OutDir> <IntDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</IntDir> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <OutDir>$(SolutionDir)..\bin\</OutDir> <IntDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</IntDir> </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ClCompile> <PrecompiledHeader> </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> <Link> <SubSystem>Console</SubSystem> <GenerateDebugInformation>true</GenerateDebugInformation> <AdditionalDependencies>$(IntDir)..\..\common\$(Configuration)\common.lib</AdditionalDependencies> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ClCompile> <WarningLevel>Level3</WarningLevel> <PrecompiledHeader> </PrecompiledHeader> <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> <Link> <SubSystem>Console</SubSystem> <GenerateDebugInformation>false</GenerateDebugInformation> <AdditionalDependencies>$(IntDir)..\..\common\$(Configuration)\common.lib</AdditionalDependencies> </Link> </ItemDefinitionGroup> <ItemGroup> <ClInclude Include="ar65\add.h" /> <ClInclude Include="ar65\del.h" /> <ClInclude Include="ar65\error.h" /> <ClInclude Include="ar65\exports.h" /> <ClInclude Include="ar65\extract.h" /> <ClInclude Include="ar65\fileio.h" /> <ClInclude Include="ar65\global.h" /> <ClInclude Include="ar65\library.h" /> <ClInclude Include="ar65\list.h" /> <ClInclude Include="ar65\objdata.h" /> <ClInclude Include="ar65\objfile.h" /> </ItemGroup> <ItemGroup> <ClCompile Include="ar65\add.c" /> <ClCompile Include="ar65\del.c" /> <ClCompile Include="ar65\error.c" /> <ClCompile Include="ar65\exports.c" /> <ClCompile Include="ar65\extract.c" /> <ClCompile Include="ar65\fileio.c" /> <ClCompile Include="ar65\global.c" /> <ClCompile Include="ar65\library.c" /> <ClCompile Include="ar65\list.c" /> <ClCompile Include="ar65\main.c" /> <ClCompile Include="ar65\objdata.c" /> <ClCompile Include="ar65\objfile.c" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> </Project>��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ar65/���������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0013551�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ar65/add.c����������������������������������������������������������������������������0000664�0000000�0000000�00000006640�13473601511�0014453�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* add.c */ /* */ /* Object file adding for the ar65 archiver */ /* */ /* */ /* */ /* (C) 1998 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdlib.h> #include "error.h" #include "objfile.h" #include "library.h" #include "add.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void AddObjFiles (int argc, char* argv []) /* Add object files to a library */ { int I; /* Check the argument count */ if (argc <= 0) { Error ("No library name given"); } if (argc <= 1) { Error ("No object files to add"); } /* Open the library, read the index */ LibOpen (argv [0], 0, 1); /* Add the object files */ I = 1; while (I < argc) { ObjAdd (argv [I]); ++I; } /* Create a new library file and close the old one */ LibClose (); /* Successful end */ exit (EXIT_SUCCESS); } ������������������������������������������������������������������������������������������������cc65-2.18/src/ar65/add.h����������������������������������������������������������������������������0000664�0000000�0000000�00000005603�13473601511�0014456�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* add.h */ /* */ /* Object file adding for the ar65 archiver */ /* */ /* */ /* */ /* (C) 1998 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 ADD_H #define ADD_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ void AddObjFiles (int argc, char* argv []); /* Add object files to a library */ /* End of add.h */ #endif �����������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ar65/del.c����������������������������������������������������������������������������0000664�0000000�0000000�00000006716�13473601511�0014473�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* del.h */ /* */ /* Object file deleting for the ar65 archiver */ /* */ /* */ /* */ /* (C) 1998 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdlib.h> #include "error.h" #include "objdata.h" #include "library.h" #include "del.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void DelObjFiles (int argc, char* argv []) /* Delete modules from a library */ { int I; /* Check the argument count */ if (argc <= 0) { Error ("No library name given"); } if (argc <= 1) { Error ("No modules to delete"); } /* Open the library, read the index */ LibOpen (argv [0], 1, 1); /* Delete the modules */ I = 1; while (I < argc) { /* Delete the module from the list */ DelObjData (argv [I]); ++I; } /* Create a new library file and close the old one */ LibClose (); /* Successful end */ exit (EXIT_SUCCESS); } ��������������������������������������������������cc65-2.18/src/ar65/del.h����������������������������������������������������������������������������0000664�0000000�0000000�00000005622�13473601511�0014473�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* del.h */ /* */ /* Object file deleting for the ar65 archiver */ /* */ /* */ /* */ /* (C) 1998 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 DEL_H #define DEL_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ void DelObjFiles (int argc, char* argv []); /* Delete modules from a library */ /* End of del.h */ #endif ��������������������������������������������������������������������������������������������������������������cc65-2.18/src/ar65/error.c��������������������������������������������������������������������������0000664�0000000�0000000�00000007237�13473601511�0015057�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* global.c */ /* */ /* Error handling for the ar65 archiver */ /* */ /* */ /* */ /* (C) 1998-2003 Ullrich von Bassewitz */ /* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> /* common */ #include "cmdline.h" /* ar65 */ #include "error.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Warning (const char* Format, ...) /* Print a warning message */ { va_list ap; va_start (ap, Format); fprintf (stderr, "%s: Warning: ", ProgName); vfprintf (stderr, Format, ap); putc ('\n', stderr); va_end (ap); } void Error (const char* Format, ...) /* Print an error message and die */ { va_list ap; va_start (ap, Format); fprintf (stderr, "%s: Error: ", ProgName); vfprintf (stderr, Format, ap); putc ('\n', stderr); va_end (ap); exit (EXIT_FAILURE); } void Internal (const char* Format, ...) /* Print an internal error message and die */ { va_list ap; va_start (ap, Format); fprintf (stderr, "%s: Internal error: ", ProgName); vfprintf (stderr, Format, ap); putc ('\n', stderr); va_end (ap); exit (EXIT_FAILURE); } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ar65/error.h��������������������������������������������������������������������������0000664�0000000�0000000�00000006273�13473601511�0015063�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* global.h */ /* */ /* Error handling for the ar65 archiver */ /* */ /* */ /* */ /* (C) 1998-2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef ERROR_H #define ERROR_H /* common */ #include "attrib.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Warning (const char* Format, ...) attribute((format(printf,1,2))); /* Print a warning message */ void Error (const char* Format, ...) attribute((noreturn, format(printf,1,2))); /* Print an error message and die */ void Internal (const char* Format, ...) attribute((noreturn, format(printf,1,2))); /* Print an internal error message and die */ /* End of error.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ar65/exports.c������������������������������������������������������������������������0000664�0000000�0000000�00000012730�13473601511�0015424�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* exports.c */ /* */ /* Duplicate export checking for the ar65 archiver */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* common */ #include "hashfunc.h" #include "xmalloc.h" /* ar65 */ #include "error.h" #include "library.h" #include "objdata.h" #include "exports.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* A hash table entry */ typedef struct HashEntry HashEntry; struct HashEntry { HashEntry* Next; /* Next in list */ const ObjData* Module; /* Pointer to object module */ char Name [1]; /* Name of identifier */ }; /* Hash table */ #define HASHTAB_SIZE 4783 static HashEntry* HashTab [HASHTAB_SIZE]; /*****************************************************************************/ /* Code */ /*****************************************************************************/ static HashEntry* NewHashEntry (const char* Name, const ObjData* Module) /* Create and return a new hash entry */ { /* Get the length of the name */ unsigned Len = strlen (Name); /* Get memory for the struct */ HashEntry* H = xmalloc (sizeof (HashEntry) + Len); /* Initialize the fields and return it */ H->Next = 0; H->Module = Module; memcpy (H->Name, Name, Len); H->Name [Len] = '\0'; return H; } void ExpInsert (const char* Name, const ObjData* Module) /* Insert an exported identifier and check if it's already in the list */ { HashEntry* L; /* Create a hash value for the given name */ unsigned HashVal = HashStr (Name) % HASHTAB_SIZE; /* Create a new hash entry */ HashEntry* H = NewHashEntry (Name, Module); /* Search through the list in that slot and print matching duplicates */ if (HashTab [HashVal] == 0) { /* The slot is empty */ HashTab [HashVal] = H; return; } L = HashTab [HashVal]; while (1) { if (strcmp (L->Name, Name) == 0) { /* Duplicate entry */ Warning ("External symbol '%s' in module '%s', library '%s', " "is duplicated in module '%s'", Name, L->Module->Name, LibName, Module->Name); } if (L->Next == 0) { break; } else { L = L->Next; } } L->Next = H; } const ObjData* ExpFind (const char* Name) /* Check for an identifier in the list. Return NULL if not found, otherwise ** return a pointer to the module, that exports the identifer. */ { /* Get a pointer to the list with the symbols hash value */ HashEntry* L = HashTab [HashStr (Name) % HASHTAB_SIZE]; while (L) { /* Search through the list in that slot */ if (strcmp (L->Name, Name) == 0) { /* Entry found */ return L->Module; } L = L->Next; } /* Not found */ return 0; } ����������������������������������������cc65-2.18/src/ar65/exports.h������������������������������������������������������������������������0000664�0000000�0000000�00000006621�13473601511�0015433�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* exports.h */ /* */ /* Duplicate export checking for the ar65 archiver */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef EXPORTS_H #define EXPORTS_H /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ struct ObjData; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void ExpInsert (const char* Name, const struct ObjData* Module); /* Insert an exported identifier and check if it's already in the list */ const struct ObjData* ExpFind (const char* Name); /* Check for an identifier in the list. Return NULL if not found, otherwise ** return a pointer to the module, that exports the identifer. */ /* End of exports.h */ #endif ���������������������������������������������������������������������������������������������������������������cc65-2.18/src/ar65/extract.c������������������������������������������������������������������������0000664�0000000�0000000�00000006672�13473601511�0015402�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* extract.c */ /* */ /* Object file extraction for the ar65 archiver */ /* */ /* */ /* */ /* (C) 1998 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdlib.h> #include "error.h" #include "objfile.h" #include "library.h" #include "extract.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void ExtractObjFiles (int argc, char* argv []) /* Extract object files from a library */ { int I; /* Check the argument count */ if (argc <= 0) { Error ("No library name given"); } if (argc <= 1) { Error ("No object files to extract"); } /* Open the library, read the index */ LibOpen (argv [0], 1, 0); /* Extract the object files */ I = 1; while (I < argc) { ObjExtract (argv [I]); ++I; } /* Create a new library file and close the old one */ LibClose (); /* Successful end */ exit (EXIT_SUCCESS); } ����������������������������������������������������������������������cc65-2.18/src/ar65/extract.h������������������������������������������������������������������������0000664�0000000�0000000�00000005631�13473601511�0015401�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* extract.h */ /* */ /* Object file extraction for the ar65 archiver */ /* */ /* */ /* */ /* (C) 1998 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 EXTRACT_H #define EXTRACT_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ void ExtractObjFiles (int argc, char* argv []); /* Extract object files from a library */ /* End of extract.h */ #endif �������������������������������������������������������������������������������������������������������cc65-2.18/src/ar65/fileio.c�������������������������������������������������������������������������0000664�0000000�0000000�00000013652�13473601511�0015173�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* fileio.c */ /* */ /* File I/O for the ar65 archiver */ /* */ /* */ /* */ /* (C) 1998-2003 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* common */ #include "xmalloc.h" /* ar65 */ #include "error.h" #include "fileio.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Write8 (FILE* F, unsigned char Val) /* Write an 8 bit value to the file */ { if (putc (Val, F) == EOF) { Error ("Write error (disk full?)"); } } void Write16 (FILE* F, unsigned Val) /* Write a 16 bit value to the file */ { Write8 (F, (unsigned char) Val); Write8 (F, (unsigned char) (Val >> 8)); } void Write32 (FILE* F, unsigned long Val) /* Write a 32 bit value to the file */ { Write8 (F, (unsigned char) Val); Write8 (F, (unsigned char) (Val >> 8)); Write8 (F, (unsigned char) (Val >> 16)); Write8 (F, (unsigned char) (Val >> 24)); } void WriteVar (FILE* F, unsigned long V) /* Write a variable sized value to the file in special encoding */ { /* We will write the value to the file in 7 bit chunks. If the 8th bit ** is clear, we're done, if it is set, another chunk follows. This will ** allow us to encode smaller values with less bytes, at the expense of ** needing 5 bytes if a 32 bit value is written to file. */ do { unsigned char C = (V & 0x7F); V >>= 7; if (V) { C |= 0x80; } Write8 (F, C); } while (V != 0); } void WriteStr (FILE* F, const char* S) /* Write a string to the file */ { unsigned Len = strlen (S); WriteVar (F, Len); WriteData (F, S, Len); } void WriteData (FILE* F, const void* Data, unsigned Size) /* Write data to the file */ { if (fwrite (Data, 1, Size, F) != Size) { Error ("Write error (disk full?)"); } } unsigned Read8 (FILE* F) /* Read an 8 bit value from the file */ { int C = getc (F); if (C == EOF) { Error ("Read error (file corrupt?)"); } return C; } unsigned Read16 (FILE* F) /* Read a 16 bit value from the file */ { unsigned Lo = Read8 (F); unsigned Hi = Read8 (F); return (Hi << 8) | Lo; } unsigned long Read32 (FILE* F) /* Read a 32 bit value from the file */ { unsigned long Lo = Read16 (F); unsigned long Hi = Read16 (F); return (Hi << 16) | Lo; } unsigned long ReadVar (FILE* F) /* Read a variable size value from the file */ { /* The value was written to the file in 7 bit chunks LSB first. If there ** are more bytes, bit 8 is set, otherwise it is clear. */ unsigned char C; unsigned long V = 0; unsigned Shift = 0; do { /* Read one byte */ C = Read8 (F); /* Encode it into the target value */ V |= ((unsigned long)(C & 0x7F)) << Shift; /* Next value */ Shift += 7; } while (C & 0x80); /* Return the value read */ return V; } char* ReadStr (FILE* F) /* Read a string from the file (the memory will be malloc'ed) */ { /* Read the length */ unsigned Len = ReadVar (F); /* Allocate memory and read the string itself */ char* S = xmalloc (Len + 1); ReadData (F, S, Len); /* Terminate the string and return it */ S [Len] = '\0'; return S; } void* ReadData (FILE* F, void* Data, unsigned Size) /* Read data from the file */ { if (fread (Data, 1, Size, F) != Size) { Error ("Read error (file corrupt?)"); } return Data; } ��������������������������������������������������������������������������������������cc65-2.18/src/ar65/fileio.h�������������������������������������������������������������������������0000664�0000000�0000000�00000007445�13473601511�0015203�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* fileio.h */ /* */ /* File I/O for the ar65 archiver */ /* */ /* */ /* */ /* (C) 1998-2000 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 FILEIO_H #define FILEIO_H #include <stdio.h> /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Write8 (FILE* F, unsigned char Val); /* Write an 8 bit value to the file */ void Write16 (FILE* F, unsigned Val); /* Write a 16 bit value to the file */ void Write32 (FILE* F, unsigned long Val); /* Write a 32 bit value to the file */ void WriteVar (FILE* F, unsigned long V); /* Write a variable sized value to the file in special encoding */ void WriteStr (FILE* F, const char* S); /* Write a string to the file */ void WriteData (FILE* F, const void* Data, unsigned Size); /* Write data to the file */ unsigned Read8 (FILE* F); /* Read an 8 bit value from the file */ unsigned Read16 (FILE* F); /* Read a 16 bit value from the file */ unsigned long Read32 (FILE* F); /* Read a 32 bit value from the file */ unsigned long ReadVar (FILE* F); /* Read a variable size value from the file */ char* ReadStr (FILE* F); /* Read a string from the file (the memory will be malloc'ed) */ void* ReadData (FILE* F, void* Data, unsigned Size); /* Read data from the file */ /* End of fileio.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ar65/global.c�������������������������������������������������������������������������0000664�0000000�0000000�00000005412�13473601511�0015157�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* global.c */ /* */ /* Global variables for the ar65 archiver */ /* */ /* */ /* */ /* (C) 1998 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include "global.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ar65/global.h�������������������������������������������������������������������������0000664�0000000�0000000�00000005471�13473601511�0015171�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* global.h */ /* */ /* Global variables for the ar65 archiver */ /* */ /* */ /* */ /* (C) 1998 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 GLOBAL_H #define GLOBAL_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* End of global.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ar65/library.c������������������������������������������������������������������������0000664�0000000�0000000�00000027662�13473601511�0015376�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* library.c */ /* */ /* Library data structures and helpers for the ar65 archiver */ /* */ /* */ /* */ /* (C) 1998-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> #include <errno.h> /* common */ #include "cmdline.h" #include "exprdefs.h" #include "libdefs.h" #include "print.h" #include "symdefs.h" #include "xmalloc.h" /* ar65 */ #include "error.h" #include "exports.h" #include "fileio.h" #include "global.h" #include "library.h" #include "objdata.h" #include "objfile.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Name of the library file */ const char* LibName = 0; static char* NewLibName = 0; /* File descriptor for the library file */ static FILE* Lib = 0; static FILE* NewLib = 0; /* The library header */ static LibHeader Header = { LIB_MAGIC, LIB_VERSION, 0, 0 }; /*****************************************************************************/ /* Writing file data structures */ /*****************************************************************************/ static void ReadHeader (void) /* Read the header of a library file */ { /* Seek to position zero */ fseek (Lib, 0, SEEK_SET); /* Read the header fields, checking magic and version */ Header.Magic = Read32 (Lib); if (Header.Magic != LIB_MAGIC) { Error ("'%s' is not a valid library file", LibName); } Header.Version = Read16 (Lib); if (Header.Version != LIB_VERSION) { Error ("Wrong data version in '%s'", LibName); } Header.Flags = Read16 (Lib); Header.IndexOffs = Read32 (Lib); } static void ReadIndexEntry (void) /* Read one entry in the index */ { /* Create a new entry and insert it into the list */ ObjData* O = NewObjData (); /* Module name/flags/MTime/Start/Size */ O->Name = ReadStr (Lib); O->Flags = Read16 (Lib); O->MTime = Read32 (Lib); O->Start = Read32 (Lib); O->Size = Read32 (Lib); } static void ReadIndex (void) /* Read the index of a library file */ { unsigned Count, I; /* Seek to the start of the index */ fseek (Lib, Header.IndexOffs, SEEK_SET); /* Read the object file count and calculate the cross ref size */ Count = ReadVar (Lib); /* Read all entries in the index */ while (Count--) { ReadIndexEntry (); } /* Read basic object file data from the actual entries */ for (I = 0; I < CollCount (&ObjPool); ++I) { /* Get the object file entry */ ObjData* O = CollAtUnchecked (&ObjPool, I); /* Read data */ ObjReadData (Lib, O); } } /*****************************************************************************/ /* Writing file data structures */ /*****************************************************************************/ static void WriteHeader (void) /* Write the header to the library file */ { /* Seek to position zero */ fseek (NewLib, 0, SEEK_SET); /* Write the header fields */ Write32 (NewLib, Header.Magic); Write16 (NewLib, Header.Version); Write16 (NewLib, Header.Flags); Write32 (NewLib, Header.IndexOffs); } static void WriteIndexEntry (const ObjData* O) /* Write one index entry */ { /* Module name/flags/MTime/start/size */ WriteStr (NewLib, O->Name); Write16 (NewLib, O->Flags & ~OBJ_HAVEDATA); Write32 (NewLib, O->MTime); Write32 (NewLib, O->Start); Write32 (NewLib, O->Size); } static void WriteIndex (void) /* Write the index of a library file */ { unsigned I; /* Sync I/O in case the last operation was a read */ fseek (NewLib, 0, SEEK_CUR); /* Remember the current offset in the header */ Header.IndexOffs = ftell (NewLib); /* Write the object file count */ WriteVar (NewLib, CollCount (&ObjPool)); /* Write the object files */ for (I = 0; I < CollCount (&ObjPool); ++I) { WriteIndexEntry (CollConstAt (&ObjPool, I)); } } /*****************************************************************************/ /* High level stuff */ /*****************************************************************************/ void LibOpen (const char* Name, int MustExist, int NeedTemp) /* Open an existing library and a temporary copy. If MustExist is true, the ** old library is expected to exist. If NeedTemp is true, a temporary library ** is created. */ { /* Remember the name */ LibName = xstrdup (Name); /* Open the existing library for reading */ Lib = fopen (Name, "rb"); if (Lib == 0) { /* File does not exist */ if (MustExist) { Error ("Library '%s' does not exist", Name); } else { /* Announce the library's creation if ar65 is verbose. */ Print (stdout, 1, "%s: Library '%s' will be created.\n", ProgName, Name); } } else { /* We have an existing file: Read the header */ ReadHeader (); /* Now read the existing index */ ReadIndex (); } if (NeedTemp) { /* Create the temporary library name */ NewLibName = xmalloc (strlen (Name) + strlen (".temp") + 1); strcpy (NewLibName, Name); strcat (NewLibName, ".temp"); /* Create the temporary library */ NewLib = fopen (NewLibName, "w+b"); if (NewLib == 0) { Error ("Cannot create temporary library file: %s", strerror (errno)); } /* Write a dummy header to the temp file */ WriteHeader (); } } unsigned long LibCopyTo (FILE* F, unsigned long Bytes) /* Copy data from F to the temp library file, return the start position in ** the temporary library file. */ { unsigned char Buf [4096]; /* Remember the position */ unsigned long Pos = ftell (NewLib); /* Copy loop */ while (Bytes) { unsigned Count = (Bytes > sizeof (Buf))? sizeof (Buf) : Bytes; ReadData (F, Buf, Count); WriteData (NewLib, Buf, Count); Bytes -= Count; } /* Return the start position */ return Pos; } void LibCopyFrom (unsigned long Pos, unsigned long Bytes, FILE* F) /* Copy data from the library file into another file */ { unsigned char Buf [4096]; /* Seek to the correct position */ fseek (Lib, Pos, SEEK_SET); /* Copy loop */ while (Bytes) { unsigned Count = (Bytes > sizeof (Buf))? sizeof (Buf) : Bytes; ReadData (Lib, Buf, Count); WriteData (F, Buf, Count); Bytes -= Count; } } static void LibCheckExports (ObjData* O) /* Insert all exports from the given object file into the global list ** checking for duplicates. */ { unsigned I; /* Let the user know what we do */ Print (stdout, 2, "Module '%s' (%u exports):\n", O->Name, CollCount (&O->Exports)); /* Insert the exports into the global table */ for (I = 0; I < CollCount (&O->Exports); ++I) { /* Get the name of the export */ const char* Name = CollConstAt (&O->Exports, I); /* Insert the name into the hash table */ Print (stdout, 2, " %s\n", Name); ExpInsert (Name, O); } } void LibClose (void) /* Write remaining data, close both files and copy the temp file to the old ** filename */ { /* Do we have a temporary library? */ if (NewLib) { unsigned I; unsigned char Buf [4096]; size_t Count; /* Walk through the object file list, inserting exports into the ** export list checking for duplicates. Copy any data that is still ** in the old library into the new one. */ for (I = 0; I < CollCount (&ObjPool); ++I) { /* Get a pointer to the object */ ObjData* O = CollAtUnchecked (&ObjPool, I); /* Check exports, make global export table */ LibCheckExports (O); /* Copy data if needed */ if ((O->Flags & OBJ_HAVEDATA) == 0) { /* Data is still in the old library */ fseek (Lib, O->Start, SEEK_SET); O->Start = ftell (NewLib); LibCopyTo (Lib, O->Size); O->Flags |= OBJ_HAVEDATA; } } /* Write the index */ WriteIndex (); /* Write the updated header */ WriteHeader (); /* Close the file */ if (Lib && fclose (Lib) != 0) { Error ("Error closing library: %s", strerror (errno)); } /* Reopen the library and truncate it */ Lib = fopen (LibName, "wb"); if (Lib == 0) { Error ("Cannot open library '%s' for writing: %s", LibName, strerror (errno)); } /* Copy the temporary library to the new one */ fseek (NewLib, 0, SEEK_SET); while ((Count = fread (Buf, 1, sizeof (Buf), NewLib)) != 0) { if (fwrite (Buf, 1, Count, Lib) != Count) { Error ("Cannot write to '%s': %s", LibName, strerror (errno)); } } } /* Close both files */ if (Lib && fclose (Lib) != 0) { Error ("Problem closing '%s': %s", LibName, strerror (errno)); } if (NewLib && fclose (NewLib) != 0) { Error ("Problem closing temporary library file: %s", strerror (errno)); } if (NewLibName && remove (NewLibName) != 0) { Error ("Problem deleting temporary library file: %s", strerror (errno)); } } ������������������������������������������������������������������������������cc65-2.18/src/ar65/library.h������������������������������������������������������������������������0000664�0000000�0000000�00000007405�13473601511�0015374�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* library.h */ /* */ /* Library data structures and helpers for the ar65 archiver */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef LIBRARY_H #define LIBRARY_H #include <stdio.h> /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Name of the library file */ extern const char* LibName; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void LibOpen (const char* Name, int MustExist, int NeedTemp); /* Open an existing library and a temporary copy. If MustExist is true, the ** old library is expected to exist. If NeedTemp is true, a temporary library ** is created. */ unsigned long LibCopyTo (FILE* F, unsigned long Bytes); /* Copy data from F to the temp library file, return the start position in ** the temporary library file. */ void LibCopyFrom (unsigned long Pos, unsigned long Bytes, FILE* F); /* Copy data from the library file into another file */ void LibClose (void); /* Write remaining data, close both files and copy the temp file to the old ** filename */ /* End of library.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ar65/list.c���������������������������������������������������������������������������0000664�0000000�0000000�00000007246�13473601511�0014701�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* list.c */ /* */ /* Module listing for the ar65 archiver */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> /* common */ #include "print.h" /* ar65 */ #include "error.h" #include "library.h" #include "list.h" #include "objdata.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void ListObjFiles (int argc, char* argv []) /* List modules in a library */ { unsigned I; const ObjData* O; /* Check the argument count */ if (argc <= 0) { Error ("No library name given"); } if (argc > 2) { Error ("Too many arguments"); } /* Open the library, read the index */ LibOpen (argv [0], 1, 0); /* List the modules */ for (I = 0; I < CollCount (&ObjPool); ++I) { /* Get the entry */ O = CollConstAt (&ObjPool, I); /* Print the size if verbose */ Print (stdout, 1, "%5lu ", O->Size); /* Print the name */ puts (O->Name); } /* Create a new library file and close the old one */ LibClose (); /* Successful end */ exit (EXIT_SUCCESS); } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ar65/list.h���������������������������������������������������������������������������0000664�0000000�0000000�00000005603�13473601511�0014701�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* list.h */ /* */ /* Module listing for the ar65 archiver */ /* */ /* */ /* */ /* (C) 1998 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 LIST_H #define LIST_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ void ListObjFiles (int argc, char* argv []); /* List modules in a library */ /* End of list.h */ #endif �����������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ar65/main.c���������������������������������������������������������������������������0000664�0000000�0000000�00000011676�13473601511�0014654�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* main.c */ /* */ /* Main program for the ar65 archiver */ /* */ /* */ /* */ /* (C) 1998-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* common */ #include "cmdline.h" #include "print.h" #include "version.h" #include "global.h" #include "add.h" #include "del.h" #include "list.h" #include "extract.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void Usage (void) /* Print usage information and exit */ { fprintf (stderr, "Usage: %s <operation ...> lib file|module ...\n" "Operations are some of:\n" "\tr\tAdd modules\n" "\td\tDelete modules\n" "\tt\tList library table\n" "\tv\tIncrease verbosity (put before other operation)\n" "\tx\tExtract modules\n" "\tV\tPrint the archiver version\n", ProgName); exit (EXIT_FAILURE); } int main (int argc, char* argv []) /* Assembler main program */ { unsigned I; /* Initialize the cmdline module */ InitCmdLine (&argc, &argv, "ar65"); /* We must have a file name */ if (ArgCount < 2) { Usage (); } /* Check the parameters */ I = 1; while (I < ArgCount) { /* Get the argument */ const char* Arg = ArgVec [I]; switch (Arg [0]) { case 'r': /* POSIX.2 */ case 'a': /* staying compatible */ AddObjFiles (ArgCount - I - 1, &ArgVec[I+1]); break; case 'd': DelObjFiles (ArgCount - I - 1, &ArgVec [I+1]); break; case 't': /* POSIX.2 */ case 'l': /* staying compatible */ if (Arg [1] == 'v') { ++Verbosity; } ListObjFiles (ArgCount - I - 1, &ArgVec [I+1]); break; case 'v': ++Verbosity; break; case 'x': ExtractObjFiles (ArgCount - I - 1, &ArgVec [I+1]); break; case 'V': fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ()); break; default: fprintf (stderr, "Unknown option: %s\n", Arg); Usage (); } /* Next argument */ ++I; } /* Return an apropriate exit code */ return EXIT_SUCCESS; } ������������������������������������������������������������������cc65-2.18/src/ar65/objdata.c������������������������������������������������������������������������0000664�0000000�0000000�00000012531�13473601511�0015323�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* objdata.c */ /* */ /* Handling object file data for the ar65 archiver */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* common */ #include "check.h" #include "xmalloc.h" /* ar65 */ #include "error.h" #include "library.h" #include "objdata.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Collection with object files */ Collection ObjPool = STATIC_COLLECTION_INITIALIZER; /*****************************************************************************/ /* Code */ /*****************************************************************************/ ObjData* NewObjData (void) /* Allocate a new structure on the heap, insert it into the list, return it */ { /* Allocate memory */ ObjData* O = xmalloc (sizeof (ObjData)); /* Initialize the data */ O->Name = 0; O->Flags = 0; O->MTime = 0; O->Start = 0; O->Size = 0; O->Strings = EmptyCollection; O->Exports = EmptyCollection; /* Add it to the list */ CollAppend (&ObjPool, O); /* Return the new entry */ return O; } void FreeObjData (ObjData* O) /* Free a complete struct */ { unsigned I; xfree (O->Name); for (I = 0; I < CollCount (&O->Strings); ++I) { xfree (CollAt (&O->Strings, I)); } DoneCollection (&O->Strings); DoneCollection (&O->Exports); xfree (O); } void ClearObjData (ObjData* O) /* Remove any data stored in O */ { unsigned I; xfree (O->Name); O->Name = 0; for (I = 0; I < CollCount (&O->Strings); ++I) { xfree (CollAt (&O->Strings, I)); } CollDeleteAll (&O->Strings); CollDeleteAll (&O->Exports); } ObjData* FindObjData (const char* Module) /* Search for the module with the given name and return it. Return NULL if the ** module is not in the list. */ { unsigned I; /* Hmm. Maybe we should hash the module names? */ for (I = 0; I < CollCount (&ObjPool); ++I) { /* Get this object file */ ObjData* O = CollAtUnchecked (&ObjPool, I); /* Did we find it? */ if (strcmp (O->Name, Module) == 0) { return O; } } return 0; } void DelObjData (const char* Module) /* Delete the object module from the list */ { unsigned I; for (I = 0; I < CollCount (&ObjPool); ++I) { /* Get this object file */ ObjData* O = CollAtUnchecked (&ObjPool, I); /* Did we find it? */ if (strcmp (O->Name, Module) == 0) { /* Free the entry */ CollDelete (&ObjPool, I); FreeObjData (O); /* Done */ return; } } /* Not found! */ Warning ("Module '%s' not found in library '%s'", Module, LibName); } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ar65/objdata.h������������������������������������������������������������������������0000664�0000000�0000000�00000010702�13473601511�0015326�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* objdata.h */ /* */ /* Handling object file data for the ar65 archiver */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef OBJDATA_H #define OBJDATA_H /* common */ #include "coll.h" #include "objdefs.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Values for the Flags field */ #define OBJ_HAVEDATA 0x0001 /* The object data is in the tmp file */ /* Internal structure holding object file data */ typedef struct ObjData ObjData; struct ObjData { char* Name; /* Module name */ /* Index entry */ unsigned Flags; unsigned long MTime; /* Modifiation time of object file */ unsigned long Start; /* Start offset of data in library */ unsigned long Size; /* Size of data in library */ /* Object file header */ ObjHeader Header; /* Basic data needed for simple checks */ Collection Strings; /* Strings from the object file */ Collection Exports; /* Exports list from object file */ }; /* Collection with all object files */ extern Collection ObjPool; /*****************************************************************************/ /* Code */ /*****************************************************************************/ ObjData* NewObjData (void); /* Allocate a new structure on the heap, insert it into the list, return it */ void FreeObjData (ObjData* O); /* Free a complete struct */ void ClearObjData (ObjData* O); /* Remove any data stored in O */ ObjData* FindObjData (const char* Module); /* Search for the module with the given name and return it. Return NULL if the ** module is not in the list. */ void DelObjData (const char* Module); /* Delete the object module from the list */ /* End of objdata.h */ #endif ��������������������������������������������������������������cc65-2.18/src/ar65/objfile.c������������������������������������������������������������������������0000664�0000000�0000000�00000024672�13473601511�0015342�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* objfile.c */ /* */ /* Object file handling for the ar65 archiver */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> #include <errno.h> /* common */ #include "cddefs.h" #include "exprdefs.h" #include "filestat.h" #include "filetime.h" #include "fname.h" #include "symdefs.h" #include "xmalloc.h" /* ar65 */ #include "error.h" #include "objdata.h" #include "fileio.h" #include "library.h" #include "objfile.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ static const char* GetModule (const char* Name) /* Get a module name from the file name */ { /* Make a module name from the file name */ const char* Module = FindName (Name); /* Must not end with a path separator */ if (*Module == 0) { Error ("Cannot make module name from '%s'", Name); } /* Done */ return Module; } static void ObjReadHeader (FILE* Obj, ObjHeader* H, const char* Name) /* Read the header of the object file checking the signature */ { H->Magic = Read32 (Obj); if (H->Magic != OBJ_MAGIC) { Error ("'%s' is not an object file", Name); } H->Version = Read16 (Obj); if (H->Version != OBJ_VERSION) { Error ("Object file '%s' has wrong version", Name); } H->Flags = Read16 (Obj); H->OptionOffs = Read32 (Obj); H->OptionSize = Read32 (Obj); H->FileOffs = Read32 (Obj); H->FileSize = Read32 (Obj); H->SegOffs = Read32 (Obj); H->SegSize = Read32 (Obj); H->ImportOffs = Read32 (Obj); H->ImportSize = Read32 (Obj); H->ExportOffs = Read32 (Obj); H->ExportSize = Read32 (Obj); H->DbgSymOffs = Read32 (Obj); H->DbgSymSize = Read32 (Obj); H->LineInfoOffs = Read32 (Obj); H->LineInfoSize = Read32 (Obj); H->StrPoolOffs = Read32 (Obj); H->StrPoolSize = Read32 (Obj); H->AssertOffs = Read32 (Obj); H->AssertSize = Read32 (Obj); H->ScopeOffs = Read32 (Obj); H->ScopeSize = Read32 (Obj); H->SpanOffs = Read32 (Obj); H->SpanSize = Read32 (Obj); } static void SkipExpr (FILE* F) /* Skip an expression in F */ { /* Get the operation and skip it */ unsigned char Op = Read8 (F); /* Handle then different expression nodes */ switch (Op) { case EXPR_NULL: break; case EXPR_LITERAL: /* 32 bit literal value */ (void) Read32 (F); break; case EXPR_SYMBOL: /* Variable seized symbol index */ (void) ReadVar (F); break; case EXPR_SECTION: /* 8 bit segment number */ (void) Read8 (F); break; default: /* What's left are unary and binary nodes */ SkipExpr (F); /* Left */ SkipExpr (F); /* right */ break; } } static void SkipLineInfoList (FILE* F) /* Skip a list of line infos in F */ { /* Number of indices preceeds the list */ unsigned long Count = ReadVar (F); /* Skip indices */ while (Count--) { (void) ReadVar (F); } } void ObjReadData (FILE* F, ObjData* O) /* Read object file data from the given file. The function expects the Name ** and Start fields to be valid. Header and basic data are read. */ { unsigned long Count; /* Seek to the start of the object file data */ fseek (F, O->Start, SEEK_SET); /* Read the object file header */ ObjReadHeader (F, &O->Header, O->Name); /* Read the string pool */ fseek (F, O->Start + O->Header.StrPoolOffs, SEEK_SET); Count = ReadVar (F); CollGrow (&O->Strings, Count); while (Count--) { CollAppend (&O->Strings, ReadStr (F)); } /* Read the exports */ fseek (F, O->Start + O->Header.ExportOffs, SEEK_SET); Count = ReadVar (F); CollGrow (&O->Exports, Count); while (Count--) { unsigned char ConDes[CD_TYPE_COUNT]; /* Skip data until we get to the name */ unsigned Type = ReadVar (F); (void) Read8 (F); /* AddrSize */ ReadData (F, ConDes, SYM_GET_CONDES_COUNT (Type)); /* Now this is what we actually need: The name of the export */ CollAppend (&O->Exports, CollAt (&O->Strings, ReadVar (F))); /* Skip the export value */ if (SYM_IS_EXPR (Type)) { /* Expression tree */ SkipExpr (F); } else { /* Literal value */ (void) Read32 (F); } /* Skip the size if necessary */ if (SYM_HAS_SIZE (Type)) { (void) ReadVar (F); } /* Line info indices */ SkipLineInfoList (F); SkipLineInfoList (F); } } void ObjAdd (const char* Name) /* Add an object file to the library */ { struct stat StatBuf; const char* Module; ObjHeader H; ObjData* O; /* Open the object file */ FILE* Obj = fopen (Name, "rb"); if (Obj == 0) { Error ("Could not open '%s': %s", Name, strerror (errno)); } /* Get the modification time of the object file. There's a race condition ** here, since we cannot use fileno() (non-standard identifier in standard ** header file), and therefore not fstat. When using stat with the ** file name, there's a risk that the file was deleted and recreated ** while it was open. Since mtime and size are only used to check ** if a file has changed in the debugger, we will ignore this problem ** here. */ if (FileStat (Name, &StatBuf) != 0) { Error ("Cannot stat object file '%s': %s", Name, strerror (errno)); } /* Read and check the header */ ObjReadHeader (Obj, &H, Name); /* Make a module name from the file name */ Module = GetModule (Name); /* Check if we already have a module with this name */ O = FindObjData (Module); if (O == 0) { /* Not found, create a new entry */ O = NewObjData (); } else { /* Found - check the file modification times of the internal copy ** and the external one. */ if (difftime ((time_t)O->MTime, StatBuf.st_mtime) > 0.0) { Warning ("Replacing module '%s' by older version in library '%s'", O->Name, LibName); } /* Free data */ ClearObjData (O); } /* Initialize the object module data structure */ O->Name = xstrdup (Module); O->Flags = OBJ_HAVEDATA; O->MTime = (unsigned long) StatBuf.st_mtime; O->Start = 0; /* Determine the file size. Note: Race condition here */ fseek (Obj, 0, SEEK_END); O->Size = ftell (Obj); /* Read the basic data from the object file */ ObjReadData (Obj, O); /* Copy the complete object data to the library file and update the ** starting offset */ fseek (Obj, 0, SEEK_SET); O->Start = LibCopyTo (Obj, O->Size); /* Done, close the file (we read it only, so no error check) */ fclose (Obj); } void ObjExtract (const char* Name) /* Extract a module from the library */ { FILE* Obj; /* Make a module name from the file name */ const char* Module = GetModule (Name); /* Try to find the module in the library */ const ObjData* O = FindObjData (Module); /* Bail out if the module does not exist */ if (O == 0) { Error ("Module '%s' not found in library '%s'", Module, LibName); } /* Open the output file */ Obj = fopen (Name, "w+b"); if (Obj == 0) { Error ("Cannot open target file '%s': %s", Name, strerror (errno)); } /* Copy the complete object file data from the library to the new object ** file. */ LibCopyFrom (O->Start, O->Size, Obj); /* Close the file */ if (fclose (Obj) != 0) { Error ("Problem closing object file '%s': %s", Name, strerror (errno)); } /* Set access and modification time */ if (SetFileTimes (Name, O->MTime) != 0) { Error ("Cannot set mod time on '%s': %s", Name, strerror (errno)); } } ����������������������������������������������������������������������cc65-2.18/src/ar65/objfile.h������������������������������������������������������������������������0000664�0000000�0000000�00000006660�13473601511�0015344�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* objfile.h */ /* */ /* Object file handling for the ar65 archiver */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef OBJFILE_H #define OBJFILE_H #include <stdio.h> /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ struct ObjData; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void ObjReadData (FILE* F, struct ObjData* O); /* Read object file data from the given file. The function expects the Name ** and Start fields to be valid. Header and basic data are read. */ void ObjAdd (const char* Name); /* Add an object file to the library */ void ObjExtract (const char* Name); /* Extract a module from the library */ /* End of objfile.h */ #endif ��������������������������������������������������������������������������������cc65-2.18/src/ca65.vcxproj��������������������������������������������������������������������������0000664�0000000�0000000�00000016616�13473601511�0015161�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> <ProjectConfiguration Include="Release|Win32"> <Configuration>Release</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> </ItemGroup> <PropertyGroup Label="Globals"> <ProjectGuid>{D28CB737-E6CA-49C4-8CE9-FF05F86DD4EC}</ProjectGuid> <Keyword>Win32Proj</Keyword> <RootNamespace>ca65</RootNamespace> <WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <UseDebugLibraries>true</UseDebugLibraries> <PlatformToolset>v141</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <UseDebugLibraries>false</UseDebugLibraries> <WholeProgramOptimization>true</WholeProgramOptimization> <PlatformToolset>v141</PlatformToolset> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <PropertyGroup Label="UserMacros" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <IntDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</IntDir> <OutDir>$(SolutionDir)..\bin\</OutDir> <LinkIncremental>true</LinkIncremental> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <IntDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</IntDir> <OutDir>$(SolutionDir)..\bin\</OutDir> </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ClCompile> <PrecompiledHeader> </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> <TreatWarningAsError>true</TreatWarningAsError> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> </ClCompile> <Link> <SubSystem>Console</SubSystem> <GenerateDebugInformation>true</GenerateDebugInformation> <AdditionalDependencies>$(IntDir)..\..\common\$(Configuration)\common.lib</AdditionalDependencies> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ClCompile> <WarningLevel>Level3</WarningLevel> <PrecompiledHeader> </PrecompiledHeader> <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> <TreatWarningAsError>true</TreatWarningAsError> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> </ClCompile> <Link> <SubSystem>Console</SubSystem> <GenerateDebugInformation>false</GenerateDebugInformation> <AdditionalDependencies>$(IntDir)..\..\common\$(Configuration)\common.lib</AdditionalDependencies> </Link> </ItemDefinitionGroup> <ItemGroup> <ClInclude Include="ca65\anonname.h" /> <ClInclude Include="ca65\asserts.h" /> <ClInclude Include="ca65\condasm.h" /> <ClInclude Include="ca65\dbginfo.h" /> <ClInclude Include="ca65\ea.h" /> <ClInclude Include="ca65\ea65.h" /> <ClInclude Include="ca65\easw16.h" /> <ClInclude Include="ca65\enum.h" /> <ClInclude Include="ca65\error.h" /> <ClInclude Include="ca65\expr.h" /> <ClInclude Include="ca65\feature.h" /> <ClInclude Include="ca65\filetab.h" /> <ClInclude Include="ca65\fragment.h" /> <ClInclude Include="ca65\global.h" /> <ClInclude Include="ca65\incpath.h" /> <ClInclude Include="ca65\instr.h" /> <ClInclude Include="ca65\istack.h" /> <ClInclude Include="ca65\lineinfo.h" /> <ClInclude Include="ca65\listing.h" /> <ClInclude Include="ca65\macro.h" /> <ClInclude Include="ca65\nexttok.h" /> <ClInclude Include="ca65\objcode.h" /> <ClInclude Include="ca65\objfile.h" /> <ClInclude Include="ca65\options.h" /> <ClInclude Include="ca65\pseudo.h" /> <ClInclude Include="ca65\repeat.h" /> <ClInclude Include="ca65\scanner.h" /> <ClInclude Include="ca65\segdef.h" /> <ClInclude Include="ca65\segment.h" /> <ClInclude Include="ca65\sizeof.h" /> <ClInclude Include="ca65\span.h" /> <ClInclude Include="ca65\spool.h" /> <ClInclude Include="ca65\struct.h" /> <ClInclude Include="ca65\studyexpr.h" /> <ClInclude Include="ca65\symbol.h" /> <ClInclude Include="ca65\symentry.h" /> <ClInclude Include="ca65\symtab.h" /> <ClInclude Include="ca65\token.h" /> <ClInclude Include="ca65\toklist.h" /> <ClInclude Include="ca65\ulabel.h" /> </ItemGroup> <ItemGroup> <ClCompile Include="ca65\anonname.c" /> <ClCompile Include="ca65\asserts.c" /> <ClCompile Include="ca65\condasm.c" /> <ClCompile Include="ca65\dbginfo.c" /> <ClCompile Include="ca65\ea65.c" /> <ClCompile Include="ca65\easw16.c" /> <ClCompile Include="ca65\enum.c" /> <ClCompile Include="ca65\error.c" /> <ClCompile Include="ca65\expr.c" /> <ClCompile Include="ca65\feature.c" /> <ClCompile Include="ca65\filetab.c" /> <ClCompile Include="ca65\fragment.c" /> <ClCompile Include="ca65\global.c" /> <ClCompile Include="ca65\incpath.c" /> <ClCompile Include="ca65\instr.c" /> <ClCompile Include="ca65\istack.c" /> <ClCompile Include="ca65\lineinfo.c" /> <ClCompile Include="ca65\listing.c" /> <ClCompile Include="ca65\macro.c" /> <ClCompile Include="ca65\main.c" /> <ClCompile Include="ca65\nexttok.c" /> <ClCompile Include="ca65\objcode.c" /> <ClCompile Include="ca65\objfile.c" /> <ClCompile Include="ca65\options.c" /> <ClCompile Include="ca65\pseudo.c" /> <ClCompile Include="ca65\repeat.c" /> <ClCompile Include="ca65\scanner.c" /> <ClCompile Include="ca65\segdef.c" /> <ClCompile Include="ca65\segment.c" /> <ClCompile Include="ca65\sizeof.c" /> <ClCompile Include="ca65\span.c" /> <ClCompile Include="ca65\spool.c" /> <ClCompile Include="ca65\struct.c" /> <ClCompile Include="ca65\studyexpr.c" /> <ClCompile Include="ca65\symbol.c" /> <ClCompile Include="ca65\symentry.c" /> <ClCompile Include="ca65\symtab.c" /> <ClCompile Include="ca65\token.c" /> <ClCompile Include="ca65\toklist.c" /> <ClCompile Include="ca65\ulabel.c" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> </Project>������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/���������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0013532�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/anonname.c�����������������������������������������������������������������������0000664�0000000�0000000�00000007402�13473601511�0015475�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* anonname.c */ /* */ /* Create names for anonymous scopes/variables/types */ /* */ /* */ /* */ /* (C) 2000-2008 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> /* ca65 */ #include "anonname.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ static const char AnonTag[] = "$anon"; /*****************************************************************************/ /* Code */ /*****************************************************************************/ StrBuf* AnonName (StrBuf* Buf, const char* Spec) /* Get a name for an anonymous scope, variable or type. Size is the size of ** the buffer passed to the function, Spec will be used as part of the ** identifier if given. A pointer to the buffer is returned. */ { static unsigned ACount = 0; SB_Printf (Buf, "%s-%s-%04X", AnonTag, Spec, ++ACount); return Buf; } int IsAnonName (const StrBuf* Name) /* Check if the given symbol name is that of an anonymous symbol */ { if (SB_GetLen (Name) < sizeof (AnonTag) - 1) { /* Too short */ return 0; } return (strncmp (SB_GetConstBuf (Name), AnonTag, sizeof (AnonTag) - 1) == 0); } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/anonname.h�����������������������������������������������������������������������0000664�0000000�0000000�00000006333�13473601511�0015504�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* anonname.h */ /* */ /* Create names for anonymous scopes/variables/types */ /* */ /* */ /* */ /* (C) 2000-2008 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef ANONNAME_H #define ANONNAME_H /* common */ #include "strbuf.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ StrBuf* AnonName (StrBuf* Buf, const char* Spec); /* Get a name for an anonymous scope, variable or type. Size is the size of ** the buffer passed to the function, Spec will be used as part of the ** identifier if given. A pointer to the buffer is returned. */ int IsAnonName (const StrBuf* Name); /* Check if the given symbol name is that of an anonymous symbol */ /* End of anonname.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/asserts.c������������������������������������������������������������������������0000664�0000000�0000000�00000014154�13473601511�0015367�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* asserts.c */ /* */ /* Linker assertions for the ca65 crossassembler */ /* */ /* */ /* */ /* (C) 2003-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "coll.h" #include "xmalloc.h" /* ca65 */ #include "asserts.h" #include "error.h" #include "expr.h" #include "lineinfo.h" #include "objfile.h" #include "spool.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* An assertion entry */ typedef struct Assertion Assertion; struct Assertion { ExprNode* Expr; /* Expression to evaluate */ AssertAction Action; /* Action to take */ unsigned Msg; /* Message to print (if any) */ Collection LI; /* Line infos for the assertion */ }; /* Collection with all assertions for a module */ static Collection Assertions = STATIC_COLLECTION_INITIALIZER; /*****************************************************************************/ /* Code */ /*****************************************************************************/ static Assertion* NewAssertion (ExprNode* Expr, AssertAction Action, unsigned Msg) /* Create a new Assertion struct and return it */ { /* Allocate memory */ Assertion* A = xmalloc (sizeof (Assertion)); /* Initialize the fields */ A->Expr = Expr; A->Action = Action; A->Msg = Msg; A->LI = EmptyCollection; GetFullLineInfo (&A->LI); /* Return the new struct */ return A; } void AddAssertion (ExprNode* Expr, AssertAction Action, unsigned Msg) /* Add an assertion to the assertion table */ { /* Add an assertion object to the table */ CollAppend (&Assertions, NewAssertion (Expr, Action, Msg)); } void CheckAssertions (void) /* Check all assertions and evaluate the ones we can evaluate here. */ { unsigned I; /* Get the number of assertions */ unsigned Count = CollCount (&Assertions); /* Check the assertions */ for (I = 0; I < Count; ++I) { long Val; /* Get the next assertion */ Assertion* A = CollAtUnchecked (&Assertions, I); /* Ignore it, if it should only be evaluated by the linker */ if (!AssertAtAsmTime (A->Action)) { continue; } /* Can we evaluate the expression? */ if (IsConstExpr (A->Expr, &Val) && Val == 0) { /* Apply the action */ const char* Msg = GetString (A->Msg); switch (A->Action) { case ASSERT_ACT_WARN: LIWarning (&A->LI, 0, "%s", Msg); break; case ASSERT_ACT_ERROR: LIError (&A->LI, "%s", Msg); break; default: Internal ("Illegal assert action specifier"); break; } } } } void WriteAssertions (void) /* Write the assertion table to the object file */ { unsigned I; /* Get the number of assertions */ unsigned Count = CollCount (&Assertions); /* Tell the object file module that we're about to start the assertions */ ObjStartAssertions (); /* Write the string count to the list */ ObjWriteVar (Count); /* Write the assertions */ for (I = 0; I < Count; ++I) { /* Get the next assertion */ Assertion* A = CollAtUnchecked (&Assertions, I); /* Write it to the file */ WriteExpr (A->Expr); ObjWriteVar ((unsigned) A->Action); ObjWriteVar (A->Msg); WriteLineInfo (&A->LI); } /* Done writing the assertions */ ObjEndAssertions (); } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/asserts.h������������������������������������������������������������������������0000664�0000000�0000000�00000006656�13473601511�0015404�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* asserts.h */ /* */ /* Linker assertions for the ca65 crossassembler */ /* */ /* */ /* */ /* (C) 2003-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef ASSERTS_H #define ASSERTS_H /* common */ #include "assertion.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Forwards */ struct ExprNode; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void AddAssertion (struct ExprNode* Expr, AssertAction Action, unsigned Msg); /* Add an assertion to the assertion table */ void CheckAssertions (void); /* Check all assertions and evaluate the ones we can evaluate here. */ void WriteAssertions (void); /* Write the assertion table to the object file */ /* End of asserts.h */ #endif ����������������������������������������������������������������������������������cc65-2.18/src/ca65/condasm.c������������������������������������������������������������������������0000664�0000000�0000000�00000037364�13473601511�0015337�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* condasm.c */ /* */ /* Conditional assembly support for ca65 */ /* */ /* */ /* */ /* (C) 2000-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* ca65 */ #include "error.h" #include "expr.h" #include "instr.h" #include "lineinfo.h" #include "nexttok.h" #include "symbol.h" #include "symtab.h" #include "condasm.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Maximum count of nested .ifs */ #define MAX_IFS 256 /* Set of bitmapped flags for the if descriptor */ enum { ifNone = 0x0000, /* No flag */ ifCond = 0x0001, /* IF condition was true */ ifParentCond= 0x0002, /* IF condition of parent */ ifElse = 0x0004, /* We had a .ELSE branch */ ifNeedTerm = 0x0008, /* Need .ENDIF termination */ }; /* The overall .IF condition */ int IfCond = 1; /*****************************************************************************/ /* struct IfDesc */ /*****************************************************************************/ /* One .IF descriptor */ typedef struct IfDesc IfDesc; struct IfDesc { unsigned Flags; /* Bitmapped flags, see above */ Collection LineInfos; /* File position of the .IF */ const char* Name; /* Name of the directive */ }; /* The .IF stack */ static IfDesc IfStack [MAX_IFS]; static unsigned IfCount = 0; static IfDesc* GetCurrentIf (void) /* Return the current .IF descriptor */ { if (IfCount == 0) { return 0; } else { return &IfStack[IfCount-1]; } } static int GetOverallIfCond (void) /* Get the overall condition based on all conditions on the stack. */ { /* Since the last entry contains the overall condition of the parent, we ** must check it in combination of the current condition. If there is no ** last entry, the overall condition is true. */ return (IfCount == 0) || ((IfStack[IfCount-1].Flags & (ifCond | ifParentCond)) == (ifCond | ifParentCond)); } static void CalcOverallIfCond (void) /* Calculate the overall condition, based on all conditions on the stack. */ { IfCond = GetOverallIfCond (); } static void SetIfCond (IfDesc* ID, int C) /* Set the .IF condition */ { if (C) { ID->Flags |= ifCond; } else { ID->Flags &= ~ifCond; } } static void ElseClause (IfDesc* ID, const char* Directive) /* Enter an .ELSE clause */ { /* Check if we have an open .IF - otherwise .ELSE is not allowed */ if (ID == 0) { Error ("Unexpected %s", Directive); return; } /* Check for a duplicate else, then remember that we had one */ if (ID->Flags & ifElse) { /* We already had a .ELSE ! */ Error ("Duplicate .ELSE"); } ID->Flags |= ifElse; /* Condition is inverted now */ ID->Flags ^= ifCond; } static IfDesc* AllocIf (const char* Directive, int NeedTerm) /* Alloc a new element from the .IF stack */ { IfDesc* ID; /* Check for stack overflow */ if (IfCount >= MAX_IFS) { Fatal ("Too many nested .IFs"); } /* Get the next element */ ID = &IfStack[IfCount]; /* Initialize elements */ ID->Flags = NeedTerm? ifNeedTerm : ifNone; if (GetOverallIfCond ()) { /* The parents .IF condition is true */ ID->Flags |= ifParentCond; } ID->LineInfos = EmptyCollection; GetFullLineInfo (&ID->LineInfos); ID->Name = Directive; /* One more slot allocated */ ++IfCount; /* Return the result */ return ID; } static void FreeIf (void) /* Free all .IF descriptors until we reach one with the NeedTerm bit set */ { int Done; do { IfDesc* ID = GetCurrentIf(); if (ID == 0) { Error (" Unexpected .ENDIF"); Done = 1; } else { Done = (ID->Flags & ifNeedTerm) != 0; ReleaseFullLineInfo (&ID->LineInfos); DoneCollection (&ID->LineInfos); --IfCount; } } while (!Done); } /*****************************************************************************/ /* Code */ /*****************************************************************************/ void DoConditionals (void) /* Catch all for conditional directives */ { IfDesc* D; do { switch (CurTok.Tok) { case TOK_ELSE: D = GetCurrentIf (); /* Allow an .ELSE */ ElseClause (D, ".ELSE"); /* Remember the data for the .ELSE */ if (D) { ReleaseFullLineInfo (&D->LineInfos); GetFullLineInfo (&D->LineInfos); D->Name = ".ELSE"; } /* Calculate the new overall condition */ CalcOverallIfCond (); /* Skip .ELSE */ NextTok (); ExpectSep (); break; case TOK_ELSEIF: D = GetCurrentIf (); /* Handle as if there was an .ELSE first */ ElseClause (D, ".ELSEIF"); /* Calculate the new overall if condition */ CalcOverallIfCond (); /* Allocate and prepare a new descriptor */ D = AllocIf (".ELSEIF", 0); NextTok (); /* Ignore the new condition if we are inside a false .ELSE ** branch. This way we won't get any errors about undefined ** symbols or similar... */ if (IfCond) { SetIfCond (D, ConstExpression ()); ExpectSep (); } /* Get the new overall condition */ CalcOverallIfCond (); break; case TOK_ENDIF: /* We're done with this .IF.. - remove the descriptor(s) */ FreeIf (); /* Be sure not to read the next token until the .IF stack ** has been cleanup up, since we may be at end of file. */ NextTok (); ExpectSep (); /* Get the new overall condition */ CalcOverallIfCond (); break; case TOK_IF: D = AllocIf (".IF", 1); NextTok (); if (IfCond) { SetIfCond (D, ConstExpression ()); ExpectSep (); } CalcOverallIfCond (); break; case TOK_IFBLANK: D = AllocIf (".IFBLANK", 1); NextTok (); if (IfCond) { if (TokIsSep (CurTok.Tok)) { SetIfCond (D, 1); } else { SetIfCond (D, 0); SkipUntilSep (); } } CalcOverallIfCond (); break; case TOK_IFCONST: D = AllocIf (".IFCONST", 1); NextTok (); if (IfCond) { ExprNode* Expr = Expression(); SetIfCond (D, IsConstExpr (Expr, 0)); FreeExpr (Expr); ExpectSep (); } CalcOverallIfCond (); break; case TOK_IFDEF: D = AllocIf (".IFDEF", 1); NextTok (); if (IfCond) { SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING); SetIfCond (D, Sym != 0 && SymIsDef (Sym)); } CalcOverallIfCond (); break; case TOK_IFNBLANK: D = AllocIf (".IFNBLANK", 1); NextTok (); if (IfCond) { if (TokIsSep (CurTok.Tok)) { SetIfCond (D, 0); } else { SetIfCond (D, 1); SkipUntilSep (); } } CalcOverallIfCond (); break; case TOK_IFNCONST: D = AllocIf (".IFNCONST", 1); NextTok (); if (IfCond) { ExprNode* Expr = Expression(); SetIfCond (D, !IsConstExpr (Expr, 0)); FreeExpr (Expr); ExpectSep (); } CalcOverallIfCond (); break; case TOK_IFNDEF: D = AllocIf (".IFNDEF", 1); NextTok (); if (IfCond) { SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING); SetIfCond (D, Sym == 0 || !SymIsDef (Sym)); ExpectSep (); } CalcOverallIfCond (); break; case TOK_IFNREF: D = AllocIf (".IFNREF", 1); NextTok (); if (IfCond) { SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING); SetIfCond (D, Sym == 0 || !SymIsRef (Sym)); ExpectSep (); } CalcOverallIfCond (); break; case TOK_IFP02: D = AllocIf (".IFP02", 1); NextTok (); if (IfCond) { SetIfCond (D, GetCPU() == CPU_6502); } ExpectSep (); CalcOverallIfCond (); break; case TOK_IFP4510: D = AllocIf (".IFP4510", 1); NextTok (); if (IfCond) { SetIfCond (D, GetCPU() == CPU_4510); } ExpectSep (); CalcOverallIfCond (); break; case TOK_IFP816: D = AllocIf (".IFP816", 1); NextTok (); if (IfCond) { SetIfCond (D, GetCPU() == CPU_65816); } ExpectSep (); CalcOverallIfCond (); break; case TOK_IFPC02: D = AllocIf (".IFPC02", 1); NextTok (); if (IfCond) { SetIfCond (D, GetCPU() == CPU_65C02); } ExpectSep (); CalcOverallIfCond (); break; case TOK_IFPSC02: D = AllocIf (".IFPSC02", 1); NextTok (); if (IfCond) { SetIfCond (D, GetCPU() == CPU_65SC02); } ExpectSep (); CalcOverallIfCond (); break; case TOK_IFREF: D = AllocIf (".IFREF", 1); NextTok (); if (IfCond) { SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING); SetIfCond (D, Sym != 0 && SymIsRef (Sym)); ExpectSep (); } CalcOverallIfCond (); break; default: /* Skip tokens */ NextTok (); } } while (IfCond == 0 && CurTok.Tok != TOK_EOF); } int CheckConditionals (void) /* Check if the current token is one that starts a conditional directive, and ** call DoConditionals if so. Return true if a conditional directive was found, ** return false otherwise. */ { switch (CurTok.Tok) { case TOK_ELSE: case TOK_ELSEIF: case TOK_ENDIF: case TOK_IF: case TOK_IFBLANK: case TOK_IFCONST: case TOK_IFDEF: case TOK_IFNBLANK: case TOK_IFNCONST: case TOK_IFNDEF: case TOK_IFNREF: case TOK_IFP02: case TOK_IFP4510: case TOK_IFP816: case TOK_IFPC02: case TOK_IFPSC02: case TOK_IFREF: DoConditionals (); return 1; default: return 0; } } void CheckOpenIfs (void) /* Called from the scanner before closing an input file. Will check for any ** open .ifs in this file. */ { const LineInfo* LI; while (1) { /* Get the current file number and check if the topmost entry on the ** .IF stack was inserted with this file number */ IfDesc* D = GetCurrentIf (); if (D == 0) { /* There are no open .IFs */ break; } LI = CollConstAt (&D->LineInfos, 0); if (GetSourcePos (LI)->Name != CurTok.Pos.Name) { /* The .if is from another file, bail out */ break; } /* Start of .if is in the file we're about to leave */ LIError (&D->LineInfos, "Conditional assembly branch was never closed"); FreeIf (); } /* Calculate the new overall .IF condition */ CalcOverallIfCond (); } unsigned GetIfStack (void) /* Get the current .IF stack pointer */ { return IfCount; } void CleanupIfStack (unsigned SP) /* Cleanup the .IF stack, remove anything above the given stack pointer */ { while (IfCount > SP) { FreeIf (); } /* Calculate the new overall .IF condition */ CalcOverallIfCond (); } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/condasm.h������������������������������������������������������������������������0000664�0000000�0000000�00000007303�13473601511�0015332�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* condasm.h */ /* */ /* Conditional assembly support for ca65 */ /* */ /* */ /* */ /* (C) 2000-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef CONDASM_H #define CONDASM_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* The overall .IF condition */ extern int IfCond; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void DoConditionals (void); /* Catch all for conditional directives */ int CheckConditionals (void); /* Check if the current token is one that starts a conditional directive, and ** call DoConditionals if so. Return true if a conditional directive was found, ** return false otherwise. */ void CheckOpenIfs (void); /* Called from the scanner before closing an input file. Will check for any ** open .ifs in this file. */ unsigned GetIfStack (void); /* Get the current .IF stack pointer */ void CleanupIfStack (unsigned SP); /* Cleanup the .IF stack, remove anything above the given stack pointer */ /* End of condasm.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/dbginfo.c������������������������������������������������������������������������0000664�0000000�0000000�00000036253�13473601511�0015317�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* dbginfo.c */ /* */ /* Handle the .dbg commands */ /* */ /* */ /* */ /* (C) 2000-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* common */ #include "chartype.h" #include "coll.h" #include "filepos.h" #include "hlldbgsym.h" #include "scopedefs.h" #include "strbuf.h" /* ca65 */ #include "dbginfo.h" #include "error.h" #include "expr.h" #include "filetab.h" #include "global.h" #include "lineinfo.h" #include "objfile.h" #include "nexttok.h" #include "symentry.h" #include "symtab.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Structure used for a high level language function or symbol */ typedef struct HLLDbgSym HLLDbgSym; struct HLLDbgSym { unsigned Flags; /* See above */ unsigned Name; /* String id of name */ unsigned AsmName; /* String id of asm symbol name */ SymEntry* Sym; /* The assembler symbol */ int Offs; /* Offset if any */ unsigned Type; /* String id of type */ SymTable* Scope; /* Parent scope */ unsigned FuncId; /* Id of hll function if any */ FilePos Pos; /* Position of statement */ }; /* The current line info */ static LineInfo* CurLineInfo = 0; /* List of high level language debug symbols */ static Collection HLLDbgSyms = STATIC_COLLECTION_INITIALIZER; /*****************************************************************************/ /* Code */ /*****************************************************************************/ static HLLDbgSym* NewHLLDbgSym (unsigned Flags, unsigned Name, unsigned Type) /* Allocate and return a new HLLDbgSym structure */ { /* Allocate memory */ HLLDbgSym* S = xmalloc (sizeof (*S)); /* Initialize the fields as necessary */ S->Flags = Flags; S->Name = Name; S->AsmName = EMPTY_STRING_ID; S->Sym = 0; S->Offs = 0; S->Type = Type; S->Scope = CurrentScope; S->FuncId = ~0U; S->Pos = CurTok.Pos; /* Return the result */ return S; } static unsigned HexValue (char C) /* Convert the ascii representation of a hex nibble into the hex nibble */ { if (isdigit (C)) { return C - '0'; } else if (islower (C)) { return C - 'a' + 10; } else { return C - 'A' + 10; } } static int ValidateType (StrBuf* Type) /* Check if the given type is valid and if so, return a string id for it. If ** the type isn't valid, return -1. Type is overwritten when checking. */ { unsigned I; const char* A; char* B; /* The length must not be zero and divideable by two */ unsigned Length = SB_GetLen (Type); if (Length < 2 || (Length & 0x01) != 0) { ErrorSkip ("Type value has invalid length"); return -1; } /* The string must consist completely of hex digit chars */ A = SB_GetConstBuf (Type); for (I = 0; I < Length; ++I) { if (!IsXDigit (A[I])) { ErrorSkip ("Type value contains invalid characters"); return -1; } } /* Convert the type to binary */ B = SB_GetBuf (Type); while (A < SB_GetConstBuf (Type) + Length) { /* Since we know, there are only hex digits, there can't be any errors */ *B++ = (HexValue (A[0]) << 4) | HexValue (A[1]); A += 2; } Type->Len = (Length /= 2); /* Allocate the type and return it */ return GetStrBufId (Type); } void DbgInfoFile (void) /* Parse and handle FILE subcommand of the .dbg pseudo instruction */ { StrBuf Name = STATIC_STRBUF_INITIALIZER; unsigned long Size; unsigned long MTime; /* Parameters are separated by a comma */ ConsumeComma (); /* Name */ if (CurTok.Tok != TOK_STRCON) { ErrorSkip ("String constant expected"); return; } SB_Copy (&Name, &CurTok.SVal); NextTok (); /* Comma expected */ ConsumeComma (); /* Size */ Size = ConstExpression (); /* Comma expected */ ConsumeComma (); /* MTime */ MTime = ConstExpression (); /* Insert the file into the table */ AddFile (&Name, FT_DBGINFO, Size, MTime); /* Free memory used for Name */ SB_Done (&Name); } void DbgInfoFunc (void) /* Parse and handle func subcommand of the .dbg pseudo instruction */ { static const char* const StorageKeys[] = { "EXTERN", "STATIC", }; unsigned Name; int Type; unsigned AsmName; unsigned Flags; HLLDbgSym* S; /* Parameters are separated by a comma */ ConsumeComma (); /* Name */ if (CurTok.Tok != TOK_STRCON) { ErrorSkip ("String constant expected"); return; } Name = GetStrBufId (&CurTok.SVal); NextTok (); /* Comma expected */ ConsumeComma (); /* Type */ if (CurTok.Tok != TOK_STRCON) { ErrorSkip ("String constant expected"); return; } Type = ValidateType (&CurTok.SVal); if (Type < 0) { return; } NextTok (); /* Comma expected */ ConsumeComma (); /* The storage class follows */ if (CurTok.Tok != TOK_IDENT) { ErrorSkip ("Storage class specifier expected"); return; } switch (GetSubKey (StorageKeys, sizeof (StorageKeys)/sizeof (StorageKeys[0]))) { case 0: Flags = HLL_TYPE_FUNC | HLL_SC_EXTERN; break; case 1: Flags = HLL_TYPE_FUNC | HLL_SC_STATIC; break; default: ErrorSkip ("Storage class specifier expected"); return; } NextTok (); /* Comma expected */ ConsumeComma (); /* Assembler name follows */ if (CurTok.Tok != TOK_STRCON) { ErrorSkip ("String constant expected"); return; } AsmName = GetStrBufId (&CurTok.SVal); NextTok (); /* There may only be one function per scope */ if (CurrentScope == RootScope) { ErrorSkip ("Functions may not be used in the root scope"); return; } else if (CurrentScope->Type != SCOPE_SCOPE || CurrentScope->Label == 0) { ErrorSkip ("Functions can only be tagged to .PROC scopes"); return; } else if (CurrentScope->Label->HLLSym != 0) { ErrorSkip ("Only one HLL symbol per asm symbol is allowed"); return; } else if (CurrentScope->Label->Name != AsmName) { ErrorSkip ("Scope label and asm name for function must match"); return; } /* Add the function */ S = NewHLLDbgSym (Flags, Name, Type); S->Sym = CurrentScope->Label; CurrentScope->Label->HLLSym = S; CollAppend (&HLLDbgSyms, S); } void DbgInfoLine (void) /* Parse and handle LINE subcommand of the .dbg pseudo instruction */ { long Line; FilePos Pos = STATIC_FILEPOS_INITIALIZER; /* Any new line info terminates the last one */ if (CurLineInfo) { EndLine (CurLineInfo); CurLineInfo = 0; } /* If a parameters follow, this is actual line info. If no parameters ** follow, the last line info is terminated. */ if (CurTok.Tok == TOK_SEP) { return; } /* Parameters are separated by a comma */ ConsumeComma (); /* The name of the file follows */ if (CurTok.Tok != TOK_STRCON) { ErrorSkip ("String constant expected"); return; } /* Get the index in the file table for the name */ Pos.Name = GetFileIndex (&CurTok.SVal); /* Skip the name */ NextTok (); /* Comma expected */ ConsumeComma (); /* Line number */ Line = ConstExpression (); if (Line < 0) { ErrorSkip ("Line number is out of valid range"); return; } Pos.Line = Line; /* Generate a new external line info */ CurLineInfo = StartLine (&Pos, LI_TYPE_EXT, 0); } void DbgInfoSym (void) /* Parse and handle SYM subcommand of the .dbg pseudo instruction */ { static const char* const StorageKeys[] = { "AUTO", "EXTERN", "REGISTER", "STATIC", }; unsigned Name; int Type; unsigned AsmName = EMPTY_STRING_ID; unsigned Flags; int Offs = 0; HLLDbgSym* S; /* Parameters are separated by a comma */ ConsumeComma (); /* Name */ if (CurTok.Tok != TOK_STRCON) { ErrorSkip ("String constant expected"); return; } Name = GetStrBufId (&CurTok.SVal); NextTok (); /* Comma expected */ ConsumeComma (); /* Type */ if (CurTok.Tok != TOK_STRCON) { ErrorSkip ("String constant expected"); return; } Type = ValidateType (&CurTok.SVal); if (Type < 0) { return; } NextTok (); /* Comma expected */ ConsumeComma (); /* The storage class follows */ if (CurTok.Tok != TOK_IDENT) { ErrorSkip ("Storage class specifier expected"); return; } switch (GetSubKey (StorageKeys, sizeof (StorageKeys)/sizeof (StorageKeys[0]))) { case 0: Flags = HLL_SC_AUTO; break; case 1: Flags = HLL_SC_EXTERN; break; case 2: Flags = HLL_SC_REG; break; case 3: Flags = HLL_SC_STATIC; break; default: ErrorSkip ("Storage class specifier expected"); return; } /* Skip the storage class token and the following comma */ NextTok (); ConsumeComma (); /* The next tokens depend on the storage class */ if (Flags == HLL_SC_AUTO) { /* Auto: Stack offset follows */ Offs = ConstExpression (); } else { /* Register, extern or static: Assembler name follows */ if (CurTok.Tok != TOK_STRCON) { ErrorSkip ("String constant expected"); return; } AsmName = GetStrBufId (&CurTok.SVal); NextTok (); /* For register, an offset follows */ if (Flags == HLL_SC_REG) { ConsumeComma (); Offs = ConstExpression (); } } /* Add the function */ S = NewHLLDbgSym (Flags | HLL_TYPE_SYM, Name, Type); S->AsmName = AsmName; S->Offs = Offs; CollAppend (&HLLDbgSyms, S); } void DbgInfoCheck (void) /* Do checks on all hll debug info symbols when assembly is complete */ { /* When parsing the debug statements for HLL symbols, we have already ** tagged the functions to their asm counterparts. This wasn't done for ** C symbols, since we will allow forward declarations. So we have to ** resolve the normal C symbols now. */ unsigned I; for (I = 0; I < CollCount (&HLLDbgSyms); ++I) { /* Get the next symbol */ HLLDbgSym* S = CollAtUnchecked (&HLLDbgSyms, I); /* Ignore functions and auto symbols, because the later live on the ** stack and don't have corresponding asm symbols. */ if (HLL_IS_FUNC (S->Flags) || HLL_GET_SC (S->Flags) == HLL_SC_AUTO) { continue; } /* Safety */ CHECK (S->Sym == 0 && S->Scope != 0); /* Search for the symbol name */ S->Sym = SymFindAny (S->Scope, GetStrBuf (S->AsmName)); if (S->Sym == 0) { PError (&S->Pos, "Assembler symbol '%s' not found", GetString (S->AsmName)); } else { /* Set the backlink */ S->Sym->HLLSym = S; } } } void WriteHLLDbgSyms (void) /* Write a list of all high level language symbols to the object file. */ { unsigned I; /* Only if debug info is enabled */ if (DbgSyms) { /* Write the symbol count to the list */ ObjWriteVar (CollCount (&HLLDbgSyms)); /* Walk through list and write all symbols to the file. */ for (I = 0; I < CollCount (&HLLDbgSyms); ++I) { /* Get the next symbol */ HLLDbgSym* S = CollAtUnchecked (&HLLDbgSyms, I); /* Get the type of the symbol */ unsigned SC = HLL_GET_SC (S->Flags); /* Remember if the symbol has debug info attached ** ### This should go into DbgInfoCheck */ if (S->Sym && S->Sym->DebugSymId != ~0U) { S->Flags |= HLL_DATA_SYM; } /* Write the symbol data */ ObjWriteVar (S->Flags); ObjWriteVar (S->Name); if (HLL_HAS_SYM (S->Flags)) { ObjWriteVar (S->Sym->DebugSymId); } if (SC == HLL_SC_AUTO || SC == HLL_SC_REG) { ObjWriteVar (S->Offs); } ObjWriteVar (S->Type); ObjWriteVar (S->Scope->Id); } } else { /* Write a count of zero */ ObjWriteVar (0); } } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/dbginfo.h������������������������������������������������������������������������0000664�0000000�0000000�00000006607�13473601511�0015324�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* dbginfo.h */ /* */ /* Handle the .dbg commands */ /* */ /* */ /* */ /* (C) 2000-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef DBGINFO_H #define DBGINFO_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ void DbgInfoFile (void); /* Parse and handle FILE subcommand of the .dbg pseudo instruction */ void DbgInfoFunc (void); /* Parse and handle FUNC subcommand of the .dbg pseudo instruction */ void DbgInfoLine (void); /* Parse and handle LINE subcommand of the .dbg pseudo instruction */ void DbgInfoSym (void); /* Parse and handle SYM subcommand of the .dbg pseudo instruction */ void DbgInfoCheck (void); /* Do checks on all hll debug info symbols when assembly is complete */ void WriteHLLDbgSyms (void); /* Write a list of all high level language symbols to the object file. */ /* End of dbginfo.h */ #endif �������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/ea.h�����������������������������������������������������������������������������0000664�0000000�0000000�00000006641�13473601511�0014277�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* ea65.h */ /* */ /* Effective address structure definition */ /* */ /* */ /* */ /* (C) 1998-2004 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef EA_H #define EA_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* GetEA result struct */ typedef struct EffAddr EffAddr; struct EffAddr { /* First three fields get filled when calling GetEA */ unsigned long AddrModeSet; /* Possible addressing modes */ struct ExprNode* Expr; /* Expression if any (NULL otherwise) */ unsigned Reg; /* Register number in sweet16 mode */ /* The following fields are used inside instr.c */ unsigned AddrMode; /* Actual addressing mode used */ unsigned long AddrModeBit; /* Addressing mode as bit mask */ unsigned char Opcode; /* Opcode */ }; /* End of ea.h */ #endif �����������������������������������������������������������������������������������������������cc65-2.18/src/ca65/ea65.c���������������������������������������������������������������������������0000664�0000000�0000000�00000017067�13473601511�0014451�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* ea65.c */ /* */ /* 65XX effective address parsing for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* ca65 */ #include "ea.h" #include "ea65.h" #include "error.h" #include "expr.h" #include "instr.h" #include "nexttok.h" #include "global.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void GetEA (EffAddr* A) /* Parse an effective address, return the result in A */ { unsigned long Restrictions; token_t IndirectEnter; token_t IndirectLeave; const char* IndirectExpect; /* Choose syntax for indirection */ if (BracketAsIndirect) { IndirectEnter = TOK_LBRACK; IndirectLeave = TOK_RBRACK; IndirectExpect = "']' expected"; } else { IndirectEnter = TOK_LPAREN; IndirectLeave = TOK_RPAREN; IndirectExpect = "')' expected"; } /* Clear the output struct */ A->AddrModeSet = 0; A->Expr = 0; /* Handle an addressing size override */ switch (CurTok.Tok) { case TOK_OVERRIDE_ZP: Restrictions = AM65_DIR | AM65_DIR_X | AM65_DIR_Y; NextTok (); break; case TOK_OVERRIDE_ABS: Restrictions = AM65_ABS | AM65_ABS_X | AM65_ABS_Y; NextTok (); break; case TOK_OVERRIDE_FAR: Restrictions = AM65_ABS_LONG | AM65_ABS_LONG_X; NextTok (); break; default: Restrictions = ~0UL; /* None */ break; } /* Parse the effective address */ if (TokIsSep (CurTok.Tok)) { A->AddrModeSet = AM65_IMPLICIT; } else if (CurTok.Tok == TOK_HASH) { /* #val */ NextTok (); A->Expr = Expression (); A->AddrModeSet = AM65_ALL_IMM; } else if (CurTok.Tok == TOK_A) { NextTok (); A->AddrModeSet = AM65_ACCU; } else if (CurTok.Tok == IndirectEnter) { /* One of the indirect modes */ NextTok (); A->Expr = Expression (); if (CurTok.Tok == TOK_COMMA) { /* (expr,X) or (rel,S),y */ NextTok (); if (CurTok.Tok == TOK_X) { /* (adr,x) */ NextTok (); A->AddrModeSet = AM65_ABS_X_IND | AM65_DIR_X_IND; Consume (IndirectLeave, IndirectExpect); } else if (CurTok.Tok == TOK_S) { /* (rel,s),y */ NextTok (); A->AddrModeSet = AM65_STACK_REL_IND_Y; Consume (IndirectLeave, IndirectExpect); ConsumeComma (); Consume (TOK_Y, "'Y' expected"); } else { Error ("Syntax error"); } } else { /* (adr), (adr),y or (adr),z */ Consume (IndirectLeave, IndirectExpect); if (CurTok.Tok == TOK_COMMA) { /* (adr),y */ NextTok (); switch (CurTok.Tok) { case TOK_Z: /* only set by scanner.c if in 4510-mode */ NextTok (); A->AddrModeSet = AM65_DIR_IND; break; default: Consume (TOK_Y, "'Y' expected"); A->AddrModeSet = AM65_DIR_IND_Y; break; } } else { /* (adr) */ A->AddrModeSet = (CPU == CPU_4510) ? AM65_ABS_IND : AM65_ABS_IND | AM65_ABS_IND_LONG | AM65_DIR_IND; } } } else if (CurTok.Tok == TOK_LBRACK) { /* Never executed if BracketAsIndirect feature is enabled. */ /* [dir] or [dir],y */ NextTok (); A->Expr = Expression (); Consume (TOK_RBRACK, "']' expected"); if (CurTok.Tok == TOK_COMMA) { /* [dir],y */ NextTok (); Consume (TOK_Y, "'Y' expected"); A->AddrModeSet = AM65_DIR_IND_LONG_Y; } else { /* [dir] */ A->AddrModeSet = AM65_DIR_IND_LONG | AM65_ABS_IND_LONG; } } else { /* Remaining stuff: ** ** adr ** adr,x ** adr,y ** adr,s */ A->Expr = Expression (); if (CurTok.Tok == TOK_COMMA) { NextTok (); switch (CurTok.Tok) { case TOK_X: A->AddrModeSet = AM65_ABS_LONG_X | AM65_ABS_X | AM65_DIR_X; NextTok (); break; case TOK_Y: A->AddrModeSet = AM65_ABS_Y | AM65_DIR_Y; NextTok (); break; case TOK_S: A->AddrModeSet = AM65_STACK_REL; NextTok (); break; default: Error ("Syntax error"); } } else { A->AddrModeSet = AM65_ABS_LONG | AM65_ABS | AM65_DIR; } } /* Apply addressing mode overrides */ A->AddrModeSet &= Restrictions; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/ea65.h���������������������������������������������������������������������������0000664�0000000�0000000�00000006216�13473601511�0014450�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* ea65.h */ /* */ /* 65XX effective address parsing for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 1998-2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef EA65_H #define EA65_H /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ struct EffAddr; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void GetEA (EffAddr* A); /* Parse an effective address, return the result in A */ /* End of ea65.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/easw16.c�������������������������������������������������������������������������0000664�0000000�0000000�00000012237�13473601511�0015011�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* easw16.c */ /* */ /* SWEET16 effective address parsing for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 2004-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* ca65 */ #include "ea.h" #include "ea65.h" #include "error.h" #include "expr.h" #include "instr.h" #include "nexttok.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ static long RegNum () /* Try to read a register number specified not as a register (Rx) but as a ** numeric value between 0 and 15. Return the register number or -1 on ** failure. */ { long Val; ExprNode* Expr = Expression (); if (!IsConstExpr (Expr, &Val) || Val < 0 || Val > 15) { /* Invalid register */ Val = -1L; } /* Free the expression and return the register number */ FreeExpr (Expr); return Val; } void GetSweet16EA (EffAddr* A) /* Parse an effective address, return the result in A */ { long Reg; /* Clear the output struct */ A->AddrModeSet = 0; A->Expr = 0; A->Reg = 0; /* Parse the effective address */ if (TokIsSep (CurTok.Tok)) { A->AddrModeSet = AMSW16_IMP; } else if (CurTok.Tok == TOK_AT) { /* @reg or @regnumber */ A->AddrModeSet = AMSW16_IND; NextTok (); if (CurTok.Tok == TOK_REG) { A->Reg = (unsigned) CurTok.IVal; NextTok (); } else if ((Reg = RegNum ()) >= 0) { /* Register number */ A->Reg = (unsigned) Reg; } else { ErrorSkip ("Register or register number expected"); A->Reg = 0; } } else if (CurTok.Tok == TOK_REG) { A->Reg = (unsigned) CurTok.IVal; NextTok (); if (CurTok.Tok == TOK_COMMA) { /* Rx, constant */ NextTok (); A->Expr = Expression (); A->AddrModeSet = AMSW16_IMM; } else { A->AddrModeSet = AMSW16_REG; } } else { /* OPC ea or: OPC regnum, constant */ A->Expr = Expression (); A->AddrModeSet = AMSW16_BRA; /* If the value is a constant between 0 and 15, it may also be a ** register number. */ if (IsConstExpr (A->Expr, &Reg) && Reg >= 0 && Reg <= 15) { FreeExpr (A->Expr); A->Reg = (unsigned) Reg; /* If a comma follows, it is: OPC Rx, constant */ if (CurTok.Tok == TOK_COMMA) { NextTok (); A->Expr = Expression (); A->AddrModeSet = AMSW16_IMM; } else { A->Expr = 0; A->AddrModeSet |= AMSW16_REG; } } } } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/easw16.h�������������������������������������������������������������������������0000664�0000000�0000000�00000006257�13473601511�0015023�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* easw16.h */ /* */ /* SWEET16 effective address parsing for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 2004 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef EASW16_H #define EASW16_H /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ struct EffAddr; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void GetSweet16EA (EffAddr* A); /* Parse an effective address, return the result in A */ /* End of easw16.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/enum.c���������������������������������������������������������������������������0000664�0000000�0000000�00000012555�13473601511�0014652�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* enum.c */ /* */ /* .ENUM command */ /* */ /* */ /* */ /* (C) 2003-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "addrsize.h" #include "scopedefs.h" /* ca65 */ #include "condasm.h" #include "enum.h" #include "error.h" #include "expr.h" #include "macro.h" #include "nexttok.h" #include "scanner.h" #include "symbol.h" #include "symtab.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void DoEnum (void) /* Handle the .ENUM command */ { /* Start at zero */ long Offs = 0; ExprNode* BaseExpr = GenLiteral0 (); /* Check for a name */ int Anon = (CurTok.Tok != TOK_IDENT); if (!Anon) { /* Enter a new scope, then skip the name */ SymEnterLevel (&CurTok.SVal, SCOPE_ENUM, ADDR_SIZE_ABS, 0); NextTok (); } /* Test for end of line */ ConsumeSep (); /* Read until end of struct */ while (CurTok.Tok != TOK_ENDENUM && CurTok.Tok != TOK_EOF) { Macro* M; SymEntry* Sym; ExprNode* EnumExpr; /* Skip empty lines */ if (CurTok.Tok == TOK_SEP) { NextTok (); continue; } /* The format is "identifier [ = value ]" */ if (CurTok.Tok != TOK_IDENT) { /* Maybe it's a conditional? */ if (!CheckConditionals ()) { ErrorSkip ("Identifier expected"); } continue; } /* We have an identifier. Is it a macro? */ if ((M = FindMacro (&CurTok.SVal)) != 0) { MacExpandStart (M); continue; } /* We have an identifier, generate a symbol */ Sym = SymFind (CurrentScope, &CurTok.SVal, SYM_ALLOC_NEW); /* Skip the member name */ NextTok (); /* Check for an assignment */ if (CurTok.Tok == TOK_EQ) { /* Skip the equal sign */ NextTok (); /* Read the new expression */ EnumExpr = Expression (); /* Reset the base expression and the offset */ FreeExpr (BaseExpr); BaseExpr = CloneExpr (EnumExpr); Offs = 0; } else { /* No assignment, use last value + 1 */ EnumExpr = GenAddExpr (CloneExpr (BaseExpr), GenLiteralExpr (Offs)); } /* Assign the value to the enum member */ SymDef (Sym, EnumExpr, ADDR_SIZE_DEFAULT, SF_NONE); /* Increment the offset for the next member */ ++Offs; /* Expect end of line */ ConsumeSep (); } /* If this is not an anon enum, leave its scope */ if (!Anon) { /* Close the enum scope */ SymLeaveLevel (); } /* End of enum definition */ Consume (TOK_ENDENUM, "'.ENDENUM' expected"); /* Free the base expression */ FreeExpr (BaseExpr); } ���������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/enum.h���������������������������������������������������������������������������0000664�0000000�0000000�00000005551�13473601511�0014655�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* enum.h */ /* */ /* .ENUM command */ /* */ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ /* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef ENUM_H #define ENUM_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ void DoEnum (void); /* Handle the .ENUM command */ /* End of enum.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/error.c��������������������������������������������������������������������������0000664�0000000�0000000�00000027015�13473601511�0015034�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* error.c */ /* */ /* Error handling for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> /* common */ #include "strbuf.h" /* ca65 */ #include "error.h" #include "filetab.h" #include "lineinfo.h" #include "nexttok.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Warning level */ unsigned WarnLevel = 1; /* Statistics */ unsigned ErrorCount = 0; unsigned WarningCount = 0; /* Maximum number of additional notifications */ #define MAX_NOTES 8 /*****************************************************************************/ /* Helper functions */ /*****************************************************************************/ static void VPrintMsg (const FilePos* Pos, const char* Desc, const char* Format, va_list ap) /* Format and output an error/warning message. */ { StrBuf S = STATIC_STRBUF_INITIALIZER; /* Format the actual message */ StrBuf Msg = STATIC_STRBUF_INITIALIZER; SB_VPrintf (&Msg, Format, ap); SB_Terminate (&Msg); /* Format the message header */ SB_Printf (&S, "%s(%u): %s: ", SB_GetConstBuf (GetFileName (Pos->Name)), Pos->Line, Desc); /* Append the message to the message header */ SB_Append (&S, &Msg); /* Delete the formatted message */ SB_Done (&Msg); /* Add a new line and terminate the generated full message */ SB_AppendChar (&S, '\n'); SB_Terminate (&S); /* Output the full message */ fputs (SB_GetConstBuf (&S), stderr); /* Delete the buffer for the full message */ SB_Done (&S); } static void PrintMsg (const FilePos* Pos, const char* Desc, const char* Format, ...) /* Format and output an error/warning message. */ { va_list ap; va_start (ap, Format); VPrintMsg (Pos, Desc, Format, ap); va_end (ap); } static void AddNotifications (const Collection* LineInfos) /* Output additional notifications for an error or warning */ { unsigned I; unsigned Output; unsigned Skipped; /* The basic line info is always in slot zero. It has been used to ** output the actual error or warning. The following slots may contain ** more information. Check them and print additional notifications if ** they're present, but limit the number to a reasonable value. */ for (I = 1, Output = 0, Skipped = 0; I < CollCount (LineInfos); ++I) { /* Get next line info */ const LineInfo* LI = CollConstAt (LineInfos, I); /* Check the type and output an appropriate note */ const char* Msg; switch (GetLineInfoType (LI)) { case LI_TYPE_ASM: Msg = "Expanded from here"; break; case LI_TYPE_EXT: Msg = "Assembly code generated from this line"; break; case LI_TYPE_MACRO: Msg = "Macro was defined here"; break; case LI_TYPE_MACPARAM: Msg = "Macro parameter came from here"; break; default: /* No output */ Msg = 0; break; } /* Output until an upper limit of messages is reached */ if (Msg) { if (Output < MAX_NOTES) { PrintMsg (GetSourcePos (LI), "Note", "%s", Msg); ++Output; } else { ++Skipped; } } } /* Add a note if we have more stuff that we won't output */ if (Skipped > 0) { const LineInfo* LI = CollConstAt (LineInfos, 0); PrintMsg (GetSourcePos (LI), "Note", "Dropping %u additional line infos", Skipped); } } /*****************************************************************************/ /* Warnings */ /*****************************************************************************/ static void WarningMsg (const Collection* LineInfos, const char* Format, va_list ap) /* Print warning message. */ { /* The first entry in the collection is that of the actual source pos */ const LineInfo* LI = CollConstAt (LineInfos, 0); /* Output a warning for this position */ VPrintMsg (GetSourcePos (LI), "Warning", Format, ap); /* Add additional notifications if necessary */ AddNotifications (LineInfos); /* Count warnings */ ++WarningCount; } void Warning (unsigned Level, const char* Format, ...) /* Print warning message. */ { if (Level <= WarnLevel) { va_list ap; Collection LineInfos = STATIC_COLLECTION_INITIALIZER; /* Get line infos for the current position */ GetFullLineInfo (&LineInfos); /* Output the message */ va_start (ap, Format); WarningMsg (&LineInfos, Format, ap); va_end (ap); /* Free the line info list */ ReleaseFullLineInfo (&LineInfos); DoneCollection (&LineInfos); } } void PWarning (const FilePos* Pos, unsigned Level, const char* Format, ...) /* Print warning message giving an explicit file and position. */ { if (Level <= WarnLevel) { va_list ap; va_start (ap, Format); VPrintMsg (Pos, "Warning", Format, ap); va_end (ap); /* Count warnings */ ++WarningCount; } } void LIWarning (const Collection* LineInfos, unsigned Level, const char* Format, ...) /* Print warning message using the given line infos */ { if (Level <= WarnLevel) { /* Output the message */ va_list ap; va_start (ap, Format); WarningMsg (LineInfos, Format, ap); va_end (ap); } } /*****************************************************************************/ /* Errors */ /*****************************************************************************/ void ErrorMsg (const Collection* LineInfos, const char* Format, va_list ap) /* Print an error message */ { /* The first entry in the collection is that of the actual source pos */ const LineInfo* LI = CollConstAt (LineInfos, 0); /* Output an error for this position */ VPrintMsg (GetSourcePos (LI), "Error", Format, ap); /* Add additional notifications if necessary */ AddNotifications (LineInfos); /* Count errors */ ++ErrorCount; } void Error (const char* Format, ...) /* Print an error message */ { va_list ap; Collection LineInfos = STATIC_COLLECTION_INITIALIZER; /* Get line infos for the current position */ GetFullLineInfo (&LineInfos); /* Output the message */ va_start (ap, Format); ErrorMsg (&LineInfos, Format, ap); va_end (ap); /* Free the line info list */ ReleaseFullLineInfo (&LineInfos); DoneCollection (&LineInfos); } void PError (const FilePos* Pos, const char* Format, ...) /* Print an error message giving an explicit file and position. */ { va_list ap; va_start (ap, Format); VPrintMsg (Pos, "Error", Format, ap); va_end (ap); /* Count errors */ ++ErrorCount; } void LIError (const Collection* LineInfos, const char* Format, ...) /* Print an error message using the given line infos. */ { /* Output an error for this position */ va_list ap; va_start (ap, Format); ErrorMsg (LineInfos, Format, ap); va_end (ap); } void ErrorSkip (const char* Format, ...) /* Print an error message and skip the rest of the line */ { va_list ap; Collection LineInfos = STATIC_COLLECTION_INITIALIZER; /* Get line infos for the current position */ GetFullLineInfo (&LineInfos); /* Output the message */ va_start (ap, Format); ErrorMsg (&LineInfos, Format, ap); va_end (ap); /* Free the line info list */ ReleaseFullLineInfo (&LineInfos); DoneCollection (&LineInfos); /* Skip tokens until we reach the end of the line */ SkipUntilSep (); } /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Fatal (const char* Format, ...) /* Print a message about a fatal error and die */ { va_list ap; StrBuf S = STATIC_STRBUF_INITIALIZER; va_start (ap, Format); SB_VPrintf (&S, Format, ap); SB_Terminate (&S); va_end (ap); fprintf (stderr, "Fatal error: %s\n", SB_GetConstBuf (&S)); SB_Done (&S); /* And die... */ exit (EXIT_FAILURE); } void Internal (const char* Format, ...) /* Print a message about an internal assembler error and die. */ { va_list ap; StrBuf S = STATIC_STRBUF_INITIALIZER; va_start (ap, Format); SB_VPrintf (&S, Format, ap); SB_Terminate (&S); va_end (ap); fprintf (stderr, "Internal assembler error: %s\n", SB_GetConstBuf (&S)); SB_Done (&S); exit (EXIT_FAILURE); } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/error.h��������������������������������������������������������������������������0000664�0000000�0000000�00000011166�13473601511�0015041�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* error.h */ /* */ /* Error handling for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef ERROR_H #define ERROR_H #if defined( __MINGW32__) # pragma GCC diagnostic ignored "-Wformat" #endif /* common */ #include "attrib.h" #include "coll.h" #include "filepos.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Warning levels */ extern unsigned WarnLevel; /* Statistics */ extern unsigned ErrorCount; extern unsigned WarningCount; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Warning (unsigned Level, const char* Format, ...) attribute ((format (printf, 2, 3))); /* Print warning message. */ void PWarning (const FilePos* Pos, unsigned Level, const char* Format, ...) attribute ((format (printf, 3, 4))); /* Print warning message giving an explicit file and position. */ void LIWarning (const Collection* LineInfos, unsigned Level, const char* Format, ...) attribute ((format (printf, 3, 4))); /* Print warning message using the given line infos */ void Error (const char* Format, ...) attribute ((format (printf, 1, 2))); /* Print an error message */ void PError (const FilePos* Pos, const char* Format, ...) attribute ((format (printf, 2, 3))); /* Print an error message giving an explicit file and position. */ void LIError (const Collection* LineInfos, const char* Format, ...) attribute ((format (printf, 2, 3))); /* Print an error message using the given line infos. */ void ErrorSkip (const char* Format, ...) attribute ((format (printf, 1, 2))); /* Print an error message and skip the rest of the line */ void Fatal (const char* Format, ...) attribute((noreturn, format(printf,1,2))); /* Print a message about a fatal error and die */ void Internal (const char* Format, ...) attribute((noreturn, format(printf,1,2))); /* Print a message about an internal assembler error and die. */ /* End of error.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/expr.c���������������������������������������������������������������������������0000664�0000000�0000000�00000150245�13473601511�0014663�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* expr.c */ /* */ /* Expression evaluation for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> #include <time.h> /* common */ #include "check.h" #include "cpu.h" #include "exprdefs.h" #include "print.h" #include "shift.h" #include "segdefs.h" #include "strbuf.h" #include "tgttrans.h" #include "version.h" #include "xmalloc.h" /* ca65 */ #include "error.h" #include "expr.h" #include "global.h" #include "instr.h" #include "nexttok.h" #include "objfile.h" #include "segment.h" #include "sizeof.h" #include "studyexpr.h" #include "symbol.h" #include "symtab.h" #include "toklist.h" #include "ulabel.h" #include "macro.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Since all expressions are first packed into expression trees, and each ** expression tree node is allocated on the heap, we add some type of special ** purpose memory allocation here: Instead of freeing the nodes, we save some ** number of freed nodes for later and remember them in a single linked list ** using the Left link. */ #define MAX_FREE_NODES 64 static ExprNode* FreeExprNodes = 0; static unsigned FreeNodeCount = 0; /*****************************************************************************/ /* Helpers */ /*****************************************************************************/ static ExprNode* NewExprNode (unsigned Op) /* Create a new expression node */ { ExprNode* N; /* Do we have some nodes in the list already? */ if (FreeNodeCount) { /* Use first node from list */ N = FreeExprNodes; FreeExprNodes = N->Left; --FreeNodeCount; } else { /* Allocate fresh memory */ N = xmalloc (sizeof (ExprNode)); } N->Op = Op; N->Left = N->Right = 0; N->Obj = 0; return N; } static void FreeExprNode (ExprNode* E) /* Free a node */ { if (E) { if (E->Op == EXPR_SYMBOL) { /* Remove the symbol reference */ SymDelExprRef (E->V.Sym, E); } /* Place the symbol into the free nodes list if possible */ if (FreeNodeCount < MAX_FREE_NODES) { /* Remember this node for later */ E->Left = FreeExprNodes; FreeExprNodes = E; ++FreeNodeCount; } else { /* Free the memory */ xfree (E); } } } /*****************************************************************************/ /* Code */ /*****************************************************************************/ static ExprNode* Expr0 (void); int IsByteRange (long Val) /* Return true if this is a byte value */ { return (Val & ~0xFFL) == 0; } int IsWordRange (long Val) /* Return true if this is a word value */ { return (Val & ~0xFFFFL) == 0; } int IsFarRange (long Val) /* Return true if this is a far (24 bit) value */ { return (Val & ~0xFFFFFFL) == 0; } int IsEasyConst (const ExprNode* E, long* Val) /* Do some light checking if the given node is a constant. Don't care if E is ** a complex expression. If E is a constant, return true and place its value ** into Val, provided that Val is not NULL. */ { /* Resolve symbols, follow symbol chains */ while (E->Op == EXPR_SYMBOL) { E = SymResolve (E->V.Sym); if (E == 0) { /* Could not resolve */ return 0; } } /* Symbols resolved, check for a literal */ if (E->Op == EXPR_LITERAL) { if (Val) { *Val = E->V.IVal; } return 1; } /* Not found to be a const according to our tests */ return 0; } static ExprNode* LoByte (ExprNode* Operand) /* Return the low byte of the given expression */ { ExprNode* Expr; long Val; /* Special handling for const expressions */ if (IsEasyConst (Operand, &Val)) { FreeExpr (Operand); Expr = GenLiteralExpr (Val & 0xFF); } else { /* Extract byte #0 */ Expr = NewExprNode (EXPR_BYTE0); Expr->Left = Operand; } return Expr; } static ExprNode* HiByte (ExprNode* Operand) /* Return the high byte of the given expression */ { ExprNode* Expr; long Val; /* Special handling for const expressions */ if (IsEasyConst (Operand, &Val)) { FreeExpr (Operand); Expr = GenLiteralExpr ((Val >> 8) & 0xFF); } else { /* Extract byte #1 */ Expr = NewExprNode (EXPR_BYTE1); Expr->Left = Operand; } return Expr; } static ExprNode* Bank (ExprNode* Operand) /* Return the bank of the given segmented expression */ { /* Generate the bank expression */ ExprNode* Expr = NewExprNode (EXPR_BANK); Expr->Left = Operand; /* Return the result */ return Expr; } static ExprNode* BankByte (ExprNode* Operand) /* Return the bank byte of the given expression */ { ExprNode* Expr; long Val; /* Special handling for const expressions */ if (IsEasyConst (Operand, &Val)) { FreeExpr (Operand); Expr = GenLiteralExpr ((Val >> 16) & 0xFF); } else { /* Extract byte #2 */ Expr = NewExprNode (EXPR_BYTE2); Expr->Left = Operand; } return Expr; } static ExprNode* LoWord (ExprNode* Operand) /* Return the low word of the given expression */ { ExprNode* Expr; long Val; /* Special handling for const expressions */ if (IsEasyConst (Operand, &Val)) { FreeExpr (Operand); Expr = GenLiteralExpr (Val & 0xFFFF); } else { /* Extract word #0 */ Expr = NewExprNode (EXPR_WORD0); Expr->Left = Operand; } return Expr; } static ExprNode* HiWord (ExprNode* Operand) /* Return the high word of the given expression */ { ExprNode* Expr; long Val; /* Special handling for const expressions */ if (IsEasyConst (Operand, &Val)) { FreeExpr (Operand); Expr = GenLiteralExpr ((Val >> 16) & 0xFFFF); } else { /* Extract word #1 */ Expr = NewExprNode (EXPR_WORD1); Expr->Left = Operand; } return Expr; } static ExprNode* Symbol (SymEntry* S) /* Reference a symbol and return an expression for it */ { if (S == 0) { /* Some weird error happened before */ return GenLiteralExpr (0); } else { /* Mark the symbol as referenced */ SymRef (S); /* If the symbol is a variable, return just its value, otherwise ** return a reference to the symbol. */ if (SymIsVar (S)) { return CloneExpr (GetSymExpr (S)); } else { /* Create symbol node */ return GenSymExpr (S); } } } ExprNode* FuncBank (void) /* Handle the .BANK builtin function */ { return Bank (Expression ()); } ExprNode* FuncBankByte (void) /* Handle the .BANKBYTE builtin function */ { return BankByte (Expression ()); } static ExprNode* FuncBlank (void) /* Handle the .BLANK builtin function */ { /* We have a list of tokens that ends with the closing paren. Skip ** the tokens, and count them. Allow optionally curly braces. */ token_t Term = GetTokListTerm (TOK_RPAREN); unsigned Count = 0; while (CurTok.Tok != Term) { /* Check for end of line or end of input. Since the calling function ** will check for the closing paren, we don't need to print an error ** here, just bail out. */ if (TokIsSep (CurTok.Tok)) { break; } /* One more token */ ++Count; /* Skip the token */ NextTok (); } /* If the list was enclosed in curly braces, skip the closing brace */ if (Term == TOK_RCURLY && CurTok.Tok == TOK_RCURLY) { NextTok (); } /* Return true if the list was empty */ return GenLiteralExpr (Count == 0); } static ExprNode* FuncConst (void) /* Handle the .CONST builtin function */ { /* Read an expression */ ExprNode* Expr = Expression (); /* Check the constness of the expression */ ExprNode* Result = GenLiteralExpr (IsConstExpr (Expr, 0)); /* Free the expression */ FreeExpr (Expr); /* Done */ return Result; } static ExprNode* FuncDefined (void) /* Handle the .DEFINED builtin function */ { /* Parse the symbol name and search for the symbol */ SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING); /* Check if the symbol is defined */ return GenLiteralExpr (Sym != 0 && SymIsDef (Sym)); } 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 */ { return HiByte (Expression ()); } static ExprNode* FuncHiWord (void) /* Handle the .HIWORD builtin function */ { return HiWord (Expression ()); } 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 */ { return LoByte (Expression ()); } static ExprNode* FuncLoWord (void) /* Handle the .LOWORD builtin function */ { return LoWord (Expression ()); } static ExprNode* DoMatch (enum TC EqualityLevel) /* Handle the .MATCH and .XMATCH builtin functions */ { int Result; TokNode* Root = 0; TokNode* Last = 0; TokNode* Node; /* A list of tokens follows. Read this list and remember it building a ** single linked list of tokens including attributes. The list is ** either enclosed in curly braces, or terminated by a comma. */ token_t Term = GetTokListTerm (TOK_COMMA); while (CurTok.Tok != Term) { /* We may not end-of-line of end-of-file here */ if (TokIsSep (CurTok.Tok)) { Error ("Unexpected end of line"); return GenLiteral0 (); } /* Get a node with this token */ Node = NewTokNode (); /* Insert the node into the list */ if (Last == 0) { Root = Node; } else { Last->Next = Node; } Last = Node; /* Skip the token */ NextTok (); } /* Skip the terminator token*/ NextTok (); /* If the token list was enclosed in curly braces, we expect a comma */ if (Term == TOK_RCURLY) { ConsumeComma (); } /* Read the second list which is optionally enclosed in curly braces and ** terminated by the right parenthesis. Compare each token against the ** one in the first list. */ Term = GetTokListTerm (TOK_RPAREN); Result = 1; Node = Root; while (CurTok.Tok != Term) { /* We may not end-of-line of end-of-file here */ if (TokIsSep (CurTok.Tok)) { Error ("Unexpected end of line"); return GenLiteral0 (); } /* Compare the tokens if the result is not already known */ if (Result != 0) { if (Node == 0) { /* The second list is larger than the first one */ Result = 0; } else if (TokCmp (Node) < EqualityLevel) { /* Tokens do not match */ Result = 0; } } /* Next token in first list */ if (Node) { Node = Node->Next; } /* Next token in current list */ NextTok (); } /* If the token list was enclosed in curly braces, eat the closing brace */ if (Term == TOK_RCURLY) { NextTok (); } /* Check if there are remaining tokens in the first list */ if (Node != 0) { Result = 0; } /* Free the token list */ while (Root) { Node = Root; Root = Root->Next; FreeTokNode (Node); } /* Done, return the result */ return GenLiteralExpr (Result); } static ExprNode* FuncMatch (void) /* Handle the .MATCH function */ { return DoMatch (tcSameToken); } static ExprNode* FuncMax (void) /* Handle the .MAX function */ { ExprNode* Left; ExprNode* Right; ExprNode* Expr; long LeftVal, RightVal; /* Two arguments to the pseudo function */ Left = Expression (); ConsumeComma (); Right = Expression (); /* Check if we can evaluate the value immediately */ if (IsEasyConst (Left, &LeftVal) && IsEasyConst (Right, &RightVal)) { FreeExpr (Left); FreeExpr (Right); Expr = GenLiteralExpr ((LeftVal > RightVal)? LeftVal : RightVal); } else { /* Make an expression node */ Expr = NewExprNode (EXPR_MAX); Expr->Left = Left; Expr->Right = Right; } return Expr; } static ExprNode* FuncMin (void) /* Handle the .MIN function */ { ExprNode* Left; ExprNode* Right; ExprNode* Expr; long LeftVal, RightVal; /* Two arguments to the pseudo function */ Left = Expression (); ConsumeComma (); Right = Expression (); /* Check if we can evaluate the value immediately */ if (IsEasyConst (Left, &LeftVal) && IsEasyConst (Right, &RightVal)) { FreeExpr (Left); FreeExpr (Right); Expr = GenLiteralExpr ((LeftVal < RightVal)? LeftVal : RightVal); } else { /* Make an expression node */ Expr = NewExprNode (EXPR_MIN); Expr->Left = Left; Expr->Right = Right; } return Expr; } static ExprNode* FuncReferenced (void) /* Handle the .REFERENCED builtin function */ { /* Parse the symbol name and search for the symbol */ SymEntry* Sym = ParseAnySymName (SYM_FIND_EXISTING); /* Check if the symbol is referenced */ return GenLiteralExpr (Sym != 0 && SymIsRef (Sym)); } 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 */ { StrBuf ScopeName = STATIC_STRBUF_INITIALIZER; StrBuf Name = STATIC_STRBUF_INITIALIZER; SymTable* Scope; SymEntry* Sym; SymEntry* SizeSym; long Size; int NoScope; /* Assume an error */ SizeSym = 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 { SizeSym = GetSizeOfSymbol (Sym); } /* 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); /* First search for a scope with the given name */ if (NoScope) { Scope = SymFindAnyScope (ParentScope, &Name); } else { Scope = SymFindScope (ParentScope, &Name, SYM_FIND_EXISTING); } /* 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 (Scope) { /* Yep, it's a scope */ SizeSym = GetSizeOfScope (Scope); } else { 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) { SizeSym = GetSizeOfSymbol (Sym); } else { Error ("Unknown symbol or scope: '%m%p%m%p'", &ScopeName, &Name); } } } /* Check if we have a size */ if (SizeSym == 0 || !SymIsConst (SizeSym, &Size)) { Error ("Size of '%m%p%m%p' is unknown", &ScopeName, &Name); Size = 0; } /* Free the string buffers */ SB_Done (&ScopeName); SB_Done (&Name); /* Return the size */ return GenLiteralExpr (Size); } static ExprNode* FuncStrAt (void) /* Handle the .STRAT function */ { StrBuf Str = STATIC_STRBUF_INITIALIZER; long Index; unsigned char C = 0; /* String constant expected */ if (CurTok.Tok != TOK_STRCON) { Error ("String constant expected"); NextTok (); goto ExitPoint; } /* Remember the string and skip it */ SB_Copy (&Str, &CurTok.SVal); NextTok (); /* Comma must follow */ ConsumeComma (); /* Expression expected */ Index = ConstExpression (); /* Must be a valid index */ if (Index >= (long) SB_GetLen (&Str)) { Error ("Range error"); goto ExitPoint; } /* Get the char, handle as unsigned. Be sure to translate it into ** the target character set. */ C = TgtTranslateChar (SB_At (&Str, (unsigned)Index)); ExitPoint: /* Free string buffer memory */ SB_Done (&Str); /* Return the char expression */ return GenLiteralExpr (C); } static ExprNode* FuncStrLen (void) /* Handle the .STRLEN function */ { int Len; /* String constant expected */ if (CurTok.Tok != TOK_STRCON) { Error ("String constant expected"); /* Smart error recovery */ if (CurTok.Tok != TOK_RPAREN) { NextTok (); } Len = 0; } else { /* Get the length of the string */ Len = SB_GetLen (&CurTok.SVal); /* Skip the string */ NextTok (); } /* Return the length */ return GenLiteralExpr (Len); } static ExprNode* FuncTCount (void) /* Handle the .TCOUNT function */ { /* We have a list of tokens that ends with the closing paren. Skip ** the tokens, and count them. Allow optionally curly braces. */ token_t Term = GetTokListTerm (TOK_RPAREN); int Count = 0; while (CurTok.Tok != Term) { /* Check for end of line or end of input. Since the calling function ** will check for the closing paren, we don't need to print an error ** here, just bail out. */ if (TokIsSep (CurTok.Tok)) { break; } /* One more token */ ++Count; /* Skip the token */ NextTok (); } /* If the list was enclosed in curly braces, skip the closing brace */ if (Term == TOK_RCURLY && CurTok.Tok == TOK_RCURLY) { NextTok (); } /* Return the number of tokens */ return GenLiteralExpr (Count); } static ExprNode* FuncXMatch (void) /* Handle the .XMATCH function */ { return DoMatch (tcIdentical); } static ExprNode* Function (ExprNode* (*F) (void)) /* Handle builtin functions */ { ExprNode* E; /* Skip the keyword */ NextTok (); /* Expression must be enclosed in braces */ if (CurTok.Tok != TOK_LPAREN) { Error ("'(' expected"); SkipUntilSep (); return GenLiteral0 (); } NextTok (); /* Call the function itself */ E = F (); /* Closing brace must follow */ ConsumeRParen (); /* Return the result of the actual function */ return E; } static ExprNode* Factor (void) { ExprNode* L; ExprNode* N; long Val; switch (CurTok.Tok) { case TOK_INTCON: N = GenLiteralExpr (CurTok.IVal); NextTok (); break; case TOK_CHARCON: N = GenLiteralExpr (TgtTranslateChar (CurTok.IVal)); NextTok (); break; case TOK_NAMESPACE: case TOK_IDENT: case TOK_LOCAL_IDENT: N = Symbol (ParseAnySymName (SYM_ALLOC_NEW)); break; case TOK_ULABEL: N = ULabRef (CurTok.IVal); NextTok (); break; case TOK_PLUS: NextTok (); N = Factor (); break; case TOK_MINUS: NextTok (); L = Factor (); if (IsEasyConst (L, &Val)) { FreeExpr (L); N = GenLiteralExpr (-Val); } else { N = NewExprNode (EXPR_UNARY_MINUS); N->Left = L; } break; case TOK_NOT: NextTok (); L = Factor (); if (IsEasyConst (L, &Val)) { FreeExpr (L); N = GenLiteralExpr (~Val); } else { N = NewExprNode (EXPR_NOT); N->Left = L; } break; case TOK_STAR: case TOK_PC: NextTok (); N = GenCurrentPC (); break; case TOK_LT: NextTok (); N = LoByte (Factor ()); break; case TOK_GT: NextTok (); N = HiByte (Factor ()); break; case TOK_XOR: /* ^ means the bank byte of an expression */ NextTok (); N = BankByte (Factor ()); break; case TOK_LPAREN: NextTok (); N = Expr0 (); ConsumeRParen (); break; case TOK_BANK: N = Function (FuncBank); break; case TOK_BANKBYTE: 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; case TOK_CONST: N = Function (FuncConst); break; case TOK_CPU: N = GenLiteralExpr (CPUIsets[CPU]); NextTok (); break; case TOK_DEFINED: N = Function (FuncDefined); break; case TOK_DEFINEDMACRO: N = Function (FuncDefinedMacro); break; case TOK_HIBYTE: N = Function (FuncHiByte); break; case TOK_HIWORD: 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; case TOK_LOWORD: N = Function (FuncLoWord); break; case TOK_MATCH: N = Function (FuncMatch); break; case TOK_MAX: N = Function (FuncMax); break; case TOK_MIN: N = Function (FuncMin); break; case TOK_REFERENCED: N = Function (FuncReferenced); break; case TOK_SIZEOF: N = Function (FuncSizeOf); break; case TOK_STRAT: N = Function (FuncStrAt); break; case TOK_STRLEN: N = Function (FuncStrLen); break; case TOK_TCOUNT: N = Function (FuncTCount); break; case TOK_TIME: N = GenLiteralExpr ((long) time (0)); NextTok (); break; case TOK_VERSION: N = GenLiteralExpr (GetVersionAsNumber ()); NextTok (); break; case TOK_XMATCH: N = Function (FuncXMatch); break; default: if (LooseCharTerm && CurTok.Tok == TOK_STRCON && SB_GetLen (&CurTok.SVal) == 1) { /* A character constant */ N = GenLiteralExpr (TgtTranslateChar (SB_At (&CurTok.SVal, 0))); } else { N = GenLiteral0 (); /* Dummy */ Error ("Syntax error"); } NextTok (); break; } return N; } static ExprNode* Term (void) { /* Read left hand side */ ExprNode* Root = Factor (); /* Handle multiplicative operations */ while (CurTok.Tok == TOK_MUL || CurTok.Tok == TOK_DIV || CurTok.Tok == TOK_MOD || CurTok.Tok == TOK_AND || CurTok.Tok == TOK_XOR || CurTok.Tok == TOK_SHL || CurTok.Tok == TOK_SHR) { long LVal, RVal, Val; ExprNode* Left; ExprNode* Right; /* Remember the token and skip it */ token_t T = CurTok.Tok; NextTok (); /* Move root to left side and read the right side */ Left = Root; Right = Factor (); /* If both expressions are constant, we can evaluate the term */ if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) { switch (T) { case TOK_MUL: Val = LVal * RVal; break; case TOK_DIV: if (RVal == 0) { Error ("Division by zero"); Val = 1; } else { Val = LVal / RVal; } break; case TOK_MOD: if (RVal == 0) { Error ("Modulo operation with zero"); Val = 1; } else { Val = LVal % RVal; } break; case TOK_AND: Val = LVal & RVal; break; case TOK_XOR: Val = LVal ^ RVal; break; case TOK_SHL: Val = shl_l (LVal, RVal); break; case TOK_SHR: Val = shr_l (LVal, RVal); break; default: Internal ("Invalid token"); } /* Generate a literal expression and delete the old left and ** right sides. */ FreeExpr (Left); FreeExpr (Right); Root = GenLiteralExpr (Val); } else { /* Generate an expression tree */ unsigned char Op; switch (T) { case TOK_MUL: Op = EXPR_MUL; break; case TOK_DIV: Op = EXPR_DIV; break; case TOK_MOD: Op = EXPR_MOD; break; case TOK_AND: Op = EXPR_AND; break; case TOK_XOR: Op = EXPR_XOR; break; case TOK_SHL: Op = EXPR_SHL; break; case TOK_SHR: Op = EXPR_SHR; break; default: Internal ("Invalid token"); } Root = NewExprNode (Op); Root->Left = Left; Root->Right = Right; } } /* Return the expression tree we've created */ return Root; } static ExprNode* SimpleExpr (void) { /* Read left hand side */ ExprNode* Root = Term (); /* Handle additive operations */ while (CurTok.Tok == TOK_PLUS || CurTok.Tok == TOK_MINUS || CurTok.Tok == TOK_OR) { long LVal, RVal, Val; ExprNode* Left; ExprNode* Right; /* Remember the token and skip it */ token_t T = CurTok.Tok; NextTok (); /* Move root to left side and read the right side */ Left = Root; Right = Term (); /* If both expressions are constant, we can evaluate the term */ if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) { switch (T) { case TOK_PLUS: Val = LVal + RVal; break; case TOK_MINUS: Val = LVal - RVal; break; case TOK_OR: Val = LVal | RVal; break; default: Internal ("Invalid token"); } /* Generate a literal expression and delete the old left and ** right sides. */ FreeExpr (Left); FreeExpr (Right); Root = GenLiteralExpr (Val); } else { /* Generate an expression tree */ unsigned char Op; switch (T) { case TOK_PLUS: Op = EXPR_PLUS; break; case TOK_MINUS: Op = EXPR_MINUS; break; case TOK_OR: Op = EXPR_OR; break; default: Internal ("Invalid token"); } Root = NewExprNode (Op); Root->Left = Left; Root->Right = Right; } } /* Return the expression tree we've created */ return Root; } static ExprNode* BoolExpr (void) /* Evaluate a boolean expression */ { /* Read left hand side */ ExprNode* Root = SimpleExpr (); /* Handle booleans */ while (CurTok.Tok == TOK_EQ || CurTok.Tok == TOK_NE || CurTok.Tok == TOK_LT || CurTok.Tok == TOK_GT || CurTok.Tok == TOK_LE || CurTok.Tok == TOK_GE) { long LVal, RVal, Val; ExprNode* Left; ExprNode* Right; /* Remember the token and skip it */ token_t T = CurTok.Tok; NextTok (); /* Move root to left side and read the right side */ Left = Root; Right = SimpleExpr (); /* If both expressions are constant, we can evaluate the term */ if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) { switch (T) { case TOK_EQ: Val = (LVal == RVal); break; case TOK_NE: Val = (LVal != RVal); break; case TOK_LT: Val = (LVal < RVal); break; case TOK_GT: Val = (LVal > RVal); break; case TOK_LE: Val = (LVal <= RVal); break; case TOK_GE: Val = (LVal >= RVal); break; default: Internal ("Invalid token"); } /* Generate a literal expression and delete the old left and ** right sides. */ FreeExpr (Left); FreeExpr (Right); Root = GenLiteralExpr (Val); } else { /* Generate an expression tree */ unsigned char Op; switch (T) { case TOK_EQ: Op = EXPR_EQ; break; case TOK_NE: Op = EXPR_NE; break; case TOK_LT: Op = EXPR_LT; break; case TOK_GT: Op = EXPR_GT; break; case TOK_LE: Op = EXPR_LE; break; case TOK_GE: Op = EXPR_GE; break; default: Internal ("Invalid token"); } Root = NewExprNode (Op); Root->Left = Left; Root->Right = Right; } } /* Return the expression tree we've created */ return Root; } static ExprNode* Expr2 (void) /* Boolean operators: AND and XOR */ { /* Read left hand side */ ExprNode* Root = BoolExpr (); /* Handle booleans */ while (CurTok.Tok == TOK_BOOLAND || CurTok.Tok == TOK_BOOLXOR) { long LVal, RVal, Val; ExprNode* Left; ExprNode* Right; /* Remember the token and skip it */ token_t T = CurTok.Tok; NextTok (); /* Move root to left side and read the right side */ Left = Root; Right = BoolExpr (); /* If both expressions are constant, we can evaluate the term */ if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) { switch (T) { case TOK_BOOLAND: Val = ((LVal != 0) && (RVal != 0)); break; case TOK_BOOLXOR: Val = ((LVal != 0) ^ (RVal != 0)); break; default: Internal ("Invalid token"); } /* Generate a literal expression and delete the old left and ** right sides. */ FreeExpr (Left); FreeExpr (Right); Root = GenLiteralExpr (Val); } else { /* Generate an expression tree */ unsigned char Op; switch (T) { case TOK_BOOLAND: Op = EXPR_BOOLAND; break; case TOK_BOOLXOR: Op = EXPR_BOOLXOR; break; default: Internal ("Invalid token"); } Root = NewExprNode (Op); Root->Left = Left; Root->Right = Right; } } /* Return the expression tree we've created */ return Root; } static ExprNode* Expr1 (void) /* Boolean operators: OR */ { /* Read left hand side */ ExprNode* Root = Expr2 (); /* Handle booleans */ while (CurTok.Tok == TOK_BOOLOR) { long LVal, RVal, Val; ExprNode* Left; ExprNode* Right; /* Remember the token and skip it */ token_t T = CurTok.Tok; NextTok (); /* Move root to left side and read the right side */ Left = Root; Right = Expr2 (); /* If both expressions are constant, we can evaluate the term */ if (IsEasyConst (Left, &LVal) && IsEasyConst (Right, &RVal)) { switch (T) { case TOK_BOOLOR: Val = ((LVal != 0) || (RVal != 0)); break; default: Internal ("Invalid token"); } /* Generate a literal expression and delete the old left and ** right sides. */ FreeExpr (Left); FreeExpr (Right); Root = GenLiteralExpr (Val); } else { /* Generate an expression tree */ unsigned char Op; switch (T) { case TOK_BOOLOR: Op = EXPR_BOOLOR; break; default: Internal ("Invalid token"); } Root = NewExprNode (Op); Root->Left = Left; Root->Right = Right; } } /* Return the expression tree we've created */ return Root; } static ExprNode* Expr0 (void) /* Boolean operators: NOT */ { ExprNode* Root; /* Handle booleans */ if (CurTok.Tok == TOK_BOOLNOT) { long Val; ExprNode* Left; /* Skip the operator token */ NextTok (); /* Read the argument */ Left = Expr0 (); /* If the argument is const, evaluate it directly */ if (IsEasyConst (Left, &Val)) { FreeExpr (Left); Root = GenLiteralExpr (!Val); } else { Root = NewExprNode (EXPR_BOOLNOT); Root->Left = Left; } } else { /* Read left hand side */ Root = Expr1 (); } /* Return the expression tree we've created */ return Root; } ExprNode* Expression (void) /* Evaluate an expression, build the expression tree on the heap and return ** a pointer to the root of the tree. */ { return Expr0 (); } long ConstExpression (void) /* Parse an expression. Check if the expression is const, and print an error ** message if not. Return the value of the expression, or a dummy, if it is ** not constant. */ { long Val; /* Read the expression */ ExprNode* Expr = Expression (); /* Study the expression */ ExprDesc D; ED_Init (&D); StudyExpr (Expr, &D); /* Check if the expression is constant */ if (ED_IsConst (&D)) { Val = D.Val; } else { Error ("Constant expression expected"); Val = 0; } /* Free the expression tree and allocated memory for D */ FreeExpr (Expr); ED_Done (&D); /* Return the value */ return Val; } void FreeExpr (ExprNode* Root) /* Free the expression, Root is pointing to. */ { if (Root) { FreeExpr (Root->Left); FreeExpr (Root->Right); FreeExprNode (Root); } } ExprNode* SimplifyExpr (ExprNode* Expr, const ExprDesc* D) /* Try to simplify the given expression tree */ { if (Expr->Op != EXPR_LITERAL && ED_IsConst (D)) { /* No external references */ FreeExpr (Expr); Expr = GenLiteralExpr (D->Val); } return Expr; } ExprNode* GenLiteralExpr (long Val) /* Return an expression tree that encodes the given literal value */ { ExprNode* Expr = NewExprNode (EXPR_LITERAL); Expr->V.IVal = Val; return Expr; } ExprNode* GenLiteral0 (void) /* Return an expression tree that encodes the the number zero */ { return GenLiteralExpr (0); } ExprNode* GenSymExpr (SymEntry* Sym) /* Return an expression node that encodes the given symbol */ { ExprNode* Expr = NewExprNode (EXPR_SYMBOL); Expr->V.Sym = Sym; SymAddExprRef (Sym, Expr); return Expr; } static ExprNode* GenSectionExpr (unsigned SecNum) /* Return an expression node for the given section */ { ExprNode* Expr = NewExprNode (EXPR_SECTION); Expr->V.SecNum = SecNum; return Expr; } static ExprNode* GenBankExpr (unsigned SecNum) /* Return an expression node for the given bank */ { ExprNode* Expr = NewExprNode (EXPR_BANK); Expr->V.SecNum = SecNum; return Expr; } ExprNode* GenAddExpr (ExprNode* Left, ExprNode* Right) /* Generate an addition from the two operands */ { long Val; if (IsEasyConst (Left, &Val) && Val == 0) { FreeExpr (Left); return Right; } else if (IsEasyConst (Right, &Val) && Val == 0) { FreeExpr (Right); return Left; } else { ExprNode* Root = NewExprNode (EXPR_PLUS); Root->Left = Left; Root->Right = Right; return Root; } } ExprNode* GenCurrentPC (void) /* Return the current program counter as expression */ { ExprNode* Root; if (GetRelocMode ()) { /* Create SegmentBase + Offset */ Root = GenAddExpr (GenSectionExpr (GetCurrentSegNum ()), GenLiteralExpr (GetPC ())); } else { /* Absolute mode, just return PC value */ Root = GenLiteralExpr (GetPC ()); } return Root; } ExprNode* GenSwapExpr (ExprNode* Expr) /* Return an extended expression with lo and hi bytes swapped */ { ExprNode* N = NewExprNode (EXPR_SWAP); N->Left = Expr; return N; } ExprNode* GenBranchExpr (unsigned Offs) /* Return an expression that encodes the difference between current PC plus ** offset and the target expression (that is, Expression() - (*+Offs) ). */ { ExprNode* N; ExprNode* Root; long Val; /* Read Expression() */ N = Expression (); /* If the expression is a cheap constant, generate a simpler tree */ if (IsEasyConst (N, &Val)) { /* Free the constant expression tree */ FreeExpr (N); /* Generate the final expression: ** Val - (* + Offs) ** Val - ((Seg + PC) + Offs) ** Val - Seg - PC - Offs ** (Val - PC - Offs) - Seg */ Root = GenLiteralExpr (Val - GetPC () - Offs); if (GetRelocMode ()) { N = Root; Root = NewExprNode (EXPR_MINUS); Root->Left = N; Root->Right = GenSectionExpr (GetCurrentSegNum ()); } } else { /* Generate the expression: ** N - (* + Offs) ** N - ((Seg + PC) + Offs) ** N - Seg - PC - Offs ** N - (PC + Offs) - Seg */ Root = NewExprNode (EXPR_MINUS); Root->Left = N; Root->Right = GenLiteralExpr (GetPC () + Offs); if (GetRelocMode ()) { N = Root; Root = NewExprNode (EXPR_MINUS); Root->Left = N; Root->Right = GenSectionExpr (GetCurrentSegNum ()); } } /* Return the result */ return Root; } ExprNode* GenULabelExpr (unsigned Num) /* Return an expression for an unnamed label with the given index */ { ExprNode* Node = NewExprNode (EXPR_ULABEL); Node->V.IVal = Num; /* Return the new node */ return Node; } ExprNode* GenByteExpr (ExprNode* Expr) /* Force the given expression into a byte and return the result */ { /* Use the low byte operator to force the expression into byte size */ return LoByte (Expr); } ExprNode* GenWordExpr (ExprNode* Expr) /* Force the given expression into a word and return the result. */ { /* Use the low byte operator to force the expression into word size */ return LoWord (Expr); } ExprNode* GenNearAddrExpr (ExprNode* Expr) /* A word sized expression that will error if given a far expression at assemble time. */ { long Val; /* Special handling for const expressions */ if (IsEasyConst (Expr, &Val)) { FreeExpr (Expr); Expr = GenLiteralExpr (Val & 0xFFFF); if (Val > 0xFFFF) { Error("Range error: constant too large for assumed near address."); } } else { ExprNode* Operand = Expr; Expr = NewExprNode (EXPR_NEARADDR); Expr->Left = Operand; } return Expr; } ExprNode* GenFarAddrExpr (ExprNode* Expr) /* Force the given expression into a far address and return the result. */ { long Val; /* Special handling for const expressions */ if (IsEasyConst (Expr, &Val)) { FreeExpr (Expr); Expr = GenLiteralExpr (Val & 0xFFFFFF); } else { ExprNode* Operand = Expr; Expr = NewExprNode (EXPR_FARADDR); Expr->Left = Operand; } return Expr; } ExprNode* GenDWordExpr (ExprNode* Expr) /* Force the given expression into a dword and return the result. */ { long Val; /* Special handling for const expressions */ if (IsEasyConst (Expr, &Val)) { FreeExpr (Expr); Expr = GenLiteralExpr (Val & 0xFFFFFFFF); } else { ExprNode* Operand = Expr; Expr = NewExprNode (EXPR_DWORD); Expr->Left = Operand; } return Expr; } ExprNode* GenNE (ExprNode* Expr, long Val) /* Generate an expression that compares Expr and Val for inequality */ { /* Generate a compare node */ ExprNode* Root = NewExprNode (EXPR_NE); Root->Left = Expr; Root->Right = GenLiteralExpr (Val); /* Return the result */ return Root; } int IsConstExpr (ExprNode* Expr, long* Val) /* Return true if the given expression is a constant expression, that is, one ** with no references to external symbols. If Val is not NULL and the ** expression is constant, the constant value is stored here. */ { int IsConst; /* Study the expression */ ExprDesc D; ED_Init (&D); StudyExpr (Expr, &D); /* Check if the expression is constant */ IsConst = ED_IsConst (&D); if (IsConst && Val != 0) { *Val = D.Val; } /* Delete allocated memory and return the result */ ED_Done (&D); return IsConst; } ExprNode* CloneExpr (ExprNode* Expr) /* Clone the given expression tree. The function will simply clone symbol ** nodes, it will not resolve them. */ { ExprNode* Clone; /* Accept NULL pointers */ if (Expr == 0) { return 0; } /* Clone the node */ switch (Expr->Op) { case EXPR_LITERAL: Clone = GenLiteralExpr (Expr->V.IVal); break; case EXPR_ULABEL: Clone = GenULabelExpr (Expr->V.IVal); break; case EXPR_SYMBOL: Clone = GenSymExpr (Expr->V.Sym); break; case EXPR_SECTION: Clone = GenSectionExpr (Expr->V.SecNum); break; case EXPR_BANK: Clone = GenBankExpr (Expr->V.SecNum); break; default: /* Generate a new node */ Clone = NewExprNode (Expr->Op); /* Clone the tree nodes */ Clone->Left = CloneExpr (Expr->Left); Clone->Right = CloneExpr (Expr->Right); break; } /* Done */ return Clone; } void WriteExpr (ExprNode* Expr) /* Write the given expression to the object file */ { /* Null expressions are encoded by a type byte of zero */ if (Expr == 0) { ObjWrite8 (EXPR_NULL); return; } /* If the is a leafnode, write the expression attribute, otherwise ** write the expression operands. */ switch (Expr->Op) { case EXPR_LITERAL: ObjWrite8 (EXPR_LITERAL); ObjWrite32 (Expr->V.IVal); break; case EXPR_SYMBOL: if (SymIsImport (Expr->V.Sym)) { ObjWrite8 (EXPR_SYMBOL); ObjWriteVar (GetSymImportId (Expr->V.Sym)); } else { WriteExpr (GetSymExpr (Expr->V.Sym)); } break; case EXPR_SECTION: ObjWrite8 (EXPR_SECTION); ObjWriteVar (Expr->V.SecNum); break; case EXPR_ULABEL: WriteExpr (ULabResolve (Expr->V.IVal)); break; default: /* Not a leaf node */ ObjWrite8 (Expr->Op); WriteExpr (Expr->Left); WriteExpr (Expr->Right); break; } } void ExprGuessedAddrSize (const ExprNode* Expr, unsigned char AddrSize) /* Mark the address size of the given expression tree as guessed. The address ** size passed as argument is the one NOT used, because the actual address ** size wasn't known. Example: Zero page addressing was not used because symbol ** is undefined, and absolute addressing was available. ** This function will actually parse the expression tree for undefined symbols, ** and mark these symbols accordingly. */ { /* Accept NULL expressions */ if (Expr == 0) { return; } /* Check the type code */ switch (EXPR_NODETYPE (Expr->Op)) { case EXPR_LEAFNODE: if (Expr->Op == EXPR_SYMBOL) { if (!SymIsDef (Expr->V.Sym)) { /* Symbol is undefined, mark it */ SymGuessedAddrSize (Expr->V.Sym, AddrSize); } } return; case EXPR_BINARYNODE: ExprGuessedAddrSize (Expr->Right, AddrSize); /* FALLTHROUGH */ case EXPR_UNARYNODE: ExprGuessedAddrSize (Expr->Left, AddrSize); break; } } ExprNode* MakeBoundedExpr (ExprNode* Expr, unsigned Size) /* Force the given expression into a specific size of ForceRange is true */ { if (ForceRange) { switch (Size) { case 1: Expr = GenByteExpr (Expr); break; case 2: Expr = GenWordExpr (Expr); break; case 3: Expr = GenFarAddrExpr (Expr); break; case 4: Expr = GenDWordExpr (Expr); break; default: Internal ("Invalid size in BoundedExpr: %u", Size); } } return Expr; } ExprNode* BoundedExpr (ExprNode* (*ExprFunc) (void), unsigned Size) /* Parse an expression and force it within a given size if ForceRange is true */ { return MakeBoundedExpr (ExprFunc (), Size); } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/expr.h���������������������������������������������������������������������������0000664�0000000�0000000�00000016341�13473601511�0014666�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* expr.h */ /* */ /* Expression evaluation for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef EXPR_H #define EXPR_H /* common */ #include "coll.h" #include "exprdefs.h" /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ struct ExprDesc; /*****************************************************************************/ /* Code */ /*****************************************************************************/ ExprNode* Expression (void); /* Evaluate an expression, build the expression tree on the heap and return ** a pointer to the root of the tree. */ long ConstExpression (void); /* Parse an expression. Check if the expression is const, and print an error ** message if not. Return the value of the expression, or a dummy, if it is ** not constant. */ void FreeExpr (ExprNode* Root); /* Free the expression tree, Root is pointing to. */ ExprNode* SimplifyExpr (ExprNode* Expr, const struct ExprDesc* D); /* Try to simplify the given expression tree */ ExprNode* GenLiteralExpr (long Val); /* Return an expression tree that encodes the given literal value */ ExprNode* GenLiteral0 (void); /* Return an expression tree that encodes the the number zero */ ExprNode* GenSymExpr (struct SymEntry* Sym); /* Return an expression node that encodes the given symbol */ ExprNode* GenAddExpr (ExprNode* Left, ExprNode* Right); /* Generate an addition from the two operands */ ExprNode* GenCurrentPC (void); /* Return the current program counter as expression */ ExprNode* GenSwapExpr (ExprNode* Expr); /* Return an extended expression with lo and hi bytes swapped */ ExprNode* GenBranchExpr (unsigned Offs); /* Return an expression that encodes the difference between current PC plus ** offset and the target expression (that is, Expression() - (*+Offs) ). */ ExprNode* GenULabelExpr (unsigned Num); /* Return an expression for an unnamed label with the given index */ ExprNode* GenByteExpr (ExprNode* Expr); /* Force the given expression into a byte and return the result */ ExprNode* GenWordExpr (ExprNode* Expr); /* Force the given expression into a word and return the result. */ ExprNode* GenNearAddrExpr (ExprNode* Expr); /* A word sized expression that will error if given a far expression at assemble time. */ ExprNode* GenFarAddrExpr (ExprNode* Expr); /* Force the given expression into a far address and return the result. */ ExprNode* GenDWordExpr (ExprNode* Expr); /* Force the given expression into a dword and return the result. */ ExprNode* GenNE (ExprNode* Expr, long Val); /* Generate an expression that compares Expr and Val for inequality */ int IsConstExpr (ExprNode* Expr, long* Val); /* Return true if the given expression is a constant expression, that is, one ** with no references to external symbols. If Val is not NULL and the ** expression is constant, the constant value is stored here. */ int IsByteExpr (ExprNode* Root); /* Return true if this is a byte expression */ int IsByteRange (long Val); /* Return true if this is a byte value */ int IsWordRange (long Val); /* Return true if this is a word value */ int IsFarRange (long Val); /* Return true if this is a far (24 bit) value */ int IsEasyConst (const ExprNode* E, long* Val); /* Do some light checking if the given node is a constant. Don't care if E is ** a complex expression. If E is a constant, return true and place its value ** into Val, provided that Val is not NULL. */ ExprNode* CloneExpr (ExprNode* Expr); /* Clone the given expression tree. The function will simply clone symbol ** nodes, it will not resolve them. */ void WriteExpr (ExprNode* Expr); /* Write the given expression to the object file */ void ExprGuessedAddrSize (const ExprNode* Expr, unsigned char AddrSize); /* Mark the address size of the given expression tree as guessed. The address ** size passed as argument is the one NOT used, because the actual address ** size wasn't known. Example: Zero page addressing was not used because symbol ** is undefined, and absolute addressing was available. ** This function will actually parse the expression tree for undefined symbols, ** and mark these symbols accordingly. */ ExprNode* FuncBankByte (void); /* Handle the .BANKBYTE builtin function */ ExprNode* FuncLoByte (void); /* Handle the .LOBYTE builtin function */ ExprNode* FuncHiByte (void); /* Handle the .HIBYTE builtin function */ ExprNode* MakeBoundedExpr (ExprNode* Expr, unsigned Size); /* Force the given expression into a specific size of ForceRange is true */ ExprNode* BoundedExpr (ExprNode* (*ExprFunc) (void), unsigned Size); /* Parse an expression and force it within a given size if ForceRange is true */ /* End of expr.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/feature.c������������������������������������������������������������������������0000664�0000000�0000000�00000013452�13473601511�0015336�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* feature.c */ /* */ /* Subroutines for the emulation features */ /* */ /* */ /* */ /* (C) 2000-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* ca65 */ #include "global.h" #include "feature.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Names of the features */ static const char* const FeatureKeys[FEAT_COUNT] = { "dollar_is_pc", "labels_without_colons", "loose_string_term", "loose_char_term", "at_in_identifiers", "dollar_in_identifiers", "leading_dot_in_identifiers", "org_per_seg", "pc_assignment", "missing_char_term", "ubiquitous_idents", "c_comments", "force_range", "underline_in_numbers", "addrsize", "bracket_as_indirect", "string_escapes", }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ feature_t FindFeature (const StrBuf* Key) /* Find the feature in a table and return the corresponding enum value. If the ** feature is invalid, return FEAT_UNKNOWN. */ { feature_t F; /* This is not time critical, so do a linear search */ for (F = (feature_t) 0; F < FEAT_COUNT; ++F) { if (SB_CompareStr (Key, FeatureKeys[F]) == 0) { /* Found, index is enum value */ return F; } } /* Not found */ return FEAT_UNKNOWN; } feature_t SetFeature (const StrBuf* Key) /* Find the feature and set the corresponding flag if the feature is known. ** In any case, return the feature found. An invalid Key will return ** FEAT_UNKNOWN. */ { /* Map the string to an enum value */ feature_t Feature = FindFeature (Key); /* Set the flags */ switch (Feature) { case FEAT_DOLLAR_IS_PC: DollarIsPC = 1; break; case FEAT_LABELS_WITHOUT_COLONS: NoColonLabels = 1; break; case FEAT_LOOSE_STRING_TERM: LooseStringTerm = 1; break; case FEAT_LOOSE_CHAR_TERM: LooseCharTerm = 1; break; case FEAT_AT_IN_IDENTIFIERS: AtInIdents = 1; break; case FEAT_DOLLAR_IN_IDENTIFIERS: DollarInIdents = 1; break; case FEAT_LEADING_DOT_IN_IDENTIFIERS: LeadingDotInIdents= 1; break; case FEAT_ORG_PER_SEG: OrgPerSeg = 1; break; case FEAT_PC_ASSIGNMENT: PCAssignment = 1; break; case FEAT_MISSING_CHAR_TERM: MissingCharTerm = 1; break; case FEAT_UBIQUITOUS_IDENTS: UbiquitousIdents = 1; break; case FEAT_C_COMMENTS: CComments = 1; break; case FEAT_FORCE_RANGE: ForceRange = 1; break; case FEAT_UNDERLINE_IN_NUMBERS: UnderlineInNumbers= 1; break; case FEAT_ADDRSIZE: AddrSize = 1; break; case FEAT_BRACKET_AS_INDIRECT: BracketAsIndirect = 1; break; case FEAT_STRING_ESCAPES: StringEscapes = 1; break; default: /* Keep gcc silent */ break; } /* Return the value found */ return Feature; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/feature.h������������������������������������������������������������������������0000664�0000000�0000000�00000010042�13473601511�0015333�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* feature.h */ /* */ /* Subroutines for the emulation features */ /* */ /* */ /* */ /* (C) 2000-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef FEATURE_H #define FEATURE_H /* common */ #include "strbuf.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ typedef enum { FEAT_UNKNOWN = -1, FEAT_DOLLAR_IS_PC, FEAT_LABELS_WITHOUT_COLONS, FEAT_LOOSE_STRING_TERM, FEAT_LOOSE_CHAR_TERM, FEAT_AT_IN_IDENTIFIERS, FEAT_DOLLAR_IN_IDENTIFIERS, FEAT_LEADING_DOT_IN_IDENTIFIERS, FEAT_ORG_PER_SEG, FEAT_PC_ASSIGNMENT, FEAT_MISSING_CHAR_TERM, FEAT_UBIQUITOUS_IDENTS, FEAT_C_COMMENTS, FEAT_FORCE_RANGE, FEAT_UNDERLINE_IN_NUMBERS, FEAT_ADDRSIZE, FEAT_BRACKET_AS_INDIRECT, FEAT_STRING_ESCAPES, /* Special value: Number of features available */ FEAT_COUNT } feature_t; /*****************************************************************************/ /* Code */ /*****************************************************************************/ feature_t FindFeature (const StrBuf* Key); /* Find the feature in a table and return the corresponding enum value. If the ** feature is invalid, return FEAT_UNKNOWN. */ feature_t SetFeature (const StrBuf* Key); /* Find the feature and set the corresponding flag if the feature is known. ** In any case, return the feature found. An invalid Key will return ** FEAT_UNKNOWN. */ /* End of feature.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/filetab.c������������������������������������������������������������������������0000664�0000000�0000000�00000025570�13473601511�0015315�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* filetab.h */ /* */ /* Input file table for ca65 */ /* */ /* */ /* */ /* (C) 2000-2008 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> #include <errno.h> /* common */ #include "check.h" #include "coll.h" #include "hashtab.h" #include "xmalloc.h" /* ca65 */ #include "error.h" #include "filetab.h" #include "global.h" #include "objfile.h" #include "spool.h" /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ static unsigned HT_GenHash (const void* Key); /* Generate the hash over a key. */ static const void* HT_GetKey (const void* Entry); /* Given a pointer to the user entry data, return a pointer to the key. */ static int HT_Compare (const void* Key1, const void* Key2); /* Compare two keys. The function must return a value less than zero if ** Key1 is smaller than Key2, zero if both are equal, and a value greater ** than zero if Key1 is greater then Key2. */ /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Number of entries in the table and the mask to generate the hash */ #define HASHTAB_MASK 0x1F #define HASHTAB_COUNT (HASHTAB_MASK + 1) /* An entry in the file table */ typedef struct FileEntry FileEntry; struct FileEntry { HashNode Node; unsigned Name; /* File name */ unsigned Index; /* Index of entry */ FileType Type; /* Type of file */ unsigned long Size; /* Size of file */ unsigned long MTime; /* Time of last modification */ }; /* Array of all entries, listed by index */ static Collection FileTab = STATIC_COLLECTION_INITIALIZER; /* Hash table functions */ static const HashFunctions HashFunc = { HT_GenHash, HT_GetKey, HT_Compare }; /* Hash table, hashed by name */ static HashTable HashTab = STATIC_HASHTABLE_INITIALIZER (HASHTAB_COUNT, &HashFunc); /*****************************************************************************/ /* Hash table functions */ /*****************************************************************************/ static unsigned HT_GenHash (const void* Key) /* Generate the hash over a key. */ { return (*(const unsigned*)Key & HASHTAB_MASK); } static const void* HT_GetKey (const void* Entry) /* Given a pointer to the user entry data, return a pointer to the index */ { return &((FileEntry*) Entry)->Name; } static int HT_Compare (const void* Key1, const void* Key2) /* Compare two keys. The function must return a value less than zero if ** Key1 is smaller than Key2, zero if both are equal, and a value greater ** than zero if Key1 is greater then Key2. */ { return (int)*(const unsigned*)Key1 - (int)*(const unsigned*)Key2; } /*****************************************************************************/ /* Code */ /*****************************************************************************/ static FileEntry* NewFileEntry (unsigned Name, FileType Type, unsigned long Size, unsigned long MTime) /* Create a new FileEntry, insert it into the tables and return it */ { /* Allocate memory for the entry */ FileEntry* F = xmalloc (sizeof (FileEntry)); /* Initialize the fields */ InitHashNode (&F->Node); F->Name = Name; F->Index = CollCount (&FileTab) + 1; /* First file has index #1 */ F->Type = Type; F->Size = Size; F->MTime = MTime; /* Insert the file into the file table */ CollAppend (&FileTab, F); /* Insert the entry into the hash table */ HT_Insert (&HashTab, F); /* Return the new entry */ return F; } const StrBuf* GetFileName (unsigned Name) /* Get the name of a file where the name index is known */ { static const StrBuf ErrorMsg = LIT_STRBUF_INITIALIZER ("(outside file scope)"); const FileEntry* F; if (Name == 0) { /* Name was defined outside any file scope, use the name of the first ** file instead. Errors are then reported with a file position of ** line zero in the first file. */ if (CollCount (&FileTab) == 0) { /* No files defined until now */ return &ErrorMsg; } else { F = CollConstAt (&FileTab, 0); } } else { F = CollConstAt (&FileTab, Name-1); } return GetStrBuf (F->Name); } unsigned GetFileIndex (const StrBuf* Name) /* Return the file index for the given file name. */ { /* Get the string pool index from the name */ unsigned NameIdx = GetStrBufId (Name); /* Search in the hash table for the name */ const FileEntry* F = HT_Find (&HashTab, &NameIdx); /* If we don't have this index, print a diagnostic and use the main file */ if (F == 0) { Error ("File name '%m%p' not found in file table", Name); return 0; } else { return F->Index; } } unsigned AddFile (const StrBuf* Name, FileType Type, unsigned long Size, unsigned long MTime) /* Add a new file to the list of input files. Return the index of the file in ** the table. */ { /* Create a new file entry and insert it into the tables */ FileEntry* F = NewFileEntry (GetStrBufId (Name), Type, Size, MTime); /* Return the index */ return F->Index; } void WriteFiles (void) /* Write the list of input files to the object file */ { unsigned I; /* Tell the obj file module that we're about to start the file list */ ObjStartFiles (); /* Write the file count */ ObjWriteVar (CollCount (&FileTab)); /* Write the file data */ for (I = 0; I < CollCount (&FileTab); ++I) { /* Get a pointer to the entry */ const FileEntry* F = CollConstAt (&FileTab, I); /* Write the fields */ ObjWriteVar (F->Name); ObjWrite32 (F->MTime); ObjWriteVar (F->Size); } /* Done writing files */ ObjEndFiles (); } 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 */ { unsigned I; /* Loop over all files */ for (I = 0; I < CollCount (&FileTab); ++I) { const StrBuf* Filename; /* Get the next input file */ const FileEntry* E = (const FileEntry*) CollAt (&FileTab, I); /* Ignore it if it is not of the correct type */ if ((E->Type & Types) == 0) { continue; } /* If this is not the first file, add a space */ if (I > 0) { fputc (' ', F); } /* Print the dependency escaping spaces */ Filename = GetStrBuf (E->Name); WriteEscaped (F, SB_GetConstBuf (Filename)); } } static void CreateDepFile (const char* Name, FileType Types) /* Create a dependency file with the given name and place dependencies for ** all files with the given types there. */ { /* Open the file */ FILE* F = fopen (Name, "w"); if (F == 0) { Fatal ("Cannot open dependency file '%s': %s", Name, strerror (errno)); } /* Print the output file followed by a tab char */ WriteEscaped (F, OutFile); fputs (":\t", F); /* Write out the dependencies for the output file */ WriteDep (F, Types); fputs ("\n\n", F); /* Write out a phony dependency for the included files */ WriteDep (F, Types); fputs (":\n\n", F); /* Close the file, check for errors */ if (fclose (F) != 0) { remove (Name); Fatal ("Cannot write to dependeny file (disk full?)"); } } void CreateDependencies (void) /* Create dependency files requested by the user */ { if (SB_NotEmpty (&DepName)) { CreateDepFile (SB_GetConstBuf (&DepName), FT_MAIN | FT_INCLUDE | FT_BINARY); } if (SB_NotEmpty (&FullDepName)) { CreateDepFile (SB_GetConstBuf (&FullDepName), FT_MAIN | FT_INCLUDE | FT_BINARY | FT_DBGINFO); } } ����������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/filetab.h������������������������������������������������������������������������0000664�0000000�0000000�00000010041�13473601511�0015305�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* filetab.h */ /* */ /* Input file table for ca65 */ /* */ /* */ /* */ /* (C) 2000-2008 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef FILETAB_H #define FILETAB_H /* common */ #include "strbuf.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* An enum that describes different types of input files. The members are ** choosen so that it is possible to combine them to bitsets */ typedef enum { FT_MAIN = 0x01, /* Main input file */ FT_INCLUDE = 0x02, /* Normal include file */ FT_BINARY = 0x04, /* Binary include file */ FT_DBGINFO = 0x08, /* File from debug info */ } FileType; /*****************************************************************************/ /* Code */ /*****************************************************************************/ const StrBuf* GetFileName (unsigned Name); /* Get the name of a file where the name index is known */ unsigned GetFileIndex (const StrBuf* Name); /* Return the file index for the given file name. */ unsigned AddFile (const StrBuf* Name, FileType Type, unsigned long Size, unsigned long MTime); /* Add a new file to the list of input files. Return the index of the file in ** the table. */ void WriteFiles (void); /* Write the list of input files to the object file */ void CreateDependencies (void); /* Create dependency files requested by the user */ /* End of filetab.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/fragment.c�����������������������������������������������������������������������0000664�0000000�0000000�00000006422�13473601511�0015505�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* fragment.c */ /* */ /* Data fragments for the ca65 crossassembler */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "xmalloc.h" /* ca65 */ #include "fragment.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ Fragment* NewFragment (unsigned char Type, unsigned short Len) /* Create, initialize and return a new fragment. The fragment will be inserted ** into the current segment. */ { /* Create a new fragment */ Fragment* F = xmalloc (sizeof (*F)); /* Initialize it */ F->Next = 0; F->LineList = 0; F->LI = EmptyCollection; GetFullLineInfo (&F->LI); F->Len = Len; F->Type = Type; /* And return it */ return F; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/fragment.h�����������������������������������������������������������������������0000664�0000000�0000000�00000007577�13473601511�0015526�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* fragment.h */ /* */ /* Data fragments for the ca65 crossassembler */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef FRAGMENT_H #define FRAGMENT_H /* common */ #include "exprdefs.h" #include "coll.h" /* ca65 */ #include "lineinfo.h" /*****************************************************************************/ /* struct Fragment */ /*****************************************************************************/ typedef struct Fragment Fragment; struct Fragment { Fragment* Next; /* Pointer to next fragment in segment */ Fragment* LineList; /* List of fragments for one src line */ Collection LI; /* Line info for this fragment */ unsigned short Len; /* Length for this fragment */ unsigned char Type; /* Fragment type */ union { unsigned char Data[sizeof (ExprNode*)]; /* Literal values */ ExprNode* Expr; /* Expression */ } V; }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ Fragment* NewFragment (unsigned char Type, unsigned short Len); /* Create, initialize and return a new fragment. The fragment will be inserted ** into the current segment. */ /* End of fragment.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/global.c�������������������������������������������������������������������������0000664�0000000�0000000�00000012144�13473601511�0015140�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* global.c */ /* */ /* Global variables for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 1998-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "addrsize.h" /* ca65 */ #include "global.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* File names */ const char* InFile = 0; /* Name of input file */ const char* OutFile = 0; /* Name of output file */ StrBuf ListingName = STATIC_STRBUF_INITIALIZER; /* Name of listing file */ StrBuf DepName = STATIC_STRBUF_INITIALIZER; /* Dependency file */ StrBuf FullDepName = STATIC_STRBUF_INITIALIZER; /* Full dependency file */ /* Default extensions */ const char ObjExt[] = ".o";/* Default object extension */ char LocalStart = '@'; /* This char starts local symbols */ unsigned char IgnoreCase = 0; /* Ignore case on identifiers? */ unsigned char AutoImport = 0; /* Mark unresolveds as import */ unsigned char SmartMode = 0; /* Smart mode */ unsigned char DbgSyms = 0; /* Add debug symbols */ unsigned char LineCont = 0; /* Allow line continuation */ unsigned char LargeAlignment = 0; /* Don't warn about large alignments */ unsigned char RelaxChecks = 0; /* Relax a few assembler checks */ unsigned char StringEscapes = 0; /* Allow C-style escapes in strings */ /* Emulation features */ unsigned char DollarIsPC = 0; /* Allow the $ symbol as current PC */ unsigned char NoColonLabels = 0; /* Allow labels without a colon */ unsigned char LooseStringTerm = 0; /* Allow ' as string terminator */ unsigned char LooseCharTerm = 0; /* Allow " for char constants */ unsigned char AtInIdents = 0; /* Allow '@' in identifiers */ unsigned char DollarInIdents = 0; /* Allow '$' in identifiers */ unsigned char LeadingDotInIdents = 0; /* Allow '.' to start an identifier */ unsigned char PCAssignment = 0; /* Allow "* = $XXX" or "$ = $XXX" */ unsigned char MissingCharTerm = 0; /* Allow lda #'a (no closing term) */ unsigned char UbiquitousIdents = 0; /* Allow ubiquitous identifiers */ 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 */ unsigned char BracketAsIndirect = 0; /* Use '[]' not '()' for indirection */ ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/global.h�������������������������������������������������������������������������0000664�0000000�0000000�00000012401�13473601511�0015141�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* global.h */ /* */ /* Global variables for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 1998-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef GLOBAL_H #define GLOBAL_H /* common */ #include "strbuf.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* File names */ extern const char* InFile; /* Name of input file */ extern const char* OutFile; /* Name of output file */ extern StrBuf ListingName; /* Name of listing file */ extern StrBuf DepName; /* Name of dependencies file */ extern StrBuf FullDepName; /* Name of full dependencies file */ /* Default extensions */ extern const char ObjExt[]; /* Default object extension */ extern char LocalStart; /* This char starts local symbols */ extern unsigned char IgnoreCase; /* Ignore case on identifiers? */ extern unsigned char AutoImport; /* Mark unresolveds as import */ extern unsigned char SmartMode; /* Smart mode */ extern unsigned char DbgSyms; /* Add debug symbols */ extern unsigned char LineCont; /* Allow line continuation */ extern unsigned char LargeAlignment; /* Don't warn about large alignments */ extern unsigned char RelaxChecks; /* Relax a few assembler checks */ extern unsigned char StringEscapes; /* Allow C-style escapes in strings */ /* Emulation features */ extern unsigned char DollarIsPC; /* Allow the $ symbol as current PC */ extern unsigned char NoColonLabels; /* Allow labels without a colon */ extern unsigned char LooseStringTerm; /* Allow ' as string terminator */ extern unsigned char LooseCharTerm; /* Allow " for char constants */ extern unsigned char AtInIdents; /* Allow '@' in identifiers */ extern unsigned char DollarInIdents; /* Allow '$' in identifiers */ extern unsigned char LeadingDotInIdents; /* Allow '.' to start an identifier */ extern unsigned char PCAssignment; /* Allow "* = $XXX" or "$ = $XXX" */ extern unsigned char MissingCharTerm; /* Allow lda #'a (no closing term) */ extern unsigned char UbiquitousIdents; /* Allow ubiquitous identifiers */ 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 */ extern unsigned char BracketAsIndirect; /* Use '[]' not '()' for indirection */ /* End of global.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/incpath.c������������������������������������������������������������������������0000664�0000000�0000000�00000007741�13473601511�0015335�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* incpath.c */ /* */ /* Include path handling for the ca65 macro assembler */ /* */ /* */ /* */ /* (C) 2000-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* ca65 */ #include "incpath.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ SearchPaths* IncSearchPath; /* Standard include path */ SearchPaths* BinSearchPath; /* Binary include path */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ void InitIncludePaths (void) /* Initialize the include path search list */ { /* Create the search path lists */ IncSearchPath = NewSearchPath (); BinSearchPath = NewSearchPath (); } void FinishIncludePaths (void) /* Finish creating the include path search list. */ { /* Add specific paths from the environment */ AddSearchPathFromEnv (IncSearchPath, "CA65_INC"); /* Add paths relative to a main directory defined in an env. var. */ AddSubSearchPathFromEnv (IncSearchPath, "CC65_HOME", "asminc"); /* Add some compiled-in search paths if defined at compile time. */ #if defined(CA65_INC) && !defined(_WIN32) AddSearchPath (IncSearchPath, STRINGIZE (CA65_INC)); #endif /* Add paths relative to the parent directory of the Windows binary. */ AddSubSearchPathFromWinBin (IncSearchPath, "asminc"); } �������������������������������cc65-2.18/src/ca65/incpath.h������������������������������������������������������������������������0000664�0000000�0000000�00000006624�13473601511�0015341�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* incpath.h */ /* */ /* Include path handling for the ca65 macro assembler */ /* */ /* */ /* */ /* (C) 2000-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef INCPATH_H #define INCPATH_H /* common */ #include "searchpath.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ extern SearchPaths* IncSearchPath; /* Standard include path */ extern SearchPaths* BinSearchPath; /* Binary include path */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ void InitIncludePaths (void); /* Initialize the include path search list */ void FinishIncludePaths (void); /* Finish creating the include path search list. */ /* End of incpath.h */ #endif ������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/instr.c��������������������������������������������������������������������������0000664�0000000�0000000�00000202504�13473601511�0015040�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* instr.c */ /* */ /* Instruction encoding for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdlib.h> #include <string.h> #include <ctype.h> /* common */ #include "addrsize.h" #include "attrib.h" #include "bitops.h" #include "check.h" #include "mmodel.h" /* ca65 */ #include "asserts.h" #include "ea.h" #include "ea65.h" #include "easw16.h" #include "error.h" #include "expr.h" #include "global.h" #include "instr.h" #include "nexttok.h" #include "objcode.h" #include "spool.h" #include "studyexpr.h" #include "symtab.h" /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ static void PutPCRel8 (const InsDesc* Ins); /* Handle branches with a 8 bit distance */ static void PutPCRel16 (const InsDesc* Ins); /* Handle branches with an 16 bit distance and PER */ static void PutPCRel4510 (const InsDesc* Ins); /* Handle branches with a 16 bit distance for 4510 */ static void PutBlockMove (const InsDesc* Ins); /* Handle the blockmove instructions (65816) */ static void PutBlockTransfer (const InsDesc* Ins); /* Handle the block transfer instructions (HuC6280) */ static void PutBitBranch (const InsDesc* Ins); /* Handle 65C02 branch on bit condition */ static void PutREP (const InsDesc* Ins); /* Emit a REP instruction, track register sizes */ static void PutSEP (const InsDesc* Ins); /* Emit a SEP instruction (65816), track register sizes */ static void PutTAMn (const InsDesc* Ins); /* Emit a TAMn instruction (HuC6280). Since this is a two byte instruction with ** implicit addressing mode, the opcode byte in the table is actually the ** second operand byte. The TAM instruction is the more generic form, it takes ** an immediate argument. */ static void PutTMA (const InsDesc* Ins); /* Emit a TMA instruction (HuC6280) with an immediate argument. Only one bit ** in the argument byte may be set. */ static void PutTMAn (const InsDesc* Ins); /* Emit a TMAn instruction (HuC6280). Since this is a two byte instruction with ** implicit addressing mode, the opcode byte in the table is actually the ** second operand byte. The TAM instruction is the more generic form, it takes ** an immediate argument. */ static void PutTST (const InsDesc* Ins); /* Emit a TST instruction (HuC6280). */ static void PutJMP (const InsDesc* Ins); /* Handle the jump instruction for the 6502. Problem is that these chips have ** a bug: If the address crosses a page, the upper byte gets not corrected and ** the instruction will fail. The PutJmp function will add a linker assertion ** to check for this case and is otherwise identical to PutAll. */ static void PutRTS (const InsDesc* Ins attribute ((unused))); /* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if ** the enclosing scope is FAR. */ static void PutAll (const InsDesc* Ins); /* Handle all other instructions */ static void Put4510 (const InsDesc* Ins); /* Handle instructions of 4510 not matching any EATab */ static void PutSweet16 (const InsDesc* Ins); /* Handle a generic sweet16 instruction */ static void PutSweet16Branch (const InsDesc* Ins); /* Handle a sweet16 branch instruction */ /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Empty instruction table */ static const struct { unsigned Count; } InsTabNone = { 0 }; /* Instruction table for the 6502 */ static const struct { unsigned Count; InsDesc Ins[56]; } InsTab6502 = { sizeof (InsTab6502.Ins) / sizeof (InsTab6502.Ins[0]), { { "ADC", 0x080A26C, 0x60, 0, PutAll }, { "AND", 0x080A26C, 0x20, 0, PutAll }, { "ASL", 0x000006e, 0x02, 1, PutAll }, { "BCC", 0x0020000, 0x90, 0, PutPCRel8 }, { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 }, { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 }, { "BIT", 0x000000C, 0x00, 2, PutAll }, { "BMI", 0x0020000, 0x30, 0, PutPCRel8 }, { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, { "BRK", 0x0000001, 0x00, 0, PutAll }, { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, { "CLC", 0x0000001, 0x18, 0, PutAll }, { "CLD", 0x0000001, 0xd8, 0, PutAll }, { "CLI", 0x0000001, 0x58, 0, PutAll }, { "CLV", 0x0000001, 0xb8, 0, PutAll }, { "CMP", 0x080A26C, 0xc0, 0, PutAll }, { "CPX", 0x080000C, 0xe0, 1, PutAll }, { "CPY", 0x080000C, 0xc0, 1, PutAll }, { "DEC", 0x000006C, 0x00, 3, PutAll }, { "DEX", 0x0000001, 0xca, 0, PutAll }, { "DEY", 0x0000001, 0x88, 0, PutAll }, { "EOR", 0x080A26C, 0x40, 0, PutAll }, { "INC", 0x000006c, 0x00, 4, PutAll }, { "INX", 0x0000001, 0xe8, 0, PutAll }, { "INY", 0x0000001, 0xc8, 0, PutAll }, { "JMP", 0x0000808, 0x4c, 6, PutJMP }, { "JSR", 0x0000008, 0x20, 7, PutAll }, { "LDA", 0x080A26C, 0xa0, 0, PutAll }, { "LDX", 0x080030C, 0xa2, 1, PutAll }, { "LDY", 0x080006C, 0xa0, 1, PutAll }, { "LSR", 0x000006F, 0x42, 1, PutAll }, { "NOP", 0x0000001, 0xea, 0, PutAll }, { "ORA", 0x080A26C, 0x00, 0, PutAll }, { "PHA", 0x0000001, 0x48, 0, PutAll }, { "PHP", 0x0000001, 0x08, 0, PutAll }, { "PLA", 0x0000001, 0x68, 0, PutAll }, { "PLP", 0x0000001, 0x28, 0, PutAll }, { "ROL", 0x000006F, 0x22, 1, PutAll }, { "ROR", 0x000006F, 0x62, 1, PutAll }, { "RTI", 0x0000001, 0x40, 0, PutAll }, { "RTS", 0x0000001, 0x60, 0, PutAll }, { "SBC", 0x080A26C, 0xe0, 0, PutAll }, { "SEC", 0x0000001, 0x38, 0, PutAll }, { "SED", 0x0000001, 0xf8, 0, PutAll }, { "SEI", 0x0000001, 0x78, 0, PutAll }, { "STA", 0x000A26C, 0x80, 0, PutAll }, { "STX", 0x000010c, 0x82, 1, PutAll }, { "STY", 0x000002c, 0x80, 1, PutAll }, { "TAX", 0x0000001, 0xaa, 0, PutAll }, { "TAY", 0x0000001, 0xa8, 0, PutAll }, { "TSX", 0x0000001, 0xba, 0, PutAll }, { "TXA", 0x0000001, 0x8a, 0, PutAll }, { "TXS", 0x0000001, 0x9a, 0, PutAll }, { "TYA", 0x0000001, 0x98, 0, PutAll } } }; /* Instruction table for the 6502 with illegal instructions */ static const struct { unsigned Count; InsDesc Ins[75]; } InsTab6502X = { sizeof (InsTab6502X.Ins) / sizeof (InsTab6502X.Ins[0]), { { "ADC", 0x080A26C, 0x60, 0, PutAll }, { "ALR", 0x0800000, 0x4B, 0, PutAll }, /* X */ { "ANC", 0x0800000, 0x0B, 0, PutAll }, /* X */ { "AND", 0x080A26C, 0x20, 0, PutAll }, { "ANE", 0x0800000, 0x8B, 0, PutAll }, /* X */ { "ARR", 0x0800000, 0x6B, 0, PutAll }, /* X */ { "ASL", 0x000006e, 0x02, 1, PutAll }, { "AXS", 0x0800000, 0xCB, 0, PutAll }, /* X */ { "BCC", 0x0020000, 0x90, 0, PutPCRel8 }, { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 }, { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 }, { "BIT", 0x000000C, 0x00, 2, PutAll }, { "BMI", 0x0020000, 0x30, 0, PutPCRel8 }, { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, { "BRK", 0x0000001, 0x00, 0, PutAll }, { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, { "CLC", 0x0000001, 0x18, 0, PutAll }, { "CLD", 0x0000001, 0xd8, 0, PutAll }, { "CLI", 0x0000001, 0x58, 0, PutAll }, { "CLV", 0x0000001, 0xb8, 0, PutAll }, { "CMP", 0x080A26C, 0xc0, 0, PutAll }, { "CPX", 0x080000C, 0xe0, 1, PutAll }, { "CPY", 0x080000C, 0xc0, 1, PutAll }, { "DCP", 0x000A26C, 0xC3, 0, PutAll }, /* X */ { "DEC", 0x000006C, 0x00, 3, PutAll }, { "DEX", 0x0000001, 0xca, 0, PutAll }, { "DEY", 0x0000001, 0x88, 0, PutAll }, { "EOR", 0x080A26C, 0x40, 0, PutAll }, { "INC", 0x000006c, 0x00, 4, PutAll }, { "INX", 0x0000001, 0xe8, 0, PutAll }, { "INY", 0x0000001, 0xc8, 0, PutAll }, { "ISC", 0x000A26C, 0xE3, 0, PutAll }, /* X */ { "JAM", 0x0000001, 0x02, 0, PutAll }, /* X */ { "JMP", 0x0000808, 0x4c, 6, PutJMP }, { "JSR", 0x0000008, 0x20, 7, PutAll }, { "LAS", 0x0000200, 0xBB, 0, PutAll }, /* X */ { "LAX", 0x080A30C, 0xA3, 11, PutAll }, /* X */ { "LDA", 0x080A26C, 0xa0, 0, PutAll }, { "LDX", 0x080030C, 0xa2, 1, PutAll }, { "LDY", 0x080006C, 0xa0, 1, PutAll }, { "LSR", 0x000006F, 0x42, 1, PutAll }, { "NOP", 0x080006D, 0x00, 10, PutAll }, /* X */ { "ORA", 0x080A26C, 0x00, 0, PutAll }, { "PHA", 0x0000001, 0x48, 0, PutAll }, { "PHP", 0x0000001, 0x08, 0, PutAll }, { "PLA", 0x0000001, 0x68, 0, PutAll }, { "PLP", 0x0000001, 0x28, 0, PutAll }, { "RLA", 0x000A26C, 0x23, 0, PutAll }, /* X */ { "ROL", 0x000006F, 0x22, 1, PutAll }, { "ROR", 0x000006F, 0x62, 1, PutAll }, { "RRA", 0x000A26C, 0x63, 0, PutAll }, /* X */ { "RTI", 0x0000001, 0x40, 0, PutAll }, { "RTS", 0x0000001, 0x60, 0, PutAll }, { "SAX", 0x000810C, 0x83, 1, PutAll }, /* X */ { "SBC", 0x080A26C, 0xe0, 0, PutAll }, { "SEC", 0x0000001, 0x38, 0, PutAll }, { "SED", 0x0000001, 0xf8, 0, PutAll }, { "SEI", 0x0000001, 0x78, 0, PutAll }, { "SHA", 0x0002200, 0x93, 1, PutAll }, /* X */ { "SHX", 0x0000200, 0x9e, 1, PutAll }, /* X */ { "SHY", 0x0000040, 0x9c, 1, PutAll }, /* X */ { "SLO", 0x000A26C, 0x03, 0, PutAll }, /* X */ { "SRE", 0x000A26C, 0x43, 0, PutAll }, /* X */ { "STA", 0x000A26C, 0x80, 0, PutAll }, { "STX", 0x000010c, 0x82, 1, PutAll }, { "STY", 0x000002c, 0x80, 1, PutAll }, { "TAS", 0x0000200, 0x9b, 0, PutAll }, /* X */ { "TAX", 0x0000001, 0xaa, 0, PutAll }, { "TAY", 0x0000001, 0xa8, 0, PutAll }, { "TSX", 0x0000001, 0xba, 0, PutAll }, { "TXA", 0x0000001, 0x8a, 0, PutAll }, { "TXS", 0x0000001, 0x9a, 0, PutAll }, { "TYA", 0x0000001, 0x98, 0, PutAll } } }; /* Instruction table for the 65SC02 */ static const struct { unsigned Count; InsDesc Ins[66]; } InsTab65SC02 = { sizeof (InsTab65SC02.Ins) / sizeof (InsTab65SC02.Ins[0]), { { "ADC", 0x080A66C, 0x60, 0, PutAll }, { "AND", 0x080A66C, 0x20, 0, PutAll }, { "ASL", 0x000006e, 0x02, 1, PutAll }, { "BCC", 0x0020000, 0x90, 0, PutPCRel8 }, { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 }, { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 }, { "BIT", 0x0A0006C, 0x00, 2, PutAll }, { "BMI", 0x0020000, 0x30, 0, PutPCRel8 }, { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, { "BRA", 0x0020000, 0x80, 0, PutPCRel8 }, { "BRK", 0x0000001, 0x00, 0, PutAll }, { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, { "CLC", 0x0000001, 0x18, 0, PutAll }, { "CLD", 0x0000001, 0xd8, 0, PutAll }, { "CLI", 0x0000001, 0x58, 0, PutAll }, { "CLV", 0x0000001, 0xb8, 0, PutAll }, { "CMP", 0x080A66C, 0xc0, 0, PutAll }, { "CPX", 0x080000C, 0xe0, 1, PutAll }, { "CPY", 0x080000C, 0xc0, 1, PutAll }, { "DEA", 0x0000001, 0x00, 3, PutAll }, /* == DEC */ { "DEC", 0x000006F, 0x00, 3, PutAll }, { "DEX", 0x0000001, 0xca, 0, PutAll }, { "DEY", 0x0000001, 0x88, 0, PutAll }, { "EOR", 0x080A66C, 0x40, 0, PutAll }, { "INA", 0x0000001, 0x00, 4, PutAll }, /* == INC */ { "INC", 0x000006f, 0x00, 4, PutAll }, { "INX", 0x0000001, 0xe8, 0, PutAll }, { "INY", 0x0000001, 0xc8, 0, PutAll }, { "JMP", 0x0010808, 0x4c, 6, PutAll }, { "JSR", 0x0000008, 0x20, 7, PutAll }, { "LDA", 0x080A66C, 0xa0, 0, PutAll }, { "LDX", 0x080030C, 0xa2, 1, PutAll }, { "LDY", 0x080006C, 0xa0, 1, PutAll }, { "LSR", 0x000006F, 0x42, 1, PutAll }, { "NOP", 0x0000001, 0xea, 0, PutAll }, { "ORA", 0x080A66C, 0x00, 0, PutAll }, { "PHA", 0x0000001, 0x48, 0, PutAll }, { "PHP", 0x0000001, 0x08, 0, PutAll }, { "PHX", 0x0000001, 0xda, 0, PutAll }, { "PHY", 0x0000001, 0x5a, 0, PutAll }, { "PLA", 0x0000001, 0x68, 0, PutAll }, { "PLP", 0x0000001, 0x28, 0, PutAll }, { "PLX", 0x0000001, 0xfa, 0, PutAll }, { "PLY", 0x0000001, 0x7a, 0, PutAll }, { "ROL", 0x000006F, 0x22, 1, PutAll }, { "ROR", 0x000006F, 0x62, 1, PutAll }, { "RTI", 0x0000001, 0x40, 0, PutAll }, { "RTS", 0x0000001, 0x60, 0, PutAll }, { "SBC", 0x080A66C, 0xe0, 0, PutAll }, { "SEC", 0x0000001, 0x38, 0, PutAll }, { "SED", 0x0000001, 0xf8, 0, PutAll }, { "SEI", 0x0000001, 0x78, 0, PutAll }, { "STA", 0x000A66C, 0x80, 0, PutAll }, { "STX", 0x000010c, 0x82, 1, PutAll }, { "STY", 0x000002c, 0x80, 1, PutAll }, { "STZ", 0x000006c, 0x04, 5, PutAll }, { "TAX", 0x0000001, 0xaa, 0, PutAll }, { "TAY", 0x0000001, 0xa8, 0, PutAll }, { "TRB", 0x000000c, 0x10, 1, PutAll }, { "TSB", 0x000000c, 0x00, 1, PutAll }, { "TSX", 0x0000001, 0xba, 0, PutAll }, { "TXA", 0x0000001, 0x8a, 0, PutAll }, { "TXS", 0x0000001, 0x9a, 0, PutAll }, { "TYA", 0x0000001, 0x98, 0, PutAll } } }; /* Instruction table for the 65C02 */ static const struct { unsigned Count; InsDesc Ins[100]; } InsTab65C02 = { sizeof (InsTab65C02.Ins) / sizeof (InsTab65C02.Ins[0]), { { "ADC", 0x080A66C, 0x60, 0, PutAll }, { "AND", 0x080A66C, 0x20, 0, PutAll }, { "ASL", 0x000006e, 0x02, 1, PutAll }, { "BBR0", 0x0000000, 0x0F, 0, PutBitBranch }, { "BBR1", 0x0000000, 0x1F, 0, PutBitBranch }, { "BBR2", 0x0000000, 0x2F, 0, PutBitBranch }, { "BBR3", 0x0000000, 0x3F, 0, PutBitBranch }, { "BBR4", 0x0000000, 0x4F, 0, PutBitBranch }, { "BBR5", 0x0000000, 0x5F, 0, PutBitBranch }, { "BBR6", 0x0000000, 0x6F, 0, PutBitBranch }, { "BBR7", 0x0000000, 0x7F, 0, PutBitBranch }, { "BBS0", 0x0000000, 0x8F, 0, PutBitBranch }, { "BBS1", 0x0000000, 0x9F, 0, PutBitBranch }, { "BBS2", 0x0000000, 0xAF, 0, PutBitBranch }, { "BBS3", 0x0000000, 0xBF, 0, PutBitBranch }, { "BBS4", 0x0000000, 0xCF, 0, PutBitBranch }, { "BBS5", 0x0000000, 0xDF, 0, PutBitBranch }, { "BBS6", 0x0000000, 0xEF, 0, PutBitBranch }, { "BBS7", 0x0000000, 0xFF, 0, PutBitBranch }, { "BCC", 0x0020000, 0x90, 0, PutPCRel8 }, { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 }, { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 }, { "BIT", 0x0A0006C, 0x00, 2, PutAll }, { "BMI", 0x0020000, 0x30, 0, PutPCRel8 }, { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, { "BRA", 0x0020000, 0x80, 0, PutPCRel8 }, { "BRK", 0x0000001, 0x00, 0, PutAll }, { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, { "CLC", 0x0000001, 0x18, 0, PutAll }, { "CLD", 0x0000001, 0xd8, 0, PutAll }, { "CLI", 0x0000001, 0x58, 0, PutAll }, { "CLV", 0x0000001, 0xb8, 0, PutAll }, { "CMP", 0x080A66C, 0xc0, 0, PutAll }, { "CPX", 0x080000C, 0xe0, 1, PutAll }, { "CPY", 0x080000C, 0xc0, 1, PutAll }, { "DEA", 0x0000001, 0x00, 3, PutAll }, /* == DEC */ { "DEC", 0x000006F, 0x00, 3, PutAll }, { "DEX", 0x0000001, 0xca, 0, PutAll }, { "DEY", 0x0000001, 0x88, 0, PutAll }, { "EOR", 0x080A66C, 0x40, 0, PutAll }, { "INA", 0x0000001, 0x00, 4, PutAll }, /* == INC */ { "INC", 0x000006f, 0x00, 4, PutAll }, { "INX", 0x0000001, 0xe8, 0, PutAll }, { "INY", 0x0000001, 0xc8, 0, PutAll }, { "JMP", 0x0010808, 0x4c, 6, PutAll }, { "JSR", 0x0000008, 0x20, 7, PutAll }, { "LDA", 0x080A66C, 0xa0, 0, PutAll }, { "LDX", 0x080030C, 0xa2, 1, PutAll }, { "LDY", 0x080006C, 0xa0, 1, PutAll }, { "LSR", 0x000006F, 0x42, 1, PutAll }, { "NOP", 0x0000001, 0xea, 0, PutAll }, { "ORA", 0x080A66C, 0x00, 0, PutAll }, { "PHA", 0x0000001, 0x48, 0, PutAll }, { "PHP", 0x0000001, 0x08, 0, PutAll }, { "PHX", 0x0000001, 0xda, 0, PutAll }, { "PHY", 0x0000001, 0x5a, 0, PutAll }, { "PLA", 0x0000001, 0x68, 0, PutAll }, { "PLP", 0x0000001, 0x28, 0, PutAll }, { "PLX", 0x0000001, 0xfa, 0, PutAll }, { "PLY", 0x0000001, 0x7a, 0, PutAll }, { "RMB0", 0x0000004, 0x07, 1, PutAll }, { "RMB1", 0x0000004, 0x17, 1, PutAll }, { "RMB2", 0x0000004, 0x27, 1, PutAll }, { "RMB3", 0x0000004, 0x37, 1, PutAll }, { "RMB4", 0x0000004, 0x47, 1, PutAll }, { "RMB5", 0x0000004, 0x57, 1, PutAll }, { "RMB6", 0x0000004, 0x67, 1, PutAll }, { "RMB7", 0x0000004, 0x77, 1, PutAll }, { "ROL", 0x000006F, 0x22, 1, PutAll }, { "ROR", 0x000006F, 0x62, 1, PutAll }, { "RTI", 0x0000001, 0x40, 0, PutAll }, { "RTS", 0x0000001, 0x60, 0, PutAll }, { "SBC", 0x080A66C, 0xe0, 0, PutAll }, { "SEC", 0x0000001, 0x38, 0, PutAll }, { "SED", 0x0000001, 0xf8, 0, PutAll }, { "SEI", 0x0000001, 0x78, 0, PutAll }, { "SMB0", 0x0000004, 0x87, 1, PutAll }, { "SMB1", 0x0000004, 0x97, 1, PutAll }, { "SMB2", 0x0000004, 0xA7, 1, PutAll }, { "SMB3", 0x0000004, 0xB7, 1, PutAll }, { "SMB4", 0x0000004, 0xC7, 1, PutAll }, { "SMB5", 0x0000004, 0xD7, 1, PutAll }, { "SMB6", 0x0000004, 0xE7, 1, PutAll }, { "SMB7", 0x0000004, 0xF7, 1, PutAll }, { "STA", 0x000A66C, 0x80, 0, PutAll }, { "STP", 0x0000001, 0xdb, 0, PutAll }, { "STX", 0x000010c, 0x82, 1, PutAll }, { "STY", 0x000002c, 0x80, 1, PutAll }, { "STZ", 0x000006c, 0x04, 5, PutAll }, { "TAX", 0x0000001, 0xaa, 0, PutAll }, { "TAY", 0x0000001, 0xa8, 0, PutAll }, { "TRB", 0x000000c, 0x10, 1, PutAll }, { "TSB", 0x000000c, 0x00, 1, PutAll }, { "TSX", 0x0000001, 0xba, 0, PutAll }, { "TXA", 0x0000001, 0x8a, 0, PutAll }, { "TXS", 0x0000001, 0x9a, 0, PutAll }, { "TYA", 0x0000001, 0x98, 0, PutAll }, { "WAI", 0x0000001, 0xcb, 0, PutAll } } }; /* Instruction table for the 4510 */ static const struct { unsigned Count; InsDesc Ins[133]; } InsTab4510 = { sizeof (InsTab4510.Ins) / sizeof (InsTab4510.Ins[0]), { { "ADC", 0x080A66C, 0x60, 0, PutAll }, { "AND", 0x080A66C, 0x20, 0, PutAll }, { "ASL", 0x000006e, 0x02, 1, PutAll }, { "ASR", 0x0000026, 0x43, 0, Put4510 }, { "ASW", 0x0000008, 0xcb, 6, PutAll }, { "BBR0", 0x0000000, 0x0F, 0, PutBitBranch }, { "BBR1", 0x0000000, 0x1F, 0, PutBitBranch }, { "BBR2", 0x0000000, 0x2F, 0, PutBitBranch }, { "BBR3", 0x0000000, 0x3F, 0, PutBitBranch }, { "BBR4", 0x0000000, 0x4F, 0, PutBitBranch }, { "BBR5", 0x0000000, 0x5F, 0, PutBitBranch }, { "BBR6", 0x0000000, 0x6F, 0, PutBitBranch }, { "BBR7", 0x0000000, 0x7F, 0, PutBitBranch }, { "BBS0", 0x0000000, 0x8F, 0, PutBitBranch }, { "BBS1", 0x0000000, 0x9F, 0, PutBitBranch }, { "BBS2", 0x0000000, 0xAF, 0, PutBitBranch }, { "BBS3", 0x0000000, 0xBF, 0, PutBitBranch }, { "BBS4", 0x0000000, 0xCF, 0, PutBitBranch }, { "BBS5", 0x0000000, 0xDF, 0, PutBitBranch }, { "BBS6", 0x0000000, 0xEF, 0, PutBitBranch }, { "BBS7", 0x0000000, 0xFF, 0, PutBitBranch }, { "BCC", 0x0020000, 0x90, 0, PutPCRel8 }, { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 }, { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 }, { "BIT", 0x0A0006C, 0x00, 2, PutAll }, { "BMI", 0x0020000, 0x30, 0, PutPCRel8 }, { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, { "BRA", 0x0020000, 0x80, 0, PutPCRel8 }, { "BRK", 0x0000001, 0x00, 0, PutAll }, { "BSR", 0x0040000, 0x63, 0, PutPCRel4510 }, { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, { "CLC", 0x0000001, 0x18, 0, PutAll }, { "CLD", 0x0000001, 0xd8, 0, PutAll }, { "CLE", 0x0000001, 0x02, 0, PutAll }, { "CLI", 0x0000001, 0x58, 0, PutAll }, { "CLV", 0x0000001, 0xb8, 0, PutAll }, { "CMP", 0x080A66C, 0xc0, 0, PutAll }, { "CPX", 0x080000C, 0xe0, 1, PutAll }, { "CPY", 0x080000C, 0xc0, 1, PutAll }, { "CPZ", 0x080000C, 0xd0, 1, Put4510 }, { "DEA", 0x0000001, 0x00, 3, PutAll }, /* == DEC */ { "DEC", 0x000006F, 0x00, 3, PutAll }, { "DEW", 0x0000004, 0xc3, 9, PutAll }, { "DEX", 0x0000001, 0xca, 0, PutAll }, { "DEY", 0x0000001, 0x88, 0, PutAll }, { "DEZ", 0x0000001, 0x3B, 0, PutAll }, { "EOM", 0x0000001, 0xea, 0, PutAll }, { "EOR", 0x080A66C, 0x40, 0, PutAll }, { "INA", 0x0000001, 0x00, 4, PutAll }, /* == INC */ { "INC", 0x000006f, 0x00, 4, PutAll }, { "INW", 0x0000004, 0xe3, 9, PutAll }, { "INX", 0x0000001, 0xe8, 0, PutAll }, { "INY", 0x0000001, 0xc8, 0, PutAll }, { "INZ", 0x0000001, 0x1B, 0, PutAll }, { "JMP", 0x0010808, 0x4c, 6, PutAll }, { "JSR", 0x0010808, 0x20, 7, Put4510 }, { "LBCC", 0x0040000, 0x93, 0, PutPCRel4510 }, { "LBCS", 0x0040000, 0xb3, 0, PutPCRel4510 }, { "LBEQ", 0x0040000, 0xf3, 0, PutPCRel4510 }, { "LBMI", 0x0040000, 0x33, 0, PutPCRel4510 }, { "LBNE", 0x0040000, 0xd3, 0, PutPCRel4510 }, { "LBPL", 0x0040000, 0x13, 0, PutPCRel4510 }, { "LBRA", 0x0040000, 0x83, 0, PutPCRel4510 }, { "LBVC", 0x0040000, 0x53, 0, PutPCRel4510 }, { "LBVS", 0x0040000, 0x73, 0, PutPCRel4510 }, { "LDA", 0x090A66C, 0xa0, 0, Put4510 }, { "LDX", 0x080030C, 0xa2, 1, PutAll }, { "LDY", 0x080006C, 0xa0, 1, PutAll }, { "LDZ", 0x0800048, 0xa3, 1, Put4510 }, { "LSR", 0x000006F, 0x42, 1, PutAll }, { "MAP", 0x0000001, 0x5C, 0, PutAll }, { "NEG", 0x0000001, 0x42, 0, PutAll }, { "NOP", 0x0000001, 0xea, 0, PutAll }, /* == EOM */ { "ORA", 0x080A66C, 0x00, 0, PutAll }, { "PHA", 0x0000001, 0x48, 0, PutAll }, { "PHD", 0x8000008, 0xf4, 1, PutAll }, /* == PHW */ { "PHP", 0x0000001, 0x08, 0, PutAll }, { "PHW", 0x8000008, 0xf4, 1, PutAll }, { "PHX", 0x0000001, 0xda, 0, PutAll }, { "PHY", 0x0000001, 0x5a, 0, PutAll }, { "PHZ", 0x0000001, 0xdb, 0, PutAll }, { "PLA", 0x0000001, 0x68, 0, PutAll }, { "PLP", 0x0000001, 0x28, 0, PutAll }, { "PLX", 0x0000001, 0xfa, 0, PutAll }, { "PLY", 0x0000001, 0x7a, 0, PutAll }, { "PLZ", 0x0000001, 0xfb, 0, PutAll }, { "RMB0", 0x0000004, 0x07, 1, PutAll }, { "RMB1", 0x0000004, 0x17, 1, PutAll }, { "RMB2", 0x0000004, 0x27, 1, PutAll }, { "RMB3", 0x0000004, 0x37, 1, PutAll }, { "RMB4", 0x0000004, 0x47, 1, PutAll }, { "RMB5", 0x0000004, 0x57, 1, PutAll }, { "RMB6", 0x0000004, 0x67, 1, PutAll }, { "RMB7", 0x0000004, 0x77, 1, PutAll }, { "ROL", 0x000006F, 0x22, 1, PutAll }, { "ROR", 0x000006F, 0x62, 1, PutAll }, { "ROW", 0x0000008, 0xeb, 6, PutAll }, { "RTI", 0x0000001, 0x40, 0, PutAll }, { "RTN", 0x0800000, 0x62, 1, PutAll }, { "RTS", 0x0000001, 0x60, 0, PutAll }, { "SBC", 0x080A66C, 0xe0, 0, PutAll }, { "SEC", 0x0000001, 0x38, 0, PutAll }, { "SED", 0x0000001, 0xf8, 0, PutAll }, { "SEE", 0x0000001, 0x03, 0, PutAll }, { "SEI", 0x0000001, 0x78, 0, PutAll }, { "SMB0", 0x0000004, 0x87, 1, PutAll }, { "SMB1", 0x0000004, 0x97, 1, PutAll }, { "SMB2", 0x0000004, 0xA7, 1, PutAll }, { "SMB3", 0x0000004, 0xB7, 1, PutAll }, { "SMB4", 0x0000004, 0xC7, 1, PutAll }, { "SMB5", 0x0000004, 0xD7, 1, PutAll }, { "SMB6", 0x0000004, 0xE7, 1, PutAll }, { "SMB7", 0x0000004, 0xF7, 1, PutAll }, { "STA", 0x010A66C, 0x80, 0, Put4510 }, { "STX", 0x000030c, 0x82, 1, Put4510 }, { "STY", 0x000006c, 0x80, 1, Put4510 }, { "STZ", 0x000006c, 0x04, 5, PutAll }, { "TAB", 0x0000001, 0x5b, 0, PutAll }, { "TAX", 0x0000001, 0xaa, 0, PutAll }, { "TAY", 0x0000001, 0xa8, 0, PutAll }, { "TAZ", 0x0000001, 0x4b, 0, PutAll }, { "TBA", 0x0000001, 0x7b, 0, PutAll }, { "TRB", 0x000000c, 0x10, 1, PutAll }, { "TSB", 0x000000c, 0x00, 1, PutAll }, { "TSX", 0x0000001, 0xba, 0, PutAll }, { "TSY", 0x0000001, 0x0b, 0, PutAll }, { "TXA", 0x0000001, 0x8a, 0, PutAll }, { "TXS", 0x0000001, 0x9a, 0, PutAll }, { "TYA", 0x0000001, 0x98, 0, PutAll }, { "TYS", 0x0000001, 0x2b, 0, PutAll }, { "TZA", 0x0000001, 0x6b, 0, PutAll }, } }; /* Instruction table for the 65816 */ static const struct { unsigned Count; InsDesc Ins[100]; } InsTab65816 = { sizeof (InsTab65816.Ins) / sizeof (InsTab65816.Ins[0]), { { "ADC", 0x0b8f6fc, 0x60, 0, PutAll }, { "AND", 0x0b8f6fc, 0x20, 0, PutAll }, { "ASL", 0x000006e, 0x02, 1, PutAll }, { "BCC", 0x0020000, 0x90, 0, PutPCRel8 }, { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 }, { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 }, { "BIT", 0x0a0006c, 0x00, 2, PutAll }, { "BMI", 0x0020000, 0x30, 0, PutPCRel8 }, { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, { "BRA", 0x0020000, 0x80, 0, PutPCRel8 }, { "BRK", 0x0000005, 0x00, 6, PutAll }, { "BRL", 0x0040000, 0x82, 0, PutPCRel16 }, { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, { "CLC", 0x0000001, 0x18, 0, PutAll }, { "CLD", 0x0000001, 0xd8, 0, PutAll }, { "CLI", 0x0000001, 0x58, 0, PutAll }, { "CLV", 0x0000001, 0xb8, 0, PutAll }, { "CMP", 0x0b8f6fc, 0xc0, 0, PutAll }, { "COP", 0x0000004, 0x02, 6, PutAll }, { "CPA", 0x0b8f6fc, 0xc0, 0, PutAll }, /* == CMP */ { "CPX", 0x0c0000c, 0xe0, 1, PutAll }, { "CPY", 0x0c0000c, 0xc0, 1, PutAll }, { "DEA", 0x0000001, 0x00, 3, PutAll }, /* == DEC */ { "DEC", 0x000006F, 0x00, 3, PutAll }, { "DEX", 0x0000001, 0xca, 0, PutAll }, { "DEY", 0x0000001, 0x88, 0, PutAll }, { "EOR", 0x0b8f6fc, 0x40, 0, PutAll }, { "INA", 0x0000001, 0x00, 4, PutAll }, /* == INC */ { "INC", 0x000006F, 0x00, 4, PutAll }, { "INX", 0x0000001, 0xe8, 0, PutAll }, { "INY", 0x0000001, 0xc8, 0, PutAll }, { "JML", 0x4000010, 0x5c, 1, PutAll }, { "JMP", 0x4010818, 0x4c, 6, PutAll }, { "JSL", 0x0000010, 0x20, 7, PutAll }, { "JSR", 0x0010018, 0x20, 7, PutAll }, { "LDA", 0x0b8f6fc, 0xa0, 0, PutAll }, { "LDX", 0x0c0030c, 0xa2, 1, PutAll }, { "LDY", 0x0c0006c, 0xa0, 1, PutAll }, { "LSR", 0x000006F, 0x42, 1, PutAll }, { "MVN", 0x1000000, 0x54, 0, PutBlockMove }, { "MVP", 0x1000000, 0x44, 0, PutBlockMove }, { "NOP", 0x0000001, 0xea, 0, PutAll }, { "ORA", 0x0b8f6fc, 0x00, 0, PutAll }, { "PEA", 0x0000008, 0xf4, 6, PutAll }, { "PEI", 0x0000400, 0xd4, 1, PutAll }, { "PER", 0x0040000, 0x62, 0, PutPCRel16 }, { "PHA", 0x0000001, 0x48, 0, PutAll }, { "PHB", 0x0000001, 0x8b, 0, PutAll }, { "PHD", 0x0000001, 0x0b, 0, PutAll }, { "PHK", 0x0000001, 0x4b, 0, PutAll }, { "PHP", 0x0000001, 0x08, 0, PutAll }, { "PHX", 0x0000001, 0xda, 0, PutAll }, { "PHY", 0x0000001, 0x5a, 0, PutAll }, { "PLA", 0x0000001, 0x68, 0, PutAll }, { "PLB", 0x0000001, 0xab, 0, PutAll }, { "PLD", 0x0000001, 0x2b, 0, PutAll }, { "PLP", 0x0000001, 0x28, 0, PutAll }, { "PLX", 0x0000001, 0xfa, 0, PutAll }, { "PLY", 0x0000001, 0x7a, 0, PutAll }, { "REP", 0x0800000, 0xc2, 1, PutREP }, { "ROL", 0x000006F, 0x22, 1, PutAll }, { "ROR", 0x000006F, 0x62, 1, PutAll }, { "RTI", 0x0000001, 0x40, 0, PutAll }, { "RTL", 0x0000001, 0x6b, 0, PutAll }, { "RTS", 0x0000001, 0x60, 0, PutRTS }, { "SBC", 0x0b8f6fc, 0xe0, 0, PutAll }, { "SEC", 0x0000001, 0x38, 0, PutAll }, { "SED", 0x0000001, 0xf8, 0, PutAll }, { "SEI", 0x0000001, 0x78, 0, PutAll }, { "SEP", 0x0800000, 0xe2, 1, PutSEP }, { "STA", 0x018f6fc, 0x80, 0, PutAll }, { "STP", 0x0000001, 0xdb, 0, PutAll }, { "STX", 0x000010c, 0x82, 1, PutAll }, { "STY", 0x000002c, 0x80, 1, PutAll }, { "STZ", 0x000006c, 0x04, 5, PutAll }, { "SWA", 0x0000001, 0xeb, 0, PutAll }, /* == XBA */ { "TAD", 0x0000001, 0x5b, 0, PutAll }, /* == TCD */ { "TAS", 0x0000001, 0x1b, 0, PutAll }, /* == TCS */ { "TAX", 0x0000001, 0xaa, 0, PutAll }, { "TAY", 0x0000001, 0xa8, 0, PutAll }, { "TCD", 0x0000001, 0x5b, 0, PutAll }, { "TCS", 0x0000001, 0x1b, 0, PutAll }, { "TDA", 0x0000001, 0x7b, 0, PutAll }, /* == TDC */ { "TDC", 0x0000001, 0x7b, 0, PutAll }, { "TRB", 0x000000c, 0x10, 1, PutAll }, { "TSA", 0x0000001, 0x3b, 0, PutAll }, /* == TSC */ { "TSB", 0x000000c, 0x00, 1, PutAll }, { "TSC", 0x0000001, 0x3b, 0, PutAll }, { "TSX", 0x0000001, 0xba, 0, PutAll }, { "TXA", 0x0000001, 0x8a, 0, PutAll }, { "TXS", 0x0000001, 0x9a, 0, PutAll }, { "TXY", 0x0000001, 0x9b, 0, PutAll }, { "TYA", 0x0000001, 0x98, 0, PutAll }, { "TYX", 0x0000001, 0xbb, 0, PutAll }, { "WAI", 0x0000001, 0xcb, 0, PutAll }, { "WDM", 0x0000004, 0x42, 6, PutAll }, { "XBA", 0x0000001, 0xeb, 0, PutAll }, { "XCE", 0x0000001, 0xfb, 0, PutAll } } }; /* Instruction table for the SWEET16 pseudo CPU */ static const struct { unsigned Count; InsDesc Ins[26]; } InsTabSweet16 = { sizeof (InsTabSweet16.Ins) / sizeof (InsTabSweet16.Ins[0]), { { "ADD", AMSW16_REG, 0xA0, 0, PutSweet16 }, { "BC", AMSW16_BRA, 0x03, 0, PutSweet16Branch }, { "BK", AMSW16_IMP, 0x0A, 0, PutSweet16 }, { "BM", AMSW16_BRA, 0x05, 0, PutSweet16Branch }, { "BM1", AMSW16_BRA, 0x08, 0, PutSweet16Branch }, { "BNC", AMSW16_BRA, 0x02, 0, PutSweet16Branch }, { "BNM1", AMSW16_BRA, 0x09, 0, PutSweet16Branch }, { "BNZ", AMSW16_BRA, 0x07, 0, PutSweet16Branch }, { "BP", AMSW16_BRA, 0x04, 0, PutSweet16Branch }, { "BR", AMSW16_BRA, 0x01, 0, PutSweet16Branch }, { "BS", AMSW16_BRA, 0x0C, 0, PutSweet16Branch }, { "BZ", AMSW16_BRA, 0x06, 0, PutSweet16Branch }, { "CPR", AMSW16_REG, 0xD0, 0, PutSweet16 }, { "DCR", AMSW16_REG, 0xF0, 0, PutSweet16 }, { "INR", AMSW16_REG, 0xE0, 0, PutSweet16 }, { "LD", AMSW16_REG | AMSW16_IND, 0x00, 1, PutSweet16 }, { "LDD", AMSW16_IND, 0x60, 0, PutSweet16 }, { "POP", AMSW16_IND, 0x80, 0, PutSweet16 }, { "POPD", AMSW16_IND, 0xC0, 0, PutSweet16 }, { "RS", AMSW16_IMP, 0x0B, 0, PutSweet16 }, { "RTN", AMSW16_IMP, 0x00, 0, PutSweet16 }, { "SET", AMSW16_IMM, 0x10, 0, PutSweet16 }, { "ST", AMSW16_REG | AMSW16_IND, 0x10, 1, PutSweet16 }, { "STD", AMSW16_IND, 0x70, 0, PutSweet16 }, { "STP", AMSW16_IND, 0x90, 0, PutSweet16 }, { "SUB", AMSW16_REG, 0xB0, 0, PutSweet16 }, } }; /* Instruction table for the HuC6280 (the CPU used in the PC engine) */ static const struct { unsigned Count; InsDesc Ins[135]; } InsTabHuC6280 = { sizeof (InsTabHuC6280.Ins) / sizeof (InsTabHuC6280.Ins[0]), { { "ADC", 0x080A66C, 0x60, 0, PutAll }, { "AND", 0x080A66C, 0x20, 0, PutAll }, { "ASL", 0x000006e, 0x02, 1, PutAll }, { "BBR0", 0x0000000, 0x0F, 0, PutBitBranch }, { "BBR1", 0x0000000, 0x1F, 0, PutBitBranch }, { "BBR2", 0x0000000, 0x2F, 0, PutBitBranch }, { "BBR3", 0x0000000, 0x3F, 0, PutBitBranch }, { "BBR4", 0x0000000, 0x4F, 0, PutBitBranch }, { "BBR5", 0x0000000, 0x5F, 0, PutBitBranch }, { "BBR6", 0x0000000, 0x6F, 0, PutBitBranch }, { "BBR7", 0x0000000, 0x7F, 0, PutBitBranch }, { "BBS0", 0x0000000, 0x8F, 0, PutBitBranch }, { "BBS1", 0x0000000, 0x9F, 0, PutBitBranch }, { "BBS2", 0x0000000, 0xAF, 0, PutBitBranch }, { "BBS3", 0x0000000, 0xBF, 0, PutBitBranch }, { "BBS4", 0x0000000, 0xCF, 0, PutBitBranch }, { "BBS5", 0x0000000, 0xDF, 0, PutBitBranch }, { "BBS6", 0x0000000, 0xEF, 0, PutBitBranch }, { "BBS7", 0x0000000, 0xFF, 0, PutBitBranch }, { "BCC", 0x0020000, 0x90, 0, PutPCRel8 }, { "BCS", 0x0020000, 0xb0, 0, PutPCRel8 }, { "BEQ", 0x0020000, 0xf0, 0, PutPCRel8 }, { "BIT", 0x0A0006C, 0x00, 2, PutAll }, { "BMI", 0x0020000, 0x30, 0, PutPCRel8 }, { "BNE", 0x0020000, 0xd0, 0, PutPCRel8 }, { "BPL", 0x0020000, 0x10, 0, PutPCRel8 }, { "BRA", 0x0020000, 0x80, 0, PutPCRel8 }, { "BRK", 0x0000001, 0x00, 0, PutAll }, { "BSR", 0x0020000, 0x44, 0, PutPCRel8 }, { "BVC", 0x0020000, 0x50, 0, PutPCRel8 }, { "BVS", 0x0020000, 0x70, 0, PutPCRel8 }, { "CLA", 0x0000001, 0x62, 0, PutAll }, { "CLC", 0x0000001, 0x18, 0, PutAll }, { "CLD", 0x0000001, 0xd8, 0, PutAll }, { "CLI", 0x0000001, 0x58, 0, PutAll }, { "CLV", 0x0000001, 0xb8, 0, PutAll }, { "CLX", 0x0000001, 0x82, 0, PutAll }, { "CLY", 0x0000001, 0xc2, 0, PutAll }, { "CMP", 0x080A66C, 0xc0, 0, PutAll }, { "CPX", 0x080000C, 0xe0, 1, PutAll }, { "CPY", 0x080000C, 0xc0, 1, PutAll }, { "CSH", 0x0000001, 0xd4, 0, PutAll }, { "CSL", 0x0000001, 0x54, 0, PutAll }, { "DEA", 0x0000001, 0x00, 3, PutAll }, /* == DEC */ { "DEC", 0x000006F, 0x00, 3, PutAll }, { "DEX", 0x0000001, 0xca, 0, PutAll }, { "DEY", 0x0000001, 0x88, 0, PutAll }, { "EOR", 0x080A66C, 0x40, 0, PutAll }, { "INA", 0x0000001, 0x00, 4, PutAll }, /* == INC */ { "INC", 0x000006f, 0x00, 4, PutAll }, { "INX", 0x0000001, 0xe8, 0, PutAll }, { "INY", 0x0000001, 0xc8, 0, PutAll }, { "JMP", 0x0010808, 0x4c, 6, PutAll }, { "JSR", 0x0000008, 0x20, 7, PutAll }, { "LDA", 0x080A66C, 0xa0, 0, PutAll }, { "LDX", 0x080030C, 0xa2, 1, PutAll }, { "LDY", 0x080006C, 0xa0, 1, PutAll }, { "LSR", 0x000006F, 0x42, 1, PutAll }, { "NOP", 0x0000001, 0xea, 0, PutAll }, { "ORA", 0x080A66C, 0x00, 0, PutAll }, { "PHA", 0x0000001, 0x48, 0, PutAll }, { "PHP", 0x0000001, 0x08, 0, PutAll }, { "PHX", 0x0000001, 0xda, 0, PutAll }, { "PHY", 0x0000001, 0x5a, 0, PutAll }, { "PLA", 0x0000001, 0x68, 0, PutAll }, { "PLP", 0x0000001, 0x28, 0, PutAll }, { "PLX", 0x0000001, 0xfa, 0, PutAll }, { "PLY", 0x0000001, 0x7a, 0, PutAll }, { "RMB0", 0x0000004, 0x07, 1, PutAll }, { "RMB1", 0x0000004, 0x17, 1, PutAll }, { "RMB2", 0x0000004, 0x27, 1, PutAll }, { "RMB3", 0x0000004, 0x37, 1, PutAll }, { "RMB4", 0x0000004, 0x47, 1, PutAll }, { "RMB5", 0x0000004, 0x57, 1, PutAll }, { "RMB6", 0x0000004, 0x67, 1, PutAll }, { "RMB7", 0x0000004, 0x77, 1, PutAll }, { "ROL", 0x000006F, 0x22, 1, PutAll }, { "ROR", 0x000006F, 0x62, 1, PutAll }, { "RTI", 0x0000001, 0x40, 0, PutAll }, { "RTS", 0x0000001, 0x60, 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 }, { "SET", 0x0000001, 0xf4, 0, PutAll }, { "SMB0", 0x0000004, 0x87, 1, PutAll }, { "SMB1", 0x0000004, 0x97, 1, PutAll }, { "SMB2", 0x0000004, 0xA7, 1, PutAll }, { "SMB3", 0x0000004, 0xB7, 1, PutAll }, { "SMB4", 0x0000004, 0xC7, 1, PutAll }, { "SMB5", 0x0000004, 0xD7, 1, PutAll }, { "SMB6", 0x0000004, 0xE7, 1, PutAll }, { "SMB7", 0x0000004, 0xF7, 1, PutAll }, { "ST0", 0x0800000, 0x03, 1, PutAll }, { "ST1", 0x0800000, 0x13, 1, PutAll }, { "ST2", 0x0800000, 0x23, 1, PutAll }, { "STA", 0x000A66C, 0x80, 0, PutAll }, { "STX", 0x000010c, 0x82, 1, PutAll }, { "STY", 0x000002c, 0x80, 1, PutAll }, { "STZ", 0x000006c, 0x04, 5, PutAll }, { "SXY", 0x0000001, 0x02, 0, PutAll }, { "TAI", 0x2000000, 0xf3, 0, PutBlockTransfer }, { "TAM", 0x0800000, 0x53, 1, PutAll }, { "TAM0", 0x0000001, 0x01, 0, PutTAMn}, { "TAM1", 0x0000001, 0x02, 0, PutTAMn}, { "TAM2", 0x0000001, 0x04, 0, PutTAMn}, { "TAM3", 0x0000001, 0x08, 0, PutTAMn}, { "TAM4", 0x0000001, 0x10, 0, PutTAMn}, { "TAM5", 0x0000001, 0x20, 0, PutTAMn}, { "TAM6", 0x0000001, 0x40, 0, PutTAMn}, { "TAM7", 0x0000001, 0x80, 0, PutTAMn}, { "TAX", 0x0000001, 0xaa, 0, PutAll }, { "TAY", 0x0000001, 0xa8, 0, PutAll }, { "TDD", 0x2000000, 0xc3, 0, PutBlockTransfer }, { "TIA", 0x2000000, 0xe3, 0, PutBlockTransfer }, { "TII", 0x2000000, 0x73, 0, PutBlockTransfer }, { "TIN", 0x2000000, 0xD3, 0, PutBlockTransfer }, { "TMA", 0x0800000, 0x43, 1, PutTMA }, { "TMA0", 0x0000001, 0x01, 0, PutTMAn}, { "TMA1", 0x0000001, 0x02, 0, PutTMAn}, { "TMA2", 0x0000001, 0x04, 0, PutTMAn}, { "TMA3", 0x0000001, 0x08, 0, PutTMAn}, { "TMA4", 0x0000001, 0x10, 0, PutTMAn}, { "TMA5", 0x0000001, 0x20, 0, PutTMAn}, { "TMA6", 0x0000001, 0x40, 0, PutTMAn}, { "TMA7", 0x0000001, 0x80, 0, PutTMAn}, { "TRB", 0x000000c, 0x10, 1, PutAll }, { "TSB", 0x000000c, 0x00, 1, PutAll }, { "TST", 0x000006c, 0x83, 9, PutTST }, { "TSX", 0x0000001, 0xba, 0, PutAll }, { "TXA", 0x0000001, 0x8a, 0, PutAll }, { "TXS", 0x0000001, 0x9a, 0, PutAll }, { "TYA", 0x0000001, 0x98, 0, PutAll } } }; /* An array with instruction tables */ static const InsTable* InsTabs[CPU_COUNT] = { (const InsTable*) &InsTabNone, (const InsTable*) &InsTab6502, (const InsTable*) &InsTab6502X, (const InsTable*) &InsTab65SC02, (const InsTable*) &InsTab65C02, (const InsTable*) &InsTab65816, (const InsTable*) &InsTabSweet16, (const InsTable*) &InsTabHuC6280, 0, /* Mitsubishi 740 */ (const InsTable*) &InsTab4510, }; const InsTable* InsTab = (const InsTable*) &InsTab6502; /* Table to build the effective 65xx opcode from a base opcode and an ** addressing mode. (The value in the table is ORed with the base opcode) */ static unsigned char EATab[12][AM65I_COUNT] = { { /* Table 0 */ 0x00, 0x00, 0x05, 0x0D, 0x0F, 0x15, 0x1D, 0x1F, 0x00, 0x19, 0x12, 0x00, 0x07, 0x11, 0x17, 0x01, 0x00, 0x00, 0x00, 0x03, 0x13, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00 }, { /* Table 1 */ 0x08, 0x08, 0x04, 0x0C, 0x00, 0x14, 0x1C, 0x00, 0x14, 0x1C, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 }, { /* Table 2 */ 0x00, 0x00, 0x24, 0x2C, 0x0F, 0x34, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { /* Table 3 */ 0x3A, 0x3A, 0xC6, 0xCE, 0x00, 0xD6, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { /* Table 4 */ 0x1A, 0x1A, 0xE6, 0xEE, 0x00, 0xF6, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { /* Table 5 */ 0x00, 0x00, 0x60, 0x98, 0x00, 0x70, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { /* Table 6 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00 }, { /* Table 7 (Subroutine opcodes) */ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { /* Table 8 */ 0x00, 0x40, 0x01, 0x41, 0x00, 0x09, 0x49, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { /* Table 9 */ 0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { /* Table 10 (NOPs) */ 0xea, 0x00, 0x04, 0x0c, 0x00, 0x14, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00 }, { /* Table 11 (LAX) */ 0x08, 0x08, 0x04, 0x0C, 0x00, 0x14, 0x1C, 0x00, 0x14, 0x1C, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x80, 0x00 }, }; /* Table to build the effective SWEET16 opcode from a base opcode and an ** addressing mode. */ static unsigned char Sweet16EATab[2][AMSW16I_COUNT] = { { /* Table 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, }, { /* Table 1 */ 0x00, 0x00, 0x00, 0x40, 0x20, }, }; /* Table that encodes the additional bytes for each 65xx instruction */ unsigned char ExtBytes[AM65I_COUNT] = { 0, /* Implicit */ 0, /* Accu */ 1, /* Direct */ 2, /* Absolute */ 3, /* Absolute long */ 1, /* Direct,X */ 2, /* Absolute,X */ 3, /* Absolute long,X */ 1, /* Direct,Y */ 2, /* Absolute,Y */ 1, /* (Direct) */ 2, /* (Absolute) */ 1, /* [Direct] */ 1, /* (Direct),Y */ 1, /* [Direct],Y */ 1, /* (Direct,X) */ 2, /* (Absolute,X) */ 1, /* Relative short */ 2, /* Relative long */ 1, /* r,s */ 1, /* (r,s),y */ 1, /* Immidiate accu */ 1, /* Immidiate index */ 1, /* Immidiate byte */ 2, /* Blockmove (65816) */ 7, /* Block transfer (HuC6280) */ 2, /* Absolute Indirect long */ 2, /* Immidiate word */ }; /* Table that encodes the additional bytes for each SWEET16 instruction */ static unsigned char Sweet16ExtBytes[AMSW16I_COUNT] = { 0, /* AMSW16_IMP */ 1, /* AMSW16_BRA */ 2, /* AMSW16_IMM */ 0, /* AMSW16_IND */ 0, /* AMSW16_REG */ }; /*****************************************************************************/ /* Handler functions for 6502 derivates */ /*****************************************************************************/ static int EvalEA (const InsDesc* Ins, EffAddr* A) /* Evaluate the effective address. All fields in A will be valid after calling ** this function. The function returns true on success and false on errors. */ { /* Get the set of possible addressing modes */ GetEA (A); /* From the possible addressing modes, remove the ones that are invalid ** for this instruction or CPU. */ A->AddrModeSet &= Ins->AddrMode; /* If we have an expression, check it and remove any addressing modes that ** are too small for the expression size. Since we have to study the ** expression anyway, do also replace it by a simpler one if possible. */ if (A->Expr) { ExprDesc ED; ED_Init (&ED); /* Study the expression */ StudyExpr (A->Expr, &ED); /* Simplify it if possible */ A->Expr = SimplifyExpr (A->Expr, &ED); if (ED.AddrSize == ADDR_SIZE_DEFAULT) { /* We don't know how big the expression is. If the instruction ** allows just one addressing mode, assume this as address size ** for the expression. Otherwise assume the default address size ** for data. */ if ((A->AddrModeSet & ~AM65_ALL_ZP) == 0) { ED.AddrSize = ADDR_SIZE_ZP; } else if ((A->AddrModeSet & ~AM65_ALL_ABS) == 0) { ED.AddrSize = ADDR_SIZE_ABS; } else if ((A->AddrModeSet & ~AM65_ALL_FAR) == 0) { ED.AddrSize = ADDR_SIZE_FAR; } else { ED.AddrSize = DataAddrSize; /* If the default address size of the data segment is unequal ** to zero page addressing, but zero page addressing is ** allowed by the instruction, mark all symbols in the ** expression tree. This mark will be checked at end of ** assembly, and a warning is issued, if a zero page symbol ** was guessed wrong here. */ if (ED.AddrSize > ADDR_SIZE_ZP && (A->AddrModeSet & AM65_SET_ZP)) { ExprGuessedAddrSize (A->Expr, ADDR_SIZE_ZP); } } } /* Check the size */ switch (ED.AddrSize) { case ADDR_SIZE_ABS: A->AddrModeSet &= ~AM65_SET_ZP; break; case ADDR_SIZE_FAR: A->AddrModeSet &= ~(AM65_SET_ZP | AM65_SET_ABS); break; } /* Free any resource associated with the expression desc */ ED_Done (&ED); } /* Check if we have any adressing modes left */ if (A->AddrModeSet == 0) { Error ("Illegal addressing mode"); return 0; } A->AddrMode = BitFind (A->AddrModeSet); A->AddrModeBit = (0x01UL << A->AddrMode); /* If the instruction has a one byte operand and immediate addressing is ** allowed but not used, check for an operand expression in the form ** <label or >label, where label is a far or absolute label. If found, ** emit a warning. This warning protects against a typo, where the '#' ** for the immediate operand is omitted. */ if (A->Expr && (Ins->AddrMode & AM65_ALL_IMM) && (A->AddrModeSet & (AM65_DIR | AM65_ABS | AM65_ABS_LONG)) && ExtBytes[A->AddrMode] == 1) { /* Found, check the expression */ ExprNode* Left = A->Expr->Left; if ((A->Expr->Op == EXPR_BYTE0 || A->Expr->Op == EXPR_BYTE1) && Left->Op == EXPR_SYMBOL && GetSymAddrSize (Left->V.Sym) != ADDR_SIZE_ZP) { /* Output a warning */ Warning (1, "Suspicious address expression"); } } /* Build the opcode */ A->Opcode = Ins->BaseCode | EATab[Ins->ExtCode][A->AddrMode]; /* If feature force_range is active, and we have immediate addressing mode, ** limit the expression to the maximum possible value. */ if (A->AddrMode == AM65I_IMM_ACCU || A->AddrMode == AM65I_IMM_INDEX || A->AddrMode == AM65I_IMM_IMPLICIT || A->AddrMode == AM65I_IMM_IMPLICIT_WORD) { if (ForceRange && A->Expr) { A->Expr = MakeBoundedExpr (A->Expr, ExtBytes[A->AddrMode]); } } /* Success */ return 1; } static void EmitCode (EffAddr* A) /* Output code for the data in A */ { /* Check how many extension bytes are needed and output the instruction */ switch (ExtBytes[A->AddrMode]) { case 0: Emit0 (A->Opcode); break; case 1: Emit1 (A->Opcode, A->Expr); break; case 2: if (CPU == CPU_65816 && (A->AddrModeBit & (AM65_ABS | AM65_ABS_X | AM65_ABS_Y))) { /* This is a 16 bit mode that uses an address. If in 65816, ** mode, force this address into 16 bit range to allow ** addressing inside a 64K segment. */ Emit2 (A->Opcode, GenNearAddrExpr (A->Expr)); } else { Emit2 (A->Opcode, A->Expr); } break; case 3: /* Far argument */ Emit3 (A->Opcode, A->Expr); break; default: Internal ("Invalid operand byte count: %u", ExtBytes[A->AddrMode]); } } static long PutImmed8 (const InsDesc* Ins) /* Parse and emit an immediate 8 bit instruction. Return the value of the ** operand if it's available and const. */ { EffAddr A; long Val = -1; /* Evaluate the addressing mode */ if (EvalEA (Ins, &A) == 0) { /* An error occurred */ return -1L; } /* If we have an expression and it's const, get it's value */ if (A.Expr) { (void) IsConstExpr (A.Expr, &Val); } /* Check how many extension bytes are needed and output the instruction */ switch (ExtBytes[A.AddrMode]) { case 1: Emit1 (A.Opcode, A.Expr); break; default: Internal ("Invalid operand byte count: %u", ExtBytes[A.AddrMode]); } /* Return the expression value */ return Val; } static void PutPCRel8 (const InsDesc* Ins) /* Handle branches with a 8 bit distance */ { EmitPCRel (Ins->BaseCode, GenBranchExpr (2), 1); } static void PutPCRel16 (const InsDesc* Ins) /* Handle branches with an 16 bit distance and PER */ { EmitPCRel (Ins->BaseCode, GenBranchExpr (3), 2); } static void PutPCRel4510 (const InsDesc* Ins) /* Handle branches with a 16 bit distance */ { /* 16 bit branch opcode is 8 bit branch opcode or'ed with 0x03 */ EmitPCRel (Ins->BaseCode, GenBranchExpr (2), 2); } static void PutBlockMove (const InsDesc* Ins) /* Handle the blockmove instructions (65816) */ { ExprNode* Arg1; ExprNode* Arg2; Emit0 (Ins->BaseCode); if (CurTok.Tok == TOK_HASH) { /* The operand is a bank-byte expression. */ NextTok (); Arg1 = Expression (); } else { /* The operand is a far-address expression. ** Use only its bank part. */ Arg1 = FuncBankByte (); } ConsumeComma (); if (CurTok.Tok == TOK_HASH) { NextTok (); Arg2 = Expression (); } else { Arg2 = FuncBankByte (); } /* The operands are written in Assembly code as source, destination; ** but, they're assembled as <destination> <source>. */ EmitByte (Arg2); EmitByte (Arg1); } static void PutBlockTransfer (const InsDesc* Ins) /* Handle the block transfer instructions (HuC6280) */ { Emit0 (Ins->BaseCode); EmitWord (Expression ()); ConsumeComma (); EmitWord (Expression ()); ConsumeComma (); EmitWord (Expression ()); } static void PutBitBranch (const InsDesc* Ins) /* Handle 65C02 branch on bit condition */ { Emit0 (Ins->BaseCode); EmitByte (Expression ()); ConsumeComma (); EmitSigned (GenBranchExpr (1), 1); } static void PutREP (const InsDesc* Ins) /* Emit a REP instruction, track register sizes */ { /* Use the generic handler */ long Val = PutImmed8 (Ins); /* We track the status only for the 816 CPU and in smart mode */ if (CPU == CPU_65816 && SmartMode) { /* Check the range for Val. */ if (Val < 0) { /* We had an error */ Warning (1, "Cannot track processor status byte"); } else { if (Val & 0x10) { /* Index registers to 16 bit */ ExtBytes[AM65I_IMM_INDEX] = 2; } if (Val & 0x20) { /* Accu to 16 bit */ ExtBytes[AM65I_IMM_ACCU] = 2; } } } } static void PutSEP (const InsDesc* Ins) /* Emit a SEP instruction (65816), track register sizes */ { /* Use the generic handler */ long Val = PutImmed8 (Ins); /* We track the status only for the 816 CPU and in smart mode */ if (CPU == CPU_65816 && SmartMode) { /* Check the range for Val. */ if (Val < 0) { /* We had an error */ Warning (1, "Cannot track processor status byte"); } else { if (Val & 0x10) { /* Index registers to 8 bit */ ExtBytes[AM65I_IMM_INDEX] = 1; } if (Val & 0x20) { /* Accu to 8 bit */ ExtBytes[AM65I_IMM_ACCU] = 1; } } } } static void PutTAMn (const InsDesc* Ins) /* Emit a TAMn instruction (HuC6280). Since this is a two byte instruction with ** implicit addressing mode, the opcode byte in the table is actually the ** second operand byte. The TAM instruction is the more generic form, it takes ** an immediate argument. */ { /* Emit the TAM opcode itself */ Emit0 (0x53); /* Emit the argument, which is the opcode from the table */ Emit0 (Ins->BaseCode); } static void PutTMA (const InsDesc* Ins) /* Emit a TMA instruction (HuC6280) with an immediate argument. Only one bit ** in the argument byte may be set. */ { /* Use the generic handler */ long Val = PutImmed8 (Ins); /* Check the range for Val. */ if (Val < 0) { /* We had an error */ Warning (1, "Cannot check argument of TMA instruction"); } else { /* Make sure just one bit is set */ if ((Val & (Val - 1)) != 0) { Error ("Argument to TAM must be a power of two"); } } } static void PutTMAn (const InsDesc* Ins) /* Emit a TMAn instruction (HuC6280). Since this is a two byte instruction with ** implicit addressing mode, the opcode byte in the table is actually the ** second operand byte. The TAM instruction is the more generic form, it takes ** an immediate argument. */ { /* Emit the TMA opcode itself */ Emit0 (0x43); /* Emit the argument, which is the opcode from the table */ Emit0 (Ins->BaseCode); } static void PutTST (const InsDesc* Ins) /* Emit a TST instruction (HuC6280). */ { ExprNode* Arg1; EffAddr A; /* The first argument is always an immediate byte */ if (CurTok.Tok != TOK_HASH) { ErrorSkip ("Invalid addressing mode"); return; } NextTok (); Arg1 = Expression (); /* Second argument follows */ ConsumeComma (); /* For the second argument, we use the standard function */ if (EvalEA (Ins, &A)) { /* No error, output code */ Emit1 (A.Opcode, Arg1); /* Check how many extension bytes are needed and output the instruction */ switch (ExtBytes[A.AddrMode]) { case 1: EmitByte (A.Expr); break; case 2: EmitWord (A.Expr); break; } } } static void PutJMP (const InsDesc* Ins) /* Handle the jump instruction for the 6502. Problem is that these chips have ** a bug: If the address crosses a page, the upper byte gets not corrected and ** the instruction will fail. The PutJmp function will add a linker assertion ** to check for this case and is otherwise identical to PutAll. */ { EffAddr A; /* Evaluate the addressing mode used */ if (EvalEA (Ins, &A)) { /* Check for indirect addressing */ if (A.AddrModeBit & AM65_ABS_IND) { /* Compare the low byte of the expression to 0xFF to check for ** a page cross. Be sure to use a copy of the expression otherwise ** things will go weird later. */ ExprNode* E = GenNE (GenByteExpr (CloneExpr (A.Expr)), 0xFF); /* Generate the message */ unsigned Msg = GetStringId ("\"jmp (abs)\" across page border"); /* Generate the assertion */ AddAssertion (E, ASSERT_ACT_WARN, Msg); } /* No error, output code */ EmitCode (&A); } } static void PutRTS (const InsDesc* Ins attribute ((unused))) /* Handle the RTS instruction for the 816. In smart mode emit a RTL opcode if ** the enclosing scope is FAR. */ { if (SmartMode && CurrentScope->AddrSize == ADDR_SIZE_FAR) { Emit0 (0x6B); /* RTL */ } else { Emit0 (0x60); /* RTS */ } } static void PutAll (const InsDesc* Ins) /* Handle all other instructions */ { EffAddr A; /* Evaluate the addressing mode used */ if (EvalEA (Ins, &A)) { /* No error, output code */ EmitCode (&A); } } static void Put4510 (const InsDesc* Ins) /* Handle all other instructions, with modifications for 4510 */ { /* The 4510 uses all 256 possible opcodes, so the last ones were crammed ** in where an opcode was still undefined. As a result, some of those ** don't follow any rules for encoding the addressmodes. So the EATab ** approach does not work always. In this function, the wrongly calculated ** opcode is replaced by the correct one "on the fly". Suggestions for a ** better approach are welcome. ** ** These are: ** $47 -> $44 : ASR $12 ** $57 -> $54 : ASR $12,X ** $93 -> $82 : STA ($12,SP),Y ** $9c -> $8b : STY $1234,X ** $9e -> $9b : STX $1234,Y ** $af -> $ab : LDZ $1234 ** $bf -> $bb : LDZ $1234,X ** $b3 -> $e2 : LDA ($12,SP),Y ** $d0 -> $c2 : CPZ #$00 ** $fc -> $23 : JSR ($1234,X) */ EffAddr A; /* Evaluate the addressing mode used */ if (EvalEA (Ins, &A)) { switch (A.Opcode) { case 0x47: A.Opcode = 0x44; break; case 0x57: A.Opcode = 0x54; break; case 0x93: A.Opcode = 0x82; break; case 0x9C: A.Opcode = 0x8B; break; case 0x9E: A.Opcode = 0x9B; break; case 0xAF: A.Opcode = 0xAB; break; case 0xBF: A.Opcode = 0xBB; break; case 0xB3: A.Opcode = 0xE2; break; case 0xD0: A.Opcode = 0xC2; break; case 0xFC: A.Opcode = 0x23; break; default: /* Keep opcode as it is */ break; } /* No error, output code */ EmitCode (&A); } } /*****************************************************************************/ /* Handler functions for SWEET16 */ /*****************************************************************************/ static void PutSweet16 (const InsDesc* Ins) /* Handle a generic sweet16 instruction */ { EffAddr A; /* Evaluate the addressing mode used */ GetSweet16EA (&A); /* From the possible addressing modes, remove the ones that are invalid ** for this instruction or CPU. */ A.AddrModeSet &= Ins->AddrMode; /* Check if we have any adressing modes left */ if (A.AddrModeSet == 0) { Error ("Illegal addressing mode"); return; } A.AddrMode = BitFind (A.AddrModeSet); A.AddrModeBit = (0x01UL << A.AddrMode); /* Build the opcode */ A.Opcode = Ins->BaseCode | Sweet16EATab[Ins->ExtCode][A.AddrMode] | A.Reg; /* Check how many extension bytes are needed and output the instruction */ switch (Sweet16ExtBytes[A.AddrMode]) { case 0: Emit0 (A.Opcode); break; case 1: Emit1 (A.Opcode, A.Expr); break; case 2: Emit2 (A.Opcode, A.Expr); break; default: Internal ("Invalid operand byte count: %u", Sweet16ExtBytes[A.AddrMode]); } } static void PutSweet16Branch (const InsDesc* Ins) /* Handle a sweet16 branch instruction */ { EmitPCRel (Ins->BaseCode, GenBranchExpr (2), 1); } /*****************************************************************************/ /* Code */ /*****************************************************************************/ static int CmpName (const void* Key, const void* Instr) /* Compare function for bsearch */ { return strcmp ((const char*)Key, ((const InsDesc*) Instr)->Mnemonic); } void SetCPU (cpu_t NewCPU) /* Set a new CPU */ { /* Make sure the parameter is correct */ CHECK (NewCPU < CPU_COUNT); /* Check if we have support for the new CPU, if so, use it */ if (NewCPU != CPU_UNKNOWN && InsTabs[NewCPU]) { CPU = NewCPU; InsTab = InsTabs[CPU]; } else { Error ("CPU not supported"); } } cpu_t GetCPU (void) /* Return the current CPU */ { return CPU; } int FindInstruction (const StrBuf* Ident) /* Check if Ident is a valid mnemonic. If so, return the index in the ** instruction table. If not, return -1. */ { unsigned I; const InsDesc* ID; char Key[sizeof (ID->Mnemonic)]; /* Shortcut for the "none" CPU: If there are no instructions to search ** for, bail out early. */ if (InsTab->Count == 0) { /* Not found */ return -1; } /* Make a copy, and uppercase that copy */ I = 0; while (I < SB_GetLen (Ident)) { /* If the identifier is longer than the longest mnemonic, it cannot ** be one. */ if (I >= sizeof (Key) - 1) { /* Not found, no need for further action */ return -1; } Key[I] = toupper ((unsigned char)SB_AtUnchecked (Ident, I)); ++I; } Key[I] = '\0'; /* Search for the key */ ID = bsearch (Key, InsTab->Ins, InsTab->Count, sizeof (InsDesc), CmpName); if (ID == 0) { /* Not found */ return -1; } else { /* Found, return the entry */ return ID - InsTab->Ins; } } void HandleInstruction (unsigned Index) /* Handle the mnemonic with the given index */ { /* Safety check */ PRECONDITION (Index < InsTab->Count); /* Skip the mnemonic token */ NextTok (); /* Call the handler */ InsTab->Ins[Index].Emit (&InsTab->Ins[Index]); } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/instr.h��������������������������������������������������������������������������0000664�0000000�0000000�00000017132�13473601511�0015046�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* instr.h */ /* */ /* Instruction encoding for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef INSTR_H #define INSTR_H /* common */ #include "cpu.h" #include "strbuf.h" /*****************************************************************************/ /* Data for 6502 and successors */ /*****************************************************************************/ /* Constants for the addressing mode. If an opcode is available in zero page ** and absolut adressing mode, both bits are set. When checking for valid ** modes, the zeropage bit is checked first. Similar, the implicit bit is set ** on accu adressing modes, so the 'A' for accu adressing is not needed (but ** may be specified). ** When assembling for the 6502 or 65C02, all addressing modes that are not ** available on these CPUs are removed before doing any checks. */ #define AM65_IMPLICIT 0x00000003UL #define AM65_ACCU 0x00000002UL #define AM65_DIR 0x00000004UL #define AM65_ABS 0x00000008UL #define AM65_ABS_LONG 0x00000010UL #define AM65_DIR_X 0x00000020UL #define AM65_ABS_X 0x00000040UL #define AM65_ABS_LONG_X 0x00000080UL #define AM65_DIR_Y 0x00000100UL #define AM65_ABS_Y 0x00000200UL #define AM65_DIR_IND 0x00000400UL #define AM65_ABS_IND 0x00000800UL #define AM65_DIR_IND_LONG 0x00001000UL #define AM65_DIR_IND_Y 0x00002000UL #define AM65_DIR_IND_LONG_Y 0x00004000UL #define AM65_DIR_X_IND 0x00008000UL #define AM65_ABS_X_IND 0x00010000UL #define AM65_REL 0x00020000UL #define AM65_REL_LONG 0x00040000UL #define AM65_STACK_REL 0x00080000UL #define AM65_STACK_REL_IND_Y 0x00100000UL #define AM65_IMM_ACCU 0x00200000UL #define AM65_IMM_INDEX 0x00400000UL #define AM65_IMM_IMPLICIT 0x00800000UL #define AM65_BLOCKMOVE 0x01000000UL #define AM65_BLOCKXFER 0x02000000UL #define AM65_ABS_IND_LONG 0x04000000UL #define AM65_IMM_IMPLICIT_WORD 0x08000000UL /* PHW #$1234 (4510 only) */ /* Bitmask for all ZP operations that have correspondent ABS ops */ #define AM65_SET_ZP (AM65_DIR | AM65_DIR_X | AM65_DIR_Y | AM65_DIR_IND | AM65_DIR_X_IND) /* Bitmask for all ABS operations that have correspondent FAR ops */ #define AM65_SET_ABS (AM65_ABS | AM65_ABS_X) /* Bitmask for all ZP operations */ #define AM65_ALL_ZP (AM65_DIR | AM65_DIR_X | AM65_DIR_Y | AM65_DIR_IND | AM65_DIR_X_IND) /* Bitmask for all ABS operations */ #define AM65_ALL_ABS (AM65_ABS | AM65_ABS_X | AM65_ABS_Y | AM65_ABS_IND | AM65_ABS_X_IND) /* Bitmask for all FAR operations */ #define AM65_ALL_FAR (AM65_ABS_LONG | AM65_ABS_LONG_X) /* Bitmask for all immediate operations */ #define AM65_ALL_IMM (AM65_IMM_ACCU | AM65_IMM_INDEX | AM65_IMM_IMPLICIT | AM65_IMM_IMPLICIT_WORD) /* Bit numbers and count */ #define AM65I_IMM_ACCU 21 #define AM65I_IMM_INDEX 22 #define AM65I_IMM_IMPLICIT 23 #define AM65I_IMM_IMPLICIT_WORD 27 #define AM65I_COUNT 28 /* Description for one instruction */ typedef struct InsDesc InsDesc; struct InsDesc { char Mnemonic[5]; unsigned long AddrMode; /* Valid adressing modes */ unsigned char BaseCode; /* Base opcode */ unsigned char ExtCode; /* Number of ext code table */ void (*Emit) (const InsDesc*);/* Handler function */ }; /* An instruction table */ typedef struct InsTable InsTable; struct InsTable { unsigned Count; /* Number of intstructions */ InsDesc Ins[1]; /* Varying length */ }; /* The instruction table for the currently active CPU */ extern const InsTable* InsTab; /* Table that encodes the additional bytes for each instruction */ extern unsigned char ExtBytes[AM65I_COUNT]; /*****************************************************************************/ /* Data for the SWEET16 pseudo CPU */ /*****************************************************************************/ /* SWEET16 addressing modes */ #define AMSW16_IMP 0x0001 /* Implicit */ #define AMSW16_BRA 0x0002 /* A branch */ #define AMSW16_IMM 0x0004 /* Immediate */ #define AMSW16_IND 0x0008 /* Indirect */ #define AMSW16_REG 0x0010 /* Register */ #define AMSW16I_COUNT 5 /* Number of addressing modes */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ void SetCPU (cpu_t NewCPU); /* Set a new CPU */ cpu_t GetCPU (void); /* Return the current CPU */ int FindInstruction (const StrBuf* Ident); /* Check if Ident is a valid mnemonic. If so, return the index in the ** instruction table. If not, return -1. */ void HandleInstruction (unsigned Index); /* Handle the mnemonic with the given index */ /* End of instr.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/istack.c�������������������������������������������������������������������������0000664�0000000�0000000�00000012344�13473601511�0015160�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* istack.c */ /* */ /* Input stack for the scanner */ /* */ /* */ /* */ /* (C) 2000-2003 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "check.h" #include "xmalloc.h" /* ca65 */ #include "error.h" #include "istack.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Size of the stack (== maximum nested macro or repeat count) */ #define ISTACK_MAX 256 /* Structure holding a stack element */ typedef struct IElement IElement; struct IElement { IElement* Next; /* Next stack element */ int (*Func)(void*); /* Function called for input */ void* Data; /* User data given as argument */ const char* Desc; /* Description */ }; /* The stack */ static IElement* IStack = 0; /* Input stack pointer */ static unsigned ICount = 0; /* Number of items on the stack */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ void PushInput (int (*Func) (void*), void* Data, const char* Desc) /* Push an input function onto the input stack */ { IElement* E; /* Check for a stack overflow */ if (ICount > ISTACK_MAX) { Fatal ("Maximum input stack nesting exceeded"); } /* Create a new stack element */ E = xmalloc (sizeof (*E)); /* Initialize it */ E->Func = Func; E->Data = Data; E->Desc = Desc; /* Push it */ E->Next = IStack; IStack = E; } void PopInput (void) /* Pop the current input function from the input stack */ { IElement* E; /* We cannot pop from an empty stack */ PRECONDITION (IStack != 0); /* Remember the last element */ E = IStack; /* Pop it */ IStack = IStack->Next; /* And delete it */ xfree (E); } int InputFromStack (void) /* Try to get input from the input stack. Return true if we had such input, ** return false otherwise. */ { /* Repeatedly call the TOS routine until we have a token or if run out of ** routines. */ while (IStack) { if (IStack->Func (IStack->Data) != 0) { /* We have a token */ return 1; } } /* Nothing is on the stack */ return 0; } int HavePushedInput (void) /* Return true if we have stacked input available, return false if not */ { return (IStack != 0); } void CheckInputStack (void) /* Called from the scanner before closing an input file. Will check for any ** stuff on the input stack. */ { if (IStack) { Error ("Open %s", IStack->Desc); } } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/istack.h�������������������������������������������������������������������������0000664�0000000�0000000�00000006572�13473601511�0015173�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* istack.h */ /* */ /* Input stack for the scanner */ /* */ /* */ /* */ /* (C) 2000 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 ISTACK_H #define ISTACK_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ void PushInput (int (*Func) (void*), void* Data, const char* Desc); /* Push an input function onto the input stack */ void PopInput (void); /* Pop the current input function from the input stack */ int InputFromStack (void); /* Try to get input from the input stack. Return true if we had such input, ** return false otherwise. */ int HavePushedInput (void); /* Return true if we have stacked input available, return false if not */ void CheckInputStack (void); /* Called from the scanner before closing an input file. Will check for any ** stuff on the input stack. */ /* End of istack.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/lineinfo.c�����������������������������������������������������������������������0000664�0000000�0000000�00000036206�13473601511�0015510�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* lineinfo.c */ /* */ /* Source file line info structure */ /* */ /* */ /* */ /* (C) 2001-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* 70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> /* common */ #include "coll.h" #include "hashfunc.h" #include "xmalloc.h" /* ca65 */ #include "filetab.h" #include "global.h" #include "lineinfo.h" #include "objfile.h" #include "scanner.h" #include "span.h" /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ static unsigned HT_GenHash (const void* Key); /* Generate the hash over a key. */ static const void* HT_GetKey (const void* Entry); /* Given a pointer to the user entry data, return a pointer to the key */ static int HT_Compare (const void* Key1, const void* Key2); /* Compare two keys. The function must return a value less than zero if ** Key1 is smaller than Key2, zero if both are equal, and a value greater ** than zero if Key1 is greater then Key2. */ /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Structure that holds the key for a line info */ typedef struct LineInfoKey LineInfoKey; struct LineInfoKey { FilePos Pos; /* File position */ unsigned Type; /* Type/count of line info */ }; /* Structure that holds line info */ struct LineInfo { HashNode Node; /* Hash table node */ unsigned Id; /* Index */ LineInfoKey Key; /* Key for this line info */ unsigned RefCount; /* Reference counter */ Collection Spans; /* Segment spans for this line info */ Collection OpenSpans; /* List of currently open spans */ }; /* Collection containing all line infos */ static Collection LineInfoList = STATIC_COLLECTION_INITIALIZER; /* Collection with currently active line infos */ static Collection CurLineInfo = STATIC_COLLECTION_INITIALIZER; /* Hash table functions */ static const HashFunctions HashFunc = { HT_GenHash, HT_GetKey, HT_Compare }; /* Line info hash table */ static HashTable LineInfoTab = STATIC_HASHTABLE_INITIALIZER (1051, &HashFunc); /* The current assembler input line */ static LineInfo* AsmLineInfo = 0; /*****************************************************************************/ /* Hash table functions */ /*****************************************************************************/ static unsigned HT_GenHash (const void* Key) /* Generate the hash over a key. */ { /* Key is a LineInfoKey pointer */ const LineInfoKey* K = Key; /* Hash over a combination of type, file and line */ return HashInt ((K->Type << 21) ^ (K->Pos.Name << 14) ^ K->Pos.Line); } static const void* HT_GetKey (const void* Entry) /* Given a pointer to the user entry data, return a pointer to the key */ { return &((const LineInfo*)Entry)->Key; } static int HT_Compare (const void* Key1, const void* Key2) /* Compare two keys. The function must return a value less than zero if ** Key1 is smaller than Key2, zero if both are equal, and a value greater ** than zero if Key1 is greater then Key2. */ { /* Convert both parameters to FileInfoKey pointers */ const LineInfoKey* K1 = Key1; const LineInfoKey* K2 = Key2; /* Compare line number, then file and type */ int Res = (int)K2->Pos.Line - (int)K1->Pos.Line; if (Res == 0) { Res = (int)K2->Pos.Name - (int)K1->Pos.Name; if (Res == 0) { Res = (int)K2->Type - (int)K1->Type; } } /* Done */ return Res; } /*****************************************************************************/ /* struct LineInfo */ /*****************************************************************************/ static LineInfo* NewLineInfo (const LineInfoKey* Key) /* Create and return a new line info. Usage will be zero. */ { /* Allocate memory */ LineInfo* LI = xmalloc (sizeof (LineInfo)); /* Initialize the fields */ InitHashNode (&LI->Node); LI->Id = ~0U; LI->Key = *Key; LI->RefCount = 0; InitCollection (&LI->Spans); InitCollection (&LI->OpenSpans); /* Add it to the hash table, so we will find it if necessary */ HT_Insert (&LineInfoTab, LI); /* Return the new struct */ return LI; } static void FreeLineInfo (LineInfo* LI) /* Free a LineInfo structure */ { /* Free the Spans collection. It is supposed to be empty */ CHECK (CollCount (&LI->Spans) == 0); DoneCollection (&LI->Spans); DoneCollection (&LI->OpenSpans); /* Free the structure itself */ xfree (LI); } static int CheckLineInfo (void* Entry, void* Data attribute ((unused))) /* Called from HT_Walk. Remembers used line infos and assigns them an id */ { /* Entry is actually a line info */ LineInfo* LI = Entry; /* The entry is used if there are spans or the ref counter is non zero */ if (LI->RefCount > 0 || CollCount (&LI->Spans) > 0) { LI->Id = CollCount (&LineInfoList); CollAppend (&LineInfoList, LI); return 0; /* Keep the entry */ } else { FreeLineInfo (LI); return 1; /* Remove entry from table */ } } /*****************************************************************************/ /* Code */ /*****************************************************************************/ #if 0 static void DumpLineInfos (const char* Title, const Collection* C) /* Dump line infos from the given collection */ { unsigned I; fprintf (stderr, "%s:\n", Title); for (I = 0; I < CollCount (C); ++I) { const LineInfo* LI = CollConstAt (C, I); const char* Type; switch (GetLineInfoType (LI)) { case LI_TYPE_ASM: Type = "ASM"; break; case LI_TYPE_EXT: Type = "EXT"; break; case LI_TYPE_MACRO: Type = "MACRO"; break; case LI_TYPE_MACPARAM: Type = "MACPARAM"; break; default: Type = "unknown"; break; } fprintf (stderr, "%2u: %-8s %2u %-16s %u/%u\n", I, Type, LI->Key.Pos.Name, SB_GetConstBuf (GetFileName (LI->Key.Pos.Name)), LI->Key.Pos.Line, LI->Key.Pos.Col); } } #endif void InitLineInfo (void) /* Initialize the line infos */ { static const FilePos DefaultPos = STATIC_FILEPOS_INITIALIZER; /* Increase the initial count of the line info collection */ CollGrow (&LineInfoList, 200); /* Create a LineInfo for the default source. This is necessary to allow ** error message to be generated without any input file open. */ AsmLineInfo = StartLine (&DefaultPos, LI_TYPE_ASM, 0); } void DoneLineInfo (void) /* Close down line infos */ { /* Close all current line infos */ unsigned Count = CollCount (&CurLineInfo); while (Count) { EndLine (CollAt (&CurLineInfo, --Count)); } /* Walk over the entries in the hash table and sort them into used and ** unused ones. Add the used ones to the line info list and assign them ** an id. */ HT_Walk (&LineInfoTab, CheckLineInfo, 0); } void EndLine (LineInfo* LI) /* End a line that is tracked by the given LineInfo structure */ { /* Close the spans for the line */ CloseSpanList (&LI->OpenSpans); /* Move the spans to the list of all spans for this line, then clear the ** list of open spans. */ CollTransfer (&LI->Spans, &LI->OpenSpans); CollDeleteAll (&LI->OpenSpans); /* Line info is no longer active - remove it from the list of current ** line infos. */ CollDeleteItem (&CurLineInfo, LI); } LineInfo* StartLine (const FilePos* Pos, unsigned Type, unsigned Count) /* Start line info for a new line */ { LineInfoKey Key; LineInfo* LI; /* Prepare the key struct */ Key.Pos = *Pos; Key.Type = LI_MAKE_TYPE (Type, Count); /* Try to find a line info with this position and type in the hash table. ** If so, reuse it. Otherwise create a new one. */ LI = HT_Find (&LineInfoTab, &Key); if (LI == 0) { /* Allocate a new LineInfo */ LI = NewLineInfo (&Key); } /* Open the spans for this line info */ OpenSpanList (&LI->OpenSpans); /* Add the line info to the list of current line infos */ CollAppend (&CurLineInfo, LI); /* Return the new info */ return LI; } void NewAsmLine (void) /* Start a new assembler input line. Use this function when generating new ** line of LI_TYPE_ASM. It will check if line and/or file have actually ** changed, end the old and start the new line as necessary. */ { /* Check if we can reuse the old line */ if (AsmLineInfo) { if (AsmLineInfo->Key.Pos.Line == CurTok.Pos.Line && AsmLineInfo->Key.Pos.Name == CurTok.Pos.Name) { /* We do already have line info for this line */ return; } /* Line has changed -> end the old line */ EndLine (AsmLineInfo); } /* Start a new line using the current line info */ AsmLineInfo = StartLine (&CurTok.Pos, LI_TYPE_ASM, 0); /* If the first LineInfo in the list came from a .dbg line, then we want ** errors and warnings to show it as an additional note, not as the primary ** line. Therefore, swap the first two LineInfo items. */ if (GetLineInfoType (CollAtUnchecked (&CurLineInfo, 0)) == LI_TYPE_EXT) { CollMove (&CurLineInfo, 1, 0); } } LineInfo* GetAsmLineInfo (void) /* Return the line info for the current assembler file. The function will ** bump the reference counter before returning the line info. */ { ++AsmLineInfo->RefCount; return AsmLineInfo; } void ReleaseLineInfo (LineInfo* LI) /* Decrease the reference count for a line info */ { /* Decrease the reference counter */ CHECK (LI->RefCount > 0); ++LI->RefCount; } void GetFullLineInfo (Collection* LineInfos) /* Return full line infos, that is line infos for currently active Slots. The ** infos will be added to the given collection, existing entries will be left ** intact. The reference count of all added entries will be increased. */ { unsigned I; /* Bum the reference counter for all active line infos */ for (I = 0; I < CollCount (&CurLineInfo); ++I) { ++((LineInfo*)CollAt (&CurLineInfo, I))->RefCount; } /* Copy all line infos over */ CollTransfer (LineInfos, &CurLineInfo); } void ReleaseFullLineInfo (Collection* LineInfos) /* Decrease the reference count for a collection full of LineInfos, then clear ** the collection. */ { unsigned I; /* Walk over all entries */ for (I = 0; I < CollCount (LineInfos); ++I) { /* Release the the line info */ ReleaseLineInfo (CollAt (LineInfos, I)); } /* Delete all entries */ CollDeleteAll (LineInfos); } const FilePos* GetSourcePos (const LineInfo* LI) /* Return the source file position from the given line info */ { return &LI->Key.Pos; } unsigned GetLineInfoType (const LineInfo* LI) /* Return the type of a line info */ { return LI_GET_TYPE (LI->Key.Type); } void WriteLineInfo (const Collection* LineInfos) /* Write a list of line infos to the object file. */ { unsigned I; /* Write the count */ ObjWriteVar (CollCount (LineInfos)); /* Write the line info indices */ for (I = 0; I < CollCount (LineInfos); ++I) { /* Get a pointer to the line info */ const LineInfo* LI = CollConstAt (LineInfos, I); /* Safety */ CHECK (LI->Id != ~0U); /* Write the index to the file */ ObjWriteVar (LI->Id); } } void WriteLineInfos (void) /* Write a list of all line infos to the object file. */ { unsigned I; /* Tell the object file module that we're about to write line infos */ ObjStartLineInfos (); /* Write the line info count to the list */ ObjWriteVar (CollCount (&LineInfoList)); /* Walk over the list and write all line infos */ for (I = 0; I < CollCount (&LineInfoList); ++I) { /* Get a pointer to this line info */ LineInfo* LI = CollAt (&LineInfoList, I); /* Write the source file position */ ObjWritePos (&LI->Key.Pos); /* Write the type and count of the line info */ ObjWriteVar (LI->Key.Type); /* Write the ids of the spans for this line */ WriteSpanList (&LI->Spans); } /* End of line infos */ ObjEndLineInfos (); } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/lineinfo.h�����������������������������������������������������������������������0000664�0000000�0000000�00000011524�13473601511�0015511�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* lineinfo.h */ /* */ /* Source file line info management */ /* */ /* */ /* */ /* (C) 2001-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* 70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef LINEINFO_H #define LINEINFO_H /* common */ #include "coll.h" #include "filepos.h" #include "hashtab.h" #include "lidefs.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Opaque structure used to handle line information */ typedef struct LineInfo LineInfo; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void InitLineInfo (void); /* Initialize the line infos */ void DoneLineInfo (void); /* Close down line infos */ void EndLine (LineInfo* LI); /* End a line that is tracked by the given LineInfo structure */ LineInfo* StartLine (const FilePos* Pos, unsigned Type, unsigned Count); /* Start line info for a new line */ void NewAsmLine (void); /* Start a new assembler input line. Use this function when generating new ** line of LI_TYPE_ASM. It will check if line and/or file have actually ** changed, end the old and start the new line as necessary. */ LineInfo* GetAsmLineInfo (void); /* Return the line info for the current assembler file. The function will ** bump the reference counter before returning the line info. */ void ReleaseLineInfo (LineInfo* LI); /* Decrease the reference count for a line info */ void GetFullLineInfo (Collection* LineInfos); /* Return full line infos, that is line infos for currently active Slots. The ** infos will be added to the given collection, existing entries will be left ** intact. The reference count of all added entries will be increased. */ void ReleaseFullLineInfo (Collection* LineInfos); /* Decrease the reference count for a collection full of LineInfos, then clear ** the collection. */ const FilePos* GetSourcePos (const LineInfo* LI); /* Return the source file position from the given line info */ unsigned GetLineInfoType (const LineInfo* LI); /* Return the type of a line info */ void WriteLineInfo (const Collection* LineInfos); /* Write a list of line infos to the object file. */ void WriteLineInfos (void); /* Write a list of all line infos to the object file. */ /* End of lineinfo.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/listing.c������������������������������������������������������������������������0000664�0000000�0000000�00000032421�13473601511�0015351�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* listing.c */ /* */ /* Listing support for the ca65 crossassembler */ /* */ /* */ /* */ /* (C) 2000-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> #include <errno.h> /* common */ #include "check.h" #include "fname.h" #include "fragdefs.h" #include "strbuf.h" #include "version.h" #include "xmalloc.h" /* ca65 */ #include "error.h" #include "filetab.h" #include "global.h" #include "listing.h" #include "segment.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Single linked list of lines */ ListLine* LineList = 0; /* List of listing lines */ ListLine* LineCur = 0; /* Current listing line */ ListLine* LineLast = 0; /* Last (current) listing line */ /* Page and other formatting */ int PageLength = -1; /* Length of a listing page */ static unsigned PageNumber = 1; /* Current listing page number */ static int PageLines = 0; /* Current line on page */ static unsigned ListBytes = 12; /* Number of bytes to list for one line */ /* Switch the listing on/off */ static int ListingEnabled = 1; /* Enabled if > 0 */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ void NewListingLine (const StrBuf* Line, unsigned char File, unsigned char Depth) /* Create a new ListLine struct and insert it */ { /* Store only if listing is enabled */ if (SB_GetLen (&ListingName) > 0) { ListLine* L; /* Get the length of the line */ unsigned Len = SB_GetLen (Line); /* Ignore trailing newlines */ while (Len > 0 && SB_AtUnchecked (Line, Len-1) == '\n') { --Len; } /* Allocate memory */ L = xmalloc (sizeof (ListLine) + Len); /* Initialize the fields. */ L->Next = 0; L->FragList = 0; L->FragLast = 0; L->PC = GetPC (); L->Reloc = GetRelocMode (); L->File = File; L->Depth = Depth; L->Output = (ListingEnabled > 0); L->ListBytes = (unsigned char) ListBytes; memcpy (L->Line, SB_GetConstBuf (Line), Len); L->Line[Len] = '\0'; /* Insert the line into the list of lines */ if (LineList == 0) { LineList = L; } else { LineLast->Next = L; } LineLast = L; } } void EnableListing (void) /* Enable output of lines to the listing */ { if (SB_GetLen (&ListingName) > 0) { /* If we're about to enable the listing, do this for the current line ** also, so we will see the source line that did this. */ if (ListingEnabled++ == 0) { LineCur->Output = 1; } } } void DisableListing (void) /* Disable output of lines to the listing */ { if (SB_GetLen (&ListingName) > 0) { if (ListingEnabled == 0) { /* Cannot switch the listing off once more */ Error ("Counter underflow"); } else { --ListingEnabled; } } } void SetListBytes (int Bytes) /* Set the maximum number of bytes listed for one line */ { if (Bytes < 0) { Bytes = 0; /* Encode "unlimited" as zero */ } ListBytes = Bytes; } void InitListingLine (void) /* Initialize the current listing line */ { if (SB_GetLen (&ListingName) > 0) { /* Make the last loaded line the current line */ /* ###### This code is a hack! We really need to do it right -- ** as soon as we know how. :-( */ if (LineCur && LineCur->Next && LineCur->Next != LineLast) { ListLine* L = LineCur; do { L = L->Next; /* Set the values for this line */ CHECK (L != 0); L->PC = GetPC (); L->Reloc = GetRelocMode (); L->Output = (ListingEnabled > 0); L->ListBytes = (unsigned char) ListBytes; } while (L->Next != LineLast); } LineCur = LineLast; /* Set the values for this line */ CHECK (LineCur != 0); LineCur->PC = GetPC (); LineCur->Reloc = GetRelocMode (); LineCur->Output = (ListingEnabled > 0); LineCur->ListBytes = (unsigned char) ListBytes; } } static char* AddHex (char* S, unsigned Val) /* Add a hex byte in ASCII to the given string and return the new pointer */ { static const char HexTab [16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' }; *S++ = HexTab [(Val >> 4) & 0x0F]; *S++ = HexTab [Val & 0x0F]; return S; } static void PrintPageHeader (FILE* F, const ListLine* L) /* Print the header for a new page. It is assumed that the given line is the ** last line of the previous page. */ { /* Gte a pointer to the current input file */ const StrBuf* CurFile = GetFileName (L->File); /* Print the header on the new page */ fprintf (F, "ca65 V%s\n" "Main file : %s\n" "Current file: %.*s\n" "\n", GetVersionAsString (), InFile, (int) SB_GetLen (CurFile), SB_GetConstBuf (CurFile)); /* Count pages, reset lines */ ++PageNumber; PageLines = 4; } static void PrintLine (FILE* F, const char* Header, const char* Line, const ListLine* L) /* Print one line to the listing file, adding a newline and counting lines */ { /* Print the given line */ fprintf (F, "%s%s\n", Header, Line); /* Increment the current line */ ++PageLines; /* Switch to a new page if needed. Do not switch, if the current line is ** the last one, to avoid pages that consist of just the header. */ if (PageLength > 0 && PageLines >= PageLength && L->Next != 0) { /* Do a formfeed */ putc ('\f', F); /* Print the header on the new page */ PrintPageHeader (F, L); } } static char* AddMult (char* S, char C, unsigned Count) /* Add multiple instances of character C to S, return updated S. */ { memset (S, C, Count); return S + Count; } static char* MakeLineHeader (char* H, const ListLine* L) /* Prepare the line header */ { char Mode; char Depth; /* Setup the PC mode */ Mode = (L->Reloc)? 'r' : ' '; /* Set up the include depth */ Depth = (L->Depth < 10)? L->Depth + '0' : '+'; /* Format the line */ sprintf (H, "%06lX%c %c", L->PC, Mode, Depth); memset (H+9, ' ', LINE_HEADER_LEN-9); /* Return the buffer */ return H; } void CreateListing (void) /* Create the listing */ { FILE* F; Fragment* Frag; ListLine* L; char HeaderBuf [LINE_HEADER_LEN+1]; /* Open the real listing file */ F = fopen (SB_GetConstBuf (&ListingName), "w"); if (F == 0) { Fatal ("Cannot open listing file '%s': %s", SB_GetConstBuf (&ListingName), strerror (errno)); } /* Reset variables, print the header for the first page */ PageNumber = 0; PrintPageHeader (F, LineList); /* Terminate the header buffer. The last byte will never get overwritten */ HeaderBuf [LINE_HEADER_LEN] = '\0'; /* Walk through all listing lines */ L = LineList; while (L) { char* Buf; char* B; unsigned Count; unsigned I; char* Line; /* If we should not output this line, go to the next */ if (L->Output == 0) { L = L->Next; continue; } /* If we don't have a fragment list for this line, things are easy */ if (L->FragList == 0) { PrintLine (F, MakeLineHeader (HeaderBuf, L), L->Line, L); L = L->Next; continue; } /* Count the number of bytes in the complete fragment list */ Count = 0; Frag = L->FragList; while (Frag) { Count += Frag->Len; Frag = Frag->LineList; } /* Allocate memory for the given number of bytes */ Buf = xmalloc (Count*2+1); /* Copy an ASCII representation of the bytes into the buffer */ B = Buf; Frag = L->FragList; while (Frag) { /* Write data depending on the type */ switch (Frag->Type) { case FRAG_LITERAL: for (I = 0; I < Frag->Len; ++I) { B = AddHex (B, Frag->V.Data[I]); } break; case FRAG_EXPR: case FRAG_SEXPR: B = AddMult (B, 'r', Frag->Len*2); break; case FRAG_FILL: B = AddMult (B, 'x', Frag->Len*2); break; default: Internal ("Invalid fragment type: %u", Frag->Type); } /* Next fragment */ Frag = Frag->LineList; } /* Limit the number of bytes actually printed */ if (L->ListBytes != 0) { /* Not unlimited */ if (Count > L->ListBytes) { Count = L->ListBytes; } } /* Output the data. The format of a listing line is: ** ** PPPPPPm I 11 22 33 44 ** ** where ** ** PPPPPP is the PC ** m is the mode ('r' or empty) ** I is the include level ** 11 .. are code or data bytes */ Line = L->Line; B = Buf; while (Count) { unsigned Chunk; char* P; /* Prepare the line header */ MakeLineHeader (HeaderBuf, L); /* Get the number of bytes for the next line */ Chunk = Count; if (Chunk > 4) { Chunk = 4; } Count -= Chunk; /* Increment the program counter. Since we don't need the PC stored ** in the LineList object for anything else, just increment this ** variable. */ L->PC += Chunk; /* Copy the bytes into the line */ P = HeaderBuf + 11; for (I = 0; I < Chunk; ++I) { *P++ = *B++; *P++ = *B++; *P++ = ' '; } /* Output this line */ PrintLine (F, HeaderBuf, Line, L); /* Don't output a line twice */ Line = ""; } /* Delete the temporary buffer */ xfree (Buf); /* Next line */ L = L->Next; } /* Close the listing file */ (void) fclose (F); } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/listing.h������������������������������������������������������������������������0000664�0000000�0000000�00000012254�13473601511�0015360�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* listing.h */ /* */ /* Listing support for the ca65 crossassembler */ /* */ /* */ /* */ /* (C) 2000-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef LISTING_H #define LISTING_H /* ca65 */ #include "fragment.h" /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ struct StrBuf; /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Length of the header of a listing line */ #define LINE_HEADER_LEN 24 /* One listing line as it is stored in memory */ typedef struct ListLine ListLine; struct ListLine { ListLine* Next; /* Pointer to next line */ Fragment* FragList; /* List of fragments for this line */ Fragment* FragLast; /* Last entry in fragment list */ unsigned long PC; /* Program counter for this line */ unsigned char Reloc; /* Relocatable mode? */ unsigned char File; /* From which file is the line? */ unsigned char Depth; /* Include depth */ unsigned char Output; /* Should we output this line? */ unsigned char ListBytes; /* How many bytes at max? */ char Line[1]; /* Line with dynamic length */ }; /* Single linked list of lines */ extern ListLine* LineList; /* List of listing lines */ extern ListLine* LineCur; /* Current listing line */ extern ListLine* LineLast; /* Last listing line */ /* Page formatting */ #define MIN_PAGE_LEN 32 #define MAX_PAGE_LEN 127 extern int PageLength; /* Length of a listing page */ /* Byte for one listing line */ #define MIN_LIST_BYTES 4 #define MAX_LIST_BYTES 255 /*****************************************************************************/ /* Code */ /*****************************************************************************/ void NewListingLine (const struct StrBuf* Line, unsigned char File, unsigned char Depth); /* Create a new ListLine struct */ void EnableListing (void); /* Enable output of lines to the listing */ void DisableListing (void); /* Disable output of lines to the listing */ void SetListBytes (int Bytes); /* Set the maximum number of bytes listed for one line */ void InitListingLine (void); /* Initialize the current listing line */ void CreateListing (void); /* Create the listing */ /* End of listing.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/macro.c��������������������������������������������������������������������������0000664�0000000�0000000�00000073045�13473601511�0015010�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* macro.c */ /* */ /* Macros for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> /* common */ #include "check.h" #include "hashfunc.h" #include "hashtab.h" #include "xmalloc.h" /* ca65 */ #include "condasm.h" #include "error.h" #include "global.h" #include "instr.h" #include "istack.h" #include "lineinfo.h" #include "nexttok.h" #include "pseudo.h" #include "toklist.h" #include "macro.h" /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ static unsigned HT_GenHash (const void* Key); /* Generate the hash over a key. */ static const void* HT_GetKey (const void* Entry); /* Given a pointer to the user entry data, return a pointer to the key */ static int HT_Compare (const void* Key1, const void* Key2); /* Compare two keys. The function must return a value less than zero if ** Key1 is smaller than Key2, zero if both are equal, and a value greater ** than zero if Key1 is greater then Key2. */ /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Struct that describes an identifer (macro param, local list) */ typedef struct IdDesc IdDesc; struct IdDesc { IdDesc* Next; /* Linked list */ StrBuf Id; /* Identifier, dynamically allocated */ }; /* Struct that describes a macro definition */ struct Macro { HashNode Node; /* Hash list node */ Macro* List; /* List of all macros */ unsigned LocalCount; /* Count of local symbols */ IdDesc* Locals; /* List of local symbols */ unsigned ParamCount; /* Parameter count of macro */ IdDesc* Params; /* Identifiers of macro parameters */ unsigned TokCount; /* Number of tokens for this macro */ TokNode* TokRoot; /* Root of token list */ TokNode* TokLast; /* Pointer to last token in list */ StrBuf Name; /* Macro name, dynamically allocated */ unsigned Expansions; /* Number of active macro expansions */ unsigned char Style; /* Macro style */ unsigned char Incomplete; /* Macro is currently built */ }; /* Hash table functions */ static const HashFunctions HashFunc = { HT_GenHash, HT_GetKey, HT_Compare }; /* Macro hash table */ static HashTable MacroTab = STATIC_HASHTABLE_INITIALIZER (117, &HashFunc); /* Structs that holds data for a macro expansion */ typedef struct MacExp MacExp; struct MacExp { MacExp* Next; /* Pointer to next expansion */ Macro* M; /* Which macro do we expand? */ unsigned IfSP; /* .IF stack pointer at start of expansion */ TokNode* Exp; /* Pointer to current token */ TokNode* Final; /* Pointer to final token */ unsigned MacExpansions; /* Number of active macro expansions */ unsigned LocalStart; /* Start of counter for local symbol names */ unsigned ParamCount; /* Number of actual parameters */ TokNode** Params; /* List of actual parameters */ TokNode* ParamExp; /* Node for expanding parameters */ LineInfo* LI; /* Line info for the expansion */ LineInfo* ParamLI; /* Line info for parameter expansion */ }; /* Maximum number of nested macro expansions */ #define MAX_MACEXPANSIONS 256U /* Number of active macro expansions */ static unsigned MacExpansions = 0; /* Flag if a macro expansion should get aborted */ static int DoMacAbort = 0; /* Counter to create local names for symbols */ static unsigned LocalName = 0; /* Define-style macros disabled if != 0 */ static unsigned DisableDefines = 0; /*****************************************************************************/ /* Hash table functions */ /*****************************************************************************/ static unsigned HT_GenHash (const void* Key) /* Generate the hash over a key. */ { return HashBuf (Key); } static const void* HT_GetKey (const void* Entry) /* Given a pointer to the user entry data, return a pointer to the index */ { return &((Macro*) Entry)->Name; } static int HT_Compare (const void* Key1, const void* Key2) /* Compare two keys. The function must return a value less than zero if ** Key1 is smaller than Key2, zero if both are equal, and a value greater ** than zero if Key1 is greater then Key2. */ { return SB_Compare (Key1, Key2); } /*****************************************************************************/ /* Code */ /*****************************************************************************/ static IdDesc* NewIdDesc (const StrBuf* Id) /* Create a new IdDesc, initialize and return it */ { /* Allocate memory */ IdDesc* ID = xmalloc (sizeof (IdDesc)); /* Initialize the struct */ ID->Next = 0; SB_Init (&ID->Id); SB_Copy (&ID->Id, Id); /* Return the new struct */ return ID; } static void FreeIdDesc (IdDesc* ID) /* Free an IdDesc */ { /* Free the name */ SB_Done (&ID->Id); /* Free the structure itself */ xfree (ID); } static void FreeIdDescList (IdDesc* ID) /* Free a complete list of IdDesc structures */ { while (ID) { IdDesc* This = ID; ID = ID->Next; FreeIdDesc (This); } } static Macro* NewMacro (const StrBuf* Name, unsigned char Style) /* Generate a new macro entry, initialize and return it */ { /* Allocate memory */ Macro* M = xmalloc (sizeof (Macro)); /* Initialize the macro struct */ InitHashNode (&M->Node); M->LocalCount = 0; M->Locals = 0; M->ParamCount = 0; M->Params = 0; M->TokCount = 0; M->TokRoot = 0; M->TokLast = 0; SB_Init (&M->Name); SB_Copy (&M->Name, Name); M->Expansions = 0; M->Style = Style; M->Incomplete = 1; /* Insert the macro into the hash table */ HT_Insert (&MacroTab, &M->Node); /* Return the new macro struct */ return M; } static void FreeMacro (Macro* M) /* Free a macro entry which has already been removed from the macro table. */ { TokNode* T; /* Free locals */ FreeIdDescList (M->Locals); /* Free identifiers of parameters */ FreeIdDescList (M->Params); /* Free the token list for the macro */ while ((T = M->TokRoot) != 0) { M->TokRoot = T->Next; FreeTokNode (T); } /* Free the macro name */ SB_Done (&M->Name); /* Free the macro structure itself */ xfree (M); } static MacExp* NewMacExp (Macro* M) /* Create a new expansion structure for the given macro */ { unsigned I; /* Allocate memory */ MacExp* E = xmalloc (sizeof (MacExp)); /* Initialize the data */ E->M = M; E->IfSP = GetIfStack (); E->Exp = M->TokRoot; E->Final = 0; E->MacExpansions = ++MacExpansions; /* One macro expansion more */ E->LocalStart = LocalName; LocalName += M->LocalCount; E->ParamCount = 0; E->Params = xmalloc (M->ParamCount * sizeof (TokNode*)); for (I = 0; I < M->ParamCount; ++I) { E->Params[I] = 0; } E->ParamExp = 0; E->LI = 0; E->ParamLI = 0; /* Mark the macro as expanding */ ++M->Expansions; /* Return the new macro expansion */ return E; } static void FreeMacExp (MacExp* E) /* Remove and free the current macro expansion */ { unsigned I; /* One macro expansion less */ --MacExpansions; /* No longer expanding this macro */ --E->M->Expansions; /* Free the parameter lists */ for (I = 0; I < E->ParamCount; ++I) { /* Free one parameter list */ TokNode* N = E->Params[I]; while (N) { TokNode* P = N->Next; FreeTokNode (N); N = P; } } xfree (E->Params); /* Free the additional line info */ if (E->ParamLI) { EndLine (E->ParamLI); } if (E->LI) { EndLine (E->LI); } /* Free the final token if we have one */ if (E->Final) { FreeTokNode (E->Final); } /* Free the structure itself */ xfree (E); } static void MacSkipDef (unsigned Style) /* Skip a macro definition */ { if (Style == MAC_STYLE_CLASSIC) { /* Skip tokens until we reach the final .endmacro */ while (CurTok.Tok != TOK_ENDMACRO && CurTok.Tok != TOK_EOF) { NextTok (); } if (CurTok.Tok != TOK_EOF) { SkipUntilSep (); } else { Error ("'.ENDMACRO' expected"); } } else { /* Skip until end of line */ SkipUntilSep (); } } void MacDef (unsigned Style) /* Parse a macro definition */ { Macro* M; TokNode* N; int HaveParams; /* We expect a macro name here */ if (CurTok.Tok != TOK_IDENT) { Error ("Identifier expected"); MacSkipDef (Style); return; } else if (!UbiquitousIdents && FindInstruction (&CurTok.SVal) >= 0) { /* The identifier is a name of a 6502 instruction, which is not ** allowed if not explicitly enabled. */ Error ("Cannot use an instruction as macro name"); MacSkipDef (Style); return; } /* Did we already define that macro? */ if (HT_Find (&MacroTab, &CurTok.SVal) != 0) { /* Macro is already defined */ Error ("A macro named '%m%p' is already defined", &CurTok.SVal); /* Skip tokens until we reach the final .endmacro */ MacSkipDef (Style); return; } /* Define the macro */ M = NewMacro (&CurTok.SVal, Style); /* Switch to raw token mode and skip the macro name */ EnterRawTokenMode (); NextTok (); /* 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; } else { if (CurTok.Tok == TOK_LPAREN) { HaveParams = 1; NextTok (); } else { HaveParams = 0; } } /* Parse the parameter list */ if (HaveParams) { while (CurTok.Tok == TOK_IDENT) { /* Create a struct holding the identifier */ IdDesc* I = NewIdDesc (&CurTok.SVal); /* Insert the struct into the list, checking for duplicate idents */ if (M->ParamCount == 0) { M->Params = I; } else { IdDesc* List = M->Params; while (1) { if (SB_Compare (&List->Id, &CurTok.SVal) == 0) { Error ("Duplicate symbol '%m%p'", &CurTok.SVal); } if (List->Next == 0) { break; } else { List = List->Next; } } List->Next = I; } ++M->ParamCount; /* Skip the name */ NextTok (); /* Maybe there are more params... */ if (CurTok.Tok == TOK_COMMA) { NextTok (); } else { break; } } } /* For classic macros, we expect a separator token, for define-style macros, ** we expect the closing paren. */ if (Style == MAC_STYLE_CLASSIC) { ConsumeSep (); } else if (HaveParams) { ConsumeRParen (); } /* 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 a token list internal to the macro. For classic macros, ** the .LOCAL command is detected and removed, at this time. */ while (1) { /* Check for end of macro */ if (Style == MAC_STYLE_CLASSIC) { /* In classic macros, only .endmacro is allowed */ if (CurTok.Tok == TOK_ENDMACRO) { /* Done */ break; } /* May not have end of file in a macro definition */ if (CurTok.Tok == TOK_EOF) { Error ("'.ENDMACRO' expected"); goto Done; } } else { /* Accept a newline or end of file for new style macros */ if (TokIsSep (CurTok.Tok)) { break; } } /* Check for a .LOCAL declaration */ if (CurTok.Tok == TOK_LOCAL && Style == MAC_STYLE_CLASSIC) { while (1) { IdDesc* I; /* Skip .local or comma */ NextTok (); /* Need an identifer */ if (CurTok.Tok != TOK_IDENT && CurTok.Tok != TOK_LOCAL_IDENT) { Error ("Identifier expected"); SkipUntilSep (); break; } /* Put the identifier into the locals list and skip it */ I = NewIdDesc (&CurTok.SVal); I->Next = M->Locals; M->Locals = I; ++M->LocalCount; NextTok (); /* Check for end of list */ if (CurTok.Tok != TOK_COMMA) { break; } } /* We need end of line after the locals */ ConsumeSep (); continue; } /* Create a token node for the current token */ N = NewTokNode (); /* If the token is an identifier, check if it is a local parameter */ if (CurTok.Tok == TOK_IDENT) { unsigned Count = 0; IdDesc* I = M->Params; while (I) { if (SB_Compare (&I->Id, &CurTok.SVal) == 0) { /* Local param name, replace it */ N->T.Tok = TOK_MACPARAM; N->T.IVal = Count; break; } ++Count; I = I->Next; } } /* Insert the new token in the list */ if (M->TokCount == 0) { /* First token */ M->TokRoot = M->TokLast = N; } else { /* We have already tokens */ M->TokLast->Next = N; M->TokLast = N; } ++M->TokCount; /* Read the next token */ NextTok (); } /* Skip the .endmacro for a classic macro */ if (Style == MAC_STYLE_CLASSIC) { NextTok (); } /* Reset the Incomplete flag now that parsing is done */ M->Incomplete = 0; Done: /* Switch out of raw token mode */ LeaveRawTokenMode (); } void MacUndef (const StrBuf* Name, unsigned char Style) /* Undefine the macro with the given name and style. A style mismatch is ** treated as if the macro didn't exist. */ { /* Search for the macro */ Macro* M = HT_Find (&MacroTab, Name); /* Don't let the user kid with us */ if (M == 0 || M->Style != Style) { Error ("No such macro: %m%p", Name); return; } if (M->Expansions > 0) { Error ("Cannot delete a macro that is currently expanded"); return; } /* Remove the macro from the macro table */ HT_Remove (&MacroTab, M); /* Free the macro structure */ FreeMacro (M); } static int MacExpand (void* Data) /* If we're currently expanding a macro, set the the scanner token and ** attribute to the next value and return true. If we are not expanding ** a macro, return false. */ { /* Cast the Data pointer to the actual data structure */ MacExp* Mac = (MacExp*) Data; /* Check if we should abort this macro */ if (DoMacAbort) { /* Reset the flag */ DoMacAbort = 0; /* Abort any open .IF statements in this macro expansion */ CleanupIfStack (Mac->IfSP); /* Terminate macro expansion */ goto MacEnd; } /* We're expanding a macro. Check if we are expanding one of the ** macro parameters. */ ExpandParam: if (Mac->ParamExp) { /* Ok, use token from parameter list */ TokSet (Mac->ParamExp); /* Create new line info for this parameter token */ if (Mac->ParamLI) { EndLine (Mac->ParamLI); } Mac->ParamLI = StartLine (&CurTok.Pos, LI_TYPE_MACPARAM, Mac->MacExpansions); /* Set pointer to next token */ Mac->ParamExp = Mac->ParamExp->Next; /* Done */ return 1; } else if (Mac->ParamLI) { /* There's still line info open from the parameter expansion - end it */ EndLine (Mac->ParamLI); Mac->ParamLI = 0; } /* We're not expanding macro parameters. Check if we have tokens left from ** the macro itself. */ if (Mac->Exp) { /* Use next macro token */ TokSet (Mac->Exp); /* Create new line info for this token */ if (Mac->LI) { EndLine (Mac->LI); } Mac->LI = StartLine (&CurTok.Pos, LI_TYPE_MACRO, Mac->MacExpansions); /* Set pointer to next token */ Mac->Exp = Mac->Exp->Next; /* Is it a request for actual parameter count? */ if (CurTok.Tok == TOK_PARAMCOUNT) { CurTok.Tok = TOK_INTCON; CurTok.IVal = Mac->ParamCount; return 1; } /* Is it the name of a macro parameter? */ if (CurTok.Tok == TOK_MACPARAM) { /* Start to expand the parameter token list */ Mac->ParamExp = Mac->Params[CurTok.IVal]; /* Go back and expand the parameter */ goto ExpandParam; } /* If it's an identifier, it may in fact be a local symbol */ if ((CurTok.Tok == TOK_IDENT || CurTok.Tok == TOK_LOCAL_IDENT) && Mac->M->LocalCount) { /* Search for the local symbol in the list */ unsigned Index = 0; IdDesc* I = Mac->M->Locals; while (I) { if (SB_Compare (&CurTok.SVal, &I->Id) == 0) { /* This is in fact a local symbol, change the name. Be sure ** to generate a local label name if the original name was ** a local label, and also generate a name that cannot be ** generated by a user. */ if (SB_At (&I->Id, 0) == LocalStart) { /* Must generate a local symbol */ SB_Printf (&CurTok.SVal, "%cLOCAL-MACRO_SYMBOL-%04X", LocalStart, Mac->LocalStart + Index); } else { /* Global symbol */ SB_Printf (&CurTok.SVal, "LOCAL-MACRO_SYMBOL-%04X", Mac->LocalStart + Index); } break; } /* Next symbol */ ++Index; I = I->Next; } /* Done */ return 1; } /* The token was successfully set */ return 1; } /* No more macro tokens. Do we have a final token? */ if (Mac->Final) { /* Set the final token and remove it */ TokSet (Mac->Final); FreeTokNode (Mac->Final); Mac->Final = 0; /* 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 ** line info slots are "stacked", this runs into a CHECK FAILED. For ** 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. */ /* End of macro expansion and pop the input function */ FreeMacExp (Mac); PopInput (); /* The token was successfully set */ return 1; } MacEnd: /* End of macro expansion */ FreeMacExp (Mac); /* Pop the input function */ PopInput (); /* No token available */ return 0; } static void StartExpClassic (MacExp* E) /* Start expanding a classic macro */ { token_t Term; /* Skip the macro name */ NextTok (); /* Does this invocation have any arguments? */ if (!TokIsSep (CurTok.Tok)) { /* Read the actual parameters */ while (1) { TokNode* Last; /* Check for maximum parameter count */ if (E->ParamCount >= E->M->ParamCount) { ErrorSkip ("Too many macro parameters"); break; } /* The macro argument optionally may be enclosed in curly braces */ Term = GetTokListTerm (TOK_COMMA); /* Read tokens for one parameter, accept empty params */ Last = 0; while (CurTok.Tok != Term && CurTok.Tok != TOK_SEP) { TokNode* T; /* Check for end of file */ if (CurTok.Tok == TOK_EOF) { Error ("Unexpected end of file"); FreeMacExp (E); return; } /* Get the next token in a node */ T = NewTokNode (); /* Insert it into the list */ if (Last == 0) { E->Params [E->ParamCount] = T; } else { Last->Next = T; } Last = T; /* And skip it... */ NextTok (); } /* One parameter more */ ++E->ParamCount; /* If the macro argument was enclosed in curly braces, end-of-line ** is an error. Skip the closing curly brace. */ if (Term == TOK_RCURLY) { if (CurTok.Tok == TOK_SEP) { Error ("End of line encountered within macro argument"); break; } NextTok (); } /* Check for a comma */ if (CurTok.Tok == TOK_COMMA) { NextTok (); } else { break; } } } /* We must be at end of line now, otherwise something is wrong */ ExpectSep (); /* Insert a new token input function */ PushInput (MacExpand, E, ".MACRO"); } static void StartExpDefine (MacExp* E) /* Start expanding a DEFINE-style macro */ { /* 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; /* Skip the current token */ NextTok (); /* Read the actual parameters */ while (Count--) { TokNode* Last; /* The macro argument optionally may be enclosed in curly braces */ token_t Term = GetTokListTerm (TOK_COMMA); /* Check if there is really a parameter */ if (TokIsSep (CurTok.Tok) || CurTok.Tok == Term) { ErrorSkip ("Macro parameter #%u is empty", E->ParamCount+1); FreeMacExp (E); return; } /* Read tokens for one parameter */ Last = 0; do { TokNode* T; /* Get the next token in a node */ T = NewTokNode (); /* Insert it into the list */ if (Last == 0) { E->Params [E->ParamCount] = T; } else { Last->Next = T; } Last = T; /* And skip it... */ NextTok (); } while (CurTok.Tok != Term && !TokIsSep (CurTok.Tok)); /* 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 (TokIsSep (CurTok.Tok)) { Error ("End of line encountered within macro argument"); break; } NextTok (); } /* Check for a comma */ if (Count > 0) { if (CurTok.Tok == TOK_COMMA) { NextTok (); } else { Error ("',' expected"); } } } /* Macro expansion will overwrite the current token. This is a problem ** 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. */ E->Final = NewTokNode (); /* Insert a new token input function */ PushInput (MacExpand, E, ".DEFINE"); } void MacExpandStart (Macro* M) /* Start expanding a macro */ { MacExp* E; /* Check the argument */ PRECONDITION (M && (M->Style != MAC_STYLE_DEFINE || DisableDefines == 0)); /* We cannot expand an incomplete macro */ if (M->Incomplete) { Error ("Cannot expand an incomplete macro"); return; } /* Don't allow too many nested macro expansions - otherwise it is possible ** to force an endless loop and assembler crash. */ if (MacExpansions >= MAX_MACEXPANSIONS) { Error ("Too many nested macro expansions"); return; } /* Create a structure holding expansion data */ E = NewMacExp (M); /* Call the apropriate subroutine */ switch (M->Style) { case MAC_STYLE_CLASSIC: StartExpClassic (E); break; case MAC_STYLE_DEFINE: StartExpDefine (E); break; default: Internal ("Invalid macro style: %d", M->Style); } } void MacAbort (void) /* Abort the current macro expansion */ { /* Must have an expansion */ CHECK (MacExpansions > 0); /* Set a flag so macro expansion will terminate on the next call */ DoMacAbort = 1; } Macro* FindMacro (const StrBuf* Name) /* Try to find the macro with the given name and return it. If no macro with ** this name was found, return NULL. */ { Macro* M = HT_Find (&MacroTab, Name); return (M != 0 && M->Style == MAC_STYLE_CLASSIC)? M : 0; } 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. */ { Macro* M; /* Never if disabled */ if (DisableDefines) { return 0; } /* Check if we have such a macro */ M = HT_Find (&MacroTab, Name); return (M != 0 && M->Style == MAC_STYLE_DEFINE)? M : 0; } int InMacExpansion (void) /* Return true if we're currently expanding a macro */ { return (MacExpansions > 0); } void DisableDefineStyleMacros (void) /* Disable define-style macros until EnableDefineStyleMacros() is called */ { ++DisableDefines; } void EnableDefineStyleMacros (void) /* Re-enable define-style macros previously disabled with ** DisableDefineStyleMacros(). */ { PRECONDITION (DisableDefines > 0); --DisableDefines; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/macro.h��������������������������������������������������������������������������0000664�0000000�0000000�00000010772�13473601511�0015013�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* macro.h */ /* */ /* Macros for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef MACRO_H #define MACRO_H /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ struct StrBuf; /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Macro styles */ #define MAC_STYLE_CLASSIC 0 #define MAC_STYLE_DEFINE 1 /* Macro as an opaque data type */ struct Macro; typedef struct Macro Macro; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void MacDef (unsigned Style); /* Parse a macro definition */ void MacUndef (const struct StrBuf* Name, unsigned char Style); /* Undefine the macro with the given name and style. A style mismatch is ** treated as if the macro didn't exist. */ void MacExpandStart (Macro* M); /* Start expanding a macro */ void MacAbort (void); /* Abort the current macro expansion */ Macro* FindMacro (const struct StrBuf* Name); /* Try to find the macro with the given name and return it. If no macro with ** this name was found, return NULL. */ Macro* FindDefine (const struct StrBuf* Name); /* Try to find the define style macro with the given name and return it. If no ** such macro was found, return NULL. */ int InMacExpansion (void); /* Return true if we're currently expanding a macro */ void DisableDefineStyleMacros (void); /* Disable define style macros until EnableDefineStyleMacros is called */ void EnableDefineStyleMacros (void); /* Re-enable define style macros previously disabled with ** DisableDefineStyleMacros. */ /* End of macro.h */ #endif ������cc65-2.18/src/ca65/main.c���������������������������������������������������������������������������0000664�0000000�0000000�00000075676�13473601511�0014647�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* main.c */ /* */ /* Main program for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 1998-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* common */ #include "addrsize.h" #include "chartype.h" #include "cmdline.h" #include "debugflag.h" #include "mmodel.h" #include "print.h" #include "scopedefs.h" #include "strbuf.h" #include "target.h" #include "tgttrans.h" #include "version.h" /* ca65 */ #include "abend.h" #include "asserts.h" #include "dbginfo.h" #include "error.h" #include "expr.h" #include "feature.h" #include "filetab.h" #include "global.h" #include "incpath.h" #include "instr.h" #include "istack.h" #include "lineinfo.h" #include "listing.h" #include "macro.h" #include "nexttok.h" #include "objfile.h" #include "options.h" #include "pseudo.h" #include "scanner.h" #include "segment.h" #include "sizeof.h" #include "span.h" #include "spool.h" #include "symbol.h" #include "symtab.h" #include "ulabel.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void Usage (void) /* Print usage information and exit */ { printf ("Usage: %s [options] file\n" "Short options:\n" " -D name[=value]\t\tDefine a symbol\n" " -I dir\t\t\tSet an include directory search path\n" " -U\t\t\t\tMark unresolved symbols as import\n" " -V\t\t\t\tPrint the assembler version\n" " -W n\t\t\t\tSet warning level n\n" " -d\t\t\t\tDebug mode\n" " -g\t\t\t\tAdd debug info to object file\n" " -h\t\t\t\tHelp (this text)\n" " -i\t\t\t\tIgnore case of symbols\n" " -l name\t\t\tCreate a listing file if assembly was ok\n" " -mm model\t\t\tSet the memory model\n" " -o name\t\t\tName the output file\n" " -s\t\t\t\tEnable smart mode\n" " -t sys\t\t\tSet the target system\n" " -v\t\t\t\tIncrease verbosity\n" "\n" "Long options:\n" " --auto-import\t\t\tMark unresolved symbols as import\n" " --bin-include-dir dir\t\tSet a search path for binary includes\n" " --cpu type\t\t\tSet cpu type\n" " --create-dep name\t\tCreate a make dependency file\n" " --create-full-dep name\tCreate a full make dependency file\n" " --debug\t\t\tDebug mode\n" " --debug-info\t\t\tAdd debug info to object file\n" " --feature name\t\tSet an emulation feature\n" " --help\t\t\tHelp (this text)\n" " --ignore-case\t\t\tIgnore case of symbols\n" " --include-dir dir\t\tSet an include directory search path\n" " --large-alignment\t\tDon't warn about large alignments\n" " --listing name\t\tCreate a listing file if assembly was ok\n" " --list-bytes n\t\tMaximum number of bytes per listing line\n" " --memory-model model\t\tSet the memory model\n" " --pagelength n\t\tSet the page length for the listing\n" " --relax-checks\t\tRelax some checks (see docs)\n" " --smart\t\t\tEnable smart mode\n" " --target sys\t\t\tSet the target system\n" " --verbose\t\t\tIncrease verbosity\n" " --version\t\t\tPrint the assembler version\n", ProgName); } static void SetOptions (void) /* Set the option for the translator */ { StrBuf Buf = STATIC_STRBUF_INITIALIZER; /* Set the translator */ SB_Printf (&Buf, "ca65 V%s", GetVersionAsString ()); OptTranslator (&Buf); /* Set date and time */ OptDateTime ((unsigned long) time(0)); /* Release memory for the string */ SB_Done (&Buf); } static void NewSymbol (const char* SymName, long Val) /* Define a symbol with a fixed numeric value in the current scope */ { ExprNode* Expr; SymEntry* Sym; /* Convert the name to a string buffer */ StrBuf SymBuf = STATIC_STRBUF_INITIALIZER; SB_CopyStr (&SymBuf, SymName); /* Search for the symbol, allocate a new one if it doesn't exist */ Sym = SymFind (CurrentScope, &SymBuf, SYM_ALLOC_NEW); /* Check if have already a symbol with this name */ if (SymIsDef (Sym)) { AbEnd ("'%s' is already defined", SymName); } /* Generate an expression for the symbol */ Expr = GenLiteralExpr (Val); /* Mark the symbol as defined */ SymDef (Sym, Expr, ADDR_SIZE_DEFAULT, SF_NONE); /* Free string buffer memory */ SB_Done (&SymBuf); } static void CBMSystem (const char* Sys) /* Define a CBM system */ { NewSymbol ("__CBM__", 1); NewSymbol (Sys, 1); } static void SetSys (const char* Sys) /* Define a target system */ { switch (Target = FindTarget (Sys)) { case TGT_NONE: break; case TGT_MODULE: AbEnd ("Cannot use 'module' as a target for the assembler"); break; case TGT_ATARI2600: NewSymbol ("__ATARI2600__", 1); break; case TGT_ATARI5200: NewSymbol ("__ATARI5200__", 1); break; case TGT_ATARI: NewSymbol ("__ATARI__", 1); break; case TGT_ATARIXL: NewSymbol ("__ATARI__", 1); NewSymbol ("__ATARIXL__", 1); break; case TGT_C16: CBMSystem ("__C16__"); break; case TGT_C64: CBMSystem ("__C64__"); break; case TGT_C65: CBMSystem ("__C65__"); break; case TGT_VIC20: CBMSystem ("__VIC20__"); break; case TGT_C128: CBMSystem ("__C128__"); break; case TGT_PLUS4: CBMSystem ("__C16__"); NewSymbol ("__PLUS4__", 1); break; case TGT_CBM510: CBMSystem ("__CBM510__"); break; case TGT_CBM610: CBMSystem ("__CBM610__"); break; case TGT_PET: CBMSystem ("__PET__"); break; case TGT_BBC: NewSymbol ("__BBC__", 1); break; case TGT_APPLE2: NewSymbol ("__APPLE2__", 1); break; case TGT_APPLE2ENH: NewSymbol ("__APPLE2__", 1); NewSymbol ("__APPLE2ENH__", 1); break; case TGT_GAMATE: NewSymbol ("__GAMATE__", 1); break; case TGT_GEOS_CBM: /* Do not handle as a CBM system */ NewSymbol ("__GEOS__", 1); NewSymbol ("__GEOS_CBM__", 1); break; case TGT_CREATIVISION: NewSymbol ("__CREATIVISION__", 1); break; case TGT_GEOS_APPLE: NewSymbol ("__GEOS__", 1); NewSymbol ("__GEOS_APPLE__", 1); break; case TGT_LUNIX: NewSymbol ("__LUNIX__", 1); break; case TGT_ATMOS: NewSymbol ("__ATMOS__", 1); break; case TGT_TELESTRAT: NewSymbol ("__TELESTRAT__", 1); break; case TGT_NES: NewSymbol ("__NES__", 1); break; case TGT_SUPERVISION: NewSymbol ("__SUPERVISION__", 1); break; case TGT_LYNX: NewSymbol ("__LYNX__", 1); break; case TGT_SIM6502: NewSymbol ("__SIM6502__", 1); break; case TGT_SIM65C02: 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); } /* Initialize the translation tables for the target system */ TgtTranslateInit (); } static void FileNameOption (const char* Opt, const char* Arg, StrBuf* Name) /* Handle an option that remembers a file name for later */ { /* Cannot have the option twice */ if (SB_NotEmpty (Name)) { AbEnd ("Cannot use option '%s' twice", Opt); } /* Remember the file name for later */ SB_CopyStr (Name, Arg); SB_Terminate (Name); } static void DefineSymbol (const char* Def) /* Define a symbol from the command line */ { const char* P; long Val; StrBuf SymName = AUTO_STRBUF_INITIALIZER; /* The symbol must start with a character or underline */ if (!IsIdStart (Def [0])) { InvDef (Def); } P = Def; /* Copy the symbol, checking the rest */ while (IsIdChar (*P)) { SB_AppendChar (&SymName, *P++); } SB_Terminate (&SymName); /* Do we have a value given? */ if (*P != '=') { if (*P != '\0') { InvDef (Def); } Val = 0; } else { /* We have a value */ ++P; if (*P == '$') { ++P; if (sscanf (P, "%lx", &Val) != 1) { InvDef (Def); } } else { if (sscanf (P, "%li", &Val) != 1) { InvDef (Def); } } } /* Define the new symbol */ NewSymbol (SB_GetConstBuf (&SymName), Val); /* Release string memory */ SB_Done (&SymName); } static void OptAutoImport (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Mark unresolved symbols as imported */ { AutoImport = 1; } static void OptBinIncludeDir (const char* Opt attribute ((unused)), const char* Arg) /* Add an include search path for binaries */ { AddSearchPath (BinSearchPath, Arg); } static void OptCPU (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --cpu option */ { cpu_t CPU = FindCPU (Arg); if (CPU == CPU_UNKNOWN) { AbEnd ("Invalid CPU: '%s'", Arg); } else { SetCPU (CPU); } } static void OptCreateDep (const char* Opt, const char* Arg) /* Handle the --create-dep option */ { FileNameOption (Opt, Arg, &DepName); } static void OptCreateFullDep (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --create-full-dep option */ { FileNameOption (Opt, Arg, &FullDepName); } static void OptDebug (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Compiler debug mode */ { ++Debug; } static void OptDebugInfo (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Add debug info to the object file */ { DbgSyms = 1; } static void OptFeature (const char* Opt attribute ((unused)), const char* Arg) /* Set an emulation feature */ { /* Make a string buffer from Arg */ StrBuf Feature; /* Set the feature, check for errors */ if (SetFeature (SB_InitFromString (&Feature, Arg)) == FEAT_UNKNOWN) { AbEnd ("Illegal emulation feature: '%s'", Arg); } } static void OptHelp (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Print usage information and exit */ { Usage (); exit (EXIT_SUCCESS); } static void OptIgnoreCase (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Ignore case on symbols */ { IgnoreCase = 1; } static void OptIncludeDir (const char* Opt attribute ((unused)), const char* Arg) /* Add an include search path */ { AddSearchPath (IncSearchPath, Arg); } static void OptLargeAlignment (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Don't warn about large alignments */ { LargeAlignment = 1; } static void OptListBytes (const char* Opt, const char* Arg) /* Set the maximum number of bytes per listing line */ { unsigned Num; char Check; /* Convert the argument to a number */ if (sscanf (Arg, "%u%c", &Num, &Check) != 1) { InvArg (Opt, Arg); } /* Check the bounds */ if (Num != 0 && (Num < MIN_LIST_BYTES || Num > MAX_LIST_BYTES)) { AbEnd ("Argument for option '%s' is out of range", Opt); } /* Use the value */ SetListBytes (Num); } static void OptListing (const char* Opt, const char* Arg) /* Create a listing file */ { /* Since the meaning of -l and --listing has changed, print an error if ** the filename is empty or begins with the option char. */ if (Arg == 0 || *Arg == '\0' || *Arg == '-') { Fatal ("The meaning of '%s' has changed. It does now " "expect a file name as argument.", Opt); } /* Get the file name */ FileNameOption (Opt, Arg, &ListingName); } static void OptMemoryModel (const char* Opt, const char* Arg) /* Set the memory model */ { mmodel_t M; /* Check the current memory model */ if (MemoryModel != MMODEL_UNKNOWN) { AbEnd ("Cannot use option '%s' twice", Opt); } /* Translate the memory model name and check it */ M = FindMemoryModel (Arg); if (M == MMODEL_UNKNOWN) { AbEnd ("Unknown memory model: %s", Arg); } else if (M == MMODEL_HUGE) { AbEnd ("Unsupported memory model: %s", Arg); } /* Set the memory model */ SetMemoryModel (M); } static void OptPageLength (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --pagelength option */ { int Len = atoi (Arg); if (Len != -1 && (Len < MIN_PAGE_LEN || Len > MAX_PAGE_LEN)) { AbEnd ("Invalid page length: %d", Len); } PageLength = Len; } static void OptRelaxChecks (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Handle the --relax-checks options */ { RelaxChecks = 1; } static void OptSmart (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Handle the -s/--smart options */ { SmartMode = 1; } static void OptTarget (const char* Opt attribute ((unused)), const char* Arg) /* Set the target system */ { SetSys (Arg); } static void OptVerbose (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Increase verbosity */ { ++Verbosity; } static void OptVersion (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Print the assembler version */ { fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ()); exit(EXIT_SUCCESS); } static void DoPCAssign (void) /* Start absolute code */ { long PC = ConstExpression (); if (PC < 0 || PC > 0xFFFFFF) { Error ("Range error"); } else { EnterAbsoluteMode (PC); } } static void OneLine (void) /* Assemble one line */ { Segment* Seg = 0; unsigned long PC = 0; SymEntry* Sym = 0; Macro* Mac = 0; int Instr = -1; /* Initialize the new listing line if we are actually reading from file ** and not from internally pushed input. */ if (!HavePushedInput ()) { InitListingLine (); } /* Single colon means unnamed label */ if (CurTok.Tok == TOK_COLON) { ULabDef (); NextTok (); } /* If the first token on the line is an identifier, check for a macro or ** an instruction. */ if (CurTok.Tok == TOK_IDENT) { if (UbiquitousIdents) { /* Macros CAN be instructions, so check for them first */ Mac = FindMacro (&CurTok.SVal); if (Mac == 0) { Instr = FindInstruction (&CurTok.SVal); } } else { /* Macros and symbols may NOT use the names of instructions */ Instr = FindInstruction (&CurTok.SVal); if (Instr < 0) { Mac = FindMacro (&CurTok.SVal); } } } /* Handle an identifier. This may be a cheap local symbol, or a fully ** scoped identifier which may start with a namespace token (for global ** namespace) */ if (CurTok.Tok == TOK_LOCAL_IDENT || CurTok.Tok == TOK_NAMESPACE || (CurTok.Tok == TOK_IDENT && Instr < 0 && Mac == 0)) { /* Did we have whitespace before the ident? */ int HadWS = CurTok.WS; /* Generate the symbol table entry, then skip the name */ Sym = ParseAnySymName (SYM_ALLOC_NEW); /* If a colon follows, this is a label definition. If there ** is no colon, it's an assignment. */ if (CurTok.Tok == TOK_EQ || CurTok.Tok == TOK_ASSIGN) { /* Determine the symbol flags from the assignment token */ unsigned Flags = (CurTok.Tok == TOK_ASSIGN)? SF_LABEL : SF_NONE; /* Skip the '=' */ NextTok (); /* Define the symbol with the expression following the '=' */ SymDef (Sym, Expression(), ADDR_SIZE_DEFAULT, Flags); /* Don't allow anything after a symbol definition */ ConsumeSep (); return; } else if (CurTok.Tok == TOK_SET) { ExprNode* Expr; /* .SET defines variables (= redefinable symbols) */ NextTok (); /* Read the assignment expression, which must be constant */ Expr = GenLiteralExpr (ConstExpression ()); /* Define the symbol with the constant expression following ** the '=' */ SymDef (Sym, Expr, ADDR_SIZE_DEFAULT, SF_VAR); /* Don't allow anything after a symbol definition */ ConsumeSep (); return; } else { /* A label. Remember the current segment, so we can later ** determine the size of the data stored under the label. */ Seg = ActiveSeg; PC = GetPC (); /* Define the label */ SymDef (Sym, GenCurrentPC (), ADDR_SIZE_DEFAULT, SF_LABEL); /* Skip the colon. If NoColonLabels is enabled, allow labels ** without a colon if there is no whitespace before the ** identifier. */ if (CurTok.Tok != TOK_COLON) { if (HadWS || !NoColonLabels) { Error ("':' expected"); /* Try some smart error recovery */ if (CurTok.Tok == TOK_NAMESPACE) { NextTok (); } } } else { /* Skip the colon */ NextTok (); } /* If we come here, a new identifier may be waiting, which may ** be a macro or instruction. */ if (CurTok.Tok == TOK_IDENT) { if (UbiquitousIdents) { /* Macros CAN be instructions, so check for them first */ Mac = FindMacro (&CurTok.SVal); if (Mac == 0) { Instr = FindInstruction (&CurTok.SVal); } } else { /* Macros and symbols may NOT use the names of instructions */ Instr = FindInstruction (&CurTok.SVal); if (Instr < 0) { Mac = FindMacro (&CurTok.SVal); } } } } } /* We've handled a possible label, now handle the remainder of the line */ if (CurTok.Tok >= TOK_FIRSTPSEUDO && CurTok.Tok <= TOK_LASTPSEUDO) { /* A control command */ HandlePseudo (); } else if (Mac != 0) { /* A macro expansion */ MacExpandStart (Mac); } else if (Instr >= 0) { /* A mnemonic - assemble one instruction */ HandleInstruction (Instr); } else if (PCAssignment && (CurTok.Tok == TOK_STAR || CurTok.Tok == TOK_PC)) { NextTok (); if (CurTok.Tok != TOK_EQ) { Error ("'=' expected"); SkipUntilSep (); } else { /* Skip the equal sign */ NextTok (); /* Enter absolute mode */ DoPCAssign (); } } /* If we have defined a label, remember its size. Sym is also set by ** a symbol assignment, but in this case Done is false, so we don't ** come here. */ if (Sym) { unsigned long Size; if (Seg == ActiveSeg) { /* Same segment */ Size = GetPC () - PC; } else { /* The line has switched the segment */ Size = 0; } DefSizeOfSymbol (Sym, Size); } /* Line separator must come here */ ConsumeSep (); } static void Assemble (void) /* Start the ball rolling ... */ { /* Prime the pump */ NextTok (); /* Assemble lines until end of file */ while (CurTok.Tok != TOK_EOF) { OneLine (); } } static void CreateObjFile (void) /* Create the object file */ { /* Open the object, write the header */ ObjOpen (); /* Write the object file options */ WriteOptions (); /* Write the list of input files */ WriteFiles (); /* Write the segment data to the file */ WriteSegments (); /* Write the import list */ WriteImports (); /* Write the export list */ WriteExports (); /* Write debug symbols if requested */ WriteDbgSyms (); /* Write the scopes if requested */ WriteScopes (); /* Write line infos if requested */ WriteLineInfos (); /* Write the string pool */ WriteStrPool (); /* Write the assertions */ WriteAssertions (); /* Write the spans */ WriteSpans (); /* Write an updated header and close the file */ ObjClose (); } int main (int argc, char* argv []) /* Assembler main program */ { /* Program long options */ static const LongOpt OptTab[] = { { "--auto-import", 0, OptAutoImport }, { "--bin-include-dir", 1, OptBinIncludeDir }, { "--cpu", 1, OptCPU }, { "--create-dep", 1, OptCreateDep }, { "--create-full-dep", 1, OptCreateFullDep }, { "--debug", 0, OptDebug }, { "--debug-info", 0, OptDebugInfo }, { "--feature", 1, OptFeature }, { "--help", 0, OptHelp }, { "--ignore-case", 0, OptIgnoreCase }, { "--include-dir", 1, OptIncludeDir }, { "--large-alignment", 0, OptLargeAlignment }, { "--list-bytes", 1, OptListBytes }, { "--listing", 1, OptListing }, { "--memory-model", 1, OptMemoryModel }, { "--pagelength", 1, OptPageLength }, { "--relax-checks", 0, OptRelaxChecks }, { "--smart", 0, OptSmart }, { "--target", 1, OptTarget }, { "--verbose", 0, OptVerbose }, { "--version", 0, OptVersion }, }; /* Name of the global name space */ static const StrBuf GlobalNameSpace = STATIC_STRBUF_INITIALIZER; unsigned I; /* Initialize the cmdline module */ InitCmdLine (&argc, &argv, "ca65"); /* Initialize the string pool */ InitStrPool (); /* Initialize the include search paths */ InitIncludePaths (); /* Create the predefined segments */ SegInit (); /* Enter the base lexical level. We must do that here, since we may ** define symbols using -D. */ SymEnterLevel (&GlobalNameSpace, SCOPE_FILE, ADDR_SIZE_DEFAULT, 0); /* Initialize the line infos. Must be done here, since we need line infos ** for symbol definitions. */ InitLineInfo (); /* Check the parameters */ I = 1; while (I < ArgCount) { /* Get the argument */ const char* Arg = ArgVec [I]; /* Check for an option */ if (Arg[0] == '-') { switch (Arg[1]) { case '-': LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0])); break; case 'd': OptDebug (Arg, 0); break; case 'g': OptDebugInfo (Arg, 0); break; case 'h': OptHelp (Arg, 0); break; case 'i': OptIgnoreCase (Arg, 0); break; case 'l': OptListing (Arg, GetArg (&I, 2)); break; case 'm': if (Arg[2] == 'm') { OptMemoryModel (Arg, GetArg (&I, 3)); } else { UnknownOption (Arg); } break; case 'o': OutFile = GetArg (&I, 2); break; case 's': OptSmart (Arg, 0); break; case 't': OptTarget (Arg, GetArg (&I, 2)); break; case 'v': OptVerbose (Arg, 0); break; case 'D': DefineSymbol (GetArg (&I, 2)); break; case 'I': OptIncludeDir (Arg, GetArg (&I, 2)); break; case 'U': OptAutoImport (Arg, 0); break; case 'V': OptVersion (Arg, 0); break; case 'W': WarnLevel = atoi (GetArg (&I, 2)); break; default: UnknownOption (Arg); break; } } else { /* Filename. Check if we already had one */ if (InFile) { fprintf (stderr, "%s: Don't know what to do with '%s'\n", ProgName, Arg); exit (EXIT_FAILURE); } else { InFile = Arg; } } /* Next argument */ ++I; } /* Do we have an input file? */ if (InFile == 0) { fprintf (stderr, "%s: No input files\n", ProgName); exit (EXIT_FAILURE); } /* Add the default include search paths. */ FinishIncludePaths (); /* If no CPU given, use the default CPU for the target */ if (GetCPU () == CPU_UNKNOWN) { if (Target != TGT_UNKNOWN) { SetCPU (GetTargetProperties (Target)->DefaultCPU); } else { SetCPU (CPU_6502); } } /* If no memory model was given, use the default */ if (MemoryModel == MMODEL_UNKNOWN) { SetMemoryModel (MMODEL_NEAR); } /* Set the default segment sizes according to the memory model */ SetSegmentSizes (); /* Initialize the scanner, open the input file */ InitScanner (InFile); /* Define the default options */ SetOptions (); /* Assemble the input */ Assemble (); /* If we didn't have any errors, check the pseudo insn stacks */ if (ErrorCount == 0) { CheckPseudo (); } /* If we didn't have any errors, check and cleanup the unnamed labels */ if (ErrorCount == 0) { ULabDone (); } /* If we didn't have any errors, check the symbol table */ if (ErrorCount == 0) { SymCheck (); } /* If we didn't have any errors, check the hll debug symbols */ if (ErrorCount == 0) { DbgInfoCheck (); } /* If we didn't have any errors, close the file scope lexical level */ if (ErrorCount == 0) { SymLeaveLevel (); } /* If we didn't have any errors, check and resolve the segment data */ if (ErrorCount == 0) { SegDone (); } /* If we didn't have any errors, check the assertions */ if (ErrorCount == 0) { CheckAssertions (); } /* Dump the data */ if (Verbosity >= 2) { SymDump (stdout); SegDump (); } /* If we didn't have an errors, finish off the line infos */ DoneLineInfo (); /* If we didn't have any errors, create the object, listing and ** dependency files */ if (ErrorCount == 0) { CreateObjFile (); if (SB_GetLen (&ListingName) > 0) { CreateListing (); } CreateDependencies (); } /* Close the input file */ DoneScanner (); /* Return an apropriate exit code */ return (ErrorCount == 0)? EXIT_SUCCESS : EXIT_FAILURE; } ������������������������������������������������������������������cc65-2.18/src/ca65/nexttok.c������������������������������������������������������������������������0000664�0000000�0000000�00000053570�13473601511�0015404�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* nexttok.c */ /* */ /* Get next token and handle token level functions */ /* */ /* */ /* */ /* (C) 2000-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> /* common */ #include "chartype.h" #include "check.h" #include "strbuf.h" /* ca65 */ #include "condasm.h" #include "error.h" #include "expr.h" #include "global.h" #include "scanner.h" #include "toklist.h" #include "nexttok.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ static unsigned RawMode = 0; /* Raw token mode flag/counter */ /*****************************************************************************/ /* Error handling */ /*****************************************************************************/ static int LookAtStrCon (void) /* Make sure the next token is a string constant. If not, print an error ** messages skip the remainder of the line and return false. Otherwise return ** true. */ { if (CurTok.Tok != TOK_STRCON) { Error ("String constant expected"); SkipUntilSep (); return 0; } else { return 1; } } /*****************************************************************************/ /* Code */ /*****************************************************************************/ static TokList* CollectTokens (unsigned Start, unsigned Count) /* Read a list of tokens that is optionally enclosed in curly braces and ** terminated by a right paren. For all tokens starting at the one with index ** Start, and ending at (Start+Count-1), place them into a token list, and ** return this token list. */ { /* Create the token list */ TokList* List = NewTokList (); /* Determine if the list is enclosed in curly braces. */ token_t Term = GetTokListTerm (TOK_RPAREN); /* Read the token list */ unsigned Current = 0; while (CurTok.Tok != Term) { /* Check for end of line or end of input */ if (TokIsSep (CurTok.Tok)) { Error ("Unexpected end of line"); return List; } /* Collect tokens in the given range */ if (Current >= Start && Current < Start+Count) { /* Add the current token to the list */ AddCurTok (List); } /* Get the next token */ ++Current; NextTok (); } /* Eat the terminator token */ NextTok (); /* If the list was enclosed in curly braces, we do expect now a right paren */ if (Term == TOK_RCURLY) { ConsumeRParen (); } /* Return the list of collected tokens */ return List; } static void FuncConcat (void) /* Handle the .CONCAT function */ { StrBuf Buf = STATIC_STRBUF_INITIALIZER; /* Skip it */ NextTok (); /* Left paren expected */ ConsumeLParen (); /* Concatenate any number of strings */ while (1) { /* Next token must be a string */ if (!LookAtStrCon ()) { SB_Done (&Buf); return; } /* Append the string */ SB_Append (&Buf, &CurTok.SVal); /* Skip the string token */ NextTok (); /* Comma means another argument */ if (CurTok.Tok == TOK_COMMA) { NextTok (); } else { /* Done */ break; } } /* We expect a closing parenthesis, but will not skip it but replace it ** by the string token just created. */ if (CurTok.Tok != TOK_RPAREN) { Error ("')' expected"); } else { CurTok.Tok = TOK_STRCON; SB_Copy (&CurTok.SVal, &Buf); SB_Terminate (&CurTok.SVal); } /* Free the string buffer */ SB_Done (&Buf); } static void NoIdent (void) /* Print an error message and skip the remainder of the line */ { Error ("Argument of .IDENT is not a valid identifier"); SkipUntilSep (); } static void FuncIdent (void) /* Handle the .IDENT function */ { StrBuf Buf = STATIC_STRBUF_INITIALIZER; token_t Id; unsigned I; /* Skip it */ NextTok (); /* Left paren expected */ ConsumeLParen (); /* The function expects a string argument */ if (!LookAtStrCon ()) { return; } /* Check that the string contains a valid identifier. While doing so, ** determine if it is a cheap local, or global one. */ SB_Reset (&CurTok.SVal); /* Check for a cheap local symbol */ if (SB_Peek (&CurTok.SVal) == LocalStart) { SB_Skip (&CurTok.SVal); Id = TOK_LOCAL_IDENT; } else { Id = TOK_IDENT; } /* Next character must be a valid identifier start */ if (!IsIdStart (SB_Get (&CurTok.SVal))) { NoIdent (); return; } for (I = SB_GetIndex (&CurTok.SVal); I < SB_GetLen (&CurTok.SVal); ++I) { if (!IsIdChar (SB_AtUnchecked (&CurTok.SVal, I))) { NoIdent (); return; } } if (IgnoreCase) { UpcaseSVal (); } /* If anything is ok, save and skip the string. Check that the next token ** is a right paren, then replace the token by an identifier token. */ SB_Copy (&Buf, &CurTok.SVal); NextTok (); if (CurTok.Tok != TOK_RPAREN) { Error ("')' expected"); } else { CurTok.Tok = Id; SB_Copy (&CurTok.SVal, &Buf); SB_Terminate (&CurTok.SVal); } /* Free buffer memory */ SB_Done (&Buf); } static void FuncLeft (void) /* Handle the .LEFT function */ { long Count; TokList* List; /* Skip it */ NextTok (); /* Left paren expected */ ConsumeLParen (); /* Count argument. Correct negative counts to zero. */ Count = ConstExpression (); if (Count < 0) { Count = 0; } ConsumeComma (); /* Read the token list */ List = CollectTokens (0, (unsigned) Count); /* Since we want to insert the list before the now current token, we have ** to save the current token in some way and then skip it. To do this, we ** will add the current token at the end of the token list (so the list ** will never be empty), push the token list, and then skip the current ** token. This will replace the current token by the first token from the ** list (which will be the old current token in case the list was empty). */ AddCurTok (List); /* Insert it into the scanner feed */ PushTokList (List, ".LEFT"); /* Skip the current token */ NextTok (); } static void FuncMid (void) /* Handle the .MID function */ { long Start; long Count; TokList* List; /* Skip it */ NextTok (); /* Left paren expected */ ConsumeLParen (); /* Start argument. Since the start argument can get negative with ** expressions like ".tcount(arg)-2", we correct it to zero silently. */ Start = ConstExpression (); if (Start < 0 || Start > 100) { Start = 0; } ConsumeComma (); /* Count argument. Similar as above, we will accept negative counts and ** correct them to zero silently. */ Count = ConstExpression (); if (Count < 0) { Count = 0; } ConsumeComma (); /* Read the token list */ List = CollectTokens ((unsigned) Start, (unsigned) Count); /* Since we want to insert the list before the now current token, we have ** to save the current token in some way and then skip it. To do this, we ** will add the current token at the end of the token list (so the list ** will never be empty), push the token list, and then skip the current ** token. This will replace the current token by the first token from the ** list (which will be the old current token in case the list was empty). */ AddCurTok (List); /* Insert it into the scanner feed */ PushTokList (List, ".MID"); /* Skip the current token */ NextTok (); } static void FuncRight (void) /* Handle the .RIGHT function */ { long Count; TokList* List; /* Skip it */ NextTok (); /* Left paren expected */ ConsumeLParen (); /* Count argument. Correct negative counts to zero. */ Count = ConstExpression (); if (Count < 0) { Count = 0; } ConsumeComma (); /* Read the complete token list */ List = CollectTokens (0, 9999); /* Delete tokens from the list until Count tokens are remaining */ while (List->Count > (unsigned) Count) { /* Get the first node */ TokNode* T = List->Root; /* Remove it from the list */ List->Root = List->Root->Next; /* Free the node */ FreeTokNode (T); /* Corrent the token counter */ List->Count--; } /* Since we want to insert the list before the now current token, we have ** to save the current token in some way and then skip it. To do this, we ** will add the current token at the end of the token list (so the list ** will never be empty), push the token list, and then skip the current ** token. This will replace the current token by the first token from the ** list (which will be the old current token in case the list was empty). */ AddCurTok (List); /* Insert it into the scanner feed */ PushTokList (List, ".RIGHT"); /* Skip the current token */ NextTok (); } static void InvalidFormatString (void) /* Print an error message and skip the remainder of the line */ { Error ("Invalid format string"); SkipUntilSep (); } static void FuncSPrintF (void) /* Handle the .SPRINTF function */ { StrBuf Format = STATIC_STRBUF_INITIALIZER; /* User supplied format */ StrBuf R = STATIC_STRBUF_INITIALIZER; /* Result string */ StrBuf F1 = STATIC_STRBUF_INITIALIZER; /* One format spec from F */ StrBuf R1 = STATIC_STRBUF_INITIALIZER; /* One result */ char C; int Done; long IVal; /* Integer value */ /* Skip the .SPRINTF token */ NextTok (); /* Left paren expected */ ConsumeLParen (); /* First argument is a format string. Remember and skip it */ if (!LookAtStrCon ()) { return; } SB_Copy (&Format, &CurTok.SVal); NextTok (); /* Walk over the format string, generating the function result in R */ while (1) { /* Get the next char from the format string and check for EOS */ if (SB_Peek (&Format) == '\0') { break; } /* Check for a format specifier */ if (SB_Peek (&Format) != '%') { /* No format specifier, just copy */ SB_AppendChar (&R, SB_Get (&Format)); continue; } SB_Skip (&Format); if (SB_Peek (&Format) == '%') { /* %% */ SB_AppendChar (&R, '%'); SB_Skip (&Format); continue; } if (SB_Peek (&Format) == '\0') { InvalidFormatString (); break; } /* Since a format specifier follows, we do expect another argument for ** the .sprintf function. */ ConsumeComma (); /* We will copy the format spec into F1 checking for the things we ** support, and later use xsprintf to do the actual formatting. This ** is easier than adding another printf implementation... */ SB_Clear (&F1); SB_AppendChar (&F1, '%'); /* Check for flags */ Done = 0; while ((C = SB_Peek (&Format)) != '\0' && !Done) { switch (C) { case '-': /* FALLTHROUGH */ case '+': /* FALLTHROUGH */ case ' ': /* FALLTHROUGH */ case '#': /* FALLTHROUGH */ case '0': SB_AppendChar (&F1, SB_Get (&Format)); break; default: Done = 1; break; } } /* We do only support a numerical width field */ while (IsDigit (SB_Peek (&Format))) { SB_AppendChar (&F1, SB_Get (&Format)); } /* Precision - only positive numerical fields supported */ if (SB_Peek (&Format) == '.') { SB_AppendChar (&F1, SB_Get (&Format)); while (IsDigit (SB_Peek (&Format))) { SB_AppendChar (&F1, SB_Get (&Format)); } } /* Length modifiers aren't supported, so read the conversion specs */ switch (SB_Peek (&Format)) { case 'd': case 'i': case 'o': case 'u': case 'X': case 'x': /* Our ints are actually longs, so we use the 'l' modifier when ** calling xsprintf later. Terminate the format string. */ SB_AppendChar (&F1, 'l'); SB_AppendChar (&F1, SB_Get (&Format)); SB_Terminate (&F1); /* The argument must be a constant expression */ IVal = ConstExpression (); /* Format this argument according to the spec */ SB_Printf (&R1, SB_GetConstBuf (&F1), IVal); /* Append the formatted argument to the result */ SB_Append (&R, &R1); break; case 's': /* Add the format spec and terminate the format */ SB_AppendChar (&F1, SB_Get (&Format)); SB_Terminate (&F1); /* The argument must be a string constant */ if (!LookAtStrCon ()) { /* Make it one */ SB_CopyStr (&CurTok.SVal, "**undefined**"); } /* Format this argument according to the spec */ SB_Printf (&R1, SB_GetConstBuf (&F1), SB_GetConstBuf (&CurTok.SVal)); /* Skip the string constant */ NextTok (); /* Append the formatted argument to the result */ SB_Append (&R, &R1); break; case 'c': /* Add the format spec and terminate the format */ SB_AppendChar (&F1, SB_Get (&Format)); SB_Terminate (&F1); /* The argument must be a constant expression */ IVal = ConstExpression (); /* Check for a valid character range */ if (IVal <= 0 || IVal > 255) { Error ("Char argument out of range"); IVal = ' '; } /* Format this argument according to the spec. Be sure to pass ** an int as the char value. */ SB_Printf (&R1, SB_GetConstBuf (&F1), (int) IVal); /* Append the formatted argument to the result */ SB_Append (&R, &R1); break; default: Error ("Invalid format string"); SB_Skip (&Format); break; } } /* Terminate the result string */ SB_Terminate (&R); /* We expect a closing parenthesis, but will not skip it but replace it ** by the string token just created. */ if (CurTok.Tok != TOK_RPAREN) { Error ("')' expected"); } else { CurTok.Tok = TOK_STRCON; SB_Copy (&CurTok.SVal, &R); SB_Terminate (&CurTok.SVal); } /* Delete the string buffers */ SB_Done (&Format); SB_Done (&R); SB_Done (&F1); SB_Done (&R1); } static void FuncString (void) /* Handle the .STRING function */ { StrBuf Buf = STATIC_STRBUF_INITIALIZER; /* Skip it */ NextTok (); /* Left paren expected */ ConsumeLParen (); /* Accept identifiers or numeric expressions */ if (CurTok.Tok == TOK_LOCAL_IDENT) { /* Save the identifier, then skip it */ SB_Copy (&Buf, &CurTok.SVal); NextTok (); } else if (CurTok.Tok == TOK_NAMESPACE || CurTok.Tok == TOK_IDENT) { /* Parse a fully qualified symbol name. We cannot use ** ParseScopedSymName here since the name may be invalid. */ int NameSpace; do { NameSpace = (CurTok.Tok == TOK_NAMESPACE); if (NameSpace) { SB_AppendStr (&Buf, "::"); } else { SB_Append (&Buf, &CurTok.SVal); } NextTok (); } while ((NameSpace != 0 && CurTok.Tok == TOK_IDENT) || (NameSpace == 0 && CurTok.Tok == TOK_NAMESPACE)); } else { /* Numeric expression */ long Val = ConstExpression (); SB_Printf (&Buf, "%ld", Val); } /* We expect a closing parenthesis, but will not skip it but replace it ** by the string token just created. */ if (CurTok.Tok != TOK_RPAREN) { Error ("')' expected"); } else { CurTok.Tok = TOK_STRCON; SB_Copy (&CurTok.SVal, &Buf); SB_Terminate (&CurTok.SVal); } /* Free string memory */ SB_Done (&Buf); } void NextTok (void) /* Get next token and handle token level functions */ { /* Get the next raw token */ NextRawTok (); /* In raw mode, or when output is suppressed via conditional assembly, ** pass the token unchanged. */ if (RawMode == 0 && IfCond) { /* Execute token handling functions */ switch (CurTok.Tok) { case TOK_CONCAT: FuncConcat (); break; case TOK_LEFT: FuncLeft (); break; case TOK_MAKEIDENT: FuncIdent (); break; case TOK_MID: FuncMid (); break; case TOK_RIGHT: FuncRight (); break; case TOK_SPRINTF: FuncSPrintF (); break; case TOK_STRING: FuncString (); break; default: /* Quiet down gcc */ break; } } } void Consume (token_t Expected, const char* ErrMsg) /* Consume Expected, print an error if we don't find it */ { if (CurTok.Tok == Expected) { NextTok (); } else { Error ("%s", ErrMsg); } } void ConsumeSep (void) /* Consume a separator token */ { /* We expect a separator token */ ExpectSep (); /* If we are at end of line, skip it */ if (CurTok.Tok == TOK_SEP) { NextTok (); } } void ConsumeLParen (void) /* Consume a left paren */ { Consume (TOK_LPAREN, "'(' expected"); } void ConsumeRParen (void) /* Consume a right paren */ { Consume (TOK_RPAREN, "')' expected"); } void ConsumeComma (void) /* Consume a comma */ { Consume (TOK_COMMA, "',' expected"); } void SkipUntilSep (void) /* Skip tokens until we reach a line separator or end of file */ { while (!TokIsSep (CurTok.Tok)) { NextTok (); } } void ExpectSep (void) /* Check if we've reached a line separator, and output an error if not. Do ** not skip the line separator. */ { if (!TokIsSep (CurTok.Tok)) { ErrorSkip ("Unexpected trailing garbage characters"); } } void EnterRawTokenMode (void) /* Enter raw token mode. In raw mode, token handling functions are not ** executed, but the function tokens are passed untouched to the upper ** layer. Raw token mode is used when storing macro tokens for later ** use. ** Calls to EnterRawTokenMode and LeaveRawTokenMode may be nested. */ { ++RawMode; } void LeaveRawTokenMode (void) /* Leave raw token mode. */ { PRECONDITION (RawMode > 0); --RawMode; } ����������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/nexttok.h������������������������������������������������������������������������0000664�0000000�0000000�00000007510�13473601511�0015402�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* nexttok.h */ /* */ /* Get next token and handle token level functions */ /* */ /* */ /* */ /* (C) 2000-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef NEXTTOK_H #define NEXTTOK_H #include "scanner.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void NextTok (void); /* Get next token and handle token level functions */ void Consume (token_t Expected, const char* ErrMsg); /* Consume Token, print an error if we don't find it */ void ConsumeSep (void); /* Consume a separator token */ void ConsumeLParen (void); /* Consume a left paren */ void ConsumeRParen (void); /* Consume a right paren */ void ConsumeComma (void); /* Consume a comma */ void SkipUntilSep (void); /* Skip tokens until we reach a line separator or end of file */ void ExpectSep (void); /* Check if we've reached a line separator, and output an error if not. Do ** not skip the line separator. */ void EnterRawTokenMode (void); /* Enter raw token mode. In raw mode, token handling functions are not ** executed, but the function tokens are passed untouched to the upper ** layer. Raw token mode is used when storing macro tokens for later ** use. ** Calls to EnterRawTokenMode and LeaveRawTokenMode may be nested. */ void LeaveRawTokenMode (void); /* Leave raw token mode. */ /* End of nexttok.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/objcode.c������������������������������������������������������������������������0000664�0000000�0000000�00000017043�13473601511�0015310�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* objcode.c */ /* */ /* Objectcode management for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> #include <errno.h> /* cc65 */ #include "error.h" #include "fragment.h" #include "objcode.h" #include "segment.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Emit0 (unsigned char OPC) /* Emit an instruction with a zero sized operand */ { Fragment* F = GenFragment (FRAG_LITERAL, 1); F->V.Data[0] = OPC; } void Emit1 (unsigned char OPC, ExprNode* Value) /* Emit an instruction with an one byte argument */ { long V; Fragment* F; if (IsEasyConst (Value, &V)) { /* Must be in byte range */ if (!IsByteRange (V)) { Error ("Range error (%ld not in [0..255])", V); } /* Create a literal fragment */ F = GenFragment (FRAG_LITERAL, 2); F->V.Data[0] = OPC; F->V.Data[1] = (unsigned char) V; FreeExpr (Value); } else { /* Emit the opcode */ Emit0 (OPC); /* Emit the argument as an expression */ F = GenFragment (FRAG_EXPR, 1); F->V.Expr = Value; } } void Emit2 (unsigned char OPC, ExprNode* Value) /* Emit an instruction with a two byte argument */ { long V; Fragment* F; if (IsEasyConst (Value, &V)) { /* Must be in byte range */ if (!IsWordRange (V)) { Error ("Range error (%ld not in [0..65535])", V); } /* Create a literal fragment */ F = GenFragment (FRAG_LITERAL, 3); F->V.Data[0] = OPC; F->V.Data[1] = (unsigned char) V; F->V.Data[2] = (unsigned char) (V >> 8); FreeExpr (Value); } else { /* Emit the opcode */ Emit0 (OPC); /* Emit the argument as an expression */ F = GenFragment (FRAG_EXPR, 2); F->V.Expr = Value; } } void Emit3 (unsigned char OPC, ExprNode* Expr) /* Emit an instruction with a three byte argument */ { Emit0 (OPC); EmitFarAddr (Expr); } void EmitSigned (ExprNode* Expr, unsigned Size) /* Emit a signed expression with the given size */ { Fragment* F = GenFragment (FRAG_SEXPR, Size); F->V.Expr = Expr; } void EmitPCRel (unsigned char OPC, ExprNode* Expr, unsigned Size) /* Emit an opcode with a PC relative argument of one or two bytes */ { Emit0 (OPC); EmitSigned (Expr, Size); } void EmitData (const void* D, unsigned Size) /* Emit data into the current segment */ { /* Make a useful pointer from Data */ const unsigned char* Data = D; /* Create lots of fragments for the data */ while (Size) { Fragment* F; /* Determine the length of the next fragment */ unsigned Len = Size; if (Len > sizeof (F->V.Data)) { Len = sizeof (F->V.Data); } /* Create a new fragment */ F = GenFragment (FRAG_LITERAL, Len); /* Copy the data */ memcpy (F->V.Data, Data, Len); /* Next chunk */ Data += Len; Size -= Len; } } void EmitStrBuf (const StrBuf* Data) /* Emit a string into the current segment */ { /* Use EmitData to output the data */ EmitData (SB_GetConstBuf (Data), SB_GetLen (Data)); } void EmitByte (ExprNode* Expr) /* Emit one byte */ { long V; Fragment* F; if (IsEasyConst (Expr, &V)) { /* Must be in byte range */ if (!IsByteRange (V)) { Error ("Range error (%ld not in [0..255])", V); } /* Create a literal fragment */ F = GenFragment (FRAG_LITERAL, 1); F->V.Data[0] = (unsigned char) V; FreeExpr (Expr); } else { /* Emit the argument as an expression */ F = GenFragment (FRAG_EXPR, 1); F->V.Expr = Expr; } } void EmitWord (ExprNode* Expr) /* Emit one word */ { long V; Fragment* F; if (IsEasyConst (Expr, &V)) { /* Must be in byte range */ if (!IsWordRange (V)) { Error ("Range error (%ld not in [0..65535])", V); } /* Create a literal fragment */ F = GenFragment (FRAG_LITERAL, 2); F->V.Data[0] = (unsigned char) V; F->V.Data[1] = (unsigned char) (V >> 8); FreeExpr (Expr); } else { /* Emit the argument as an expression */ Fragment* F = GenFragment (FRAG_EXPR, 2); F->V.Expr = Expr; } } void EmitFarAddr (ExprNode* Expr) /* Emit a 24 bit expression */ { /* Create a new fragment */ Fragment* F = GenFragment (FRAG_EXPR, 3); /* Set the data */ F->V.Expr = Expr; } void EmitDWord (ExprNode* Expr) /* Emit one dword */ { /* Create a new fragment */ Fragment* F = GenFragment (FRAG_EXPR, 4); /* Set the data */ F->V.Expr = Expr; } void EmitFill (unsigned long Count) /* Emit Count fill bytes */ { while (Count) { /* Calculate the size of the next chunk */ unsigned Chunk = (Count > 0xFFFF)? 0xFFFF : (unsigned) Count; Count -= Chunk; /* Emit one chunk */ GenFragment (FRAG_FILL, Chunk); } } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/objcode.h������������������������������������������������������������������������0000664�0000000�0000000�00000007673�13473601511�0015325�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* objcode.h */ /* */ /* Objectcode management for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 1998-2008 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef OBJCODE_H #define OBJCODE_H /* ca65 */ #include "expr.h" #include "strbuf.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Emit0 (unsigned char OPC); /* Emit an instruction with a zero sized operand */ void Emit1 (unsigned char OPC, ExprNode* Value); /* Emit an instruction with an one byte argument */ void Emit2 (unsigned char OPC, ExprNode* Value); /* Emit an instruction with a two byte argument */ void Emit3 (unsigned char OPC, ExprNode* Expr); /* Emit an instruction with a three byte argument */ void EmitSigned (ExprNode* Expr, unsigned Size); /* Emit a signed expression with the given size */ void EmitPCRel (unsigned char OPC, ExprNode* Expr, unsigned Size); /* Emit an opcode with a PC relative argument of one or two bytes */ void EmitData (const void* Data, unsigned Size); /* Emit data into the current segment */ void EmitStrBuf (const StrBuf* Data); /* Emit a string into the current segment */ void EmitByte (ExprNode* Expr); /* Emit one byte */ void EmitWord (ExprNode* Expr); /* Emit one word */ void EmitFarAddr (ExprNode* Expr); /* Emit a 24 bit expression */ void EmitDWord (ExprNode* Expr); /* Emit one dword */ void EmitFill (unsigned long Count); /* Emit Count fill bytes */ /* End of objcode.h */ #endif ���������������������������������������������������������������������cc65-2.18/src/ca65/objfile.c������������������������������������������������������������������������0000664�0000000�0000000�00000031004�13473601511�0015306�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* objfile.c */ /* */ /* Object file writing routines for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> /* common */ #include "fname.h" #include "objdefs.h" /* ca65 */ #include "global.h" #include "error.h" #include "objfile.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* File descriptor */ static FILE* F = 0; /* Default extension */ #define OBJ_EXT ".o" /* Header structure */ static ObjHeader Header = { OBJ_MAGIC, /* 32: Magic number */ OBJ_VERSION, /* 16: Version number */ 0, /* 16: flags */ 0, /* 32: Offset to option table */ 0, /* 32: Size of options */ 0, /* 32: Offset to file table */ 0, /* 32: Size of files */ 0, /* 32: Offset to segment table */ 0, /* 32: Size of segment table */ 0, /* 32: Offset to import list */ 0, /* 32: Size of import list */ 0, /* 32: Offset to export list */ 0, /* 32: Size of export list */ 0, /* 32: Offset to list of debug symbols */ 0, /* 32: Size of debug symbols */ 0, /* 32: Offset to list of line infos */ 0, /* 32: Size of line infos */ 0, /* 32: Offset to string pool */ 0, /* 32: Size of string pool */ 0, /* 32: Offset to assertion table */ 0, /* 32: Size of assertion table */ 0, /* 32: Offset into scope table */ 0, /* 32: Size of scope table */ 0, /* 32: Offset into span table */ 0, /* 32: Size of span table */ }; /*****************************************************************************/ /* Internally used functions */ /*****************************************************************************/ static void ObjWriteError (void) /* Called on a write error. Will try to close and remove the file, then ** print a fatal error. */ { /* Remember the error */ int Error = errno; /* Force a close of the file, ignoring errors */ fclose (F); /* Try to remove the file, also ignoring errors */ remove (OutFile); /* Now abort with a fatal error */ Fatal ("Cannot write to output file '%s': %s", OutFile, strerror (Error)); } static void ObjWriteHeader (void) /* Write the object file header to the current file position */ { ObjWrite32 (Header.Magic); ObjWrite16 (Header.Version); ObjWrite16 (Header.Flags); ObjWrite32 (Header.OptionOffs); ObjWrite32 (Header.OptionSize); ObjWrite32 (Header.FileOffs); ObjWrite32 (Header.FileSize); ObjWrite32 (Header.SegOffs); ObjWrite32 (Header.SegSize); ObjWrite32 (Header.ImportOffs); ObjWrite32 (Header.ImportSize); ObjWrite32 (Header.ExportOffs); ObjWrite32 (Header.ExportSize); ObjWrite32 (Header.DbgSymOffs); ObjWrite32 (Header.DbgSymSize); ObjWrite32 (Header.LineInfoOffs); ObjWrite32 (Header.LineInfoSize); ObjWrite32 (Header.StrPoolOffs); ObjWrite32 (Header.StrPoolSize); ObjWrite32 (Header.AssertOffs); ObjWrite32 (Header.AssertSize); ObjWrite32 (Header.ScopeOffs); ObjWrite32 (Header.ScopeSize); ObjWrite32 (Header.SpanOffs); ObjWrite32 (Header.SpanSize); } /*****************************************************************************/ /* Code */ /*****************************************************************************/ void ObjOpen (void) /* Open the object file for writing, write a dummy header */ { /* Do we have a name for the output file? */ if (OutFile == 0) { /* We don't have an output name explicitly given, construct one from ** the name of the input file. */ OutFile = MakeFilename (InFile, OBJ_EXT); } /* Create the output file */ F = fopen (OutFile, "w+b"); if (F == 0) { Fatal ("Cannot open output file '%s': %s", OutFile, strerror (errno)); } /* Write a dummy header */ ObjWriteHeader (); } void ObjClose (void) /* Write an update header and close the object file. */ { /* Go back to the beginning */ if (fseek (F, 0, SEEK_SET) != 0) { ObjWriteError (); } /* If we have debug infos, set the flag in the header */ if (DbgSyms) { Header.Flags |= OBJ_FLAGS_DBGINFO; } /* Write the updated header */ ObjWriteHeader (); /* Close the file */ if (fclose (F) != 0) { ObjWriteError (); } } unsigned long ObjGetFilePos (void) /* Get the current file position */ { long Pos = ftell (F); if (Pos < 0) { ObjWriteError (); } return Pos; } void ObjSetFilePos (unsigned long Pos) /* Set the file position */ { if (fseek (F, Pos, SEEK_SET) != 0) { ObjWriteError (); } } void ObjWrite8 (unsigned V) /* Write an 8 bit value to the file */ { if (putc (V, F) == EOF) { ObjWriteError (); } } void ObjWrite16 (unsigned V) /* Write a 16 bit value to the file */ { ObjWrite8 (V); ObjWrite8 (V >> 8); } void ObjWrite24 (unsigned long V) /* Write a 24 bit value to the file */ { ObjWrite8 (V); ObjWrite8 (V >> 8); ObjWrite8 (V >> 16); } void ObjWrite32 (unsigned long V) /* Write a 32 bit value to the file */ { ObjWrite8 (V); ObjWrite8 (V >> 8); ObjWrite8 (V >> 16); ObjWrite8 (V >> 24); } void ObjWriteVar (unsigned long V) /* Write a variable sized value to the file in special encoding */ { /* We will write the value to the file in 7 bit chunks. If the 8th bit ** is clear, we're done, if it is set, another chunk follows. This will ** allow us to encode smaller values with less bytes, at the expense of ** needing 5 bytes if a 32 bit value is written to file. */ do { unsigned char C = (V & 0x7F); V >>= 7; if (V) { C |= 0x80; } ObjWrite8 (C); } while (V != 0); } void ObjWriteStr (const char* S) /* Write a string to the object file */ { unsigned Len = strlen (S); /* Write the string with the length preceeded (this is easier for ** the reading routine than the C format since the length is known in ** advance). */ ObjWriteVar (Len); ObjWriteData (S, Len); } void ObjWriteBuf (const StrBuf* S) /* Write a string to the object file */ { /* Write the string with the length preceeded (this is easier for ** the reading routine than the C format since the length is known in ** advance). */ ObjWriteVar (SB_GetLen (S)); ObjWriteData (SB_GetConstBuf (S), SB_GetLen (S)); } void ObjWriteData (const void* Data, unsigned Size) /* Write literal data to the file */ { if (fwrite (Data, 1, Size, F) != Size) { ObjWriteError (); } } void ObjWritePos (const FilePos* Pos) /* Write a file position to the object file */ { /* Write the data entries */ ObjWriteVar (Pos->Line); ObjWriteVar (Pos->Col); if (Pos->Name == 0) { /* Position is outside file scope, use the main file instead */ ObjWriteVar (0); } else { ObjWriteVar (Pos->Name - 1); } } void ObjStartOptions (void) /* Mark the start of the option section */ { Header.OptionOffs = ftell (F); } void ObjEndOptions (void) /* Mark the end of the option section */ { Header.OptionSize = ftell (F) - Header.OptionOffs; } void ObjStartFiles (void) /* Mark the start of the files section */ { Header.FileOffs = ftell (F); } void ObjEndFiles (void) /* Mark the end of the files section */ { Header.FileSize = ftell (F) - Header.FileOffs; } void ObjStartSegments (void) /* Mark the start of the segment section */ { Header.SegOffs = ftell (F); } void ObjEndSegments (void) /* Mark the end of the segment section */ { Header.SegSize = ftell (F) - Header.SegOffs; } void ObjStartImports (void) /* Mark the start of the import section */ { Header.ImportOffs = ftell (F); } void ObjEndImports (void) /* Mark the end of the import section */ { Header.ImportSize = ftell (F) - Header.ImportOffs; } void ObjStartExports (void) /* Mark the start of the export section */ { Header.ExportOffs = ftell (F); } void ObjEndExports (void) /* Mark the end of the export section */ { Header.ExportSize = ftell (F) - Header.ExportOffs; } void ObjStartDbgSyms (void) /* Mark the start of the debug symbol section */ { Header.DbgSymOffs = ftell (F); } void ObjEndDbgSyms (void) /* Mark the end of the debug symbol section */ { Header.DbgSymSize = ftell (F) - Header.DbgSymOffs; } void ObjStartLineInfos (void) /* Mark the start of the line info section */ { Header.LineInfoOffs = ftell (F); } void ObjEndLineInfos (void) /* Mark the end of the line info section */ { Header.LineInfoSize = ftell (F) - Header.LineInfoOffs; } void ObjStartStrPool (void) /* Mark the start of the string pool section */ { Header.StrPoolOffs = ftell (F); } void ObjEndStrPool (void) /* Mark the end of the string pool section */ { Header.StrPoolSize = ftell (F) - Header.StrPoolOffs; } void ObjStartAssertions (void) /* Mark the start of the assertion table */ { Header.AssertOffs = ftell (F); } void ObjEndAssertions (void) /* Mark the end of the assertion table */ { Header.AssertSize = ftell (F) - Header.AssertOffs; } void ObjStartScopes (void) /* Mark the start of the scope table */ { Header.ScopeOffs = ftell (F); } void ObjEndScopes (void) /* Mark the end of the scope table */ { Header.ScopeSize = ftell (F) - Header.ScopeOffs; } void ObjStartSpans (void) /* Mark the start of the span table */ { Header.SpanOffs = ftell (F); } void ObjEndSpans (void) /* Mark the end of the span table */ { Header.SpanSize = ftell (F) - Header.SpanOffs; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/objfile.h������������������������������������������������������������������������0000664�0000000�0000000�00000012646�13473601511�0015326�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* objfile.h */ /* */ /* Object file writing routines for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef OBJFILE_H #define OBJFILE_H /* common */ #include "filepos.h" #include "strbuf.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void ObjOpen (void); /* Open the object file for writing, write a dummy header */ void ObjClose (void); /* Write an update header and close the object file. */ unsigned long ObjGetFilePos (void); /* Get the current file position */ void ObjSetFilePos (unsigned long Pos); /* Set the file position */ void ObjWrite8 (unsigned V); /* Write an 8 bit value to the file */ void ObjWrite16 (unsigned V); /* Write a 16 bit value to the file */ void ObjWrite24 (unsigned long V); /* Write a 24 bit value to the file */ void ObjWrite32 (unsigned long V); /* Write a 32 bit value to the file */ void ObjWriteVar (unsigned long V); /* Write a variable sized value to the file in special encoding */ void ObjWriteStr (const char* S); /* Write a string to the object file */ void ObjWriteBuf (const StrBuf* S); /* Write a string to the object file */ void ObjWriteData (const void* Data, unsigned Size); /* Write literal data to the file */ void ObjWritePos (const FilePos* Pos); /* Write a file position to the object file */ void ObjStartOptions (void); /* Mark the start of the option section */ void ObjEndOptions (void); /* Mark the end of the option section */ void ObjStartFiles (void); /* Mark the start of the files section */ void ObjEndFiles (void); /* Mark the end of the files section */ void ObjStartSegments (void); /* Mark the start of the segment section */ void ObjEndSegments (void); /* Mark the end of the segment section */ void ObjStartImports (void); /* Mark the start of the import section */ void ObjEndImports (void); /* Mark the end of the import section */ void ObjStartExports (void); /* Mark the start of the export section */ void ObjEndExports (void); /* Mark the end of the export section */ void ObjStartDbgSyms (void); /* Mark the start of the debug symbol section */ void ObjEndDbgSyms (void); /* Mark the end of the debug symbol section */ void ObjStartLineInfos (void); /* Mark the start of the line info section */ void ObjEndLineInfos (void); /* Mark the end of the line info section */ void ObjStartStrPool (void); /* Mark the start of the string pool section */ void ObjEndStrPool (void); /* Mark the end of the string pool section */ void ObjStartAssertions (void); /* Mark the start of the assertion table */ void ObjEndAssertions (void); /* Mark the end of the assertion table */ void ObjStartScopes (void); /* Mark the start of the scope table */ void ObjEndScopes (void); /* Mark the end of the scope table */ void ObjStartSpans (void); /* Mark the start of the span table */ void ObjEndSpans (void); /* Mark the end of the span table */ /* End of objfile.h */ #endif ������������������������������������������������������������������������������������������cc65-2.18/src/ca65/options.c������������������������������������������������������������������������0000664�0000000�0000000�00000012404�13473601511�0015372�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* options.c */ /* */ /* Object file options for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 1998-2008, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* common */ #include "optdefs.h" #include "xmalloc.h" /* ca65 */ #include "error.h" #include "objfile.h" #include "options.h" #include "spool.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Option list */ static Option* OptRoot = 0; static Option* OptLast = 0; static unsigned OptCount = 0; /*****************************************************************************/ /* Code */ /*****************************************************************************/ static Option* NewOption (unsigned char Type, unsigned long Val) /* Create a new option, insert it into the list and return it */ { Option* Opt; /* Allocate memory */ Opt = xmalloc (sizeof (*Opt)); /* Initialize fields */ Opt->Next = 0; Opt->Type = Type; Opt->Val = Val; /* Insert it into the list */ if (OptRoot == 0) { OptRoot = Opt; } else { OptLast->Next = Opt; } OptLast = Opt; /* One more option now */ ++OptCount; /* Return the new struct */ return Opt; } void OptStr (unsigned char Type, const StrBuf* Text) /* Add a string option */ { NewOption (Type, GetStrBufId (Text)); } void OptComment (const StrBuf* Comment) /* Add a comment */ { NewOption (OPT_COMMENT, GetStrBufId (Comment)); } void OptAuthor (const StrBuf* Author) /* Add an author statement */ { NewOption (OPT_AUTHOR, GetStrBufId (Author)); } void OptTranslator (const StrBuf* Translator) /* Add a translator option */ { NewOption (OPT_TRANSLATOR, GetStrBufId (Translator)); } void OptCompiler (const StrBuf* Compiler) /* Add a compiler option */ { NewOption (OPT_COMPILER, GetStrBufId (Compiler)); } void OptOS (const StrBuf* OS) /* Add an operating system option */ { NewOption (OPT_OS, GetStrBufId (OS)); } void OptDateTime (unsigned long DateTime) /* Add a date/time option */ { NewOption (OPT_DATETIME, DateTime); } void WriteOptions (void) /* Write the options to the object file */ { Option* O; /* Tell the object file module that we're about to start the options */ ObjStartOptions (); /* Write the option count */ ObjWriteVar (OptCount); /* Walk through the list and write the options */ O = OptRoot; while (O) { /* Write the type of the option, then the value */ ObjWrite8 (O->Type); ObjWriteVar (O->Val); /* Next option */ O = O->Next; } /* Done writing options */ ObjEndOptions (); } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/options.h������������������������������������������������������������������������0000664�0000000�0000000�00000006575�13473601511�0015413�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* options.h */ /* */ /* Object file options for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 1998-2008, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef OPTIONS_H #define OPTIONS_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ void OptStr (unsigned char Type, const StrBuf* Text); /* Add a string option */ void OptComment (const StrBuf* Comment); /* Add a comment */ void OptAuthor (const StrBuf* Author); /* Add an author statement */ void OptTranslator (const StrBuf* Translator); /* Add a translator option */ void OptCompiler (const StrBuf* Compiler); /* Add a compiler option */ void OptOS (const StrBuf* OS); /* Add an operating system option */ void OptDateTime (unsigned long DateTime); /* Add a date/time option */ void WriteOptions (void); /* Write the options to the object file */ /* End of options.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/pseudo.c�������������������������������������������������������������������������0000664�0000000�0000000�00000152070�13473601511�0015202�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* pseudo.c */ /* */ /* Pseudo instructions for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <errno.h> /* common */ #include "alignment.h" #include "assertion.h" #include "bitops.h" #include "cddefs.h" #include "coll.h" #include "filestat.h" #include "gentype.h" #include "intstack.h" #include "scopedefs.h" #include "symdefs.h" #include "tgttrans.h" #include "xmalloc.h" /* ca65 */ #include "anonname.h" #include "asserts.h" #include "condasm.h" #include "dbginfo.h" #include "enum.h" #include "error.h" #include "expr.h" #include "feature.h" #include "filetab.h" #include "global.h" #include "incpath.h" #include "instr.h" #include "listing.h" #include "macro.h" #include "nexttok.h" #include "objcode.h" #include "options.h" #include "pseudo.h" #include "repeat.h" #include "segment.h" #include "sizeof.h" #include "span.h" #include "spool.h" #include "struct.h" #include "symbol.h" #include "symtab.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Keyword we're about to handle */ static StrBuf Keyword = STATIC_STRBUF_INITIALIZER; /* CPU stack */ static IntStack CPUStack = STATIC_INTSTACK_INITIALIZER; /* Segment stack */ #define MAX_PUSHED_SEGMENTS 16 static Collection SegStack = STATIC_COLLECTION_INITIALIZER; /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ static void DoUnexpected (void); /* Got an unexpected keyword */ static void DoInvalid (void); /* Handle a token that is invalid here, since it should have been handled on ** a much lower level of the expression hierarchy. Getting this sort of token ** means that the lower level code has bugs. ** This function differs to DoUnexpected in that the latter may be triggered ** by the user by using keywords in the wrong location. DoUnexpected is not ** an error in the assembler itself, while DoInvalid is. */ /*****************************************************************************/ /* Helper functions */ /*****************************************************************************/ static unsigned char OptionalAddrSize (void) /* If a colon follows, parse an optional address size spec and return it. ** Otherwise return ADDR_SIZE_DEFAULT. */ { unsigned AddrSize = ADDR_SIZE_DEFAULT; if (CurTok.Tok == TOK_COLON) { NextTok (); AddrSize = ParseAddrSize (); if (!ValidAddrSizeForCPU (AddrSize)) { /* Print an error and reset to default */ Error ("Invalid address size specification for current CPU"); AddrSize = ADDR_SIZE_DEFAULT; } NextTok (); } return AddrSize; } static void SetBoolOption (unsigned char* Flag) /* Read a on/off/+/- option and set flag accordingly */ { static const char* const Keys[] = { "OFF", "ON", }; if (CurTok.Tok == TOK_PLUS) { *Flag = 1; NextTok (); } else if (CurTok.Tok == TOK_MINUS) { *Flag = 0; NextTok (); } else if (CurTok.Tok == TOK_IDENT) { /* Map the keyword to a number */ switch (GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]))) { case 0: *Flag = 0; NextTok (); break; case 1: *Flag = 1; NextTok (); break; default: ErrorSkip ("'on' or 'off' expected"); break; } } else if (TokIsSep (CurTok.Tok)) { /* Without anything assume switch on */ *Flag = 1; } else { ErrorSkip ("'on' or 'off' expected"); } } static void ExportWithAssign (SymEntry* Sym, unsigned char AddrSize, unsigned Flags) /* Allow to assign the value of an export in an .export statement */ { /* The name and optional address size spec may be followed by an assignment ** or equal token. */ if (CurTok.Tok == TOK_ASSIGN || CurTok.Tok == TOK_EQ) { /* Assignment means the symbol is a label */ if (CurTok.Tok == TOK_ASSIGN) { Flags |= SF_LABEL; } /* Skip the assignment token */ NextTok (); /* Define the symbol with the expression following the '=' */ SymDef (Sym, Expression(), ADDR_SIZE_DEFAULT, Flags); } /* Now export the symbol */ SymExport (Sym, AddrSize, Flags); } static void ExportImport (void (*Func) (SymEntry*, unsigned char, unsigned), unsigned char DefAddrSize, unsigned Flags) /* Export or import symbols */ { SymEntry* Sym; unsigned char AddrSize; while (1) { /* We need an identifier here */ if (CurTok.Tok != TOK_IDENT) { ErrorSkip ("Identifier expected"); return; } /* Find the symbol table entry, allocate a new one if necessary */ Sym = SymFind (CurrentScope, &CurTok.SVal, SYM_ALLOC_NEW); /* Skip the name */ NextTok (); /* Get an optional address size */ AddrSize = OptionalAddrSize (); if (AddrSize == ADDR_SIZE_DEFAULT) { AddrSize = DefAddrSize; } /* Call the actual import/export function */ Func (Sym, AddrSize, Flags); /* More symbols? */ if (CurTok.Tok == TOK_COMMA) { NextTok (); } else { break; } } } static long IntArg (long Min, long Max) /* Read an integer argument and check a range. Accept the token "unlimited" ** and return -1 in this case. */ { if (CurTok.Tok == TOK_IDENT && SB_CompareStr (&CurTok.SVal, "unlimited") == 0) { NextTok (); return -1; } else { long Val = ConstExpression (); if (Val < Min || Val > Max) { Error ("Range error"); Val = Min; } return Val; } } static void ConDes (const StrBuf* Name, unsigned Type) /* Parse remaining line for constructor/destructor of the remaining type */ { long Prio; /* Find the symbol table entry, allocate a new one if necessary */ SymEntry* Sym = SymFind (CurrentScope, Name, SYM_ALLOC_NEW); /* Optional constructor priority */ if (CurTok.Tok == TOK_COMMA) { /* Priority value follows */ NextTok (); Prio = ConstExpression (); if (Prio < CD_PRIO_MIN || Prio > CD_PRIO_MAX) { /* Value out of range */ Error ("Range error"); return; } } else { /* Use the default priority value */ Prio = CD_PRIO_DEF; } /* Define the symbol */ SymConDes (Sym, ADDR_SIZE_DEFAULT, Type, (unsigned) Prio); } static StrBuf* GenArrayType (StrBuf* Type, unsigned SpanSize, const char* ElementType, unsigned ElementTypeLen) /* Create an array (or single data) of the given type. SpanSize is the size ** of the span, ElementType is a string that encodes the element data type. ** The function returns Type. */ { /* Get the size of the element type */ unsigned ElementSize = GT_GET_SIZE (ElementType[0]); /* Get the number of array elements */ unsigned ElementCount = SpanSize / ElementSize; /* The span size must be divideable by the element size */ CHECK ((SpanSize % ElementSize) == 0); /* Encode the array */ GT_AddArray (Type, ElementCount); SB_AppendBuf (Type, ElementType, ElementTypeLen); /* Return the pointer to the created array type */ return Type; } /*****************************************************************************/ /* Handler functions */ /*****************************************************************************/ static void DoA16 (void) /* Switch the accu to 16 bit mode (assembler only) */ { if (GetCPU() != CPU_65816) { Error ("Command is only valid in 65816 mode"); } else { /* Immidiate mode has two extension bytes */ ExtBytes [AM65I_IMM_ACCU] = 2; } } static void DoA8 (void) /* Switch the accu to 8 bit mode (assembler only) */ { if (GetCPU() != CPU_65816) { Error ("Command is only valid in 65816 mode"); } else { /* Immidiate mode has one extension byte */ ExtBytes [AM65I_IMM_ACCU] = 1; } } static void DoAddr (void) /* Define addresses */ { /* Element type for the generated array */ static const char EType[2] = { GT_PTR, GT_VOID }; /* Record type information */ Span* S = OpenSpan (); StrBuf Type = STATIC_STRBUF_INITIALIZER; /* Parse arguments */ while (1) { ExprNode* Expr = Expression (); if (GetCPU () == CPU_65816 || ForceRange) { /* Do a range check */ Expr = GenWordExpr (Expr); } EmitWord (Expr); if (CurTok.Tok != TOK_COMMA) { break; } else { NextTok (); } } /* Close the span, then add type information to it */ S = CloseSpan (S); SetSpanType (S, GenArrayType (&Type, GetSpanSize (S), EType, sizeof (EType))); /* Free the strings */ SB_Done (&Type); } static void DoAlign (void) /* Align the PC to some boundary */ { long FillVal; long Alignment; /* Read the alignment value */ Alignment = ConstExpression (); if (Alignment <= 0 || (unsigned long) Alignment > MAX_ALIGNMENT) { ErrorSkip ("Range error"); return; } /* Optional value follows */ if (CurTok.Tok == TOK_COMMA) { NextTok (); FillVal = ConstExpression (); /* We need a byte value here */ if (!IsByteRange (FillVal)) { ErrorSkip ("Range error"); return; } } else { FillVal = -1; } /* Generate the alignment */ SegAlign (Alignment, (int) FillVal); } static void DoASCIIZ (void) /* Define text with a zero terminator */ { while (1) { /* Must have a string constant */ if (CurTok.Tok != TOK_STRCON) { ErrorSkip ("String constant expected"); return; } /* Translate into target charset and emit */ TgtTranslateStrBuf (&CurTok.SVal); EmitStrBuf (&CurTok.SVal); NextTok (); if (CurTok.Tok == TOK_COMMA) { NextTok (); } else { break; } } Emit0 (0); } static void DoAssert (void) /* Add an assertion */ { static const char* const ActionTab [] = { "WARN", "WARNING", "ERROR", "LDWARN", "LDWARNING", "LDERROR", }; AssertAction Action; unsigned Msg; /* First we have the expression that has to evaluated */ ExprNode* Expr = Expression (); ConsumeComma (); /* Action follows */ if (CurTok.Tok != TOK_IDENT) { ErrorSkip ("Identifier expected"); return; } switch (GetSubKey (ActionTab, sizeof (ActionTab) / sizeof (ActionTab[0]))) { case 0: case 1: /* Warning */ Action = ASSERT_ACT_WARN; break; case 2: /* Error */ Action = ASSERT_ACT_ERROR; break; case 3: case 4: /* Linker warning */ Action = ASSERT_ACT_LDWARN; break; case 5: /* Linker error */ Action = ASSERT_ACT_LDERROR; break; default: Error ("Illegal assert action specifier"); /* Use lderror - there won't be an .o file anyway */ Action = ASSERT_ACT_LDERROR; break; } NextTok (); /* We can have an optional message. If no message is present, use ** "Assertion failed". */ if (CurTok.Tok == TOK_COMMA) { /* Skip the comma */ NextTok (); /* Read the message */ if (CurTok.Tok != TOK_STRCON) { ErrorSkip ("String constant expected"); return; } /* Translate the message into a string id. We can then skip the input ** string. */ Msg = GetStrBufId (&CurTok.SVal); NextTok (); } else { /* Use "Assertion failed" */ Msg = GetStringId ("Assertion failed"); } /* Remember the assertion */ AddAssertion (Expr, (AssertAction) Action, Msg); } static void DoAutoImport (void) /* Mark unresolved symbols as imported */ { SetBoolOption (&AutoImport); } static void DoBankBytes (void) /* Define bytes, extracting the bank byte from each expression in the list */ { while (1) { EmitByte (FuncBankByte ()); if (CurTok.Tok != TOK_COMMA) { break; } else { NextTok (); } } } static void DoBss (void) /* Switch to the BSS segment */ { UseSeg (&BssSegDef); } static void DoByte (void) /* Define bytes */ { /* Element type for the generated array */ static const char EType[1] = { GT_BYTE }; /* Record type information */ Span* S = OpenSpan (); StrBuf Type = AUTO_STRBUF_INITIALIZER; /* Parse arguments */ while (1) { if (CurTok.Tok == TOK_STRCON) { /* A string, translate into target charset and emit */ TgtTranslateStrBuf (&CurTok.SVal); EmitStrBuf (&CurTok.SVal); NextTok (); } else { EmitByte (BoundedExpr (Expression, 1)); } if (CurTok.Tok != TOK_COMMA) { break; } else { NextTok (); /* Do smart handling of dangling comma */ if (CurTok.Tok == TOK_SEP) { Error ("Unexpected end of line"); break; } } } /* Close the span, then add type information to it. ** Note: empty string operands emit nothing; ** so, add a type only if there's a span. */ S = CloseSpan (S); if (S != 0) { SetSpanType (S, GenArrayType (&Type, GetSpanSize (S), EType, sizeof (EType))); } /* Free the type string */ SB_Done (&Type); } static void DoCase (void) /* Switch the IgnoreCase option */ { SetBoolOption (&IgnoreCase); IgnoreCase = !IgnoreCase; } static void DoCharMap (void) /* Allow custom character mappings */ { long Index; long Code; /* Read the index as numerical value */ Index = ConstExpression (); if (Index < 0 || Index > 255) { /* Value out of range */ ErrorSkip ("Index range error"); return; } /* Comma follows */ ConsumeComma (); /* Read the character code */ Code = ConstExpression (); if (Code < 0 || Code > 255) { /* Value out of range */ ErrorSkip ("Code range error"); return; } /* Set the character translation */ TgtTranslateSet ((unsigned) Index, (unsigned char) Code); } static void DoCode (void) /* Switch to the code segment */ { UseSeg (&CodeSegDef); } static void DoConDes (void) /* Export a symbol as constructor/destructor */ { static const char* const Keys[] = { "CONSTRUCTOR", "DESTRUCTOR", "INTERRUPTOR", }; StrBuf Name = STATIC_STRBUF_INITIALIZER; long Type; /* Symbol name follows */ if (CurTok.Tok != TOK_IDENT) { ErrorSkip ("Identifier expected"); return; } SB_Copy (&Name, &CurTok.SVal); NextTok (); /* Type follows. May be encoded as identifier or numerical */ ConsumeComma (); if (CurTok.Tok == TOK_IDENT) { /* Map the following keyword to a number, then skip it */ Type = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0])); NextTok (); /* Check if we got a valid keyword */ if (Type < 0) { ErrorSkip ("Syntax error"); goto ExitPoint; } } else { /* Read the type as numerical value */ Type = ConstExpression (); if (Type < CD_TYPE_MIN || Type > CD_TYPE_MAX) { /* Value out of range */ ErrorSkip ("Range error"); goto ExitPoint; } } /* Parse the remainder of the line and export the symbol */ ConDes (&Name, (unsigned) Type); ExitPoint: /* Free string memory */ SB_Done (&Name); } static void DoConstructor (void) /* Export a symbol as constructor */ { StrBuf Name = STATIC_STRBUF_INITIALIZER; /* Symbol name follows */ if (CurTok.Tok != TOK_IDENT) { ErrorSkip ("Identifier expected"); return; } SB_Copy (&Name, &CurTok.SVal); NextTok (); /* Parse the remainder of the line and export the symbol */ ConDes (&Name, CD_TYPE_CON); /* Free string memory */ SB_Done (&Name); } static void DoData (void) /* Switch to the data segment */ { UseSeg (&DataSegDef); } static void DoDbg (void) /* Add debug information from high level code */ { static const char* const Keys[] = { "FILE", "FUNC", "LINE", "SYM", }; int Key; /* We expect a subkey */ if (CurTok.Tok != TOK_IDENT) { ErrorSkip ("Identifier expected"); return; } /* Map the following keyword to a number */ Key = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0])); /* Skip the subkey */ NextTok (); /* Check the key and dispatch to a handler */ switch (Key) { case 0: DbgInfoFile (); break; case 1: DbgInfoFunc (); break; case 2: DbgInfoLine (); break; case 3: DbgInfoSym (); break; default: ErrorSkip ("Syntax error"); break; } } static void DoDByt (void) /* Output double bytes */ { /* Element type for the generated array */ static const char EType[1] = { GT_DBYTE }; /* Record type information */ Span* S = OpenSpan (); StrBuf Type = STATIC_STRBUF_INITIALIZER; /* Parse arguments */ while (1) { EmitWord (GenSwapExpr (BoundedExpr (Expression, 2))); if (CurTok.Tok != TOK_COMMA) { break; } else { NextTok (); } } /* Close the span, then add type information to it */ S = CloseSpan (S); SetSpanType (S, GenArrayType (&Type, GetSpanSize (S), EType, sizeof (EType))); /* Free the type string */ SB_Done (&Type); } static void DoDebugInfo (void) /* Switch debug info on or off */ { SetBoolOption (&DbgSyms); } static void DoDefine (void) /* Define a one line macro */ { MacDef (MAC_STYLE_DEFINE); } static void DoDelMac (void) /* Delete a classic macro */ { /* We expect an identifier */ if (CurTok.Tok != TOK_IDENT) { ErrorSkip ("Identifier expected"); } else { MacUndef (&CurTok.SVal, MAC_STYLE_CLASSIC); NextTok (); } } static void DoDestructor (void) /* Export a symbol as destructor */ { StrBuf Name = STATIC_STRBUF_INITIALIZER; /* Symbol name follows */ if (CurTok.Tok != TOK_IDENT) { ErrorSkip ("Identifier expected"); return; } SB_Copy (&Name, &CurTok.SVal); NextTok (); /* Parse the remainder of the line and export the symbol */ ConDes (&Name, CD_TYPE_DES); /* Free string memory */ SB_Done (&Name); } static void DoDWord (void) /* Define dwords */ { while (1) { EmitDWord (BoundedExpr (Expression, 4)); if (CurTok.Tok != TOK_COMMA) { break; } else { NextTok (); } } } static void DoEnd (void) /* End of assembly */ { ForcedEnd = 1; NextTok (); } static void DoEndProc (void) /* Leave a lexical level */ { if (CurrentScope->Type != SCOPE_SCOPE || CurrentScope->Label == 0) { /* No local scope */ ErrorSkip ("No open .PROC"); } else { SymLeaveLevel (); } } static void DoEndScope (void) /* Leave a lexical level */ { if (CurrentScope->Type != SCOPE_SCOPE || CurrentScope->Label != 0) { /* No local scope */ ErrorSkip ("No open .SCOPE"); } else { SymLeaveLevel (); } } static void DoError (void) /* User error */ { if (CurTok.Tok != TOK_STRCON) { ErrorSkip ("String constant expected"); } else { Error ("User error: %m%p", &CurTok.SVal); SkipUntilSep (); } } static void DoExitMacro (void) /* Exit a macro expansion */ { if (!InMacExpansion ()) { /* We aren't expanding a macro currently */ DoUnexpected (); } else { MacAbort (); } } static void DoExport (void) /* Export a symbol */ { ExportImport (ExportWithAssign, ADDR_SIZE_DEFAULT, SF_NONE); } static void DoExportZP (void) /* Export a zeropage symbol */ { ExportImport (ExportWithAssign, ADDR_SIZE_ZP, SF_NONE); } static void DoFarAddr (void) /* Define far addresses (24 bit) */ { /* Element type for the generated array */ static const char EType[2] = { GT_FAR_PTR, GT_VOID }; /* Record type information */ Span* S = OpenSpan (); StrBuf Type = STATIC_STRBUF_INITIALIZER; /* Parse arguments */ while (1) { EmitFarAddr (BoundedExpr (Expression, 3)); if (CurTok.Tok != TOK_COMMA) { break; } else { NextTok (); } } /* Close the span, then add type information to it */ S = CloseSpan (S); SetSpanType (S, GenArrayType (&Type, GetSpanSize (S), EType, sizeof (EType))); /* Free the type string */ SB_Done (&Type); } static void DoFatal (void) /* Fatal user error */ { if (CurTok.Tok != TOK_STRCON) { ErrorSkip ("String constant expected"); } else { Fatal ("User error: %m%p", &CurTok.SVal); SkipUntilSep (); } } static void DoFeature (void) /* Switch the Feature option */ { /* Allow a list of comma separated keywords */ while (1) { /* We expect an identifier */ if (CurTok.Tok != TOK_IDENT) { ErrorSkip ("Identifier expected"); return; } /* Make the string attribute lower case */ LocaseSVal (); /* Set the feature and check for errors */ if (SetFeature (&CurTok.SVal) == FEAT_UNKNOWN) { /* Not found */ ErrorSkip ("Invalid feature: '%m%p'", &CurTok.SVal); return; } else { /* Skip the keyword */ NextTok (); } /* Allow more than one keyword */ if (CurTok.Tok == TOK_COMMA) { NextTok (); } else { break; } } } static void DoFileOpt (void) /* Insert a file option */ { long OptNum; /* The option type may be given as a keyword or as a number. */ if (CurTok.Tok == TOK_IDENT) { /* Option given as keyword */ static const char* const Keys [] = { "AUTHOR", "COMMENT", "COMPILER" }; /* Map the option to a number */ OptNum = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0])); if (OptNum < 0) { /* Not found */ ErrorSkip ("File option keyword expected"); return; } /* Skip the keyword */ NextTok (); /* Must be followed by a comma */ ConsumeComma (); /* We accept only string options for now */ if (CurTok.Tok != TOK_STRCON) { ErrorSkip ("String constant expected"); return; } /* Insert the option */ switch (OptNum) { case 0: /* Author */ OptAuthor (&CurTok.SVal); break; case 1: /* Comment */ OptComment (&CurTok.SVal); break; case 2: /* Compiler */ OptCompiler (&CurTok.SVal); break; default: Internal ("Invalid OptNum: %ld", OptNum); } /* Done */ NextTok (); } else { /* Option given as number */ OptNum = ConstExpression (); if (!IsByteRange (OptNum)) { ErrorSkip ("Range error"); return; } /* Must be followed by a comma */ ConsumeComma (); /* We accept only string options for now */ if (CurTok.Tok != TOK_STRCON) { ErrorSkip ("String constant expected"); return; } /* Insert the option */ OptStr ((unsigned char) OptNum, &CurTok.SVal); /* Done */ NextTok (); } } static void DoForceImport (void) /* Do a forced import on a symbol */ { ExportImport (SymImport, ADDR_SIZE_DEFAULT, SF_FORCED); } static void DoGlobal (void) /* Declare a global symbol */ { ExportImport (SymGlobal, ADDR_SIZE_DEFAULT, SF_NONE); } static void DoGlobalZP (void) /* Declare a global zeropage symbol */ { ExportImport (SymGlobal, ADDR_SIZE_ZP, SF_NONE); } static void DoHiBytes (void) /* Define bytes, extracting the hi byte from each expression in the list */ { while (1) { EmitByte (FuncHiByte ()); if (CurTok.Tok != TOK_COMMA) { break; } else { NextTok (); } } } static void DoI16 (void) /* Switch the index registers to 16 bit mode (assembler only) */ { if (GetCPU() != CPU_65816) { Error ("Command is only valid in 65816 mode"); } else { /* Immidiate mode has two extension bytes */ ExtBytes [AM65I_IMM_INDEX] = 2; } } static void DoI8 (void) /* Switch the index registers to 16 bit mode (assembler only) */ { if (GetCPU() != CPU_65816) { Error ("Command is only valid in 65816 mode"); } else { /* Immidiate mode has one extension byte */ ExtBytes [AM65I_IMM_INDEX] = 1; } } static void DoImport (void) /* Import a symbol */ { ExportImport (SymImport, ADDR_SIZE_DEFAULT, SF_NONE); } static void DoImportZP (void) /* Import a zero page symbol */ { ExportImport (SymImport, ADDR_SIZE_ZP, SF_NONE); } static void DoIncBin (void) /* Include a binary file */ { StrBuf Name = STATIC_STRBUF_INITIALIZER; struct stat StatBuf; long Start = 0L; long Count = -1L; long Size; FILE* F; /* Name must follow */ if (CurTok.Tok != TOK_STRCON) { ErrorSkip ("String constant expected"); return; } SB_Copy (&Name, &CurTok.SVal); SB_Terminate (&Name); NextTok (); /* A starting offset may follow */ if (CurTok.Tok == TOK_COMMA) { NextTok (); Start = ConstExpression (); /* And a length may follow */ if (CurTok.Tok == TOK_COMMA) { NextTok (); Count = ConstExpression (); } } /* Try to open the file */ F = fopen (SB_GetConstBuf (&Name), "rb"); if (F == 0) { /* Search for the file in the binary include directory */ char* PathName = SearchFile (BinSearchPath, SB_GetConstBuf (&Name)); if (PathName == 0 || (F = fopen (PathName, "rb")) == 0) { /* Not found or cannot open, print an error and bail out */ ErrorSkip ("Cannot open include file '%m%p': %s", &Name, strerror (errno)); xfree (PathName); goto ExitPoint; } /* Remember the new file name */ SB_CopyStr (&Name, PathName); /* Free the allocated memory */ xfree (PathName); } /* Get the size of the file */ fseek (F, 0, SEEK_END); Size = ftell (F); /* Stat the file and remember the values. There's a race condition here, ** since we cannot use fileno() (non-standard identifier in standard ** header file), and therefore not fstat. When using stat with the ** file name, there's a risk that the file was deleted and recreated ** while it was open. Since mtime and size are only used to check ** if a file has changed in the debugger, we will ignore this problem ** here. */ SB_Terminate (&Name); if (FileStat (SB_GetConstBuf (&Name), &StatBuf) != 0) { Fatal ("Cannot stat input file '%m%p': %s", &Name, strerror (errno)); } /* Add the file to the input file table */ AddFile (&Name, FT_BINARY, Size, (unsigned long) StatBuf.st_mtime); /* If a count was not given, calculate it now */ if (Count < 0) { Count = Size - Start; if (Count < 0) { /* Nothing to read - flag this as a range error */ ErrorSkip ("Range error"); goto Done; } } else { /* Count was given, check if it is valid */ if (Start + Count > Size) { ErrorSkip ("Range error"); goto Done; } } /* Seek to the start position */ fseek (F, Start, SEEK_SET); /* Read chunks and insert them into the output */ while (Count > 0) { unsigned char Buf [1024]; /* Calculate the number of bytes to read */ size_t BytesToRead = (Count > (long)sizeof(Buf))? sizeof(Buf) : (size_t) Count; /* Read chunk */ size_t BytesRead = fread (Buf, 1, BytesToRead, F); if (BytesToRead != BytesRead) { /* Some sort of error */ ErrorSkip ("Cannot read from include file '%m%p': %s", &Name, strerror (errno)); break; } /* Insert it into the output */ EmitData (Buf, BytesRead); /* Keep the counters current */ Count -= BytesRead; } Done: /* Close the file, ignore errors since it's r/o */ (void) fclose (F); ExitPoint: /* Free string memory */ SB_Done (&Name); } static void DoInclude (void) /* Include another file */ { /* Name must follow */ if (CurTok.Tok != TOK_STRCON) { ErrorSkip ("String constant expected"); } else { SB_Terminate (&CurTok.SVal); if (NewInputFile (SB_GetConstBuf (&CurTok.SVal)) == 0) { /* Error opening the file, skip remainder of line */ SkipUntilSep (); } } } static void DoInterruptor (void) /* Export a symbol as interruptor */ { StrBuf Name = STATIC_STRBUF_INITIALIZER; /* Symbol name follows */ if (CurTok.Tok != TOK_IDENT) { ErrorSkip ("Identifier expected"); return; } SB_Copy (&Name, &CurTok.SVal); NextTok (); /* Parse the remainder of the line and export the symbol */ ConDes (&Name, CD_TYPE_INT); /* Free string memory */ SB_Done (&Name); } static void DoInvalid (void) /* Handle a token that is invalid here, since it should have been handled on ** a much lower level of the expression hierarchy. Getting this sort of token ** means that the lower level code has bugs. ** This function differs to DoUnexpected in that the latter may be triggered ** by the user by using keywords in the wrong location. DoUnexpected is not ** an error in the assembler itself, while DoInvalid is. */ { Internal ("Unexpected token: %m%p", &Keyword); } static void DoLineCont (void) /* Switch the use of line continuations */ { SetBoolOption (&LineCont); } static void DoList (void) /* Enable/disable the listing */ { /* Get the setting */ unsigned char List = 0; SetBoolOption (&List); /* Manage the counter */ if (List) { EnableListing (); } else { DisableListing (); } } static void DoLoBytes (void) /* Define bytes, extracting the lo byte from each expression in the list */ { while (1) { EmitByte (FuncLoByte ()); if (CurTok.Tok != TOK_COMMA) { break; } else { NextTok (); } } } static void DoListBytes (void) /* Set maximum number of bytes to list for one line */ { SetListBytes (IntArg (MIN_LIST_BYTES, MAX_LIST_BYTES)); } static void DoLocalChar (void) /* Define the character that starts local labels */ { if (CurTok.Tok != TOK_CHARCON) { ErrorSkip ("Character constant expected"); } else { if (CurTok.IVal != '@' && CurTok.IVal != '?') { Error ("Invalid start character for locals"); } else { LocalStart = (char) CurTok.IVal; } NextTok (); } } static void DoMacPack (void) /* Insert a macro package */ { /* We expect an identifier */ if (CurTok.Tok != TOK_IDENT) { ErrorSkip ("Identifier expected"); } else { SB_AppendStr (&CurTok.SVal, ".mac"); SB_Terminate (&CurTok.SVal); if (NewInputFile (SB_GetConstBuf (&CurTok.SVal)) == 0) { /* Error opening the file, skip remainder of line */ SkipUntilSep (); } } } static void DoMacro (void) /* Start a macro definition */ { MacDef (MAC_STYLE_CLASSIC); } static void DoNull (void) /* Switch to the NULL segment */ { UseSeg (&NullSegDef); } static void DoOrg (void) /* Start absolute code */ { long PC = ConstExpression (); if (PC < 0 || PC > 0xFFFFFF) { Error ("Range error"); return; } EnterAbsoluteMode (PC); } static void DoOut (void) /* Output a string */ { if (CurTok.Tok != TOK_STRCON) { ErrorSkip ("String constant expected"); } else { /* Output the string and be sure to flush the output to keep it in ** sync with any error messages if the output is redirected to a file. */ printf ("%.*s\n", (int) SB_GetLen (&CurTok.SVal), SB_GetConstBuf (&CurTok.SVal)); fflush (stdout); NextTok (); } } static void DoP02 (void) /* Switch to 6502 CPU */ { SetCPU (CPU_6502); } static void DoPC02 (void) /* Switch to 65C02 CPU */ { SetCPU (CPU_65C02); } static void DoP816 (void) /* Switch to 65816 CPU */ { SetCPU (CPU_65816); } static void DoP4510 (void) /* Switch to 4510 CPU */ { SetCPU (CPU_4510); } static void DoPageLength (void) /* Set the page length for the listing */ { PageLength = IntArg (MIN_PAGE_LEN, MAX_PAGE_LEN); } static void DoPopCPU (void) /* Pop an old CPU setting from the CPU stack */ { /* Must have a CPU on the stack */ if (IS_IsEmpty (&CPUStack)) { ErrorSkip ("CPU stack is empty"); return; } /* Set the CPU to the value popped from stack */ SetCPU (IS_Pop (&CPUStack)); } static void DoPopSeg (void) /* Pop an old segment from the segment stack */ { SegDef* Def; /* Must have a segment on the stack */ if (CollCount (&SegStack) == 0) { ErrorSkip ("Segment stack is empty"); return; } /* Pop the last element */ Def = CollPop (&SegStack); /* Restore this segment */ UseSeg (Def); /* Delete the segment definition */ FreeSegDef (Def); } static void DoProc (void) /* Start a new lexical scope */ { StrBuf Name = STATIC_STRBUF_INITIALIZER; unsigned char AddrSize; SymEntry* Sym = 0; if (CurTok.Tok == TOK_IDENT) { /* The new scope has a name. Remember it. */ SB_Copy (&Name, &CurTok.SVal); /* Search for the symbol, generate a new one if needed */ Sym = SymFind (CurrentScope, &Name, SYM_ALLOC_NEW); /* Skip the scope name */ NextTok (); /* Read an optional address size specifier */ AddrSize = OptionalAddrSize (); /* Mark the symbol as defined */ SymDef (Sym, GenCurrentPC (), AddrSize, SF_LABEL); } else { /* A .PROC statement without a name */ Warning (1, "Unnamed .PROCs are deprecated, please use .SCOPE"); AnonName (&Name, "PROC"); AddrSize = ADDR_SIZE_DEFAULT; } /* Enter a new scope */ SymEnterLevel (&Name, SCOPE_SCOPE, AddrSize, Sym); /* Free memory for Name */ SB_Done (&Name); } static void DoPSC02 (void) /* Switch to 65SC02 CPU */ { SetCPU (CPU_65SC02); } static void DoPushCPU (void) /* Push the current CPU setting onto the CPU stack */ { /* Can only push a limited size of segments */ if (IS_IsFull (&CPUStack)) { ErrorSkip ("CPU stack overflow"); return; } /* Get the current segment and push it */ IS_Push (&CPUStack, GetCPU ()); } static void DoPushSeg (void) /* Push the current segment onto the segment stack */ { /* Can only push a limited size of segments */ if (CollCount (&SegStack) >= MAX_PUSHED_SEGMENTS) { ErrorSkip ("Segment stack overflow"); return; } /* Get the current segment and push it */ CollAppend (&SegStack, DupSegDef (GetCurrentSegDef ())); } static void DoReloc (void) /* Enter relocatable mode */ { EnterRelocMode (); } static void DoRepeat (void) /* Repeat some instruction block */ { ParseRepeat (); } static void DoRes (void) /* Reserve some number of storage bytes */ { long Count; long Val; Count = ConstExpression (); if (Count > 0xFFFF || Count < 0) { ErrorSkip ("Range error"); return; } if (CurTok.Tok == TOK_COMMA) { NextTok (); Val = ConstExpression (); /* We need a byte value here */ if (!IsByteRange (Val)) { ErrorSkip ("Range error"); return; } /* Emit constant values */ while (Count--) { Emit0 ((unsigned char) Val); } } else { /* Emit fill fragments */ EmitFill (Count); } } static void DoROData (void) /* Switch to the r/o data segment */ { UseSeg (&RODataSegDef); } static void DoScope (void) /* Start a local scope */ { StrBuf Name = STATIC_STRBUF_INITIALIZER; unsigned char AddrSize; if (CurTok.Tok == TOK_IDENT) { /* The new scope has a name. Remember and skip it. */ SB_Copy (&Name, &CurTok.SVal); NextTok (); } else { /* An unnamed scope */ AnonName (&Name, "SCOPE"); } /* Read an optional address size specifier */ AddrSize = OptionalAddrSize (); /* Enter the new scope */ SymEnterLevel (&Name, SCOPE_SCOPE, AddrSize, 0); /* Free memory for Name */ SB_Done (&Name); } static void DoSegment (void) /* Switch to another segment */ { StrBuf Name = STATIC_STRBUF_INITIALIZER; SegDef Def; if (CurTok.Tok != TOK_STRCON) { ErrorSkip ("String constant expected"); } else { /* Save the name of the segment and skip it */ SB_Copy (&Name, &CurTok.SVal); NextTok (); /* Use the name for the segment definition */ SB_Terminate (&Name); Def.Name = SB_GetBuf (&Name); /* Check for an optional address size modifier */ Def.AddrSize = OptionalAddrSize (); /* Set the segment */ UseSeg (&Def); } /* Free memory for Name */ SB_Done (&Name); } static void DoSetCPU (void) /* Switch the CPU instruction set */ { /* We expect an identifier */ if (CurTok.Tok != TOK_STRCON) { ErrorSkip ("String constant expected"); } else { cpu_t CPU; /* Try to find the CPU */ SB_Terminate (&CurTok.SVal); CPU = FindCPU (SB_GetConstBuf (&CurTok.SVal)); /* Switch to the new CPU */ SetCPU (CPU); /* Skip the identifier. If the CPU switch was successful, the scanner ** will treat the input now correctly for the new CPU. */ NextTok (); } } static void DoSmart (void) /* Smart mode on/off */ { SetBoolOption (&SmartMode); } static void DoTag (void) /* Allocate space for a struct */ { SymEntry* SizeSym; long Size; /* Read the struct name */ SymTable* Struct = ParseScopedSymTable (); /* Check the supposed struct */ if (Struct == 0) { ErrorSkip ("Unknown struct"); return; } if (GetSymTabType (Struct) != SCOPE_STRUCT) { ErrorSkip ("Not a struct"); return; } /* Get the symbol that defines the size of the struct */ SizeSym = GetSizeOfScope (Struct); /* Check if it does exist and if its value is known */ if (SizeSym == 0 || !SymIsConst (SizeSym, &Size)) { ErrorSkip ("Size of struct/union is unknown"); return; } /* Optional multiplicator may follow */ if (CurTok.Tok == TOK_COMMA) { long Multiplicator; NextTok (); Multiplicator = ConstExpression (); /* Multiplicator must make sense */ if (Multiplicator <= 0) { ErrorSkip ("Range error"); return; } Size *= Multiplicator; } /* Emit fill fragments */ EmitFill (Size); } static void DoUnDef (void) /* Undefine a define style macro */ { /* The function is called with the .UNDEF token in place, because we need ** to disable .define macro expansions before reading the next token. ** Otherwise the name of the macro would be expanded, so we would never ** see it. */ DisableDefineStyleMacros (); NextTok (); EnableDefineStyleMacros (); /* We expect an identifier */ if (CurTok.Tok != TOK_IDENT) { ErrorSkip ("Identifier expected"); } else { MacUndef (&CurTok.SVal, MAC_STYLE_DEFINE); NextTok (); } } static void DoUnexpected (void) /* Got an unexpected keyword */ { Error ("Unexpected '%m%p'", &Keyword); SkipUntilSep (); } static void DoWarning (void) /* User warning */ { if (CurTok.Tok != TOK_STRCON) { ErrorSkip ("String constant expected"); } else { Warning (0, "User warning: %m%p", &CurTok.SVal); SkipUntilSep (); } } static void DoWord (void) /* Define words */ { /* Element type for the generated array */ static const char EType[1] = { GT_WORD }; /* Record type information */ Span* S = OpenSpan (); StrBuf Type = STATIC_STRBUF_INITIALIZER; /* Parse arguments */ while (1) { EmitWord (BoundedExpr (Expression, 2)); if (CurTok.Tok != TOK_COMMA) { break; } else { NextTok (); } } /* Close the span, then add type information to it */ S = CloseSpan (S); SetSpanType (S, GenArrayType (&Type, GetSpanSize (S), EType, sizeof (EType))); /* Free the type string */ SB_Done (&Type); } static void DoZeropage (void) /* Switch to the zeropage segment */ { UseSeg (&ZeropageSegDef); } /*****************************************************************************/ /* Table data */ /*****************************************************************************/ /* Control commands flags */ enum { ccNone = 0x0000, /* No special flags */ ccKeepToken = 0x0001 /* Do not skip the current token */ }; /* Control command table */ typedef struct CtrlDesc CtrlDesc; struct CtrlDesc { unsigned Flags; /* Flags for this directive */ void (*Handler) (void); /* Command handler */ }; #define PSEUDO_COUNT (sizeof (CtrlCmdTab) / sizeof (CtrlCmdTab [0])) 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 */ { ccNone, DoUnexpected }, /* .BANKBYTE */ { ccNone, DoBankBytes }, { ccNone, DoUnexpected }, /* .BLANK */ { ccNone, DoBss }, { ccNone, DoByte }, { ccNone, DoCase }, { ccNone, DoCharMap }, { ccNone, DoCode }, { ccNone, DoUnexpected, }, /* .CONCAT */ { ccNone, DoConDes }, { ccNone, DoUnexpected }, /* .CONST */ { ccNone, DoConstructor }, { ccNone, DoUnexpected }, /* .CPU */ { ccNone, DoData }, { ccNone, DoDbg, }, { ccNone, DoDByt }, { ccNone, DoDebugInfo }, { ccNone, DoDefine }, { ccNone, DoUnexpected }, /* .DEFINED */ { ccNone, DoUnexpected }, /* .DEFINEDMACRO */ { ccNone, DoDelMac }, { ccNone, DoDestructor }, { ccNone, DoDWord }, { ccKeepToken, DoConditionals }, /* .ELSE */ { ccKeepToken, DoConditionals }, /* .ELSEIF */ { ccKeepToken, DoEnd }, { ccNone, DoUnexpected }, /* .ENDENUM */ { ccKeepToken, DoConditionals }, /* .ENDIF */ { ccNone, DoUnexpected }, /* .ENDMACRO */ { ccNone, DoEndProc }, { ccNone, DoUnexpected }, /* .ENDREPEAT */ { ccNone, DoEndScope }, { ccNone, DoUnexpected }, /* .ENDSTRUCT */ { ccNone, DoUnexpected }, /* .ENDUNION */ { ccNone, DoEnum }, { ccNone, DoError }, { ccNone, DoExitMacro }, { ccNone, DoExport }, { ccNone, DoExportZP }, { ccNone, DoFarAddr }, { ccNone, DoFatal }, { ccNone, DoFeature }, { ccNone, DoFileOpt }, { ccNone, DoForceImport }, { ccNone, DoUnexpected }, /* .FORCEWORD */ { ccNone, DoGlobal }, { ccNone, DoGlobalZP }, { ccNone, DoUnexpected }, /* .HIBYTE */ { ccNone, DoHiBytes }, { ccNone, DoUnexpected }, /* .HIWORD */ { ccNone, DoI16 }, { ccNone, DoI8 }, { ccNone, DoUnexpected }, /* .IDENT */ { ccKeepToken, DoConditionals }, /* .IF */ { ccKeepToken, DoConditionals }, /* .IFBLANK */ { ccKeepToken, DoConditionals }, /* .IFCONST */ { ccKeepToken, DoConditionals }, /* .IFDEF */ { ccKeepToken, DoConditionals }, /* .IFNBLANK */ { ccKeepToken, DoConditionals }, /* .IFNCONST */ { ccKeepToken, DoConditionals }, /* .IFNDEF */ { ccKeepToken, DoConditionals }, /* .IFNREF */ { ccKeepToken, DoConditionals }, /* .IFP02 */ { ccKeepToken, DoConditionals }, /* .IFP4510 */ { ccKeepToken, DoConditionals }, /* .IFP816 */ { ccKeepToken, DoConditionals }, /* .IFPC02 */ { ccKeepToken, DoConditionals }, /* .IFPSC02 */ { ccKeepToken, DoConditionals }, /* .IFREF */ { ccNone, DoImport }, { ccNone, DoImportZP }, { ccNone, DoIncBin }, { ccNone, DoInclude }, { ccNone, DoInterruptor }, { ccNone, DoUnexpected }, /* .ISIZE */ { ccNone, DoUnexpected }, /* .ISMNEMONIC */ { ccNone, DoInvalid }, /* .LEFT */ { ccNone, DoLineCont }, { ccNone, DoList }, { ccNone, DoListBytes }, { ccNone, DoUnexpected }, /* .LOBYTE */ { ccNone, DoLoBytes }, { ccNone, DoUnexpected }, /* .LOCAL */ { ccNone, DoLocalChar }, { ccNone, DoUnexpected }, /* .LOWORD */ { ccNone, DoMacPack }, { ccNone, DoMacro }, { ccNone, DoUnexpected }, /* .MATCH */ { ccNone, DoUnexpected }, /* .MAX */ { ccNone, DoInvalid }, /* .MID */ { ccNone, DoUnexpected }, /* .MIN */ { ccNone, DoNull }, { ccNone, DoOrg }, { ccNone, DoOut }, { ccNone, DoP02 }, { ccNone, DoP4510 }, { ccNone, DoP816 }, { ccNone, DoPageLength }, { ccNone, DoUnexpected }, /* .PARAMCOUNT */ { ccNone, DoPC02 }, { ccNone, DoPopCPU }, { ccNone, DoPopSeg }, { ccNone, DoProc }, { ccNone, DoPSC02 }, { ccNone, DoPushCPU }, { ccNone, DoPushSeg }, { ccNone, DoUnexpected }, /* .REFERENCED */ { ccNone, DoReloc }, { ccNone, DoRepeat }, { ccNone, DoRes }, { ccNone, DoInvalid }, /* .RIGHT */ { ccNone, DoROData }, { ccNone, DoScope }, { ccNone, DoSegment }, { ccNone, DoUnexpected }, /* .SET */ { ccNone, DoSetCPU }, { ccNone, DoUnexpected }, /* .SIZEOF */ { ccNone, DoSmart }, { ccNone, DoUnexpected }, /* .SPRINTF */ { ccNone, DoUnexpected }, /* .STRAT */ { ccNone, DoUnexpected }, /* .STRING */ { ccNone, DoUnexpected }, /* .STRLEN */ { ccNone, DoStruct }, { ccNone, DoTag }, { ccNone, DoUnexpected }, /* .TCOUNT */ { ccNone, DoUnexpected }, /* .TIME */ { ccKeepToken, DoUnDef }, { ccNone, DoUnion }, { ccNone, DoUnexpected }, /* .VERSION */ { ccNone, DoWarning }, { ccNone, DoWord }, { ccNone, DoUnexpected }, /* .XMATCH */ { ccNone, DoZeropage }, }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void HandlePseudo (void) /* Handle a pseudo instruction */ { CtrlDesc* D; /* Calculate the index into the table */ unsigned Index = CurTok.Tok - TOK_FIRSTPSEUDO; /* Safety check */ if (PSEUDO_COUNT != (TOK_LASTPSEUDO - TOK_FIRSTPSEUDO + 1)) { Internal ("Pseudo mismatch: PSEUDO_COUNT = %u, actual count = %u\n", (unsigned) PSEUDO_COUNT, TOK_LASTPSEUDO - TOK_FIRSTPSEUDO + 1); } CHECK (Index < PSEUDO_COUNT); /* Get the pseudo intruction descriptor */ D = &CtrlCmdTab [Index]; /* Remember the instruction, then skip it if needed */ if ((D->Flags & ccKeepToken) == 0) { SB_Copy (&Keyword, &CurTok.SVal); NextTok (); } /* Call the handler */ D->Handler (); } void CheckPseudo (void) /* Check if the stacks are empty at end of assembly */ { if (CollCount (&SegStack) != 0) { Warning (1, "Segment stack is not empty"); } if (!IS_IsEmpty (&CPUStack)) { Warning (1, "CPU stack is not empty"); } } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/pseudo.h�������������������������������������������������������������������������0000664�0000000�0000000�00000005711�13473601511�0015206�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* pseudo.h */ /* */ /* Pseudo instructions for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef PSEUDO_H #define PSEUDO_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ void HandlePseudo (void); /* Handle a pseudo instruction */ void CheckPseudo (void); /* Check if the stacks are empty at end of assembly */ /* End of pseudo.h */ #endif �������������������������������������������������������cc65-2.18/src/ca65/repeat.c�������������������������������������������������������������������������0000664�0000000�0000000�00000013442�13473601511�0015162�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* repeat.c */ /* */ /* Handle the .REPEAT pseudo instruction */ /* */ /* */ /* */ /* (C) 2000-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* common */ #include "xmalloc.h" /* ca65 */ #include "error.h" #include "expr.h" #include "nexttok.h" #include "toklist.h" #include "repeat.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ static TokList* CollectRepeatTokens (void) /* Collect all tokens inside the .REPEAT body in a token list and return ** this list. In case of errors, NULL is returned. */ { /* Create the token list */ TokList* List = NewTokList (); /* Read the token list */ unsigned Repeats = 0; while (Repeats != 0 || CurTok.Tok != TOK_ENDREP) { /* Check for end of input */ if (CurTok.Tok == TOK_EOF) { Error ("Unexpected end of file"); FreeTokList (List); return 0; } /* Collect all tokens in the list */ AddCurTok (List); /* Check for and count nested .REPEATs */ if (CurTok.Tok == TOK_REPEAT) { ++Repeats; } else if (CurTok.Tok == TOK_ENDREP) { --Repeats; } /* Get the next token */ NextTok (); } /* Eat the closing .ENDREP */ NextTok (); /* Return the list of collected tokens */ return List; } static void RepeatTokenCheck (TokList* L) /* Called each time a token from a repeat token list is set. Is used to check ** for and replace identifiers that are the repeat counter. */ { if (CurTok.Tok == TOK_IDENT && L->Data != 0 && SB_CompareStr (&CurTok.SVal, L->Data) == 0) { /* Must replace by the repeat counter */ CurTok.Tok = TOK_INTCON; CurTok.IVal = L->RepCount; } } void ParseRepeat (void) /* Parse and handle the .REPEAT statement */ { char* Name; TokList* List; /* Repeat count follows */ long RepCount = ConstExpression (); if (RepCount < 0) { Error ("Range error"); RepCount = 0; } /* Optional there is a comma and a counter variable */ Name = 0; if (CurTok.Tok == TOK_COMMA) { /* Skip the comma */ NextTok (); /* Check for an identifier */ if (CurTok.Tok != TOK_IDENT) { ErrorSkip ("Identifier expected"); } else { /* Remember the name and skip it */ SB_Terminate (&CurTok.SVal); Name = xstrdup (SB_GetConstBuf (&CurTok.SVal)); NextTok (); } } /* Switch to raw token mode, then skip the separator */ EnterRawTokenMode (); ConsumeSep (); /* Read the token list */ List = CollectRepeatTokens (); /* If we had an error, bail out */ if (List == 0) { xfree (Name); goto Done; } /* Update the token list for replay */ List->RepMax = (unsigned) RepCount; List->Data = Name; List->Check = RepeatTokenCheck; /* If the list is empty, or repeat count zero, there is nothing ** to repeat. */ if (List->Count == 0 || RepCount == 0) { FreeTokList (List); goto Done; } /* Read input from the repeat descriptor */ PushTokList (List, ".REPEAT"); Done: /* Switch out of raw token mode */ LeaveRawTokenMode (); } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/repeat.h�������������������������������������������������������������������������0000664�0000000�0000000�00000005602�13473601511�0015166�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* repeat.h */ /* */ /* Handle the .REPEAT pseudo instruction */ /* */ /* */ /* */ /* (C) 2000 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 REPEAT_H #define REPEAT_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ void ParseRepeat (void); /* Parse and handle the .REPEAT statement */ /* End of repeat.h */ #endif ������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/scanner.c������������������������������������������������������������������������0000664�0000000�0000000�00000136177�13473601511�0015346�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* scanner.c */ /* */ /* The scanner for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 1998-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <errno.h> /* common */ #include "addrsize.h" #include "attrib.h" #include "chartype.h" #include "check.h" #include "filestat.h" #include "fname.h" #include "xmalloc.h" /* ca65 */ #include "condasm.h" #include "error.h" #include "filetab.h" #include "global.h" #include "incpath.h" #include "instr.h" #include "istack.h" #include "listing.h" #include "macro.h" #include "toklist.h" #include "scanner.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Current input token incl. attributes */ Token CurTok = STATIC_TOKEN_INITIALIZER; /* Struct to handle include files. */ typedef struct InputFile InputFile; struct InputFile { FILE* F; /* Input file descriptor */ FilePos Pos; /* Position in file */ token_t Tok; /* Last token */ int C; /* Last character */ StrBuf Line; /* The current input line */ int IncSearchPath; /* True if we've added a search path */ int BinSearchPath; /* True if we've added a search path */ InputFile* Next; /* Linked list of input files */ }; /* Struct to handle textual input data */ typedef struct InputData InputData; struct InputData { char* Text; /* Pointer to the text data */ const char* Pos; /* Pointer to current position */ int Malloced; /* Memory was malloced */ token_t Tok; /* Last token */ int C; /* Last character */ InputData* Next; /* Linked list of input data */ }; /* Input source: Either file or data */ typedef struct CharSource CharSource; /* Set of input functions */ typedef struct CharSourceFunctions CharSourceFunctions; struct CharSourceFunctions { void (*MarkStart) (CharSource*); /* Mark the start pos of a token */ void (*NextChar) (CharSource*); /* Read next char from input */ void (*Done) (CharSource*); /* Close input source */ }; /* Input source: Either file or data */ struct CharSource { CharSource* Next; /* Linked list of char sources */ token_t Tok; /* Last token */ int C; /* Last character */ const CharSourceFunctions* Func; /* Pointer to function table */ union { InputFile File; /* File data */ InputData Data; /* Textual data */ } V; }; /* Current input variables */ static CharSource* Source = 0; /* Current char source */ static unsigned FCount = 0; /* Count of input files */ static int C = 0; /* Current input character */ /* Force end of assembly */ int ForcedEnd = 0; /* List of dot keywords with the corresponding tokens */ struct DotKeyword { const char* Key; /* MUST be first field */ token_t Tok; } DotKeywords [] = { { ".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 }, { ".IFP4510", TOK_IFP4510 }, { ".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 }, { ".P4510", TOK_P4510 }, { ".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 }, }; /*****************************************************************************/ /* CharSource functions */ /*****************************************************************************/ static void UseCharSource (CharSource* S) /* Initialize a new input source and start to use it. */ { /* Remember the current input char and token */ S->Tok = CurTok.Tok; S->C = C; /* Use the new input source */ S->Next = Source; Source = S; /* Read the first character from the new file */ S->Func->NextChar (S); /* Setup the next token so it will be skipped on the next call to ** NextRawTok(). */ CurTok.Tok = TOK_SEP; } static void DoneCharSource (void) /* Close the top level character source */ { CharSource* S; /* First, call the type specific function */ Source->Func->Done (Source); /* Restore the old token */ CurTok.Tok = Source->Tok; C = Source->C; /* Remember the last stacked input source */ S = Source->Next; /* Delete the top level one ... */ xfree (Source); /* ... and use the one before */ Source = S; } /*****************************************************************************/ /* InputFile functions */ /*****************************************************************************/ static void IFMarkStart (CharSource* S) /* Mark the start of the next token */ { CurTok.Pos = S->V.File.Pos; } static void IFNextChar (CharSource* S) /* Read the next character from the input file */ { /* Check for end of line, read the next line if needed */ while (SB_GetIndex (&S->V.File.Line) >= SB_GetLen (&S->V.File.Line)) { unsigned Len; /* End of current line reached, read next line */ SB_Clear (&S->V.File.Line); while (1) { int N = fgetc (S->V.File.F); if (N == EOF) { /* End of file. Accept files without a newline at the end */ if (SB_NotEmpty (&S->V.File.Line)) { break; } /* No more data - add an empty line to the listing. This ** is a small hack needed to keep the PC output in sync. */ NewListingLine (&EmptyStrBuf, S->V.File.Pos.Name, FCount); C = EOF; return; /* Check for end of line */ } else if (N == '\n') { /* End of line */ break; /* Collect other stuff */ } else { /* Append data to line */ SB_AppendChar (&S->V.File.Line, N); } } /* If we come here, we have a new input line. To avoid problems ** with strange line terminators, remove all whitespace from the ** end of the line, then add a single newline. */ Len = SB_GetLen (&S->V.File.Line); while (Len > 0 && IsSpace (SB_AtUnchecked (&S->V.File.Line, Len-1))) { --Len; } SB_Drop (&S->V.File.Line, SB_GetLen (&S->V.File.Line) - Len); SB_AppendChar (&S->V.File.Line, '\n'); /* Terminate the string buffer */ SB_Terminate (&S->V.File.Line); /* One more line */ S->V.File.Pos.Line++; /* Remember the new line for the listing */ NewListingLine (&S->V.File.Line, S->V.File.Pos.Name, FCount); } /* Set the column pointer */ S->V.File.Pos.Col = SB_GetIndex (&S->V.File.Line); /* Return the next character from the buffer */ C = SB_Get (&S->V.File.Line); } void IFDone (CharSource* S) /* Close the current input file */ { /* We're at the end of an include file. Check if we have any ** open .IFs, or any open token lists in this file. This ** enforcement is artificial, using conditionals that start ** in one file and end in another are uncommon, and don't ** allowing these things will help finding errors. */ CheckOpenIfs (); /* If we've added search paths for this file, remove them */ if (S->V.File.IncSearchPath) { PopSearchPath (IncSearchPath); } if (S->V.File.BinSearchPath) { PopSearchPath (BinSearchPath); } /* Free the line buffer */ SB_Done (&S->V.File.Line); /* Close the input file and decrement the file count. We will ignore ** errors here, since we were just reading from the file. */ (void) fclose (S->V.File.F); --FCount; } /* Set of input file handling functions */ static const CharSourceFunctions IFFunc = { IFMarkStart, IFNextChar, IFDone }; int NewInputFile (const char* Name) /* Open a new input file. Returns true if the file could be successfully opened ** and false otherwise. */ { int RetCode = 0; /* Return code. Assume an error. */ char* PathName = 0; FILE* F; struct stat Buf; StrBuf NameBuf; /* No need to initialize */ StrBuf Path = AUTO_STRBUF_INITIALIZER; unsigned FileIdx; CharSource* S; /* If this is the main file, just try to open it. If it's an include file, ** search for it using the include path list. */ if (FCount == 0) { /* Main file */ F = fopen (Name, "r"); if (F == 0) { Fatal ("Cannot open input file '%s': %s", Name, strerror (errno)); } } else { /* We are on include level. Search for the file in the include ** directories. */ PathName = SearchFile (IncSearchPath, Name); if (PathName == 0 || (F = fopen (PathName, "r")) == 0) { /* Not found or cannot open, print an error and bail out */ Error ("Cannot open include file '%s': %s", Name, strerror (errno)); goto ExitPoint; } /* Use the path name from now on */ Name = PathName; } /* Stat the file and remember the values. There's a race condition here, ** since we cannot use fileno() (non-standard identifier in standard ** header file), and therefore not fstat. When using stat with the ** file name, there's a risk that the file was deleted and recreated ** while it was open. Since mtime and size are only used to check ** if a file has changed in the debugger, we will ignore this problem ** here. */ if (FileStat (Name, &Buf) != 0) { Fatal ("Cannot stat input file '%s': %s", Name, strerror (errno)); } /* Add the file to the input file table and remember the index */ FileIdx = AddFile (SB_InitFromString (&NameBuf, Name), (FCount == 0)? FT_MAIN : FT_INCLUDE, Buf.st_size, (unsigned long) Buf.st_mtime); /* Create a new input source variable and initialize it */ S = xmalloc (sizeof (*S)); S->Func = &IFFunc; S->V.File.F = F; S->V.File.Pos.Line = 0; S->V.File.Pos.Col = 0; S->V.File.Pos.Name = FileIdx; SB_Init (&S->V.File.Line); /* Push the path for this file onto the include search lists */ SB_CopyBuf (&Path, Name, FindName (Name) - Name); SB_Terminate (&Path); S->V.File.IncSearchPath = PushSearchPath (IncSearchPath, SB_GetConstBuf (&Path)); S->V.File.BinSearchPath = PushSearchPath (BinSearchPath, SB_GetConstBuf (&Path)); SB_Done (&Path); /* Count active input files */ ++FCount; /* Use this input source */ UseCharSource (S); /* File successfully opened */ RetCode = 1; ExitPoint: /* Free an allocated name buffer */ xfree (PathName); /* Return the success code */ return RetCode; } /*****************************************************************************/ /* InputData functions */ /*****************************************************************************/ static void IDMarkStart (CharSource* S attribute ((unused))) /* Mark the start of the next token */ { /* Nothing to do here */ } static void IDNextChar (CharSource* S) /* Read the next character from the input text */ { C = *S->V.Data.Pos++; if (C == '\0') { /* End of input data */ --S->V.Data.Pos; C = EOF; } } void IDDone (CharSource* S) /* Close the current input data */ { /* Cleanup the current stuff */ if (S->V.Data.Malloced) { xfree (S->V.Data.Text); } } /* Set of input data handling functions */ static const CharSourceFunctions IDFunc = { IDMarkStart, IDNextChar, IDDone }; void NewInputData (char* Text, int Malloced) /* Add a chunk of input data to the input stream */ { CharSource* S; /* Create a new input source variable and initialize it */ S = xmalloc (sizeof (*S)); S->Func = &IDFunc; S->V.Data.Text = Text; S->V.Data.Pos = Text; S->V.Data.Malloced = Malloced; /* Use this input source */ UseCharSource (S); } /*****************************************************************************/ /* Character classification functions */ /*****************************************************************************/ int IsIdChar (int C) /* Return true if the character is a valid character for an identifier */ { return IsAlNum (C) || (C == '_') || (C == '@' && AtInIdents) || (C == '$' && DollarInIdents); } int IsIdStart (int C) /* Return true if the character may start an identifier */ { return IsAlpha (C) || C == '_'; } /*****************************************************************************/ /* Code */ /*****************************************************************************/ static unsigned DigitVal (unsigned char C) /* Convert a digit into it's numerical representation */ { if (IsDigit (C)) { return C - '0'; } else { return toupper (C) - 'A' + 10; } } static void NextChar (void) /* Read the next character from the input file */ { Source->Func->NextChar (Source); } void LocaseSVal (void) /* Make SVal lower case */ { SB_ToLower (&CurTok.SVal); } void UpcaseSVal (void) /* Make SVal upper case */ { SB_ToUpper (&CurTok.SVal); } static int CmpDotKeyword (const void* K1, const void* K2) /* Compare function for the dot keyword search */ { return strcmp (((struct DotKeyword*)K1)->Key, ((struct DotKeyword*)K2)->Key); } static token_t FindDotKeyword (void) /* Find the dot keyword in SVal. Return the corresponding token if found, ** return TOK_NONE if not found. */ { struct DotKeyword K; struct DotKeyword* R; /* Initialize K */ K.Key = SB_GetConstBuf (&CurTok.SVal); K.Tok = 0; /* If we aren't in ignore case mode, we have to uppercase the keyword */ if (!IgnoreCase) { UpcaseSVal (); } /* Search for the keyword */ 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; } } static void ReadIdent (void) /* Read an identifier from the current input position into Ident. Filling SVal ** starts at the current position with the next character in C. It is assumed ** that any characters already filled in are ok, and the character in C is ** checked. */ { /* Read the identifier */ do { SB_AppendChar (&CurTok.SVal, C); NextChar (); } while (IsIdChar (C)); SB_Terminate (&CurTok.SVal); /* If we should ignore case, convert the identifier to upper case */ if (IgnoreCase) { UpcaseSVal (); } } static void ReadStringConst (int StringTerm) /* Read a string constant into SVal. */ { /* Skip the leading string terminator */ NextChar (); /* Read the string */ while (1) { if (C == StringTerm) { break; } if (C == '\n' || C == EOF) { Error ("Newline in string constant"); break; } if (C == '\\' && StringEscapes) { NextChar (); switch (C) { case EOF: Error ("Unterminated escape sequence in string constant"); break; case '\\': case '\'': case '"': break; case 't': C = '\x09'; break; case 'r': C = '\x0D'; break; case 'n': C = '\x0A'; break; case 'x': NextChar (); if (IsXDigit (C)) { char high_nibble = DigitVal (C) << 4; NextChar (); if (IsXDigit (C)) { C = high_nibble | DigitVal (C); break; } } /* FALLTHROUGH */ default: Error ("Unsupported escape sequence in string constant"); break; } } /* Append the char to the string */ SB_AppendChar (&CurTok.SVal, C); /* Skip the character */ NextChar (); } /* Skip the trailing terminator */ NextChar (); /* Terminate the string */ SB_Terminate (&CurTok.SVal); } static int Sweet16Reg (const StrBuf* Id) /* Check if the given identifier is a sweet16 register. Return -1 if this is ** not the case, return the register number otherwise. */ { unsigned RegNum; char Check; if (SB_GetLen (Id) < 2) { return -1; } if (toupper (SB_AtUnchecked (Id, 0)) != 'R') { return -1; } if (!IsDigit (SB_AtUnchecked (Id, 1))) { return -1; } if (sscanf (SB_GetConstBuf (Id)+1, "%u%c", &RegNum, &Check) != 1 || RegNum > 15) { /* Invalid register */ return -1; } /* The register number is valid */ return (int) RegNum; } void NextRawTok (void) /* Read the next raw token from the input stream */ { Macro* M; /* If we've a forced end of assembly, don't read further */ if (ForcedEnd) { CurTok.Tok = TOK_EOF; return; } Restart: /* Check if we have tokens from another input source */ if (InputFromStack ()) { if (CurTok.Tok == TOK_IDENT && (M = FindDefine (&CurTok.SVal)) != 0) { /* This is a define style macro - expand it */ MacExpandStart (M); goto Restart; } return; } Again: /* Skip whitespace, remember if we had some */ if ((CurTok.WS = IsBlank (C)) != 0) { do { NextChar (); } while (IsBlank (C)); } /* Mark the file position of the next token */ Source->Func->MarkStart (Source); /* Clear the string attribute */ SB_Clear (&CurTok.SVal); /* Generate line info for the current token */ NewAsmLine (); /* Hex number or PC symbol? */ if (C == '$') { NextChar (); /* Hex digit must follow or DollarIsPC must be enabled */ if (!IsXDigit (C)) { if (DollarIsPC) { CurTok.Tok = TOK_PC; return; } else { Error ("Hexadecimal digit expected"); } } /* Read the number */ CurTok.IVal = 0; while (1) { if (UnderlineInNumbers && C == '_') { while (C == '_') { NextChar (); } if (!IsXDigit (C)) { Error ("Number may not end with underline"); } } if (IsXDigit (C)) { if (CurTok.IVal & 0xF0000000) { Error ("Overflow in hexadecimal number"); CurTok.IVal = 0; } CurTok.IVal = (CurTok.IVal << 4) + DigitVal (C); NextChar (); } else { break; } } /* This is an integer constant */ CurTok.Tok = TOK_INTCON; return; } /* Binary number? */ if (C == '%') { NextChar (); /* 0 or 1 must follow */ if (!IsBDigit (C)) { Error ("Binary digit expected"); } /* Read the number */ CurTok.IVal = 0; while (1) { if (UnderlineInNumbers && C == '_') { while (C == '_') { NextChar (); } if (!IsBDigit (C)) { Error ("Number may not end with underline"); } } if (IsBDigit (C)) { if (CurTok.IVal & 0x80000000) { Error ("Overflow in binary number"); CurTok.IVal = 0; } CurTok.IVal = (CurTok.IVal << 1) + DigitVal (C); NextChar (); } else { break; } } /* This is an integer constant */ CurTok.Tok = TOK_INTCON; return; } /* Number? */ if (IsDigit (C)) { char Buf[16]; unsigned Digits; unsigned Base; unsigned I; long Max; unsigned DVal; /* Ignore leading zeros */ while (C == '0') { NextChar (); } /* Read the number into Buf counting the digits */ Digits = 0; while (1) { if (UnderlineInNumbers && C == '_') { while (C == '_') { NextChar (); } if (!IsXDigit (C)) { Error ("Number may not end with underline"); } } if (IsXDigit (C)) { /* Buf is big enough to allow any decimal and hex number to ** overflow, so ignore excess digits here, they will be detected ** when we convert the value. */ if (Digits < sizeof (Buf)) { Buf[Digits++] = C; } NextChar (); } else { break; } } /* Allow zilog/intel style hex numbers with a 'h' suffix */ if (C == 'h' || C == 'H') { NextChar (); Base = 16; Max = 0xFFFFFFFFUL / 16; } else { Base = 10; Max = 0xFFFFFFFFUL / 10; } /* Convert the number using the given base */ CurTok.IVal = 0; for (I = 0; I < Digits; ++I) { if (CurTok.IVal > Max) { Error ("Number out of range"); CurTok.IVal = 0; break; } DVal = DigitVal (Buf[I]); if (DVal >= Base) { Error ("Invalid digits in number"); CurTok.IVal = 0; break; } CurTok.IVal = (CurTok.IVal * Base) + DVal; } /* This is an integer constant */ CurTok.Tok = TOK_INTCON; return; } /* Control command? */ if (C == '.') { /* Remember and skip the dot */ NextChar (); /* Check if it's just a dot */ if (!IsIdStart (C)) { /* Just a dot */ CurTok.Tok = TOK_DOT; } else { /* Read the remainder of the identifier */ SB_AppendChar (&CurTok.SVal, '.'); ReadIdent (); /* Dot keyword, search for it */ CurTok.Tok = FindDotKeyword (); if (CurTok.Tok == TOK_NONE) { /* Not found */ if (!LeadingDotInIdents) { /* Invalid pseudo instruction */ Error ("'%m%p' is not a recognized control command", &CurTok.SVal); goto Again; } /* An identifier with a dot. Check if it's a define style ** macro. */ if ((M = FindDefine (&CurTok.SVal)) != 0) { /* This is a define style macro - expand it */ MacExpandStart (M); goto Restart; } /* Just an identifier with a dot */ CurTok.Tok = TOK_IDENT; } } return; } /* Indirect op for sweet16 cpu. Must check this before checking for local ** symbols, because these may also use the '@' symbol. */ if (CPU == CPU_SWEET16 && C == '@') { NextChar (); CurTok.Tok = TOK_AT; return; } /* Local symbol? */ if (C == LocalStart) { /* Read the identifier. */ ReadIdent (); /* Start character alone is not enough */ if (SB_GetLen (&CurTok.SVal) == 1) { Error ("Invalid cheap local symbol"); goto Again; } /* A local identifier */ CurTok.Tok = TOK_LOCAL_IDENT; return; } /* Identifier or keyword? */ if (IsIdStart (C)) { /* Read the identifier */ ReadIdent (); /* Check for special names. Bail out if we have identified the type of ** the token. Go on if the token is an identifier. */ switch (SB_GetLen (&CurTok.SVal)) { case 1: switch (toupper (SB_AtUnchecked (&CurTok.SVal, 0))) { case 'A': if (C == ':') { NextChar (); CurTok.Tok = TOK_OVERRIDE_ABS; } else { CurTok.Tok = TOK_A; } return; case 'F': if (C == ':') { NextChar (); CurTok.Tok = TOK_OVERRIDE_FAR; return; } break; case 'S': if ((CPU == CPU_4510) || (CPU == CPU_65816)) { CurTok.Tok = TOK_S; return; } break; case 'X': CurTok.Tok = TOK_X; return; case 'Y': CurTok.Tok = TOK_Y; return; case 'Z': if (C == ':') { NextChar (); CurTok.Tok = TOK_OVERRIDE_ZP; return; } else { if (CPU == CPU_4510) { CurTok.Tok = TOK_Z; return; } } break; default: break; } break; case 2: if ((CPU == CPU_4510) && (toupper (SB_AtUnchecked (&CurTok.SVal, 0)) == 'S') && (toupper (SB_AtUnchecked (&CurTok.SVal, 1)) == 'P')) { CurTok.Tok = TOK_S; return; } /* FALL THROUGH */ default: if (CPU == CPU_SWEET16 && (CurTok.IVal = Sweet16Reg (&CurTok.SVal)) >= 0) { /* A sweet16 register number in sweet16 mode */ CurTok.Tok = TOK_REG; return; } } /* Check for define style macro */ if ((M = FindDefine (&CurTok.SVal)) != 0) { /* Macro - expand it */ MacExpandStart (M); goto Restart; } else { /* An identifier */ CurTok.Tok = TOK_IDENT; } return; } /* Ok, let's do the switch */ CharAgain: switch (C) { case '+': NextChar (); CurTok.Tok = TOK_PLUS; return; case '-': NextChar (); CurTok.Tok = TOK_MINUS; return; case '/': NextChar (); if (C != '*') { CurTok.Tok = TOK_DIV; } else if (CComments) { /* Remember the position, then skip the '*' */ Collection LineInfos = STATIC_COLLECTION_INITIALIZER; GetFullLineInfo (&LineInfos); NextChar (); do { while (C != '*') { if (C == EOF) { LIError (&LineInfos, "Unterminated comment"); ReleaseFullLineInfo (&LineInfos); DoneCollection (&LineInfos); goto CharAgain; } NextChar (); } NextChar (); } while (C != '/'); NextChar (); ReleaseFullLineInfo (&LineInfos); DoneCollection (&LineInfos); goto Again; } return; case '*': NextChar (); CurTok.Tok = TOK_MUL; return; case '^': NextChar (); CurTok.Tok = TOK_XOR; return; case '&': NextChar (); if (C == '&') { NextChar (); CurTok.Tok = TOK_BOOLAND; } else { CurTok.Tok = TOK_AND; } return; case '|': NextChar (); if (C == '|') { NextChar (); CurTok.Tok = TOK_BOOLOR; } else { CurTok.Tok = TOK_OR; } return; case ':': NextChar (); switch (C) { case ':': NextChar (); CurTok.Tok = TOK_NAMESPACE; break; case '-': CurTok.IVal = 0; do { --CurTok.IVal; NextChar (); } while (C == '-'); CurTok.Tok = TOK_ULABEL; break; case '+': CurTok.IVal = 0; do { ++CurTok.IVal; NextChar (); } while (C == '+'); CurTok.Tok = TOK_ULABEL; break; case '=': NextChar (); CurTok.Tok = TOK_ASSIGN; break; default: CurTok.Tok = TOK_COLON; break; } return; case ',': NextChar (); CurTok.Tok = TOK_COMMA; return; case ';': NextChar (); while (C != '\n' && C != EOF) { NextChar (); } goto CharAgain; case '#': NextChar (); CurTok.Tok = TOK_HASH; return; case '(': NextChar (); CurTok.Tok = TOK_LPAREN; return; case ')': NextChar (); CurTok.Tok = TOK_RPAREN; return; case '[': NextChar (); CurTok.Tok = TOK_LBRACK; return; case ']': NextChar (); CurTok.Tok = TOK_RBRACK; return; case '{': NextChar (); CurTok.Tok = TOK_LCURLY; return; case '}': NextChar (); CurTok.Tok = TOK_RCURLY; return; case '<': NextChar (); if (C == '=') { NextChar (); CurTok.Tok = TOK_LE; } else if (C == '<') { NextChar (); CurTok.Tok = TOK_SHL; } else if (C == '>') { NextChar (); CurTok.Tok = TOK_NE; } else { CurTok.Tok = TOK_LT; } return; case '=': NextChar (); CurTok.Tok = TOK_EQ; return; case '!': NextChar (); CurTok.Tok = TOK_BOOLNOT; return; case '>': NextChar (); if (C == '=') { NextChar (); CurTok.Tok = TOK_GE; } else if (C == '>') { NextChar (); CurTok.Tok = TOK_SHR; } else { CurTok.Tok = TOK_GT; } return; case '~': NextChar (); CurTok.Tok = TOK_NOT; return; case '\'': /* Hack: If we allow ' as terminating character for strings, read ** the following stuff as a string, and check for a one character ** string later. */ if (LooseStringTerm) { ReadStringConst ('\''); if (SB_GetLen (&CurTok.SVal) == 1) { CurTok.IVal = SB_AtUnchecked (&CurTok.SVal, 0); CurTok.Tok = TOK_CHARCON; } else { CurTok.Tok = TOK_STRCON; } } else { /* Always a character constant */ NextChar (); if (C == EOF || IsControl (C)) { Error ("Illegal character constant"); goto CharAgain; } CurTok.IVal = C; CurTok.Tok = TOK_CHARCON; NextChar (); if (C != '\'') { if (!MissingCharTerm) { Error ("Illegal character constant"); } } else { NextChar (); } } return; case '\"': ReadStringConst ('\"'); CurTok.Tok = TOK_STRCON; return; case '\\': /* Line continuation? */ if (LineCont) { NextChar (); /* Next char should be a LF, if not, will result in an error later */ if (C == '\n') { /* Ignore the '\n' */ NextChar (); goto Again; } else { /* Make it clear what the problem is: */ Error ("EOL expected."); } } break; case '\n': NextChar (); CurTok.Tok = TOK_SEP; return; case EOF: CheckInputStack (); /* In case of the main file, do not close it, but return EOF. */ if (Source && Source->Next) { DoneCharSource (); goto Again; } else { CurTok.Tok = TOK_EOF; } return; } /* If we go here, we could not identify the current character. Skip it ** and try again. */ Error ("Invalid input character: 0x%02X", C & 0xFF); NextChar (); goto Again; } int GetSubKey (const char* const* Keys, unsigned Count) /* Search for a subkey in a table of keywords. The current token must be an ** identifier and all keys must be in upper case. The identifier will be ** uppercased in the process. The function returns the index of the keyword, ** or -1 if the keyword was not found. */ { unsigned I; /* Must have an identifier */ PRECONDITION (CurTok.Tok == TOK_IDENT); /* If we aren't in ignore case mode, we have to uppercase the identifier */ if (!IgnoreCase) { UpcaseSVal (); } /* Do a linear search (a binary search is not worth the effort) */ for (I = 0; I < Count; ++I) { if (SB_CompareStr (&CurTok.SVal, Keys [I]) == 0) { /* Found it */ return I; } } /* Not found */ return -1; } unsigned char ParseAddrSize (void) /* Check if the next token is a keyword that denotes an address size specifier. ** If so, return the corresponding address size constant, otherwise output an ** error message and return ADDR_SIZE_DEFAULT. */ { unsigned char AddrSize; /* Check for an identifier */ if (CurTok.Tok != TOK_IDENT) { Error ("Address size specifier expected"); return ADDR_SIZE_DEFAULT; } /* Convert the attribute */ AddrSize = AddrSizeFromStr (SB_GetConstBuf (&CurTok.SVal)); if (AddrSize == ADDR_SIZE_INVALID) { Error ("Address size specifier expected"); AddrSize = ADDR_SIZE_DEFAULT; } /* Done */ return AddrSize; } void InitScanner (const char* InFile) /* Initialize the scanner, open the given input file */ { /* Open the input file */ NewInputFile (InFile); } void DoneScanner (void) /* Release scanner resources */ { DoneCharSource (); } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/scanner.h������������������������������������������������������������������������0000664�0000000�0000000�00000011046�13473601511�0015336�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* scanner.h */ /* */ /* The scanner for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef SCANNER_H #define SCANNER_H /* ca65 */ #include "token.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Scanner variables */ extern Token CurTok; /* Current input token incl. attributes */ extern int ForcedEnd; /* Force end of assembly */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ int IsIdChar (int C); /* Return true if the character is a valid character for an identifier */ int IsIdStart (int C); /* Return true if the character may start an identifier */ int NewInputFile (const char* Name); /* Open a new input file. Returns true if the file could be successfully opened ** and false otherwise. */ void NewInputData (char* Text, int Malloced); /* Add a chunk of input data to the input stream */ void LocaseSVal (void); /* Make SVal lower case */ void UpcaseSVal (void); /* Make SVal upper case */ void NextRawTok (void); /* Read the next raw token from the input stream */ int GetSubKey (const char* const* Keys, unsigned Count); /* Search for a subkey in a table of keywords. The current token must be an ** identifier and all keys must be in upper case. The identifier will be ** uppercased in the process. The function returns the index of the keyword, ** or -1 if the keyword was not found. */ unsigned char ParseAddrSize (void); /* Check if the next token is a keyword that denotes an address size specifier. ** If so, return the corresponding address size constant, otherwise output an ** error message and return ADDR_SIZE_DEFAULT. */ void InitScanner (const char* InFile); /* Initialize the scanner, open the given input file */ void DoneScanner (void); /* Release scanner resources */ /* End of scanner.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/segdef.c�������������������������������������������������������������������������0000664�0000000�0000000�00000006557�13473601511�0015150�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* segdef.c */ /* */ /* Segment definitions for the ca65 assembler */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "xmalloc.h" /* ca65 */ #include "segdef.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ SegDef* NewSegDef (const char* Name, unsigned char AddrSize) /* Create a new segment definition and return it */ { /* Allocate memory */ SegDef* D = xmalloc (sizeof (SegDef)); /* Initialize it */ D->Name = xstrdup (Name); D->AddrSize = AddrSize; /* Return the result */ return D; } void FreeSegDef (SegDef* D) /* Free a segment definition */ { xfree (D->Name); xfree (D); } SegDef* DupSegDef (const SegDef* Def) /* Duplicate a segment definition and return it */ { return NewSegDef (Def->Name, Def->AddrSize); } �������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/segdef.h�������������������������������������������������������������������������0000664�0000000�0000000�00000007204�13473601511�0015143�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* segdef.h */ /* */ /* Segment definitions for the ca65 assembler */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef SEGDEF_H #define SEGDEF_H /* common */ #include "addrsize.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Segment definition */ typedef struct SegDef SegDef; struct SegDef { char* Name; /* Segment name */ unsigned char AddrSize; /* Default address size */ }; /* Initializer for static SegDefs */ #define STATIC_SEGDEF_INITIALIZER(name, addrsize) { name, addrsize } /*****************************************************************************/ /* Code */ /*****************************************************************************/ SegDef* NewSegDef (const char* Name, unsigned char AddrSize); /* Create a new segment definition and return it */ void FreeSegDef (SegDef* D); /* Free a segment definition */ SegDef* DupSegDef (const SegDef* D); /* Duplicate a segment definition and return it */ /* End of segdef.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/segment.c������������������������������������������������������������������������0000664�0000000�0000000�00000047424�13473601511�0015353�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* segment.c */ /* */ /* Segments for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> #include <errno.h> /* common */ #include "addrsize.h" #include "alignment.h" #include "coll.h" #include "mmodel.h" #include "segdefs.h" #include "segnames.h" #include "xmalloc.h" /* cc65 */ #include "error.h" #include "fragment.h" #include "global.h" #include "lineinfo.h" #include "listing.h" #include "objcode.h" #include "objfile.h" #include "segment.h" #include "span.h" #include "spool.h" #include "studyexpr.h" #include "symtab.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* If OrgPerSeg is false, all segments share the RelocMode flag and a PC ** used when in absolute mode. OrgPerSeg may be set by .feature org_per_seg */ static int RelocMode = 1; static unsigned long AbsPC = 0; /* PC if in absolute mode */ /* Definitions for predefined segments */ SegDef NullSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_NULL, ADDR_SIZE_ABS); SegDef ZeropageSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_ZEROPAGE, ADDR_SIZE_ZP); SegDef DataSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_DATA, ADDR_SIZE_ABS); SegDef BssSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_BSS, ADDR_SIZE_ABS); SegDef RODataSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_RODATA, ADDR_SIZE_ABS); SegDef CodeSegDef = STATIC_SEGDEF_INITIALIZER (SEGNAME_CODE, ADDR_SIZE_ABS); /* Collection containing all segments */ Collection SegmentList = STATIC_COLLECTION_INITIALIZER; /* Currently active segment */ Segment* ActiveSeg; /*****************************************************************************/ /* Code */ /*****************************************************************************/ static Segment* NewSegFromDef (SegDef* Def) /* Create a new segment from a segment definition. Used only internally, no ** checks. */ { /* Create a new segment */ Segment* S = xmalloc (sizeof (*S)); /* Initialize it */ S->Root = 0; S->Last = 0; S->FragCount = 0; S->Num = CollCount (&SegmentList); S->Flags = SEG_FLAG_NONE; S->Align = 1; S->RelocMode = 1; S->PC = 0; S->AbsPC = 0; S->Def = Def; /* Insert it into the segment list */ CollAppend (&SegmentList, S); /* And return it... */ return S; } static Segment* NewSegment (const char* Name, unsigned char AddrSize) /* Create a new segment, insert it into the global list and return it */ { /* Check for too many segments */ if (CollCount (&SegmentList) >= 256) { Fatal ("Too many segments"); } /* Check the segment name for invalid names */ if (!ValidSegName (Name)) { Error ("Illegal segment name: '%s'", Name); } /* Create a new segment and return it */ return NewSegFromDef (NewSegDef (Name, AddrSize)); } Fragment* GenFragment (unsigned char Type, unsigned short Len) /* Generate a new fragment, add it to the current segment and return it. */ { /* Create the new fragment */ Fragment* F = NewFragment (Type, Len); /* Insert the fragment into the current segment */ if (ActiveSeg->Root) { ActiveSeg->Last->Next = F; ActiveSeg->Last = F; } else { ActiveSeg->Root = ActiveSeg->Last = F; } ++ActiveSeg->FragCount; /* Add this fragment to the current listing line */ if (LineCur) { if (LineCur->FragList == 0) { LineCur->FragList = F; } else { LineCur->FragLast->LineList = F; } LineCur->FragLast = F; } /* Increment the program counter */ ActiveSeg->PC += F->Len; if (OrgPerSeg) { /* Relocatable mode is switched per segment */ if (!ActiveSeg->RelocMode) { ActiveSeg->AbsPC += F->Len; } } else { /* Relocatable mode is switched globally */ if (!RelocMode) { AbsPC += F->Len; } } /* Return the fragment */ return F; } void UseSeg (const SegDef* D) /* Use the segment with the given name */ { unsigned I; for (I = 0; I < CollCount (&SegmentList); ++I) { Segment* Seg = CollAtUnchecked (&SegmentList, I); if (strcmp (Seg->Def->Name, D->Name) == 0) { /* We found this segment. Check if the type is identical */ if (D->AddrSize != ADDR_SIZE_DEFAULT && Seg->Def->AddrSize != D->AddrSize) { Error ("Segment attribute mismatch"); /* Use the new attribute to avoid errors */ Seg->Def->AddrSize = D->AddrSize; } ActiveSeg = Seg; return; } } /* Segment is not in list, create a new one */ if (D->AddrSize == ADDR_SIZE_DEFAULT) { ActiveSeg = NewSegment (D->Name, ADDR_SIZE_ABS); } else { ActiveSeg = NewSegment (D->Name, D->AddrSize); } } unsigned long GetPC (void) /* Get the program counter of the current segment */ { if (OrgPerSeg) { /* Relocatable mode is switched per segment */ return ActiveSeg->RelocMode? ActiveSeg->PC : ActiveSeg->AbsPC; } else { /* Relocatable mode is switched globally */ return RelocMode? ActiveSeg->PC : AbsPC; } } void EnterAbsoluteMode (unsigned long PC) /* Enter absolute (non relocatable mode). Depending on the OrgPerSeg flag, ** this will either switch the mode globally or for the current segment. */ { if (OrgPerSeg) { /* Relocatable mode is switched per segment */ ActiveSeg->RelocMode = 0; ActiveSeg->AbsPC = PC; } else { /* Relocatable mode is switched globally */ RelocMode = 0; AbsPC = PC; } } int GetRelocMode (void) /* Return true if we're currently in relocatable mode */ { if (OrgPerSeg) { /* Relocatable mode is switched per segment */ return ActiveSeg->RelocMode; } else { /* Relocatable mode is switched globally */ return RelocMode; } } void EnterRelocMode (void) /* Enter relocatable mode. Depending on the OrgPerSeg flag, this will either ** switch the mode globally or for the current segment. */ { if (OrgPerSeg) { /* Relocatable mode is switched per segment */ ActiveSeg->RelocMode = 1; } else { /* Relocatable mode is switched globally */ RelocMode = 1; } } void SegAlign (unsigned long Alignment, int FillVal) /* Align the PC segment to Alignment. If FillVal is -1, emit fill fragments ** (the actual fill value will be determined by the linker), otherwise use ** the given value. */ { unsigned char Data [4]; unsigned long CombinedAlignment; unsigned long Count; /* The segment must have the combined alignment of all separate alignments ** in the source. Calculate this alignment and check it for sanity. */ CombinedAlignment = LeastCommonMultiple (ActiveSeg->Align, Alignment); if (CombinedAlignment > MAX_ALIGNMENT) { Error ("Combined alignment for active segment is %lu which exceeds %lu", CombinedAlignment, MAX_ALIGNMENT); /* Avoid creating large fills for an object file that is thrown away ** later. */ Count = 1; } else { ActiveSeg->Align = CombinedAlignment; /* Output a warning for larger alignments if not suppressed */ if (CombinedAlignment > LARGE_ALIGNMENT && !LargeAlignment) { Warning (0, "Combined alignment is suspiciously large (%lu)", CombinedAlignment); } /* Calculate the number of fill bytes */ Count = AlignCount (ActiveSeg->PC, Alignment); } /* Emit the data or a fill fragment */ if (FillVal != -1) { /* User defined fill value */ memset (Data, FillVal, sizeof (Data)); while (Count) { if (Count > sizeof (Data)) { EmitData (Data, sizeof (Data)); Count -= sizeof (Data); } else { EmitData (Data, Count); Count = 0; } } } else { /* Linker defined fill value */ EmitFill (Count); } } unsigned char GetSegAddrSize (unsigned SegNum) /* Return the address size of the segment with the given number */ { /* Is there such a segment? */ if (SegNum >= CollCount (&SegmentList)) { FAIL ("Invalid segment number"); } /* Return the address size */ return ((Segment*) CollAtUnchecked (&SegmentList, SegNum))->Def->AddrSize; } void SegDone (void) /* Check the segments for range and other errors. Do cleanup. */ { static const unsigned long U_Hi[4] = { 0x000000FFUL, 0x0000FFFFUL, 0x00FFFFFFUL, 0xFFFFFFFFUL }; static const long S_Hi[4] = { 0x0000007FL, 0x00007FFFL, 0x007FFFFFL, 0x7FFFFFFFL }; unsigned I; for (I = 0; I < CollCount (&SegmentList); ++I) { Segment* S = CollAtUnchecked (&SegmentList, I); Fragment* F = S->Root; while (F) { if (F->Type == FRAG_EXPR || F->Type == FRAG_SEXPR) { /* We have an expression, study it */ ExprDesc ED; ED_Init (&ED); StudyExpr (F->V.Expr, &ED); /* Check if the expression is constant */ if (ED_IsConst (&ED)) { unsigned J; /* The expression is constant. Check for range errors. */ CHECK (F->Len <= 4); if (F->Type == FRAG_SEXPR) { long Hi = S_Hi[F->Len-1]; long Lo = ~Hi; if (ED.Val > Hi || ED.Val < Lo) { LIError (&F->LI, "Range error (%ld not in [%ld..%ld])", ED.Val, Lo, Hi); } } else { if (((unsigned long)ED.Val) > U_Hi[F->Len-1]) { LIError (&F->LI, "Range error (%lu not in [0..%lu])", (unsigned long)ED.Val, U_Hi[F->Len-1]); } } /* We don't need the expression tree any longer */ FreeExpr (F->V.Expr); /* Convert the fragment into a literal fragment */ for (J = 0; J < F->Len; ++J) { F->V.Data[J] = ED.Val & 0xFF; ED.Val >>= 8; } F->Type = FRAG_LITERAL; } else if (RelaxChecks == 0) { /* We cannot evaluate the expression now, leave the job for ** the linker. However, we can check if the address size ** matches the fragment size. Mismatches are errors in ** most situations. */ if ((F->Len == 1 && ED.AddrSize > ADDR_SIZE_ZP) || (F->Len == 2 && ED.AddrSize > ADDR_SIZE_ABS) || (F->Len == 3 && ED.AddrSize > ADDR_SIZE_FAR)) { LIError (&F->LI, "Range error"); } } /* Release memory allocated for the expression decriptor */ ED_Done (&ED); } F = F->Next; } } } void SegDump (void) /* Dump the contents of all segments */ { unsigned I; unsigned X = 0; printf ("\n"); for (I = 0; I < CollCount (&SegmentList); ++I) { Segment* S = CollAtUnchecked (&SegmentList, I); unsigned I; Fragment* F; int State = -1; printf ("New segment: %s", S->Def->Name); F = S->Root; while (F) { if (F->Type == FRAG_LITERAL) { if (State != 0) { printf ("\n Literal:"); X = 15; State = 0; } for (I = 0; I < F->Len; ++I) { printf (" %02X", F->V.Data [I]); X += 3; } } else if (F->Type == FRAG_EXPR || F->Type == FRAG_SEXPR) { State = 1; printf ("\n Expression (%u): ", F->Len); DumpExpr (F->V.Expr, SymResolve); } else if (F->Type == FRAG_FILL) { State = 1; printf ("\n Fill bytes (%u)", F->Len); } else { Internal ("Unknown fragment type: %u", F->Type); } if (X > 65) { State = -1; } F = F->Next; } printf ("\n End PC = $%04X\n", (unsigned)(S->PC & 0xFFFF)); } printf ("\n"); } void SegInit (void) /* Initialize segments */ { /* Create the predefined segments. Code segment is active */ ActiveSeg = NewSegFromDef (&CodeSegDef); NewSegFromDef (&RODataSegDef); NewSegFromDef (&BssSegDef); NewSegFromDef (&DataSegDef); NewSegFromDef (&ZeropageSegDef); NewSegFromDef (&NullSegDef); } void SetSegmentSizes (void) /* Set the default segment sizes according to the memory model */ { /* Initialize segment sizes. The segment definitions do already contain ** the correct values for the default case (near), so we must only change ** things that should be different. */ switch (MemoryModel) { case MMODEL_NEAR: break; case MMODEL_FAR: CodeSegDef.AddrSize = ADDR_SIZE_FAR; break; case MMODEL_HUGE: CodeSegDef.AddrSize = ADDR_SIZE_FAR; DataSegDef.AddrSize = ADDR_SIZE_FAR; BssSegDef.AddrSize = ADDR_SIZE_FAR; RODataSegDef.AddrSize = ADDR_SIZE_FAR; break; default: Internal ("Invalid memory model: %d", MemoryModel); } } static void WriteOneSeg (Segment* Seg) /* Write one segment to the object file */ { Fragment* Frag; unsigned long DataSize; unsigned long EndPos; /* Remember the file position, then write a dummy for the size of the ** following data */ unsigned long SizePos = ObjGetFilePos (); ObjWrite32 (0); /* Write the segment data */ ObjWriteVar (GetStringId (Seg->Def->Name)); /* Name of the segment */ ObjWriteVar (Seg->Flags); /* Segment flags */ ObjWriteVar (Seg->PC); /* Size */ ObjWriteVar (Seg->Align); /* Segment alignment */ ObjWrite8 (Seg->Def->AddrSize); /* Address size of the segment */ ObjWriteVar (Seg->FragCount); /* Number of fragments */ /* Now walk through the fragment list for this segment and write the ** fragments. */ Frag = Seg->Root; while (Frag) { /* Write data depending on the type */ switch (Frag->Type) { case FRAG_LITERAL: ObjWrite8 (FRAG_LITERAL); ObjWriteVar (Frag->Len); ObjWriteData (Frag->V.Data, Frag->Len); break; case FRAG_EXPR: switch (Frag->Len) { case 1: ObjWrite8 (FRAG_EXPR8); break; case 2: ObjWrite8 (FRAG_EXPR16); break; case 3: ObjWrite8 (FRAG_EXPR24); break; case 4: ObjWrite8 (FRAG_EXPR32); break; default: Internal ("Invalid fragment size: %u", Frag->Len); } WriteExpr (Frag->V.Expr); break; case FRAG_SEXPR: switch (Frag->Len) { case 1: ObjWrite8 (FRAG_SEXPR8); break; case 2: ObjWrite8 (FRAG_SEXPR16); break; case 3: ObjWrite8 (FRAG_SEXPR24); break; case 4: ObjWrite8 (FRAG_SEXPR32); break; default: Internal ("Invalid fragment size: %u", Frag->Len); } WriteExpr (Frag->V.Expr); break; case FRAG_FILL: ObjWrite8 (FRAG_FILL); ObjWriteVar (Frag->Len); break; default: Internal ("Invalid fragment type: %u", Frag->Type); } /* Write the line infos for this fragment */ WriteLineInfo (&Frag->LI); /* Next fragment */ Frag = Frag->Next; } /* Calculate the size of the data, seek back and write it */ EndPos = ObjGetFilePos (); /* Remember where we are */ DataSize = EndPos - SizePos - 4; /* Don't count size itself */ ObjSetFilePos (SizePos); /* Seek back to the size */ ObjWrite32 (DataSize); /* Write the size */ ObjSetFilePos (EndPos); /* Seek back to the end */ } void WriteSegments (void) /* Write the segment data to the object file */ { unsigned I; /* Tell the object file module that we're about to start the seg list */ ObjStartSegments (); /* First thing is segment count */ ObjWriteVar (CollCount (&SegmentList)); /* Now walk through all segments and write them to the object file */ for (I = 0; I < CollCount (&SegmentList); ++I) { /* Write one segment */ WriteOneSeg (CollAtUnchecked (&SegmentList, I)); } /* Done writing segments */ ObjEndSegments (); } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/segment.h������������������������������������������������������������������������0000664�0000000�0000000�00000014630�13473601511�0015351�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* segment.h */ /* */ /* Segments for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef SEGMENT_H #define SEGMENT_H /* common */ #include "coll.h" #include "fragdefs.h" #include "inline.h" /* ca65 */ #include "fragment.h" #include "segdef.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Segment definition */ typedef struct Segment Segment; struct Segment { Fragment* Root; /* Root of fragment list */ Fragment* Last; /* Pointer to last fragment */ unsigned long FragCount; /* Number of fragments */ unsigned Num; /* Segment number */ unsigned Flags; /* Segment flags */ unsigned long Align; /* Segment alignment */ int RelocMode; /* Relocatable mode if OrgPerSeg */ unsigned long PC; /* PC if in relocatable mode */ unsigned long AbsPC; /* PC if in local absolute mode */ /* (OrgPerSeg is true) */ SegDef* Def; /* Segment definition (name and type) */ }; /* Definitions for predefined segments */ extern SegDef NullSegDef; extern SegDef ZeropageSegDef; extern SegDef DataSegDef; extern SegDef BssSegDef; extern SegDef RODataSegDef; extern SegDef CodeSegDef; /* Collection containing all segments */ extern Collection SegmentList; /* Currently active segment */ extern Segment* ActiveSeg; /*****************************************************************************/ /* Code */ /*****************************************************************************/ Fragment* GenFragment (unsigned char Type, unsigned short Len); /* Generate a new fragment, add it to the current segment and return it. */ void UseSeg (const SegDef* D); /* Use the given segment */ #if defined(HAVE_INLINE) INLINE const SegDef* GetCurrentSegDef (void) /* Get a pointer to the segment defininition of the current segment */ { return ActiveSeg->Def; } #else # define GetCurrentSegDef() (ActiveSeg->Def) #endif #if defined(HAVE_INLINE) INLINE unsigned GetCurrentSegNum (void) /* Get the number of the current segment */ { return ActiveSeg->Num; } #else # define GetCurrentSegNum() (ActiveSeg->Num) #endif #if defined(HAVE_INLINE) INLINE unsigned char GetCurrentSegAddrSize (void) /* Get the address size of the current segment */ { return ActiveSeg->Def->AddrSize; } #else # define GetCurrentSegAddrSize() (ActiveSeg->Def->AddrSize) #endif void SegAlign (unsigned long Alignment, int FillVal); /* Align the PC segment to Alignment. If FillVal is -1, emit fill fragments ** (the actual fill value will be determined by the linker), otherwise use ** the given value. */ unsigned char GetSegAddrSize (unsigned SegNum); /* Return the address size of the segment with the given number */ unsigned long GetPC (void); /* Get the program counter of the current segment */ int GetRelocMode (void); /* Return true if we're currently in relocatable mode */ void EnterAbsoluteMode (unsigned long AbsPC); /* Enter absolute (non relocatable mode). Depending on the OrgPerSeg flag, ** this will either switch the mode globally or for the current segment. */ void EnterRelocMode (void); /* Enter relocatable mode. Depending on the OrgPerSeg flag, this will either ** switch the mode globally or for the current segment. */ void SegDone (void); /* Check the segments for range and other errors. Do cleanup. */ void SegDump (void); /* Dump the contents of all segments */ void SegInit (void); /* Initialize segments */ void SetSegmentSizes (void); /* Set the default segment sizes according to the memory model */ void WriteSegments (void); /* Write the segment data to the object file */ /* End of segment.h */ #endif ��������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/sizeof.c�������������������������������������������������������������������������0000664�0000000�0000000�00000012167�13473601511�0015204�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* sizeof.c */ /* */ /* Handle sizes of types and data */ /* */ /* */ /* */ /* (C) 2003-2011, Ullrich von Bassewit */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "addrsize.h" /* ca65 */ #include "expr.h" #include "sizeof.h" #include "symtab.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* The name of the symbol used to encode the size. The name of this entry is ** choosen so that it cannot be accessed by the user. */ static const StrBuf SizeEntryName = LIT_STRBUF_INITIALIZER (".size"); /*****************************************************************************/ /* Code */ /*****************************************************************************/ int IsSizeOfSymbol (const SymEntry* Sym) /* Return true if the given symbol is the one that encodes the size of some ** entity. Sym may also be a NULL pointer in which case false is returned. */ { return (Sym != 0 && SB_Compare (GetSymName (Sym), &SizeEntryName) == 0); } SymEntry* FindSizeOfScope (SymTable* Scope) /* Get the size of a scope. The function returns the symbol table entry that ** encodes the size or NULL if there is no such entry. */ { return SymFind (Scope, &SizeEntryName, SYM_FIND_EXISTING); } SymEntry* FindSizeOfSymbol (SymEntry* Sym) /* Get the size of a symbol table entry. The function returns the symbol table ** entry that encodes the size of the symbol or NULL if there is no such entry. */ { return SymFindLocal (Sym, &SizeEntryName, SYM_FIND_EXISTING); } SymEntry* GetSizeOfScope (SymTable* Scope) /* Get the size of a scope. The function returns the symbol table entry that ** encodes the size, and will create a new entry if it does not exist. */ { return SymFind (Scope, &SizeEntryName, SYM_ALLOC_NEW); } SymEntry* GetSizeOfSymbol (SymEntry* Sym) /* Get the size of a symbol table entry. The function returns the symbol table ** entry that encodes the size of the symbol and will create a new one if it ** does not exist. */ { return SymFindLocal (Sym, &SizeEntryName, SYM_ALLOC_NEW); } SymEntry* DefSizeOfScope (SymTable* Scope, long Size) /* Define the size of a scope and return the size symbol */ { SymEntry* SizeSym = GetSizeOfScope (Scope); SymDef (SizeSym, GenLiteralExpr (Size), ADDR_SIZE_DEFAULT, SF_NONE); return SizeSym; } SymEntry* DefSizeOfSymbol (SymEntry* Sym, long Size) /* Define the size of a symbol and return the size symbol */ { SymEntry* SizeSym = GetSizeOfSymbol (Sym); SymDef (SizeSym, GenLiteralExpr (Size), ADDR_SIZE_DEFAULT, SF_NONE); return SizeSym; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/sizeof.h�������������������������������������������������������������������������0000664�0000000�0000000�00000010645�13473601511�0015210�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* sizeof.h */ /* */ /* Handle sizes of types and data */ /* */ /* */ /* */ /* (C) 2003-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef SIZEOF_H #define SIZEOF_H /* common */ #include "strbuf.h" /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ struct SymEntry; struct SymTable; /*****************************************************************************/ /* Code */ /*****************************************************************************/ int IsSizeOfSymbol (const struct SymEntry* Sym); /* Return true if the given symbol is the one that encodes the size of some ** entity. Sym may also be a NULL pointer in which case false is returned. */ struct SymEntry* FindSizeOfScope (struct SymTable* Scope); /* Get the size of a scope. The function returns the symbol table entry that ** encodes the size or NULL if there is no such entry. */ struct SymEntry* FindSizeOfSymbol (struct SymEntry* Sym); /* Get the size of a symbol table entry. The function returns the symbol table ** entry that encodes the size of the symbol or NULL if there is no such entry. */ struct SymEntry* GetSizeOfScope (struct SymTable* Scope); /* Get the size of a scope. The function returns the symbol table entry that ** encodes the size, and will create a new entry if it does not exist. */ struct SymEntry* GetSizeOfSymbol (struct SymEntry* Sym); /* Get the size of a symbol table entry. The function returns the symbol table ** entry that encodes the size of the symbol and will create a new one if it ** does not exist. */ struct SymEntry* DefSizeOfScope (struct SymTable* Scope, long Size); /* Define the size of a scope and return the size symbol */ struct SymEntry* DefSizeOfSymbol (struct SymEntry* Sym, long Size); /* Define the size of a symbol and return the size symbol */ /* End of sizeof.h */ #endif �������������������������������������������������������������������������������������������cc65-2.18/src/ca65/span.c���������������������������������������������������������������������������0000664�0000000�0000000�00000030157�13473601511�0014645�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* span.c */ /* */ /* A span of data within a segment */ /* */ /* */ /* */ /* (C) 2003-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "hashfunc.h" #include "hashtab.h" #include "xmalloc.h" /* ca65 */ #include "global.h" #include "objfile.h" #include "segment.h" #include "span.h" #include "spool.h" /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ static unsigned HT_GenHash (const void* Key); /* Generate the hash over a key. */ static const void* HT_GetKey (const void* Entry); /* Given a pointer to the user entry data, return a pointer to the key */ static int HT_Compare (const void* Key1, const void* Key2); /* Compare two keys. The function must return a value less than zero if ** Key1 is smaller than Key2, zero if both are equal, and a value greater ** than zero if Key1 is greater then Key2. */ /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Hash table functions */ static const HashFunctions HashFunc = { HT_GenHash, HT_GetKey, HT_Compare }; /* Span hash table */ static HashTable SpanTab = STATIC_HASHTABLE_INITIALIZER (1051, &HashFunc); /*****************************************************************************/ /* Hash table functions */ /*****************************************************************************/ static unsigned HT_GenHash (const void* Key) /* Generate the hash over a key. */ { /* Key is a Span pointer */ const Span* S = Key; /* Hash over a combination of segment number, start and end */ return HashInt ((S->Seg->Num << 28) ^ (S->Start << 14) ^ S->End); } static const void* HT_GetKey (const void* Entry) /* Given a pointer to the user entry data, return a pointer to the key */ { return Entry; } static int HT_Compare (const void* Key1, const void* Key2) /* Compare two keys. The function must return a value less than zero if ** Key1 is smaller than Key2, zero if both are equal, and a value greater ** than zero if Key1 is greater then Key2. */ { /* Convert both parameters to Span pointers */ const Span* S1 = Key1; const Span* S2 = Key2; /* Compare segment number, then start and end */ int Res = (int)S2->Seg->Num - (int)S1->Seg->Num; if (Res == 0) { Res = (int)S2->Start - (int)S1->Start; if (Res == 0) { Res = (int)S2->End - (int)S1->End; } } /* Done */ return Res; } /*****************************************************************************/ /* Code */ /*****************************************************************************/ static Span* NewSpan (Segment* Seg, unsigned long Start, unsigned long End) /* Create a new span. The segment is set to Seg, Start and End are set to the ** current PC of the segment. */ { /* Allocate memory */ Span* S = xmalloc (sizeof (Span)); /* Initialize the struct */ InitHashNode (&S->Node); S->Id = ~0U; S->Seg = Seg; S->Start = Start; S->End = End; S->Type = EMPTY_STRING_ID; /* Return the new struct */ return S; } static void FreeSpan (Span* S) /* Free a span */ { xfree (S); } static Span* MergeSpan (Span* S) /* Check if we have a span with the same data as S already. If so, free S and ** return the already existing one. If not, remember S and return it. */ { /* Check if we have such a span already. If so use the existing ** one and free the one from the collection. If not, add the one to ** the hash table and return it. */ Span* E = HT_Find (&SpanTab, S); if (E) { /* If S has a type and E not, move the type */ if (S->Type != EMPTY_STRING_ID) { CHECK (E->Type == EMPTY_STRING_ID); E->Type = S->Type; } /* Free S and return E */ FreeSpan (S); return E; } else { /* Assign the id, insert S, then return it */ S->Id = HT_GetCount (&SpanTab); HT_Insert (&SpanTab, S); return S; } } void SetSpanType (Span* S, const StrBuf* Type) /* Set the generic type of the span to Type */ { /* Ignore the call if we won't generate debug infos */ if (DbgSyms) { S->Type = GetStrBufId (Type); } } Span* OpenSpan (void) /* Open a span for the active segment and return it. */ { return NewSpan (ActiveSeg, ActiveSeg->PC, ActiveSeg->PC); } Span* CloseSpan (Span* S) /* Close the given span. Be sure to replace the passed span by the one ** returned, since the span will get deleted if it is empty or may be ** replaced if a duplicate exists. */ { /* Set the end offset */ if (S->Start == S->Seg->PC) { /* Span is empty */ FreeSpan (S); return 0; } else { /* Span is not empty */ S->End = S->Seg->PC; /* Check if we have such a span already. If so use the existing ** one and free the one from the collection. If not, add the one to ** the hash table and return it. */ return MergeSpan (S); } } void OpenSpanList (Collection* Spans) /* Open a list of spans for all existing segments to the given collection of ** spans. The currently active segment will be inserted first with all others ** following. */ { unsigned I; /* Grow the Spans collection as necessary */ CollGrow (Spans, CollCount (&SegmentList)); /* Add the currently active segment */ CollAppend (Spans, NewSpan (ActiveSeg, ActiveSeg->PC, ActiveSeg->PC)); /* Walk through the segment list and add all other segments */ for (I = 0; I < CollCount (&SegmentList); ++I) { Segment* Seg = CollAtUnchecked (&SegmentList, I); /* Be sure to skip the active segment, since it was already added */ if (Seg != ActiveSeg) { CollAppend (Spans, NewSpan (Seg, Seg->PC, Seg->PC)); } } } void CloseSpanList (Collection* Spans) /* Close a list of spans. This will add new segments to the list, mark the end ** of existing ones, and remove empty spans from the list. */ { unsigned I, J; /* Have new segments been added while the span list was open? */ for (I = CollCount (Spans); I < CollCount (&SegmentList); ++I) { /* Add new spans if not empty */ Segment* S = CollAtUnchecked (&SegmentList, I); if (S->PC == 0) { /* Segment is empty */ continue; } CollAppend (Spans, NewSpan (S, 0, S->PC)); } /* Walk over the spans, close open, remove empty ones */ for (I = 0, J = 0; I < CollCount (Spans); ++I) { /* Get the next span */ Span* S = CollAtUnchecked (Spans, I); /* Set the end offset */ if (S->Start == S->Seg->PC) { /* Span is empty */ FreeSpan (S); } else { /* Span is not empty */ S->End = S->Seg->PC; /* Merge duplicate spans, then insert it at the new position */ CollReplace (Spans, MergeSpan (S), J++); } } /* New Count is now in J */ Spans->Count = J; } void WriteSpanList (const Collection* Spans) /* Write a list of spans to the output file */ { unsigned I; /* We only write spans if debug info is enabled */ if (DbgSyms == 0) { /* Number of spans is zero */ ObjWriteVar (0); } else { /* Write the number of spans */ ObjWriteVar (CollCount (Spans)); /* Write the spans */ for (I = 0; I < CollCount (Spans); ++I) { /* Write the id of the next span */ ObjWriteVar (((const Span*)CollConstAt (Spans, I))->Id); } } } static int CollectSpans (void* Entry, void* Data) /* Collect all spans in a collection sorted by id */ { /* Cast the pointers to real objects */ Span* S = Entry; Collection* C = Data; /* Place the entry into the collection */ CollReplaceExpand (C, S, S->Id); /* Keep the span */ return 0; } void WriteSpans (void) /* Write all spans to the object file */ { /* Tell the object file module that we're about to start the spans */ ObjStartSpans (); /* We will write scopes only if debug symbols are requested */ if (DbgSyms) { unsigned I; /* We must first collect all items in a collection sorted by id */ Collection SpanList = STATIC_COLLECTION_INITIALIZER; CollGrow (&SpanList, HT_GetCount (&SpanTab)); /* Walk over the hash table and fill the span list */ HT_Walk (&SpanTab, CollectSpans, &SpanList); /* Write the span count to the file */ ObjWriteVar (CollCount (&SpanList)); /* Write all spans */ for (I = 0; I < CollCount (&SpanList); ++I) { /* Get the span and check it */ const Span* S = CollAtUnchecked (&SpanList, I); CHECK (S->End > S->Start); /* Write data for the span We will write the size instead of the ** end offset to save some bytes, since most spans are expected ** to be rather small. */ ObjWriteVar (S->Seg->Num); ObjWriteVar (S->Start); ObjWriteVar (S->End - S->Start); ObjWriteVar (S->Type); } /* Free the collection with the spans */ DoneCollection (&SpanList); } else { /* No debug info requested */ ObjWriteVar (0); } /* Done writing the spans */ ObjEndSpans (); } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/span.h���������������������������������������������������������������������������0000664�0000000�0000000�00000011261�13473601511�0014645�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* span.h */ /* */ /* A span of data within a segment */ /* */ /* */ /* */ /* (C) 2003-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef SPAN_H #define SPAN_H /* common */ #include "coll.h" #include "gentype.h" #include "hashtab.h" #include "inline.h" #include "strbuf.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Forwards */ struct Segment; /* Span definition */ typedef struct Span Span; struct Span{ HashNode Node; /* Node for hash table */ unsigned Id; /* Id of span */ struct Segment* Seg; /* Pointer to segment */ unsigned Start; /* Start of range */ unsigned End; /* End of range */ unsigned Type; /* Type of data in span */ }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ #if defined(HAVE_INLINE) INLINE unsigned long GetSpanSize (const Span* R) /* Return the span size in bytes */ { return (R->End - R->Start); } #else # define GetSpanSize(R) ((R)->End - (R)->Start) #endif void SetSpanType (Span* S, const StrBuf* Type); /* Set the generic type of the span to Type */ Span* OpenSpan (void); /* Open a span for the active segment and return it. */ Span* CloseSpan (Span* S); /* Close the given span. Be sure to replace the passed span by the one ** returned, since the span will get deleted if it is empty or may be ** replaced if a duplicate exists. */ void OpenSpanList (Collection* Spans); /* Open a list of spans for all existing segments to the given collection of ** spans. The currently active segment will be inserted first with all others ** following. */ void CloseSpanList (Collection* Spans); /* Close all open spans by setting PC to the current PC for the segment. */ void WriteSpanList (const Collection* Spans); /* Write a list of spans to the output file */ void WriteSpans (void); /* Write all spans to the object file */ /* End of span.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/spool.c��������������������������������������������������������������������������0000664�0000000�0000000�00000007501�13473601511�0015035�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* spool.c */ /* */ /* Id and message pool for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 2003-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* ca65 */ #include "objfile.h" #include "spool.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ StringPool* StrPool = 0; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void WriteStrPool (void) /* Write the string pool to the object file */ { unsigned I; /* Get the number of strings in the string pool */ unsigned Count = SP_GetCount (StrPool); /* Tell the object file module that we're about to start the string pool */ ObjStartStrPool (); /* Write the string count to the list */ ObjWriteVar (Count); /* Write the strings in id order */ for (I = 0; I < Count; ++I) { ObjWriteBuf (SP_Get (StrPool, I)); } /* Done writing the string pool */ ObjEndStrPool (); } void InitStrPool (void) /* Initialize the string pool */ { /* Create a string pool */ StrPool = NewStringPool (1103); /* Insert an empty string. It will have string id 0 */ SP_AddStr (StrPool, ""); } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/spool.h��������������������������������������������������������������������������0000664�0000000�0000000�00000010363�13473601511�0015042�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* spool.h */ /* */ /* Id and message pool for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 2003-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef SPOOL_H #define SPOOL_H /* common */ #include "strpool.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* The index for an empty string */ #define EMPTY_STRING_ID 0U /* The string pool */ extern StringPool* StrPool; /*****************************************************************************/ /* Code */ /*****************************************************************************/ #if defined(HAVE_INLINE) INLINE unsigned GetStrBufId (const StrBuf* S) /* Return the id of the given string buffer */ { return SP_Add (StrPool, S); } #else # define GetStrBufId(S) SP_Add (StrPool, (S)) #endif #if defined(HAVE_INLINE) INLINE unsigned GetStringId (const char* S) /* Return the id of the given string */ { return SP_AddStr (StrPool, S); } #else # define GetStringId(S) SP_AddStr (StrPool, (S)) #endif #if defined(HAVE_INLINE) INLINE const StrBuf* GetStrBuf (unsigned Index) /* Convert a string index into a string */ { return SP_Get (StrPool, Index); } #else # define GetStrBuf(Index) SP_Get (StrPool, (Index)) #endif #if defined(HAVE_INLINE) INLINE const char* GetString (unsigned Index) /* Convert a string index into a string */ { return SB_GetConstBuf (SP_Get (StrPool, Index)); } #else # define GetString(Index) SB_GetConstBuf (SP_Get (StrPool, (Index))) #endif void WriteStrPool (void); /* Write the string pool to the object file */ void InitStrPool (void); /* Initialize the string pool */ /* End of spool.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/struct.c�������������������������������������������������������������������������0000664�0000000�0000000�00000022507�13473601511�0015230�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* struct.c */ /* */ /* .STRUCT/.UNION commands */ /* */ /* */ /* */ /* (C) 2003-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "addrsize.h" #include "scopedefs.h" /* ca65 */ #include "condasm.h" #include "error.h" #include "expr.h" #include "macro.h" #include "nexttok.h" #include "scanner.h" #include "sizeof.h" #include "symbol.h" #include "symtab.h" #include "struct.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ enum { STRUCT, UNION }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ static long Member (long AllocSize) /* Read one struct member and return its size */ { long Multiplicator; /* A multiplicator may follow */ if (CurTok.Tok != TOK_SEP) { Multiplicator = ConstExpression (); if (Multiplicator <= 0) { ErrorSkip ("Range error"); Multiplicator = 1; } AllocSize *= Multiplicator; } /* Check the size for a reasonable value */ if (AllocSize >= 0x10000) { ErrorSkip ("Range error"); } /* Return the size */ return AllocSize; } static long DoStructInternal (long Offs, unsigned Type) /* Handle the .STRUCT command */ { long Size = 0; /* Outside of other structs, we need a name. Inside another struct or ** union, the struct may be anonymous, in which case no new lexical level ** is started. */ int Anon = (CurTok.Tok != TOK_IDENT); if (!Anon) { /* Enter a new scope, then skip the name */ SymEnterLevel (&CurTok.SVal, SCOPE_STRUCT, ADDR_SIZE_ABS, 0); NextTok (); /* Start at zero offset in the new scope */ Offs = 0; } /* Test for end of line */ ConsumeSep (); /* Read until end of struct */ while (CurTok.Tok != TOK_ENDSTRUCT && CurTok.Tok != TOK_ENDUNION && CurTok.Tok != TOK_EOF) { long MemberSize; SymTable* Struct; SymEntry* Sym; /* Allow empty and comment lines */ if (CurTok.Tok == TOK_SEP) { NextTok (); continue; } /* The format is "[identifier] storage-allocator [, multiplicator]" */ Sym = 0; if (CurTok.Tok == TOK_IDENT) { /* Beware: An identifier may also be a macro, in which case we have ** to start over. */ Macro* M = FindMacro (&CurTok.SVal); if (M) { MacExpandStart (M); continue; } /* We have an identifier, generate a symbol */ Sym = SymFind (CurrentScope, &CurTok.SVal, SYM_ALLOC_NEW); /* Assign the symbol the offset of the current member */ SymDef (Sym, GenLiteralExpr (Offs), ADDR_SIZE_DEFAULT, SF_NONE); /* Skip the member name */ NextTok (); } /* Read storage allocators */ MemberSize = 0; /* In case of errors, use zero */ switch (CurTok.Tok) { case TOK_BYTE: NextTok (); MemberSize = Member (1); break; case TOK_DBYT: case TOK_WORD: case TOK_ADDR: NextTok (); MemberSize = Member (2); break; case TOK_FARADDR: NextTok (); MemberSize = Member (3); break; case TOK_DWORD: NextTok (); MemberSize = Member (4); break; case TOK_RES: NextTok (); if (CurTok.Tok == TOK_SEP) { ErrorSkip ("Size is missing"); } else { MemberSize = Member (1); } break; case TOK_TAG: NextTok (); Struct = ParseScopedSymTable (); if (Struct == 0) { ErrorSkip ("Unknown struct/union"); } else if (GetSymTabType (Struct) != SCOPE_STRUCT) { ErrorSkip ("Not a struct/union"); } else { SymEntry* SizeSym = GetSizeOfScope (Struct); if (!SymIsDef (SizeSym) || !SymIsConst (SizeSym, &MemberSize)) { ErrorSkip ("Size of struct/union is unknown"); } } MemberSize = Member (MemberSize); break; case TOK_STRUCT: NextTok (); MemberSize = DoStructInternal (Offs, STRUCT); break; case TOK_UNION: NextTok (); MemberSize = DoStructInternal (Offs, UNION); break; default: if (!CheckConditionals ()) { /* Not a conditional directive */ ErrorSkip ("Invalid storage allocator in struct/union"); } } /* Assign the size to the member if it has a name */ if (Sym) { DefSizeOfSymbol (Sym, MemberSize); } /* Next member */ if (Type == STRUCT) { /* Struct */ Offs += MemberSize; Size += MemberSize; } else { /* Union */ if (MemberSize > Size) { Size = MemberSize; } } /* Expect end of line */ ConsumeSep (); } /* If this is not a anon struct, enter a special symbol named ".size" ** into the symbol table of the struct that holds the size of the ** struct. Since the symbol starts with a dot, it cannot be accessed ** by user code. ** Leave the struct scope level. */ if (!Anon) { /* Add a symbol */ SymEntry* SizeSym = GetSizeOfScope (CurrentScope); SymDef (SizeSym, GenLiteralExpr (Size), ADDR_SIZE_DEFAULT, SF_NONE); /* Close the struct scope */ SymLeaveLevel (); } /* End of struct/union definition */ if (Type == STRUCT) { Consume (TOK_ENDSTRUCT, "'.ENDSTRUCT' expected"); } else { Consume (TOK_ENDUNION, "'.ENDUNION' expected"); } /* Return the size of the struct */ return Size; } long GetStructSize (SymTable* Struct) /* Get the size of a struct or union */ { SymEntry* SizeSym = FindSizeOfScope (Struct); if (SizeSym == 0) { Error ("Size of struct/union is unknown"); return 0; } else { return GetSymVal (SizeSym); } } void DoStruct (void) /* Handle the .STRUCT command */ { DoStructInternal (0, STRUCT); } void DoUnion (void) /* Handle the .UNION command */ { DoStructInternal (0, UNION); } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/struct.h�������������������������������������������������������������������������0000664�0000000�0000000�00000006376�13473601511�0015243�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* struct.h */ /* */ /* .STRUCT/.UNION commands */ /* */ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ /* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef STRUCT_H #define STRUCT_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ struct SymTable; /*****************************************************************************/ /* Code */ /*****************************************************************************/ long GetStructSize (struct SymTable* Struct); /* Get the size of a struct */ void DoStruct (void); /* Handle the .STRUCT command */ void DoUnion (void); /* Handle the .UNION command */ /* End of struct.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/studyexpr.c����������������������������������������������������������������������0000664�0000000�0000000�00000112566�13473601511�0015760�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* studyexpr.c */ /* */ /* Study an expression tree */ /* */ /* */ /* */ /* (C) 2003-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* common */ #include "check.h" #include "debugflag.h" #include "shift.h" #include "xmalloc.h" /* ca65 */ #include "error.h" #include "segment.h" #include "studyexpr.h" #include "symtab.h" #include "ulabel.h" /*****************************************************************************/ /* struct ExprDesc */ /*****************************************************************************/ ExprDesc* ED_Init (ExprDesc* ED) /* Initialize an ExprDesc structure for use with StudyExpr */ { ED->Flags = ED_OK; ED->AddrSize = ADDR_SIZE_DEFAULT; ED->Val = 0; ED->SymCount = 0; ED->SymLimit = 0; ED->SymRef = 0; ED->SecCount = 0; ED->SecLimit = 0; ED->SecRef = 0; return ED; } void ED_Done (ExprDesc* ED) /* Delete allocated memory for an ExprDesc. */ { xfree (ED->SymRef); xfree (ED->SecRef); } int ED_IsConst (const ExprDesc* D) /* Return true if the expression is constant */ { unsigned I; if (D->Flags & ED_TOO_COMPLEX) { return 0; } for (I = 0; I < D->SymCount; ++I) { if (D->SymRef[I].Count != 0) { return 0; } } for (I = 0; I < D->SecCount; ++I) { if (D->SecRef[I].Count != 0) { return 0; } } return 1; } static int ED_IsValid (const ExprDesc* D) /* Return true if the expression is valid, that is, neither the ERROR nor the ** TOO_COMPLEX flags are set. */ { return ((D->Flags & (ED_ERROR | ED_TOO_COMPLEX)) == 0); } static int ED_HasError (const ExprDesc* D) /* Return true if the expression has an error. */ { return ((D->Flags & ED_ERROR) != 0); } static void ED_Invalidate (ExprDesc* D) /* Set the TOO_COMPLEX flag for D */ { D->Flags |= ED_TOO_COMPLEX; } static void ED_SetError (ExprDesc* D) /* Set the TOO_COMPLEX and ERROR flags for D */ { D->Flags |= (ED_ERROR | ED_TOO_COMPLEX); } static void ED_UpdateAddrSize (ExprDesc* ED, unsigned char AddrSize) /* Update the address size of the expression */ { if (ED_IsValid (ED)) { /* ADDR_SIZE_DEFAULT may get overridden */ if (ED->AddrSize == ADDR_SIZE_DEFAULT || AddrSize > ED->AddrSize) { ED->AddrSize = AddrSize; } } else { /* ADDR_SIZE_DEFAULT takes precedence */ if (ED->AddrSize != ADDR_SIZE_DEFAULT) { if (AddrSize == ADDR_SIZE_DEFAULT || AddrSize > ED->AddrSize) { ED->AddrSize = AddrSize; } } } } static void ED_MergeAddrSize (ExprDesc* ED, const ExprDesc* Right) /* Merge the address sizes of two expressions into ED */ { if (ED->AddrSize == ADDR_SIZE_DEFAULT) { /* If ED is valid, ADDR_SIZE_DEFAULT gets always overridden, otherwise ** it takes precedence over anything else. */ if (ED_IsValid (ED)) { ED->AddrSize = Right->AddrSize; } } else if (Right->AddrSize == ADDR_SIZE_DEFAULT) { /* If Right is valid, ADDR_SIZE_DEFAULT gets always overridden, ** otherwise it takes precedence over anything else. */ if (!ED_IsValid (Right)) { ED->AddrSize = Right->AddrSize; } } else { /* Neither ED nor Right has a default address size, use the larger of ** the two. */ if (Right->AddrSize > ED->AddrSize) { ED->AddrSize = Right->AddrSize; } } } static ED_SymRef* ED_FindSymRef (ExprDesc* ED, SymEntry* Sym) /* Find a symbol reference and return it. Return NULL if the reference does ** not exist. */ { unsigned I; ED_SymRef* SymRef; for (I = 0, SymRef = ED->SymRef; I < ED->SymCount; ++I, ++SymRef) { if (SymRef->Ref == Sym) { return SymRef; } } return 0; } static ED_SecRef* ED_FindSecRef (ExprDesc* ED, unsigned Sec) /* Find a section reference and return it. Return NULL if the reference does ** not exist. */ { unsigned I; ED_SecRef* SecRef; for (I = 0, SecRef = ED->SecRef; I < ED->SecCount; ++I, ++SecRef) { if (SecRef->Ref == Sec) { return SecRef; } } return 0; } static ED_SymRef* ED_AllocSymRef (ExprDesc* ED, SymEntry* Sym) /* Allocate a new symbol reference and return it. The count of the new ** reference will be set to zero, and the reference itself to Sym. */ { ED_SymRef* SymRef; /* Make sure we have enough SymRef slots */ if (ED->SymCount >= ED->SymLimit) { ED->SymLimit *= 2; if (ED->SymLimit == 0) { ED->SymLimit = 2; } ED->SymRef = xrealloc (ED->SymRef, ED->SymLimit * sizeof (ED->SymRef[0])); } /* Allocate a new slot */ SymRef = ED->SymRef + ED->SymCount++; /* Initialize the new struct and return it */ SymRef->Count = 0; SymRef->Ref = Sym; return SymRef; } static ED_SecRef* ED_AllocSecRef (ExprDesc* ED, unsigned Sec) /* Allocate a new section reference and return it. The count of the new ** reference will be set to zero, and the reference itself to Sec. */ { ED_SecRef* SecRef; /* Make sure we have enough SecRef slots */ if (ED->SecCount >= ED->SecLimit) { ED->SecLimit *= 2; if (ED->SecLimit == 0) { ED->SecLimit = 2; } ED->SecRef = xrealloc (ED->SecRef, ED->SecLimit * sizeof (ED->SecRef[0])); } /* Allocate a new slot */ SecRef = ED->SecRef + ED->SecCount++; /* Initialize the new struct and return it */ SecRef->Count = 0; SecRef->Ref = Sec; return SecRef; } static ED_SymRef* ED_GetSymRef (ExprDesc* ED, SymEntry* Sym) /* Get a symbol reference and return it. If the symbol reference does not ** exist, a new one is created and returned. */ { ED_SymRef* SymRef = ED_FindSymRef (ED, Sym); if (SymRef == 0) { SymRef = ED_AllocSymRef (ED, Sym); } return SymRef; } static ED_SecRef* ED_GetSecRef (ExprDesc* ED, unsigned Sec) /* Get a section reference and return it. If the section reference does not ** exist, a new one is created and returned. */ { ED_SecRef* SecRef = ED_FindSecRef (ED, Sec); if (SecRef == 0) { SecRef = ED_AllocSecRef (ED, Sec); } return SecRef; } static void ED_MergeSymRefs (ExprDesc* ED, const ExprDesc* New) /* Merge the symbol references from New into ED */ { unsigned I; for (I = 0; I < New->SymCount; ++I) { /* Get a pointer to the SymRef entry */ const ED_SymRef* NewRef = New->SymRef + I; /* Get the corresponding entry in ED */ ED_SymRef* SymRef = ED_GetSymRef (ED, NewRef->Ref); /* Sum up the references */ SymRef->Count += NewRef->Count; } } static void ED_MergeSecRefs (ExprDesc* ED, const ExprDesc* New) /* Merge the section references from New into ED */ { unsigned I; for (I = 0; I < New->SecCount; ++I) { /* Get a pointer to the SymRef entry */ const ED_SecRef* NewRef = New->SecRef + I; /* Get the corresponding entry in ED */ ED_SecRef* SecRef = ED_GetSecRef (ED, NewRef->Ref); /* Sum up the references */ SecRef->Count += NewRef->Count; } } static void ED_MergeRefs (ExprDesc* ED, const ExprDesc* New) /* Merge all references from New into ED */ { ED_MergeSymRefs (ED, New); ED_MergeSecRefs (ED, New); } static void ED_NegRefs (ExprDesc* D) /* Negate the references in ED */ { unsigned I; for (I = 0; I < D->SymCount; ++I) { D->SymRef[I].Count = -D->SymRef[I].Count; } for (I = 0; I < D->SecCount; ++I) { D->SecRef[I].Count = -D->SecRef[I].Count; } } static void ED_Add (ExprDesc* ED, const ExprDesc* Right) /* Calculate ED = ED + Right, update address size in ED */ { ED->Val += Right->Val; ED_MergeRefs (ED, Right); ED_MergeAddrSize (ED, Right); } static void ED_Sub (ExprDesc* ED, const ExprDesc* Right) /* Calculate ED = ED - Right, update address size in ED */ { ExprDesc D = *Right; /* Temporary */ ED_NegRefs (&D); ED->Val -= Right->Val; ED_MergeRefs (ED, &D); /* Merge negatives */ ED_MergeAddrSize (ED, Right); } static void ED_Mul (ExprDesc* ED, const ExprDesc* Right) /* Calculate ED = ED * Right, update address size in ED */ { unsigned I; ED->Val *= Right->Val; for (I = 0; I < ED->SymCount; ++I) { ED->SymRef[I].Count *= Right->Val; } for (I = 0; I < ED->SecCount; ++I) { ED->SecRef[I].Count *= Right->Val; } ED_MergeAddrSize (ED, Right); } static void ED_Neg (ExprDesc* D) /* Negate an expression */ { D->Val = -D->Val; ED_NegRefs (D); } static void ED_Move (ExprDesc* From, ExprDesc* To) /* Move the data from one ExprDesc to another. Old data is freed, and From ** is prepared to that ED_Done may be called safely. */ { /* Delete old data */ ED_Done (To); /* Move the data */ *To = *From; /* Cleanup From */ ED_Init (From); } /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void StudyExprInternal (ExprNode* Expr, ExprDesc* D); /* Study an expression tree and place the contents into D */ static unsigned char GetConstAddrSize (long Val) /* Get the address size of a constant */ { if ((Val & ~0xFFL) == 0) { return ADDR_SIZE_ZP; } else if ((Val & ~0xFFFFL) == 0) { return ADDR_SIZE_ABS; } else if ((Val & ~0xFFFFFFL) == 0) { return ADDR_SIZE_FAR; } else { return ADDR_SIZE_LONG; } } static void StudyBinaryExpr (ExprNode* Expr, ExprDesc* D) /* Study a binary expression subtree. This is a helper function for StudyExpr ** used for operations that succeed when both operands are known and constant. ** It evaluates the two subtrees and checks if they are constant. If they ** aren't constant, it will set the TOO_COMPLEX flag, and merge references. ** Otherwise the first value is returned in D->Val, the second one in D->Right, ** so the actual operation can be done by the caller. */ { ExprDesc Right; /* Study the left side of the expression */ StudyExprInternal (Expr->Left, D); /* Study the right side of the expression */ ED_Init (&Right); StudyExprInternal (Expr->Right, &Right); /* Check if we can handle the operation */ if (ED_IsConst (D) && ED_IsConst (&Right)) { /* Remember the constant value from Right */ D->Right = Right.Val; } else { /* Cannot evaluate */ ED_Invalidate (D); /* Merge references and update address size */ ED_MergeRefs (D, &Right); ED_MergeAddrSize (D, &Right); } /* Cleanup Right */ ED_Done (&Right); } static void StudyLiteral (ExprNode* Expr, ExprDesc* D) /* Study a literal expression node */ { /* This one is easy */ D->Val = Expr->V.IVal; D->AddrSize = GetConstAddrSize (D->Val); } static void StudySymbol (ExprNode* Expr, ExprDesc* D) /* Study a symbol expression node */ { /* Get the symbol from the expression */ SymEntry* Sym = Expr->V.Sym; /* If the symbol is defined somewhere, it has an expression associated. ** In this case, just study the expression associated with the symbol, ** but mark the symbol so if we encounter it twice, we know that we have ** a circular reference. */ if (SymHasExpr (Sym)) { if (SymHasUserMark (Sym)) { LIError (&Sym->DefLines, "Circular reference in definition of symbol '%m%p'", GetSymName (Sym)); ED_SetError (D); } else { unsigned char AddrSize; /* Mark the symbol and study its associated expression */ SymMarkUser (Sym); StudyExprInternal (GetSymExpr (Sym), D); SymUnmarkUser (Sym); /* If requested and if the expression is valid, dump it */ if (Debug > 0 && !ED_HasError (D)) { DumpExpr (Expr, SymResolve); } /* If the symbol has an explicit address size, use it. This may ** lead to range errors later (maybe even in the linker stage), if ** the user lied about the address size, but for now we trust him. */ AddrSize = GetSymAddrSize (Sym); if (AddrSize != ADDR_SIZE_DEFAULT) { D->AddrSize = AddrSize; } } } else if (SymIsImport (Sym)) { /* The symbol is an import. Track the symbols used and update the ** address size. */ ED_SymRef* SymRef = ED_GetSymRef (D, Sym); ++SymRef->Count; ED_UpdateAddrSize (D, GetSymAddrSize (Sym)); } else { unsigned char AddrSize; SymTable* Parent; /* The symbol is undefined. Track symbol usage but set the "too ** complex" flag, since we cannot evaluate the final result. */ ED_SymRef* SymRef = ED_GetSymRef (D, Sym); ++SymRef->Count; ED_Invalidate (D); /* Since the symbol may be a forward, and we may need a statement ** about the address size, check higher lexical levels for a symbol ** with the same name and use its address size if we find such a ** symbol which is defined. */ AddrSize = GetSymAddrSize (Sym); Parent = GetSymParentScope (Sym); if (AddrSize == ADDR_SIZE_DEFAULT && Parent != 0) { SymEntry* H = SymFindAny (Parent, GetSymName (Sym)); if (H) { AddrSize = GetSymAddrSize (H); if (AddrSize != ADDR_SIZE_DEFAULT) { D->AddrSize = AddrSize; } } } else { D->AddrSize = AddrSize; } } } static void StudySection (ExprNode* Expr, ExprDesc* D) /* Study a section expression node */ { /* Get the section reference */ ED_SecRef* SecRef = ED_GetSecRef (D, Expr->V.SecNum); /* Update the data and the address size */ ++SecRef->Count; ED_UpdateAddrSize (D, GetSegAddrSize (SecRef->Ref)); } static void StudyULabel (ExprNode* Expr, ExprDesc* D) /* Study an unnamed label expression node */ { /* If we can resolve the label, study the expression associated with it, ** otherwise mark the expression as too complex to evaluate. */ if (ULabCanResolve ()) { /* We can resolve the label */ StudyExprInternal (ULabResolve (Expr->V.IVal), D); } else { ED_Invalidate (D); } } static void StudyPlus (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_PLUS binary expression node */ { ExprDesc Right; /* Study the left side of the expression */ StudyExprInternal (Expr->Left, D); /* Study the right side of the expression */ ED_Init (&Right); StudyExprInternal (Expr->Right, &Right); /* Check if we can handle the operation */ if (ED_IsValid (D) && ED_IsValid (&Right)) { /* Add both */ ED_Add (D, &Right); } else { /* Cannot evaluate */ ED_Invalidate (D); /* Merge references and update address size */ ED_MergeRefs (D, &Right); ED_MergeAddrSize (D, &Right); } /* Done */ ED_Done (&Right); } static void StudyMinus (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_MINUS binary expression node */ { ExprDesc Right; /* Study the left side of the expression */ StudyExprInternal (Expr->Left, D); /* Study the right side of the expression */ ED_Init (&Right); StudyExprInternal (Expr->Right, &Right); /* Check if we can handle the operation */ if (ED_IsValid (D) && ED_IsValid (&Right)) { /* Subtract both */ ED_Sub (D, &Right); } else { /* Cannot evaluate */ ED_Invalidate (D); /* Merge references and update address size */ ED_MergeRefs (D, &Right); ED_MergeAddrSize (D, &Right); } /* Done */ ED_Done (&Right); } static void StudyMul (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_MUL binary expression node */ { ExprDesc Right; /* Study the left side of the expression */ StudyExprInternal (Expr->Left, D); /* Study the right side of the expression */ ED_Init (&Right); StudyExprInternal (Expr->Right, &Right); /* We can handle the operation if at least one of both operands is const ** and the other one is valid. */ if (ED_IsConst (D) && ED_IsValid (&Right)) { /* Multiplicate both, result goes into Right */ ED_Mul (&Right, D); /* Move result into D */ ED_Move (&Right, D); } else if (ED_IsConst (&Right) && ED_IsValid (D)) { /* Multiplicate both */ ED_Mul (D, &Right); } else { /* Cannot handle this operation */ ED_Invalidate (D); } /* If we could not handle the op, merge references and update address size */ if (!ED_IsValid (D)) { ED_MergeRefs (D, &Right); ED_MergeAddrSize (D, &Right); } /* Done */ ED_Done (&Right); } static void StudyDiv (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_DIV binary expression node */ { /* Use helper function */ StudyBinaryExpr (Expr, D); /* If the result is valid, apply the operation */ if (ED_IsValid (D)) { if (D->Right == 0) { Error ("Division by zero"); ED_SetError (D); } else { D->Val /= D->Right; } } } static void StudyMod (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_MOD binary expression node */ { /* Use helper function */ StudyBinaryExpr (Expr, D); /* If the result is valid, apply the operation */ if (ED_IsValid (D)) { if (D->Right == 0) { Error ("Modulo operation with zero"); ED_SetError (D); } else { D->Val %= D->Right; } } } static void StudyOr (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_OR binary expression node */ { /* Use helper function */ StudyBinaryExpr (Expr, D); /* If the result is valid, apply the operation */ if (ED_IsValid (D)) { D->Val |= D->Right; } } static void StudyXor (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_XOR binary expression node */ { /* Use helper function */ StudyBinaryExpr (Expr, D); /* If the result is valid, apply the operation */ if (ED_IsValid (D)) { D->Val ^= D->Right; } } static void StudyAnd (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_AND binary expression node */ { /* Use helper function */ StudyBinaryExpr (Expr, D); /* If the result is valid, apply the operation */ if (ED_IsValid (D)) { D->Val &= D->Right; } } static void StudyShl (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_SHL binary expression node */ { /* Use helper function */ StudyBinaryExpr (Expr, D); /* If the result is valid, apply the operation */ if (ED_IsValid (D)) { D->Val = shl_l (D->Val, D->Right); } } static void StudyShr (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_SHR binary expression node */ { /* Use helper function */ StudyBinaryExpr (Expr, D); /* If the result is valid, apply the operation */ if (ED_IsValid (D)) { D->Val = shr_l (D->Val, D->Right); } } static void StudyEQ (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_EQ binary expression node */ { /* Use helper function */ StudyBinaryExpr (Expr, D); /* If the result is valid, apply the operation */ if (ED_IsValid (D)) { D->Val = (D->Val == D->Right); } /* In any case, the result is 0 or 1 */ D->AddrSize = ADDR_SIZE_ZP; } static void StudyNE (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_NE binary expression node */ { /* Use helper function */ StudyBinaryExpr (Expr, D); /* If the result is valid, apply the operation */ if (ED_IsValid (D)) { D->Val = (D->Val != D->Right); } /* In any case, the result is 0 or 1 */ D->AddrSize = ADDR_SIZE_ZP; } static void StudyLT (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_LT binary expression node */ { /* Use helper function */ StudyBinaryExpr (Expr, D); /* If the result is valid, apply the operation */ if (ED_IsValid (D)) { D->Val = (D->Val < D->Right); } /* In any case, the result is 0 or 1 */ D->AddrSize = ADDR_SIZE_ZP; } static void StudyGT (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_GT binary expression node */ { /* Use helper function */ StudyBinaryExpr (Expr, D); /* If the result is valid, apply the operation */ if (ED_IsValid (D)) { D->Val = (D->Val > D->Right); } /* In any case, the result is 0 or 1 */ D->AddrSize = ADDR_SIZE_ZP; } static void StudyLE (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_LE binary expression node */ { /* Use helper function */ StudyBinaryExpr (Expr, D); /* If the result is valid, apply the operation */ if (ED_IsValid (D)) { D->Val = (D->Val <= D->Right); } /* In any case, the result is 0 or 1 */ D->AddrSize = ADDR_SIZE_ZP; } static void StudyGE (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_GE binary expression node */ { /* Use helper function */ StudyBinaryExpr (Expr, D); /* If the result is valid, apply the operation */ if (ED_IsValid (D)) { D->Val = (D->Val >= D->Right); } /* In any case, the result is 0 or 1 */ D->AddrSize = ADDR_SIZE_ZP; } static void StudyBoolAnd (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_BOOLAND binary expression node */ { StudyExprInternal (Expr->Left, D); if (ED_IsConst (D)) { if (D->Val != 0) { /* Shortcut op */ ED_Done (D); ED_Init (D); StudyExprInternal (Expr->Right, D); if (ED_IsConst (D)) { D->Val = (D->Val != 0); } else { ED_Invalidate (D); } } } else { ED_Invalidate (D); } /* In any case, the result is 0 or 1 */ D->AddrSize = ADDR_SIZE_ZP; } static void StudyBoolOr (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_BOOLOR binary expression node */ { StudyExprInternal (Expr->Left, D); if (ED_IsConst (D)) { if (D->Val == 0) { /* Shortcut op */ ED_Done (D); ED_Init (D); StudyExprInternal (Expr->Right, D); if (ED_IsConst (D)) { D->Val = (D->Val != 0); } else { ED_Invalidate (D); } } else { D->Val = 1; } } else { ED_Invalidate (D); } /* In any case, the result is 0 or 1 */ D->AddrSize = ADDR_SIZE_ZP; } static void StudyBoolXor (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_BOOLXOR binary expression node */ { /* Use helper function */ StudyBinaryExpr (Expr, D); /* If the result is valid, apply the operation */ if (ED_IsValid (D)) { D->Val = (D->Val != 0) ^ (D->Right != 0); } /* In any case, the result is 0 or 1 */ D->AddrSize = ADDR_SIZE_ZP; } static void StudyMax (ExprNode* Expr, ExprDesc* D) /* Study an MAX binary expression node */ { /* Use helper function */ StudyBinaryExpr (Expr, D); /* If the result is valid, apply the operation */ if (ED_IsValid (D)) { D->Val = (D->Val > D->Right)? D->Val : D->Right; } } static void StudyMin (ExprNode* Expr, ExprDesc* D) /* Study an MIN binary expression node */ { /* Use helper function */ StudyBinaryExpr (Expr, D); /* If the result is valid, apply the operation */ if (ED_IsValid (D)) { D->Val = (D->Val < D->Right)? D->Val : D->Right; } } static void StudyUnaryMinus (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_UNARY_MINUS expression node */ { /* Study the expression */ StudyExprInternal (Expr->Left, D); /* If it is valid, negate it */ if (ED_IsValid (D)) { ED_Neg (D); } } static void StudyNot (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_NOT expression node */ { /* Study the expression */ StudyExprInternal (Expr->Left, D); /* We can handle only const expressions */ if (ED_IsConst (D)) { D->Val = ~D->Val; } else { ED_Invalidate (D); } } static void StudySwap (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_SWAP expression node */ { /* Study the expression */ StudyExprInternal (Expr->Left, D); /* We can handle only const expressions */ if (ED_IsConst (D)) { D->Val = (D->Val & ~0xFFFFUL) | ((D->Val >> 8) & 0xFF) | ((D->Val << 8) & 0xFF00); } else { ED_Invalidate (D); } } static void StudyBoolNot (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_BOOLNOT expression node */ { /* Study the expression */ StudyExprInternal (Expr->Left, D); /* We can handle only const expressions */ if (ED_IsConst (D)) { D->Val = (D->Val == 0); } else { ED_Invalidate (D); } /* In any case, the result is 0 or 1 */ D->AddrSize = ADDR_SIZE_ZP; } static void StudyBank (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_BANK expression node */ { /* Study the expression extracting section references */ StudyExprInternal (Expr->Left, D); /* The expression is always linker evaluated, so invalidate it */ ED_Invalidate (D); } static void StudyByte0 (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_BYTE0 expression node */ { /* Study the expression */ StudyExprInternal (Expr->Left, D); /* We can handle only const expressions */ if (ED_IsConst (D)) { D->Val = (D->Val & 0xFF); } else { ED_Invalidate (D); } /* In any case, the result is a zero page expression */ D->AddrSize = ADDR_SIZE_ZP; } static void StudyByte1 (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_BYTE1 expression node */ { /* Study the expression */ StudyExprInternal (Expr->Left, D); /* We can handle only const expressions */ if (ED_IsConst (D)) { D->Val = (D->Val >> 8) & 0xFF; } else { ED_Invalidate (D); } /* In any case, the result is a zero page expression */ D->AddrSize = ADDR_SIZE_ZP; } static void StudyByte2 (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_BYTE2 expression node */ { /* Study the expression */ StudyExprInternal (Expr->Left, D); /* We can handle only const expressions */ if (ED_IsConst (D)) { D->Val = (D->Val >> 16) & 0xFF; } else { ED_Invalidate (D); } /* In any case, the result is a zero page expression */ D->AddrSize = ADDR_SIZE_ZP; } static void StudyByte3 (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_BYTE3 expression node */ { /* Study the expression */ StudyExprInternal (Expr->Left, D); /* We can handle only const expressions */ if (ED_IsConst (D)) { D->Val = (D->Val >> 24) & 0xFF; } else { ED_Invalidate (D); } /* In any case, the result is a zero page expression */ D->AddrSize = ADDR_SIZE_ZP; } static void StudyWord0 (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_WORD0 expression node */ { /* Study the expression */ StudyExprInternal (Expr->Left, D); /* We can handle only const expressions */ if (ED_IsConst (D)) { D->Val &= 0xFFFFL; } else { ED_Invalidate (D); } /* In any case, the result is an absolute expression */ D->AddrSize = ADDR_SIZE_ABS; } static void StudyWord1 (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_WORD1 expression node */ { /* Study the expression */ StudyExprInternal (Expr->Left, D); /* We can handle only const expressions */ if (ED_IsConst (D)) { D->Val = (D->Val >> 16) & 0xFFFFL; } else { ED_Invalidate (D); } /* In any case, the result is an absolute expression */ D->AddrSize = ADDR_SIZE_ABS; } static void StudyFarAddr (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_FARADDR expression node */ { /* Study the expression */ StudyExprInternal (Expr->Left, D); /* We can handle only const expressions */ if (ED_IsConst (D)) { D->Val &= 0xFFFFFFL; } else { ED_Invalidate (D); } /* In any case, the result is a far address */ D->AddrSize = ADDR_SIZE_FAR; } static void StudyDWord (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_DWORD expression node */ { /* Study the expression */ StudyExprInternal (Expr->Left, D); /* We can handle only const expressions */ if (ED_IsConst (D)) { D->Val &= 0xFFFFFFFFL; } else { ED_Invalidate (D); } /* In any case, the result is a long expression */ D->AddrSize = ADDR_SIZE_LONG; } static void StudyNearAddr (ExprNode* Expr, ExprDesc* D) /* Study an EXPR_NEARADDR expression node */ { /* Study the expression */ StudyExprInternal (Expr->Left, D); /* We can handle only const expressions */ if (!ED_IsConst (D)) { ED_Invalidate (D); } /* Promote to absolute if smaller. */ if (D->AddrSize < ADDR_SIZE_ABS) { D->AddrSize = ADDR_SIZE_ABS; } } static void StudyExprInternal (ExprNode* Expr, ExprDesc* D) /* Study an expression tree and place the contents into D */ { /* Study this expression node */ switch (Expr->Op) { case EXPR_LITERAL: StudyLiteral (Expr, D); break; case EXPR_SYMBOL: StudySymbol (Expr, D); break; case EXPR_SECTION: StudySection (Expr, D); break; case EXPR_ULABEL: StudyULabel (Expr, D); break; case EXPR_PLUS: StudyPlus (Expr, D); break; case EXPR_MINUS: StudyMinus (Expr, D); break; case EXPR_MUL: StudyMul (Expr, D); break; case EXPR_DIV: StudyDiv (Expr, D); break; case EXPR_MOD: StudyMod (Expr, D); break; case EXPR_OR: StudyOr (Expr, D); break; case EXPR_XOR: StudyXor (Expr, D); break; case EXPR_AND: StudyAnd (Expr, D); break; case EXPR_SHL: StudyShl (Expr, D); break; case EXPR_SHR: StudyShr (Expr, D); break; case EXPR_EQ: StudyEQ (Expr, D); break; case EXPR_NE: StudyNE (Expr, D); break; case EXPR_LT: StudyLT (Expr, D); break; case EXPR_GT: StudyGT (Expr, D); break; case EXPR_LE: StudyLE (Expr, D); break; case EXPR_GE: StudyGE (Expr, D); break; case EXPR_BOOLAND: StudyBoolAnd (Expr, D); break; case EXPR_BOOLOR: StudyBoolOr (Expr, D); break; case EXPR_BOOLXOR: StudyBoolXor (Expr, D); break; case EXPR_MAX: StudyMax (Expr, D); break; case EXPR_MIN: StudyMin (Expr, D); break; case EXPR_UNARY_MINUS: StudyUnaryMinus (Expr, D); break; case EXPR_NOT: StudyNot (Expr, D); break; case EXPR_SWAP: StudySwap (Expr, D); break; case EXPR_BOOLNOT: StudyBoolNot (Expr, D); break; case EXPR_BANK: StudyBank (Expr, D); break; case EXPR_BYTE0: StudyByte0 (Expr, D); break; case EXPR_BYTE1: StudyByte1 (Expr, D); break; case EXPR_BYTE2: StudyByte2 (Expr, D); break; case EXPR_BYTE3: StudyByte3 (Expr, D); break; case EXPR_WORD0: StudyWord0 (Expr, D); break; case EXPR_WORD1: StudyWord1 (Expr, D); break; case EXPR_FARADDR: StudyFarAddr (Expr, D); break; case EXPR_DWORD: StudyDWord (Expr, D); break; case EXPR_NEARADDR: StudyNearAddr (Expr, D); break; default: Internal ("Unknown Op type: %u", Expr->Op); break; } } void StudyExpr (ExprNode* Expr, ExprDesc* D) /* Study an expression tree and place the contents into D */ { unsigned I, J; /* Call the internal function */ StudyExprInternal (Expr, D); /* Remove symbol references with count zero */ I = J = 0; while (I < D->SymCount) { if (D->SymRef[I].Count == 0) { /* Delete the entry */ --D->SymCount; memmove (D->SymRef + I, D->SymRef + I + 1, (D->SymCount - I) * sizeof (D->SymRef[0])); } else { /* Next entry */ ++I; } } /* Remove section references with count zero */ I = 0; while (I < D->SecCount) { if (D->SecRef[I].Count == 0) { /* Delete the entry */ --D->SecCount; memmove (D->SecRef + I, D->SecRef + I + 1, (D->SecCount - I) * sizeof (D->SecRef[0])); } else { /* Next entry */ ++I; } } /* If we don't have an address size, assign one if the expression is a ** constant. */ if (D->AddrSize == ADDR_SIZE_DEFAULT && ED_IsConst (D)) { D->AddrSize = GetConstAddrSize (D->Val); } /* If the expression is valid, throw away the address size and recalculate ** it using the data we have. This is more exact than the on-the-fly ** calculation done when evaluating the tree, because symbols may have ** been removed from the expression, and the final numeric value is now ** known. */ if (ED_IsValid (D)) { unsigned char AddrSize; /* If there are symbols or sections, use the largest one. If the ** expression resolves to a const, use the address size of the value. */ if (D->SymCount > 0 || D->SecCount > 0) { D->AddrSize = ADDR_SIZE_DEFAULT; for (I = 0; I < D->SymCount; ++I) { const SymEntry* Sym = D->SymRef[I].Ref; AddrSize = GetSymAddrSize (Sym); if (AddrSize > D->AddrSize) { D->AddrSize = AddrSize; } } for (I = 0; I < D->SecCount; ++I) { unsigned SegNum = D->SecRef[0].Ref; AddrSize = GetSegAddrSize (SegNum); if (AddrSize > D->AddrSize) { D->AddrSize = AddrSize; } } } else { AddrSize = GetConstAddrSize (D->Val); if (AddrSize > D->AddrSize) { D->AddrSize = AddrSize; } } } #if 0 /* Debug code */ printf ("StudyExpr: "); DumpExpr (Expr, SymResolve); printf ("Value: %08lX\n", D->Val); if (!ED_IsValid (D)) { printf ("Invalid: %s\n", AddrSizeToStr (D->AddrSize)); } else { printf ("Valid: %s\n", AddrSizeToStr (D->AddrSize)); } printf ("%u symbols:\n", D->SymCount); printf ("%u sections:\n", D->SecCount); #endif } ������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/studyexpr.h����������������������������������������������������������������������0000664�0000000�0000000�00000012327�13473601511�0015757�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* studyexpr.h */ /* */ /* Study an expression tree */ /* */ /* */ /* */ /* (C) 2003-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef STUDYEXPR_H #define STUDYEXPR_H /* common */ #include "exprdefs.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Flags */ #define ED_OK 0x00 /* Nothing special */ #define ED_TOO_COMPLEX 0x01 /* Expression is too complex */ #define ED_ERROR 0x02 /* Error evaluating the expression */ /* Symbol reference */ typedef struct ED_SymRef ED_SymRef; struct ED_SymRef { long Count; /* Number of references */ struct SymEntry* Ref; /* Actual reference */ }; /* Section reference */ typedef struct ED_SecRef ED_SecRef; struct ED_SecRef { long Count; /* Number of references */ unsigned Ref; /* Actual reference */ }; /* Structure for parsing expression trees */ typedef struct ExprDesc ExprDesc; struct ExprDesc { unsigned short Flags; /* See ED_xxx */ unsigned char AddrSize; /* Address size of the expression */ long Val; /* The offset value */ long Right; /* Right value for StudyBinaryExpr */ /* Symbol reference management */ unsigned SymCount; /* Number of symbols referenced */ unsigned SymLimit; /* Memory allocated */ ED_SymRef* SymRef; /* Symbol references */ /* Section reference management */ unsigned SecCount; /* Number of sections referenced */ unsigned SecLimit; /* Memory allocated */ ED_SecRef* SecRef; /* Section references */ }; /*****************************************************************************/ /* struct ExprDesc */ /*****************************************************************************/ ExprDesc* ED_Init (ExprDesc* ED); /* Initialize an ExprDesc structure for use with StudyExpr */ void ED_Done (ExprDesc* ED); /* Delete allocated memory for an ExprDesc. */ int ED_IsConst (const ExprDesc* ED); /* Return true if the expression is constant */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ void StudyExpr (ExprNode* Expr, ExprDesc* D); /* Study an expression tree and place the contents into D */ /* End of studyexpr.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/symbol.c�������������������������������������������������������������������������0000664�0000000�0000000�00000021121�13473601511�0015200�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* symbol.c */ /* */ /* Parse a symbol name and search for it */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* common */ #include "strbuf.h" /* ca65 */ #include "error.h" #include "nexttok.h" #include "scanner.h" #include "symbol.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ SymTable* ParseScopedIdent (StrBuf* Name, StrBuf* FullName) /* Parse a (possibly scoped) identifer. The scope of the name must exist and ** is returned as function result, while the last part (the identifier) which ** may be either a symbol or a scope depending on the context is returned in ** Name. FullName is a string buffer that is used to store the full name of ** the identifier including the scope. It is used internally and may be used ** by the caller for error messages or similar. */ { SymTable* Scope; /* Clear both passed string buffers */ SB_Clear (Name); SB_Clear (FullName); /* Get the starting table */ if (CurTok.Tok == TOK_NAMESPACE) { /* Start from the root scope */ Scope = RootScope; } else if (CurTok.Tok == TOK_IDENT) { /* Remember the name and skip it */ SB_Copy (Name, &CurTok.SVal); NextTok (); /* If no namespace symbol follows, we're already done */ if (CurTok.Tok != TOK_NAMESPACE) { SB_Terminate (FullName); return CurrentScope; } /* Pass the scope back to the caller */ SB_Append (FullName, Name); /* The scope must exist, so search for it starting with the current ** scope. */ Scope = SymFindAnyScope (CurrentScope, Name); if (Scope == 0) { /* Scope not found */ SB_Terminate (FullName); Error ("No such scope: '%m%p'", FullName); return 0; } } else { /* Invalid token */ Error ("Identifier expected"); return 0; } /* Skip the namespace token that follows */ SB_AppendStr (FullName, "::"); NextTok (); /* Resolve scopes. */ while (1) { /* Next token must be an identifier. */ if (CurTok.Tok != TOK_IDENT) { Error ("Identifier expected"); return 0; } /* Remember and skip the identifier */ SB_Copy (Name, &CurTok.SVal); NextTok (); /* If a namespace token follows, we search for another scope, otherwise ** the name is a symbol and we're done. */ if (CurTok.Tok != TOK_NAMESPACE) { /* Symbol */ return Scope; } /* Pass the scope back to the caller */ SB_Append (FullName, Name); /* Search for the child scope */ Scope = SymFindScope (Scope, Name, SYM_FIND_EXISTING); if (Scope == 0) { /* Scope not found */ Error ("No such scope: '%m%p'", FullName); return 0; } /* Skip the namespace token that follows */ SB_AppendStr (FullName, "::"); NextTok (); } } SymEntry* ParseScopedSymName (SymFindAction Action) /* Parse a (possibly scoped) symbol name, search for it in the symbol table ** and return the symbol table entry. */ { StrBuf ScopeName = STATIC_STRBUF_INITIALIZER; StrBuf Ident = STATIC_STRBUF_INITIALIZER; int NoScope; SymEntry* Sym; /* Parse the scoped symbol name */ SymTable* Scope = ParseScopedIdent (&Ident, &ScopeName); /* If ScopeName is empty, no scope was specified */ NoScope = SB_IsEmpty (&ScopeName); /* We don't need ScopeName any longer */ SB_Done (&ScopeName); /* Check if the scope is valid. Errors have already been diagnosed by ** the routine, so just exit. */ if (Scope) { /* Search for the symbol and return it. If no scope was specified, ** search also in the upper levels. */ if (NoScope && (Action & SYM_ALLOC_NEW) == 0) { Sym = SymFindAny (Scope, &Ident); } else { Sym = SymFind (Scope, &Ident, Action); } } else { /* No scope ==> no symbol. To avoid errors in the calling routine that ** may not expect NULL to be returned if Action contains SYM_ALLOC_NEW, ** create a new symbol. */ if (Action & SYM_ALLOC_NEW) { Sym = NewSymEntry (&Ident, SF_NONE); } else { Sym = 0; } } /* Deallocate memory for ident */ SB_Done (&Ident); /* Return the symbol found */ return Sym; } SymTable* ParseScopedSymTable (void) /* Parse a (possibly scoped) symbol table (scope) name, search for it in the ** symbol space and return the symbol table struct. */ { StrBuf ScopeName = STATIC_STRBUF_INITIALIZER; StrBuf Name = STATIC_STRBUF_INITIALIZER; int NoScope; /* Parse the scoped symbol name */ SymTable* Scope = ParseScopedIdent (&Name, &ScopeName); /* If ScopeName is empty, no scope was specified */ NoScope = SB_IsEmpty (&ScopeName); /* We don't need FullName any longer */ SB_Done (&ScopeName); /* If we got no error, search for the child scope withint the enclosing one. ** Beware: If no explicit parent scope was specified, search in all upper ** levels. */ if (Scope) { /* Search for the last scope */ if (NoScope) { Scope = SymFindAnyScope (Scope, &Name); } else { Scope = SymFindScope (Scope, &Name, SYM_FIND_EXISTING); } } /* Free memory for name */ SB_Done (&Name); /* Return the scope found */ return Scope; } SymEntry* ParseAnySymName (SymFindAction Action) /* Parse a cheap local symbol or a a (possibly scoped) symbol name, search ** for it in the symbol table and return the symbol table entry. */ { SymEntry* Sym; /* Distinguish cheap locals and other symbols */ if (CurTok.Tok == TOK_LOCAL_IDENT) { Sym = SymFindLocal (SymLast, &CurTok.SVal, Action); NextTok (); } else { Sym = ParseScopedSymName (Action); } /* Return the symbol found */ return Sym; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/symbol.h�������������������������������������������������������������������������0000664�0000000�0000000�00000010226�13473601511�0015211�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* symbol.h */ /* */ /* Parse a symbol name and search for it */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef SYMBOL_H #define SYMBOL_H /* cc65 */ #include "symtab.h" /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ struct StrBuf; /*****************************************************************************/ /* Code */ /*****************************************************************************/ struct SymTable* ParseScopedIdent (struct StrBuf* Name, struct StrBuf* FullName); /* Parse a (possibly scoped) identifer. The scope of the name must exist and ** is returned as function result, while the last part (the identifier) which ** may be either a symbol or a scope depending on the context is returned in ** Name. FullName is a string buffer that is used to store the full name of ** the identifier including the scope. It is used internally and may be used ** by the caller for error messages or similar. */ struct SymEntry* ParseScopedSymName (SymFindAction Action); /* Parse a (possibly scoped) symbol name, search for it in the symbol table ** and return the symbol table entry. */ struct SymTable* ParseScopedSymTable (void); /* Parse a (possibly scoped) symbol table (scope) name, search for it in the ** symbol space and return the symbol table struct. */ struct SymEntry* ParseAnySymName (SymFindAction Action); /* Parse a cheap local symbol or a a (possibly scoped) symbol name, search ** for it in the symbol table and return the symbol table entry. */ /* End of symbol.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/symentry.c�����������������������������������������������������������������������0000664�0000000�0000000�00000056705�13473601511�0015605�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* symentry.c */ /* */ /* Symbol table entry for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* common */ #include "addrsize.h" #include "symdefs.h" #include "xmalloc.h" /* ca65 */ #include "error.h" #include "expr.h" #include "global.h" #include "scanner.h" #include "segment.h" #include "spool.h" #include "studyexpr.h" /* ### */ #include "symentry.h" #include "symtab.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* List of all symbol table entries */ SymEntry* SymList = 0; /* Pointer to last defined symbol */ SymEntry* SymLast = 0; /*****************************************************************************/ /* Code */ /*****************************************************************************/ SymEntry* NewSymEntry (const StrBuf* Name, unsigned Flags) /* Allocate a symbol table entry, initialize and return it */ { unsigned I; /* Allocate memory */ SymEntry* S = xmalloc (sizeof (SymEntry)); /* Initialize the entry */ S->Left = 0; S->Right = 0; S->Locals = 0; S->Sym.Tab = 0; S->DefLines = EmptyCollection; S->RefLines = EmptyCollection; for (I = 0; I < sizeof (S->GuessedUse) / sizeof (S->GuessedUse[0]); ++I) { S->GuessedUse[I] = 0; } S->HLLSym = 0; S->Flags = Flags; S->DebugSymId = ~0U; S->ImportId = ~0U; S->ExportId = ~0U; S->Expr = 0; S->ExprRefs = AUTO_COLLECTION_INITIALIZER; S->ExportSize = ADDR_SIZE_DEFAULT; S->AddrSize = ADDR_SIZE_DEFAULT; memset (S->ConDesPrio, 0, sizeof (S->ConDesPrio)); S->Name = GetStrBufId (Name); /* Insert it into the list of all entries */ S->List = SymList; SymList = S; /* Return the initialized entry */ return S; } int SymSearchTree (SymEntry* T, const StrBuf* Name, SymEntry** E) /* Search in the given tree for a name. If we find the symbol, the function ** will return 0 and put the entry pointer into E. If we did not find the ** symbol, and the tree is empty, E is set to NULL. If the tree is not empty, ** E will be set to the last entry, and the result of the function is <0 if ** the entry should be inserted on the left side, and >0 if it should get ** inserted on the right side. */ { /* Is there a tree? */ if (T == 0) { *E = 0; return 1; } /* We have a table, search it */ while (1) { /* Get the symbol name */ const StrBuf* SymName = GetStrBuf (T->Name); /* Choose next entry */ int Cmp = SB_Compare (Name, SymName); if (Cmp < 0 && T->Left) { T = T->Left; } else if (Cmp > 0 && T->Right) { T = T->Right; } else { /* Found or end of search, return the result */ *E = T; return Cmp; } } } void SymTransferExprRefs (SymEntry* From, SymEntry* To) /* Transfer all expression references from one symbol to another. */ { unsigned I; for (I = 0; I < CollCount (&From->ExprRefs); ++I) { /* Get the expression node */ ExprNode* E = CollAtUnchecked (&From->ExprRefs, I); /* Safety */ CHECK (E->Op == EXPR_SYMBOL && E->V.Sym == From); /* Replace the symbol reference */ E->V.Sym = To; /* Add the expression reference */ SymAddExprRef (To, E); } /* Remove all symbol references from the old symbol */ CollDeleteAll (&From->ExprRefs); } static void SymReplaceExprRefs (SymEntry* S) /* Replace the references to this symbol by a copy of the symbol expression */ { unsigned I; long Val; /* Check if the expression is const and get its value */ int IsConst = IsConstExpr (S->Expr, &Val); CHECK (IsConst); /* Loop over all references */ for (I = 0; I < CollCount (&S->ExprRefs); ++I) { /* Get the expression node */ ExprNode* E = CollAtUnchecked (&S->ExprRefs, I); /* Safety */ CHECK (E->Op == EXPR_SYMBOL && E->V.Sym == S); /* We cannot touch the root node, since there are pointers to it. ** Replace it by a literal node. */ E->Op = EXPR_LITERAL; E->V.IVal = Val; } /* Remove all symbol references from the symbol */ CollDeleteAll (&S->ExprRefs); } void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags) /* Define a new symbol */ { if (S->Flags & SF_IMPORT) { /* Defined symbol is marked as imported external symbol */ Error ("Symbol '%m%p' is already an import", GetSymName (S)); return; } if ((Flags & SF_VAR) != 0 && (S->Flags & (SF_EXPORT | SF_GLOBAL))) { /* Variable symbols cannot be exports or globals */ Error ("Var symbol '%m%p' cannot be an export or global symbol", GetSymName (S)); return; } if (S->Flags & SF_DEFINED) { /* Multiple definition. In case of a variable, this is legal. */ if ((S->Flags & SF_VAR) == 0) { Error ("Symbol '%m%p' is already defined", GetSymName (S)); S->Flags |= SF_MULTDEF; return; } else { /* Redefinition must also be a variable symbol */ if ((Flags & SF_VAR) == 0) { Error ("Symbol '%m%p' is already different kind", GetSymName (S)); return; } /* Delete the current symbol expression, since it will get ** replaced */ FreeExpr (S->Expr); S->Expr = 0; } } /* Map a default address size to a real value */ if (AddrSize == ADDR_SIZE_DEFAULT) { /* ### Must go! Delay address size calculation until end of assembly! */ ExprDesc ED; ED_Init (&ED); StudyExpr (Expr, &ED); AddrSize = ED.AddrSize; ED_Done (&ED); } /* Set the symbol value */ S->Expr = Expr; /* In case of a variable symbol, walk over all expressions containing ** this symbol and replace the (sub-)expression by the literal value of ** the tree. Be sure to replace the expression node in place, since there ** may be pointers to it. */ if (Flags & SF_VAR) { SymReplaceExprRefs (S); } /* If the symbol is marked as global, export it. Address size is checked ** below. */ if (S->Flags & SF_GLOBAL) { S->Flags = (S->Flags & ~SF_GLOBAL) | SF_EXPORT; ReleaseFullLineInfo (&S->DefLines); } /* Mark the symbol as defined and use the given address size */ S->Flags |= (SF_DEFINED | Flags); S->AddrSize = AddrSize; /* Remember the line info of the symbol definition */ GetFullLineInfo (&S->DefLines); /* If the symbol is exported, check the address sizes */ if (S->Flags & SF_EXPORT) { if (S->ExportSize == ADDR_SIZE_DEFAULT) { /* Use the real size of the symbol */ S->ExportSize = S->AddrSize; } else if (S->AddrSize > S->ExportSize) { /* We're exporting a symbol smaller than it actually is */ Warning (1, "Symbol '%m%p' is %s but exported %s", GetSymName (S), AddrSizeToStr (S->AddrSize), AddrSizeToStr (S->ExportSize)); } } /* If this is not a local symbol, remember it as the last global one */ if ((S->Flags & SF_LOCAL) == 0) { SymLast = S; } } void SymRef (SymEntry* S) /* Mark the given symbol as referenced */ { /* Mark the symbol as referenced */ S->Flags |= SF_REFERENCED; /* Remember the current location */ CollAppend (&S->RefLines, GetAsmLineInfo ()); } void SymImport (SymEntry* S, unsigned char AddrSize, unsigned Flags) /* Mark the given symbol as an imported symbol */ { if (S->Flags & SF_DEFINED) { Error ("Symbol '%m%p' is already defined", GetSymName (S)); S->Flags |= SF_MULTDEF; return; } if (S->Flags & SF_EXPORT) { /* The symbol is already marked as exported symbol */ Error ("Cannot import exported symbol '%m%p'", GetSymName (S)); return; } /* If no address size is given, use the address size of the enclosing ** segment. */ if (AddrSize == ADDR_SIZE_DEFAULT) { AddrSize = GetCurrentSegAddrSize (); } /* If the symbol is marked as import or global, check the address size, ** then do silently remove the global flag. */ if (S->Flags & SF_IMPORT) { if ((Flags & SF_FORCED) != (S->Flags & SF_FORCED)) { Error ("Redeclaration mismatch for symbol '%m%p'", GetSymName (S)); } if (AddrSize != S->AddrSize) { Error ("Address size mismatch for symbol '%m%p'", GetSymName (S)); } } if (S->Flags & SF_GLOBAL) { S->Flags &= ~SF_GLOBAL; if (AddrSize != S->AddrSize) { Error ("Address size mismatch for symbol '%m%p'", GetSymName (S)); } } /* Set the symbol data */ S->Flags |= (SF_IMPORT | Flags); S->AddrSize = AddrSize; /* Mark the position of the import as the position of the definition. ** Please note: In case of multiple .global or .import statements, the line ** infos add up. */ GetFullLineInfo (&S->DefLines); } void SymExport (SymEntry* S, unsigned char AddrSize, unsigned Flags) /* Mark the given symbol as an exported symbol */ { /* Check if it's ok to export the symbol */ if (S->Flags & SF_IMPORT) { /* The symbol is already marked as imported external symbol */ Error ("Symbol '%m%p' is already an import", GetSymName (S)); return; } if (S->Flags & SF_VAR) { /* Variable symbols cannot be exported */ Error ("Var symbol '%m%p' cannot be exported", GetSymName (S)); return; } /* If the symbol was marked as global before, remove the global flag and ** proceed, but check the address size. */ if (S->Flags & SF_GLOBAL) { if (AddrSize != S->ExportSize) { Error ("Address size mismatch for symbol '%m%p'", GetSymName (S)); } S->Flags &= ~SF_GLOBAL; /* .GLOBAL remembers line infos in case an .IMPORT follows. We have ** to remove these here. */ ReleaseFullLineInfo (&S->DefLines); } /* If the symbol was already marked as an export, but wasn't defined ** before, the address sizes in both definitions must match. */ if ((S->Flags & (SF_EXPORT|SF_DEFINED)) == SF_EXPORT) { if (S->ExportSize != AddrSize) { Error ("Address size mismatch for symbol '%m%p'", GetSymName (S)); } } S->ExportSize = AddrSize; /* If the symbol is already defined, check symbol size against the ** exported size. */ if (S->Flags & SF_DEFINED) { if (S->ExportSize == ADDR_SIZE_DEFAULT) { /* No export size given, use the real size of the symbol */ S->ExportSize = S->AddrSize; } else if (S->AddrSize > S->ExportSize) { /* We're exporting a symbol smaller than it actually is */ Warning (1, "Symbol '%m%p' is %s but exported %s", GetSymName (S), AddrSizeToStr (S->AddrSize), AddrSizeToStr (S->ExportSize)); } } /* Set the symbol data */ S->Flags |= (SF_EXPORT | SF_REFERENCED | Flags); /* Remember line info for this reference */ CollAppend (&S->RefLines, GetAsmLineInfo ()); } void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags) /* Mark the given symbol as a global symbol, that is, as a symbol that is ** either imported or exported. */ { if (S->Flags & SF_VAR) { /* Variable symbols cannot be exported or imported */ Error ("Var symbol '%m%p' cannot be made global", GetSymName (S)); return; } /* If the symbol is already marked as import, the address size must match. ** Apart from that, ignore the global declaration. */ if (S->Flags & SF_IMPORT) { if (AddrSize == ADDR_SIZE_DEFAULT) { /* Use the size of the current segment */ AddrSize = GetCurrentSegAddrSize (); } if (AddrSize != S->AddrSize) { Error ("Address size mismatch for symbol '%m%p'", GetSymName (S)); } return; } /* If the symbol is already an export: If it is not defined, the address ** sizes must match. */ if (S->Flags & SF_EXPORT) { if ((S->Flags & SF_DEFINED) == 0) { /* Symbol is undefined */ if (AddrSize != S->ExportSize) { Error ("Address size mismatch for symbol '%m%p'", GetSymName (S)); } } else if (AddrSize != ADDR_SIZE_DEFAULT) { /* Symbol is defined and address size given */ if (AddrSize != S->ExportSize) { Error ("Address size mismatch for symbol '%m%p'", GetSymName (S)); } } return; } /* If the symbol is already marked as global, the address size must match. ** Use the ExportSize here, since it contains the actual address size ** passed to this function. */ if (S->Flags & SF_GLOBAL) { if (AddrSize != S->ExportSize) { Error ("Address size mismatch for symbol '%m%p'", GetSymName (S)); } return; } /* If we come here, the symbol was neither declared as export, import or ** global before. Check if it is already defined, in which case it will ** become an export. If it is not defined, mark it as global and remember ** the given address sizes. */ if (S->Flags & SF_DEFINED) { /* The symbol is defined, export it */ S->ExportSize = AddrSize; if (S->ExportSize == ADDR_SIZE_DEFAULT) { /* No export size given, use the real size of the symbol */ S->ExportSize = S->AddrSize; } else if (S->AddrSize > S->ExportSize) { /* We're exporting a symbol smaller than it actually is */ Warning (1, "Symbol '%m%p' is %s but exported %s", GetSymName (S), AddrSizeToStr (S->AddrSize), AddrSizeToStr (S->ExportSize)); } S->Flags |= (SF_EXPORT | Flags); } else { /* Since we don't know if the symbol will get exported or imported, ** remember two different address sizes: One for an import in AddrSize, ** and the other one for an export in ExportSize. */ S->AddrSize = AddrSize; if (S->AddrSize == ADDR_SIZE_DEFAULT) { /* Use the size of the current segment */ S->AddrSize = GetCurrentSegAddrSize (); } S->ExportSize = AddrSize; S->Flags |= (SF_GLOBAL | Flags); /* Remember the current location as location of definition in case ** an .IMPORT follows later. */ GetFullLineInfo (&S->DefLines); } } void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Prio) /* Mark the given symbol as a module constructor/destructor. This will also ** mark the symbol as an export. Initializers may never be zero page symbols. */ { /* Check the parameters */ #if (CD_TYPE_MIN != 0) CHECK (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX); #else CHECK (Type <= CD_TYPE_MAX); #endif CHECK (Prio >= CD_PRIO_MIN && Prio <= CD_PRIO_MAX); /* Check for errors */ if (S->Flags & SF_IMPORT) { /* The symbol is already marked as imported external symbol */ Error ("Symbol '%m%p' is already an import", GetSymName (S)); return; } if (S->Flags & SF_VAR) { /* Variable symbols cannot be exported or imported */ Error ("Var symbol '%m%p' cannot be exported", GetSymName (S)); return; } /* If the symbol was already marked as an export or global, check if ** this was done specifiying the same address size. In case of a global ** declaration, silently remove the global flag. */ if (S->Flags & (SF_EXPORT | SF_GLOBAL)) { if (S->ExportSize != AddrSize) { Error ("Address size mismatch for symbol '%m%p'", GetSymName (S)); } S->Flags &= ~SF_GLOBAL; } S->ExportSize = AddrSize; /* If the symbol is already defined, check symbol size against the ** exported size. */ if (S->Flags & SF_DEFINED) { if (S->ExportSize == ADDR_SIZE_DEFAULT) { /* Use the real size of the symbol */ S->ExportSize = S->AddrSize; } else if (S->AddrSize != S->ExportSize) { Error ("Address size mismatch for symbol '%m%p'", GetSymName (S)); } } /* 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) { Error ("Redeclaration mismatch for symbol '%m%p'", GetSymName (S)); } } S->ConDesPrio[Type] = Prio; /* Set the symbol data */ S->Flags |= (SF_EXPORT | SF_REFERENCED); /* Remember the line info for this reference */ CollAppend (&S->RefLines, GetAsmLineInfo ()); } void SymGuessedAddrSize (SymEntry* Sym, unsigned char AddrSize) /* Mark the address size of the given symbol as guessed. The address size ** passed as argument is the one NOT used, because the actual address size ** wasn't known. Example: Zero page addressing was not used because symbol ** is undefined, and absolute addressing was available. */ { /* We must have a valid address size passed */ PRECONDITION (AddrSize != ADDR_SIZE_DEFAULT); /* We do not support all address sizes currently */ if (AddrSize > sizeof (Sym->GuessedUse) / sizeof (Sym->GuessedUse[0])) { return; } /* We can only remember one such occurance */ if (Sym->GuessedUse[AddrSize-1]) { return; } /* Ok, remember the file position */ Sym->GuessedUse[AddrSize-1] = xdup (&CurTok.Pos, sizeof (CurTok.Pos)); } void SymExportFromGlobal (SymEntry* S) /* Called at the end of assembly. Converts a global symbol that is defined ** into an export. */ { /* Remove the global flag and make the symbol an export */ S->Flags &= ~SF_GLOBAL; S->Flags |= SF_EXPORT; } void SymImportFromGlobal (SymEntry* S) /* Called at the end of assembly. Converts a global symbol that is undefined ** into an import. */ { /* Remove the global flag and make it an import */ S->Flags &= ~SF_GLOBAL; S->Flags |= SF_IMPORT; } int SymIsConst (const SymEntry* S, long* Val) /* Return true if the given symbol has a constant value. If Val is not NULL ** and the symbol has a constant value, store it's value there. */ { /* Check for constness */ return (SymHasExpr (S) && IsConstExpr (S->Expr, Val)); } SymTable* GetSymParentScope (SymEntry* S) /* Get the parent scope of the symbol (not the one it is defined in). Return ** NULL if the symbol is a cheap local, or defined on global level. */ { if ((S->Flags & SF_LOCAL) != 0) { /* This is a cheap local symbol */ return 0; } else if (S->Sym.Tab == 0) { /* Symbol not in a table. This may happen if there have been errors ** before. Return NULL in this case to avoid further errors. */ return 0; } else { /* This is a global symbol */ return S->Sym.Tab->Parent; } } struct ExprNode* GetSymExpr (SymEntry* S) /* Get the expression for a non-const symbol */ { PRECONDITION (S != 0 && SymHasExpr (S)); return S->Expr; } const struct ExprNode* SymResolve (const SymEntry* S) /* Helper function for DumpExpr. Resolves a symbol into an expression or return ** NULL. Do not call in other contexts! */ { return SymHasExpr (S)? S->Expr : 0; } long GetSymVal (SymEntry* S) /* Return the value of a symbol assuming it's constant. FAIL will be called ** in case the symbol is undefined or not constant. */ { long Val; CHECK (S != 0 && SymHasExpr (S) && IsConstExpr (GetSymExpr (S), &Val)); return Val; } unsigned GetSymImportId (const SymEntry* S) /* Return the import id for the given symbol */ { PRECONDITION (S != 0 && (S->Flags & SF_IMPORT) && S->ImportId != ~0U); return S->ImportId; } unsigned GetSymExportId (const SymEntry* S) /* Return the export id for the given symbol */ { PRECONDITION (S != 0 && (S->Flags & SF_EXPORT) && S->ExportId != ~0U); return S->ExportId; } unsigned GetSymInfoFlags (const SymEntry* S, long* ConstVal) /* Return a set of flags used when writing symbol information into a file. ** If the SYM_CONST bit is set, ConstVal will contain the constant value ** of the symbol. The result does not include the condes count. ** See common/symdefs.h for more information. */ { /* Setup info flags */ unsigned Flags = 0; Flags |= SymIsConst (S, ConstVal)? SYM_CONST : SYM_EXPR; Flags |= (S->Flags & SF_LABEL)? SYM_LABEL : SYM_EQUATE; Flags |= (S->Flags & SF_LOCAL)? SYM_CHEAP_LOCAL : SYM_STD; if (S->Flags & SF_EXPORT) { Flags |= SYM_EXPORT; } if (S->Flags & SF_IMPORT) { Flags |= SYM_IMPORT; } /* Return the result */ return Flags; } �����������������������������������������������������������cc65-2.18/src/ca65/symentry.h�����������������������������������������������������������������������0000664�0000000�0000000�00000032143�13473601511�0015600�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* symentry.h */ /* */ /* Symbol table entry forward for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef SYMENTRY_H #define SYMENTRY_H /* common */ #include "cddefs.h" #include "coll.h" #include "filepos.h" #include "inline.h" #include "strbuf.h" /* ca65 */ #include "spool.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Forwards */ struct HLLDbgSym; /* Bits for the Flags value in SymEntry */ #define SF_NONE 0x0000 /* Empty flag set */ #define SF_USER 0x0001 /* User bit */ #define SF_UNUSED 0x0002 /* Unused entry */ #define SF_EXPORT 0x0004 /* Export this symbol */ #define SF_IMPORT 0x0008 /* Import this symbol */ #define SF_GLOBAL 0x0010 /* Global symbol */ #define SF_LOCAL 0x0020 /* Cheap local symbol */ #define SF_LABEL 0x0040 /* Used as a label */ #define SF_VAR 0x0080 /* Variable symbol */ #define SF_FORCED 0x0100 /* Forced import, SF_IMPORT also set */ #define SF_FIXED 0x0200 /* May not be trampoline */ #define SF_MULTDEF 0x1000 /* Multiply defined symbol */ #define SF_DEFINED 0x2000 /* Defined */ #define SF_REFERENCED 0x4000 /* Referenced */ /* Combined values */ #define SF_REFIMP (SF_REFERENCED|SF_IMPORT) /* A ref'd import */ /* Structure of a symbol table entry */ typedef struct SymEntry SymEntry; struct SymEntry { SymEntry* Left; /* Lexically smaller entry */ SymEntry* Right; /* Lexically larger entry */ SymEntry* List; /* List of all entries */ SymEntry* Locals; /* Root of subtree for local symbols */ union { struct SymTable* Tab; /* Table this symbol is in */ struct SymEntry* Entry; /* Parent for cheap locals */ } Sym; Collection DefLines; /* Line infos for definition */ Collection RefLines; /* Line infos for references */ FilePos* GuessedUse[1]; /* File position where symbol ** address size was guessed, and the ** smallest possible addressing was NOT ** used. Currently only for zero page ** addressing */ struct HLLDbgSym* HLLSym; /* Symbol from high level language */ unsigned Flags; /* Symbol flags */ unsigned DebugSymId; /* Debug symbol id */ unsigned ImportId; /* Id of import if this is one */ unsigned ExportId; /* Id of export if this is one */ struct ExprNode* Expr; /* Symbol expression */ Collection ExprRefs; /* Expressions using this symbol */ unsigned char ExportSize; /* Export address size */ unsigned char AddrSize; /* Address size of label */ unsigned char ConDesPrio[CD_TYPE_COUNT]; /* ConDes priorities... */ /* ...actually value+1 (used as flag) */ unsigned Name; /* Name index in global string pool */ }; /* List of all symbol table entries */ extern SymEntry* SymList; /* Pointer to last defined symbol */ extern SymEntry* SymLast; /*****************************************************************************/ /* Code */ /*****************************************************************************/ SymEntry* NewSymEntry (const StrBuf* Name, unsigned Flags); /* Allocate a symbol table entry, initialize and return it */ int SymSearchTree (SymEntry* T, const StrBuf* Name, SymEntry** E); /* Search in the given tree for a name. If we find the symbol, the function ** will return 0 and put the entry pointer into E. If we did not find the ** symbol, and the tree is empty, E is set to NULL. If the tree is not empty, ** E will be set to the last entry, and the result of the function is <0 if ** the entry should be inserted on the left side, and >0 if it should get ** inserted on the right side. */ #if defined(HAVE_INLINE) INLINE void SymAddExprRef (SymEntry* Sym, struct ExprNode* Expr) /* Add an expression reference to this symbol */ { CollAppend (&Sym->ExprRefs, Expr); } #else #define SymAddExprRef(Sym,Expr) CollAppend (&(Sym)->ExprRefs, Expr) #endif #if defined(HAVE_INLINE) INLINE void SymDelExprRef (SymEntry* Sym, struct ExprNode* Expr) /* Delete an expression reference to this symbol */ { CollDeleteItem (&Sym->ExprRefs, Expr); } #else #define SymDelExprRef(Sym,Expr) CollDeleteItem (&(Sym)->ExprRefs, Expr) #endif void SymTransferExprRefs (SymEntry* From, SymEntry* To); /* Transfer all expression references from one symbol to another. */ void SymDef (SymEntry* Sym, ExprNode* Expr, unsigned char AddrSize, unsigned Flags); /* Mark a symbol as defined */ void SymRef (SymEntry* Sym); /* Mark the given symbol as referenced */ void SymImport (SymEntry* Sym, unsigned char AddrSize, unsigned Flags); /* Mark the given symbol as an imported symbol */ void SymExport (SymEntry* Sym, unsigned char AddrSize, unsigned Flags); /* Mark the given symbol as an exported symbol */ void SymGlobal (SymEntry* Sym, unsigned char AddrSize, unsigned Flags); /* Mark the given symbol as a global symbol, that is, as a symbol that is ** either imported or exported. */ void SymConDes (SymEntry* Sym, unsigned char AddrSize, unsigned Type, unsigned Prio); /* Mark the given symbol as a module constructor/destructor. This will also ** mark the symbol as an export. Initializers may never be zero page symbols. */ void SymGuessedAddrSize (SymEntry* Sym, unsigned char AddrSize); /* Mark the address size of the given symbol as guessed. The address size ** passed as argument is the one NOT used, because the actual address size ** wasn't known. Example: Zero page addressing was not used because symbol ** is undefined, and absolute addressing was available. */ void SymExportFromGlobal (SymEntry* S); /* Called at the end of assembly. Converts a global symbol that is defined ** into an export. */ void SymImportFromGlobal (SymEntry* S); /* Called at the end of assembly. Converts a global symbol that is undefined ** into an import. */ #if defined(HAVE_INLINE) INLINE int SymIsDef (const SymEntry* S) /* Return true if the given symbol is already defined */ { return (S->Flags & SF_DEFINED) != 0; } #else # define SymIsDef(S) (((S)->Flags & SF_DEFINED) != 0) #endif #if defined(HAVE_INLINE) INLINE int SymIsRef (const SymEntry* S) /* Return true if the given symbol has been referenced */ { return (S->Flags & SF_REFERENCED) != 0; } #else # define SymIsRef(S) (((S)->Flags & SF_REFERENCED) != 0) #endif #if defined(HAVE_INLINE) INLINE int SymIsImport (const SymEntry* S) /* Return true if the given symbol is marked as import */ { /* Check the import flag */ return (S->Flags & SF_IMPORT) != 0; } #else # define SymIsImport(S) (((S)->Flags & SF_IMPORT) != 0) #endif #if defined(HAVE_INLINE) INLINE int SymIsExport (const SymEntry* S) /* Return true if the given symbol is marked as export */ { /* Check the export flag */ return (S->Flags & SF_EXPORT) != 0; } #else # define SymIsExport(S) (((S)->Flags & SF_EXPORT) != 0) #endif #if defined(HAVE_INLINE) INLINE int SymIsVar (const SymEntry* S) /* Return true if the given symbol is marked as variable */ { /* Check the variable flag */ return (S->Flags & SF_VAR) != 0; } #else # define SymIsVar(S) (((S)->Flags & SF_VAR) != 0) #endif int SymIsConst (const SymEntry* Sym, long* Val); /* Return true if the given symbol has a constant value. If Val is not NULL ** and the symbol has a constant value, store it's value there. */ #if defined(HAVE_INLINE) INLINE int SymHasExpr (const SymEntry* S) /* Return true if the given symbol has an associated expression */ { /* Check the expression */ return ((S->Flags & (SF_DEFINED|SF_IMPORT)) == SF_DEFINED); } #else # define SymHasExpr(S) (((S)->Flags & (SF_DEFINED|SF_IMPORT)) == SF_DEFINED) #endif #if defined(HAVE_INLINE) INLINE void SymMarkUser (SymEntry* S) /* Set a user mark on the specified symbol */ { /* Set the bit */ S->Flags |= SF_USER; } #else # define SymMarkUser(S) ((S)->Flags |= SF_USER) #endif #if defined(HAVE_INLINE) INLINE void SymUnmarkUser (SymEntry* S) /* Remove a user mark from the specified symbol */ { /* Reset the bit */ S->Flags &= ~SF_USER; } #else # define SymUnmarkUser(S) ((S)->Flags &= ~SF_USER) #endif #if defined(HAVE_INLINE) INLINE int SymHasUserMark (SymEntry* S) /* Return the state of the user mark for the specified symbol */ { /* Check the bit */ return (S->Flags & SF_USER) != 0; } #else # define SymHasUserMark(S) (((S)->Flags & SF_USER) != 0) #endif struct SymTable* GetSymParentScope (SymEntry* S); /* Get the parent scope of the symbol (not the one it is defined in). Return ** NULL if the symbol is a cheap local, or defined on global level. */ struct ExprNode* GetSymExpr (SymEntry* Sym); /* Get the expression for a non-const symbol */ const struct ExprNode* SymResolve (const SymEntry* Sym); /* Helper function for DumpExpr. Resolves a symbol into an expression or return ** NULL. Do not call in other contexts! */ #if defined(HAVE_INLINE) INLINE const StrBuf* GetSymName (const SymEntry* S) /* Return the name of the symbol */ { return GetStrBuf (S->Name); } #else # define GetSymName(S) GetStrBuf ((S)->Name) #endif #if defined(HAVE_INLINE) INLINE unsigned char GetSymAddrSize (const SymEntry* S) /* Return the address size of the symbol. Beware: This function will just ** return the AddrSize member, it will not look at the expression! */ { return S->AddrSize; } #else # define GetSymAddrSize(S) ((S)->AddrSize) #endif long GetSymVal (SymEntry* Sym); /* Return the value of a symbol assuming it's constant. FAIL will be called ** in case the symbol is undefined or not constant. */ unsigned GetSymImportId (const SymEntry* Sym); /* Return the import id for the given symbol */ unsigned GetSymExportId (const SymEntry* Sym); /* Return the export id for the given symbol */ unsigned GetSymInfoFlags (const SymEntry* Sym, long* ConstVal); /* Return a set of flags used when writing symbol information into a file. ** If the SYM_CONST bit is set, ConstVal will contain the constant value ** of the symbol. The result does not include the condes count. ** See common/symdefs.h for more information. */ /* End of symentry.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/symtab.c�������������������������������������������������������������������������0000664�0000000�0000000�00000077563�13473601511�0015217�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* symtab.c */ /* */ /* Symbol table for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 1998-2014, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* common */ #include "addrsize.h" #include "check.h" #include "hashfunc.h" #include "mmodel.h" #include "scopedefs.h" #include "symdefs.h" #include "xmalloc.h" /* ca65 */ #include "dbginfo.h" #include "error.h" #include "expr.h" #include "global.h" #include "objfile.h" #include "scanner.h" #include "segment.h" #include "sizeof.h" #include "span.h" #include "spool.h" #include "studyexpr.h" #include "symtab.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Combined symbol entry flags used within this module */ #define SF_UNDEFMASK (SF_REFERENCED | SF_DEFINED | SF_IMPORT) #define SF_UNDEFVAL (SF_REFERENCED) /* Symbol tables */ SymTable* CurrentScope = 0; /* Pointer to current symbol table */ SymTable* RootScope = 0; /* Root symbol table */ static SymTable* LastScope = 0; /* Pointer to last scope in list */ static unsigned ScopeCount = 0; /* Number of scopes */ /* Symbol table variables */ static unsigned ImportCount = 0; /* Counter for import symbols */ static unsigned ExportCount = 0; /* Counter for export symbols */ /*****************************************************************************/ /* Internally used functions */ /*****************************************************************************/ static int IsDbgSym (const SymEntry* S) /* Return true if this is a debug symbol */ { if ((S->Flags & (SF_DEFINED | SF_UNUSED)) == SF_DEFINED) { /* Defined symbols are debug symbols if they aren't sizes */ return !IsSizeOfSymbol (S); } else { /* Others are debug symbols if they're referenced imports */ return ((S->Flags & SF_REFIMP) == SF_REFIMP); } } static unsigned ScopeTableSize (unsigned Level) /* Get the size of a table for the given lexical level */ { switch (Level) { case 0: return 213; case 1: return 53; default: return 29; } } static SymTable* NewSymTable (SymTable* Parent, const StrBuf* Name) /* Allocate a symbol table on the heap and return it */ { /* Determine the lexical level and the number of table slots */ unsigned Level = Parent? Parent->Level + 1 : 0; unsigned Slots = ScopeTableSize (Level); /* Allocate memory */ SymTable* S = xmalloc (sizeof (SymTable) + (Slots-1) * sizeof (SymEntry*)); /* Set variables and clear hash table entries */ S->Next = 0; S->Left = 0; S->Right = 0; S->Childs = 0; S->Label = 0; S->Spans = AUTO_COLLECTION_INITIALIZER; S->Id = ScopeCount++; S->Flags = ST_NONE; S->AddrSize = ADDR_SIZE_DEFAULT; S->Type = SCOPE_UNDEF; S->Level = Level; S->TableSlots = Slots; S->TableEntries = 0; S->Parent = Parent; S->Name = GetStrBufId (Name); while (Slots--) { S->Table[Slots] = 0; } /* Insert the symbol table into the list of all symbol tables */ if (RootScope == 0) { RootScope = S; } else { LastScope->Next = S; } LastScope = S; /* Insert the symbol table into the child tree of the parent */ if (Parent) { SymTable* T = Parent->Childs; if (T == 0) { /* First entry */ Parent->Childs = S; } else { while (1) { /* Choose next entry */ int Cmp = SB_Compare (Name, GetStrBuf (T->Name)); if (Cmp < 0) { if (T->Left) { T = T->Left; } else { T->Left = S; break; } } else if (Cmp > 0) { if (T->Right) { T = T->Right; } else { T->Right = S; break; } } else { /* Duplicate scope name */ Internal ("Duplicate scope name: '%m%p'", Name); } } } } /* Return the prepared struct */ return S; } /*****************************************************************************/ /* Code */ /*****************************************************************************/ void SymEnterLevel (const StrBuf* ScopeName, unsigned char Type, unsigned char AddrSize, SymEntry* ScopeLabel) /* Enter a new lexical level */ { /* Map a default address size to something real */ if (AddrSize == ADDR_SIZE_DEFAULT) { /* Use the segment address size */ AddrSize = GetCurrentSegAddrSize (); } /* If we have a current scope, search for the given name and create a ** new one if it doesn't exist. If this is the root scope, just create it. */ if (CurrentScope) { /* Search for the scope, create a new one */ CurrentScope = SymFindScope (CurrentScope, ScopeName, SYM_ALLOC_NEW); /* Check if the scope has been defined before */ if (CurrentScope->Flags & ST_DEFINED) { Error ("Duplicate scope '%m%p'", ScopeName); } } else { CurrentScope = RootScope = NewSymTable (0, ScopeName); } /* Mark the scope as defined and set type, address size and owner symbol */ CurrentScope->Flags |= ST_DEFINED; CurrentScope->AddrSize = AddrSize; CurrentScope->Type = Type; CurrentScope->Label = ScopeLabel; /* If this is a scope that allows to emit data into segments, add spans ** for all currently existing segments. Doing this for just a few scope ** types is not really necessary but an optimization, because it does not ** allocate memory for useless data (unhandled types here don't occupy ** space in any segment). */ if (CurrentScope->Type <= SCOPE_HAS_DATA) { OpenSpanList (&CurrentScope->Spans); } } void SymLeaveLevel (void) /* Leave the current lexical level */ { /* If this is a scope that allows to emit data into segments, close the ** open the spans. */ if (CurrentScope->Type <= SCOPE_HAS_DATA) { CloseSpanList (&CurrentScope->Spans); } /* If we have spans, the first one is the segment that was active, when the ** scope was opened. Set the size of the scope to the number of data bytes ** emitted into this segment. If we have an owner symbol set the size of ** this symbol, too. */ if (CollCount (&CurrentScope->Spans) > 0) { const Span* S = CollAtUnchecked (&CurrentScope->Spans, 0); unsigned long Size = GetSpanSize (S); DefSizeOfScope (CurrentScope, Size); if (CurrentScope->Label) { DefSizeOfSymbol (CurrentScope->Label, Size); } } /* Mark the scope as closed */ CurrentScope->Flags |= ST_CLOSED; /* Leave the scope */ CurrentScope = CurrentScope->Parent; } SymTable* SymFindScope (SymTable* Parent, const StrBuf* Name, SymFindAction Action) /* Find a scope in the given enclosing scope */ { SymTable** T = &Parent->Childs; while (*T) { int Cmp = SB_Compare (Name, GetStrBuf ((*T)->Name)); if (Cmp < 0) { T = &(*T)->Left; } else if (Cmp > 0) { T = &(*T)->Right; } else { /* Found the scope */ return *T; } } /* Create a new scope if requested and we didn't find one */ if (*T == 0 && (Action & SYM_ALLOC_NEW) != 0) { *T = NewSymTable (Parent, Name); } /* Return the scope */ return *T; } SymTable* SymFindAnyScope (SymTable* Parent, const StrBuf* Name) /* Find a scope in the given or any of its parent scopes. The function will ** never create a new symbol, since this can only be done in one specific ** scope. */ { SymTable* Scope; do { /* Search in the current table */ Scope = SymFindScope (Parent, Name, SYM_FIND_EXISTING); if (Scope == 0) { /* Not found, search in the parent scope, if we have one */ Parent = Parent->Parent; } } while (Scope == 0 && Parent != 0); return Scope; } SymEntry* SymFindLocal (SymEntry* Parent, const StrBuf* Name, SymFindAction Action) /* Find a cheap local symbol. If Action contains SYM_ALLOC_NEW and the entry is ** not found, create a new one. Return the entry found, or the new entry ** created, or - in case Action is SYM_FIND_EXISTING - return 0. */ { SymEntry* S; int Cmp; /* Local symbol, get the table */ if (!Parent) { /* No last global, so there's no local table */ Error ("No preceeding global symbol"); if (Action & SYM_ALLOC_NEW) { return NewSymEntry (Name, SF_LOCAL); } else { return 0; } } /* Search for the symbol if we have a table */ Cmp = SymSearchTree (Parent->Locals, Name, &S); /* If we found an entry, return it */ if (Cmp == 0) { return S; } if (Action & SYM_ALLOC_NEW) { /* Otherwise create a new entry, insert and return it */ SymEntry* N = NewSymEntry (Name, SF_LOCAL); N->Sym.Entry = Parent; if (S == 0) { Parent->Locals = N; } else if (Cmp < 0) { S->Left = N; } else { S->Right = N; } return N; } /* We did not find the entry and AllocNew is false. */ return 0; } SymEntry* SymFind (SymTable* Scope, const StrBuf* Name, SymFindAction Action) /* Find a new symbol table entry in the given table. If Action contains ** SYM_ALLOC_NEW and the entry is not found, create a new one. Return the ** entry found, or the new entry created, or - in case Action is ** SYM_FIND_EXISTING - return 0. */ { SymEntry* S; /* Global symbol: Get the hash value for the name */ unsigned Hash = HashBuf (Name) % Scope->TableSlots; /* Search for the entry */ int Cmp = SymSearchTree (Scope->Table[Hash], Name, &S); /* If we found an entry, return it */ if (Cmp == 0) { if ((Action & SYM_CHECK_ONLY) == 0 && SymTabIsClosed (Scope)) { S->Flags |= SF_FIXED; } return S; } if (Action & SYM_ALLOC_NEW) { /* Otherwise create a new entry, insert and return it. If the scope is ** already closed, mark the symbol as fixed so it won't be resolved ** by a symbol in the enclosing scopes later. */ SymEntry* N = NewSymEntry (Name, SF_NONE); if (SymTabIsClosed (Scope)) { N->Flags |= SF_FIXED; } N->Sym.Tab = Scope; if (S == 0) { Scope->Table[Hash] = N; } else if (Cmp < 0) { S->Left = N; } else { S->Right = N; } ++Scope->TableEntries; return N; } /* We did not find the entry and AllocNew is false. */ return 0; } SymEntry* SymFindAny (SymTable* Scope, const StrBuf* Name) /* Find a symbol in the given or any of its parent scopes. The function will ** never create a new symbol, since this can only be done in one specific ** scope. */ { /* Generate the name hash */ unsigned Hash = HashBuf (Name); /* Search for the symbol */ SymEntry* Sym; do { /* Search in the current table. Ignore entries flagged with SF_UNUSED, ** because for such symbols there is a real entry in one of the parent ** scopes. */ if (SymSearchTree (Scope->Table[Hash % Scope->TableSlots], Name, &Sym) == 0) { if (Sym->Flags & SF_UNUSED) { Sym = 0; } else { /* Found, return it */ break; } } else { Sym = 0; } /* Not found, search in the parent scope, if we have one */ Scope = Scope->Parent; } while (Sym == 0 && Scope != 0); /* Return the result */ return Sym; } static void SymCheckUndefined (SymEntry* S) /* Handle an undefined symbol */ { /* Undefined symbol. It may be... ** ** - An undefined symbol in a nested lexical level. If the symbol is not ** fixed to this level, search for the symbol in the higher levels and ** make the entry a trampoline entry if we find one. ** ** - If the symbol is not found, it is a real undefined symbol. If the ** AutoImport flag is set, make it an import. If the AutoImport flag is ** not set, it's an error. */ SymEntry* Sym = 0; if ((S->Flags & SF_FIXED) == 0) { SymTable* Tab = GetSymParentScope (S); while (Tab) { Sym = SymFind (Tab, GetStrBuf (S->Name), SYM_FIND_EXISTING | SYM_CHECK_ONLY); if (Sym && (Sym->Flags & (SF_DEFINED | SF_IMPORT)) != 0) { /* We've found a symbol in a higher level that is ** either defined in the source, or an import. */ break; } /* No matching symbol found in this level. Look further */ Tab = Tab->Parent; } } if (Sym) { /* We found the symbol in a higher level. Transfer the flags and ** address size from the local symbol to that in the higher level ** and check for problems. */ if (S->Flags & SF_EXPORT) { if (Sym->Flags & SF_IMPORT) { /* The symbol is already marked as import */ LIError (&S->RefLines, "Symbol '%s' is already an import", GetString (Sym->Name)); } if ((Sym->Flags & SF_EXPORT) == 0) { /* Mark the symbol as an export */ Sym->Flags |= SF_EXPORT; Sym->ExportSize = S->ExportSize; if (Sym->ExportSize == ADDR_SIZE_DEFAULT) { /* Use the actual size of the symbol */ Sym->ExportSize = Sym->AddrSize; } if (Sym->AddrSize > Sym->ExportSize) { /* We're exporting a symbol smaller than it actually is */ LIWarning (&Sym->DefLines, 1, "Symbol '%m%p' is %s but exported %s", GetSymName (Sym), AddrSizeToStr (Sym->AddrSize), AddrSizeToStr (Sym->ExportSize)); } } } if (S->Flags & SF_REFERENCED) { /* Mark as referenced and move the line info */ Sym->Flags |= SF_REFERENCED; CollTransfer (&Sym->RefLines, &S->RefLines); CollDeleteAll (&S->RefLines); } /* Transfer all expression references */ SymTransferExprRefs (S, Sym); /* Mark the symbol as unused removing all other flags */ S->Flags = SF_UNUSED; } else { /* The symbol is definitely undefined */ if (S->Flags & SF_EXPORT) { /* We will not auto-import an export */ LIError (&S->RefLines, "Exported symbol '%m%p' was never defined", GetSymName (S)); } else { if (AutoImport) { /* Mark as import, will be indexed later */ S->Flags |= SF_IMPORT; /* Use the address size for code */ S->AddrSize = CodeAddrSize; /* Mark point of import */ GetFullLineInfo (&S->DefLines); } else { /* Error */ LIError (&S->RefLines, "Symbol '%m%p' is undefined", GetSymName (S)); } } } } void SymCheck (void) /* Run through all symbols and check for anomalies and errors */ { SymEntry* S; /* Check for open scopes */ if (CurrentScope->Parent != 0) { Error ("Local scope was not closed"); } /* First pass: Walk through all symbols, checking for undefined's and ** changing them to trampoline symbols or make them imports. */ S = SymList; while (S) { /* If the symbol is marked as global, mark it as export, if it is ** already defined, otherwise mark it as import. */ if (S->Flags & SF_GLOBAL) { if (S->Flags & SF_DEFINED) { SymExportFromGlobal (S); } else { SymImportFromGlobal (S); } } /* Handle undefined symbols */ if ((S->Flags & SF_UNDEFMASK) == SF_UNDEFVAL) { /* This is an undefined symbol. Handle it. */ SymCheckUndefined (S); } /* Next symbol */ S = S->List; } /* Second pass: Walk again through the symbols. Count exports and imports ** and set address sizes where this has not happened before. Ignore ** undefined's, since we handled them in the last pass, and ignore unused ** symbols, since we handled them in the last pass, too. */ S = SymList; while (S) { if ((S->Flags & SF_UNUSED) == 0 && (S->Flags & SF_UNDEFMASK) != SF_UNDEFVAL) { /* Check for defined symbols that were never referenced */ if (IsSizeOfSymbol (S)) { /* Remove line infos, we don't need them any longer */ ReleaseFullLineInfo (&S->DefLines); ReleaseFullLineInfo (&S->RefLines); } else if ((S->Flags & SF_DEFINED) != 0 && (S->Flags & SF_REFERENCED) == 0) { LIWarning (&S->DefLines, 2, "Symbol '%m%p' is defined but never used", GetSymName (S)); } /* Assign an index to all imports */ if (S->Flags & SF_IMPORT) { if ((S->Flags & (SF_REFERENCED | SF_FORCED)) == SF_NONE) { /* Imported symbol is not referenced */ LIWarning (&S->DefLines, 2, "Symbol '%m%p' is imported but never used", GetSymName (S)); } else { /* Give the import an id, count imports */ S->ImportId = ImportCount++; } } /* Count exports, assign the export ID */ if (S->Flags & SF_EXPORT) { S->ExportId = ExportCount++; } /* If the symbol is defined but has an unknown address size, ** recalculate it. */ if (SymHasExpr (S) && S->AddrSize == ADDR_SIZE_DEFAULT) { ExprDesc ED; ED_Init (&ED); StudyExpr (S->Expr, &ED); S->AddrSize = ED.AddrSize; if (SymIsExport (S)) { if (S->ExportSize == ADDR_SIZE_DEFAULT) { /* Use the real export size */ S->ExportSize = S->AddrSize; } else if (S->AddrSize > S->ExportSize) { /* We're exporting a symbol smaller than it actually is */ LIWarning (&S->DefLines, 1, "Symbol '%m%p' is %s but exported %s", GetSymName (S), AddrSizeToStr (S->AddrSize), AddrSizeToStr (S->ExportSize)); } } ED_Done (&ED); } /* If the address size of the symbol was guessed, check the guess ** against the actual address size and print a warning if the two ** differ. */ if (S->AddrSize != ADDR_SIZE_DEFAULT) { /* Do we have data for this address size? */ if (S->AddrSize <= sizeof (S->GuessedUse) / sizeof (S->GuessedUse[0])) { /* Get the file position where the symbol was used */ const FilePos* P = S->GuessedUse[S->AddrSize - 1]; if (P) { PWarning (P, 0, "Didn't use %s addressing for '%m%p'", AddrSizeToStr (S->AddrSize), GetSymName (S)); } } } } /* Next symbol */ S = S->List; } } void SymDump (FILE* F) /* Dump the symbol table */ { SymEntry* S = SymList; while (S) { /* Ignore unused symbols */ if ((S->Flags & SF_UNUSED) == 0) { fprintf (F, "%-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" : "---", (S->Flags & SF_EXPORT)? "EXP" : "---", AddrSizeToStr (S->AddrSize)); } /* Next symbol */ S = S->List; } } void WriteImports (void) /* Write the imports list to the object file */ { SymEntry* S; /* Tell the object file module that we're about to start the imports */ ObjStartImports (); /* Write the import count to the list */ ObjWriteVar (ImportCount); /* Walk throught list and write all valid imports to the file. An import ** is considered valid, if it is either referenced, or the forced bit is ** set. Otherwise, the import is ignored (no need to link in something ** that isn't used). */ S = SymList; while (S) { if ((S->Flags & (SF_UNUSED | SF_IMPORT)) == SF_IMPORT && (S->Flags & (SF_REFERENCED | SF_FORCED)) != 0) { ObjWrite8 (S->AddrSize); ObjWriteVar (S->Name); WriteLineInfo (&S->DefLines); WriteLineInfo (&S->RefLines); } S = S->List; } /* Done writing imports */ ObjEndImports (); } void WriteExports (void) /* Write the exports list to the object file */ { SymEntry* S; unsigned Type; /* Tell the object file module that we're about to start the exports */ ObjStartExports (); /* Write the export count to the list */ ObjWriteVar (ExportCount); /* Walk throught list and write all exports to the file */ S = SymList; while (S) { if ((S->Flags & (SF_UNUSED | SF_EXPORT)) == SF_EXPORT) { /* Get the expression bits and the value */ long ConstVal; unsigned SymFlags = GetSymInfoFlags (S, &ConstVal); /* Check if this symbol has a size. If so, remember it in the ** flags. */ long Size; SymEntry* SizeSym = FindSizeOfSymbol (S); if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) { SymFlags |= SYM_SIZE; } /* Count the number of ConDes types */ for (Type = 0; Type < CD_TYPE_COUNT; ++Type) { if (S->ConDesPrio[Type] != CD_PRIO_NONE) { SYM_INC_CONDES_COUNT (SymFlags); } } /* Write the type and the export size */ ObjWriteVar (SymFlags); ObjWrite8 (S->ExportSize); /* Write any ConDes declarations */ if (SYM_GET_CONDES_COUNT (SymFlags) > 0) { for (Type = 0; Type < CD_TYPE_COUNT; ++Type) { unsigned char Prio = S->ConDesPrio[Type]; if (Prio != CD_PRIO_NONE) { ObjWrite8 (CD_BUILD (Type, Prio)); } } } /* Write the name */ ObjWriteVar (S->Name); /* Write the value */ if (SYM_IS_CONST (SymFlags)) { /* Constant value */ ObjWrite32 (ConstVal); } else { /* Expression involved */ WriteExpr (S->Expr); } /* If the symbol has a size, write it to the file */ if (SYM_HAS_SIZE (SymFlags)) { ObjWriteVar (Size); } /* Write the line infos */ WriteLineInfo (&S->DefLines); WriteLineInfo (&S->RefLines); } S = S->List; } /* Done writing exports */ ObjEndExports (); } void WriteDbgSyms (void) /* Write a list of all symbols to the object file */ { unsigned Count; SymEntry* S; /* Tell the object file module that we're about to start the debug info */ ObjStartDbgSyms (); /* Check if debug info is requested */ if (DbgSyms) { /* Walk through the list, give each symbol an id and count them */ Count = 0; S = SymList; while (S) { if (IsDbgSym (S)) { S->DebugSymId = Count++; } S = S->List; } /* Write the symbol count to the list */ ObjWriteVar (Count); /* Walk through list and write all symbols to the file. Ignore size ** symbols. */ S = SymList; while (S) { if (IsDbgSym (S)) { /* Get the expression bits and the value */ long ConstVal; unsigned SymFlags = GetSymInfoFlags (S, &ConstVal); /* Check if this symbol has a size. If so, remember it in the ** flags. */ long Size; SymEntry* SizeSym = FindSizeOfSymbol (S); if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) { SymFlags |= SYM_SIZE; } /* Write the type */ ObjWriteVar (SymFlags); /* Write the address size */ ObjWrite8 (S->AddrSize); /* Write the id of the parent. For normal symbols, this is a ** scope (symbol table), for cheap locals, it's a symbol. */ if (SYM_IS_STD (SymFlags)) { ObjWriteVar (S->Sym.Tab->Id); } else { ObjWriteVar (S->Sym.Entry->DebugSymId); } /* Write the name */ ObjWriteVar (S->Name); /* Write the value */ if (SYM_IS_CONST (SymFlags)) { /* Constant value */ ObjWrite32 (ConstVal); } else { /* Expression involved */ WriteExpr (S->Expr); } /* If the symbol has a size, write it to the file */ if (SYM_HAS_SIZE (SymFlags)) { ObjWriteVar (Size); } /* If the symbol is an im- or export, write out the ids */ if (SYM_IS_IMPORT (SymFlags)) { ObjWriteVar (GetSymImportId (S)); } if (SYM_IS_EXPORT (SymFlags)) { ObjWriteVar (GetSymExportId (S)); } /* Write the line infos */ WriteLineInfo (&S->DefLines); WriteLineInfo (&S->RefLines); } S = S->List; } } else { /* No debug symbols */ ObjWriteVar (0); } /* Write the high level symbols */ WriteHLLDbgSyms (); /* Done writing debug symbols */ ObjEndDbgSyms (); } void WriteScopes (void) /* Write the scope table to the object file */ { /* Tell the object file module that we're about to start the scopes */ ObjStartScopes (); /* We will write scopes only if debug symbols are requested */ if (DbgSyms) { /* Get head of list */ SymTable* S = RootScope; /* Write the scope count to the file */ ObjWriteVar (ScopeCount); /* Walk through all scopes and write them to the file */ while (S) { /* Flags for this scope */ unsigned Flags = 0; /* Check if this scope has a size. If so, remember it in the ** flags. */ long Size; SymEntry* SizeSym = FindSizeOfScope (S); if (SizeSym != 0 && SymIsConst (SizeSym, &Size)) { Flags |= SCOPE_SIZE; } /* Check if the scope has a label */ if (S->Label) { Flags |= SCOPE_LABELED; } /* Scope must be defined */ CHECK (S->Type != SCOPE_UNDEF); /* Id of parent scope */ if (S->Parent) { ObjWriteVar (S->Parent->Id); } else { ObjWriteVar (0); } /* Lexical level */ ObjWriteVar (S->Level); /* Scope flags */ ObjWriteVar (Flags); /* Type of scope */ ObjWriteVar (S->Type); /* Name of the scope */ ObjWriteVar (S->Name); /* If the scope has a size, write it to the file */ if (SCOPE_HAS_SIZE (Flags)) { ObjWriteVar (Size); } /* If the scope has a label, write its id to the file */ if (SCOPE_HAS_LABEL (Flags)) { ObjWriteVar (S->Label->DebugSymId); } /* Spans for this scope */ WriteSpanList (&S->Spans); /* Next scope */ S = S->Next; } } else { /* No debug info requested */ ObjWriteVar (0); } /* Done writing the scopes */ ObjEndScopes (); } ���������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/symtab.h�������������������������������������������������������������������������0000664�0000000�0000000�00000016146�13473601511�0015212�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* symtab.h */ /* */ /* Symbol table for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef SYMTAB_H #define SYMTAB_H #include <stdio.h> /* common */ #include "exprdefs.h" #include "inline.h" /* ca65 */ #include "symentry.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Arguments for SymFind... */ typedef enum { SYM_FIND_EXISTING = 0x00, SYM_ALLOC_NEW = 0x01, SYM_CHECK_ONLY = 0x02, } SymFindAction; /* Symbol table flags */ #define ST_NONE 0x00 /* No flags */ #define ST_DEFINED 0x01 /* Scope has been defined */ #define ST_CLOSED 0x02 /* Scope is closed */ /* A symbol table */ typedef struct SymTable SymTable; struct SymTable { SymTable* Next; /* Pointer to next table in list */ SymTable* Left; /* Pointer to smaller entry */ SymTable* Right; /* Pointer to greater entry */ SymTable* Parent; /* Link to enclosing scope if any */ SymTable* Childs; /* Pointer to child scopes */ SymEntry* Label; /* Scope label */ Collection Spans; /* Spans for this scope */ unsigned Id; /* Scope id */ unsigned short Flags; /* Symbol table flags */ unsigned char AddrSize; /* Address size */ unsigned char Type; /* Type of the scope */ unsigned Level; /* Lexical level */ unsigned TableSlots; /* Number of hash table slots */ unsigned TableEntries; /* Number of entries in the table */ unsigned Name; /* Name of the scope */ SymEntry* Table[1]; /* Dynamic allocation */ }; /* Symbol tables */ extern SymTable* CurrentScope; /* Pointer to current symbol table */ extern SymTable* RootScope; /* Root symbol table */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ void SymEnterLevel (const StrBuf* ScopeName, unsigned char Type, unsigned char AddrSize, SymEntry* OwnerSym); /* Enter a new lexical level */ void SymLeaveLevel (void); /* Leave the current lexical level */ SymTable* SymFindScope (SymTable* Parent, const StrBuf* Name, SymFindAction Action); /* Find a scope in the given enclosing scope */ SymTable* SymFindAnyScope (SymTable* Parent, const StrBuf* Name); /* Find a scope in the given or any of its parent scopes. The function will ** never create a new symbol, since this can only be done in one specific ** scope. */ SymEntry* SymFindLocal (SymEntry* Parent, const StrBuf* Name, SymFindAction Action); /* Find a cheap local symbol. If Action contains SYM_ALLOC_NEW and the entry is ** not found, create a new one. Return the entry found, or the new entry ** created, or - in case Action is SYM_FIND_EXISTING - return 0. */ SymEntry* SymFind (SymTable* Scope, const StrBuf* Name, SymFindAction Action); /* Find a new symbol table entry in the given table. If Action contains ** SYM_ALLOC_NEW and the entry is not found, create a new one. Return the ** entry found, or the new entry created, or - in case Action is ** SYM_FIND_EXISTING - return 0. */ SymEntry* SymFindAny (SymTable* Scope, const StrBuf* Name); /* Find a symbol in the given or any of its parent scopes. The function will ** never create a new symbol, since this can only be done in one specific ** scope. */ #if defined(HAVE_INLINE) INLINE unsigned char GetSymTabType (const SymTable* S) /* Return the type of the given symbol table */ { return S->Type; } #else # define GetSymTabType(S) ((S)->Type) #endif #if defined(HAVE_INLINE) INLINE int SymTabIsClosed (const SymTable* S) /* Return true if the symbol table has been closed */ { return (S->Flags & ST_CLOSED) != 0; } #else # define SymTabIsClosed(S) (((S)->Flags & ST_CLOSED) != 0) #endif void SymCheck (void); /* Run through all symbols and check for anomalies and errors */ void SymDump (FILE* F); /* Dump the symbol table */ void WriteImports (void); /* Write the imports list to the object file */ void WriteExports (void); /* Write the exports list to the object file */ void WriteDbgSyms (void); /* Write a list of all symbols to the object file */ void WriteScopes (void); /* Write the scope table to the object file */ /* End of symtab.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/token.c��������������������������������������������������������������������������0000664�0000000�0000000�00000006657�13473601511�0015034�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* token.c */ /* */ /* Token list for the ca65 macro assembler */ /* */ /* */ /* */ /* (C) 2007-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* ca65 */ #include "token.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ int TokHasSVal (token_t Tok) /* Return true if the given token has an attached SVal */ { return (Tok == TOK_IDENT || Tok == TOK_LOCAL_IDENT || Tok == TOK_STRCON); } int TokHasIVal (token_t Tok) /* Return true if the given token has an attached IVal */ { return (Tok == TOK_INTCON || Tok == TOK_CHARCON || Tok == TOK_REG); } void CopyToken (Token* Dst, const Token* Src) /* Copy a token from Src to Dst. The current value of Dst.SVal is free'd, ** so Dst must be initialized. */ { /* Copy the fields */ Dst->Tok = Src->Tok; Dst->WS = Src->WS; Dst->IVal = Src->IVal; SB_Copy (&Dst->SVal, &Src->SVal); Dst->Pos = Src->Pos; } ���������������������������������������������������������������������������������cc65-2.18/src/ca65/token.h��������������������������������������������������������������������������0000664�0000000�0000000�00000021701�13473601511�0015024�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* token.h */ /* */ /* Token list for the ca65 macro assembler */ /* */ /* */ /* */ /* (C) 2007-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef TOKEN_H #define TOKEN_H /* common */ #include "filepos.h" #include "inline.h" #include "strbuf.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Tokens */ typedef enum token_t { TOK_NONE, /* Start value, invalid */ TOK_EOF, /* End of input file */ TOK_SEP, /* Separator (usually newline) */ TOK_IDENT, /* An identifier */ TOK_LOCAL_IDENT, /* A cheap local identifier */ TOK_INTCON, /* Integer constant */ TOK_CHARCON, /* Character constant */ TOK_STRCON, /* String constant */ TOK_A, /* A)ccumulator */ TOK_X, /* X register */ TOK_Y, /* Y register */ TOK_Z, /* Z register */ TOK_S, /* S register */ TOK_REG, /* Sweet16 R.. register (in sweet16 mode) */ TOK_ASSIGN, /* := */ TOK_ULABEL, /* :++ or :-- */ TOK_EQ, /* = */ TOK_NE, /* <> */ TOK_LT, /* < */ TOK_GT, /* > */ TOK_LE, /* <= */ TOK_GE, /* >= */ TOK_BOOLAND, /* .and */ TOK_BOOLOR, /* .or */ TOK_BOOLXOR, /* .xor */ TOK_BOOLNOT, /* .not */ TOK_PLUS, /* + */ TOK_MINUS, /* - */ TOK_MUL, /* * */ TOK_STAR = TOK_MUL, /* Alias */ TOK_DIV, /* / */ TOK_MOD, /* ! */ TOK_OR, /* | */ TOK_XOR, /* ^ */ TOK_AND, /* & */ TOK_SHL, /* << */ TOK_SHR, /* >> */ TOK_NOT, /* ~ */ TOK_PC, /* $ if enabled */ TOK_NAMESPACE, /* :: */ TOK_DOT, /* . */ TOK_COMMA, /* , */ TOK_HASH, /* # */ TOK_COLON, /* : */ TOK_LPAREN, /* ( */ TOK_RPAREN, /* ) */ TOK_LBRACK, /* [ */ TOK_RBRACK, /* ] */ TOK_LCURLY, /* { */ TOK_RCURLY, /* } */ TOK_AT, /* @ - in Sweet16 mode */ TOK_OVERRIDE_ZP, /* z: */ TOK_OVERRIDE_ABS, /* a: */ TOK_OVERRIDE_FAR, /* f: */ TOK_MACPARAM, /* Macro parameter, not generated by scanner */ TOK_REPCOUNTER, /* Repeat counter, not generated by scanner */ /* The next ones are tokens for the pseudo instructions. Keep together! */ TOK_FIRSTPSEUDO, TOK_A16 = TOK_FIRSTPSEUDO, TOK_A8, TOK_ADDR, TOK_ADDRSIZE, TOK_ALIGN, TOK_ASCIIZ, TOK_ASIZE, TOK_ASSERT, TOK_AUTOIMPORT, TOK_BANK, TOK_BANKBYTE, TOK_BANKBYTES, TOK_BLANK, TOK_BSS, TOK_BYTE, TOK_CASE, TOK_CHARMAP, TOK_CODE, TOK_CONCAT, TOK_CONDES, TOK_CONST, TOK_CONSTRUCTOR, TOK_CPU, TOK_DATA, TOK_DBG, TOK_DBYT, TOK_DEBUGINFO, TOK_DEFINE, TOK_DEFINED, TOK_DEFINEDMACRO, TOK_DELMAC, TOK_DESTRUCTOR, TOK_DWORD, TOK_ELSE, TOK_ELSEIF, TOK_END, TOK_ENDENUM, TOK_ENDIF, TOK_ENDMACRO, TOK_ENDPROC, TOK_ENDREP, TOK_ENDSCOPE, TOK_ENDSTRUCT, TOK_ENDUNION, TOK_ENUM, TOK_ERROR, TOK_EXITMACRO, TOK_EXPORT, TOK_EXPORTZP, TOK_FARADDR, TOK_FATAL, TOK_FEATURE, TOK_FILEOPT, TOK_FORCEIMPORT, TOK_FORCEWORD, TOK_GLOBAL, TOK_GLOBALZP, TOK_HIBYTE, TOK_HIBYTES, TOK_HIWORD, TOK_I16, TOK_I8, TOK_MAKEIDENT, TOK_IF, TOK_IFBLANK, TOK_IFCONST, TOK_IFDEF, TOK_IFNBLANK, TOK_IFNCONST, TOK_IFNDEF, TOK_IFNREF, TOK_IFP02, TOK_IFP4510, TOK_IFP816, TOK_IFPC02, TOK_IFPSC02, TOK_IFREF, TOK_IMPORT, TOK_IMPORTZP, TOK_INCBIN, TOK_INCLUDE, TOK_INTERRUPTOR, TOK_ISIZE, TOK_ISMNEMONIC, TOK_LEFT, TOK_LINECONT, TOK_LIST, TOK_LISTBYTES, TOK_LOBYTE, TOK_LOBYTES, TOK_LOCAL, TOK_LOCALCHAR, TOK_LOWORD, TOK_MACPACK, TOK_MACRO, TOK_MATCH, TOK_MAX, TOK_MID, TOK_MIN, TOK_NULL, TOK_ORG, TOK_OUT, TOK_P02, TOK_P4510, TOK_P816, TOK_PAGELENGTH, TOK_PARAMCOUNT, TOK_PC02, TOK_POPCPU, TOK_POPSEG, TOK_PROC, TOK_PSC02, TOK_PUSHCPU, TOK_PUSHSEG, TOK_REFERENCED, TOK_RELOC, TOK_REPEAT, TOK_RES, TOK_RIGHT, TOK_RODATA, TOK_SCOPE, TOK_SEGMENT, TOK_SET, TOK_SETCPU, TOK_SIZEOF, TOK_SMART, TOK_SPRINTF, TOK_STRAT, TOK_STRING, TOK_STRLEN, TOK_STRUCT, TOK_TAG, TOK_TCOUNT, TOK_TIME, TOK_UNDEF, TOK_UNION, TOK_VERSION, TOK_WARNING, TOK_WORD, TOK_XMATCH, TOK_ZEROPAGE, TOK_LASTPSEUDO = TOK_ZEROPAGE, TOK_COUNT /* Count of tokens */ } token_t; /* Complete token including attributes and flags */ typedef struct Token Token; struct Token { token_t Tok; /* The actual token value */ int WS; /* Flag for "whitespace before token" */ long IVal; /* Integer attribute value */ StrBuf SVal; /* String attribute value */ FilePos Pos; /* Position from which token was read */ }; /* Initializer value for a token */ #define STATIC_TOKEN_INITIALIZER { \ TOK_NONE, \ 0, \ 0, \ STATIC_STRBUF_INITIALIZER, \ STATIC_FILEPOS_INITIALIZER \ } /*****************************************************************************/ /* Code */ /*****************************************************************************/ int TokHasSVal (token_t Tok); /* Return true if the given token has an attached SVal */ int TokHasIVal (token_t Tok); /* Return true if the given token has an attached IVal */ #if defined(HAVE_INLINE) INLINE int TokIsSep (enum token_t T) /* Return true if this is a separator token */ { return (T == TOK_SEP || T == TOK_EOF); } #else # define TokIsSep(T) ((T) == TOK_SEP || (T) == TOK_EOF) #endif void CopyToken (Token* Dst, const Token* Src); /* Copy a token. The current value of Dst.SVal is free'd, so Dst must be ** initialized. */ /* End of token.h */ #endif ���������������������������������������������������������������cc65-2.18/src/ca65/toklist.c������������������������������������������������������������������������0000664�0000000�0000000�00000017613�13473601511�0015377�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* toklist.c */ /* */ /* Token list for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* common */ #include "check.h" #include "xmalloc.h" /* ca65 */ #include "error.h" #include "istack.h" #include "lineinfo.h" #include "nexttok.h" #include "scanner.h" #include "toklist.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Number of currently pushed token lists */ static unsigned PushCounter = 0; /*****************************************************************************/ /* Code */ /*****************************************************************************/ TokNode* NewTokNode (void) /* Create and return a token node with the current token value */ { /* Allocate memory */ TokNode* N = xmalloc (sizeof (TokNode)); /* Initialize the token contents */ N->Next = 0; SB_Init (&N->T.SVal); CopyToken (&N->T, &CurTok); /* Return the node */ return N; } void FreeTokNode (TokNode* N) /* Free the given token node */ { SB_Done (&N->T.SVal); xfree (N); } void TokSet (TokNode* N) /* Set the scanner token from the given token node. */ { /* Set the values */ CopyToken (&CurTok, &N->T); SB_Terminate (&CurTok.SVal); } enum TC TokCmp (const TokNode* N) /* Compare the token given as parameter against the current token */ { if (N->T.Tok != CurTok.Tok) { /* Different token */ return tcDifferent; } /* If the token has string attribute, check it */ if (TokHasSVal (N->T.Tok)) { if (SB_Compare (&CurTok.SVal, &N->T.SVal) != 0) { return tcSameToken; } } else if (TokHasIVal (N->T.Tok)) { if (N->T.IVal != CurTok.IVal) { return tcSameToken; } } /* Tokens are identical */ return tcIdentical; } TokList* NewTokList (void) /* Create a new, empty token list */ { /* Allocate memory for the list structure */ TokList* T = xmalloc (sizeof (TokList)); /* Initialize the fields */ T->Next = 0; T->Root = 0; T->Last = 0; T->RepCount = 0; T->RepMax = 1; T->Count = 0; T->Check = 0; T->Data = 0; T->LI = 0; /* Return the new list */ return T; } void FreeTokList (TokList* List) /* Delete the token list including all token nodes */ { /* Free the token list */ TokNode* T = List->Root; while (T) { TokNode* Tmp = T; T = T->Next; FreeTokNode (Tmp); } /* Free associated line info */ if (List->LI) { EndLine (List->LI); } /* If we have associated data, free it */ if (List->Data) { xfree (List->Data); } /* Free the list structure itself */ xfree (List); } enum token_t GetTokListTerm (enum token_t Term) /* Determine if the following token list is enclosed in curly braces. This is ** the case if the next token is the opening brace. If so, skip it and return ** a closing brace, otherwise return Term. */ { if (CurTok.Tok == TOK_LCURLY) { NextTok (); return TOK_RCURLY; } else { return Term; } } void AddCurTok (TokList* List) /* Add the current token to the token list */ { /* Create a token node with the current token value */ TokNode* T = NewTokNode (); /* Insert the node into the list */ if (List->Root == 0) { List->Root = T; } else { List->Last->Next = T; } List->Last = T; /* Count nodes */ List->Count++; } static int ReplayTokList (void* List) /* Function that gets the next token from a token list and sets it. This ** function may be used together with the PushInput function from the istack ** module. */ { /* Cast the generic pointer to an actual list */ TokList* L = List; /* If there are no more tokens, decrement the repeat counter. If it goes ** zero, delete the list and remove the function from the stack. */ if (L->Last == 0) { if (++L->RepCount >= L->RepMax) { /* Done with this list */ FreeTokList (L); --PushCounter; PopInput (); return 0; } else { /* Replay one more time */ L->Last = L->Root; } } /* Set the next token from the list */ TokSet (L->Last); /* Set the line info for the new token */ if (L->LI) { EndLine (L->LI); } L->LI = StartLine (&CurTok.Pos, LI_TYPE_ASM, PushCounter); /* If a check function is defined, call it, so it may look at the token ** just set and changed it as apropriate. */ if (L->Check) { L->Check (L); } /* Set the pointer to the next token */ L->Last = L->Last->Next; /* We have a token */ return 1; } void PushTokList (TokList* List, const char* Desc) /* Push a token list to be used as input for InputFromStack. This includes ** several initializations needed in the token list structure, so don't use ** PushInput directly. */ { /* If the list is empty, just delete it and bail out */ if (List->Count == 0) { FreeTokList (List); return; } /* Reset the last pointer to the first element */ List->Last = List->Root; /* Insert the list specifying our input function */ ++PushCounter; PushInput (ReplayTokList, List, Desc); } ���������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/toklist.h������������������������������������������������������������������������0000664�0000000�0000000�00000012573�13473601511�0015404�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* toklist.h */ /* */ /* Token list for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 2000-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef TOKLIST_H #define TOKLIST_H /* common */ #include "strbuf.h" /* ca65 */ #include "lineinfo.h" #include "scanner.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Struct holding a token */ typedef struct TokNode TokNode; struct TokNode { TokNode* Next; /* For single linked list */ Token T; /* Token value */ }; /* Struct holding a token list */ typedef struct TokList TokList; struct TokList { TokList* Next; /* Single linked list (for replay) */ TokNode* Root; /* First node in list */ TokNode* Last; /* Last node in list or replay */ unsigned RepCount; /* Repeat counter (used for replay) */ unsigned RepMax; /* Maximum repeat count for replay */ unsigned Count; /* Token count */ void (*Check)(TokList*); /* Token check function */ void* Data; /* Additional data for check */ LineInfo* LI; /* Line info for replay */ }; /* Return codes for TokCmp - higher numeric code means better match */ enum TC { tcDifferent, /* Different tokents */ tcSameToken, /* Same token, different attribute */ tcIdentical /* Identical (token + attribute) */ }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ TokNode* NewTokNode (void); /* Create and return a token node with the current token value */ void FreeTokNode (TokNode* N); /* Free the given token node */ void TokSet (TokNode* N); /* Set the scanner token from the given token node. */ enum TC TokCmp (const TokNode* N); /* Compare the token given as parameter against the current token */ TokList* NewTokList (void); /* Create a new, empty token list */ void FreeTokList (TokList* T); /* Delete the token list including all token nodes */ token_t GetTokListTerm (token_t Term); /* Determine if the following token list is enclosed in curly braces. This is ** the case if the next token is the opening brace. If so, skip it and return ** a closing brace, otherwise return Term. */ void AddCurTok (TokList* T); /* Add the current token to the token list */ void PushTokList (TokList* List, const char* Desc); /* Push a token list to be used as input for InputFromStack. This includes ** several initializations needed in the token list structure, so don't use ** PushInput directly. */ /* End of toklist.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/ulabel.c�������������������������������������������������������������������������0000664�0000000�0000000�00000017176�13473601511�0015156�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* ulabel.c */ /* */ /* Unnamed labels for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 2000-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "check.h" #include "coll.h" #include "xmalloc.h" /* ca65 */ #include "error.h" #include "expr.h" #include "lineinfo.h" #include "scanner.h" #include "ulabel.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Struct that describes an unnamed label */ typedef struct ULabel ULabel; struct ULabel { Collection LineInfos; /* Position of the label in the source */ ExprNode* Val; /* The label value - may be NULL */ unsigned Ref; /* Number of references */ }; /* List management */ static Collection ULabList = STATIC_COLLECTION_INITIALIZER; static unsigned ULabDefCount = 0; /* Number of defined labels */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ static ULabel* NewULabel (ExprNode* Val) /* Create a new ULabel and insert it into the collection. The created label ** structure is returned. */ { /* Allocate memory for the ULabel structure */ ULabel* L = xmalloc (sizeof (ULabel)); /* Initialize the fields */ L->LineInfos = EmptyCollection; GetFullLineInfo (&L->LineInfos); L->Val = Val; L->Ref = 0; /* Insert the label into the collection */ CollAppend (&ULabList, L); /* Return the created label */ return L; } ExprNode* ULabRef (int Which) /* Get an unnamed label. If Which is negative, it is a backreference (a ** reference to an already defined label), and the function will return a ** segment relative expression. If Which is positive, it is a forward ref, ** and the function will return a expression node for an unnamed label that ** must be resolved later. */ { int Index; ULabel* L; /* Which can never be 0 */ PRECONDITION (Which != 0); /* Get the index of the referenced label */ if (Which > 0) { --Which; } Index = (int) ULabDefCount + Which; /* We cannot have negative label indices */ if (Index < 0) { /* Label does not exist */ Error ("Undefined label"); /* We must return something valid */ return GenCurrentPC(); } /* Check if the label exists. If not, generate enough forward labels. */ if (Index < (int) CollCount (&ULabList)) { /* The label exists, get it. */ L = CollAtUnchecked (&ULabList, Index); } else { /* Generate new, undefined labels */ while (Index >= (int) CollCount (&ULabList)) { L = NewULabel (0); } } /* Mark the label as referenced */ ++L->Ref; /* If the label is already defined, return its value, otherwise return ** just a reference. */ if (L->Val) { return CloneExpr (L->Val); } else { return GenULabelExpr (Index); } } void ULabDef (void) /* Define an unnamed label at the current PC */ { if (ULabDefCount < CollCount (&ULabList)) { /* We did already have a forward reference to this label, so has ** already been generated, but doesn't have a value. Use the current ** PC for the label value. */ ULabel* L = CollAtUnchecked (&ULabList, ULabDefCount); CHECK (L->Val == 0); L->Val = GenCurrentPC (); ReleaseFullLineInfo (&L->LineInfos); GetFullLineInfo (&L->LineInfos); } else { /* There is no such label, create it */ NewULabel (GenCurrentPC ()); } /* We have one more defined label */ ++ULabDefCount; } int ULabCanResolve (void) /* Return true if we can resolve arbitrary ULabels. */ { /* We can resolve labels if we don't have any undefineds */ return (ULabDefCount == CollCount (&ULabList)); } ExprNode* ULabResolve (unsigned Index) /* Return a valid expression for the unnamed label with the given index. This ** is used to resolve unnamed labels when assembly is done, so it is an error ** if a label is still undefined in this phase. */ { /* Get the label and check that it is defined */ ULabel* L = CollAt (&ULabList, Index); CHECK (L->Val != 0); /* Return the label value */ return CloneExpr (L->Val); } void ULabDone (void) /* Run through all unnamed labels, check for anomalies and errors and do ** necessary cleanups. */ { /* Check if there are undefined labels */ unsigned I = ULabDefCount; while (I < CollCount (&ULabList)) { ULabel* L = CollAtUnchecked (&ULabList, I); LIError (&L->LineInfos, "Undefined label"); ++I; } /* Walk over all labels and emit a warning if any unreferenced ones ** are found. Remove line infos because they're no longer needed. */ for (I = 0; I < CollCount (&ULabList); ++I) { ULabel* L = CollAtUnchecked (&ULabList, I); if (L->Ref == 0) { LIWarning (&L->LineInfos, 1, "No reference to unnamed label"); } ReleaseFullLineInfo (&L->LineInfos); } } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ca65/ulabel.h�������������������������������������������������������������������������0000664�0000000�0000000�00000007255�13473601511�0015160�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* ulabel.h */ /* */ /* Unnamed labels for the ca65 macroassembler */ /* */ /* */ /* */ /* (C) 2000-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef ULABEL_H #define ULABEL_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ ExprNode* ULabRef (int Which); /* Get an unnamed label. If Which is negative, it is a backreference (a ** reference to an already defined label), and the function will return a ** segment relative expression. If Which is positive, it is a forward ref, ** and the function will return a expression node for an unnamed label that ** must be resolved later. */ void ULabDef (void); /* Define an unnamed label at the current PC */ int ULabCanResolve (void); /* Return true if we can resolve arbitrary ULabels. */ ExprNode* ULabResolve (unsigned Index); /* Return a valid expression for the unnamed label with the given index. This ** is used to resolve unnamed labels when assembly is done, so it is an error ** if a label is still undefined in this phase. */ void ULabDone (void); /* Run through all unnamed labels, check for anomalies and errors and do ** necessary cleanups. */ /* End of ulabel.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65.sln������������������������������������������������������������������������������0000664�0000000�0000000�00000017453�13473601511�0014264�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ Microsoft Visual Studio Solution File, Format Version 11.00 # Visual C++ Express 2010 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "common.vcxproj", "{71DC1F68-BFC4-478C-8655-C8E9C9654D2B}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cc65", "cc65.vcxproj", "{B17EDBD5-DC04-4970-9CBD-56A98B6A3FCA}" ProjectSection(ProjectDependencies) = postProject {71DC1F68-BFC4-478C-8655-C8E9C9654D2B} = {71DC1F68-BFC4-478C-8655-C8E9C9654D2B} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ca65", "ca65.vcxproj", "{D28CB737-E6CA-49C4-8CE9-FF05F86DD4EC}" ProjectSection(ProjectDependencies) = postProject {71DC1F68-BFC4-478C-8655-C8E9C9654D2B} = {71DC1F68-BFC4-478C-8655-C8E9C9654D2B} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ar65", "ar65.vcxproj", "{5E8C19C6-B167-440C-8BEF-3CBF109CDB49}" ProjectSection(ProjectDependencies) = postProject {71DC1F68-BFC4-478C-8655-C8E9C9654D2B} = {71DC1F68-BFC4-478C-8655-C8E9C9654D2B} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ld65", "ld65.vcxproj", "{26C749A0-814C-47A2-9D36-AE92AE932FE4}" ProjectSection(ProjectDependencies) = postProject {71DC1F68-BFC4-478C-8655-C8E9C9654D2B} = {71DC1F68-BFC4-478C-8655-C8E9C9654D2B} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cl65", "cl65.vcxproj", "{F657912F-050A-488B-B203-50ED5715CDD7}" ProjectSection(ProjectDependencies) = postProject {71DC1F68-BFC4-478C-8655-C8E9C9654D2B} = {71DC1F68-BFC4-478C-8655-C8E9C9654D2B} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "da65", "da65.vcxproj", "{0BCFB793-2B25-40E2-B265-75848824AC4C}" ProjectSection(ProjectDependencies) = postProject {71DC1F68-BFC4-478C-8655-C8E9C9654D2B} = {71DC1F68-BFC4-478C-8655-C8E9C9654D2B} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "co65", "co65.vcxproj", "{F5DB5D1A-05BC-48FE-B346-4E96DD522AA2}" ProjectSection(ProjectDependencies) = postProject {71DC1F68-BFC4-478C-8655-C8E9C9654D2B} = {71DC1F68-BFC4-478C-8655-C8E9C9654D2B} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grc65", "grc65.vcxproj", "{E0FD0AB3-3BEE-496F-8108-A8E0F8933F39}" ProjectSection(ProjectDependencies) = postProject {71DC1F68-BFC4-478C-8655-C8E9C9654D2B} = {71DC1F68-BFC4-478C-8655-C8E9C9654D2B} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "od65", "od65.vcxproj", "{FF8576C2-1253-44FE-A51B-D9AE35F3CEAD}" ProjectSection(ProjectDependencies) = postProject {71DC1F68-BFC4-478C-8655-C8E9C9654D2B} = {71DC1F68-BFC4-478C-8655-C8E9C9654D2B} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sp65", "sp65.vcxproj", "{4388D1AF-C7EA-4AD4-8E80-CA1FB7BF76BF}" ProjectSection(ProjectDependencies) = postProject {71DC1F68-BFC4-478C-8655-C8E9C9654D2B} = {71DC1F68-BFC4-478C-8655-C8E9C9654D2B} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sim65", "sim65.vcxproj", "{002A366E-2863-46A8-BDDE-DDF534AAEC73}" ProjectSection(ProjectDependencies) = postProject {71DC1F68-BFC4-478C-8655-C8E9C9654D2B} = {71DC1F68-BFC4-478C-8655-C8E9C9654D2B} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "chrcvt65", "chrcvt65.vcxproj", "{1C7A3FEF-DD0B-4B10-BC33-C3BE29BF67CC}" ProjectSection(ProjectDependencies) = postProject {71DC1F68-BFC4-478C-8655-C8E9C9654D2B} = {71DC1F68-BFC4-478C-8655-C8E9C9654D2B} EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {71DC1F68-BFC4-478C-8655-C8E9C9654D2B}.Debug|Win32.ActiveCfg = Debug|Win32 {71DC1F68-BFC4-478C-8655-C8E9C9654D2B}.Debug|Win32.Build.0 = Debug|Win32 {71DC1F68-BFC4-478C-8655-C8E9C9654D2B}.Release|Win32.ActiveCfg = Release|Win32 {71DC1F68-BFC4-478C-8655-C8E9C9654D2B}.Release|Win32.Build.0 = Release|Win32 {B17EDBD5-DC04-4970-9CBD-56A98B6A3FCA}.Debug|Win32.ActiveCfg = Debug|Win32 {B17EDBD5-DC04-4970-9CBD-56A98B6A3FCA}.Debug|Win32.Build.0 = Debug|Win32 {B17EDBD5-DC04-4970-9CBD-56A98B6A3FCA}.Release|Win32.ActiveCfg = Release|Win32 {B17EDBD5-DC04-4970-9CBD-56A98B6A3FCA}.Release|Win32.Build.0 = Release|Win32 {D28CB737-E6CA-49C4-8CE9-FF05F86DD4EC}.Debug|Win32.ActiveCfg = Debug|Win32 {D28CB737-E6CA-49C4-8CE9-FF05F86DD4EC}.Debug|Win32.Build.0 = Debug|Win32 {D28CB737-E6CA-49C4-8CE9-FF05F86DD4EC}.Release|Win32.ActiveCfg = Release|Win32 {D28CB737-E6CA-49C4-8CE9-FF05F86DD4EC}.Release|Win32.Build.0 = Release|Win32 {5E8C19C6-B167-440C-8BEF-3CBF109CDB49}.Debug|Win32.ActiveCfg = Debug|Win32 {5E8C19C6-B167-440C-8BEF-3CBF109CDB49}.Debug|Win32.Build.0 = Debug|Win32 {5E8C19C6-B167-440C-8BEF-3CBF109CDB49}.Release|Win32.ActiveCfg = Release|Win32 {5E8C19C6-B167-440C-8BEF-3CBF109CDB49}.Release|Win32.Build.0 = Release|Win32 {26C749A0-814C-47A2-9D36-AE92AE932FE4}.Debug|Win32.ActiveCfg = Debug|Win32 {26C749A0-814C-47A2-9D36-AE92AE932FE4}.Debug|Win32.Build.0 = Debug|Win32 {26C749A0-814C-47A2-9D36-AE92AE932FE4}.Release|Win32.ActiveCfg = Release|Win32 {26C749A0-814C-47A2-9D36-AE92AE932FE4}.Release|Win32.Build.0 = Release|Win32 {F657912F-050A-488B-B203-50ED5715CDD7}.Debug|Win32.ActiveCfg = Debug|Win32 {F657912F-050A-488B-B203-50ED5715CDD7}.Debug|Win32.Build.0 = Debug|Win32 {F657912F-050A-488B-B203-50ED5715CDD7}.Release|Win32.ActiveCfg = Release|Win32 {F657912F-050A-488B-B203-50ED5715CDD7}.Release|Win32.Build.0 = Release|Win32 {0BCFB793-2B25-40E2-B265-75848824AC4C}.Debug|Win32.ActiveCfg = Debug|Win32 {0BCFB793-2B25-40E2-B265-75848824AC4C}.Debug|Win32.Build.0 = Debug|Win32 {0BCFB793-2B25-40E2-B265-75848824AC4C}.Release|Win32.ActiveCfg = Release|Win32 {0BCFB793-2B25-40E2-B265-75848824AC4C}.Release|Win32.Build.0 = Release|Win32 {F5DB5D1A-05BC-48FE-B346-4E96DD522AA2}.Debug|Win32.ActiveCfg = Debug|Win32 {F5DB5D1A-05BC-48FE-B346-4E96DD522AA2}.Debug|Win32.Build.0 = Debug|Win32 {F5DB5D1A-05BC-48FE-B346-4E96DD522AA2}.Release|Win32.ActiveCfg = Release|Win32 {F5DB5D1A-05BC-48FE-B346-4E96DD522AA2}.Release|Win32.Build.0 = Release|Win32 {E0FD0AB3-3BEE-496F-8108-A8E0F8933F39}.Debug|Win32.ActiveCfg = Debug|Win32 {E0FD0AB3-3BEE-496F-8108-A8E0F8933F39}.Debug|Win32.Build.0 = Debug|Win32 {E0FD0AB3-3BEE-496F-8108-A8E0F8933F39}.Release|Win32.ActiveCfg = Release|Win32 {E0FD0AB3-3BEE-496F-8108-A8E0F8933F39}.Release|Win32.Build.0 = Release|Win32 {FF8576C2-1253-44FE-A51B-D9AE35F3CEAD}.Debug|Win32.ActiveCfg = Debug|Win32 {FF8576C2-1253-44FE-A51B-D9AE35F3CEAD}.Debug|Win32.Build.0 = Debug|Win32 {FF8576C2-1253-44FE-A51B-D9AE35F3CEAD}.Release|Win32.ActiveCfg = Release|Win32 {FF8576C2-1253-44FE-A51B-D9AE35F3CEAD}.Release|Win32.Build.0 = Release|Win32 {4388D1AF-C7EA-4AD4-8E80-CA1FB7BF76BF}.Debug|Win32.ActiveCfg = Debug|Win32 {4388D1AF-C7EA-4AD4-8E80-CA1FB7BF76BF}.Debug|Win32.Build.0 = Debug|Win32 {4388D1AF-C7EA-4AD4-8E80-CA1FB7BF76BF}.Release|Win32.ActiveCfg = Release|Win32 {4388D1AF-C7EA-4AD4-8E80-CA1FB7BF76BF}.Release|Win32.Build.0 = Release|Win32 {002A366E-2863-46A8-BDDE-DDF534AAEC73}.Debug|Win32.ActiveCfg = Debug|Win32 {002A366E-2863-46A8-BDDE-DDF534AAEC73}.Debug|Win32.Build.0 = Debug|Win32 {002A366E-2863-46A8-BDDE-DDF534AAEC73}.Release|Win32.ActiveCfg = Release|Win32 {002A366E-2863-46A8-BDDE-DDF534AAEC73}.Release|Win32.Build.0 = Release|Win32 {1C7A3FEF-DD0B-4B10-BC33-C3BE29BF67CC}.Debug|Win32.ActiveCfg = Debug|Win32 {1C7A3FEF-DD0B-4B10-BC33-C3BE29BF67CC}.Debug|Win32.Build.0 = Debug|Win32 {1C7A3FEF-DD0B-4B10-BC33-C3BE29BF67CC}.Release|Win32.ActiveCfg = Release|Win32 {1C7A3FEF-DD0B-4B10-BC33-C3BE29BF67CC}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65.vcxproj��������������������������������������������������������������������������0000664�0000000�0000000�00000024206�13473601511�0015155�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> <ProjectConfiguration Include="Release|Win32"> <Configuration>Release</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> </ItemGroup> <PropertyGroup Label="Globals"> <ProjectGuid>{B17EDBD5-DC04-4970-9CBD-56A98B6A3FCA}</ProjectGuid> <Keyword>Win32Proj</Keyword> <RootNamespace>cc65</RootNamespace> <WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <UseDebugLibraries>true</UseDebugLibraries> <PlatformToolset>v141</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <UseDebugLibraries>false</UseDebugLibraries> <WholeProgramOptimization>true</WholeProgramOptimization> <PlatformToolset>v141</PlatformToolset> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <PropertyGroup Label="UserMacros" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <IntDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</IntDir> <OutDir>$(SolutionDir)..\bin\</OutDir> <LinkIncremental>true</LinkIncremental> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <IntDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</IntDir> <OutDir>$(SolutionDir)..\bin\</OutDir> </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ClCompile> <PrecompiledHeader> </PrecompiledHeader> <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <WarningLevel>Level3</WarningLevel> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> <Link> <SubSystem>Console</SubSystem> <GenerateDebugInformation>true</GenerateDebugInformation> <AdditionalDependencies>$(IntDir)..\..\common\$(Configuration)\common.lib</AdditionalDependencies> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ClCompile> <WarningLevel>Level3</WarningLevel> <PrecompiledHeader> </PrecompiledHeader> <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> <Link> <SubSystem>Console</SubSystem> <GenerateDebugInformation>false</GenerateDebugInformation> <AdditionalDependencies>$(IntDir)..\..\common\$(Configuration)\common.lib</AdditionalDependencies> </Link> </ItemDefinitionGroup> <ItemGroup> <ClInclude Include="cc65\anonname.h" /> <ClInclude Include="cc65\asmcode.h" /> <ClInclude Include="cc65\asmlabel.h" /> <ClInclude Include="cc65\asmstmt.h" /> <ClInclude Include="cc65\assignment.h" /> <ClInclude Include="cc65\casenode.h" /> <ClInclude Include="cc65\codeent.h" /> <ClInclude Include="cc65\codegen.h" /> <ClInclude Include="cc65\codeinfo.h" /> <ClInclude Include="cc65\codelab.h" /> <ClInclude Include="cc65\codeopt.h" /> <ClInclude Include="cc65\codeseg.h" /> <ClInclude Include="cc65\compile.h" /> <ClInclude Include="cc65\coptadd.h" /> <ClInclude Include="cc65\coptc02.h" /> <ClInclude Include="cc65\coptcmp.h" /> <ClInclude Include="cc65\coptind.h" /> <ClInclude Include="cc65\coptneg.h" /> <ClInclude Include="cc65\coptptrload.h" /> <ClInclude Include="cc65\coptptrstore.h" /> <ClInclude Include="cc65\coptpush.h" /> <ClInclude Include="cc65\coptshift.h" /> <ClInclude Include="cc65\coptsize.h" /> <ClInclude Include="cc65\coptstop.h" /> <ClInclude Include="cc65\coptstore.h" /> <ClInclude Include="cc65\coptsub.h" /> <ClInclude Include="cc65\copttest.h" /> <ClInclude Include="cc65\dataseg.h" /> <ClInclude Include="cc65\datatype.h" /> <ClInclude Include="cc65\declare.h" /> <ClInclude Include="cc65\declattr.h" /> <ClInclude Include="cc65\error.h" /> <ClInclude Include="cc65\expr.h" /> <ClInclude Include="cc65\exprdesc.h" /> <ClInclude Include="cc65\funcdesc.h" /> <ClInclude Include="cc65\function.h" /> <ClInclude Include="cc65\global.h" /> <ClInclude Include="cc65\goto.h" /> <ClInclude Include="cc65\hexval.h" /> <ClInclude Include="cc65\ident.h" /> <ClInclude Include="cc65\incpath.h" /> <ClInclude Include="cc65\input.h" /> <ClInclude Include="cc65\lineinfo.h" /> <ClInclude Include="cc65\litpool.h" /> <ClInclude Include="cc65\loadexpr.h" /> <ClInclude Include="cc65\locals.h" /> <ClInclude Include="cc65\loop.h" /> <ClInclude Include="cc65\macrotab.h" /> <ClInclude Include="cc65\opcodes.h" /> <ClInclude Include="cc65\output.h" /> <ClInclude Include="cc65\pragma.h" /> <ClInclude Include="cc65\preproc.h" /> <ClInclude Include="cc65\reginfo.h" /> <ClInclude Include="cc65\scanner.h" /> <ClInclude Include="cc65\scanstrbuf.h" /> <ClInclude Include="cc65\segments.h" /> <ClInclude Include="cc65\shiftexpr.h" /> <ClInclude Include="cc65\stackptr.h" /> <ClInclude Include="cc65\standard.h" /> <ClInclude Include="cc65\stdfunc.h" /> <ClInclude Include="cc65\stdnames.h" /> <ClInclude Include="cc65\stmt.h" /> <ClInclude Include="cc65\swstmt.h" /> <ClInclude Include="cc65\symentry.h" /> <ClInclude Include="cc65\symtab.h" /> <ClInclude Include="cc65\testexpr.h" /> <ClInclude Include="cc65\textseg.h" /> <ClInclude Include="cc65\typecmp.h" /> <ClInclude Include="cc65\typeconv.h" /> <ClInclude Include="cc65\util.h" /> <ClInclude Include="cc65\wrappedcall.h" /> </ItemGroup> <ItemGroup> <ClCompile Include="cc65\anonname.c" /> <ClCompile Include="cc65\asmcode.c" /> <ClCompile Include="cc65\asmlabel.c" /> <ClCompile Include="cc65\asmstmt.c" /> <ClCompile Include="cc65\assignment.c" /> <ClCompile Include="cc65\casenode.c" /> <ClCompile Include="cc65\codeent.c" /> <ClCompile Include="cc65\codegen.c" /> <ClCompile Include="cc65\codeinfo.c" /> <ClCompile Include="cc65\codelab.c" /> <ClCompile Include="cc65\codeopt.c" /> <ClCompile Include="cc65\codeseg.c" /> <ClCompile Include="cc65\compile.c" /> <ClCompile Include="cc65\coptadd.c" /> <ClCompile Include="cc65\coptc02.c" /> <ClCompile Include="cc65\coptcmp.c" /> <ClCompile Include="cc65\coptind.c" /> <ClCompile Include="cc65\coptneg.c" /> <ClCompile Include="cc65\coptptrload.c" /> <ClCompile Include="cc65\coptptrstore.c" /> <ClCompile Include="cc65\coptpush.c" /> <ClCompile Include="cc65\coptshift.c" /> <ClCompile Include="cc65\coptsize.c" /> <ClCompile Include="cc65\coptstop.c" /> <ClCompile Include="cc65\coptstore.c" /> <ClCompile Include="cc65\coptsub.c" /> <ClCompile Include="cc65\copttest.c" /> <ClCompile Include="cc65\dataseg.c" /> <ClCompile Include="cc65\datatype.c" /> <ClCompile Include="cc65\declare.c" /> <ClCompile Include="cc65\declattr.c" /> <ClCompile Include="cc65\error.c" /> <ClCompile Include="cc65\expr.c" /> <ClCompile Include="cc65\exprdesc.c" /> <ClCompile Include="cc65\funcdesc.c" /> <ClCompile Include="cc65\function.c" /> <ClCompile Include="cc65\global.c" /> <ClCompile Include="cc65\goto.c" /> <ClCompile Include="cc65\hexval.c" /> <ClCompile Include="cc65\ident.c" /> <ClCompile Include="cc65\incpath.c" /> <ClCompile Include="cc65\input.c" /> <ClCompile Include="cc65\lineinfo.c" /> <ClCompile Include="cc65\litpool.c" /> <ClCompile Include="cc65\loadexpr.c" /> <ClCompile Include="cc65\locals.c" /> <ClCompile Include="cc65\loop.c" /> <ClCompile Include="cc65\macrotab.c" /> <ClCompile Include="cc65\main.c" /> <ClCompile Include="cc65\opcodes.c" /> <ClCompile Include="cc65\output.c" /> <ClCompile Include="cc65\pragma.c" /> <ClCompile Include="cc65\preproc.c" /> <ClCompile Include="cc65\reginfo.c" /> <ClCompile Include="cc65\scanner.c" /> <ClCompile Include="cc65\scanstrbuf.c" /> <ClCompile Include="cc65\segments.c" /> <ClCompile Include="cc65\shiftexpr.c" /> <ClCompile Include="cc65\stackptr.c" /> <ClCompile Include="cc65\standard.c" /> <ClCompile Include="cc65\stdfunc.c" /> <ClCompile Include="cc65\stdnames.c" /> <ClCompile Include="cc65\stmt.c" /> <ClCompile Include="cc65\swstmt.c" /> <ClCompile Include="cc65\symentry.c" /> <ClCompile Include="cc65\symtab.c" /> <ClCompile Include="cc65\testexpr.c" /> <ClCompile Include="cc65\textseg.c" /> <ClCompile Include="cc65\typecmp.c" /> <ClCompile Include="cc65\typeconv.c" /> <ClCompile Include="cc65\util.c" /> <ClCompile Include="cc65\wrappedcall.c" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> </Project>������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/���������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0013534�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/.lclintrc������������������������������������������������������������������������0000664�0000000�0000000�00000000066�13473601511�0015351�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������+boolint -boolops -retvalint -retvalother -I../common ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/anonname.c�����������������������������������������������������������������������0000664�0000000�0000000�00000007205�13473601511�0015500�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* anonname.c */ /* */ /* Create names for anonymous variables/types */ /* */ /* */ /* */ /* (C) 2000-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> /* common */ #include "xsprintf.h" /* cc65 */ #include "anonname.h" #include "ident.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ static const char AnonTag[] = "$anon"; /*****************************************************************************/ /* Code */ /*****************************************************************************/ char* AnonName (char* Buf, const char* Spec) /* Get a name for an anonymous variable or type. The given buffer is expected ** to be IDENTSIZE characters long. A pointer to the buffer is returned. */ { static unsigned ACount = 0; xsprintf (Buf, IDENTSIZE, "%s-%s-%04X", AnonTag, Spec, ++ACount); return Buf; } int IsAnonName (const char* Name) /* Check if the given symbol name is that of an anonymous symbol */ { return (strncmp (Name, AnonTag, sizeof (AnonTag) - 1) == 0); } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/anonname.h�����������������������������������������������������������������������0000664�0000000�0000000�00000006162�13473601511�0015506�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* anonname.h */ /* */ /* Create names for anonymous variables/types */ /* */ /* */ /* */ /* (C) 2000 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef ANONNAME_H #define ANONNAME_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ char* AnonName (char* Buf, const char* Spec); /* Get a name for an anonymous variable or type. The given buffer is expected ** to be IDENTSIZE characters long. A pointer to the buffer is returned. */ int IsAnonName (const char* Name); /* Check if the given symbol name is that of an anonymous symbol */ /* End of anonname.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/asmcode.c������������������������������������������������������������������������0000664�0000000�0000000�00000011313�13473601511�0015312�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* asmcode.c */ /* */ /* Assembler output code handling for the cc65 C compiler */ /* */ /* */ /* */ /* (C) 2000-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "check.h" /* cc65 */ #include "asmcode.h" #include "codeseg.h" #include "dataseg.h" #include "segments.h" #include "stackptr.h" #include "symtab.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void GetCodePos (CodeMark* M) /* Get a marker pointing to the current output position */ { M->Pos = CS_GetEntryCount (CS->Code); M->SP = StackPtr; } void RemoveCodeRange (const CodeMark* Start, const CodeMark* End) /* Remove all code between two code markers */ { /* Nothing to do if the range is empty */ if (Start->Pos == End->Pos) { return; } /* Delete the range */ CS_DelCodeRange (CS->Code, Start->Pos, End->Pos-1); } void RemoveCode (const CodeMark* M) /* Remove all code after the given code marker */ { CS_DelCodeAfter (CS->Code, M->Pos); StackPtr = M->SP; } void MoveCode (const CodeMark* Start, const CodeMark* End, const CodeMark* Target) /* Move the code between Start (inclusive) and End (exclusive) to ** (before) Target. The code marks aren't updated. */ { CS_MoveEntries (CS->Code, Start->Pos, End->Pos - Start->Pos, Target->Pos); } int CodeRangeIsEmpty (const CodeMark* Start, const CodeMark* End) /* Return true if the given code range is empty (no code between Start and End) */ { int Empty; PRECONDITION (Start->Pos <= End->Pos); Empty = (Start->Pos == End->Pos); if (Empty) { /* Safety */ CHECK (Start->SP == End->SP); } return Empty; } void WriteAsmOutput (void) /* Write the final assembler output to the output file */ { SymTable* SymTab; SymEntry* Entry; /* Output the global data segment */ CHECK (!HaveGlobalCode ()); OutputSegments (CS); /* Output all global or referenced functions */ SymTab = GetGlobalSymTab (); Entry = SymTab->SymHead; while (Entry) { if (SymIsOutputFunc (Entry)) { /* Function which is defined and referenced or extern */ OutputSegments (Entry->V.F.Seg); } Entry = Entry->NextSym; } } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/asmcode.h������������������������������������������������������������������������0000664�0000000�0000000�00000010017�13473601511�0015317�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* asmcode.h */ /* */ /* Assembler output code handling for the cc65 C compiler */ /* */ /* */ /* */ /* (C) 2000-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef ASMCODE_H #define ASMCODE_H #include <stdio.h> /* common */ #include "attrib.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Marker for an assembler code position */ typedef struct { unsigned Pos; /* Code position */ int SP; /* Stack pointer at this position */ } CodeMark; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void GetCodePos (CodeMark* M); /* Get a marker pointing to the current output position */ void RemoveCodeRange (const CodeMark* Start, const CodeMark* End); /* Remove all code between two code markers */ void RemoveCode (const CodeMark* M); /* Remove all code after the given code marker */ void MoveCode (const CodeMark* Start, const CodeMark* End, const CodeMark* Target); /* Move the code between Start (inclusive) and End (exclusive) to ** (before) Target. The code marks aren't updated. */ int CodeRangeIsEmpty (const CodeMark* Start, const CodeMark* End); /* Return true if the given code range is empty (no code between Start and End) */ void WriteAsmOutput (void); /* Write the final assembler output to the output file */ /* End of asmcode.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/asmlabel.c�����������������������������������������������������������������������0000664�0000000�0000000�00000007453�13473601511�0015471�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* asmlabel.c */ /* */ /* Generate assembler code labels */ /* */ /* */ /* */ /* (C) 2000-2009 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> /* common */ #include "chartype.h" /* cc65 */ #include "asmlabel.h" #include "error.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned GetLocalLabel (void) /* Get an unused label. Will never return zero. */ { /* Number to generate unique labels */ static unsigned NextLabel = 0; /* Check for an overflow */ if (NextLabel >= 0xFFFF) { Internal ("Local label overflow"); } /* Return the next label */ return ++NextLabel; } const char* LocalLabelName (unsigned L) /* Make a label name from the given label number. The label name will be ** created in static storage and overwritten when calling the function ** again. */ { static char Buf[64]; sprintf (Buf, "L%04X", L); return Buf; } int IsLocalLabelName (const char* Name) /* Return true if Name is the name of a local label */ { unsigned I; if (Name[0] != 'L' || strlen (Name) != 5) { return 0; } for (I = 1; I <= 4; ++I) { if (!IsXDigit (Name[I])) { return 0; } } /* Local label name */ return 1; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/asmlabel.h�����������������������������������������������������������������������0000664�0000000�0000000�00000006306�13473601511�0015472�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* asmlabel.h */ /* */ /* Generate assembler code labels */ /* */ /* */ /* */ /* (C) 2000-2009 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef ASMLABEL_H #define ASMLABEL_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned GetLocalLabel (void); /* Get an unused assembler label. Will never return zero. */ const char* LocalLabelName (unsigned L); /* Make a label name from the given label number. The label name will be ** created in static storage and overwritten when calling the function ** again. */ int IsLocalLabelName (const char* Name); /* Return true if Name is the name of a local label */ /* End of asmlabel.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/asmstmt.c������������������������������������������������������������������������0000664�0000000�0000000�00000032111�13473601511�0015366�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* asmstmt.c */ /* */ /* Inline assembler statements for the cc65 C compiler */ /* */ /* */ /* */ /* (C) 2001-2008 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@musoftware.de */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* common */ #include "xsprintf.h" /* cc65 */ #include "asmlabel.h" #include "codegen.h" #include "codeseg.h" #include "datatype.h" #include "error.h" #include "expr.h" #include "function.h" #include "litpool.h" #include "scanner.h" #include "segments.h" #include "stackptr.h" #include "symtab.h" #include "asmstmt.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void AsmRangeError (unsigned Arg) /* Print a diagnostic about a range error in the argument with the given number */ { Error ("Range error in argument %u", Arg); } static void AsmErrorSkip (void) /* Called in case of an error, skips tokens until the closing paren or a ** semicolon is reached. */ { static const token_t TokenList[] = { TOK_RPAREN, TOK_SEMI }; SkipTokens (TokenList, sizeof(TokenList) / sizeof(TokenList[0])); } static SymEntry* AsmGetSym (unsigned Arg, unsigned Type) /* Find the symbol with the name currently in NextTok. The symbol must be of ** the given type. On errors, NULL is returned. */ { SymEntry* Sym; /* We expect an argument separated by a comma */ ConsumeComma (); /* Argument must be an identifier */ if (CurTok.Tok != TOK_IDENT) { Error ("Identifier expected for argument %u", Arg); AsmErrorSkip (); return 0; } /* Get a pointer to the symbol table entry */ Sym = FindSym (CurTok.Ident); /* Did we find a symbol with this name? */ if (Sym == 0) { Error ("Undefined symbol '%s' for argument %u", CurTok.Ident, Arg); AsmErrorSkip (); return 0; } /* We found the symbol - skip the name token */ NextToken (); /* Check if we have a global symbol */ if ((Sym->Flags & Type) != Type) { Error ("Type of argument %u differs from format specifier", Arg); AsmErrorSkip (); return 0; } /* Mark the symbol as referenced */ Sym->Flags |= SC_REF; /* Return it */ return Sym; } static void ParseByteArg (StrBuf* T, unsigned Arg) /* Parse the %b format specifier */ { ExprDesc Expr; char Buf [16]; /* We expect an argument separated by a comma */ ConsumeComma (); /* Evaluate the expression */ ConstAbsIntExpr (hie1, &Expr); /* Check the range but allow negative values if the type is signed */ if (IsSignUnsigned (Expr.Type)) { if (Expr.IVal < 0 || Expr.IVal > 0xFF) { AsmRangeError (Arg); Expr.IVal = 0; } } else { if (Expr.IVal < -128 || Expr.IVal > 127) { AsmRangeError (Arg); Expr.IVal = 0; } } /* Convert into a hex number */ xsprintf (Buf, sizeof (Buf), "$%02lX", Expr.IVal & 0xFF); /* Add the number to the target buffer */ SB_AppendStr (T, Buf); } static void ParseWordArg (StrBuf* T, unsigned Arg) /* Parse the %w format specifier */ { ExprDesc Expr; char Buf [16]; /* We expect an argument separated by a comma */ ConsumeComma (); /* Evaluate the expression */ ConstAbsIntExpr (hie1, &Expr); /* Check the range but allow negative values if the type is signed */ if (IsSignUnsigned (Expr.Type)) { if (Expr.IVal < 0 || Expr.IVal > 0xFFFF) { AsmRangeError (Arg); Expr.IVal = 0; } } else { if (Expr.IVal < -32768 || Expr.IVal > 32767) { AsmRangeError (Arg); Expr.IVal = 0; } } /* Convert into a hex number */ xsprintf (Buf, sizeof (Buf), "$%04lX", Expr.IVal & 0xFFFF); /* Add the number to the target buffer */ SB_AppendStr (T, Buf); } static void ParseLongArg (StrBuf* T, unsigned Arg attribute ((unused))) /* Parse the %l format specifier */ { ExprDesc Expr; char Buf [16]; /* We expect an argument separated by a comma */ ConsumeComma (); /* Evaluate the expression */ ConstAbsIntExpr (hie1, &Expr); /* Convert into a hex number */ xsprintf (Buf, sizeof (Buf), "$%08lX", Expr.IVal & 0xFFFFFFFF); /* Add the number to the target buffer */ SB_AppendStr (T, Buf); } static void ParseGVarArg (StrBuf* T, unsigned Arg) /* Parse the %v format specifier */ { /* Parse the symbol name parameter and check the type */ SymEntry* Sym = AsmGetSym (Arg, SC_STATIC); if (Sym == 0) { /* Some sort of error */ return; } /* Check for external linkage */ if (Sym->Flags & (SC_EXTERN | SC_STORAGE | SC_FUNC)) { /* External linkage or a function */ /* ### FIXME: Asm name should be generated by codegen */ SB_AppendChar (T, '_'); SB_AppendStr (T, Sym->Name); } else if (Sym->Flags & SC_REGISTER) { char Buf[32]; xsprintf (Buf, sizeof (Buf), "regbank+%d", Sym->V.R.RegOffs); SB_AppendStr (T, Buf); } else { /* Static variable */ char Buf [16]; xsprintf (Buf, sizeof (Buf), "L%04X", Sym->V.L.Label); SB_AppendStr (T, Buf); } } static void ParseLVarArg (StrBuf* T, unsigned Arg) /* Parse the %o format specifier */ { unsigned Offs; char Buf [16]; /* Parse the symbol name parameter and check the type */ SymEntry* Sym = AsmGetSym (Arg, SC_AUTO); if (Sym == 0) { /* Some sort of error */ return; } /* The symbol may be a parameter to a variadic function. In this case, we ** don't have a fixed stack offset, so check it and bail out with an error ** if this is the case. */ if ((Sym->Flags & SC_PARAM) == SC_PARAM && F_IsVariadic (CurrentFunc)) { Error ("Argument %u has no fixed stack offset", Arg); AsmErrorSkip (); return; } /* Calculate the current offset from SP */ Offs = Sym->V.Offs - StackPtr; /* Output the offset */ xsprintf (Buf, sizeof (Buf), (Offs > 0xFF)? "$%04X" : "$%02X", Offs); SB_AppendStr (T, Buf); } static void ParseLabelArg (StrBuf* T, unsigned Arg attribute ((unused))) /* Parse the %g format specifier */ { /* We expect an identifier separated by a comma */ ConsumeComma (); if (CurTok.Tok != TOK_IDENT) { Error ("Label name expected"); } else { /* Add a new label symbol if we don't have one until now */ SymEntry* Entry = AddLabelSym (CurTok.Ident, SC_REF); /* Append the label name to the buffer */ SB_AppendStr (T, LocalLabelName (Entry->V.L.Label)); /* Eat the label name */ NextToken (); } } static void ParseStrArg (StrBuf* T, unsigned Arg attribute ((unused))) /* Parse the %s format specifier */ { ExprDesc Expr; char Buf [64]; /* We expect an argument separated by a comma */ ConsumeComma (); /* Check what comes */ switch (CurTok.Tok) { case TOK_IDENT: /* Identifier */ SB_AppendStr (T, CurTok.Ident); NextToken (); break; case TOK_SCONST: /* String constant */ SB_Append (T, GetLiteralStrBuf (CurTok.SVal)); NextToken (); break; default: ConstAbsIntExpr (hie1, &Expr); xsprintf (Buf, sizeof (Buf), "%ld", Expr.IVal); SB_AppendStr (T, Buf); break; } } static void ParseAsm (void) /* Parse the contents of the ASM statement */ { unsigned Arg; char C; /* Create a target string buffer */ StrBuf T = AUTO_STRBUF_INITIALIZER; /* Create a string buffer from the string literal */ StrBuf S = AUTO_STRBUF_INITIALIZER; SB_Append (&S, GetLiteralStrBuf (CurTok.SVal)); /* Skip the string token */ NextToken (); /* Parse the statement. It may contain several lines and one or more ** of the following place holders: ** %b - Numerical 8 bit value ** %w - Numerical 16 bit value ** %l - Numerical 32 bit value ** %v - Assembler name of a (global) variable ** %o - Stack offset of a (local) variable ** %g - Assembler name of a C label ** %s - Any argument converted to a string (almost) ** %% - The % sign */ Arg = 0; while ((C = SB_Get (&S)) != '\0') { /* If it is a newline, the current line is ready to go */ if (C == '\n') { /* Pass it to the backend and start over */ g_asmcode (&T); SB_Clear (&T); } else if (C == '%') { /* Format specifier */ ++Arg; C = SB_Get (&S); switch (C) { case '%': SB_AppendChar (&T, '%'); break; case 'b': ParseByteArg (&T, Arg); break; case 'g': ParseLabelArg (&T, Arg); break; case 'l': ParseLongArg (&T, Arg); break; case 'o': ParseLVarArg (&T, Arg); break; case 's': ParseStrArg (&T, Arg); break; case 'v': ParseGVarArg (&T, Arg); break; case 'w': ParseWordArg (&T, Arg); break; default: Error ("Error in __asm__ format specifier %u", Arg); AsmErrorSkip (); goto Done; } } else { /* A normal character, just copy it */ SB_AppendChar (&T, C); } } /* If the target buffer is not empty, we have a last line in there */ if (!SB_IsEmpty (&T)) { g_asmcode (&T); } Done: /* Call the string buf destructors */ SB_Done (&S); SB_Done (&T); } void AsmStatement (void) /* This function parses ASM statements. The syntax of the ASM directive ** looks like the one defined for C++ (C has no ASM directive), that is, ** a string literal in parenthesis. */ { /* Skip the ASM */ NextToken (); /* An optional volatile qualifier disables optimization for ** the entire function [same as #pragma optimize(push, off)]. */ if (CurTok.Tok == TOK_VOLATILE) { /* Don't optimize the Current code Segment */ CS->Code->Optimize = 0; NextToken (); } /* Need left parenthesis */ if (!ConsumeLParen ()) { return; } /* String literal */ if (CurTok.Tok != TOK_SCONST) { /* Print a diagnostic */ Error ("String literal expected"); /* Try some smart error recovery: Skip tokens until we reach the ** enclosing paren, or a semicolon. */ AsmErrorSkip (); } else { /* Parse the ASM statement */ ParseAsm (); } /* Closing paren needed */ ConsumeRParen (); } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/asmstmt.h������������������������������������������������������������������������0000664�0000000�0000000�00000006021�13473601511�0015374�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* asmstmt.h */ /* */ /* Inline assembler statements for the cc65 C compiler */ /* */ /* */ /* */ /* (C) 2001 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 ASMSTMT_H #define ASMSTMT_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ void AsmStatement (void); /* This function parses ASM statements. The syntax of the ASM directive ** looks like the one defined for C++ (C has no ASM directive), that is, ** a string literal in parenthesis. */ /* End of asmstmt.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/assignment.c���������������������������������������������������������������������0000664�0000000�0000000�00000022677�13473601511�0016066�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* assignment.c */ /* */ /* Parse assignments */ /* */ /* */ /* */ /* (C) 2002-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* cc65 */ #include "asmcode.h" #include "assignment.h" #include "codegen.h" #include "datatype.h" #include "error.h" #include "expr.h" #include "loadexpr.h" #include "scanner.h" #include "stdnames.h" #include "typecmp.h" #include "typeconv.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Assignment (ExprDesc* Expr) /* Parse an assignment */ { ExprDesc Expr2; Type* ltype = Expr->Type; /* We must have an lvalue for an assignment */ if (ED_IsRVal (Expr)) { Error ("Invalid lvalue in assignment"); } /* Check for assignment to const */ if (IsQualConst (ltype)) { Error ("Assignment to const"); } /* Skip the '=' token */ NextToken (); /* cc65 does not have full support for handling structs by value. Since ** assigning structs is one of the more useful operations from this ** family, allow it here. */ if (IsClassStruct (ltype)) { /* Get the size of the left hand side. */ unsigned Size = SizeOf (ltype); /* If the size is that of a basic type (char, int, long), we will copy ** the struct using the primary register, otherwise we use memcpy. In ** the former case, push the address only if really needed. */ int UseReg = 1; Type* stype; switch (Size) { case SIZEOF_CHAR: stype = type_uchar; break; case SIZEOF_INT: stype = type_uint; break; case SIZEOF_LONG: stype = type_ulong; break; default: stype = ltype; UseReg = 0; break; } if (UseReg) { PushAddr (Expr); } else { ED_MakeRVal (Expr); LoadExpr (CF_NONE, Expr); g_push (CF_PTR | CF_UNSIGNED, 0); } /* Get the expression on the right of the '=' into the primary */ hie1 (&Expr2); /* Check for equality of the structs */ if (TypeCmp (ltype, Expr2.Type) < TC_STRICT_COMPATIBLE) { Error ("Incompatible types"); } /* Check if the right hand side is an lvalue */ if (ED_IsLVal (&Expr2)) { /* We have an lvalue. Do we copy using the primary? */ if (UseReg) { /* Just use the replacement type */ Expr2.Type = stype; /* Load the value into the primary */ LoadExpr (CF_FORCECHAR, &Expr2); /* Store it into the new location */ Store (Expr, stype); } else { /* We will use memcpy. Push the address of the rhs */ ED_MakeRVal (&Expr2); LoadExpr (CF_NONE, &Expr2); /* Push the address (or whatever is in ax in case of errors) */ g_push (CF_PTR | CF_UNSIGNED, 0); /* Load the size of the struct into the primary */ g_getimmed (CF_INT | CF_UNSIGNED | CF_CONST, CheckedSizeOf (ltype), 0); /* Call the memcpy function */ g_call (CF_FIXARGC, Func_memcpy, 4); } } else { /* We have an rvalue. This can only happen if a function returns ** a struct, since there is no other way to generate an expression ** that has a struct as an rvalue result. We allow only 1, 2, and 4 ** byte sized structs, and do direct assignment. */ if (UseReg) { /* Do the store */ Store (Expr, stype); } else { /* Print a diagnostic */ Error ("Structs of this size are not supported"); /* Adjust the stack so we won't run in an internal error later */ pop (CF_PTR); } } } else if (ED_IsBitField (Expr)) { CodeMark AndPos; CodeMark PushPos; unsigned Mask; unsigned Flags; /* If the bit-field fits within one byte, do the following operations ** with bytes. */ if (Expr->BitOffs / CHAR_BITS == (Expr->BitOffs + Expr->BitWidth - 1) / CHAR_BITS) { Expr->Type = type_uchar; } /* Determine code generator flags */ Flags = TypeOf (Expr->Type); /* Assignment to a bit field. Get the address on stack for the store. */ PushAddr (Expr); /* Load the value from the location */ Expr->Flags &= ~E_BITFIELD; LoadExpr (CF_NONE, Expr); /* Mask unwanted bits */ Mask = (0x0001U << Expr->BitWidth) - 1U; GetCodePos (&AndPos); g_and (Flags | CF_CONST, ~(Mask << Expr->BitOffs)); /* Push it on stack */ GetCodePos (&PushPos); g_push (Flags, 0); /* Read the expression on the right side of the '=' */ MarkedExprWithCheck (hie1, &Expr2); /* Do type conversion if necessary. Beware: Do not use char type ** here! */ TypeConversion (&Expr2, ltype); /* Special treatment if the value is constant. */ /* Beware: Expr2 may contain side effects, so there must not be ** code generated for Expr2. */ if (ED_IsConstAbsInt (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) { /* Get the value and apply the mask */ unsigned Val = (unsigned) (Expr2.IVal & Mask); /* Since we will do the OR with a constant, we can remove the push */ RemoveCode (&PushPos); /* If the value is equal to the mask now, all bits are one, and we ** can remove the mask operation from above. */ if (Val == Mask) { RemoveCode (&AndPos); } /* Generate the or operation */ g_or (Flags | CF_CONST, Val << Expr->BitOffs); } else { /* If necessary, load the value into the primary register */ LoadExpr (CF_NONE, &Expr2); /* Apply the mask */ g_and (Flags | CF_CONST, Mask); /* Shift it into the right position */ g_asl (Flags | CF_CONST, Expr->BitOffs); /* Or both values */ g_or (Flags, 0); } /* Generate a store instruction */ Store (Expr, 0); /* Restore the expression type */ Expr->Type = ltype; } else { /* Get the address on stack if needed */ PushAddr (Expr); /* Read the expression on the right side of the '=' */ hie1 (&Expr2); /* Do type conversion if necessary */ TypeConversion (&Expr2, ltype); /* If necessary, load the value into the primary register */ LoadExpr (CF_NONE, &Expr2); /* Generate a store instruction */ Store (Expr, 0); } /* Value is still in primary and not an lvalue */ ED_MakeRValExpr (Expr); } �����������������������������������������������������������������cc65-2.18/src/cc65/assignment.h���������������������������������������������������������������������0000664�0000000�0000000�00000005650�13473601511�0016063�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* assignment.h */ /* */ /* Parse assignments */ /* */ /* */ /* */ /* (C) 2002-2004 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef ASSIGNMENT_H #define ASSIGNMENT_H /* cc65 */ #include "exprdesc.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Assignment (ExprDesc* lval); /* Parse an assignment */ /* End of assignment.h */ #endif ����������������������������������������������������������������������������������������cc65-2.18/src/cc65/casenode.c�����������������������������������������������������������������������0000664�0000000�0000000�00000013764�13473601511�0015474�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* casenode.c */ /* */ /* Node for the tree that is generated for a switch statement */ /* */ /* */ /* */ /* (C) 2001 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <limits.h> /* common */ #include "coll.h" #include "xmalloc.h" /* cc65 */ #include "asmlabel.h" #include "error.h" #include "casenode.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ CaseNode* NewCaseNode (unsigned char Value) /* Create and initialize a new CaseNode */ { /* Allocate memory */ CaseNode* N = xmalloc (sizeof (CaseNode)); /* Initialize the fields */ N->Value = Value; N->Label = 0; N->Nodes = 0; /* Return the new node */ return N; } void FreeCaseNode (CaseNode* N) /* Delete a case node plus all sub nodes */ { if (N->Nodes) { FreeCaseNodeColl (N->Nodes); } xfree (N); } void FreeCaseNodeColl (Collection* Nodes) /* Free a collection of case nodes */ { unsigned I; for (I = 0; I < CollCount (Nodes); ++I) { FreeCaseNode (CollAtUnchecked (Nodes, I)); } FreeCollection (Nodes); } int SearchCaseNode (const Collection* Nodes, unsigned char Key, int* Index) /* Search for a node in the given collection. If the node has been found, ** set Index to the index of the node and return true. If the node was not ** found, set Index the the insertion position of the node and return ** false. */ { /* Do a binary search */ int First = 0; int Last = CollCount (Nodes) - 1; int S = 0; while (First <= Last) { /* Set current to mid of range */ int Current = (Last + First) / 2; /* Get the entry from this position */ const CaseNode* N = CollConstAt (Nodes, Current); /* Compare the values */ if (N->Value < Key) { First = Current + 1; } else { Last = Current - 1; if (N->Value == Key) { /* Found. We cannot have duplicates, so end the search here. */ S = 1; First = Current; } } } *Index = First; return S; } unsigned InsertCaseValue (Collection* Nodes, unsigned long Val, unsigned Depth) /* Insert a new case value into a CaseNode tree with the given depth. Return ** the code label for the value. */ { CaseNode* N = 0; unsigned CaseLabel = GetLocalLabel (); /* Code label */ while (Depth--) { int Index; /* Get the key */ unsigned char Key = (Val >> (Depth * CHAR_BIT)) & 0xFF; /* Search for the node in the collection */ if (SearchCaseNode (Nodes, Key, &Index) == 0) { /* Node not found - insert one */ N = NewCaseNode (Key); CollInsert (Nodes, N, Index); /* If this is not the last round, create the collection for ** the subnodes, otherwise get a label for the code. */ if (Depth > 0) { N->Nodes = NewCollection (); } else { N->Label = CaseLabel; } } else { /* Node found, get it */ N = CollAt (Nodes, Index); /* If this is the last round and we found a node, we have a ** duplicate case label in a switch. */ if (Depth == 0) { Error ("Duplicate case label"); } } /* Get the collection from the node for the next round. */ Nodes = N->Nodes; } /* Return the label of the node we found/created */ return CaseLabel; } ������������cc65-2.18/src/cc65/casenode.h�����������������������������������������������������������������������0000664�0000000�0000000�00000011413�13473601511�0015466�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* casenode.h */ /* */ /* Node for the tree that is generated for a switch statement */ /* */ /* */ /* */ /* (C) 2001 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef CASENODE_H #define CASENODE_H /* common */ #include "coll.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ typedef struct CaseNode CaseNode; struct CaseNode { unsigned char Value; unsigned Label; Collection* Nodes; }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ CaseNode* NewCaseNode (unsigned char Value); /* Create and initialize a new CaseNode */ void FreeCaseNode (CaseNode* N); /* Delete a case node plus all sub nodes */ #if defined(HAVE_INLINE) INLINE CaseNode* CN_GetSubNode (CaseNode* N, unsigned Index) /* Get a sub node of the given node */ { return CollAt (N->Nodes, Index); } #else # define CN_GetSubNode(N, Index) CollAt (&(N)->Nodes, Index) #endif #if defined(HAVE_INLINE) INLINE unsigned char CN_GetValue (const CaseNode* N) /* Return the value for a case node */ { return N->Value; } #else # define CN_GetValue(N) ((N)->Value) #endif #if defined(HAVE_INLINE) INLINE unsigned CN_GetLabel (const CaseNode* N) /* Return the label for a case node */ { return N->Label; } #else # define CN_GetLabel(N) ((N)->Label) #endif #if defined(HAVE_INLINE) INLINE int CN_IsLeafNode (const CaseNode* N) /* Return true if this is a leaf node */ { return (N->Nodes == 0); } #else # define CN_IsLeafNode(N) ((N)->Nodes == 0) #endif void FreeCaseNodeColl (Collection* Nodes); /* Free a collection of case nodes */ int SearchCaseNode (const Collection* Nodes, unsigned char Key, int* Index); /* Search for a node in the given collection. If the node has been found, ** set Index to the index of the node and return true. If the node was not ** found, set Index the the insertion position of the node and return ** false. */ unsigned InsertCaseValue (Collection* Nodes, unsigned long Val, unsigned Depth); /* Insert a new case value into a CaseNode tree with the given depth. Return ** the code label for the value. */ /* End of casenode.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/codeent.c������������������������������������������������������������������������0000664�0000000�0000000�00000131215�13473601511�0015324�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* codeent.c */ /* */ /* Code segment entry */ /* */ /* */ /* */ /* (C) 2001-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdlib.h> /* common */ #include "chartype.h" #include "check.h" #include "debugflag.h" #include "xmalloc.h" #include "xsprintf.h" /* cc65 */ #include "codeent.h" #include "codeinfo.h" #include "error.h" #include "global.h" #include "codelab.h" #include "opcodes.h" #include "output.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Empty argument */ static char EmptyArg[] = ""; /*****************************************************************************/ /* Helper functions */ /*****************************************************************************/ static void FreeArg (char* Arg) /* Free a code entry argument */ { if (Arg != EmptyArg) { xfree (Arg); } } static char* GetArgCopy (const char* Arg) /* Create an argument copy for assignment */ { if (Arg && Arg[0] != '\0') { /* Create a copy */ return xstrdup (Arg); } else { /* Use the empty argument string */ return EmptyArg; } } static int NumArg (const char* Arg, unsigned long* Num) /* If the given argument is numerical, convert it and return true. Otherwise ** set Num to zero and return false. */ { char* End; unsigned long Val; /* Determine the base */ int Base = 10; if (*Arg == '$') { ++Arg; Base = 16; } else if (*Arg == '%') { ++Arg; Base = 2; } /* Convert the value. strtol is not exactly what we want here, but it's ** cheap and may be replaced by something fancier later. */ Val = strtoul (Arg, &End, Base); /* Check if the conversion was successful */ if (*End != '\0') { /* Could not convert */ *Num = 0; return 0; } else { /* Conversion ok */ *Num = Val; return 1; } } static void SetUseChgInfo (CodeEntry* E, const OPCDesc* D) /* Set the Use and Chg in E */ { const ZPInfo* Info; /* If this is a subroutine call, or a jump to an external function, ** lookup the information about this function and use it. The jump itself ** does not change any registers, so we don't need to use the data from D. */ if ((E->Info & (OF_UBRA | OF_CALL)) != 0 && E->JumpTo == 0) { /* A subroutine call or jump to external symbol (function exit) */ GetFuncInfo (E->Arg, &E->Use, &E->Chg); } else { /* Some other instruction. Use the values from the opcode description ** plus addressing mode info. */ E->Use = D->Use | GetAMUseInfo (E->AM); E->Chg = D->Chg; /* Check for special zero page registers used */ switch (E->AM) { case AM65_ACC: if (E->OPC == OP65_ASL || E->OPC == OP65_DEC || E->OPC == OP65_INC || E->OPC == OP65_LSR || E->OPC == OP65_ROL || E->OPC == OP65_ROR) { /* A is changed by these insns */ E->Chg |= REG_A; } break; case AM65_ZP: case AM65_ABS: /* Be conservative: */ case AM65_ZPX: case AM65_ABSX: case AM65_ABSY: Info = GetZPInfo (E->Arg); if (Info && Info->ByteUse != REG_NONE) { if (E->OPC == OP65_ASL || E->OPC == OP65_DEC || E->OPC == OP65_INC || E->OPC == OP65_LSR || E->OPC == OP65_ROL || E->OPC == OP65_ROR || E->OPC == OP65_TRB || E->OPC == OP65_TSB) { /* The zp loc is both, input and output */ E->Chg |= Info->ByteUse; E->Use |= Info->ByteUse; } else if ((E->Info & OF_STORE) != 0) { /* Just output */ E->Chg |= Info->ByteUse; } else { /* Input only */ E->Use |= Info->ByteUse; } } break; case AM65_ZPX_IND: case AM65_ZP_INDY: case AM65_ZP_IND: Info = GetZPInfo (E->Arg); if (Info && Info->ByteUse != REG_NONE) { /* These addressing modes will never change the zp loc */ E->Use |= Info->WordUse; } break; default: /* Keep gcc silent */ break; } } } /*****************************************************************************/ /* Code */ /*****************************************************************************/ const char* MakeHexArg (unsigned Num) /* Convert Num into a string in the form $XY, suitable for passing it as an ** argument to NewCodeEntry, and return a pointer to the string. ** BEWARE: The function returns a pointer to a static buffer, so the value is ** gone if you call it twice (and apart from that it's not thread and signal ** safe). */ { static char Buf[16]; xsprintf (Buf, sizeof (Buf), "$%02X", (unsigned char) Num); return Buf; } CodeEntry* NewCodeEntry (opc_t OPC, am_t AM, const char* Arg, CodeLabel* JumpTo, LineInfo* LI) /* Create a new code entry, initialize and return it */ { /* Get the opcode description */ const OPCDesc* D = GetOPCDesc (OPC); /* Allocate memory */ CodeEntry* E = xmalloc (sizeof (CodeEntry)); /* Initialize the fields */ E->OPC = D->OPC; E->AM = AM; E->Size = GetInsnSize (E->OPC, E->AM); E->Arg = GetArgCopy (Arg); E->Flags = NumArg (E->Arg, &E->Num)? CEF_NUMARG : 0; /* Needs E->Arg */ E->Info = D->Info; E->JumpTo = JumpTo; E->LI = UseLineInfo (LI); E->RI = 0; SetUseChgInfo (E, D); InitCollection (&E->Labels); /* If we have a label given, add this entry to the label */ if (JumpTo) { CollAppend (&JumpTo->JumpFrom, E); } /* Return the initialized struct */ return E; } void FreeCodeEntry (CodeEntry* E) /* Free the given code entry */ { /* Free the string argument if we have one */ FreeArg (E->Arg); /* Cleanup the collection */ DoneCollection (&E->Labels); /* Release the line info */ ReleaseLineInfo (E->LI); /* Delete the register info */ CE_FreeRegInfo (E); /* Free the entry */ xfree (E); } void CE_ReplaceOPC (CodeEntry* E, opc_t OPC) /* Replace the opcode of the instruction. This will also replace related info, ** Size, Use and Chg, but it will NOT update any arguments or labels. */ { /* Get the opcode descriptor */ const OPCDesc* D = GetOPCDesc (OPC); /* Replace the opcode */ E->OPC = OPC; E->Info = D->Info; E->Size = GetInsnSize (E->OPC, E->AM); SetUseChgInfo (E, D); } int CodeEntriesAreEqual (const CodeEntry* E1, const CodeEntry* E2) /* Check if both code entries are equal */ { return (E1->OPC == E2->OPC && E1->AM == E2->AM && strcmp (E1->Arg, E2->Arg) == 0); } void CE_AttachLabel (CodeEntry* E, CodeLabel* L) /* Attach the label to the entry */ { /* Add it to the entries label list */ CollAppend (&E->Labels, L); /* Tell the label about it's owner */ L->Owner = E; } void CE_ClearJumpTo (CodeEntry* E) /* Clear the JumpTo entry and the argument (which contained the name of the ** label). Note: The function will not clear the backpointer from the label, ** so use it with care. */ { /* Clear the JumpTo entry */ E->JumpTo = 0; /* Clear the argument and assign the empty one */ FreeArg (E->Arg); E->Arg = EmptyArg; } void CE_MoveLabel (CodeLabel* L, CodeEntry* E) /* Move the code label L from it's former owner to the code entry E. */ { /* Delete the label from the owner */ CollDeleteItem (&L->Owner->Labels, L); /* Set the new owner */ CollAppend (&E->Labels, L); L->Owner = E; } void CE_SetArg (CodeEntry* E, const char* Arg) /* Replace the argument by the new one. */ { /* Free the old argument */ FreeArg (E->Arg); /* Assign the new one */ E->Arg = GetArgCopy (Arg); } void CE_SetNumArg (CodeEntry* E, long Num) /* Set a new numeric argument for the given code entry that must already ** have a numeric argument. */ { char Buf[16]; /* Check that the entry has a numerical argument */ CHECK (E->Flags & CEF_NUMARG); /* Make the new argument string */ if (E->Size == 2) { Num &= 0xFF; xsprintf (Buf, sizeof (Buf), "$%02X", (unsigned) Num); } else if (E->Size == 3) { Num &= 0xFFFF; xsprintf (Buf, sizeof (Buf), "$%04X", (unsigned) Num); } else { Internal ("Invalid instruction size in CE_SetNumArg"); } /* Replace the argument by the new one */ CE_SetArg (E, Buf); /* Use the new numerical value */ E->Num = Num; } int CE_IsConstImm (const CodeEntry* E) /* Return true if the argument of E is a constant immediate value */ { return (E->AM == AM65_IMM && CE_HasNumArg (E)); } int CE_IsKnownImm (const CodeEntry* E, unsigned long Num) /* Return true if the argument of E is a constant immediate value that is ** equal to Num. */ { return (E->AM == AM65_IMM && CE_HasNumArg (E) && E->Num == Num); } int CE_UseLoadFlags (CodeEntry* E) /* Return true if the instruction uses any flags that are set by a load of ** a register (N and Z). */ { /* Follow unconditional branches, but beware of endless loops. After this, ** E will point to the first entry that is not a branch. */ if (E->Info & OF_UBRA) { Collection C = AUTO_COLLECTION_INITIALIZER; /* Follow the chain */ while (E->Info & OF_UBRA) { /* Remember the entry so we can detect loops */ CollAppend (&C, E); /* Check the target */ if (E->JumpTo == 0 || CollIndex (&C, E->JumpTo->Owner) >= 0) { /* Unconditional jump to external symbol, or endless loop. */ DoneCollection (&C); return 0; /* Flags not used */ } /* Follow the chain */ E = E->JumpTo->Owner; } /* Delete the collection */ DoneCollection (&C); } /* A branch will use the flags */ if (E->Info & OF_FBRA) { return 1; } /* Call of a boolean transformer routine will also use the flags */ if (E->OPC == OP65_JSR) { /* Get the condition that is evaluated and check it */ switch (FindBoolCmpCond (E->Arg)) { case CMP_EQ: case CMP_NE: case CMP_GT: case CMP_GE: case CMP_LT: case CMP_LE: case CMP_UGT: case CMP_ULE: /* Will use the N or Z flags */ return 1; case CMP_UGE: /* Uses only carry */ case CMP_ULT: /* Dito */ default: /* No bool transformer subroutine */ return 0; } } /* Anything else */ return 0; } void CE_FreeRegInfo (CodeEntry* E) /* Free an existing register info struct */ { if (E->RI) { FreeRegInfo (E->RI); E->RI = 0; } } void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs) /* Generate register info for this instruction. If an old info exists, it is ** overwritten. */ { /* Pointers to the register contents */ RegContents* In; RegContents* Out; /* Function register usage */ unsigned short Use, Chg; /* If we don't have a register info struct, allocate one. */ if (E->RI == 0) { E->RI = NewRegInfo (InputRegs); } else { if (InputRegs) { E->RI->In = *InputRegs; } else { RC_Invalidate (&E->RI->In); } E->RI->Out2 = E->RI->Out = E->RI->In; } /* Get pointers to the register contents */ In = &E->RI->In; Out = &E->RI->Out; /* Handle the different instructions */ switch (E->OPC) { case OP65_ADC: /* We don't know the value of the carry, so the result is ** always unknown. */ Out->RegA = UNKNOWN_REGVAL; break; case OP65_AND: if (RegValIsKnown (In->RegA)) { if (CE_IsConstImm (E)) { Out->RegA = In->RegA & (short) E->Num; } else if (E->AM == AM65_ZP) { switch (GetKnownReg (E->Use & REG_ZP, In)) { case REG_TMP1: Out->RegA = In->RegA & In->Tmp1; break; case REG_PTR1_LO: Out->RegA = In->RegA & In->Ptr1Lo; break; case REG_PTR1_HI: Out->RegA = In->RegA & In->Ptr1Hi; break; case REG_SREG_LO: Out->RegA = In->RegA & In->SRegLo; break; case REG_SREG_HI: Out->RegA = In->RegA & In->SRegHi; break; default: Out->RegA = UNKNOWN_REGVAL; break; } } else { Out->RegA = UNKNOWN_REGVAL; } } else if (CE_IsKnownImm (E, 0)) { /* A and $00 does always give zero */ Out->RegA = 0; } break; case OP65_ASL: if (E->AM == AM65_ACC && RegValIsKnown (In->RegA)) { Out->RegA = (In->RegA << 1) & 0xFF; } else if (E->AM == AM65_ZP) { switch (GetKnownReg (E->Chg & REG_ZP, In)) { case REG_TMP1: Out->Tmp1 = (In->Tmp1 << 1) & 0xFF; break; case REG_PTR1_LO: Out->Ptr1Lo = (In->Ptr1Lo << 1) & 0xFF; break; case REG_PTR1_HI: Out->Ptr1Hi = (In->Ptr1Hi << 1) & 0xFF; break; case REG_SREG_LO: Out->SRegLo = (In->SRegLo << 1) & 0xFF; break; case REG_SREG_HI: Out->SRegHi = (In->SRegHi << 1) & 0xFF; break; } } else if (E->AM == AM65_ZPX) { /* Invalidates all ZP registers */ RC_InvalidateZP (Out); } break; case OP65_BCC: break; case OP65_BCS: break; case OP65_BEQ: break; case OP65_BIT: break; case OP65_BMI: break; case OP65_BNE: break; case OP65_BPL: break; case OP65_BRA: break; case OP65_BRK: break; case OP65_BVC: break; case OP65_BVS: break; case OP65_CLC: break; case OP65_CLD: break; case OP65_CLI: break; case OP65_CLV: break; case OP65_CMP: break; case OP65_CPX: break; case OP65_CPY: break; case OP65_DEA: if (RegValIsKnown (In->RegA)) { Out->RegA = (In->RegA - 1) & 0xFF; } break; case OP65_DEC: if (E->AM == AM65_ACC && RegValIsKnown (In->RegA)) { Out->RegA = (In->RegA - 1) & 0xFF; } else if (E->AM == AM65_ZP) { switch (GetKnownReg (E->Chg & REG_ZP, In)) { case REG_TMP1: Out->Tmp1 = (In->Tmp1 - 1) & 0xFF; break; case REG_PTR1_LO: Out->Ptr1Lo = (In->Ptr1Lo - 1) & 0xFF; break; case REG_PTR1_HI: Out->Ptr1Hi = (In->Ptr1Hi - 1) & 0xFF; break; case REG_SREG_LO: Out->SRegLo = (In->SRegLo - 1) & 0xFF; break; case REG_SREG_HI: Out->SRegHi = (In->SRegHi - 1) & 0xFF; break; } } else if (E->AM == AM65_ZPX) { /* Invalidates all ZP registers */ RC_InvalidateZP (Out); } break; case OP65_DEX: if (RegValIsKnown (In->RegX)) { Out->RegX = (In->RegX - 1) & 0xFF; } break; case OP65_DEY: if (RegValIsKnown (In->RegY)) { Out->RegY = (In->RegY - 1) & 0xFF; } break; case OP65_EOR: if (RegValIsKnown (In->RegA)) { if (CE_IsConstImm (E)) { Out->RegA = In->RegA ^ (short) E->Num; } else if (E->AM == AM65_ZP) { switch (GetKnownReg (E->Use & REG_ZP, In)) { case REG_TMP1: Out->RegA = In->RegA ^ In->Tmp1; break; case REG_PTR1_LO: Out->RegA = In->RegA ^ In->Ptr1Lo; break; case REG_PTR1_HI: Out->RegA = In->RegA ^ In->Ptr1Hi; break; case REG_SREG_LO: Out->RegA = In->RegA ^ In->SRegLo; break; case REG_SREG_HI: Out->RegA = In->RegA ^ In->SRegHi; break; default: Out->RegA = UNKNOWN_REGVAL; break; } } else { Out->RegA = UNKNOWN_REGVAL; } } break; case OP65_INA: if (RegValIsKnown (In->RegA)) { Out->RegA = (In->RegA + 1) & 0xFF; } break; case OP65_INC: if (E->AM == AM65_ACC && RegValIsKnown (In->RegA)) { Out->RegA = (In->RegA + 1) & 0xFF; } else if (E->AM == AM65_ZP) { switch (GetKnownReg (E->Chg & REG_ZP, In)) { case REG_TMP1: Out->Tmp1 = (In->Tmp1 + 1) & 0xFF; break; case REG_PTR1_LO: Out->Ptr1Lo = (In->Ptr1Lo + 1) & 0xFF; break; case REG_PTR1_HI: Out->Ptr1Hi = (In->Ptr1Hi + 1) & 0xFF; break; case REG_SREG_LO: Out->SRegLo = (In->SRegLo + 1) & 0xFF; break; case REG_SREG_HI: Out->SRegHi = (In->SRegHi + 1) & 0xFF; break; } } else if (E->AM == AM65_ZPX) { /* Invalidates all ZP registers */ RC_InvalidateZP (Out); } break; case OP65_INX: if (RegValIsKnown (In->RegX)) { Out->RegX = (In->RegX + 1) & 0xFF; } break; case OP65_INY: if (RegValIsKnown (In->RegY)) { Out->RegY = (In->RegY + 1) & 0xFF; } break; case OP65_JCC: break; case OP65_JCS: break; case OP65_JEQ: break; case OP65_JMI: break; case OP65_JMP: break; case OP65_JNE: break; case OP65_JPL: break; case OP65_JSR: /* Get the code info for the function */ GetFuncInfo (E->Arg, &Use, &Chg); if (Chg & REG_A) { Out->RegA = UNKNOWN_REGVAL; } if (Chg & REG_X) { Out->RegX = UNKNOWN_REGVAL; } if (Chg & REG_Y) { Out->RegY = UNKNOWN_REGVAL; } if (Chg & REG_TMP1) { Out->Tmp1 = UNKNOWN_REGVAL; } if (Chg & REG_PTR1_LO) { Out->Ptr1Lo = UNKNOWN_REGVAL; } if (Chg & REG_PTR1_HI) { Out->Ptr1Hi = UNKNOWN_REGVAL; } if (Chg & REG_SREG_LO) { Out->SRegLo = UNKNOWN_REGVAL; } if (Chg & REG_SREG_HI) { Out->SRegHi = UNKNOWN_REGVAL; } /* ## FIXME: Quick hack for some known functions: */ if (strcmp (E->Arg, "complax") == 0) { if (RegValIsKnown (In->RegA)) { Out->RegA = (In->RegA ^ 0xFF); } if (RegValIsKnown (In->RegX)) { Out->RegX = (In->RegX ^ 0xFF); } } else if (strcmp (E->Arg, "tosandax") == 0) { if (In->RegA == 0) { Out->RegA = 0; } if (In->RegX == 0) { Out->RegX = 0; } } else if (strcmp (E->Arg, "tosaslax") == 0) { if (RegValIsKnown (In->RegA) && (In->RegA & 0x0F) >= 8) { printf ("Hey!\n"); Out->RegA = 0; } } else if (strcmp (E->Arg, "tosorax") == 0) { if (In->RegA == 0xFF) { Out->RegA = 0xFF; } if (In->RegX == 0xFF) { Out->RegX = 0xFF; } } else if (strcmp (E->Arg, "tosshlax") == 0) { if ((In->RegA & 0x0F) >= 8) { Out->RegA = 0; } } else if (FindBoolCmpCond (E->Arg) != CMP_INV || FindTosCmpCond (E->Arg) != CMP_INV) { /* Result is boolean value, so X is zero on output */ Out->RegX = 0; } break; case OP65_JVC: break; case OP65_JVS: break; case OP65_LDA: if (CE_IsConstImm (E)) { Out->RegA = (unsigned char) E->Num; } else if (E->AM == AM65_ZP) { switch (GetKnownReg (E->Use & REG_ZP, In)) { case REG_TMP1: Out->RegA = In->Tmp1; break; case REG_PTR1_LO: Out->RegA = In->Ptr1Lo; break; case REG_PTR1_HI: Out->RegA = In->Ptr1Hi; break; case REG_SREG_LO: Out->RegA = In->SRegLo; break; case REG_SREG_HI: Out->RegA = In->SRegHi; break; default: Out->RegA = UNKNOWN_REGVAL; break; } } else { /* A is now unknown */ Out->RegA = UNKNOWN_REGVAL; } break; case OP65_LDX: if (CE_IsConstImm (E)) { Out->RegX = (unsigned char) E->Num; } else if (E->AM == AM65_ZP) { switch (GetKnownReg (E->Use & REG_ZP, In)) { case REG_TMP1: Out->RegX = In->Tmp1; break; case REG_PTR1_LO: Out->RegX = In->Ptr1Lo; break; case REG_PTR1_HI: Out->RegX = In->Ptr1Hi; break; case REG_SREG_LO: Out->RegX = In->SRegLo; break; case REG_SREG_HI: Out->RegX = In->SRegHi; break; default: Out->RegX = UNKNOWN_REGVAL; break; } } else { /* X is now unknown */ Out->RegX = UNKNOWN_REGVAL; } break; case OP65_LDY: if (CE_IsConstImm (E)) { Out->RegY = (unsigned char) E->Num; } else if (E->AM == AM65_ZP) { switch (GetKnownReg (E->Use & REG_ZP, In)) { case REG_TMP1: Out->RegY = In->Tmp1; break; case REG_PTR1_LO: Out->RegY = In->Ptr1Lo; break; case REG_PTR1_HI: Out->RegY = In->Ptr1Hi; break; case REG_SREG_LO: Out->RegY = In->SRegLo; break; case REG_SREG_HI: Out->RegY = In->SRegHi; break; default: Out->RegY = UNKNOWN_REGVAL; break; } } else { /* Y is now unknown */ Out->RegY = UNKNOWN_REGVAL; } break; case OP65_LSR: if (E->AM == AM65_ACC && RegValIsKnown (In->RegA)) { Out->RegA = (In->RegA >> 1) & 0xFF; } else if (E->AM == AM65_ZP) { switch (GetKnownReg (E->Chg & REG_ZP, In)) { case REG_TMP1: Out->Tmp1 = (In->Tmp1 >> 1) & 0xFF; break; case REG_PTR1_LO: Out->Ptr1Lo = (In->Ptr1Lo >> 1) & 0xFF; break; case REG_PTR1_HI: Out->Ptr1Hi = (In->Ptr1Hi >> 1) & 0xFF; break; case REG_SREG_LO: Out->SRegLo = (In->SRegLo >> 1) & 0xFF; break; case REG_SREG_HI: Out->SRegHi = (In->SRegHi >> 1) & 0xFF; break; } } else if (E->AM == AM65_ZPX) { /* Invalidates all ZP registers */ RC_InvalidateZP (Out); } break; case OP65_NOP: break; case OP65_ORA: if (RegValIsKnown (In->RegA)) { if (CE_IsConstImm (E)) { Out->RegA = In->RegA | (short) E->Num; } else if (E->AM == AM65_ZP) { switch (GetKnownReg (E->Use & REG_ZP, In)) { case REG_TMP1: Out->RegA = In->RegA | In->Tmp1; break; case REG_PTR1_LO: Out->RegA = In->RegA | In->Ptr1Lo; break; case REG_PTR1_HI: Out->RegA = In->RegA | In->Ptr1Hi; break; case REG_SREG_LO: Out->RegA = In->RegA | In->SRegLo; break; case REG_SREG_HI: Out->RegA = In->RegA | In->SRegHi; break; default: Out->RegA = UNKNOWN_REGVAL; break; } } else { /* A is now unknown */ Out->RegA = UNKNOWN_REGVAL; } } else if (CE_IsKnownImm (E, 0xFF)) { /* ORA with 0xFF does always give 0xFF */ Out->RegA = 0xFF; } break; case OP65_PHA: break; case OP65_PHP: break; case OP65_PHX: break; case OP65_PHY: break; case OP65_PLA: Out->RegA = UNKNOWN_REGVAL; break; case OP65_PLP: break; case OP65_PLX: Out->RegX = UNKNOWN_REGVAL; break; case OP65_PLY: Out->RegY = UNKNOWN_REGVAL; break; case OP65_ROL: /* We don't know the value of the carry bit */ if (E->AM == AM65_ACC) { Out->RegA = UNKNOWN_REGVAL; } else if (E->AM == AM65_ZP) { switch (GetKnownReg (E->Chg & REG_ZP, In)) { case REG_TMP1: Out->Tmp1 = UNKNOWN_REGVAL; break; case REG_PTR1_LO: Out->Ptr1Lo = UNKNOWN_REGVAL; break; case REG_PTR1_HI: Out->Ptr1Hi = UNKNOWN_REGVAL; break; case REG_SREG_LO: Out->SRegLo = UNKNOWN_REGVAL; break; case REG_SREG_HI: Out->SRegHi = UNKNOWN_REGVAL; break; } } else if (E->AM == AM65_ZPX) { /* Invalidates all ZP registers */ RC_InvalidateZP (Out); } break; case OP65_ROR: /* We don't know the value of the carry bit */ if (E->AM == AM65_ACC) { Out->RegA = UNKNOWN_REGVAL; } else if (E->AM == AM65_ZP) { switch (GetKnownReg (E->Chg & REG_ZP, In)) { case REG_TMP1: Out->Tmp1 = UNKNOWN_REGVAL; break; case REG_PTR1_LO: Out->Ptr1Lo = UNKNOWN_REGVAL; break; case REG_PTR1_HI: Out->Ptr1Hi = UNKNOWN_REGVAL; break; case REG_SREG_LO: Out->SRegLo = UNKNOWN_REGVAL; break; case REG_SREG_HI: Out->SRegHi = UNKNOWN_REGVAL; break; } } else if (E->AM == AM65_ZPX) { /* Invalidates all ZP registers */ RC_InvalidateZP (Out); } break; case OP65_RTI: break; case OP65_RTS: break; case OP65_SBC: /* We don't know the value of the carry bit */ Out->RegA = UNKNOWN_REGVAL; break; case OP65_SEC: break; case OP65_SED: break; case OP65_SEI: break; case OP65_STA: if (E->AM == AM65_ZP) { switch (GetKnownReg (E->Chg & REG_ZP, 0)) { case REG_TMP1: Out->Tmp1 = In->RegA; break; case REG_PTR1_LO: Out->Ptr1Lo = In->RegA; break; case REG_PTR1_HI: Out->Ptr1Hi = In->RegA; break; case REG_SREG_LO: Out->SRegLo = In->RegA; break; case REG_SREG_HI: Out->SRegHi = In->RegA; break; } } else if (E->AM == AM65_ZPX) { /* Invalidates all ZP registers */ RC_InvalidateZP (Out); } break; case OP65_STX: if (E->AM == AM65_ZP) { switch (GetKnownReg (E->Chg & REG_ZP, 0)) { case REG_TMP1: Out->Tmp1 = In->RegX; break; case REG_PTR1_LO: Out->Ptr1Lo = In->RegX; break; case REG_PTR1_HI: Out->Ptr1Hi = In->RegX; break; case REG_SREG_LO: Out->SRegLo = In->RegX; break; case REG_SREG_HI: Out->SRegHi = In->RegX; break; } } else if (E->AM == AM65_ZPX) { /* Invalidates all ZP registers */ RC_InvalidateZP (Out); } break; case OP65_STY: if (E->AM == AM65_ZP) { switch (GetKnownReg (E->Chg & REG_ZP, 0)) { case REG_TMP1: Out->Tmp1 = In->RegY; break; case REG_PTR1_LO: Out->Ptr1Lo = In->RegY; break; case REG_PTR1_HI: Out->Ptr1Hi = In->RegY; break; case REG_SREG_LO: Out->SRegLo = In->RegY; break; case REG_SREG_HI: Out->SRegHi = In->RegY; break; } } else if (E->AM == AM65_ZPX) { /* Invalidates all ZP registers */ RC_InvalidateZP (Out); } break; case OP65_STZ: if (E->AM == AM65_ZP) { switch (GetKnownReg (E->Chg & REG_ZP, 0)) { case REG_TMP1: Out->Tmp1 = 0; break; case REG_PTR1_LO: Out->Ptr1Lo = 0; break; case REG_PTR1_HI: Out->Ptr1Hi = 0; break; case REG_SREG_LO: Out->SRegLo = 0; break; case REG_SREG_HI: Out->SRegHi = 0; break; } } else if (E->AM == AM65_ZPX) { /* Invalidates all ZP registers */ RC_InvalidateZP (Out); } break; case OP65_TAX: Out->RegX = In->RegA; break; case OP65_TAY: Out->RegY = In->RegA; break; case OP65_TRB: if (E->AM == AM65_ZPX) { /* Invalidates all ZP registers */ RC_InvalidateZP (Out); } else if (E->AM == AM65_ZP) { if (RegValIsKnown (In->RegA)) { switch (GetKnownReg (E->Chg & REG_ZP, In)) { case REG_TMP1: Out->Tmp1 &= ~In->RegA; break; case REG_PTR1_LO: Out->Ptr1Lo &= ~In->RegA; break; case REG_PTR1_HI: Out->Ptr1Hi &= ~In->RegA; break; case REG_SREG_LO: Out->SRegLo &= ~In->RegA; break; case REG_SREG_HI: Out->SRegHi &= ~In->RegA; break; } } else { switch (GetKnownReg (E->Chg & REG_ZP, In)) { case REG_TMP1: Out->Tmp1 = UNKNOWN_REGVAL; break; case REG_PTR1_LO: Out->Ptr1Lo = UNKNOWN_REGVAL; break; case REG_PTR1_HI: Out->Ptr1Hi = UNKNOWN_REGVAL; break; case REG_SREG_LO: Out->SRegLo = UNKNOWN_REGVAL; break; case REG_SREG_HI: Out->SRegHi = UNKNOWN_REGVAL; break; } } } break; case OP65_TSB: if (E->AM == AM65_ZPX) { /* Invalidates all ZP registers */ RC_InvalidateZP (Out); } else if (E->AM == AM65_ZP) { if (RegValIsKnown (In->RegA)) { switch (GetKnownReg (E->Chg & REG_ZP, In)) { case REG_TMP1: Out->Tmp1 |= In->RegA; break; case REG_PTR1_LO: Out->Ptr1Lo |= In->RegA; break; case REG_PTR1_HI: Out->Ptr1Hi |= In->RegA; break; case REG_SREG_LO: Out->SRegLo |= In->RegA; break; case REG_SREG_HI: Out->SRegHi |= In->RegA; break; } } else { switch (GetKnownReg (E->Chg & REG_ZP, In)) { case REG_TMP1: Out->Tmp1 = UNKNOWN_REGVAL; break; case REG_PTR1_LO: Out->Ptr1Lo = UNKNOWN_REGVAL; break; case REG_PTR1_HI: Out->Ptr1Hi = UNKNOWN_REGVAL; break; case REG_SREG_LO: Out->SRegLo = UNKNOWN_REGVAL; break; case REG_SREG_HI: Out->SRegHi = UNKNOWN_REGVAL; break; } } } break; case OP65_TSX: Out->RegX = UNKNOWN_REGVAL; break; case OP65_TXA: Out->RegA = In->RegX; break; case OP65_TXS: break; case OP65_TYA: Out->RegA = In->RegY; break; default: break; } } static char* RegInfoDesc (unsigned U, char* Buf) /* Return a string containing register info */ { Buf[0] = '\0'; strcat (Buf, U & REG_SREG_HI? "H" : "_"); strcat (Buf, U & REG_SREG_LO? "L" : "_"); strcat (Buf, U & REG_A? "A" : "_"); strcat (Buf, U & REG_X? "X" : "_"); strcat (Buf, U & REG_Y? "Y" : "_"); strcat (Buf, U & REG_TMP1? "T1" : "__"); strcat (Buf, U & REG_PTR1? "1" : "_"); strcat (Buf, U & REG_PTR2? "2" : "_"); strcat (Buf, U & REG_SAVE? "V" : "_"); strcat (Buf, U & REG_SP? "S" : "_"); return Buf; } static char* RegContentDesc (const RegContents* RC, char* Buf) /* Return a string containing register contents */ { char* B = Buf; if (RegValIsUnknown (RC->RegA)) { strcpy (B, "A:XX "); } else { sprintf (B, "A:%02X ", RC->RegA); } B += 5; if (RegValIsUnknown (RC->RegX)) { strcpy (B, "X:XX "); } else { sprintf (B, "X:%02X ", RC->RegX); } B += 5; if (RegValIsUnknown (RC->RegY)) { strcpy (B, "Y:XX"); } else { sprintf (B, "Y:%02X", RC->RegY); } B += 4; return Buf; } void CE_Output (const CodeEntry* E) /* Output the code entry to the output file */ { const OPCDesc* D; unsigned Chars; int Space; const char* Target; /* If we have a label, print that */ unsigned LabelCount = CollCount (&E->Labels); unsigned I; for (I = 0; I < LabelCount; ++I) { CL_Output (CollConstAt (&E->Labels, I)); } /* Get the opcode description */ D = GetOPCDesc (E->OPC); /* Print the mnemonic */ Chars = WriteOutput ("\t%s", D->Mnemo); /* Space to leave before the operand */ Space = 9 - Chars; /* Print the operand */ switch (E->AM) { case AM65_IMP: /* implicit */ break; case AM65_ACC: /* accumulator */ Chars += WriteOutput ("%*sa", Space, ""); break; case AM65_IMM: /* immidiate */ Chars += WriteOutput ("%*s#%s", Space, "", E->Arg); break; case AM65_ZP: case AM65_ABS: /* zeropage and absolute */ Chars += WriteOutput ("%*s%s", Space, "", E->Arg); break; case AM65_ZPX: case AM65_ABSX: /* zeropage,X and absolute,X */ Chars += WriteOutput ("%*s%s,x", Space, "", E->Arg); break; case AM65_ABSY: /* absolute,Y */ Chars += WriteOutput ("%*s%s,y", Space, "", E->Arg); break; case AM65_ZPX_IND: /* (zeropage,x) */ Chars += WriteOutput ("%*s(%s,x)", Space, "", E->Arg); break; case AM65_ZP_INDY: /* (zeropage),y */ Chars += WriteOutput ("%*s(%s),y", Space, "", E->Arg); break; case AM65_ZP_IND: /* (zeropage) */ Chars += WriteOutput ("%*s(%s)", Space, "", E->Arg); break; case AM65_BRA: /* branch */ Target = E->JumpTo? E->JumpTo->Name : E->Arg; Chars += WriteOutput ("%*s%s", Space, "", Target); break; default: Internal ("Invalid addressing mode"); } /* Print usage info if requested by the debugging flag */ if (Debug) { char Use [128]; char Chg [128]; WriteOutput ("%*s; USE: %-12s CHG: %-12s SIZE: %u", (int)(30-Chars), "", RegInfoDesc (E->Use, Use), RegInfoDesc (E->Chg, Chg), E->Size); if (E->RI) { char RegIn[32]; char RegOut[32]; WriteOutput (" In %s Out %s", RegContentDesc (&E->RI->In, RegIn), RegContentDesc (&E->RI->Out, RegOut)); } } /* Terminate the line */ WriteOutput ("\n"); } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/codeent.h������������������������������������������������������������������������0000664�0000000�0000000�00000020762�13473601511�0015335�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* codeent.h */ /* */ /* Code segment entry */ /* */ /* */ /* */ /* (C) 2001-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef CODEENT_H #define CODEENT_H #include <string.h> /* common */ #include "coll.h" #include "inline.h" /* cc65 */ #include "codelab.h" #include "lineinfo.h" #include "opcodes.h" #include "reginfo.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Flags used */ #define CEF_USERMARK 0x0001U /* Generic mark by user functions */ #define CEF_NUMARG 0x0002U /* Insn has numerical argument */ /* Code entry structure */ typedef struct CodeEntry CodeEntry; struct CodeEntry { unsigned char OPC; /* Opcode */ unsigned char AM; /* Adressing mode */ unsigned char Size; /* Estimated size */ unsigned char Flags; /* Flags */ char* Arg; /* Argument as string */ unsigned long Num; /* Numeric argument */ unsigned short Info; /* Additional code info */ unsigned short Use; /* Registers used */ unsigned short Chg; /* Registers changed/destroyed */ CodeLabel* JumpTo; /* Jump label */ Collection Labels; /* Labels for this instruction */ LineInfo* LI; /* Source line info for this insn */ RegInfo* RI; /* Register info for this insn */ }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ const char* MakeHexArg (unsigned Num); /* Convert Num into a string in the form $XY, suitable for passing it as an ** argument to NewCodeEntry, and return a pointer to the string. ** BEWARE: The function returns a pointer to a static buffer, so the value is ** gone if you call it twice (and apart from that it's not thread and signal ** safe). */ CodeEntry* NewCodeEntry (opc_t OPC, am_t AM, const char* Arg, CodeLabel* JumpTo, LineInfo* LI); /* Create a new code entry, initialize and return it */ void FreeCodeEntry (CodeEntry* E); /* Free the given code entry */ void CE_ReplaceOPC (CodeEntry* E, opc_t OPC); /* Replace the opcode of the instruction. This will also replace related info, ** Size, Use and Chg, but it will NOT update any arguments or labels. */ int CodeEntriesAreEqual (const CodeEntry* E1, const CodeEntry* E2); /* Check if both code entries are equal */ void CE_AttachLabel (CodeEntry* E, CodeLabel* L); /* Attach the label to the entry */ void CE_ClearJumpTo (CodeEntry* E); /* Clear the JumpTo entry and the argument (which contained the name of the ** label). Note: The function will not clear the backpointer from the label, ** so use it with care. */ #if defined(HAVE_INLINE) INLINE int CE_HasLabel (const CodeEntry* E) /* Check if the given code entry has labels attached */ { return (CollCount (&E->Labels) > 0); } #else # define CE_HasLabel(E) (CollCount (&(E)->Labels) > 0) #endif #if defined(HAVE_INLINE) INLINE unsigned CE_GetLabelCount (const CodeEntry* E) /* Get the number of labels attached to this entry */ { return CollCount (&E->Labels); } #else # define CE_GetLabelCount(E) CollCount (&(E)->Labels) #endif #if defined(HAVE_INLINE) INLINE CodeLabel* CE_GetLabel (CodeEntry* E, unsigned Index) /* Get a label from this code entry */ { return CollAt (&E->Labels, Index); } #else # define CE_GetLabel(E, Index) CollAt (&(E)->Labels, (Index)) #endif void CE_MoveLabel (CodeLabel* L, CodeEntry* E); /* Move the code label L from it's former owner to the code entry E. */ #if defined(HAVE_INLINE) INLINE int CE_HasMark (const CodeEntry* E) /* Return true if the given code entry has the CEF_USERMARK flag set */ { return (E->Flags & CEF_USERMARK) != 0; } #else # define CE_HasMark(E) (((E)->Flags & CEF_USERMARK) != 0) #endif #if defined(HAVE_INLINE) INLINE void CE_SetMark (CodeEntry* E) /* Set the CEF_USERMARK flag for the given entry */ { E->Flags |= CEF_USERMARK; } #else # define CE_SetMark(E) ((E)->Flags |= CEF_USERMARK) #endif #if defined(HAVE_INLINE) INLINE void CE_ResetMark (CodeEntry* E) /* Reset the CEF_USERMARK flag for the given entry */ { E->Flags &= ~CEF_USERMARK; } #else # define CE_ResetMark(E) ((E)->Flags &= ~CEF_USERMARK) #endif #if defined(HAVE_INLINE) INLINE int CE_HasNumArg (const CodeEntry* E) /* Return true if the instruction has a numeric argument */ { return (E->Flags & CEF_NUMARG) != 0; } #else # define CE_HasNumArg(E) (((E)->Flags & CEF_NUMARG) != 0) #endif void CE_SetArg (CodeEntry* E, const char* Arg); /* Replace the argument by the new one. */ void CE_SetNumArg (CodeEntry* E, long Num); /* Set a new numeric argument for the given code entry that must already ** have a numeric argument. */ int CE_IsConstImm (const CodeEntry* E); /* Return true if the argument of E is a constant immediate value */ int CE_IsKnownImm (const CodeEntry* E, unsigned long Num); /* Return true if the argument of E is a constant immediate value that is ** equal to Num. */ #if defined(HAVE_INLINE) INLINE int CE_IsCallTo (const CodeEntry* E, const char* Name) /* Check if this is a call to the given function */ { return (E->OPC == OP65_JSR && strcmp (E->Arg, Name) == 0); } #else # define CE_IsCallTo(E, Name) ((E)->OPC == OP65_JSR && strcmp ((E)->Arg, (Name)) == 0) #endif int CE_UseLoadFlags (CodeEntry* E); /* Return true if the instruction uses any flags that are set by a load of ** a register (N and Z). */ void CE_FreeRegInfo (CodeEntry* E); /* Free an existing register info struct */ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs); /* Generate register info for this instruction. If an old info exists, it is ** overwritten. */ void CE_Output (const CodeEntry* E); /* Output the code entry to the output file */ /* End of codeent.h */ #endif ��������������cc65-2.18/src/cc65/codegen.c������������������������������������������������������������������������0000664�0000000�0000000�00000402440�13473601511�0015310�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* codegen.c */ /* */ /* 6502 code generator */ /* */ /* */ /* */ /* (C) 1998-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> #include <stdarg.h> /* common */ #include "check.h" #include "cpu.h" #include "inttypes.h" #include "strbuf.h" #include "xmalloc.h" #include "xsprintf.h" #include "version.h" /* cc65 */ #include "asmcode.h" #include "asmlabel.h" #include "casenode.h" #include "codeseg.h" #include "dataseg.h" #include "error.h" #include "global.h" #include "segments.h" #include "stackptr.h" #include "stdfunc.h" #include "textseg.h" #include "util.h" #include "codegen.h" /*****************************************************************************/ /* Helpers */ /*****************************************************************************/ static void typeerror (unsigned type) /* Print an error message about an invalid operand type */ { /* Special handling for floats here: */ if ((type & CF_TYPEMASK) == CF_FLOAT) { Fatal ("Floating point type is currently unsupported"); } else { Internal ("Invalid type in CF flags: %04X, type = %u", type, type & CF_TYPEMASK); } } static void CheckLocalOffs (unsigned Offs) /* Check the offset into the stack for 8bit range */ { if (Offs >= 256) { /* Too many local vars */ Error ("Too many local variables"); } } static const char* GetLabelName (unsigned Flags, uintptr_t Label, long Offs) { static char Buf [256]; /* Label name */ /* Create the correct label name */ switch (Flags & CF_ADDRMASK) { case CF_STATIC: /* Static memory cell */ if (Offs) { xsprintf (Buf, sizeof (Buf), "%s%+ld", LocalLabelName (Label), Offs); } else { xsprintf (Buf, sizeof (Buf), "%s", LocalLabelName (Label)); } break; case CF_EXTERNAL: /* External label */ if (Offs) { xsprintf (Buf, sizeof (Buf), "_%s%+ld", (char*) Label, Offs); } else { xsprintf (Buf, sizeof (Buf), "_%s", (char*) Label); } break; case CF_ABSOLUTE: /* Absolute address */ xsprintf (Buf, sizeof (Buf), "$%04X", (unsigned)((Label+Offs) & 0xFFFF)); break; case CF_REGVAR: /* Variable in register bank */ xsprintf (Buf, sizeof (Buf), "regbank+%u", (unsigned)((Label+Offs) & 0xFFFF)); break; default: Internal ("Invalid address flags: %04X", Flags); } /* Return a pointer to the static buffer */ return Buf; } /*****************************************************************************/ /* Pre- and postamble */ /*****************************************************************************/ void g_preamble (void) /* Generate the assembler code preamble */ { /* Identify the compiler version */ AddTextLine (";"); AddTextLine ("; File generated by cc65 v %s", GetVersionAsString ()); AddTextLine (";"); /* Insert some object file options */ AddTextLine ("\t.fopt\t\tcompiler,\"cc65 v %s\"", GetVersionAsString ()); /* If we're producing code for some other CPU, switch the command set */ switch (CPU) { case CPU_6502: AddTextLine ("\t.setcpu\t\t\"6502\""); break; case CPU_6502X: AddTextLine ("\t.setcpu\t\t\"6502X\""); break; case CPU_65SC02: AddTextLine ("\t.setcpu\t\t\"65SC02\""); break; case CPU_65C02: AddTextLine ("\t.setcpu\t\t\"65C02\""); break; case CPU_65816: AddTextLine ("\t.setcpu\t\t\"65816\""); break; case CPU_HUC6280: AddTextLine ("\t.setcpu\t\t\"HUC6280\""); break; default: Internal ("Unknown CPU: %d", CPU); } /* Use smart mode */ AddTextLine ("\t.smart\t\ton"); /* Allow auto import for runtime library routines */ AddTextLine ("\t.autoimport\ton"); /* Switch the assembler into case sensitive mode */ AddTextLine ("\t.case\t\ton"); /* Tell the assembler if we want to generate debug info */ AddTextLine ("\t.debuginfo\t%s", (DebugInfo != 0)? "on" : "off"); /* Import zero page variables */ AddTextLine ("\t.importzp\tsp, sreg, regsave, regbank"); AddTextLine ("\t.importzp\ttmp1, tmp2, tmp3, tmp4, ptr1, ptr2, ptr3, ptr4"); /* Define long branch macros */ AddTextLine ("\t.macpack\tlongbranch"); } void g_fileinfo (const char* Name, unsigned long Size, unsigned long MTime) /* If debug info is enabled, place a file info into the source */ { if (DebugInfo) { /* We have to place this into the global text segment, so it will ** appear before all .dbg line statements. */ TS_AddLine (GS->Text, "\t.dbg\t\tfile, \"%s\", %lu, %lu", Name, Size, MTime); } } /*****************************************************************************/ /* Segment support */ /*****************************************************************************/ void g_userodata (void) /* Switch to the read only data segment */ { UseDataSeg (SEG_RODATA); } void g_usedata (void) /* Switch to the data segment */ { UseDataSeg (SEG_DATA); } void g_usebss (void) /* Switch to the bss segment */ { UseDataSeg (SEG_BSS); } void g_segname (segment_t Seg) /* Emit the name of a segment if necessary */ { /* Emit a segment directive for the data style segments */ DataSeg* S; switch (Seg) { case SEG_RODATA: S = CS->ROData; break; case SEG_DATA: S = CS->Data; break; case SEG_BSS: S = CS->BSS; break; default: S = 0; break; } if (S) { DS_AddLine (S, ".segment\t\"%s\"", GetSegName (Seg)); } } /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned sizeofarg (unsigned flags) /* Return the size of a function argument type that is encoded in flags */ { switch (flags & CF_TYPEMASK) { case CF_CHAR: return (flags & CF_FORCECHAR)? 1 : 2; case CF_INT: return 2; case CF_LONG: return 4; case CF_FLOAT: return 4; default: typeerror (flags); /* NOTREACHED */ return 2; } } int pop (unsigned flags) /* Pop an argument of the given size */ { return StackPtr += sizeofarg (flags); } int push (unsigned flags) /* Push an argument of the given size */ { return StackPtr -= sizeofarg (flags); } static unsigned MakeByteOffs (unsigned Flags, unsigned Offs) /* The value in Offs is an offset to an address in a/x. Make sure, an object ** of the type given in Flags can be loaded or stored into this address by ** adding part of the offset to the address in ax, so that the remaining ** offset fits into an index register. Return the remaining offset. */ { /* If the offset is too large for a byte register, add the high byte ** of the offset to the primary. Beware: We need a special correction ** if the offset in the low byte will overflow in the operation. */ unsigned O = Offs & ~0xFFU; if ((Offs & 0xFF) > 256 - sizeofarg (Flags)) { /* We need to add the low byte also */ O += Offs & 0xFF; } /* Do the correction if we need one */ if (O != 0) { g_inc (CF_INT | CF_CONST, O); Offs -= O; } /* Return the new offset */ return Offs; } /*****************************************************************************/ /* Functions handling local labels */ /*****************************************************************************/ void g_defcodelabel (unsigned label) /* Define a local code label */ { CS_AddLabel (CS->Code, LocalLabelName (label)); } void g_defdatalabel (unsigned label) /* Define a local data label */ { AddDataLine ("%s:", LocalLabelName (label)); } void g_aliasdatalabel (unsigned label, unsigned baselabel, long offs) /* Define label as a local alias for baselabel+offs */ { /* We need an intermediate buffer here since LocalLabelName uses a ** static buffer which changes with each call. */ StrBuf L = AUTO_STRBUF_INITIALIZER; SB_AppendStr (&L, LocalLabelName (label)); SB_Terminate (&L); AddDataLine ("%s\t:=\t%s+%ld", SB_GetConstBuf (&L), LocalLabelName (baselabel), offs); SB_Done (&L); } /*****************************************************************************/ /* Functions handling global labels */ /*****************************************************************************/ void g_defgloblabel (const char* Name) /* Define a global label with the given name */ { /* Global labels are always data labels */ AddDataLine ("_%s:", Name); } void g_defexport (const char* Name, int ZP) /* Export the given label */ { if (ZP) { AddTextLine ("\t.exportzp\t_%s", Name); } else { AddTextLine ("\t.export\t\t_%s", Name); } } void g_defimport (const char* Name, int ZP) /* Import the given label */ { if (ZP) { AddTextLine ("\t.importzp\t_%s", Name); } else { AddTextLine ("\t.import\t\t_%s", Name); } } void g_importstartup (void) /* Forced import of the startup module */ { AddTextLine ("\t.forceimport\t__STARTUP__"); } void g_importmainargs (void) /* Forced import of a special symbol that handles arguments to main */ { AddTextLine ("\t.forceimport\tinitmainargs"); } /*****************************************************************************/ /* Function entry and exit */ /*****************************************************************************/ /* Remember the argument size of a function. The variable is set by g_enter ** and used by g_leave. If the function gets its argument size by the caller ** (variable param list or function without prototype), g_enter will set the ** value to -1. */ static int funcargs; void g_enter (unsigned flags, unsigned argsize) /* Function prologue */ { if ((flags & CF_FIXARGC) != 0) { /* Just remember the argument size for the leave */ funcargs = argsize; } else { funcargs = -1; AddCodeLine ("jsr enter"); } } void g_leave (void) /* Function epilogue */ { /* How many bytes of locals do we have to drop? */ unsigned ToDrop = (unsigned) -StackPtr; /* If we didn't have a variable argument list, don't call leave */ if (funcargs >= 0) { /* Drop stackframe if needed */ g_drop (ToDrop + funcargs); } else if (StackPtr != 0) { /* We've a stack frame to drop */ if (ToDrop > 255) { g_drop (ToDrop); /* Inlines the code */ AddCodeLine ("jsr leave"); } else { AddCodeLine ("ldy #$%02X", ToDrop); AddCodeLine ("jsr leavey"); } } else { /* Nothing to drop */ AddCodeLine ("jsr leave"); } /* Add the final rts */ AddCodeLine ("rts"); } /*****************************************************************************/ /* Register variables */ /*****************************************************************************/ void g_swap_regvars (int StackOffs, int RegOffs, unsigned Bytes) /* Swap a register variable with a location on the stack */ { /* Calculate the actual stack offset and check it */ StackOffs -= StackPtr; CheckLocalOffs (StackOffs); /* Generate code */ AddCodeLine ("ldy #$%02X", StackOffs & 0xFF); if (Bytes == 1) { if (IS_Get (&CodeSizeFactor) < 165) { AddCodeLine ("ldx #$%02X", RegOffs & 0xFF); AddCodeLine ("jsr regswap1"); } else { AddCodeLine ("lda (sp),y"); AddCodeLine ("ldx regbank%+d", RegOffs); AddCodeLine ("sta regbank%+d", RegOffs); AddCodeLine ("txa"); AddCodeLine ("sta (sp),y"); } } else if (Bytes == 2) { AddCodeLine ("ldx #$%02X", RegOffs & 0xFF); AddCodeLine ("jsr regswap2"); } else { AddCodeLine ("ldx #$%02X", RegOffs & 0xFF); AddCodeLine ("lda #$%02X", Bytes & 0xFF); AddCodeLine ("jsr regswap"); } } void g_save_regvars (int RegOffs, unsigned Bytes) /* Save register variables */ { /* Don't loop for up to two bytes */ if (Bytes == 1) { AddCodeLine ("lda regbank%+d", RegOffs); AddCodeLine ("jsr pusha"); } else if (Bytes == 2) { AddCodeLine ("lda regbank%+d", RegOffs); AddCodeLine ("ldx regbank%+d", RegOffs+1); AddCodeLine ("jsr pushax"); } else { /* More than two bytes - loop */ unsigned Label = GetLocalLabel (); g_space (Bytes); AddCodeLine ("ldy #$%02X", (unsigned char) (Bytes - 1)); AddCodeLine ("ldx #$%02X", (unsigned char) Bytes); g_defcodelabel (Label); AddCodeLine ("lda regbank%+d,x", RegOffs-1); AddCodeLine ("sta (sp),y"); AddCodeLine ("dey"); AddCodeLine ("dex"); AddCodeLine ("bne %s", LocalLabelName (Label)); } /* We pushed stuff, correct the stack pointer */ StackPtr -= Bytes; } void g_restore_regvars (int StackOffs, int RegOffs, unsigned Bytes) /* Restore register variables */ { /* Calculate the actual stack offset and check it */ StackOffs -= StackPtr; CheckLocalOffs (StackOffs); /* Don't loop for up to two bytes */ if (Bytes == 1) { AddCodeLine ("ldy #$%02X", StackOffs); AddCodeLine ("lda (sp),y"); AddCodeLine ("sta regbank%+d", RegOffs); } else if (Bytes == 2) { AddCodeLine ("ldy #$%02X", StackOffs); AddCodeLine ("lda (sp),y"); AddCodeLine ("sta regbank%+d", RegOffs); AddCodeLine ("iny"); AddCodeLine ("lda (sp),y"); AddCodeLine ("sta regbank%+d", RegOffs+1); } else if (Bytes == 3 && IS_Get (&CodeSizeFactor) >= 133) { AddCodeLine ("ldy #$%02X", StackOffs); AddCodeLine ("lda (sp),y"); AddCodeLine ("sta regbank%+d", RegOffs); AddCodeLine ("iny"); AddCodeLine ("lda (sp),y"); AddCodeLine ("sta regbank%+d", RegOffs+1); AddCodeLine ("iny"); AddCodeLine ("lda (sp),y"); AddCodeLine ("sta regbank%+d", RegOffs+2); } else if (StackOffs <= RegOffs) { /* More bytes, but the relation between the register offset in the ** register bank and the stack offset allows us to generate short ** code that uses just one index register. */ unsigned Label = GetLocalLabel (); AddCodeLine ("ldy #$%02X", StackOffs); g_defcodelabel (Label); AddCodeLine ("lda (sp),y"); AddCodeLine ("sta regbank%+d,y", RegOffs - StackOffs); AddCodeLine ("iny"); AddCodeLine ("cpy #$%02X", StackOffs + Bytes); AddCodeLine ("bne %s", LocalLabelName (Label)); } else { /* OK, this is the generic code. We need to save X because the ** caller will only save A. */ unsigned Label = GetLocalLabel (); AddCodeLine ("stx tmp1"); AddCodeLine ("ldy #$%02X", (unsigned char) (StackOffs + Bytes - 1)); AddCodeLine ("ldx #$%02X", (unsigned char) (Bytes - 1)); g_defcodelabel (Label); AddCodeLine ("lda (sp),y"); AddCodeLine ("sta regbank%+d,x", RegOffs); AddCodeLine ("dey"); AddCodeLine ("dex"); AddCodeLine ("bpl %s", LocalLabelName (Label)); AddCodeLine ("ldx tmp1"); } } /*****************************************************************************/ /* Fetching memory cells */ /*****************************************************************************/ void g_getimmed (unsigned Flags, unsigned long Val, long Offs) /* Load a constant into the primary register */ { unsigned char B1, B2, B3, B4; unsigned Done; if ((Flags & CF_CONST) != 0) { /* Numeric constant */ switch (Flags & CF_TYPEMASK) { case CF_CHAR: if ((Flags & CF_FORCECHAR) != 0) { AddCodeLine ("lda #$%02X", (unsigned char) Val); break; } /* FALL THROUGH */ case CF_INT: AddCodeLine ("ldx #$%02X", (unsigned char) (Val >> 8)); AddCodeLine ("lda #$%02X", (unsigned char) Val); break; case CF_LONG: /* Split the value into 4 bytes */ B1 = (unsigned char) (Val >> 0); B2 = (unsigned char) (Val >> 8); B3 = (unsigned char) (Val >> 16); B4 = (unsigned char) (Val >> 24); /* Remember which bytes are done */ Done = 0; /* Load the value */ AddCodeLine ("ldx #$%02X", B2); Done |= 0x02; if (B2 == B3) { AddCodeLine ("stx sreg"); Done |= 0x04; } if (B2 == B4) { AddCodeLine ("stx sreg+1"); Done |= 0x08; } if ((Done & 0x04) == 0 && B1 != B3) { AddCodeLine ("lda #$%02X", B3); AddCodeLine ("sta sreg"); Done |= 0x04; } if ((Done & 0x08) == 0 && B1 != B4) { AddCodeLine ("lda #$%02X", B4); AddCodeLine ("sta sreg+1"); Done |= 0x08; } AddCodeLine ("lda #$%02X", B1); Done |= 0x01; if ((Done & 0x04) == 0) { CHECK (B1 == B3); AddCodeLine ("sta sreg"); } if ((Done & 0x08) == 0) { CHECK (B1 == B4); AddCodeLine ("sta sreg+1"); } break; default: typeerror (Flags); break; } } else { /* Some sort of label */ const char* Label = GetLabelName (Flags, Val, Offs); /* Load the address into the primary */ AddCodeLine ("lda #<(%s)", Label); AddCodeLine ("ldx #>(%s)", Label); } } void g_getstatic (unsigned flags, uintptr_t label, long offs) /* Fetch an static memory cell into the primary register */ { /* Create the correct label name */ const char* lbuf = GetLabelName (flags, label, offs); /* Check the size and generate the correct load operation */ switch (flags & CF_TYPEMASK) { case CF_CHAR: if ((flags & CF_FORCECHAR) || (flags & CF_TEST)) { AddCodeLine ("lda %s", lbuf); /* load A from the label */ } else { AddCodeLine ("ldx #$00"); AddCodeLine ("lda %s", lbuf); /* load A from the label */ if (!(flags & CF_UNSIGNED)) { /* Must sign extend */ unsigned L = GetLocalLabel (); AddCodeLine ("bpl %s", LocalLabelName (L)); AddCodeLine ("dex"); g_defcodelabel (L); } } break; case CF_INT: AddCodeLine ("lda %s", lbuf); if (flags & CF_TEST) { AddCodeLine ("ora %s+1", lbuf); } else { AddCodeLine ("ldx %s+1", lbuf); } break; case CF_LONG: if (flags & CF_TEST) { AddCodeLine ("lda %s+3", lbuf); AddCodeLine ("ora %s+2", lbuf); AddCodeLine ("ora %s+1", lbuf); AddCodeLine ("ora %s+0", lbuf); } else { AddCodeLine ("lda %s+3", lbuf); AddCodeLine ("sta sreg+1"); AddCodeLine ("lda %s+2", lbuf); AddCodeLine ("sta sreg"); AddCodeLine ("ldx %s+1", lbuf); AddCodeLine ("lda %s", lbuf); } break; default: typeerror (flags); } } void g_getlocal (unsigned Flags, int Offs) /* Fetch specified local object (local var). */ { Offs -= StackPtr; switch (Flags & CF_TYPEMASK) { case CF_CHAR: CheckLocalOffs (Offs); if ((Flags & CF_FORCECHAR) || (Flags & CF_TEST)) { AddCodeLine ("ldy #$%02X", Offs); AddCodeLine ("lda (sp),y"); } else { AddCodeLine ("ldy #$%02X", Offs); AddCodeLine ("ldx #$00"); AddCodeLine ("lda (sp),y"); if ((Flags & CF_UNSIGNED) == 0) { unsigned L = GetLocalLabel(); AddCodeLine ("bpl %s", LocalLabelName (L)); AddCodeLine ("dex"); g_defcodelabel (L); } } break; case CF_INT: CheckLocalOffs (Offs + 1); AddCodeLine ("ldy #$%02X", (unsigned char) (Offs+1)); if (Flags & CF_TEST) { AddCodeLine ("lda (sp),y"); AddCodeLine ("dey"); AddCodeLine ("ora (sp),y"); } else { AddCodeLine ("jsr ldaxysp"); } break; case CF_LONG: CheckLocalOffs (Offs + 3); AddCodeLine ("ldy #$%02X", (unsigned char) (Offs+3)); AddCodeLine ("jsr ldeaxysp"); if (Flags & CF_TEST) { g_test (Flags); } break; default: typeerror (Flags); } } void g_getind (unsigned Flags, unsigned Offs) /* Fetch the specified object type indirect through the primary register ** into the primary register */ { /* If the offset is greater than 255, add the part that is > 255 to ** the primary. This way we get an easy addition and use the low byte ** as the offset */ Offs = MakeByteOffs (Flags, Offs); /* Handle the indirect fetch */ switch (Flags & CF_TYPEMASK) { case CF_CHAR: /* Character sized */ AddCodeLine ("ldy #$%02X", Offs); if (Flags & CF_UNSIGNED) { AddCodeLine ("jsr ldauidx"); } else { AddCodeLine ("jsr ldaidx"); } break; case CF_INT: if (Flags & CF_TEST) { AddCodeLine ("ldy #$%02X", Offs); AddCodeLine ("sta ptr1"); AddCodeLine ("stx ptr1+1"); AddCodeLine ("lda (ptr1),y"); AddCodeLine ("iny"); AddCodeLine ("ora (ptr1),y"); } else { AddCodeLine ("ldy #$%02X", Offs+1); AddCodeLine ("jsr ldaxidx"); } break; case CF_LONG: AddCodeLine ("ldy #$%02X", Offs+3); AddCodeLine ("jsr ldeaxidx"); if (Flags & CF_TEST) { g_test (Flags); } break; default: typeerror (Flags); } } void g_leasp (int Offs) /* Fetch the address of the specified symbol into the primary register */ { unsigned char Lo, Hi; /* Calculate the offset relative to sp */ Offs -= StackPtr; /* Get low and high byte */ Lo = (unsigned char) Offs; Hi = (unsigned char) (Offs >> 8); /* Generate code */ if (Lo == 0) { if (Hi <= 3) { AddCodeLine ("lda sp"); AddCodeLine ("ldx sp+1"); while (Hi--) { AddCodeLine ("inx"); } } else { AddCodeLine ("lda sp+1"); AddCodeLine ("clc"); AddCodeLine ("adc #$%02X", Hi); AddCodeLine ("tax"); AddCodeLine ("lda sp"); } } else if (Hi == 0) { /* 8 bit offset */ if (IS_Get (&CodeSizeFactor) < 200) { /* 8 bit offset with subroutine call */ AddCodeLine ("lda #$%02X", Lo); AddCodeLine ("jsr leaa0sp"); } else { /* 8 bit offset inlined */ unsigned L = GetLocalLabel (); AddCodeLine ("lda sp"); AddCodeLine ("ldx sp+1"); AddCodeLine ("clc"); AddCodeLine ("adc #$%02X", Lo); AddCodeLine ("bcc %s", LocalLabelName (L)); AddCodeLine ("inx"); g_defcodelabel (L); } } else if (IS_Get (&CodeSizeFactor) < 170) { /* Full 16 bit offset with subroutine call */ AddCodeLine ("lda #$%02X", Lo); AddCodeLine ("ldx #$%02X", Hi); AddCodeLine ("jsr leaaxsp"); } else { /* Full 16 bit offset inlined */ AddCodeLine ("lda sp"); AddCodeLine ("clc"); AddCodeLine ("adc #$%02X", Lo); AddCodeLine ("pha"); AddCodeLine ("lda sp+1"); AddCodeLine ("adc #$%02X", Hi); AddCodeLine ("tax"); AddCodeLine ("pla"); } } void g_leavariadic (int Offs) /* Fetch the address of a parameter in a variadic function into the primary ** register */ { unsigned ArgSizeOffs; /* Calculate the offset relative to sp */ Offs -= StackPtr; /* Get the offset of the parameter which is stored at sp+0 on function ** entry and check if this offset is reachable with a byte offset. */ CHECK (StackPtr <= 0); ArgSizeOffs = -StackPtr; CheckLocalOffs (ArgSizeOffs); /* Get the size of all parameters. */ AddCodeLine ("ldy #$%02X", ArgSizeOffs); AddCodeLine ("lda (sp),y"); /* Add the value of the stackpointer */ if (IS_Get (&CodeSizeFactor) > 250) { unsigned L = GetLocalLabel(); AddCodeLine ("ldx sp+1"); AddCodeLine ("clc"); AddCodeLine ("adc sp"); AddCodeLine ("bcc %s", LocalLabelName (L)); AddCodeLine ("inx"); g_defcodelabel (L); } else { AddCodeLine ("ldx #$00"); AddCodeLine ("jsr leaaxsp"); } /* Add the offset to the primary */ if (Offs > 0) { g_inc (CF_INT | CF_CONST, Offs); } else if (Offs < 0) { g_dec (CF_INT | CF_CONST, -Offs); } } /*****************************************************************************/ /* Store into memory */ /*****************************************************************************/ void g_putstatic (unsigned flags, uintptr_t label, long offs) /* Store the primary register into the specified static memory cell */ { /* Create the correct label name */ const char* lbuf = GetLabelName (flags, label, offs); /* Check the size and generate the correct store operation */ switch (flags & CF_TYPEMASK) { case CF_CHAR: AddCodeLine ("sta %s", lbuf); break; case CF_INT: AddCodeLine ("sta %s", lbuf); AddCodeLine ("stx %s+1", lbuf); break; case CF_LONG: AddCodeLine ("sta %s", lbuf); AddCodeLine ("stx %s+1", lbuf); AddCodeLine ("ldy sreg"); AddCodeLine ("sty %s+2", lbuf); AddCodeLine ("ldy sreg+1"); AddCodeLine ("sty %s+3", lbuf); break; default: typeerror (flags); } } void g_putlocal (unsigned Flags, int Offs, long Val) /* Put data into local object. */ { Offs -= StackPtr; CheckLocalOffs (Offs); switch (Flags & CF_TYPEMASK) { case CF_CHAR: if (Flags & CF_CONST) { AddCodeLine ("lda #$%02X", (unsigned char) Val); } AddCodeLine ("ldy #$%02X", Offs); AddCodeLine ("sta (sp),y"); break; case CF_INT: if (Flags & CF_CONST) { AddCodeLine ("ldy #$%02X", Offs+1); AddCodeLine ("lda #$%02X", (unsigned char) (Val >> 8)); AddCodeLine ("sta (sp),y"); if ((Flags & CF_NOKEEP) == 0) { /* Place high byte into X */ AddCodeLine ("tax"); } if ((Val & 0xFF) == Offs+1) { /* The value we need is already in Y */ AddCodeLine ("tya"); AddCodeLine ("dey"); } else { AddCodeLine ("dey"); AddCodeLine ("lda #$%02X", (unsigned char) Val); } AddCodeLine ("sta (sp),y"); } else { AddCodeLine ("ldy #$%02X", Offs); if ((Flags & CF_NOKEEP) == 0 || IS_Get (&CodeSizeFactor) < 160) { AddCodeLine ("jsr staxysp"); } else { AddCodeLine ("sta (sp),y"); AddCodeLine ("iny"); AddCodeLine ("txa"); AddCodeLine ("sta (sp),y"); } } break; case CF_LONG: if (Flags & CF_CONST) { g_getimmed (Flags, Val, 0); } AddCodeLine ("ldy #$%02X", Offs); AddCodeLine ("jsr steaxysp"); break; default: typeerror (Flags); } } void g_putind (unsigned Flags, unsigned Offs) /* Store the specified object type in the primary register at the address ** on the top of the stack */ { /* We can handle offsets below $100 directly, larger offsets must be added ** to the address. Since a/x is in use, best code is achieved by adding ** just the high byte. Be sure to check if the low byte will overflow while ** while storing. */ if ((Offs & 0xFF) > 256 - sizeofarg (Flags | CF_FORCECHAR)) { /* Overflow - we need to add the low byte also */ AddCodeLine ("ldy #$00"); AddCodeLine ("clc"); AddCodeLine ("pha"); AddCodeLine ("lda #$%02X", Offs & 0xFF); AddCodeLine ("adc (sp),y"); AddCodeLine ("sta (sp),y"); AddCodeLine ("iny"); AddCodeLine ("lda #$%02X", (Offs >> 8) & 0xFF); AddCodeLine ("adc (sp),y"); AddCodeLine ("sta (sp),y"); AddCodeLine ("pla"); /* Complete address is on stack, new offset is zero */ Offs = 0; } else if ((Offs & 0xFF00) != 0) { /* We can just add the high byte */ AddCodeLine ("ldy #$01"); AddCodeLine ("clc"); AddCodeLine ("pha"); AddCodeLine ("lda #$%02X", (Offs >> 8) & 0xFF); AddCodeLine ("adc (sp),y"); AddCodeLine ("sta (sp),y"); AddCodeLine ("pla"); /* Offset is now just the low byte */ Offs &= 0x00FF; } /* Check the size and determine operation */ AddCodeLine ("ldy #$%02X", Offs); switch (Flags & CF_TYPEMASK) { case CF_CHAR: AddCodeLine ("jsr staspidx"); break; case CF_INT: AddCodeLine ("jsr staxspidx"); break; case CF_LONG: AddCodeLine ("jsr steaxspidx"); break; default: typeerror (Flags); } /* Pop the argument which is always a pointer */ pop (CF_PTR); } /*****************************************************************************/ /* type conversion and similiar stuff */ /*****************************************************************************/ void g_toslong (unsigned flags) /* Make sure, the value on TOS is a long. Convert if necessary */ { switch (flags & CF_TYPEMASK) { case CF_CHAR: case CF_INT: if (flags & CF_UNSIGNED) { AddCodeLine ("jsr tosulong"); } else { AddCodeLine ("jsr toslong"); } push (CF_INT); break; case CF_LONG: break; default: typeerror (flags); } } void g_tosint (unsigned flags) /* Make sure, the value on TOS is an int. Convert if necessary */ { switch (flags & CF_TYPEMASK) { case CF_CHAR: case CF_INT: break; case CF_LONG: AddCodeLine ("jsr tosint"); pop (CF_INT); break; default: typeerror (flags); } } static void g_regchar (unsigned Flags) /* Make sure, the value in the primary register is in the range of char. Truncate if necessary */ { unsigned L; AddCodeLine ("ldx #$00"); if ((Flags & CF_UNSIGNED) == 0) { /* Sign extend */ L = GetLocalLabel(); AddCodeLine ("cmp #$80"); AddCodeLine ("bcc %s", LocalLabelName (L)); AddCodeLine ("dex"); g_defcodelabel (L); } } void g_regint (unsigned Flags) /* Make sure, the value in the primary register an int. Convert if necessary */ { switch (Flags & CF_TYPEMASK) { case CF_CHAR: if (Flags & CF_FORCECHAR) { /* Conversion is from char */ g_regchar (Flags); } /* FALLTHROUGH */ case CF_INT: case CF_LONG: break; default: typeerror (Flags); } } void g_reglong (unsigned Flags) /* Make sure, the value in the primary register a long. Convert if necessary */ { switch (Flags & CF_TYPEMASK) { case CF_CHAR: if (Flags & CF_FORCECHAR) { /* Conversion is from char */ if (Flags & CF_UNSIGNED) { if (IS_Get (&CodeSizeFactor) >= 200) { AddCodeLine ("ldx #$00"); AddCodeLine ("stx sreg"); AddCodeLine ("stx sreg+1"); } else { AddCodeLine ("jsr aulong"); } } else { if (IS_Get (&CodeSizeFactor) >= 366) { g_regchar (Flags); AddCodeLine ("stx sreg"); AddCodeLine ("stx sreg+1"); } else { AddCodeLine ("jsr along"); } } } /* FALLTHROUGH */ case CF_INT: if (Flags & CF_UNSIGNED) { if (IS_Get (&CodeSizeFactor) >= 200) { AddCodeLine ("ldy #$00"); AddCodeLine ("sty sreg"); AddCodeLine ("sty sreg+1"); } else { AddCodeLine ("jsr axulong"); } } else { AddCodeLine ("jsr axlong"); } break; case CF_LONG: break; default: typeerror (Flags); } } unsigned g_typeadjust (unsigned lhs, unsigned rhs) /* Adjust the integer operands before doing a binary operation. lhs is a flags ** value, that corresponds to the value on TOS, rhs corresponds to the value ** in (e)ax. The return value is the the flags value for the resulting type. */ { unsigned ltype, rtype; unsigned result; /* Get the type spec from the flags */ ltype = lhs & CF_TYPEMASK; rtype = rhs & CF_TYPEMASK; /* Check if a conversion is needed */ if (ltype == CF_LONG && rtype != CF_LONG && (rhs & CF_CONST) == 0) { /* We must promote the primary register to long */ g_reglong (rhs); /* Get the new rhs type */ rhs = (rhs & ~CF_TYPEMASK) | CF_LONG; rtype = CF_LONG; } else if (ltype != CF_LONG && (lhs & CF_CONST) == 0 && rtype == CF_LONG) { /* We must promote the lhs to long */ if (lhs & CF_REG) { g_reglong (lhs); } else { g_toslong (lhs); } /* Get the new rhs type */ lhs = (lhs & ~CF_TYPEMASK) | CF_LONG; ltype = CF_LONG; } /* Determine the result type for the operation: ** - The result is const if both operands are const. ** - The result is unsigned if one of the operands is unsigned. ** - The result is long if one of the operands is long. ** - Otherwise the result is int sized. */ result = (lhs & CF_CONST) & (rhs & CF_CONST); result |= (lhs & CF_UNSIGNED) | (rhs & CF_UNSIGNED); if (rtype == CF_LONG || ltype == CF_LONG) { result |= CF_LONG; } else { result |= CF_INT; } return result; } unsigned g_typecast (unsigned lhs, unsigned rhs) /* Cast the value in the primary register to the operand size that is flagged ** by the lhs value. Return the result value. */ { /* Check if a conversion is needed */ if ((rhs & CF_CONST) == 0) { switch (lhs & CF_TYPEMASK) { case CF_LONG: /* We must promote the primary register to long */ g_reglong (rhs); break; case CF_INT: /* We must promote the primary register to int */ g_regint (rhs); break; case CF_CHAR: /* We must truncate the primary register to char */ g_regchar (lhs); break; default: typeerror (lhs); } } /* Do not need any other action. If the left type is int, and the primary ** register is long, it will be automagically truncated. If the right hand ** side is const, it is not located in the primary register and handled by ** the expression parser code. */ /* Result is const if the right hand side was const */ lhs |= (rhs & CF_CONST); /* The resulting type is that of the left hand side (that's why you called ** this function :-) */ return lhs; } void g_scale (unsigned flags, long val) /* Scale the value in the primary register by the given value. If val is positive, ** scale up, is val is negative, scale down. This function is used to scale ** the operands or results of pointer arithmetic by the size of the type, the ** pointer points to. */ { int p2; /* Value may not be zero */ if (val == 0) { Internal ("Data type has no size"); } else if (val > 0) { /* Scale up */ if ((p2 = PowerOf2 (val)) > 0 && p2 <= 4) { /* Factor is 2, 4, 8 and 16, use special function */ switch (flags & CF_TYPEMASK) { case CF_CHAR: if (flags & CF_FORCECHAR) { while (p2--) { AddCodeLine ("asl a"); } break; } /* FALLTHROUGH */ case CF_INT: if (flags & CF_UNSIGNED) { AddCodeLine ("jsr shlax%d", p2); } else { AddCodeLine ("jsr aslax%d", p2); } break; case CF_LONG: if (flags & CF_UNSIGNED) { AddCodeLine ("jsr shleax%d", p2); } else { AddCodeLine ("jsr asleax%d", p2); } break; default: typeerror (flags); } } else if (val != 1) { /* Use a multiplication instead */ g_mul (flags | CF_CONST, val); } } else { /* Scale down */ val = -val; if ((p2 = PowerOf2 (val)) > 0 && p2 <= 4) { /* Factor is 2, 4, 8 and 16 use special function */ switch (flags & CF_TYPEMASK) { case CF_CHAR: if (flags & CF_FORCECHAR) { if (flags & CF_UNSIGNED) { while (p2--) { AddCodeLine ("lsr a"); } break; } else if (p2 <= 2) { AddCodeLine ("cmp #$80"); AddCodeLine ("ror a"); break; } } /* FALLTHROUGH */ case CF_INT: if (flags & CF_UNSIGNED) { AddCodeLine ("jsr lsrax%d", p2); } else { AddCodeLine ("jsr asrax%d", p2); } break; case CF_LONG: if (flags & CF_UNSIGNED) { AddCodeLine ("jsr lsreax%d", p2); } else { AddCodeLine ("jsr asreax%d", p2); } break; default: typeerror (flags); } } else if (val != 1) { /* Use a division instead */ g_div (flags | CF_CONST, val); } } } /*****************************************************************************/ /* Adds and subs of variables fix a fixed address */ /*****************************************************************************/ void g_addlocal (unsigned flags, int offs) /* Add a local variable to ax */ { unsigned L; /* Correct the offset and check it */ offs -= StackPtr; CheckLocalOffs (offs); switch (flags & CF_TYPEMASK) { case CF_CHAR: L = GetLocalLabel(); AddCodeLine ("ldy #$%02X", offs & 0xFF); AddCodeLine ("clc"); AddCodeLine ("adc (sp),y"); AddCodeLine ("bcc %s", LocalLabelName (L)); AddCodeLine ("inx"); g_defcodelabel (L); break; case CF_INT: AddCodeLine ("ldy #$%02X", offs & 0xFF); AddCodeLine ("clc"); AddCodeLine ("adc (sp),y"); AddCodeLine ("pha"); AddCodeLine ("txa"); AddCodeLine ("iny"); AddCodeLine ("adc (sp),y"); AddCodeLine ("tax"); AddCodeLine ("pla"); break; case CF_LONG: /* Do it the old way */ g_push (flags, 0); g_getlocal (flags, offs); g_add (flags, 0); break; default: typeerror (flags); } } void g_addstatic (unsigned flags, uintptr_t label, long offs) /* Add a static variable to ax */ { unsigned L; /* Create the correct label name */ const char* lbuf = GetLabelName (flags, label, offs); switch (flags & CF_TYPEMASK) { case CF_CHAR: L = GetLocalLabel(); AddCodeLine ("clc"); AddCodeLine ("adc %s", lbuf); AddCodeLine ("bcc %s", LocalLabelName (L)); AddCodeLine ("inx"); g_defcodelabel (L); break; case CF_INT: AddCodeLine ("clc"); AddCodeLine ("adc %s", lbuf); AddCodeLine ("tay"); AddCodeLine ("txa"); AddCodeLine ("adc %s+1", lbuf); AddCodeLine ("tax"); AddCodeLine ("tya"); break; case CF_LONG: /* Do it the old way */ g_push (flags, 0); g_getstatic (flags, label, offs); g_add (flags, 0); break; default: typeerror (flags); } } /*****************************************************************************/ /* Special op= functions */ /*****************************************************************************/ void g_addeqstatic (unsigned flags, uintptr_t label, long offs, unsigned long val) /* Emit += for a static variable */ { /* Create the correct label name */ const char* lbuf = GetLabelName (flags, label, offs); /* Check the size and determine operation */ switch (flags & CF_TYPEMASK) { case CF_CHAR: if (flags & CF_FORCECHAR) { AddCodeLine ("ldx #$00"); if (flags & CF_CONST) { if (val == 1) { AddCodeLine ("inc %s", lbuf); AddCodeLine ("lda %s", lbuf); } else { AddCodeLine ("lda #$%02X", (int)(val & 0xFF)); AddCodeLine ("clc"); AddCodeLine ("adc %s", lbuf); AddCodeLine ("sta %s", lbuf); } } else { AddCodeLine ("clc"); AddCodeLine ("adc %s", lbuf); AddCodeLine ("sta %s", lbuf); } if ((flags & CF_UNSIGNED) == 0) { unsigned L = GetLocalLabel(); AddCodeLine ("bpl %s", LocalLabelName (L)); AddCodeLine ("dex"); g_defcodelabel (L); } break; } /* FALLTHROUGH */ case CF_INT: if (flags & CF_CONST) { if (val == 1) { unsigned L = GetLocalLabel (); AddCodeLine ("inc %s", lbuf); AddCodeLine ("bne %s", LocalLabelName (L)); AddCodeLine ("inc %s+1", lbuf); g_defcodelabel (L); AddCodeLine ("lda %s", lbuf); /* Hmmm... */ AddCodeLine ("ldx %s+1", lbuf); } else { AddCodeLine ("lda #$%02X", (int)(val & 0xFF)); AddCodeLine ("clc"); AddCodeLine ("adc %s", lbuf); AddCodeLine ("sta %s", lbuf); if (val < 0x100) { unsigned L = GetLocalLabel (); AddCodeLine ("bcc %s", LocalLabelName (L)); AddCodeLine ("inc %s+1", lbuf); g_defcodelabel (L); AddCodeLine ("ldx %s+1", lbuf); } else { AddCodeLine ("lda #$%02X", (unsigned char)(val >> 8)); AddCodeLine ("adc %s+1", lbuf); AddCodeLine ("sta %s+1", lbuf); AddCodeLine ("tax"); AddCodeLine ("lda %s", lbuf); } } } else { AddCodeLine ("clc"); AddCodeLine ("adc %s", lbuf); AddCodeLine ("sta %s", lbuf); AddCodeLine ("txa"); AddCodeLine ("adc %s+1", lbuf); AddCodeLine ("sta %s+1", lbuf); AddCodeLine ("tax"); AddCodeLine ("lda %s", lbuf); } break; case CF_LONG: if (flags & CF_CONST) { if (val < 0x100) { AddCodeLine ("ldy #<(%s)", lbuf); AddCodeLine ("sty ptr1"); AddCodeLine ("ldy #>(%s)", lbuf); if (val == 1) { AddCodeLine ("jsr laddeq1"); } else { AddCodeLine ("lda #$%02X", (int)(val & 0xFF)); AddCodeLine ("jsr laddeqa"); } } else { g_getstatic (flags, label, offs); g_inc (flags, val); g_putstatic (flags, label, offs); } } else { AddCodeLine ("ldy #<(%s)", lbuf); AddCodeLine ("sty ptr1"); AddCodeLine ("ldy #>(%s)", lbuf); AddCodeLine ("jsr laddeq"); } break; default: typeerror (flags); } } void g_addeqlocal (unsigned flags, int Offs, unsigned long val) /* Emit += for a local variable */ { /* Calculate the true offset, check it, load it into Y */ Offs -= StackPtr; CheckLocalOffs (Offs); /* Check the size and determine operation */ switch (flags & CF_TYPEMASK) { case CF_CHAR: if (flags & CF_FORCECHAR) { AddCodeLine ("ldy #$%02X", Offs); AddCodeLine ("ldx #$00"); if (flags & CF_CONST) { AddCodeLine ("clc"); AddCodeLine ("lda #$%02X", (int)(val & 0xFF)); AddCodeLine ("adc (sp),y"); AddCodeLine ("sta (sp),y"); } else { AddCodeLine ("clc"); AddCodeLine ("adc (sp),y"); AddCodeLine ("sta (sp),y"); } if ((flags & CF_UNSIGNED) == 0) { unsigned L = GetLocalLabel(); AddCodeLine ("bpl %s", LocalLabelName (L)); AddCodeLine ("dex"); g_defcodelabel (L); } break; } /* FALLTHROUGH */ case CF_INT: AddCodeLine ("ldy #$%02X", Offs); if (flags & CF_CONST) { if (IS_Get (&CodeSizeFactor) >= 400) { AddCodeLine ("clc"); AddCodeLine ("lda #$%02X", (int)(val & 0xFF)); AddCodeLine ("adc (sp),y"); AddCodeLine ("sta (sp),y"); AddCodeLine ("iny"); AddCodeLine ("lda #$%02X", (int) ((val >> 8) & 0xFF)); AddCodeLine ("adc (sp),y"); AddCodeLine ("sta (sp),y"); AddCodeLine ("tax"); AddCodeLine ("dey"); AddCodeLine ("lda (sp),y"); } else { g_getimmed (flags, val, 0); AddCodeLine ("jsr addeqysp"); } } else { AddCodeLine ("jsr addeqysp"); } break; case CF_LONG: if (flags & CF_CONST) { g_getimmed (flags, val, 0); } AddCodeLine ("ldy #$%02X", Offs); AddCodeLine ("jsr laddeqysp"); break; default: typeerror (flags); } } void g_addeqind (unsigned flags, unsigned offs, unsigned long val) /* Emit += for the location with address in ax */ { /* If the offset is too large for a byte register, add the high byte ** of the offset to the primary. Beware: We need a special correction ** if the offset in the low byte will overflow in the operation. */ offs = MakeByteOffs (flags, offs); /* Check the size and determine operation */ switch (flags & CF_TYPEMASK) { case CF_CHAR: AddCodeLine ("sta ptr1"); AddCodeLine ("stx ptr1+1"); AddCodeLine ("ldy #$%02X", offs); AddCodeLine ("ldx #$00"); AddCodeLine ("lda #$%02X", (int)(val & 0xFF)); AddCodeLine ("clc"); AddCodeLine ("adc (ptr1),y"); AddCodeLine ("sta (ptr1),y"); break; case CF_INT: case CF_LONG: AddCodeLine ("jsr pushax"); /* Push the address */ push (CF_PTR); /* Correct the internal sp */ g_getind (flags, offs); /* Fetch the value */ g_inc (flags, val); /* Increment value in primary */ g_putind (flags, offs); /* Store the value back */ break; default: typeerror (flags); } } void g_subeqstatic (unsigned flags, uintptr_t label, long offs, unsigned long val) /* Emit -= for a static variable */ { /* Create the correct label name */ const char* lbuf = GetLabelName (flags, label, offs); /* Check the size and determine operation */ switch (flags & CF_TYPEMASK) { case CF_CHAR: if (flags & CF_FORCECHAR) { AddCodeLine ("ldx #$00"); if (flags & CF_CONST) { if (val == 1) { AddCodeLine ("dec %s", lbuf); AddCodeLine ("lda %s", lbuf); } else { AddCodeLine ("lda %s", lbuf); AddCodeLine ("sec"); AddCodeLine ("sbc #$%02X", (int)(val & 0xFF)); AddCodeLine ("sta %s", lbuf); } } else { AddCodeLine ("eor #$FF"); AddCodeLine ("sec"); AddCodeLine ("adc %s", lbuf); AddCodeLine ("sta %s", lbuf); } if ((flags & CF_UNSIGNED) == 0) { unsigned L = GetLocalLabel(); AddCodeLine ("bpl %s", LocalLabelName (L)); AddCodeLine ("dex"); g_defcodelabel (L); } break; } /* FALLTHROUGH */ case CF_INT: if (flags & CF_CONST) { AddCodeLine ("lda %s", lbuf); AddCodeLine ("sec"); AddCodeLine ("sbc #$%02X", (unsigned char)val); AddCodeLine ("sta %s", lbuf); if (val < 0x100) { unsigned L = GetLocalLabel (); AddCodeLine ("bcs %s", LocalLabelName (L)); AddCodeLine ("dec %s+1", lbuf); g_defcodelabel (L); AddCodeLine ("ldx %s+1", lbuf); } else { AddCodeLine ("lda %s+1", lbuf); AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 8)); AddCodeLine ("sta %s+1", lbuf); AddCodeLine ("tax"); AddCodeLine ("lda %s", lbuf); } } else { AddCodeLine ("eor #$FF"); AddCodeLine ("sec"); AddCodeLine ("adc %s", lbuf); AddCodeLine ("sta %s", lbuf); AddCodeLine ("txa"); AddCodeLine ("eor #$FF"); AddCodeLine ("adc %s+1", lbuf); AddCodeLine ("sta %s+1", lbuf); AddCodeLine ("tax"); AddCodeLine ("lda %s", lbuf); } break; case CF_LONG: if (flags & CF_CONST) { if (val < 0x100) { AddCodeLine ("ldy #<(%s)", lbuf); AddCodeLine ("sty ptr1"); AddCodeLine ("ldy #>(%s)", lbuf); AddCodeLine ("lda #$%02X", (unsigned char)val); AddCodeLine ("jsr lsubeqa"); } else { g_getstatic (flags, label, offs); g_dec (flags, val); g_putstatic (flags, label, offs); } } else { AddCodeLine ("ldy #<(%s)", lbuf); AddCodeLine ("sty ptr1"); AddCodeLine ("ldy #>(%s)", lbuf); AddCodeLine ("jsr lsubeq"); } break; default: typeerror (flags); } } void g_subeqlocal (unsigned flags, int Offs, unsigned long val) /* Emit -= for a local variable */ { /* Calculate the true offset, check it, load it into Y */ Offs -= StackPtr; CheckLocalOffs (Offs); /* Check the size and determine operation */ switch (flags & CF_TYPEMASK) { case CF_CHAR: if (flags & CF_FORCECHAR) { AddCodeLine ("ldy #$%02X", Offs); AddCodeLine ("ldx #$00"); if (flags & CF_CONST) { AddCodeLine ("lda (sp),y"); AddCodeLine ("sec"); AddCodeLine ("sbc #$%02X", (unsigned char)val); } else { AddCodeLine ("eor #$FF"); AddCodeLine ("sec"); AddCodeLine ("adc (sp),y"); } AddCodeLine ("sta (sp),y"); if ((flags & CF_UNSIGNED) == 0) { unsigned L = GetLocalLabel(); AddCodeLine ("bpl %s", LocalLabelName (L)); AddCodeLine ("dex"); g_defcodelabel (L); } break; } /* FALLTHROUGH */ case CF_INT: if (flags & CF_CONST) { g_getimmed (flags, val, 0); } AddCodeLine ("ldy #$%02X", Offs); AddCodeLine ("jsr subeqysp"); break; case CF_LONG: if (flags & CF_CONST) { g_getimmed (flags, val, 0); } AddCodeLine ("ldy #$%02X", Offs); AddCodeLine ("jsr lsubeqysp"); break; default: typeerror (flags); } } void g_subeqind (unsigned flags, unsigned offs, unsigned long val) /* Emit -= for the location with address in ax */ { /* If the offset is too large for a byte register, add the high byte ** of the offset to the primary. Beware: We need a special correction ** if the offset in the low byte will overflow in the operation. */ offs = MakeByteOffs (flags, offs); /* Check the size and determine operation */ switch (flags & CF_TYPEMASK) { case CF_CHAR: AddCodeLine ("sta ptr1"); AddCodeLine ("stx ptr1+1"); AddCodeLine ("ldy #$%02X", offs); AddCodeLine ("ldx #$00"); AddCodeLine ("lda (ptr1),y"); AddCodeLine ("sec"); AddCodeLine ("sbc #$%02X", (unsigned char)val); AddCodeLine ("sta (ptr1),y"); break; case CF_INT: case CF_LONG: AddCodeLine ("jsr pushax"); /* Push the address */ push (CF_PTR); /* Correct the internal sp */ g_getind (flags, offs); /* Fetch the value */ g_dec (flags, val); /* Increment value in primary */ g_putind (flags, offs); /* Store the value back */ break; default: typeerror (flags); } } /*****************************************************************************/ /* Add a variable address to the value in ax */ /*****************************************************************************/ void g_addaddr_local (unsigned flags attribute ((unused)), int offs) /* Add the address of a local variable to ax */ { unsigned L = 0; /* Add the offset */ offs -= StackPtr; if (offs != 0) { /* We cannot address more then 256 bytes of locals anyway */ L = GetLocalLabel(); CheckLocalOffs (offs); AddCodeLine ("clc"); AddCodeLine ("adc #$%02X", offs & 0xFF); /* Do also skip the CLC insn below */ AddCodeLine ("bcc %s", LocalLabelName (L)); AddCodeLine ("inx"); } /* Add the current stackpointer value */ AddCodeLine ("clc"); if (L != 0) { /* Label was used above */ g_defcodelabel (L); } AddCodeLine ("adc sp"); AddCodeLine ("tay"); AddCodeLine ("txa"); AddCodeLine ("adc sp+1"); AddCodeLine ("tax"); AddCodeLine ("tya"); } void g_addaddr_static (unsigned flags, uintptr_t label, long offs) /* Add the address of a static variable to ax */ { /* Create the correct label name */ const char* lbuf = GetLabelName (flags, label, offs); /* Add the address to the current ax value */ AddCodeLine ("clc"); AddCodeLine ("adc #<(%s)", lbuf); AddCodeLine ("tay"); AddCodeLine ("txa"); AddCodeLine ("adc #>(%s)", lbuf); AddCodeLine ("tax"); AddCodeLine ("tya"); } /*****************************************************************************/ /* */ /*****************************************************************************/ void g_save (unsigned flags) /* Copy primary register to hold register. */ { /* Check the size and determine operation */ switch (flags & CF_TYPEMASK) { case CF_CHAR: if (flags & CF_FORCECHAR) { AddCodeLine ("pha"); break; } /* FALLTHROUGH */ case CF_INT: AddCodeLine ("sta regsave"); AddCodeLine ("stx regsave+1"); break; case CF_LONG: AddCodeLine ("jsr saveeax"); break; default: typeerror (flags); } } void g_restore (unsigned flags) /* Copy hold register to primary. */ { /* Check the size and determine operation */ switch (flags & CF_TYPEMASK) { case CF_CHAR: if (flags & CF_FORCECHAR) { AddCodeLine ("pla"); break; } /* FALLTHROUGH */ case CF_INT: AddCodeLine ("lda regsave"); AddCodeLine ("ldx regsave+1"); break; case CF_LONG: AddCodeLine ("jsr resteax"); break; default: typeerror (flags); } } void g_cmp (unsigned flags, unsigned long val) /* Immidiate compare. The primary register will not be changed, Z flag ** will be set. */ { unsigned L; /* Check the size and determine operation */ switch (flags & CF_TYPEMASK) { case CF_CHAR: if (flags & CF_FORCECHAR) { AddCodeLine ("cmp #$%02X", (unsigned char)val); break; } /* FALLTHROUGH */ case CF_INT: L = GetLocalLabel(); AddCodeLine ("cmp #$%02X", (unsigned char)val); AddCodeLine ("bne %s", LocalLabelName (L)); AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8)); g_defcodelabel (L); break; case CF_LONG: Internal ("g_cmp: Long compares not implemented"); break; default: typeerror (flags); } } static void oper (unsigned Flags, unsigned long Val, const char* const* Subs) /* Encode a binary operation. subs is a pointer to four strings: ** 0 --> Operate on ints ** 1 --> Operate on unsigneds ** 2 --> Operate on longs ** 3 --> Operate on unsigned longs */ { /* Determine the offset into the array */ if (Flags & CF_UNSIGNED) { ++Subs; } if ((Flags & CF_TYPEMASK) == CF_LONG) { Subs += 2; } /* Load the value if it is not already in the primary */ if (Flags & CF_CONST) { /* Load value */ g_getimmed (Flags, Val, 0); } /* Output the operation */ AddCodeLine ("jsr %s", *Subs); /* The operation will pop it's argument */ pop (Flags); } void g_test (unsigned flags) /* Test the value in the primary and set the condition codes */ { switch (flags & CF_TYPEMASK) { case CF_CHAR: if (flags & CF_FORCECHAR) { AddCodeLine ("tax"); break; } /* FALLTHROUGH */ case CF_INT: AddCodeLine ("stx tmp1"); AddCodeLine ("ora tmp1"); break; case CF_LONG: if (flags & CF_UNSIGNED) { AddCodeLine ("jsr utsteax"); } else { AddCodeLine ("jsr tsteax"); } break; default: typeerror (flags); } } void g_push (unsigned flags, unsigned long val) /* Push the primary register or a constant value onto the stack */ { if (flags & CF_CONST && (flags & CF_TYPEMASK) != CF_LONG) { /* We have a constant 8 or 16 bit value */ if ((flags & CF_TYPEMASK) == CF_CHAR && (flags & CF_FORCECHAR)) { /* Handle as 8 bit value */ AddCodeLine ("lda #$%02X", (unsigned char) val); AddCodeLine ("jsr pusha"); } else { /* Handle as 16 bit value */ g_getimmed (flags, val, 0); AddCodeLine ("jsr pushax"); } } else { /* Value is not 16 bit or not constant */ if (flags & CF_CONST) { /* Constant 32 bit value, load into eax */ g_getimmed (flags, val, 0); } /* Push the primary register */ switch (flags & CF_TYPEMASK) { case CF_CHAR: if (flags & CF_FORCECHAR) { /* Handle as char */ AddCodeLine ("jsr pusha"); break; } /* FALL THROUGH */ case CF_INT: AddCodeLine ("jsr pushax"); break; case CF_LONG: AddCodeLine ("jsr pusheax"); break; default: typeerror (flags); } } /* Adjust the stack offset */ push (flags); } void g_swap (unsigned flags) /* Swap the primary register and the top of the stack. flags give the type ** of *both* values (must have same size). */ { switch (flags & CF_TYPEMASK) { case CF_CHAR: case CF_INT: AddCodeLine ("jsr swapstk"); break; case CF_LONG: AddCodeLine ("jsr swapestk"); break; default: typeerror (flags); } } void g_call (unsigned Flags, const char* Label, unsigned ArgSize) /* Call the specified subroutine name */ { if ((Flags & CF_FIXARGC) == 0) { /* Pass the argument count */ AddCodeLine ("ldy #$%02X", ArgSize); } AddCodeLine ("jsr _%s", Label); StackPtr += ArgSize; /* callee pops args */ } void g_callind (unsigned Flags, unsigned ArgSize, int Offs) /* Call subroutine indirect */ { if ((Flags & CF_LOCAL) == 0) { /* Address is in a/x */ if ((Flags & CF_FIXARGC) == 0) { /* Pass arg count */ AddCodeLine ("ldy #$%02X", ArgSize); } AddCodeLine ("jsr callax"); } else { /* The address is on stack, offset is on Val */ Offs -= StackPtr; CheckLocalOffs (Offs); AddCodeLine ("pha"); AddCodeLine ("ldy #$%02X", Offs); AddCodeLine ("lda (sp),y"); AddCodeLine ("sta jmpvec+1"); AddCodeLine ("iny"); AddCodeLine ("lda (sp),y"); AddCodeLine ("sta jmpvec+2"); AddCodeLine ("pla"); AddCodeLine ("jsr jmpvec"); } /* Callee pops args */ StackPtr += ArgSize; } void g_jump (unsigned Label) /* Jump to specified internal label number */ { AddCodeLine ("jmp %s", LocalLabelName (Label)); } void g_truejump (unsigned flags attribute ((unused)), unsigned label) /* Jump to label if zero flag clear */ { AddCodeLine ("jne %s", LocalLabelName (label)); } void g_falsejump (unsigned flags attribute ((unused)), unsigned label) /* Jump to label if zero flag set */ { AddCodeLine ("jeq %s", LocalLabelName (label)); } void g_lateadjustSP (unsigned label) /* Adjust stack based on non-immediate data */ { AddCodeLine ("pha"); AddCodeLine ("lda %s", LocalLabelName (label)); AddCodeLine ("clc"); AddCodeLine ("adc sp"); AddCodeLine ("sta sp"); AddCodeLine ("lda %s+1", LocalLabelName (label)); AddCodeLine ("adc sp+1"); AddCodeLine ("sta sp+1"); AddCodeLine ("pla"); } void g_drop (unsigned Space) /* Drop space allocated on the stack */ { if (Space > 255) { /* Inline the code since calling addysp repeatedly is quite some ** overhead. */ AddCodeLine ("pha"); AddCodeLine ("lda #$%02X", (unsigned char) Space); AddCodeLine ("clc"); AddCodeLine ("adc sp"); AddCodeLine ("sta sp"); AddCodeLine ("lda #$%02X", (unsigned char) (Space >> 8)); AddCodeLine ("adc sp+1"); AddCodeLine ("sta sp+1"); AddCodeLine ("pla"); } else if (Space > 8) { AddCodeLine ("ldy #$%02X", Space); AddCodeLine ("jsr addysp"); } else if (Space != 0) { AddCodeLine ("jsr incsp%u", Space); } } void g_space (int Space) /* Create or drop space on the stack */ { if (Space < 0) { /* This is actually a drop operation */ g_drop (-Space); } else if (Space > 255) { /* Inline the code since calling subysp repeatedly is quite some ** overhead. */ AddCodeLine ("pha"); AddCodeLine ("lda sp"); AddCodeLine ("sec"); AddCodeLine ("sbc #$%02X", (unsigned char) Space); AddCodeLine ("sta sp"); AddCodeLine ("lda sp+1"); AddCodeLine ("sbc #$%02X", (unsigned char) (Space >> 8)); AddCodeLine ("sta sp+1"); AddCodeLine ("pla"); } else if (Space > 8) { AddCodeLine ("ldy #$%02X", Space); AddCodeLine ("jsr subysp"); } else if (Space != 0) { AddCodeLine ("jsr decsp%u", Space); } } void g_cstackcheck (void) /* Check for a C stack overflow */ { AddCodeLine ("jsr cstkchk"); } void g_stackcheck (void) /* Check for a stack overflow */ { AddCodeLine ("jsr stkchk"); } void g_add (unsigned flags, unsigned long val) /* Primary = TOS + Primary */ { static const char* const ops[4] = { "tosaddax", "tosaddax", "tosaddeax", "tosaddeax" }; if (flags & CF_CONST) { flags &= ~CF_FORCECHAR; /* Handle chars as ints */ g_push (flags & ~CF_CONST, 0); } oper (flags, val, ops); } void g_sub (unsigned flags, unsigned long val) /* Primary = TOS - Primary */ { static const char* const ops[4] = { "tossubax", "tossubax", "tossubeax", "tossubeax" }; if (flags & CF_CONST) { flags &= ~CF_FORCECHAR; /* Handle chars as ints */ g_push (flags & ~CF_CONST, 0); } oper (flags, val, ops); } void g_rsub (unsigned flags, unsigned long val) /* Primary = Primary - TOS */ { static const char* const ops[4] = { "tosrsubax", "tosrsubax", "tosrsubeax", "tosrsubeax" }; oper (flags, val, ops); } void g_mul (unsigned flags, unsigned long val) /* Primary = TOS * Primary */ { static const char* const ops[4] = { "tosmulax", "tosumulax", "tosmuleax", "tosumuleax" }; int p2; /* Do strength reduction if the value is constant and a power of two */ if (flags & CF_CONST && (p2 = PowerOf2 (val)) >= 0) { /* Generate a shift instead */ g_asl (flags, p2); return; } /* If the right hand side is const, the lhs is not on stack but still ** in the primary register. */ if (flags & CF_CONST) { switch (flags & CF_TYPEMASK) { case CF_CHAR: if (flags & CF_FORCECHAR) { /* Handle some special cases */ switch (val) { case 3: AddCodeLine ("sta tmp1"); AddCodeLine ("asl a"); AddCodeLine ("clc"); AddCodeLine ("adc tmp1"); return; case 5: AddCodeLine ("sta tmp1"); AddCodeLine ("asl a"); AddCodeLine ("asl a"); AddCodeLine ("clc"); AddCodeLine ("adc tmp1"); return; case 6: AddCodeLine ("sta tmp1"); AddCodeLine ("asl a"); AddCodeLine ("clc"); AddCodeLine ("adc tmp1"); AddCodeLine ("asl a"); return; case 10: AddCodeLine ("sta tmp1"); AddCodeLine ("asl a"); AddCodeLine ("asl a"); AddCodeLine ("clc"); AddCodeLine ("adc tmp1"); AddCodeLine ("asl a"); return; } } /* FALLTHROUGH */ case CF_INT: switch (val) { case 3: AddCodeLine ("jsr mulax3"); return; case 5: AddCodeLine ("jsr mulax5"); return; case 6: AddCodeLine ("jsr mulax6"); return; case 7: AddCodeLine ("jsr mulax7"); return; case 9: AddCodeLine ("jsr mulax9"); return; case 10: AddCodeLine ("jsr mulax10"); return; } break; case CF_LONG: break; default: typeerror (flags); } /* If we go here, we didn't emit code. Push the lhs on stack and fall ** into the normal, non-optimized stuff. */ flags &= ~CF_FORCECHAR; /* Handle chars as ints */ g_push (flags & ~CF_CONST, 0); } /* Use long way over the stack */ oper (flags, val, ops); } void g_div (unsigned flags, unsigned long val) /* Primary = TOS / Primary */ { static const char* const ops[4] = { "tosdivax", "tosudivax", "tosdiveax", "tosudiveax" }; /* Do strength reduction if the value is constant and a power of two */ int p2; if ((flags & CF_CONST) && (p2 = PowerOf2 (val)) >= 0) { /* Generate a shift instead */ g_asr (flags, p2); } else { /* Generate a division */ if (flags & CF_CONST) { /* lhs is not on stack */ flags &= ~CF_FORCECHAR; /* Handle chars as ints */ g_push (flags & ~CF_CONST, 0); } oper (flags, val, ops); } } void g_mod (unsigned flags, unsigned long val) /* Primary = TOS % Primary */ { static const char* const ops[4] = { "tosmodax", "tosumodax", "tosmodeax", "tosumodeax" }; int p2; /* Check if we can do some cost reduction */ if ((flags & CF_CONST) && (flags & CF_UNSIGNED) && val != 0xFFFFFFFF && (p2 = PowerOf2 (val)) >= 0) { /* We can do that with an AND operation */ g_and (flags, val - 1); } else { /* Do it the hard way... */ if (flags & CF_CONST) { /* lhs is not on stack */ flags &= ~CF_FORCECHAR; /* Handle chars as ints */ g_push (flags & ~CF_CONST, 0); } oper (flags, val, ops); } } void g_or (unsigned flags, unsigned long val) /* Primary = TOS | Primary */ { static const char* const ops[4] = { "tosorax", "tosorax", "tosoreax", "tosoreax" }; /* If the right hand side is const, the lhs is not on stack but still ** in the primary register. */ if (flags & CF_CONST) { switch (flags & CF_TYPEMASK) { case CF_CHAR: if (flags & CF_FORCECHAR) { if ((val & 0xFF) != 0) { AddCodeLine ("ora #$%02X", (unsigned char)val); } return; } /* FALLTHROUGH */ case CF_INT: if (val <= 0xFF) { if ((val & 0xFF) != 0) { AddCodeLine ("ora #$%02X", (unsigned char)val); } } else if ((val & 0xFF00) == 0xFF00) { if ((val & 0xFF) != 0) { AddCodeLine ("ora #$%02X", (unsigned char)val); } AddCodeLine ("ldx #$FF"); } else if (val != 0) { AddCodeLine ("ora #$%02X", (unsigned char)val); AddCodeLine ("pha"); AddCodeLine ("txa"); AddCodeLine ("ora #$%02X", (unsigned char)(val >> 8)); AddCodeLine ("tax"); AddCodeLine ("pla"); } return; case CF_LONG: if (val <= 0xFF) { if ((val & 0xFF) != 0) { AddCodeLine ("ora #$%02X", (unsigned char)val); } return; } break; default: typeerror (flags); } /* If we go here, we didn't emit code. Push the lhs on stack and fall ** into the normal, non-optimized stuff. Note: The standard stuff will ** always work with ints. */ flags &= ~CF_FORCECHAR; g_push (flags & ~CF_CONST, 0); } /* Use long way over the stack */ oper (flags, val, ops); } void g_xor (unsigned flags, unsigned long val) /* Primary = TOS ^ Primary */ { static const char* const ops[4] = { "tosxorax", "tosxorax", "tosxoreax", "tosxoreax" }; /* If the right hand side is const, the lhs is not on stack but still ** in the primary register. */ if (flags & CF_CONST) { switch (flags & CF_TYPEMASK) { case CF_CHAR: if (flags & CF_FORCECHAR) { if ((val & 0xFF) != 0) { AddCodeLine ("eor #$%02X", (unsigned char)val); } return; } /* FALLTHROUGH */ case CF_INT: if (val <= 0xFF) { if (val != 0) { AddCodeLine ("eor #$%02X", (unsigned char)val); } } else if (val != 0) { if ((val & 0xFF) != 0) { AddCodeLine ("eor #$%02X", (unsigned char)val); } AddCodeLine ("pha"); AddCodeLine ("txa"); AddCodeLine ("eor #$%02X", (unsigned char)(val >> 8)); AddCodeLine ("tax"); AddCodeLine ("pla"); } return; case CF_LONG: if (val <= 0xFF) { if (val != 0) { AddCodeLine ("eor #$%02X", (unsigned char)val); } return; } break; default: typeerror (flags); } /* If we go here, we didn't emit code. Push the lhs on stack and fall ** into the normal, non-optimized stuff. Note: The standard stuff will ** always work with ints. */ flags &= ~CF_FORCECHAR; g_push (flags & ~CF_CONST, 0); } /* Use long way over the stack */ oper (flags, val, ops); } void g_and (unsigned Flags, unsigned long Val) /* Primary = TOS & Primary */ { static const char* const ops[4] = { "tosandax", "tosandax", "tosandeax", "tosandeax" }; /* If the right hand side is const, the lhs is not on stack but still ** in the primary register. */ if (Flags & CF_CONST) { switch (Flags & CF_TYPEMASK) { case CF_CHAR: if (Flags & CF_FORCECHAR) { if ((Val & 0xFF) == 0x00) { AddCodeLine ("lda #$00"); } else if ((Val & 0xFF) != 0xFF) { AddCodeLine ("and #$%02X", (unsigned char)Val); } return; } /* FALLTHROUGH */ case CF_INT: if ((Val & 0xFFFF) != 0xFFFF) { if (Val <= 0xFF) { AddCodeLine ("ldx #$00"); if (Val == 0) { AddCodeLine ("lda #$00"); } else if (Val != 0xFF) { AddCodeLine ("and #$%02X", (unsigned char)Val); } } else if ((Val & 0xFFFF) == 0xFF00) { AddCodeLine ("lda #$00"); } else if ((Val & 0xFF00) == 0xFF00) { AddCodeLine ("and #$%02X", (unsigned char)Val); } else if ((Val & 0x00FF) == 0x0000) { AddCodeLine ("txa"); AddCodeLine ("and #$%02X", (unsigned char)(Val >> 8)); AddCodeLine ("tax"); AddCodeLine ("lda #$00"); } else { AddCodeLine ("tay"); AddCodeLine ("txa"); AddCodeLine ("and #$%02X", (unsigned char)(Val >> 8)); AddCodeLine ("tax"); AddCodeLine ("tya"); if ((Val & 0x00FF) == 0x0000) { AddCodeLine ("lda #$00"); } else if ((Val & 0x00FF) != 0x00FF) { AddCodeLine ("and #$%02X", (unsigned char)Val); } } } return; case CF_LONG: if (Val <= 0xFF) { AddCodeLine ("ldx #$00"); AddCodeLine ("stx sreg+1"); AddCodeLine ("stx sreg"); if ((Val & 0xFF) != 0xFF) { AddCodeLine ("and #$%02X", (unsigned char)Val); } return; } else if (Val == 0xFF00) { AddCodeLine ("lda #$00"); AddCodeLine ("sta sreg+1"); AddCodeLine ("sta sreg"); return; } break; default: typeerror (Flags); } /* If we go here, we didn't emit code. Push the lhs on stack and fall ** into the normal, non-optimized stuff. Note: The standard stuff will ** always work with ints. */ Flags &= ~CF_FORCECHAR; g_push (Flags & ~CF_CONST, 0); } /* Use long way over the stack */ oper (Flags, Val, ops); } void g_asr (unsigned flags, unsigned long val) /* Primary = TOS >> Primary */ { static const char* const ops[4] = { "tosasrax", "tosshrax", "tosasreax", "tosshreax" }; /* If the right hand side is const, the lhs is not on stack but still ** in the primary register. */ if (flags & CF_CONST) { switch (flags & CF_TYPEMASK) { case CF_CHAR: case CF_INT: val &= 0x0F; if (val >= 8) { if (flags & CF_UNSIGNED) { AddCodeLine ("txa"); AddCodeLine ("ldx #$00"); } else { unsigned L = GetLocalLabel(); AddCodeLine ("cpx #$80"); /* Sign bit into carry */ AddCodeLine ("txa"); AddCodeLine ("ldx #$00"); AddCodeLine ("bcc %s", LocalLabelName (L)); AddCodeLine ("dex"); /* Make $FF */ g_defcodelabel (L); } val -= 8; } if (val >= 4) { if (flags & CF_UNSIGNED) { AddCodeLine ("jsr shrax4"); } else { AddCodeLine ("jsr asrax4"); } val -= 4; } if (val > 0) { if (flags & CF_UNSIGNED) { AddCodeLine ("jsr shrax%ld", val); } else { AddCodeLine ("jsr asrax%ld", val); } } return; case CF_LONG: val &= 0x1F; if (val >= 24) { AddCodeLine ("ldx #$00"); AddCodeLine ("lda sreg+1"); if ((flags & CF_UNSIGNED) == 0) { unsigned L = GetLocalLabel(); AddCodeLine ("bpl %s", LocalLabelName (L)); AddCodeLine ("dex"); g_defcodelabel (L); } AddCodeLine ("stx sreg"); AddCodeLine ("stx sreg+1"); val -= 24; } if (val >= 16) { AddCodeLine ("ldy #$00"); AddCodeLine ("ldx sreg+1"); if ((flags & CF_UNSIGNED) == 0) { unsigned L = GetLocalLabel(); AddCodeLine ("bpl %s", LocalLabelName (L)); AddCodeLine ("dey"); g_defcodelabel (L); } AddCodeLine ("lda sreg"); AddCodeLine ("sty sreg+1"); AddCodeLine ("sty sreg"); val -= 16; } if (val >= 8) { AddCodeLine ("txa"); AddCodeLine ("ldx sreg"); AddCodeLine ("ldy sreg+1"); AddCodeLine ("sty sreg"); if ((flags & CF_UNSIGNED) == 0) { unsigned L = GetLocalLabel(); AddCodeLine ("cpy #$80"); AddCodeLine ("ldy #$00"); AddCodeLine ("bcc %s", LocalLabelName (L)); AddCodeLine ("dey"); g_defcodelabel (L); } else { AddCodeLine ("ldy #$00"); } AddCodeLine ("sty sreg+1"); val -= 8; } if (val >= 4) { if (flags & CF_UNSIGNED) { AddCodeLine ("jsr shreax4"); } else { AddCodeLine ("jsr asreax4"); } val -= 4; } if (val > 0) { if (flags & CF_UNSIGNED) { AddCodeLine ("jsr shreax%ld", val); } else { AddCodeLine ("jsr asreax%ld", val); } } return; default: typeerror (flags); } /* If we go here, we didn't emit code. Push the lhs on stack and fall ** into the normal, non-optimized stuff. Note: The standard stuff will ** always work with ints. */ flags &= ~CF_FORCECHAR; g_push (flags & ~CF_CONST, 0); } /* Use long way over the stack */ oper (flags, val, ops); } void g_asl (unsigned flags, unsigned long val) /* Primary = TOS << Primary */ { static const char* const ops[4] = { "tosaslax", "tosshlax", "tosasleax", "tosshleax" }; /* If the right hand side is const, the lhs is not on stack but still ** in the primary register. */ if (flags & CF_CONST) { switch (flags & CF_TYPEMASK) { case CF_CHAR: case CF_INT: val &= 0x0F; if (val >= 8) { AddCodeLine ("tax"); AddCodeLine ("lda #$00"); val -= 8; } if (val >= 4) { if (flags & CF_UNSIGNED) { AddCodeLine ("jsr shlax4"); } else { AddCodeLine ("jsr aslax4"); } val -= 4; } if (val > 0) { if (flags & CF_UNSIGNED) { AddCodeLine ("jsr shlax%ld", val); } else { AddCodeLine ("jsr aslax%ld", val); } } return; case CF_LONG: val &= 0x1F; if (val >= 24) { AddCodeLine ("sta sreg+1"); AddCodeLine ("lda #$00"); AddCodeLine ("tax"); AddCodeLine ("sta sreg"); val -= 24; } if (val >= 16) { AddCodeLine ("stx sreg+1"); AddCodeLine ("sta sreg"); AddCodeLine ("lda #$00"); AddCodeLine ("tax"); val -= 16; } if (val >= 8) { AddCodeLine ("ldy sreg"); AddCodeLine ("sty sreg+1"); AddCodeLine ("stx sreg"); AddCodeLine ("tax"); AddCodeLine ("lda #$00"); val -= 8; } if (val > 4) { if (flags & CF_UNSIGNED) { AddCodeLine ("jsr shleax4"); } else { AddCodeLine ("jsr asleax4"); } val -= 4; } if (val > 0) { if (flags & CF_UNSIGNED) { AddCodeLine ("jsr shleax%ld", val); } else { AddCodeLine ("jsr asleax%ld", val); } } return; default: typeerror (flags); } /* If we go here, we didn't emit code. Push the lhs on stack and fall ** into the normal, non-optimized stuff. Note: The standard stuff will ** always work with ints. */ flags &= ~CF_FORCECHAR; g_push (flags & ~CF_CONST, 0); } /* Use long way over the stack */ oper (flags, val, ops); } void g_neg (unsigned Flags) /* Primary = -Primary */ { switch (Flags & CF_TYPEMASK) { case CF_CHAR: if (Flags & CF_FORCECHAR) { AddCodeLine ("eor #$FF"); AddCodeLine ("clc"); AddCodeLine ("adc #$01"); return; } /* FALLTHROUGH */ case CF_INT: AddCodeLine ("jsr negax"); break; case CF_LONG: AddCodeLine ("jsr negeax"); break; default: typeerror (Flags); } } void g_bneg (unsigned flags) /* Primary = !Primary */ { switch (flags & CF_TYPEMASK) { case CF_CHAR: AddCodeLine ("jsr bnega"); break; case CF_INT: AddCodeLine ("jsr bnegax"); break; case CF_LONG: AddCodeLine ("jsr bnegeax"); break; default: typeerror (flags); } } void g_com (unsigned Flags) /* Primary = ~Primary */ { switch (Flags & CF_TYPEMASK) { case CF_CHAR: if (Flags & CF_FORCECHAR) { AddCodeLine ("eor #$FF"); return; } /* FALLTHROUGH */ case CF_INT: AddCodeLine ("jsr complax"); break; case CF_LONG: AddCodeLine ("jsr compleax"); break; default: typeerror (Flags); } } void g_inc (unsigned flags, unsigned long val) /* Increment the primary register by a given number */ { /* Don't inc by zero */ if (val == 0) { return; } /* Generate code for the supported types */ flags &= ~CF_CONST; switch (flags & CF_TYPEMASK) { case CF_CHAR: if (flags & CF_FORCECHAR) { if ((CPUIsets[CPU] & CPU_ISET_65SC02) != 0 && val <= 2) { while (val--) { AddCodeLine ("ina"); } } else { AddCodeLine ("clc"); AddCodeLine ("adc #$%02X", (unsigned char)val); } break; } /* FALLTHROUGH */ case CF_INT: if ((CPUIsets[CPU] & CPU_ISET_65SC02) != 0 && val == 1) { unsigned L = GetLocalLabel(); AddCodeLine ("ina"); AddCodeLine ("bne %s", LocalLabelName (L)); AddCodeLine ("inx"); g_defcodelabel (L); } else if (IS_Get (&CodeSizeFactor) < 200) { /* Use jsr calls */ if (val <= 8) { AddCodeLine ("jsr incax%lu", val); } else if (val <= 255) { AddCodeLine ("ldy #$%02X", (unsigned char) val); AddCodeLine ("jsr incaxy"); } else { g_add (flags | CF_CONST, val); } } else { /* Inline the code */ if (val <= 0x300) { if ((val & 0xFF) != 0) { unsigned L = GetLocalLabel(); AddCodeLine ("clc"); AddCodeLine ("adc #$%02X", (unsigned char) val); AddCodeLine ("bcc %s", LocalLabelName (L)); AddCodeLine ("inx"); g_defcodelabel (L); } if (val >= 0x100) { AddCodeLine ("inx"); } if (val >= 0x200) { AddCodeLine ("inx"); } if (val >= 0x300) { AddCodeLine ("inx"); } } else if ((val & 0xFF) != 0) { AddCodeLine ("clc"); AddCodeLine ("adc #$%02X", (unsigned char) val); AddCodeLine ("pha"); AddCodeLine ("txa"); AddCodeLine ("adc #$%02X", (unsigned char) (val >> 8)); AddCodeLine ("tax"); AddCodeLine ("pla"); } else { AddCodeLine ("pha"); AddCodeLine ("txa"); AddCodeLine ("clc"); AddCodeLine ("adc #$%02X", (unsigned char) (val >> 8)); AddCodeLine ("tax"); AddCodeLine ("pla"); } } break; case CF_LONG: if (val <= 255) { AddCodeLine ("ldy #$%02X", (unsigned char) val); AddCodeLine ("jsr inceaxy"); } else { g_add (flags | CF_CONST, val); } break; default: typeerror (flags); } } void g_dec (unsigned flags, unsigned long val) /* Decrement the primary register by a given number */ { /* Don't dec by zero */ if (val == 0) { return; } /* Generate code for the supported types */ flags &= ~CF_CONST; switch (flags & CF_TYPEMASK) { case CF_CHAR: if (flags & CF_FORCECHAR) { if ((CPUIsets[CPU] & CPU_ISET_65SC02) != 0 && val <= 2) { while (val--) { AddCodeLine ("dea"); } } else { AddCodeLine ("sec"); AddCodeLine ("sbc #$%02X", (unsigned char)val); } break; } /* FALLTHROUGH */ case CF_INT: if (IS_Get (&CodeSizeFactor) < 200) { /* Use subroutines */ if (val <= 8) { AddCodeLine ("jsr decax%d", (int) val); } else if (val <= 255) { AddCodeLine ("ldy #$%02X", (unsigned char) val); AddCodeLine ("jsr decaxy"); } else { g_sub (flags | CF_CONST, val); } } else { /* Inline the code */ if (val < 0x300) { if ((val & 0xFF) != 0) { unsigned L = GetLocalLabel(); AddCodeLine ("sec"); AddCodeLine ("sbc #$%02X", (unsigned char) val); AddCodeLine ("bcs %s", LocalLabelName (L)); AddCodeLine ("dex"); g_defcodelabel (L); } if (val >= 0x100) { AddCodeLine ("dex"); } if (val >= 0x200) { AddCodeLine ("dex"); } } else { if ((val & 0xFF) != 0) { AddCodeLine ("sec"); AddCodeLine ("sbc #$%02X", (unsigned char) val); AddCodeLine ("pha"); AddCodeLine ("txa"); AddCodeLine ("sbc #$%02X", (unsigned char) (val >> 8)); AddCodeLine ("tax"); AddCodeLine ("pla"); } else { AddCodeLine ("pha"); AddCodeLine ("txa"); AddCodeLine ("sec"); AddCodeLine ("sbc #$%02X", (unsigned char) (val >> 8)); AddCodeLine ("tax"); AddCodeLine ("pla"); } } } break; case CF_LONG: if (val <= 255) { AddCodeLine ("ldy #$%02X", (unsigned char) val); AddCodeLine ("jsr deceaxy"); } else { g_sub (flags | CF_CONST, val); } break; default: typeerror (flags); } } /* ** Following are the conditional operators. They compare the TOS against ** the primary and put a literal 1 in the primary if the condition is ** true, otherwise they clear the primary register */ void g_eq (unsigned flags, unsigned long val) /* Test for equal */ { static const char* const ops[4] = { "toseqax", "toseqax", "toseqeax", "toseqeax" }; unsigned L; /* If the right hand side is const, the lhs is not on stack but still ** in the primary register. */ if (flags & CF_CONST) { switch (flags & CF_TYPEMASK) { case CF_CHAR: if (flags & CF_FORCECHAR) { AddCodeLine ("cmp #$%02X", (unsigned char)val); AddCodeLine ("jsr booleq"); return; } /* FALLTHROUGH */ case CF_INT: L = GetLocalLabel(); AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8)); AddCodeLine ("bne %s", LocalLabelName (L)); AddCodeLine ("cmp #$%02X", (unsigned char)val); g_defcodelabel (L); AddCodeLine ("jsr booleq"); return; case CF_LONG: break; default: typeerror (flags); } /* If we go here, we didn't emit code. Push the lhs on stack and fall ** into the normal, non-optimized stuff. Note: The standard stuff will ** always work with ints. */ flags &= ~CF_FORCECHAR; g_push (flags & ~CF_CONST, 0); } /* Use long way over the stack */ oper (flags, val, ops); } void g_ne (unsigned flags, unsigned long val) /* Test for not equal */ { static const char* const ops[4] = { "tosneax", "tosneax", "tosneeax", "tosneeax" }; unsigned L; /* If the right hand side is const, the lhs is not on stack but still ** in the primary register. */ if (flags & CF_CONST) { switch (flags & CF_TYPEMASK) { case CF_CHAR: if (flags & CF_FORCECHAR) { AddCodeLine ("cmp #$%02X", (unsigned char)val); AddCodeLine ("jsr boolne"); return; } /* FALLTHROUGH */ case CF_INT: L = GetLocalLabel(); AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8)); AddCodeLine ("bne %s", LocalLabelName (L)); AddCodeLine ("cmp #$%02X", (unsigned char)val); g_defcodelabel (L); AddCodeLine ("jsr boolne"); return; case CF_LONG: break; default: typeerror (flags); } /* If we go here, we didn't emit code. Push the lhs on stack and fall ** into the normal, non-optimized stuff. Note: The standard stuff will ** always work with ints. */ flags &= ~CF_FORCECHAR; g_push (flags & ~CF_CONST, 0); } /* Use long way over the stack */ oper (flags, val, ops); } void g_lt (unsigned flags, unsigned long val) /* Test for less than */ { static const char* const ops[4] = { "tosltax", "tosultax", "toslteax", "tosulteax" }; unsigned Label; /* If the right hand side is const, the lhs is not on stack but still ** in the primary register. */ if (flags & CF_CONST) { /* Because the handling of the overflow flag is too complex for ** inlining, we can handle only unsigned compares, and signed ** compares against zero here. */ if (flags & CF_UNSIGNED) { /* Give a warning in some special cases */ if (val == 0) { Warning ("Condition is never true"); AddCodeLine ("jsr return0"); return; } /* Look at the type */ switch (flags & CF_TYPEMASK) { case CF_CHAR: if (flags & CF_FORCECHAR) { AddCodeLine ("cmp #$%02X", (unsigned char)val); AddCodeLine ("jsr boolult"); return; } /* FALLTHROUGH */ case CF_INT: /* If the low byte is zero, we must only test the high byte */ AddCodeLine ("cpx #$%02X", (unsigned char)(val >> 8)); if ((val & 0xFF) != 0) { unsigned L = GetLocalLabel(); AddCodeLine ("bne %s", LocalLabelName (L)); AddCodeLine ("cmp #$%02X", (unsigned char)val); g_defcodelabel (L); } AddCodeLine ("jsr boolult"); return; case CF_LONG: /* Do a subtraction */ AddCodeLine ("cmp #$%02X", (unsigned char)val); AddCodeLine ("txa"); AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 8)); AddCodeLine ("lda sreg"); AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 16)); AddCodeLine ("lda sreg+1"); AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 24)); AddCodeLine ("jsr boolult"); return; default: typeerror (flags); } } else if (val == 0) { /* A signed compare against zero must only look at the sign bit */ switch (flags & CF_TYPEMASK) { case CF_CHAR: if (flags & CF_FORCECHAR) { AddCodeLine ("asl a"); /* Bit 7 -> carry */ AddCodeLine ("lda #$00"); AddCodeLine ("ldx #$00"); AddCodeLine ("rol a"); return; } /* FALLTHROUGH */ case CF_INT: /* Just check the high byte */ AddCodeLine ("cpx #$80"); /* Bit 7 -> carry */ AddCodeLine ("lda #$00"); AddCodeLine ("ldx #$00"); AddCodeLine ("rol a"); return; case CF_LONG: /* Just check the high byte */ AddCodeLine ("lda sreg+1"); AddCodeLine ("asl a"); /* Bit 7 -> carry */ AddCodeLine ("lda #$00"); AddCodeLine ("ldx #$00"); AddCodeLine ("rol a"); return; default: typeerror (flags); } } else { /* Signed compare against a constant != zero */ switch (flags & CF_TYPEMASK) { case CF_CHAR: if (flags & CF_FORCECHAR) { Label = GetLocalLabel (); AddCodeLine ("sec"); AddCodeLine ("sbc #$%02X", (unsigned char)val); AddCodeLine ("bvc %s", LocalLabelName (Label)); AddCodeLine ("eor #$80"); g_defcodelabel (Label); AddCodeLine ("asl a"); /* Bit 7 -> carry */ AddCodeLine ("lda #$00"); AddCodeLine ("ldx #$00"); AddCodeLine ("rol a"); return; } /* FALLTHROUGH */ case CF_INT: /* Do a subtraction */ Label = GetLocalLabel (); AddCodeLine ("cmp #$%02X", (unsigned char)val); AddCodeLine ("txa"); AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 8)); AddCodeLine ("bvc %s", LocalLabelName (Label)); AddCodeLine ("eor #$80"); g_defcodelabel (Label); AddCodeLine ("asl a"); /* Bit 7 -> carry */ AddCodeLine ("lda #$00"); AddCodeLine ("ldx #$00"); AddCodeLine ("rol a"); return; case CF_LONG: /* This one is too costly */ break; default: typeerror (flags); } } /* If we go here, we didn't emit code. Push the lhs on stack and fall ** into the normal, non-optimized stuff. Note: The standard stuff will ** always work with ints. */ flags &= ~CF_FORCECHAR; g_push (flags & ~CF_CONST, 0); } /* Use long way over the stack */ oper (flags, val, ops); } void g_le (unsigned flags, unsigned long val) /* Test for less than or equal to */ { static const char* const ops[4] = { "tosleax", "tosuleax", "tosleeax", "tosuleeax" }; /* If the right hand side is const, the lhs is not on stack but still ** in the primary register. */ if (flags & CF_CONST) { /* Look at the type */ switch (flags & CF_TYPEMASK) { case CF_CHAR: if (flags & CF_FORCECHAR) { if (flags & CF_UNSIGNED) { /* Unsigned compare */ if (val < 0xFF) { /* Use < instead of <= because the former gives ** better code on the 6502 than the latter. */ g_lt (flags, val+1); } else { /* Always true */ Warning ("Condition is always true"); AddCodeLine ("jsr return1"); } } else { /* Signed compare */ if ((long) val < 0x7F) { /* Use < instead of <= because the former gives ** better code on the 6502 than the latter. */ g_lt (flags, val+1); } else { /* Always true */ Warning ("Condition is always true"); AddCodeLine ("jsr return1"); } } return; } /* FALLTHROUGH */ case CF_INT: if (flags & CF_UNSIGNED) { /* Unsigned compare */ if (val < 0xFFFF) { /* Use < instead of <= because the former gives ** better code on the 6502 than the latter. */ g_lt (flags, val+1); } else { /* Always true */ Warning ("Condition is always true"); AddCodeLine ("jsr return1"); } } else { /* Signed compare */ if ((long) val < 0x7FFF) { g_lt (flags, val+1); } else { /* Always true */ Warning ("Condition is always true"); AddCodeLine ("jsr return1"); } } return; case CF_LONG: if (flags & CF_UNSIGNED) { /* Unsigned compare */ if (val < 0xFFFFFFFF) { /* Use < instead of <= because the former gives ** better code on the 6502 than the latter. */ g_lt (flags, val+1); } else { /* Always true */ Warning ("Condition is always true"); AddCodeLine ("jsr return1"); } } else { /* Signed compare */ if ((long) val < 0x7FFFFFFF) { g_lt (flags, val+1); } else { /* Always true */ Warning ("Condition is always true"); AddCodeLine ("jsr return1"); } } return; default: typeerror (flags); } /* If we go here, we didn't emit code. Push the lhs on stack and fall ** into the normal, non-optimized stuff. Note: The standard stuff will ** always work with ints. */ flags &= ~CF_FORCECHAR; g_push (flags & ~CF_CONST, 0); } /* Use long way over the stack */ oper (flags, val, ops); } void g_gt (unsigned flags, unsigned long val) /* Test for greater than */ { static const char* const ops[4] = { "tosgtax", "tosugtax", "tosgteax", "tosugteax" }; /* If the right hand side is const, the lhs is not on stack but still ** in the primary register. */ if (flags & CF_CONST) { /* Look at the type */ switch (flags & CF_TYPEMASK) { case CF_CHAR: if (flags & CF_FORCECHAR) { if (flags & CF_UNSIGNED) { if (val == 0) { /* If we have a compare > 0, we will replace it by ** != 0 here, since both are identical but the ** latter is easier to optimize. */ g_ne (flags, val); } else if (val < 0xFF) { /* Use >= instead of > because the former gives ** better code on the 6502 than the latter. */ g_ge (flags, val+1); } else { /* Never true */ Warning ("Condition is never true"); AddCodeLine ("jsr return0"); } } else { if ((long) val < 0x7F) { /* Use >= instead of > because the former gives ** better code on the 6502 than the latter. */ g_ge (flags, val+1); } else { /* Never true */ Warning ("Condition is never true"); AddCodeLine ("jsr return0"); } } return; } /* FALLTHROUGH */ case CF_INT: if (flags & CF_UNSIGNED) { /* Unsigned compare */ if (val == 0) { /* If we have a compare > 0, we will replace it by ** != 0 here, since both are identical but the latter ** is easier to optimize. */ g_ne (flags, val); } else if (val < 0xFFFF) { /* Use >= instead of > because the former gives better ** code on the 6502 than the latter. */ g_ge (flags, val+1); } else { /* Never true */ Warning ("Condition is never true"); AddCodeLine ("jsr return0"); } } else { /* Signed compare */ if ((long) val < 0x7FFF) { g_ge (flags, val+1); } else { /* Never true */ Warning ("Condition is never true"); AddCodeLine ("jsr return0"); } } return; case CF_LONG: if (flags & CF_UNSIGNED) { /* Unsigned compare */ if (val == 0) { /* If we have a compare > 0, we will replace it by ** != 0 here, since both are identical but the latter ** is easier to optimize. */ g_ne (flags, val); } else if (val < 0xFFFFFFFF) { /* Use >= instead of > because the former gives better ** code on the 6502 than the latter. */ g_ge (flags, val+1); } else { /* Never true */ Warning ("Condition is never true"); AddCodeLine ("jsr return0"); } } else { /* Signed compare */ if ((long) val < 0x7FFFFFFF) { g_ge (flags, val+1); } else { /* Never true */ Warning ("Condition is never true"); AddCodeLine ("jsr return0"); } } return; default: typeerror (flags); } /* If we go here, we didn't emit code. Push the lhs on stack and fall ** into the normal, non-optimized stuff. Note: The standard stuff will ** always work with ints. */ flags &= ~CF_FORCECHAR; g_push (flags & ~CF_CONST, 0); } /* Use long way over the stack */ oper (flags, val, ops); } void g_ge (unsigned flags, unsigned long val) /* Test for greater than or equal to */ { static const char* const ops[4] = { "tosgeax", "tosugeax", "tosgeeax", "tosugeeax" }; unsigned Label; /* If the right hand side is const, the lhs is not on stack but still ** in the primary register. */ if (flags & CF_CONST) { /* Because the handling of the overflow flag is too complex for ** inlining, we can handle only unsigned compares, and signed ** compares against zero here. */ if (flags & CF_UNSIGNED) { /* Give a warning in some special cases */ if (val == 0) { Warning ("Condition is always true"); AddCodeLine ("jsr return1"); return; } /* Look at the type */ switch (flags & CF_TYPEMASK) { case CF_CHAR: if (flags & CF_FORCECHAR) { /* Do a subtraction. Condition is true if carry set */ AddCodeLine ("cmp #$%02X", (unsigned char)val); AddCodeLine ("lda #$00"); AddCodeLine ("ldx #$00"); AddCodeLine ("rol a"); return; } /* FALLTHROUGH */ case CF_INT: /* Do a subtraction. Condition is true if carry set */ AddCodeLine ("cmp #$%02X", (unsigned char)val); AddCodeLine ("txa"); AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 8)); AddCodeLine ("lda #$00"); AddCodeLine ("ldx #$00"); AddCodeLine ("rol a"); return; case CF_LONG: /* Do a subtraction. Condition is true if carry set */ AddCodeLine ("cmp #$%02X", (unsigned char)val); AddCodeLine ("txa"); AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 8)); AddCodeLine ("lda sreg"); AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 16)); AddCodeLine ("lda sreg+1"); AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 24)); AddCodeLine ("lda #$00"); AddCodeLine ("ldx #$00"); AddCodeLine ("rol a"); return; default: typeerror (flags); } } else if (val == 0) { /* A signed compare against zero must only look at the sign bit */ switch (flags & CF_TYPEMASK) { case CF_CHAR: if (flags & CF_FORCECHAR) { AddCodeLine ("tax"); AddCodeLine ("jsr boolge"); return; } /* FALLTHROUGH */ case CF_INT: /* Just test the high byte */ AddCodeLine ("txa"); AddCodeLine ("jsr boolge"); return; case CF_LONG: /* Just test the high byte */ AddCodeLine ("lda sreg+1"); AddCodeLine ("jsr boolge"); return; default: typeerror (flags); } } else { /* Signed compare against a constant != zero */ switch (flags & CF_TYPEMASK) { case CF_CHAR: if (flags & CF_FORCECHAR) { Label = GetLocalLabel (); AddCodeLine ("sec"); AddCodeLine ("sbc #$%02X", (unsigned char)val); AddCodeLine ("bvs %s", LocalLabelName (Label)); AddCodeLine ("eor #$80"); g_defcodelabel (Label); AddCodeLine ("asl a"); /* Bit 7 -> carry */ AddCodeLine ("lda #$00"); AddCodeLine ("ldx #$00"); AddCodeLine ("rol a"); return; } /* FALLTHROUGH */ case CF_INT: /* Do a subtraction */ Label = GetLocalLabel (); AddCodeLine ("cmp #$%02X", (unsigned char)val); AddCodeLine ("txa"); AddCodeLine ("sbc #$%02X", (unsigned char)(val >> 8)); AddCodeLine ("bvs %s", LocalLabelName (Label)); AddCodeLine ("eor #$80"); g_defcodelabel (Label); AddCodeLine ("asl a"); /* Bit 7 -> carry */ AddCodeLine ("lda #$00"); AddCodeLine ("ldx #$00"); AddCodeLine ("rol a"); return; case CF_LONG: /* This one is too costly */ break; default: typeerror (flags); } } /* If we go here, we didn't emit code. Push the lhs on stack and fall ** into the normal, non-optimized stuff. Note: The standard stuff will ** always work with ints. */ flags &= ~CF_FORCECHAR; g_push (flags & ~CF_CONST, 0); } /* Use long way over the stack */ oper (flags, val, ops); } /*****************************************************************************/ /* Allocating static storage */ /*****************************************************************************/ void g_res (unsigned n) /* Reserve static storage, n bytes */ { AddDataLine ("\t.res\t%u,$00", n); } void g_defdata (unsigned flags, unsigned long val, long offs) /* Define data with the size given in flags */ { if (flags & CF_CONST) { /* Numeric constant */ switch (flags & CF_TYPEMASK) { case CF_CHAR: AddDataLine ("\t.byte\t$%02lX", val & 0xFF); break; case CF_INT: AddDataLine ("\t.word\t$%04lX", val & 0xFFFF); break; case CF_LONG: AddDataLine ("\t.dword\t$%08lX", val & 0xFFFFFFFF); break; default: typeerror (flags); break; } } else { /* Create the correct label name */ const char* Label = GetLabelName (flags, val, offs); /* Labels are always 16 bit */ AddDataLine ("\t.addr\t%s", Label); } } void g_defbytes (const void* Bytes, unsigned Count) /* Output a row of bytes as a constant */ { unsigned Chunk; char Buf [128]; char* B; /* Cast the buffer pointer */ const unsigned char* Data = (const unsigned char*) Bytes; /* Output the stuff */ while (Count) { /* How many go into this line? */ if ((Chunk = Count) > 16) { Chunk = 16; } Count -= Chunk; /* Output one line */ strcpy (Buf, "\t.byte\t"); B = Buf + 7; do { B += sprintf (B, "$%02X", *Data++); if (--Chunk) { *B++ = ','; } } while (Chunk); /* Output the line */ AddDataLine ("%s", Buf); } } void g_zerobytes (unsigned Count) /* Output Count bytes of data initialized with zero */ { if (Count > 0) { AddDataLine ("\t.res\t%u,$00", Count); } } void g_initregister (unsigned Label, unsigned Reg, unsigned Size) /* Initialize a register variable from static initialization data */ { /* Register variables do always have less than 128 bytes */ unsigned CodeLabel = GetLocalLabel (); AddCodeLine ("ldx #$%02X", (unsigned char) (Size - 1)); g_defcodelabel (CodeLabel); AddCodeLine ("lda %s,x", GetLabelName (CF_STATIC, Label, 0)); AddCodeLine ("sta %s,x", GetLabelName (CF_REGVAR, Reg, 0)); AddCodeLine ("dex"); AddCodeLine ("bpl %s", LocalLabelName (CodeLabel)); } void g_initauto (unsigned Label, unsigned Size) /* Initialize a local variable at stack offset zero from static data */ { unsigned CodeLabel = GetLocalLabel (); CheckLocalOffs (Size); if (Size <= 128) { AddCodeLine ("ldy #$%02X", Size-1); g_defcodelabel (CodeLabel); AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, Label, 0)); AddCodeLine ("sta (sp),y"); AddCodeLine ("dey"); AddCodeLine ("bpl %s", LocalLabelName (CodeLabel)); } else if (Size <= 256) { AddCodeLine ("ldy #$00"); g_defcodelabel (CodeLabel); AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, Label, 0)); AddCodeLine ("sta (sp),y"); AddCodeLine ("iny"); AddCmpCodeIfSizeNot256 ("cpy #$%02X", Size); AddCodeLine ("bne %s", LocalLabelName (CodeLabel)); } } void g_initstatic (unsigned InitLabel, unsigned VarLabel, unsigned Size) /* Initialize a static local variable from static initialization data */ { if (Size <= 128) { unsigned CodeLabel = GetLocalLabel (); AddCodeLine ("ldy #$%02X", Size-1); g_defcodelabel (CodeLabel); AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, InitLabel, 0)); AddCodeLine ("sta %s,y", GetLabelName (CF_STATIC, VarLabel, 0)); AddCodeLine ("dey"); AddCodeLine ("bpl %s", LocalLabelName (CodeLabel)); } else if (Size <= 256) { unsigned CodeLabel = GetLocalLabel (); AddCodeLine ("ldy #$00"); g_defcodelabel (CodeLabel); AddCodeLine ("lda %s,y", GetLabelName (CF_STATIC, InitLabel, 0)); AddCodeLine ("sta %s,y", GetLabelName (CF_STATIC, VarLabel, 0)); AddCodeLine ("iny"); AddCmpCodeIfSizeNot256 ("cpy #$%02X", Size); AddCodeLine ("bne %s", LocalLabelName (CodeLabel)); } else { /* Use the easy way here: memcpy() */ g_getimmed (CF_STATIC, VarLabel, 0); AddCodeLine ("jsr pushax"); g_getimmed (CF_STATIC, InitLabel, 0); AddCodeLine ("jsr pushax"); g_getimmed (CF_INT | CF_UNSIGNED | CF_CONST, Size, 0); AddCodeLine ("jsr %s", GetLabelName (CF_EXTERNAL, (uintptr_t) "memcpy", 0)); } } /*****************************************************************************/ /* Switch statement */ /*****************************************************************************/ void g_switch (Collection* Nodes, unsigned DefaultLabel, unsigned Depth) /* Generate code for a switch statement */ { unsigned NextLabel = 0; unsigned I; /* Setup registers and determine which compare insn to use */ const char* Compare; switch (Depth) { case 1: Compare = "cmp #$%02X"; break; case 2: Compare = "cpx #$%02X"; break; case 3: AddCodeLine ("ldy sreg"); Compare = "cpy #$%02X"; break; case 4: AddCodeLine ("ldy sreg+1"); Compare = "cpy #$%02X"; break; default: Internal ("Invalid depth in g_switch: %u", Depth); } /* Walk over all nodes */ for (I = 0; I < CollCount (Nodes); ++I) { /* Get the next case node */ CaseNode* N = CollAtUnchecked (Nodes, I); /* If we have a next label, define it */ if (NextLabel) { g_defcodelabel (NextLabel); NextLabel = 0; } /* Do the compare */ AddCodeLine (Compare, CN_GetValue (N)); /* If this is the last level, jump directly to the case code if found */ if (Depth == 1) { /* Branch if equal */ g_falsejump (0, CN_GetLabel (N)); } else { /* Determine the next label */ if (I == CollCount (Nodes) - 1) { /* Last node means not found */ g_truejump (0, DefaultLabel); } else { /* Jump to the next check */ NextLabel = GetLocalLabel (); g_truejump (0, NextLabel); } /* Check the next level */ g_switch (N->Nodes, DefaultLabel, Depth-1); } } /* If we go here, we haven't found the label */ g_jump (DefaultLabel); } /*****************************************************************************/ /* User supplied assembler code */ /*****************************************************************************/ void g_asmcode (struct StrBuf* B) /* Output one line of assembler code. */ { AddCodeLine ("%.*s", (int) SB_GetLen (B), SB_GetConstBuf (B)); } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/codegen.h������������������������������������������������������������������������0000664�0000000�0000000�00000041613�13473601511�0015316�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* codegen.h */ /* */ /* 6502 code generator */ /* */ /* */ /* */ /* (C) 1998-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef CODEGEN_H #define CODEGEN_H /* common */ #include "coll.h" #include "inttypes.h" /* cc65 */ #include "segments.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Code generator flags. ** Note: The type flags are designed so that a smaller type may override a ** larger one by or'ing it into the existing one. ** Note^2: The actual type including the sign flag is in the lower bits, so ** we can mask the information and use them as a table index. */ #define CF_NONE 0x0000 /* No special flags */ /* Values for the actual type */ #define CF_CHAR 0x0003 /* Operation on characters */ #define CF_INT 0x0001 /* Operation on ints */ #define CF_PTR CF_INT /* Alias for readability */ #define CF_LONG 0x0000 /* Operation on longs */ #define CF_FLOAT 0x0004 /* Operation on a float */ /* Signedness */ #define CF_UNSIGNED 0x0008 /* Value is unsigned */ /* Masks for retrieving type information */ #define CF_TYPEMASK 0x0007 /* Type information */ #define CF_STYPEMASK 0x000F /* Includes signedness */ #define CF_NOKEEP 0x0010 /* Value may get destroyed when storing */ #define CF_CONST 0x0020 /* Constant value available */ #define CF_CONSTADDR 0x0040 /* Constant address value available */ #define CF_TEST 0x0080 /* Test value */ #define CF_FIXARGC 0x0100 /* Function has fixed arg count */ #define CF_FORCECHAR 0x0200 /* Handle chars as chars, not ints */ #define CF_REG 0x0800 /* Value is in primary register */ /* Type of static address */ #define CF_ADDRMASK 0xF000 /* Type of address */ #define CF_STATIC 0x0000 /* Static local */ #define CF_EXTERNAL 0x1000 /* Static external */ #define CF_ABSOLUTE 0x2000 /* Numeric absolute address */ #define CF_LOCAL 0x4000 /* Auto variable */ #define CF_REGVAR 0x8000 /* Register variable */ /* Forward */ struct StrBuf; /*****************************************************************************/ /* Files, pre- and postamble */ /*****************************************************************************/ void g_preamble (void); /* Generate the assembler code preamble */ void g_fileinfo (const char* Name, unsigned long Size, unsigned long MTime); /* If debug info is enabled, place a file info into the source */ /*****************************************************************************/ /* Segment support */ /*****************************************************************************/ void g_userodata (void); /* Switch to the read only data segment */ void g_usedata (void); /* Switch to the data segment */ void g_usebss (void); /* Switch to the bss segment */ void g_segname (segment_t Seg); /* Emit the name of a segment if necessary */ /*****************************************************************************/ /* Functions handling local labels */ /*****************************************************************************/ void g_defcodelabel (unsigned label); /* Define a local code label */ void g_defdatalabel (unsigned label); /* Define a local data label */ void g_aliasdatalabel (unsigned label, unsigned baselabel, long offs); /* Define label as a local alias for baselabel+offs */ /*****************************************************************************/ /* Functions handling global labels */ /*****************************************************************************/ void g_defgloblabel (const char* Name); /* Define a global label with the given name */ void g_defexport (const char* Name, int ZP); /* Export the given label */ void g_defimport (const char* Name, int ZP); /* Import the given label */ void g_importstartup (void); /* Forced import of the startup segment */ void g_importmainargs (void); /* Forced import of a special symbol that handles arguments to main */ /*****************************************************************************/ /* stack */ /*****************************************************************************/ int pop (unsigned flags); /* Pop an argument of the given size */ int push (unsigned flags); /* Push an argument of the given size */ unsigned sizeofarg (unsigned flags); /* Return the size of a function argument type that is encoded in flags */ /*****************************************************************************/ /* type conversion and similiar stuff */ /*****************************************************************************/ void g_toslong (unsigned flags); /* Make sure, the value on TOS is a long. Convert if necessary */ void g_tosint (unsigned flags); /* Make sure, the value on TOS is an int. Convert if necessary */ void g_regint (unsigned Flags); /* Make sure, the value in the primary register an int. Convert if necessary */ void g_reglong (unsigned Flags); /* Make sure, the value in the primary register a long. Convert if necessary */ unsigned g_typeadjust (unsigned lhs, unsigned rhs); /* Adjust the integer operands before doing a binary operation. lhs is a flags ** value, that corresponds to the value on TOS, rhs corresponds to the value ** in (e)ax. The return value is the the flags value for the resulting type. */ unsigned g_typecast (unsigned lhs, unsigned rhs); /* Cast the value in the primary register to the operand size that is flagged ** by the lhs value. Return the result value. */ void g_scale (unsigned flags, long val); /* Scale the value in the primary register by the given value. If val is positive, ** scale up, is val is negative, scale down. This function is used to scale ** the operands or results of pointer arithmetic by the size of the type, the ** pointer points to. */ /*****************************************************************************/ /* Function entry and exit */ /*****************************************************************************/ void g_enter (unsigned flags, unsigned argsize); /* Function prologue */ void g_leave (void); /* Function epilogue */ /*****************************************************************************/ /* Register variables */ /*****************************************************************************/ void g_swap_regvars (int StackOffs, int RegOffs, unsigned Bytes); /* Swap a register variable with a location on the stack */ void g_save_regvars (int RegOffs, unsigned Bytes); /* Save register variables */ void g_restore_regvars (int StackOffs, int RegOffs, unsigned Bytes); /* Restore register variables */ /*****************************************************************************/ /* Fetching memory cells */ /*****************************************************************************/ void g_getimmed (unsigned Flags, unsigned long Val, long Offs); /* Load a constant into the primary register */ void g_getstatic (unsigned Flags, uintptr_t Label, long Offs); /* Fetch an static memory cell into the primary register */ void g_getlocal (unsigned Flags, int Offs); /* Fetch specified local object (local var). */ void g_getind (unsigned Flags, unsigned Offs); /* Fetch the specified object type indirect through the primary register ** into the primary register */ void g_leasp (int Offs); /* Fetch the address of the specified symbol into the primary register */ void g_leavariadic (int Offs); /* Fetch the address of a parameter in a variadic function into the primary ** register */ /*****************************************************************************/ /* Store into memory */ /*****************************************************************************/ void g_putstatic (unsigned flags, uintptr_t label, long offs); /* Store the primary register into the specified static memory cell */ void g_putlocal (unsigned Flags, int Offs, long Val); /* Put data into local object. */ void g_putind (unsigned flags, unsigned offs); /* Store the specified object type in the primary register at the address ** on the top of the stack */ /*****************************************************************************/ /* Adds and subs of variables fix a fixed address */ /*****************************************************************************/ void g_addlocal (unsigned flags, int offs); /* Add a local variable to ax */ void g_addstatic (unsigned flags, uintptr_t label, long offs); /* Add a static variable to ax */ /*****************************************************************************/ /* Special op= functions */ /*****************************************************************************/ void g_addeqstatic (unsigned flags, uintptr_t label, long offs, unsigned long val); /* Emit += for a static variable */ void g_addeqlocal (unsigned flags, int offs, unsigned long val); /* Emit += for a local variable */ void g_addeqind (unsigned flags, unsigned offs, unsigned long val); /* Emit += for the location with address in ax */ void g_subeqstatic (unsigned flags, uintptr_t label, long offs, unsigned long val); /* Emit -= for a static variable */ void g_subeqlocal (unsigned flags, int offs, unsigned long val); /* Emit -= for a local variable */ void g_subeqind (unsigned flags, unsigned offs, unsigned long val); /* Emit -= for the location with address in ax */ /*****************************************************************************/ /* Add a variable address to the value in ax */ /*****************************************************************************/ void g_addaddr_local (unsigned flags, int offs); /* Add the address of a local variable to ax */ void g_addaddr_static (unsigned flags, uintptr_t label, long offs); /* Add the address of a static variable to ax */ /*****************************************************************************/ /* */ /*****************************************************************************/ void g_save (unsigned flags); /* Copy primary register to hold register. */ void g_restore (unsigned flags); /* Copy hold register to primary. */ void g_cmp (unsigned flags, unsigned long val); /* Immidiate compare. The primary register will not be changed, Z flag ** will be set. */ void g_test (unsigned flags); /* Test the value in the primary and set the condition codes */ void g_push (unsigned flags, unsigned long val); /* Push the primary register or a constant value onto the stack */ void g_swap (unsigned flags); /* Swap the primary register and the top of the stack. flags give the type ** of *both* values (must have same size). */ void g_call (unsigned Flags, const char* Label, unsigned ArgSize); /* Call the specified subroutine name */ void g_callind (unsigned Flags, unsigned ArgSize, int Offs); /* Call subroutine indirect */ void g_jump (unsigned Label); /* Jump to specified internal label number */ void g_truejump (unsigned flags, unsigned label); /* Jump to label if zero flag clear */ void g_falsejump (unsigned flags, unsigned label); /* Jump to label if zero flag set */ void g_lateadjustSP (unsigned label); /* Adjust stack based on non-immediate data */ void g_drop (unsigned Space); /* Drop space allocated on the stack */ void g_space (int space); /* Create or drop space on the stack */ void g_cstackcheck (void); /* Check for a C stack overflow */ void g_stackcheck (void); /* Check for a stack overflow */ void g_add (unsigned flags, unsigned long val); void g_sub (unsigned flags, unsigned long val); void g_rsub (unsigned flags, unsigned long val); void g_mul (unsigned flags, unsigned long val); void g_div (unsigned flags, unsigned long val); void g_mod (unsigned flags, unsigned long val); void g_or (unsigned flags, unsigned long val); void g_xor (unsigned flags, unsigned long val); void g_and (unsigned flags, unsigned long val); void g_asr (unsigned flags, unsigned long val); void g_asl (unsigned flags, unsigned long val); void g_neg (unsigned flags); void g_bneg (unsigned flags); void g_com (unsigned flags); void g_inc (unsigned flags, unsigned long n); void g_dec (unsigned flags, unsigned long n); void g_eq (unsigned flags, unsigned long val); void g_ne (unsigned flags, unsigned long val); void g_lt (unsigned flags, unsigned long val); void g_le (unsigned flags, unsigned long val); void g_gt (unsigned flags, unsigned long val); void g_ge (unsigned flags, unsigned long val); void g_res (unsigned n); /* Reserve static storage, n bytes */ void g_defdata (unsigned flags, unsigned long val, long offs); /* Define data with the size given in flags */ void g_defbytes (const void* bytes, unsigned count); /* Output a row of bytes as a constant */ void g_zerobytes (unsigned Count); /* Output Count bytes of data initialized with zero */ void g_initregister (unsigned Label, unsigned Reg, unsigned Size); /* Initialize a register variable from static initialization data */ void g_initauto (unsigned Label, unsigned Size); /* Initialize a local variable at stack offset zero from static data */ void g_initstatic (unsigned InitLabel, unsigned VarLabel, unsigned Size); /* Initialize a static local variable from static initialization data */ /*****************************************************************************/ /* Switch statement */ /*****************************************************************************/ void g_switch (Collection* Nodes, unsigned DefaultLabel, unsigned Depth); /* Generate code for a switch statement */ /*****************************************************************************/ /* User supplied assembler code */ /*****************************************************************************/ void g_asmcode (struct StrBuf* B); /* Output one line of assembler code. */ /* End of codegen.h */ #endif ���������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/codeinfo.c�����������������������������������������������������������������������0000664�0000000�0000000�00000115771�13473601511�0015502�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* codeinfo.c */ /* */ /* Additional information about 6502 code */ /* */ /* */ /* */ /* (C) 2001-2015, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdlib.h> #include <string.h> /* common */ #include "chartype.h" #include "coll.h" #include "debugflag.h" /* cc65 */ #include "codeent.h" #include "codeseg.h" #include "datatype.h" #include "error.h" #include "global.h" #include "reginfo.h" #include "symtab.h" #include "codeinfo.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Table with the compare suffixes */ static const char CmpSuffixTab [][4] = { "eq", "ne", "gt", "ge", "lt", "le", "ugt", "uge", "ult", "ule" }; /* Table listing the function names and code info values for known internally ** used functions. This table should get auto-generated in the future. */ typedef struct FuncInfo FuncInfo; struct FuncInfo { const char* Name; /* Function name */ unsigned short Use; /* Register usage */ unsigned short Chg; /* Changed/destroyed registers */ }; /* Note for the shift functions: Shifts are done modulo 32, so all shift ** routines are marked to use only the A register. The remainder is ignored ** anyway. */ static const FuncInfo FuncInfoTable[] = { { "addeq0sp", REG_AX, REG_AXY }, { "addeqysp", REG_AXY, REG_AXY }, { "addysp", REG_Y, REG_NONE }, { "aslax1", REG_AX, REG_AX | REG_TMP1 }, { "aslax2", REG_AX, REG_AX | REG_TMP1 }, { "aslax3", REG_AX, REG_AX | REG_TMP1 }, { "aslax4", REG_AX, REG_AX | REG_TMP1 }, { "aslaxy", REG_AXY, REG_AXY | REG_TMP1 }, { "asleax1", REG_EAX, REG_EAX | REG_TMP1 }, { "asleax2", REG_EAX, REG_EAX | REG_TMP1 }, { "asleax3", REG_EAX, REG_EAX | REG_TMP1 }, { "asleax4", REG_EAX, REG_EAXY | REG_TMP1 }, { "asrax1", REG_AX, REG_AX | REG_TMP1 }, { "asrax2", REG_AX, REG_AX | REG_TMP1 }, { "asrax3", REG_AX, REG_AX | REG_TMP1 }, { "asrax4", REG_AX, REG_AX | REG_TMP1 }, { "asraxy", REG_AXY, REG_AXY | REG_TMP1 }, { "asreax1", REG_EAX, REG_EAX | REG_TMP1 }, { "asreax2", REG_EAX, REG_EAX | REG_TMP1 }, { "asreax3", REG_EAX, REG_EAX | REG_TMP1 }, { "asreax4", REG_EAX, REG_EAXY | REG_TMP1 }, { "bnega", REG_A, REG_AX }, { "bnegax", REG_AX, REG_AX }, { "bnegeax", REG_EAX, REG_EAX }, { "booleq", REG_NONE, REG_AX }, { "boolge", REG_NONE, REG_AX }, { "boolgt", REG_NONE, REG_AX }, { "boolle", REG_NONE, REG_AX }, { "boollt", REG_NONE, REG_AX }, { "boolne", REG_NONE, REG_AX }, { "booluge", REG_NONE, REG_AX }, { "boolugt", REG_NONE, REG_AX }, { "boolule", REG_NONE, REG_AX }, { "boolult", REG_NONE, REG_AX }, { "callax", REG_AX, REG_ALL }, { "complax", REG_AX, REG_AX }, { "decax1", REG_AX, REG_AX }, { "decax2", REG_AX, REG_AX }, { "decax3", REG_AX, REG_AX }, { "decax4", REG_AX, REG_AX }, { "decax5", REG_AX, REG_AX }, { "decax6", REG_AX, REG_AX }, { "decax7", REG_AX, REG_AX }, { "decax8", REG_AX, REG_AX }, { "decaxy", REG_AXY, REG_AX | REG_TMP1 }, { "deceaxy", REG_EAXY, REG_EAX }, { "decsp1", REG_NONE, REG_Y }, { "decsp2", REG_NONE, REG_A }, { "decsp3", REG_NONE, REG_A }, { "decsp4", REG_NONE, REG_A }, { "decsp5", REG_NONE, REG_A }, { "decsp6", REG_NONE, REG_A }, { "decsp7", REG_NONE, REG_A }, { "decsp8", REG_NONE, REG_A }, { "incax1", REG_AX, REG_AX }, { "incax2", REG_AX, REG_AX }, { "incax3", REG_AX, REG_AXY | REG_TMP1 }, { "incax4", REG_AX, REG_AXY | REG_TMP1 }, { "incax5", REG_AX, REG_AXY | REG_TMP1 }, { "incax6", REG_AX, REG_AXY | REG_TMP1 }, { "incax7", REG_AX, REG_AXY | REG_TMP1 }, { "incax8", REG_AX, REG_AXY | REG_TMP1 }, { "incaxy", REG_AXY, REG_AXY | REG_TMP1 }, { "incsp1", REG_NONE, REG_NONE }, { "incsp2", REG_NONE, REG_Y }, { "incsp3", REG_NONE, REG_Y }, { "incsp4", REG_NONE, REG_Y }, { "incsp5", REG_NONE, REG_Y }, { "incsp6", REG_NONE, REG_Y }, { "incsp7", REG_NONE, REG_Y }, { "incsp8", REG_NONE, REG_Y }, { "laddeq", REG_EAXY|REG_PTR1_LO, REG_EAXY | REG_PTR1_HI }, { "laddeq0sp", REG_EAX, REG_EAXY }, { "laddeq1", REG_Y | REG_PTR1_LO, REG_EAXY | REG_PTR1_HI }, { "laddeqa", REG_AY | REG_PTR1_LO, REG_EAXY | REG_PTR1_HI }, { "laddeqysp", REG_EAXY, REG_EAXY }, { "ldaidx", REG_AXY, REG_AX | REG_PTR1 }, { "ldauidx", REG_AXY, REG_AX | REG_PTR1 }, { "ldax0sp", REG_NONE, REG_AXY }, { "ldaxi", REG_AX, REG_AXY | REG_PTR1 }, { "ldaxidx", REG_AXY, REG_AXY | REG_PTR1 }, { "ldaxysp", REG_Y, REG_AXY }, { "ldeax0sp", REG_NONE, REG_EAXY }, { "ldeaxi", REG_AX, REG_EAXY | REG_PTR1 }, { "ldeaxidx", REG_AXY, REG_EAXY | REG_PTR1 }, { "ldeaxysp", REG_Y, REG_EAXY }, { "leaa0sp", REG_A, REG_AX }, { "leaaxsp", REG_AX, REG_AX }, { "lsubeq", REG_EAXY|REG_PTR1_LO, REG_EAXY | REG_PTR1_HI }, { "lsubeq0sp", REG_EAX, REG_EAXY }, { "lsubeq1", REG_Y | REG_PTR1_LO, REG_EAXY | REG_PTR1_HI }, { "lsubeqa", REG_AY | REG_PTR1_LO, REG_EAXY | REG_PTR1_HI }, { "lsubeqysp", REG_EAXY, REG_EAXY }, { "mulax10", REG_AX, REG_AX | REG_PTR1 }, { "mulax3", REG_AX, REG_AX | REG_PTR1 }, { "mulax5", REG_AX, REG_AX | REG_PTR1 }, { "mulax6", REG_AX, REG_AX | REG_PTR1 }, { "mulax7", REG_AX, REG_AX | REG_PTR1 }, { "mulax9", REG_AX, REG_AX | REG_PTR1 }, { "negax", REG_AX, REG_AX }, { "push0", REG_NONE, REG_AXY }, { "push0ax", REG_AX, REG_Y | REG_SREG }, { "push1", REG_NONE, REG_AXY }, { "push2", REG_NONE, REG_AXY }, { "push3", REG_NONE, REG_AXY }, { "push4", REG_NONE, REG_AXY }, { "push5", REG_NONE, REG_AXY }, { "push6", REG_NONE, REG_AXY }, { "push7", REG_NONE, REG_AXY }, { "pusha", REG_A, REG_Y }, { "pusha0", REG_A, REG_XY }, { "pusha0sp", REG_NONE, REG_AY }, { "pushaFF", REG_A, REG_Y }, { "pushax", REG_AX, REG_Y }, { "pushaysp", REG_Y, REG_AY }, { "pushc0", REG_NONE, REG_A | REG_Y }, { "pushc1", REG_NONE, REG_A | REG_Y }, { "pushc2", REG_NONE, REG_A | REG_Y }, { "pusheax", REG_EAX, REG_Y }, { "pushl0", REG_NONE, REG_AXY }, { "pushw", REG_AX, REG_AXY | REG_PTR1 }, { "pushw0sp", REG_NONE, REG_AXY }, { "pushwidx", REG_AXY, REG_AXY | REG_PTR1 }, { "pushwysp", REG_Y, REG_AXY }, { "regswap", REG_AXY, REG_AXY | REG_TMP1 }, { "regswap1", REG_XY, REG_A }, { "regswap2", REG_XY, REG_A | REG_Y }, { "return0", REG_NONE, REG_AX }, { "return1", REG_NONE, REG_AX }, { "shlax1", REG_AX, REG_AX | REG_TMP1 }, { "shlax2", REG_AX, REG_AX | REG_TMP1 }, { "shlax3", REG_AX, REG_AX | REG_TMP1 }, { "shlax4", REG_AX, REG_AX | REG_TMP1 }, { "shlaxy", REG_AXY, REG_AXY | REG_TMP1 }, { "shleax1", REG_EAX, REG_EAX | REG_TMP1 }, { "shleax2", REG_EAX, REG_EAX | REG_TMP1 }, { "shleax3", REG_EAX, REG_EAX | REG_TMP1 }, { "shleax4", REG_EAX, REG_EAXY | REG_TMP1 }, { "shrax1", REG_AX, REG_AX | REG_TMP1 }, { "shrax2", REG_AX, REG_AX | REG_TMP1 }, { "shrax3", REG_AX, REG_AX | REG_TMP1 }, { "shrax4", REG_AX, REG_AX | REG_TMP1 }, { "shraxy", REG_AXY, REG_AXY | REG_TMP1 }, { "shreax1", REG_EAX, REG_EAX | REG_TMP1 }, { "shreax2", REG_EAX, REG_EAX | REG_TMP1 }, { "shreax3", REG_EAX, REG_EAX | REG_TMP1 }, { "shreax4", REG_EAX, REG_EAXY | REG_TMP1 }, { "staspidx", REG_A | REG_Y, REG_Y | REG_TMP1 | REG_PTR1 }, { "stax0sp", REG_AX, REG_Y }, { "staxspidx", REG_AXY, REG_TMP1 | REG_PTR1 }, { "staxysp", REG_AXY, REG_Y }, { "steax0sp", REG_EAX, REG_Y }, { "steaxysp", REG_EAXY, REG_Y }, { "subeq0sp", REG_AX, REG_AXY }, { "subeqysp", REG_AXY, REG_AXY }, { "subysp", REG_Y, REG_AY }, { "tosadd0ax", REG_AX, REG_EAXY | REG_TMP1 }, { "tosadda0", REG_A, REG_AXY }, { "tosaddax", REG_AX, REG_AXY }, { "tosaddeax", REG_EAX, REG_EAXY | REG_TMP1 }, { "tosand0ax", REG_AX, REG_EAXY | REG_TMP1 }, { "tosanda0", REG_A, REG_AXY }, { "tosandax", REG_AX, REG_AXY }, { "tosandeax", REG_EAX, REG_EAXY | REG_TMP1 }, { "tosaslax", REG_A, REG_AXY | REG_TMP1 }, { "tosasleax", REG_A, REG_EAXY | REG_TMP1 }, { "tosasrax", REG_A, REG_AXY | REG_TMP1 }, { "tosasreax", REG_A, REG_EAXY | REG_TMP1 }, { "tosdiv0ax", REG_AX, REG_ALL }, { "tosdiva0", REG_A, REG_ALL }, { "tosdivax", REG_AX, REG_ALL }, { "tosdiveax", REG_EAX, REG_ALL }, { "toseq00", REG_NONE, REG_AXY | REG_SREG }, { "toseqa0", REG_A, REG_AXY | REG_SREG }, { "toseqax", REG_AX, REG_AXY | REG_SREG }, { "toseqeax", REG_EAX, REG_AXY | REG_PTR1 }, { "tosge00", REG_NONE, REG_AXY | REG_SREG }, { "tosgea0", REG_A, REG_AXY | REG_SREG }, { "tosgeax", REG_AX, REG_AXY | REG_SREG }, { "tosgeeax", REG_EAX, REG_AXY | REG_PTR1 }, { "tosgt00", REG_NONE, REG_AXY | REG_SREG }, { "tosgta0", REG_A, REG_AXY | REG_SREG }, { "tosgtax", REG_AX, REG_AXY | REG_SREG }, { "tosgteax", REG_EAX, REG_AXY | REG_PTR1 }, { "tosicmp", REG_AX, REG_AXY | REG_SREG }, { "tosicmp0", REG_A, REG_AXY | REG_SREG }, { "toslcmp", REG_EAX, REG_A | REG_Y | REG_PTR1 }, { "tosle00", REG_NONE, REG_AXY | REG_SREG }, { "toslea0", REG_A, REG_AXY | REG_SREG }, { "tosleax", REG_AX, REG_AXY | REG_SREG }, { "tosleeax", REG_EAX, REG_AXY | REG_PTR1 }, { "toslt00", REG_NONE, REG_AXY | REG_SREG }, { "toslta0", REG_A, REG_AXY | REG_SREG }, { "tosltax", REG_AX, REG_AXY | REG_SREG }, { "toslteax", REG_EAX, REG_AXY | REG_PTR1 }, { "tosmod0ax", REG_AX, REG_ALL }, { "tosmodeax", REG_EAX, REG_ALL }, { "tosmul0ax", REG_AX, REG_ALL }, { "tosmula0", REG_A, REG_ALL }, { "tosmulax", REG_AX, REG_ALL }, { "tosmuleax", REG_EAX, REG_ALL }, { "tosne00", REG_NONE, REG_AXY | REG_SREG }, { "tosnea0", REG_A, REG_AXY | REG_SREG }, { "tosneax", REG_AX, REG_AXY | REG_SREG }, { "tosneeax", REG_EAX, REG_AXY | REG_PTR1 }, { "tosor0ax", REG_AX, REG_EAXY | REG_TMP1 }, { "tosora0", REG_A, REG_AXY | REG_TMP1 }, { "tosorax", REG_AX, REG_AXY | REG_TMP1 }, { "tosoreax", REG_EAX, REG_EAXY | REG_TMP1 }, { "tosrsub0ax", REG_AX, REG_EAXY | REG_TMP1 }, { "tosrsuba0", REG_A, REG_AXY | REG_TMP1 }, { "tosrsubax", REG_AX, REG_AXY | REG_TMP1 }, { "tosrsubeax", REG_EAX, REG_EAXY | REG_TMP1 }, { "tosshlax", REG_A, REG_AXY | REG_TMP1 }, { "tosshleax", REG_A, REG_EAXY | REG_TMP1 }, { "tosshrax", REG_A, REG_AXY | REG_TMP1 }, { "tosshreax", REG_A, REG_EAXY | REG_TMP1 }, { "tossub0ax", REG_AX, REG_EAXY }, { "tossuba0", REG_A, REG_AXY }, { "tossubax", REG_AX, REG_AXY }, { "tossubeax", REG_EAX, REG_EAXY }, { "tosudiv0ax", REG_AX, REG_ALL & ~REG_SAVE }, { "tosudiva0", REG_A, REG_EAXY | REG_PTR1 }, /* also ptr4 */ { "tosudivax", REG_AX, REG_EAXY | REG_PTR1 }, /* also ptr4 */ { "tosudiveax", REG_EAX, REG_ALL & ~REG_SAVE }, { "tosuge00", REG_NONE, REG_AXY | REG_SREG }, { "tosugea0", REG_A, REG_AXY | REG_SREG }, { "tosugeax", REG_AX, REG_AXY | REG_SREG }, { "tosugeeax", REG_EAX, REG_AXY | REG_PTR1 }, { "tosugt00", REG_NONE, REG_AXY | REG_SREG }, { "tosugta0", REG_A, REG_AXY | REG_SREG }, { "tosugtax", REG_AX, REG_AXY | REG_SREG }, { "tosugteax", REG_EAX, REG_AXY | REG_PTR1 }, { "tosule00", REG_NONE, REG_AXY | REG_SREG }, { "tosulea0", REG_A, REG_AXY | REG_SREG }, { "tosuleax", REG_AX, REG_AXY | REG_SREG }, { "tosuleeax", REG_EAX, REG_AXY | REG_PTR1 }, { "tosult00", REG_NONE, REG_AXY | REG_SREG }, { "tosulta0", REG_A, REG_AXY | REG_SREG }, { "tosultax", REG_AX, REG_AXY | REG_SREG }, { "tosulteax", REG_EAX, REG_AXY | REG_PTR1 }, { "tosumod0ax", REG_AX, REG_ALL & ~REG_SAVE }, { "tosumoda0", REG_A, REG_EAXY | REG_PTR1 }, /* also ptr4 */ { "tosumodax", REG_AX, REG_EAXY | REG_PTR1 }, /* also ptr4 */ { "tosumodeax", REG_EAX, REG_ALL & ~REG_SAVE }, { "tosumul0ax", REG_AX, REG_ALL }, { "tosumula0", REG_A, REG_ALL }, { "tosumulax", REG_AX, REG_ALL }, { "tosumuleax", REG_EAX, REG_ALL }, { "tosxor0ax", REG_AX, REG_EAXY | REG_TMP1 }, { "tosxora0", REG_A, REG_AXY | REG_TMP1 }, { "tosxorax", REG_AX, REG_AXY | REG_TMP1 }, { "tosxoreax", REG_EAX, REG_EAXY | REG_TMP1 }, { "tsteax", REG_EAX, REG_Y }, { "utsteax", REG_EAX, REG_Y }, }; #define FuncInfoCount (sizeof(FuncInfoTable) / sizeof(FuncInfoTable[0])) /* Table with names of zero page locations used by the compiler */ static const ZPInfo ZPInfoTable[] = { { 0, "ptr1", REG_PTR1_LO, REG_PTR1 }, { 0, "ptr1+1", REG_PTR1_HI, REG_PTR1 }, { 0, "ptr2", REG_PTR2_LO, REG_PTR2 }, { 0, "ptr2+1", REG_PTR2_HI, REG_PTR2 }, { 4, "ptr3", REG_NONE, REG_NONE }, { 4, "ptr4", REG_NONE, REG_NONE }, { 7, "regbank", REG_NONE, REG_NONE }, { 0, "regsave", REG_SAVE_LO, REG_SAVE }, { 0, "regsave+1", REG_SAVE_HI, REG_SAVE }, { 0, "sp", REG_SP_LO, REG_SP }, { 0, "sp+1", REG_SP_HI, REG_SP }, { 0, "sreg", REG_SREG_LO, REG_SREG }, { 0, "sreg+1", REG_SREG_HI, REG_SREG }, { 0, "tmp1", REG_TMP1, REG_TMP1 }, { 0, "tmp2", REG_NONE, REG_NONE }, { 0, "tmp3", REG_NONE, REG_NONE }, { 0, "tmp4", REG_NONE, REG_NONE }, }; #define ZPInfoCount (sizeof(ZPInfoTable) / sizeof(ZPInfoTable[0])) /*****************************************************************************/ /* Code */ /*****************************************************************************/ static int CompareFuncInfo (const void* Key, const void* Info) /* Compare function for bsearch */ { return strcmp (Key, ((const FuncInfo*) Info)->Name); } void GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg) /* For the given function, lookup register information and store it into ** the given variables. If the function is unknown, assume it will use and ** load all registers. */ { /* If the function name starts with an underline, it is an external ** function. Search for it in the symbol table. If the function does ** not start with an underline, it may be a runtime support function. ** 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? */ if (E && IsTypeFunc (E->Type)) { FuncDesc* D = E->V.F.Func; /* 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 ((D->Flags & FD_VARIADIC) != 0) { *Use = REG_Y; } else if (D->Flags & FD_CALL_WRAPPER) { /* Wrappers may go to any functions, so mark them as using all ** registers. */ *Use = REG_EAXY; } 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; } /* Will destroy all registers */ *Chg = REG_ALL; /* Done */ return; } } else if (IsDigit (Name[0]) || Name[0] == '$') { /* A call to a numeric address. Assume that anything gets used and ** destroyed. This is not a real problem, since numeric addresses ** are used mostly in inline assembly anyway. */ *Use = REG_ALL; *Chg = REG_ALL; return; } else { /* Search for the function in the list of builtin functions */ const FuncInfo* Info = bsearch (Name, FuncInfoTable, FuncInfoCount, sizeof(FuncInfo), CompareFuncInfo); /* Do we know the function? */ if (Info) { /* Use the information we have */ *Use = Info->Use; *Chg = Info->Chg; } else { /* It's an internal function we have no information for. If in ** debug mode, output an additional warning, so we have a chance ** to fix it. Otherwise assume that the internal function will ** use and change all registers. */ if (Debug) { fprintf (stderr, "No info about internal function '%s'\n", Name); } *Use = REG_ALL; *Chg = REG_ALL; } return; } /* Function not found - assume that the primary register is input, and all ** registers are changed */ *Use = REG_EAXY; *Chg = REG_ALL; } static int CompareZPInfo (const void* Name, const void* Info) /* Compare function for bsearch */ { /* Cast the pointers to the correct data type */ const char* N = (const char*) Name; const ZPInfo* E = (const ZPInfo*) Info; /* Do the compare. Be careful because of the length (Info may contain ** more than just the zeropage name). */ if (E->Len == 0) { /* Do a full compare */ return strcmp (N, E->Name); } else { /* Only compare the first part */ int Res = strncmp (N, E->Name, E->Len); if (Res == 0 && (N[E->Len] != '\0' && N[E->Len] != '+')) { /* Name is actually longer than Info->Name */ Res = -1; } return Res; } } const ZPInfo* GetZPInfo (const char* Name) /* If the given name is a zero page symbol, return a pointer to the info ** struct for this symbol, otherwise return NULL. */ { /* Search for the zp location in the list */ return bsearch (Name, ZPInfoTable, ZPInfoCount, sizeof(ZPInfo), CompareZPInfo); } static unsigned GetRegInfo2 (CodeSeg* S, CodeEntry* E, int Index, Collection* Visited, unsigned Used, unsigned Unused, unsigned Wanted) /* Recursively called subfunction for GetRegInfo. */ { /* Follow the instruction flow recording register usage. */ while (1) { unsigned R; /* Check if we have already visited the current code entry. If so, ** bail out. */ if (CE_HasMark (E)) { break; } /* Mark this entry as already visited */ CE_SetMark (E); CollAppend (Visited, E); /* Evaluate the used registers */ R = E->Use; if (E->OPC == OP65_RTS || ((E->Info & OF_UBRA) != 0 && E->JumpTo == 0)) { /* This instruction will leave the function */ R |= S->ExitRegs; } if (R != REG_NONE) { /* We are not interested in the use of any register that has been ** used before. */ R &= ~Unused; /* Remember the remaining registers */ Used |= R; } /* Evaluate the changed registers */ if ((R = E->Chg) != REG_NONE) { /* We are not interested in the use of any register that has been ** used before. */ R &= ~Used; /* Remember the remaining registers */ Unused |= R; } /* If we know about all registers now, bail out */ if (((Used | Unused) & Wanted) == Wanted) { break; } /* If the instruction is an RTS or RTI, we're done */ if ((E->Info & OF_RET) != 0) { break; } /* If we have an unconditional branch, follow this branch if possible, ** otherwise we're done. */ if ((E->Info & OF_UBRA) != 0) { /* Does this jump have a valid target? */ if (E->JumpTo) { /* Unconditional jump */ E = E->JumpTo->Owner; Index = -1; /* Invalidate */ } else { /* Jump outside means we're done */ break; } /* In case of conditional branches, follow the branch if possible and ** follow the normal flow (branch not taken) afterwards. If we cannot ** follow the branch, we're done. */ } else if ((E->Info & OF_CBRA) != 0) { /* Recursively determine register usage at the branch target */ unsigned U1; unsigned U2; if (E->JumpTo) { /* Jump to internal label */ U1 = GetRegInfo2 (S, E->JumpTo->Owner, -1, Visited, Used, Unused, Wanted); } else { /* Jump to external label. This will effectively exit the ** function, so we use the exitregs information here. */ U1 = S->ExitRegs; } /* Get the next entry */ if (Index < 0) { Index = CS_GetEntryIndex (S, E); } if ((E = CS_GetEntry (S, ++Index)) == 0) { Internal ("GetRegInfo2: No next entry!"); } /* Follow flow if branch not taken */ U2 = GetRegInfo2 (S, E, Index, Visited, Used, Unused, Wanted); /* Registers are used if they're use in any of the branches */ return U1 | U2; } else { /* Just go to the next instruction */ if (Index < 0) { Index = CS_GetEntryIndex (S, E); } E = CS_GetEntry (S, ++Index); if (E == 0) { /* No next entry */ Internal ("GetRegInfo2: No next entry!"); } } } /* Return to the caller the complement of all unused registers */ return Used; } static unsigned GetRegInfo1 (CodeSeg* S, CodeEntry* E, int Index, Collection* Visited, unsigned Used, unsigned Unused, unsigned Wanted) /* Recursively called subfunction for GetRegInfo. */ { /* Remember the current count of the line collection */ unsigned Count = CollCount (Visited); /* Call the worker routine */ unsigned R = GetRegInfo2 (S, E, Index, Visited, Used, Unused, Wanted); /* Restore the old count, unmarking all new entries */ unsigned NewCount = CollCount (Visited); while (NewCount-- > Count) { CodeEntry* E = CollAt (Visited, NewCount); CE_ResetMark (E); CollDelete (Visited, NewCount); } /* Return the registers used */ return R; } unsigned GetRegInfo (struct CodeSeg* S, unsigned Index, unsigned Wanted) /* Determine register usage information for the instructions starting at the ** given index. */ { CodeEntry* E; Collection Visited; /* Visited entries */ unsigned R; /* Get the code entry for the given index */ if (Index >= CS_GetEntryCount (S)) { /* There is no such code entry */ return REG_NONE; } E = CS_GetEntry (S, Index); /* Initialize the data structure used to collection information */ InitCollection (&Visited); /* Call the recursive subfunction */ R = GetRegInfo1 (S, E, Index, &Visited, REG_NONE, REG_NONE, Wanted); /* Delete the line collection */ DoneCollection (&Visited); /* Return the registers used */ return R; } int RegAUsed (struct CodeSeg* S, unsigned Index) /* Check if the value in A is used. */ { return (GetRegInfo (S, Index, REG_A) & REG_A) != 0; } int RegXUsed (struct CodeSeg* S, unsigned Index) /* Check if the value in X is used. */ { return (GetRegInfo (S, Index, REG_X) & REG_X) != 0; } int RegYUsed (struct CodeSeg* S, unsigned Index) /* Check if the value in Y is used. */ { return (GetRegInfo (S, Index, REG_Y) & REG_Y) != 0; } int RegAXUsed (struct CodeSeg* S, unsigned Index) /* Check if the value in A or(!) the value in X are used. */ { return (GetRegInfo (S, Index, REG_AX) & REG_AX) != 0; } int RegEAXUsed (struct CodeSeg* S, unsigned Index) /* Check if any of the four bytes in EAX are used. */ { return (GetRegInfo (S, Index, REG_EAX) & REG_EAX) != 0; } unsigned GetKnownReg (unsigned Use, const RegContents* RC) /* Return the register or zero page location from the set in Use, thats ** contents are known. If Use does not contain any register, or if the ** register in question does not have a known value, return REG_NONE. */ { if ((Use & REG_A) != 0) { return (RC == 0 || RC->RegA >= 0)? REG_A : REG_NONE; } else if ((Use & REG_X) != 0) { return (RC == 0 || RC->RegX >= 0)? REG_X : REG_NONE; } else if ((Use & REG_Y) != 0) { return (RC == 0 || RC->RegY >= 0)? REG_Y : REG_NONE; } else if ((Use & REG_TMP1) != 0) { return (RC == 0 || RC->Tmp1 >= 0)? REG_TMP1 : REG_NONE; } else if ((Use & REG_PTR1_LO) != 0) { return (RC == 0 || RC->Ptr1Lo >= 0)? REG_PTR1_LO : REG_NONE; } else if ((Use & REG_PTR1_HI) != 0) { return (RC == 0 || RC->Ptr1Hi >= 0)? REG_PTR1_HI : REG_NONE; } else if ((Use & REG_SREG_LO) != 0) { return (RC == 0 || RC->SRegLo >= 0)? REG_SREG_LO : REG_NONE; } else if ((Use & REG_SREG_HI) != 0) { return (RC == 0 || RC->SRegHi >= 0)? REG_SREG_HI : REG_NONE; } else { return REG_NONE; } } static cmp_t FindCmpCond (const char* Code, unsigned CodeLen) /* Search for a compare condition by the given code using the given length */ { unsigned I; /* Linear search */ for (I = 0; I < sizeof (CmpSuffixTab) / sizeof (CmpSuffixTab [0]); ++I) { if (strncmp (Code, CmpSuffixTab [I], CodeLen) == 0) { /* Found */ return I; } } /* Not found */ return CMP_INV; } cmp_t FindBoolCmpCond (const char* Name) /* Check if the given string is the name of one of the boolean transformer ** subroutine, and if so, return the condition that is evaluated by this ** routine. Return CMP_INV if the condition is not recognised. */ { /* Check for the correct subroutine name */ if (strncmp (Name, "bool", 4) == 0) { /* Name is ok, search for the code in the table */ return FindCmpCond (Name+4, strlen(Name)-4); } else { /* Not found */ return CMP_INV; } } cmp_t FindTosCmpCond (const char* Name) /* Check if this is a call to one of the TOS compare functions (tosgtax). ** Return the condition code or CMP_INV on failure. */ { unsigned Len = strlen (Name); /* Check for the correct subroutine name */ if (strncmp (Name, "tos", 3) == 0 && strcmp (Name+Len-2, "ax") == 0) { /* Name is ok, search for the code in the table */ return FindCmpCond (Name+3, Len-3-2); } else { /* Not found */ return CMP_INV; } } �������cc65-2.18/src/cc65/codeinfo.h�����������������������������������������������������������������������0000664�0000000�0000000�00000015410�13473601511�0015474�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* codeinfo.h */ /* */ /* Additional information about 6502 code */ /* */ /* */ /* */ /* (C) 2001-2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef CODEINFO_H #define CODEINFO_H /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ struct CodeSeg; /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Forward to struct RegContents */ struct RegContents; /* Defines for registers. */ #define REG_NONE 0x0000U #define REG_A 0x0001U #define REG_X 0x0002U #define REG_Y 0x0004U #define REG_TMP1 0x0008U #define REG_PTR1_LO 0x0010U #define REG_PTR1_HI 0x0020U #define REG_PTR2_LO 0x0040U #define REG_PTR2_HI 0x0080U #define REG_SREG_LO 0x0100U #define REG_SREG_HI 0x0200U #define REG_SAVE_LO 0x0400U #define REG_SAVE_HI 0x0800U #define REG_SP_LO 0x1000U #define REG_SP_HI 0x2000U /* Combined register defines */ #define REG_PTR1 (REG_PTR1_LO | REG_PTR1_HI) #define REG_PTR2 (REG_PTR2_LO | REG_PTR2_HI) #define REG_SREG (REG_SREG_LO | REG_SREG_HI) #define REG_SAVE (REG_SAVE_LO | REG_SAVE_HI) #define REG_SP (REG_SP_LO | REG_SP_HI) #define REG_AX (REG_A | REG_X) #define REG_AY (REG_A | REG_Y) #define REG_XY (REG_X | REG_Y) #define REG_AXY (REG_AX | REG_Y) #define REG_EAX (REG_AX | REG_SREG) #define REG_EAXY (REG_EAX | REG_Y) #define REG_ZP 0xFFF8U #define REG_ALL 0xFFFFU /* Zero page register info */ typedef struct ZPInfo ZPInfo; struct ZPInfo { unsigned char Len; /* Length of the following string */ char Name[11]; /* Name of zero page symbol */ unsigned short ByteUse; /* Register info for this symbol */ unsigned short WordUse; /* Register info for 16 bit access */ }; /* Defines for the conditions in a compare */ typedef enum { CMP_INV = -1, CMP_EQ, CMP_NE, CMP_GT, CMP_GE, CMP_LT, CMP_LE, CMP_UGT, CMP_UGE, CMP_ULT, CMP_ULE } cmp_t; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg); /* For the given function, lookup register information and store it into ** the given variables. If the function is unknown, assume it will use and ** load all registers. */ const ZPInfo* GetZPInfo (const char* Name); /* If the given name is a zero page symbol, return a pointer to the info ** struct for this symbol, otherwise return NULL. */ unsigned GetRegInfo (struct CodeSeg* S, unsigned Index, unsigned Wanted); /* Determine register usage information for the instructions starting at the ** given index. */ int RegAUsed (struct CodeSeg* S, unsigned Index); /* Check if the value in A is used. */ int RegXUsed (struct CodeSeg* S, unsigned Index); /* Check if the value in X is used. */ int RegYUsed (struct CodeSeg* S, unsigned Index); /* Check if the value in Y is used. */ int RegAXUsed (struct CodeSeg* S, unsigned Index); /* Check if the value in A or(!) the value in X are used. */ int RegEAXUsed (struct CodeSeg* S, unsigned Index); /* Check if any of the four bytes in EAX are used. */ unsigned GetKnownReg (unsigned Use, const struct RegContents* RC); /* Return the register or zero page location from the set in Use, thats ** contents are known. If Use does not contain any register, or if the ** register in question does not have a known value, return REG_NONE. */ cmp_t FindBoolCmpCond (const char* Name); /* Check if the given string is the name of one of the boolean transformer ** subroutine, and if so, return the condition that is evaluated by this ** routine. Return CMP_INV if the condition is not recognised. */ cmp_t FindTosCmpCond (const char* Name); /* Check if this is a call to one of the TOS compare functions (tosgtax). ** Return the condition code or CMP_INV on failure. */ /* End of codeinfo.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/codelab.c������������������������������������������������������������������������0000664�0000000�0000000�00000011302�13473601511�0015266�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* codelab.c */ /* */ /* Code label structure */ /* */ /* */ /* */ /* (C) 2001-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "check.h" #include "xmalloc.h" /* cc65 */ #include "codeent.h" #include "codelab.h" #include "output.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ CodeLabel* NewCodeLabel (const char* Name, unsigned Hash) /* Create a new code label, initialize and return it */ { /* Allocate memory */ CodeLabel* L = xmalloc (sizeof (CodeLabel)); /* Initialize the fields */ L->Next = 0; L->Name = xstrdup (Name); L->Hash = Hash; L->Owner = 0; InitCollection (&L->JumpFrom); /* Return the new label */ return L; } void FreeCodeLabel (CodeLabel* L) /* Free the given code label */ { /* Free the name */ xfree (L->Name); /* Free the collection */ DoneCollection (&L->JumpFrom); /* Delete the struct */ xfree (L); } void CL_AddRef (CodeLabel* L, struct CodeEntry* E) /* Let the CodeEntry E reference the label L */ { /* The insn at E jumps to this label */ E->JumpTo = L; /* Replace the code entry argument with the name of the new label */ CE_SetArg (E, L->Name); /* Remember that in the label */ CollAppend (&L->JumpFrom, E); } void CL_MoveRefs (CodeLabel* OldLabel, CodeLabel* NewLabel) /* Move all references to OldLabel to point to NewLabel. OldLabel will have no ** more references on return. */ { /* Walk through all instructions referencing the old label */ unsigned Count = CL_GetRefCount (OldLabel); while (Count--) { /* Get the instruction that references the old label */ CodeEntry* E = CL_GetRef (OldLabel, Count); /* Change the reference to the new label */ CHECK (E->JumpTo == OldLabel); CL_AddRef (NewLabel, E); } /* There are no more references to the old label */ CollDeleteAll (&OldLabel->JumpFrom); } void CL_Output (const CodeLabel* L) /* Output the code label to the output file */ { WriteOutput ("%s:", L->Name); if (strlen (L->Name) > 6) { /* Label is too long, add a linefeed */ WriteOutput ("\n"); } } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/codelab.h������������������������������������������������������������������������0000664�0000000�0000000�00000011375�13473601511�0015305�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* codelab.h */ /* */ /* Code label structure */ /* */ /* */ /* */ /* (C) 2001-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef CODELAB_H #define CODELAB_H /* common */ #include "coll.h" /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ struct CodeEntry; /*****************************************************************************/ /* struct CodeLabel */ /*****************************************************************************/ /* Label structure */ typedef struct CodeLabel CodeLabel; struct CodeLabel { CodeLabel* Next; /* Next in hash list */ char* Name; /* Label name */ unsigned Hash; /* Hash over the name */ struct CodeEntry* Owner; /* Owner entry */ Collection JumpFrom; /* Entries that jump here */ }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ CodeLabel* NewCodeLabel (const char* Name, unsigned Hash); /* Create a new code label, initialize and return it */ void FreeCodeLabel (CodeLabel* L); /* Free the given code label */ #if defined(HAVE_INLINE) INLINE unsigned CL_GetRefCount (const CodeLabel* L) /* Get the number of references for this label */ { return CollCount (&L->JumpFrom); } #else # define CL_GetRefCount(L) CollCount (&(L)->JumpFrom) #endif #if defined(HAVE_INLINE) INLINE struct CodeEntry* CL_GetRef (CodeLabel* L, unsigned Index) /* Get a code entry referencing this label */ { return CollAt (&L->JumpFrom, Index); } #else # define CL_GetRef(L, Index) CollAt (&(L)->JumpFrom, (Index)) #endif void CL_AddRef (CodeLabel* L, struct CodeEntry* E); /* Let the CodeEntry E reference the label L */ void CL_MoveRefs (CodeLabel* OldLabel, CodeLabel* NewLabel); /* Move all references to OldLabel to point to NewLabel. OldLabel will have no ** more references on return. */ void CL_Output (const CodeLabel* L); /* Output the code label to the output file */ /* End of codelab.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/codeopt.c������������������������������������������������������������������������0000664�0000000�0000000�00000150301�13473601511�0015335�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* codeopt.c */ /* */ /* Optimizer subroutines */ /* */ /* */ /* */ /* (C) 2001-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdlib.h> #include <string.h> #include <stdarg.h> /* common */ #include "abend.h" #include "chartype.h" #include "cpu.h" #include "debugflag.h" #include "print.h" #include "strbuf.h" #include "xmalloc.h" #include "xsprintf.h" /* cc65 */ #include "asmlabel.h" #include "codeent.h" #include "codeinfo.h" #include "codeopt.h" #include "coptadd.h" #include "coptc02.h" #include "coptcmp.h" #include "coptind.h" #include "coptneg.h" #include "coptptrload.h" #include "coptptrstore.h" #include "coptpush.h" #include "coptshift.h" #include "coptsize.h" #include "coptstop.h" #include "coptstore.h" #include "coptsub.h" #include "copttest.h" #include "error.h" #include "global.h" #include "output.h" #include "symtab.h" /*****************************************************************************/ /* Optimize loads */ /*****************************************************************************/ static unsigned OptLoad1 (CodeSeg* S) /* Search for a call to ldaxysp where X is not used later and replace it by ** a load of just the A register. */ { unsigned I; unsigned Changes = 0; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* E; /* Get next entry */ E = CS_GetEntry (S, I); /* Check for the sequence */ if (CE_IsCallTo (E, "ldaxysp") && RegValIsKnown (E->RI->In.RegY) && !RegXUsed (S, I+1)) { CodeEntry* X; /* Reload the Y register */ const char* Arg = MakeHexArg (E->RI->In.RegY - 1); X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI); CS_InsertEntry (S, X, I+1); /* Load from stack */ X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, E->LI); CS_InsertEntry (S, X, I+2); /* Now remove the call to the subroutine */ CS_DelEntry (S, I); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } static unsigned OptLoad2 (CodeSeg* S) /* Replace calls to ldaxysp by inline code */ { unsigned I; unsigned Changes = 0; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[3]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (CE_IsCallTo (L[0], "ldaxysp")) { CodeEntry* X; /* Followed by sta abs/stx abs? */ if (CS_GetEntries (S, L+1, I+1, 2) && L[1]->OPC == OP65_STA && L[2]->OPC == OP65_STX && (L[1]->Arg == 0 || L[2]->Arg == 0 || strcmp (L[1]->Arg, L[2]->Arg) != 0) && !CS_RangeHasLabel (S, I+1, 2) && !RegXUsed (S, I+3)) { /* A/X are stored into memory somewhere and X is not used ** later */ /* lda (sp),y */ X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, L[0]->LI); CS_InsertEntry (S, X, I+3); /* sta abs */ X = NewCodeEntry (OP65_STA, L[2]->AM, L[2]->Arg, 0, L[2]->LI); CS_InsertEntry (S, X, I+4); /* dey */ X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, L[0]->LI); CS_InsertEntry (S, X, I+5); /* lda (sp),y */ X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, L[0]->LI); CS_InsertEntry (S, X, I+6); /* sta abs */ X = NewCodeEntry (OP65_STA, L[1]->AM, L[1]->Arg, 0, L[1]->LI); CS_InsertEntry (S, X, I+7); /* Now remove the call to the subroutine and the sta/stx */ CS_DelEntries (S, I, 3); } else { /* Standard replacement */ /* lda (sp),y */ X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, L[0]->LI); CS_InsertEntry (S, X, I+1); /* tax */ X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, L[0]->LI); CS_InsertEntry (S, X, I+2); /* dey */ X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, L[0]->LI); CS_InsertEntry (S, X, I+3); /* lda (sp),y */ X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, L[0]->LI); CS_InsertEntry (S, X, I+4); /* Now remove the call to the subroutine */ CS_DelEntry (S, I); } /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } static unsigned OptLoad3 (CodeSeg* S) /* Remove repeated loads from one and the same memory location */ { unsigned Changes = 0; CodeEntry* Load = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Forget a preceeding load if we have a label */ if (Load && CE_HasLabel (E)) { Load = 0; } /* Check if this insn is a load */ if (E->Info & OF_LOAD) { CodeEntry* N; /* If we had a preceeding load that is identical, remove this one. ** If it is not identical, or we didn't have one, remember it. */ if (Load != 0 && E->OPC == Load->OPC && E->AM == Load->AM && ((E->Arg == 0 && Load->Arg == 0) || strcmp (E->Arg, Load->Arg) == 0) && (N = CS_GetNextEntry (S, I)) != 0 && (N->Info & OF_CBRA) == 0) { /* Now remove the call to the subroutine */ CS_DelEntry (S, I); /* Remember, we had changes */ ++Changes; /* Next insn */ continue; } else { Load = E; } } else if ((E->Info & OF_CMP) == 0 && (E->Info & OF_CBRA) == 0) { /* Forget the first load on occurance of any insn we don't like */ Load = 0; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } /*****************************************************************************/ /* Decouple operations */ /*****************************************************************************/ static unsigned OptDecouple (CodeSeg* S) /* Decouple operations, that is, do the following replacements: ** ** dex -> ldx #imm ** inx -> ldx #imm ** dey -> ldy #imm ** iny -> ldy #imm ** tax -> ldx #imm ** txa -> lda #imm ** tay -> ldy #imm ** tya -> lda #imm ** lda zp -> lda #imm ** ldx zp -> ldx #imm ** ldy zp -> ldy #imm ** ** Provided that the register values are known of course. */ { unsigned Changes = 0; unsigned I; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { const char* Arg; /* Get next entry and it's input register values */ CodeEntry* E = CS_GetEntry (S, I); const RegContents* In = &E->RI->In; /* Assume we have no replacement */ CodeEntry* X = 0; /* Check the instruction */ switch (E->OPC) { case OP65_DEA: if (RegValIsKnown (In->RegA)) { Arg = MakeHexArg ((In->RegA - 1) & 0xFF); X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, E->LI); } break; case OP65_DEX: if (RegValIsKnown (In->RegX)) { Arg = MakeHexArg ((In->RegX - 1) & 0xFF); X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, E->LI); } break; case OP65_DEY: if (RegValIsKnown (In->RegY)) { Arg = MakeHexArg ((In->RegY - 1) & 0xFF); X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI); } break; case OP65_INA: if (RegValIsKnown (In->RegA)) { Arg = MakeHexArg ((In->RegA + 1) & 0xFF); X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, E->LI); } break; case OP65_INX: if (RegValIsKnown (In->RegX)) { Arg = MakeHexArg ((In->RegX + 1) & 0xFF); X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, E->LI); } break; case OP65_INY: if (RegValIsKnown (In->RegY)) { Arg = MakeHexArg ((In->RegY + 1) & 0xFF); X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI); } break; case OP65_LDA: if (E->AM == AM65_ZP) { switch (GetKnownReg (E->Use & REG_ZP, In)) { case REG_TMP1: Arg = MakeHexArg (In->Tmp1); X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, E->LI); break; case REG_PTR1_LO: Arg = MakeHexArg (In->Ptr1Lo); X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, E->LI); break; case REG_PTR1_HI: Arg = MakeHexArg (In->Ptr1Hi); X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, E->LI); break; case REG_SREG_LO: Arg = MakeHexArg (In->SRegLo); X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, E->LI); break; case REG_SREG_HI: Arg = MakeHexArg (In->SRegHi); X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, E->LI); break; } } break; case OP65_LDX: if (E->AM == AM65_ZP) { switch (GetKnownReg (E->Use & REG_ZP, In)) { case REG_TMP1: Arg = MakeHexArg (In->Tmp1); X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, E->LI); break; case REG_PTR1_LO: Arg = MakeHexArg (In->Ptr1Lo); X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, E->LI); break; case REG_PTR1_HI: Arg = MakeHexArg (In->Ptr1Hi); X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, E->LI); break; case REG_SREG_LO: Arg = MakeHexArg (In->SRegLo); X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, E->LI); break; case REG_SREG_HI: Arg = MakeHexArg (In->SRegHi); X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, E->LI); break; } } break; case OP65_LDY: if (E->AM == AM65_ZP) { switch (GetKnownReg (E->Use, In)) { case REG_TMP1: Arg = MakeHexArg (In->Tmp1); X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI); break; case REG_PTR1_LO: Arg = MakeHexArg (In->Ptr1Lo); X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI); break; case REG_PTR1_HI: Arg = MakeHexArg (In->Ptr1Hi); X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI); break; case REG_SREG_LO: Arg = MakeHexArg (In->SRegLo); X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI); break; case REG_SREG_HI: Arg = MakeHexArg (In->SRegHi); X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI); break; } } break; case OP65_TAX: if (E->RI->In.RegA >= 0) { Arg = MakeHexArg (In->RegA); X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, E->LI); } break; case OP65_TAY: if (E->RI->In.RegA >= 0) { Arg = MakeHexArg (In->RegA); X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI); } break; case OP65_TXA: if (E->RI->In.RegX >= 0) { Arg = MakeHexArg (In->RegX); X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, E->LI); } break; case OP65_TYA: if (E->RI->In.RegY >= 0) { Arg = MakeHexArg (In->RegY); X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, E->LI); } break; default: /* Avoid gcc warnings */ break; } /* Insert the replacement if we have one */ if (X) { CS_InsertEntry (S, X, I+1); CS_DelEntry (S, I); ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } /*****************************************************************************/ /* Optimize stack pointer ops */ /*****************************************************************************/ static unsigned IsDecSP (const CodeEntry* E) /* Check if this is an insn that decrements the stack pointer. If so, return ** the decrement. If not, return zero. ** The function expects E to be a subroutine call. */ { if (strncmp (E->Arg, "decsp", 5) == 0) { if (E->Arg[5] >= '1' && E->Arg[5] <= '8') { return (E->Arg[5] - '0'); } } else if (strcmp (E->Arg, "subysp") == 0 && RegValIsKnown (E->RI->In.RegY)) { return E->RI->In.RegY; } /* If we come here, it's not a decsp op */ return 0; } static unsigned OptStackPtrOps (CodeSeg* S) /* Merge adjacent calls to decsp into one. NOTE: This function won't merge all ** known cases! */ { unsigned Changes = 0; unsigned I; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { unsigned Dec1; unsigned Dec2; const CodeEntry* N; /* Get the next entry */ const CodeEntry* E = CS_GetEntry (S, I); /* Check for decspn or subysp */ if (E->OPC == OP65_JSR && (Dec1 = IsDecSP (E)) > 0 && (N = CS_GetNextEntry (S, I)) != 0 && (Dec2 = IsDecSP (N)) > 0 && (Dec1 += Dec2) <= 255 && !CE_HasLabel (N)) { CodeEntry* X; char Buf[20]; /* We can combine the two */ if (Dec1 <= 8) { /* Insert a call to decsp */ xsprintf (Buf, sizeof (Buf), "decsp%u", Dec1); X = NewCodeEntry (OP65_JSR, AM65_ABS, Buf, 0, N->LI); CS_InsertEntry (S, X, I+2); } else { /* Insert a call to subysp */ const char* Arg = MakeHexArg (Dec1); X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, N->LI); CS_InsertEntry (S, X, I+2); X = NewCodeEntry (OP65_JSR, AM65_ABS, "subysp", 0, N->LI); CS_InsertEntry (S, X, I+3); } /* Delete the old code */ CS_DelEntries (S, I, 2); /* Regenerate register info */ CS_GenRegInfo (S); /* Remember we had changes */ ++Changes; } else { /* Next entry */ ++I; } } /* Return the number of changes made */ return Changes; } static unsigned OptGotoSPAdj (CodeSeg* S) /* Optimize SP adjustment for forward 'goto' */ { unsigned Changes = 0; unsigned I; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[10], *X; unsigned short adjustment; const char* Arg; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence generated by g_lateadjustSP */ if (L[0]->OPC == OP65_PHA && CS_GetEntries (S, L+1, I+1, 9) && L[1]->OPC == OP65_LDA && L[1]->AM == AM65_ABS && L[2]->OPC == OP65_CLC && L[3]->OPC == OP65_ADC && strcmp (L[3]->Arg, "sp") == 0 && L[6]->OPC == OP65_ADC && strcmp (L[6]->Arg, "sp+1") == 0 && L[9]->OPC == OP65_JMP) { adjustment = FindSPAdjustment (L[1]->Arg); if (adjustment == 0) { /* No SP adjustment needed, remove the whole sequence */ CS_DelEntries (S, I, 9); } else if (adjustment >= 65536 - 8) { /* If adjustment is in range [-8, 0) we use decsp* calls */ char Buf[20]; adjustment = 65536 - adjustment; xsprintf (Buf, sizeof (Buf), "decsp%u", adjustment); X = NewCodeEntry (OP65_JSR, AM65_ABS, Buf, 0, L[1]->LI); CS_InsertEntry (S, X, I + 9); /* Delete the old code */ CS_DelEntries (S, I, 9); } else if (adjustment >= 65536 - 255) { /* For range [-255, -8) we have ldy #, jsr subysp */ adjustment = 65536 - adjustment; Arg = MakeHexArg (adjustment); X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[1]->LI); CS_InsertEntry (S, X, I + 9); X = NewCodeEntry (OP65_JSR, AM65_ABS, "subysp", 0, L[1]->LI); CS_InsertEntry (S, X, I + 10); /* Delete the old code */ CS_DelEntries (S, I, 9); } else if (adjustment > 255) { /* For ranges [-32768, 255) and (255, 32767) the only modification ** is to replace the absolute with immediate addressing */ Arg = MakeHexArg (adjustment & 0xff); X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, L[1]->LI); CS_InsertEntry (S, X, I + 1); Arg = MakeHexArg (adjustment >> 8); X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, L[5]->LI); CS_InsertEntry (S, X, I + 6); /* Delete the old code */ CS_DelEntry (S, I + 2); CS_DelEntry (S, I + 6); } else if (adjustment > 8) { /* For range (8, 255] we have ldy #, jsr addysp */ Arg = MakeHexArg (adjustment & 0xff); X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[1]->LI); CS_InsertEntry (S, X, I + 9); X = NewCodeEntry (OP65_JSR, AM65_ABS, "addysp", 0, L[1]->LI); CS_InsertEntry (S, X, I + 10); /* Delete the old code */ CS_DelEntries (S, I, 9); } else { /* If adjustment is in range (0, 8] we use incsp* calls */ char Buf[20]; xsprintf (Buf, sizeof (Buf), "incsp%u", adjustment); X = NewCodeEntry (OP65_JSR, AM65_ABS, Buf, 0, L[1]->LI); CS_InsertEntry (S, X, I + 9); /* Delete the old code */ CS_DelEntries (S, I, 9); } /* Regenerate register info */ CS_GenRegInfo (S); /* Remember we had changes */ Changes++; } else { /* Next entry */ ++I; } } /* Return the number of changes made */ return Changes; } /*****************************************************************************/ /* struct OptFunc */ /*****************************************************************************/ typedef struct OptFunc OptFunc; struct OptFunc { unsigned (*Func) (CodeSeg*); /* Optimizer function */ const char* Name; /* Name of the function/group */ unsigned CodeSizeFactor; /* Code size factor for this opt func */ unsigned long TotalRuns; /* Total number of runs */ unsigned long LastRuns; /* Last number of runs */ unsigned long TotalChanges; /* Total number of changes */ unsigned long LastChanges; /* Last number of changes */ char Disabled; /* True if function disabled */ }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ /* A list of all the function descriptions */ static OptFunc DOpt65C02BitOps = { Opt65C02BitOps, "Opt65C02BitOps", 66, 0, 0, 0, 0, 0 }; static OptFunc DOpt65C02Ind = { Opt65C02Ind, "Opt65C02Ind", 100, 0, 0, 0, 0, 0 }; static OptFunc DOpt65C02Stores = { Opt65C02Stores, "Opt65C02Stores", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptAdd1 = { OptAdd1, "OptAdd1", 125, 0, 0, 0, 0, 0 }; static OptFunc DOptAdd2 = { OptAdd2, "OptAdd2", 200, 0, 0, 0, 0, 0 }; static OptFunc DOptAdd3 = { OptAdd3, "OptAdd3", 65, 0, 0, 0, 0, 0 }; static OptFunc DOptAdd4 = { OptAdd4, "OptAdd4", 90, 0, 0, 0, 0, 0 }; static OptFunc DOptAdd5 = { OptAdd5, "OptAdd5", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptAdd6 = { OptAdd6, "OptAdd6", 40, 0, 0, 0, 0, 0 }; static OptFunc DOptBNegA1 = { OptBNegA1, "OptBNegA1", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptBNegA2 = { OptBNegA2, "OptBNegA2", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptBNegAX1 = { OptBNegAX1, "OptBNegAX1", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptBNegAX2 = { OptBNegAX2, "OptBNegAX2", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptBNegAX3 = { OptBNegAX3, "OptBNegAX3", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptBNegAX4 = { OptBNegAX4, "OptBNegAX4", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptBoolTrans = { OptBoolTrans, "OptBoolTrans", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptBranchDist = { OptBranchDist, "OptBranchDist", 0, 0, 0, 0, 0, 0 }; static OptFunc DOptCmp1 = { OptCmp1, "OptCmp1", 42, 0, 0, 0, 0, 0 }; static OptFunc DOptCmp2 = { OptCmp2, "OptCmp2", 85, 0, 0, 0, 0, 0 }; static OptFunc DOptCmp3 = { OptCmp3, "OptCmp3", 75, 0, 0, 0, 0, 0 }; static OptFunc DOptCmp4 = { OptCmp4, "OptCmp4", 75, 0, 0, 0, 0, 0 }; static OptFunc DOptCmp5 = { OptCmp5, "OptCmp5", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptCmp6 = { OptCmp6, "OptCmp6", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptCmp7 = { OptCmp7, "OptCmp7", 85, 0, 0, 0, 0, 0 }; static OptFunc DOptCmp8 = { OptCmp8, "OptCmp8", 50, 0, 0, 0, 0, 0 }; static OptFunc DOptCmp9 = { OptCmp9, "OptCmp9", 85, 0, 0, 0, 0, 0 }; static OptFunc DOptComplAX1 = { OptComplAX1, "OptComplAX1", 65, 0, 0, 0, 0, 0 }; static OptFunc DOptCondBranches1= { OptCondBranches1,"OptCondBranches1", 80, 0, 0, 0, 0, 0 }; static OptFunc DOptCondBranches2= { OptCondBranches2,"OptCondBranches2", 0, 0, 0, 0, 0, 0 }; static OptFunc DOptDeadCode = { OptDeadCode, "OptDeadCode", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptDeadJumps = { OptDeadJumps, "OptDeadJumps", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptDecouple = { OptDecouple, "OptDecouple", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptDupLoads = { OptDupLoads, "OptDupLoads", 0, 0, 0, 0, 0, 0 }; static OptFunc DOptGotoSPAdj = { OptGotoSPAdj, "OptGotoSPAdj", 0, 0, 0, 0, 0, 0 }; static OptFunc DOptIndLoads1 = { OptIndLoads1, "OptIndLoads1", 0, 0, 0, 0, 0, 0 }; static OptFunc DOptIndLoads2 = { OptIndLoads2, "OptIndLoads2", 0, 0, 0, 0, 0, 0 }; static OptFunc DOptJumpCascades = { OptJumpCascades, "OptJumpCascades", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptJumpTarget1 = { OptJumpTarget1, "OptJumpTarget1", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptJumpTarget2 = { OptJumpTarget2, "OptJumpTarget2", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptJumpTarget3 = { OptJumpTarget3, "OptJumpTarget3", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptLoad1 = { OptLoad1, "OptLoad1", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptLoad2 = { OptLoad2, "OptLoad2", 200, 0, 0, 0, 0, 0 }; static OptFunc DOptLoad3 = { OptLoad3, "OptLoad3", 0, 0, 0, 0, 0, 0 }; static OptFunc DOptNegAX1 = { OptNegAX1, "OptNegAX1", 165, 0, 0, 0, 0, 0 }; static OptFunc DOptNegAX2 = { OptNegAX2, "OptNegAX2", 200, 0, 0, 0, 0, 0 }; static OptFunc DOptRTS = { OptRTS, "OptRTS", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptRTSJumps1 = { OptRTSJumps1, "OptRTSJumps1", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptRTSJumps2 = { OptRTSJumps2, "OptRTSJumps2", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptPrecalc = { OptPrecalc, "OptPrecalc", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad1 = { OptPtrLoad1, "OptPtrLoad1", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad2 = { OptPtrLoad2, "OptPtrLoad2", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad3 = { OptPtrLoad3, "OptPtrLoad3", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad4 = { OptPtrLoad4, "OptPtrLoad4", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad5 = { OptPtrLoad5, "OptPtrLoad5", 50, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad6 = { OptPtrLoad6, "OptPtrLoad6", 60, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad7 = { OptPtrLoad7, "OptPtrLoad7", 140, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad11 = { OptPtrLoad11, "OptPtrLoad11", 92, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad12 = { OptPtrLoad12, "OptPtrLoad12", 50, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad13 = { OptPtrLoad13, "OptPtrLoad13", 65, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad14 = { OptPtrLoad14, "OptPtrLoad14", 108, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad15 = { OptPtrLoad15, "OptPtrLoad15", 86, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad16 = { OptPtrLoad16, "OptPtrLoad16", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad17 = { OptPtrLoad17, "OptPtrLoad17", 190, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad18 = { OptPtrLoad18, "OptPtrLoad18", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrLoad19 = { OptPtrLoad19, "OptPtrLoad19", 65, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrStore1 = { OptPtrStore1, "OptPtrStore1", 65, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrStore2 = { OptPtrStore2, "OptPtrStore2", 65, 0, 0, 0, 0, 0 }; static OptFunc DOptPtrStore3 = { OptPtrStore3, "OptPtrStore3", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptPush1 = { OptPush1, "OptPush1", 65, 0, 0, 0, 0, 0 }; static OptFunc DOptPush2 = { OptPush2, "OptPush2", 50, 0, 0, 0, 0, 0 }; static OptFunc DOptPushPop = { OptPushPop, "OptPushPop", 0, 0, 0, 0, 0, 0 }; static OptFunc DOptShift1 = { OptShift1, "OptShift1", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptShift2 = { OptShift2, "OptShift2", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptShift3 = { OptShift3, "OptShift3", 17, 0, 0, 0, 0, 0 }; static OptFunc DOptShift4 = { OptShift4, "OptShift4", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptShift5 = { OptShift5, "OptShift5", 110, 0, 0, 0, 0, 0 }; static OptFunc DOptShift6 = { OptShift6, "OptShift6", 200, 0, 0, 0, 0, 0 }; static OptFunc DOptSize1 = { OptSize1, "OptSize1", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptSize2 = { OptSize2, "OptSize2", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptStackOps = { OptStackOps, "OptStackOps", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptStackPtrOps = { OptStackPtrOps, "OptStackPtrOps", 50, 0, 0, 0, 0, 0 }; static OptFunc DOptStore1 = { OptStore1, "OptStore1", 70, 0, 0, 0, 0, 0 }; static OptFunc DOptStore2 = { OptStore2, "OptStore2", 115, 0, 0, 0, 0, 0 }; static OptFunc DOptStore3 = { OptStore3, "OptStore3", 120, 0, 0, 0, 0, 0 }; static OptFunc DOptStore4 = { OptStore4, "OptStore4", 50, 0, 0, 0, 0, 0 }; static OptFunc DOptStore5 = { OptStore5, "OptStore5", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptStoreLoad = { OptStoreLoad, "OptStoreLoad", 0, 0, 0, 0, 0, 0 }; static OptFunc DOptSub1 = { OptSub1, "OptSub1", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptSub2 = { OptSub2, "OptSub2", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptSub3 = { OptSub3, "OptSub3", 100, 0, 0, 0, 0, 0 }; static OptFunc DOptTest1 = { OptTest1, "OptTest1", 65, 0, 0, 0, 0, 0 }; static OptFunc DOptTest2 = { OptTest2, "OptTest2", 50, 0, 0, 0, 0, 0 }; static OptFunc DOptTransfers1 = { OptTransfers1, "OptTransfers1", 0, 0, 0, 0, 0, 0 }; static OptFunc DOptTransfers2 = { OptTransfers2, "OptTransfers2", 60, 0, 0, 0, 0, 0 }; static OptFunc DOptTransfers3 = { OptTransfers3, "OptTransfers3", 65, 0, 0, 0, 0, 0 }; static OptFunc DOptTransfers4 = { OptTransfers4, "OptTransfers4", 65, 0, 0, 0, 0, 0 }; static OptFunc DOptUnusedLoads = { OptUnusedLoads, "OptUnusedLoads", 0, 0, 0, 0, 0, 0 }; static OptFunc DOptUnusedStores = { OptUnusedStores, "OptUnusedStores", 0, 0, 0, 0, 0, 0 }; /* Table containing all the steps in alphabetical order */ static OptFunc* OptFuncs[] = { &DOpt65C02BitOps, &DOpt65C02Ind, &DOpt65C02Stores, &DOptAdd1, &DOptAdd2, &DOptAdd3, &DOptAdd4, &DOptAdd5, &DOptAdd6, &DOptBNegA1, &DOptBNegA2, &DOptBNegAX1, &DOptBNegAX2, &DOptBNegAX3, &DOptBNegAX4, &DOptBoolTrans, &DOptBranchDist, &DOptCmp1, &DOptCmp2, &DOptCmp3, &DOptCmp4, &DOptCmp5, &DOptCmp6, &DOptCmp7, &DOptCmp8, &DOptCmp9, &DOptComplAX1, &DOptCondBranches1, &DOptCondBranches2, &DOptDeadCode, &DOptDeadJumps, &DOptDecouple, &DOptDupLoads, &DOptGotoSPAdj, &DOptIndLoads1, &DOptIndLoads2, &DOptJumpCascades, &DOptJumpTarget1, &DOptJumpTarget2, &DOptJumpTarget3, &DOptLoad1, &DOptLoad2, &DOptLoad3, &DOptNegAX1, &DOptNegAX2, &DOptPrecalc, &DOptPtrLoad1, &DOptPtrLoad11, &DOptPtrLoad12, &DOptPtrLoad13, &DOptPtrLoad14, &DOptPtrLoad15, &DOptPtrLoad16, &DOptPtrLoad17, &DOptPtrLoad18, &DOptPtrLoad19, &DOptPtrLoad2, &DOptPtrLoad3, &DOptPtrLoad4, &DOptPtrLoad5, &DOptPtrLoad6, &DOptPtrLoad7, &DOptPtrStore1, &DOptPtrStore2, &DOptPtrStore3, &DOptPush1, &DOptPush2, &DOptPushPop, &DOptRTS, &DOptRTSJumps1, &DOptRTSJumps2, &DOptShift1, &DOptShift2, &DOptShift3, &DOptShift4, &DOptShift5, &DOptShift6, &DOptSize1, &DOptSize2, &DOptStackOps, &DOptStackPtrOps, &DOptStore1, &DOptStore2, &DOptStore3, &DOptStore4, &DOptStore5, &DOptStoreLoad, &DOptSub1, &DOptSub2, &DOptSub3, &DOptTest1, &DOptTest2, &DOptTransfers1, &DOptTransfers2, &DOptTransfers3, &DOptTransfers4, &DOptUnusedLoads, &DOptUnusedStores, }; #define OPTFUNC_COUNT (sizeof(OptFuncs) / sizeof(OptFuncs[0])) static int CmpOptStep (const void* Key, const void* Func) /* Compare function for bsearch */ { return strcmp (Key, (*(const OptFunc**)Func)->Name); } static OptFunc* FindOptFunc (const char* Name) /* Find an optimizer step by name in the table and return a pointer. Return ** NULL if no such step is found. */ { /* Search for the function in the list */ OptFunc** O = bsearch (Name, OptFuncs, OPTFUNC_COUNT, sizeof (OptFuncs[0]), CmpOptStep); return O? *O : 0; } static OptFunc* GetOptFunc (const char* Name) /* Find an optimizer step by name in the table and return a pointer. Print an ** error and call AbEnd if not found. */ { /* Search for the function in the list */ OptFunc* F = FindOptFunc (Name); if (F == 0) { /* Not found */ AbEnd ("Optimization step '%s' not found", Name); } return F; } void DisableOpt (const char* Name) /* Disable the optimization with the given name */ { if (strcmp (Name, "any") == 0) { unsigned I; for (I = 0; I < OPTFUNC_COUNT; ++I) { OptFuncs[I]->Disabled = 1; } } else { GetOptFunc(Name)->Disabled = 1; } } void EnableOpt (const char* Name) /* Enable the optimization with the given name */ { if (strcmp (Name, "any") == 0) { unsigned I; for (I = 0; I < OPTFUNC_COUNT; ++I) { OptFuncs[I]->Disabled = 0; } } else { GetOptFunc(Name)->Disabled = 0; } } void ListOptSteps (FILE* F) /* List all optimization steps */ { unsigned I; fprintf (F, "any\n"); for (I = 0; I < OPTFUNC_COUNT; ++I) { fprintf (F, "%s\n", OptFuncs[I]->Name); } } static void ReadOptStats (const char* Name) /* Read the optimizer statistics file */ { char Buf [256]; unsigned Lines; /* Try to open the file */ FILE* F = fopen (Name, "r"); if (F == 0) { /* Ignore the error */ return; } /* Read and parse the lines */ Lines = 0; while (fgets (Buf, sizeof (Buf), F) != 0) { char* B; unsigned Len; OptFunc* Func; /* Fields */ char Name[32]; unsigned long TotalRuns; unsigned long TotalChanges; /* Count lines */ ++Lines; /* Remove trailing white space including the line terminator */ B = Buf; Len = strlen (B); while (Len > 0 && IsSpace (B[Len-1])) { --Len; } B[Len] = '\0'; /* Remove leading whitespace */ while (IsSpace (*B)) { ++B; } /* Check for empty and comment lines */ if (*B == '\0' || *B == ';' || *B == '#') { continue; } /* Parse the line */ if (sscanf (B, "%31s %lu %*u %lu %*u", Name, &TotalRuns, &TotalChanges) != 3) { /* Syntax error */ continue; } /* Search for the optimizer step. */ Func = FindOptFunc (Name); if (Func == 0) { /* Not found */ continue; } /* Found the step, set the fields */ Func->TotalRuns = TotalRuns; Func->TotalChanges = TotalChanges; } /* Close the file, ignore errors here. */ fclose (F); } static void WriteOptStats (const char* Name) /* Write the optimizer statistics file */ { unsigned I; /* Try to open the file */ FILE* F = fopen (Name, "w"); if (F == 0) { /* Ignore the error */ return; } /* Write a header */ fprintf (F, "; Optimizer Total Last Total Last\n" "; Step Runs Runs Chg Chg\n"); /* Write the data */ for (I = 0; I < OPTFUNC_COUNT; ++I) { const OptFunc* O = OptFuncs[I]; fprintf (F, "%-20s %10lu %10lu %10lu %10lu\n", O->Name, O->TotalRuns, O->LastRuns, O->TotalChanges, O->LastChanges); } /* Close the file, ignore errors here. */ fclose (F); } static void OpenDebugFile (const CodeSeg* S) /* Open the debug file for the given segment if the flag is on */ { if (DebugOptOutput) { StrBuf Name = AUTO_STRBUF_INITIALIZER; if (S->Func) { SB_CopyStr (&Name, S->Func->Name); } else { SB_CopyStr (&Name, "global"); } SB_AppendStr (&Name, ".opt"); SB_Terminate (&Name); OpenDebugOutputFile (SB_GetConstBuf (&Name)); SB_Done (&Name); } } static void WriteDebugOutput (CodeSeg* S, const char* Step) /* Write a separator line into the debug file if the flag is on */ { if (DebugOptOutput) { /* Output a separator */ WriteOutput ("=========================================================================\n"); /* Output a header line */ if (Step == 0) { /* Initial output */ WriteOutput ("Initial code for function '%s':\n", S->Func? S->Func->Name : "<global>"); } else { WriteOutput ("Code after applying '%s':\n", Step); } /* Output the code segment */ CS_Output (S); } } static unsigned RunOptFunc (CodeSeg* S, OptFunc* F, unsigned Max) /* Run one optimizer function Max times or until there are no more changes */ { unsigned Changes, C; /* Don't run the function if it is disabled or if it is prohibited by the ** code size factor */ if (F->Disabled || F->CodeSizeFactor > S->CodeSizeFactor) { return 0; } /* Run this until there are no more changes */ Changes = 0; do { /* Run the function */ C = F->Func (S); Changes += C; /* Do statistics */ ++F->TotalRuns; ++F->LastRuns; F->TotalChanges += C; F->LastChanges += C; /* If we had changes, output stuff and regenerate register info */ if (C) { if (Debug) { printf ("Applied %s: %u changes\n", F->Name, C); } WriteDebugOutput (S, F->Name); CS_GenRegInfo (S); } } while (--Max && C > 0); /* Return the number of changes */ return Changes; } static unsigned RunOptGroup1 (CodeSeg* S) /* Run the first group of optimization steps. These steps translate known ** patterns emitted by the code generator into more optimal patterns. Order ** of the steps is important, because some of the steps done earlier cover ** the same patterns as later steps as subpatterns. */ { unsigned Changes = 0; Changes += RunOptFunc (S, &DOptGotoSPAdj, 1); Changes += RunOptFunc (S, &DOptStackPtrOps, 5); Changes += RunOptFunc (S, &DOptPtrStore1, 1); Changes += RunOptFunc (S, &DOptPtrStore2, 1); Changes += RunOptFunc (S, &DOptPtrStore3, 1); Changes += RunOptFunc (S, &DOptAdd3, 1); /* Before OptPtrLoad5! */ Changes += RunOptFunc (S, &DOptPtrLoad1, 1); Changes += RunOptFunc (S, &DOptPtrLoad2, 1); Changes += RunOptFunc (S, &DOptPtrLoad3, 1); Changes += RunOptFunc (S, &DOptPtrLoad4, 1); Changes += RunOptFunc (S, &DOptPtrLoad5, 1); Changes += RunOptFunc (S, &DOptPtrLoad6, 1); Changes += RunOptFunc (S, &DOptPtrLoad18, 1); /* Before OptPtrLoad7 */ Changes += RunOptFunc (S, &DOptPtrLoad19, 1); /* Before OptPtrLoad7 */ Changes += RunOptFunc (S, &DOptPtrLoad7, 1); Changes += RunOptFunc (S, &DOptPtrLoad11, 1); Changes += RunOptFunc (S, &DOptPtrLoad12, 1); Changes += RunOptFunc (S, &DOptPtrLoad13, 1); Changes += RunOptFunc (S, &DOptPtrLoad14, 1); Changes += RunOptFunc (S, &DOptPtrLoad15, 1); Changes += RunOptFunc (S, &DOptPtrLoad16, 1); Changes += RunOptFunc (S, &DOptPtrLoad17, 1); Changes += RunOptFunc (S, &DOptBNegAX1, 1); Changes += RunOptFunc (S, &DOptBNegAX2, 1); Changes += RunOptFunc (S, &DOptBNegAX3, 1); Changes += RunOptFunc (S, &DOptBNegAX4, 1); Changes += RunOptFunc (S, &DOptAdd1, 1); Changes += RunOptFunc (S, &DOptAdd2, 1); Changes += RunOptFunc (S, &DOptAdd4, 1); Changes += RunOptFunc (S, &DOptAdd5, 1); Changes += RunOptFunc (S, &DOptAdd6, 1); Changes += RunOptFunc (S, &DOptSub1, 1); Changes += RunOptFunc (S, &DOptSub3, 1); Changes += RunOptFunc (S, &DOptStore4, 1); Changes += RunOptFunc (S, &DOptStore5, 1); Changes += RunOptFunc (S, &DOptShift1, 1); Changes += RunOptFunc (S, &DOptShift2, 1); Changes += RunOptFunc (S, &DOptShift5, 1); Changes += RunOptFunc (S, &DOptShift6, 1); Changes += RunOptFunc (S, &DOptStore1, 1); Changes += RunOptFunc (S, &DOptStore2, 5); Changes += RunOptFunc (S, &DOptStore3, 5); /* Return the number of changes */ return Changes; } static unsigned RunOptGroup2 (CodeSeg* S) /* Run one group of optimization steps. This step involves just decoupling ** instructions by replacing them by instructions that do not depend on ** previous instructions. This makes it easier to find instructions that ** aren't used. */ { unsigned Changes = 0; Changes += RunOptFunc (S, &DOptDecouple, 1); /* Return the number of changes */ return Changes; } static unsigned RunOptGroup3 (CodeSeg* S) /* Run one group of optimization steps. These steps depend on each other, ** that means that one step may allow another step to do additional work, ** so we will repeat the steps as long as we see any changes. */ { unsigned Changes, C; Changes = 0; do { C = 0; C += RunOptFunc (S, &DOptBNegA1, 1); C += RunOptFunc (S, &DOptBNegA2, 1); C += RunOptFunc (S, &DOptNegAX1, 1); C += RunOptFunc (S, &DOptNegAX2, 1); C += RunOptFunc (S, &DOptStackOps, 3); C += RunOptFunc (S, &DOptShift1, 1); C += RunOptFunc (S, &DOptShift4, 1); C += RunOptFunc (S, &DOptComplAX1, 1); C += RunOptFunc (S, &DOptSub1, 1); C += RunOptFunc (S, &DOptSub2, 1); C += RunOptFunc (S, &DOptSub3, 1); C += RunOptFunc (S, &DOptAdd5, 1); C += RunOptFunc (S, &DOptAdd6, 1); C += RunOptFunc (S, &DOptJumpCascades, 1); C += RunOptFunc (S, &DOptDeadJumps, 1); C += RunOptFunc (S, &DOptRTS, 1); C += RunOptFunc (S, &DOptDeadCode, 1); C += RunOptFunc (S, &DOptBoolTrans, 1); C += RunOptFunc (S, &DOptJumpTarget1, 1); C += RunOptFunc (S, &DOptJumpTarget2, 1); C += RunOptFunc (S, &DOptCondBranches1, 1); C += RunOptFunc (S, &DOptCondBranches2, 1); C += RunOptFunc (S, &DOptRTSJumps1, 1); C += RunOptFunc (S, &DOptCmp1, 1); C += RunOptFunc (S, &DOptCmp2, 1); C += RunOptFunc (S, &DOptCmp8, 1); /* Must run before OptCmp3 */ C += RunOptFunc (S, &DOptCmp3, 1); C += RunOptFunc (S, &DOptCmp4, 1); C += RunOptFunc (S, &DOptCmp5, 1); C += RunOptFunc (S, &DOptCmp6, 1); C += RunOptFunc (S, &DOptCmp7, 1); C += RunOptFunc (S, &DOptCmp9, 1); C += RunOptFunc (S, &DOptTest1, 1); C += RunOptFunc (S, &DOptLoad1, 1); C += RunOptFunc (S, &DOptJumpTarget3, 1); /* After OptCondBranches2 */ C += RunOptFunc (S, &DOptUnusedLoads, 1); C += RunOptFunc (S, &DOptUnusedStores, 1); C += RunOptFunc (S, &DOptDupLoads, 1); C += RunOptFunc (S, &DOptStoreLoad, 1); C += RunOptFunc (S, &DOptTransfers1, 1); C += RunOptFunc (S, &DOptTransfers3, 1); C += RunOptFunc (S, &DOptTransfers4, 1); C += RunOptFunc (S, &DOptStore1, 1); C += RunOptFunc (S, &DOptStore5, 1); C += RunOptFunc (S, &DOptPushPop, 1); C += RunOptFunc (S, &DOptPrecalc, 1); Changes += C; } while (C); /* Return the number of changes */ return Changes; } static unsigned RunOptGroup4 (CodeSeg* S) /* Run another round of pattern replacements. These are done late, since there ** may be better replacements before. */ { unsigned Changes = 0; /* Repeat some of the steps here */ Changes += RunOptFunc (S, &DOptShift3, 1); Changes += RunOptFunc (S, &DOptPush1, 1); Changes += RunOptFunc (S, &DOptPush2, 1); Changes += RunOptFunc (S, &DOptUnusedLoads, 1); Changes += RunOptFunc (S, &DOptTest2, 1); Changes += RunOptFunc (S, &DOptTransfers2, 1); Changes += RunOptFunc (S, &DOptLoad2, 1); Changes += RunOptFunc (S, &DOptLoad3, 1); Changes += RunOptFunc (S, &DOptDupLoads, 1); /* Return the number of changes */ return Changes; } static unsigned RunOptGroup5 (CodeSeg* S) /* 65C02 specific optimizations. */ { unsigned Changes = 0; if (CPUIsets[CPU] & CPU_ISET_65SC02) { Changes += RunOptFunc (S, &DOpt65C02BitOps, 1); Changes += RunOptFunc (S, &DOpt65C02Ind, 1); Changes += RunOptFunc (S, &DOpt65C02Stores, 1); if (Changes) { /* The 65C02 replacement codes do often make the use of a register ** value unnecessary, so if we have changes, run another load ** removal pass. */ Changes += RunOptFunc (S, &DOptUnusedLoads, 1); } } /* Return the number of changes */ return Changes; } static unsigned RunOptGroup6 (CodeSeg* S) /* This one is quite special. It tries to replace "lda (sp),y" by "lda (sp,x)". ** The latter is ony cycle slower, but if we're able to remove the necessary ** load of the Y register, because X is zero anyway, we gain 1 cycle and ** shorten the code by one (transfer) or two bytes (load). So what we do is ** to replace the insns, remove unused loads, and then change back all insns ** where Y is still zero (meaning that the load has not been removed). */ { unsigned Changes = 0; /* This group will only run for a standard 6502, because the 65C02 has a ** better addressing mode that covers this case. */ if ((CPUIsets[CPU] & CPU_ISET_65SC02) == 0) { Changes += RunOptFunc (S, &DOptIndLoads1, 1); Changes += RunOptFunc (S, &DOptUnusedLoads, 1); Changes += RunOptFunc (S, &DOptIndLoads2, 1); } /* Return the number of changes */ return Changes; } static unsigned RunOptGroup7 (CodeSeg* S) /* The last group of optimization steps. Adjust branches, do size optimizations. */ { unsigned Changes = 0; unsigned C; /* Optimize for size, that is replace operations by shorter ones, even ** if this does hinder further optimizations (no problem since we're ** done soon). */ C = RunOptFunc (S, &DOptSize1, 1); if (C) { Changes += C; /* Run some optimization passes again, since the size optimizations ** may have opened new oportunities. */ Changes += RunOptFunc (S, &DOptUnusedLoads, 1); Changes += RunOptFunc (S, &DOptUnusedStores, 1); Changes += RunOptFunc (S, &DOptJumpTarget1, 5); Changes += RunOptFunc (S, &DOptStore5, 1); } C = RunOptFunc (S, &DOptSize2, 1); if (C) { Changes += C; /* Run some optimization passes again, since the size optimizations ** may have opened new oportunities. */ Changes += RunOptFunc (S, &DOptUnusedLoads, 1); Changes += RunOptFunc (S, &DOptJumpTarget1, 5); Changes += RunOptFunc (S, &DOptStore5, 1); Changes += RunOptFunc (S, &DOptTransfers1, 1); Changes += RunOptFunc (S, &DOptTransfers3, 1); } /* Adjust branch distances */ Changes += RunOptFunc (S, &DOptBranchDist, 3); /* Replace conditional branches to RTS. If we had changes, we must run dead ** code elimination again, since the change may have introduced dead code. */ C = RunOptFunc (S, &DOptRTSJumps2, 1); Changes += C; if (C) { Changes += RunOptFunc (S, &DOptDeadCode, 1); } /* Return the number of changes */ return Changes; } void RunOpt (CodeSeg* S) /* Run the optimizer */ { const char* StatFileName; /* If we shouldn't run the optimizer, bail out */ if (!S->Optimize) { return; } /* Check if we are requested to write optimizer statistics */ StatFileName = getenv ("CC65_OPTSTATS"); if (StatFileName) { ReadOptStats (StatFileName); } /* Print the name of the function we are working on */ if (S->Func) { Print (stdout, 1, "Running optimizer for function '%s'\n", S->Func->Name); } else { Print (stdout, 1, "Running optimizer for global code segment\n"); } /* If requested, open an output file */ OpenDebugFile (S); WriteDebugOutput (S, 0); /* Generate register info for all instructions */ CS_GenRegInfo (S); /* Run groups of optimizations */ RunOptGroup1 (S); RunOptGroup2 (S); RunOptGroup3 (S); RunOptGroup4 (S); RunOptGroup5 (S); RunOptGroup6 (S); RunOptGroup7 (S); /* Free register info */ CS_FreeRegInfo (S); /* Close output file if necessary */ if (DebugOptOutput) { CloseOutputFile (); } /* Write statistics */ if (StatFileName) { WriteOptStats (StatFileName); } } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/codeopt.h������������������������������������������������������������������������0000664�0000000�0000000�00000006202�13473601511�0015342�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* codeopt.h */ /* */ /* Optimizer subroutines */ /* */ /* */ /* */ /* (C) 2001 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef CODEOPT_H #define CODEOPT_H /* cc65 */ #include "codeseg.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void DisableOpt (const char* Name); /* Disable the optimization with the given name */ void EnableOpt (const char* Name); /* Enable the optimization with the given name */ void ListOptSteps (FILE* F); /* List all optimization steps */ void RunOpt (CodeSeg* S); /* Run the optimizer */ /* End of codeopt.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/codeseg.c������������������������������������������������������������������������0000664�0000000�0000000�00000147437�13473601511�0015331�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* codeseg.c */ /* */ /* Code segment structure */ /* */ /* */ /* */ /* (C) 2001-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> #include <ctype.h> /* common */ #include "chartype.h" #include "check.h" #include "debugflag.h" #include "global.h" #include "hashfunc.h" #include "strbuf.h" #include "strutil.h" #include "xmalloc.h" /* cc65 */ #include "asmlabel.h" #include "codeent.h" #include "codeinfo.h" #include "codeseg.h" #include "datatype.h" #include "error.h" #include "global.h" #include "ident.h" #include "output.h" #include "symentry.h" /*****************************************************************************/ /* Helper functions */ /*****************************************************************************/ static void CS_PrintFunctionHeader (const CodeSeg* S) /* Print a comment with the function signature to the output file */ { /* Get the associated function */ const SymEntry* Func = S->Func; /* If this is a global code segment, do nothing */ if (Func) { WriteOutput ("; ---------------------------------------------------------------\n" "; "); PrintFuncSig (OutputFile, Func->Name, Func->Type); WriteOutput ("\n" "; ---------------------------------------------------------------\n" "\n"); } } static void CS_MoveLabelsToEntry (CodeSeg* S, CodeEntry* E) /* Move all labels from the label pool to the given entry and remove them ** from the pool. */ { /* Transfer the labels if we have any */ unsigned I; unsigned LabelCount = CollCount (&S->Labels); for (I = 0; I < LabelCount; ++I) { /* Get the label */ CodeLabel* L = CollAt (&S->Labels, I); /* Attach it to the entry */ CE_AttachLabel (E, L); } /* Delete the transfered labels */ CollDeleteAll (&S->Labels); } static void CS_MoveLabelsToPool (CodeSeg* S, CodeEntry* E) /* Move the labels of the code entry E to the label pool of the code segment */ { unsigned LabelCount = CE_GetLabelCount (E); while (LabelCount--) { CodeLabel* L = CE_GetLabel (E, LabelCount); L->Owner = 0; CollAppend (&S->Labels, L); } CollDeleteAll (&E->Labels); } static CodeLabel* CS_FindLabel (CodeSeg* S, const char* Name, unsigned Hash) /* Find the label with the given name. Return the label or NULL if not found */ { /* Get the first hash chain entry */ CodeLabel* L = S->LabelHash[Hash]; /* Search the list */ while (L) { if (strcmp (Name, L->Name) == 0) { /* Found */ break; } L = L->Next; } return L; } static CodeLabel* CS_NewCodeLabel (CodeSeg* S, const char* Name, unsigned Hash) /* Create a new label and insert it into the label hash table */ { /* Create a new label */ CodeLabel* L = NewCodeLabel (Name, Hash); /* Enter the label into the hash table */ L->Next = S->LabelHash[L->Hash]; S->LabelHash[L->Hash] = L; /* Return the new label */ return L; } static void CS_RemoveLabelFromHash (CodeSeg* S, CodeLabel* L) /* Remove the given code label from the hash list */ { /* Get the first entry in the hash chain */ CodeLabel* List = S->LabelHash[L->Hash]; CHECK (List != 0); /* First, remove the label from the hash chain */ if (List == L) { /* First entry in hash chain */ S->LabelHash[L->Hash] = L->Next; } else { /* Must search through the chain */ while (List->Next != L) { /* If we've reached the end of the chain, something is *really* wrong */ CHECK (List->Next != 0); /* Next entry */ List = List->Next; } /* The next entry is the one, we have been searching for */ List->Next = L->Next; } } /*****************************************************************************/ /* Functions for parsing instructions */ /*****************************************************************************/ static const char* SkipSpace (const char* S) /* Skip white space and return an updated pointer */ { while (IsSpace (*S)) { ++S; } return S; } static const char* ReadToken (const char* L, const char* Term, char* Buf, unsigned BufSize) /* Read the next token into Buf, return the updated line pointer. The ** token is terminated by one of the characters given in term. */ { /* Read/copy the token */ unsigned I = 0; unsigned ParenCount = 0; while (*L && (ParenCount > 0 || strchr (Term, *L) == 0)) { if (I < BufSize-1) { Buf[I] = *L; } else if (I == BufSize-1) { /* Cannot store this character, this is an input error (maybe ** identifier too long or similar). */ Error ("ASM code error: syntax error"); } ++I; if (*L == ')') { --ParenCount; } else if (*L == '(') { ++ParenCount; } ++L; } /* Terminate the buffer contents */ Buf[I] = '\0'; /* Return the updated line pointer */ return L; } static CodeEntry* ParseInsn (CodeSeg* S, LineInfo* LI, const char* L) /* Parse an instruction nnd generate a code entry from it. If the line contains ** errors, output an error message and return NULL. ** For simplicity, we don't accept the broad range of input a "real" assembler ** does. The instruction and the argument are expected to be separated by ** white space, for example. */ { char Mnemo[IDENTSIZE+10]; const OPCDesc* OPC; am_t AM = 0; /* Initialize to keep gcc silent */ char Arg[IDENTSIZE+10]; char Reg; CodeEntry* E; CodeLabel* Label; /* Read the first token and skip white space after it */ L = SkipSpace (ReadToken (L, " \t:", Mnemo, sizeof (Mnemo))); /* Check if we have a label */ if (*L == ':') { /* Skip the colon and following white space */ L = SkipSpace (L+1); /* Add the label */ CS_AddLabel (S, Mnemo); /* If we have reached end of line, bail out, otherwise a mnemonic ** may follow. */ if (*L == '\0') { return 0; } L = SkipSpace (ReadToken (L, " \t", Mnemo, sizeof (Mnemo))); } /* Try to find the opcode description for the mnemonic */ OPC = FindOP65 (Mnemo); /* If we didn't find the opcode, print an error and bail out */ if (OPC == 0) { Error ("ASM code error: %s is not a valid mnemonic", Mnemo); return 0; } /* Get the addressing mode */ Arg[0] = '\0'; switch (*L) { case '\0': /* Implicit or accu */ if (OPC->Info & OF_NOIMP) { AM = AM65_ACC; } else { AM = AM65_IMP; } break; case '#': /* Immidiate */ StrCopy (Arg, sizeof (Arg), L+1); AM = AM65_IMM; break; case '(': /* Indirect */ L = ReadToken (L+1, ",)", Arg, sizeof (Arg)); /* Check for errors */ if (*L == '\0') { Error ("ASM code error: syntax error"); return 0; } /* Check the different indirect modes */ if (*L == ',') { /* Expect zp x indirect */ L = SkipSpace (L+1); if (toupper (*L) != 'X') { Error ("ASM code error: 'X' expected"); return 0; } L = SkipSpace (L+1); if (*L != ')') { Error ("ASM code error: ')' expected"); return 0; } L = SkipSpace (L+1); if (*L != '\0') { Error ("ASM code error: syntax error"); return 0; } AM = AM65_ZPX_IND; } else if (*L == ')') { /* zp indirect or zp indirect, y */ L = SkipSpace (L+1); if (*L == ',') { L = SkipSpace (L+1); if (toupper (*L) != 'Y') { Error ("ASM code error: 'Y' expected"); return 0; } L = SkipSpace (L+1); if (*L != '\0') { Error ("ASM code error: syntax error"); return 0; } AM = AM65_ZP_INDY; } else if (*L == '\0') { AM = AM65_ZP_IND; } else { Error ("ASM code error: syntax error"); return 0; } } break; case 'a': case 'A': /* Accumulator? */ if (L[1] == '\0') { AM = AM65_ACC; break; } /* FALLTHROUGH */ default: /* Absolute, maybe indexed */ L = ReadToken (L, ",", Arg, sizeof (Arg)); if (*L == '\0') { /* Absolute, zeropage or branch */ if ((OPC->Info & OF_BRA) != 0) { /* Branch */ AM = AM65_BRA; } else if (GetZPInfo(Arg) != 0) { AM = AM65_ZP; } else { /* Check for subroutine call to local label */ if ((OPC->Info & OF_CALL) && IsLocalLabelName (Arg)) { Error ("ASM code error: " "Cannot use local label '%s' in subroutine call", Arg); } AM = AM65_ABS; } } else if (*L == ',') { /* Indexed */ L = SkipSpace (L+1); if (*L == '\0') { Error ("ASM code error: syntax error"); return 0; } else { Reg = toupper (*L); L = SkipSpace (L+1); if (Reg == 'X') { if (GetZPInfo(Arg) != 0) { AM = AM65_ZPX; } else { AM = AM65_ABSX; } } else if (Reg == 'Y') { AM = AM65_ABSY; } else { Error ("ASM code error: syntax error"); return 0; } if (*L != '\0') { Error ("ASM code error: syntax error"); return 0; } } } break; } /* If the instruction is a branch, check for the label and generate it ** if it does not exist. This may lead to unused labels (if the label ** is actually an external one) which are removed by the CS_MergeLabels ** function later. */ Label = 0; if (AM == AM65_BRA) { /* Generate the hash over the label, then search for the label */ unsigned Hash = HashStr (Arg) % CS_LABEL_HASH_SIZE; Label = CS_FindLabel (S, Arg, Hash); /* If we don't have the label, it's a forward ref - create it unless ** it's an external function. */ if (Label == 0 && (OPC->OPC != OP65_JMP || IsLocalLabelName (Arg)) ) { /* Generate a new label */ Label = CS_NewCodeLabel (S, Arg, Hash); } } /* We do now have the addressing mode in AM. Allocate a new CodeEntry ** structure and initialize it. */ E = NewCodeEntry (OPC->OPC, AM, Arg, Label, LI); /* Return the new code entry */ return E; } /*****************************************************************************/ /* Code */ /*****************************************************************************/ CodeSeg* NewCodeSeg (const char* SegName, SymEntry* Func) /* Create a new code segment, initialize and return it */ { unsigned I; const Type* RetType; /* Allocate memory */ CodeSeg* S = xmalloc (sizeof (CodeSeg)); /* Initialize the fields */ S->SegName = xstrdup (SegName); S->Func = Func; InitCollection (&S->Entries); InitCollection (&S->Labels); for (I = 0; I < sizeof(S->LabelHash) / sizeof(S->LabelHash[0]); ++I) { S->LabelHash[I] = 0; } /* If we have a function given, get the return type of the function. ** Assume ANY return type besides void will use the A and X registers. */ if (S->Func && !IsTypeVoid ((RetType = GetFuncReturn (Func->Type)))) { if (SizeOf (RetType) == SizeOf (type_long)) { S->ExitRegs = REG_EAX; } else { S->ExitRegs = REG_AX; } } else { S->ExitRegs = REG_NONE; } /* Copy the global optimization settings */ S->Optimize = (unsigned char) IS_Get (&Optimize); S->CodeSizeFactor = (unsigned) IS_Get (&CodeSizeFactor); /* Return the new struct */ return S; } void CS_AddEntry (CodeSeg* S, struct CodeEntry* E) /* Add an entry to the given code segment */ { /* Transfer the labels if we have any */ CS_MoveLabelsToEntry (S, E); /* Add the entry to the list of code entries in this segment */ CollAppend (&S->Entries, E); } void CS_AddVLine (CodeSeg* S, LineInfo* LI, const char* Format, va_list ap) /* Add a line to the given code segment */ { const char* L; CodeEntry* E; char Token[IDENTSIZE+10]; /* Format the line */ StrBuf Buf = STATIC_STRBUF_INITIALIZER; SB_VPrintf (&Buf, Format, ap); /* Skip whitespace */ L = SkipSpace (SB_GetConstBuf (&Buf)); /* Check which type of instruction we have */ E = 0; /* Assume no insn created */ switch (*L) { case '\0': /* Empty line, just ignore it */ break; case ';': /* Comment or hint, ignore it for now */ break; case '.': /* Control instruction */ ReadToken (L, " \t", Token, sizeof (Token)); Error ("ASM code error: Pseudo instruction '%s' not supported", Token); break; default: E = ParseInsn (S, LI, L); break; } /* If we have a code entry, transfer the labels and insert it */ if (E) { CS_AddEntry (S, E); } /* Cleanup the string buffer */ SB_Done (&Buf); } void CS_AddLine (CodeSeg* S, LineInfo* LI, const char* Format, ...) /* Add a line to the given code segment */ { va_list ap; va_start (ap, Format); CS_AddVLine (S, LI, Format, ap); va_end (ap); } void CS_InsertEntry (CodeSeg* S, struct CodeEntry* E, unsigned Index) /* Insert the code entry at the index given. Following code entries will be ** moved to slots with higher indices. */ { /* Insert the entry into the collection */ CollInsert (&S->Entries, E, Index); } void CS_DelEntry (CodeSeg* S, unsigned Index) /* Delete an entry from the code segment. This includes moving any associated ** labels, removing references to labels and even removing the referenced labels ** if the reference count drops to zero. ** Note: Labels are moved forward if possible, that is, they are moved to the ** next insn (not the preceeding one). */ { /* Get the code entry for the given index */ CodeEntry* E = CS_GetEntry (S, Index); /* If the entry has a labels, we have to move this label to the next insn. ** If there is no next insn, move the label into the code segement label ** pool. The operation is further complicated by the fact that the next ** insn may already have a label. In that case change all reference to ** this label and delete the label instead of moving it. */ unsigned Count = CE_GetLabelCount (E); if (Count > 0) { /* The instruction has labels attached. Check if there is a next ** instruction. */ if (Index == CS_GetEntryCount (S)-1) { /* No next instruction, move to the codeseg label pool */ CS_MoveLabelsToPool (S, E); } else { /* There is a next insn, get it */ CodeEntry* N = CS_GetEntry (S, Index+1); /* Move labels to the next entry */ CS_MoveLabels (S, E, N); } } /* If this insn references a label, remove the reference. And, if the ** the reference count for this label drops to zero, remove this label. */ if (E->JumpTo) { /* Remove the reference */ CS_RemoveLabelRef (S, E); } /* Delete the pointer to the insn */ CollDelete (&S->Entries, Index); /* Delete the instruction itself */ FreeCodeEntry (E); } void CS_DelEntries (CodeSeg* S, unsigned Start, unsigned Count) /* Delete a range of code entries. This includes removing references to labels, ** labels attached to the entries and so on. */ { /* Start deleting the entries from the rear, because this involves less ** memory moving. */ while (Count--) { CS_DelEntry (S, Start + Count); } } void CS_MoveEntries (CodeSeg* S, unsigned Start, unsigned Count, unsigned NewPos) /* Move a range of entries from one position to another. Start is the index ** of the first entry to move, Count is the number of entries and NewPos is ** the index of the target entry. The entry with the index Start will later ** have the index NewPos. All entries with indices NewPos and above are ** moved to higher indices. If the code block is moved to the end of the ** current code, and if pending labels exist, these labels will get attached ** to the first instruction of the moved block (the first one after the ** current code end) */ { /* Transparently handle an empty range */ if (Count == 0) { return; } /* If NewPos is at the end of the code segment, move any labels from the ** label pool to the first instruction of the moved range. */ if (NewPos == CS_GetEntryCount (S)) { CS_MoveLabelsToEntry (S, CS_GetEntry (S, Start)); } /* Move the code block to the destination */ CollMoveMultiple (&S->Entries, Start, Count, NewPos); } struct CodeEntry* CS_GetPrevEntry (CodeSeg* S, unsigned Index) /* Get the code entry preceeding the one with the index Index. If there is no ** preceeding code entry, return NULL. */ { if (Index == 0) { /* This is the first entry */ return 0; } else { /* Previous entry available */ return CollAtUnchecked (&S->Entries, Index-1); } } struct CodeEntry* CS_GetNextEntry (CodeSeg* S, unsigned Index) /* Get the code entry following the one with the index Index. If there is no ** following code entry, return NULL. */ { if (Index >= CollCount (&S->Entries)-1) { /* This is the last entry */ return 0; } else { /* Code entries left */ return CollAtUnchecked (&S->Entries, Index+1); } } int CS_GetEntries (CodeSeg* S, struct CodeEntry** List, unsigned Start, unsigned Count) /* Get Count code entries into List starting at index start. Return true if ** we got the lines, return false if not enough lines were available. */ { /* Check if enough entries are available */ if (Start + Count > CollCount (&S->Entries)) { return 0; } /* Copy the entries */ while (Count--) { *List++ = CollAtUnchecked (&S->Entries, Start++); } /* We have the entries */ return 1; } unsigned CS_GetEntryIndex (CodeSeg* S, struct CodeEntry* E) /* Return the index of a code entry */ { int Index = CollIndex (&S->Entries, E); CHECK (Index >= 0); return Index; } int CS_RangeHasLabel (CodeSeg* S, unsigned Start, unsigned Count) /* Return true if any of the code entries in the given range has a label ** attached. If the code segment does not span the given range, check the ** possible span instead. */ { unsigned EntryCount = CS_GetEntryCount(S); /* Adjust count. We expect at least Start to be valid. */ CHECK (Start < EntryCount); if (Start + Count > EntryCount) { Count = EntryCount - Start; } /* Check each entry. Since we have validated the index above, we may ** use the unchecked access function in the loop which is faster. */ while (Count--) { const CodeEntry* E = CollAtUnchecked (&S->Entries, Start++); if (CE_HasLabel (E)) { return 1; } } /* No label in the complete range */ return 0; } CodeLabel* CS_AddLabel (CodeSeg* S, const char* Name) /* Add a code label for the next instruction to follow */ { /* Calculate the hash from the name */ unsigned Hash = HashStr (Name) % CS_LABEL_HASH_SIZE; /* Try to find the code label if it does already exist */ CodeLabel* L = CS_FindLabel (S, Name, Hash); /* Did we find it? */ if (L) { /* We found it - be sure it does not already have an owner */ if (L->Owner) { Error ("ASM label '%s' is already defined", Name); return L; } } else { /* Not found - create a new one */ L = CS_NewCodeLabel (S, Name, Hash); } /* Safety. This call is quite costly, but safety is better */ if (CollIndex (&S->Labels, L) >= 0) { Error ("ASM label '%s' is already defined", Name); return L; } /* We do now have a valid label. Remember it for later */ CollAppend (&S->Labels, L); /* Return the label */ return L; } CodeLabel* CS_GenLabel (CodeSeg* S, struct CodeEntry* E) /* If the code entry E does already have a label, return it. Otherwise ** create a new label, attach it to E and return it. */ { CodeLabel* L; if (CE_HasLabel (E)) { /* Get the label from this entry */ L = CE_GetLabel (E, 0); } else { /* Get a new name */ const char* Name = LocalLabelName (GetLocalLabel ()); /* Generate the hash over the name */ unsigned Hash = HashStr (Name) % CS_LABEL_HASH_SIZE; /* Create a new label */ L = CS_NewCodeLabel (S, Name, Hash); /* Attach this label to the code entry */ CE_AttachLabel (E, L); } /* Return the label */ return L; } void CS_DelLabel (CodeSeg* S, CodeLabel* L) /* Remove references from this label and delete it. */ { unsigned Count, I; /* First, remove the label from the hash chain */ CS_RemoveLabelFromHash (S, L); /* Remove references from insns jumping to this label */ Count = CollCount (&L->JumpFrom); for (I = 0; I < Count; ++I) { /* Get the insn referencing this label */ CodeEntry* E = CollAt (&L->JumpFrom, I); /* Remove the reference */ CE_ClearJumpTo (E); } CollDeleteAll (&L->JumpFrom); /* Remove the reference to the owning instruction if it has one. The ** function may be called for a label without an owner when deleting ** unfinished parts of the code. This is unfortunate since it allows ** errors to slip through. */ if (L->Owner) { CollDeleteItem (&L->Owner->Labels, L); } /* All references removed, delete the label itself */ FreeCodeLabel (L); } void CS_MergeLabels (CodeSeg* S) /* Merge code labels. That means: For each instruction, remove all labels but ** one and adjust references accordingly. */ { unsigned I; unsigned J; /* First, remove all labels from the label symbol table that don't have an ** owner (this means that they are actually external labels but we didn't ** know that previously since they may have also been forward references). */ for (I = 0; I < CS_LABEL_HASH_SIZE; ++I) { /* Get the first label in this hash chain */ CodeLabel** L = &S->LabelHash[I]; while (*L) { if ((*L)->Owner == 0) { /* The label does not have an owner, remove it from the chain */ CodeLabel* X = *L; *L = X->Next; /* Cleanup any entries jumping to this label */ for (J = 0; J < CL_GetRefCount (X); ++J) { /* Get the entry referencing this label */ CodeEntry* E = CL_GetRef (X, J); /* And remove the reference. Do NOT call CE_ClearJumpTo ** here, because this will also clear the label name, ** which is not what we want. */ E->JumpTo = 0; } /* Print some debugging output */ if (Debug) { printf ("Removing unused global label '%s'", X->Name); } /* And free the label */ FreeCodeLabel (X); } else { /* Label is owned, point to next code label pointer */ L = &((*L)->Next); } } } /* Walk over all code entries */ for (I = 0; I < CS_GetEntryCount (S); ++I) { CodeLabel* RefLab; unsigned J; /* Get a pointer to the next entry */ CodeEntry* E = CS_GetEntry (S, I); /* If this entry has zero labels, continue with the next one */ unsigned LabelCount = CE_GetLabelCount (E); if (LabelCount == 0) { continue; } /* We have at least one label. Use the first one as reference label. */ RefLab = CE_GetLabel (E, 0); /* Walk through the remaining labels and change references to these ** labels to a reference to the one and only label. Delete the labels ** that are no longer used. To increase performance, walk backwards ** through the list. */ for (J = LabelCount-1; J >= 1; --J) { /* Get the next label */ CodeLabel* L = CE_GetLabel (E, J); /* Move all references from this label to the reference label */ CL_MoveRefs (L, RefLab); /* Remove the label completely. */ CS_DelLabel (S, L); } /* The reference label is the only remaining label. Check if there ** are any references to this label, and delete it if this is not ** the case. */ if (CollCount (&RefLab->JumpFrom) == 0) { /* Delete the label */ CS_DelLabel (S, RefLab); } } } void CS_MoveLabels (CodeSeg* S, struct CodeEntry* Old, struct CodeEntry* New) /* Move all labels from Old to New. The routine will move the labels itself ** if New does not have any labels, and move references if there is at least ** a label for new. If references are moved, the old label is deleted ** afterwards. */ { /* Get the number of labels to move */ unsigned OldLabelCount = CE_GetLabelCount (Old); /* Does the new entry have itself a label? */ if (CE_HasLabel (New)) { /* The new entry does already have a label - move references */ CodeLabel* NewLabel = CE_GetLabel (New, 0); while (OldLabelCount--) { /* Get the next label */ CodeLabel* OldLabel = CE_GetLabel (Old, OldLabelCount); /* Move references */ CL_MoveRefs (OldLabel, NewLabel); /* Delete the label */ CS_DelLabel (S, OldLabel); } } else { /* The new entry does not have a label, just move them */ while (OldLabelCount--) { /* Move the label to the new entry */ CE_MoveLabel (CE_GetLabel (Old, OldLabelCount), New); } } } void CS_RemoveLabelRef (CodeSeg* S, struct CodeEntry* E) /* Remove the reference between E and the label it jumps to. The reference ** will be removed on both sides and E->JumpTo will be 0 after that. If ** the reference was the only one for the label, the label will get ** deleted. */ { /* Get a pointer to the label and make sure it exists */ CodeLabel* L = E->JumpTo; CHECK (L != 0); /* Delete the entry from the label */ CollDeleteItem (&L->JumpFrom, E); /* The entry jumps no longer to L */ CE_ClearJumpTo (E); /* If there are no more references, delete the label */ if (CollCount (&L->JumpFrom) == 0) { CS_DelLabel (S, L); } } void CS_MoveLabelRef (CodeSeg* S, struct CodeEntry* E, CodeLabel* L) /* Change the reference of E to L instead of the current one. If this ** was the only reference to the old label, the old label will get ** deleted. */ { /* Get the old label */ CodeLabel* OldLabel = E->JumpTo; /* Be sure that code entry references a label */ PRECONDITION (OldLabel != 0); /* Remove the reference to our label */ CS_RemoveLabelRef (S, E); /* Use the new label */ CL_AddRef (L, E); } void CS_DelCodeRange (CodeSeg* S, unsigned First, unsigned Last) /* Delete all entries between first and last, both inclusive. The function ** can only handle basic blocks (First is the only entry, Last the only exit) ** and no open labels. It will call FAIL if any of these preconditions are ** violated. */ { unsigned I; CodeEntry* FirstEntry; /* Do some sanity checks */ CHECK (First <= Last && Last < CS_GetEntryCount (S)); /* If Last is actually the last insn, call CS_DelCodeAfter instead, which ** is more flexible in this case. */ if (Last == CS_GetEntryCount (S) - 1) { CS_DelCodeAfter (S, First); return; } /* Get the first entry and check if it has any labels. If it has, move ** them to the insn following Last. If Last is the last insn of the code ** segment, make them ownerless and move them to the label pool. */ FirstEntry = CS_GetEntry (S, First); if (CE_HasLabel (FirstEntry)) { /* Get the entry following last */ CodeEntry* FollowingEntry = CS_GetNextEntry (S, Last); if (FollowingEntry) { /* There is an entry after Last - move the labels */ CS_MoveLabels (S, FirstEntry, FollowingEntry); } else { /* Move the labels to the pool and clear the owner pointer */ CS_MoveLabelsToPool (S, FirstEntry); } } /* First pass: Delete all references to labels. If the reference count ** for a label drops to zero, delete it. */ for (I = Last; I >= First; --I) { /* Get the next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if this entry has a label reference */ if (E->JumpTo) { /* If the label is a label in the label pool, this is an error */ CodeLabel* L = E->JumpTo; CHECK (CollIndex (&S->Labels, L) < 0); /* Remove the reference to the label */ CS_RemoveLabelRef (S, E); } } /* Second pass: Delete the instructions. If a label attached to an ** instruction still has references, it must be references from outside ** the deleted area, which is an error. */ for (I = Last; I >= First; --I) { /* Get the next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if this entry has a label attached */ CHECK (!CE_HasLabel (E)); /* Delete the pointer to the entry */ CollDelete (&S->Entries, I); /* Delete the entry itself */ FreeCodeEntry (E); } } void CS_DelCodeAfter (CodeSeg* S, unsigned Last) /* Delete all entries including the given one */ { /* Get the number of entries in this segment */ unsigned Count = CS_GetEntryCount (S); /* First pass: Delete all references to labels. If the reference count ** for a label drops to zero, delete it. */ unsigned C = Count; while (Last < C--) { /* Get the next entry */ CodeEntry* E = CS_GetEntry (S, C); /* Check if this entry has a label reference */ if (E->JumpTo) { /* If the label is a label in the label pool and this is the last ** reference to the label, remove the label from the pool. */ CodeLabel* L = E->JumpTo; int Index = CollIndex (&S->Labels, L); if (Index >= 0 && CollCount (&L->JumpFrom) == 1) { /* Delete it from the pool */ CollDelete (&S->Labels, Index); } /* Remove the reference to the label */ CS_RemoveLabelRef (S, E); } } /* Second pass: Delete the instructions. If a label attached to an ** instruction still has references, it must be references from outside ** the deleted area. Don't delete the label in this case, just make it ** ownerless and move it to the label pool. */ C = Count; while (Last < C--) { /* Get the next entry */ CodeEntry* E = CS_GetEntry (S, C); /* Check if this entry has a label attached */ if (CE_HasLabel (E)) { /* Move the labels to the pool and clear the owner pointer */ CS_MoveLabelsToPool (S, E); } /* Delete the pointer to the entry */ CollDelete (&S->Entries, C); /* Delete the entry itself */ FreeCodeEntry (E); } } void CS_ResetMarks (CodeSeg* S, unsigned First, unsigned Last) /* Remove all user marks from the entries in the given range */ { while (First <= Last) { CE_ResetMark (CS_GetEntry (S, First++)); } } int CS_IsBasicBlock (CodeSeg* S, unsigned First, unsigned Last) /* Check if the given code segment range is a basic block. That is, check if ** First is the only entrance and Last is the only exit. This means that no ** jump/branch inside the block may jump to an insn below First or after(!) ** Last, and that no insn may jump into this block from the outside. */ { unsigned I; /* Don't accept invalid ranges */ CHECK (First <= Last); /* First pass: Walk over the range and remove all marks from the entries */ CS_ResetMarks (S, First, Last); /* Second pass: Walk over the range checking all labels. Note: There may be ** label on the first insn which is ok. */ I = First + 1; while (I <= Last) { /* Get the next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if this entry has one or more labels, if so, check which ** entries jump to this label. */ unsigned LabelCount = CE_GetLabelCount (E); unsigned LabelIndex; for (LabelIndex = 0; LabelIndex < LabelCount; ++LabelIndex) { /* Get this label */ CodeLabel* L = CE_GetLabel (E, LabelIndex); /* Walk over all entries that jump to this label. Check for each ** of the entries if it is out of the range. */ unsigned RefCount = CL_GetRefCount (L); unsigned RefIndex; for (RefIndex = 0; RefIndex < RefCount; ++RefIndex) { /* Get the code entry that jumps here */ CodeEntry* Ref = CL_GetRef (L, RefIndex); /* Walk over out complete range and check if we find the ** refering entry. This is cheaper than using CS_GetEntryIndex, ** because CS_GetEntryIndex will search the complete code ** segment and not just our range. */ unsigned J; for (J = First; J <= Last; ++J) { if (Ref == CS_GetEntry (S, J)) { break; } } if (J > Last) { /* We did not find the entry. This means that the jump to ** out code segment entry E came from outside the range, ** which in turn means that the given range is not a basic ** block. */ CS_ResetMarks (S, First, Last); return 0; } /* If we come here, we found the entry. Mark it, so we know ** that the branch to the label is in range. */ CE_SetMark (Ref); } } /* Next entry */ ++I; } /* Third pass: Walk again over the range and check all branches. If we ** find a branch that is not marked, its target is not inside the range ** (since we checked all the labels in the range before). */ I = First; while (I <= Last) { /* Get the next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if this is a branch and if so, if it has a mark */ if (E->Info & (OF_UBRA | OF_CBRA)) { if (!CE_HasMark (E)) { /* No mark means not a basic block. Before bailing out, be sure ** to remove the marks from the remaining entries. */ CS_ResetMarks (S, I+1, Last); return 0; } /* Remove the mark */ CE_ResetMark (E); } /* Next entry */ ++I; } /* Done - this is a basic block */ return 1; } void CS_OutputPrologue (const CodeSeg* S) /* If the given code segment is a code segment for a function, output the ** assembler prologue into the file. That is: Output a comment header, switch ** to the correct segment and enter the local function scope. If the code ** segment is global, do nothing. */ { /* Get the function associated with the code segment */ SymEntry* Func = S->Func; /* If the code segment is associated with a function, print a function ** header and enter a local scope. Be sure to switch to the correct ** segment before outputing the function label. */ if (Func) { /* Get the function descriptor */ CS_PrintFunctionHeader (S); WriteOutput (".segment\t\"%s\"\n\n.proc\t_%s", S->SegName, Func->Name); if (IsQualNear (Func->Type)) { WriteOutput (": near"); } else if (IsQualFar (Func->Type)) { WriteOutput (": far"); } WriteOutput ("\n\n"); } } void CS_OutputEpilogue (const CodeSeg* S) /* If the given code segment is a code segment for a function, output the ** assembler epilogue into the file. That is: Close the local function scope. */ { if (S->Func) { WriteOutput ("\n.endproc\n\n"); } } void CS_Output (CodeSeg* S) /* Output the code segment data to the output file */ { unsigned I; const LineInfo* LI; /* Get the number of entries in this segment */ unsigned Count = CS_GetEntryCount (S); /* If the code segment is empty, bail out here */ if (Count == 0) { return; } /* Generate register info */ CS_GenRegInfo (S); /* Output the segment directive */ WriteOutput (".segment\t\"%s\"\n\n", S->SegName); /* Output all entries, prepended by the line information if it has changed */ LI = 0; for (I = 0; I < Count; ++I) { /* Get the next entry */ const CodeEntry* E = CollConstAt (&S->Entries, I); /* Check if the line info has changed. If so, output the source line ** if the option is enabled and output debug line info if the debug ** option is enabled. */ if (E->LI != LI) { /* Line info has changed, remember the new line info */ LI = E->LI; /* Add the source line as a comment. Beware: When line continuation ** was used, the line may contain newlines. */ if (AddSource) { const char* L = LI->Line; WriteOutput (";\n; "); while (*L) { const char* N = strchr (L, '\n'); if (N) { /* We have a newline, just write the first part */ WriteOutput ("%.*s\n; ", (int) (N - L), L); L = N+1; } else { /* No Newline, write as is */ WriteOutput ("%s\n", L); break; } } WriteOutput (";\n"); } /* Add line debug info */ if (DebugInfo) { WriteOutput ("\t.dbg\tline, \"%s\", %u\n", GetInputName (LI), GetInputLine (LI)); } } /* Output the code */ CE_Output (E); } /* If debug info is enabled, terminate the last line number information */ if (DebugInfo) { WriteOutput ("\t.dbg\tline\n"); } /* Free register info */ CS_FreeRegInfo (S); } void CS_FreeRegInfo (CodeSeg* S) /* Free register infos for all instructions */ { unsigned I; for (I = 0; I < CS_GetEntryCount (S); ++I) { CE_FreeRegInfo (CS_GetEntry(S, I)); } } void CS_GenRegInfo (CodeSeg* S) /* Generate register infos for all instructions */ { unsigned I; RegContents Regs; /* Initial register contents */ RegContents* CurrentRegs; /* Current register contents */ int WasJump; /* True if last insn was a jump */ int Done; /* All runs done flag */ /* Be sure to delete all register infos */ CS_FreeRegInfo (S); /* We may need two runs to get back references right */ do { /* Assume we're done after this run */ Done = 1; /* On entry, the register contents are unknown */ RC_Invalidate (&Regs); CurrentRegs = &Regs; /* Walk over all insns and note just the changes from one insn to the ** next one. */ WasJump = 0; for (I = 0; I < CS_GetEntryCount (S); ++I) { CodeEntry* P; /* Get the next instruction */ CodeEntry* E = CollAtUnchecked (&S->Entries, I); /* If the instruction has a label, we need some special handling */ unsigned LabelCount = CE_GetLabelCount (E); if (LabelCount > 0) { /* Loop over all entry points that jump here. If these entry ** points already have register info, check if all values are ** known and identical. If all values are identical, and the ** preceeding instruction was not an unconditional branch, check ** if the register value on exit of the preceeding instruction ** is also identical. If all these values are identical, the ** value of a register is known, otherwise it is unknown. */ CodeLabel* Label = CE_GetLabel (E, 0); unsigned Entry; if (WasJump) { /* Preceeding insn was an unconditional branch */ CodeEntry* J = CL_GetRef(Label, 0); if (J->RI) { Regs = J->RI->Out2; } else { RC_Invalidate (&Regs); } Entry = 1; } else { Regs = *CurrentRegs; Entry = 0; } while (Entry < CL_GetRefCount (Label)) { /* Get this entry */ CodeEntry* J = CL_GetRef (Label, Entry); if (J->RI == 0) { /* No register info for this entry. This means that the ** instruction that jumps here is at higher addresses and ** the jump is a backward jump. We need a second run to ** get the register info right in this case. Until then, ** assume unknown register contents. */ Done = 0; RC_Invalidate (&Regs); break; } if (J->RI->Out2.RegA != Regs.RegA) { Regs.RegA = UNKNOWN_REGVAL; } if (J->RI->Out2.RegX != Regs.RegX) { Regs.RegX = UNKNOWN_REGVAL; } if (J->RI->Out2.RegY != Regs.RegY) { Regs.RegY = UNKNOWN_REGVAL; } if (J->RI->Out2.SRegLo != Regs.SRegLo) { Regs.SRegLo = UNKNOWN_REGVAL; } if (J->RI->Out2.SRegHi != Regs.SRegHi) { Regs.SRegHi = UNKNOWN_REGVAL; } if (J->RI->Out2.Tmp1 != Regs.Tmp1) { Regs.Tmp1 = UNKNOWN_REGVAL; } ++Entry; } /* Use this register info */ CurrentRegs = &Regs; } /* Generate register info for this instruction */ CE_GenRegInfo (E, CurrentRegs); /* Remember for the next insn if this insn was an uncondition branch */ WasJump = (E->Info & OF_UBRA) != 0; /* Output registers for this insn are input for the next */ CurrentRegs = &E->RI->Out; /* If this insn is a branch on zero flag, we may have more info on ** register contents for one of both flow directions, but only if ** there is a previous instruction. */ if ((E->Info & OF_ZBRA) != 0 && (P = CS_GetPrevEntry (S, I)) != 0) { /* Get the branch condition */ bc_t BC = GetBranchCond (E->OPC); /* Check the previous instruction */ switch (P->OPC) { case OP65_ADC: case OP65_AND: case OP65_DEA: case OP65_EOR: case OP65_INA: case OP65_LDA: case OP65_ORA: case OP65_PLA: case OP65_SBC: /* A is zero in one execution flow direction */ if (BC == BC_EQ) { E->RI->Out2.RegA = 0; } else { E->RI->Out.RegA = 0; } break; case OP65_CMP: /* If this is an immidiate compare, the A register has ** the value of the compare later. */ if (CE_IsConstImm (P)) { if (BC == BC_EQ) { E->RI->Out2.RegA = (unsigned char)P->Num; } else { E->RI->Out.RegA = (unsigned char)P->Num; } } break; case OP65_CPX: /* If this is an immidiate compare, the X register has ** the value of the compare later. */ if (CE_IsConstImm (P)) { if (BC == BC_EQ) { E->RI->Out2.RegX = (unsigned char)P->Num; } else { E->RI->Out.RegX = (unsigned char)P->Num; } } break; case OP65_CPY: /* If this is an immidiate compare, the Y register has ** the value of the compare later. */ if (CE_IsConstImm (P)) { if (BC == BC_EQ) { E->RI->Out2.RegY = (unsigned char)P->Num; } else { E->RI->Out.RegY = (unsigned char)P->Num; } } break; case OP65_DEX: case OP65_INX: case OP65_LDX: case OP65_PLX: /* X is zero in one execution flow direction */ if (BC == BC_EQ) { E->RI->Out2.RegX = 0; } else { E->RI->Out.RegX = 0; } break; case OP65_DEY: case OP65_INY: case OP65_LDY: case OP65_PLY: /* X is zero in one execution flow direction */ if (BC == BC_EQ) { E->RI->Out2.RegY = 0; } else { E->RI->Out.RegY = 0; } break; case OP65_TAX: case OP65_TXA: /* If the branch is a beq, both A and X are zero at the ** branch target, otherwise they are zero at the next ** insn. */ if (BC == BC_EQ) { E->RI->Out2.RegA = E->RI->Out2.RegX = 0; } else { E->RI->Out.RegA = E->RI->Out.RegX = 0; } break; case OP65_TAY: case OP65_TYA: /* If the branch is a beq, both A and Y are zero at the ** branch target, otherwise they are zero at the next ** insn. */ if (BC == BC_EQ) { E->RI->Out2.RegA = E->RI->Out2.RegY = 0; } else { E->RI->Out.RegA = E->RI->Out.RegY = 0; } break; default: break; } } } } while (!Done); } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/codeseg.h������������������������������������������������������������������������0000664�0000000�0000000�00000027032�13473601511�0015322�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* codeseg.h */ /* */ /* Code segment structure */ /* */ /* */ /* */ /* (C) 2001-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef CODESEG_H #define CODESEG_H #include <stdarg.h> /* common */ #include "attrib.h" #include "coll.h" #include "inline.h" /* cc65 */ #include "codelab.h" #include "lineinfo.h" #include "symentry.h" /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ struct CodeEntry; /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Size of the label hash table */ #define CS_LABEL_HASH_SIZE 29 /* Code segment structure */ typedef struct CodeSeg CodeSeg; struct CodeSeg { char* SegName; /* Segment name */ SymEntry* Func; /* Owner function */ Collection Entries; /* List of code entries */ Collection Labels; /* Labels for next insn */ CodeLabel* LabelHash[CS_LABEL_HASH_SIZE]; /* Label hash table */ unsigned short ExitRegs; /* Register use on exit */ /* Optimization settings for this segment */ unsigned char Optimize; /* On/off switch */ unsigned CodeSizeFactor; }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ CodeSeg* NewCodeSeg (const char* SegName, SymEntry* Func); /* Create a new code segment, initialize and return it */ void CS_AddEntry (CodeSeg* S, struct CodeEntry* E); /* Add an entry to the given code segment */ void CS_AddVLine (CodeSeg* S, LineInfo* LI, const char* Format, va_list ap) attribute ((format(printf,3,0))); /* Add a line to the given code segment */ void CS_AddLine (CodeSeg* S, LineInfo* LI, const char* Format, ...) attribute ((format(printf,3,4))); /* Add a line to the given code segment */ #if defined(HAVE_INLINE) INLINE unsigned CS_GetEntryCount (const CodeSeg* S) /* Return the number of entries for the given code segment */ { return CollCount (&S->Entries); } #else # define CS_GetEntryCount(S) CollCount (&(S)->Entries) #endif void CS_InsertEntry (CodeSeg* S, struct CodeEntry* E, unsigned Index); /* Insert the code entry at the index given. Following code entries will be ** moved to slots with higher indices. */ void CS_DelEntry (CodeSeg* S, unsigned Index); /* Delete an entry from the code segment. This includes moving any associated ** labels, removing references to labels and even removing the referenced labels ** if the reference count drops to zero. ** Note: Labels are moved forward if possible, that is, they are moved to the ** next insn (not the preceeding one). */ void CS_DelEntries (CodeSeg* S, unsigned Start, unsigned Count); /* Delete a range of code entries. This includes removing references to labels, ** labels attached to the entries and so on. */ void CS_MoveEntries (CodeSeg* S, unsigned Start, unsigned Count, unsigned NewPos); /* Move a range of entries from one position to another. Start is the index ** of the first entry to move, Count is the number of entries and NewPos is ** the index of the target entry. The entry with the index Start will later ** have the index NewPos. All entries with indices NewPos and above are ** moved to higher indices. If the code block is moved to the end of the ** current code, and if pending labels exist, these labels will get attached ** to the first instruction of the moved block (the first one after the ** current code end) */ #if defined(HAVE_INLINE) INLINE void CS_MoveEntry (CodeSeg* S, unsigned OldPos, unsigned NewPos) /* Move an entry from one position to another. OldPos is the current position ** of the entry, NewPos is the new position of the entry. */ { CollMove (&S->Entries, OldPos, NewPos); } #else # define CS_MoveEntry(S, OldPos, NewPos) CollMove (&(S)->Entries, OldPos, NewPos) #endif #if defined(HAVE_INLINE) INLINE struct CodeEntry* CS_GetEntry (CodeSeg* S, unsigned Index) /* Get an entry from the given code segment */ { return CollAt (&S->Entries, Index); } #else # define CS_GetEntry(S, Index) ((struct CodeEntry*) CollAt(&(S)->Entries, (Index))) #endif struct CodeEntry* CS_GetPrevEntry (CodeSeg* S, unsigned Index); /* Get the code entry preceeding the one with the index Index. If there is no ** preceeding code entry, return NULL. */ struct CodeEntry* CS_GetNextEntry (CodeSeg* S, unsigned Index); /* Get the code entry following the one with the index Index. If there is no ** following code entry, return NULL. */ int CS_GetEntries (CodeSeg* S, struct CodeEntry** List, unsigned Start, unsigned Count); /* Get Count code entries into List starting at index start. Return true if ** we got the lines, return false if not enough lines were available. */ unsigned CS_GetEntryIndex (CodeSeg* S, struct CodeEntry* E); /* Return the index of a code entry */ int CS_RangeHasLabel (CodeSeg* S, unsigned Start, unsigned Count); /* Return true if any of the code entries in the given range has a label ** attached. If the code segment does not span the given range, check the ** possible span instead. */ #if defined(HAVE_INLINE) INLINE int CS_HavePendingLabel (const CodeSeg* S) /* Return true if there are open labels that will get attached to the next ** instruction that is added. */ { return (CollCount (&S->Labels) > 0); } #else # define CS_HavePendingLabel(S) (CollCount (&(S)->Labels) > 0) #endif CodeLabel* CS_AddLabel (CodeSeg* S, const char* Name); /* Add a code label for the next instruction to follow */ CodeLabel* CS_GenLabel (CodeSeg* S, struct CodeEntry* E); /* If the code entry E does already have a label, return it. Otherwise ** create a new label, attach it to E and return it. */ void CS_DelLabel (CodeSeg* S, CodeLabel* L); /* Remove references from this label and delete it. */ void CS_MergeLabels (CodeSeg* S); /* Merge code labels. That means: For each instruction, remove all labels but ** one and adjust references accordingly. */ void CS_MoveLabels (CodeSeg* S, struct CodeEntry* Old, struct CodeEntry* New); /* Move all labels from Old to New. The routine will move the labels itself ** if New does not have any labels, and move references if there is at least ** a label for new. If references are moved, the old label is deleted ** afterwards. */ void CS_RemoveLabelRef (CodeSeg* S, struct CodeEntry* E); /* Remove the reference between E and the label it jumps to. The reference ** will be removed on both sides and E->JumpTo will be 0 after that. If ** the reference was the only one for the label, the label will get ** deleted. */ void CS_MoveLabelRef (CodeSeg* S, struct CodeEntry* E, CodeLabel* L); /* Change the reference of E to L instead of the current one. If this ** was the only reference to the old label, the old label will get ** deleted. */ void CS_DelCodeRange (CodeSeg* S, unsigned First, unsigned Last); /* Delete all entries between first and last, both inclusive. The function ** can only handle basic blocks (First is the only entry, Last the only exit) ** and no open labels. It will call FAIL if any of these preconditions are ** violated. */ void CS_DelCodeAfter (CodeSeg* S, unsigned Last); /* Delete all entries including the given one */ void CS_ResetMarks (CodeSeg* S, unsigned First, unsigned Last); /* Remove all user marks from the entries in the given range */ #if defined(HAVE_INLINE) INLINE void CS_ResetAllMarks (CodeSeg* S) /* Remove all user marks from the code segment */ { if (CS_GetEntryCount (S) > 0) { CS_ResetMarks (S, 0, CS_GetEntryCount (S)); } } #else # define CS_ResetAllMarks(S) \ ((CS_GetEntryCount (S) > 0)? CS_ResetMarks (S, 0, CS_GetEntryCount (S)) : (void) 0) #endif int CS_IsBasicBlock (CodeSeg* S, unsigned First, unsigned Last); /* Check if the given code segment range is a basic block. That is, check if ** First is the only entrance and Last is the only exit. This means that no ** jump/branch inside the block may jump to an insn below First or after(!) ** Last, and that no insn may jump into this block from the outside. */ void CS_OutputPrologue (const CodeSeg* S); /* If the given code segment is a code segment for a function, output the ** assembler prologue into the file. That is: Output a comment header, switch ** to the correct segment and enter the local function scope. If the code ** segment is global, do nothing. */ void CS_OutputEpilogue (const CodeSeg* S); /* If the given code segment is a code segment for a function, output the ** assembler epilogue into the file. That is: Close the local function scope. */ void CS_Output (CodeSeg* S); /* Output the code segment data to a file */ void CS_FreeRegInfo (CodeSeg* S); /* Free register infos for all instructions */ void CS_GenRegInfo (CodeSeg* S); /* Generate register infos for all instructions */ /* End of codeseg.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/compile.c������������������������������������������������������������������������0000664�0000000�0000000�00000040240�13473601511�0015330�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* compile.c */ /* */ /* Top level compiler subroutine */ /* */ /* */ /* */ /* (C) 2000-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdlib.h> #include <time.h> /* common */ #include "debugflag.h" #include "segnames.h" #include "version.h" #include "xmalloc.h" #include "xsprintf.h" /* cc65 */ #include "asmlabel.h" #include "asmstmt.h" #include "codegen.h" #include "codeopt.h" #include "compile.h" #include "declare.h" #include "error.h" #include "expr.h" #include "function.h" #include "global.h" #include "input.h" #include "litpool.h" #include "macrotab.h" #include "output.h" #include "pragma.h" #include "preproc.h" #include "standard.h" #include "symtab.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void Parse (void) /* Top level parser routine. */ { int comma; SymEntry* Entry; /* Go... */ NextToken (); NextToken (); /* Parse until end of input */ while (CurTok.Tok != TOK_CEOF) { DeclSpec Spec; /* Check for empty statements */ if (CurTok.Tok == TOK_SEMI) { NextToken (); continue; } /* Disallow ASM statements on global level */ if (CurTok.Tok == TOK_ASM) { Error ("__asm__ is not allowed here"); /* Parse and remove the statement for error recovery */ AsmStatement (); ConsumeSemi (); RemoveGlobalCode (); continue; } /* Check for a #pragma */ if (CurTok.Tok == TOK_PRAGMA) { DoPragma (); continue; } /* Read variable defs and functions */ ParseDeclSpec (&Spec, SC_EXTERN | SC_STATIC, T_INT); /* Don't accept illegal storage classes */ if ((Spec.StorageClass & SC_TYPE) == 0) { if ((Spec.StorageClass & SC_AUTO) != 0 || (Spec.StorageClass & SC_REGISTER) != 0) { Error ("Illegal storage class"); Spec.StorageClass = SC_EXTERN | SC_STATIC; } } /* Check if this is only a type declaration */ if (CurTok.Tok == TOK_SEMI) { CheckEmptyDecl (&Spec); NextToken (); continue; } /* Read declarations for this type */ Entry = 0; comma = 0; while (1) { Declaration Decl; /* Read the next declaration */ ParseDecl (&Spec, &Decl, DM_NEED_IDENT); if (Decl.Ident[0] == '\0') { NextToken (); break; } /* Check if we must reserve storage for the variable. We do this, ** ** - if it is not a typedef or function, ** - if we don't had a storage class given ("int i") ** - if the storage class is explicitly specified as static, ** - or if there is an initialization. ** ** This means that "extern int i;" will not get storage allocated. */ if ((Decl.StorageClass & SC_FUNC) != SC_FUNC && (Decl.StorageClass & SC_TYPEMASK) != SC_TYPEDEF && ((Spec.Flags & DS_DEF_STORAGE) != 0 || (Decl.StorageClass & (SC_EXTERN|SC_STATIC)) == SC_STATIC || ((Decl.StorageClass & SC_EXTERN) != 0 && CurTok.Tok == TOK_ASSIGN))) { /* We will allocate storage */ Decl.StorageClass |= SC_STORAGE; } /* If this is a function declarator that is not followed by a comma ** or semicolon, it must be followed by a function body. If this is ** the case, convert an empty parameter list into one accepting no ** parameters (same as void) as required by the standard. */ if ((Decl.StorageClass & SC_FUNC) != 0 && (CurTok.Tok != TOK_COMMA) && (CurTok.Tok != TOK_SEMI)) { FuncDesc* D = GetFuncDesc (Decl.Type); if (D->Flags & FD_EMPTY) { D->Flags = (D->Flags & ~(FD_EMPTY | FD_VARIADIC)) | FD_VOID_PARAM; } } /* Add an entry to the symbol table */ Entry = AddGlobalSym (Decl.Ident, Decl.Type, Decl.StorageClass); /* Add declaration attributes */ SymUseAttr (Entry, &Decl); /* Reserve storage for the variable if we need to */ if (Decl.StorageClass & SC_STORAGE) { /* Get the size of the variable */ unsigned Size = SizeOf (Decl.Type); /* Allow initialization */ if (CurTok.Tok == TOK_ASSIGN) { /* This is a definition */ if (SymIsDef (Entry)) { Error ("Global variable '%s' has already been defined", Entry->Name); } Entry->Flags |= SC_DEF; /* We cannot initialize types of unknown size, or ** void types in ISO modes. */ if (Size == 0) { if (!IsTypeVoid (Decl.Type)) { if (!IsTypeArray (Decl.Type)) { /* Size is unknown and not an array */ Error ("Variable '%s' has unknown size", Decl.Ident); } } else if (IS_Get (&Standard) != STD_CC65) { /* We cannot declare variables of type void */ Error ("Illegal type for variable '%s'", Decl.Ident); } } /* Switch to the data or rodata segment. For arrays, check ** the element qualifiers, since not the array but its ** elements are const. */ if (IsQualConst (GetBaseElementType (Decl.Type))) { g_userodata (); } else { g_usedata (); } /* Define a label */ g_defgloblabel (Entry->Name); /* Skip the '=' */ NextToken (); /* Parse the initialization */ ParseInit (Entry->Type); } else { if (IsTypeVoid (Decl.Type)) { /* We cannot declare variables of type void */ Error ("Illegal type for variable '%s'", Decl.Ident); Entry->Flags &= ~(SC_STORAGE | SC_DEF); } else if (Size == 0) { /* Size is unknown. Is it an array? */ if (!IsTypeArray (Decl.Type)) { Error ("Variable '%s' has unknown size", Decl.Ident); } Entry->Flags &= ~(SC_STORAGE | SC_DEF); } else { /* A global (including static) uninitialized variable is ** only a tentative definition. For example, this is valid: ** int i; ** int i; ** static int j; ** static int j = 42; ** Code for them will be generated by FinishCompile(). ** For now, just save the BSS segment name ** (can be set by #pragma bss-name). */ const char* bssName = GetSegName (SEG_BSS); if (Entry->V.BssName && strcmp (Entry->V.BssName, bssName) != 0) { Error ("Global variable '%s' already was defined in the '%s' segment.", Entry->Name, Entry->V.BssName); } Entry->V.BssName = xstrdup (bssName); } } } /* Check for end of declaration list */ if (CurTok.Tok == TOK_COMMA) { NextToken (); comma = 1; } else { break; } } /* Function declaration? */ if (Entry && IsTypeFunc (Entry->Type)) { /* Function */ if (!comma) { if (CurTok.Tok == TOK_SEMI) { /* Prototype only */ NextToken (); } else { /* Function body. Check for duplicate function definitions */ if (SymIsDef (Entry)) { Error ("Body for function '%s' has already been defined", Entry->Name); } /* Parse the function body */ NewFunc (Entry); } } } else { /* Must be followed by a semicolon */ ConsumeSemi (); } } } void Compile (const char* FileName) /* Top level compile routine. Will setup things and call the parser. */ { char DateStr[32]; char TimeStr[32]; time_t Time; struct tm* TM; /* Since strftime is locale dependent, we need the abbreviated month names ** in English. */ static const char MonthNames[12][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; /* Add macros that are always defined */ DefineNumericMacro ("__CC65__", GetVersionAsNumber ()); /* Language standard that is supported */ DefineNumericMacro ("__CC65_STD_C89__", STD_C89); DefineNumericMacro ("__CC65_STD_C99__", STD_C99); DefineNumericMacro ("__CC65_STD_CC65__", STD_CC65); DefineNumericMacro ("__CC65_STD__", IS_Get (&Standard)); /* Optimization macros. Since no source code has been parsed for now, the ** IS_Get functions access the values in effect now, regardless of any ** changes using #pragma later. */ if (IS_Get (&Optimize)) { DefineNumericMacro ("__OPT__", 1); } { long CodeSize = IS_Get (&CodeSizeFactor); if (CodeSize > 100) { DefineNumericMacro ("__OPT_i__", CodeSize); } } if (IS_Get (&EnableRegVars)) { DefineNumericMacro ("__OPT_r__", 1); } if (IS_Get (&InlineStdFuncs)) { DefineNumericMacro ("__OPT_s__", 1); } if (IS_Get (&EagerlyInlineFuncs)) { DefineNumericMacro ("__EAGERLY_INLINE_FUNCS__", 1); } /* __TIME__ and __DATE__ macros */ Time = time (0); TM = localtime (&Time); xsprintf (DateStr, sizeof (DateStr), "\"%s %2d %d\"", MonthNames[TM->tm_mon], TM->tm_mday, TM->tm_year + 1900); strftime (TimeStr, sizeof (TimeStr), "\"%H:%M:%S\"", TM); DefineTextMacro ("__DATE__", DateStr); DefineTextMacro ("__TIME__", TimeStr); /* Other standard macros */ /* DefineNumericMacro ("__STDC__", 1); <- not now */ DefineNumericMacro ("__STDC_HOSTED__", 1); /* Create the base lexical level */ EnterGlobalLevel (); /* Create the global code and data segments */ CreateGlobalSegments (); /* Initialize the literal pool */ InitLiteralPool (); /* Generate the code generator preamble */ g_preamble (); /* Open the input file */ OpenMainFile (FileName); /* Are we supposed to compile or just preprocess the input? */ if (PreprocessOnly) { /* Open the file */ OpenOutputFile (); /* Preprocess each line and write it to the output file */ while (NextLine ()) { Preprocess (); WriteOutput ("%.*s\n", (int) SB_GetLen (Line), SB_GetConstBuf (Line)); } /* Close the output file */ CloseOutputFile (); } else { /* Ok, start the ball rolling... */ Parse (); } if (Debug) { PrintMacroStats (stdout); } /* Print an error report */ ErrorReport (); } void FinishCompile (void) /* Emit literals, externals, debug info, do cleanup and optimizations */ { SymEntry* Entry; /* Reset the BSS segment name to its default; so that the below strcmp() ** will work as expected, at the beginning of the list of variables */ SetSegName (SEG_BSS, SEGNAME_BSS); /* Walk over all global symbols: ** - for functions, do clean-up and optimizations ** - generate code for uninitialized global variables */ for (Entry = GetGlobalSymTab ()->SymHead; Entry; Entry = Entry->NextSym) { if (SymIsOutputFunc (Entry)) { /* Function which is defined and referenced or extern */ MoveLiteralPool (Entry->V.F.LitPool); CS_MergeLabels (Entry->V.F.Seg->Code); RunOpt (Entry->V.F.Seg->Code); } else if ((Entry->Flags & (SC_STORAGE | SC_DEF | SC_STATIC)) == (SC_STORAGE | SC_STATIC)) { /* Assembly definition of uninitialized global variable */ /* Set the segment name only when it changes */ if (strcmp (GetSegName (SEG_BSS), Entry->V.BssName) != 0) { SetSegName (SEG_BSS, Entry->V.BssName); g_segname (SEG_BSS); } g_usebss (); g_defgloblabel (Entry->Name); g_res (SizeOf (Entry->Type)); /* Mark as defined; so that it will be exported, not imported */ Entry->Flags |= SC_DEF; } } /* Output the literal pool */ OutputLiteralPool (); /* Emit debug infos if enabled */ EmitDebugInfo (); /* Write imported/exported symbols */ EmitExternals (); /* Leave the main lexical level */ LeaveGlobalLevel (); } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/compile.h������������������������������������������������������������������������0000664�0000000�0000000�00000006005�13473601511�0015336�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* compile.h */ /* */ /* Top level compiler subroutine */ /* */ /* */ /* */ /* (C) 2000-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef COMPILE_H #define COMPILE_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Compile (const char* FileName); /* Top level compile routine. Will setup things and call the parser. */ void FinishCompile (void); /* Emit literals, externals, do cleanup and optimizations */ /* End of compile.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/coptadd.c������������������������������������������������������������������������0000664�0000000�0000000�00000037515�13473601511�0015331�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* coptadd.c */ /* */ /* Optimize addition sequences */ /* */ /* */ /* */ /* (C) 2001-2005, Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "chartype.h" /* cc65 */ #include "codeent.h" #include "codeinfo.h" #include "coptadd.h" /*****************************************************************************/ /* Optimize additions */ /*****************************************************************************/ unsigned OptAdd1 (CodeSeg* S) /* Search for the sequence ** ** ldy #xx ** jsr ldaxysp ** jsr pushax ** ldy #yy ** jsr ldaxysp ** jsr tosaddax ** ** and replace it by: ** ** ldy #xx-1 ** lda (sp),y ** ldy #yy-3 ** clc ** adc (sp),y ** pha ** ldy #xx ** lda (sp),y ** ldy #yy-2 ** adc (sp),y ** tax ** pla */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[6]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (L[0]->OPC == OP65_LDY && CE_IsConstImm (L[0]) && !CS_RangeHasLabel (S, I+1, 5) && CS_GetEntries (S, L+1, I+1, 5) && CE_IsCallTo (L[1], "ldaxysp") && CE_IsCallTo (L[2], "pushax") && L[3]->OPC == OP65_LDY && CE_IsConstImm (L[3]) && CE_IsCallTo (L[4], "ldaxysp") && CE_IsCallTo (L[5], "tosaddax")) { CodeEntry* X; const char* Arg; /* Correct the stack of the first Y register load */ CE_SetNumArg (L[0], L[0]->Num - 1); /* lda (sp),y */ X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, L[1]->LI); CS_InsertEntry (S, X, I+1); /* ldy #yy-3 */ Arg = MakeHexArg (L[3]->Num - 3); X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[4]->LI); CS_InsertEntry (S, X, I+2); /* clc */ X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, L[5]->LI); CS_InsertEntry (S, X, I+3); /* adc (sp),y */ X = NewCodeEntry (OP65_ADC, AM65_ZP_INDY, "sp", 0, L[5]->LI); CS_InsertEntry (S, X, I+4); /* pha */ X = NewCodeEntry (OP65_PHA, AM65_IMP, 0, 0, L[5]->LI); CS_InsertEntry (S, X, I+5); /* ldy #xx (beware: L[0] has changed) */ Arg = MakeHexArg (L[0]->Num + 1); X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[1]->LI); CS_InsertEntry (S, X, I+6); /* lda (sp),y */ X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, L[1]->LI); CS_InsertEntry (S, X, I+7); /* ldy #yy-2 */ Arg = MakeHexArg (L[3]->Num - 2); X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[4]->LI); CS_InsertEntry (S, X, I+8); /* adc (sp),y */ X = NewCodeEntry (OP65_ADC, AM65_ZP_INDY, "sp", 0, L[5]->LI); CS_InsertEntry (S, X, I+9); /* tax */ X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, L[5]->LI); CS_InsertEntry (S, X, I+10); /* pla */ X = NewCodeEntry (OP65_PLA, AM65_IMP, 0, 0, L[5]->LI); CS_InsertEntry (S, X, I+11); /* Delete the old code */ CS_DelEntries (S, I+12, 5); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptAdd2 (CodeSeg* S) /* Search for the sequence ** ** ldy #xx ** jsr ldaxysp ** ldy #yy ** jsr addeqysp ** ** and replace it by: ** ** ldy #xx-1 ** lda (sp),y ** ldy #yy ** clc ** adc (sp),y ** sta (sp),y ** ldy #xx ** lda (sp),y ** ldy #yy+1 ** adc (sp),y ** sta (sp),y ** ** provided that a/x is not used later. */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[4]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (L[0]->OPC == OP65_LDY && CE_IsConstImm (L[0]) && !CS_RangeHasLabel (S, I+1, 3) && CS_GetEntries (S, L+1, I+1, 3) && CE_IsCallTo (L[1], "ldaxysp") && L[2]->OPC == OP65_LDY && CE_IsConstImm (L[2]) && CE_IsCallTo (L[3], "addeqysp") && (GetRegInfo (S, I+4, REG_AX) & REG_AX) == 0) { /* Insert new code behind the addeqysp */ const char* Arg; CodeEntry* X; /* ldy #xx-1 */ Arg = MakeHexArg (L[0]->Num-1); X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[0]->LI); CS_InsertEntry (S, X, I+4); /* lda (sp),y */ X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, L[1]->LI); CS_InsertEntry (S, X, I+5); /* ldy #yy */ X = NewCodeEntry (OP65_LDY, AM65_IMM, L[2]->Arg, 0, L[2]->LI); CS_InsertEntry (S, X, I+6); /* clc */ X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, L[3]->LI); CS_InsertEntry (S, X, I+7); /* adc (sp),y */ X = NewCodeEntry (OP65_ADC, AM65_ZP_INDY, "sp", 0, L[3]->LI); CS_InsertEntry (S, X, I+8); /* sta (sp),y */ X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, "sp", 0, L[3]->LI); CS_InsertEntry (S, X, I+9); /* ldy #xx */ X = NewCodeEntry (OP65_LDY, AM65_IMM, L[0]->Arg, 0, L[0]->LI); CS_InsertEntry (S, X, I+10); /* lda (sp),y */ X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, L[1]->LI); CS_InsertEntry (S, X, I+11); /* ldy #yy+1 */ Arg = MakeHexArg (L[2]->Num+1); X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[2]->LI); CS_InsertEntry (S, X, I+12); /* adc (sp),y */ X = NewCodeEntry (OP65_ADC, AM65_ZP_INDY, "sp", 0, L[3]->LI); CS_InsertEntry (S, X, I+13); /* sta (sp),y */ X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, "sp", 0, L[3]->LI); CS_InsertEntry (S, X, I+14); /* Delete the old code */ CS_DelEntries (S, I, 4); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptAdd3 (CodeSeg* S) /* Search for the sequence ** ** jsr pushax ** ldx #$00 ** lda xxx ** jsr tosaddax ** ** and replace it by ** ** clc ** adc xxx ** bcc L1 ** inx ** L1: */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[5]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (CE_IsCallTo (L[0], "pushax") && CS_GetEntries (S, L+1, I+1, 4) && !CS_RangeHasLabel (S, I+1, 3) && L[1]->OPC == OP65_LDX && CE_IsKnownImm (L[1], 0) && L[2]->OPC == OP65_LDA && CE_IsCallTo (L[3], "tosaddax")) { CodeEntry* X; CodeLabel* Label; /* Insert new code behind the sequence */ X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, L[3]->LI); CS_InsertEntry (S, X, I+4); /* adc xxx */ X = NewCodeEntry (OP65_ADC, L[2]->AM, L[2]->Arg, 0, L[3]->LI); CS_InsertEntry (S, X, I+5); /* bcc L1 */ Label = CS_GenLabel (S, L[4]); X = NewCodeEntry (OP65_BCC, AM65_BRA, Label->Name, Label, L[3]->LI); CS_InsertEntry (S, X, I+6); /* inx */ X = NewCodeEntry (OP65_INX, AM65_IMP, 0, 0, L[3]->LI); CS_InsertEntry (S, X, I+7); /* Delete the old code */ CS_DelEntries (S, I, 4); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptAdd4 (CodeSeg* S) /* Search for the sequence ** ** jsr pushax ** lda xxx ** ldx yyy ** jsr tosaddax ** ** and replace it by ** ** clc ** adc xxx ** pha ** txa ** adc yyy ** tax ** pla */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[4]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (CE_IsCallTo (L[0], "pushax") && CS_GetEntries (S, L+1, I+1, 3) && !CS_RangeHasLabel (S, I+1, 3) && L[1]->OPC == OP65_LDA && (L[1]->AM == AM65_ABS || L[1]->AM == AM65_ZP) && L[2]->OPC == OP65_LDX && (L[2]->AM == AM65_ABS || L[2]->AM == AM65_ZP) && CE_IsCallTo (L[3], "tosaddax")) { CodeEntry* X; /* Insert new code behind the sequence */ X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, L[3]->LI); CS_InsertEntry (S, X, I+4); /* adc xxx */ X = NewCodeEntry (OP65_ADC, L[1]->AM, L[1]->Arg, 0, L[3]->LI); CS_InsertEntry (S, X, I+5); /* pha */ X = NewCodeEntry (OP65_PHA, AM65_IMP, 0, 0, L[3]->LI); CS_InsertEntry (S, X, I+6); /* txa */ X = NewCodeEntry (OP65_TXA, AM65_IMP, 0, 0, L[3]->LI); CS_InsertEntry (S, X, I+7); /* adc yyy */ X = NewCodeEntry (OP65_ADC, L[2]->AM, L[2]->Arg, 0, L[3]->LI); CS_InsertEntry (S, X, I+8); /* tax */ X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, L[3]->LI); CS_InsertEntry (S, X, I+9); /* pla */ X = NewCodeEntry (OP65_PLA, AM65_IMP, 0, 0, L[3]->LI); CS_InsertEntry (S, X, I+10); /* Delete the old code */ CS_DelEntries (S, I, 4); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptAdd5 (CodeSeg* S) /* Search for a call to incaxn and replace it by an 8 bit add if the X register ** is not used later. */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* E; /* Get next entry */ E = CS_GetEntry (S, I); /* Check for the sequence */ if (E->OPC == OP65_JSR && strncmp (E->Arg, "incax", 5) == 0 && IsDigit (E->Arg[5]) && E->Arg[6] == '\0' && !RegXUsed (S, I+1)) { CodeEntry* X; const char* Arg; /* Insert new code behind the sequence */ X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, E->LI); CS_InsertEntry (S, X, I+1); Arg = MakeHexArg (E->Arg[5] - '0'); X = NewCodeEntry (OP65_ADC, AM65_IMM, Arg, 0, E->LI); CS_InsertEntry (S, X, I+2); /* Delete the old code */ CS_DelEntry (S, I); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptAdd6 (CodeSeg* S) /* Search for the sequence ** ** adc ... ** bcc L ** inx ** L: ** ** and remove the handling of the high byte if X is not used later. */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[3]; /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check for the sequence */ if (E->OPC == OP65_ADC && CS_GetEntries (S, L, I+1, 3) && (L[0]->OPC == OP65_BCC || L[0]->OPC == OP65_JCC) && L[0]->JumpTo != 0 && !CE_HasLabel (L[0]) && L[1]->OPC == OP65_INX && !CE_HasLabel (L[1]) && L[0]->JumpTo->Owner == L[2] && !RegXUsed (S, I+3)) { /* Remove the bcs/dex */ CS_DelEntries (S, I+1, 2); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/coptadd.h������������������������������������������������������������������������0000664�0000000�0000000�00000010741�13473601511�0015326�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* coptadd.h */ /* */ /* Optimize addition sequences */ /* */ /* */ /* */ /* (C) 2001-2005, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef COPTADD_H #define COPTADD_H /* cc65 */ #include "codeseg.h" /*****************************************************************************/ /* Optimize additions */ /*****************************************************************************/ unsigned OptAdd1 (CodeSeg* S); /* Search for the sequence ** ** jsr pushax ** ldy xxx ** ldx #$00 ** lda (sp),y ** jsr tosaddax ** ** and replace it by: ** ** ldy xxx-2 ** clc ** adc (sp),y ** bcc L ** inx ** L: */ unsigned OptAdd2 (CodeSeg* S); /* Search for the sequence ** ** ldy #xx ** lda (sp),y ** tax ** dey ** lda (sp),y ** ldy #$yy ** jsr addeqysp ** ** and replace it by: ** ** ldy #xx-1 ** lda (sp),y ** ldy #yy ** clc ** adc (sp),y ** sta (sp),y ** ldy #xx ** lda (sp),y ** ldy #yy+1 ** adc (sp),y ** sta (sp),y ** ** provided that a/x is not used later. */ unsigned OptAdd3 (CodeSeg* S); /* Search for the sequence ** ** jsr pushax ** ldx #$00 ** lda xxx ** jsr tosaddax ** ** and replace it by ** ** clc ** adc xxx ** bcc L1 ** inx ** L1: */ unsigned OptAdd4 (CodeSeg* S); /* Search for the sequence ** ** jsr pushax ** lda xxx ** ldx yyy ** jsr tosaddax ** ** and replace it by ** ** clc ** adc xxx ** pha ** txa ** adc yyy ** tax ** pla */ unsigned OptAdd5 (CodeSeg* S); /* Search for a call to incaxn and replace it by an 8 bit add if the X register ** is not used later. */ unsigned OptAdd6 (CodeSeg* S); /* Search for the sequence ** ** adc ... ** bcc L ** inx ** L: ** ** and remove the handling of the high byte if X is not used later. */ /* End of coptadd.h */ #endif �������������������������������cc65-2.18/src/cc65/coptc02.c������������������������������������������������������������������������0000664�0000000�0000000�00000016702�13473601511�0015160�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* coptc02.h */ /* */ /* 65C02 specific optimizations */ /* */ /* */ /* */ /* (C) 2001-2012, Ullrich von Bassewitz */ /* Roeerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* cc65 */ #include "codeent.h" #include "codeinfo.h" #include "error.h" #include "coptc02.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /*****************************************************************************/ /* Helper functions */ /*****************************************************************************/ /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned Opt65C02Ind (CodeSeg* S) /* Try to use the indirect addressing mode where possible */ { unsigned Changes = 0; unsigned I; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check for addressing mode indirect indexed Y where Y is zero. ** Note: All opcodes that are available as (zp),y are also available ** as (zp), so we can ignore the actual opcode here. */ if (E->AM == AM65_ZP_INDY && E->RI->In.RegY == 0) { /* Replace it by indirect addressing mode */ CodeEntry* X = NewCodeEntry (E->OPC, AM65_ZP_IND, E->Arg, 0, E->LI); CS_InsertEntry (S, X, I+1); CS_DelEntry (S, I); /* We had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned Opt65C02BitOps (CodeSeg* S) /* Use special bit op instructions of the C02 */ { unsigned Changes = 0; unsigned I; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[3]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (L[0]->OPC == OP65_LDA && (L[0]->AM == AM65_ZP || L[0]->AM == AM65_ABS) && !CS_RangeHasLabel (S, I+1, 2) && CS_GetEntries (S, L+1, I+1, 2) && (L[1]->OPC == OP65_AND || L[1]->OPC == OP65_ORA) && CE_IsConstImm (L[1]) && L[2]->OPC == OP65_STA && L[2]->AM == L[0]->AM && strcmp (L[2]->Arg, L[0]->Arg) == 0 && !RegAUsed (S, I+3)) { char Buf[32]; CodeEntry* X; /* Use TRB for AND and TSB for ORA */ if (L[1]->OPC == OP65_AND) { /* LDA #XX */ sprintf (Buf, "$%02X", (int) ((~L[1]->Num) & 0xFF)); X = NewCodeEntry (OP65_LDA, AM65_IMM, Buf, 0, L[1]->LI); CS_InsertEntry (S, X, I+3); /* TRB */ X = NewCodeEntry (OP65_TRB, L[0]->AM, L[0]->Arg, 0, L[0]->LI); CS_InsertEntry (S, X, I+4); } else { /* LDA #XX */ sprintf (Buf, "$%02X", (int) L[1]->Num); X = NewCodeEntry (OP65_LDA, AM65_IMM, Buf, 0, L[1]->LI); CS_InsertEntry (S, X, I+3); /* TSB */ X = NewCodeEntry (OP65_TSB, L[0]->AM, L[0]->Arg, 0, L[0]->LI); CS_InsertEntry (S, X, I+4); } /* Delete the old stuff */ CS_DelEntries (S, I, 3); /* We had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned Opt65C02Stores (CodeSeg* S) /* Use STZ where possible */ { unsigned Changes = 0; unsigned I; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check for a store with a register value of zero and an addressing ** mode available with STZ. */ if (((E->OPC == OP65_STA && E->RI->In.RegA == 0) || (E->OPC == OP65_STX && E->RI->In.RegX == 0) || (E->OPC == OP65_STY && E->RI->In.RegY == 0)) && (E->AM == AM65_ZP || E->AM == AM65_ABS || E->AM == AM65_ZPX || E->AM == AM65_ABSX)) { /* Replace by STZ */ CodeEntry* X = NewCodeEntry (OP65_STZ, E->AM, E->Arg, 0, E->LI); CS_InsertEntry (S, X, I+1); /* Delete the old stuff */ CS_DelEntry (S, I); /* We had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } ��������������������������������������������������������������cc65-2.18/src/cc65/coptc02.h������������������������������������������������������������������������0000664�0000000�0000000�00000006136�13473601511�0015165�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* coptc02.h */ /* */ /* 65C02 specific optimizations */ /* */ /* */ /* */ /* (C) 2001-2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef COPTC02_H #define COPTC02_H /* cc65 */ #include "codeseg.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned Opt65C02Ind (CodeSeg* S); /* Try to use the indirect addressing mode where possible */ unsigned Opt65C02BitOps (CodeSeg* S); /* Use special bit op instructions of the C02 */ unsigned Opt65C02Stores (CodeSeg* S); /* Use STZ where possible */ /* End of coptc02.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/coptcmp.c������������������������������������������������������������������������0000664�0000000�0000000�00000073562�13473601511�0015362�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* coptcmp.c */ /* */ /* Optimize compares */ /* */ /* */ /* */ /* (C) 2001-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* cc65 */ #include "codeent.h" #include "codeinfo.h" #include "error.h" #include "coptcmp.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Table used to invert a condition, indexed by condition */ static const unsigned char CmpInvertTab [] = { CMP_NE, CMP_EQ, CMP_LE, CMP_LT, CMP_GE, CMP_GT, CMP_ULE, CMP_ULT, CMP_UGE, CMP_UGT }; /*****************************************************************************/ /* Helper functions */ /*****************************************************************************/ static void ReplaceCmp (CodeSeg* S, unsigned I, cmp_t Cond) /* Helper function for the replacement of routines that return a boolean ** followed by a conditional jump. Instead of the boolean value, the condition ** codes are evaluated directly. ** I is the index of the conditional branch, the sequence is already checked ** to be correct. */ { CodeEntry* N; CodeLabel* L; /* Get the entry */ CodeEntry* E = CS_GetEntry (S, I); /* Replace the conditional branch */ switch (Cond) { case CMP_EQ: CE_ReplaceOPC (E, OP65_JEQ); break; case CMP_NE: CE_ReplaceOPC (E, OP65_JNE); break; case CMP_GT: /* Replace by ** beq @L ** jpl Target ** @L: ... */ if ((N = CS_GetNextEntry (S, I)) == 0) { /* No such entry */ Internal ("Invalid program flow"); } L = CS_GenLabel (S, N); N = NewCodeEntry (OP65_BEQ, AM65_BRA, L->Name, L, E->LI); CS_InsertEntry (S, N, I); CE_ReplaceOPC (E, OP65_JPL); break; case CMP_GE: CE_ReplaceOPC (E, OP65_JPL); break; case CMP_LT: CE_ReplaceOPC (E, OP65_JMI); break; case CMP_LE: /* Replace by ** jmi Target ** jeq Target */ CE_ReplaceOPC (E, OP65_JMI); L = E->JumpTo; N = NewCodeEntry (OP65_JEQ, AM65_BRA, L->Name, L, E->LI); CS_InsertEntry (S, N, I+1); break; case CMP_UGT: /* Replace by ** beq @L ** jcs Target ** @L: ... */ if ((N = CS_GetNextEntry (S, I)) == 0) { /* No such entry */ Internal ("Invalid program flow"); } L = CS_GenLabel (S, N); N = NewCodeEntry (OP65_BEQ, AM65_BRA, L->Name, L, E->LI); CS_InsertEntry (S, N, I); CE_ReplaceOPC (E, OP65_JCS); break; case CMP_UGE: CE_ReplaceOPC (E, OP65_JCS); break; case CMP_ULT: CE_ReplaceOPC (E, OP65_JCC); break; case CMP_ULE: /* Replace by ** jcc Target ** jeq Target */ CE_ReplaceOPC (E, OP65_JCC); L = E->JumpTo; N = NewCodeEntry (OP65_JEQ, AM65_BRA, L->Name, L, E->LI); CS_InsertEntry (S, N, I+1); break; default: Internal ("Unknown jump condition: %d", Cond); } } static int IsImmCmp16 (CodeEntry** L) /* Check if the instructions at L are an immediate compare of a/x: ** ** */ { return (L[0]->OPC == OP65_CPX && L[0]->AM == AM65_IMM && (L[0]->Flags & CEF_NUMARG) != 0 && !CE_HasLabel (L[0]) && (L[1]->OPC == OP65_JNE || L[1]->OPC == OP65_BNE) && L[1]->JumpTo != 0 && !CE_HasLabel (L[1]) && L[2]->OPC == OP65_CMP && L[2]->AM == AM65_IMM && (L[2]->Flags & CEF_NUMARG) != 0 && (L[3]->Info & OF_CBRA) != 0 && L[3]->JumpTo != 0 && (L[1]->JumpTo->Owner == L[3] || L[1]->JumpTo == L[3]->JumpTo)); } static int GetCmpRegVal (const CodeEntry* E) /* Return the register value for an immediate compare */ { switch (E->OPC) { case OP65_CMP: return E->RI->In.RegA; case OP65_CPX: return E->RI->In.RegX; case OP65_CPY: return E->RI->In.RegY; default: Internal ("Invalid opcode in GetCmpRegVal"); return 0; /* Not reached */ } } /*****************************************************************************/ /* Remove calls to the bool transformer subroutines */ /*****************************************************************************/ unsigned OptBoolTrans (CodeSeg* S) /* Try to remove the call to boolean transformer routines where the call is ** not really needed. */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* N; cmp_t Cond; /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check for a boolean transformer */ if (E->OPC == OP65_JSR && (Cond = FindBoolCmpCond (E->Arg)) != CMP_INV && (N = CS_GetNextEntry (S, I)) != 0 && (N->Info & OF_ZBRA) != 0) { /* Make the boolean transformer unnecessary by changing the ** the conditional jump to evaluate the condition flags that ** are set after the compare directly. Note: jeq jumps if ** the condition is not met, jne jumps if the condition is met. ** Invert the code if we jump on condition not met. */ if (GetBranchCond (N->OPC) == BC_EQ) { /* Jumps if condition false, invert condition */ Cond = CmpInvertTab [Cond]; } /* Check if we can replace the code by something better */ ReplaceCmp (S, I+1, Cond); /* Remove the call to the bool transformer */ CS_DelEntry (S, I); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } /*****************************************************************************/ /* Optimizations for compares */ /*****************************************************************************/ unsigned OptCmp1 (CodeSeg* S) /* Search for the sequence ** ** ldx xx ** stx tmp1 ** ora tmp1 ** ** and replace it by ** ** ora xx */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[3]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (L[0]->OPC == OP65_LDX && !CS_RangeHasLabel (S, I+1, 2) && CS_GetEntries (S, L+1, I+1, 2) && L[1]->OPC == OP65_STX && strcmp (L[1]->Arg, "tmp1") == 0 && L[2]->OPC == OP65_ORA && strcmp (L[2]->Arg, "tmp1") == 0) { CodeEntry* X; /* Insert the ora instead */ X = NewCodeEntry (OP65_ORA, L[0]->AM, L[0]->Arg, 0, L[0]->LI); CS_InsertEntry (S, X, I); /* Remove all other instructions */ CS_DelEntries (S, I+1, 3); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptCmp2 (CodeSeg* S) /* Search for the sequence ** ** stx xx ** stx tmp1 ** ora tmp1 ** ** and replace it by ** ** stx xx ** ora xx */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[2]; /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check for the sequence */ if (E->OPC == OP65_STX && !CS_RangeHasLabel (S, I+1, 2) && CS_GetEntries (S, L, I+1, 2) && L[0]->OPC == OP65_STX && strcmp (L[0]->Arg, "tmp1") == 0 && L[1]->OPC == OP65_ORA && strcmp (L[1]->Arg, "tmp1") == 0) { /* Remove the remaining instructions */ CS_DelEntries (S, I+1, 2); /* Insert the ora instead */ CS_InsertEntry (S, NewCodeEntry (OP65_ORA, E->AM, E->Arg, 0, E->LI), I+1); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptCmp3 (CodeSeg* S) /* Search for ** ** lda/and/ora/eor ... ** cmp #$00 ** jeq/jne ** or ** lda/and/ora/eor ... ** cmp #$00 ** jsr boolxx ** ** and remove the cmp. */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[3]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if ((L[0]->OPC == OP65_ADC || L[0]->OPC == OP65_AND || L[0]->OPC == OP65_ASL || L[0]->OPC == OP65_DEA || L[0]->OPC == OP65_EOR || L[0]->OPC == OP65_INA || L[0]->OPC == OP65_LDA || L[0]->OPC == OP65_LSR || L[0]->OPC == OP65_ORA || L[0]->OPC == OP65_PLA || L[0]->OPC == OP65_SBC || L[0]->OPC == OP65_TXA || L[0]->OPC == OP65_TYA) && !CS_RangeHasLabel (S, I+1, 2) && CS_GetEntries (S, L+1, I+1, 2) && L[1]->OPC == OP65_CMP && CE_IsKnownImm (L[1], 0)) { int Delete = 0; /* Check for the call to boolxx. We only remove the compare if ** the carry flag is not evaluated later, because the load will ** not set the carry flag. */ if (L[2]->OPC == OP65_JSR) { switch (FindBoolCmpCond (L[2]->Arg)) { case CMP_EQ: case CMP_NE: case CMP_GT: case CMP_GE: case CMP_LT: case CMP_LE: /* Remove the compare */ Delete = 1; break; case CMP_UGT: case CMP_UGE: case CMP_ULT: case CMP_ULE: case CMP_INV: /* Leave it alone */ break; } } else if ((L[2]->Info & OF_FBRA) != 0) { /* The following insn branches on the condition of the load, ** so the compare instruction might be removed. For safety, ** do some more checks if the carry isn't used later, since ** the compare does set the carry, but the load does not. */ CodeEntry* E; CodeEntry* N; if ((E = CS_GetNextEntry (S, I+2)) != 0 && L[2]->JumpTo != 0 && (N = L[2]->JumpTo->Owner) != 0 && N->OPC != OP65_BCC && N->OPC != OP65_BCS && N->OPC != OP65_JCC && N->OPC != OP65_JCS && (N->OPC != OP65_JSR || FindBoolCmpCond (N->Arg) == CMP_INV)) { /* The following insn branches on the condition of a load, ** and there's no use of the carry flag in sight, so the ** compare instruction can be removed. */ Delete = 1; } } /* Delete the compare if we can */ if (Delete) { CS_DelEntry (S, I+1); ++Changes; } } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptCmp4 (CodeSeg* S) /* Search for ** ** lda x ** ldx y ** cpx #a ** bne L1 ** cmp #b ** L1: jne/jeq L2 ** ** If a is zero, we may remove the compare. If a and b are both zero, we may ** replace it by the sequence ** ** lda x ** ora x+1 ** jne/jeq ... ** ** L1 may be either the label at the branch instruction, or the target label ** of this instruction. */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[5]; /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check for the sequence */ if (E->OPC == OP65_LDA && CS_GetEntries (S, L, I+1, 5) && L[0]->OPC == OP65_LDX && !CE_HasLabel (L[0]) && IsImmCmp16 (L+1) && !RegAXUsed (S, I+6)) { if ((L[4]->Info & OF_FBRA) != 0 && L[1]->Num == 0 && L[3]->Num == 0) { /* The value is zero, we may use the simple code version. */ CE_ReplaceOPC (L[0], OP65_ORA); CS_DelEntries (S, I+2, 3); } else { /* Move the lda instruction after the first branch. This will ** improve speed, since the load is delayed after the first ** test. */ CS_MoveEntry (S, I, I+4); /* We will replace the ldx/cpx by lda/cmp */ CE_ReplaceOPC (L[0], OP65_LDA); CE_ReplaceOPC (L[1], OP65_CMP); /* Beware: If the first LDA instruction had a label, we have ** to move this label to the top of the sequence again. */ if (CE_HasLabel (E)) { CS_MoveLabels (S, E, L[0]); } } ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptCmp5 (CodeSeg* S) /* Optimize compares of local variables: ** ** ldy #o ** jsr ldaxysp ** cpx #a ** bne L1 ** cmp #b ** jne/jeq L2 */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[6]; /* Get the next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (L[0]->OPC == OP65_LDY && CE_IsConstImm (L[0]) && CS_GetEntries (S, L+1, I+1, 5) && !CE_HasLabel (L[1]) && CE_IsCallTo (L[1], "ldaxysp") && IsImmCmp16 (L+2)) { if ((L[5]->Info & OF_FBRA) != 0 && L[2]->Num == 0 && L[4]->Num == 0) { CodeEntry* X; char Buf[20]; /* The value is zero, we may use the simple code version: ** ldy #o-1 ** lda (sp),y ** ldy #o ** ora (sp),y ** jne/jeq ... */ sprintf (Buf, "$%02X", (int)(L[0]->Num-1)); X = NewCodeEntry (OP65_LDY, AM65_IMM, Buf, 0, L[0]->LI); CS_InsertEntry (S, X, I+1); X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, L[1]->LI); CS_InsertEntry (S, X, I+2); X = NewCodeEntry (OP65_LDY, AM65_IMM, L[0]->Arg, 0, L[0]->LI); CS_InsertEntry (S, X, I+3); X = NewCodeEntry (OP65_ORA, AM65_ZP_INDY, "sp", 0, L[1]->LI); CS_InsertEntry (S, X, I+4); CS_DelEntries (S, I+5, 3); /* cpx/bne/cmp */ CS_DelEntry (S, I); /* ldy */ } else { CodeEntry* X; char Buf[20]; /* Change the code to just use the A register. Move the load ** of the low byte after the first branch if possible: ** ** ldy #o ** lda (sp),y ** cmp #a ** bne L1 ** ldy #o-1 ** lda (sp),y ** cmp #b ** jne/jeq ... */ X = NewCodeEntry (OP65_LDY, AM65_IMM, L[0]->Arg, 0, L[0]->LI); CS_InsertEntry (S, X, I+3); X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, L[1]->LI); CS_InsertEntry (S, X, I+4); X = NewCodeEntry (OP65_CMP, L[2]->AM, L[2]->Arg, 0, L[2]->LI); CS_InsertEntry (S, X, I+5); sprintf (Buf, "$%02X", (int)(L[0]->Num-1)); X = NewCodeEntry (OP65_LDY, AM65_IMM, Buf, 0, L[0]->LI); CS_InsertEntry (S, X, I+7); X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, L[1]->LI); CS_InsertEntry (S, X, I+8); CS_DelEntries (S, I, 3); /* ldy/jsr/cpx */ } ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptCmp6 (CodeSeg* S) /* Search for calls to compare subroutines followed by a conditional branch ** and replace them by cheaper versions, since the branch means that the ** boolean value returned by these routines is not needed (we may also check ** that explicitly, but for the current code generator it is always true). */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* N; cmp_t Cond; /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check for the sequence */ if (E->OPC == OP65_JSR && (Cond = FindTosCmpCond (E->Arg)) != CMP_INV && (N = CS_GetNextEntry (S, I)) != 0 && (N->Info & OF_ZBRA) != 0 && !CE_HasLabel (N)) { /* The tos... functions will return a boolean value in a/x and ** the Z flag says if this value is zero or not. We will call ** a cheaper subroutine instead, one that does not return a ** boolean value but only valid flags. Note: jeq jumps if ** the condition is not met, jne jumps if the condition is met. ** Invert the code if we jump on condition not met. */ if (GetBranchCond (N->OPC) == BC_EQ) { /* Jumps if condition false, invert condition */ Cond = CmpInvertTab [Cond]; } /* Replace the subroutine call. */ E = NewCodeEntry (OP65_JSR, AM65_ABS, "tosicmp", 0, E->LI); CS_InsertEntry (S, E, I+1); CS_DelEntry (S, I); /* Replace the conditional branch */ ReplaceCmp (S, I+1, Cond); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptCmp7 (CodeSeg* S) /* Search for a sequence ldx/txa/branch and remove the txa if A is not ** used later. */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[2]; /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check for the sequence */ if ((E->OPC == OP65_LDX) && CS_GetEntries (S, L, I+1, 2) && L[0]->OPC == OP65_TXA && !CE_HasLabel (L[0]) && (L[1]->Info & OF_FBRA) != 0 && !CE_HasLabel (L[1]) && !RegAUsed (S, I+3)) { /* Remove the txa */ CS_DelEntry (S, I+1); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptCmp8 (CodeSeg* S) /* Check for register compares where the contents of the register and therefore ** the result of the compare is known. */ { unsigned Changes = 0; unsigned I; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { int RegVal; /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check for a compare against an immediate value */ if ((E->Info & OF_CMP) != 0 && (RegVal = GetCmpRegVal (E)) >= 0 && CE_IsConstImm (E)) { /* We are able to evaluate the compare at compile time. Check if ** one or more branches are ahead. */ unsigned ProtectCompare = 0; unsigned JumpsChanged = 0; CodeEntry* N; while ((N = CS_GetNextEntry (S, I)) != 0 && /* Followed by something.. */ (N->Info & OF_CBRA) != 0 && /* ..that is a cond branch.. */ !CE_HasLabel (N)) { /* ..and has no label */ /* Evaluate the branch condition */ int Cond; switch (GetBranchCond (N->OPC)) { case BC_CC: Cond = ((unsigned char)RegVal) < ((unsigned char)E->Num); break; case BC_CS: Cond = ((unsigned char)RegVal) >= ((unsigned char)E->Num); break; case BC_EQ: Cond = ((unsigned char)RegVal) == ((unsigned char)E->Num); break; case BC_MI: Cond = ((signed char)RegVal) < ((signed char)E->Num); break; case BC_NE: Cond = ((unsigned char)RegVal) != ((unsigned char)E->Num); break; case BC_PL: Cond = ((signed char)RegVal) >= ((signed char)E->Num); break; case BC_VC: case BC_VS: /* Not set by the compare operation, bail out (Note: ** Just skipping anything here is rather stupid, but ** the sequence is never generated by the compiler, ** so it's quite safe to skip). */ goto NextEntry; default: Internal ("Unknown branch condition"); } /* If the condition is false, we may remove the jump. Otherwise ** the branch will always be taken, so we may replace it by a ** jump (and bail out). */ if (!Cond) { CS_DelEntry (S, I+1); } else { CodeLabel* L = N->JumpTo; const char* LabelName = L? L->Name : N->Arg; CodeEntry* X = NewCodeEntry (OP65_JMP, AM65_BRA, LabelName, L, N->LI); CS_InsertEntry (S, X, I+2); CS_DelEntry (S, I+1); /* Normally we can remove the compare as well, ** but some comparisons generate code with a ** shared branch operation. This prevents the unsafe ** removal of the compare for known problem cases. */ if ( /* Jump to branch that relies on the comparison. */ (L->Owner->Info & (OF_CBRA | OF_ZBRA)) || /* Jump to boolean transformer that relies on the comparison. */ (L->Owner->OPC == OP65_JSR && (FindBoolCmpCond (L->Owner->Arg)) != CMP_INV) ) { ++ProtectCompare; } } /* Remember, we had changes */ ++JumpsChanged; ++Changes; } /* Delete the original compare, if safe to do so. */ if (JumpsChanged && !ProtectCompare) { CS_DelEntry (S, I); } } NextEntry: /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptCmp9 (CodeSeg* S) /* Search for the sequence ** ** sbc xx ** bvs/bvc L ** eor #$80 ** L: asl a ** bcc/bcs somewhere ** ** If A is not used later (which should be the case), we can branch on the N ** flag instead of the carry flag and remove the asl. */ { unsigned Changes = 0; unsigned I; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[5]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (L[0]->OPC == OP65_SBC && CS_GetEntries (S, L+1, I+1, 4) && (L[1]->OPC == OP65_BVC || L[1]->OPC == OP65_BVS) && L[1]->JumpTo != 0 && L[1]->JumpTo->Owner == L[3] && L[2]->OPC == OP65_EOR && CE_IsKnownImm (L[2], 0x80) && L[3]->OPC == OP65_ASL && L[3]->AM == AM65_ACC && (L[4]->OPC == OP65_BCC || L[4]->OPC == OP65_BCS || L[4]->OPC == OP65_JCC || L[4]->OPC == OP65_JCS) && !CE_HasLabel (L[4]) && !RegAUsed (S, I+4)) { /* Replace the branch condition */ switch (GetBranchCond (L[4]->OPC)) { case BC_CC: CE_ReplaceOPC (L[4], OP65_JPL); break; case BC_CS: CE_ReplaceOPC (L[4], OP65_JMI); break; default: Internal ("Unknown branch condition in OptCmp9"); } /* Delete the asl insn */ CS_DelEntry (S, I+3); /* Next sequence is somewhat ahead (if any) */ I += 3; /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } ����������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/coptcmp.h������������������������������������������������������������������������0000664�0000000�0000000�00000012527�13473601511�0015361�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* coptcmp.h */ /* */ /* Optimize compares */ /* */ /* */ /* */ /* (C) 2001-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef COPTCMP_H #define COPTCMP_H /* cc65 */ #include "codeseg.h" /*****************************************************************************/ /* Remove calls to the bool transformer subroutines */ /*****************************************************************************/ unsigned OptBoolTrans (CodeSeg* S); /* Try to remove the call to boolean transformer routines where the call is ** not really needed. */ /*****************************************************************************/ /* Optimizations for compares */ /*****************************************************************************/ unsigned OptCmp1 (CodeSeg* S); /* Search for the sequence ** ** ldx xx ** stx tmp1 ** ora tmp1 ** ** and replace it by ** ** ora xx */ unsigned OptCmp2 (CodeSeg* S); /* Search for the sequence ** ** stx xx ** stx tmp1 ** ora tmp1 ** ** and replace it by ** ** stx xx ** ora xx */ unsigned OptCmp3 (CodeSeg* S); /* Search for ** ** lda/and/ora/eor ... ** cmp #$00 ** jeq/jne ** or ** lda/and/ora/eor ... ** cmp #$00 ** jsr boolxx ** ** and remove the cmp. */ unsigned OptCmp4 (CodeSeg* S); /* Search for ** ** lda x ** ldx y ** cpx #a ** bne L1 ** cmp #b ** jne/jeq L2 ** ** If a is zero, we may remove the compare. If a and b are both zero, we may ** replace it by the sequence ** ** lda x ** ora x+1 ** jne/jeq ... ** ** L1 may be either the label at the branch instruction, or the target label ** of this instruction. */ unsigned OptCmp5 (CodeSeg* S); /* Optimize compares of local variables: ** ** ldy #o ** lda (sp),y ** tax ** dey ** lda (sp),y ** cpx #a ** bne L1 ** cmp #b ** jne/jeq L2 */ unsigned OptCmp6 (CodeSeg* S); /* Search for calls to compare subroutines followed by a conditional branch ** and replace them by cheaper versions, since the branch means that the ** boolean value returned by these routines is not needed (we may also check ** that explicitly, but for the current code generator it is always true). */ unsigned OptCmp7 (CodeSeg* S); /* Search for a sequence ldx/txa/branch and remove the txa if A is not ** used later. */ unsigned OptCmp8 (CodeSeg* S); /* Check for register compares where the contents of the register and therefore ** the result of the compare is known. */ unsigned OptCmp9 (CodeSeg* S); /* Search for the sequence ** ** sbc xx ** bvs/bvc L ** eor #$80 ** L: asl a ** bcc/bcs somewhere ** ** If A is not used later (which should be the case), we can branch on the N ** flag instead of the carry flag and remove the asl. */ /* End of coptcmp.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/coptind.c������������������������������������������������������������������������0000664�0000000�0000000�00000222407�13473601511�0015347�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* coptind.c */ /* */ /* Environment independent low level optimizations */ /* */ /* */ /* */ /* (C) 2001-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "cpu.h" /* cc65 */ #include "codeent.h" #include "coptind.h" #include "codeinfo.h" #include "codeopt.h" #include "error.h" /*****************************************************************************/ /* Helper functions */ /*****************************************************************************/ static int MemAccess (CodeSeg* S, unsigned From, unsigned To, const CodeEntry* N) /* Checks a range of code entries if there are any memory accesses to N->Arg */ { /* Get the length of the argument */ unsigned NLen = strlen (N->Arg); /* What to check for? */ enum { None = 0x00, Base = 0x01, /* Check for location without "+1" */ Word = 0x02, /* Check for location with "+1" added */ } What = None; /* If the argument of N is a zero page location that ends with "+1", we ** must also check for word accesses to the location without +1. */ if (N->AM == AM65_ZP && NLen > 2 && strcmp (N->Arg + NLen - 2, "+1") == 0) { What |= Base; } /* If the argument is zero page indirect, we must also check for accesses ** to "arg+1" */ if (N->AM == AM65_ZP_INDY || N->AM == AM65_ZPX_IND || N->AM == AM65_ZP_IND) { What |= Word; } /* Walk over all code entries */ while (From <= To) { /* Get the next entry */ CodeEntry* E = CS_GetEntry (S, From); /* Check if there is an argument and if this argument equals Arg in ** some variants. */ if (E->Arg[0] != '\0') { unsigned ELen; if (strcmp (E->Arg, N->Arg) == 0) { /* Found an access */ return 1; } ELen = strlen (E->Arg); if ((What & Base) != 0) { if (ELen == NLen - 2 && strncmp (E->Arg, N->Arg, NLen-2) == 0) { /* Found an access */ return 1; } } if ((What & Word) != 0) { if (ELen == NLen + 2 && strncmp (E->Arg, N->Arg, NLen) == 0 && E->Arg[NLen] == '+' && E->Arg[NLen+1] == '1') { /* Found an access */ return 1; } } } /* Next entry */ ++From; } /* Nothing found */ return 0; } static int GetBranchDist (CodeSeg* S, unsigned From, CodeEntry* To) /* Get the branch distance between the two entries and return it. The distance ** will be negative for backward jumps and positive for forward jumps. */ { /* Get the index of the branch target */ unsigned TI = CS_GetEntryIndex (S, To); /* Determine the branch distance */ int Distance = 0; if (TI >= From) { /* Forward branch, do not count the current insn */ unsigned J = From+1; while (J < TI) { CodeEntry* N = CS_GetEntry (S, J++); Distance += N->Size; } } else { /* Backward branch */ unsigned J = TI; while (J < From) { CodeEntry* N = CS_GetEntry (S, J++); Distance -= N->Size; } } /* Return the calculated distance */ return Distance; } static int IsShortDist (int Distance) /* Return true if the given distance is a short branch distance */ { return (Distance >= -125 && Distance <= 125); } static short ZPRegVal (unsigned short Use, const RegContents* RC) /* Return the contents of the given zeropage register */ { if ((Use & REG_TMP1) != 0) { return RC->Tmp1; } else if ((Use & REG_PTR1_LO) != 0) { return RC->Ptr1Lo; } else if ((Use & REG_PTR1_HI) != 0) { return RC->Ptr1Hi; } else if ((Use & REG_SREG_LO) != 0) { return RC->SRegLo; } else if ((Use & REG_SREG_HI) != 0) { return RC->SRegHi; } else { return UNKNOWN_REGVAL; } } static short RegVal (unsigned short Use, const RegContents* RC) /* Return the contents of the given register */ { if ((Use & REG_A) != 0) { return RC->RegA; } else if ((Use & REG_X) != 0) { return RC->RegX; } else if ((Use & REG_Y) != 0) { return RC->RegY; } else { return ZPRegVal (Use, RC); } } /*****************************************************************************/ /* Replace jumps to RTS by RTS */ /*****************************************************************************/ unsigned OptRTSJumps1 (CodeSeg* S) /* Replace jumps to RTS by RTS */ { unsigned Changes = 0; /* Walk over all entries minus the last one */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { /* Get the next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if it's an unconditional branch to a local target */ if ((E->Info & OF_UBRA) != 0 && E->JumpTo != 0 && E->JumpTo->Owner->OPC == OP65_RTS) { /* Insert an RTS instruction */ CodeEntry* X = NewCodeEntry (OP65_RTS, AM65_IMP, 0, 0, E->LI); CS_InsertEntry (S, X, I+1); /* Delete the jump */ CS_DelEntry (S, I); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptRTSJumps2 (CodeSeg* S) /* Replace long conditional jumps to RTS or to a final target */ { unsigned Changes = 0; /* Walk over all entries minus the last one */ unsigned I = 0; while (I < CS_GetEntryCount (S) - 1) { /* Get the next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if it's an conditional branch to a local target */ if ((E->Info & OF_CBRA) != 0 && /* Conditional branch */ (E->Info & OF_LBRA) != 0 && /* Long branch */ E->JumpTo != 0) { /* Local label */ /* Get the jump target and the next entry. There's always a next ** entry, because we don't cover the last entry in the loop. */ CodeEntry* X = 0; CodeEntry* T = E->JumpTo->Owner; CodeEntry* N = CS_GetNextEntry (S, I); /* Check if it's a jump to an RTS insn */ if (T->OPC == OP65_RTS) { /* It's a jump to RTS. Create a conditional branch around an ** RTS insn. */ X = NewCodeEntry (OP65_RTS, AM65_IMP, 0, 0, T->LI); } else if (T->OPC == OP65_JMP && T->JumpTo == 0) { /* It's a jump to a label outside the function. Create a ** conditional branch around a jump to the external label. */ X = NewCodeEntry (OP65_JMP, AM65_ABS, T->Arg, T->JumpTo, T->LI); } /* If we have a replacement insn, insert it */ if (X) { CodeLabel* LN; opc_t NewBranch; /* Insert the new insn */ CS_InsertEntry (S, X, I+1); /* Create a conditional branch with the inverse condition ** around the replacement insn */ /* Get the new branch opcode */ NewBranch = MakeShortBranch (GetInverseBranch (E->OPC)); /* Get the label attached to N, create a new one if needed */ LN = CS_GenLabel (S, N); /* Generate the branch */ X = NewCodeEntry (NewBranch, AM65_BRA, LN->Name, LN, E->LI); CS_InsertEntry (S, X, I+1); /* Delete the long branch */ CS_DelEntry (S, I); /* Remember, we had changes */ ++Changes; } } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } /*****************************************************************************/ /* Remove dead jumps */ /*****************************************************************************/ unsigned OptDeadJumps (CodeSeg* S) /* Remove dead jumps (jumps to the next instruction) */ { unsigned Changes = 0; /* Walk over all entries minus the last one */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { /* Get the next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if it's a branch, if it has a local target, and if the target ** is the next instruction. */ if (E->AM == AM65_BRA && E->JumpTo && E->JumpTo->Owner == CS_GetNextEntry (S, I)) { /* Delete the dead jump */ CS_DelEntry (S, I); /* Remember, we had changes */ ++Changes; } else { /* Next entry */ ++I; } } /* Return the number of changes made */ return Changes; } /*****************************************************************************/ /* Remove dead code */ /*****************************************************************************/ unsigned OptDeadCode (CodeSeg* S) /* Remove dead code (code that follows an unconditional jump or an rts/rti ** and has no label) */ { unsigned Changes = 0; /* Walk over all entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* N; CodeLabel* LN; /* Get this entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if it's an unconditional branch, and if the next entry has ** no labels attached, or if the label is just used so that the insn ** can jump to itself. */ if ((E->Info & OF_DEAD) != 0 && /* Dead code follows */ (N = CS_GetNextEntry (S, I)) != 0 && /* Has next entry */ (!CE_HasLabel (N) || /* Don't has a label */ ((N->Info & OF_UBRA) != 0 && /* Uncond branch */ (LN = N->JumpTo) != 0 && /* Jumps to known label */ LN->Owner == N && /* Attached to insn */ CL_GetRefCount (LN) == 1))) { /* Only reference */ /* Delete the next entry */ CS_DelEntry (S, I+1); /* Remember, we had changes */ ++Changes; } else { /* Next entry */ ++I; } } /* Return the number of changes made */ return Changes; } /*****************************************************************************/ /* Optimize jump cascades */ /*****************************************************************************/ unsigned OptJumpCascades (CodeSeg* S) /* Optimize jump cascades (jumps to jumps). In such a case, the jump is ** replaced by a jump to the final location. This will in some cases produce ** worse code, because some jump targets are no longer reachable by short ** branches, but this is quite rare, so there are more advantages than ** disadvantages. */ { unsigned Changes = 0; /* Walk over all entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* N; CodeLabel* OldLabel; /* Get this entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check: ** - if it's a branch, ** - if it has a jump label, ** - if this jump label is not attached to the instruction itself, ** - if the target instruction is itself a branch, ** - if either the first branch is unconditional or the target of ** the second branch is internal to the function. ** The latter condition will avoid conditional branches to targets ** outside of the function (usually incspx), which won't simplify the ** code, since conditional far branches are emulated by a short branch ** around a jump. */ if ((E->Info & OF_BRA) != 0 && (OldLabel = E->JumpTo) != 0 && (N = OldLabel->Owner) != E && (N->Info & OF_BRA) != 0 && ((E->Info & OF_CBRA) == 0 || N->JumpTo != 0)) { /* Check if we can use the final target label. That is the case, ** if the target branch is an absolute branch; or, if it is a ** conditional branch checking the same condition as the first one. */ if ((N->Info & OF_UBRA) != 0 || ((E->Info & OF_CBRA) != 0 && GetBranchCond (E->OPC) == GetBranchCond (N->OPC))) { /* This is a jump cascade and we may jump to the final target, ** provided that the other insn does not jump to itself. If ** this is the case, we can also jump to ourselves, otherwise ** insert a jump to the new instruction and remove the old one. */ CodeEntry* X; CodeLabel* LN = N->JumpTo; if (LN != 0 && LN->Owner == N) { /* We found a jump to a jump to itself. Replace our jump ** by a jump to itself. */ CodeLabel* LE = CS_GenLabel (S, E); X = NewCodeEntry (E->OPC, E->AM, LE->Name, LE, E->LI); } else { /* Jump to the final jump target */ X = NewCodeEntry (E->OPC, E->AM, N->Arg, N->JumpTo, E->LI); } /* Insert it behind E */ CS_InsertEntry (S, X, I+1); /* Remove E */ CS_DelEntry (S, I); /* Remember, we had changes */ ++Changes; /* Check if both are conditional branches, and the condition of ** the second is the inverse of that of the first. In this case, ** the second branch will never be taken, and we may jump directly ** to the instruction behind this one. */ } else if ((E->Info & OF_CBRA) != 0 && (N->Info & OF_CBRA) != 0) { CodeEntry* X; /* Instruction behind N */ CodeLabel* LX; /* Label attached to X */ /* Get the branch conditions of both branches */ bc_t BC1 = GetBranchCond (E->OPC); bc_t BC2 = GetBranchCond (N->OPC); /* Check the branch conditions */ if (BC1 != GetInverseCond (BC2)) { /* Condition not met */ goto NextEntry; } /* We may jump behind this conditional branch. Get the ** pointer to the next instruction */ if ((X = CS_GetNextEntry (S, CS_GetEntryIndex (S, N))) == 0) { /* N is the last entry, bail out */ goto NextEntry; } /* Get the label attached to X, create a new one if needed */ LX = CS_GenLabel (S, X); /* Move the reference from E to the new label */ CS_MoveLabelRef (S, E, LX); /* Remember, we had changes */ ++Changes; } } NextEntry: /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } /*****************************************************************************/ /* Optimize jsr/rts */ /*****************************************************************************/ unsigned OptRTS (CodeSeg* S) /* Optimize subroutine calls followed by an RTS. The subroutine call will get ** replaced by a jump. Don't bother to delete the RTS if it does not have a ** label, the dead code elimination should take care of it. */ { unsigned Changes = 0; /* Walk over all entries minus the last one */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* N; /* Get this entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if it's a subroutine call and if the following insn is RTS */ if (E->OPC == OP65_JSR && (N = CS_GetNextEntry (S, I)) != 0 && N->OPC == OP65_RTS) { /* Change the jsr to a jmp and use the additional info for a jump */ E->AM = AM65_BRA; CE_ReplaceOPC (E, OP65_JMP); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } /*****************************************************************************/ /* Optimize jump targets */ /*****************************************************************************/ unsigned OptJumpTarget1 (CodeSeg* S) /* If the instruction preceeding an unconditional branch is the same as the ** instruction preceeding the jump target, the jump target may be moved ** one entry back. This is a size optimization, since the instruction before ** the branch gets removed. */ { unsigned Changes = 0; CodeEntry* E1; /* Entry 1 */ CodeEntry* E2; /* Entry 2 */ CodeEntry* T1; /* Jump target entry 1 */ CodeLabel* TL1; /* Target label 1 */ /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { /* Get next entry */ E2 = CS_GetNextEntry (S, I); /* Check if we have a jump or branch without a label attached, and ** a jump target, which is not attached to the jump itself */ if (E2 != 0 && (E2->Info & OF_UBRA) != 0 && !CE_HasLabel (E2) && E2->JumpTo && E2->JumpTo->Owner != E2) { /* Get the entry preceeding the branch target */ T1 = CS_GetPrevEntry (S, CS_GetEntryIndex (S, E2->JumpTo->Owner)); if (T1 == 0) { /* There is no such entry */ goto NextEntry; } /* The entry preceeding the branch target may not be the branch ** insn. */ if (T1 == E2) { goto NextEntry; } /* Get the entry preceeding the jump */ E1 = CS_GetEntry (S, I); /* Check if both preceeding instructions are identical */ if (!CodeEntriesAreEqual (E1, T1)) { /* Not equal, try next */ goto NextEntry; } /* Get the label for the instruction preceeding the jump target. ** This routine will create a new label if the instruction does ** not already have one. */ TL1 = CS_GenLabel (S, T1); /* Change the jump target to point to this new label */ CS_MoveLabelRef (S, E2, TL1); /* If the instruction preceeding the jump has labels attached, ** move references to this label to the new label. */ if (CE_HasLabel (E1)) { CS_MoveLabels (S, E1, T1); } /* Remove the entry preceeding the jump */ CS_DelEntry (S, I); /* Remember, we had changes */ ++Changes; } else { NextEntry: /* Next entry */ ++I; } } /* Return the number of changes made */ return Changes; } unsigned OptJumpTarget2 (CodeSeg* S) /* If a bcs jumps to a sec insn or a bcc jumps to clc, skip this insn, since ** it's job is already done. */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { /* OP that may be skipped */ opc_t OPC; /* Jump target insn, old and new */ CodeEntry* T; CodeEntry* N; /* New jump label */ CodeLabel* L; /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if this is a bcc insn */ if (E->OPC == OP65_BCC || E->OPC == OP65_JCC) { OPC = OP65_CLC; } else if (E->OPC == OP65_BCS || E->OPC == OP65_JCS) { OPC = OP65_SEC; } else { /* Not what we're looking for */ goto NextEntry; } /* Must have a jump target */ if (E->JumpTo == 0) { goto NextEntry; } /* Get the owner insn of the jump target and check if it's the one, we ** will skip if present. */ T = E->JumpTo->Owner; if (T->OPC != OPC) { goto NextEntry; } /* Get the entry following the branch target */ N = CS_GetNextEntry (S, CS_GetEntryIndex (S, T)); if (N == 0) { /* There is no such entry */ goto NextEntry; } /* Get the label for the instruction following the jump target. ** This routine will create a new label if the instruction does ** not already have one. */ L = CS_GenLabel (S, N); /* Change the jump target to point to this new label */ CS_MoveLabelRef (S, E, L); /* Remember that we had changes */ ++Changes; NextEntry: /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptJumpTarget3 (CodeSeg* S) /* Jumps to load instructions of a register, that do already have the matching ** register contents may skip the load instruction, since it's job is already ** done. */ { unsigned Changes = 0; unsigned I; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* N; /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if this is a load insn with a label and the next insn is not ** a conditional branch that needs the flags from the load. */ if ((E->Info & OF_LOAD) != 0 && CE_IsConstImm (E) && CE_HasLabel (E) && (N = CS_GetNextEntry (S, I)) != 0 && !CE_UseLoadFlags (N)) { unsigned J; int K; /* New jump label */ CodeLabel* LN = 0; /* Walk over all insn that jump here */ for (J = 0; J < CE_GetLabelCount (E); ++J) { /* Get the label */ CodeLabel* L = CE_GetLabel (E, J); /* Loop over all insn that reference this label. Since we may ** eventually remove a reference in the loop, we must loop ** from end down to start. */ for (K = CL_GetRefCount (L) - 1; K >= 0; --K) { /* Get the entry that jumps here */ CodeEntry* Jump = CL_GetRef (L, K); /* Get the register info from this insn */ short Val = RegVal (E->Chg, &Jump->RI->Out2); /* Check if the outgoing value is the one thats's loaded */ if (Val == (unsigned char) E->Num) { /* OK, skip the insn. First, generate a label for the ** next insn after E. */ if (LN == 0) { LN = CS_GenLabel (S, N); } /* Change the jump target to point to this new label */ CS_MoveLabelRef (S, Jump, LN); /* Remember that we had changes */ ++Changes; } } } } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } /*****************************************************************************/ /* Optimize conditional branches */ /*****************************************************************************/ unsigned OptCondBranches1 (CodeSeg* S) /* Performs several optimization steps: ** ** - If an immediate load of a register is followed by a conditional jump that ** is never taken because the load of the register sets the flags in such a ** manner, remove the conditional branch. ** - If the conditional branch is always taken because of the register load, ** replace it by a jmp. ** - If a conditional branch jumps around an unconditional branch, remove the ** conditional branch and make the jump a conditional branch with the ** inverse condition of the first one. */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* N; CodeLabel* L; /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if it's a register load */ if ((E->Info & OF_LOAD) != 0 && /* It's a load instruction */ E->AM == AM65_IMM && /* ..with immidiate addressing */ (E->Flags & CEF_NUMARG) != 0 && /* ..and a numeric argument. */ (N = CS_GetNextEntry (S, I)) != 0 && /* There is a following entry */ (N->Info & OF_CBRA) != 0 && /* ..which is a conditional branch */ !CE_HasLabel (N)) { /* ..and does not have a label */ /* Get the branch condition */ bc_t BC = GetBranchCond (N->OPC); /* Check the argument against the branch condition */ if ((BC == BC_EQ && E->Num != 0) || (BC == BC_NE && E->Num == 0) || (BC == BC_PL && (E->Num & 0x80) != 0) || (BC == BC_MI && (E->Num & 0x80) == 0)) { /* Remove the conditional branch */ CS_DelEntry (S, I+1); /* Remember, we had changes */ ++Changes; } else if ((BC == BC_EQ && E->Num == 0) || (BC == BC_NE && E->Num != 0) || (BC == BC_PL && (E->Num & 0x80) == 0) || (BC == BC_MI && (E->Num & 0x80) != 0)) { /* The branch is always taken, replace it by a jump */ CE_ReplaceOPC (N, OP65_JMP); /* Remember, we had changes */ ++Changes; } } if ((E->Info & OF_CBRA) != 0 && /* It's a conditional branch */ (L = E->JumpTo) != 0 && /* ..referencing a local label */ (N = CS_GetNextEntry (S, I)) != 0 && /* There is a following entry */ (N->Info & OF_UBRA) != 0 && /* ..which is an uncond branch, */ !CE_HasLabel (N) && /* ..has no label attached */ L->Owner == CS_GetNextEntry (S, I+1)) { /* ..and jump target follows */ /* Replace the jump by a conditional branch with the inverse branch ** condition than the branch around it. */ CE_ReplaceOPC (N, GetInverseBranch (E->OPC)); /* Remove the conditional branch */ CS_DelEntry (S, I); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptCondBranches2 (CodeSeg* S) /* If on entry to a "rol a" instruction the accu is zero, and a beq/bne follows, ** we can remove the rol and branch on the state of the carry flag. */ { unsigned Changes = 0; unsigned I; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* N; /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if it's a rol insn with A in accu and a branch follows */ if (E->OPC == OP65_ROL && E->AM == AM65_ACC && E->RI->In.RegA == 0 && !CE_HasLabel (E) && (N = CS_GetNextEntry (S, I)) != 0 && (N->Info & OF_ZBRA) != 0 && !RegAUsed (S, I+1)) { /* Replace the branch condition */ switch (GetBranchCond (N->OPC)) { case BC_EQ: CE_ReplaceOPC (N, OP65_JCC); break; case BC_NE: CE_ReplaceOPC (N, OP65_JCS); break; default: Internal ("Unknown branch condition in OptCondBranches2"); } /* Delete the rol insn */ CS_DelEntry (S, I); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } /*****************************************************************************/ /* Remove unused loads and stores */ /*****************************************************************************/ unsigned OptUnusedLoads (CodeSeg* S) /* Remove loads of registers where the value loaded is not used later. */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* N; /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if it's a register load or transfer insn */ if ((E->Info & (OF_LOAD | OF_XFR | OF_REG_INCDEC)) != 0 && (N = CS_GetNextEntry (S, I)) != 0 && !CE_UseLoadFlags (N)) { /* Check which sort of load or transfer it is */ unsigned R; switch (E->OPC) { case OP65_DEA: case OP65_INA: case OP65_LDA: case OP65_TXA: case OP65_TYA: R = REG_A; break; case OP65_DEX: case OP65_INX: case OP65_LDX: case OP65_TAX: R = REG_X; break; case OP65_DEY: case OP65_INY: case OP65_LDY: case OP65_TAY: R = REG_Y; break; default: goto NextEntry; /* OOPS */ } /* Get register usage and check if the register value is used later */ if ((GetRegInfo (S, I+1, R) & R) == 0) { /* Register value is not used, remove the load */ CS_DelEntry (S, I); /* Remember, we had changes. Account the deleted entry in I. */ ++Changes; --I; } } NextEntry: /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptUnusedStores (CodeSeg* S) /* Remove stores into zero page registers that aren't used later */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if it's a register load or transfer insn */ if ((E->Info & OF_STORE) != 0 && E->AM == AM65_ZP && (E->Chg & REG_ZP) != 0) { /* Check for the zero page location. We know that there cannot be ** more than one zero page location involved in the store. */ unsigned R = E->Chg & REG_ZP; /* Get register usage and check if the register value is used later */ if ((GetRegInfo (S, I+1, R) & R) == 0) { /* Register value is not used, remove the load */ CS_DelEntry (S, I); /* Remember, we had changes */ ++Changes; /* Continue with next insn */ continue; } } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptDupLoads (CodeSeg* S) /* Remove loads of registers where the value loaded is already in the register. */ { unsigned Changes = 0; unsigned I; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* N; /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Assume we won't delete the entry */ int Delete = 0; /* Get a pointer to the input registers of the insn */ const RegContents* In = &E->RI->In; /* Handle the different instructions */ switch (E->OPC) { case OP65_LDA: if (RegValIsKnown (In->RegA) && /* Value of A is known */ CE_IsKnownImm (E, In->RegA) && /* Value to be loaded is known */ (N = CS_GetNextEntry (S, I)) != 0 && /* There is a next entry */ !CE_UseLoadFlags (N)) { /* Which does not use the flags */ Delete = 1; } break; case OP65_LDX: if (RegValIsKnown (In->RegX) && /* Value of X is known */ CE_IsKnownImm (E, In->RegX) && /* Value to be loaded is known */ (N = CS_GetNextEntry (S, I)) != 0 && /* There is a next entry */ !CE_UseLoadFlags (N)) { /* Which does not use the flags */ Delete = 1; } break; case OP65_LDY: if (RegValIsKnown (In->RegY) && /* Value of Y is known */ CE_IsKnownImm (E, In->RegY) && /* Value to be loaded is known */ (N = CS_GetNextEntry (S, I)) != 0 && /* There is a next entry */ !CE_UseLoadFlags (N)) { /* Which does not use the flags */ Delete = 1; } break; case OP65_STA: /* If we store into a known zero page location, and this ** location does already contain the value to be stored, ** remove the store. */ if (RegValIsKnown (In->RegA) && /* Value of A is known */ E->AM == AM65_ZP && /* Store into zp */ In->RegA == ZPRegVal (E->Chg, In)) { /* Value identical */ Delete = 1; } break; case OP65_STX: /* If we store into a known zero page location, and this ** location does already contain the value to be stored, ** remove the store. */ if (RegValIsKnown (In->RegX) && /* Value of A is known */ E->AM == AM65_ZP && /* Store into zp */ In->RegX == ZPRegVal (E->Chg, In)) { /* Value identical */ Delete = 1; /* If the value in the X register is known and the same as ** that in the A register, replace the store by a STA. The ** optimizer will then remove the load instruction for X ** later. STX does support the zeropage,y addressing mode, ** so be sure to check for that. */ } else if (RegValIsKnown (In->RegX) && In->RegX == In->RegA && E->AM != AM65_ABSY && E->AM != AM65_ZPY) { /* Use the A register instead */ CE_ReplaceOPC (E, OP65_STA); } break; case OP65_STY: /* If we store into a known zero page location, and this ** location does already contain the value to be stored, ** remove the store. */ if (RegValIsKnown (In->RegY) && /* Value of Y is known */ E->AM == AM65_ZP && /* Store into zp */ In->RegY == ZPRegVal (E->Chg, In)) { /* Value identical */ Delete = 1; /* If the value in the Y register is known and the same as ** that in the A register, replace the store by a STA. The ** optimizer will then remove the load instruction for Y ** later. If replacement by A is not possible try a ** replacement by X, but check for invalid addressing modes ** in this case. */ } else if (RegValIsKnown (In->RegY)) { if (In->RegY == In->RegA) { CE_ReplaceOPC (E, OP65_STA); } else if (In->RegY == In->RegX && E->AM != AM65_ABSX && E->AM != AM65_ZPX) { CE_ReplaceOPC (E, OP65_STX); } } break; case OP65_STZ: /* If we store into a known zero page location, and this ** location does already contain the value to be stored, ** remove the store. */ if ((CPUIsets[CPU] & CPU_ISET_65SC02) != 0 && E->AM == AM65_ZP) { if (ZPRegVal (E->Chg, In) == 0) { Delete = 1; } } break; case OP65_TAX: if (RegValIsKnown (In->RegA) && In->RegA == In->RegX && (N = CS_GetNextEntry (S, I)) != 0 && !CE_UseLoadFlags (N)) { /* Value is identical and not followed by a branch */ Delete = 1; } break; case OP65_TAY: if (RegValIsKnown (In->RegA) && In->RegA == In->RegY && (N = CS_GetNextEntry (S, I)) != 0 && !CE_UseLoadFlags (N)) { /* Value is identical and not followed by a branch */ Delete = 1; } break; case OP65_TXA: if (RegValIsKnown (In->RegX) && In->RegX == In->RegA && (N = CS_GetNextEntry (S, I)) != 0 && !CE_UseLoadFlags (N)) { /* Value is identical and not followed by a branch */ Delete = 1; } break; case OP65_TYA: if (RegValIsKnown (In->RegY) && In->RegY == In->RegA && (N = CS_GetNextEntry (S, I)) != 0 && !CE_UseLoadFlags (N)) { /* Value is identical and not followed by a branch */ Delete = 1; } break; default: break; } /* Delete the entry if requested */ if (Delete) { /* Register value is not used, remove the load */ CS_DelEntry (S, I); /* Remember, we had changes */ ++Changes; } else { /* Next entry */ ++I; } } /* Return the number of changes made */ return Changes; } unsigned OptStoreLoad (CodeSeg* S) /* Remove a store followed by a load from the same location. */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* N; CodeEntry* X; /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if it is a store instruction followed by a load from the ** same address which is itself not followed by a conditional branch. */ if ((E->Info & OF_STORE) != 0 && (N = CS_GetNextEntry (S, I)) != 0 && !CE_HasLabel (N) && E->AM == N->AM && ((E->OPC == OP65_STA && N->OPC == OP65_LDA) || (E->OPC == OP65_STX && N->OPC == OP65_LDX) || (E->OPC == OP65_STY && N->OPC == OP65_LDY)) && strcmp (E->Arg, N->Arg) == 0 && (X = CS_GetNextEntry (S, I+1)) != 0 && !CE_UseLoadFlags (X)) { /* Register has already the correct value, remove the load */ CS_DelEntry (S, I+1); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptTransfers1 (CodeSeg* S) /* Remove transfers from one register to another and back */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* N; CodeEntry* X; CodeEntry* P; /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if we have two transfer instructions */ if ((E->Info & OF_XFR) != 0 && (N = CS_GetNextEntry (S, I)) != 0 && !CE_HasLabel (N) && (N->Info & OF_XFR) != 0) { /* Check if it's a transfer and back */ if ((E->OPC == OP65_TAX && N->OPC == OP65_TXA && !RegXUsed (S, I+2)) || (E->OPC == OP65_TAY && N->OPC == OP65_TYA && !RegYUsed (S, I+2)) || (E->OPC == OP65_TXA && N->OPC == OP65_TAX && !RegAUsed (S, I+2)) || (E->OPC == OP65_TYA && N->OPC == OP65_TAY && !RegAUsed (S, I+2))) { /* If the next insn is a conditional branch, check if the insn ** preceeding the first xfr will set the flags right, otherwise we ** may not remove the sequence. */ if ((X = CS_GetNextEntry (S, I+1)) == 0) { goto NextEntry; } if (CE_UseLoadFlags (X)) { if (I == 0) { /* No preceeding entry */ goto NextEntry; } P = CS_GetEntry (S, I-1); if ((P->Info & OF_SETF) == 0) { /* Does not set the flags */ goto NextEntry; } } /* Remove both transfers */ CS_DelEntry (S, I+1); CS_DelEntry (S, I); /* Remember, we had changes */ ++Changes; } } NextEntry: /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptTransfers2 (CodeSeg* S) /* Replace loads followed by a register transfer by a load with the second ** register if possible. */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* N; /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if we have a load followed by a transfer where the loaded ** register is not used later. */ if ((E->Info & OF_LOAD) != 0 && (N = CS_GetNextEntry (S, I)) != 0 && !CE_HasLabel (N) && (N->Info & OF_XFR) != 0 && GetRegInfo (S, I+2, E->Chg) != E->Chg) { CodeEntry* X = 0; if (E->OPC == OP65_LDA && N->OPC == OP65_TAX) { /* LDA/TAX - check for the right addressing modes */ if (E->AM == AM65_IMM || E->AM == AM65_ZP || E->AM == AM65_ABS || E->AM == AM65_ABSY) { /* Replace */ X = NewCodeEntry (OP65_LDX, E->AM, E->Arg, 0, N->LI); } } else if (E->OPC == OP65_LDA && N->OPC == OP65_TAY) { /* LDA/TAY - check for the right addressing modes */ if (E->AM == AM65_IMM || E->AM == AM65_ZP || E->AM == AM65_ZPX || E->AM == AM65_ABS || E->AM == AM65_ABSX) { /* Replace */ X = NewCodeEntry (OP65_LDY, E->AM, E->Arg, 0, N->LI); } } else if (E->OPC == OP65_LDY && N->OPC == OP65_TYA) { /* LDY/TYA. LDA supports all addressing modes LDY does */ X = NewCodeEntry (OP65_LDA, E->AM, E->Arg, 0, N->LI); } else if (E->OPC == OP65_LDX && N->OPC == OP65_TXA) { /* LDX/TXA. LDA doesn't support zp,y, so we must map it to ** abs,y instead. */ am_t AM = (E->AM == AM65_ZPY)? AM65_ABSY : E->AM; X = NewCodeEntry (OP65_LDA, AM, E->Arg, 0, N->LI); } /* If we have a load entry, add it and remove the old stuff */ if (X) { CS_InsertEntry (S, X, I+2); CS_DelEntries (S, I, 2); ++Changes; --I; /* Correct for one entry less */ } } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptTransfers3 (CodeSeg* S) /* Replace a register transfer followed by a store of the second register by a ** store of the first register if this is possible. */ { unsigned Changes = 0; unsigned UsedRegs = REG_NONE; /* Track used registers */ unsigned Xfer = 0; /* Index of transfer insn */ unsigned Store = 0; /* Index of store insn */ CodeEntry* XferEntry = 0; /* Pointer to xfer insn */ CodeEntry* StoreEntry = 0; /* Pointer to store insn */ enum { Initialize, Search, FoundXfer, FoundStore } State = Initialize; /* Walk over the entries. Look for a xfer instruction that is followed by ** a store later, where the value of the register is not used later. */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); switch (State) { case Initialize: /* Clear the list of used registers */ UsedRegs = REG_NONE; /* FALLTHROUGH */ case Search: if (E->Info & OF_XFR) { /* Found start of sequence */ Xfer = I; XferEntry = E; State = FoundXfer; } break; case FoundXfer: /* If we find a conditional jump, abort the sequence, since ** handling them makes things really complicated. */ if (E->Info & OF_CBRA) { /* Switch back to searching */ I = Xfer; State = Initialize; /* Does this insn use the target register of the transfer? */ } else if ((E->Use & XferEntry->Chg) != 0) { /* It it's a store instruction, and the block is a basic ** block, proceed. Otherwise restart */ if ((E->Info & OF_STORE) != 0 && CS_IsBasicBlock (S, Xfer, I)) { Store = I; StoreEntry = E; State = FoundStore; } else { I = Xfer; State = Initialize; } /* Does this insn change the target register of the transfer? */ } else if (E->Chg & XferEntry->Chg) { /* We *may* add code here to remove the transfer, but I'm ** currently not sure about the consequences, so I won't ** do that and bail out instead. */ I = Xfer; State = Initialize; /* Does this insn have a label? */ } else if (CE_HasLabel (E)) { /* Too complex to handle - bail out */ I = Xfer; State = Initialize; } else { /* Track used registers */ UsedRegs |= E->Use; } break; case FoundStore: /* We are at the instruction behind the store. If the register ** isn't used later, and we have an address mode match, we can ** replace the transfer by a store and remove the store here. */ if ((GetRegInfo (S, I, XferEntry->Chg) & XferEntry->Chg) == 0 && (StoreEntry->AM == AM65_ABS || StoreEntry->AM == AM65_ZP) && (StoreEntry->AM != AM65_ZP || (StoreEntry->Chg & UsedRegs) == 0) && !MemAccess (S, Xfer+1, Store-1, StoreEntry)) { /* Generate the replacement store insn */ CodeEntry* X = 0; switch (XferEntry->OPC) { case OP65_TXA: X = NewCodeEntry (OP65_STX, StoreEntry->AM, StoreEntry->Arg, 0, StoreEntry->LI); break; case OP65_TAX: X = NewCodeEntry (OP65_STA, StoreEntry->AM, StoreEntry->Arg, 0, StoreEntry->LI); break; case OP65_TYA: X = NewCodeEntry (OP65_STY, StoreEntry->AM, StoreEntry->Arg, 0, StoreEntry->LI); break; case OP65_TAY: X = NewCodeEntry (OP65_STA, StoreEntry->AM, StoreEntry->Arg, 0, StoreEntry->LI); break; default: break; } /* If we have a replacement store, change the code */ if (X) { /* Insert after the xfer insn */ CS_InsertEntry (S, X, Xfer+1); /* Remove the xfer instead */ CS_DelEntry (S, Xfer); /* Remove the final store */ CS_DelEntry (S, Store); /* Correct I so we continue with the next insn */ I -= 2; /* Remember we had changes */ ++Changes; } else { /* Restart after last xfer insn */ I = Xfer; } } else { /* Restart after last xfer insn */ I = Xfer; } State = Initialize; break; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptTransfers4 (CodeSeg* S) /* Replace a load of a register followed by a transfer insn of the same register ** by a load of the second register if possible. */ { unsigned Changes = 0; unsigned Load = 0; /* Index of load insn */ unsigned Xfer = 0; /* Index of transfer insn */ CodeEntry* LoadEntry = 0; /* Pointer to load insn */ CodeEntry* XferEntry = 0; /* Pointer to xfer insn */ enum { Search, FoundLoad, FoundXfer } State = Search; /* Walk over the entries. Look for a load instruction that is followed by ** a load later. */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); switch (State) { case Search: if (E->Info & OF_LOAD) { /* Found start of sequence */ Load = I; LoadEntry = E; State = FoundLoad; } break; case FoundLoad: /* If we find a conditional jump, abort the sequence, since ** handling them makes things really complicated. */ if (E->Info & OF_CBRA) { /* Switch back to searching */ I = Load; State = Search; /* Does this insn use the target register of the load? */ } else if ((E->Use & LoadEntry->Chg) != 0) { /* It it's a xfer instruction, and the block is a basic ** block, proceed. Otherwise restart */ if ((E->Info & OF_XFR) != 0 && CS_IsBasicBlock (S, Load, I)) { Xfer = I; XferEntry = E; State = FoundXfer; } else { I = Load; State = Search; } /* Does this insn change the target register of the load? */ } else if (E->Chg & LoadEntry->Chg) { /* We *may* add code here to remove the load, but I'm ** currently not sure about the consequences, so I won't ** do that and bail out instead. */ I = Load; State = Search; } break; case FoundXfer: /* We are at the instruction behind the xfer. If the register ** isn't used later, and we have an address mode match, we can ** replace the transfer by a load and remove the initial load. */ if ((GetRegInfo (S, I, LoadEntry->Chg) & LoadEntry->Chg) == 0 && (LoadEntry->AM == AM65_ABS || LoadEntry->AM == AM65_ZP || LoadEntry->AM == AM65_IMM) && !MemAccess (S, Load+1, Xfer-1, LoadEntry)) { /* Generate the replacement load insn */ CodeEntry* X = 0; switch (XferEntry->OPC) { case OP65_TXA: case OP65_TYA: X = NewCodeEntry (OP65_LDA, LoadEntry->AM, LoadEntry->Arg, 0, LoadEntry->LI); break; case OP65_TAX: X = NewCodeEntry (OP65_LDX, LoadEntry->AM, LoadEntry->Arg, 0, LoadEntry->LI); break; case OP65_TAY: X = NewCodeEntry (OP65_LDY, LoadEntry->AM, LoadEntry->Arg, 0, LoadEntry->LI); break; default: break; } /* If we have a replacement load, change the code */ if (X) { /* Insert after the xfer insn */ CS_InsertEntry (S, X, Xfer+1); /* Remove the xfer instead */ CS_DelEntry (S, Xfer); /* Remove the initial load */ CS_DelEntry (S, Load); /* Correct I so we continue with the next insn */ I -= 2; /* Remember we had changes */ ++Changes; } else { /* Restart after last xfer insn */ I = Xfer; } } else { /* Restart after last xfer insn */ I = Xfer; } State = Search; break; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptPushPop (CodeSeg* S) /* Remove a PHA/PLA sequence were A is not used later */ { unsigned Changes = 0; unsigned Push = 0; /* Index of push insn */ unsigned Pop = 0; /* Index of pop insn */ unsigned ChgA = 0; /* Flag for A changed */ enum { Searching, FoundPush, FoundPop } State = Searching; /* Walk over the entries. Look for a push instruction that is followed by ** a pop later, where the pop is not followed by an conditional branch, ** and where the value of the A register is not used later on. ** Look out for the following problems: ** ** - There may be another PHA/PLA inside the sequence: Restart it. ** - If the PLA has a label, all jumps to this label must be inside ** the sequence, otherwise we cannot remove the PHA/PLA. */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* X; /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); switch (State) { case Searching: if (E->OPC == OP65_PHA) { /* Found start of sequence */ Push = I; ChgA = 0; State = FoundPush; } break; case FoundPush: if (E->OPC == OP65_PHA) { /* Inner push/pop, restart */ Push = I; ChgA = 0; } else if (E->OPC == OP65_PLA) { /* Found a matching pop */ Pop = I; /* Check that the block between Push and Pop is a basic ** block (one entry, one exit). Otherwise ignore it. */ if (CS_IsBasicBlock (S, Push, Pop)) { State = FoundPop; } else { /* Go into searching mode again */ State = Searching; } } else if (E->Chg & REG_A) { ChgA = 1; } break; case FoundPop: /* We're at the instruction after the PLA. ** Check for the following conditions: ** - If this instruction is a store of A that doesn't use ** another register, if the instruction does not have a ** label, and A is not used later, we may replace the PHA ** by the store and remove pla if several other conditions ** are met. ** - If this instruction is not a conditional branch, and A ** is either unused later, or not changed by the code ** between push and pop, we may remove PHA and PLA. */ if (E->OPC == OP65_STA && (E->AM == AM65_ABS || E->AM == AM65_ZP) && !CE_HasLabel (E) && !RegAUsed (S, I+1) && !MemAccess (S, Push+1, Pop-1, E)) { /* Insert a STA after the PHA */ X = NewCodeEntry (E->OPC, E->AM, E->Arg, E->JumpTo, E->LI); CS_InsertEntry (S, X, Push+1); /* Remove the PHA instead */ CS_DelEntry (S, Push); /* Remove the PLA/STA sequence */ CS_DelEntries (S, Pop, 2); /* Correct I so we continue with the next insn */ I -= 2; /* Remember we had changes */ ++Changes; } else if ((E->Info & OF_CBRA) == 0 && (!RegAUsed (S, I) || !ChgA)) { /* We can remove the PHA and PLA instructions */ CS_DelEntry (S, Pop); CS_DelEntry (S, Push); /* Correct I so we continue with the next insn */ I -= 2; /* Remember we had changes */ ++Changes; } /* Go into search mode again */ State = Searching; break; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptPrecalc (CodeSeg* S) /* Replace immediate operations with the accu where the current contents are ** known by a load of the final value. */ { unsigned Changes = 0; unsigned I; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Get pointers to the input and output registers of the insn */ const RegContents* Out = &E->RI->Out; const RegContents* In = &E->RI->In; /* Argument for LDn and flag */ const char* Arg = 0; opc_t OPC = OP65_LDA; /* Handle the different instructions */ switch (E->OPC) { case OP65_LDA: if (E->AM != AM65_IMM && RegValIsKnown (Out->RegA)) { /* Result of load is known */ Arg = MakeHexArg (Out->RegA); } break; case OP65_LDX: if (E->AM != AM65_IMM && RegValIsKnown (Out->RegX)) { /* Result of load is known but register is X */ Arg = MakeHexArg (Out->RegX); OPC = OP65_LDX; } break; case OP65_LDY: if (E->AM != AM65_IMM && RegValIsKnown (Out->RegY)) { /* Result of load is known but register is Y */ Arg = MakeHexArg (Out->RegY); OPC = OP65_LDY; } break; case OP65_EOR: if (RegValIsKnown (Out->RegA)) { /* Accu op zp with known contents */ Arg = MakeHexArg (Out->RegA); } break; case OP65_ADC: case OP65_SBC: /* If this is an operation with an immediate operand of zero, ** and the register is zero, the operation won't give us any ** results we don't already have (including the flags), so ** remove it. Something like this is generated as a result of ** a compare where parts of the values are known to be zero. ** The only situation where we need to leave things as they are ** is when V flag is being tested in the next instruction, ** because ADC/SBC #0 always clears it. */ if (In->RegA == 0 && CE_IsKnownImm (E, 0x00) && (E = CS_GetEntry (S, I + 1)) && E->OPC != OP65_BVC && E->OPC != OP65_BVS ) { /* 0-0 or 0+0 -> remove */ CS_DelEntry (S, I); ++Changes; } break; case OP65_AND: if (CE_IsKnownImm (E, 0xFF)) { /* AND with 0xFF, remove */ CS_DelEntry (S, I); ++Changes; } else if (CE_IsKnownImm (E, 0x00)) { /* AND with 0x00, replace by lda #$00 */ Arg = MakeHexArg (0x00); } else if (RegValIsKnown (Out->RegA)) { /* Accu AND zp with known contents */ Arg = MakeHexArg (Out->RegA); } else if (In->RegA == 0xFF) { /* AND but A contains 0xFF - replace by lda */ CE_ReplaceOPC (E, OP65_LDA); ++Changes; } break; case OP65_ORA: if (CE_IsKnownImm (E, 0x00)) { /* ORA with zero, remove */ CS_DelEntry (S, I); ++Changes; } else if (CE_IsKnownImm (E, 0xFF)) { /* ORA with 0xFF, replace by lda #$ff */ Arg = MakeHexArg (0xFF); } else if (RegValIsKnown (Out->RegA)) { /* Accu AND zp with known contents */ Arg = MakeHexArg (Out->RegA); } else if (In->RegA == 0) { /* ORA but A contains 0x00 - replace by lda */ CE_ReplaceOPC (E, OP65_LDA); ++Changes; } break; default: break; } /* Check if we have to replace the insn by LDA */ if (Arg) { CodeEntry* X = NewCodeEntry (OPC, AM65_IMM, Arg, 0, E->LI); CS_InsertEntry (S, X, I+1); CS_DelEntry (S, I); ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } /*****************************************************************************/ /* Optimize branch types */ /*****************************************************************************/ unsigned OptBranchDist (CodeSeg* S) /* Change branches for the distance needed. */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if it's a conditional branch to a local label. */ if (E->Info & OF_CBRA) { /* Is this a branch to a local symbol? */ if (E->JumpTo != 0) { /* Check if the branch distance is short */ int IsShort = IsShortDist (GetBranchDist (S, I, E->JumpTo->Owner)); /* Make the branch short/long according to distance */ if ((E->Info & OF_LBRA) == 0 && !IsShort) { /* Short branch but long distance */ CE_ReplaceOPC (E, MakeLongBranch (E->OPC)); ++Changes; } else if ((E->Info & OF_LBRA) != 0 && IsShort) { /* Long branch but short distance */ CE_ReplaceOPC (E, MakeShortBranch (E->OPC)); ++Changes; } } else if ((E->Info & OF_LBRA) == 0) { /* Short branch to external symbol - make it long */ CE_ReplaceOPC (E, MakeLongBranch (E->OPC)); ++Changes; } } else if ((CPUIsets[CPU] & CPU_ISET_65SC02) != 0 && (E->Info & OF_UBRA) != 0 && E->JumpTo != 0 && IsShortDist (GetBranchDist (S, I, E->JumpTo->Owner))) { /* The jump is short and may be replaced by a BRA on the 65C02 CPU */ CE_ReplaceOPC (E, OP65_BRA); ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } /*****************************************************************************/ /* Optimize indirect loads */ /*****************************************************************************/ unsigned OptIndLoads1 (CodeSeg* S) /* Change ** ** lda (zp),y ** ** into ** ** lda (zp,x) ** ** provided that x and y are both zero. */ { unsigned Changes = 0; unsigned I; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if it's what we're looking for */ if (E->OPC == OP65_LDA && E->AM == AM65_ZP_INDY && E->RI->In.RegY == 0 && E->RI->In.RegX == 0) { /* Replace by the same insn with other addressing mode */ CodeEntry* X = NewCodeEntry (E->OPC, AM65_ZPX_IND, E->Arg, 0, E->LI); CS_InsertEntry (S, X, I+1); /* Remove the old insn */ CS_DelEntry (S, I); ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptIndLoads2 (CodeSeg* S) /* Change ** ** lda (zp,x) ** ** into ** ** lda (zp),y ** ** provided that x and y are both zero. */ { unsigned Changes = 0; unsigned I; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if it's what we're looking for */ if (E->OPC == OP65_LDA && E->AM == AM65_ZPX_IND && E->RI->In.RegY == 0 && E->RI->In.RegX == 0) { /* Replace by the same insn with other addressing mode */ CodeEntry* X = NewCodeEntry (E->OPC, AM65_ZP_INDY, E->Arg, 0, E->LI); CS_InsertEntry (S, X, I+1); /* Remove the old insn */ CS_DelEntry (S, I); ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/coptind.h������������������������������������������������������������������������0000664�0000000�0000000�00000014761�13473601511�0015356�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* coptind.h */ /* */ /* Environment independent low level optimizations */ /* */ /* */ /* */ /* (C) 2001-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef COPTIND_H #define COPTIND_H /* cc65 */ #include "codeseg.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned OptRTSJumps1 (CodeSeg* S); /* Replace jumps to RTS by RTS */ unsigned OptRTSJumps2 (CodeSeg* S); /* Replace long conditional jumps to RTS */ unsigned OptDeadJumps (CodeSeg* S); /* Remove dead jumps (jumps to the next instruction) */ unsigned OptDeadCode (CodeSeg* S); /* Remove dead code (code that follows an unconditional jump or an rts/rti ** and has no label) */ unsigned OptJumpCascades (CodeSeg* S); /* Optimize jump cascades (jumps to jumps). In such a case, the jump is ** replaced by a jump to the final location. This will in some cases produce ** worse code, because some jump targets are no longer reachable by short ** branches, but this is quite rare, so there are more advantages than ** disadvantages. */ unsigned OptRTS (CodeSeg* S); /* Optimize subroutine calls followed by an RTS. The subroutine call will get ** replaced by a jump. Don't bother to delete the RTS if it does not have a ** label, the dead code elimination should take care of it. */ unsigned OptJumpTarget1 (CodeSeg* S); /* If the instruction preceeding an unconditional branch is the same as the ** instruction preceeding the jump target, the jump target may be moved ** one entry back. This is a size optimization, since the instruction before ** the branch gets removed. */ unsigned OptJumpTarget2 (CodeSeg* S); /* If a bcs jumps to a sec insn or a bcc jumps to clc, skip this insn, since ** it's job is already done. */ unsigned OptJumpTarget3 (CodeSeg* S); /* Jumps to load instructions of a register, that do already have the matching ** register contents may skip the load instruction, since it's job is already ** done. */ unsigned OptCondBranches1 (CodeSeg* S); /* If an immidiate load of a register is followed by a conditional jump that ** is never taken because the load of the register sets the flags in such a ** manner, remove the conditional branch. */ unsigned OptCondBranches2 (CodeSeg* S); /* If on entry to a "rol a" instruction the accu is zero, and a beq/bne follows, ** we can remove the rol and branch on the state of the carry. */ unsigned OptUnusedLoads (CodeSeg* S); /* Remove loads of registers where the value loaded is not used later. */ unsigned OptUnusedStores (CodeSeg* S); /* Remove stores into zero page registers that aren't used later */ unsigned OptDupLoads (CodeSeg* S); /* Remove loads of registers where the value loaded is already in the register. */ unsigned OptStoreLoad (CodeSeg* S); /* Remove a store followed by a load from the same location. */ unsigned OptTransfers1 (CodeSeg* S); /* Remove transfers from one register to another and back */ unsigned OptTransfers2 (CodeSeg* S); /* Replace loads followed by a register transfer by a load with the second ** register if possible. */ unsigned OptTransfers3 (CodeSeg* S); /* Replace a register transfer followed by a store of the second register by a ** store of the first register if this is possible. */ unsigned OptTransfers4 (CodeSeg* S); /* Replace a load of a register followed by a transfer insn of the same register ** by a load of the second register if possible. */ unsigned OptPushPop (CodeSeg* S); /* Remove a PHA/PLA sequence were A is not used later */ unsigned OptPrecalc (CodeSeg* S); /* Replace immediate operations with the accu where the current contents are ** known by a load of the final value. */ unsigned OptBranchDist (CodeSeg* S); /* Change branches for the distance needed. */ unsigned OptIndLoads1 (CodeSeg* S); /* Change ** ** lda (zp),y ** ** into ** ** lda (zp,x) ** ** provided that x and y are both zero. */ unsigned OptIndLoads2 (CodeSeg* S); /* Change ** ** lda (zp,x) ** ** into ** ** lda (zp),y ** ** provided that x and y are both zero. */ /* End of coptind.h */ #endif ���������������cc65-2.18/src/cc65/coptneg.c������������������������������������������������������������������������0000664�0000000�0000000�00000037532�13473601511�0015351�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* coptneg.c */ /* */ /* Optimize negation sequences */ /* */ /* */ /* */ /* (C) 2001-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* cc65 */ #include "codeent.h" #include "codeinfo.h" #include "coptneg.h" /*****************************************************************************/ /* bnega optimizations */ /*****************************************************************************/ unsigned OptBNegA1 (CodeSeg* S) /* Check for ** ** ldx #$00 ** lda .. ** jsr bnega ** ** Remove the ldx if the lda does not use it. */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[2]; /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check for a ldx */ if (E->OPC == OP65_LDX && E->AM == AM65_IMM && (E->Flags & CEF_NUMARG) != 0 && E->Num == 0 && CS_GetEntries (S, L, I+1, 2) && L[0]->OPC == OP65_LDA && (L[0]->Use & REG_X) == 0 && !CE_HasLabel (L[0]) && CE_IsCallTo (L[1], "bnega") && !CE_HasLabel (L[1])) { /* Remove the ldx instruction */ CS_DelEntry (S, I); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptBNegA2 (CodeSeg* S) /* Check for ** ** lda .. ** jsr bnega ** jeq/jne .. ** ** Adjust the conditional branch and remove the call to the subroutine. */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[2]; /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check for the sequence */ if ((E->OPC == OP65_ADC || E->OPC == OP65_AND || E->OPC == OP65_DEA || E->OPC == OP65_EOR || E->OPC == OP65_INA || E->OPC == OP65_LDA || E->OPC == OP65_ORA || E->OPC == OP65_PLA || E->OPC == OP65_SBC || E->OPC == OP65_TXA || E->OPC == OP65_TYA) && CS_GetEntries (S, L, I+1, 2) && CE_IsCallTo (L[0], "bnega") && !CE_HasLabel (L[0]) && (L[1]->Info & OF_ZBRA) != 0 && !CE_HasLabel (L[1])) { /* Invert the branch */ CE_ReplaceOPC (L[1], GetInverseBranch (L[1]->OPC)); /* Delete the subroutine call */ CS_DelEntry (S, I+1); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } /*****************************************************************************/ /* bnegax optimizations */ /*****************************************************************************/ unsigned OptBNegAX1 (CodeSeg* S) /* On a call to bnegax, if X is zero, the result depends only on the value in ** A, so change the call to a call to bnega. This will get further optimized ** later if possible. */ { unsigned Changes = 0; unsigned I; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if this is a call to bnegax, and if X is known and zero */ if (E->RI->In.RegX == 0 && CE_IsCallTo (E, "bnegax")) { CodeEntry* X = NewCodeEntry (OP65_JSR, AM65_ABS, "bnega", 0, E->LI); CS_InsertEntry (S, X, I+1); CS_DelEntry (S, I); /* We had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptBNegAX2 (CodeSeg* S) /* Search for the sequence: ** ** ldy #xx ** jsr ldaxysp ** jsr bnegax ** jne/jeq ... ** ** and replace it by ** ** ldy #xx ** lda (sp),y ** dey ** ora (sp),y ** jeq/jne ... */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[4]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (L[0]->OPC == OP65_LDY && CE_IsConstImm (L[0]) && !CS_RangeHasLabel (S, I+1, 3) && CS_GetEntries (S, L+1, I+1, 3) && CE_IsCallTo (L[1], "ldaxysp") && CE_IsCallTo (L[2], "bnegax") && (L[3]->Info & OF_ZBRA) != 0) { CodeEntry* X; /* lda (sp),y */ X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "sp", 0, L[1]->LI); CS_InsertEntry (S, X, I+1); /* dey */ X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, L[1]->LI); CS_InsertEntry (S, X, I+2); /* ora (sp),y */ X = NewCodeEntry (OP65_ORA, AM65_ZP_INDY, "sp", 0, L[1]->LI); CS_InsertEntry (S, X, I+3); /* Invert the branch */ CE_ReplaceOPC (L[3], GetInverseBranch (L[3]->OPC)); /* Delete the entries no longer needed. */ CS_DelEntries (S, I+4, 2); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptBNegAX3 (CodeSeg* S) /* Search for the sequence: ** ** lda xx ** ldx yy ** jsr bnegax ** jne/jeq ... ** ** and replace it by ** ** lda xx ** ora xx+1 ** jeq/jne ... */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[3]; /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check for the sequence */ if (E->OPC == OP65_LDA && CS_GetEntries (S, L, I+1, 3) && L[0]->OPC == OP65_LDX && !CE_HasLabel (L[0]) && CE_IsCallTo (L[1], "bnegax") && !CE_HasLabel (L[1]) && (L[2]->Info & OF_ZBRA) != 0 && !CE_HasLabel (L[2])) { /* ldx --> ora */ CE_ReplaceOPC (L[0], OP65_ORA); /* Invert the branch */ CE_ReplaceOPC (L[2], GetInverseBranch (L[2]->OPC)); /* Delete the subroutine call */ CS_DelEntry (S, I+2); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptBNegAX4 (CodeSeg* S) /* Search for the sequence: ** ** jsr xxx ** jsr bnega(x) ** jeq/jne ... ** ** and replace it by: ** ** jsr xxx ** <boolean test> ** jne/jeq ... */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[2]; /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check for the sequence */ if (E->OPC == OP65_JSR && CS_GetEntries (S, L, I+1, 2) && L[0]->OPC == OP65_JSR && strncmp (L[0]->Arg,"bnega",5) == 0 && !CE_HasLabel (L[0]) && (L[1]->Info & OF_ZBRA) != 0 && !CE_HasLabel (L[1])) { CodeEntry* X; /* Check if we're calling bnega or bnegax */ int ByteSized = (strcmp (L[0]->Arg, "bnega") == 0); /* Insert apropriate test code */ if (ByteSized) { /* Test bytes */ X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, L[0]->LI); CS_InsertEntry (S, X, I+2); } else { /* Test words */ X = NewCodeEntry (OP65_STX, AM65_ZP, "tmp1", 0, L[0]->LI); CS_InsertEntry (S, X, I+2); X = NewCodeEntry (OP65_ORA, AM65_ZP, "tmp1", 0, L[0]->LI); CS_InsertEntry (S, X, I+3); } /* Delete the subroutine call */ CS_DelEntry (S, I+1); /* Invert the branch */ CE_ReplaceOPC (L[1], GetInverseBranch (L[1]->OPC)); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } /*****************************************************************************/ /* negax optimizations */ /*****************************************************************************/ unsigned OptNegAX1 (CodeSeg* S) /* Search for a call to negax and replace it by ** ** eor #$FF ** clc ** adc #$01 ** ** if X isn't used later. */ { unsigned Changes = 0; unsigned I; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if this is a call to negax, and if X isn't used later */ if (CE_IsCallTo (E, "negax") && !RegXUsed (S, I+1)) { CodeEntry* X; /* Add replacement code behind */ X = NewCodeEntry (OP65_EOR, AM65_IMM, "$FF", 0, E->LI); CS_InsertEntry (S, X, I+1); X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, E->LI); CS_InsertEntry (S, X, I+2); X = NewCodeEntry (OP65_ADC, AM65_IMM, "$01", 0, E->LI); CS_InsertEntry (S, X, I+3); /* Delete the call to negax */ CS_DelEntry (S, I); /* Skip the generated code */ I += 2; /* We had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptNegAX2 (CodeSeg* S) /* Search for a call to negax and replace it by ** ** ldx #$FF ** eor #$FF ** clc ** adc #$01 ** bne L1 ** inx ** L1: ** ** if X is known and zero on entry. */ { unsigned Changes = 0; unsigned I; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* P; /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if this is a call to negax, and if X is known and zero */ if (E->RI->In.RegX == 0 && CE_IsCallTo (E, "negax") && (P = CS_GetNextEntry (S, I)) != 0) { CodeEntry* X; CodeLabel* L; /* Add replacement code behind */ /* ldx #$FF */ X = NewCodeEntry (OP65_LDX, AM65_IMM, "$FF", 0, E->LI); CS_InsertEntry (S, X, I+1); /* eor #$FF */ X = NewCodeEntry (OP65_EOR, AM65_IMM, "$FF", 0, E->LI); CS_InsertEntry (S, X, I+2); /* clc */ X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, E->LI); CS_InsertEntry (S, X, I+3); /* adc #$01 */ X = NewCodeEntry (OP65_ADC, AM65_IMM, "$01", 0, E->LI); CS_InsertEntry (S, X, I+4); /* Get the label attached to the insn following the call */ L = CS_GenLabel (S, P); /* bne L */ X = NewCodeEntry (OP65_BNE, AM65_BRA, L->Name, L, E->LI); CS_InsertEntry (S, X, I+5); /* inx */ X = NewCodeEntry (OP65_INX, AM65_IMP, 0, 0, E->LI); CS_InsertEntry (S, X, I+6); /* Delete the call to negax */ CS_DelEntry (S, I); /* Skip the generated code */ I += 5; /* We had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } /*****************************************************************************/ /* complax optimizations */ /*****************************************************************************/ unsigned OptComplAX1 (CodeSeg* S) /* Search for a call to complax and replace it by ** ** eor #$FF ** ** if X isn't used later. */ { unsigned Changes = 0; unsigned I; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check if this is a call to negax, and if X isn't used later */ if (CE_IsCallTo (E, "complax") && !RegXUsed (S, I+1)) { CodeEntry* X; /* Add replacement code behind */ X = NewCodeEntry (OP65_EOR, AM65_IMM, "$FF", 0, E->LI); CS_InsertEntry (S, X, I+1); /* Delete the call to negax */ CS_DelEntry (S, I); /* We had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/coptneg.h������������������������������������������������������������������������0000664�0000000�0000000�00000012615�13473601511�0015351�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* coptneg.h */ /* */ /* Optimize negation sequences */ /* */ /* */ /* */ /* (C) 2001-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef COPTNEG_H #define COPTNEG_H /* cc65 */ #include "codeseg.h" /*****************************************************************************/ /* bnega optimizations */ /*****************************************************************************/ unsigned OptBNegA1 (CodeSeg* S); /* Check for ** ** ldx #$00 ** lda .. ** jsr bnega ** ** Remove the ldx if the lda does not use it. */ unsigned OptBNegA2 (CodeSeg* S); /* Check for ** ** lda .. ** jsr bnega ** jeq/jne .. ** ** Adjust the conditional branch and remove the call to the subroutine. */ /*****************************************************************************/ /* bnegax optimizations */ /*****************************************************************************/ unsigned OptBNegAX1 (CodeSeg* S); /* On a call to bnegax, if X is zero, the result depends only on the value in ** A, so change the call to a call to bnega. This will get further optimized ** later if possible. */ unsigned OptBNegAX2 (CodeSeg* S); /* Search for the sequence: ** ** lda (xx),y ** tax ** dey ** lda (xx),y ** jsr bnegax ** jne/jeq ... ** ** and replace it by ** ** lda (xx),y ** dey ** ora (xx),y ** jeq/jne ... */ unsigned OptBNegAX3 (CodeSeg* S); /* Search for the sequence: ** ** lda xx ** ldx yy ** jsr bnegax ** jne/jeq ... ** ** and replace it by ** ** lda xx ** ora xx+1 ** jeq/jne ... */ unsigned OptBNegAX4 (CodeSeg* S); /* Search for the sequence: ** ** jsr xxx ** jsr bnega(x) ** jeq/jne ... ** ** and replace it by: ** ** jsr xxx ** <boolean test> ** jne/jeq ... */ /*****************************************************************************/ /* negax optimizations */ /*****************************************************************************/ unsigned OptNegAX1 (CodeSeg* S); /* Search for a call to negax and replace it by ** ** eor #$FF ** clc ** adc #$01 ** ** if X isn't used later. */ unsigned OptNegAX2 (CodeSeg* S); /* Search for a call to negax and replace it by ** ** ldx #$FF ** eor #$FF ** clc ** adc #$01 ** bne L1 ** inx ** L1: ** ** if X is known and zero on entry. */ /*****************************************************************************/ /* complax optimizations */ /*****************************************************************************/ unsigned OptComplAX1 (CodeSeg* S); /* Search for a call to complax and replace it by ** ** eor #$FF ** ** if X isn't used later. */ /* End of coptneg.h */ #endif �������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/coptptrload.c��������������������������������������������������������������������0000664�0000000�0000000�00000143406�13473601511�0016243�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* coptptrload.c */ /* */ /* Optimize loads through pointers */ /* */ /* */ /* */ /* (C) 2001-2009 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* common */ #include "xmalloc.h" /* cc65 */ #include "codeent.h" #include "codeinfo.h" #include "coptptrload.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned OptPtrLoad1 (CodeSeg* S) /* Search for the sequence: ** ** clc ** adc xxx ** tay ** txa ** adc yyy ** tax ** tya ** ldy #$00 ** jsr ldauidx ** ** and replace it by: ** ** sta ptr1 ** txa ** clc ** adc yyy ** sta ptr1+1 ** ldy xxx ** ldx #$00 ** lda (ptr1),y */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[9]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (L[0]->OPC == OP65_CLC && CS_GetEntries (S, L+1, I+1, 8) && L[1]->OPC == OP65_ADC && (L[1]->AM == AM65_ABS || L[1]->AM == AM65_ZP || L[1]->AM == AM65_IMM) && L[2]->OPC == OP65_TAY && L[3]->OPC == OP65_TXA && L[4]->OPC == OP65_ADC && L[5]->OPC == OP65_TAX && L[6]->OPC == OP65_TYA && L[7]->OPC == OP65_LDY && CE_IsKnownImm (L[7], 0) && CE_IsCallTo (L[8], "ldauidx") && !CS_RangeHasLabel (S, I+1, 8)) { CodeEntry* X; CodeEntry* P; /* Track the insertion point */ unsigned IP = I+9; /* sta ptr1 */ X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[2]->LI); CS_InsertEntry (S, X, IP++); /* If the instruction before the clc is a ldx, replace the ** txa by an lda with the same location of the ldx. Otherwise ** transfer the value in X to A. */ if ((P = CS_GetPrevEntry (S, I)) != 0 && P->OPC == OP65_LDX && !CE_HasLabel (P)) { X = NewCodeEntry (OP65_LDA, P->AM, P->Arg, 0, P->LI); } else { X = NewCodeEntry (OP65_TXA, AM65_IMP, 0, 0, L[3]->LI); } CS_InsertEntry (S, X, IP++); /* clc */ X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, L[0]->LI); CS_InsertEntry (S, X, IP++); /* adc yyy */ X = NewCodeEntry (OP65_ADC, L[4]->AM, L[4]->Arg, 0, L[4]->LI); CS_InsertEntry (S, X, IP++); /* sta ptr1+1 */ X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1+1", 0, L[5]->LI); CS_InsertEntry (S, X, IP++); /* ldy xxx */ X = NewCodeEntry (OP65_LDY, L[1]->AM, L[1]->Arg, 0, L[1]->LI); CS_InsertEntry (S, X, IP++); /* ldx #$00 */ X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[8]->LI); CS_InsertEntry (S, X, IP++); /* lda (ptr1),y */ X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[8]->LI); CS_InsertEntry (S, X, IP++); /* Remove the old instructions */ CS_DelEntries (S, I, 9); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptPtrLoad2 (CodeSeg* S) /* Search for the sequence: ** ** adc xxx ** pha ** txa ** iny ** adc yyy ** tax ** pla ** ldy ** jsr ldauidx ** ** and replace it by: ** ** adc xxx ** sta ptr1 ** txa ** iny ** adc yyy ** sta ptr1+1 ** ldy ** ldx #$00 ** lda (ptr1),y */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[9]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (L[0]->OPC == OP65_ADC && CS_GetEntries (S, L+1, I+1, 8) && L[1]->OPC == OP65_PHA && L[2]->OPC == OP65_TXA && L[3]->OPC == OP65_INY && L[4]->OPC == OP65_ADC && L[5]->OPC == OP65_TAX && L[6]->OPC == OP65_PLA && L[7]->OPC == OP65_LDY && CE_IsCallTo (L[8], "ldauidx") && !CS_RangeHasLabel (S, I+1, 8)) { CodeEntry* X; /* Store the low byte and remove the PHA instead */ X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[0]->LI); CS_InsertEntry (S, X, I+1); /* Store the high byte */ X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1+1", 0, L[4]->LI); CS_InsertEntry (S, X, I+6); /* Load high and low byte */ X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[6]->LI); CS_InsertEntry (S, X, I+10); X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[6]->LI); CS_InsertEntry (S, X, I+11); /* Delete the old code */ CS_DelEntry (S, I+12); /* jsr ldauidx */ CS_DelEntry (S, I+8); /* pla */ CS_DelEntry (S, I+7); /* tax */ CS_DelEntry (S, I+2); /* pha */ /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptPtrLoad3 (CodeSeg* S) /* Search for the sequence: ** ** lda #<(label+0) ** ldx #>(label+0) ** clc ** adc xxx ** bcc L ** inx ** L: ldy #$00 ** jsr ldauidx ** ** and replace it by: ** ** ldy xxx ** ldx #$00 ** lda label,y */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[8]; unsigned Len; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (L[0]->OPC == OP65_LDA && L[0]->AM == AM65_IMM && CS_GetEntries (S, L+1, I+1, 7) && L[1]->OPC == OP65_LDX && L[1]->AM == AM65_IMM && L[2]->OPC == OP65_CLC && L[3]->OPC == OP65_ADC && (L[3]->AM == AM65_ABS || L[3]->AM == AM65_ZP) && (L[4]->OPC == OP65_BCC || L[4]->OPC == OP65_JCC) && L[4]->JumpTo != 0 && L[4]->JumpTo->Owner == L[6] && L[5]->OPC == OP65_INX && L[6]->OPC == OP65_LDY && CE_IsKnownImm (L[6], 0) && CE_IsCallTo (L[7], "ldauidx") && !CS_RangeHasLabel (S, I+1, 5) && !CE_HasLabel (L[7]) && /* Check the label last because this is quite costly */ (Len = strlen (L[0]->Arg)) > 3 && L[0]->Arg[0] == '<' && L[0]->Arg[1] == '(' && strlen (L[1]->Arg) == Len && L[1]->Arg[0] == '>' && memcmp (L[0]->Arg+1, L[1]->Arg+1, Len-1) == 0) { CodeEntry* X; char* Label; /* We will create all the new stuff behind the current one so ** we keep the line references. */ X = NewCodeEntry (OP65_LDY, L[3]->AM, L[3]->Arg, 0, L[0]->LI); CS_InsertEntry (S, X, I+8); X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[0]->LI); CS_InsertEntry (S, X, I+9); Label = memcpy (xmalloc (Len-2), L[0]->Arg+2, Len-3); Label[Len-3] = '\0'; X = NewCodeEntry (OP65_LDA, AM65_ABSY, Label, 0, L[0]->LI); CS_InsertEntry (S, X, I+10); xfree (Label); /* Remove the old code */ CS_DelEntries (S, I, 8); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptPtrLoad4 (CodeSeg* S) /* Search for the sequence: ** ** lda #<(label+0) ** ldx #>(label+0) ** ldy #$xx ** clc ** adc (sp),y ** bcc L ** inx ** L: ldy #$00 ** jsr ldauidx ** ** and replace it by: ** ** ldy #$xx ** lda (sp),y ** tay ** ldx #$00 ** lda label,y */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[9]; unsigned Len; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (L[0]->OPC == OP65_LDA && L[0]->AM == AM65_IMM && CS_GetEntries (S, L+1, I+1, 8) && L[1]->OPC == OP65_LDX && L[1]->AM == AM65_IMM && !CE_HasLabel (L[1]) && L[2]->OPC == OP65_LDY && CE_IsConstImm (L[2]) && !CE_HasLabel (L[2]) && L[3]->OPC == OP65_CLC && !CE_HasLabel (L[3]) && L[4]->OPC == OP65_ADC && L[4]->AM == AM65_ZP_INDY && !CE_HasLabel (L[4]) && (L[5]->OPC == OP65_BCC || L[5]->OPC == OP65_JCC) && L[5]->JumpTo != 0 && L[5]->JumpTo->Owner == L[7] && !CE_HasLabel (L[5]) && L[6]->OPC == OP65_INX && !CE_HasLabel (L[6]) && L[7]->OPC == OP65_LDY && CE_IsKnownImm (L[7], 0) && CE_IsCallTo (L[8], "ldauidx") && !CE_HasLabel (L[8]) && /* Check the label last because this is quite costly */ (Len = strlen (L[0]->Arg)) > 3 && L[0]->Arg[0] == '<' && L[0]->Arg[1] == '(' && strlen (L[1]->Arg) == Len && L[1]->Arg[0] == '>' && memcmp (L[0]->Arg+1, L[1]->Arg+1, Len-1) == 0) { CodeEntry* X; char* Label; /* Add the lda */ X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, L[4]->Arg, 0, L[0]->LI); CS_InsertEntry (S, X, I+3); /* Add the tay */ X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, L[0]->LI); CS_InsertEntry (S, X, I+4); /* Add the ldx */ X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[0]->LI); CS_InsertEntry (S, X, I+5); /* Add the lda */ Label = memcpy (xmalloc (Len-2), L[0]->Arg+2, Len-3); Label[Len-3] = '\0'; X = NewCodeEntry (OP65_LDA, AM65_ABSY, Label, 0, L[0]->LI); CS_InsertEntry (S, X, I+6); xfree (Label); /* Remove the old code */ CS_DelEntries (S, I, 2); CS_DelEntries (S, I+5, 6); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptPtrLoad5 (CodeSeg* S) /* Search for the sequence: ** ** jsr pushax ** ldx #$00 ** lda yyy ** jsr tosaddax ** ldy #$00 ** jsr ldauidx ** ** and replace it by: ** ** sta ptr1 ** stx ptr1+1 ** ldy yyy ** ldx #$00 ** lda (ptr1),y */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[6]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (CE_IsCallTo (L[0], "pushax") && CS_GetEntries (S, L+1, I+1, 5) && L[1]->OPC == OP65_LDX && CE_IsKnownImm (L[1], 0) && L[2]->OPC == OP65_LDA && (L[2]->AM == AM65_ABS || L[2]->AM == AM65_ZP || L[2]->AM == AM65_IMM) && CE_IsCallTo (L[3], "tosaddax") && L[4]->OPC == OP65_LDY && CE_IsKnownImm (L[4], 0) && CE_IsCallTo (L[5], "ldauidx") && !CS_RangeHasLabel (S, I+1, 5)) { CodeEntry* X; /* sta ptr1 */ X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[0]->LI); CS_InsertEntry (S, X, I+6); /* stx ptr1+1 */ X = NewCodeEntry (OP65_STX, AM65_ZP, "ptr1+1", 0, L[0]->LI); CS_InsertEntry (S, X, I+7); /* ldy yyy */ X = NewCodeEntry (OP65_LDY, L[2]->AM, L[2]->Arg, 0, L[2]->LI); CS_InsertEntry (S, X, I+8); /* ldx #$00 */ X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[5]->LI); CS_InsertEntry (S, X, I+9); /* lda (ptr1),y */ X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[5]->LI); CS_InsertEntry (S, X, I+10); /* Remove the old code */ CS_DelEntries (S, I, 6); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptPtrLoad6 (CodeSeg* S) /* Search for the sequence: ** ** jsr pushax ** ldy #xxx ** ldx #$00 ** lda (sp),y ** jsr tosaddax ** ldy #$00 ** jsr ldauidx ** ** and replace it by: ** ** sta ptr1 ** stx ptr1+1 ** ldy #xxx-2 ** lda (sp),y ** tay ** ldx #$00 ** lda (ptr1),y */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[7]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (CE_IsCallTo (L[0], "pushax") && CS_GetEntries (S, L+1, I+1, 6) && L[1]->OPC == OP65_LDY && CE_IsConstImm (L[1]) && L[1]->Num >= 2 && L[2]->OPC == OP65_LDX && CE_IsKnownImm (L[2], 0) && L[3]->OPC == OP65_LDA && L[3]->AM == AM65_ZP_INDY && CE_IsCallTo (L[4], "tosaddax") && L[5]->OPC == OP65_LDY && CE_IsKnownImm (L[5], 0) && CE_IsCallTo (L[6], "ldauidx") && !CS_RangeHasLabel (S, I+1, 6) && !RegYUsed (S, I+7)) { CodeEntry* X; const char* Arg; /* sta ptr1 */ X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[0]->LI); CS_InsertEntry (S, X, I+7); /* stx ptr1+1 */ X = NewCodeEntry (OP65_STX, AM65_ZP, "ptr1+1", 0, L[0]->LI); CS_InsertEntry (S, X, I+8); /* ldy #xxx-2 */ Arg = MakeHexArg (L[1]->Num - 2); X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[1]->LI); CS_InsertEntry (S, X, I+9); /* lda (sp),y */ X = NewCodeEntry (OP65_LDA, L[3]->AM, L[3]->Arg, 0, L[3]->LI); CS_InsertEntry (S, X, I+10); /* tay */ X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, L[3]->LI); CS_InsertEntry (S, X, I+11); /* ldx #$00 */ X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[5]->LI); CS_InsertEntry (S, X, I+12); /* lda (ptr1),y */ X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[6]->LI); CS_InsertEntry (S, X, I+13); /* Remove the old code */ CS_DelEntries (S, I, 7); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptPtrLoad7 (CodeSeg* S) /* Search for the sequence: ** ** jsr aslax1/shlax1 ** clc ** adc xxx ** tay ** txa ** adc yyy ** tax ** tya ** ldy zzz ** jsr ldaxidx ** ** and replace it by: ** ** stx tmp1 ** asl a ** rol tmp1 ** clc ** adc xxx ** sta ptr1 ** lda tmp1 ** adc yyy ** sta ptr1+1 ** ldy zzz ** lda (ptr1),y ** tax ** dey ** lda (ptr1),y */ { unsigned Changes = 0; unsigned I; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[10]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (L[0]->OPC == OP65_JSR && (strcmp (L[0]->Arg, "aslax1") == 0 || strcmp (L[0]->Arg, "shlax1") == 0) && CS_GetEntries (S, L+1, I+1, 9) && L[1]->OPC == OP65_CLC && L[2]->OPC == OP65_ADC && L[3]->OPC == OP65_TAY && L[4]->OPC == OP65_TXA && L[5]->OPC == OP65_ADC && L[6]->OPC == OP65_TAX && L[7]->OPC == OP65_TYA && L[8]->OPC == OP65_LDY && CE_IsCallTo (L[9], "ldaxidx") && !CS_RangeHasLabel (S, I+1, 9)) { CodeEntry* X; /* Track the insertion point */ unsigned IP = I + 10; /* If X is zero on entry to aslax1, we can generate: ** ** asl a ** bcc L1 ** inx ** L1: clc ** ** instead of the code above. "lda tmp1" needs to be changed ** to "txa" in this case. */ int ShortCode = (L[0]->RI->In.RegX == 0); if (ShortCode) { CodeLabel* Lab; /* asl a */ X = NewCodeEntry (OP65_ASL, AM65_ACC, "a", 0, L[0]->LI); CS_InsertEntry (S, X, IP++); /* Generate clc first, since we need the label */ X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, L[1]->LI); CS_InsertEntry (S, X, IP); /* Get the label */ Lab = CS_GenLabel (S, X); /* bcc Lab */ X = NewCodeEntry (OP65_BCC, AM65_BRA, Lab->Name, Lab, L[0]->LI); CS_InsertEntry (S, X, IP++); /* inx */ X = NewCodeEntry (OP65_INX, AM65_IMP, 0, 0, L[0]->LI); CS_InsertEntry (S, X, IP++); /* Skip the clc insn */ ++IP; } else { /* stx tmp1 */ X = NewCodeEntry (OP65_STX, AM65_ZP, "tmp1", 0, L[0]->LI); CS_InsertEntry (S, X, IP++); /* asl a */ X = NewCodeEntry (OP65_ASL, AM65_ACC, "a", 0, L[0]->LI); CS_InsertEntry (S, X, IP++); /* rol tmp1 */ X = NewCodeEntry (OP65_ROL, AM65_ZP, "tmp1", 0, L[0]->LI); CS_InsertEntry (S, X, IP++); /* clc */ X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, L[1]->LI); CS_InsertEntry (S, X, IP++); } /* adc xxx */ X = NewCodeEntry (L[2]->OPC, L[2]->AM, L[2]->Arg, 0, L[2]->LI); CS_InsertEntry (S, X, IP++); /* sta ptr1 */ X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[9]->LI); CS_InsertEntry (S, X, IP++); if (ShortCode) { /* txa */ X = NewCodeEntry (OP65_TXA, AM65_IMP, 0, 0, L[4]->LI); } else { /* lda tmp1 */ X = NewCodeEntry (OP65_LDA, AM65_ZP, "tmp1", 0, L[4]->LI); } CS_InsertEntry (S, X, IP++); /* adc xxx */ X = NewCodeEntry (L[5]->OPC, L[5]->AM, L[5]->Arg, 0, L[5]->LI); CS_InsertEntry (S, X, IP++); /* sta ptr1+1 */ X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1+1", 0, L[9]->LI); CS_InsertEntry (S, X, IP++); /* ldy zzz */ X = NewCodeEntry (L[8]->OPC, L[8]->AM, L[8]->Arg, 0, L[8]->LI); CS_InsertEntry (S, X, IP++); /* lda (ptr1),y */ X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[9]->LI); CS_InsertEntry (S, X, IP++); /* tax */ X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, L[9]->LI); CS_InsertEntry (S, X, IP++); /* dey */ X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, L[9]->LI); CS_InsertEntry (S, X, IP++); /* lda (ptr1),y */ X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[9]->LI); CS_InsertEntry (S, X, IP++); /* Remove the old code */ CS_DelEntries (S, I, 10); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptPtrLoad11 (CodeSeg* S) /* Search for the sequence: ** ** clc ** adc xxx ** bcc L ** inx ** L: ldy #$00 ** jsr ldauidx ** ** and replace it by: ** ** ldy xxx ** sta ptr1 ** stx ptr1+1 ** ldx #$00 ** lda (ptr1),y */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[6]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (L[0]->OPC == OP65_CLC && CS_GetEntries (S, L+1, I+1, 5) && L[1]->OPC == OP65_ADC && (L[1]->AM == AM65_ABS || L[1]->AM == AM65_ZP || L[1]->AM == AM65_IMM) && (L[2]->OPC == OP65_BCC || L[2]->OPC == OP65_JCC) && L[2]->JumpTo != 0 && L[2]->JumpTo->Owner == L[4] && L[3]->OPC == OP65_INX && L[4]->OPC == OP65_LDY && CE_IsKnownImm (L[4], 0) && CE_IsCallTo (L[5], "ldauidx") && !CS_RangeHasLabel (S, I+1, 3) && !CE_HasLabel (L[5])) { CodeEntry* X; /* We will create all the new stuff behind the current one so ** we keep the line references. */ X = NewCodeEntry (OP65_LDY, L[1]->AM, L[1]->Arg, 0, L[0]->LI); CS_InsertEntry (S, X, I+6); /* sta ptr1 */ X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[0]->LI); CS_InsertEntry (S, X, I+7); /* stx ptr1+1 */ X = NewCodeEntry (OP65_STX, AM65_ZP, "ptr1+1", 0, L[0]->LI); CS_InsertEntry (S, X, I+8); /* ldx #$00 */ X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[0]->LI); CS_InsertEntry (S, X, I+9); X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[0]->LI); CS_InsertEntry (S, X, I+10); /* Remove the old code */ CS_DelEntries (S, I, 6); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptPtrLoad12 (CodeSeg* S) /* Search for the sequence: ** ** lda regbank+n ** ldx regbank+n+1 ** sta regsave ** stx regsave+1 ** clc ** adc #$01 ** bcc L0005 ** inx ** L: sta regbank+n ** stx regbank+n+1 ** lda regsave ** ldx regsave+1 ** ldy #$00 ** jsr ldauidx ** ** and replace it by: ** ** ldy #$00 ** ldx #$00 ** lda (regbank+n),y ** inc regbank+n ** bne L1 ** inc regbank+n+1 ** L1: tay <- only if flags are used ** ** This function must execute before OptPtrLoad7! ** */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[15]; unsigned Len; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (L[0]->OPC == OP65_LDA && L[0]->AM == AM65_ZP && strncmp (L[0]->Arg, "regbank+", 8) == 0 && (Len = strlen (L[0]->Arg)) > 0 && CS_GetEntries (S, L+1, I+1, 14) && !CS_RangeHasLabel (S, I+1, 7) && !CS_RangeHasLabel (S, I+9, 5) && L[1]->OPC == OP65_LDX && L[1]->AM == AM65_ZP && strncmp (L[1]->Arg, L[0]->Arg, Len) == 0 && strcmp (L[1]->Arg+Len, "+1") == 0 && L[2]->OPC == OP65_STA && L[2]->AM == AM65_ZP && strcmp (L[2]->Arg, "regsave") == 0 && L[3]->OPC == OP65_STX && L[3]->AM == AM65_ZP && strcmp (L[3]->Arg, "regsave+1") == 0 && L[4]->OPC == OP65_CLC && L[5]->OPC == OP65_ADC && CE_IsKnownImm (L[5], 1) && L[6]->OPC == OP65_BCC && L[6]->JumpTo != 0 && L[6]->JumpTo->Owner == L[8] && L[7]->OPC == OP65_INX && L[8]->OPC == OP65_STA && L[8]->AM == AM65_ZP && strcmp (L[8]->Arg, L[0]->Arg) == 0 && L[9]->OPC == OP65_STX && L[9]->AM == AM65_ZP && strcmp (L[9]->Arg, L[1]->Arg) == 0 && L[10]->OPC == OP65_LDA && L[10]->AM == AM65_ZP && strcmp (L[10]->Arg, "regsave") == 0 && L[11]->OPC == OP65_LDX && L[11]->AM == AM65_ZP && strcmp (L[11]->Arg, "regsave+1") == 0 && L[12]->OPC == OP65_LDY && CE_IsConstImm (L[12]) && CE_IsCallTo (L[13], "ldauidx")) { CodeEntry* X; CodeLabel* Label; /* Check if the instruction following the sequence uses the flags ** set by the load. If so, insert a test of the value in the ** accumulator. */ if (CE_UseLoadFlags (L[14])) { X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, L[13]->LI); CS_InsertEntry (S, X, I+14); } /* Attach a label to L[14]. This may be either the just inserted ** instruction, or the one following the sequence. */ Label = CS_GenLabel (S, L[14]); /* ldy #$xx */ X = NewCodeEntry (OP65_LDY, AM65_IMM, L[12]->Arg, 0, L[12]->LI); CS_InsertEntry (S, X, I+14); /* ldx #$xx */ X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[13]->LI); CS_InsertEntry (S, X, I+15); /* lda (regbank+n),y */ X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, L[0]->Arg, 0, L[13]->LI); CS_InsertEntry (S, X, I+16); /* inc regbank+n */ X = NewCodeEntry (OP65_INC, AM65_ZP, L[0]->Arg, 0, L[5]->LI); CS_InsertEntry (S, X, I+17); /* bne ... */ X = NewCodeEntry (OP65_BNE, AM65_BRA, Label->Name, Label, L[6]->LI); CS_InsertEntry (S, X, I+18); /* inc regbank+n+1 */ X = NewCodeEntry (OP65_INC, AM65_ZP, L[1]->Arg, 0, L[7]->LI); CS_InsertEntry (S, X, I+19); /* Delete the old code */ CS_DelEntries (S, I, 14); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptPtrLoad13 (CodeSeg* S) /* Search for the sequence: ** ** lda zp ** ldx zp+1 ** ldy xx ** jsr ldauidx ** ** and replace it by: ** ** ldy xx ** ldx #$00 ** lda (zp),y */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[4]; unsigned Len; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (L[0]->OPC == OP65_LDA && L[0]->AM == AM65_ZP && CS_GetEntries (S, L+1, I+1, 3) && !CS_RangeHasLabel (S, I+1, 3) && L[1]->OPC == OP65_LDX && L[1]->AM == AM65_ZP && (Len = strlen (L[0]->Arg)) > 0 && strncmp (L[0]->Arg, L[1]->Arg, Len) == 0 && strcmp (L[1]->Arg + Len, "+1") == 0 && L[2]->OPC == OP65_LDY && CE_IsCallTo (L[3], "ldauidx")) { CodeEntry* X; /* ldx #$00 */ X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[3]->LI); CS_InsertEntry (S, X, I+3); /* lda (zp),y */ X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, L[0]->Arg, 0, L[3]->LI); CS_InsertEntry (S, X, I+4); /* Remove the old code */ CS_DelEntry (S, I+5); CS_DelEntries (S, I, 2); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptPtrLoad14 (CodeSeg* S) /* Search for the sequence: ** ** lda zp ** ldx zp+1 ** (anything that doesn't change a/x) ** ldy xx ** jsr ldauidx ** ** and replace it by: ** ** lda zp ** ldx zp+1 ** (anything that doesn't change a/x) ** ldy xx ** ldx #$00 ** lda (zp),y */ { unsigned Changes = 0; unsigned I; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[5]; unsigned Len; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (L[0]->OPC == OP65_LDA && L[0]->AM == AM65_ZP && CS_GetEntries (S, L+1, I+1, 4) && !CS_RangeHasLabel (S, I+1, 4) && L[1]->OPC == OP65_LDX && L[1]->AM == AM65_ZP && (Len = strlen (L[0]->Arg)) > 0 && strncmp (L[0]->Arg, L[1]->Arg, Len) == 0 && strcmp (L[1]->Arg + Len, "+1") == 0 && (L[2]->Chg & REG_AX) == 0 && L[3]->OPC == OP65_LDY && CE_IsCallTo (L[4], "ldauidx")) { CodeEntry* X; /* ldx #$00 */ X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[3]->LI); CS_InsertEntry (S, X, I+5); /* lda (zp),y */ X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, L[0]->Arg, 0, L[3]->LI); CS_InsertEntry (S, X, I+6); /* Remove the old code */ CS_DelEntry (S, I+4); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptPtrLoad15 (CodeSeg* S) /* Search for the sequence: ** ** lda zp ** ldx zp+1 ** jsr pushax <- optional ** ldy xx ** jsr ldaxidx ** ** and replace it by: ** ** lda zp <- only if ** ldx zp+1 <- call to ** jsr pushax <- pushax present ** ldy xx ** lda (zp),y ** tax ** dey ** lda (zp),y */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[5]; unsigned Len; /* Check for the start of the sequence */ if (CS_GetEntries (S, L, I, 3) && L[0]->OPC == OP65_LDA && L[0]->AM == AM65_ZP && L[1]->OPC == OP65_LDX && L[1]->AM == AM65_ZP && !CS_RangeHasLabel (S, I+1, 2) && (Len = strlen (L[0]->Arg)) > 0 && strncmp (L[0]->Arg, L[1]->Arg, Len) == 0 && strcmp (L[1]->Arg + Len, "+1") == 0) { unsigned PushAX = CE_IsCallTo (L[2], "pushax"); /* Check for the remainder of the sequence */ if (CS_GetEntries (S, L+3, I+3, 1 + PushAX) && !CS_RangeHasLabel (S, I+3, 1 + PushAX) && L[2+PushAX]->OPC == OP65_LDY && CE_IsCallTo (L[3+PushAX], "ldaxidx")) { CodeEntry* X; /* lda (zp),y */ X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, L[0]->Arg, 0, L[3]->LI); CS_InsertEntry (S, X, I+PushAX+4); /* tax */ X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, L[3]->LI); CS_InsertEntry (S, X, I+PushAX+5); /* dey */ X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, L[3]->LI); CS_InsertEntry (S, X, I+PushAX+6); /* lda (zp),y */ X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, L[0]->Arg, 0, L[3]->LI); CS_InsertEntry (S, X, I+PushAX+7); /* Remove the old code */ CS_DelEntry (S, I+PushAX+3); if (!PushAX) { CS_DelEntries (S, I, 2); } /* Remember, we had changes */ ++Changes; } } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptPtrLoad16 (CodeSeg* S) /* Search for the sequence ** ** ldy ... ** jsr ldauidx ** ** and replace it by: ** ** stx ptr1+1 ** sta ptr1 ** ldy ... ** ldx #$00 ** lda (ptr1),y ** ** This step must be executed *after* OptPtrLoad1! */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[2]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (L[0]->OPC == OP65_LDY && CS_GetEntries (S, L+1, I+1, 1) && CE_IsCallTo (L[1], "ldauidx") && !CE_HasLabel (L[1])) { CodeEntry* X; /* stx ptr1+1 */ X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[1]->LI); CS_InsertEntry (S, X, I+2); /* sta ptr1 */ X = NewCodeEntry (OP65_STX, AM65_ZP, "ptr1+1", 0, L[1]->LI); CS_InsertEntry (S, X, I+3); /* ldy ... */ X = NewCodeEntry (L[0]->OPC, L[0]->AM, L[0]->Arg, 0, L[0]->LI); CS_InsertEntry (S, X, I+4); /* ldx #$00 */ X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[1]->LI); CS_InsertEntry (S, X, I+5); /* lda (ptr1),y */ X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[1]->LI); CS_InsertEntry (S, X, I+6); /* Delete the old code */ CS_DelEntries (S, I, 2); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptPtrLoad17 (CodeSeg* S) /* Search for the sequence ** ** ldy ... ** jsr ldaxidx ** ** and replace it by: ** ** sta ptr1 ** stx ptr1+1 ** ldy ... ** lda (ptr1),y ** tax ** dey ** lda (ptr1),y ** ** This step must be executed *after* OptPtrLoad9! While code size increases ** by more than 200%, inlining will greatly improve visibility for the ** optimizer, so often part of the code gets improved later. So we will mark ** the step with less than 200% so it gets executed when -Oi is in effect. */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[2]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (L[0]->OPC == OP65_LDY && CS_GetEntries (S, L+1, I+1, 1) && CE_IsCallTo (L[1], "ldaxidx") && !CE_HasLabel (L[1])) { CodeEntry* X; /* Store the high byte */ X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[0]->LI); CS_InsertEntry (S, X, I+2); /* Store the low byte */ X = NewCodeEntry (OP65_STX, AM65_ZP, "ptr1+1", 0, L[0]->LI); CS_InsertEntry (S, X, I+3); /* ldy ... */ X = NewCodeEntry (L[0]->OPC, L[0]->AM, L[0]->Arg, 0, L[0]->LI); CS_InsertEntry (S, X, I+4); /* lda (ptr1),y */ X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[1]->LI); CS_InsertEntry (S, X, I+5); /* tax */ X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, L[1]->LI); CS_InsertEntry (S, X, I+6); /* dey */ X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, L[1]->LI); CS_InsertEntry (S, X, I+7); /* lda (ptr1),y */ X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, "ptr1", 0, L[1]->LI); CS_InsertEntry (S, X, I+8); /* Delete original sequence */ CS_DelEntries (S, I, 2); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptPtrLoad18 (CodeSeg* S) /* Search for the sequence: ** ** ldx #$xx ** lda #$yy ** clc ** adc xxx ** bcc L ** inx ** L: ldy #$00 ** jsr ldauidx ** ** and replace it by: ** ** ldy xxx ** ldx #$00 ** lda $xxyy,y ** ** This is similar to OptPtrLoad3 but works on a constant address ** instead of a label. Also, the initial X and A loads are reversed. ** Must be run before OptPtrLoad7(). */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[8]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (L[0]->OPC == OP65_LDX && L[0]->AM == AM65_IMM && CS_GetEntries (S, L+1, I+1, 7) && L[1]->OPC == OP65_LDA && L[1]->AM == AM65_IMM && L[2]->OPC == OP65_CLC && L[3]->OPC == OP65_ADC && (L[3]->AM == AM65_ABS || L[3]->AM == AM65_ZP) && (L[4]->OPC == OP65_BCC || L[4]->OPC == OP65_JCC) && L[4]->JumpTo != 0 && L[4]->JumpTo->Owner == L[6] && L[5]->OPC == OP65_INX && L[6]->OPC == OP65_LDY && CE_IsKnownImm (L[6], 0) && CE_IsCallTo (L[7], "ldauidx") && !CS_RangeHasLabel (S, I+1, 5) && !CE_HasLabel (L[7]) && L[0]->Arg[0] == '$' && L[1]->Arg[0] == '$' && strlen (L[0]->Arg) == 3 && strlen (L[1]->Arg) == 3 ) { CodeEntry* X; char* Label; /* We will create all the new stuff behind the current one so ** we keep the line references. */ X = NewCodeEntry (OP65_LDY, L[3]->AM, L[3]->Arg, 0, L[0]->LI); CS_InsertEntry (S, X, I+8); X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[0]->LI); CS_InsertEntry (S, X, I+9); Label = xmalloc(6); sprintf(Label, "$%s%s", L[0]->Arg+1, L[1]->Arg+1); X = NewCodeEntry (OP65_LDA, AM65_ABSY, Label, 0, L[0]->LI); CS_InsertEntry (S, X, I+10); xfree (Label); /* Remove the old code */ CS_DelEntries (S, I, 8); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptPtrLoad19 (CodeSeg* S) /* Search for the sequence: ** ** ldx #0 ** and #mask (any value < 0x80) ** jsr aslax1/shlax1 ** clc ** adc #<(label+0) ** tay ** txa ** adc #>(label+0) ** tax ** tya ** ldy #$01 ** jsr ldaxidx ** ** and replace it by: ** ** and #mask (remove if == 0x7F) ** asl ** tay ** lda label,y ** ldx label+1,y */ { unsigned Changes = 0; unsigned I; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[12]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (L[0]->OPC == OP65_LDX && CE_IsKnownImm(L[0], 0) && CS_GetEntries (S, L+1, I+1, 11) && L[1]->OPC == OP65_AND && L[1]->AM == AM65_IMM && CE_HasNumArg (L[1]) && L[1]->Num <= 0x7F && L[2]->OPC == OP65_JSR && L[3]->OPC == OP65_CLC && L[4]->OPC == OP65_ADC && L[5]->OPC == OP65_TAY && L[6]->OPC == OP65_TXA && L[7]->OPC == OP65_ADC && L[8]->OPC == OP65_TAX && L[9]->OPC == OP65_TYA && L[10]->OPC == OP65_LDY && CE_IsKnownImm(L[10], 1) && L[4]->Arg[0] == '<' && L[7]->Arg[0] == '>' && strlen(L[4]->Arg) > 3 && strlen(L[7]->Arg) > 3 && strcmp(L[4]->Arg+1, L[7]->Arg+1) == 0 && (strcmp (L[2]->Arg, "aslax1") == 0 || strcmp (L[2]->Arg, "shlax1") == 0) && CE_IsCallTo (L[11], "ldaxidx") && !CS_RangeHasLabel (S, I+1, 11)) { CodeEntry* X; char* Label; int Len = strlen(L[4]->Arg); /* Track the insertion point */ unsigned IP = I + 12; /* asl a */ X = NewCodeEntry (OP65_ASL, AM65_ACC, "a", 0, L[2]->LI); CS_InsertEntry (S, X, IP++); /* tay */ X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, L[2]->LI); CS_InsertEntry (S, X, IP++); /* lda label,y */ /* allocate Label memory */ Label = memcpy (xmalloc (Len), L[4]->Arg+2, Len-3); Label[Len-3] = '\0'; X = NewCodeEntry (OP65_LDA, AM65_ABSY, Label, 0, L[10]->LI); CS_InsertEntry (S, X, IP++); /* ldx label+1,y */ strcpy(&Label[Len-3], "+1"); X = NewCodeEntry (OP65_LDX, AM65_ABSY, Label, 0, L[10]->LI); CS_InsertEntry (S, X, IP++); /* free Label memory */ xfree (Label); /* Remove the old code */ /* Remove the AND only if it's == 0x7F, since ASL erases high bit */ if (L[1]->Num == 0x7F) { CS_DelEntries (S, I+1, 11); } else { CS_DelEntries (S, I+2, 10); } /* Remove the ldx #0 */ CS_DelEntry(S, I); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/coptptrload.h��������������������������������������������������������������������0000664�0000000�0000000�00000022330�13473601511�0016240�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* coptptrload.h */ /* */ /* Optimize loads through pointers */ /* */ /* */ /* */ /* (C) 2001-2009 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef COPTPTRLOAD_H #define COPTPTRLOAD_H /* cc65 */ #include "codeseg.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned OptPtrLoad1 (CodeSeg* S); /* Search for the sequence: ** ** clc ** adc xxx ** tay ** txa ** adc yyy ** tax ** tya ** ldy ** jsr ldauidx ** ** and replace it by: ** ** clc ** adc xxx ** sta ptr1 ** txa ** adc yyy ** sta ptr1+1 ** ldy ** ldx #$00 ** lda (ptr1),y */ unsigned OptPtrLoad2 (CodeSeg* S); /* Search for the sequence: ** ** adc xxx ** pha ** txa ** iny ** adc yyy ** tax ** pla ** ldy ** jsr ldauidx ** ** and replace it by: ** ** adc xxx ** sta ptr1 ** txa ** iny ** adc yyy ** sta ptr1+1 ** ldy ** ldx #$00 ** lda (ptr1),y */ unsigned OptPtrLoad3 (CodeSeg* S); /* Search for the sequence: ** ** lda #<(label+0) ** ldx #>(label+0) ** clc ** adc xxx ** bcc L ** inx ** L: ldy #$00 ** jsr ldauidx ** ** and replace it by: ** ** ldy xxx ** ldx #$00 ** lda label,y */ unsigned OptPtrLoad4 (CodeSeg* S); /* Search for the sequence: ** ** lda #<(label+0) ** ldx #>(label+0) ** ldy #$xx ** clc ** adc (sp),y ** bcc L ** inx ** L: ldy #$00 ** jsr ldauidx ** ** and replace it by: ** ** ldy #$xx ** lda (sp),y ** tay ** ldx #$00 ** lda label,y */ unsigned OptPtrLoad5 (CodeSeg* S); /* Search for the sequence: ** ** jsr pushax ** ldx #$00 ** lda yyy ** jsr tosaddax ** ldy #$00 ** jsr ldauidx ** ** and replace it by: ** ** sta ptr1 ** stx ptr1+1 ** ldy yyy ** lda (ptr1),y */ unsigned OptPtrLoad6 (CodeSeg* S); /* Search for the sequence: ** ** jsr pushax ** ldy xxx ** ldx #$00 ** lda (sp),y ** jsr tosaddax ** ldy #$00 ** jsr ldauidx ** ** and replace it by: ** ** sta ptr1 ** stx ptr1+1 ** ldy xxx ** lda (sp),y ** tay ** lda (ptr1),y */ unsigned OptPtrLoad7 (CodeSeg* S); /* Search for the sequence: ** ** jsr aslax1/shlax1 ** clc ** adc xxx ** tay ** txa ** adc yyy ** tax ** tya ** ldy zzz ** jsr ldaxidx ** ** and replace it by: ** ** stx tmp1 ** asl a ** rol tmp1 ** clc ** adc xxx ** sta ptr1 ** lda tmp1 ** adc yyy ** sta ptr1+1 ** ldy zzz ** lda (ptr1),y ** tax ** dey ** lda (ptr1),y */ unsigned OptPtrLoad11 (CodeSeg* S); /* Search for the sequence: ** ** clc ** adc xxx ** bcc L ** inx ** L: ldy #$00 ** jsr ldauidx ** ** and replace it by: ** ** ldy xxx ** sta ptr1 ** stx ptr1+1 ** ldx #$00 ** lda (ptr1),y */ unsigned OptPtrLoad12 (CodeSeg* S); /* Search for the sequence: ** ** lda regbank+n ** ldx regbank+n+1 ** sta regsave ** stx regsave+1 ** clc ** adc #$01 ** bcc L0005 ** inx ** L: sta regbank+n ** stx regbank+n+1 ** lda regsave ** ldx regsave+1 ** ldy #$00 ** jsr ldauidx ** ** and replace it by: ** ** ldy #$00 ** ldx #$00 ** lda (regbank+n),y ** inc regbank+n ** bne L1 ** inc regbank+n+1 ** L1: tay <- only if flags are used ** ** This function must execute before OptPtrLoad7! ** */ unsigned OptPtrLoad13 (CodeSeg* S); /* Search for the sequence: ** ** lda zp ** ldx zp+1 ** ldy xx ** jsr ldauidx ** ** and replace it by: ** ** ldy xx ** ldx #$00 ** lda (zp),y */ unsigned OptPtrLoad14 (CodeSeg* S); /* Search for the sequence: ** ** lda zp ** ldx zp+1 ** (anything that doesn't change a/x) ** ldy xx ** jsr ldauidx ** ** and replace it by: ** ** lda zp ** ldx zp+1 ** (anything that doesn't change a/x) ** ldy xx ** ldx #$00 ** lda (zp),y ** ** Must execute before OptPtrLoad10! */ unsigned OptPtrLoad15 (CodeSeg* S); /* Search for the sequence: ** ** lda zp ** ldx zp+1 ** ldy xx ** jsr ldaxidx ** ** and replace it by: ** ** ldy xx ** lda (zp),y ** tax ** dey ** lda (zp),y */ unsigned OptPtrLoad16 (CodeSeg* S); /* Search for the sequence ** ** ldy ... ** jsr ldauidx ** ** and replace it by: ** ** ldy ... ** stx ptr1+1 ** sta ptr1 ** ldx #$00 ** lda (ptr1),y ** ** This step must be executed *after* OptPtrLoad1! */ unsigned OptPtrLoad17 (CodeSeg* S); /* Search for the sequence ** ** ldy ... ** jsr ldaxidx ** ** and replace it by: ** ** ldy ... ** sta ptr1 ** stx ptr1+1 ** lda (ptr1),y ** tax ** dey ** lda (ptr1),y ** ** This step must be executed *after* OptPtrLoad9! While code size increases ** by more than 200%, inlining will greatly improve visibility for the ** optimizer, so often part of the code gets improved later. So we will mark ** the step with less than 200% so it gets executed when -Oi is in effect. */ unsigned OptPtrLoad18 (CodeSeg* S); /* Search for the sequence: ** ** ldx #$xx ** lda #$yy ** clc ** adc xxx ** bcc L ** inx ** L: ldy #$00 ** jsr ldauidx ** ** and replace it by: ** ** ldy xxx ** ldx #$00 ** lda $xxyy,y ** ** This is similar to OptPtrLoad3 but works on a constant address ** instead of a label. Also, the initial X and A loads are reversed. */ unsigned OptPtrLoad19 (CodeSeg* S); /* Search for the sequence: ** ** ldx #0 ** and #mask (any value < 0x80) ** jsr aslax1/shlax1 ** clc ** adc #<(label+0) ** tay ** txa ** adc #>(label+0) ** tax ** tya ** ldy #$01 ** jsr ldaxidx ** ** and replace it by: ** ** and #mask (remove if == 0x7F) ** asl ** tay ** lda label,y ** ldx label+1,y */ /* End of coptptrload.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/coptptrstore.c�������������������������������������������������������������������0000664�0000000�0000000�00000062304�13473601511�0016455�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* coptptrstore.c */ /* */ /* Optimize stores through pointers */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* common */ #include "chartype.h" #include "strbuf.h" #include "xmalloc.h" #include "xsprintf.h" /* cc65 */ #include "codeent.h" #include "codeinfo.h" #include "coptptrstore.h" /*****************************************************************************/ /* Helper functions */ /*****************************************************************************/ static unsigned OptPtrStore1Sub (CodeSeg* S, unsigned I, CodeEntry** const L) /* Check if this is one of the allowed suboperation for OptPtrStore1 */ { /* Check for a label attached to the entry */ if (CE_HasLabel (L[0])) { return 0; } /* Check for single insn sub ops */ if (L[0]->OPC == OP65_AND || L[0]->OPC == OP65_EOR || L[0]->OPC == OP65_ORA || (L[0]->OPC == OP65_JSR && (strncmp (L[0]->Arg, "shlax", 5) == 0 || strncmp (L[0]->Arg, "shrax", 5) == 0) && strlen (L[0]->Arg) == 6 && IsDigit (L[0]->Arg[5]))) { /* One insn */ return 1; } else if (L[0]->OPC == OP65_CLC && (L[1] = CS_GetNextEntry (S, I)) != 0 && L[1]->OPC == OP65_ADC && !CE_HasLabel (L[1])) { return 2; } else if (L[0]->OPC == OP65_SEC && (L[1] = CS_GetNextEntry (S, I)) != 0 && L[1]->OPC == OP65_SBC && !CE_HasLabel (L[1])) { return 2; } /* Not found */ return 0; } static const char* LoadAXZP (CodeSeg* S, unsigned I) /* If the two instructions preceeding S/I are a load of A/X from a two byte ** zero byte location, return the name of the zero page location. Otherwise ** return NULL. */ { CodeEntry* L[2]; unsigned Len; if (I >= 2 && CS_GetEntries (S, L, I-2, 2) && L[0]->OPC == OP65_LDA && L[0]->AM == AM65_ZP && L[1]->OPC == OP65_LDX && L[1]->AM == AM65_ZP && !CE_HasLabel (L[1]) && (Len = strlen (L[0]->Arg)) == strlen (L[1]->Arg) - 2 && memcmp (L[0]->Arg, L[1]->Arg, Len) == 0 && L[1]->Arg[Len] == '+' && L[1]->Arg[Len+1] == '1') { /* Return the label */ return L[0]->Arg; } else { /* Not found */ return 0; } } static const char* LoadAXImm (CodeSeg* S, unsigned I) /* If the instructions preceeding S/I are a load of A/X of a constant value ** or a word sized address label, return the address of the location as a ** string. ** Beware: In case of a numeric value, the result is returned in static ** storage which is overwritten with each call. */ { static StrBuf Buf = STATIC_STRBUF_INITIALIZER; CodeEntry* L[2]; CodeEntry* ALoad; CodeEntry* XLoad; unsigned Len; /* Fetch entry at I and check if A/X is known */ L[0] = CS_GetEntry (S, I); if (L[0] != 0 && RegValIsKnown (L[0]->RI->In.RegA) && RegValIsKnown (L[0]->RI->In.RegX)) { /* Numeric argument - get low and high byte */ unsigned Lo = (L[0]->RI->In.RegA & 0xFF); unsigned Hi = (L[0]->RI->In.RegX & 0xFF); /* Format into buffer */ SB_Printf (&Buf, "$%04X", Lo | (Hi << 8)); /* Return the address as a string */ return SB_GetConstBuf (&Buf); } /* Search back for the two instructions loading A and X. Abort ** the search if the registers are changed in any other way or ** if a label is reached while we don't have both loads. */ ALoad = 0; XLoad = 0; while (I-- > 0) { /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check for the loads of A and X */ if (ALoad == 0 && E->OPC == OP65_LDA && E->AM == AM65_IMM) { ALoad = E; } else if (E->Chg & REG_A) { /* A is changed before we get the load */ return 0; } else if (XLoad == 0 && E->OPC == OP65_LDX && E->AM == AM65_IMM) { XLoad = E; } else if (E->Chg & REG_X) { /* X is changed before we get the load */ return 0; } if (ALoad != 0 && XLoad != 0) { /* We have both */ break; } /* If we have a label, before both are found, bail out */ if (CE_HasLabel (E)) { return 0; } } /* Check for a load of a label address */ if ((Len = strlen (ALoad->Arg)) > 3 && ALoad->Arg[0] == '<' && ALoad->Arg[1] == '(' && strlen (XLoad->Arg) == Len && XLoad->Arg[0] == '>' && memcmp (ALoad->Arg+1, XLoad->Arg+1, Len-1) == 0) { /* Load of an address label */ SB_CopyBuf (&Buf, ALoad->Arg + 2, Len - 3); SB_Terminate (&Buf); return SB_GetConstBuf (&Buf); } /* Not found */ return 0; } /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned OptPtrStore1 (CodeSeg* S) /* Search for the sequence: ** ** clc ** adc xxx ** bcc L ** inx ** L: jsr pushax ** ldx #$00 ** lda yyy ** ldy #$00 ** jsr staspidx ** ** and replace it by: ** ** sta ptr1 ** stx ptr1+1 ** ldy xxx ** ldx #$00 ** lda yyy ** sta (ptr1),y ** ** or by ** ** ldy xxx ** ldx #$00 ** lda yyy ** sta (zp),y ** ** or by ** ** ldy xxx ** ldx #$00 ** lda yyy ** sta label,y ** ** or by ** ** ldy xxx ** ldx #$00 ** lda yyy ** sta $xxxx,y ** ** depending on the code preceeding the sequence above. */ { unsigned Changes = 0; unsigned I; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[9]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (L[0]->OPC == OP65_CLC && CS_GetEntries (S, L+1, I+1, 8) && L[1]->OPC == OP65_ADC && (L[1]->AM == AM65_ABS || L[1]->AM == AM65_ZP || L[1]->AM == AM65_IMM || (L[1]->AM == AM65_ZP_INDY && RegValIsKnown (L[1]->RI->In.RegY))) && (L[2]->OPC == OP65_BCC || L[2]->OPC == OP65_JCC) && L[2]->JumpTo != 0 && L[2]->JumpTo->Owner == L[4] && L[3]->OPC == OP65_INX && CE_IsCallTo (L[4], "pushax") && L[5]->OPC == OP65_LDX && L[6]->OPC == OP65_LDA && L[7]->OPC == OP65_LDY && CE_IsKnownImm (L[7], 0) && CE_IsCallTo (L[8], "staspidx") && !CS_RangeHasLabel (S, I+1, 3) && !CS_RangeHasLabel (S, I+5, 4)) { CodeEntry* X; const char* Loc; am_t AM; /* Track the insertion point */ unsigned IP = I + 9; if ((Loc = LoadAXZP (S, I)) != 0) { /* If the sequence is preceeded by a load of a ZP value, ** we can use this ZP value as a pointer using ZP ** indirect Y addressing. */ AM = AM65_ZP_INDY; } else if ((Loc = LoadAXImm (S, I)) != 0) { /* If the sequence is preceeded by a load of an immediate ** value, we can use this absolute value as an address ** using absolute indexed Y addressing. */ AM = AM65_ABSY; } /* If we don't have a store location, we use ptr1 with zp ** indirect Y addressing. We must store the value in A/X into ** ptr1 in this case. */ if (Loc == 0) { /* Must use ptr1 */ Loc = "ptr1"; AM = AM65_ZP_INDY; X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[8]->LI); CS_InsertEntry (S, X, IP++); X = NewCodeEntry (OP65_STX, AM65_ZP, "ptr1+1", 0, L[8]->LI); CS_InsertEntry (S, X, IP++); } /* If the index is loaded from (zp),y, we cannot do that directly. ** Note: In this case, the Y register will contain the correct ** value after removing the old code, so we don't need to load ** it here. */ if (L[1]->AM == AM65_ZP_INDY) { X = NewCodeEntry (OP65_LDA, L[1]->AM, L[1]->Arg, 0, L[1]->LI); CS_InsertEntry (S, X, IP++); X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, L[1]->LI); CS_InsertEntry (S, X, IP++); } else { X = NewCodeEntry (OP65_LDY, L[1]->AM, L[1]->Arg, 0, L[1]->LI); CS_InsertEntry (S, X, IP++); } X = NewCodeEntry (OP65_LDX, L[5]->AM, L[5]->Arg, 0, L[5]->LI); CS_InsertEntry (S, X, IP++); X = NewCodeEntry (OP65_LDA, L[6]->AM, L[6]->Arg, 0, L[6]->LI); CS_InsertEntry (S, X, IP++); X = NewCodeEntry (OP65_STA, AM, Loc, 0, L[8]->LI); CS_InsertEntry (S, X, IP++); /* Remove the old code */ CS_DelEntries (S, I, 9); /* Skip most of the generated replacement code */ I += 3; /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptPtrStore2 (CodeSeg* S) /* Search for the sequence: ** ** clc ** adc xxx ** bcc L ** inx ** L: jsr pushax ** ldy yyy ** ldx #$00 ** lda (sp),y ** ldy #$00 ** jsr staspidx ** ** and replace it by: ** ** sta ptr1 ** stx ptr1+1 ** ldy yyy-2 ** ldx #$00 ** lda (sp),y ** ldy xxx ** sta (ptr1),y ** ** or by ** ** ldy yyy-2 ** ldx #$00 ** lda (sp),y ** ldy xxx ** sta (zp),y ** ** or by ** ** ldy yyy-2 ** ldx #$00 ** lda (sp),y ** ldy xxx ** sta label,y ** ** or by ** ** ldy yyy-2 ** ldx #$00 ** lda (sp),y ** ldy xxx ** sta $xxxx,y ** ** depending on the code preceeding the sequence above. */ { unsigned Changes = 0; unsigned I; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[10]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (L[0]->OPC == OP65_CLC && CS_GetEntries (S, L+1, I+1, 9) && L[1]->OPC == OP65_ADC && (L[1]->AM == AM65_ABS || L[1]->AM == AM65_ZP || L[1]->AM == AM65_IMM || (L[1]->AM == AM65_ZP_INDY && RegValIsKnown (L[1]->RI->In.RegY))) && (L[2]->OPC == OP65_BCC || L[2]->OPC == OP65_JCC) && L[2]->JumpTo != 0 && L[2]->JumpTo->Owner == L[4] && L[3]->OPC == OP65_INX && CE_IsCallTo (L[4], "pushax") && L[5]->OPC == OP65_LDY && CE_IsConstImm (L[5]) && L[6]->OPC == OP65_LDX && L[7]->OPC == OP65_LDA && L[7]->AM == AM65_ZP_INDY && strcmp (L[7]->Arg, "sp") == 0 && L[8]->OPC == OP65_LDY && (L[8]->AM == AM65_ABS || L[8]->AM == AM65_ZP || L[8]->AM == AM65_IMM) && CE_IsCallTo (L[9], "staspidx") && !CS_RangeHasLabel (S, I+1, 3) && !CS_RangeHasLabel (S, I+5, 5)) { CodeEntry* X; const char* Arg; const char* Loc; am_t AM; /* Track the insertion point */ unsigned IP = I + 10; if ((Loc = LoadAXZP (S, I)) != 0) { /* If the sequence is preceeded by a load of a ZP value, ** we can use this ZP value as a pointer using ZP ** indirect Y addressing. */ AM = AM65_ZP_INDY; } else if ((Loc = LoadAXImm (S, I)) != 0) { /* If the sequence is preceeded by a load of an immediate ** value, we can use this absolute value as an address ** using absolute indexed Y addressing. */ AM = AM65_ABSY; } /* If we don't have a store location, we use ptr1 with zp ** indirect Y addressing. We must store the value in A/X into ** ptr1 in this case. */ if (Loc == 0) { /* Must use ptr1 */ Loc = "ptr1"; AM = AM65_ZP_INDY; X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[8]->LI); CS_InsertEntry (S, X, IP++); X = NewCodeEntry (OP65_STX, AM65_ZP, "ptr1+1", 0, L[8]->LI); CS_InsertEntry (S, X, IP++); } /* Generate four different replacements depending on the addressing ** mode of the store and from where the index is loaded: ** ** 1. If the index is not loaded ZP indirect Y, we can use Y for ** the store index. ** ** 2. If the index is loaded ZP indirect Y and we store absolute ** indexed, we need Y to load the index and will therefore ** use X as index for the store. The disadvantage is that we ** need to reload X later. ** ** 3. If the index is loaded ZP indirect Y and we store ZP indirect ** Y, we must use Y for load and store and must therefore save ** the A register when loading Y the second time. */ if (L[1]->AM != AM65_ZP_INDY) { /* Case 1 */ Arg = MakeHexArg (L[5]->Num - 2); X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[5]->LI); CS_InsertEntry (S, X, IP++); X = NewCodeEntry (OP65_LDX, L[6]->AM, L[6]->Arg, 0, L[6]->LI); CS_InsertEntry (S, X, IP++); X = NewCodeEntry (OP65_LDA, L[7]->AM, L[7]->Arg, 0, L[7]->LI); CS_InsertEntry (S, X, IP++); X = NewCodeEntry (OP65_LDY, L[1]->AM, L[1]->Arg, 0, L[1]->LI); CS_InsertEntry (S, X, IP++); X = NewCodeEntry (OP65_STA, AM, Loc, 0, L[9]->LI); CS_InsertEntry (S, X, IP++); } else if (AM == AM65_ABSY) { /* Case 2 */ X = NewCodeEntry (OP65_LDA, L[1]->AM, L[1]->Arg, 0, L[1]->LI); CS_InsertEntry (S, X, IP++); X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, L[1]->LI); CS_InsertEntry (S, X, IP++); Arg = MakeHexArg (L[5]->Num - 2); X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[5]->LI); CS_InsertEntry (S, X, IP++); X = NewCodeEntry (OP65_LDA, L[7]->AM, L[7]->Arg, 0, L[7]->LI); CS_InsertEntry (S, X, IP++); X = NewCodeEntry (OP65_STA, AM65_ABSX, Loc, 0, L[9]->LI); CS_InsertEntry (S, X, IP++); X = NewCodeEntry (OP65_LDX, L[6]->AM, L[6]->Arg, 0, L[6]->LI); CS_InsertEntry (S, X, IP++); } else { /* Case 3 */ Arg = MakeHexArg (L[5]->Num - 2); X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[5]->LI); CS_InsertEntry (S, X, IP++); X = NewCodeEntry (OP65_LDX, L[6]->AM, L[6]->Arg, 0, L[6]->LI); CS_InsertEntry (S, X, IP++); X = NewCodeEntry (OP65_LDA, L[7]->AM, L[7]->Arg, 0, L[7]->LI); CS_InsertEntry (S, X, IP++); X = NewCodeEntry (OP65_PHA, AM65_IMP, 0, 0, L[6]->LI); CS_InsertEntry (S, X, IP++); Arg = MakeHexArg (L[1]->RI->In.RegY); X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[1]->LI); CS_InsertEntry (S, X, IP++); X = NewCodeEntry (OP65_LDA, L[1]->AM, L[1]->Arg, 0, L[1]->LI); CS_InsertEntry (S, X, IP++); X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, L[1]->LI); CS_InsertEntry (S, X, IP++); X = NewCodeEntry (OP65_PLA, AM65_IMP, 0, 0, L[6]->LI); CS_InsertEntry (S, X, IP++); X = NewCodeEntry (OP65_STA, AM, Loc, 0, L[9]->LI); CS_InsertEntry (S, X, IP++); } /* Remove the old code */ CS_DelEntries (S, I, 10); /* Skip most of the generated replacement code */ I += 4; /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptPtrStore3 (CodeSeg* S) /* Search for the sequence: ** ** jsr pushax ** ldy xxx ** jsr ldauidx ** subop ** ldy yyy ** jsr staspidx ** ** and replace it by: ** ** sta ptr1 ** stx ptr1+1 ** ldy xxx ** ldx #$00 ** lda (ptr1),y ** subop ** ldy yyy ** sta (ptr1),y ** ** In case a/x is loaded from the register bank before the pushax, we can even ** use the register bank instead of ptr1. */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { unsigned K; CodeEntry* L[10]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (CE_IsCallTo (L[0], "pushax") && CS_GetEntries (S, L+1, I+1, 3) && L[1]->OPC == OP65_LDY && CE_IsConstImm (L[1]) && !CE_HasLabel (L[1]) && CE_IsCallTo (L[2], "ldauidx") && !CE_HasLabel (L[2]) && (K = OptPtrStore1Sub (S, I+3, L+3)) > 0 && CS_GetEntries (S, L+3+K, I+3+K, 2) && L[3+K]->OPC == OP65_LDY && CE_IsConstImm (L[3+K]) && !CE_HasLabel (L[3+K]) && CE_IsCallTo (L[4+K], "staspidx") && !CE_HasLabel (L[4+K])) { const char* RegBank = 0; const char* ZPLoc = "ptr1"; CodeEntry* X; /* Get the preceeding two instructions and check them. We check ** for: ** lda regbank+n ** ldx regbank+n+1 */ if (I > 1) { CodeEntry* P[2]; P[0] = CS_GetEntry (S, I-2); P[1] = CS_GetEntry (S, I-1); if (P[0]->OPC == OP65_LDA && P[0]->AM == AM65_ZP && P[1]->OPC == OP65_LDX && P[1]->AM == AM65_ZP && !CE_HasLabel (P[1]) && strncmp (P[0]->Arg, "regbank+", 8) == 0) { unsigned Len = strlen (P[0]->Arg); if (strncmp (P[0]->Arg, P[1]->Arg, Len) == 0 && P[1]->Arg[Len+0] == '+' && P[1]->Arg[Len+1] == '1' && P[1]->Arg[Len+2] == '\0') { /* Ok, found. Use the name of the register bank */ RegBank = ZPLoc = P[0]->Arg; } } } /* Insert the load via the zp pointer */ X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, L[3]->LI); CS_InsertEntry (S, X, I+3); X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, ZPLoc, 0, L[2]->LI); CS_InsertEntry (S, X, I+4); /* Insert the store through the zp pointer */ X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, ZPLoc, 0, L[3]->LI); CS_InsertEntry (S, X, I+6+K); /* Delete the old code */ CS_DelEntry (S, I+7+K); /* jsr spaspidx */ CS_DelEntry (S, I+2); /* jsr ldauidx */ /* Create and insert the stores into the zp pointer if needed */ if (RegBank == 0) { X = NewCodeEntry (OP65_STA, AM65_ZP, "ptr1", 0, L[0]->LI); CS_InsertEntry (S, X, I+1); X = NewCodeEntry (OP65_STX, AM65_ZP, "ptr1+1", 0, L[0]->LI); CS_InsertEntry (S, X, I+2); } /* Delete more old code. Do it here to keep a label attached to ** entry I in place. */ CS_DelEntry (S, I); /* jsr pushax */ /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/coptptrstore.h�������������������������������������������������������������������0000664�0000000�0000000�00000011753�13473601511�0016464�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* coptptrstore.h */ /* */ /* Optimize stores through pointers */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef COPTPTRSTORE_H #define COPTPTRSTORE_H /* cc65 */ #include "codeseg.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned OptPtrStore1 (CodeSeg* S); /* Search for the sequence: ** ** clc ** adc xxx ** bcc L ** inx ** L: jsr pushax ** ldx #$00 ** lda yyy ** ldy #$00 ** jsr staspidx ** ** and replace it by: ** ** sta ptr1 ** stx ptr1+1 ** ldy xxx ** ldx #$00 ** lda yyy ** sta (ptr1),y ** ** or by ** ** ldy xxx ** ldx #$00 ** lda yyy ** sta (zp),y ** ** or by ** ** ldy xxx ** ldx #$00 ** lda yyy ** sta label,y ** ** or by ** ** ldy xxx ** ldx #$00 ** lda yyy ** sta $xxxx,y ** ** depending on the two instructions preceeding the sequence above. */ unsigned OptPtrStore2 (CodeSeg* S); /* Search for the sequence: ** ** clc ** adc xxx ** bcc L ** inx ** L: jsr pushax ** ldy yyy ** ldx #$00 ** lda (sp),y ** ldy #$00 ** jsr staspidx ** ** and replace it by: ** ** sta ptr1 ** stx ptr1+1 ** ldy yyy-2 ** ldx #$00 ** lda (sp),y ** ldy xxx ** sta (ptr1),y ** ** or by ** ** ldy yyy-2 ** ldx #$00 ** lda (sp),y ** ldy xxx ** sta (zp),y ** ** or by ** ** ldy yyy-2 ** ldx #$00 ** lda (sp),y ** ldy xxx ** sta label,y ** ** or by ** ** ldy yyy-2 ** ldx #$00 ** lda (sp),y ** ldy xxx ** sta $xxxx,y ** ** depending on the code preceeding the sequence above. */ unsigned OptPtrStore3 (CodeSeg* S); /* Search for the sequence: ** ** jsr pushax ** ldy xxx ** jsr ldauidx ** subop ** ldy yyy ** jsr staspidx ** ** and replace it by: ** ** sta ptr1 ** stx ptr1+1 ** ldy xxx ** ldx #$00 ** lda (ptr1),y ** subop ** ldy yyy ** sta (ptr1),y ** ** In case a/x is loaded from the register bank before the pushax, we can even ** use the register bank instead of ptr1. */ /* End of coptptrstore.h */ #endif ���������������������cc65-2.18/src/cc65/coptpush.c�����������������������������������������������������������������������0000664�0000000�0000000�00000012772�13473601511�0015556�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* coptpush.c */ /* */ /* Optimize push sequences */ /* */ /* */ /* */ /* (C) 2001-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* cc65 */ #include "codeent.h" #include "codeinfo.h" #include "coptpush.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned OptPush1 (CodeSeg* S) /* Given a sequence ** ** jsr ldaxysp ** jsr pushax ** ** If a/x are not used later, and Y is known, replace that by ** ** ldy #xx+2 ** jsr pushwysp ** ** saving 3 bytes and several cycles. */ { unsigned I; unsigned Changes = 0; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[2]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (CE_IsCallTo (L[0], "ldaxysp") && RegValIsKnown (L[0]->RI->In.RegY) && L[0]->RI->In.RegY < 0xFE && (L[1] = CS_GetNextEntry (S, I)) != 0 && !CE_HasLabel (L[1]) && CE_IsCallTo (L[1], "pushax") && !RegAXUsed (S, I+2)) { /* Insert new code behind the pushax */ const char* Arg; CodeEntry* X; /* ldy #xx+1 */ Arg = MakeHexArg (L[0]->RI->In.RegY+2); X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, L[0]->LI); CS_InsertEntry (S, X, I+2); /* jsr pushwysp */ X = NewCodeEntry (OP65_JSR, AM65_ABS, "pushwysp", 0, L[1]->LI); CS_InsertEntry (S, X, I+3); /* Delete the old code */ CS_DelEntries (S, I, 2); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptPush2 (CodeSeg* S) /* A sequence ** ** jsr ldaxidx ** jsr pushax ** ** may get replaced by ** ** jsr pushwidx */ { unsigned I; unsigned Changes = 0; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[2]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (CE_IsCallTo (L[0], "ldaxidx") && (L[1] = CS_GetNextEntry (S, I)) != 0 && !CE_HasLabel (L[1]) && CE_IsCallTo (L[1], "pushax")) { /* Insert new code behind the pushax */ CodeEntry* X; /* jsr pushwidx */ X = NewCodeEntry (OP65_JSR, AM65_ABS, "pushwidx", 0, L[1]->LI); CS_InsertEntry (S, X, I+2); /* Delete the old code */ CS_DelEntries (S, I, 2); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } ������cc65-2.18/src/cc65/coptpush.h�����������������������������������������������������������������������0000664�0000000�0000000�00000006400�13473601511�0015552�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* coptpush.h */ /* */ /* Optimize push sequences */ /* */ /* */ /* */ /* (C) 2001-2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef COPTPUSH_H #define COPTPUSH_H /* cc65 */ #include "codeseg.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned OptPush1 (CodeSeg* S); /* Given a sequence ** ** ldy #xx ** jsr ldaxysp ** jsr pushax ** ** If a/x are not used later, replace that by ** ** ldy #xx+2 ** jsr pushwysp ** ** saving 3 bytes and several cycles. */ unsigned OptPush2 (CodeSeg* S); /* A sequence ** ** jsr ldaxidx ** jsr pushax ** ** may get replaced by ** ** jsr pushwidx */ /* End of coptpush.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/coptshift.c����������������������������������������������������������������������0000664�0000000�0000000�00000061643�13473601511�0015715�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* coptshift.c */ /* */ /* Optimize shifts */ /* */ /* */ /* */ /* (C) 2001-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "chartype.h" /* cc65 */ #include "codeent.h" #include "codeinfo.h" #include "coptshift.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Shift types. Shift type is in the first byte, shift count in the second */ enum { SHIFT_NONE = 0x0000, /* Masks */ SHIFT_MASK_COUNT = 0x00FF, SHIFT_MASK_DIR = 0x0F00, SHIFT_MASK_MODE = 0xF000, /* Arithmetic or logical */ SHIFT_MASK_TYPE = SHIFT_MASK_DIR | SHIFT_MASK_MODE, /* Shift counts */ SHIFT_COUNT_Y = 0x0000, /* Count is in Y register */ SHIFT_COUNT_1 = 0x0001, SHIFT_COUNT_2 = 0x0002, SHIFT_COUNT_3 = 0x0003, SHIFT_COUNT_4 = 0x0004, SHIFT_COUNT_5 = 0x0005, SHIFT_COUNT_6 = 0x0006, SHIFT_COUNT_7 = 0x0007, /* Shift directions */ SHIFT_DIR_LEFT = 0x0100, SHIFT_DIR_RIGHT = 0x0200, /* Shift modes */ SHIFT_MODE_ARITH = 0x1000, SHIFT_MODE_LOGICAL = 0x2000, /* Shift types */ SHIFT_TYPE_ASL = SHIFT_DIR_LEFT | SHIFT_MODE_ARITH, SHIFT_TYPE_ASR = SHIFT_DIR_RIGHT | SHIFT_MODE_ARITH, SHIFT_TYPE_LSL = SHIFT_DIR_LEFT | SHIFT_MODE_LOGICAL, SHIFT_TYPE_LSR = SHIFT_DIR_RIGHT | SHIFT_MODE_LOGICAL, /* Complete specs */ SHIFT_ASL_Y = SHIFT_TYPE_ASL | SHIFT_COUNT_Y, SHIFT_ASR_Y = SHIFT_TYPE_ASR | SHIFT_COUNT_Y, SHIFT_LSL_Y = SHIFT_TYPE_LSL | SHIFT_COUNT_Y, SHIFT_LSR_Y = SHIFT_TYPE_LSR | SHIFT_COUNT_Y, SHIFT_ASL_1 = SHIFT_TYPE_ASL | SHIFT_COUNT_1, SHIFT_ASR_1 = SHIFT_TYPE_ASR | SHIFT_COUNT_1, SHIFT_LSL_1 = SHIFT_TYPE_LSL | SHIFT_COUNT_1, SHIFT_LSR_1 = SHIFT_TYPE_LSR | SHIFT_COUNT_1, SHIFT_ASL_2 = SHIFT_TYPE_ASL | SHIFT_COUNT_2, SHIFT_ASR_2 = SHIFT_TYPE_ASR | SHIFT_COUNT_2, SHIFT_LSL_2 = SHIFT_TYPE_LSL | SHIFT_COUNT_2, SHIFT_LSR_2 = SHIFT_TYPE_LSR | SHIFT_COUNT_2, SHIFT_ASL_3 = SHIFT_TYPE_ASL | SHIFT_COUNT_3, SHIFT_ASR_3 = SHIFT_TYPE_ASR | SHIFT_COUNT_3, SHIFT_LSL_3 = SHIFT_TYPE_LSL | SHIFT_COUNT_3, SHIFT_LSR_3 = SHIFT_TYPE_LSR | SHIFT_COUNT_3, SHIFT_ASL_4 = SHIFT_TYPE_ASL | SHIFT_COUNT_4, SHIFT_ASR_4 = SHIFT_TYPE_ASR | SHIFT_COUNT_4, SHIFT_LSL_4 = SHIFT_TYPE_LSL | SHIFT_COUNT_4, SHIFT_LSR_4 = SHIFT_TYPE_LSR | SHIFT_COUNT_4, SHIFT_ASL_5 = SHIFT_TYPE_ASL | SHIFT_COUNT_5, SHIFT_ASR_5 = SHIFT_TYPE_ASR | SHIFT_COUNT_5, SHIFT_LSL_5 = SHIFT_TYPE_LSL | SHIFT_COUNT_5, SHIFT_LSR_5 = SHIFT_TYPE_LSR | SHIFT_COUNT_5, SHIFT_ASL_6 = SHIFT_TYPE_ASL | SHIFT_COUNT_6, SHIFT_ASR_6 = SHIFT_TYPE_ASR | SHIFT_COUNT_6, SHIFT_LSL_6 = SHIFT_TYPE_LSL | SHIFT_COUNT_6, SHIFT_LSR_6 = SHIFT_TYPE_LSR | SHIFT_COUNT_6, SHIFT_ASL_7 = SHIFT_TYPE_ASL | SHIFT_COUNT_7, SHIFT_ASR_7 = SHIFT_TYPE_ASR | SHIFT_COUNT_7, SHIFT_LSL_7 = SHIFT_TYPE_LSL | SHIFT_COUNT_7, SHIFT_LSR_7 = SHIFT_TYPE_LSR | SHIFT_COUNT_7, }; /* Macros to extract values from a shift type */ #define SHIFT_COUNT(S) ((S) & SHIFT_MASK_COUNT) #define SHIFT_DIR(S) ((S) & SHIFT_MASK_DIR) #define SHIFT_MODE(S) ((S) & SHIFT_MASK_MODE) #define SHIFT_TYPE(S) ((S) & SHIFT_MASK_TYPE) /*****************************************************************************/ /* Helper routines */ /*****************************************************************************/ static unsigned GetShift (const char* Name) /* Determine the shift from the name of the subroutine */ { unsigned Type; if (strncmp (Name, "aslax", 5) == 0) { Type = SHIFT_TYPE_ASL; } else if (strncmp (Name, "asrax", 5) == 0) { Type = SHIFT_TYPE_ASR; } else if (strncmp (Name, "shlax", 5) == 0) { Type = SHIFT_TYPE_LSL; } else if (strncmp (Name, "shrax", 5) == 0) { Type = SHIFT_TYPE_LSR; } else { /* Nothing we know */ return SHIFT_NONE; } /* Get the count */ switch (Name[5]) { case 'y': Type |= SHIFT_COUNT_Y; break; case '1': Type |= SHIFT_COUNT_1; break; case '2': Type |= SHIFT_COUNT_2; break; case '3': Type |= SHIFT_COUNT_3; break; case '4': Type |= SHIFT_COUNT_4; break; case '5': Type |= SHIFT_COUNT_5; break; case '6': Type |= SHIFT_COUNT_6; break; case '7': Type |= SHIFT_COUNT_7; break; default: return SHIFT_NONE; } /* Make sure nothing follows */ if (Name[6] == '\0') { return Type; } else { return SHIFT_NONE; } } /*****************************************************************************/ /* Optimize shifts */ /*****************************************************************************/ unsigned OptShift1 (CodeSeg* S) /* A call to the shlaxN routine may get replaced by one or more asl insns ** if the value of X is not used later. If X is used later, but it is zero ** on entry and it's a shift by one, it may get replaced by: ** ** asl a ** bcc L1 ** inx ** L1: */ { unsigned Changes = 0; unsigned I; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { unsigned Shift; CodeEntry* N; CodeEntry* X; CodeLabel* L; /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check for the sequence */ if (E->OPC == OP65_JSR && (Shift = GetShift (E->Arg)) != SHIFT_NONE && SHIFT_DIR (Shift) == SHIFT_DIR_LEFT) { unsigned Count = SHIFT_COUNT (Shift); if (!RegXUsed (S, I+1)) { if (Count == SHIFT_COUNT_Y) { CodeLabel* L; if (S->CodeSizeFactor < 200) { goto NextEntry; } /* Change into ** ** L1: asl a ** dey ** bpl L1 ** ror a */ /* asl a */ X = NewCodeEntry (OP65_ASL, AM65_ACC, "a", 0, E->LI); CS_InsertEntry (S, X, I+1); L = CS_GenLabel (S, X); /* dey */ X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, E->LI); CS_InsertEntry (S, X, I+2); /* bpl L1 */ X = NewCodeEntry (OP65_BPL, AM65_BRA, L->Name, L, E->LI); CS_InsertEntry (S, X, I+3); /* ror a */ X = NewCodeEntry (OP65_ROR, AM65_ACC, "a", 0, E->LI); CS_InsertEntry (S, X, I+4); } else { /* Insert shift insns */ while (Count--) { X = NewCodeEntry (OP65_ASL, AM65_ACC, "a", 0, E->LI); CS_InsertEntry (S, X, I+1); } } } else if (E->RI->In.RegX == 0 && Count == 1 && (N = CS_GetNextEntry (S, I)) != 0) { /* asl a */ X = NewCodeEntry (OP65_ASL, AM65_ACC, "a", 0, E->LI); CS_InsertEntry (S, X, I+1); /* bcc L1 */ L = CS_GenLabel (S, N); X = NewCodeEntry (OP65_BCC, AM65_BRA, L->Name, L, E->LI); CS_InsertEntry (S, X, I+2); /* inx */ X = NewCodeEntry (OP65_INX, AM65_IMP, 0, 0, E->LI); CS_InsertEntry (S, X, I+3); } else { /* We won't handle this one */ goto NextEntry; } /* Delete the call to shlax */ CS_DelEntry (S, I); /* Remember, we had changes */ ++Changes; } NextEntry: /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } 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 = 0; /* Walk over the entries */ while (I < CS_GetEntryCount (S)) { unsigned Shift; unsigned Count, Count2; unsigned K; CodeEntry* L[4]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ 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) { if (L[3]->OPC == OP65_JSR && SHIFT_TYPE (Shift = GetShift (L[3]->Arg)) == SHIFT_TYPE_ASR && (Count2 = SHIFT_COUNT (Shift)) > 0) { /* Found a second jsr asraxN */ Count += Count2; K = 4; } else { K = 3; } if (Count * 100 <= S->CodeSizeFactor && !RegXUsed (S, I+K)) { CodeEntry* X; unsigned J = I+K; /* 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 */ return Changes; } unsigned OptShift3 (CodeSeg* S) /* The sequence ** ** bcc L ** inx ** L: jsr shrax1 ** ** may get replaced by ** ** ror a ** ** if X is zero on entry. For shift counts > 1, more ** ** shr a ** ** must be added. */ { unsigned Changes = 0; unsigned I; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { unsigned Shift; unsigned Count; CodeEntry* L[3]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if ((L[0]->OPC == OP65_BCC || L[0]->OPC == OP65_JCC) && L[0]->JumpTo != 0 && L[0]->RI->In.RegX == 0 && CS_GetEntries (S, L+1, I+1, 2) && L[1]->OPC == OP65_INX && L[0]->JumpTo->Owner == L[2] && !CS_RangeHasLabel (S, I, 2) && L[2]->OPC == OP65_JSR && (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); while (--Count) { X = NewCodeEntry (OP65_LSR, AM65_ACC, "a", 0, L[2]->LI); CS_InsertEntry (S, X, I+4); } /* Remove the bcc/inx/jsr */ CS_DelEntries (S, I, 3); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptShift4 (CodeSeg* S) /* Calls to the asraxN or shraxN routines may get replaced by one or more lsr ** insns if the value of X is zero. */ { unsigned Changes = 0; unsigned I; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { unsigned Shift; unsigned Count; /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check for the sequence */ if (E->OPC == OP65_JSR && (Shift = GetShift (E->Arg)) != SHIFT_NONE && SHIFT_DIR (Shift) == SHIFT_DIR_RIGHT && E->RI->In.RegX == 0) { CodeEntry* X; /* Shift count may be in Y */ Count = SHIFT_COUNT (Shift); if (Count == SHIFT_COUNT_Y) { CodeLabel* L; if (S->CodeSizeFactor < 200) { /* Not acceptable */ goto NextEntry; } /* Generate: ** ** L1: lsr a ** dey ** bpl L1 ** rol a ** ** A negative shift count or one that is greater or equal than ** the bit width of the left operand (which is promoted to ** integer before the operation) causes undefined behaviour, so ** above transformation is safe. */ /* lsr a */ X = NewCodeEntry (OP65_LSR, AM65_ACC, "a", 0, E->LI); CS_InsertEntry (S, X, I+1); L = CS_GenLabel (S, X); /* dey */ X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, E->LI); CS_InsertEntry (S, X, I+2); /* bpl L1 */ X = NewCodeEntry (OP65_BPL, AM65_BRA, L->Name, L, E->LI); CS_InsertEntry (S, X, I+3); /* rol a */ X = NewCodeEntry (OP65_ROL, AM65_ACC, "a", 0, E->LI); CS_InsertEntry (S, X, I+4); } else { /* Insert shift insns */ while (Count--) { X = NewCodeEntry (OP65_LSR, AM65_ACC, "a", 0, E->LI); CS_InsertEntry (S, X, I+1); } } /* Delete the call to shrax */ CS_DelEntry (S, I); /* Remember, we had changes */ ++Changes; } NextEntry: /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptShift5 (CodeSeg* S) /* Search for the sequence ** ** lda xxx ** ldx yyy ** jsr aslax1/asrax1/shlax1/shrax1 ** sta aaa ** stx bbb ** ** and replace it by ** ** lda xxx ** asl a ** sta aaa ** lda yyy ** rol a ** sta bbb ** ** or similar, provided that a/x is not used later */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { unsigned ShiftType; CodeEntry* L[5]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (L[0]->OPC == OP65_LDA && (L[0]->AM == AM65_ABS || L[0]->AM == AM65_ZP) && CS_GetEntries (S, L+1, I+1, 4) && !CS_RangeHasLabel (S, I+1, 4) && L[1]->OPC == OP65_LDX && (L[1]->AM == AM65_ABS || L[1]->AM == AM65_ZP) && L[2]->OPC == OP65_JSR && (ShiftType = GetShift (L[2]->Arg)) != SHIFT_NONE && SHIFT_COUNT(ShiftType) == 1 && L[3]->OPC == OP65_STA && (L[3]->AM == AM65_ABS || L[3]->AM == AM65_ZP) && L[4]->OPC == OP65_STX && (L[4]->AM == AM65_ABS || L[4]->AM == AM65_ZP) && !RegAXUsed (S, I+5)) { CodeEntry* X; /* Handle the four shift types differently */ switch (ShiftType) { case SHIFT_ASR_1: X = NewCodeEntry (OP65_LDA, L[1]->AM, L[1]->Arg, 0, L[1]->LI); CS_InsertEntry (S, X, I+5); X = NewCodeEntry (OP65_CMP, AM65_IMM, "$80", 0, L[2]->LI); CS_InsertEntry (S, X, I+6); X = NewCodeEntry (OP65_ROR, AM65_ACC, "a", 0, L[2]->LI); CS_InsertEntry (S, X, I+7); X = NewCodeEntry (OP65_STA, L[4]->AM, L[4]->Arg, 0, L[4]->LI); CS_InsertEntry (S, X, I+8); X = NewCodeEntry (OP65_LDA, L[0]->AM, L[0]->Arg, 0, L[0]->LI); CS_InsertEntry (S, X, I+9); X = NewCodeEntry (OP65_ROR, AM65_ACC, "a", 0, L[2]->LI); CS_InsertEntry (S, X, I+10); X = NewCodeEntry (OP65_STA, L[3]->AM, L[3]->Arg, 0, L[3]->LI); CS_InsertEntry (S, X, I+11); CS_DelEntries (S, I, 5); break; case SHIFT_LSR_1: X = NewCodeEntry (OP65_LDA, L[1]->AM, L[1]->Arg, 0, L[1]->LI); CS_InsertEntry (S, X, I+5); X = NewCodeEntry (OP65_LSR, AM65_ACC, "a", 0, L[2]->LI); CS_InsertEntry (S, X, I+6); X = NewCodeEntry (OP65_STA, L[4]->AM, L[4]->Arg, 0, L[4]->LI); CS_InsertEntry (S, X, I+7); X = NewCodeEntry (OP65_LDA, L[0]->AM, L[0]->Arg, 0, L[0]->LI); CS_InsertEntry (S, X, I+8); X = NewCodeEntry (OP65_ROR, AM65_ACC, "a", 0, L[2]->LI); CS_InsertEntry (S, X, I+9); X = NewCodeEntry (OP65_STA, L[3]->AM, L[3]->Arg, 0, L[3]->LI); CS_InsertEntry (S, X, I+10); CS_DelEntries (S, I, 5); break; case SHIFT_LSL_1: case SHIFT_ASL_1: /* These two are identical */ X = NewCodeEntry (OP65_ASL, AM65_ACC, "a", 0, L[2]->LI); CS_InsertEntry (S, X, I+1); X = NewCodeEntry (OP65_STA, L[3]->AM, L[3]->Arg, 0, L[3]->LI); CS_InsertEntry (S, X, I+2); X = NewCodeEntry (OP65_LDA, L[1]->AM, L[1]->Arg, 0, L[1]->LI); CS_InsertEntry (S, X, I+3); X = NewCodeEntry (OP65_ROL, AM65_ACC, "a", 0, L[2]->LI); CS_InsertEntry (S, X, I+4); X = NewCodeEntry (OP65_STA, L[4]->AM, L[4]->Arg, 0, L[4]->LI); CS_InsertEntry (S, X, I+5); CS_DelEntries (S, I+6, 4); break; } /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptShift6 (CodeSeg* S) /* Inline the shift subroutines. */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { unsigned Shift; unsigned Count; CodeEntry* X; unsigned IP; /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check for a call to one of the shift routine */ if (E->OPC == OP65_JSR && (Shift = GetShift (E->Arg)) != SHIFT_NONE && SHIFT_DIR (Shift) == SHIFT_DIR_LEFT && (Count = SHIFT_COUNT (Shift)) > 0) { /* Code is: ** ** stx tmp1 ** asl a ** rol tmp1 ** (repeat ShiftCount-1 times) ** ldx tmp1 ** ** which makes 4 + 3 * ShiftCount bytes, compared to the original ** 3 bytes for the subroutine call. However, in most cases, the ** final load of the X register gets merged with some other insn ** and replaces a txa, so for a shift count of 1, we get a factor ** of 200, which matches nicely the CodeSizeFactor enabled with -Oi */ if (Count > 1 || S->CodeSizeFactor > 200) { unsigned Size = 4 + 3 * Count; if ((Size * 100 / 3) > S->CodeSizeFactor) { /* Not acceptable */ goto NextEntry; } } /* Inline the code. Insertion point is behind the subroutine call */ IP = (I + 1); /* stx tmp1 */ X = NewCodeEntry (OP65_STX, AM65_ZP, "tmp1", 0, E->LI); CS_InsertEntry (S, X, IP++); while (Count--) { /* asl a */ X = NewCodeEntry (OP65_ASL, AM65_ACC, "a", 0, E->LI); CS_InsertEntry (S, X, IP++); /* rol tmp1 */ X = NewCodeEntry (OP65_ROL, AM65_ZP, "tmp1", 0, E->LI); CS_InsertEntry (S, X, IP++); } /* ldx tmp1 */ X = NewCodeEntry (OP65_LDX, AM65_ZP, "tmp1", 0, E->LI); CS_InsertEntry (S, X, IP++); /* Remove the subroutine call */ CS_DelEntry (S, I); /* Remember, we had changes */ ++Changes; } NextEntry: /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } ���������������������������������������������������������������������������������������������cc65-2.18/src/cc65/coptshift.h����������������������������������������������������������������������0000664�0000000�0000000�00000010411�13473601511�0015705�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* coptshift.h */ /* */ /* Optimize shifts */ /* */ /* */ /* */ /* (C) 2001-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef COPTSHIFT_H #define COPTSHIFT_H /* cc65 */ #include "codeseg.h" /*****************************************************************************/ /* Optimize shifts */ /*****************************************************************************/ unsigned OptShift1 (CodeSeg* S); /* A call to the shlaxN routine may get replaced by one or more asl insns ** if the value of X is not used later. If X is used later, but it is zero ** on entry and it's a shift by one, it may get replaced by: ** ** asl a ** bcc L1 ** inx ** L1: */ 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); /* The sequence ** ** bcc L ** inx ** L: jsr shrax1 ** ** may get replaced by ** ** ror a ** ** if X is zero on entry and unused later. For shift counts > 1, more ** ** shr a ** ** must be added. */ unsigned OptShift4 (CodeSeg* S); /* Calls to the asraxN or shraxN routines may get replaced by one or more lsr ** insns if the value of X is zero. */ unsigned OptShift5 (CodeSeg* S); /* Search for the sequence ** ** lda xxx ** ldx yyy ** jsr aslax1/asrax1/shlax1/shrax1 ** sta aaa ** stx bbb ** ** and replace it by ** ** lda xxx ** asl a ** sta aaa ** lda yyy ** rol a ** sta bbb ** ** or similar, provided that a/x is not used later */ unsigned OptShift6 (CodeSeg* S); /* Inline the shift subroutines. */ /* End of coptshift.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/coptsize.c�����������������������������������������������������������������������0000664�0000000�0000000�00000115132�13473601511�0015543�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* coptsize.c */ /* */ /* Size optimizations */ /* */ /* */ /* */ /* (C) 2002-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdlib.h> /* common */ #include "cpu.h" /* cc65 */ #include "codeent.h" #include "codeinfo.h" #include "coptsize.h" #include "reginfo.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Flags for CallDesc */ #define F_NONE 0x0000U /* No extra flags */ #define F_SLOWER 0x0001U /* Function call is slower */ typedef struct CallDesc CallDesc; struct CallDesc { const char* LongFunc; /* Long function name */ RegContents Regs; /* Register contents */ unsigned Flags; /* Flags from above */ const char* ShortFunc; /* Short function name */ }; /* Note: The table is sorted. If there is more than one entry with the same ** name, entries are sorted best match first, so when searching linear for ** a match, the first one can be used because it is also the best one (or ** at least none of the following ones are better). ** Note^2: Ptr1 and Tmp1 aren't evaluated, because runtime routines don't ** expect parameters here. */ static const CallDesc CallTable [] = { /* Name A register X register Y register flags replacement */ { "addeqysp", { /* A X Y SRegLo */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "addeq0sp" },{ "laddeq", { /* A X Y SRegLo */ 1, 0, UNKNOWN_REGVAL, 0, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "laddeq1" },{ "laddeq", { /* A X Y SRegLo */ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, 0, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "laddeqa" },{ "laddeqysp", { /* A X Y SRegLo */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "laddeq0sp" },{ "ldaxidx", { /* A X Y SRegLo */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, 1, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "ldaxi" },{ "ldaxysp", { /* A X Y SRegLo */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, 1, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "ldax0sp" },{ "ldeaxidx", { /* A X Y SRegLo */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, 3, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "ldeaxi" },{ "ldeaxysp", { /* A X Y SRegLo */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, 3, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "ldeax0sp" },{ "leaaxsp", { /* A X Y SRegLo */ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "leaa0sp" },{ "lsubeq", { /* A X Y SRegLo */ 1, 0, UNKNOWN_REGVAL, 0, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "lsubeq1" },{ "lsubeq", { /* A X Y SRegLo */ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, 0, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "lsubeqa" },{ "lsubeqysp", { /* A X Y SRegLo */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "lsubeq0sp" },{ "pusha", { /* A X Y SRegLo */ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_SLOWER, "pushc0" },{ "pusha", { /* A X Y SRegLo */ 1, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_SLOWER, "pushc1" },{ "pusha", { /* A X Y SRegLo */ 2, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_SLOWER, "pushc2" },{ "pushax", { /* A X Y SRegLo */ 0, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "push0" },{ "pushax", { /* A X Y SRegLo */ 1, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_SLOWER, "push1" },{ "pushax", { /* A X Y SRegLo */ 2, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_SLOWER, "push2" },{ "pushax", { /* A X Y SRegLo */ 3, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_SLOWER, "push3" },{ "pushax", { /* A X Y SRegLo */ 4, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_SLOWER, "push4" },{ "pushax", { /* A X Y SRegLo */ 5, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_SLOWER, "push5" },{ "pushax", { /* A X Y SRegLo */ 6, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_SLOWER, "push6" },{ "pushax", { /* A X Y SRegLo */ 7, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_SLOWER, "push7" },{ "pushax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "pusha0" },{ "pushax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, 0xFF, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_SLOWER, "pushaFF" },{ "pushaysp", { /* A X Y SRegLo */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "pusha0sp" },{ "pusheax", { /* A X Y SRegLo */ 0, 0, UNKNOWN_REGVAL, 0, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "pushl0" },{ "pusheax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "push0ax" },{ "pushwidx", { /* A X Y SRegLo */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, 1, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "pushw" },{ "pushwysp", { /* A X Y SRegLo */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, 3, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "pushw0sp" },{ "staxysp", { /* A X Y SRegLo */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "stax0sp" },{ "steaxysp", { /* A X Y SRegLo */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "steax0sp" },{ "subeqysp", { /* A X Y SRegLo */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "subeq0sp" },{ "tosaddax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosadda0" },{ "tosaddeax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosadd0ax" },{ "tosandax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosanda0" },{ "tosandeax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosand0ax" },{ "tosdivax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosdiva0" },{ "tosdiveax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosdiv0ax" },{ "toseqax", { /* A X Y SRegLo */ 0, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "toseq00" },{ "toseqax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "toseqa0" },{ "tosgeax", { /* A X Y SRegLo */ 0, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosge00" },{ "tosgeax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosgea0" },{ "tosgtax", { /* A X Y SRegLo */ 0, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosgt00" },{ "tosgtax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosgta0" },{ "tosicmp", { /* A X Y SRegLo */ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosicmp0" },{ "tosleax", { /* A X Y SRegLo */ 0, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosle00" },{ "tosleax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "toslea0" },{ "tosltax", { /* A X Y SRegLo */ 0, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "toslt00" },{ "tosltax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "toslta0" },{ "tosmodax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosmoda0" },{ "tosmodeax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosmod0ax" },{ "tosmulax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosmula0" },{ "tosmuleax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosmul0ax" },{ "tosneax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosnea0" },{ "tosorax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosora0" },{ "tosoreax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosor0ax" },{ "tosrsubax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosrsuba0" },{ "tosrsubeax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosrsub0ax" },{ "tossubax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tossuba0" },{ "tossubeax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tossub0ax" },{ "tosudivax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosudiva0" },{ "tosudiveax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosudiv0ax" },{ "tosugeax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosugea0" },{ "tosugtax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosugta0" },{ "tosuleax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosulea0" },{ "tosultax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosulta0" },{ "tosumodax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosumoda0" },{ "tosumodeax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosumod0ax" },{ "tosumulax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosumula0" },{ "tosumuleax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosumul0ax" },{ "tosxorax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosxora0" },{ "tosxoreax", { /* A X Y SRegLo */ UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL, 0, /* SRegHi Ptr1Lo Ptr1Hi Tmp1 */ 0, UNKNOWN_REGVAL, UNKNOWN_REGVAL, UNKNOWN_REGVAL }, F_NONE, "tosxor0ax" }, }; #define CALL_COUNT (sizeof(CallTable) / sizeof(CallTable[0])) /*****************************************************************************/ /* Helpers */ /*****************************************************************************/ static const CallDesc* FindCall (const char* Name) /* Find the function with the given name. Return a pointer to the table entry ** or NULL if the function was not found. */ { /* Do a binary search */ int First = 0; int Last = CALL_COUNT - 1; int Found = 0; while (First <= Last) { /* Set current to mid of range */ int Current = (Last + First) / 2; /* Do a compare */ int Result = strcmp (CallTable[Current].LongFunc, Name); if (Result < 0) { First = Current + 1; } else { Last = Current - 1; if (Result == 0) { /* Found. Repeat the procedure until the first of all entries ** with the same name is found. */ Found = 1; } } } /* Return the first entry if found, or NULL otherwise */ return Found? &CallTable[First] : 0; } static int RegMatch (short Expected, short Actual) /* Check for a register match. If Expected has a value, it must be identical ** to Actual. */ { return RegValIsUnknown (Expected) || (Expected == Actual); } /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned OptSize1 (CodeSeg* S) /* Do size optimization by calling special subroutines that preload registers. ** This routine does not work standalone, it needs a following register load ** removal pass. */ { CodeEntry* E; unsigned Changes = 0; unsigned I; /* Are we optimizing for size */ int OptForSize = (S->CodeSizeFactor < 100); /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { const CallDesc* D; /* Get next entry */ E = CS_GetEntry (S, I); /* Check if it's a subroutine call */ if (E->OPC == OP65_JSR && (D = FindCall (E->Arg)) != 0) { /* Get input register info for this insn */ const RegContents* In = &E->RI->In; /* FindCall finds the first entry that matches our function name. ** The names are listed in "best match" order, so search for the ** first one, that fulfills our conditions. */ while (1) { /* Check the registers and allow slower code only if ** optimizing for size. */ if ((OptForSize || (D->Flags & F_SLOWER) == 0) && RegMatch (D->Regs.RegA, In->RegA) && RegMatch (D->Regs.RegX, In->RegX) && RegMatch (D->Regs.RegY, In->RegY) && RegMatch (D->Regs.SRegLo, In->SRegLo) && RegMatch (D->Regs.SRegHi, In->SRegHi)) { /* Ok, match for all conditions */ CodeEntry* X; X = NewCodeEntry (E->OPC, E->AM, D->ShortFunc, 0, E->LI); CS_InsertEntry (S, X, I+1); CS_DelEntry (S, I); /* Remember that we had changes */ ++Changes; /* Done */ break; } /* Next table entry, bail out if next entry not valid */ if (++D >= CallTable + CALL_COUNT || strcmp (D->LongFunc, E->Arg) != 0) { /* End of table or entries reached */ break; } } } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptSize2 (CodeSeg* S) /* Do size optimization by using shorter code sequences, even if this ** introduces relations between instructions. This step must be one of the ** last steps, because it makes further work much more difficult. */ { unsigned Changes = 0; unsigned I; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Get the input registers */ const RegContents* In = &E->RI->In; /* Assume we have no replacement */ CodeEntry* X = 0; /* Check the instruction */ switch (E->OPC) { case OP65_LDA: if (CE_IsConstImm (E)) { short Val = (short) E->Num; if (Val == In->RegX) { X = NewCodeEntry (OP65_TXA, AM65_IMP, 0, 0, E->LI); } else if (Val == In->RegY) { X = NewCodeEntry (OP65_TYA, AM65_IMP, 0, 0, E->LI); } else if (RegValIsKnown (In->RegA) && (CPUIsets[CPU] & CPU_ISET_65SC02) != 0) { if (Val == ((In->RegA - 1) & 0xFF)) { X = NewCodeEntry (OP65_DEA, AM65_IMP, 0, 0, E->LI); } else if (Val == ((In->RegA + 1) & 0xFF)) { X = NewCodeEntry (OP65_INA, AM65_IMP, 0, 0, E->LI); } } } break; case OP65_LDX: if (CE_IsConstImm (E)) { short Val = (short) E->Num; if (RegValIsKnown (In->RegX) && Val == ((In->RegX - 1) & 0xFF)) { X = NewCodeEntry (OP65_DEX, AM65_IMP, 0, 0, E->LI); } else if (RegValIsKnown (In->RegX) && Val == ((In->RegX + 1) & 0xFF)) { X = NewCodeEntry (OP65_INX, AM65_IMP, 0, 0, E->LI); } else if (Val == In->RegA) { X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, E->LI); } } break; case OP65_LDY: if (CE_IsConstImm (E)) { short Val = (short) E->Num; if (RegValIsKnown (In->RegY) && Val == ((In->RegY - 1) & 0xFF)) { X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, E->LI); } else if (RegValIsKnown (In->RegY) && Val == ((In->RegY + 1) & 0xFF)) { X = NewCodeEntry (OP65_INY, AM65_IMP, 0, 0, E->LI); } else if (Val == In->RegA) { X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, E->LI); } } break; default: /* Avoid gcc warnings */ break; } /* Insert the replacement if we have one */ if (X) { CS_InsertEntry (S, X, I+1); CS_DelEntry (S, I); ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/coptsize.h�����������������������������������������������������������������������0000664�0000000�0000000�00000006454�13473601511�0015556�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* coptsize.c */ /* */ /* Size optimizations */ /* */ /* */ /* */ /* (C) 2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef COPTSIZE_H #define COPTSIZE_H /* cc65 */ #include "codeseg.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned OptSize1 (CodeSeg* S); /* Do size optimization by calling special subroutines that preload registers. ** This routine does not work standalone, it needs a following register load ** removal pass. */ unsigned OptSize2 (CodeSeg* S); /* Do size optimization by using shorter code sequences, even if this ** introduces relations between instructions. This step must be one of the ** last steps, because it makes further work much more difficult. */ /* End of coptsize.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/coptstop.c�����������������������������������������������������������������������0000664�0000000�0000000�00000203516�13473601511�0015562�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* coptstop.c */ /* */ /* Optimize operations that take operands via the stack */ /* */ /* */ /* */ /* (C) 2001-2019, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdlib.h> /* common */ #include "chartype.h" /* cc65 */ #include "codeent.h" #include "codeinfo.h" #include "coptstop.h" #include "error.h" /*****************************************************************************/ /* Load tracking data */ /*****************************************************************************/ /* LoadRegInfo flags set by DirectOp */ typedef enum { LI_NONE = 0x00, LI_DIRECT = 0x01, /* Direct op may be used */ LI_RELOAD_Y = 0x02, /* Reload index register Y */ LI_REMOVE = 0x04, /* Load may be removed */ LI_DONT_REMOVE = 0x08, /* Load may not be removed */ LI_DUP_LOAD = 0x10, /* Duplicate load */ } LI_FLAGS; /* Structure that tells us how to load the lhs values */ typedef struct LoadRegInfo LoadRegInfo; struct LoadRegInfo { LI_FLAGS Flags; /* Tells us how to load */ int LoadIndex; /* Index of load insn, -1 if invalid */ CodeEntry* LoadEntry; /* The actual entry, 0 if invalid */ int XferIndex; /* Index of transfer insn */ CodeEntry* XferEntry; /* The actual transfer entry */ int Offs; /* Stack offset if data is on stack */ }; /* Now combined for both registers */ typedef struct LoadInfo LoadInfo; struct LoadInfo { LoadRegInfo A; /* Info for A register */ LoadRegInfo X; /* Info for X register */ LoadRegInfo Y; /* Info for Y register */ }; /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Flags for the functions */ typedef enum { OP_NONE = 0x00, /* Nothing special */ OP_A_KNOWN = 0x01, /* Value of A must be known */ OP_X_ZERO = 0x02, /* X must be zero */ OP_LHS_LOAD = 0x04, /* Must have load insns for LHS */ OP_LHS_LOAD_DIRECT = 0x0C, /* Must have direct load insn for LHS */ OP_RHS_LOAD = 0x10, /* Must have load insns for RHS */ OP_RHS_LOAD_DIRECT = 0x30, /* Must have direct load insn for RHS */ } OP_FLAGS; /* Structure forward decl */ typedef struct StackOpData StackOpData; /* Structure that describes an optimizer subfunction for a specific op */ typedef unsigned (*OptFunc) (StackOpData* D); typedef struct OptFuncDesc OptFuncDesc; struct OptFuncDesc { const char* Name; /* Name of the replaced runtime function */ OptFunc Func; /* Function pointer */ unsigned UnusedRegs; /* Regs that must not be used later */ OP_FLAGS Flags; /* Flags */ }; /* Structure that holds the needed data */ struct StackOpData { CodeSeg* Code; /* Pointer to code segment */ unsigned Flags; /* Flags to remember things */ /* Pointer to optimizer subfunction description */ const OptFuncDesc* OptFunc; /* ZP register usage inside the sequence */ unsigned ZPUsage; /* Register load information for lhs and rhs */ LoadInfo Lhs; LoadInfo Rhs; /* Several indices of insns in the code segment */ int PushIndex; /* Index of call to pushax in codeseg */ int OpIndex; /* Index of actual operation */ /* Pointers to insns in the code segment */ CodeEntry* PrevEntry; /* Entry before the call to pushax */ CodeEntry* PushEntry; /* Pointer to entry with call to pushax */ CodeEntry* OpEntry; /* Pointer to entry with op */ CodeEntry* NextEntry; /* Entry after the op */ const char* ZPLo; /* Lo byte of zero page loc to use */ const char* ZPHi; /* Hi byte of zero page loc to use */ unsigned IP; /* Insertion point used by some routines */ }; /*****************************************************************************/ /* Load tracking code */ /*****************************************************************************/ static void ClearLoadRegInfo (LoadRegInfo* RI) /* Clear a LoadRegInfo struct */ { RI->Flags = LI_NONE; RI->LoadIndex = -1; RI->XferIndex = -1; RI->Offs = 0; } static void FinalizeLoadRegInfo (LoadRegInfo* RI, CodeSeg* S) /* Prepare a LoadRegInfo struct for use */ { /* Get the entries */ if (RI->LoadIndex >= 0) { RI->LoadEntry = CS_GetEntry (S, RI->LoadIndex); } else { RI->LoadEntry = 0; } if (RI->XferIndex >= 0) { RI->XferEntry = CS_GetEntry (S, RI->XferIndex); } else { RI->XferEntry = 0; } } static void ClearLoadInfo (LoadInfo* LI) /* Clear a LoadInfo struct */ { ClearLoadRegInfo (&LI->A); ClearLoadRegInfo (&LI->X); ClearLoadRegInfo (&LI->Y); } static void AdjustLoadRegInfo (LoadRegInfo* RI, int Index, int Change) /* Adjust a load register info struct after deleting or inserting an entry ** with a given index */ { CHECK (abs (Change) == 1); if (Change < 0) { /* Deletion */ if (Index < RI->LoadIndex) { --RI->LoadIndex; } else if (Index == RI->LoadIndex) { /* Has been removed */ RI->LoadIndex = -1; RI->LoadEntry = 0; } if (Index < RI->XferIndex) { --RI->XferIndex; } else if (Index == RI->XferIndex) { /* Has been removed */ RI->XferIndex = -1; RI->XferEntry = 0; } } else { /* Insertion */ if (Index <= RI->LoadIndex) { ++RI->LoadIndex; } if (Index <= RI->XferIndex) { ++RI->XferIndex; } } } static void FinalizeLoadInfo (LoadInfo* LI, CodeSeg* S) /* Prepare a LoadInfo struct for use */ { /* Get the entries */ FinalizeLoadRegInfo (&LI->A, S); FinalizeLoadRegInfo (&LI->X, S); FinalizeLoadRegInfo (&LI->Y, S); } static void AdjustLoadInfo (LoadInfo* LI, int Index, int Change) /* Adjust a load info struct after deleting entry with a given index */ { AdjustLoadRegInfo (&LI->A, Index, Change); AdjustLoadRegInfo (&LI->X, Index, Change); AdjustLoadRegInfo (&LI->Y, Index, Change); } static void HonourUseAndChg (LoadRegInfo* RI, unsigned Reg, const CodeEntry* E) /* Honour use and change flags for an instruction */ { if (E->Chg & Reg) { ClearLoadRegInfo (RI); } else if ((E->Use & Reg) && RI->LoadIndex >= 0) { RI->Flags |= LI_DONT_REMOVE; } } static void TrackLoads (LoadInfo* LI, CodeEntry* E, int I) /* Track loads for a code entry */ { if (E->Info & OF_LOAD) { LoadRegInfo* RI = 0; /* Determine, which register was loaded */ if (E->Chg & REG_A) { RI = &LI->A; } else if (E->Chg & REG_X) { RI = &LI->X; } else if (E->Chg & REG_Y) { RI = &LI->Y; } CHECK (RI != 0); /* If we had a load or xfer op before, this is a duplicate load which ** can cause problems if it encountered between the pushax and the op, ** so remember it. */ if (RI->LoadIndex >= 0 || RI->XferIndex >= 0) { RI->Flags |= LI_DUP_LOAD; } /* Remember the load */ RI->LoadIndex = I; RI->XferIndex = -1; /* Set load flags */ RI->Flags &= ~(LI_DIRECT | LI_RELOAD_Y); if (E->AM == AM65_IMM || E->AM == AM65_ZP || E->AM == AM65_ABS) { /* These insns are all ok and replaceable */ RI->Flags |= LI_DIRECT; } else if (E->AM == AM65_ZP_INDY && RegValIsKnown (E->RI->In.RegY) && strcmp (E->Arg, "sp") == 0) { /* A load from the stack with known offset is also ok, but in this ** case we must reload the index register later. Please note that ** a load indirect via other zero page locations is not ok, since ** these locations may change between the push and the actual ** operation. */ RI->Offs = (unsigned char) E->RI->In.RegY; RI->Flags |= (LI_DIRECT | LI_RELOAD_Y); } } else if (E->Info & OF_XFR) { /* Determine source and target of the transfer and handle the TSX insn */ LoadRegInfo* Src; LoadRegInfo* Tgt; switch (E->OPC) { case OP65_TAX: Src = &LI->A; Tgt = &LI->X; break; case OP65_TAY: Src = &LI->A; Tgt = &LI->Y; break; case OP65_TXA: Src = &LI->X; Tgt = &LI->A; break; case OP65_TYA: Src = &LI->Y; Tgt = &LI->A; break; case OP65_TSX: ClearLoadRegInfo (&LI->X); return; case OP65_TXS: return; default: Internal ("Unknown XFR insn in TrackLoads"); } /* If we had a load or xfer op before, this is a duplicate load which ** can cause problems if it encountered between the pushax and the op, ** so remember it. */ if (Tgt->LoadIndex >= 0 || Tgt->XferIndex >= 0) { Tgt->Flags |= LI_DUP_LOAD; } /* Transfer the data */ Tgt->LoadIndex = Src->LoadIndex; Tgt->XferIndex = I; Tgt->Offs = Src->Offs; Tgt->Flags &= ~(LI_DIRECT | LI_RELOAD_Y); Tgt->Flags |= Src->Flags & (LI_DIRECT | LI_RELOAD_Y); } else if (CE_IsCallTo (E, "ldaxysp") && RegValIsKnown (E->RI->In.RegY)) { /* If we had a load or xfer op before, this is a duplicate load which ** can cause problems if it encountered between the pushax and the op, ** so remember it for both registers involved. */ if (LI->A.LoadIndex >= 0 || LI->A.XferIndex >= 0) { LI->A.Flags |= LI_DUP_LOAD; } if (LI->X.LoadIndex >= 0 || LI->X.XferIndex >= 0) { LI->X.Flags |= LI_DUP_LOAD; } /* Both registers set, Y changed */ LI->A.LoadIndex = I; LI->A.XferIndex = -1; LI->A.Flags |= (LI_DIRECT | LI_RELOAD_Y); LI->A.Offs = (unsigned char) E->RI->In.RegY - 1; LI->X.LoadIndex = I; LI->X.XferIndex = -1; LI->X.Flags |= (LI_DIRECT | LI_RELOAD_Y); LI->X.Offs = (unsigned char) E->RI->In.RegY; ClearLoadRegInfo (&LI->Y); } else { HonourUseAndChg (&LI->A, REG_A, E); HonourUseAndChg (&LI->X, REG_X, E); HonourUseAndChg (&LI->Y, REG_Y, E); } } /*****************************************************************************/ /* Helpers */ /*****************************************************************************/ static void InsertEntry (StackOpData* D, CodeEntry* E, int Index) /* Insert a new entry. Depending on Index, D->PushIndex and D->OpIndex will ** be adjusted by this function. */ { /* Insert the entry into the code segment */ CS_InsertEntry (D->Code, E, Index); /* Adjust register loads if necessary */ AdjustLoadInfo (&D->Lhs, Index, 1); AdjustLoadInfo (&D->Rhs, Index, 1); /* Adjust the indices if necessary */ if (D->PushEntry && Index <= D->PushIndex) { ++D->PushIndex; } if (D->OpEntry && Index <= D->OpIndex) { ++D->OpIndex; } } static void DelEntry (StackOpData* D, int Index) /* Delete an entry. Depending on Index, D->PushIndex and D->OpIndex will be ** adjusted by this function, and PushEntry/OpEntry may get invalidated. */ { /* Delete the entry from the code segment */ CS_DelEntry (D->Code, Index); /* Adjust register loads if necessary */ AdjustLoadInfo (&D->Lhs, Index, -1); AdjustLoadInfo (&D->Rhs, Index, -1); /* Adjust the other indices if necessary */ if (Index < D->PushIndex) { --D->PushIndex; } else if (Index == D->PushIndex) { D->PushEntry = 0; } if (Index < D->OpIndex) { --D->OpIndex; } else if (Index == D->OpIndex) { D->OpEntry = 0; } } static void AdjustStackOffset (StackOpData* D, unsigned Offs) /* Adjust the offset for all stack accesses in the range PushIndex to OpIndex. ** OpIndex is adjusted according to the insertions. */ { /* Walk over all entries */ int I = D->PushIndex + 1; while (I < D->OpIndex) { CodeEntry* E = CS_GetEntry (D->Code, I); /* Check if this entry does a stack access, and if so, if it's a plain ** load from stack, since this is needed later. */ int Correction = 0; if ((E->Use & REG_SP) != 0) { /* Check for some things that should not happen */ CHECK (E->AM == AM65_ZP_INDY || E->RI->In.RegY >= (short) Offs); CHECK (strcmp (E->Arg, "sp") == 0); /* We need to correct this one */ Correction = (E->OPC == OP65_LDA)? 2 : 1; } else if (CE_IsCallTo (E, "ldaxysp")) { /* We need to correct this one */ Correction = 1; } if (Correction) { /* Get the code entry before this one. If it's a LDY, adjust the ** value. */ CodeEntry* P = CS_GetPrevEntry (D->Code, I); if (P && P->OPC == OP65_LDY && CE_IsConstImm (P)) { /* The Y load is just before the stack access, adjust it */ CE_SetNumArg (P, P->Num - Offs); } else { /* Insert a new load instruction before the stack access */ const char* Arg = MakeHexArg (E->RI->In.RegY - Offs); CodeEntry* X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI); InsertEntry (D, X, I++); } /* If we need the value of Y later, be sure to reload it */ if (RegYUsed (D->Code, I+1)) { CodeEntry* N; const char* Arg = MakeHexArg (E->RI->In.RegY); if (Correction == 2 && (N = CS_GetNextEntry(D->Code, I)) != 0 && ((N->Info & OF_ZBRA) != 0) && N->JumpTo != 0) { /* The Y register is used but the load instruction loads A ** and is followed by a branch that evaluates the zero flag. ** This means that we cannot just insert the load insn ** for the Y register at this place, because it would ** destroy the Z flag. Instead place load insns at the ** target of the branch and after it. ** Note: There is a chance that this code won't work. The ** jump may be a backwards jump (in which case the stack ** offset has already been adjusted) or there may be other ** instructions between the load and the conditional jump. ** Currently the compiler does not generate such code, but ** it is possible to force the optimizer into something ** invalid by use of inline assembler. */ /* Add load insn after the branch */ CodeEntry* X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI); InsertEntry (D, X, I+2); /* Add load insn before branch target */ CodeEntry* Y = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI); int J = CS_GetEntryIndex (D->Code, N->JumpTo->Owner); CHECK (J > I); /* Must not happen */ InsertEntry (D, Y, J); /* Move the label to the new insn */ CodeLabel* L = CS_GenLabel (D->Code, Y); CS_MoveLabelRef (D->Code, N, L); } else { CodeEntry* X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, E->LI); InsertEntry (D, X, I+1); /* Skip this instruction in the next round */ ++I; } } } /* Next entry */ ++I; } /* If we have rhs load insns that load from stack, we'll have to adjust ** the offsets for these also. */ if (D->Rhs.A.Flags & LI_RELOAD_Y) { D->Rhs.A.Offs -= Offs; } if (D->Rhs.X.Flags & LI_RELOAD_Y) { D->Rhs.X.Offs -= Offs; } } static void AddStoreA (StackOpData* D) /* Add a store to zero page after the push insn */ { CodeEntry* X = NewCodeEntry (OP65_STA, AM65_ZP, D->ZPLo, 0, D->PushEntry->LI); InsertEntry (D, X, D->PushIndex+1); } static void AddStoreX (StackOpData* D) /* Add a store to zero page after the push insn */ { CodeEntry* X = NewCodeEntry (OP65_STX, AM65_ZP, D->ZPHi, 0, D->PushEntry->LI); InsertEntry (D, X, D->PushIndex+1); } static void ReplacePushByStore (StackOpData* D) /* Replace the call to the push subroutine by a store into the zero page ** location (actually, the push is not replaced, because we need it for ** later, but the name is still ok since the push will get removed at the ** end of each routine). */ { /* Store the value into the zeropage instead of pushing it. Check high ** byte first so that the store is later in A/X order. */ if ((D->Lhs.X.Flags & LI_DIRECT) == 0) { AddStoreX (D); } if ((D->Lhs.A.Flags & LI_DIRECT) == 0) { AddStoreA (D); } } static void AddOpLow (StackOpData* D, opc_t OPC, LoadInfo* LI) /* Add an op for the low byte of an operator. This function honours the ** OP_DIRECT and OP_RELOAD_Y flags and generates the necessary instructions. ** All code is inserted at the current insertion point. */ { CodeEntry* X; if ((LI->A.Flags & LI_DIRECT) != 0) { /* Op with a variable location. If the location is on the stack, we ** need to reload the Y register. */ if ((LI->A.Flags & LI_RELOAD_Y) == 0) { /* opc ... */ CodeEntry* LoadA = LI->A.LoadEntry; X = NewCodeEntry (OPC, LoadA->AM, LoadA->Arg, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); } else { /* ldy #offs */ const char* Arg = MakeHexArg (LI->A.Offs); X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* opc (sp),y */ X = NewCodeEntry (OPC, AM65_ZP_INDY, "sp", 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); } /* In both cases, we can remove the load */ LI->A.Flags |= LI_REMOVE; } else { /* Op with temp storage */ X = NewCodeEntry (OPC, AM65_ZP, D->ZPLo, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); } } static void AddOpHigh (StackOpData* D, opc_t OPC, LoadInfo* LI, int KeepResult) /* Add an op for the high byte of an operator. Special cases (constant values ** or similar) have to be checked separately, the function covers only the ** generic case. Code is inserted at the insertion point. */ { CodeEntry* X; if (KeepResult) { /* pha */ X = NewCodeEntry (OP65_PHA, AM65_IMP, 0, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); } /* txa */ X = NewCodeEntry (OP65_TXA, AM65_IMP, 0, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); if ((LI->X.Flags & LI_DIRECT) != 0) { if ((LI->X.Flags & LI_RELOAD_Y) == 0) { /* opc xxx */ CodeEntry* LoadX = LI->X.LoadEntry; X = NewCodeEntry (OPC, LoadX->AM, LoadX->Arg, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); } else { /* ldy #const */ const char* Arg = MakeHexArg (LI->X.Offs); X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* opc (sp),y */ X = NewCodeEntry (OPC, AM65_ZP_INDY, "sp", 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); } /* In both cases, we can remove the load */ LI->X.Flags |= LI_REMOVE; } else { /* opc zphi */ X = NewCodeEntry (OPC, AM65_ZP, D->ZPHi, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); } if (KeepResult) { /* tax */ X = NewCodeEntry (OP65_TAX, AM65_IMP, 0, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* pla */ X = NewCodeEntry (OP65_PLA, AM65_IMP, 0, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); } } static void RemoveRegLoads (StackOpData* D, LoadInfo* LI) /* Remove register load insns */ { /* Both registers may be loaded with one insn, but DelEntry will in this ** case clear the other one. */ if ((LI->A.Flags & (LI_REMOVE | LI_DONT_REMOVE)) == LI_REMOVE) { if (LI->A.LoadIndex >= 0) { DelEntry (D, LI->A.LoadIndex); } if (LI->A.XferIndex >= 0) { DelEntry (D, LI->A.XferIndex); } } if ((LI->X.Flags & (LI_REMOVE | LI_DONT_REMOVE)) == LI_REMOVE) { if (LI->X.LoadIndex >= 0) { DelEntry (D, LI->X.LoadIndex); } if (LI->X.XferIndex >= 0) { DelEntry (D, LI->X.XferIndex); } } } static void RemoveRemainders (StackOpData* D) /* Remove the code that is unnecessary after translation of the sequence */ { /* Remove the register loads for lhs and rhs */ RemoveRegLoads (D, &D->Lhs); RemoveRegLoads (D, &D->Rhs); /* Remove the push and the operator routine */ DelEntry (D, D->OpIndex); DelEntry (D, D->PushIndex); } static int IsRegVar (StackOpData* D) /* If the value pushed is that of a zeropage variable, replace ZPLo and ZPHi ** in the given StackOpData struct by the variable and return true. Otherwise ** leave D untouched and return false. */ { CodeEntry* LoadA = D->Lhs.A.LoadEntry; CodeEntry* LoadX = D->Lhs.X.LoadEntry; unsigned Len; /* Must have both load insns */ if (LoadA == 0 || LoadX == 0) { return 0; } /* Must be loads from zp */ if (LoadA->AM != AM65_ZP || LoadX->AM != AM65_ZP) { return 0; } /* Must be the same zp loc with high byte in X */ Len = strlen (LoadA->Arg); if (strncmp (LoadA->Arg, LoadX->Arg, Len) != 0 || strcmp (LoadX->Arg + Len, "+1") != 0) { return 0; } /* Use the zero page location directly */ D->ZPLo = LoadA->Arg; D->ZPHi = LoadX->Arg; return 1; } /*****************************************************************************/ /* Actual optimization functions */ /*****************************************************************************/ static unsigned Opt_toseqax_tosneax (StackOpData* D, const char* BoolTransformer) /* Optimize the toseqax and tosneax sequences. */ { CodeEntry* X; CodeLabel* L; /* Create a call to the boolean transformer function and a label for this ** insn. This is needed for all variants. Other insns are inserted *before* ** the call. */ X = NewCodeEntry (OP65_JSR, AM65_ABS, BoolTransformer, 0, D->OpEntry->LI); InsertEntry (D, X, D->OpIndex + 1); L = CS_GenLabel (D->Code, X); /* If the lhs is direct (but not stack relative), encode compares with lhs ** effectively reverting the order (which doesn't matter for ==). */ if ((D->Lhs.A.Flags & (LI_DIRECT | LI_RELOAD_Y)) == LI_DIRECT && (D->Lhs.X.Flags & (LI_DIRECT | LI_RELOAD_Y)) == LI_DIRECT) { CodeEntry* LoadX = D->Lhs.X.LoadEntry; CodeEntry* LoadA = D->Lhs.A.LoadEntry; D->IP = D->OpIndex+1; /* cpx */ X = NewCodeEntry (OP65_CPX, LoadX->AM, LoadX->Arg, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* bne L */ X = NewCodeEntry (OP65_BNE, AM65_BRA, L->Name, L, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* cmp */ X = NewCodeEntry (OP65_CMP, LoadA->AM, LoadA->Arg, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* Lhs load entries can be removed */ 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) { CodeEntry* LoadX = D->Rhs.X.LoadEntry; CodeEntry* LoadA = D->Rhs.A.LoadEntry; D->IP = D->OpIndex+1; /* cpx */ X = NewCodeEntry (OP65_CPX, LoadX->AM, LoadX->Arg, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* bne L */ X = NewCodeEntry (OP65_BNE, AM65_BRA, L->Name, L, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* cmp */ X = NewCodeEntry (OP65_CMP, LoadA->AM, LoadA->Arg, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* Rhs load entries can be removed */ 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) { D->IP = D->OpIndex+1; /* Add operand for low byte */ AddOpLow (D, OP65_CMP, &D->Rhs); /* bne L */ X = NewCodeEntry (OP65_BNE, AM65_BRA, L->Name, L, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* Add operand for high byte */ AddOpHigh (D, OP65_CMP, &D->Rhs, 0); } else { /* Save lhs into zeropage, then compare */ AddStoreX (D); AddStoreA (D); D->IP = D->OpIndex+1; /* cpx */ X = NewCodeEntry (OP65_CPX, AM65_ZP, D->ZPHi, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* bne L */ X = NewCodeEntry (OP65_BNE, AM65_BRA, L->Name, L, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* cmp */ X = NewCodeEntry (OP65_CMP, AM65_ZP, D->ZPLo, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); } /* Remove the push and the call to the tosgeax function */ RemoveRemainders (D); /* We changed the sequence */ return 1; } static unsigned Opt_tosshift (StackOpData* D, const char* Name) /* Optimize shift sequences. */ { CodeEntry* X; /* Store the value into the zeropage instead of pushing it */ ReplacePushByStore (D); /* If the lhs is direct (but not stack relative), we can just reload the ** data later. */ if ((D->Lhs.A.Flags & (LI_DIRECT | LI_RELOAD_Y)) == LI_DIRECT && (D->Lhs.X.Flags & (LI_DIRECT | LI_RELOAD_Y)) == LI_DIRECT) { CodeEntry* LoadX = D->Lhs.X.LoadEntry; CodeEntry* LoadA = D->Lhs.A.LoadEntry; /* Inline the shift */ D->IP = D->OpIndex+1; /* tay */ X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* lda */ X = NewCodeEntry (OP65_LDA, LoadA->AM, LoadA->Arg, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* ldx */ X = NewCodeEntry (OP65_LDX, LoadX->AM, LoadX->Arg, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* Lhs load entries can be removed */ D->Lhs.X.Flags |= LI_REMOVE; D->Lhs.A.Flags |= LI_REMOVE; } else { /* Save lhs into zeropage and reload later */ AddStoreX (D); AddStoreA (D); /* Be sure to setup IP after adding the stores, otherwise it will get ** messed up. */ D->IP = D->OpIndex+1; /* tay */ X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* lda zp */ X = NewCodeEntry (OP65_LDA, AM65_ZP, D->ZPLo, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* ldx zp+1 */ X = NewCodeEntry (OP65_LDX, AM65_ZP, D->ZPHi, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); } /* jsr shlaxy/aslaxy/whatever */ X = NewCodeEntry (OP65_JSR, AM65_ABS, Name, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* Remove the push and the call to the shift function */ RemoveRemainders (D); /* We changed the sequence */ return 1; } static unsigned Opt___bzero (StackOpData* D) /* Optimize the __bzero sequence */ { CodeEntry* X; const char* Arg; CodeLabel* L; /* Check if we're using a register variable */ if (!IsRegVar (D)) { /* Store the value into the zeropage instead of pushing it */ AddStoreX (D); AddStoreA (D); } /* If the return value of __bzero is used, we have to add code to reload ** a/x from the pointer variable. */ if (RegAXUsed (D->Code, D->OpIndex+1)) { X = NewCodeEntry (OP65_LDA, AM65_ZP, D->ZPLo, 0, D->OpEntry->LI); InsertEntry (D, X, D->OpIndex+1); X = NewCodeEntry (OP65_LDX, AM65_ZP, D->ZPHi, 0, D->OpEntry->LI); InsertEntry (D, X, D->OpIndex+2); } /* X is always zero, A contains the size of the data area to zero. ** Note: A may be zero, in which case the operation is null op. */ if (D->OpEntry->RI->In.RegA != 0) { /* lda #$00 */ X = NewCodeEntry (OP65_LDA, AM65_IMM, "$00", 0, D->OpEntry->LI); InsertEntry (D, X, D->OpIndex+1); /* The value of A is known */ if (D->OpEntry->RI->In.RegA <= 0x81) { /* Loop using the sign bit */ /* ldy #count-1 */ Arg = MakeHexArg (D->OpEntry->RI->In.RegA - 1); X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, D->OpEntry->LI); InsertEntry (D, X, D->OpIndex+2); /* L: sta (zp),y */ X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, D->ZPLo, 0, D->OpEntry->LI); InsertEntry (D, X, D->OpIndex+3); L = CS_GenLabel (D->Code, X); /* dey */ X = NewCodeEntry (OP65_DEY, AM65_IMP, 0, 0, D->OpEntry->LI); InsertEntry (D, X, D->OpIndex+4); /* bpl L */ X = NewCodeEntry (OP65_BPL, AM65_BRA, L->Name, L, D->OpEntry->LI); InsertEntry (D, X, D->OpIndex+5); } else { /* Loop using an explicit compare */ /* ldy #$00 */ X = NewCodeEntry (OP65_LDY, AM65_IMM, "$00", 0, D->OpEntry->LI); InsertEntry (D, X, D->OpIndex+2); /* L: sta (zp),y */ X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, D->ZPLo, 0, D->OpEntry->LI); InsertEntry (D, X, D->OpIndex+3); L = CS_GenLabel (D->Code, X); /* iny */ X = NewCodeEntry (OP65_INY, AM65_IMP, 0, 0, D->OpEntry->LI); InsertEntry (D, X, D->OpIndex+4); /* cpy #count */ Arg = MakeHexArg (D->OpEntry->RI->In.RegA); X = NewCodeEntry (OP65_CPY, AM65_IMM, Arg, 0, D->OpEntry->LI); InsertEntry (D, X, D->OpIndex+5); /* bne L */ X = NewCodeEntry (OP65_BNE, AM65_BRA, L->Name, L, D->OpEntry->LI); InsertEntry (D, X, D->OpIndex+6); } } /* Remove the push and the call to the __bzero function */ RemoveRemainders (D); /* We changed the sequence */ return 1; } static unsigned Opt_staspidx (StackOpData* D) /* Optimize the staspidx sequence */ { CodeEntry* X; /* Check if we're using a register variable */ if (!IsRegVar (D)) { /* Store the value into the zeropage instead of pushing it */ AddStoreX (D); AddStoreA (D); } /* Replace the store subroutine call by a direct op */ X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, D->ZPLo, 0, D->OpEntry->LI); InsertEntry (D, X, D->OpIndex+1); /* Remove the push and the call to the staspidx function */ RemoveRemainders (D); /* We changed the sequence */ return 1; } static unsigned Opt_staxspidx (StackOpData* D) /* Optimize the staxspidx sequence */ { CodeEntry* X; /* Check if we're using a register variable */ if (!IsRegVar (D)) { /* Store the value into the zeropage instead of pushing it */ AddStoreX (D); AddStoreA (D); } /* Inline the store */ /* sta (zp),y */ X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, D->ZPLo, 0, D->OpEntry->LI); InsertEntry (D, X, D->OpIndex+1); if (RegValIsKnown (D->OpEntry->RI->In.RegY)) { /* Value of Y is known */ const char* Arg = MakeHexArg (D->OpEntry->RI->In.RegY + 1); X = NewCodeEntry (OP65_LDY, AM65_IMM, Arg, 0, D->OpEntry->LI); } else { X = NewCodeEntry (OP65_INY, AM65_IMP, 0, 0, D->OpEntry->LI); } InsertEntry (D, X, D->OpIndex+2); if (RegValIsKnown (D->OpEntry->RI->In.RegX)) { /* Value of X is known */ const char* Arg = MakeHexArg (D->OpEntry->RI->In.RegX); X = NewCodeEntry (OP65_LDA, AM65_IMM, Arg, 0, D->OpEntry->LI); } else { /* Value unknown */ X = NewCodeEntry (OP65_TXA, AM65_IMP, 0, 0, D->OpEntry->LI); } InsertEntry (D, X, D->OpIndex+3); /* sta (zp),y */ X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, D->ZPLo, 0, D->OpEntry->LI); InsertEntry (D, X, D->OpIndex+4); /* If we remove staxspidx, we must restore the Y register to what the ** function would return. */ X = NewCodeEntry (OP65_LDY, AM65_IMM, "$00", 0, D->OpEntry->LI); InsertEntry (D, X, D->OpIndex+5); /* Remove the push and the call to the staxspidx function */ RemoveRemainders (D); /* We changed the sequence */ return 1; } static unsigned Opt_tosaddax (StackOpData* D) /* Optimize the tosaddax sequence */ { CodeEntry* X; CodeEntry* N; /* We need the entry behind the add */ CHECK (D->NextEntry != 0); /* Check if the X register is known and zero when the add is done, and ** if the add is followed by ** ** ldy #$00 ** jsr ldauidx ; or ldaidx ** ** If this is true, the addition does actually add an offset to a pointer ** before it is dereferenced. Since both subroutines take an offset in Y, ** we can pass the offset (instead of #$00) and remove the addition ** alltogether. */ if (D->OpEntry->RI->In.RegX == 0 && D->NextEntry->OPC == OP65_LDY && CE_IsKnownImm (D->NextEntry, 0) && !CE_HasLabel (D->NextEntry) && (N = CS_GetNextEntry (D->Code, D->OpIndex + 1)) != 0 && (CE_IsCallTo (N, "ldauidx") || CE_IsCallTo (N, "ldaidx"))) { int Signed = (strcmp (N->Arg, "ldaidx") == 0); /* Store the value into the zeropage instead of pushing it */ AddStoreX (D); AddStoreA (D); /* Replace the ldy by a tay. Be sure to create the new entry before ** deleting the ldy, since we will reference the line info from this ** insn. */ X = NewCodeEntry (OP65_TAY, AM65_IMP, 0, 0, D->NextEntry->LI); DelEntry (D, D->OpIndex + 1); InsertEntry (D, X, D->OpIndex + 1); /* Replace the call to ldaidx/ldauidx. Since X is already zero, and ** the ptr is in the zero page location, we just need to load from ** the pointer, and fix X in case of ldaidx. */ X = NewCodeEntry (OP65_LDA, AM65_ZP_INDY, D->ZPLo, 0, N->LI); DelEntry (D, D->OpIndex + 2); InsertEntry (D, X, D->OpIndex + 2); if (Signed) { CodeLabel* L; /* Add sign extension - N is unused now */ N = CS_GetNextEntry (D->Code, D->OpIndex + 2); CHECK (N != 0); L = CS_GenLabel (D->Code, N); X = NewCodeEntry (OP65_BPL, AM65_BRA, L->Name, L, X->LI); InsertEntry (D, X, D->OpIndex + 3); X = NewCodeEntry (OP65_DEX, AM65_IMP, 0, 0, X->LI); InsertEntry (D, X, D->OpIndex + 4); } } else { /* Store the value into the zeropage instead of pushing it */ ReplacePushByStore (D); /* Inline the add */ D->IP = D->OpIndex+1; /* clc */ X = NewCodeEntry (OP65_CLC, AM65_IMP, 0, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* Low byte */ AddOpLow (D, OP65_ADC, &D->Lhs); /* High byte */ if (D->PushEntry->RI->In.RegX == 0) { /* The high byte is the value in X plus the carry */ CodeLabel* L = CS_GenLabel (D->Code, D->NextEntry); /* bcc L */ X = NewCodeEntry (OP65_BCC, AM65_BRA, L->Name, L, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* inx */ X = NewCodeEntry (OP65_INX, AM65_IMP, 0, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); } else if (D->OpEntry->RI->In.RegX == 0 && (RegValIsKnown (D->PushEntry->RI->In.RegX) || (D->Lhs.X.Flags & LI_RELOAD_Y) == 0)) { /* The high byte is that of the first operand plus carry */ CodeLabel* L; if (RegValIsKnown (D->PushEntry->RI->In.RegX)) { /* Value of first op high byte is known */ const char* Arg = MakeHexArg (D->PushEntry->RI->In.RegX); X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, D->OpEntry->LI); } else { /* Value of first op high byte is unknown. Load from ZP or ** original storage. */ if (D->Lhs.X.Flags & LI_DIRECT) { CodeEntry* LoadX = D->Lhs.X.LoadEntry; X = NewCodeEntry (OP65_LDX, LoadX->AM, LoadX->Arg, 0, D->OpEntry->LI); } else { X = NewCodeEntry (OP65_LDX, AM65_ZP, D->ZPHi, 0, D->OpEntry->LI); } } InsertEntry (D, X, D->IP++); /* bcc label */ L = CS_GenLabel (D->Code, D->NextEntry); X = NewCodeEntry (OP65_BCC, AM65_BRA, L->Name, L, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* inx */ X = NewCodeEntry (OP65_INX, AM65_IMP, 0, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); } else { /* High byte is unknown */ AddOpHigh (D, OP65_ADC, &D->Lhs, 1); } } /* Remove the push and the call to the tosaddax function */ RemoveRemainders (D); /* We changed the sequence */ return 1; } static unsigned Opt_tosandax (StackOpData* D) /* Optimize the tosandax sequence */ { /* Store the value into the zeropage instead of pushing it */ ReplacePushByStore (D); /* Inline the and, low byte */ D->IP = D->OpIndex + 1; AddOpLow (D, OP65_AND, &D->Lhs); /* High byte */ AddOpHigh (D, OP65_AND, &D->Lhs, 1); /* Remove the push and the call to the tosandax function */ RemoveRemainders (D); /* We changed the sequence */ return 1; } static unsigned Opt_tosaslax (StackOpData* D) /* Optimize the tosaslax sequence */ { return Opt_tosshift (D, "aslaxy"); } static unsigned Opt_tosasrax (StackOpData* D) /* Optimize the tosasrax sequence */ { return Opt_tosshift (D, "asraxy"); } static unsigned Opt_toseqax (StackOpData* D) /* Optimize the toseqax sequence */ { return Opt_toseqax_tosneax (D, "booleq"); } static unsigned Opt_tosgeax (StackOpData* D) /* Optimize the tosgeax sequence */ { CodeEntry* X; CodeLabel* L; /* Inline the sbc */ D->IP = D->OpIndex+1; /* Must be true because of OP_RHS_LOAD */ CHECK ((D->Rhs.A.Flags & D->Rhs.X.Flags & LI_DIRECT) != 0); /* Add code for low operand */ AddOpLow (D, OP65_CMP, &D->Rhs); /* Add code for high operand */ AddOpHigh (D, OP65_SBC, &D->Rhs, 0); /* eor #$80 */ X = NewCodeEntry (OP65_EOR, AM65_IMM, "$80", 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* asl a */ X = NewCodeEntry (OP65_ASL, AM65_ACC, "a", 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); L = CS_GenLabel (D->Code, X); /* Insert a bvs L before the eor insn */ X = NewCodeEntry (OP65_BVS, AM65_BRA, L->Name, L, D->OpEntry->LI); InsertEntry (D, X, D->IP - 2); ++D->IP; /* lda #$00 */ X = NewCodeEntry (OP65_LDA, AM65_IMM, "$00", 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* ldx #$00 */ X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* rol a */ X = NewCodeEntry (OP65_ROL, AM65_ACC, "a", 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* Remove the push and the call to the tosgeax function */ RemoveRemainders (D); /* We changed the sequence */ return 1; } static unsigned Opt_tosltax (StackOpData* D) /* Optimize the tosltax sequence */ { CodeEntry* X; CodeLabel* L; /* Inline the compare */ D->IP = D->OpIndex+1; /* Must be true because of OP_RHS_LOAD */ CHECK ((D->Rhs.A.Flags & D->Rhs.X.Flags & LI_DIRECT) != 0); /* Add code for low operand */ AddOpLow (D, OP65_CMP, &D->Rhs); /* Add code for high operand */ AddOpHigh (D, OP65_SBC, &D->Rhs, 0); /* eor #$80 */ X = NewCodeEntry (OP65_EOR, AM65_IMM, "$80", 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* asl a */ X = NewCodeEntry (OP65_ASL, AM65_ACC, "a", 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); L = CS_GenLabel (D->Code, X); /* Insert a bvc L before the eor insn */ X = NewCodeEntry (OP65_BVC, AM65_BRA, L->Name, L, D->OpEntry->LI); InsertEntry (D, X, D->IP - 2); ++D->IP; /* lda #$00 */ X = NewCodeEntry (OP65_LDA, AM65_IMM, "$00", 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* ldx #$00 */ X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* rol a */ X = NewCodeEntry (OP65_ROL, AM65_ACC, "a", 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* Remove the push and the call to the tosltax function */ RemoveRemainders (D); /* We changed the sequence */ return 1; } static unsigned Opt_tosneax (StackOpData* D) /* Optimize the tosneax sequence */ { return Opt_toseqax_tosneax (D, "boolne"); } static unsigned Opt_tosorax (StackOpData* D) /* Optimize the tosorax sequence */ { /* Store the value into the zeropage instead of pushing it */ ReplacePushByStore (D); /* Inline the or, low byte */ D->IP = D->OpIndex + 1; AddOpLow (D, OP65_ORA, &D->Lhs); /* High byte */ AddOpHigh (D, OP65_ORA, &D->Lhs, 1); /* Remove the push and the call to the tosorax function */ RemoveRemainders (D); /* We changed the sequence */ return 1; } static unsigned Opt_tosshlax (StackOpData* D) /* Optimize the tosshlax sequence */ { return Opt_tosshift (D, "shlaxy"); } static unsigned Opt_tosshrax (StackOpData* D) /* Optimize the tosshrax sequence */ { return Opt_tosshift (D, "shraxy"); } static unsigned Opt_tossubax (StackOpData* D) /* Optimize the tossubax sequence. Note: subtraction is not commutative! */ { CodeEntry* X; /* Inline the sbc */ D->IP = D->OpIndex+1; /* sec */ X = NewCodeEntry (OP65_SEC, AM65_IMP, 0, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* Must be true because of OP_RHS_LOAD */ CHECK ((D->Rhs.A.Flags & D->Rhs.X.Flags & LI_DIRECT) != 0); /* Add code for low operand */ AddOpLow (D, OP65_SBC, &D->Rhs); /* Add code for high operand */ AddOpHigh (D, OP65_SBC, &D->Rhs, 1); /* Remove the push and the call to the tossubax function */ RemoveRemainders (D); /* We changed the sequence */ return 1; } static unsigned Opt_tosugeax (StackOpData* D) /* Optimize the tosugeax sequence */ { CodeEntry* X; /* Inline the sbc */ D->IP = D->OpIndex+1; /* Must be true because of OP_RHS_LOAD */ CHECK ((D->Rhs.A.Flags & D->Rhs.X.Flags & LI_DIRECT) != 0); /* Add code for low operand */ AddOpLow (D, OP65_CMP, &D->Rhs); /* Add code for high operand */ AddOpHigh (D, OP65_SBC, &D->Rhs, 0); /* lda #$00 */ X = NewCodeEntry (OP65_LDA, AM65_IMM, "$00", 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* ldx #$00 */ X = NewCodeEntry (OP65_LDX, AM65_IMM, "$00", 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* rol a */ X = NewCodeEntry (OP65_ROL, AM65_ACC, "a", 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* Remove the push and the call to the tosugeax function */ RemoveRemainders (D); /* We changed the sequence */ return 1; } static unsigned Opt_tosugtax (StackOpData* D) /* Optimize the tosugtax sequence */ { CodeEntry* X; /* Inline the sbc */ D->IP = D->OpIndex+1; /* Must be true because of OP_RHS_LOAD */ CHECK ((D->Rhs.A.Flags & D->Rhs.X.Flags & LI_DIRECT) != 0); /* sec */ X = NewCodeEntry (OP65_SEC, AM65_IMP, 0, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* Add code for low operand */ AddOpLow (D, OP65_SBC, &D->Rhs); /* We need the zero flag, so remember the immediate result */ X = NewCodeEntry (OP65_STA, AM65_ZP, "tmp1", 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* Add code for high operand */ AddOpHigh (D, OP65_SBC, &D->Rhs, 0); /* Set Z flag */ X = NewCodeEntry (OP65_ORA, AM65_ZP, "tmp1", 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* Transform to boolean */ X = NewCodeEntry (OP65_JSR, AM65_ABS, "boolugt", 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* Remove the push and the call to the operator function */ RemoveRemainders (D); /* We changed the sequence */ return 1; } static unsigned Opt_tosuleax (StackOpData* D) /* Optimize the tosuleax sequence */ { CodeEntry* X; /* Inline the sbc */ D->IP = D->OpIndex+1; /* Must be true because of OP_RHS_LOAD */ CHECK ((D->Rhs.A.Flags & D->Rhs.X.Flags & LI_DIRECT) != 0); /* sec */ X = NewCodeEntry (OP65_SEC, AM65_IMP, 0, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* Add code for low operand */ AddOpLow (D, OP65_SBC, &D->Rhs); /* We need the zero flag, so remember the immediate result */ X = NewCodeEntry (OP65_STA, AM65_ZP, "tmp1", 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* Add code for high operand */ AddOpHigh (D, OP65_SBC, &D->Rhs, 0); /* Set Z flag */ X = NewCodeEntry (OP65_ORA, AM65_ZP, "tmp1", 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* Transform to boolean */ X = NewCodeEntry (OP65_JSR, AM65_ABS, "boolule", 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* Remove the push and the call to the operator function */ RemoveRemainders (D); /* We changed the sequence */ return 1; } static unsigned Opt_tosultax (StackOpData* D) /* Optimize the tosultax sequence */ { CodeEntry* X; /* Inline the sbc */ D->IP = D->OpIndex+1; /* Must be true because of OP_RHS_LOAD */ CHECK ((D->Rhs.A.Flags & D->Rhs.X.Flags & LI_DIRECT) != 0); /* Add code for low operand */ AddOpLow (D, OP65_CMP, &D->Rhs); /* Add code for high operand */ AddOpHigh (D, OP65_SBC, &D->Rhs, 0); /* Transform to boolean */ X = NewCodeEntry (OP65_JSR, AM65_ABS, "boolult", 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); /* Remove the push and the call to the operator function */ RemoveRemainders (D); /* We changed the sequence */ return 1; } static unsigned Opt_tosxorax (StackOpData* D) /* Optimize the tosxorax sequence */ { CodeEntry* X; /* Store the value into the zeropage instead of pushing it */ ReplacePushByStore (D); /* Inline the xor, low byte */ D->IP = D->OpIndex + 1; AddOpLow (D, OP65_EOR, &D->Lhs); /* High byte */ if (RegValIsKnown (D->PushEntry->RI->In.RegX) && RegValIsKnown (D->OpEntry->RI->In.RegX)) { /* Both values known, precalculate the result */ const char* Arg = MakeHexArg (D->PushEntry->RI->In.RegX ^ D->OpEntry->RI->In.RegX); X = NewCodeEntry (OP65_LDX, AM65_IMM, Arg, 0, D->OpEntry->LI); InsertEntry (D, X, D->IP++); } else if (D->PushEntry->RI->In.RegX != 0) { /* High byte is unknown */ AddOpHigh (D, OP65_EOR, &D->Lhs, 1); } /* Remove the push and the call to the tosandax function */ RemoveRemainders (D); /* We changed the sequence */ return 1; } /*****************************************************************************/ /* Code */ /*****************************************************************************/ static const OptFuncDesc FuncTable[] = { { "__bzero", Opt___bzero, REG_NONE, OP_X_ZERO | OP_A_KNOWN }, { "staspidx", Opt_staspidx, REG_NONE, OP_NONE }, { "staxspidx", Opt_staxspidx, REG_AX, OP_NONE }, { "tosaddax", Opt_tosaddax, REG_NONE, OP_NONE }, { "tosandax", Opt_tosandax, REG_NONE, OP_NONE }, { "tosaslax", Opt_tosaslax, REG_NONE, OP_NONE }, { "tosasrax", Opt_tosasrax, REG_NONE, OP_NONE }, { "toseqax", Opt_toseqax, REG_NONE, OP_NONE }, { "tosgeax", Opt_tosgeax, REG_NONE, OP_RHS_LOAD_DIRECT }, { "tosltax", Opt_tosltax, REG_NONE, OP_RHS_LOAD_DIRECT }, { "tosneax", Opt_tosneax, REG_NONE, OP_NONE }, { "tosorax", Opt_tosorax, REG_NONE, OP_NONE }, { "tosshlax", Opt_tosshlax, REG_NONE, OP_NONE }, { "tosshrax", Opt_tosshrax, REG_NONE, OP_NONE }, { "tossubax", Opt_tossubax, REG_NONE, OP_RHS_LOAD_DIRECT }, { "tosugeax", Opt_tosugeax, REG_NONE, OP_RHS_LOAD_DIRECT }, { "tosugtax", Opt_tosugtax, REG_NONE, OP_RHS_LOAD_DIRECT }, { "tosuleax", Opt_tosuleax, REG_NONE, OP_RHS_LOAD_DIRECT }, { "tosultax", Opt_tosultax, REG_NONE, OP_RHS_LOAD_DIRECT }, { "tosxorax", Opt_tosxorax, REG_NONE, OP_NONE }, }; #define FUNC_COUNT (sizeof(FuncTable) / sizeof(FuncTable[0])) static int CmpFunc (const void* Key, const void* Func) /* Compare function for bsearch */ { return strcmp (Key, ((const OptFuncDesc*) Func)->Name); } static const OptFuncDesc* FindFunc (const char* Name) /* Find the function with the given name. Return a pointer to the table entry ** or NULL if the function was not found. */ { return bsearch (Name, FuncTable, FUNC_COUNT, sizeof(OptFuncDesc), CmpFunc); } static int CmpHarmless (const void* Key, const void* Entry) /* Compare function for bsearch */ { return strcmp (Key, *(const char**)Entry); } static int HarmlessCall (const char* Name) /* Check if this is a call to a harmless subroutine that will not interrupt ** the pushax/op sequence when encountered. */ { static const char* const Tab[] = { "aslax1", "aslax2", "aslax3", "aslax4", "aslaxy", "asrax1", "asrax2", "asrax3", "asrax4", "asraxy", "bnegax", "complax", "decax1", "decax2", "decax3", "decax4", "decax5", "decax6", "decax7", "decax8", "decaxy", "incax1", "incax2", "incax3", "incax4", "incax5", "incax6", "incax7", "incax8", "incaxy", "ldaxidx", "ldaxysp", "negax", "shlax1", "shlax2", "shlax3", "shlax4", "shlaxy", "shrax1", "shrax2", "shrax3", "shrax4", "shraxy", }; void* R = bsearch (Name, Tab, sizeof (Tab) / sizeof (Tab[0]), sizeof (Tab[0]), CmpHarmless); return (R != 0); } static void ResetStackOpData (StackOpData* Data) /* Reset the given data structure */ { Data->OptFunc = 0; Data->ZPUsage = REG_NONE; ClearLoadInfo (&Data->Lhs); ClearLoadInfo (&Data->Rhs); Data->PushIndex = -1; Data->OpIndex = -1; } static int PreCondOk (StackOpData* D) /* Check if the preconditions for a call to the optimizer subfunction are ** satisfied. As a side effect, this function will also choose the zero page ** register to use. */ { /* Check the flags */ unsigned UnusedRegs = D->OptFunc->UnusedRegs; if (UnusedRegs != REG_NONE && (GetRegInfo (D->Code, D->OpIndex+1, UnusedRegs) & UnusedRegs) != 0) { /* Cannot optimize */ return 0; } if ((D->OptFunc->Flags & OP_A_KNOWN) != 0 && RegValIsUnknown (D->OpEntry->RI->In.RegA)) { /* Cannot optimize */ return 0; } if ((D->OptFunc->Flags & OP_X_ZERO) != 0 && D->OpEntry->RI->In.RegX != 0) { /* Cannot optimize */ return 0; } if ((D->OptFunc->Flags & OP_LHS_LOAD) != 0) { if (D->Lhs.A.LoadIndex < 0 || D->Lhs.X.LoadIndex < 0) { /* Cannot optimize */ return 0; } else if ((D->OptFunc->Flags & OP_LHS_LOAD_DIRECT) != 0) { if ((D->Lhs.A.Flags & D->Lhs.X.Flags & LI_DIRECT) == 0) { /* Cannot optimize */ return 0; } } } if ((D->OptFunc->Flags & OP_RHS_LOAD) != 0) { if (D->Rhs.A.LoadIndex < 0 || D->Rhs.X.LoadIndex < 0) { /* Cannot optimize */ return 0; } else if ((D->OptFunc->Flags & OP_RHS_LOAD_DIRECT) != 0) { if ((D->Rhs.A.Flags & D->Rhs.X.Flags & LI_DIRECT) == 0) { /* Cannot optimize */ return 0; } } } if ((D->Rhs.A.Flags | D->Rhs.X.Flags) & LI_DUP_LOAD) { /* Cannot optimize */ return 0; } /* Determine the zero page locations to use. We've tracked the used ** ZP locations, so try to find some for us that are unused. */ if ((D->ZPUsage & REG_PTR1) == REG_NONE) { D->ZPLo = "ptr1"; D->ZPHi = "ptr1+1"; } else if ((D->ZPUsage & REG_SREG) == REG_NONE) { D->ZPLo = "sreg"; D->ZPHi = "sreg+1"; } else if ((D->ZPUsage & REG_PTR2) == REG_NONE) { D->ZPLo = "ptr2"; D->ZPHi = "ptr2+1"; } else { /* No registers available */ return 0; } /* Determine if we have a basic block */ return CS_IsBasicBlock (D->Code, D->PushIndex, D->OpIndex); } /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned OptStackOps (CodeSeg* S) /* Optimize operations that take operands via the stack */ { unsigned Changes = 0; /* Number of changes in one run */ StackOpData Data; int I; int OldEntryCount; /* Old number of entries */ unsigned UsedRegs = 0; /* Registers used */ unsigned ChangedRegs = 0;/* Registers changed */ enum { Initialize, Search, FoundPush, FoundOp } State = Initialize; /* Remember the code segment in the info struct */ Data.Code = S; /* Look for a call to pushax followed by a call to some other function ** that takes it's first argument on the stack, and the second argument ** in the primary register. ** It depends on the code between the two if we can handle/transform the ** sequence, so check this code for the following list of things: ** ** - the range must be a basic block (one entry, one exit) ** - there may not be accesses to local variables with unknown ** offsets (because we have to adjust these offsets). ** - no subroutine calls ** - no jump labels ** ** Since we need a zero page register later, do also check the ** intermediate code for zero page use. */ I = 0; while (I < (int)CS_GetEntryCount (S)) { /* Get the next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Actions depend on state */ switch (State) { case Initialize: ResetStackOpData (&Data); UsedRegs = ChangedRegs = REG_NONE; State = Search; /* FALLTHROUGH */ case Search: /* While searching, track register load insns, so we can tell ** what is in a register once pushax is encountered. */ if (CE_HasLabel (E)) { /* Currently we don't track across branches */ ClearLoadInfo (&Data.Lhs); } if (CE_IsCallTo (E, "pushax")) { Data.PushIndex = I; State = FoundPush; } else { /* Track load insns */ TrackLoads (&Data.Lhs, E, I); } break; case FoundPush: /* We' found a pushax before. Search for a stack op that may ** follow and in the meantime, track zeropage usage and check ** for code that will disable us from translating the sequence. */ if (CE_HasLabel (E)) { /* Currently we don't track across branches */ ClearLoadInfo (&Data.Rhs); } if (E->OPC == OP65_JSR) { /* Subroutine call: Check if this is one of the functions, ** we're going to replace. */ Data.OptFunc = FindFunc (E->Arg); if (Data.OptFunc) { /* Remember the op index and go on */ Data.OpIndex = I; Data.OpEntry = E; State = FoundOp; break; } else if (!HarmlessCall (E->Arg)) { /* A call to an unkown subroutine: We need to start ** over after the last pushax. Note: This will also ** happen if we encounter a call to pushax! */ I = Data.PushIndex; State = Initialize; break; } else { /* Track register usage */ Data.ZPUsage |= (E->Use | E->Chg); TrackLoads (&Data.Rhs, E, I); } } else if (E->Info & OF_STORE && (E->Chg & REG_ZP) == 0) { /* Too dangerous - there may be a change of a variable ** within the sequence. */ I = Data.PushIndex; State = Initialize; break; } else if ((E->Use & REG_SP) != 0 && (E->AM != AM65_ZP_INDY || RegValIsUnknown (E->RI->In.RegY) || E->RI->In.RegY < 2)) { /* If we are using the stack, and we don't have "indirect Y" ** addressing mode, or the value of Y is unknown, or less ** than two, we cannot cope with this piece of code. Having ** an unknown value of Y means that we cannot correct the ** stack offset, while having an offset less than two means ** that the code works with the value on stack which is to ** be removed. */ I = Data.PushIndex; State = Initialize; break; } else { /* Other stuff: Track register usage */ Data.ZPUsage |= (E->Use | E->Chg); TrackLoads (&Data.Rhs, E, I); } /* If the registers from the push (A/X) are used before they're ** changed, we cannot change the sequence, because this would ** with a high probability change the register contents. */ UsedRegs |= E->Use; if ((UsedRegs & ~ChangedRegs) & REG_AX) { I = Data.PushIndex; State = Initialize; break; } ChangedRegs |= E->Chg; break; case FoundOp: /* Track zero page location usage beyond this point */ Data.ZPUsage |= GetRegInfo (S, I, REG_SREG | REG_PTR1 | REG_PTR2); /* Finalize the load info */ FinalizeLoadInfo (&Data.Lhs, S); FinalizeLoadInfo (&Data.Rhs, S); /* Check if the lhs loads from zeropage. If this is true, these ** zero page locations have to be added to ZPUsage, because ** they cannot be used for intermediate storage. In addition, ** if one of these zero page locations is destroyed between ** pushing the lhs and the actual operation, we cannot use the ** original zero page locations for the final op, but must ** use another ZP location to save them. */ ChangedRegs &= REG_ZP; if (Data.Lhs.A.LoadEntry && Data.Lhs.A.LoadEntry->AM == AM65_ZP) { Data.ZPUsage |= Data.Lhs.A.LoadEntry->Use; if ((Data.Lhs.A.LoadEntry->Use & ChangedRegs) != 0) { Data.Lhs.A.Flags &= ~(LI_DIRECT | LI_RELOAD_Y); } } if (Data.Lhs.X.LoadEntry && Data.Lhs.X.LoadEntry->AM == AM65_ZP) { Data.ZPUsage |= Data.Lhs.X.LoadEntry->Use; if ((Data.Lhs.X.LoadEntry->Use & ChangedRegs) != 0) { Data.Lhs.X.Flags &= ~(LI_DIRECT | LI_RELOAD_Y); } } /* Check the preconditions. If they aren't ok, reset the insn ** pointer to the pushax and start over. We will loose part of ** load tracking but at least a/x has probably lost between ** pushax and here and will be tracked again when restarting. */ if (!PreCondOk (&Data)) { I = Data.PushIndex; State = Initialize; break; } /* Prepare the remainder of the data structure. */ Data.PrevEntry = CS_GetPrevEntry (S, Data.PushIndex); Data.PushEntry = CS_GetEntry (S, Data.PushIndex); Data.OpEntry = CS_GetEntry (S, Data.OpIndex); Data.NextEntry = CS_GetNextEntry (S, Data.OpIndex); /* Remember the current number of code lines */ OldEntryCount = CS_GetEntryCount (S); /* Adjust stack offsets to account for the upcoming removal */ AdjustStackOffset (&Data, 2); /* Regenerate register info, since AdjustStackOffset changed ** the code */ CS_GenRegInfo (S); /* Call the optimizer function */ Changes += Data.OptFunc->Func (&Data); /* Since the function may have added or deleted entries, ** correct the index. */ I += CS_GetEntryCount (S) - OldEntryCount; /* Regenerate register info */ CS_GenRegInfo (S); /* Done */ State = Initialize; continue; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/coptstop.h�����������������������������������������������������������������������0000664�0000000�0000000�00000005703�13473601511�0015565�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* coptstop.h */ /* */ /* Optimize operations that take operands via the stack */ /* */ /* */ /* */ /* (C) 2001 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef COPTSTOP_H #define COPTSTOP_H /* cc65 */ #include "codeseg.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned OptStackOps (CodeSeg* S); /* Optimize operations that take operands via the stack */ /* End of coptstop.h */ #endif �������������������������������������������������������������cc65-2.18/src/cc65/coptstore.c����������������������������������������������������������������������0000664�0000000�0000000�00000034656�13473601511�0015740�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* coptstore.c */ /* */ /* Optimize stores */ /* */ /* */ /* */ /* (C) 2002-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* cc65 */ #include "codeent.h" #include "codeinfo.h" #include "coptstore.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void InsertStore (CodeSeg* S, unsigned* IP, LineInfo* LI) { CodeEntry* X = NewCodeEntry (OP65_STA, AM65_ZP_INDY, "sp", 0, LI); CS_InsertEntry (S, X, (*IP)++); } unsigned OptStore1 (CodeSeg* S) /* Search for the sequence ** ** ldy #n ** jsr staxysp ** ldy #n+1 ** jsr ldaxysp ** ** and remove the useless load. */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[4]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (L[0]->OPC == OP65_LDY && CE_IsConstImm (L[0]) && L[0]->Num < 0xFF && !CS_RangeHasLabel (S, I+1, 3) && CS_GetEntries (S, L+1, I+1, 3) && CE_IsCallTo (L[1], "staxysp") && L[2]->OPC == OP65_LDY && CE_IsKnownImm (L[2], L[0]->Num + 1) && CE_IsCallTo (L[3], "ldaxysp")) { /* Register has already the correct value, remove the loads */ CS_DelEntries (S, I+2, 2); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptStore2 (CodeSeg* S) /* Search for a call to staxysp. If the ax register is not used later, and ** the value is constant, just use the A register and store directly into the ** stack. */ { unsigned I; unsigned Changes = 0; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Get the input registers */ const RegInfo* RI = E->RI; /* Check for the call */ if (CE_IsCallTo (E, "staxysp") && RegValIsKnown (RI->In.RegA) && RegValIsKnown (RI->In.RegX) && RegValIsKnown (RI->In.RegY) && !RegAXUsed (S, I+1)) { /* Get the register values */ unsigned char A = (unsigned char) RI->In.RegA; unsigned char X = (unsigned char) RI->In.RegX; unsigned char Y = (unsigned char) RI->In.RegY; /* Setup other variables */ CodeEntry* N; unsigned IP = I + 1; /* Insertion point */ /* Replace the store. We will not remove the loads, since this is ** too complex and will be done by other optimizer steps. */ N = NewCodeEntry (OP65_LDA, AM65_IMM, MakeHexArg (A), 0, E->LI); CS_InsertEntry (S, N, IP++); InsertStore (S, &IP, E->LI); /* Check if we can store one of the other bytes */ if (A != X) { N = NewCodeEntry (OP65_LDA, AM65_IMM, MakeHexArg (X), 0, E->LI); CS_InsertEntry (S, N, IP++); } N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+1), 0, E->LI); CS_InsertEntry (S, N, IP++); InsertStore (S, &IP, E->LI); /* Remove the call */ CS_DelEntry (S, I); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptStore3 (CodeSeg* S) /* Search for a call to steaxysp. If the eax register is not used later, and ** the value is constant, just use the A register and store directly into the ** stack. */ { unsigned I; unsigned Changes = 0; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Get the input registers */ const RegInfo* RI = E->RI; /* Check for the call */ if (CE_IsCallTo (E, "steaxysp") && RegValIsKnown (RI->In.RegA) && RegValIsKnown (RI->In.RegX) && RegValIsKnown (RI->In.RegY) && RegValIsKnown (RI->In.SRegLo) && RegValIsKnown (RI->In.SRegHi) && !RegEAXUsed (S, I+1)) { /* Get the register values */ unsigned char A = (unsigned char) RI->In.RegA; unsigned char X = (unsigned char) RI->In.RegX; unsigned char Y = (unsigned char) RI->In.RegY; unsigned char L = (unsigned char) RI->In.SRegLo; unsigned char H = (unsigned char) RI->In.SRegHi; /* Setup other variables */ unsigned Done = 0; CodeEntry* N; unsigned IP = I + 1; /* Insertion point */ /* Replace the store. We will not remove the loads, since this is ** too complex and will be done by other optimizer steps. */ N = NewCodeEntry (OP65_LDA, AM65_IMM, MakeHexArg (A), 0, E->LI); CS_InsertEntry (S, N, IP++); InsertStore (S, &IP, E->LI); Done |= 0x01; /* Check if we can store one of the other bytes */ if (A == X && (Done & 0x02) == 0) { N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+1), 0, E->LI); CS_InsertEntry (S, N, IP++); InsertStore (S, &IP, E->LI); Done |= 0x02; } if (A == L && (Done & 0x04) == 0) { N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+2), 0, E->LI); CS_InsertEntry (S, N, IP++); InsertStore (S, &IP, E->LI); Done |= 0x04; } if (A == H && (Done & 0x08) == 0) { N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+3), 0, E->LI); CS_InsertEntry (S, N, IP++); InsertStore (S, &IP, E->LI); Done |= 0x08; } /* Store the second byte */ if ((Done & 0x02) == 0) { N = NewCodeEntry (OP65_LDA, AM65_IMM, MakeHexArg (X), 0, E->LI); CS_InsertEntry (S, N, IP++); N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+1), 0, E->LI); CS_InsertEntry (S, N, IP++); InsertStore (S, &IP, E->LI); Done |= 0x02; } /* Check if we can store one of the other bytes */ if (X == L && (Done & 0x04) == 0) { N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+2), 0, E->LI); CS_InsertEntry (S, N, IP++); InsertStore (S, &IP, E->LI); Done |= 0x04; } if (X == H && (Done & 0x08) == 0) { N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+3), 0, E->LI); CS_InsertEntry (S, N, IP++); InsertStore (S, &IP, E->LI); Done |= 0x08; } /* Store the third byte */ if ((Done & 0x04) == 0) { N = NewCodeEntry (OP65_LDA, AM65_IMM, MakeHexArg (L), 0, E->LI); CS_InsertEntry (S, N, IP++); N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+2), 0, E->LI); CS_InsertEntry (S, N, IP++); InsertStore (S, &IP, E->LI); Done |= 0x04; } /* Check if we can store one of the other bytes */ if (L == H && (Done & 0x08) == 0) { N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+3), 0, E->LI); CS_InsertEntry (S, N, IP++); InsertStore (S, &IP, E->LI); Done |= 0x08; } /* Store the fourth byte */ if ((Done & 0x08) == 0) { N = NewCodeEntry (OP65_LDA, AM65_IMM, MakeHexArg (H), 0, E->LI); CS_InsertEntry (S, N, IP++); N = NewCodeEntry (OP65_LDY, AM65_IMM, MakeHexArg (Y+3), 0, E->LI); CS_InsertEntry (S, N, IP++); InsertStore (S, &IP, E->LI); Done |= 0x08; } /* Remove the call */ CS_DelEntry (S, I); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptStore4 (CodeSeg* S) /* Search for the sequence ** ** sta xx ** stx yy ** lda xx ** ldx yy ** ** and remove the useless load, provided that the next insn doesn't use flags ** from the load. */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[5]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (L[0]->OPC == OP65_STA && (L[0]->AM == AM65_ABS || L[0]->AM == AM65_ZP) && !CS_RangeHasLabel (S, I+1, 3) && CS_GetEntries (S, L+1, I+1, 4) && L[1]->OPC == OP65_STX && L[1]->AM == L[0]->AM && L[2]->OPC == OP65_LDA && L[2]->AM == L[0]->AM && L[3]->OPC == OP65_LDX && L[3]->AM == L[1]->AM && strcmp (L[0]->Arg, L[2]->Arg) == 0 && strcmp (L[1]->Arg, L[3]->Arg) == 0 && !CE_UseLoadFlags (L[4])) { /* Register has already the correct value, remove the loads */ CS_DelEntries (S, I+2, 2); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptStore5 (CodeSeg* S) /* Search for the sequence ** ** lda foo ** ldx bar ** sta something ** stx something-else ** ** and, replace it by ** ** lda bar ** sta something-else ** lda foo ** sta something ** ** if the new value of X is not used later. That replacement doesn't save any ** cycles or bytes; but, it keeps the old value of X, which may be reused later. */ { unsigned Changes = 0; unsigned I = 0; /* Walk over the entries */ while (I < CS_GetEntryCount (S)) { CodeEntry* L[4]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check for the sequence */ if (L[0]->OPC == OP65_LDA && !CS_RangeHasLabel (S, I+1, 3) && CS_GetEntries (S, L+1, I+1, 3) && L[1]->OPC == OP65_LDX && L[2]->OPC == OP65_STA && L[3]->OPC == OP65_STX && !RegXUsed (S, I+4)) { CodeEntry* E = CS_GetEntry (S, I+1); /* Move the high-byte code to the beginning of the sequence */ CS_MoveEntry (S, I+1, I); CS_MoveEntry (S, I+3, I+1); /* Change from the X register to the A register */ CE_ReplaceOPC (E, OP65_LDA); CE_ReplaceOPC (CS_GetEntry (S, I+1), OP65_STA); /* Move labels from the old first entry to the new first entry */ CS_MoveLabels (S, CS_GetEntry (S, I+2), E); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } ����������������������������������������������������������������������������������cc65-2.18/src/cc65/coptstore.h����������������������������������������������������������������������0000664�0000000�0000000�00000010225�13473601511�0015727�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* coptstore.h */ /* */ /* Optimize stores */ /* */ /* */ /* */ /* (C) 2002-2006, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef COPTSTORE_H #define COPTSTORE_H /* cc65 */ #include "codeseg.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned OptStore1 (CodeSeg* S); /* Search for the sequence ** ** ldy #n ** jsr staxysp ** ldy #n+1 ** jsr ldaxysp ** ** and remove the useless load, provided that the next insn doesn't use flags ** from the load. */ unsigned OptStore2 (CodeSeg* S); /* Search for a call to staxysp. If the ax register is not used later, and ** the value is constant, just use the A register and store directly into the ** stack. */ unsigned OptStore3 (CodeSeg* S); /* Search for a call to steaxysp. If the eax register is not used later, and ** the value is constant, just use the A register and store directly into the ** stack. */ unsigned OptStore4 (CodeSeg* S); /* Search for the sequence ** ** sta xx ** stx yy ** lda xx ** ldx yy ** ** and remove the useless load, provided that the next insn doesn't use flags ** from the load. */ unsigned OptStore5 (CodeSeg* S); /* Search for the sequence ** ** lda foo ** ldx bar ** sta something ** stx something-else ** ** and replace it by ** ** lda foo ** sta something ** lda bar ** sta something-else ** ** if X is not used later. This replacement doesn't save any cycles or bytes, ** but it keeps the value of X, which may be reused later. */ /* End of coptstore.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/coptsub.c������������������������������������������������������������������������0000664�0000000�0000000�00000016367�13473601511�0015374�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* coptsub.c */ /* */ /* Optimize subtraction sequences */ /* */ /* */ /* */ /* (C) 2001-2006, Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "chartype.h" /* cc65 */ #include "codeent.h" #include "codeinfo.h" #include "coptsub.h" /*****************************************************************************/ /* Optimize subtractions */ /*****************************************************************************/ unsigned OptSub1 (CodeSeg* S) /* Search for the sequence ** ** sbc ... ** bcs L ** dex ** L: ** ** and remove the handling of the high byte if X is not used later. */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[3]; /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check for the sequence */ if (E->OPC == OP65_SBC && CS_GetEntries (S, L, I+1, 3) && (L[0]->OPC == OP65_BCS || L[0]->OPC == OP65_JCS) && L[0]->JumpTo != 0 && !CE_HasLabel (L[0]) && L[1]->OPC == OP65_DEX && !CE_HasLabel (L[1]) && L[0]->JumpTo->Owner == L[2] && !RegXUsed (S, I+3)) { /* Remove the bcs/dex */ CS_DelEntries (S, I+1, 2); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptSub2 (CodeSeg* S) /* Search for the sequence ** ** lda xx ** sec ** sta tmp1 ** lda yy ** sbc tmp1 ** sta yy ** ** and replace it by ** ** sec ** lda yy ** sbc xx ** sta yy */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[5]; /* Get next entry */ CodeEntry* E = CS_GetEntry (S, I); /* Check for the sequence */ if (E->OPC == OP65_LDA && !CS_RangeHasLabel (S, I+1, 5) && CS_GetEntries (S, L, I+1, 5) && L[0]->OPC == OP65_SEC && L[1]->OPC == OP65_STA && strcmp (L[1]->Arg, "tmp1") == 0 && L[2]->OPC == OP65_LDA && L[3]->OPC == OP65_SBC && strcmp (L[3]->Arg, "tmp1") == 0 && L[4]->OPC == OP65_STA && strcmp (L[4]->Arg, L[2]->Arg) == 0) { /* Remove the store to tmp1 */ CS_DelEntry (S, I+2); /* Remove the subtraction */ CS_DelEntry (S, I+3); /* Move the lda to the position of the subtraction and change the ** op to SBC. */ CS_MoveEntry (S, I, I+3); CE_ReplaceOPC (E, OP65_SBC); /* If the sequence head had a label, move this label back to the ** head. */ if (CE_HasLabel (E)) { CS_MoveLabels (S, E, L[0]); } /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptSub3 (CodeSeg* S) /* Search for a call to decaxn and replace it by an 8 bit sub if the X register ** is not used later. */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* E; /* Get next entry */ E = CS_GetEntry (S, I); /* Check for the sequence */ if (E->OPC == OP65_JSR && strncmp (E->Arg, "decax", 5) == 0 && IsDigit (E->Arg[5]) && E->Arg[6] == '\0' && !RegXUsed (S, I+1)) { CodeEntry* X; const char* Arg; /* Insert new code behind the sequence */ X = NewCodeEntry (OP65_SEC, AM65_IMP, 0, 0, E->LI); CS_InsertEntry (S, X, I+1); Arg = MakeHexArg (E->Arg[5] - '0'); X = NewCodeEntry (OP65_SBC, AM65_IMM, Arg, 0, E->LI); CS_InsertEntry (S, X, I+2); /* Delete the old code */ CS_DelEntry (S, I); /* Remember, we had changes */ ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/coptsub.h������������������������������������������������������������������������0000664�0000000�0000000�00000006672�13473601511�0015377�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* coptsub.h */ /* */ /* Optimize subtraction sequences */ /* */ /* */ /* */ /* (C) 2001-2006, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef COPTSUB_H #define COPTSUB_H /* cc65 */ #include "codeseg.h" /*****************************************************************************/ /* Optimize subtractions */ /*****************************************************************************/ unsigned OptSub1 (CodeSeg* S); /* Search for the sequence ** ** sbc ... ** bcs L ** dex ** L: ** ** and remove the handling of the high byte if X is not used later. */ unsigned OptSub2 (CodeSeg* S); /* Search for the sequence ** ** lda xx ** sec ** sta tmp1 ** lda yy ** sbc tmp1 ** sta yy ** ** and replace it by ** ** sec ** lda yy ** sbc xx ** sta yy */ unsigned OptSub3 (CodeSeg* S); /* Search for a call to decaxn and replace it by an 8 bit sub if the X register ** is not used later. */ /* End of coptsub.h */ #endif ����������������������������������������������������������������������cc65-2.18/src/cc65/copttest.c�����������������������������������������������������������������������0000664�0000000�0000000�00000013720�13473601511�0015550�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* copttest.c */ /* */ /* Optimize test sequences */ /* */ /* */ /* */ /* (C) 2001-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* cc65 */ #include "codeent.h" #include "codeinfo.h" #include "copttest.h" /*****************************************************************************/ /* Optimize tests */ /*****************************************************************************/ unsigned OptTest1 (CodeSeg* S) /* Given a sequence ** ** stx xxx ** ora xxx ** beq/bne ... ** ** If X is zero, the sequence may be changed to ** ** cmp #$00 ** beq/bne ... ** ** which may be optimized further by another step. ** ** If A is zero, the sequence may be changed to ** ** txa ** beq/bne ... */ { unsigned Changes = 0; unsigned I; /* Walk over the entries */ I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[3]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check if it's the sequence we're searching for */ if (L[0]->OPC == OP65_STX && CS_GetEntries (S, L+1, I+1, 2) && !CE_HasLabel (L[1]) && L[1]->OPC == OP65_ORA && strcmp (L[0]->Arg, L[1]->Arg) == 0 && !CE_HasLabel (L[2]) && (L[2]->Info & OF_ZBRA) != 0) { /* Check if X is zero */ if (L[0]->RI->In.RegX == 0) { /* Insert the compare */ CodeEntry* N = NewCodeEntry (OP65_CMP, AM65_IMM, "$00", 0, L[0]->LI); CS_InsertEntry (S, N, I+2); /* Remove the two other insns */ CS_DelEntry (S, I+1); CS_DelEntry (S, I); /* We had changes */ ++Changes; /* Check if A is zero */ } else if (L[1]->RI->In.RegA == 0) { /* Insert the txa */ CodeEntry* N = NewCodeEntry (OP65_TXA, AM65_IMP, 0, 0, L[1]->LI); CS_InsertEntry (S, N, I+2); /* Remove the two other insns */ CS_DelEntry (S, I+1); CS_DelEntry (S, I); /* We had changes */ ++Changes; } } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } unsigned OptTest2 (CodeSeg* S) /* Search for an inc/dec operation followed by a load and a conditional ** branch based on the flags from the load. Remove the load if the insn ** isn't used later. */ { unsigned Changes = 0; /* Walk over the entries */ unsigned I = 0; while (I < CS_GetEntryCount (S)) { CodeEntry* L[3]; /* Get next entry */ L[0] = CS_GetEntry (S, I); /* Check if it's the sequence we're searching for */ if ((L[0]->OPC == OP65_INC || L[0]->OPC == OP65_DEC) && CS_GetEntries (S, L+1, I+1, 2) && !CE_HasLabel (L[1]) && (L[1]->Info & OF_LOAD) != 0 && (L[2]->Info & OF_FBRA) != 0 && L[1]->AM == L[0]->AM && strcmp (L[0]->Arg, L[1]->Arg) == 0 && (GetRegInfo (S, I+2, L[1]->Chg) & L[1]->Chg) == 0) { /* Remove the load */ CS_DelEntry (S, I+1); ++Changes; } /* Next entry */ ++I; } /* Return the number of changes made */ return Changes; } ������������������������������������������������cc65-2.18/src/cc65/copttest.h�����������������������������������������������������������������������0000664�0000000�0000000�00000006610�13473601511�0015555�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* copttest.h */ /* */ /* Optimize test sequences */ /* */ /* */ /* */ /* (C) 2001-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef COPTTEST_H #define COPTTEST_H /* cc65 */ #include "codeseg.h" /*****************************************************************************/ /* Optimize tests */ /*****************************************************************************/ unsigned OptTest1 (CodeSeg* S); /* Given a sequence ** ** stx xxx ** ora xxx ** beq/bne ... ** ** If X is zero, the sequence may be changed to ** ** cmp #$00 ** beq/bne ... ** ** which may be optimized further by another step. ** ** If A is zero, the sequence may be changed to ** ** txa ** beq/bne ... */ unsigned OptTest2 (CodeSeg* S); /* Search for an inc/dec operation followed by a load and a conditional ** branch based on the flags from the load. Remove the load if the insn ** isn't used later. */ /* End of copttest.h */ #endif ������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/copyleft.jrd���������������������������������������������������������������������0000664�0000000�0000000�00000002467�13473601511�0016073�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������-*- 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. ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/dataseg.c������������������������������������������������������������������������0000664�0000000�0000000�00000011244�13473601511�0015312�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* dataseg.c */ /* */ /* Data segment structure */ /* */ /* */ /* */ /* (C) 2001-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "check.h" #include "xmalloc.h" #include "xsprintf.h" /* cc65 */ #include "dataseg.h" #include "error.h" #include "output.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ DataSeg* NewDataSeg (const char* Name, SymEntry* Func) /* Create a new data segment, initialize and return it */ { /* Allocate memory */ DataSeg* S = xmalloc (sizeof (DataSeg)); /* Initialize the fields */ S->SegName = xstrdup (Name); S->Func = Func; InitCollection (&S->Lines); /* Return the new struct */ return S; } void DS_Append (DataSeg* Target, const DataSeg* Source) /* Append the data from Source to Target */ { unsigned I; /* Append all lines from Source to Target */ unsigned Count = CollCount (&Source->Lines); for (I = 0; I < Count; ++I) { CollAppend (&Target->Lines, xstrdup (CollConstAt (&Source->Lines, I))); } } void DS_AddVLine (DataSeg* S, const char* Format, va_list ap) /* Add a line to the given data segment */ { /* Format the line */ char Buf [256]; xvsprintf (Buf, sizeof (Buf), Format, ap); /* Add a copy to the data segment */ CollAppend (&S->Lines, xstrdup (Buf)); } void DS_AddLine (DataSeg* S, const char* Format, ...) /* Add a line to the given data segment */ { va_list ap; va_start (ap, Format); DS_AddVLine (S, Format, ap); va_end (ap); } void DS_Output (const DataSeg* S) /* Output the data segment data to the output file */ { unsigned I; /* Get the number of entries in this segment */ unsigned Count = CollCount (&S->Lines); /* If the segment is actually empty, bail out */ if (Count == 0) { return; } /* Output the segment directive */ WriteOutput (".segment\t\"%s\"\n\n", S->SegName); /* Output all entries */ for (I = 0; I < Count; ++I) { WriteOutput ("%s\n", (const char*) CollConstAt (&S->Lines, I)); } /* Add an additional newline after the segment output */ WriteOutput ("\n"); } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/dataseg.h������������������������������������������������������������������������0000664�0000000�0000000�00000007725�13473601511�0015330�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* dataseg.h */ /* */ /* Data segment structure */ /* */ /* */ /* */ /* (C) 2001-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef DATASEG_H #define DATASEG_H #include <stdarg.h> /* common */ #include "attrib.h" #include "coll.h" /* cc65 */ #include "symentry.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ typedef struct DataSeg DataSeg; struct DataSeg { char* SegName; /* Segment name */ SymEntry* Func; /* Owner function */ Collection Lines; /* List of code lines */ }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ DataSeg* NewDataSeg (const char* SegName, SymEntry* Func); /* Create a new data segment, initialize and return it */ void DS_Append (DataSeg* Target, const DataSeg* Source); /* Append the data from Source to Target. */ void DS_AddVLine (DataSeg* S, const char* Format, va_list ap) attribute ((format(printf,2,0))); /* Add a line to the given data segment */ void DS_AddLine (DataSeg* S, const char* Format, ...) attribute ((format(printf,2,3))); /* Add a line to the given data segment */ void DS_Output (const DataSeg* S); /* Output the data segment data to the output file */ /* End of dataseg.h */ #endif �������������������������������������������cc65-2.18/src/cc65/datatype.c�����������������������������������������������������������������������0000664�0000000�0000000�00000045507�13473601511�0015526�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* datatype.c */ /* */ /* Type string handling for the cc65 C compiler */ /* */ /* */ /* */ /* (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 */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* common */ #include "addrsize.h" #include "check.h" #include "mmodel.h" #include "xmalloc.h" /* cc65 */ #include "codegen.h" #include "datatype.h" #include "error.h" #include "fp.h" #include "funcdesc.h" #include "global.h" #include "symtab.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Predefined type strings */ Type type_schar[] = { TYPE(T_SCHAR), TYPE(T_END) }; Type type_uchar[] = { TYPE(T_UCHAR), TYPE(T_END) }; Type type_int[] = { TYPE(T_INT), TYPE(T_END) }; Type type_uint[] = { TYPE(T_UINT), TYPE(T_END) }; Type type_long[] = { TYPE(T_LONG), TYPE(T_END) }; Type type_ulong[] = { TYPE(T_ULONG), TYPE(T_END) }; Type type_void[] = { TYPE(T_VOID), TYPE(T_END) }; Type type_size_t[] = { TYPE(T_SIZE_T), TYPE(T_END) }; Type type_float[] = { TYPE(T_FLOAT), TYPE(T_END) }; Type type_double[] = { TYPE(T_DOUBLE), TYPE(T_END) }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned TypeLen (const Type* T) /* Return the length of the type string */ { const Type* Start = T; while (T->C != T_END) { ++T; } return T - Start; } Type* TypeCopy (Type* Dest, const Type* Src) /* Copy a type string */ { Type* Orig = Dest; while (1) { *Dest = *Src; if (Src->C == T_END) { break; } Src++; Dest++; } return Orig; } Type* TypeDup (const Type* T) /* Create a copy of the given type on the heap */ { unsigned Len = (TypeLen (T) + 1) * sizeof (Type); return memcpy (xmalloc (Len), T, Len); } Type* TypeAlloc (unsigned Len) /* Allocate memory for a type string of length Len. Len *must* include the ** trailing T_END. */ { return xmalloc (Len * sizeof (Type)); } void TypeFree (Type* T) /* Free a type string */ { xfree (T); } int SignExtendChar (int C) /* Do correct sign extension of a character */ { if (IS_Get (&SignedChars) && (C & 0x80) != 0) { return C | ~0xFF; } else { return C & 0xFF; } } TypeCode GetDefaultChar (void) /* Return the default char type (signed/unsigned) depending on the settings */ { return IS_Get (&SignedChars)? T_SCHAR : T_UCHAR; } Type* GetCharArrayType (unsigned Len) /* Return the type for a char array of the given length */ { /* Allocate memory for the type string */ Type* T = TypeAlloc (3); /* array/char/terminator */ /* Fill the type string */ T[0].C = T_ARRAY; T[0].A.L = Len; /* Array length is in the L attribute */ T[1].C = GetDefaultChar (); T[2].C = T_END; /* Return the new type */ return T; } Type* GetImplicitFuncType (void) /* Return a type string for an inplicitly declared function */ { /* Get a new function descriptor */ FuncDesc* F = NewFuncDesc (); /* Allocate memory for the type string */ Type* T = TypeAlloc (3); /* func/returns int/terminator */ /* Prepare the function descriptor */ F->Flags = FD_EMPTY | FD_VARIADIC; F->SymTab = &EmptySymTab; F->TagTab = &EmptySymTab; /* Fill the type string */ T[0].C = T_FUNC | CodeAddrSizeQualifier (); T[0].A.P = F; T[1].C = T_INT; T[2].C = T_END; /* Return the new type */ return T; } Type* PointerTo (const Type* T) /* Return a type string that is "pointer to T". The type string is allocated ** on the heap and may be freed after use. */ { /* Get the size of the type string including the terminator */ unsigned Size = TypeLen (T) + 1; /* Allocate the new type string */ Type* P = TypeAlloc (Size + 1); /* Create the return type... */ P[0].C = T_PTR | (T[0].C & T_QUAL_ADDRSIZE); memcpy (P+1, T, Size * sizeof (Type)); /* ...and return it */ return P; } static TypeCode PrintTypeComp (FILE* F, TypeCode C, TypeCode Mask, const char* Name) /* Check for a specific component of the type. If it is there, print the ** name and remove it. Return the type with the component removed. */ { if ((C & Mask) == Mask) { fprintf (F, "%s ", Name); C &= ~Mask; } return C; } void PrintType (FILE* F, const Type* T) /* Output translation of type array. */ { /* Walk over the type string */ while (T->C != T_END) { /* Get the type code */ TypeCode C = T->C; /* Print any qualifiers */ C = PrintTypeComp (F, C, T_QUAL_CONST, "const"); C = PrintTypeComp (F, C, T_QUAL_VOLATILE, "volatile"); C = PrintTypeComp (F, C, T_QUAL_RESTRICT, "restrict"); C = PrintTypeComp (F, C, T_QUAL_NEAR, "__near__"); C = PrintTypeComp (F, C, T_QUAL_FAR, "__far__"); C = PrintTypeComp (F, C, T_QUAL_FASTCALL, "__fastcall__"); C = PrintTypeComp (F, C, T_QUAL_CDECL, "__cdecl__"); /* Signedness. Omit the signedness specifier for long and int */ if ((C & T_MASK_TYPE) != T_TYPE_INT && (C & T_MASK_TYPE) != T_TYPE_LONG) { C = PrintTypeComp (F, C, T_SIGN_SIGNED, "signed"); } C = PrintTypeComp (F, C, T_SIGN_UNSIGNED, "unsigned"); /* Now check the real type */ switch (C & T_MASK_TYPE) { case T_TYPE_CHAR: fprintf (F, "char"); break; case T_TYPE_SHORT: fprintf (F, "short"); break; case T_TYPE_INT: fprintf (F, "int"); break; case T_TYPE_LONG: fprintf (F, "long"); break; case T_TYPE_LONGLONG: fprintf (F, "long long"); break; case T_TYPE_FLOAT: fprintf (F, "float"); break; case T_TYPE_DOUBLE: fprintf (F, "double"); break; case T_TYPE_VOID: fprintf (F, "void"); break; case T_TYPE_STRUCT: fprintf (F, "struct %s", ((SymEntry*) T->A.P)->Name); break; case T_TYPE_UNION: fprintf (F, "union %s", ((SymEntry*) T->A.P)->Name); break; case T_TYPE_ARRAY: /* Recursive call */ PrintType (F, T + 1); if (T->A.L == UNSPECIFIED) { fprintf (F, " []"); } else { fprintf (F, " [%ld]", T->A.L); } return; case T_TYPE_PTR: /* Recursive call */ PrintType (F, T + 1); fprintf (F, " *"); return; case T_TYPE_FUNC: fprintf (F, "function returning "); break; default: fprintf (F, "unknown type: %04lX", T->C); } /* Next element */ ++T; } } void PrintFuncSig (FILE* F, const char* Name, Type* T) /* Print a function signature. */ { /* Get the function descriptor */ const FuncDesc* D = GetFuncDesc (T); /* Print a comment with the function signature */ PrintType (F, GetFuncReturn (T)); if (IsQualNear (T)) { fprintf (F, " __near__"); } if (IsQualFar (T)) { fprintf (F, " __far__"); } if (IsQualFastcall (T)) { fprintf (F, " __fastcall__"); } if (IsQualCDecl (T)) { fprintf (F, " __cdecl__"); } fprintf (F, " %s (", Name); /* Parameters */ if (D->Flags & FD_VOID_PARAM) { fprintf (F, "void"); } else { unsigned I; SymEntry* E = D->SymTab->SymHead; for (I = 0; I < D->ParamCount; ++I) { if (I > 0) { fprintf (F, ", "); } if (SymIsRegVar (E)) { fprintf (F, "register "); } PrintType (F, E->Type); E = E->NextSym; } } /* End of parameter list */ fprintf (F, ")"); } void PrintRawType (FILE* F, const Type* T) /* Print a type string in raw format (for debugging) */ { while (T->C != T_END) { fprintf (F, "%04lX ", T->C); ++T; } fprintf (F, "\n"); } int TypeHasAttr (const Type* T) /* Return true if the given type has attribute data */ { return IsClassStruct (T) || IsTypeArray (T) || IsClassFunc (T); } unsigned SizeOf (const Type* T) /* Compute size of object represented by type array. */ { switch (UnqualifiedType (T->C)) { case T_VOID: /* A void variable is a cc65 extension. ** Get its size (in bytes). */ return T->A.U; /* Beware: There's a chance that this triggers problems in other parts of the compiler. The solution is to fix the callers, because calling 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; case T_SHORT: case T_USHORT: return SIZEOF_SHORT; case T_INT: case T_UINT: return SIZEOF_INT; case T_PTR: return SIZEOF_PTR; case T_LONG: case T_ULONG: return SIZEOF_LONG; case T_LONGLONG: case T_ULONGLONG: return SIZEOF_LONGLONG; case T_ENUM: return SIZEOF_INT; case T_FLOAT: return SIZEOF_FLOAT; case T_DOUBLE: return SIZEOF_DOUBLE; case T_STRUCT: case T_UNION: return ((SymEntry*) T->A.P)->V.S.Size; case T_ARRAY: if (T->A.L == UNSPECIFIED) { /* Array with unspecified size */ return 0; } else { return T->A.U * SizeOf (T + 1); } default: Internal ("Unknown type in SizeOf: %04lX", T->C); return 0; } } unsigned PSizeOf (const Type* T) /* Compute size of pointer object. */ { /* We are expecting a pointer expression */ CHECK (IsClassPtr (T)); /* Skip the pointer or array token itself */ return SizeOf (T + 1); } unsigned CheckedSizeOf (const Type* T) /* Return the size of a data type. If the size is zero, emit an error and ** return some valid size instead (so the rest of the compiler doesn't have ** to work with invalid sizes). */ { unsigned Size = SizeOf (T); if (Size == 0) { Error ("Size of data type is unknown"); Size = SIZEOF_CHAR; /* Don't return zero */ } return Size; } unsigned CheckedPSizeOf (const Type* T) /* Return the size of a data type that is pointed to by a pointer. If the ** size is zero, emit an error and return some valid size instead (so the ** rest of the compiler doesn't have to work with invalid sizes). */ { unsigned Size = PSizeOf (T); if (Size == 0) { Error ("Size of data type is unknown"); Size = SIZEOF_CHAR; /* Don't return zero */ } return Size; } unsigned TypeOf (const Type* T) /* Get the code generator base type of the object */ { switch (UnqualifiedType (T->C)) { case T_SCHAR: return CF_CHAR; case T_UCHAR: return CF_CHAR | CF_UNSIGNED; case T_SHORT: case T_INT: case T_ENUM: return CF_INT; case T_USHORT: case T_UINT: case T_PTR: case T_ARRAY: return CF_INT | CF_UNSIGNED; case T_LONG: return CF_LONG; case T_ULONG: return CF_LONG | CF_UNSIGNED; case T_FLOAT: case T_DOUBLE: /* These two are identical in the backend */ return CF_FLOAT; case T_FUNC: return (((FuncDesc*) T->A.P)->Flags & FD_VARIADIC)? 0 : CF_FIXARGC; case T_STRUCT: case T_UNION: /* Address of ... */ return CF_INT | CF_UNSIGNED; default: Error ("Illegal type %04lX", T->C); return CF_INT; } } Type* Indirect (Type* T) /* Do one indirection for the given type, that is, return the type where the ** given type points to. */ { /* We are expecting a pointer expression */ CHECK (IsClassPtr (T)); /* Skip the pointer or array token itself */ return T + 1; } Type* ArrayToPtr (Type* T) /* Convert an array to a pointer to it's first element */ { /* Return pointer to first element */ return PointerTo (GetElementType (T)); } int IsVariadicFunc (const Type* T) /* Return true if this is a function type or pointer to function type with ** variable parameter list */ { FuncDesc* F = GetFuncDesc (T); return (F->Flags & FD_VARIADIC) != 0; } FuncDesc* GetFuncDesc (const Type* T) /* Get the FuncDesc pointer from a function or pointer-to-function type */ { if (UnqualifiedType (T->C) == T_PTR) { /* Pointer to function */ ++T; } /* Be sure it's a function type */ CHECK (IsClassFunc (T)); /* Get the function descriptor from the type attributes */ return T->A.P; } void SetFuncDesc (Type* T, FuncDesc* F) /* Set the FuncDesc pointer in a function or pointer-to-function type */ { if (UnqualifiedType (T->C) == T_PTR) { /* Pointer to function */ ++T; } /* Be sure it's a function type */ CHECK (IsClassFunc (T)); /* Set the function descriptor */ T->A.P = F; } Type* GetFuncReturn (Type* T) /* Return a pointer to the return type of a function or pointer-to-function type */ { if (UnqualifiedType (T->C) == T_PTR) { /* Pointer to function */ ++T; } /* Be sure it's a function type */ CHECK (IsClassFunc (T)); /* Return a pointer to the return type */ return T + 1; } long GetElementCount (const Type* T) /* Get the element count of the array specified in T (which must be of ** array type). */ { CHECK (IsTypeArray (T)); return T->A.L; } void SetElementCount (Type* T, long Count) /* Set the element count of the array specified in T (which must be of ** array type). */ { CHECK (IsTypeArray (T)); T->A.L = Count; } Type* GetElementType (Type* T) /* Return the element type of the given array type. */ { CHECK (IsTypeArray (T)); return T + 1; } Type* GetBaseElementType (Type* T) /* Return the base element type of a given type. If T is not an array, this ** will return. Otherwise it will return the base element type, which means ** the element type that is not an array. */ { while (IsTypeArray (T)) { ++T; } return T; } SymEntry* GetSymEntry (const Type* T) /* Return a SymEntry pointer from a type */ { /* Only structs or unions have a SymEntry attribute */ CHECK (IsClassStruct (T)); /* Return the attribute */ return T->A.P; } void SetSymEntry (Type* T, SymEntry* S) /* Set the SymEntry pointer for a type */ { /* Only structs or unions have a SymEntry attribute */ CHECK (IsClassStruct (T)); /* Set the attribute */ T->A.P = S; } Type* IntPromotion (Type* T) /* Apply the integer promotions to T and return the result. The returned type ** string may be T if there is no need to change it. */ { /* We must have an int to apply int promotions */ PRECONDITION (IsClassInt (T)); /* An integer can represent all values from either signed or unsigned char, ** so convert chars to int and leave all other types alone. */ if (IsTypeChar (T)) { return type_int; } else { return T; } } Type* PtrConversion (Type* T) /* If the type is a function, convert it to pointer to function. If the ** expression is an array, convert it to pointer to first element. Otherwise ** return T. */ { if (IsTypeFunc (T)) { return PointerTo (T); } else if (IsTypeArray (T)) { return ArrayToPtr (T); } else { return T; } } TypeCode AddrSizeQualifier (unsigned AddrSize) /* Return T_QUAL_NEAR or T_QUAL_FAR depending on the address size */ { switch (AddrSize) { case ADDR_SIZE_ABS: return T_QUAL_NEAR; case ADDR_SIZE_FAR: return T_QUAL_FAR; default: Error ("Invalid address size"); return T_QUAL_NEAR; } } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/datatype.h�����������������������������������������������������������������������0000664�0000000�0000000�00000050756�13473601511�0015535�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* datatype.h */ /* */ /* Type string handling for the cc65 C compiler */ /* */ /* */ /* */ /* (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 */ /* 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 DATATYPE_H #define DATATYPE_H #include <stdio.h> /* common */ #include "attrib.h" #include "inline.h" #include "mmodel.h" /* cc65 */ #include "funcdesc.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Basic data types */ enum { T_END = 0x000000, /* Basic types */ T_TYPE_NONE = 0x000000, T_TYPE_CHAR = 0x000001, T_TYPE_SHORT = 0x000002, T_TYPE_INT = 0x000003, T_TYPE_LONG = 0x000004, T_TYPE_LONGLONG = 0x000005, T_TYPE_ENUM = 0x000006, T_TYPE_FLOAT = 0x000007, T_TYPE_DOUBLE = 0x000008, T_TYPE_VOID = 0x000009, T_TYPE_STRUCT = 0x00000A, T_TYPE_UNION = 0x00000B, T_TYPE_ARRAY = 0x00000C, T_TYPE_PTR = 0x00000D, T_TYPE_FUNC = 0x00000E, T_MASK_TYPE = 0x00000F, /* Type classes */ T_CLASS_NONE = 0x000000, T_CLASS_INT = 0x000010, T_CLASS_FLOAT = 0x000020, T_CLASS_PTR = 0x000030, T_CLASS_STRUCT = 0x000040, T_CLASS_FUNC = 0x000050, T_MASK_CLASS = 0x000070, /* Type signedness */ T_SIGN_NONE = 0x000000, T_SIGN_UNSIGNED = 0x000080, T_SIGN_SIGNED = 0x000100, T_MASK_SIGN = 0x000180, /* Type size modifiers */ T_SIZE_NONE = 0x000000, T_SIZE_SHORT = 0x000200, T_SIZE_LONG = 0x000400, T_SIZE_LONGLONG = 0x000600, T_MASK_SIZE = 0x000600, /* Type qualifiers */ T_QUAL_NONE = 0x000000, T_QUAL_CONST = 0x000800, T_QUAL_VOLATILE = 0x001000, T_QUAL_RESTRICT = 0x002000, T_QUAL_NEAR = 0x004000, T_QUAL_FAR = 0x008000, T_QUAL_ADDRSIZE = T_QUAL_NEAR | T_QUAL_FAR, T_QUAL_FASTCALL = 0x010000, T_QUAL_CDECL = 0x020000, T_QUAL_CCONV = T_QUAL_FASTCALL | T_QUAL_CDECL, T_MASK_QUAL = 0x03F800, /* Types */ T_CHAR = T_TYPE_CHAR | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_NONE, T_SCHAR = T_TYPE_CHAR | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_NONE, T_UCHAR = T_TYPE_CHAR | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_NONE, T_SHORT = T_TYPE_SHORT | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_SHORT, T_USHORT = T_TYPE_SHORT | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_SHORT, T_INT = T_TYPE_INT | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_NONE, T_UINT = T_TYPE_INT | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_NONE, T_LONG = T_TYPE_LONG | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_LONG, T_ULONG = T_TYPE_LONG | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_LONG, T_LONGLONG = T_TYPE_LONGLONG | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_LONGLONG, T_ULONGLONG = T_TYPE_LONGLONG | T_CLASS_INT | T_SIGN_UNSIGNED | T_SIZE_LONGLONG, T_ENUM = T_TYPE_ENUM | T_CLASS_INT | T_SIGN_SIGNED | T_SIZE_NONE, T_FLOAT = T_TYPE_FLOAT | T_CLASS_FLOAT | T_SIGN_NONE | T_SIZE_NONE, T_DOUBLE = T_TYPE_DOUBLE | T_CLASS_FLOAT | T_SIGN_NONE | T_SIZE_NONE, T_VOID = T_TYPE_VOID | T_CLASS_NONE | T_SIGN_NONE | T_SIZE_NONE, T_STRUCT = T_TYPE_STRUCT | T_CLASS_STRUCT | T_SIGN_NONE | T_SIZE_NONE, T_UNION = T_TYPE_UNION | T_CLASS_STRUCT | T_SIGN_NONE | T_SIZE_NONE, T_ARRAY = T_TYPE_ARRAY | T_CLASS_PTR | T_SIGN_NONE | T_SIZE_NONE, T_PTR = T_TYPE_PTR | T_CLASS_PTR | T_SIGN_NONE | T_SIZE_NONE, T_FUNC = T_TYPE_FUNC | T_CLASS_FUNC | T_SIGN_NONE | T_SIZE_NONE, /* Aliases */ T_SIZE_T = T_UINT, }; /* Type code entry */ typedef unsigned long TypeCode; /* Type entry */ typedef struct Type Type; struct Type { TypeCode C; /* Code for this entry */ union { void* P; /* Arbitrary attribute pointer */ long L; /* Numeric attribute value */ unsigned long U; /* Dito, unsigned */ } A; /* Type attribute if necessary */ }; /* A macro that expands to a full initializer for struct Type */ #define TYPE(T) { (T), { 0 } } /* Maximum length of a type string */ #define MAXTYPELEN 30 /* Special encodings for element counts of an array */ #define UNSPECIFIED -1L /* Element count was not specified */ #define FLEXIBLE 0L /* Flexible array struct member */ /* Sizes. Floating point sizes come from fp.h */ #define SIZEOF_CHAR 1U #define SIZEOF_SHORT 2U #define SIZEOF_INT 2U #define SIZEOF_LONG 4U #define SIZEOF_LONGLONG 8U #define SIZEOF_FLOAT (FP_F_Size()) #define SIZEOF_DOUBLE (FP_D_Size()) #define SIZEOF_PTR SIZEOF_INT /* Bit sizes */ #define CHAR_BITS (8 * SIZEOF_CHAR) #define SHORT_BITS (8 * SIZEOF_SHORT) #define INT_BITS (8 * SIZEOF_INT) #define LONG_BITS (8 * SIZEOF_LONG) #define LONGLONG_BITS (8 * SIZEOF_LONGLONG) #define FLOAT_BITS (8 * SIZEOF_FLOAT) #define DOUBLE_BITS (8 * SIZEOF_DOUBLE) #define PTR_BITS (8 * SIZEOF_PTR) /* Predefined type strings */ extern Type type_schar[]; extern Type type_uchar[]; extern Type type_int[]; extern Type type_uint[]; extern Type type_long[]; extern Type type_ulong[]; extern Type type_void[]; extern Type type_size_t[]; extern Type type_float[]; extern Type type_double[]; /* Forward for the SymEntry struct */ struct SymEntry; /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned TypeLen (const Type* T); /* Return the length of the type string */ Type* TypeCopy (Type* Dest, const Type* Src); /* Copy a type string */ Type* TypeDup (const Type* T); /* Create a copy of the given type on the heap */ Type* TypeAlloc (unsigned Len); /* Allocate memory for a type string of length Len. Len *must* include the ** trailing T_END. */ void TypeFree (Type* T); /* Free a type string */ int SignExtendChar (int C); /* Do correct sign extension of a character */ TypeCode GetDefaultChar (void); /* Return the default char type (signed/unsigned) depending on the settings */ Type* GetCharArrayType (unsigned Len); /* Return the type for a char array of the given length */ Type* GetImplicitFuncType (void); /* Return a type string for an inplicitly declared function */ Type* PointerTo (const Type* T); /* Return a type string that is "pointer to T". The type string is allocated ** on the heap and may be freed after use. */ void PrintType (FILE* F, const Type* T); /* Output translation of type array. */ void PrintRawType (FILE* F, const Type* T); /* Print a type string in raw format (for debugging) */ void PrintFuncSig (FILE* F, const char* Name, Type* T); /* Print a function signature. */ int TypeHasAttr (const Type* T); /* Return true if the given type has attribute data */ #if defined(HAVE_INLINE) INLINE void CopyTypeAttr (const Type* Src, Type* Dest) /* Copy attribute data from Src to Dest */ { Dest->A = Src->A; } #else # define CopyTypeAttr(Src, Dest) ((Dest)->A = (Src)->A) #endif #if defined(HAVE_INLINE) INLINE TypeCode UnqualifiedType (TypeCode T) /* Return the unqalified type code */ { return (T & ~T_MASK_QUAL); } #else # define UnqualifiedType(T) ((T) & ~T_MASK_QUAL) #endif unsigned SizeOf (const Type* T); /* Compute size of object represented by type array. */ unsigned PSizeOf (const Type* T); /* Compute size of pointer object. */ unsigned CheckedSizeOf (const Type* T); /* Return the size of a data type. If the size is zero, emit an error and ** return some valid size instead (so the rest of the compiler doesn't have ** to work with invalid sizes). */ unsigned CheckedPSizeOf (const Type* T); /* Return the size of a data type that is pointed to by a pointer. If the ** size is zero, emit an error and return some valid size instead (so the ** rest of the compiler doesn't have to work with invalid sizes). */ unsigned TypeOf (const Type* T); /* Get the code generator base type of the object */ Type* Indirect (Type* T); /* Do one indirection for the given type, that is, return the type where the ** given type points to. */ Type* ArrayToPtr (Type* T); /* Convert an array to a pointer to it's first element */ #if defined(HAVE_INLINE) INLINE TypeCode GetType (const Type* T) /* Get the raw type */ { return (T->C & T_MASK_TYPE); } #else # define GetType(T) ((T)->C & T_MASK_TYPE) #endif #if defined(HAVE_INLINE) INLINE int IsTypeChar (const Type* T) /* Return true if this is a character type */ { return (GetType (T) == T_TYPE_CHAR); } #else # define IsTypeChar(T) (GetType (T) == T_TYPE_CHAR) #endif #if defined(HAVE_INLINE) INLINE int IsTypeInt (const Type* T) /* Return true if this is an int type (signed or unsigned) */ { return (GetType (T) == T_TYPE_INT); } #else # define IsTypeInt(T) (GetType (T) == T_TYPE_INT) #endif #if defined(HAVE_INLINE) INLINE int IsTypeLong (const Type* T) /* Return true if this is a long type (signed or unsigned) */ { return (GetType (T) == T_TYPE_LONG); } #else # define IsTypeLong(T) (GetType (T) == T_TYPE_LONG) #endif #if defined(HAVE_INLINE) INLINE int IsTypeFloat (const Type* T) /* Return true if this is a float type */ { return (GetType (T) == T_TYPE_FLOAT); } #else # define IsTypeFloat(T) (GetType (T) == T_TYPE_FLOAT) #endif #if defined(HAVE_INLINE) INLINE int IsTypeDouble (const Type* T) /* Return true if this is a double type */ { return (GetType (T) == T_TYPE_DOUBLE); } #else # define IsTypeDouble(T) (GetType (T) == T_TYPE_DOUBLE) #endif #if defined(HAVE_INLINE) INLINE int IsTypePtr (const Type* T) /* Return true if this is a pointer type */ { return (GetType (T) == T_TYPE_PTR); } #else # define IsTypePtr(T) (GetType (T) == T_TYPE_PTR) #endif #if defined(HAVE_INLINE) INLINE int IsTypeStruct (const Type* T) /* Return true if this is a struct type */ { return (GetType (T) == T_TYPE_STRUCT); } #else # define IsTypeStruct(T) (GetType (T) == T_TYPE_STRUCT) #endif #if defined(HAVE_INLINE) INLINE int IsTypeUnion (const Type* T) /* Return true if this is a union type */ { return (GetType (T) == T_TYPE_UNION); } #else # define IsTypeUnion(T) (GetType (T) == T_TYPE_UNION) #endif #if defined(HAVE_INLINE) INLINE int IsTypeArray (const Type* T) /* Return true if this is an array type */ { return (GetType (T) == T_TYPE_ARRAY); } #else # define IsTypeArray(T) (GetType (T) == T_TYPE_ARRAY) #endif #if defined(HAVE_INLINE) INLINE int IsTypeVoid (const Type* T) /* Return true if this is a void type */ { return (GetType (T) == T_TYPE_VOID); } #else # define IsTypeVoid(T) (GetType (T) == T_TYPE_VOID) #endif #if defined(HAVE_INLINE) INLINE int IsTypeFunc (const Type* T) /* Return true if this is a function class */ { return (GetType (T) == T_TYPE_FUNC); } #else # define IsTypeFunc(T) (GetType (T) == T_TYPE_FUNC) #endif #if defined(HAVE_INLINE) INLINE int IsTypeFuncPtr (const Type* T) /* Return true if this is a function pointer */ { return (IsTypePtr (T) && IsTypeFunc (T+1)); } #else # define IsTypeFuncPtr(T) (IsTypePtr (T) && IsTypeFunc (T+1)) #endif #if defined(HAVE_INLINE) INLINE TypeCode GetClass (const Type* T) /* Get the class of a type string */ { return (T->C & T_MASK_CLASS); } #else # define GetClass(T) ((T)->C & T_MASK_CLASS) #endif #if defined(HAVE_INLINE) INLINE int IsClassInt (const Type* T) /* Return true if this is an integer type */ { return (GetClass (T) == T_CLASS_INT); } #else # define IsClassInt(T) (GetClass (T) == T_CLASS_INT) #endif #if defined(HAVE_INLINE) INLINE int IsClassFloat (const Type* T) /* Return true if this is a float type */ { return (GetClass (T) == T_CLASS_FLOAT); } #else # define IsClassFloat(T) (GetClass (T) == T_CLASS_FLOAT) #endif #if defined(HAVE_INLINE) INLINE int IsClassPtr (const Type* T) /* Return true if this is a pointer type */ { return (GetClass (T) == T_CLASS_PTR); } #else # define IsClassPtr(T) (GetClass (T) == T_CLASS_PTR) #endif #if defined(HAVE_INLINE) INLINE int IsClassStruct (const Type* T) /* Return true if this is a struct type */ { return (GetClass (T) == T_CLASS_STRUCT); } #else # define IsClassStruct(T) (GetClass (T) == T_CLASS_STRUCT) #endif #if defined(HAVE_INLINE) INLINE int IsClassFunc (const Type* T) /* Return true if this is a function type */ { return (GetClass (T) == T_CLASS_FUNC); } #else # define IsClassFunc(T) (GetClass (T) == T_CLASS_FUNC) #endif #if defined(HAVE_INLINE) INLINE TypeCode GetSignedness (const Type* T) /* Get the sign of a type */ { return (T->C & T_MASK_SIGN); } #else # define GetSignedness(T) ((T)->C & T_MASK_SIGN) #endif #if defined(HAVE_INLINE) INLINE int IsSignUnsigned (const Type* T) /* Return true if this is an unsigned type */ { return (GetSignedness (T) == T_SIGN_UNSIGNED); } #else # define IsSignUnsigned(T) (GetSignedness (T) == T_SIGN_UNSIGNED) #endif #if defined(HAVE_INLINE) INLINE int IsSignSigned (const Type* T) /* Return true if this is a signed type */ { return (GetSignedness (T) == T_SIGN_SIGNED); } #else # define IsSignSigned(T) (GetSignedness (T) == T_SIGN_SIGNED) #endif #if defined(HAVE_INLINE) INLINE TypeCode GetQualifier (const Type* T) /* Get the qualifier from the given type string */ { return (T->C & T_MASK_QUAL); } #else # define GetQualifier(T) ((T)->C & T_MASK_QUAL) #endif #if defined(HAVE_INLINE) INLINE int IsQualConst (const Type* T) /* Return true if the given type has a const memory image */ { return (T->C & T_QUAL_CONST) != 0; } #else # define IsQualConst(T) (((T)->C & T_QUAL_CONST) != 0) #endif #if defined(HAVE_INLINE) INLINE int IsQualVolatile (const Type* T) /* Return true if the given type has a volatile type qualifier */ { return (T->C & T_QUAL_VOLATILE) != 0; } #else # define IsQualVolatile(T) (((T)->C & T_QUAL_VOLATILE) != 0) #endif #if defined(HAVE_INLINE) INLINE int IsQualRestrict (const Type* T) /* Return true if the given type has a restrict qualifier */ { return (T->C & T_QUAL_RESTRICT) != 0; } #else # define IsQualRestrict(T) (((T)->C & T_QUAL_RESTRICT) != 0) #endif #if defined(HAVE_INLINE) INLINE int IsQualNear (const Type* T) /* Return true if the given type has a near qualifier */ { return (T->C & T_QUAL_NEAR) != 0; } #else # define IsQualNear(T) (((T)->C & T_QUAL_NEAR) != 0) #endif #if defined(HAVE_INLINE) INLINE int IsQualFar (const Type* T) /* Return true if the given type has a far qualifier */ { return (T->C & T_QUAL_FAR) != 0; } #else # define IsQualFar(T) (((T)->C & T_QUAL_FAR) != 0) #endif #if defined(HAVE_INLINE) INLINE int IsQualFastcall (const Type* T) /* Return true if the given type has a fastcall qualifier */ { return (T->C & T_QUAL_FASTCALL) != 0; } #else # define IsQualFastcall(T) (((T)->C & T_QUAL_FASTCALL) != 0) #endif #if defined(HAVE_INLINE) INLINE int IsQualCDecl (const Type* T) /* Return true if the given type has a cdecl qualifier */ { return (T->C & T_QUAL_CDECL) != 0; } #else # 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 */ #if defined(HAVE_INLINE) INLINE TypeCode GetSizeModifier (const Type* T) /* Get the size modifier of a type */ { return (T->C & T_MASK_SIZE); } #else # define GetSizeModifier(T) ((T)->C & T_MASK_SIZE) #endif FuncDesc* GetFuncDesc (const Type* T) attribute ((const)); /* Get the FuncDesc pointer from a function or pointer-to-function type */ void SetFuncDesc (Type* T, FuncDesc* F); /* Set the FuncDesc pointer in a function or pointer-to-function type */ Type* GetFuncReturn (Type* T) attribute ((const)); /* Return a pointer to the return type of a function or pointer-to-function type */ long GetElementCount (const Type* T); /* Get the element count of the array specified in T (which must be of ** array type). */ void SetElementCount (Type* T, long Count); /* Set the element count of the array specified in T (which must be of ** array type). */ Type* GetElementType (Type* T); /* Return the element type of the given array type. */ Type* GetBaseElementType (Type* T); /* Return the base element type of a given type. If T is not an array, this ** will return. Otherwise it will return the base element type, which means ** the element type that is not an array. */ struct SymEntry* GetSymEntry (const Type* T) attribute ((const)); /* Return a SymEntry pointer from a type */ void SetSymEntry (Type* T, struct SymEntry* S); /* Set the SymEntry pointer for a type */ Type* IntPromotion (Type* T); /* Apply the integer promotions to T and return the result. The returned type ** string may be T if there is no need to change it. */ Type* PtrConversion (Type* T); /* If the type is a function, convert it to pointer to function. If the ** expression is an array, convert it to pointer to first element. Otherwise ** return T. */ TypeCode AddrSizeQualifier (unsigned AddrSize); /* Return T_QUAL_NEAR or T_QUAL_FAR depending on the address size */ #if defined(HAVE_INLINE) INLINE TypeCode CodeAddrSizeQualifier (void) /* Return T_QUAL_NEAR or T_QUAL_FAR depending on the code address size */ { return AddrSizeQualifier (CodeAddrSize); } #else # define CodeAddrSizeQualifier() (AddrSizeQualifier (CodeAddrSize)) #endif #if defined(HAVE_INLINE) INLINE TypeCode DataAddrSizeQualifier (void) /* Return T_QUAL_NEAR or T_QUAL_FAR depending on the data address size */ { return AddrSizeQualifier (DataAddrSize); } #else # define DataAddrSizeQualifier() (AddrSizeQualifier (DataAddrSize)) #endif /* End of datatype.h */ #endif ������������������cc65-2.18/src/cc65/declare.c������������������������������������������������������������������������0000664�0000000�0000000�00000205262�13473601511�0015306�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* declare.c */ /* */ /* Parse variable and function declarations */ /* */ /* */ /* */ /* (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 */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> #include <errno.h> /* common */ #include "addrsize.h" #include "mmodel.h" #include "xmalloc.h" /* cc65 */ #include "anonname.h" #include "codegen.h" #include "datatype.h" #include "declare.h" #include "declattr.h" #include "error.h" #include "expr.h" #include "funcdesc.h" #include "function.h" #include "global.h" #include "litpool.h" #include "pragma.h" #include "scanner.h" #include "standard.h" #include "symtab.h" #include "wrappedcall.h" #include "typeconv.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ typedef struct StructInitData StructInitData; struct StructInitData { unsigned Size; /* Size of struct */ unsigned Offs; /* Current offset in struct */ unsigned BitVal; /* Summed up bit-field value */ unsigned ValBits; /* Valid bits in Val */ }; /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers); /* Parse a type specifier */ static unsigned ParseInitInternal (Type* T, int AllowFlexibleMembers); /* Parse initialization of variables. Return the number of data bytes. */ /*****************************************************************************/ /* Internal functions */ /*****************************************************************************/ static void DuplicateQualifier (const char* Name) /* Print an error message */ { Warning ("Duplicate qualifier: '%s'", Name); } static TypeCode OptionalQualifiers (TypeCode Allowed) /* Read type qualifiers if we have any. Allowed specifies the allowed ** qualifiers. */ { /* We start without any qualifiers */ TypeCode Q = T_QUAL_NONE; /* Check for more qualifiers */ while (1) { switch (CurTok.Tok) { case TOK_CONST: if (Allowed & T_QUAL_CONST) { if (Q & T_QUAL_CONST) { DuplicateQualifier ("const"); } Q |= T_QUAL_CONST; } else { goto Done; } break; case TOK_VOLATILE: if (Allowed & T_QUAL_VOLATILE) { if (Q & T_QUAL_VOLATILE) { DuplicateQualifier ("volatile"); } Q |= T_QUAL_VOLATILE; } else { goto Done; } break; case TOK_RESTRICT: if (Allowed & T_QUAL_RESTRICT) { if (Q & T_QUAL_RESTRICT) { DuplicateQualifier ("restrict"); } Q |= T_QUAL_RESTRICT; } else { goto Done; } break; case TOK_NEAR: if (Allowed & T_QUAL_NEAR) { if (Q & T_QUAL_NEAR) { DuplicateQualifier ("near"); } Q |= T_QUAL_NEAR; } else { goto Done; } break; case TOK_FAR: if (Allowed & T_QUAL_FAR) { if (Q & T_QUAL_FAR) { DuplicateQualifier ("far"); } Q |= T_QUAL_FAR; } else { goto Done; } break; case TOK_FASTCALL: if (Allowed & T_QUAL_FASTCALL) { if (Q & T_QUAL_FASTCALL) { DuplicateQualifier ("fastcall"); } Q |= T_QUAL_FASTCALL; } else { goto Done; } break; case TOK_CDECL: if (Allowed & T_QUAL_CDECL) { if (Q & T_QUAL_CDECL) { DuplicateQualifier ("cdecl"); } Q |= T_QUAL_CDECL; } else { goto Done; } break; default: goto Done; } /* Skip the token */ NextToken (); } Done: /* We cannot have more than one address size far qualifier */ switch (Q & T_QUAL_ADDRSIZE) { case T_QUAL_NONE: case T_QUAL_NEAR: case T_QUAL_FAR: break; default: Error ("Cannot specify more than one address size qualifier"); Q &= ~T_QUAL_ADDRSIZE; } /* We cannot have more than one calling convention specifier */ switch (Q & T_QUAL_CCONV) { case T_QUAL_NONE: case T_QUAL_FASTCALL: case T_QUAL_CDECL: break; default: Error ("Cannot specify more than one calling convention qualifier"); Q &= ~T_QUAL_CCONV; } /* Return the qualifiers read */ return Q; } static void OptionalInt (void) /* Eat an optional "int" token */ { if (CurTok.Tok == TOK_INT) { /* Skip it */ NextToken (); } } static void OptionalSigned (void) /* Eat an optional "signed" token */ { if (CurTok.Tok == TOK_SIGNED) { /* Skip it */ NextToken (); } } static void InitDeclSpec (DeclSpec* D) /* Initialize the DeclSpec struct for use */ { D->StorageClass = 0; D->Type[0].C = T_END; D->Flags = 0; } static void InitDeclaration (Declaration* D) /* Initialize the Declaration struct for use */ { D->Ident[0] = '\0'; D->Type[0].C = T_END; D->Index = 0; D->Attributes = 0; } static void NeedTypeSpace (Declaration* D, unsigned Count) /* Check if there is enough space for Count type specifiers within D */ { if (D->Index + Count >= MAXTYPELEN) { /* We must call Fatal() here, since calling Error() will try to ** continue, and the declaration type is not correctly terminated ** in case we come here. */ Fatal ("Too many type specifiers"); } } static void AddTypeToDeclaration (Declaration* D, TypeCode T) /* Add a type specifier to the type of a declaration */ { NeedTypeSpace (D, 1); D->Type[D->Index++].C = T; } static void FixQualifiers (Type* DataType) /* Apply several fixes to qualifiers */ { Type* T; TypeCode Q; /* Using typedefs, it is possible to generate declarations that have ** type qualifiers attached to an array, not the element type. Go and ** fix these here. */ T = DataType; Q = T_QUAL_NONE; while (T->C != T_END) { if (IsTypeArray (T)) { /* Extract any type qualifiers */ Q |= GetQualifier (T); T->C = UnqualifiedType (T->C); } else { /* Add extracted type qualifiers here */ T->C |= Q; Q = T_QUAL_NONE; } ++T; } /* Q must be empty now */ CHECK (Q == T_QUAL_NONE); /* Do some fixes on pointers and functions. */ T = DataType; while (T->C != T_END) { if (IsTypePtr (T)) { /* Calling convention qualifier on the pointer? */ if (IsQualCConv (T)) { /* Pull the convention off of the pointer */ Q = T[0].C & T_QUAL_CCONV; T[0].C &= ~T_QUAL_CCONV; /* 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 ("Not pointer to a function; can't use a calling convention"); } } /* Apply the default far and near qualifiers if none are given */ Q = (T[0].C & T_QUAL_ADDRSIZE); 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 doesn't have one. */ Q = (T[1].C & T_QUAL_ADDRSIZE); if (Q == T_QUAL_NONE) { Q = CodeAddrSizeQualifier (); } } else { Q = DataAddrSizeQualifier (); } T[0].C |= Q; } else { /* We have address size qualifiers. If followed by a function, ** apply them to the function also. */ if (IsTypeFunc (T+1)) { TypeCode FQ = (T[1].C & T_QUAL_ADDRSIZE); if (FQ == T_QUAL_NONE) { T[1].C |= Q; } else if (FQ != Q) { Error ("Address size qualifier mismatch"); T[1].C = (T[1].C & ~T_QUAL_ADDRSIZE) | Q; } } } } else if (IsTypeFunc (T)) { /* Apply the default far and near qualifiers if none are given */ if ((T[0].C & T_QUAL_ADDRSIZE) == 0) { T[0].C |= CodeAddrSizeQualifier (); } } ++T; } } static void ParseStorageClass (DeclSpec* D, unsigned DefStorage) /* Parse a storage class */ { /* Assume we're using an explicit storage class */ D->Flags &= ~DS_DEF_STORAGE; /* Check the storage class given */ switch (CurTok.Tok) { case TOK_EXTERN: D->StorageClass = SC_EXTERN | SC_STATIC; NextToken (); break; case TOK_STATIC: D->StorageClass = SC_STATIC; NextToken (); break; case TOK_REGISTER: D->StorageClass = SC_REGISTER | SC_STATIC; NextToken (); break; case TOK_AUTO: D->StorageClass = SC_AUTO; NextToken (); break; case TOK_TYPEDEF: D->StorageClass = SC_TYPEDEF; NextToken (); break; default: /* No storage class given, use default */ D->Flags |= DS_DEF_STORAGE; D->StorageClass = DefStorage; break; } } static void ParseEnumDecl (void) /* Process an enum declaration . */ { int EnumVal; ident Ident; /* Accept forward definitions */ if (CurTok.Tok != TOK_LCURLY) { return; } /* Skip the opening curly brace */ NextToken (); /* Read the enum tags */ EnumVal = 0; while (CurTok.Tok != TOK_RCURLY) { /* We expect an identifier */ if (CurTok.Tok != TOK_IDENT) { Error ("Identifier expected"); continue; } /* Remember the identifier and skip it */ strcpy (Ident, CurTok.Ident); NextToken (); /* Check for an assigned value */ if (CurTok.Tok == TOK_ASSIGN) { ExprDesc Expr; NextToken (); ConstAbsIntExpr (hie1, &Expr); EnumVal = Expr.IVal; } /* Add an entry to the symbol table */ AddConstSym (Ident, type_int, SC_ENUM, EnumVal++); /* Check for end of definition */ if (CurTok.Tok != TOK_COMMA) break; NextToken (); } ConsumeRCurly (); } static int ParseFieldWidth (Declaration* Decl) /* Parse an optional field width. Returns -1 if no field width is specified, ** otherwise the width of the field. */ { ExprDesc Expr; if (CurTok.Tok != TOK_COLON) { /* No bit-field declaration */ return -1; } /* Read the width */ NextToken (); ConstAbsIntExpr (hie1, &Expr); if (Expr.IVal < 0) { Error ("Negative width in bit-field"); return -1; } if (Expr.IVal > (int) INT_BITS) { Error ("Width of bit-field exceeds its type"); return -1; } if (Expr.IVal == 0 && Decl->Ident[0] != '\0') { Error ("Zero width for named bit-field"); return -1; } if (!IsTypeInt (Decl->Type)) { /* Only integer types may be used for bit-fields */ Error ("Bit-field has invalid type"); return -1; } /* Return the field width */ return (int) Expr.IVal; } static SymEntry* StructOrUnionForwardDecl (const char* Name, unsigned Type) /* Handle a struct or union forward decl */ { /* Try to find a struct/union with the given name. If there is none, ** insert a forward declaration into the current lexical level. */ SymEntry* Entry = FindTagSym (Name); if (Entry == 0) { Entry = AddStructSym (Name, Type, 0, 0); } else if ((Entry->Flags & SC_TYPEMASK) != Type) { /* Already defined, but no struct */ Error ("Symbol '%s' is already different kind", Name); } return Entry; } static unsigned CopyAnonStructFields (const Declaration* Decl, int Offs) /* Copy fields from an anon union/struct into the current lexical level. The ** function returns the size of the embedded struct/union. */ { /* Get the pointer to the symbol table entry of the anon struct */ SymEntry* Entry = GetSymEntry (Decl->Type); /* Get the size of the anon struct */ unsigned Size = Entry->V.S.Size; /* Get the symbol table containing the fields. If it is empty, there has ** been an error before, so bail out. */ SymTable* Tab = Entry->V.S.SymTab; if (Tab == 0) { /* Incomplete definition - has been flagged before */ return Size; } /* Get a pointer to the list of symbols. Then walk the list adding copies ** of the embedded struct to the current level. */ Entry = Tab->SymHead; while (Entry) { /* Enter a copy of this symbol adjusting the offset. We will just ** reuse the type string here. */ AddLocalSym (Entry->Name, Entry->Type, SC_STRUCTFIELD, Offs + Entry->V.Offs); /* Currently, there can not be any attributes, but if there will be ** some in the future, we want to know this. */ CHECK (Entry->Attr == 0); /* Next entry */ Entry = Entry->NextSym; } /* Return the size of the embedded struct */ return Size; } static SymEntry* ParseUnionDecl (const char* Name) /* Parse a union declaration. */ { unsigned UnionSize; unsigned FieldSize; int FieldWidth; /* Width in bits, -1 if not a bit-field */ SymTable* FieldTab; if (CurTok.Tok != TOK_LCURLY) { /* Just a forward declaration. */ return StructOrUnionForwardDecl (Name, SC_UNION); } /* Add a forward declaration for the struct in the current lexical level */ AddStructSym (Name, SC_UNION, 0, 0); /* Skip the curly brace */ NextToken (); /* Enter a new lexical level for the struct */ EnterStructLevel (); /* Parse union fields */ UnionSize = 0; while (CurTok.Tok != TOK_RCURLY) { /* Get the type of the entry */ DeclSpec Spec; InitDeclSpec (&Spec); ParseTypeSpec (&Spec, -1, T_QUAL_NONE); /* Read fields with this type */ while (1) { Declaration Decl; /* Get type and name of the struct field */ ParseDecl (&Spec, &Decl, DM_ACCEPT_IDENT); /* Check for a bit-field declaration */ FieldWidth = ParseFieldWidth (&Decl); /* Ignore zero sized bit fields in a union */ if (FieldWidth == 0) { goto NextMember; } /* Check for fields without a name */ if (Decl.Ident[0] == '\0') { /* In cc65 mode, we allow anonymous structs/unions within ** a union. */ if (IS_Get (&Standard) >= STD_CC65 && IsClassStruct (Decl.Type)) { /* This is an anonymous struct or union. Copy the fields ** into the current level. */ FieldSize = CopyAnonStructFields (&Decl, 0); if (FieldSize > UnionSize) { UnionSize = FieldSize; } } else { /* A non bit-field without a name is legal but useless */ Warning ("Declaration does not declare anything"); } goto NextMember; } /* Handle sizes */ FieldSize = CheckedSizeOf (Decl.Type); if (FieldSize > UnionSize) { UnionSize = FieldSize; } /* Add a field entry to the table. */ if (FieldWidth > 0) { AddBitField (Decl.Ident, 0, 0, FieldWidth); } else { AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, 0); } NextMember: if (CurTok.Tok != TOK_COMMA) { break; } NextToken (); } ConsumeSemi (); } /* Skip the closing brace */ NextToken (); /* Remember the symbol table and leave the struct level */ FieldTab = GetSymTab (); LeaveStructLevel (); /* Make a real entry from the forward decl and return it */ return AddStructSym (Name, SC_UNION, UnionSize, FieldTab); } static SymEntry* ParseStructDecl (const char* Name) /* Parse a struct declaration. */ { unsigned StructSize; int FlexibleMember; int BitOffs; /* Bit offset for bit-fields */ int FieldWidth; /* Width in bits, -1 if not a bit-field */ SymTable* FieldTab; if (CurTok.Tok != TOK_LCURLY) { /* Just a forward declaration. */ return StructOrUnionForwardDecl (Name, SC_STRUCT); } /* Add a forward declaration for the struct in the current lexical level */ AddStructSym (Name, SC_STRUCT, 0, 0); /* Skip the curly brace */ NextToken (); /* Enter a new lexical level for the struct */ EnterStructLevel (); /* Parse struct fields */ FlexibleMember = 0; StructSize = 0; BitOffs = 0; while (CurTok.Tok != TOK_RCURLY) { /* Get the type of the entry */ DeclSpec Spec; InitDeclSpec (&Spec); ParseTypeSpec (&Spec, -1, T_QUAL_NONE); /* Read fields with this type */ while (1) { Declaration Decl; ident Ident; /* If we had a flexible array member before, no other fields can ** follow. */ if (FlexibleMember) { Error ("Flexible array member must be last field"); FlexibleMember = 0; /* Avoid further errors */ } /* Get type and name of the struct field */ ParseDecl (&Spec, &Decl, DM_ACCEPT_IDENT); /* Check for a bit-field declaration */ FieldWidth = ParseFieldWidth (&Decl); /* If this is not a bit field, or the bit field is too large for ** the remainder of the current member, or we have a bit field ** with width zero, align the struct to the next member by adding ** a member with an anonymous name. */ if (BitOffs > 0) { if (FieldWidth <= 0 || (BitOffs + FieldWidth) > (int) INT_BITS) { /* We need an anonymous name */ AnonName (Ident, "bit-field"); /* Add an anonymous bit-field that aligns to the next ** storage unit. */ AddBitField (Ident, StructSize, BitOffs, INT_BITS - BitOffs); /* No bits left */ StructSize += SIZEOF_INT; BitOffs = 0; } } /* Apart from the above, a bit field with width 0 is not processed ** further. */ if (FieldWidth == 0) { goto NextMember; } /* Check if this field is a flexible array member, and ** calculate the size of the field. */ if (IsTypeArray (Decl.Type) && GetElementCount (Decl.Type) == UNSPECIFIED) { /* Array with unspecified size */ if (StructSize == 0) { Error ("Flexible array member cannot be first struct field"); } FlexibleMember = 1; /* Assume zero for size calculations */ SetElementCount (Decl.Type, FLEXIBLE); } /* Check for fields without names */ if (Decl.Ident[0] == '\0') { if (FieldWidth < 0) { /* In cc65 mode, we allow anonymous structs/unions within ** a struct. */ if (IS_Get (&Standard) >= STD_CC65 && IsClassStruct (Decl.Type)) { /* This is an anonymous struct or union. Copy the ** fields into the current level. */ StructSize += CopyAnonStructFields (&Decl, StructSize); } else { /* A non bit-field without a name is legal but useless */ Warning ("Declaration does not declare anything"); } goto NextMember; } else { /* A bit-field without a name will get an anonymous one */ AnonName (Decl.Ident, "bit-field"); } } /* Add a field entry to the table */ if (FieldWidth > 0) { /* Add full byte from the bit offset to the variable offset. ** This simplifies handling he bit-field as a char type ** in expressions. */ unsigned Offs = StructSize + (BitOffs / CHAR_BITS); AddBitField (Decl.Ident, Offs, BitOffs % CHAR_BITS, FieldWidth); BitOffs += FieldWidth; CHECK (BitOffs <= (int) INT_BITS); if (BitOffs == INT_BITS) { StructSize += SIZEOF_INT; BitOffs = 0; } } else { AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, StructSize); if (!FlexibleMember) { StructSize += CheckedSizeOf (Decl.Type); } } NextMember: if (CurTok.Tok != TOK_COMMA) { break; } NextToken (); } ConsumeSemi (); } /* If we have bits from bit-fields left, add them to the size. */ if (BitOffs > 0) { StructSize += ((BitOffs + CHAR_BITS - 1) / CHAR_BITS); } /* Skip the closing brace */ NextToken (); /* Remember the symbol table and leave the struct level */ FieldTab = GetSymTab (); LeaveStructLevel (); /* Make a real entry from the forward decl and return it */ return AddStructSym (Name, SC_STRUCT, StructSize, FieldTab); } static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers) /* Parse a type specifier */ { ident Ident; SymEntry* Entry; /* Assume we have an explicit type */ D->Flags &= ~DS_DEF_TYPE; /* Read type qualifiers if we have any */ Qualifiers |= OptionalQualifiers (T_QUAL_CONST | T_QUAL_VOLATILE); /* Look at the data type */ switch (CurTok.Tok) { case TOK_VOID: NextToken (); D->Type[0].C = T_VOID; D->Type[0].A.U = 0; D->Type[1].C = T_END; break; case TOK_CHAR: NextToken (); D->Type[0].C = GetDefaultChar(); D->Type[1].C = T_END; break; case TOK_LONG: NextToken (); if (CurTok.Tok == TOK_UNSIGNED) { NextToken (); OptionalInt (); D->Type[0].C = T_ULONG; D->Type[1].C = T_END; } else { OptionalSigned (); OptionalInt (); D->Type[0].C = T_LONG; D->Type[1].C = T_END; } break; case TOK_SHORT: NextToken (); if (CurTok.Tok == TOK_UNSIGNED) { NextToken (); OptionalInt (); D->Type[0].C = T_USHORT; D->Type[1].C = T_END; } else { OptionalSigned (); OptionalInt (); D->Type[0].C = T_SHORT; D->Type[1].C = T_END; } break; case TOK_INT: NextToken (); D->Type[0].C = T_INT; D->Type[1].C = T_END; break; case TOK_SIGNED: NextToken (); switch (CurTok.Tok) { case TOK_CHAR: NextToken (); D->Type[0].C = T_SCHAR; D->Type[1].C = T_END; break; case TOK_SHORT: NextToken (); OptionalInt (); D->Type[0].C = T_SHORT; D->Type[1].C = T_END; break; case TOK_LONG: NextToken (); OptionalInt (); D->Type[0].C = T_LONG; D->Type[1].C = T_END; break; case TOK_INT: NextToken (); /* FALL THROUGH */ default: D->Type[0].C = T_INT; D->Type[1].C = T_END; break; } break; case TOK_UNSIGNED: NextToken (); switch (CurTok.Tok) { case TOK_CHAR: NextToken (); D->Type[0].C = T_UCHAR; D->Type[1].C = T_END; break; case TOK_SHORT: NextToken (); OptionalInt (); D->Type[0].C = T_USHORT; D->Type[1].C = T_END; break; case TOK_LONG: NextToken (); OptionalInt (); D->Type[0].C = T_ULONG; D->Type[1].C = T_END; break; case TOK_INT: NextToken (); /* FALL THROUGH */ default: D->Type[0].C = T_UINT; D->Type[1].C = T_END; break; } break; case TOK_FLOAT: NextToken (); D->Type[0].C = T_FLOAT; D->Type[1].C = T_END; break; case TOK_DOUBLE: NextToken (); D->Type[0].C = T_DOUBLE; D->Type[1].C = T_END; break; case TOK_UNION: NextToken (); /* */ if (CurTok.Tok == TOK_IDENT) { strcpy (Ident, CurTok.Ident); NextToken (); } else { AnonName (Ident, "union"); } /* Remember we have an extra type decl */ D->Flags |= DS_EXTRA_TYPE; /* Declare the union in the current scope */ Entry = ParseUnionDecl (Ident); /* Encode the union entry into the type */ D->Type[0].C = T_UNION; SetSymEntry (D->Type, Entry); D->Type[1].C = T_END; break; case TOK_STRUCT: NextToken (); /* */ if (CurTok.Tok == TOK_IDENT) { strcpy (Ident, CurTok.Ident); NextToken (); } else { AnonName (Ident, "struct"); } /* Remember we have an extra type decl */ D->Flags |= DS_EXTRA_TYPE; /* Declare the struct in the current scope */ Entry = ParseStructDecl (Ident); /* Encode the struct entry into the type */ D->Type[0].C = T_STRUCT; SetSymEntry (D->Type, Entry); D->Type[1].C = T_END; break; case TOK_ENUM: NextToken (); if (CurTok.Tok != TOK_LCURLY) { /* Named enum */ if (CurTok.Tok == TOK_IDENT) { /* Find an entry with this name */ Entry = FindTagSym (CurTok.Ident); if (Entry) { if (SymIsLocal (Entry) && (Entry->Flags & SC_ENUM) == 0) { Error ("Symbol '%s' is already different kind", Entry->Name); } } else { /* Insert entry into table ### */ } /* Skip the identifier */ NextToken (); } else { Error ("Identifier expected"); } } /* Remember we have an extra type decl */ D->Flags |= DS_EXTRA_TYPE; /* Parse the enum decl */ ParseEnumDecl (); D->Type[0].C = T_INT; D->Type[1].C = T_END; break; case TOK_IDENT: Entry = FindSym (CurTok.Ident); if (Entry && SymIsTypeDef (Entry)) { /* It's a typedef */ NextToken (); TypeCopy (D->Type, Entry->Type); break; } /* FALL THROUGH */ default: if (Default < 0) { Error ("Type expected"); D->Type[0].C = T_INT; D->Type[1].C = T_END; } else { D->Flags |= DS_DEF_TYPE; D->Type[0].C = (TypeCode) Default; D->Type[1].C = T_END; } break; } /* There may also be qualifiers *after* the initial type */ D->Type[0].C |= (Qualifiers | OptionalQualifiers (T_QUAL_CONST | T_QUAL_VOLATILE)); } static Type* ParamTypeCvt (Type* T) /* If T is an array, convert it to a pointer else do nothing. Return the ** resulting type. */ { if (IsTypeArray (T)) { T->C = T_PTR; } return T; } static void ParseOldStyleParamList (FuncDesc* F) /* Parse an old style (K&R) parameter list */ { /* Some fix point tokens that are used for error recovery */ static const token_t TokenList[] = { TOK_COMMA, TOK_RPAREN, TOK_SEMI }; /* Parse params */ while (CurTok.Tok != TOK_RPAREN) { /* List of identifiers expected */ if (CurTok.Tok == TOK_IDENT) { /* Create a symbol table entry with type int */ AddLocalSym (CurTok.Ident, type_int, SC_AUTO | SC_PARAM | SC_DEF | SC_DEFTYPE, 0); /* Count arguments */ ++F->ParamCount; /* Skip the identifier */ NextToken (); } else { /* Not a parameter name */ Error ("Identifier expected"); /* Try some smart error recovery */ SkipTokens (TokenList, sizeof(TokenList) / sizeof(TokenList[0])); } /* Check for more parameters */ if (CurTok.Tok == TOK_COMMA) { NextToken (); } else { break; } } /* Skip right paren. We must explicitly check for one here, since some of ** the breaks above bail out without checking. */ ConsumeRParen (); /* An optional list of type specifications follows */ while (CurTok.Tok != TOK_LCURLY) { DeclSpec Spec; /* Read the declaration specifier */ ParseDeclSpec (&Spec, SC_AUTO, T_INT); /* We accept only auto and register as storage class specifiers, but ** we ignore all this, since we use auto anyway. */ if ((Spec.StorageClass & SC_AUTO) == 0 && (Spec.StorageClass & SC_REGISTER) == 0) { Error ("Illegal storage class"); } /* Parse a comma separated variable list */ while (1) { Declaration Decl; /* Read the parameter */ ParseDecl (&Spec, &Decl, DM_NEED_IDENT); if (Decl.Ident[0] != '\0') { /* We have a name given. Search for the symbol */ SymEntry* Sym = FindLocalSym (Decl.Ident); if (Sym) { /* Check if we already changed the type for this ** parameter */ if (Sym->Flags & SC_DEFTYPE) { /* Found it, change the default type to the one given */ ChangeSymType (Sym, ParamTypeCvt (Decl.Type)); /* Reset the "default type" flag */ Sym->Flags &= ~SC_DEFTYPE; } else { /* Type has already been changed */ Error ("Redefinition for parameter '%s'", Sym->Name); } } else { Error ("Unknown identifier: '%s'", Decl.Ident); } } if (CurTok.Tok == TOK_COMMA) { NextToken (); } else { break; } } /* Variable list must be semicolon terminated */ ConsumeSemi (); } } static void ParseAnsiParamList (FuncDesc* F) /* Parse a new style (ANSI) parameter list */ { /* Parse params */ while (CurTok.Tok != TOK_RPAREN) { DeclSpec Spec; Declaration Decl; SymEntry* Sym; /* Allow an ellipsis as last parameter */ if (CurTok.Tok == TOK_ELLIPSIS) { NextToken (); F->Flags |= FD_VARIADIC; break; } /* Read the declaration specifier */ ParseDeclSpec (&Spec, SC_AUTO, T_INT); /* We accept only auto and register as storage class specifiers */ if ((Spec.StorageClass & SC_AUTO) == SC_AUTO) { Spec.StorageClass = SC_AUTO | SC_PARAM | SC_DEF; } else if ((Spec.StorageClass & SC_REGISTER) == SC_REGISTER) { Spec.StorageClass = SC_REGISTER | SC_STATIC | SC_PARAM | SC_DEF; } else { Error ("Illegal storage class"); Spec.StorageClass = SC_AUTO | SC_PARAM | SC_DEF; } /* Allow parameters without a name, but remember if we had some to ** eventually print an error message later. */ ParseDecl (&Spec, &Decl, DM_ACCEPT_IDENT); if (Decl.Ident[0] == '\0') { /* Unnamed symbol. Generate a name that is not user accessible, ** then handle the symbol normal. */ AnonName (Decl.Ident, "param"); F->Flags |= FD_UNNAMED_PARAMS; /* Clear defined bit on nonames */ Decl.StorageClass &= ~SC_DEF; } /* Parse attributes for this parameter */ ParseAttribute (&Decl); /* Create a symbol table entry */ Sym = AddLocalSym (Decl.Ident, ParamTypeCvt (Decl.Type), Decl.StorageClass, 0); /* Add attributes if we have any */ SymUseAttr (Sym, &Decl); /* If the parameter is a struct or union, emit a warning */ if (IsClassStruct (Decl.Type)) { if (IS_Get (&WarnStructParam)) { Warning ("Passing struct by value for parameter '%s'", Decl.Ident); } } /* Count arguments */ ++F->ParamCount; /* Check for more parameters */ if (CurTok.Tok == TOK_COMMA) { NextToken (); } else { break; } } /* Skip right paren. We must explicitly check for one here, since some of ** the breaks above bail out without checking. */ ConsumeRParen (); } static FuncDesc* ParseFuncDecl (void) /* Parse the argument list of a function. */ { unsigned Offs; SymEntry* Sym; SymEntry* WrappedCall; unsigned char WrappedCallData; /* Create a new function descriptor */ FuncDesc* F = NewFuncDesc (); /* Enter a new lexical level */ EnterFunctionLevel (); /* Check for several special parameter lists */ if (CurTok.Tok == TOK_RPAREN) { /* Parameter list is empty */ F->Flags |= (FD_EMPTY | FD_VARIADIC); } else if (CurTok.Tok == TOK_VOID && NextTok.Tok == TOK_RPAREN) { /* Parameter list declared as void */ NextToken (); F->Flags |= FD_VOID_PARAM; } else if (CurTok.Tok == TOK_IDENT && (NextTok.Tok == TOK_COMMA || NextTok.Tok == TOK_RPAREN)) { /* If the identifier is a typedef, we have a new style parameter list, ** if it's some other identifier, it's an old style parameter list. */ Sym = FindSym (CurTok.Ident); if (Sym == 0 || !SymIsTypeDef (Sym)) { /* Old style (K&R) function. */ F->Flags |= FD_OLDSTYLE; } } /* Parse params */ if ((F->Flags & FD_OLDSTYLE) == 0) { /* New style function */ ParseAnsiParamList (F); } else { /* Old style function */ ParseOldStyleParamList (F); } /* Remember the last function parameter. We need it later for several ** purposes, for example when passing stuff to fastcall functions. Since ** more symbols are added to the table, it is easier if we remember it ** now, since it is currently the last entry in the symbol table. */ F->LastParam = GetSymTab()->SymTail; /* Assign offsets. If the function has a variable parameter list, ** there's one additional byte (the arg size). */ Offs = (F->Flags & FD_VARIADIC)? 1 : 0; Sym = F->LastParam; while (Sym) { unsigned Size = CheckedSizeOf (Sym->Type); if (SymIsRegVar (Sym)) { Sym->V.R.SaveOffs = Offs; } else { Sym->V.Offs = Offs; } Offs += Size; F->ParamSize += Size; Sym = Sym->PrevSym; } /* Leave the lexical level remembering the symbol tables */ RememberFunctionLevel (F); /* Did we have a WrappedCall for this function? */ GetWrappedCall((void **) &WrappedCall, &WrappedCallData); if (WrappedCall) { F->WrappedCall = WrappedCall; F->WrappedCallData = WrappedCallData; } /* Return the function descriptor */ return F; } 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. 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_CCONV); /* Pointer to something */ if (CurTok.Tok == TOK_STAR) { /* Skip the star */ NextToken (); /* Allow const, restrict, and volatile qualifiers */ Qualifiers |= OptionalQualifiers (T_QUAL_CONST | T_QUAL_VOLATILE | T_QUAL_RESTRICT); /* Parse the type that the pointer points to */ Declarator (Spec, D, Mode); /* Add the type */ AddTypeToDeclaration (D, T_PTR | Qualifiers); return; } if (CurTok.Tok == TOK_LPAREN) { NextToken (); Declarator (Spec, D, Mode); ConsumeRParen (); } else { /* Things depend on Mode now: ** - Mode == DM_NEED_IDENT means: ** we *must* have a type and a variable identifer. ** - Mode == DM_NO_IDENT means: ** we must have a type but no variable identifer ** (if there is one, it's not read). ** - Mode == DM_ACCEPT_IDENT means: ** we *may* have an identifier. If there is an identifier, ** it is read, but it is no error, if there is none. */ if (Mode == DM_NO_IDENT) { D->Ident[0] = '\0'; } else if (CurTok.Tok == TOK_IDENT) { strcpy (D->Ident, CurTok.Ident); NextToken (); } else { if (Mode == DM_NEED_IDENT) { Error ("Identifier expected"); } D->Ident[0] = '\0'; } } while (CurTok.Tok == TOK_LBRACK || CurTok.Tok == TOK_LPAREN) { if (CurTok.Tok == TOK_LPAREN) { /* Function declaration */ FuncDesc* F; SymEntry* PrevEntry; /* Skip the opening paren */ NextToken (); /* Parse the function declaration */ F = ParseFuncDecl (); /* We cannot specify fastcall for variadic functions */ if ((F->Flags & FD_VARIADIC) && (Qualifiers & T_QUAL_FASTCALL)) { Error ("Variadic functions cannot be __fastcall__"); Qualifiers &= ~T_QUAL_FASTCALL; } /* Was there a previous entry? If so, copy WrappedCall info from it */ PrevEntry = FindGlobalSym (D->Ident); if (PrevEntry && PrevEntry->Flags & SC_FUNC) { FuncDesc* D = PrevEntry->V.F.Func; if (D->WrappedCall && !F->WrappedCall) { F->WrappedCall = D->WrappedCall; F->WrappedCallData = D->WrappedCallData; } } /* Add the function type. Be sure to bounds check the type buffer */ NeedTypeSpace (D, 1); D->Type[D->Index].C = T_FUNC | Qualifiers; D->Type[D->Index].A.P = F; ++D->Index; /* Qualifiers now used */ Qualifiers = T_QUAL_NONE; } else { /* Array declaration. */ long Size = UNSPECIFIED; /* We cannot have any qualifiers for an array */ if (Qualifiers != T_QUAL_NONE) { Error ("Invalid qualifiers for array"); Qualifiers = T_QUAL_NONE; } /* Skip the left bracket */ NextToken (); /* Read the size if it is given */ if (CurTok.Tok != TOK_RBRACK) { ExprDesc Expr; ConstAbsIntExpr (hie1, &Expr); if (Expr.IVal <= 0) { if (D->Ident[0] != '\0') { Error ("Size of array '%s' is invalid", D->Ident); } else { Error ("Size of array is invalid"); } Expr.IVal = 1; } Size = Expr.IVal; } /* Skip the right bracket */ ConsumeRBrack (); /* Add the array type with the size to the type */ NeedTypeSpace (D, 1); D->Type[D->Index].C = T_ARRAY; D->Type[D->Index].A.L = Size; ++D->Index; } } /* If we have remaining qualifiers, flag them as invalid */ if (Qualifiers & T_QUAL_NEAR) { Error ("Invalid '__near__' qualifier"); } if (Qualifiers & T_QUAL_FAR) { Error ("Invalid '__far__' qualifier"); } if (Qualifiers & T_QUAL_FASTCALL) { Error ("Invalid '__fastcall__' qualifier"); } if (Qualifiers & T_QUAL_CDECL) { Error ("Invalid '__cdecl__' qualifier"); } } /*****************************************************************************/ /* code */ /*****************************************************************************/ Type* ParseType (Type* T) /* Parse a complete type specification */ { DeclSpec Spec; Declaration Decl; /* Get a type without a default */ InitDeclSpec (&Spec); ParseTypeSpec (&Spec, -1, T_QUAL_NONE); /* Parse additional declarators */ ParseDecl (&Spec, &Decl, DM_NO_IDENT); /* Copy the type to the target buffer */ TypeCopy (T, Decl.Type); /* Return a pointer to the target buffer */ return T; } void ParseDecl (const DeclSpec* Spec, Declaration* D, declmode_t Mode) /* Parse a variable, type or function declaration */ { /* Initialize the Declaration struct */ InitDeclaration (D); /* Get additional declarators and the identifier */ Declarator (Spec, D, Mode); /* Add the base type. */ NeedTypeSpace (D, TypeLen (Spec->Type) + 1); /* Bounds check */ TypeCopy (D->Type + D->Index, Spec->Type); /* Use the storage class from the declspec */ D->StorageClass = Spec->StorageClass; /* Do several fixes on qualifiers */ FixQualifiers (D->Type); /* If we have a function, add a special storage class */ if (IsTypeFunc (D->Type)) { D->StorageClass |= SC_FUNC; } /* Parse attributes for this declaration */ ParseAttribute (D); /* Check several things for function or function pointer types */ if (IsTypeFunc (D->Type) || IsTypeFuncPtr (D->Type)) { /* A function. Check the return type */ Type* RetType = GetFuncReturn (D->Type); /* Functions may not return functions or arrays */ if (IsTypeFunc (RetType)) { Error ("Functions are not allowed to return functions"); } else if (IsTypeArray (RetType)) { Error ("Functions are not allowed to return arrays"); } /* The return type must not be qualified */ if (GetQualifier (RetType) != T_QUAL_NONE && RetType[1].C == T_END) { if (GetType (RetType) == T_TYPE_VOID) { /* A qualified void type is always an error */ Error ("function definition has qualified void return type"); } else { /* For others, qualifiers are ignored */ Warning ("type qualifiers ignored on function return type"); RetType[0].C = UnqualifiedType (RetType[0].C); } } /* Warn about an implicit int return in the function */ if ((Spec->Flags & DS_DEF_TYPE) != 0 && RetType[0].C == T_INT && RetType[1].C == T_END) { /* Function has an implicit int return. Output a warning if we don't ** have the C89 standard enabled explicitly. */ if (IS_Get (&Standard) >= STD_C99) { Warning ("Implicit 'int' return type is an obsolete feature"); } GetFuncDesc (D->Type)->Flags |= FD_OLDSTYLE_INTRET; } } /* For anthing that is not a function or typedef, check for an implicit ** int declaration. */ if ((D->StorageClass & SC_FUNC) != SC_FUNC && (D->StorageClass & SC_TYPEMASK) != SC_TYPEDEF) { /* If the standard was not set explicitly to C89, print a warning ** for variables with implicit int type. */ if ((Spec->Flags & DS_DEF_TYPE) != 0 && IS_Get (&Standard) >= STD_C99) { Warning ("Implicit 'int' is an obsolete feature"); } } /* Check the size of the generated type */ if (!IsTypeFunc (D->Type) && !IsTypeVoid (D->Type)) { unsigned Size = SizeOf (D->Type); if (Size >= 0x10000) { if (D->Ident[0] != '\0') { Error ("Size of '%s' is invalid (0x%06X)", D->Ident, Size); } else { Error ("Invalid size in declaration (0x%06X)", Size); } } } } void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, long DefType) /* Parse a declaration specification */ { TypeCode Qualifiers; /* Initialize the DeclSpec struct */ InitDeclSpec (D); /* There may be qualifiers *before* the storage class specifier */ Qualifiers = OptionalQualifiers (T_QUAL_CONST | T_QUAL_VOLATILE); /* Now get the storage class specifier for this declaration */ ParseStorageClass (D, DefStorage); /* Parse the type specifiers passing any initial type qualifiers */ ParseTypeSpec (D, DefType, Qualifiers); } void CheckEmptyDecl (const DeclSpec* D) /* Called after an empty type declaration (that is, a type declaration without ** a variable). Checks if the declaration does really make sense and issues a ** warning if not. */ { if ((D->Flags & DS_EXTRA_TYPE) == 0) { Warning ("Useless declaration"); } } static void SkipInitializer (unsigned BracesExpected) /* Skip the remainder of an initializer in case of errors. Try to be somewhat ** smart so we don't have too many following errors. */ { while (CurTok.Tok != TOK_CEOF && CurTok.Tok != TOK_SEMI && BracesExpected > 0) { switch (CurTok.Tok) { case TOK_RCURLY: --BracesExpected; break; case TOK_LCURLY: ++BracesExpected; break; default: break; } NextToken (); } } static unsigned OpeningCurlyBraces (unsigned BracesNeeded) /* Accept any number of opening curly braces around an initialization, skip ** them and return the number. If the number of curly braces is less than ** BracesNeeded, issue a warning. */ { unsigned BraceCount = 0; while (CurTok.Tok == TOK_LCURLY) { ++BraceCount; NextToken (); } if (BraceCount < BracesNeeded) { Error ("'{' expected"); } return BraceCount; } static void ClosingCurlyBraces (unsigned BracesExpected) /* Accept and skip the given number of closing curly braces together with ** an optional comma. Output an error messages, if the input does not contain ** the expected number of braces. */ { while (BracesExpected) { if (CurTok.Tok == TOK_RCURLY) { NextToken (); } else if (CurTok.Tok == TOK_COMMA && NextTok.Tok == TOK_RCURLY) { NextToken (); NextToken (); } else { Error ("'}' expected"); return; } --BracesExpected; } } static void DefineData (ExprDesc* Expr) /* Output a data definition for the given expression */ { switch (ED_GetLoc (Expr)) { case E_LOC_ABS: /* Absolute: numeric address or const */ g_defdata (TypeOf (Expr->Type) | CF_CONST, Expr->IVal, 0); break; case E_LOC_GLOBAL: /* Global variable */ g_defdata (CF_EXTERNAL, Expr->Name, Expr->IVal); break; case E_LOC_STATIC: case E_LOC_LITERAL: /* Static variable or literal in the literal pool */ g_defdata (CF_STATIC, Expr->Name, Expr->IVal); break; case E_LOC_REGISTER: /* Register variable. Taking the address is usually not ** allowed. */ if (IS_Get (&AllowRegVarAddr) == 0) { Error ("Cannot take the address of a register variable"); } g_defdata (CF_REGVAR, Expr->Name, Expr->IVal); break; case E_LOC_STACK: case E_LOC_PRIMARY: case E_LOC_EXPR: Error ("Non constant initializer"); break; default: Internal ("Unknown constant type: 0x%04X", ED_GetLoc (Expr)); } } static void OutputBitFieldData (StructInitData* SI) /* Output bit field data */ { /* Ignore if we have no data */ if (SI->ValBits > 0) { /* Output the data */ g_defdata (CF_INT | CF_UNSIGNED | CF_CONST, SI->BitVal, 0); /* Clear the data from SI and account for the size */ SI->BitVal = 0; SI->ValBits = 0; SI->Offs += SIZEOF_INT; } } static void ParseScalarInitInternal (Type* T, ExprDesc* ED) /* Parse initializaton for scalar data types. This function will not output the ** data but return it in ED. */ { /* Optional opening brace */ unsigned BraceCount = OpeningCurlyBraces (0); /* We warn if an initializer for a scalar contains braces, because this is ** quite unusual and often a sign for some problem in the input. */ if (BraceCount > 0) { Warning ("Braces around scalar initializer"); } /* Get the expression and convert it to the target type */ ConstExpr (hie1, ED); TypeConversion (ED, T); /* Close eventually opening braces */ ClosingCurlyBraces (BraceCount); } static unsigned ParseScalarInit (Type* T) /* Parse initializaton for scalar data types. Return the number of data bytes. */ { ExprDesc ED; /* Parse initialization */ ParseScalarInitInternal (T, &ED); /* Output the data */ DefineData (&ED); /* Done */ return SizeOf (T); } static unsigned ParsePointerInit (Type* T) /* Parse initializaton for pointer data types. Return the number of data bytes. */ { /* Optional opening brace */ unsigned BraceCount = OpeningCurlyBraces (0); /* Expression */ ExprDesc ED; ConstExpr (hie1, &ED); TypeConversion (&ED, T); /* Output the data */ DefineData (&ED); /* Close eventually opening braces */ ClosingCurlyBraces (BraceCount); /* Done */ return SIZEOF_PTR; } static unsigned ParseArrayInit (Type* T, int AllowFlexibleMembers) /* Parse initializaton for arrays. Return the number of data bytes. */ { int Count; /* Get the array data */ Type* ElementType = GetElementType (T); unsigned ElementSize = CheckedSizeOf (ElementType); long ElementCount = GetElementCount (T); /* Special handling for a character array initialized by a literal */ if (IsTypeChar (ElementType) && (CurTok.Tok == TOK_SCONST || CurTok.Tok == TOK_WCSCONST || (CurTok.Tok == TOK_LCURLY && (NextTok.Tok == TOK_SCONST || NextTok.Tok == TOK_WCSCONST)))) { /* Char array initialized by string constant */ int NeedParen; /* If we initializer is enclosed in brackets, remember this fact and ** skip the opening bracket. */ NeedParen = (CurTok.Tok == TOK_LCURLY); if (NeedParen) { NextToken (); } /* Translate into target charset */ TranslateLiteral (CurTok.SVal); /* If the array is one too small for the string literal, omit the ** trailing zero. */ Count = GetLiteralSize (CurTok.SVal); if (ElementCount != UNSPECIFIED && ElementCount != FLEXIBLE && Count == ElementCount + 1) { /* Omit the trailing zero */ --Count; } /* Output the data */ g_defbytes (GetLiteralStr (CurTok.SVal), Count); /* Skip the string */ NextToken (); /* If the initializer was enclosed in curly braces, we need a closing ** one. */ if (NeedParen) { ConsumeRCurly (); } } else { /* Curly brace */ ConsumeLCurly (); /* Initialize the array members */ Count = 0; while (CurTok.Tok != TOK_RCURLY) { /* Flexible array members may not be initialized within ** an array (because the size of each element may differ ** otherwise). */ ParseInitInternal (ElementType, 0); ++Count; if (CurTok.Tok != TOK_COMMA) break; NextToken (); } /* Closing curly braces */ ConsumeRCurly (); } if (ElementCount == UNSPECIFIED) { /* Number of elements determined by initializer */ SetElementCount (T, Count); ElementCount = Count; } else if (ElementCount == FLEXIBLE && AllowFlexibleMembers) { /* In non ANSI mode, allow initialization of flexible array ** members. */ ElementCount = Count; } else if (Count < ElementCount) { g_zerobytes ((ElementCount - Count) * ElementSize); } else if (Count > ElementCount) { Error ("Too many initializers"); } return ElementCount * ElementSize; } static unsigned ParseStructInit (Type* T, int AllowFlexibleMembers) /* Parse initialization of a struct or union. Return the number of data bytes. */ { SymEntry* Entry; SymTable* Tab; StructInitData SI; /* Consume the opening curly brace */ ConsumeLCurly (); /* Get a pointer to the struct entry from the type */ Entry = GetSymEntry (T); /* Get the size of the struct from the symbol table entry */ SI.Size = Entry->V.S.Size; /* Check if this struct definition has a field table. If it doesn't, it ** is an incomplete definition. */ Tab = Entry->V.S.SymTab; if (Tab == 0) { Error ("Cannot initialize variables with incomplete type"); /* Try error recovery */ SkipInitializer (1); /* Nothing initialized */ return 0; } /* Get a pointer to the list of symbols */ Entry = Tab->SymHead; /* Initialize fields */ SI.Offs = 0; SI.BitVal = 0; SI.ValBits = 0; while (CurTok.Tok != TOK_RCURLY) { /* */ if (Entry == 0) { Error ("Too many initializers"); SkipInitializer (1); return SI.Offs; } /* Parse initialization of one field. Bit-fields need a special ** handling. */ if (SymIsBitField (Entry)) { ExprDesc ED; unsigned Val; unsigned Shift; /* Calculate the bitmask from the bit-field data */ unsigned Mask = (1U << Entry->V.B.BitWidth) - 1U; /* Safety ... */ CHECK (Entry->V.B.Offs * CHAR_BITS + Entry->V.B.BitOffs == SI.Offs * CHAR_BITS + SI.ValBits); /* This may be an anonymous bit-field, in which case it doesn't ** have an initializer. */ if (IsAnonName (Entry->Name)) { /* Account for the data and output it if we have a full word */ SI.ValBits += Entry->V.B.BitWidth; CHECK (SI.ValBits <= INT_BITS); if (SI.ValBits == INT_BITS) { OutputBitFieldData (&SI); } goto NextMember; } else { /* Read the data, check for a constant integer, do a range ** check. */ ParseScalarInitInternal (type_uint, &ED); if (!ED_IsConstAbsInt (&ED)) { Error ("Constant initializer expected"); ED_MakeConstAbsInt (&ED, 1); } if (ED.IVal > (long) Mask) { Warning ("Truncating value in bit-field initializer"); ED.IVal &= (long) Mask; } Val = (unsigned) ED.IVal; } /* Add the value to the currently stored bit-field value */ Shift = (Entry->V.B.Offs - SI.Offs) * CHAR_BITS + Entry->V.B.BitOffs; SI.BitVal |= (Val << Shift); /* Account for the data and output it if we have a full word */ SI.ValBits += Entry->V.B.BitWidth; CHECK (SI.ValBits <= INT_BITS); if (SI.ValBits == INT_BITS) { OutputBitFieldData (&SI); } } else { /* Standard member. We should never have stuff from a ** bit-field left */ CHECK (SI.ValBits == 0); /* Flexible array members may only be initialized if they are ** the last field (or part of the last struct field). */ SI.Offs += ParseInitInternal (Entry->Type, AllowFlexibleMembers && Entry->NextSym == 0); } /* More initializers? */ if (CurTok.Tok != TOK_COMMA) { break; } /* Skip the comma */ NextToken (); NextMember: /* Next member. For unions, only the first one can be initialized */ if (IsTypeUnion (T)) { /* Union */ Entry = 0; } else { /* Struct */ Entry = Entry->NextSym; } } /* Consume the closing curly brace */ ConsumeRCurly (); /* If we have data from a bit-field left, output it now */ OutputBitFieldData (&SI); /* If there are struct fields left, reserve additional storage */ if (SI.Offs < SI.Size) { g_zerobytes (SI.Size - SI.Offs); SI.Offs = SI.Size; } /* Return the actual number of bytes initialized. This number may be ** larger than sizeof (Struct) if flexible array members are present and ** were initialized (possible in non ANSI mode). */ return SI.Offs; } static unsigned ParseVoidInit (Type* T) /* Parse an initialization of a void variable (special cc65 extension). ** Return the number of bytes initialized. */ { ExprDesc Expr; unsigned Size; /* Opening brace */ ConsumeLCurly (); /* Allow an arbitrary list of values */ Size = 0; do { ConstExpr (hie1, &Expr); switch (UnqualifiedType (Expr.Type[0].C)) { case T_SCHAR: case T_UCHAR: if (ED_IsConstAbsInt (&Expr)) { /* Make it byte sized */ Expr.IVal &= 0xFF; } DefineData (&Expr); Size += SIZEOF_CHAR; break; case T_SHORT: case T_USHORT: case T_INT: case T_UINT: case T_PTR: case T_ARRAY: if (ED_IsConstAbsInt (&Expr)) { /* Make it word sized */ Expr.IVal &= 0xFFFF; } DefineData (&Expr); Size += SIZEOF_INT; break; case T_LONG: case T_ULONG: if (ED_IsConstAbsInt (&Expr)) { /* Make it dword sized */ Expr.IVal &= 0xFFFFFFFF; } DefineData (&Expr); Size += SIZEOF_LONG; break; default: Error ("Illegal type in initialization"); break; } if (CurTok.Tok != TOK_COMMA) { break; } NextToken (); } while (CurTok.Tok != TOK_RCURLY); /* Closing brace */ ConsumeRCurly (); /* Number of bytes determined by initializer */ T->A.U = Size; /* Return the number of bytes initialized */ return Size; } static unsigned ParseInitInternal (Type* T, int AllowFlexibleMembers) /* Parse initialization of variables. Return the number of data bytes. */ { switch (UnqualifiedType (T->C)) { case T_SCHAR: case T_UCHAR: case T_SHORT: case T_USHORT: case T_INT: case T_UINT: case T_LONG: case T_ULONG: case T_FLOAT: case T_DOUBLE: return ParseScalarInit (T); case T_PTR: return ParsePointerInit (T); case T_ARRAY: return ParseArrayInit (T, AllowFlexibleMembers); case T_STRUCT: case T_UNION: return ParseStructInit (T, AllowFlexibleMembers); case T_VOID: if (IS_Get (&Standard) == STD_CC65) { /* Special cc65 extension in non-ANSI mode */ return ParseVoidInit (T); } /* FALLTHROUGH */ default: Error ("Illegal type"); return SIZEOF_CHAR; } } unsigned ParseInit (Type* T) /* Parse initialization of variables. Return the number of data bytes. */ { /* Parse the initialization. Flexible array members can only be initialized ** in cc65 mode. */ unsigned Size = ParseInitInternal (T, IS_Get (&Standard) == STD_CC65); /* The initialization may not generate code on global level, because code ** outside function scope will never get executed. */ if (HaveGlobalCode ()) { Error ("Non constant initializers"); RemoveGlobalCode (); } /* Return the size needed for the initialization */ return Size; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/declare.h������������������������������������������������������������������������0000664�0000000�0000000�00000012053�13473601511�0015305�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* declare.h */ /* */ /* Parse variable and function declarations */ /* */ /* */ /* */ /* (C) 1998-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef DECLARE_H #define DECLARE_H /* common */ #include "coll.h" /* cc65 */ #include "scanner.h" #include "symtab.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Masks for the Flags field in DeclSpec */ #define DS_DEF_STORAGE 0x0001U /* Default storage class used */ #define DS_DEF_TYPE 0x0002U /* Default type used */ #define DS_EXTRA_TYPE 0x0004U /* Extra type declared */ /* Result of ParseDeclSpec */ typedef struct DeclSpec DeclSpec; struct DeclSpec { unsigned StorageClass; /* One of the SC_xxx flags */ Type Type[MAXTYPELEN]; /* Type of the declaration spec */ unsigned Flags; /* Bitmapped flags */ }; /* Result of ParseDecl */ typedef struct Declaration Declaration; struct Declaration { unsigned StorageClass; /* A set of SC_xxx flags */ Type Type[MAXTYPELEN]; /* The type */ ident Ident; /* The identifier, if any*/ Collection* Attributes; /* Attributes if any */ /* Working variables */ unsigned Index; /* Used to build Type */ }; /* Modes for ParseDecl */ typedef enum { DM_NEED_IDENT, /* We must have an identifier */ DM_NO_IDENT, /* We won't read an identifier */ DM_ACCEPT_IDENT, /* We will accept an id if there is one */ } declmode_t; /*****************************************************************************/ /* Code */ /*****************************************************************************/ Type* ParseType (Type* Type); /* Parse a complete type specification */ void ParseDecl (const DeclSpec* Spec, Declaration* D, declmode_t Mode); /* Parse a variable, type or function declaration */ void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, long DefType); /* Parse a declaration specification */ void CheckEmptyDecl (const DeclSpec* D); /* Called after an empty type declaration (that is, a type declaration without ** a variable). Checks if the declaration does really make sense and issues a ** warning if not. */ unsigned ParseInit (Type* T); /* Parse initialization of variables. Return the number of initialized data ** bytes. */ /* End of declare.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/declattr.c�����������������������������������������������������������������������0000664�0000000�0000000�00000017035�13473601511�0015510�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* declattr.c */ /* */ /* Declaration attributes */ /* */ /* */ /* */ /* (C) 1998-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* common */ #include "xmalloc.h" /* cc65 */ #include "declare.h" #include "declattr.h" #include "error.h" #include "scanner.h" #include "symtab.h" #include "typecmp.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Forwards for attribute handlers */ static void NoReturnAttr (Declaration* D); static void UnusedAttr (Declaration* D); /* Attribute table */ typedef struct AttrDesc AttrDesc; struct AttrDesc { const char Name[15]; void (*Handler) (Declaration*); }; static const AttrDesc AttrTable [] = { { "__noreturn__", NoReturnAttr }, { "__unused__", UnusedAttr }, { "noreturn", NoReturnAttr }, { "unused", UnusedAttr }, }; /*****************************************************************************/ /* Struct DeclAttr */ /*****************************************************************************/ static DeclAttr* NewDeclAttr (DeclAttrType AttrType) /* Create a new DeclAttr struct and return it */ { /* Allocate memory */ DeclAttr* A = xmalloc (sizeof (DeclAttr)); /* Initialize the fields */ A->AttrType = AttrType; /* Return the new struct */ return A; } /*****************************************************************************/ /* Helper functions */ /*****************************************************************************/ static const AttrDesc* FindAttribute (const char* Attr) /* Search the attribute and return the corresponding attribute descriptor. ** Return NULL if the attribute name is not known. */ { unsigned A; /* For now do a linear search */ for (A = 0; A < sizeof (AttrTable) / sizeof (AttrTable[0]); ++A) { if (strcmp (Attr, AttrTable[A].Name) == 0) { /* Found */ return AttrTable + A; } } /* Not found */ return 0; } static void ErrorSkip (void) { /* List of tokens to skip */ static const token_t SkipList[] = { TOK_RPAREN, TOK_SEMI }; /* Skip until closing brace or semicolon */ SkipTokens (SkipList, sizeof (SkipList) / sizeof (SkipList[0])); /* If we have a closing brace, read it, otherwise bail out */ if (CurTok.Tok == TOK_RPAREN) { /* Read the two closing braces */ ConsumeRParen (); ConsumeRParen (); } } static void AddAttr (Declaration* D, DeclAttr* A) /* Add an attribute to a declaration */ { /* Allocate the list if necessary, the add the attribute */ if (D->Attributes == 0) { D->Attributes = NewCollection (); } CollAppend (D->Attributes, A); } /*****************************************************************************/ /* Attribute handling code */ /*****************************************************************************/ static void NoReturnAttr (Declaration* D) /* Parse the "noreturn" attribute */ { /* Add the noreturn attribute */ AddAttr (D, NewDeclAttr (atNoReturn)); } static void UnusedAttr (Declaration* D) /* Parse the "unused" attribute */ { /* Add the noreturn attribute */ AddAttr (D, NewDeclAttr (atUnused)); } void ParseAttribute (Declaration* D) /* Parse an additional __attribute__ modifier */ { /* Do we have an attribute? */ if (CurTok.Tok != TOK_ATTRIBUTE) { /* No attribute, bail out */ return; } /* Skip the attribute token */ NextToken (); /* Expect two(!) open braces */ ConsumeLParen (); ConsumeLParen (); /* Read a list of attributes */ while (1) { ident AttrName; const AttrDesc* Attr = 0; /* Identifier follows */ if (CurTok.Tok != TOK_IDENT) { /* No attribute name */ Error ("Attribute name expected"); /* Skip until end of attribute */ ErrorSkip (); /* Bail out */ return; } /* Map the attribute name to its id, then skip the identifier */ strcpy (AttrName, CurTok.Ident); Attr = FindAttribute (AttrName); NextToken (); /* Did we find a valid attribute? */ if (Attr) { /* Call the handler */ Attr->Handler (D); } else { /* Attribute not known, maybe typo */ Error ("Illegal attribute: '%s'", AttrName); /* Skip until end of attribute */ ErrorSkip (); /* Bail out */ return; } /* If a comma follows, there's a next attribute. Otherwise this is the ** end of the attribute list. */ if (CurTok.Tok != TOK_COMMA) { break; } NextToken (); } /* The declaration is terminated with two closing braces */ ConsumeRParen (); ConsumeRParen (); } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/declattr.h�����������������������������������������������������������������������0000664�0000000�0000000�00000007041�13473601511�0015511�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* declattr.h */ /* */ /* Declaration attributes */ /* */ /* */ /* */ /* (C) 1998-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef DECLATTR_H #define DECLATTR_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Forward */ struct Declaration; /* Supported attribute types */ typedef enum { atNoReturn, /* Function does not return */ atUnused, /* Symbol is unused - don't warn */ } DeclAttrType; /* An actual attribute description */ typedef struct DeclAttr DeclAttr; struct DeclAttr { DeclAttrType AttrType; /* Type of attribute */ }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void ParseAttribute (struct Declaration* D); /* Parse an additional __attribute__ modifier */ /* End of declattr.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/error.c��������������������������������������������������������������������������0000664�0000000�0000000�00000024347�13473601511�0015043�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* error.c */ /* */ /* Error handling for the cc65 C compiler */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> /* common */ #include "print.h" /* cc65 */ #include "global.h" #include "input.h" #include "lineinfo.h" #include "scanner.h" #include "stmt.h" #include "error.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Count of errors/warnings */ unsigned ErrorCount = 0; unsigned WarningCount = 0; /* Warning and error options */ IntStack WarnEnable = INTSTACK(1); /* Enable warnings */ IntStack WarningsAreErrors = INTSTACK(0); /* Treat warnings as errors */ /* Warn about: */ IntStack WarnConstComparison= INTSTACK(1); /* - constant comparison results */ IntStack WarnNoEffect = INTSTACK(1); /* - statements without an effect */ IntStack WarnRemapZero = INTSTACK(1); /* - remapping character code zero */ IntStack WarnStructParam = INTSTACK(1); /* - structs passed by val */ IntStack WarnUnknownPragma = INTSTACK(1); /* - unknown #pragmas */ IntStack WarnUnusedLabel = INTSTACK(1); /* - unused labels */ IntStack WarnUnusedParam = INTSTACK(1); /* - unused parameters */ IntStack WarnUnusedVar = INTSTACK(1); /* - unused variables */ /* Map the name of a warning to the intstack that holds its state */ typedef struct WarnMapEntry WarnMapEntry; struct WarnMapEntry { IntStack* Stack; const char* Name; }; static WarnMapEntry WarnMap[] = { /* Keep names sorted, even if it isn't used for now */ { &WarnConstComparison, "const-comparison" }, { &WarningsAreErrors, "error" }, { &WarnNoEffect, "no-effect" }, { &WarnRemapZero, "remap-zero" }, { &WarnStructParam, "struct-param" }, { &WarnUnknownPragma, "unknown-pragma" }, { &WarnUnusedLabel, "unused-label" }, { &WarnUnusedParam, "unused-param" }, { &WarnUnusedVar, "unused-var" }, }; /*****************************************************************************/ /* Handling of fatal errors */ /*****************************************************************************/ void Fatal (const char* Format, ...) /* Print a message about a fatal error and die */ { va_list ap; const char* FileName; unsigned LineNum; if (CurTok.LI) { FileName = GetInputName (CurTok.LI); LineNum = GetInputLine (CurTok.LI); } else { FileName = GetCurrentFile (); LineNum = GetCurrentLine (); } fprintf (stderr, "%s(%u): Fatal: ", FileName, LineNum); va_start (ap, Format); vfprintf (stderr, Format, ap); va_end (ap); fprintf (stderr, "\n"); if (Line) { Print (stderr, 1, "Input: %.*s\n", (int) SB_GetLen (Line), SB_GetConstBuf (Line)); } exit (EXIT_FAILURE); } void Internal (const char* Format, ...) /* Print a message about an internal compiler error and die. */ { va_list ap; const char* FileName; unsigned LineNum; if (CurTok.LI) { FileName = GetInputName (CurTok.LI); LineNum = GetInputLine (CurTok.LI); } else { FileName = GetCurrentFile (); LineNum = GetCurrentLine (); } fprintf (stderr, "%s(%u): Internal compiler error:\n", FileName, LineNum); va_start (ap, Format); vfprintf (stderr, Format, ap); va_end (ap); fprintf (stderr, "\n"); if (Line) { fprintf (stderr, "\nInput: %.*s\n", (int) SB_GetLen (Line), SB_GetConstBuf (Line)); } /* Use abort to create a core dump */ abort (); } /*****************************************************************************/ /* Handling of errors */ /*****************************************************************************/ static void IntError (const char* Filename, unsigned LineNo, const char* Msg, va_list ap) /* Print an error message - internal function*/ { fprintf (stderr, "%s(%u): Error: ", Filename, LineNo); vfprintf (stderr, Msg, ap); fprintf (stderr, "\n"); if (Line) { Print (stderr, 1, "Input: %.*s\n", (int) SB_GetLen (Line), SB_GetConstBuf (Line)); } ++ErrorCount; if (ErrorCount > 10) { Fatal ("Too many errors"); } } void Error (const char* Format, ...) /* Print an error message */ { va_list ap; va_start (ap, Format); IntError (GetInputName (CurTok.LI), GetInputLine (CurTok.LI), Format, ap); va_end (ap); } void LIError (const LineInfo* LI, const char* Format, ...) /* Print an error message with the line info given explicitly */ { va_list ap; va_start (ap, Format); IntError (GetInputName (LI), GetInputLine (LI), Format, ap); va_end (ap); } void PPError (const char* Format, ...) /* Print an error message. For use within the preprocessor. */ { va_list ap; va_start (ap, Format); IntError (GetCurrentFile(), GetCurrentLine(), Format, ap); va_end (ap); } /*****************************************************************************/ /* Handling of warnings */ /*****************************************************************************/ static void IntWarning (const char* Filename, unsigned LineNo, const char* Msg, va_list ap) /* Print warning message - internal function. */ { if (IS_Get (&WarningsAreErrors)) { /* Treat the warning as an error */ IntError (Filename, LineNo, Msg, ap); } else if (IS_Get (&WarnEnable)) { fprintf (stderr, "%s(%u): Warning: ", Filename, LineNo); vfprintf (stderr, Msg, ap); fprintf (stderr, "\n"); if (Line) { Print (stderr, 1, "Input: %.*s\n", (int) SB_GetLen (Line), SB_GetConstBuf (Line)); } ++WarningCount; } } void Warning (const char* Format, ...) /* Print warning message. */ { va_list ap; va_start (ap, Format); IntWarning (GetInputName (CurTok.LI), GetInputLine (CurTok.LI), Format, ap); va_end (ap); } void LIWarning (const LineInfo* LI, const char* Format, ...) /* Print a warning message with the line info given explicitly */ { va_list ap; va_start (ap, Format); IntWarning (GetInputName (LI), GetInputLine (LI), Format, ap); va_end (ap); } void PPWarning (const char* Format, ...) /* Print warning message. For use within the preprocessor. */ { va_list ap; va_start (ap, Format); IntWarning (GetCurrentFile(), GetCurrentLine(), Format, ap); va_end (ap); } IntStack* FindWarning (const char* Name) /* Search for a warning in the WarnMap table and return a pointer to the ** intstack that holds its state. Return NULL if there is no such warning. */ { unsigned I; /* For now, do a linear search */ for (I = 0; I < sizeof(WarnMap) / sizeof (WarnMap[0]); ++I) { if (strcmp (WarnMap[I].Name, Name) == 0) { return WarnMap[I].Stack; } } return 0; } void ListWarnings (FILE* F) /* Print a list of warning types/names to the given file */ { unsigned I; for (I = 0; I < sizeof(WarnMap) / sizeof (WarnMap[0]); ++I) { fprintf (F, "%s\n", WarnMap[I].Name); } } /*****************************************************************************/ /* Code */ /*****************************************************************************/ void ErrorReport (void) /* Report errors (called at end of compile) */ { Print (stdout, 1, "%u errors, %u warnings\n", ErrorCount, WarningCount); } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/error.h��������������������������������������������������������������������������0000664�0000000�0000000�00000012675�13473601511�0015051�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* error.h */ /* */ /* Error handling for the cc65 C compiler */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef ERROR_H #define ERROR_H #include <stdio.h> /* common */ #include "attrib.h" #include "intstack.h" /* cc65 */ #include "lineinfo.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Count of errors/warnings */ extern unsigned ErrorCount; extern unsigned WarningCount; /* Warning and error options */ extern IntStack WarnEnable; /* Enable warnings */ extern IntStack WarningsAreErrors; /* Treat warnings as errors */ /* Warn about: */ extern IntStack WarnConstComparison; /* - constant comparison results */ extern IntStack WarnNoEffect; /* - statements without an effect */ extern IntStack WarnRemapZero; /* - remapping character code zero */ extern IntStack WarnStructParam; /* - structs passed by val */ extern IntStack WarnUnknownPragma; /* - unknown #pragmas */ extern IntStack WarnUnusedLabel; /* - unused labels */ extern IntStack WarnUnusedParam; /* - unused parameters */ extern IntStack WarnUnusedVar; /* - unused variables */ /*****************************************************************************/ /* code */ /*****************************************************************************/ void Fatal (const char* Format, ...) attribute ((noreturn, format (printf, 1, 2))); /* Print a message about a fatal error and die */ void Internal (const char* Format, ...) attribute ((noreturn, format (printf, 1, 2))); /* Print a message about an internal compiler error and die. */ void Error (const char* Format, ...) attribute ((format (printf, 1, 2))); /* Print an error message */ void LIError (const LineInfo* LI, const char* Format, ...) attribute ((format (printf, 2, 3))); /* Print an error message with the line info given explicitly */ void PPError (const char* Format, ...) attribute ((format (printf, 1, 2))); /* Print an error message. For use within the preprocessor. */ void Warning (const char* Format, ...) attribute ((format (printf, 1, 2))); /* Print warning message. */ void LIWarning (const LineInfo* LI, const char* Format, ...) attribute ((format (printf, 2, 3))); /* Print a warning message with the line info given explicitly */ void PPWarning (const char* Format, ...) attribute ((format (printf, 1, 2))); /* Print warning message. For use within the preprocessor. */ IntStack* FindWarning (const char* Name); /* Search for a warning in the WarnMap table and return a pointer to the ** intstack that holds its state. Return NULL if there is no such warning. */ void ListWarnings (FILE* F); /* Print a list of warning types/names to the given file */ void ErrorReport (void); /* Report errors (called at end of compile) */ /* End of error.h */ #endif �������������������������������������������������������������������cc65-2.18/src/cc65/expr.c���������������������������������������������������������������������������0000664�0000000�0000000�00000356657�13473601511�0014704�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* expr.c ** ** 1998-06-21, Ullrich von Bassewitz ** 2017-12-05, Greg King */ #include <stdio.h> #include <stdlib.h> /* common */ #include "check.h" #include "debugflag.h" #include "xmalloc.h" /* cc65 */ #include "asmcode.h" #include "asmlabel.h" #include "asmstmt.h" #include "assignment.h" #include "codegen.h" #include "declare.h" #include "error.h" #include "funcdesc.h" #include "function.h" #include "global.h" #include "litpool.h" #include "loadexpr.h" #include "macrotab.h" #include "preproc.h" #include "scanner.h" #include "shiftexpr.h" #include "stackptr.h" #include "standard.h" #include "stdfunc.h" #include "symtab.h" #include "typecmp.h" #include "typeconv.h" #include "expr.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* 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 { token_t Tok; /* Token to map to */ unsigned Flags; /* Flags for generator function */ void (*Func) (unsigned, unsigned long); /* Generator func */ } GenDesc; /* Descriptors for the operations */ static GenDesc GenPASGN = { TOK_PLUS_ASSIGN, GEN_NOPUSH, g_add }; static GenDesc GenSASGN = { TOK_MINUS_ASSIGN, GEN_NOPUSH, g_sub }; static GenDesc GenMASGN = { TOK_MUL_ASSIGN, GEN_NOPUSH, g_mul }; static GenDesc GenDASGN = { TOK_DIV_ASSIGN, GEN_NOPUSH, g_div }; static GenDesc GenMOASGN = { TOK_MOD_ASSIGN, GEN_NOPUSH, g_mod }; static GenDesc GenSLASGN = { TOK_SHL_ASSIGN, GEN_NOPUSH, g_asl }; static GenDesc GenSRASGN = { TOK_SHR_ASSIGN, GEN_NOPUSH, g_asr }; static GenDesc GenAASGN = { TOK_AND_ASSIGN, GEN_NOPUSH, g_and }; static GenDesc GenXOASGN = { TOK_XOR_ASSIGN, GEN_NOPUSH, g_xor }; static GenDesc GenOASGN = { TOK_OR_ASSIGN, GEN_NOPUSH, g_or }; /*****************************************************************************/ /* Helper functions */ /*****************************************************************************/ static unsigned GlobalModeFlags (const ExprDesc* Expr) /* Return the addressing mode flags for the given expression */ { switch (ED_GetLoc (Expr)) { case E_LOC_ABS: return CF_ABSOLUTE; case E_LOC_GLOBAL: return CF_EXTERNAL; case E_LOC_STATIC: return CF_STATIC; case E_LOC_REGISTER: return CF_REGVAR; case E_LOC_STACK: return CF_NONE; case E_LOC_PRIMARY: return CF_NONE; case E_LOC_EXPR: return CF_NONE; case E_LOC_LITERAL: return CF_STATIC; /* Same as static */ default: Internal ("GlobalModeFlags: Invalid location flags value: 0x%04X", Expr->Flags); /* NOTREACHED */ return 0; } } void ExprWithCheck (void (*Func) (ExprDesc*), ExprDesc* Expr) /* Call an expression function with checks. */ { /* Remember the stack pointer */ int OldSP = StackPtr; /* Call the expression function */ (*Func) (Expr); /* Do some checks to see if code generation is still consistent */ if (StackPtr != OldSP) { if (Debug) { Error ("Code generation messed up: " "StackPtr is %d, should be %d", StackPtr, OldSP); } else { Internal ("Code generation messed up: " "StackPtr is %d, should be %d", StackPtr, OldSP); } } } void MarkedExprWithCheck (void (*Func) (ExprDesc*), ExprDesc* Expr) /* Call an expression function with checks and record start and end of the ** generated code. */ { CodeMark Start, End; GetCodePos (&Start); ExprWithCheck (Func, Expr); GetCodePos (&End); ED_SetCodeRange (Expr, &Start, &End); } static Type* promoteint (Type* lhst, Type* rhst) /* In an expression with two ints, return the type of the result */ { /* Rules for integer types: ** - If one of the values is a long, the result is long. ** - If one of the values is unsigned, the result is also unsigned. ** - Otherwise the result is an int. */ if (IsTypeLong (lhst) || IsTypeLong (rhst)) { if (IsSignUnsigned (lhst) || IsSignUnsigned (rhst)) { return type_ulong; } else { return type_long; } } else { if (IsSignUnsigned (lhst) || IsSignUnsigned (rhst)) { return type_uint; } else { return type_int; } } } static unsigned typeadjust (ExprDesc* lhs, ExprDesc* rhs, int NoPush) /* Adjust the two values for a binary operation. lhs is expected on stack or ** to be constant, rhs is expected to be in the primary register or constant. ** The function will put the type of the result into lhs and return the ** code generator flags for the operation. ** If NoPush is given, it is assumed that the operation does not expect the lhs ** to be on stack, and that lhs is in a register instead. ** Beware: The function does only accept int types. */ { unsigned ltype, rtype; unsigned flags; /* Get the type strings */ Type* lhst = lhs->Type; Type* rhst = rhs->Type; /* Generate type adjustment code if needed */ ltype = TypeOf (lhst); if (ED_IsLocAbs (lhs)) { ltype |= CF_CONST; } if (NoPush) { /* Value is in primary register*/ ltype |= CF_REG; } rtype = TypeOf (rhst); if (ED_IsLocAbs (rhs)) { rtype |= CF_CONST; } flags = g_typeadjust (ltype, rtype); /* Set the type of the result */ lhs->Type = promoteint (lhst, rhst); /* Return the code generator flags */ return flags; } static const GenDesc* FindGen (token_t Tok, const GenDesc* Table) /* Find a token in a generator table */ { while (Table->Tok != TOK_INVALID) { if (Table->Tok == Tok) { return Table; } ++Table; } return 0; } static int TypeSpecAhead (void) /* Return true if some sort of type is waiting (helper for cast and sizeof() ** in hie10). */ { SymEntry* Entry; /* There's a type waiting if: ** ** We have an opening paren, and ** a. the next token is a type, or ** b. the next token is a type qualifier, or ** c. the next token is a typedef'd type */ return CurTok.Tok == TOK_LPAREN && ( TokIsType (&NextTok) || TokIsTypeQual (&NextTok) || (NextTok.Tok == TOK_IDENT && (Entry = FindSym (NextTok.Ident)) != 0 && SymIsTypeDef (Entry))); } void PushAddr (const ExprDesc* Expr) /* If the expression contains an address that was somehow evaluated, ** push this address on the stack. This is a helper function for all ** sorts of implicit or explicit assignment functions where the lvalue ** must be saved if it's not constant, before evaluating the rhs. */ { /* Get the address on stack if needed */ if (ED_IsLocExpr (Expr)) { /* Push the address (always a pointer) */ g_push (CF_PTR, 0); } } static void WarnConstCompareResult (void) /* If the result of a comparison is constant, this is suspicious when not in ** preprocessor mode. */ { if (!Preprocessing && IS_Get (&WarnConstComparison) != 0) { Warning ("Result of comparison is constant"); } } /*****************************************************************************/ /* code */ /*****************************************************************************/ static unsigned FunctionParamList (FuncDesc* Func, int IsFastcall) /* Parse a function parameter list and pass the parameters to the called ** function. Depending on several criteria this may be done by just pushing ** each parameter separately, or creating the parameter frame once and then ** storing into this frame. ** The function returns the size of the parameters pushed. */ { ExprDesc Expr; /* Initialize variables */ SymEntry* Param = 0; /* Keep gcc silent */ unsigned ParamSize = 0; /* Size of parameters pushed */ unsigned ParamCount = 0; /* Number of parameters pushed */ unsigned FrameSize = 0; /* Size of parameter frame */ unsigned FrameParams = 0; /* Number of params in frame */ int FrameOffs = 0; /* Offset into parameter frame */ int Ellipsis = 0; /* Function is variadic */ /* As an optimization, we may allocate the complete parameter frame at ** once instead of pushing each parameter as it comes. We may do that, ** if... ** ** - optimizations that increase code size are enabled (allocating the ** stack frame at once gives usually larger code). ** - we have more than one parameter to push (don't count the last param ** for __fastcall__ functions). ** ** The FrameSize variable will contain a value > 0 if storing into a frame ** (instead of pushing) is enabled. ** */ if (IS_Get (&CodeSizeFactor) >= 200) { /* Calculate the number and size of the parameters */ FrameParams = Func->ParamCount; FrameSize = Func->ParamSize; if (FrameParams > 0 && IsFastcall) { /* Last parameter is not pushed */ FrameSize -= CheckedSizeOf (Func->LastParam->Type); --FrameParams; } /* Do we have more than one parameter in the frame? */ if (FrameParams > 1) { /* Okeydokey, setup the frame */ FrameOffs = StackPtr; g_space (FrameSize); StackPtr -= FrameSize; } else { /* Don't use a preallocated frame */ FrameSize = 0; } } /* Parse the actual parameter list */ while (CurTok.Tok != TOK_RPAREN) { unsigned Flags; /* Count arguments */ ++ParamCount; /* Fetch the pointer to the next argument, check for too many args */ if (ParamCount <= Func->ParamCount) { /* Beware: If there are parameters with identical names, they ** cannot go into the same symbol table, which means that in this ** case of errorneous input, the number of nodes in the symbol ** table and ParamCount are NOT equal. We have to handle this case ** below to avoid segmentation violations. Since we know that this ** problem can only occur if there is more than one parameter, ** we will just use the last one. */ if (ParamCount == 1) { /* First argument */ Param = Func->SymTab->SymHead; } else if (Param->NextSym != 0) { /* Next argument */ Param = Param->NextSym; CHECK ((Param->Flags & SC_PARAM) != 0); } } else if (!Ellipsis) { /* Too many arguments. Do we have an open param list? */ if ((Func->Flags & FD_VARIADIC) == 0) { /* End of param list reached, no ellipsis */ Error ("Too many arguments in function call"); } /* Assume an ellipsis even in case of errors to avoid an error ** message for each other argument. */ Ellipsis = 1; } /* Evaluate the parameter expression */ hie1 (&Expr); /* If we don't have an argument spec, accept anything, otherwise ** convert the actual argument to the type needed. */ Flags = CF_NONE; if (!Ellipsis) { /* Convert the argument to the parameter type if needed */ TypeConversion (&Expr, Param->Type); /* If we have a prototype, chars may be pushed as chars */ Flags |= CF_FORCECHAR; } else { /* No prototype available. Convert array to "pointer to first ** element", and function to "pointer to function". */ Expr.Type = PtrConversion (Expr.Type); } /* Load the value into the primary if it is not already there */ LoadExpr (Flags, &Expr); /* Use the type of the argument for the push */ Flags |= TypeOf (Expr.Type); /* If this is a fastcall function, don't push the last argument */ if (ParamCount != Func->ParamCount || !IsFastcall) { unsigned ArgSize = sizeofarg (Flags); if (FrameSize > 0) { /* We have the space already allocated, store in the frame. ** Because of invalid type conversions (that have produced an ** error before), we can end up here with a non-aligned stack ** frame. Since no output will be generated anyway, handle ** these cases gracefully instead of doing a CHECK. */ if (FrameSize >= ArgSize) { FrameSize -= ArgSize; } else { FrameSize = 0; } FrameOffs -= ArgSize; /* Store */ g_putlocal (Flags | CF_NOKEEP, FrameOffs, Expr.IVal); } else { /* Push the argument */ g_push (Flags, Expr.IVal); } /* Calculate total parameter size */ ParamSize += ArgSize; } /* Check for end of argument list */ if (CurTok.Tok != TOK_COMMA) { break; } NextToken (); } /* Check if we had enough parameters */ if (ParamCount < Func->ParamCount) { Error ("Too few arguments in function call"); } /* The function returns the size of all parameters pushed onto the stack. ** However, if there are parameters missing (which is an error and was ** flagged by the compiler) AND a stack frame was preallocated above, ** we would loose track of the stackpointer and generate an internal error ** later. So we correct the value by the parameters that should have been ** pushed to avoid an internal compiler error. Since an error was ** generated before, no code will be output anyway. */ return ParamSize + FrameSize; } static void FunctionCall (ExprDesc* Expr) /* Perform a function call. */ { FuncDesc* Func; /* Function descriptor */ int IsFuncPtr; /* Flag */ unsigned ParamSize; /* Number of parameter bytes */ CodeMark Mark; int PtrOffs = 0; /* Offset of function pointer on stack */ int IsFastcall = 0; /* True if it's a fast-call function */ int PtrOnStack = 0; /* True if a pointer copy is on stack */ /* Skip the left paren */ NextToken (); /* Get a pointer to the function descriptor from the type string */ Func = GetFuncDesc (Expr->Type); /* Handle function pointers transparently */ IsFuncPtr = IsTypeFuncPtr (Expr->Type); if (IsFuncPtr) { /* 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 ** (not a local or global variable), we have to evaluate this ** expression now and save the result for later. Since calls to ** function pointers may be nested, we must save it onto the stack. ** For fastcall functions we do also need to place a copy of the ** pointer on stack, since we cannot use a/x. */ PtrOnStack = IsFastcall || !ED_IsConst (Expr); if (PtrOnStack) { /* Not a global or local variable, or a fastcall function. Load ** the pointer into the primary and mark it as an expression. */ LoadExpr (CF_NONE, Expr); ED_MakeRValExpr (Expr); /* Remember the code position */ GetCodePos (&Mark); /* Push the pointer onto the stack and remember the offset */ g_push (CF_PTR, 0); PtrOffs = StackPtr; } } else { /* Check function attributes */ if (Expr->Sym && SymHasAttr (Expr->Sym, atNoReturn)) { /* For now, handle as if a return statement was encountered */ F_ReturnFound (CurrentFunc); } /* Check for known standard functions and inline them */ if (Expr->Name != 0) { int StdFunc = FindStdFunc ((const char*) Expr->Name); if (StdFunc >= 0) { /* Inline this function */ HandleStdFunc (StdFunc, Func, Expr); return; } } /* If we didn't inline the function, get fastcall info */ IsFastcall = (Func->Flags & FD_VARIADIC) == 0 && (AutoCDecl ? IsQualFastcall (Expr->Type) : !IsQualCDecl (Expr->Type)); } /* Parse the parameter list */ ParamSize = FunctionParamList (Func, IsFastcall); /* We need the closing paren here */ ConsumeRParen (); /* Special handling for function pointers */ if (IsFuncPtr) { if (Func->WrappedCall) { Warning ("Calling a wrapped function via a pointer, wrapped-call will not be used"); } /* If the function is not a fastcall function, load the pointer to ** the function into the primary. */ if (!IsFastcall) { /* Not a fastcall function - we may use the primary */ if (PtrOnStack) { /* If we have no parameters, the pointer is still in the ** primary. Remove the code to push it and correct the ** stack pointer. */ if (ParamSize == 0) { RemoveCode (&Mark); PtrOnStack = 0; } else { /* Load from the saved copy */ g_getlocal (CF_PTR, PtrOffs); } } else { /* Load from original location */ LoadExpr (CF_NONE, Expr); } /* Call the function */ g_callind (TypeOf (Expr->Type+1), ParamSize, PtrOffs); } else { /* Fastcall function. We cannot use the primary for the function ** pointer and must therefore use an offset to the stack location. ** Since fastcall functions may never be variadic, we can use the ** index register for this purpose. */ g_callind (CF_LOCAL, ParamSize, PtrOffs); } /* If we have a pointer on stack, remove it */ if (PtrOnStack) { g_drop (SIZEOF_PTR); pop (CF_PTR); } /* Skip T_PTR */ ++Expr->Type; } else { /* Normal function */ if (Func->WrappedCall) { char tmp[64]; StrBuf S = AUTO_STRBUF_INITIALIZER; /* Store the WrappedCall data in tmp4 */ sprintf(tmp, "ldy #%u", Func->WrappedCallData); SB_AppendStr (&S, tmp); g_asmcode (&S); SB_Clear(&S); SB_AppendStr (&S, "sty tmp4"); g_asmcode (&S); SB_Clear(&S); /* Store the original function address in ptr4 */ SB_AppendStr (&S, "ldy #<(_"); SB_AppendStr (&S, (const char*) Expr->Name); SB_AppendChar (&S, ')'); g_asmcode (&S); SB_Clear(&S); SB_AppendStr (&S, "sty ptr4"); g_asmcode (&S); SB_Clear(&S); SB_AppendStr (&S, "ldy #>(_"); SB_AppendStr (&S, (const char*) Expr->Name); SB_AppendChar (&S, ')'); g_asmcode (&S); SB_Clear(&S); SB_AppendStr (&S, "sty ptr4+1"); g_asmcode (&S); SB_Clear(&S); SB_Done (&S); g_call (TypeOf (Expr->Type), Func->WrappedCall->Name, ParamSize); } else { g_call (TypeOf (Expr->Type), (const char*) Expr->Name, ParamSize); } } /* The function result is an rvalue in the primary register */ ED_MakeRValExpr (Expr); Expr->Type = GetFuncReturn (Expr->Type); } static void Primary (ExprDesc* E) /* This is the lowest level of the expression parser. */ { SymEntry* Sym; /* Initialize fields in the expression stucture */ ED_Init (E); /* Character and integer constants. */ if (CurTok.Tok == TOK_ICONST || CurTok.Tok == TOK_CCONST) { E->IVal = CurTok.IVal; E->Flags = E_LOC_ABS | E_RTYPE_RVAL; E->Type = CurTok.Type; NextToken (); return; } /* Floating point constant */ if (CurTok.Tok == TOK_FCONST) { E->FVal = CurTok.FVal; E->Flags = E_LOC_ABS | E_RTYPE_RVAL; E->Type = CurTok.Type; NextToken (); return; } /* Process parenthesized subexpression by calling the whole parser ** recursively. */ if (CurTok.Tok == TOK_LPAREN) { NextToken (); hie0 (E); ConsumeRParen (); return; } /* If we run into an identifier in preprocessing mode, we assume that this ** is an undefined macro and replace it by a constant value of zero. */ if (Preprocessing && CurTok.Tok == TOK_IDENT) { NextToken (); ED_MakeConstAbsInt (E, 0); return; } /* All others may only be used if the expression evaluation is not called ** recursively by the preprocessor. */ if (Preprocessing) { /* Illegal expression in PP mode */ Error ("Preprocessor expression expected"); ED_MakeConstAbsInt (E, 1); return; } switch (CurTok.Tok) { case TOK_BOOL_AND: /* A computed goto label address */ if (IS_Get (&Standard) >= STD_CC65) { SymEntry* Entry; NextToken (); Entry = AddLabelSym (CurTok.Ident, SC_REF | SC_GOTO_IND); /* output its label */ E->Flags = E_RTYPE_RVAL | E_LOC_STATIC; E->Name = Entry->V.L.Label; E->Type = PointerTo (type_void); NextToken (); } else { Error ("Computed gotos are a C extension, not supported with this --standard"); ED_MakeConstAbsInt (E, 1); } break; case TOK_IDENT: /* Identifier. Get a pointer to the symbol table entry */ Sym = E->Sym = FindSym (CurTok.Ident); /* Is the symbol known? */ if (Sym) { /* We found the symbol - skip the name token */ NextToken (); /* Check for illegal symbol types */ CHECK ((Sym->Flags & SC_LABEL) != SC_LABEL); if (Sym->Flags & SC_TYPE) { /* Cannot use type symbols */ Error ("Variable identifier expected"); /* Assume an int type to make E valid */ E->Flags = E_LOC_STACK | E_RTYPE_LVAL; E->Type = type_int; return; } /* Mark the symbol as referenced */ Sym->Flags |= SC_REF; /* The expression type is the symbol type */ E->Type = Sym->Type; /* Check for legal symbol types */ if ((Sym->Flags & SC_CONST) == SC_CONST) { /* Enum or some other numeric constant */ E->Flags = E_LOC_ABS | E_RTYPE_RVAL; E->IVal = Sym->V.ConstVal; } else if ((Sym->Flags & SC_FUNC) == SC_FUNC) { /* Function */ E->Flags = E_LOC_GLOBAL | E_RTYPE_LVAL; E->Name = (uintptr_t) Sym->Name; } else if ((Sym->Flags & SC_AUTO) == SC_AUTO) { /* Local variable. If this is a parameter for a variadic ** function, we have to add some address calculations, and the ** address is not const. */ if ((Sym->Flags & SC_PARAM) == SC_PARAM && F_IsVariadic (CurrentFunc)) { /* Variadic parameter */ g_leavariadic (Sym->V.Offs - F_GetParamSize (CurrentFunc)); E->Flags = E_LOC_EXPR | E_RTYPE_LVAL; } else { /* Normal parameter */ E->Flags = E_LOC_STACK | E_RTYPE_LVAL; E->IVal = Sym->V.Offs; } } else if ((Sym->Flags & SC_REGISTER) == SC_REGISTER) { /* Register variable, zero page based */ E->Flags = E_LOC_REGISTER | E_RTYPE_LVAL; E->Name = Sym->V.R.RegOffs; } else if ((Sym->Flags & SC_STATIC) == SC_STATIC) { /* Static variable */ if (Sym->Flags & (SC_EXTERN | SC_STORAGE)) { E->Flags = E_LOC_GLOBAL | E_RTYPE_LVAL; E->Name = (uintptr_t) Sym->Name; } else { E->Flags = E_LOC_STATIC | E_RTYPE_LVAL; E->Name = Sym->V.L.Label; } } else { /* Local static variable */ E->Flags = E_LOC_STATIC | E_RTYPE_LVAL; E->Name = Sym->V.Offs; } /* We've made all variables lvalues above. However, this is ** not always correct: An array is actually the address of its ** first element, which is a rvalue, and a function is a ** rvalue, too, because we cannot store anything in a function. ** So fix the flags depending on the type. */ if (IsTypeArray (E->Type) || IsTypeFunc (E->Type)) { ED_MakeRVal (E); } } else { /* We did not find the symbol. Remember the name, then skip it */ ident Ident; strcpy (Ident, CurTok.Ident); NextToken (); /* IDENT is either an auto-declared function or an undefined variable. */ if (CurTok.Tok == TOK_LPAREN) { /* C99 doesn't allow calls to undefined functions, so ** generate an error and otherwise a warning. Declare a ** function returning int. For that purpose, prepare a ** function signature for a function having an empty param ** list and returning int. */ if (IS_Get (&Standard) >= STD_C99) { Error ("Call to undefined function '%s'", Ident); } else { Warning ("Call to undefined function '%s'", Ident); } Sym = AddGlobalSym (Ident, GetImplicitFuncType(), SC_EXTERN | SC_REF | SC_FUNC); E->Type = Sym->Type; E->Flags = E_LOC_GLOBAL | E_RTYPE_RVAL; E->Name = (uintptr_t) Sym->Name; } else { /* Undeclared Variable */ Sym = AddLocalSym (Ident, type_int, SC_AUTO | SC_REF, 0); E->Flags = E_LOC_STACK | E_RTYPE_LVAL; E->Type = type_int; Error ("Undefined symbol: '%s'", Ident); } } break; case TOK_SCONST: case TOK_WCSCONST: /* String literal */ E->LVal = UseLiteral (CurTok.SVal); E->Type = GetCharArrayType (GetLiteralSize (CurTok.SVal)); E->Flags = E_LOC_LITERAL | E_RTYPE_RVAL; E->IVal = 0; E->Name = GetLiteralLabel (CurTok.SVal); NextToken (); break; case TOK_ASM: /* ASM statement */ AsmStatement (); E->Flags = E_LOC_EXPR | E_RTYPE_RVAL; E->Type = type_void; break; case TOK_A: /* Register pseudo variable */ E->Type = type_uchar; E->Flags = E_LOC_PRIMARY | E_RTYPE_LVAL; NextToken (); break; case TOK_AX: /* Register pseudo variable */ E->Type = type_uint; E->Flags = E_LOC_PRIMARY | E_RTYPE_LVAL; NextToken (); break; case TOK_EAX: /* Register pseudo variable */ E->Type = type_ulong; E->Flags = E_LOC_PRIMARY | E_RTYPE_LVAL; NextToken (); break; default: /* Illegal primary. Be sure to skip the token to avoid endless ** error loops. */ Error ("Expression expected"); NextToken (); ED_MakeConstAbsInt (E, 1); break; } } static void ArrayRef (ExprDesc* Expr) /* Handle an array reference. This function needs a rewrite. */ { int ConstBaseAddr; ExprDesc Subscript; CodeMark Mark1; CodeMark Mark2; TypeCode Qualifiers; Type* ElementType; Type* tptr1; /* Skip the bracket */ NextToken (); /* Get the type of left side */ tptr1 = Expr->Type; /* We can apply a special treatment for arrays that have a const base ** address. This is true for most arrays and will produce a lot better ** code. Check if this is a const base address. */ ConstBaseAddr = ED_IsRVal (Expr) && (ED_IsLocConst (Expr) || ED_IsLocStack (Expr)); /* If we have a constant base, we delay the address fetch */ GetCodePos (&Mark1); if (!ConstBaseAddr) { /* Get a pointer to the array into the primary */ LoadExpr (CF_NONE, Expr); /* Get the array pointer on stack. Do not push more than 16 ** bit, even if this value is greater, since we cannot handle ** other than 16bit stuff when doing indexing. */ GetCodePos (&Mark2); g_push (CF_PTR, 0); } /* TOS now contains ptr to array elements. Get the subscript. */ MarkedExprWithCheck (hie0, &Subscript); /* Check the types of array and subscript. We can either have a ** pointer/array to the left, in which case the subscript must be of an ** integer type, or we have an integer to the left, in which case the ** subscript must be a pointer/array. ** Since we do the necessary checking here, we can rely later on the ** correct types. */ Qualifiers = T_QUAL_NONE; if (IsClassPtr (Expr->Type)) { if (!IsClassInt (Subscript.Type)) { Error ("Array subscript is not an integer"); /* To avoid any compiler errors, make the expression a valid int */ ED_MakeConstAbsInt (&Subscript, 0); } if (IsTypeArray (Expr->Type)) { Qualifiers = GetQualifier (Expr->Type); } ElementType = Indirect (Expr->Type); } else if (IsClassInt (Expr->Type)) { if (!IsClassPtr (Subscript.Type)) { Error ("Subscripted value is neither array nor pointer"); /* To avoid compiler errors, make the subscript a char[] at ** address 0. */ ED_MakeConstAbs (&Subscript, 0, GetCharArrayType (1)); } else if (IsTypeArray (Subscript.Type)) { Qualifiers = GetQualifier (Subscript.Type); } ElementType = Indirect (Subscript.Type); } else { Error ("Cannot subscript"); /* To avoid compiler errors, fake both the array and the subscript, so ** we can just proceed. */ ED_MakeConstAbs (Expr, 0, GetCharArrayType (1)); ED_MakeConstAbsInt (&Subscript, 0); ElementType = Indirect (Expr->Type); } /* The element type has the combined qualifiers from itself and the array, ** it is a member of (if any). */ if (GetQualifier (ElementType) != (GetQualifier (ElementType) | Qualifiers)) { ElementType = TypeDup (ElementType); ElementType->C |= Qualifiers; } /* If the subscript is a bit-field, load it and make it an rvalue */ if (ED_IsBitField (&Subscript)) { LoadExpr (CF_NONE, &Subscript); ED_MakeRValExpr (&Subscript); } /* Check if the subscript is constant absolute value */ if (ED_IsConstAbs (&Subscript) && ED_CodeRangeIsEmpty (&Subscript)) { /* The array subscript is a numeric constant. If we had pushed the ** array base address onto the stack before, we can remove this value, ** since we can generate expression+offset. */ if (!ConstBaseAddr) { RemoveCode (&Mark2); } else { /* Get an array pointer into the primary */ LoadExpr (CF_NONE, Expr); } if (IsClassPtr (Expr->Type)) { /* Lhs is pointer/array. Scale the subscript value according to ** the element size. */ Subscript.IVal *= CheckedSizeOf (ElementType); /* Remove the address load code */ RemoveCode (&Mark1); /* In case of an array, we can adjust the offset of the expression ** already in Expr. If the base address was a constant, we can even ** remove the code that loaded the address into the primary. */ if (IsTypeArray (Expr->Type)) { /* Adjust the offset */ Expr->IVal += Subscript.IVal; } else { /* It's a pointer, so we do have to load it into the primary ** first (if it's not already there). */ if (ConstBaseAddr || ED_IsLVal (Expr)) { LoadExpr (CF_NONE, Expr); ED_MakeRValExpr (Expr); } /* Use the offset */ Expr->IVal = Subscript.IVal; } } else { /* Scale the rhs value according to the element type */ g_scale (TypeOf (tptr1), CheckedSizeOf (ElementType)); /* Add the subscript. Since arrays are indexed by integers, ** we will ignore the true type of the subscript here and ** use always an int. #### Use offset but beware of LoadExpr! */ g_inc (CF_INT | CF_CONST, Subscript.IVal); } } else { /* Array subscript is not constant. Load it into the primary */ GetCodePos (&Mark2); LoadExpr (CF_NONE, &Subscript); /* Do scaling */ if (IsClassPtr (Expr->Type)) { /* Indexing is based on unsigneds, so we will just use the integer ** portion of the index (which is in (e)ax, so there's no further ** action required). */ g_scale (CF_INT, CheckedSizeOf (ElementType)); } else { /* Get the int value on top. If we come here, we're sure, both ** values are 16 bit (the first one was truncated if necessary ** and the second one is a pointer). Note: If ConstBaseAddr is ** true, we don't have a value on stack, so to "swap" both, just ** push the subscript. */ if (ConstBaseAddr) { g_push (CF_INT, 0); LoadExpr (CF_NONE, Expr); ConstBaseAddr = 0; } else { g_swap (CF_INT); } /* Scale it */ g_scale (TypeOf (tptr1), CheckedSizeOf (ElementType)); } /* The offset is now in the primary register. It we didn't have a ** constant base address for the lhs, the lhs address is already ** on stack, and we must add the offset. If the base address was ** constant, we call special functions to add the address to the ** offset value. */ if (!ConstBaseAddr) { /* The array base address is on stack and the subscript is in the ** primary. Add both. */ g_add (CF_INT, 0); } else { /* The subscript is in the primary, and the array base address is ** in Expr. If the subscript has itself a constant address, it is ** often a better idea to reverse again the order of the ** evaluation. This will generate better code if the subscript is ** a byte sized variable. But beware: This is only possible if the ** subscript was not scaled, that is, if this was a byte array ** or pointer. */ if ((ED_IsLocConst (&Subscript) || ED_IsLocStack (&Subscript)) && CheckedSizeOf (ElementType) == SIZEOF_CHAR) { unsigned Flags; /* Reverse the order of evaluation */ if (CheckedSizeOf (Subscript.Type) == SIZEOF_CHAR) { Flags = CF_CHAR; } else { Flags = CF_INT; } RemoveCode (&Mark2); /* Get a pointer to the array into the primary. */ LoadExpr (CF_NONE, Expr); /* Add the variable */ if (ED_IsLocStack (&Subscript)) { g_addlocal (Flags, Subscript.IVal); } else { Flags |= GlobalModeFlags (&Subscript); g_addstatic (Flags, Subscript.Name, Subscript.IVal); } } else { if (ED_IsLocAbs (Expr)) { /* Constant numeric address. Just add it */ g_inc (CF_INT, Expr->IVal); } else if (ED_IsLocStack (Expr)) { /* Base address is a local variable address */ if (IsTypeArray (Expr->Type)) { g_addaddr_local (CF_INT, Expr->IVal); } else { g_addlocal (CF_PTR, Expr->IVal); } } else { /* Base address is a static variable address */ unsigned Flags = CF_INT | GlobalModeFlags (Expr); if (ED_IsRVal (Expr)) { /* Add the address of the location */ g_addaddr_static (Flags, Expr->Name, Expr->IVal); } else { /* Add the contents of the location */ g_addstatic (Flags, Expr->Name, Expr->IVal); } } } } /* The result is an expression in the primary */ ED_MakeRValExpr (Expr); } /* Result is of element type */ Expr->Type = ElementType; /* An array element is actually a variable. So the rules for variables ** with respect to the reference type apply: If it's an array, it is ** a rvalue, otherwise it's an lvalue. (A function would also be a rvalue, ** but an array cannot contain functions). */ if (IsTypeArray (Expr->Type)) { ED_MakeRVal (Expr); } else { ED_MakeLVal (Expr); } /* Consume the closing bracket */ ConsumeRBrack (); } static void StructRef (ExprDesc* Expr) /* Process struct field after . or ->. */ { ident Ident; SymEntry* Field; Type* FinalType; TypeCode Q; /* Skip the token and check for an identifier */ NextToken (); if (CurTok.Tok != TOK_IDENT) { Error ("Identifier expected"); /* Make the expression an integer at address zero */ ED_MakeConstAbs (Expr, 0, type_int); return; } /* Get the symbol table entry and check for a struct field */ strcpy (Ident, CurTok.Ident); NextToken (); Field = FindStructField (Expr->Type, Ident); if (Field == 0) { Error ("Struct/union has no field named '%s'", Ident); /* Make the expression an integer at address zero */ ED_MakeConstAbs (Expr, 0, type_int); return; } /* If we have a struct pointer that is an lvalue and not already in the ** primary, load it now. */ if (ED_IsLVal (Expr) && IsTypePtr (Expr->Type)) { /* Load into the primary */ LoadExpr (CF_NONE, Expr); /* Make it an lvalue expression */ ED_MakeLValExpr (Expr); } /* The type is the type of the field plus any qualifiers from the struct */ if (IsClassStruct (Expr->Type)) { Q = GetQualifier (Expr->Type); } else { Q = GetQualifier (Indirect (Expr->Type)); } if (GetQualifier (Field->Type) == (GetQualifier (Field->Type) | Q)) { FinalType = Field->Type; } else { FinalType = TypeDup (Field->Type); FinalType->C |= Q; } /* A struct is usually an lvalue. If not, it is a struct in the primary ** register. */ if (ED_IsRVal (Expr) && ED_IsLocExpr (Expr) && !IsTypePtr (Expr->Type)) { unsigned Flags = 0; unsigned BitOffs; /* Get the size of the type */ unsigned Size = SizeOf (Expr->Type); /* Safety check */ CHECK (Field->V.Offs + Size <= SIZEOF_LONG); /* The type of the operation depends on the type of the struct */ switch (Size) { case 1: Flags = CF_CHAR | CF_UNSIGNED | CF_CONST; break; case 2: Flags = CF_INT | CF_UNSIGNED | CF_CONST; break; case 3: /* FALLTHROUGH */ case 4: Flags = CF_LONG | CF_UNSIGNED | CF_CONST; break; default: Internal ("Invalid struct size: %u", Size); break; } /* Generate a shift to get the field in the proper position in the ** primary. For bit fields, mask the value. */ BitOffs = Field->V.Offs * CHAR_BITS; if (SymIsBitField (Field)) { BitOffs += Field->V.B.BitOffs; g_asr (Flags, BitOffs); /* Mask the value. This is unnecessary if the shift executed above ** moved only zeroes into the value. */ if (BitOffs + Field->V.B.BitWidth != Size * CHAR_BITS) { g_and (CF_INT | CF_UNSIGNED | CF_CONST, (0x0001U << Field->V.B.BitWidth) - 1U); } } else { g_asr (Flags, BitOffs); } /* Use the new type */ Expr->Type = FinalType; } else { /* Set the struct field offset */ Expr->IVal += Field->V.Offs; /* Use the new type */ Expr->Type = FinalType; /* An struct member is actually a variable. So the rules for variables ** with respect to the reference type apply: If it's an array, it is ** a rvalue, otherwise it's an lvalue. (A function would also be a rvalue, ** but a struct field cannot be a function). */ if (IsTypeArray (Expr->Type)) { ED_MakeRVal (Expr); } else { ED_MakeLVal (Expr); } /* Make the expression a bit field if necessary */ if (SymIsBitField (Field)) { ED_MakeBitField (Expr, Field->V.B.BitOffs, Field->V.B.BitWidth); } } } static void hie11 (ExprDesc *Expr) /* Handle compound types (structs and arrays) */ { /* Name value used in invalid function calls */ static const char IllegalFunc[] = "illegal_function_call"; /* Evaluate the lhs */ Primary (Expr); /* Check for a rhs */ while (CurTok.Tok == TOK_LBRACK || CurTok.Tok == TOK_LPAREN || CurTok.Tok == TOK_DOT || CurTok.Tok == TOK_PTR_REF) { switch (CurTok.Tok) { case TOK_LBRACK: /* Array reference */ ArrayRef (Expr); break; case TOK_LPAREN: /* Function call. */ if (!IsTypeFunc (Expr->Type) && !IsTypeFuncPtr (Expr->Type)) { /* Not a function */ Error ("Illegal function call"); /* Force the type to be a implicitly defined function, one ** returning an int and taking any number of arguments. ** Since we don't have a name, invent one. */ ED_MakeConstAbs (Expr, 0, GetImplicitFuncType ()); Expr->Name = (uintptr_t) IllegalFunc; } /* Call the function */ FunctionCall (Expr); break; case TOK_DOT: if (!IsClassStruct (Expr->Type)) { Error ("Struct expected"); } StructRef (Expr); break; case TOK_PTR_REF: /* If we have an array, convert it to pointer to first element */ if (IsTypeArray (Expr->Type)) { Expr->Type = ArrayToPtr (Expr->Type); } if (!IsClassPtr (Expr->Type) || !IsClassStruct (Indirect (Expr->Type))) { Error ("Struct pointer expected"); } StructRef (Expr); break; default: Internal ("Invalid token in hie11: %d", CurTok.Tok); } } } void Store (ExprDesc* Expr, const Type* StoreType) /* Store the primary register into the location denoted by Expr. If StoreType ** is given, use this type when storing instead of Expr->Type. If StoreType ** is NULL, use Expr->Type instead. */ { unsigned Flags; /* If StoreType was not given, use Expr->Type instead */ if (StoreType == 0) { StoreType = Expr->Type; } /* Prepare the code generator flags */ Flags = TypeOf (StoreType) | GlobalModeFlags (Expr); /* Do the store depending on the location */ switch (ED_GetLoc (Expr)) { case E_LOC_ABS: /* Absolute: numeric address or const */ g_putstatic (Flags, Expr->IVal, 0); break; case E_LOC_GLOBAL: /* Global variable */ g_putstatic (Flags, Expr->Name, Expr->IVal); break; case E_LOC_STATIC: case E_LOC_LITERAL: /* Static variable or literal in the literal pool */ g_putstatic (Flags, Expr->Name, Expr->IVal); break; case E_LOC_REGISTER: /* Register variable */ g_putstatic (Flags, Expr->Name, Expr->IVal); break; case E_LOC_STACK: /* Value on the stack */ g_putlocal (Flags, Expr->IVal, 0); break; case E_LOC_PRIMARY: /* The primary register (value is already there) */ break; case E_LOC_EXPR: /* An expression in the primary register */ g_putind (Flags, Expr->IVal); break; default: Internal ("Invalid location in Store(): 0x%04X", ED_GetLoc (Expr)); } /* Assume that each one of the stores will invalidate CC */ ED_MarkAsUntested (Expr); } static void PreInc (ExprDesc* Expr) /* Handle the preincrement operators */ { unsigned Flags; unsigned long Val; /* Skip the operator token */ NextToken (); /* Evaluate the expression and check that it is an lvalue */ hie10 (Expr); if (!ED_IsLVal (Expr)) { Error ("Invalid lvalue"); return; } /* We cannot modify const values */ if (IsQualConst (Expr->Type)) { Error ("Increment of read-only variable"); } /* Get the data type */ Flags = TypeOf (Expr->Type) | GlobalModeFlags (Expr) | CF_FORCECHAR | CF_CONST; /* Get the increment value in bytes */ Val = IsTypePtr (Expr->Type)? CheckedPSizeOf (Expr->Type) : 1; /* Check the location of the data */ switch (ED_GetLoc (Expr)) { case E_LOC_ABS: /* Absolute: numeric address or const */ g_addeqstatic (Flags, Expr->IVal, 0, Val); break; case E_LOC_GLOBAL: /* Global variable */ g_addeqstatic (Flags, Expr->Name, Expr->IVal, Val); break; case E_LOC_STATIC: case E_LOC_LITERAL: /* Static variable or literal in the literal pool */ g_addeqstatic (Flags, Expr->Name, Expr->IVal, Val); break; case E_LOC_REGISTER: /* Register variable */ g_addeqstatic (Flags, Expr->Name, Expr->IVal, Val); break; case E_LOC_STACK: /* Value on the stack */ g_addeqlocal (Flags, Expr->IVal, Val); break; case E_LOC_PRIMARY: /* The primary register */ g_inc (Flags, Val); break; case E_LOC_EXPR: /* An expression in the primary register */ g_addeqind (Flags, Expr->IVal, Val); break; default: Internal ("Invalid location in PreInc(): 0x%04X", ED_GetLoc (Expr)); } /* Result is an expression, no reference */ ED_MakeRValExpr (Expr); } static void PreDec (ExprDesc* Expr) /* Handle the predecrement operators */ { unsigned Flags; unsigned long Val; /* Skip the operator token */ NextToken (); /* Evaluate the expression and check that it is an lvalue */ hie10 (Expr); if (!ED_IsLVal (Expr)) { Error ("Invalid lvalue"); return; } /* We cannot modify const values */ if (IsQualConst (Expr->Type)) { Error ("Decrement of read-only variable"); } /* Get the data type */ Flags = TypeOf (Expr->Type) | GlobalModeFlags (Expr) | CF_FORCECHAR | CF_CONST; /* Get the increment value in bytes */ Val = IsTypePtr (Expr->Type)? CheckedPSizeOf (Expr->Type) : 1; /* Check the location of the data */ switch (ED_GetLoc (Expr)) { case E_LOC_ABS: /* Absolute: numeric address or const */ g_subeqstatic (Flags, Expr->IVal, 0, Val); break; case E_LOC_GLOBAL: /* Global variable */ g_subeqstatic (Flags, Expr->Name, Expr->IVal, Val); break; case E_LOC_STATIC: case E_LOC_LITERAL: /* Static variable or literal in the literal pool */ g_subeqstatic (Flags, Expr->Name, Expr->IVal, Val); break; case E_LOC_REGISTER: /* Register variable */ g_subeqstatic (Flags, Expr->Name, Expr->IVal, Val); break; case E_LOC_STACK: /* Value on the stack */ g_subeqlocal (Flags, Expr->IVal, Val); break; case E_LOC_PRIMARY: /* The primary register */ g_inc (Flags, Val); break; case E_LOC_EXPR: /* An expression in the primary register */ g_subeqind (Flags, Expr->IVal, Val); break; default: Internal ("Invalid location in PreDec(): 0x%04X", ED_GetLoc (Expr)); } /* Result is an expression, no reference */ ED_MakeRValExpr (Expr); } static void PostInc (ExprDesc* Expr) /* Handle the postincrement operator */ { unsigned Flags; NextToken (); /* The expression to increment must be an lvalue */ if (!ED_IsLVal (Expr)) { Error ("Invalid lvalue"); return; } /* We cannot modify const values */ if (IsQualConst (Expr->Type)) { Error ("Increment of read-only variable"); } /* Get the data type */ Flags = TypeOf (Expr->Type); /* Emit smaller code if a char variable is at a constant location */ if ((Flags & CF_CHAR) == CF_CHAR && ED_IsLocConst(Expr)) { LoadExpr (CF_NONE, Expr); AddCodeLine ("inc %s", ED_GetLabelName(Expr, 0)); } else { /* Push the address if needed */ PushAddr (Expr); /* Fetch the value and save it (since it's the result of the expression) */ LoadExpr (CF_NONE, Expr); g_save (Flags | CF_FORCECHAR); /* If we have a pointer expression, increment by the size of the type */ if (IsTypePtr (Expr->Type)) { g_inc (Flags | CF_CONST | CF_FORCECHAR, CheckedSizeOf (Expr->Type + 1)); } else { g_inc (Flags | CF_CONST | CF_FORCECHAR, 1); } /* Store the result back */ Store (Expr, 0); /* Restore the original value in the primary register */ g_restore (Flags | CF_FORCECHAR); } /* The result is always an expression, no reference */ ED_MakeRValExpr (Expr); } static void PostDec (ExprDesc* Expr) /* Handle the postdecrement operator */ { unsigned Flags; NextToken (); /* The expression to increment must be an lvalue */ if (!ED_IsLVal (Expr)) { Error ("Invalid lvalue"); return; } /* We cannot modify const values */ if (IsQualConst (Expr->Type)) { Error ("Decrement of read-only variable"); } /* Get the data type */ Flags = TypeOf (Expr->Type); /* Emit smaller code if a char variable is at a constant location */ if ((Flags & CF_CHAR) == CF_CHAR && ED_IsLocConst(Expr)) { LoadExpr (CF_NONE, Expr); AddCodeLine ("dec %s", ED_GetLabelName(Expr, 0)); } else { /* Push the address if needed */ PushAddr (Expr); /* Fetch the value and save it (since it's the result of the expression) */ LoadExpr (CF_NONE, Expr); g_save (Flags | CF_FORCECHAR); /* If we have a pointer expression, increment by the size of the type */ if (IsTypePtr (Expr->Type)) { g_dec (Flags | CF_CONST | CF_FORCECHAR, CheckedSizeOf (Expr->Type + 1)); } else { g_dec (Flags | CF_CONST | CF_FORCECHAR, 1); } /* Store the result back */ Store (Expr, 0); /* Restore the original value in the primary register */ g_restore (Flags | CF_FORCECHAR); } /* The result is always an expression, no reference */ ED_MakeRValExpr (Expr); } static void UnaryOp (ExprDesc* Expr) /* Handle unary -/+ and ~ */ { unsigned Flags; /* Remember the operator token and skip it */ token_t Tok = CurTok.Tok; NextToken (); /* Get the expression */ hie10 (Expr); /* We can only handle integer types */ if (!IsClassInt (Expr->Type)) { Error ("Argument must have integer type"); ED_MakeConstAbsInt (Expr, 1); } /* Check for a constant expression */ if (ED_IsConstAbs (Expr)) { /* Value is constant */ switch (Tok) { case TOK_MINUS: Expr->IVal = -Expr->IVal; break; case TOK_PLUS: break; case TOK_COMP: Expr->IVal = ~Expr->IVal; break; default: Internal ("Unexpected token: %d", Tok); } } else { /* Value is not constant */ LoadExpr (CF_NONE, Expr); /* Get the type of the expression */ Flags = TypeOf (Expr->Type); /* Handle the operation */ switch (Tok) { case TOK_MINUS: g_neg (Flags); break; case TOK_PLUS: break; case TOK_COMP: g_com (Flags); break; default: Internal ("Unexpected token: %d", Tok); } /* The result is a rvalue in the primary */ ED_MakeRValExpr (Expr); } } void hie10 (ExprDesc* Expr) /* Handle ++, --, !, unary - etc. */ { unsigned long Size; switch (CurTok.Tok) { case TOK_INC: PreInc (Expr); break; case TOK_DEC: PreDec (Expr); break; case TOK_PLUS: case TOK_MINUS: case TOK_COMP: UnaryOp (Expr); break; case TOK_BOOL_NOT: NextToken (); if (evalexpr (CF_NONE, hie10, Expr) == 0) { /* Constant expression */ Expr->IVal = !Expr->IVal; } else { g_bneg (TypeOf (Expr->Type)); ED_MakeRValExpr (Expr); ED_TestDone (Expr); /* bneg will set cc */ } break; case TOK_STAR: NextToken (); ExprWithCheck (hie10, Expr); if (ED_IsLVal (Expr) || !(ED_IsLocConst (Expr) || ED_IsLocStack (Expr))) { /* Not a const, load it into the primary and make it a ** calculated value. */ LoadExpr (CF_NONE, Expr); ED_MakeRValExpr (Expr); } /* If the expression is already a pointer to function, the ** additional dereferencing operator must be ignored. A function ** itself is represented as "pointer to function", so any number ** of dereference operators is legal, since the result will ** always be converted to "pointer to function". */ if (IsTypeFuncPtr (Expr->Type) || IsTypeFunc (Expr->Type)) { /* Expression not storable */ ED_MakeRVal (Expr); } else { if (IsClassPtr (Expr->Type)) { Expr->Type = Indirect (Expr->Type); } else { Error ("Illegal indirection"); } /* 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; case TOK_AND: NextToken (); ExprWithCheck (hie10, Expr); /* The & operator may be applied to any lvalue, and it may be ** applied to functions, even if they're no lvalues. */ if (ED_IsRVal (Expr) && !IsTypeFunc (Expr->Type) && !IsTypeArray (Expr->Type)) { Error ("Illegal address"); } else { if (ED_IsBitField (Expr)) { Error ("Cannot take address of bit-field"); /* Do it anyway, just to avoid further warnings */ Expr->Flags &= ~E_BITFIELD; } Expr->Type = PointerTo (Expr->Type); /* The & operator yields an rvalue */ ED_MakeRVal (Expr); } break; case TOK_SIZEOF: NextToken (); if (TypeSpecAhead ()) { Type T[MAXTYPELEN]; NextToken (); Size = CheckedSizeOf (ParseType (T)); ConsumeRParen (); } else { /* Remember the output queue pointer */ CodeMark Mark; GetCodePos (&Mark); hie10 (Expr); /* If the expression is a literal string, release it, so it ** won't be output as data if not used elsewhere. */ if (ED_IsLocLiteral (Expr)) { ReleaseLiteral (Expr->LVal); } /* Calculate the size */ Size = CheckedSizeOf (Expr->Type); /* Remove any generated code */ RemoveCode (&Mark); } ED_MakeConstAbs (Expr, Size, type_size_t); ED_MarkAsUntested (Expr); break; default: if (TypeSpecAhead ()) { /* A typecast */ TypeCast (Expr); } else { /* An expression */ hie11 (Expr); /* Handle post increment */ switch (CurTok.Tok) { case TOK_INC: PostInc (Expr); break; case TOK_DEC: PostDec (Expr); break; default: break; } } break; } } static void hie_internal (const GenDesc* Ops, /* List of generators */ ExprDesc* Expr, void (*hienext) (ExprDesc*), int* UsedGen) /* Helper function */ { ExprDesc Expr2; CodeMark Mark1; CodeMark Mark2; const GenDesc* Gen; token_t Tok; /* The operator token */ unsigned ltype, type; int lconst; /* Left operand is a constant */ int rconst; /* Right operand is a constant */ ExprWithCheck (hienext, Expr); *UsedGen = 0; while ((Gen = FindGen (CurTok.Tok, Ops)) != 0) { /* Tell the caller that we handled it's ops */ *UsedGen = 1; /* All operators that call this function expect an int on the lhs */ if (!IsClassInt (Expr->Type)) { Error ("Integer expression expected"); /* To avoid further errors, make Expr a valid int expression */ ED_MakeConstAbsInt (Expr, 1); } /* Remember the operator token, then skip it */ Tok = CurTok.Tok; NextToken (); /* Get the lhs on stack */ GetCodePos (&Mark1); ltype = TypeOf (Expr->Type); lconst = ED_IsConstAbs (Expr); if (lconst) { /* Constant value */ GetCodePos (&Mark2); /* If the operator is commutative, don't push the left side, if ** it's a constant, since we will exchange both operands. */ if ((Gen->Flags & GEN_COMM) == 0) { g_push (ltype | CF_CONST, Expr->IVal); } } else { /* Value not constant */ LoadExpr (CF_NONE, Expr); GetCodePos (&Mark2); g_push (ltype, 0); } /* Get the right hand side */ MarkedExprWithCheck (hienext, &Expr2); /* Check for a constant expression */ rconst = (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)); if (!rconst) { /* Not constant, load into the primary */ LoadExpr (CF_NONE, &Expr2); } /* Check the type of the rhs */ if (!IsClassInt (Expr2.Type)) { Error ("Integer expression expected"); } /* Check for const operands */ if (lconst && rconst) { /* Both operands are constant, remove the generated code */ RemoveCode (&Mark1); /* Get the type of the result */ Expr->Type = promoteint (Expr->Type, Expr2.Type); /* Handle the op differently for signed and unsigned types */ if (IsSignSigned (Expr->Type)) { /* Evaluate the result for signed operands */ signed long Val1 = Expr->IVal; signed long Val2 = Expr2.IVal; switch (Tok) { case TOK_OR: Expr->IVal = (Val1 | Val2); break; case TOK_XOR: Expr->IVal = (Val1 ^ Val2); break; case TOK_AND: Expr->IVal = (Val1 & Val2); break; case TOK_STAR: Expr->IVal = (Val1 * Val2); break; case TOK_DIV: if (Val2 == 0) { Error ("Division by zero"); Expr->IVal = 0x7FFFFFFF; } else { Expr->IVal = (Val1 / Val2); } break; case TOK_MOD: if (Val2 == 0) { Error ("Modulo operation with zero"); Expr->IVal = 0; } else { Expr->IVal = (Val1 % Val2); } break; default: Internal ("hie_internal: got token 0x%X\n", Tok); } } else { /* Evaluate the result for unsigned operands */ unsigned long Val1 = Expr->IVal; unsigned long Val2 = Expr2.IVal; switch (Tok) { case TOK_OR: Expr->IVal = (Val1 | Val2); break; case TOK_XOR: Expr->IVal = (Val1 ^ Val2); break; case TOK_AND: Expr->IVal = (Val1 & Val2); break; case TOK_STAR: Expr->IVal = (Val1 * Val2); break; case TOK_DIV: if (Val2 == 0) { Error ("Division by zero"); Expr->IVal = 0xFFFFFFFF; } else { Expr->IVal = (Val1 / Val2); } break; case TOK_MOD: if (Val2 == 0) { Error ("Modulo operation with zero"); Expr->IVal = 0; } else { Expr->IVal = (Val1 % Val2); } break; default: Internal ("hie_internal: got token 0x%X\n", Tok); } } } else if (lconst && (Gen->Flags & GEN_COMM) && !rconst) { /* The left side is constant, the right side is not, and the ** operator allows swapping the operands. We haven't pushed the ** left side onto the stack in this case, and will reverse the ** operation because this allows for better code. */ unsigned rtype = ltype | CF_CONST; ltype = TypeOf (Expr2.Type); /* Expr2 is now left */ type = CF_CONST; if ((Gen->Flags & GEN_NOPUSH) == 0) { g_push (ltype, 0); } else { ltype |= CF_REG; /* Value is in register */ } /* Determine the type of the operation result. */ type |= g_typeadjust (ltype, rtype); Expr->Type = promoteint (Expr->Type, Expr2.Type); /* Generate code */ Gen->Func (type, Expr->IVal); /* We have a rvalue in the primary now */ ED_MakeRValExpr (Expr); } else { /* If the right hand side is constant, and the generator function ** expects the lhs in the primary, remove the push of the primary ** now. */ unsigned rtype = TypeOf (Expr2.Type); type = 0; if (rconst) { /* Second value is constant - check for div */ type |= CF_CONST; rtype |= CF_CONST; if (Tok == TOK_DIV && Expr2.IVal == 0) { Error ("Division by zero"); } else if (Tok == TOK_MOD && Expr2.IVal == 0) { Error ("Modulo operation with zero"); } if ((Gen->Flags & GEN_NOPUSH) != 0) { RemoveCode (&Mark2); ltype |= CF_REG; /* Value is in register */ } } /* Determine the type of the operation result. */ type |= g_typeadjust (ltype, rtype); Expr->Type = promoteint (Expr->Type, Expr2.Type); /* Generate code */ Gen->Func (type, Expr2.IVal); /* We have a rvalue in the primary now */ ED_MakeRValExpr (Expr); } } } static void hie_compare (const GenDesc* Ops, /* List of generators */ ExprDesc* Expr, void (*hienext) (ExprDesc*)) /* Helper function for the compare operators */ { ExprDesc Expr2; CodeMark Mark0; CodeMark Mark1; CodeMark Mark2; const GenDesc* Gen; token_t Tok; /* The operator token */ unsigned ltype; int rconst; /* Operand is a constant */ GetCodePos (&Mark0); ExprWithCheck (hienext, Expr); while ((Gen = FindGen (CurTok.Tok, Ops)) != 0) { /* Remember the generator function */ void (*GenFunc) (unsigned, unsigned long) = Gen->Func; /* Remember the operator token, then skip it */ 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); if (ED_IsConstAbs (Expr)) { /* Constant value */ GetCodePos (&Mark2); g_push (ltype | CF_CONST, Expr->IVal); } else { /* Value not constant */ LoadExpr (CF_NONE, Expr); GetCodePos (&Mark2); g_push (ltype, 0); } /* 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) { /* Not constant, load into the primary */ 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))) { Error ("Incompatible types"); } } else if (IsClassPtr (Expr->Type)) { if (IsClassPtr (Expr2.Type)) { /* Both pointers are allowed in comparison if they point to ** the same type, or if one of them is a void pointer. */ Type* left = Indirect (Expr->Type); Type* right = Indirect (Expr2.Type); 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)) { Error ("Incompatible types"); } } /* Check for const operands */ if (ED_IsConstAbs (Expr) && rconst) { /* If the result is constant, this is suspicious when not in ** preprocessor mode. */ WarnConstCompareResult (); /* Both operands are constant, remove the generated code */ RemoveCode (&Mark1); /* Determine if this is a signed or unsigned compare */ if (IsClassInt (Expr->Type) && IsSignSigned (Expr->Type) && IsClassInt (Expr2.Type) && IsSignSigned (Expr2.Type)) { /* Evaluate the result for signed operands */ signed long Val1 = Expr->IVal; signed long Val2 = Expr2.IVal; switch (Tok) { case TOK_EQ: Expr->IVal = (Val1 == Val2); break; case TOK_NE: Expr->IVal = (Val1 != Val2); break; case TOK_LT: Expr->IVal = (Val1 < Val2); break; case TOK_LE: Expr->IVal = (Val1 <= Val2); break; case TOK_GE: Expr->IVal = (Val1 >= Val2); break; case TOK_GT: Expr->IVal = (Val1 > Val2); break; default: Internal ("hie_compare: got token 0x%X\n", Tok); } } else { /* Evaluate the result for unsigned operands */ unsigned long Val1 = Expr->IVal; unsigned long Val2 = Expr2.IVal; switch (Tok) { case TOK_EQ: Expr->IVal = (Val1 == Val2); break; case TOK_NE: Expr->IVal = (Val1 != Val2); break; case TOK_LT: Expr->IVal = (Val1 < Val2); break; case TOK_LE: Expr->IVal = (Val1 <= Val2); break; case TOK_GE: Expr->IVal = (Val1 >= Val2); break; case TOK_GT: Expr->IVal = (Val1 > Val2); break; default: Internal ("hie_compare: got token 0x%X\n", Tok); } } } else { /* Determine the signedness of the operands */ int LeftSigned = IsSignSigned (Expr->Type); int RightSigned = IsSignSigned (Expr2.Type); /* If the right hand side is constant, and the generator function ** expects the lhs in the primary, remove the push of the primary ** now. */ unsigned flags = 0; if (rconst) { flags |= CF_CONST; if ((Gen->Flags & GEN_NOPUSH) != 0) { RemoveCode (&Mark2); ltype |= CF_REG; /* Value is in register */ } } /* Determine the type of the operation. */ if (IsTypeChar (Expr->Type) && rconst) { /* Left side is unsigned char, right side is constant. ** Determine the minimum and maximum values */ int LeftMin, LeftMax; if (LeftSigned) { LeftMin = -128; LeftMax = 127; } else { LeftMin = 0; LeftMax = 255; } /* An integer value is always represented as a signed in the ** ExprDesc structure. This may lead to false results below, ** if it is actually unsigned, but interpreted as signed ** because of the representation. Fortunately, in this case, ** the actual value doesn't matter, since it's always greater ** than what can be represented in a char. So correct the ** value accordingly. */ if (!RightSigned && Expr2.IVal < 0) { /* Correct the value so it is an unsigned. It will then ** anyway match one of the cases below. */ Expr2.IVal = LeftMax + 1; } /* Comparing a char against a constant may have a constant ** result. Please note: It is not possible to remove the code ** for the compare alltogether, because it may have side ** effects. */ switch (Tok) { case TOK_EQ: if (Expr2.IVal < LeftMin || Expr2.IVal > LeftMax) { ED_MakeConstAbsInt (Expr, 0); WarnConstCompareResult (); goto Done; } break; case TOK_NE: if (Expr2.IVal < LeftMin || Expr2.IVal > LeftMax) { ED_MakeConstAbsInt (Expr, 1); WarnConstCompareResult (); goto Done; } break; case TOK_LT: if (Expr2.IVal <= LeftMin || Expr2.IVal > LeftMax) { ED_MakeConstAbsInt (Expr, Expr2.IVal > LeftMax); WarnConstCompareResult (); goto Done; } break; case TOK_LE: if (Expr2.IVal < LeftMin || Expr2.IVal >= LeftMax) { ED_MakeConstAbsInt (Expr, Expr2.IVal >= LeftMax); WarnConstCompareResult (); goto Done; } break; case TOK_GE: if (Expr2.IVal <= LeftMin || Expr2.IVal > LeftMax) { ED_MakeConstAbsInt (Expr, Expr2.IVal <= LeftMin); WarnConstCompareResult (); goto Done; } break; case TOK_GT: if (Expr2.IVal < LeftMin || Expr2.IVal >= LeftMax) { ED_MakeConstAbsInt (Expr, Expr2.IVal < LeftMin); WarnConstCompareResult (); goto Done; } break; default: Internal ("hie_compare: got token 0x%X\n", Tok); } /* If the result is not already constant (as evaluated in the ** switch above), we can execute the operation as a char op, ** since the right side constant is in a valid range. */ flags |= (CF_CHAR | CF_FORCECHAR); if (!LeftSigned) { flags |= CF_UNSIGNED; } } else if (IsTypeChar (Expr->Type) && IsTypeChar (Expr2.Type) && GetSignedness (Expr->Type) == GetSignedness (Expr2.Type)) { /* Both are chars with the same signedness. We can encode the ** operation as a char operation. */ flags |= CF_CHAR; if (rconst) { flags |= CF_FORCECHAR; } if (!LeftSigned) { flags |= CF_UNSIGNED; } } else { unsigned rtype = TypeOf (Expr2.Type) | (flags & CF_CONST); flags |= g_typeadjust (ltype, rtype); } /* If the left side is an unsigned and the right is a constant, ** we may be able to change the compares to something more ** effective. */ if (!LeftSigned && rconst) { switch (Tok) { case TOK_LT: if (Expr2.IVal == 1) { /* An unsigned compare to one means that the value ** must be zero. */ GenFunc = g_eq; Expr2.IVal = 0; } break; case TOK_LE: if (Expr2.IVal == 0) { /* An unsigned compare to zero means that the value ** must be zero. */ GenFunc = g_eq; } break; case TOK_GE: if (Expr2.IVal == 1) { /* An unsigned compare to one means that the value ** must not be zero. */ GenFunc = g_ne; Expr2.IVal = 0; } break; case TOK_GT: if (Expr2.IVal == 0) { /* An unsigned compare to zero means that the value ** must not be zero. */ GenFunc = g_ne; } break; default: break; } } /* Generate code */ GenFunc (flags, Expr2.IVal); /* The result is an rvalue in the primary */ ED_MakeRValExpr (Expr); } /* Result type is always int */ Expr->Type = type_int; Done: /* Condition codes are set */ ED_TestDone (Expr); } } static void hie9 (ExprDesc *Expr) /* Process * and / operators. */ { static const GenDesc hie9_ops[] = { { TOK_STAR, GEN_NOPUSH | GEN_COMM, g_mul }, { TOK_DIV, GEN_NOPUSH, g_div }, { TOK_MOD, GEN_NOPUSH, g_mod }, { TOK_INVALID, 0, 0 } }; int UsedGen; hie_internal (hie9_ops, Expr, hie10, &UsedGen); } static void parseadd (ExprDesc* Expr) /* Parse an expression with the binary plus operator. Expr contains the ** unprocessed left hand side of the expression and will contain the ** result of the expression on return. */ { ExprDesc Expr2; unsigned flags; /* Operation flags */ CodeMark Mark; /* Remember code position */ Type* lhst; /* Type of left hand side */ Type* rhst; /* Type of right hand side */ /* Skip the PLUS token */ NextToken (); /* Get the left hand side type, initialize operation flags */ lhst = Expr->Type; flags = 0; /* Check for constness on both sides */ if (ED_IsConst (Expr)) { /* The left hand side is a constant of some sort. Good. Get rhs */ ExprWithCheck (hie9, &Expr2); if (ED_IsConstAbs (&Expr2)) { /* Right hand side is a constant numeric value. Get the rhs type */ rhst = Expr2.Type; /* Both expressions are constants. Check for pointer arithmetic */ if (IsClassPtr (lhst) && IsClassInt (rhst)) { /* Left is pointer, right is int, must scale rhs */ Expr->IVal += Expr2.IVal * CheckedPSizeOf (lhst); /* Result type is a pointer */ } else if (IsClassInt (lhst) && IsClassPtr (rhst)) { /* Left is int, right is pointer, must scale lhs */ Expr->IVal = Expr->IVal * CheckedPSizeOf (rhst) + Expr2.IVal; /* Result type is a pointer */ Expr->Type = Expr2.Type; } else if (IsClassInt (lhst) && IsClassInt (rhst)) { /* Integer addition */ Expr->IVal += Expr2.IVal; typeadjust (Expr, &Expr2, 1); } else { /* OOPS */ Error ("Invalid operands for binary operator '+'"); } } else { /* lhs is a constant and rhs is not constant. Load rhs into ** the primary. */ LoadExpr (CF_NONE, &Expr2); /* Beware: The check above (for lhs) lets not only pass numeric ** constants, but also constant addresses (labels), maybe even ** with an offset. We have to check for that here. */ /* First, get the rhs type. */ rhst = Expr2.Type; /* Setup flags */ if (ED_IsLocAbs (Expr)) { /* A numerical constant */ flags |= CF_CONST; } else { /* Constant address label */ flags |= GlobalModeFlags (Expr) | CF_CONSTADDR; } /* Check for pointer arithmetic */ if (IsClassPtr (lhst) && IsClassInt (rhst)) { /* Left is pointer, right is int, must scale rhs */ g_scale (CF_INT, CheckedPSizeOf (lhst)); /* Operate on pointers, result type is a pointer */ flags |= CF_PTR; /* Generate the code for the add */ if (ED_GetLoc (Expr) == E_LOC_ABS) { /* Numeric constant */ g_inc (flags, Expr->IVal); } else { /* Constant address */ g_addaddr_static (flags, Expr->Name, Expr->IVal); } } else if (IsClassInt (lhst) && IsClassPtr (rhst)) { /* Left is int, right is pointer, must scale lhs. */ unsigned ScaleFactor = CheckedPSizeOf (rhst); /* Operate on pointers, result type is a pointer */ flags |= CF_PTR; Expr->Type = Expr2.Type; /* Since we do already have rhs in the primary, if lhs is ** not a numeric constant, and the scale factor is not one ** (no scaling), we must take the long way over the stack. */ if (ED_IsLocAbs (Expr)) { /* Numeric constant, scale lhs */ Expr->IVal *= ScaleFactor; /* Generate the code for the add */ g_inc (flags, Expr->IVal); } else if (ScaleFactor == 1) { /* Constant address but no need to scale */ g_addaddr_static (flags, Expr->Name, Expr->IVal); } else { /* Constant address that must be scaled */ g_push (TypeOf (Expr2.Type), 0); /* rhs --> stack */ g_getimmed (flags, Expr->Name, Expr->IVal); g_scale (CF_PTR, ScaleFactor); g_add (CF_PTR, 0); } } else if (IsClassInt (lhst) && IsClassInt (rhst)) { /* Integer addition */ flags |= typeadjust (Expr, &Expr2, 1); /* Generate the code for the add */ if (ED_IsLocAbs (Expr)) { /* Numeric constant */ g_inc (flags, Expr->IVal); } else { /* Constant address */ g_addaddr_static (flags, Expr->Name, Expr->IVal); } } else { /* OOPS */ Error ("Invalid operands for binary operator '+'"); flags = CF_INT; } /* Result is a rvalue in primary register */ ED_MakeRValExpr (Expr); } } else { /* Left hand side is not constant. Get the value onto the stack. */ LoadExpr (CF_NONE, Expr); /* --> primary register */ GetCodePos (&Mark); g_push (TypeOf (Expr->Type), 0); /* --> stack */ /* Evaluate the rhs */ MarkedExprWithCheck (hie9, &Expr2); /* Check for a constant rhs expression */ if (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) { /* Right hand side is a constant. Get the rhs type */ rhst = Expr2.Type; /* Remove pushed value from stack */ RemoveCode (&Mark); /* Check for pointer arithmetic */ if (IsClassPtr (lhst) && IsClassInt (rhst)) { /* Left is pointer, right is int, must scale rhs */ Expr2.IVal *= CheckedPSizeOf (lhst); /* Operate on pointers, result type is a pointer */ flags = CF_PTR; } else if (IsClassInt (lhst) && IsClassPtr (rhst)) { /* Left is int, right is pointer, must scale lhs (ptr only) */ g_scale (CF_INT | CF_CONST, CheckedPSizeOf (rhst)); /* Operate on pointers, result type is a pointer */ flags = CF_PTR; Expr->Type = Expr2.Type; } else if (IsClassInt (lhst) && IsClassInt (rhst)) { /* Integer addition */ flags = typeadjust (Expr, &Expr2, 1); } else { /* OOPS */ Error ("Invalid operands for binary operator '+'"); flags = CF_INT; } /* Generate code for the add */ g_inc (flags | CF_CONST, Expr2.IVal); } else { /* Not constant, load into the primary */ LoadExpr (CF_NONE, &Expr2); /* lhs and rhs are not constant. Get the rhs type. */ rhst = Expr2.Type; /* Check for pointer arithmetic */ if (IsClassPtr (lhst) && IsClassInt (rhst)) { /* Left is pointer, right is int, must scale rhs */ g_scale (CF_INT, CheckedPSizeOf (lhst)); /* Operate on pointers, result type is a pointer */ flags = CF_PTR; } else if (IsClassInt (lhst) && IsClassPtr (rhst)) { /* Left is int, right is pointer, must scale lhs */ 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 */ flags = CF_PTR; Expr->Type = Expr2.Type; } else if (IsClassInt (lhst) && IsClassInt (rhst)) { /* Integer addition. Note: Result is never constant. ** Problem here is that typeadjust does not know if the ** variable is an rvalue or lvalue, so if both operands ** are dereferenced constant numeric addresses, typeadjust ** thinks the operation works on constants. Removing ** CF_CONST here means handling the symptoms, however, the ** whole parser is such a mess that I fear to break anything ** when trying to apply another solution. */ flags = typeadjust (Expr, &Expr2, 0) & ~CF_CONST; } else { /* OOPS */ Error ("Invalid operands for binary operator '+'"); flags = CF_INT; } /* Generate code for the add */ g_add (flags, 0); } /* Result is a rvalue in primary register */ ED_MakeRValExpr (Expr); } /* Condition codes not set */ ED_MarkAsUntested (Expr); } static void parsesub (ExprDesc* Expr) /* Parse an expression with the binary minus operator. Expr contains the ** unprocessed left hand side of the expression and will contain the ** result of the expression on return. */ { ExprDesc Expr2; unsigned flags; /* Operation flags */ Type* lhst; /* Type of left hand side */ Type* rhst; /* Type of right hand side */ CodeMark Mark1; /* Save position of output queue */ CodeMark Mark2; /* Another position in the queue */ 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 (); /* Get the left hand side type, initialize operation flags */ lhst = Expr->Type; rscale = 1; /* Scale by 1, that is, don't scale */ /* Remember the output queue position, then bring the value onto the stack */ GetCodePos (&Mark1); LoadExpr (CF_NONE, Expr); /* --> primary register */ GetCodePos (&Mark2); g_push (TypeOf (lhst), 0); /* --> stack */ /* 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)) { /* The right hand side is constant. Get the rhs type. */ rhst = Expr2.Type; /* Check left hand side */ if (ED_IsConstAbs (Expr)) { /* Both sides are constant, remove generated code */ RemoveCode (&Mark1); /* Check for pointer arithmetic */ if (IsClassPtr (lhst) && IsClassInt (rhst)) { /* Left is pointer, right is int, must scale rhs */ Expr->IVal -= Expr2.IVal * CheckedPSizeOf (lhst); /* Operate on pointers, result type is a pointer */ } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) { /* Left is pointer, right is pointer, must scale result */ if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_QUAL_DIFF) { Error ("Incompatible pointer types"); } else { Expr->IVal = (Expr->IVal - Expr2.IVal) / CheckedPSizeOf (lhst); } /* Operate on pointers, result type is an integer */ Expr->Type = type_int; } else if (IsClassInt (lhst) && IsClassInt (rhst)) { /* Integer subtraction */ typeadjust (Expr, &Expr2, 1); Expr->IVal -= Expr2.IVal; } else { /* OOPS */ Error ("Invalid operands for binary operator '-'"); } /* Result is constant, condition codes not set */ ED_MarkAsUntested (Expr); } else { /* Left hand side is not constant, right hand side is. ** Remove pushed value from stack. */ RemoveCode (&Mark2); if (IsClassPtr (lhst) && IsClassInt (rhst)) { /* Left is pointer, right is int, must scale rhs */ Expr2.IVal *= CheckedPSizeOf (lhst); /* Operate on pointers, result type is a pointer */ flags = CF_PTR; } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) { /* Left is pointer, right is pointer, must scale result */ if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_QUAL_DIFF) { Error ("Incompatible pointer types"); } else { rscale = CheckedPSizeOf (lhst); } /* Operate on pointers, result type is an integer */ flags = CF_PTR; Expr->Type = type_int; } else if (IsClassInt (lhst) && IsClassInt (rhst)) { /* Integer subtraction */ flags = typeadjust (Expr, &Expr2, 1); } else { /* OOPS */ Error ("Invalid operands for binary operator '-'"); flags = CF_INT; } /* Do the subtraction */ g_dec (flags | CF_CONST, Expr2.IVal); /* If this was a pointer subtraction, we must scale the result */ if (rscale != 1) { g_scale (flags, -rscale); } /* Result is a rvalue in the primary register */ ED_MakeRValExpr (Expr); ED_MarkAsUntested (Expr); } } else { /* Not constant, load into the primary */ LoadExpr (CF_NONE, &Expr2); /* Right hand side is not constant. Get the rhs type. */ rhst = Expr2.Type; /* Check for pointer arithmetic */ if (IsClassPtr (lhst) && IsClassInt (rhst)) { /* Left is pointer, right is int, must scale rhs */ g_scale (CF_INT, CheckedPSizeOf (lhst)); /* Operate on pointers, result type is a pointer */ flags = CF_PTR; } else if (IsClassPtr (lhst) && IsClassPtr (rhst)) { /* Left is pointer, right is pointer, must scale result */ if (TypeCmp (Indirect (lhst), Indirect (rhst)) < TC_QUAL_DIFF) { Error ("Incompatible pointer types"); } else { rscale = CheckedPSizeOf (lhst); } /* Operate on pointers, result type is an integer */ flags = CF_PTR; Expr->Type = type_int; } else if (IsClassInt (lhst) && IsClassInt (rhst)) { /* Integer subtraction. If the left hand side descriptor says that ** the lhs is const, we have to remove this mark, since this is no ** longer true, lhs is on stack instead. */ if (ED_IsLocAbs (Expr)) { ED_MakeRValExpr (Expr); } /* Adjust operand types */ flags = typeadjust (Expr, &Expr2, 0); } else { /* OOPS */ Error ("Invalid operands for binary operator '-'"); flags = CF_INT; } /* Generate code for the sub (the & is a hack here) */ g_sub (flags & ~CF_CONST, 0); /* If this was a pointer subtraction, we must scale the result */ if (rscale != 1) { g_scale (flags, -rscale); } /* Result is a rvalue in the primary register */ ED_MakeRValExpr (Expr); ED_MarkAsUntested (Expr); } } void hie8 (ExprDesc* Expr) /* Process + and - binary operators. */ { ExprWithCheck (hie9, Expr); while (CurTok.Tok == TOK_PLUS || CurTok.Tok == TOK_MINUS) { if (CurTok.Tok == TOK_PLUS) { parseadd (Expr); } else { parsesub (Expr); } } } static void hie6 (ExprDesc* Expr) /* Handle greater-than type comparators */ { static const GenDesc hie6_ops [] = { { 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); } static void hie5 (ExprDesc* Expr) /* Handle == and != */ { static const GenDesc hie5_ops[] = { { TOK_EQ, GEN_NOPUSH, g_eq }, { TOK_NE, GEN_NOPUSH, g_ne }, { TOK_INVALID, 0, 0 } }; hie_compare (hie5_ops, Expr, hie6); } static void hie4 (ExprDesc* Expr) /* Handle & (bitwise and) */ { static const GenDesc hie4_ops[] = { { TOK_AND, GEN_NOPUSH | GEN_COMM, g_and }, { TOK_INVALID, 0, 0 } }; int UsedGen; hie_internal (hie4_ops, Expr, hie5, &UsedGen); } static void hie3 (ExprDesc* Expr) /* Handle ^ (bitwise exclusive or) */ { static const GenDesc hie3_ops[] = { { TOK_XOR, GEN_NOPUSH | GEN_COMM, g_xor }, { TOK_INVALID, 0, 0 } }; int UsedGen; hie_internal (hie3_ops, Expr, hie4, &UsedGen); } static void hie2 (ExprDesc* Expr) /* Handle | (bitwise or) */ { static const GenDesc hie2_ops[] = { { TOK_OR, GEN_NOPUSH | GEN_COMM, g_or }, { TOK_INVALID, 0, 0 } }; int UsedGen; hie_internal (hie2_ops, Expr, hie3, &UsedGen); } static void hieAndPP (ExprDesc* Expr) /* Process "exp && exp" in preprocessor mode (that is, when the parser is ** called recursively from the preprocessor. */ { ExprDesc Expr2; ConstAbsIntExpr (hie2, Expr); while (CurTok.Tok == TOK_BOOL_AND) { /* Skip the && */ NextToken (); /* Get rhs */ ConstAbsIntExpr (hie2, &Expr2); /* Combine the two */ Expr->IVal = (Expr->IVal && Expr2.IVal); } } static void hieOrPP (ExprDesc *Expr) /* Process "exp || exp" in preprocessor mode (that is, when the parser is ** called recursively from the preprocessor. */ { ExprDesc Expr2; ConstAbsIntExpr (hieAndPP, Expr); while (CurTok.Tok == TOK_BOOL_OR) { /* Skip the && */ NextToken (); /* Get rhs */ ConstAbsIntExpr (hieAndPP, &Expr2); /* Combine the two */ Expr->IVal = (Expr->IVal || Expr2.IVal); } } static void hieAnd (ExprDesc* Expr, unsigned TrueLab, int* BoolOp) /* Process "exp && exp" */ { int FalseLab; ExprDesc Expr2; ExprWithCheck (hie2, Expr); if (CurTok.Tok == TOK_BOOL_AND) { /* Tell our caller that we're evaluating a boolean */ *BoolOp = 1; /* Get a label that we will use for false expressions */ FalseLab = GetLocalLabel (); /* If the expr hasn't set condition codes, set the force-test flag */ if (!ED_IsTested (Expr)) { ED_MarkForTest (Expr); } /* Load the value */ LoadExpr (CF_FORCECHAR, Expr); /* Generate the jump */ g_falsejump (CF_NONE, FalseLab); /* Parse more boolean and's */ while (CurTok.Tok == TOK_BOOL_AND) { /* Skip the && */ NextToken (); /* Get rhs */ hie2 (&Expr2); if (!ED_IsTested (&Expr2)) { ED_MarkForTest (&Expr2); } LoadExpr (CF_FORCECHAR, &Expr2); /* Do short circuit evaluation */ if (CurTok.Tok == TOK_BOOL_AND) { g_falsejump (CF_NONE, FalseLab); } else { /* Last expression - will evaluate to true */ g_truejump (CF_NONE, TrueLab); } } /* Define the false jump label here */ g_defcodelabel (FalseLab); /* The result is an rvalue in primary */ ED_MakeRValExpr (Expr); ED_TestDone (Expr); /* Condition codes are set */ } } static void hieOr (ExprDesc *Expr) /* Process "exp || exp". */ { ExprDesc Expr2; int BoolOp = 0; /* Did we have a boolean op? */ int AndOp; /* Did we have a && operation? */ unsigned TrueLab; /* Jump to this label if true */ unsigned DoneLab; /* Get a label */ TrueLab = GetLocalLabel (); /* Call the next level parser */ hieAnd (Expr, TrueLab, &BoolOp); /* Any boolean or's? */ if (CurTok.Tok == TOK_BOOL_OR) { /* If the expr hasn't set condition codes, set the force-test flag */ if (!ED_IsTested (Expr)) { ED_MarkForTest (Expr); } /* Get first expr */ LoadExpr (CF_FORCECHAR, Expr); /* For each expression jump to TrueLab if true. Beware: If we ** had && operators, the jump is already in place! */ if (!BoolOp) { g_truejump (CF_NONE, TrueLab); } /* Remember that we had a boolean op */ BoolOp = 1; /* while there's more expr */ while (CurTok.Tok == TOK_BOOL_OR) { /* skip the || */ NextToken (); /* Get a subexpr */ AndOp = 0; hieAnd (&Expr2, TrueLab, &AndOp); if (!ED_IsTested (&Expr2)) { ED_MarkForTest (&Expr2); } LoadExpr (CF_FORCECHAR, &Expr2); /* If there is more to come, add shortcut boolean eval. */ g_truejump (CF_NONE, TrueLab); } /* The result is an rvalue in primary */ ED_MakeRValExpr (Expr); ED_TestDone (Expr); /* Condition codes are set */ } /* If we really had boolean ops, generate the end sequence */ if (BoolOp) { DoneLab = GetLocalLabel (); g_getimmed (CF_INT | CF_CONST, 0, 0); /* Load FALSE */ g_falsejump (CF_NONE, DoneLab); g_defcodelabel (TrueLab); g_getimmed (CF_INT | CF_CONST, 1, 0); /* Load TRUE */ g_defcodelabel (DoneLab); } } static void hieQuest (ExprDesc* Expr) /* Parse the ternary operator */ { int FalseLab; int TrueLab; CodeMark TrueCodeEnd; ExprDesc Expr2; /* Expression 2 */ ExprDesc Expr3; /* Expression 3 */ int Expr2IsNULL; /* Expression 2 is a NULL pointer */ int Expr3IsNULL; /* Expression 3 is a NULL pointer */ Type* ResultType; /* Type of result */ /* Call the lower level eval routine */ if (Preprocessing) { ExprWithCheck (hieOrPP, Expr); } else { ExprWithCheck (hieOr, Expr); } /* Check if it's a ternary expression */ if (CurTok.Tok == TOK_QUEST) { NextToken (); if (!ED_IsTested (Expr)) { /* Condition codes not set, request a test */ ED_MarkForTest (Expr); } LoadExpr (CF_NONE, Expr); FalseLab = GetLocalLabel (); g_falsejump (CF_NONE, FalseLab); /* Parse second expression. Remember for later if it is a NULL pointer ** expression, then load it into the primary. */ ExprWithCheck (hie1, &Expr2); Expr2IsNULL = ED_IsNullPtr (&Expr2); if (!IsTypeVoid (Expr2.Type)) { /* Load it into the primary */ LoadExpr (CF_NONE, &Expr2); ED_MakeRValExpr (&Expr2); Expr2.Type = PtrConversion (Expr2.Type); } /* Remember the current code position */ GetCodePos (&TrueCodeEnd); /* Jump around the evaluation of the third expression */ TrueLab = GetLocalLabel (); ConsumeColon (); g_jump (TrueLab); /* Jump here if the first expression was false */ g_defcodelabel (FalseLab); /* Parse third expression. Remember for later if it is a NULL pointer ** expression, then load it into the primary. */ ExprWithCheck (hie1, &Expr3); Expr3IsNULL = ED_IsNullPtr (&Expr3); if (!IsTypeVoid (Expr3.Type)) { /* Load it into the primary */ LoadExpr (CF_NONE, &Expr3); ED_MakeRValExpr (&Expr3); Expr3.Type = PtrConversion (Expr3.Type); } /* Check if any conversions are needed, if so, do them. ** Conversion rules for ?: expression are: ** - if both expressions are int expressions, default promotion ** rules for ints apply. ** - if both expressions are pointers of the same type, the ** result of the expression is of this type. ** - if one of the expressions is a pointer and the other is ** a zero constant, the resulting type is that of the pointer ** type. ** - if both expressions are void expressions, the result is of ** type void. ** - all other cases are flagged by an error. */ if (IsClassInt (Expr2.Type) && IsClassInt (Expr3.Type)) { CodeMark CvtCodeStart; CodeMark CvtCodeEnd; /* Get common type */ ResultType = promoteint (Expr2.Type, Expr3.Type); /* Convert the third expression to this type if needed */ TypeConversion (&Expr3, ResultType); /* Emit conversion code for the second expression, but remember ** where it starts end ends. */ GetCodePos (&CvtCodeStart); TypeConversion (&Expr2, ResultType); GetCodePos (&CvtCodeEnd); /* If we had conversion code, move it to the right place */ if (!CodeRangeIsEmpty (&CvtCodeStart, &CvtCodeEnd)) { MoveCode (&CvtCodeStart, &CvtCodeEnd, &TrueCodeEnd); } } else if (IsClassPtr (Expr2.Type) && IsClassPtr (Expr3.Type)) { /* Must point to same type */ if (TypeCmp (Indirect (Expr2.Type), Indirect (Expr3.Type)) < TC_EQUAL) { Error ("Incompatible pointer types"); } /* Result has the common type */ ResultType = Expr2.Type; } else if (IsClassPtr (Expr2.Type) && Expr3IsNULL) { /* Result type is pointer, no cast needed */ ResultType = Expr2.Type; } else if (Expr2IsNULL && IsClassPtr (Expr3.Type)) { /* Result type is pointer, no cast needed */ ResultType = Expr3.Type; } else if (IsTypeVoid (Expr2.Type) && IsTypeVoid (Expr3.Type)) { /* Result type is void */ ResultType = Expr3.Type; } else { Error ("Incompatible types"); ResultType = Expr2.Type; /* Doesn't matter here */ } /* Define the final label */ g_defcodelabel (TrueLab); /* Setup the target expression */ ED_MakeRValExpr (Expr); Expr->Type = ResultType; } } static void opeq (const GenDesc* Gen, ExprDesc* Expr, const char* Op) /* Process "op=" operators. */ { ExprDesc Expr2; unsigned flags; CodeMark Mark; int MustScale; /* op= can only be used with lvalues */ if (!ED_IsLVal (Expr)) { Error ("Invalid lvalue in assignment"); return; } /* The left side must not be const qualified */ if (IsQualConst (Expr->Type)) { Error ("Assignment to const"); } /* There must be an integer or pointer on the left side */ if (!IsClassInt (Expr->Type) && !IsTypePtr (Expr->Type)) { Error ("Invalid left operand type"); /* Continue. Wrong code will be generated, but the compiler won't ** break, so this is the best error recovery. */ } /* Skip the operator token */ NextToken (); /* Determine the type of the lhs */ flags = TypeOf (Expr->Type); MustScale = (Gen->Func == g_add || Gen->Func == g_sub) && IsTypePtr (Expr->Type); /* Get the lhs address on stack (if needed) */ PushAddr (Expr); /* Fetch the lhs into the primary register if needed */ LoadExpr (CF_NONE, Expr); /* Bring the lhs on stack */ GetCodePos (&Mark); g_push (flags, 0); /* Evaluate the rhs */ MarkedExprWithCheck (hie1, &Expr2); /* The rhs must be an integer (or a float, but we don't support that yet */ if (!IsClassInt (Expr2.Type)) { Error ("Invalid right operand for binary operator '%s'", Op); /* Continue. Wrong code will be generated, but the compiler won't ** break, so this is the best error recovery. */ } /* Check for a constant expression */ if (ED_IsConstAbs (&Expr2) && ED_CodeRangeIsEmpty (&Expr2)) { /* The resulting value is a constant. If the generator has the NOPUSH ** flag set, don't push the lhs. */ if (Gen->Flags & GEN_NOPUSH) { RemoveCode (&Mark); } if (MustScale) { /* lhs is a pointer, scale rhs */ Expr2.IVal *= CheckedSizeOf (Expr->Type+1); } /* If the lhs is character sized, the operation may be later done ** with characters. */ if (CheckedSizeOf (Expr->Type) == SIZEOF_CHAR) { flags |= CF_FORCECHAR; } /* Special handling for add and sub - some sort of a hack, but short code */ if (Gen->Func == g_add) { g_inc (flags | CF_CONST, Expr2.IVal); } else if (Gen->Func == g_sub) { g_dec (flags | CF_CONST, Expr2.IVal); } else { if (Expr2.IVal == 0) { /* Check for div by zero/mod by zero */ if (Gen->Func == g_div) { Error ("Division by zero"); } else if (Gen->Func == g_mod) { Error ("Modulo operation with zero"); } } Gen->Func (flags | CF_CONST, Expr2.IVal); } } else { /* rhs is not constant. Load into the primary */ LoadExpr (CF_NONE, &Expr2); if (MustScale) { /* lhs is a pointer, scale rhs */ g_scale (TypeOf (Expr2.Type), CheckedSizeOf (Expr->Type+1)); } /* If the lhs is character sized, the operation may be later done ** with characters. */ if (CheckedSizeOf (Expr->Type) == SIZEOF_CHAR) { flags |= CF_FORCECHAR; } /* Adjust the types of the operands if needed */ Gen->Func (g_typeadjust (flags, TypeOf (Expr2.Type)), 0); } Store (Expr, 0); ED_MakeRValExpr (Expr); } static void addsubeq (const GenDesc* Gen, ExprDesc *Expr, const char* Op) /* Process the += and -= operators */ { ExprDesc Expr2; unsigned lflags; unsigned rflags; int MustScale; /* We're currently only able to handle some adressing modes */ if (ED_GetLoc (Expr) == E_LOC_EXPR || ED_GetLoc (Expr) == E_LOC_PRIMARY) { /* Use generic routine */ opeq (Gen, Expr, Op); return; } /* We must have an lvalue */ if (ED_IsRVal (Expr)) { Error ("Invalid lvalue in assignment"); return; } /* The left side must not be const qualified */ if (IsQualConst (Expr->Type)) { Error ("Assignment to const"); } /* There must be an integer or pointer on the left side */ if (!IsClassInt (Expr->Type) && !IsTypePtr (Expr->Type)) { Error ("Invalid left operand type"); /* Continue. Wrong code will be generated, but the compiler won't ** break, so this is the best error recovery. */ } /* Skip the operator */ NextToken (); /* Check if we have a pointer expression and must scale rhs */ MustScale = IsTypePtr (Expr->Type); /* Initialize the code generator flags */ lflags = 0; rflags = 0; /* Evaluate the rhs. We expect an integer here, since float is not ** supported */ hie1 (&Expr2); if (!IsClassInt (Expr2.Type)) { Error ("Invalid right operand for binary operator '%s'", Op); /* Continue. Wrong code will be generated, but the compiler won't ** break, so this is the best error recovery. */ } if (ED_IsConstAbs (&Expr2)) { /* The resulting value is a constant. Scale it. */ if (MustScale) { Expr2.IVal *= CheckedSizeOf (Indirect (Expr->Type)); } rflags |= CF_CONST; lflags |= CF_CONST; } else { /* Not constant, load into the primary */ LoadExpr (CF_NONE, &Expr2); if (MustScale) { /* lhs is a pointer, scale rhs */ g_scale (TypeOf (Expr2.Type), CheckedSizeOf (Indirect (Expr->Type))); } } /* Setup the code generator flags */ lflags |= TypeOf (Expr->Type) | GlobalModeFlags (Expr) | CF_FORCECHAR; rflags |= TypeOf (Expr2.Type) | CF_FORCECHAR; /* Convert the type of the lhs to that of the rhs */ g_typecast (lflags, rflags); /* Output apropriate code depending on the location */ switch (ED_GetLoc (Expr)) { case E_LOC_ABS: /* Absolute: numeric address or const */ if (Gen->Tok == TOK_PLUS_ASSIGN) { g_addeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal); } else { g_subeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal); } break; case E_LOC_GLOBAL: /* Global variable */ if (Gen->Tok == TOK_PLUS_ASSIGN) { g_addeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal); } else { g_subeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal); } break; case E_LOC_STATIC: case E_LOC_LITERAL: /* Static variable or literal in the literal pool */ if (Gen->Tok == TOK_PLUS_ASSIGN) { g_addeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal); } else { g_subeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal); } break; case E_LOC_REGISTER: /* Register variable */ if (Gen->Tok == TOK_PLUS_ASSIGN) { g_addeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal); } else { g_subeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal); } break; case E_LOC_STACK: /* Value on the stack */ if (Gen->Tok == TOK_PLUS_ASSIGN) { g_addeqlocal (lflags, Expr->IVal, Expr2.IVal); } else { g_subeqlocal (lflags, Expr->IVal, Expr2.IVal); } break; default: Internal ("Invalid location in Store(): 0x%04X", ED_GetLoc (Expr)); } /* Expression is a rvalue in the primary now */ ED_MakeRValExpr (Expr); } void hie1 (ExprDesc* Expr) /* Parse first level of expression hierarchy. */ { hieQuest (Expr); switch (CurTok.Tok) { case TOK_ASSIGN: Assignment (Expr); break; case TOK_PLUS_ASSIGN: addsubeq (&GenPASGN, Expr, "+="); break; case TOK_MINUS_ASSIGN: addsubeq (&GenSASGN, Expr, "-="); break; case TOK_MUL_ASSIGN: opeq (&GenMASGN, Expr, "*="); break; case TOK_DIV_ASSIGN: opeq (&GenDASGN, Expr, "/="); break; case TOK_MOD_ASSIGN: opeq (&GenMOASGN, Expr, "%="); break; case TOK_SHL_ASSIGN: opeq (&GenSLASGN, Expr, "<<="); break; case TOK_SHR_ASSIGN: opeq (&GenSRASGN, Expr, ">>="); break; case TOK_AND_ASSIGN: opeq (&GenAASGN, Expr, "&="); break; case TOK_XOR_ASSIGN: opeq (&GenXOASGN, Expr, "^="); break; case TOK_OR_ASSIGN: opeq (&GenOASGN, Expr, "|="); break; default: break; } } void hie0 (ExprDesc *Expr) /* Parse comma operator. */ { hie1 (Expr); while (CurTok.Tok == TOK_COMMA) { NextToken (); hie1 (Expr); } } int evalexpr (unsigned Flags, void (*Func) (ExprDesc*), ExprDesc* Expr) /* Will evaluate an expression via the given function. If the result is a ** constant, 0 is returned and the value is put in the Expr struct. If the ** result is not constant, LoadExpr is called to bring the value into the ** primary register and 1 is returned. */ { /* Evaluate */ ExprWithCheck (Func, Expr); /* Check for a constant expression */ if (ED_IsConstAbs (Expr)) { /* Constant expression */ return 0; } else { /* Not constant, load into the primary */ LoadExpr (Flags, Expr); return 1; } } void Expression0 (ExprDesc* Expr) /* Evaluate an expression via hie0 and put the result into the primary register */ { ExprWithCheck (hie0, Expr); LoadExpr (CF_NONE, Expr); } void ConstExpr (void (*Func) (ExprDesc*), ExprDesc* Expr) /* Will evaluate an expression via the given function. If the result is not ** a constant of some sort, a diagnostic will be printed, and the value is ** replaced by a constant one to make sure there are no internal errors that ** result from this input error. */ { ExprWithCheck (Func, Expr); if (!ED_IsConst (Expr)) { Error ("Constant expression expected"); /* To avoid any compiler errors, make the expression a valid const */ ED_MakeConstAbsInt (Expr, 1); } } void BoolExpr (void (*Func) (ExprDesc*), ExprDesc* Expr) /* Will evaluate an expression via the given function. If the result is not ** something that may be evaluated in a boolean context, a diagnostic will be ** printed, and the value is replaced by a constant one to make sure there ** are no internal errors that result from this input error. */ { ExprWithCheck (Func, Expr); if (!ED_IsBool (Expr)) { Error ("Boolean expression expected"); /* To avoid any compiler errors, make the expression a valid int */ ED_MakeConstAbsInt (Expr, 1); } } void ConstAbsIntExpr (void (*Func) (ExprDesc*), ExprDesc* Expr) /* Will evaluate an expression via the given function. If the result is not ** a constant numeric integer value, a diagnostic will be printed, and the ** value is replaced by a constant one to make sure there are no internal ** errors that result from this input error. */ { ExprWithCheck (Func, Expr); if (!ED_IsConstAbsInt (Expr)) { Error ("Constant integer expression expected"); /* To avoid any compiler errors, make the expression a valid const */ ED_MakeConstAbsInt (Expr, 1); } } ���������������������������������������������������������������������������������cc65-2.18/src/cc65/expr.h���������������������������������������������������������������������������0000664�0000000�0000000�00000005700�13473601511�0014665�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** expr.h ** ** Ullrich von Bassewitz, 21.06.1998 */ #ifndef EXPR_H #define EXPR_H /* cc65 */ #include "datatype.h" #include "exprdesc.h" /*****************************************************************************/ /* code */ /*****************************************************************************/ void ExprWithCheck (void (*Func) (ExprDesc*), ExprDesc* Expr); /* Call an expression function with checks. */ void MarkedExprWithCheck (void (*Func) (ExprDesc*), ExprDesc* Expr); /* Call an expression function with checks and record start and end of the ** generated code. */ void PushAddr (const ExprDesc* Expr); /* If the expression contains an address that was somehow evaluated, ** push this address on the stack. This is a helper function for all ** sorts of implicit or explicit assignment functions where the lvalue ** must be saved if it's not constant, before evaluating the rhs. */ void Store (ExprDesc* Expr, const Type* StoreType); /* Store the primary register into the location denoted by lval. If StoreType ** is given, use this type when storing instead of lval->Type. If StoreType ** is NULL, use lval->Type instead. */ int evalexpr (unsigned flags, void (*Func) (ExprDesc*), ExprDesc* Expr); /* Will evaluate an expression via the given function. If the result is a ** constant, 0 is returned and the value is put in the Expr struct. If the ** result is not constant, LoadExpr is called to bring the value into the ** primary register and 1 is returned. */ void Expression0 (ExprDesc* Expr); /* Evaluate an expression via hie0 and put the result into the primary register */ void ConstExpr (void (*Func) (ExprDesc*), ExprDesc* Expr); /* Will evaluate an expression via the given function. If the result is not ** a constant of some sort, a diagnostic will be printed, and the value is ** replaced by a constant one to make sure there are no internal errors that ** result from this input error. */ void BoolExpr (void (*Func) (ExprDesc*), ExprDesc* Expr); /* Will evaluate an expression via the given function. If the result is not ** something that may be evaluated in a boolean context, a diagnostic will be ** printed, and the value is replaced by a constant one to make sure there ** are no internal errors that result from this input error. */ void ConstAbsIntExpr (void (*Func) (ExprDesc*), ExprDesc* Expr); /* Will evaluate an expression via the given function. If the result is not ** a constant numeric integer value, a diagnostic will be printed, and the ** value is replaced by a constant one to make sure there are no internal ** errors that result from this input error. */ void hie10 (ExprDesc* lval); /* Handle ++, --, !, unary - etc. */ void hie8 (ExprDesc* Expr); /* Process + and - binary operators. */ void hie1 (ExprDesc* lval); /* Parse first level of expression hierarchy. */ void hie0 (ExprDesc* Expr); /* Parse comma operator. */ /* End of expr.h */ #endif ����������������������������������������������������������������cc65-2.18/src/cc65/exprdesc.c�����������������������������������������������������������������������0000664�0000000�0000000�00000026173�13473601511�0015526�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* exprdesc.c */ /* */ /* Expression descriptor structure */ /* */ /* */ /* */ /* (C) 2002-2010, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "check.h" #include "strbuf.h" /* cc65 */ #include "asmlabel.h" #include "datatype.h" #include "error.h" #include "exprdesc.h" #include "stackptr.h" #include "symentry.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ ExprDesc* ED_Init (ExprDesc* Expr) /* Initialize an ExprDesc */ { Expr->Sym = 0; Expr->Type = 0; Expr->Flags = 0; Expr->Name = 0; Expr->IVal = 0; Expr->FVal = FP_D_Make (0.0); Expr->LVal = 0; Expr->BitOffs = 0; Expr->BitWidth = 0; return Expr; } void ED_MakeBitField (ExprDesc* Expr, unsigned BitOffs, unsigned BitWidth) /* Make this expression a bit field expression */ { Expr->Flags |= E_BITFIELD; Expr->BitOffs = BitOffs; Expr->BitWidth = BitWidth; } void ED_SetCodeRange (ExprDesc* Expr, const CodeMark* Start, const CodeMark* End) /* Set the code range for this expression */ { Expr->Flags |= E_HAVE_MARKS; Expr->Start = *Start; Expr->End = *End; } int ED_CodeRangeIsEmpty (const ExprDesc* Expr) /* Return true if no code was output for this expression */ { /* We must have code marks */ PRECONDITION (Expr->Flags & E_HAVE_MARKS); return CodeRangeIsEmpty (&Expr->Start, &Expr->End); } const char* ED_GetLabelName (const ExprDesc* Expr, long Offs) /* Return the assembler label name of the given expression. Beware: This ** function may use a static buffer, so the name may get "lost" on the second ** call to the function. */ { static StrBuf Buf = STATIC_STRBUF_INITIALIZER; /* Expr may have it's own offset, adjust Offs accordingly */ Offs += Expr->IVal; /* Generate a label depending on the location */ switch (ED_GetLoc (Expr)) { case E_LOC_ABS: /* Absolute: numeric address or const */ SB_Printf (&Buf, "$%04X", (int)(Offs & 0xFFFF)); break; case E_LOC_GLOBAL: case E_LOC_STATIC: /* Global or static variable */ if (Offs) { SB_Printf (&Buf, "%s%+ld", SymGetAsmName (Expr->Sym), Offs); } else { SB_Printf (&Buf, "%s", SymGetAsmName (Expr->Sym)); } break; case E_LOC_REGISTER: /* Register variable */ SB_Printf (&Buf, "regbank+%u", (unsigned)((Offs + Expr->Name) & 0xFFFFU)); break; case E_LOC_LITERAL: /* Literal in the literal pool */ if (Offs) { SB_Printf (&Buf, "%s%+ld", LocalLabelName (Expr->Name), Offs); } else { SB_Printf (&Buf, "%s", LocalLabelName (Expr->Name)); } break; default: Internal ("Invalid location in ED_GetLabelName: 0x%04X", ED_GetLoc (Expr)); } /* Return a pointer to the static buffer */ return SB_GetConstBuf (&Buf); } int ED_GetStackOffs (const ExprDesc* Expr, int Offs) /* Get the stack offset of an address on the stack in Expr taking into account ** an additional offset in Offs. */ { PRECONDITION (ED_IsLocStack (Expr)); Offs += ((int) Expr->IVal) - StackPtr; CHECK (Offs >= 0); /* Cannot handle negative stack offsets */ return Offs; } ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, Type* Type) /* Make Expr an absolute const with the given value and type. */ { Expr->Sym = 0; Expr->Type = Type; Expr->Flags = E_LOC_ABS | E_RTYPE_RVAL | (Expr->Flags & E_HAVE_MARKS); Expr->Name = 0; Expr->IVal = Value; Expr->FVal = FP_D_Make (0.0); return Expr; } ExprDesc* ED_MakeConstAbsInt (ExprDesc* Expr, long Value) /* Make Expr a constant integer expression with the given value */ { Expr->Sym = 0; Expr->Type = type_int; Expr->Flags = E_LOC_ABS | E_RTYPE_RVAL | (Expr->Flags & E_HAVE_MARKS); Expr->Name = 0; Expr->IVal = Value; Expr->FVal = FP_D_Make (0.0); return Expr; } ExprDesc* ED_MakeRValExpr (ExprDesc* Expr) /* Convert Expr into a rvalue which is in the primary register without an ** offset. */ { Expr->Sym = 0; Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE | E_BITFIELD | E_NEED_TEST | E_CC_SET); Expr->Flags |= (E_LOC_EXPR | E_RTYPE_RVAL); Expr->Name = 0; Expr->IVal = 0; /* No offset */ Expr->FVal = FP_D_Make (0.0); return Expr; } ExprDesc* ED_MakeLValExpr (ExprDesc* Expr) /* Convert Expr into a lvalue which is in the primary register without an ** offset. */ { Expr->Sym = 0; Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE | E_BITFIELD | E_NEED_TEST | E_CC_SET); Expr->Flags |= (E_LOC_EXPR | E_RTYPE_LVAL); Expr->Name = 0; Expr->IVal = 0; /* No offset */ Expr->FVal = FP_D_Make (0.0); return Expr; } int ED_IsConst (const ExprDesc* Expr) /* Return true if the expression denotes a constant of some sort. This can be a ** numeric constant, the address of a global variable (maybe with offset) or ** similar. */ { return ED_IsRVal (Expr) && (Expr->Flags & E_LOC_CONST) != 0; } int ED_IsConstAbsInt (const ExprDesc* Expr) /* Return true if the expression is a constant (numeric) integer. */ { return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL) && IsClassInt (Expr->Type); } int ED_IsNullPtr (const ExprDesc* Expr) /* Return true if the given expression is a NULL pointer constant */ { return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE|E_BITFIELD)) == (E_LOC_ABS|E_RTYPE_RVAL) && Expr->IVal == 0 && IsClassInt (Expr->Type); } int ED_IsBool (const ExprDesc* Expr) /* Return true of the expression can be treated as a boolean, that is, it can ** be an operand to a compare operation. */ { /* Either ints, floats, or pointers can be used in a boolean context */ return IsClassInt (Expr->Type) || IsClassFloat (Expr->Type) || IsClassPtr (Expr->Type); } void PrintExprDesc (FILE* F, ExprDesc* E) /* Print an ExprDesc */ { unsigned Flags; char Sep; fprintf (F, "Symbol: %s\n", E->Sym? E->Sym->Name : "(none)"); if (E->Type) { fprintf (F, "Type: "); PrintType (F, E->Type); fprintf (F, "\nRaw type: "); PrintRawType (F, E->Type); } else { fprintf (F, "Type: (unknown)\n" "Raw type: (unknown)\n"); } fprintf (F, "IVal: 0x%08lX\n", E->IVal); fprintf (F, "FVal: %f\n", FP_D_ToFloat (E->FVal)); Flags = E->Flags; Sep = '('; fprintf (F, "Flags: 0x%04X ", Flags); if (Flags & E_LOC_ABS) { fprintf (F, "%cE_LOC_ABS", Sep); Flags &= ~E_LOC_ABS; Sep = ','; } if (Flags & E_LOC_GLOBAL) { fprintf (F, "%cE_LOC_GLOBAL", Sep); Flags &= ~E_LOC_GLOBAL; Sep = ','; } if (Flags & E_LOC_STATIC) { fprintf (F, "%cE_LOC_STATIC", Sep); Flags &= ~E_LOC_STATIC; Sep = ','; } if (Flags & E_LOC_REGISTER) { fprintf (F, "%cE_LOC_REGISTER", Sep); Flags &= ~E_LOC_REGISTER; Sep = ','; } if (Flags & E_LOC_STACK) { fprintf (F, "%cE_LOC_STACK", Sep); Flags &= ~E_LOC_STACK; Sep = ','; } if (Flags & E_LOC_PRIMARY) { fprintf (F, "%cE_LOC_PRIMARY", Sep); Flags &= ~E_LOC_PRIMARY; Sep = ','; } if (Flags & E_LOC_EXPR) { fprintf (F, "%cE_LOC_EXPR", Sep); Flags &= ~E_LOC_EXPR; Sep = ','; } if (Flags & E_LOC_LITERAL) { fprintf (F, "%cE_LOC_LITERAL", Sep); Flags &= ~E_LOC_LITERAL; Sep = ','; } if (Flags & E_RTYPE_LVAL) { fprintf (F, "%cE_RTYPE_LVAL", Sep); Flags &= ~E_RTYPE_LVAL; Sep = ','; } if (Flags & E_BITFIELD) { fprintf (F, "%cE_BITFIELD", Sep); Flags &= ~E_BITFIELD; Sep = ','; } if (Flags & E_NEED_TEST) { fprintf (F, "%cE_NEED_TEST", Sep); Flags &= ~E_NEED_TEST; Sep = ','; } if (Flags & E_CC_SET) { fprintf (F, "%cE_CC_SET", Sep); Flags &= ~E_CC_SET; Sep = ','; } if (Flags) { fprintf (F, "%c,0x%04X", Sep, Flags); Sep = ','; } if (Sep != '(') { fputc (')', F); } fprintf (F, "\nName: 0x%08lX\n", (unsigned long)E->Name); } Type* ReplaceType (ExprDesc* Expr, const Type* NewType) /* Replace the type of Expr by a copy of Newtype and return the old type string */ { Type* OldType = Expr->Type; Expr->Type = TypeDup (NewType); return OldType; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/exprdesc.h�����������������������������������������������������������������������0000664�0000000�0000000�00000031217�13473601511�0015526�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* exprdesc.h */ /* */ /* Expression descriptor structure */ /* */ /* */ /* */ /* (C) 2002-2010, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef EXPRDESC_H #define EXPRDESC_H #include <string.h> /* common */ #include "fp.h" #include "inline.h" #include "inttypes.h" /* cc65 */ #include "asmcode.h" #include "datatype.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Defines for the flags field of the expression descriptor */ enum { /* Location: Where is the value we're talking about? */ E_MASK_LOC = 0x00FF, E_LOC_ABS = 0x0001, /* Absolute: numeric address or const */ E_LOC_GLOBAL = 0x0002, /* Global variable */ E_LOC_STATIC = 0x0004, /* Static variable */ E_LOC_REGISTER = 0x0008, /* Register variable */ E_LOC_STACK = 0x0010, /* Value on the stack */ E_LOC_PRIMARY = 0x0020, /* The primary register */ E_LOC_EXPR = 0x0040, /* An expression in the primary register */ E_LOC_LITERAL = 0x0080, /* Literal in the literal pool */ /* Constant location of some sort (only if rval) */ E_LOC_CONST = E_LOC_ABS | E_LOC_GLOBAL | E_LOC_STATIC | E_LOC_REGISTER | E_LOC_LITERAL, /* Reference? */ E_MASK_RTYPE = 0x0100, E_RTYPE_RVAL = 0x0000, E_RTYPE_LVAL = 0x0100, /* Bit-field? */ E_BITFIELD = 0x0200, /* Test */ E_NEED_TEST = 0x0400, /* Expression needs a test to set cc */ E_CC_SET = 0x0800, /* Condition codes are set */ E_HAVE_MARKS = 0x1000, /* Code marks are valid */ }; /* Forward */ struct Literal; /* Describe the result of an expression */ typedef struct ExprDesc ExprDesc; struct ExprDesc { struct SymEntry* Sym; /* Symbol table entry if known */ Type* Type; /* Type array of expression */ unsigned Flags; uintptr_t Name; /* Name pointer or label number */ long IVal; /* Integer value if expression constant */ Double FVal; /* Floating point value */ struct Literal* LVal; /* Literal value */ /* Bit field stuff */ unsigned BitOffs; /* Bit offset for bit fields */ unsigned BitWidth; /* Bit width for bit fields */ /* Start and end of generated code */ CodeMark Start; CodeMark End; }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ ExprDesc* ED_Init (ExprDesc* Expr); /* Initialize an ExprDesc */ #if defined(HAVE_INLINE) INLINE int ED_GetLoc (const ExprDesc* Expr) /* Return the location flags from the expression */ { return (Expr->Flags & E_MASK_LOC); } #else # define ED_GetLoc(Expr) ((Expr)->Flags & E_MASK_LOC) #endif #if defined(HAVE_INLINE) INLINE int ED_IsLocAbs (const ExprDesc* Expr) /* Return true if the expression is an absolute value */ { return (Expr->Flags & E_MASK_LOC) == E_LOC_ABS; } #else # define ED_IsLocAbs(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_ABS) #endif #if defined(HAVE_INLINE) INLINE int ED_IsLocRegister (const ExprDesc* Expr) /* Return true if the expression is located in a register */ { return (Expr->Flags & E_MASK_LOC) == E_LOC_REGISTER; } #else # define ED_IsLocRegister(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_REGISTER) #endif #if defined(HAVE_INLINE) INLINE int ED_IsLocStack (const ExprDesc* Expr) /* Return true if the expression is located on the stack */ { return (Expr->Flags & E_MASK_LOC) == E_LOC_STACK; } #else # define ED_IsLocStack(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_STACK) #endif #if defined(HAVE_INLINE) INLINE int ED_IsLocPrimary (const ExprDesc* Expr) /* Return true if the expression is an expression in the register pseudo variable */ { return (Expr->Flags & E_MASK_LOC) == E_LOC_PRIMARY; } #else # define ED_IsLocPrimary(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_PRIMARY) #endif #if defined(HAVE_INLINE) INLINE int ED_IsLocExpr (const ExprDesc* Expr) /* Return true if the expression is an expression in the primary */ { return (Expr->Flags & E_MASK_LOC) == E_LOC_EXPR; } #else # define ED_IsLocExpr(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_EXPR) #endif #if defined(HAVE_INLINE) INLINE int ED_IsLocLiteral (const ExprDesc* Expr) /* Return true if the expression is a string from the literal pool */ { return (Expr->Flags & E_MASK_LOC) == E_LOC_LITERAL; } #else # define ED_IsLocLiteral(Expr) (((Expr)->Flags & E_MASK_LOC) == E_LOC_LITERAL) #endif #if defined(HAVE_INLINE) INLINE int ED_IsLocConst (const ExprDesc* Expr) /* Return true if the expression is a constant location of some sort */ { return (Expr->Flags & E_LOC_CONST) != 0; } #else # define ED_IsLocConst(Expr) (((Expr)->Flags & E_LOC_CONST) != 0) #endif #if defined(HAVE_INLINE) INLINE int ED_IsLVal (const ExprDesc* Expr) /* Return true if the expression is a reference */ { return (Expr->Flags & E_MASK_RTYPE) == E_RTYPE_LVAL; } #else # define ED_IsLVal(Expr) (((Expr)->Flags & E_MASK_RTYPE) == E_RTYPE_LVAL) #endif #if defined(HAVE_INLINE) INLINE int ED_IsRVal (const ExprDesc* Expr) /* Return true if the expression is a rvalue */ { return (Expr->Flags & E_MASK_RTYPE) == E_RTYPE_RVAL; } #else # define ED_IsRVal(Expr) (((Expr)->Flags & E_MASK_RTYPE) == E_RTYPE_RVAL) #endif #if defined(HAVE_INLINE) INLINE void ED_MakeLVal (ExprDesc* Expr) /* Make the expression a lvalue. */ { Expr->Flags |= E_RTYPE_LVAL; } #else # define ED_MakeLVal(Expr) do { (Expr)->Flags |= E_RTYPE_LVAL; } while (0) #endif #if defined(HAVE_INLINE) INLINE void ED_MakeRVal (ExprDesc* Expr) /* Make the expression a rvalue. */ { Expr->Flags &= ~E_RTYPE_LVAL; } #else # define ED_MakeRVal(Expr) do { (Expr)->Flags &= ~E_RTYPE_LVAL; } while (0) #endif #if defined(HAVE_INLINE) INLINE int ED_IsBitField (const ExprDesc* Expr) /* Return true if the expression is a bit field */ { return (Expr->Flags & E_BITFIELD) != 0; } #else # define ED_IsBitField(Expr) (((Expr)->Flags & E_BITFIELD) != 0) #endif void ED_MakeBitField (ExprDesc* Expr, unsigned BitOffs, unsigned BitWidth); /* Make this expression a bit field expression */ #if defined(HAVE_INLINE) INLINE void ED_MarkForTest (ExprDesc* Expr) /* Mark the expression for a test. */ { Expr->Flags |= E_NEED_TEST; } #else # define ED_MarkForTest(Expr) do { (Expr)->Flags |= E_NEED_TEST; } while (0) #endif #if defined(HAVE_INLINE) INLINE int ED_NeedsTest (const ExprDesc* Expr) /* Check if the expression needs a test. */ { return (Expr->Flags & E_NEED_TEST) != 0; } #else # define ED_NeedsTest(Expr) (((Expr)->Flags & E_NEED_TEST) != 0) #endif #if defined(HAVE_INLINE) INLINE void ED_TestDone (ExprDesc* Expr) /* Mark the expression as tested and condition codes set. */ { Expr->Flags = (Expr->Flags & ~E_NEED_TEST) | E_CC_SET; } #else # define ED_TestDone(Expr) \ do { (Expr)->Flags = ((Expr)->Flags & ~E_NEED_TEST) | E_CC_SET; } while (0) #endif #if defined(HAVE_INLINE) INLINE int ED_IsTested (const ExprDesc* Expr) /* Check if the expression has set the condition codes. */ { return (Expr->Flags & E_CC_SET) != 0; } #else # define ED_IsTested(Expr) (((Expr)->Flags & E_CC_SET) != 0) #endif #if defined(HAVE_INLINE) INLINE void ED_MarkAsUntested (ExprDesc* Expr) /* Mark the expression as not tested (condition codes not set). */ { Expr->Flags &= ~E_CC_SET; } #else # define ED_MarkAsUntested(Expr) do { (Expr)->Flags &= ~E_CC_SET; } while (0) #endif void ED_SetCodeRange (ExprDesc* Expr, const CodeMark* Start, const CodeMark* End); /* Set the code range for this expression */ int ED_CodeRangeIsEmpty (const ExprDesc* Expr); /* Return true if no code was output for this expression */ const char* ED_GetLabelName (const ExprDesc* Expr, long Offs); /* Return the assembler label name of the given expression. Beware: This ** function may use a static buffer, so the name may get "lost" on the second ** call to the function. */ int ED_GetStackOffs (const ExprDesc* Expr, int Offs); /* Get the stack offset of an address on the stack in Expr taking into account ** an additional offset in Offs. */ ExprDesc* ED_MakeConstAbs (ExprDesc* Expr, long Value, Type* Type); /* Make Expr an absolute const with the given value and type. */ ExprDesc* ED_MakeConstAbsInt (ExprDesc* Expr, long Value); /* Make Expr a constant integer expression with the given value */ ExprDesc* ED_MakeRValExpr (ExprDesc* Expr); /* Convert Expr into a rvalue which is in the primary register without an ** offset. */ ExprDesc* ED_MakeLValExpr (ExprDesc* Expr); /* Convert Expr into a lvalue which is in the primary register without an ** offset. */ int ED_IsConst (const ExprDesc* Expr); /* Return true if the expression denotes a constant of some sort. This can be a ** numeric constant, the address of a global variable (maybe with offset) or ** similar. */ #if defined(HAVE_INLINE) INLINE int ED_IsConstAbs (const ExprDesc* Expr) /* Return true if the expression denotes a constant absolute value. This can be ** a numeric constant, cast to any type. */ { return (Expr->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL); } #else # define ED_IsConstAbs(E) \ (((E)->Flags & (E_MASK_LOC|E_MASK_RTYPE)) == (E_LOC_ABS|E_RTYPE_RVAL)) #endif int ED_IsConstAbsInt (const ExprDesc* Expr); /* Return true if the expression is a constant (numeric) integer. */ int ED_IsNullPtr (const ExprDesc* Expr); /* Return true if the given expression is a NULL pointer constant */ int ED_IsBool (const ExprDesc* Expr); /* Return true of the expression can be treated as a boolean, that is, it can ** be an operand to a compare operation. */ void PrintExprDesc (FILE* F, ExprDesc* Expr); /* Print an ExprDesc */ Type* ReplaceType (ExprDesc* Expr, const Type* NewType); /* Replace the type of Expr by a copy of Newtype and return the old type string */ /* End of exprdesc.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/funcdesc.c�����������������������������������������������������������������������0000664�0000000�0000000�00000006567�13473601511�0015510�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* funcdesc.c */ /* */ /* Function descriptor structure for the cc65 C compiler */ /* */ /* */ /* */ /* (C) 2000 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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. */ /* */ /*****************************************************************************/ /* common */ #include "xmalloc.h" /* cc65 */ #include "funcdesc.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ FuncDesc* NewFuncDesc (void) /* Create a new symbol table with the given name */ { /* Create a new function descriptor */ FuncDesc* F = (FuncDesc*) xmalloc (sizeof (FuncDesc)); /* Nullify the fields */ F->Flags = 0; F->SymTab = 0; F->TagTab = 0; F->ParamCount = 0; F->ParamSize = 0; F->LastParam = 0; F->WrappedCall = 0; F->WrappedCallData = 0; /* Return the new struct */ return F; } void FreeFuncDesc (FuncDesc* F) /* Free a function descriptor */ { /* Free the structure */ xfree (F); } �����������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/funcdesc.h�����������������������������������������������������������������������0000664�0000000�0000000�00000011345�13473601511�0015503�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* funcdesc.h */ /* */ /* Function descriptor structure for the cc65 C compiler */ /* */ /* */ /* */ /* (C) 2000-2008 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef FUNCDESC_H #define FUNCDESC_H /*****************************************************************************/ /* struct FuncDesc */ /*****************************************************************************/ /* Masks for the Flags field in FuncDesc */ #define FD_NONE 0x0000U /* No flags */ #define FD_EMPTY 0x0001U /* Function with empty param list */ #define FD_VOID_PARAM 0x0002U /* Function with a void param list */ #define FD_VARIADIC 0x0004U /* Function with variable param list */ #define FD_OLDSTYLE 0x0010U /* Old style (K&R) function */ #define FD_OLDSTYLE_INTRET 0x0020U /* K&R func has implicit int return */ #define FD_UNNAMED_PARAMS 0x0040U /* Function has unnamed params */ #define FD_CALL_WRAPPER 0x0080U /* This function is used as a wrapper */ /* Bits that must be ignored when comparing funcs */ #define FD_IGNORE (FD_OLDSTYLE | FD_OLDSTYLE_INTRET | FD_UNNAMED_PARAMS | FD_CALL_WRAPPER) /* Function descriptor */ typedef struct FuncDesc FuncDesc; struct FuncDesc { unsigned Flags; /* Bitmapped flags FD_... */ struct SymTable* SymTab; /* Symbol table */ struct SymTable* TagTab; /* Symbol table for structs/enums */ unsigned ParamCount; /* Number of parameters */ unsigned ParamSize; /* Size of the parameters */ struct SymEntry* LastParam; /* Pointer to last parameter */ struct SymEntry* WrappedCall; /* Pointer to the WrappedCall */ unsigned char WrappedCallData;/* The WrappedCall's user data */ }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ FuncDesc* NewFuncDesc (void); /* Create a new symbol table with the given name */ void FreeFuncDesc (FuncDesc* D); /* Free a function descriptor */ /* End of funcdesc.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/function.c�����������������������������������������������������������������������0000664�0000000�0000000�00000042240�13473601511�0015527�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* function.c */ /* */ /* Parse function entry/body/exit */ /* */ /* */ /* */ /* (C) 2000-2015, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "check.h" #include "xmalloc.h" /* cc65 */ #include "asmcode.h" #include "asmlabel.h" #include "codegen.h" #include "error.h" #include "funcdesc.h" #include "global.h" #include "litpool.h" #include "locals.h" #include "scanner.h" #include "stackptr.h" #include "standard.h" #include "stmt.h" #include "symtab.h" #include "function.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Pointer to current function */ Function* CurrentFunc = 0; /*****************************************************************************/ /* Subroutines working with struct Function */ /*****************************************************************************/ static Function* NewFunction (struct SymEntry* Sym) /* Create a new function activation structure and return it */ { /* Allocate a new structure */ Function* F = (Function*) xmalloc (sizeof (Function)); /* Initialize the fields */ F->FuncEntry = Sym; F->ReturnType = GetFuncReturn (Sym->Type); F->Desc = GetFuncDesc (Sym->Type); F->Reserved = 0; F->RetLab = GetLocalLabel (); F->TopLevelSP = 0; F->RegOffs = RegisterSpace; F->Flags = IsTypeVoid (F->ReturnType) ? FF_VOID_RETURN : FF_NONE; InitCollection (&F->LocalsBlockStack); /* Return the new structure */ return F; } static void FreeFunction (Function* F) /* Free a function activation structure */ { DoneCollection (&F->LocalsBlockStack); xfree (F); } const char* F_GetFuncName (const Function* F) /* Return the name of the current function */ { return F->FuncEntry->Name; } unsigned F_GetParamCount (const Function* F) /* Return the parameter count for the current function */ { return F->Desc->ParamCount; } unsigned F_GetParamSize (const Function* F) /* Return the parameter size for the current function */ { return F->Desc->ParamSize; } Type* F_GetReturnType (Function* F) /* Get the return type for the function */ { return F->ReturnType; } int F_HasVoidReturn (const Function* F) /* Return true if the function does not have a return value */ { return (F->Flags & FF_VOID_RETURN) != 0; } void F_ReturnFound (Function* F) /* Mark the function as having a return statement */ { F->Flags |= FF_HAS_RETURN; } int F_HasReturn (const Function* F) /* Return true if the function contains a return statement*/ { return (F->Flags & FF_HAS_RETURN) != 0; } int F_IsMainFunc (const Function* F) /* Return true if this is the main function */ { return (F->Flags & FF_IS_MAIN) != 0; } int F_IsVariadic (const Function* F) /* Return true if this is a variadic function */ { return (F->Desc->Flags & FD_VARIADIC) != 0; } int F_IsOldStyle (const Function* F) /* Return true if this is an old style (K&R) function */ { return (F->Desc->Flags & FD_OLDSTYLE) != 0; } int F_HasOldStyleIntRet (const Function* F) /* Return true if this is an old style (K&R) function with an implicit int return */ { return (F->Desc->Flags & FD_OLDSTYLE_INTRET) != 0; } unsigned F_GetRetLab (const Function* F) /* Return the return jump label */ { return F->RetLab; } int F_GetTopLevelSP (const Function* F) /* Get the value of the stack pointer on function top level */ { return F->TopLevelSP; } int F_ReserveLocalSpace (Function* F, unsigned Size) /* Reserve (but don't allocate) the given local space and return the stack ** offset. */ { F->Reserved += Size; return StackPtr - F->Reserved; } int F_GetStackPtr (const Function* F) /* Return the current stack pointer including reserved (but not allocated) ** space on the stack. */ { return StackPtr - F->Reserved; } void F_AllocLocalSpace (Function* F) /* Allocate any local space previously reserved. The function will do ** nothing if there is no reserved local space. */ { if (F->Reserved > 0) { /* Create space on the stack */ g_space (F->Reserved); /* Correct the stack pointer */ StackPtr -= F->Reserved; /* Nothing more reserved */ F->Reserved = 0; } } int F_AllocRegVar (Function* F, const Type* Type) /* Allocate a register variable for the given variable type. If the allocation ** was successful, return the offset of the register variable in the register ** bank (zero page storage). If there is no register space left, return -1. */ { /* Allow register variables only on top level and if enabled */ if (IS_Get (&EnableRegVars) && GetLexicalLevel () == LEX_LEVEL_FUNCTION) { /* Get the size of the variable */ unsigned Size = CheckedSizeOf (Type); /* Do we have space left? */ if (F->RegOffs >= Size) { /* Space left. We allocate the variables from high to low addresses, ** so the addressing is compatible with the saved values on stack. ** This allows shorter code when saving/restoring the variables. */ F->RegOffs -= Size; return F->RegOffs; } } /* No space left or no allocation */ return -1; } static void F_RestoreRegVars (Function* F) /* Restore the register variables for the local function if there are any. */ { const SymEntry* Sym; /* If we don't have register variables in this function, bail out early */ if (F->RegOffs == RegisterSpace) { return; } /* Save the accumulator if needed */ if (!F_HasVoidReturn (F)) { g_save (CF_CHAR | CF_FORCECHAR); } /* Get the first symbol from the function symbol table */ Sym = F->FuncEntry->V.F.Func->SymTab->SymHead; /* Walk through all symbols checking for register variables */ while (Sym) { if (SymIsRegVar (Sym)) { /* Check for more than one variable */ int Offs = Sym->V.R.SaveOffs; unsigned Bytes = CheckedSizeOf (Sym->Type); while (1) { /* Find next register variable */ const SymEntry* NextSym = Sym->NextSym; while (NextSym && !SymIsRegVar (NextSym)) { NextSym = NextSym->NextSym; } /* If we have a next one, compare the stack offsets */ if (NextSym) { /* We have a following register variable. Get the size */ int Size = CheckedSizeOf (NextSym->Type); /* Adjacent variable? */ if (NextSym->V.R.SaveOffs + Size != Offs) { /* No */ break; } /* Adjacent variable */ Bytes += Size; Offs -= Size; Sym = NextSym; } else { break; } } /* Restore the memory range */ g_restore_regvars (Offs, Sym->V.R.RegOffs, Bytes); } /* Check next symbol */ Sym = Sym->NextSym; } /* Restore the accumulator if needed */ if (!F_HasVoidReturn (F)) { g_restore (CF_CHAR | CF_FORCECHAR); } } static void F_EmitDebugInfo (void) /* Emit debug infos for the current function */ { if (DebugInfo) { /* Get the current function */ const SymEntry* Sym = CurrentFunc->FuncEntry; /* Output info for the function itself */ AddTextLine ("\t.dbg\tfunc, \"%s\", \"00\", %s, \"%s\"", Sym->Name, (Sym->Flags & SC_EXTERN)? "extern" : "static", Sym->AsmName); } } /*****************************************************************************/ /* code */ /*****************************************************************************/ void NewFunc (SymEntry* Func) /* Parse argument declarations and function body. */ { int C99MainFunc = 0;/* Flag for C99 main function returning int */ SymEntry* Param; /* Get the function descriptor from the function entry */ FuncDesc* D = Func->V.F.Func; /* Allocate the function activation record for the function */ CurrentFunc = NewFunction (Func); /* Reenter the lexical level */ ReenterFunctionLevel (D); /* Check if the function header contains unnamed parameters. These are ** only allowed in cc65 mode. */ if ((D->Flags & FD_UNNAMED_PARAMS) != 0 && (IS_Get (&Standard) != STD_CC65)) { Error ("Parameter name omitted"); } /* Declare two special functions symbols: __fixargs__ and __argsize__. ** The latter is different depending on the type of the function (variadic ** or not). */ AddConstSym ("__fixargs__", type_uint, SC_DEF | SC_CONST, D->ParamSize); if (D->Flags & FD_VARIADIC) { /* Variadic function. The variable must be const. */ static const Type T[] = { TYPE(T_UCHAR | T_QUAL_CONST), TYPE(T_END) }; AddLocalSym ("__argsize__", T, SC_DEF | SC_REF | SC_AUTO, 0); } else { /* Non variadic */ AddConstSym ("__argsize__", type_uchar, SC_DEF | SC_CONST, D->ParamSize); } /* Function body now defined */ Func->Flags |= SC_DEF; /* Special handling for main() */ if (strcmp (Func->Name, "main") == 0) { /* Mark this as the main function */ CurrentFunc->Flags |= FF_IS_MAIN; /* Main cannot be a fastcall function */ if (IsQualFastcall (Func->Type)) { Error ("'main' cannot be declared as __fastcall__"); } /* If cc65 extensions aren't enabled, don't allow a main function that ** doesn't return an int. */ if (IS_Get (&Standard) != STD_CC65 && CurrentFunc->ReturnType[0].C != T_INT) { Error ("'main' must always return an int"); } /* Add a forced import of a symbol that is contained in the startup ** code. This will force the startup code to be linked in. */ g_importstartup (); /* If main() takes parameters, generate a forced import to a function ** that will setup these parameters. This way, programs that do not ** need the additional code will not get it. */ 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 ** returns an int. */ if (IsTypeInt (F_GetReturnType (CurrentFunc)) && IS_Get (&Standard) == STD_C99) { C99MainFunc = 1; } } /* Allocate code and data segments for this function */ Func->V.F.Seg = PushSegments (Func); /* Allocate a new literal pool */ PushLiteralPool (Func); /* If this is a fastcall function, push the last parameter onto the stack */ if ((D->Flags & FD_VARIADIC) == 0 && D->ParamCount > 0 && (AutoCDecl ? IsQualFastcall (Func->Type) : !IsQualCDecl (Func->Type))) { unsigned Flags; /* Generate the push */ if (IsTypeFunc (D->LastParam->Type)) { /* Pointer to function */ Flags = CF_PTR; } else { Flags = TypeOf (D->LastParam->Type) | CF_FORCECHAR; } g_push (Flags, 0); } /* Generate function entry code if needed */ g_enter (TypeOf (Func->Type), F_GetParamSize (CurrentFunc)); /* If stack checking code is requested, emit a call to the helper routine */ if (IS_Get (&CheckStack)) { g_stackcheck (); } /* Setup the stack */ StackPtr = 0; /* Walk through the parameter list and allocate register variable space ** for parameters declared as register. Generate code to swap the contents ** of the register bank with the save area on the stack. */ Param = D->SymTab->SymHead; while (Param && (Param->Flags & SC_PARAM) != 0) { /* Check for a register variable */ if (SymIsRegVar (Param)) { /* Allocate space */ int Reg = F_AllocRegVar (CurrentFunc, Param->Type); /* Could we allocate a register? */ if (Reg < 0) { /* No register available: Convert parameter to auto */ CvtRegVarToAuto (Param); } else { /* Remember the register offset */ Param->V.R.RegOffs = Reg; /* Generate swap code */ g_swap_regvars (Param->V.R.SaveOffs, Reg, CheckedSizeOf (Param->Type)); } } /* Next parameter */ Param = Param->NextSym; } /* Need a starting curly brace */ ConsumeLCurly (); /* Make sure there is always something on the stack of local variable blocks */ CollAppend (&CurrentFunc->LocalsBlockStack, 0); /* Parse local variable declarations if any */ DeclareLocals (); /* Remember the current stack pointer. All variables allocated elsewhere ** must be dropped when doing a return from an inner block. */ CurrentFunc->TopLevelSP = StackPtr; /* Now process statements in this block */ while (CurTok.Tok != TOK_RCURLY && CurTok.Tok != TOK_CEOF) { Statement (0); } /* If this is not a void function, and not the main function in a C99 ** environment returning int, output a warning if we didn't see a return ** statement. */ if (!F_HasVoidReturn (CurrentFunc) && !F_HasReturn (CurrentFunc) && !C99MainFunc) { Warning ("Control reaches end of non-void function"); } /* If this is the main function in a C99 environment returning an int, let ** it always return zero. Note: Actual return statements jump to the return ** label defined below. ** The code is removed by the optimizer if unused. */ if (C99MainFunc) { g_getimmed (CF_INT | CF_CONST, 0, 0); } /* Output the function exit code label */ g_defcodelabel (F_GetRetLab (CurrentFunc)); /* Restore the register variables */ F_RestoreRegVars (CurrentFunc); /* Generate the exit code */ g_leave (); /* Emit references to imports/exports */ EmitExternals (); /* Emit function debug info */ F_EmitDebugInfo (); EmitDebugInfo (); /* Leave the lexical level */ LeaveFunctionLevel (); /* Eat the closing brace */ ConsumeRCurly (); /* Restore the old literal pool, remembering the one for the function */ Func->V.F.LitPool = PopLiteralPool (); /* Switch back to the old segments */ PopSegments (); /* Reset the current function pointer */ FreeFunction (CurrentFunc); CurrentFunc = 0; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/function.h�����������������������������������������������������������������������0000664�0000000�0000000�00000014502�13473601511�0015534�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* function.h */ /* */ /* Function management */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef FUNCTION_H #define FUNCTION_H #include "coll.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Enumeration for function flags */ typedef enum { FF_NONE = 0x0000, FF_HAS_RETURN = 0x0001, /* Function has a return statement */ FF_IS_MAIN = 0x0002, /* This is the main function */ FF_VOID_RETURN = 0x0004, /* Function returning void */ } funcflags_t; /* Structure that holds all data needed for function activation */ struct Function { struct SymEntry* FuncEntry; /* Symbol table entry */ Type* ReturnType; /* Function return type */ FuncDesc* Desc; /* Function descriptor */ int Reserved; /* Reserved local space */ unsigned RetLab; /* Return code label */ int TopLevelSP; /* SP at function top level */ unsigned RegOffs; /* Register variable space offset */ funcflags_t Flags; /* Function flags */ Collection LocalsBlockStack; /* Stack of blocks with local vars */ }; /* Structure that holds all data needed for function activation */ typedef struct Function Function; /* Function activation data for current function (or NULL) */ extern Function* CurrentFunc; /*****************************************************************************/ /* Code */ /*****************************************************************************/ const char* F_GetFuncName (const Function* F); /* Return the name of the current function */ unsigned F_GetParamCount (const Function* F); /* Return the parameter count for the current function */ unsigned F_GetParamSize (const Function* F); /* Return the parameter size for the current function */ Type* F_GetReturnType (Function* F); /* Get the return type for the function */ int F_HasVoidReturn (const Function* F); /* Return true if the function does not have a return value */ void F_ReturnFound (Function* F); /* Mark the function as having a return statement */ int F_HasReturn (const Function* F); /* Return true if the function contains a return statement*/ int F_IsMainFunc (const Function* F); /* Return true if this is the main function */ int F_IsVariadic (const Function* F); /* Return true if this is a variadic function */ int F_IsOldStyle (const Function* F); /* Return true if this is an old style (K&R) function */ int F_HasOldStyleIntRet (const Function* F); /* Return true if this is an old style (K&R) function with an implicit int return */ unsigned F_GetRetLab (const Function* F); /* Return the return jump label */ int F_GetTopLevelSP (const Function* F); /* Get the value of the stack pointer on function top level */ int F_ReserveLocalSpace (Function* F, unsigned Size); /* Reserve (but don't allocate) the given local space and return the stack ** offset. */ int F_GetStackPtr (const Function* F); /* Return the current stack pointer including reserved (but not allocated) ** space on the stack. */ void F_AllocLocalSpace (Function* F); /* Allocate any local space previously reserved. The function will do ** nothing if there is no reserved local space. */ int F_AllocRegVar (Function* F, const Type* Type); /* Allocate a register variable for the given variable type. If the allocation ** was successful, return the offset of the register variable in the register ** bank (zero page storage). If there is no register space left, return -1. */ void NewFunc (struct SymEntry* Func); /* Parse argument declarations and function body. */ /* End of function.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/global.c�������������������������������������������������������������������������0000664�0000000�0000000�00000010761�13473601511�0015145�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* global.c */ /* */ /* Global variables for the cc65 C compiler */ /* */ /* */ /* */ /* (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 */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include "global.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ 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 */ unsigned RegisterSpace = 6; /* Space available for register vars */ /* Stackable options */ IntStack WritableStrings = INTSTACK(0); /* Literal strings are r/w */ IntStack LocalStrings = INTSTACK(0); /* Emit string literals immediately */ IntStack InlineStdFuncs = INTSTACK(0); /* Inline some standard functions */ IntStack EagerlyInlineFuncs = INTSTACK(0); /* Eagerly inline some known functions */ IntStack EnableRegVars = INTSTACK(0); /* Enable register variables */ IntStack AllowRegVarAddr = INTSTACK(0); /* Allow taking addresses of register vars */ IntStack RegVarsToCallStack = INTSTACK(0); /* Save reg variables on call stack */ IntStack StaticLocals = INTSTACK(0); /* Make local variables static */ IntStack SignedChars = INTSTACK(0); /* Make characters signed by default */ IntStack CheckStack = INTSTACK(0); /* Generate stack overflow checks */ IntStack Optimize = INTSTACK(0); /* Optimize flag */ IntStack CodeSizeFactor = INTSTACK(100);/* Size factor for generated code */ IntStack DataAlignment = INTSTACK(1); /* Alignment for data */ /* File names */ StrBuf DepName = STATIC_STRBUF_INITIALIZER; /* Name of dependencies file */ StrBuf FullDepName = STATIC_STRBUF_INITIALIZER; /* Name of full dependencies file */ StrBuf DepTarget = STATIC_STRBUF_INITIALIZER; /* Name of dependency target */ ���������������cc65-2.18/src/cc65/global.h�������������������������������������������������������������������������0000664�0000000�0000000�00000011314�13473601511�0015145�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* global.h */ /* */ /* Global variables for the cc65 C compiler */ /* */ /* */ /* */ /* (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 */ /* 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 GLOBAL_H #define GLOBAL_H /* common */ #include "intstack.h" #include "strbuf.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* 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 */ extern unsigned RegisterSpace; /* Space available for register vars */ /* Stackable options */ extern IntStack WritableStrings; /* Literal strings are r/w */ extern IntStack LocalStrings; /* Emit string literals immediately */ extern IntStack InlineStdFuncs; /* Inline some standard functions */ extern IntStack EagerlyInlineFuncs; /* Eagerly inline some known functions */ extern IntStack EnableRegVars; /* Enable register variables */ extern IntStack AllowRegVarAddr; /* Allow taking addresses of register vars */ extern IntStack RegVarsToCallStack; /* Save reg variables on call stack */ extern IntStack StaticLocals; /* Make local variables static */ extern IntStack SignedChars; /* Make characters signed by default */ extern IntStack CheckStack; /* Generate stack overflow checks */ extern IntStack Optimize; /* Optimize flag */ extern IntStack CodeSizeFactor; /* Size factor for generated code */ extern IntStack DataAlignment; /* Alignment for data */ /* File names */ extern StrBuf DepName; /* Name of dependencies file */ extern StrBuf FullDepName; /* Name of full dependencies file */ extern StrBuf DepTarget; /* Name of dependency target */ /* End of global.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/goto.c���������������������������������������������������������������������������0000664�0000000�0000000�00000015620�13473601511�0014654�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* goto.c */ /* */ /* Goto and label handling for the cc65 C compiler */ /* */ /* */ /* */ /* (C) 2000 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include "asmlabel.h" #include "codeent.h" #include "codegen.h" #include "codeseg.h" #include "cpu.h" #include "error.h" #include "exprdesc.h" #include "expr.h" #include "loadexpr.h" #include "scanner.h" #include "standard.h" #include "symtab.h" #include "goto.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void GotoStatement (void) /* Process a goto statement. */ { /* Eat the "goto" */ NextToken (); /* Label name must follow */ if (CurTok.Tok == TOK_IDENT) { /* Add a new label symbol if we don't have one until now */ SymEntry* Entry = AddLabelSym (CurTok.Ident, SC_REF | SC_GOTO); /* Jump to the label */ g_jump (Entry->V.L.Label); /* Eat the label name */ NextToken (); } else if (CurTok.Tok == TOK_STAR && IS_Get (&Standard) >= STD_CC65) { SymEntry *arr, *idx, *cur; SymTable *tab; ExprDesc desc; CodeEntry *E; unsigned char val; NextToken (); /* arr[foo], we only support simple foo for now */ if (CurTok.Tok == TOK_IDENT && (arr = FindSym (CurTok.Ident))) { NextToken (); /* Find array size */ if (!IsTypeArray (arr->Type) || SizeOf (arr->Type) == 0 || !(arr->Flags & SC_STATIC) || SizeOf (GetElementType(arr->Type)) != 2) { Error ("Expected a static array"); } else if (GetElementCount (arr->Type) > 127) { Error ("Only arrays with <= 127 labels are supported, got %lu", GetElementCount (arr->Type)); } ConsumeLBrack (); if (CurTok.Tok == TOK_ICONST) { val = (unsigned char)CurTok.IVal; NextToken (); if (CPUIsets[CPU] & CPU_ISET_65SC02) { AddCodeLine ("ldx #$%02X", val * 2); AddCodeLine ("jmp (.loword(%s),x)", arr->AsmName); } else { AddCodeLine ("ldy #$%02X", val * 2); AddCodeLine ("lda %s,y", arr->AsmName); AddCodeLine ("ldx %s+1,y", arr->AsmName); AddCodeLine ("jmp callax"); } } else if (CurTok.Tok == TOK_IDENT && (idx = FindSym (CurTok.Ident))) { hie10 (&desc); LoadExpr (CF_NONE, &desc); AddCodeLine ("asl a"); if (CPUIsets[CPU] & CPU_ISET_65SC02) { AddCodeLine ("tax"); AddCodeLine ("jmp (.loword(%s),x)", arr->AsmName); } else { AddCodeLine ("tay"); AddCodeLine ("lda %s,y", arr->AsmName); AddCodeLine ("ldx %s+1,y", arr->AsmName); AddCodeLine ("jmp callax"); } } else { Error ("Only simple expressions are supported for computed goto"); } ConsumeRBrack (); /* Loop over all target labels, specifying this as a jump point. ** It's not exact -- if there's multiple gotos, the last will be used; ** but, it's needed only so the optimizer does not remove the labels. */ E = CS_GetEntry (CS->Code, CS_GetEntryCount (CS->Code) - 1); tab = GetLabelSymTab (); if (tab) { cur = tab->SymHead; while (cur) { if ((cur->Flags & SC_GOTO_IND) != 0) { cur->V.L.IndJumpFrom = E; } cur = cur->NextSym; } } } else { /* It was not TOK_IDENT, or we couldn't find the symbol */ Error ("Array name expected"); } } else { Error ("Label name expected"); } } void DoLabel (void) /* Define a label. */ { /* Add a label symbol */ SymEntry* Entry = AddLabelSym (CurTok.Ident, SC_DEF); /* Emit the jump label */ CodeLabel* L = CS_AddLabel (CS->Code, LocalLabelName (Entry->V.L.Label)); if (Entry->V.L.IndJumpFrom) { CollAppend (&L->JumpFrom, Entry->V.L.IndJumpFrom); } /* Eat the ident and colon */ NextToken (); NextToken (); } ����������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/goto.h���������������������������������������������������������������������������0000664�0000000�0000000�00000005642�13473601511�0014664�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* goto.h */ /* */ /* Goto and label handling for the cc65 C compiler */ /* */ /* */ /* */ /* (C) 2000 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 GOTO_H #define GOTO_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ void GotoStatement (void); /* Process a goto statement. */ void DoLabel (void); /* Define a goto label. */ /* End of goto.h */ #endif ����������������������������������������������������������������������������������������������cc65-2.18/src/cc65/hexval.c�������������������������������������������������������������������������0000664�0000000�0000000�00000006214�13473601511�0015172�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* hexval.c */ /* */ /* Convert hex digits to numeric values */ /* */ /* */ /* */ /* (C) 2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "chartype.h" /* cc65 */ #include "error.h" #include "hexval.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned HexVal (int C) /* Convert a hex digit into a value. The function will emit an error for ** invalid hex digits. */ { if (!IsXDigit (C)) { Error ("Invalid hexadecimal digit: '%c'", C); } if (IsDigit (C)) { return C - '0'; } else { return toupper (C) - 'A' + 10; } } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/hexval.h�������������������������������������������������������������������������0000664�0000000�0000000�00000005671�13473601511�0015205�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* hexval.h */ /* */ /* Convert hex digits to numeric values */ /* */ /* */ /* */ /* (C) 2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef HEXVAL_H #define HEXVAL_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned HexVal (int C); /* Convert a hex digit into a value. The function will emit an error for ** invalid hex digits. */ /* End of hexval.h */ #endif �����������������������������������������������������������������������cc65-2.18/src/cc65/ident.c��������������������������������������������������������������������������0000664�0000000�0000000�00000005713�13473601511�0015011�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* ident.c */ /* */ /* Identifier handling for the cc65 compiler */ /* */ /* */ /* */ /* (C) 1998 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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. */ /* */ /*****************************************************************************/ /* common */ #include "chartype.h" /* cc65 */ #include "ident.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ int IsIdent (char c) /* Return true if the given char may start an identifier */ { return (IsAlpha (c) || c == '_'); } �����������������������������������������������������cc65-2.18/src/cc65/ident.h��������������������������������������������������������������������������0000664�0000000�0000000�00000006524�13473601511�0015017�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* ident.h */ /* */ /* Identifier handling for the cc65 compiler */ /* */ /* */ /* */ /* (C) 1998 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 IDENT_H #define IDENT_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Maximum length of an identifier and the corresponding char array */ #define MAX_IDENTLEN 64 #define IDENTSIZE (MAX_IDENTLEN+1) /* Variable that holds an identifer */ typedef char ident [IDENTSIZE]; /*****************************************************************************/ /* Code */ /*****************************************************************************/ int IsIdent (char c); /* Return true if the given char may start an identifier */ /* End of ident.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/incpath.c������������������������������������������������������������������������0000664�0000000�0000000�00000010053�13473601511�0015325�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* incpath.c */ /* */ /* Include path handling for cc65 */ /* */ /* */ /* */ /* (C) 2000-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* cc65 */ #include "incpath.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ SearchPaths* SysIncSearchPath; /* System include path */ SearchPaths* UsrIncSearchPath; /* User include path */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ void InitIncludePaths (void) /* Initialize the include path search list */ { /* Create the search path lists */ SysIncSearchPath = NewSearchPath (); UsrIncSearchPath = NewSearchPath (); } void FinishIncludePaths (void) /* Finish creating the include path search lists. */ { /* Add specific paths from the environment */ AddSearchPathFromEnv (SysIncSearchPath, "CC65_INC"); AddSearchPathFromEnv (UsrIncSearchPath, "CC65_INC"); /* Add paths relative to a main directory defined in an env. var. */ AddSubSearchPathFromEnv (SysIncSearchPath, "CC65_HOME", "include"); /* Add some compiled-in search paths if defined at compile time. */ #if defined(CC65_INC) && !defined(_WIN32) AddSearchPath (SysIncSearchPath, STRINGIZE (CC65_INC)); #endif /* Add paths relative to the parent directory of the Windows binary. */ AddSubSearchPathFromWinBin (SysIncSearchPath, "include"); } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/incpath.h������������������������������������������������������������������������0000664�0000000�0000000�00000006621�13473601511�0015340�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* incpath.h */ /* */ /* Include path handling for cc65 */ /* */ /* */ /* */ /* (C) 2000-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef INCPATH_H #define INCPATH_H /* common */ #include "searchpath.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ extern SearchPaths* SysIncSearchPath; /* System include path */ extern SearchPaths* UsrIncSearchPath; /* User include path */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ void InitIncludePaths (void); /* Initialize the include path search list */ void FinishIncludePaths (void); /* Finish creating the include path search lists. */ /* End of incpath.h */ #endif ���������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/input.c��������������������������������������������������������������������������0000664�0000000�0000000�00000045547�13473601511�0015056�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* input.c */ /* */ /* Input file handling */ /* */ /* */ /* */ /* (C) 2000-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> #include <errno.h> /* common */ #include "check.h" #include "coll.h" #include "filestat.h" #include "fname.h" #include "print.h" #include "strbuf.h" #include "xmalloc.h" /* cc65 */ #include "codegen.h" #include "error.h" #include "global.h" #include "incpath.h" #include "input.h" #include "lineinfo.h" #include "output.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* The current input line */ StrBuf* Line; /* Current and next input character */ char CurC = '\0'; char NextC = '\0'; /* Maximum count of nested includes */ #define MAX_INC_NESTING 16 /* Struct that describes an input file */ typedef struct IFile IFile; struct IFile { unsigned Index; /* File index */ unsigned Usage; /* Usage counter */ unsigned long Size; /* File size */ unsigned long MTime; /* Time of last modification */ InputType Type; /* Type of input file */ char Name[1]; /* Name of file (dynamically allocated) */ }; /* Struct that describes an active input file */ typedef struct AFile AFile; struct AFile { unsigned Line; /* Line number for this file */ FILE* F; /* Input file stream */ IFile* Input; /* Points to corresponding IFile */ int SearchPath; /* True if we've added a path for this file */ }; /* List of all input files */ static Collection IFiles = STATIC_COLLECTION_INITIALIZER; /* List of all active files */ static Collection AFiles = STATIC_COLLECTION_INITIALIZER; /* Input stack used when preprocessing. */ static Collection InputStack = STATIC_COLLECTION_INITIALIZER; /*****************************************************************************/ /* struct IFile */ /*****************************************************************************/ static IFile* NewIFile (const char* Name, InputType Type) /* Create and return a new IFile */ { /* Get the length of the name */ unsigned Len = strlen (Name); /* Allocate a IFile structure */ IFile* IF = (IFile*) xmalloc (sizeof (IFile) + Len); /* Initialize the fields */ IF->Index = CollCount (&IFiles) + 1; IF->Usage = 0; IF->Size = 0; IF->MTime = 0; IF->Type = Type; memcpy (IF->Name, Name, Len+1); /* Insert the new structure into the IFile collection */ CollAppend (&IFiles, IF); /* Return the new struct */ return IF; } /*****************************************************************************/ /* struct AFile */ /*****************************************************************************/ static AFile* NewAFile (IFile* IF, FILE* F) /* Create a new AFile, push it onto the stack, add the path of the file to ** the path search list, and finally return a pointer to the new AFile struct. */ { StrBuf Path = AUTO_STRBUF_INITIALIZER; /* Allocate a AFile structure */ AFile* AF = (AFile*) xmalloc (sizeof (AFile)); /* Initialize the fields */ AF->Line = 0; AF->F = F; AF->Input = IF; /* Increment the usage counter of the corresponding IFile. If this ** is the first use, set the file data and output debug info if ** requested. */ if (IF->Usage++ == 0) { /* Get file size and modification time. There a race condition here, ** since we cannot use fileno() (non standard identifier in standard ** header file), and therefore not fstat. When using stat with the ** file name, there's a risk that the file was deleted and recreated ** while it was open. Since mtime and size are only used to check ** if a file has changed in the debugger, we will ignore this problem ** here. */ struct stat Buf; if (FileStat (IF->Name, &Buf) != 0) { /* Error */ Fatal ("Cannot stat '%s': %s", IF->Name, strerror (errno)); } IF->Size = (unsigned long) Buf.st_size; IF->MTime = (unsigned long) Buf.st_mtime; /* Set the debug data */ g_fileinfo (IF->Name, IF->Size, IF->MTime); } /* Insert the new structure into the AFile collection */ CollAppend (&AFiles, AF); /* Get the path of this file and add it as an extra search path. ** To avoid file search overhead, we will add one path only once. ** This is checked by the PushSearchPath function. */ SB_CopyBuf (&Path, IF->Name, FindName (IF->Name) - IF->Name); SB_Terminate (&Path); AF->SearchPath = PushSearchPath (UsrIncSearchPath, SB_GetConstBuf (&Path)); SB_Done (&Path); /* Return the new struct */ return AF; } static void FreeAFile (AFile* AF) /* Free an AFile structure */ { xfree (AF); } /*****************************************************************************/ /* Code */ /*****************************************************************************/ static IFile* FindFile (const char* Name) /* Find the file with the given name in the list of all files. Since the list ** is not large (usually less than 10), I don't care about using hashes or ** similar things and do a linear search. */ { unsigned I; for (I = 0; I < CollCount (&IFiles); ++I) { /* Get the file struct */ IFile* IF = (IFile*) CollAt (&IFiles, I); /* Check the name */ if (strcmp (Name, IF->Name) == 0) { /* Found, return the struct */ return IF; } } /* Not found */ return 0; } void OpenMainFile (const char* Name) /* Open the main file. Will call Fatal() in case of failures. */ { AFile* MainFile; /* Setup a new IFile structure for the main file */ IFile* IF = NewIFile (Name, IT_MAIN); /* Open the file for reading */ FILE* F = fopen (Name, "r"); if (F == 0) { /* Cannot open */ Fatal ("Cannot open input file '%s': %s", Name, strerror (errno)); } /* Allocate a new AFile structure for the file */ MainFile = NewAFile (IF, F); /* Allocate the input line buffer */ Line = NewStrBuf (); /* Update the line infos, so we have a valid line info even at start of ** the main file before the first line is read. */ UpdateLineInfo (MainFile->Input, MainFile->Line, Line); } void OpenIncludeFile (const char* Name, InputType IT) /* Open an include file and insert it into the tables. */ { char* N; FILE* F; IFile* IF; /* Check for the maximum include nesting */ if (CollCount (&AFiles) > MAX_INC_NESTING) { PPError ("Include nesting too deep"); return; } /* Search for the file */ N = SearchFile ((IT == IT_SYSINC)? SysIncSearchPath : UsrIncSearchPath, Name); if (N == 0) { PPError ("Include file '%s' not found", Name); return; } /* Search the list of all input files for this file. If we don't find ** it, create a new IFile object. */ IF = FindFile (N); if (IF == 0) { IF = NewIFile (N, IT); } /* We don't need N any longer, since we may now use IF->Name */ xfree (N); /* Open the file */ F = fopen (IF->Name, "r"); if (F == 0) { /* Error opening the file */ PPError ("Cannot open include file '%s': %s", IF->Name, strerror (errno)); return; } /* Debugging output */ Print (stdout, 1, "Opened include file '%s'\n", IF->Name); /* Allocate a new AFile structure */ (void) NewAFile (IF, F); } static void CloseIncludeFile (void) /* Close an include file and switch to the higher level file. Set Input to ** NULL if this was the main file. */ { AFile* Input; /* Get the number of active input files */ unsigned AFileCount = CollCount (&AFiles); /* Must have an input file when called */ PRECONDITION (AFileCount > 0); /* Get the current active input file */ Input = (AFile*) CollLast (&AFiles); /* Close the current input file (we're just reading so no error check) */ fclose (Input->F); /* Delete the last active file from the active file collection */ CollDelete (&AFiles, AFileCount-1); /* If we had added an extra search path for this AFile, remove it */ if (Input->SearchPath) { PopSearchPath (UsrIncSearchPath); } /* Delete the active file structure */ FreeAFile (Input); } static void GetInputChar (void) /* Read the next character from the input stream and make CurC and NextC ** valid. If end of line is reached, both are set to NUL, no more lines ** are read by this function. */ { /* Drop all pushed fragments that don't have data left */ while (SB_GetIndex (Line) >= SB_GetLen (Line)) { /* Cannot read more from this line, check next line on stack if any */ if (CollCount (&InputStack) == 0) { /* This is THE line */ break; } FreeStrBuf (Line); Line = CollPop (&InputStack); } /* Now get the next characters from the line */ if (SB_GetIndex (Line) >= SB_GetLen (Line)) { CurC = NextC = '\0'; } else { CurC = SB_AtUnchecked (Line, SB_GetIndex (Line)); if (SB_GetIndex (Line) + 1 < SB_GetLen (Line)) { /* NextC comes from this fragment */ NextC = SB_AtUnchecked (Line, SB_GetIndex (Line) + 1); } else { /* NextC comes from next fragment */ if (CollCount (&InputStack) > 0) { NextC = ' '; } else { NextC = '\0'; } } } } void NextChar (void) /* Skip the current input character and read the next one from the input ** stream. CurC and NextC are valid after the call. If end of line is ** reached, both are set to NUL, no more lines are read by this function. */ { /* Skip the last character read */ SB_Skip (Line); /* Read the next one */ GetInputChar (); } void ClearLine (void) /* Clear the current input line */ { unsigned I; /* Remove all pushed fragments from the input stack */ for (I = 0; I < CollCount (&InputStack); ++I) { FreeStrBuf (CollAtUnchecked (&InputStack, I)); } CollDeleteAll (&InputStack); /* Clear the contents of Line */ SB_Clear (Line); CurC = '\0'; NextC = '\0'; } StrBuf* InitLine (StrBuf* Buf) /* Initialize Line from Buf and read CurC and NextC from the new input line. ** The function returns the old input line. */ { StrBuf* OldLine = Line; Line = Buf; CurC = SB_LookAt (Buf, SB_GetIndex (Buf)); NextC = SB_LookAt (Buf, SB_GetIndex (Buf) + 1); return OldLine; } int NextLine (void) /* Get a line from the current input. Returns 0 on end of file. */ { AFile* Input; /* Clear the current line */ ClearLine (); /* If there is no file open, bail out, otherwise get the current input file */ if (CollCount (&AFiles) == 0) { return 0; } Input = CollLast (&AFiles); /* Read characters until we have one complete line */ while (1) { /* Read the next character */ int C = fgetc (Input->F); /* Check for EOF */ if (C == EOF) { /* Accept files without a newline at the end */ if (SB_NotEmpty (Line)) { ++Input->Line; break; } /* Leave the current file */ CloseIncludeFile (); /* If there is no file open, bail out, otherwise get the ** previous input file and start over. */ if (CollCount (&AFiles) == 0) { return 0; } Input = CollLast (&AFiles); continue; } /* Check for end of line */ if (C == '\n') { /* We got a new line */ ++Input->Line; /* If the \n is preceeded by a \r, remove the \r, so we can read ** DOS/Windows files under *nix. */ if (SB_LookAtLast (Line) == '\r') { SB_Drop (Line, 1); } /* If we don't have a line continuation character at the end, ** we're done with this line. Otherwise replace the character ** by a newline and continue reading. */ if (SB_LookAtLast (Line) == '\\') { Line->Buf[Line->Len-1] = '\n'; } else { break; } } else if (C != '\0') { /* Ignore embedded NULs */ /* Just some character, add it to the line */ SB_AppendChar (Line, C); } } /* Add a termination character to the string buffer */ SB_Terminate (Line); /* Initialize the current and next characters. */ InitLine (Line); /* Create line information for this line */ UpdateLineInfo (Input->Input, Input->Line, Line); /* Done */ return 1; } const char* GetInputFile (const struct IFile* IF) /* Return a filename from an IFile struct */ { return IF->Name; } const char* GetCurrentFile (void) /* Return the name of the current input file */ { unsigned AFileCount = CollCount (&AFiles); if (AFileCount > 0) { const AFile* AF = (const AFile*) CollAt (&AFiles, AFileCount-1); return AF->Input->Name; } else { /* No open file. Use the main file if we have one. */ unsigned IFileCount = CollCount (&IFiles); if (IFileCount > 0) { const IFile* IF = (const IFile*) CollAt (&IFiles, 0); return IF->Name; } else { return "(outside file scope)"; } } } unsigned GetCurrentLine (void) /* Return the line number in the current input file */ { unsigned AFileCount = CollCount (&AFiles); if (AFileCount > 0) { const AFile* AF = (const AFile*) CollAt (&AFiles, AFileCount-1); return AF->Line; } else { /* No open file */ return 0; } } 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, InputType Types) /* Helper function. Writes all file names that match Types to the output */ { unsigned I; /* Loop over all files */ unsigned FileCount = CollCount (&IFiles); for (I = 0; I < FileCount; ++I) { /* Get the next input file */ const IFile* IF = (const IFile*) CollAt (&IFiles, I); /* Ignore it if it is not of the correct type */ if ((IF->Type & Types) == 0) { continue; } /* If this is not the first file, add a space */ if (I > 0) { fputc (' ', F); } /* Print the dependency escaping spaces */ WriteEscaped (F, IF->Name); } } static void CreateDepFile (const char* Name, InputType Types) /* Create a dependency file with the given name and place dependencies for ** all files with the given types there. */ { /* Open the file */ FILE* F = fopen (Name, "w"); if (F == 0) { Fatal ("Cannot open dependency file '%s': %s", Name, strerror (errno)); } /* If a dependency target was given, use it, otherwise use the output ** file name as target, followed by a tab character. */ if (SB_IsEmpty (&DepTarget)) { WriteEscaped (F, OutputFilename); } else { WriteEscaped (F, SB_GetConstBuf (&DepTarget)); } fputs (":\t", F); /* Write out the dependencies for the output file */ WriteDep (F, Types); fputs ("\n\n", F); /* Write out a phony dependency for the included files */ WriteDep (F, Types); fputs (":\n\n", F); /* Close the file, check for errors */ if (fclose (F) != 0) { remove (Name); Fatal ("Cannot write to dependeny file (disk full?)"); } } void CreateDependencies (void) /* Create dependency files requested by the user */ { if (SB_NotEmpty (&DepName)) { CreateDepFile (SB_GetConstBuf (&DepName), IT_MAIN | IT_USRINC); } if (SB_NotEmpty (&FullDepName)) { CreateDepFile (SB_GetConstBuf (&FullDepName), IT_MAIN | IT_SYSINC | IT_USRINC); } } ���������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/input.h��������������������������������������������������������������������������0000664�0000000�0000000�00000011264�13473601511�0015050�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* input.h */ /* */ /* Input file handling */ /* */ /* */ /* */ /* (C) 2000-2010, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef INPUT_H #define INPUT_H #include <stdio.h> /* common */ #include "strbuf.h" /*****************************************************************************/ /* data */ /*****************************************************************************/ /* An enum that describes different types of input files. The members are ** choosen so that it is possible to combine them to bitsets */ typedef enum { IT_MAIN = 0x01, /* Main input file */ IT_SYSINC = 0x02, /* System include file (using <>) */ IT_USRINC = 0x04, /* User include file (using "") */ } InputType; /* Forward for an IFile structure */ struct IFile; /* The current input line */ extern StrBuf* Line; /* Current and next input character */ extern char CurC; extern char NextC; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void OpenMainFile (const char* Name); /* Open the main file. Will call Fatal() in case of failures. */ void OpenIncludeFile (const char* Name, InputType IT); /* Open an include file and insert it into the tables. */ void NextChar (void); /* Read the next character from the input stream and make CurC and NextC ** valid. If end of line is reached, both are set to NUL, no more lines ** are read by this function. */ void ClearLine (void); /* Clear the current input line */ StrBuf* InitLine (StrBuf* Buf); /* Initialize Line from Buf and read CurC and NextC from the new input line. ** The function returns the old input line. */ int NextLine (void); /* Get a line from the current input. Returns 0 on end of file. */ const char* GetInputFile (const struct IFile* IF); /* Return a filename from an IFile struct */ const char* GetCurrentFile (void); /* Return the name of the current input file */ unsigned GetCurrentLine (void); /* Return the line number in the current input file */ void CreateDependencies (void); /* Create dependency files requested by the user */ /* End of input.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/lineinfo.c�����������������������������������������������������������������������0000664�0000000�0000000�00000013710�13473601511�0015505�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* lineinfo.c */ /* */ /* Source file line info structure */ /* */ /* */ /* */ /* (C) 2001 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* common */ #include "chartype.h" #include "check.h" #include "xmalloc.h" /* cc65 */ #include "global.h" #include "input.h" #include "lineinfo.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Global pointer to line information for the current line */ static LineInfo* CurLineInfo = 0; /*****************************************************************************/ /* Code */ /*****************************************************************************/ static LineInfo* NewLineInfo (struct IFile* F, unsigned LineNum, const StrBuf* Line) /* Create and return a new line info. Ref count will be 1. */ { unsigned Len; LineInfo* LI; const char* S; char* T; /* Get the length of the line and a pointer to the line buffer */ Len = SB_GetLen (Line); S = SB_GetConstBuf (Line); /* Skip leading spaces in Line */ while (Len > 0 && IsBlank (*S)) { ++S; --Len; } /* Allocate memory for the line info and the input line */ LI = xmalloc (sizeof (LineInfo) + Len); /* Initialize the fields */ LI->RefCount = 1; LI->InputFile = F; LI->LineNum = LineNum; /* Copy the line, replacing tabs by spaces in the given line since tabs ** will give rather arbitrary results when used in the output later, and ** if we do it here, we won't need another copy later. */ T = LI->Line; while (Len--) { if (*S == '\t') { *T = ' '; } else { *T = *S; } ++S; ++T; } /* Add the terminator */ *T = '\0'; /* Return the new struct */ return LI; } static void FreeLineInfo (LineInfo* LI) /* Free a LineInfo structure */ { xfree (LI); } LineInfo* UseLineInfo (LineInfo* LI) /* Increase the reference count of the given line info and return it. */ { CHECK (LI != 0); ++LI->RefCount; return LI; } void ReleaseLineInfo (LineInfo* LI) /* Release a reference to the given line info, free the structure if the ** reference count drops to zero. */ { CHECK (LI && LI->RefCount > 0); if (--LI->RefCount == 0) { /* No more references, free it */ FreeLineInfo (LI); } } LineInfo* GetCurLineInfo (void) /* Return a pointer to the current line info. The reference count is NOT ** increased, use UseLineInfo for that purpose. */ { return CurLineInfo; } void UpdateLineInfo (struct IFile* F, unsigned LineNum, const StrBuf* Line) /* Update the line info - called if a new line is read */ { /* If a current line info exists, release it */ if (CurLineInfo) { ReleaseLineInfo (CurLineInfo); } /* If we have intermixed assembly switched off, use an empty line instead ** of the supplied one to save some memory. */ if (!AddSource) { Line = &EmptyStrBuf; } /* Create a new line info */ CurLineInfo = NewLineInfo (F, LineNum, Line); } const char* GetInputName (const LineInfo* LI) /* Return the file name from a line info */ { PRECONDITION (LI != 0); return GetInputFile (LI->InputFile); } unsigned GetInputLine (const LineInfo* LI) /* Return the line number from a line info */ { PRECONDITION (LI != 0); return LI->LineNum; } ��������������������������������������������������������cc65-2.18/src/cc65/lineinfo.h�����������������������������������������������������������������������0000664�0000000�0000000�00000011055�13473601511�0015512�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* lineinfo.h */ /* */ /* Source file line info structure */ /* */ /* */ /* */ /* (C) 2001 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 LINEINFO_H #define LINEINFO_H /* common */ #include "strbuf.h" /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ /* Input file structure */ struct IFile; /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* The text for the actual line is allocated at the end of the structure, so ** the size of the structure varies. */ typedef struct LineInfo LineInfo; struct LineInfo { unsigned RefCount; /* Reference counter */ struct IFile* InputFile; /* Input file for this line */ unsigned LineNum; /* Line number */ char Line[1]; /* Source code line */ }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ LineInfo* UseLineInfo (LineInfo* LI); /* Increase the reference count of the given line info and return it. */ void ReleaseLineInfo (LineInfo* LI); /* Release a reference to the given line info, free the structure if the ** reference count drops to zero. */ LineInfo* GetCurLineInfo (void); /* Return a pointer to the current line info. The reference count is NOT ** increased, use UseLineInfo for that purpose. */ void UpdateLineInfo (struct IFile* F, unsigned LineNum, const StrBuf* Line); /* Update the line info - called if a new line is read */ const char* GetInputName (const LineInfo* LI); /* Return the file name from a line info */ unsigned GetInputLine (const LineInfo* LI); /* Return the line number from a line info */ /* End of lineinfo.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/litpool.c������������������������������������������������������������������������0000664�0000000�0000000�00000033057�13473601511�0015372�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* litpool.c */ /* */ /* Literal string handling for the cc65 C compiler */ /* */ /* */ /* */ /* (C) 1998-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> /* common */ #include "attrib.h" #include "check.h" #include "coll.h" #include "tgttrans.h" #include "xmalloc.h" /* cc65 */ #include "asmlabel.h" #include "codegen.h" #include "error.h" #include "global.h" #include "litpool.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Definition of a literal */ struct Literal { unsigned Label; /* Asm label for this literal */ int RefCount; /* Reference count */ int Output; /* True if output has been generated */ StrBuf Data; /* Literal data */ }; /* Definition of the literal pool */ struct LiteralPool { struct SymEntry* Func; /* Function that owns the pool */ Collection WritableLiterals; /* Writable literals in the pool */ Collection ReadOnlyLiterals; /* Readonly literals in the pool */ }; /* The global and current literal pool */ static LiteralPool* GlobalPool = 0; static LiteralPool* LP = 0; /* Stack that contains the nested literal pools. Since TOS is in LiteralPool ** and functions aren't nested in C, the maximum depth is 1. I'm using a ** collection anyway, so the code is prepared for nested functions or ** whatever. */ static Collection LPStack = STATIC_COLLECTION_INITIALIZER; /*****************************************************************************/ /* struct Literal */ /*****************************************************************************/ static Literal* NewLiteral (const void* Buf, unsigned Len) /* Create a new literal and return it */ { /* Allocate memory */ Literal* L = xmalloc (sizeof (*L)); /* Initialize the fields */ L->Label = GetLocalLabel (); L->RefCount = 0; L->Output = 0; SB_Init (&L->Data); SB_AppendBuf (&L->Data, Buf, Len); /* Return the new literal */ return L; } static void FreeLiteral (Literal* L) /* Free a literal */ { /* Free the literal data */ SB_Done (&L->Data); /* Free the structure itself */ xfree (L); } static void OutputLiteral (Literal* L) /* Output one literal to the currently active data segment */ { /* Translate the literal into the target charset */ TranslateLiteral (L); /* Define the label for the literal */ g_defdatalabel (L->Label); /* Output the literal data */ g_defbytes (SB_GetConstBuf (&L->Data), SB_GetLen (&L->Data)); /* Mark the literal as output */ L->Output = 1; } Literal* UseLiteral (Literal* L) /* Increase the reference counter for the literal and return it */ { /* Increase the reference count */ ++L->RefCount; /* If --local-strings was given, immediately output the literal */ if (IS_Get (&LocalStrings)) { /* Switch to the proper data segment */ if (IS_Get (&WritableStrings)) { g_usedata (); } else { g_userodata (); } /* Output the literal */ OutputLiteral (L); } /* Return the literal */ return L; } void ReleaseLiteral (Literal* L) /* Decrement the reference counter for the literal */ { --L->RefCount; CHECK (L->RefCount >= 0); } void TranslateLiteral (Literal* L) /* Translate a literal into the target charset. */ { TgtTranslateBuf (SB_GetBuf (&L->Data), SB_GetLen (&L->Data)); } unsigned GetLiteralLabel (const Literal* L) /* Return the asm label for a literal */ { return L->Label; } const char* GetLiteralStr (const Literal* L) /* Return the data for a literal as pointer to char */ { return SB_GetConstBuf (&L->Data); } const StrBuf* GetLiteralStrBuf (const Literal* L) /* Return the data for a literal as pointer to the string buffer */ { return &L->Data; } unsigned GetLiteralSize (const Literal* L) /* Get the size of a literal string */ { return SB_GetLen (&L->Data); } /*****************************************************************************/ /* Code */ /*****************************************************************************/ static LiteralPool* NewLiteralPool (struct SymEntry* Func) /* Create a new literal pool and return it */ { /* Allocate memory */ LiteralPool* LP = xmalloc (sizeof (*LP)); /* Initialize the fields */ LP->Func = Func; InitCollection (&LP->WritableLiterals); InitCollection (&LP->ReadOnlyLiterals); /* Return the new pool */ return LP; } static void FreeLiteralPool (LiteralPool* LP) /* Free a LiteralPool structure */ { /* Free the collections contained within the struct */ DoneCollection (&LP->WritableLiterals); DoneCollection (&LP->ReadOnlyLiterals); /* Free the struct itself */ xfree (LP); } static int Compare (void* Data attribute ((unused)), const void* Left, const void* Right) /* Compare function used when sorting the literal pool */ { /* Larger strings are considered "smaller" */ return (int) GetLiteralSize (Right) - (int) GetLiteralSize (Left); } void InitLiteralPool (void) /* Initialize the literal pool */ { /* Create the global literal pool */ GlobalPool = LP = NewLiteralPool (0); } void PushLiteralPool (struct SymEntry* Func) /* Push the current literal pool onto the stack and create a new one */ { /* We must have a literal pool to push! */ PRECONDITION (LP != 0); /* Push the old pool */ CollAppend (&LPStack, LP); /* Create a new one */ LP = NewLiteralPool (Func); } LiteralPool* PopLiteralPool (void) /* Pop the last literal pool from TOS and activate it. Return the old ** literal pool. */ { /* Remember the current literal pool */ LiteralPool* Old = LP; /* Pop one from stack */ LP = CollPop (&LPStack); /* Return the old one */ return Old; } static void MoveLiterals (Collection* Source, Collection* Target) /* Move referenced literals from Source to Target, delete unreferenced ones */ { unsigned I; /* Move referenced literals, remove unreferenced ones */ for (I = 0; I < CollCount (Source); ++I) { /* Get the literal */ Literal* L = CollAt (Source, I); /* If it is referenced and not output, add it to the Target pool, ** otherwise free it */ if (L->RefCount && !L->Output) { CollAppend (Target, L); } else { FreeLiteral (L); } } } void MoveLiteralPool (LiteralPool* LocalPool) /* Move all referenced literals in LocalPool to the global literal pool. This ** function will free LocalPool after moving the used string literals. */ { /* Move the literals */ MoveLiterals (&LocalPool->WritableLiterals, &GlobalPool->WritableLiterals); MoveLiterals (&LocalPool->ReadOnlyLiterals, &GlobalPool->ReadOnlyLiterals); /* Free the local literal pool */ FreeLiteralPool (LocalPool); } static void OutputWritableLiterals (Collection* Literals) /* Output the given writable literals */ { unsigned I; /* If nothing there, exit... */ if (CollCount (Literals) == 0) { return; } /* Switch to the correct segment */ g_usedata (); /* Emit all literals that have a reference */ for (I = 0; I < CollCount (Literals); ++I) { /* Get a pointer to the literal */ Literal* L = CollAtUnchecked (Literals, I); /* Output this one, if it has references and wasn't already output */ if (L->RefCount > 0 && !L->Output) { OutputLiteral (L); } } } static void OutputReadOnlyLiterals (Collection* Literals) /* Output the given readonly literals merging (even partial) duplicates */ { unsigned I; /* If nothing there, exit... */ if (CollCount (Literals) == 0) { return; } /* Switch to the correct segment */ g_userodata (); /* Sort the literal pool by literal size. Larger strings go first */ CollSort (Literals, Compare, 0); /* Emit all literals that have a reference */ for (I = 0; I < CollCount (Literals); ++I) { unsigned J; Literal* C; /* Get the next literal */ Literal* L = CollAt (Literals, I); /* Ignore it, if it doesn't have references or was already output */ if (L->RefCount == 0 || L->Output) { continue; } /* Translate the literal into the target charset */ TranslateLiteral (L); /* Check if this literal is part of another one. Since the literals ** are sorted by size (larger ones first), it can only be part of a ** literal with a smaller index. ** Beware: Only check literals that have actually been referenced. */ C = 0; for (J = 0; J < I; ++J) { const void* D; /* Get a pointer to the compare literal */ Literal* L2 = CollAt (Literals, J); /* Ignore literals that have no reference */ if (L2->RefCount == 0) { continue; } /* Get a pointer to the data */ D = SB_GetConstBuf (&L2->Data) + SB_GetLen (&L2->Data) - SB_GetLen (&L->Data); /* Compare the data */ if (memcmp (D, SB_GetConstBuf (&L->Data), SB_GetLen (&L->Data)) == 0) { /* Remember the literal and terminate the loop */ C = L2; break; } } /* Check if we found a match */ if (C != 0) { /* This literal is part of a longer literal, merge them */ g_aliasdatalabel (L->Label, C->Label, GetLiteralSize (C) - GetLiteralSize (L)); } else { /* Define the label for the literal */ g_defdatalabel (L->Label); /* Output the literal data */ g_defbytes (SB_GetConstBuf (&L->Data), SB_GetLen (&L->Data)); } /* Mark the literal */ L->Output = 1; } } void OutputLiteralPool (void) /* Output the global literal pool */ { /* Output both sorts of literals */ OutputWritableLiterals (&GlobalPool->WritableLiterals); OutputReadOnlyLiterals (&GlobalPool->ReadOnlyLiterals); } Literal* AddLiteral (const char* S) /* Add a literal string to the literal pool. Return the literal. */ { return AddLiteralBuf (S, strlen (S) + 1); } Literal* AddLiteralBuf (const void* Buf, unsigned Len) /* Add a buffer containing a literal string to the literal pool. Return the ** literal. */ { /* Create a new literal */ Literal* L = NewLiteral (Buf, Len); /* Add the literal to the correct pool */ if (IS_Get (&WritableStrings)) { CollAppend (&LP->WritableLiterals, L); } else { CollAppend (&LP->ReadOnlyLiterals, L); } /* Return the new literal */ return L; } Literal* AddLiteralStr (const StrBuf* S) /* Add a literal string to the literal pool. Return the literal. */ { return AddLiteralBuf (SB_GetConstBuf (S), SB_GetLen (S)); } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/litpool.h������������������������������������������������������������������������0000664�0000000�0000000�00000012144�13473601511�0015371�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* litpool.h */ /* */ /* Literal string handling for the cc65 C compiler */ /* */ /* */ /* */ /* (C) 1998-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef LITPOOL_H #define LITPOOL_H #include <stdio.h> /* common */ #include "strbuf.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Forward for struct SymEntry */ struct SymEntry; /* Forward for a literal */ typedef struct Literal Literal; /* Forward for a literal pool */ typedef struct LiteralPool LiteralPool; /*****************************************************************************/ /* struct Literal */ /*****************************************************************************/ Literal* UseLiteral (Literal* L); /* Increase the reference counter for the literal and return it */ void ReleaseLiteral (Literal* L); /* Decrement the reference counter for the literal */ void TranslateLiteral (Literal* L); /* Translate a literal into the target charset. */ unsigned GetLiteralLabel (const Literal* L); /* Return the asm label for a literal */ const char* GetLiteralStr (const Literal* L); /* Return the data for a literal as pointer to char */ const StrBuf* GetLiteralStrBuf (const Literal* L); /* Return the data for a literal as pointer to the string buffer */ unsigned GetLiteralSize (const Literal* L); /* Get the size of a literal string */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ void InitLiteralPool (void); /* Initialize the literal pool */ void PushLiteralPool (struct SymEntry* Func); /* Push the current literal pool onto the stack and create a new one */ LiteralPool* PopLiteralPool (void); /* Pop the last literal pool from TOS and activate it. Return the old ** literal pool. */ void MoveLiteralPool (LiteralPool* LocalPool); /* Move all referenced literals in LocalPool to the global literal pool. This ** function will free LocalPool after moving the used string literals. */ void OutputLiteralPool (void); /* Output the literal pool */ Literal* AddLiteral (const char* S); /* Add a literal string to the literal pool. Return the literal. */ Literal* AddLiteralBuf (const void* Buf, unsigned Len); /* Add a buffer containing a literal string to the literal pool. Return the ** literal. */ Literal* AddLiteralStr (const StrBuf* S); /* Add a literal string to the literal pool. Return the literal. */ /* End of litpool.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/loadexpr.c�����������������������������������������������������������������������0000664�0000000�0000000�00000017203�13473601511�0015521�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* loadexpr.c */ /* */ /* Load an expression into the primary register */ /* */ /* */ /* */ /* (C) 2004-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* cc65 */ #include "codegen.h" #include "error.h" #include "exprdesc.h" #include "global.h" #include "loadexpr.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void LoadConstant (unsigned Flags, ExprDesc* Expr) /* Load the primary register with some constant value. */ { switch (ED_GetLoc (Expr)) { case E_LOC_ABS: /* Number constant */ g_getimmed (Flags | TypeOf (Expr->Type) | CF_CONST, Expr->IVal, 0); break; case E_LOC_GLOBAL: /* Global symbol, load address */ g_getimmed ((Flags | CF_EXTERNAL) & ~CF_CONST, Expr->Name, Expr->IVal); break; case E_LOC_STATIC: case E_LOC_LITERAL: /* Static symbol or literal, load address */ g_getimmed ((Flags | CF_STATIC) & ~CF_CONST, Expr->Name, Expr->IVal); break; case E_LOC_REGISTER: /* Register variable. Taking the address is usually not ** allowed. */ if (IS_Get (&AllowRegVarAddr) == 0) { Error ("Cannot take the address of a register variable"); } g_getimmed ((Flags | CF_REGVAR) & ~CF_CONST, Expr->Name, Expr->IVal); break; case E_LOC_STACK: g_leasp (Expr->IVal); break; default: Internal ("Unknown constant type: %04X", Expr->Flags); } } void LoadExpr (unsigned Flags, struct ExprDesc* Expr) /* Load an expression into the primary register if it is not already there. */ { if (ED_IsLVal (Expr)) { /* Dereferenced lvalue. If this is a bit field its type is unsigned. ** But if the field is completely contained in the lower byte, we will ** throw away the high byte anyway and may therefore load just the ** low byte. */ if (ED_IsBitField (Expr)) { Flags |= (Expr->BitOffs + Expr->BitWidth <= CHAR_BITS)? CF_CHAR : CF_INT; Flags |= CF_UNSIGNED; } else { Flags |= TypeOf (Expr->Type); } if (ED_NeedsTest (Expr)) { Flags |= CF_TEST; } switch (ED_GetLoc (Expr)) { case E_LOC_ABS: /* Absolute: numeric address or const */ g_getstatic (Flags | CF_ABSOLUTE, Expr->IVal, 0); break; case E_LOC_GLOBAL: /* Global variable */ g_getstatic (Flags | CF_EXTERNAL, Expr->Name, Expr->IVal); break; case E_LOC_STATIC: case E_LOC_LITERAL: /* Static variable or literal in the literal pool */ g_getstatic (Flags | CF_STATIC, Expr->Name, Expr->IVal); break; case E_LOC_REGISTER: /* Register variable */ g_getstatic (Flags | CF_REGVAR, Expr->Name, Expr->IVal); break; case E_LOC_STACK: /* Value on the stack */ g_getlocal (Flags, Expr->IVal); break; case E_LOC_PRIMARY: /* The primary register - just test if necessary */ if (Flags & CF_TEST) { g_test (Flags); } break; case E_LOC_EXPR: /* Reference to address in primary with offset in Expr */ g_getind (Flags, Expr->IVal); break; default: Internal ("Invalid location in LoadExpr: 0x%04X", ED_GetLoc (Expr)); } /* Handle bit fields. The actual type may have been casted or ** converted, so be sure to always use unsigned ints for the ** operations. */ if (ED_IsBitField (Expr)) { unsigned F = CF_INT | CF_UNSIGNED | CF_CONST | (Flags & CF_TEST); /* Shift right by the bit offset */ g_asr (F, Expr->BitOffs); /* And by the width if the field doesn't end on an int boundary */ if (Expr->BitOffs + Expr->BitWidth != CHAR_BITS && Expr->BitOffs + Expr->BitWidth != INT_BITS) { g_and (F, (0x0001U << Expr->BitWidth) - 1U); } } /* Expression was tested */ ED_TestDone (Expr); } else { /* An rvalue */ if (ED_IsLocExpr (Expr)) { if (Expr->IVal != 0) { /* We have an expression in the primary plus a constant ** offset. Adjust the value in the primary accordingly. */ Flags |= TypeOf (Expr->Type); g_inc (Flags | CF_CONST, Expr->IVal); } } else { /* Constant of some sort, load it into the primary */ LoadConstant (Flags, Expr); } /* Are we testing this value? */ if (ED_NeedsTest (Expr)) { /* Yes, force a test */ Flags |= TypeOf (Expr->Type); g_test (Flags); ED_TestDone (Expr); } } } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/loadexpr.h�����������������������������������������������������������������������0000664�0000000�0000000�00000006317�13473601511�0015532�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* loadexpr.h */ /* */ /* Load an expression into the primary register */ /* */ /* */ /* */ /* (C) 2004 Ullrich von Bassewitz */ /* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef LOADEXPR_H #define LOADEXPR_H /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ struct ExprDesc; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void LoadExpr (unsigned Flags, struct ExprDesc* Expr); /* Load an expression into the primary register if it is not already there. */ /* End of loadexpr.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/locals.c�������������������������������������������������������������������������0000664�0000000�0000000�00000044774�13473601511�0015175�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* locals.c */ /* */ /* Local variable handling for the cc65 C compiler */ /* */ /* */ /* */ /* (C) 2000-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "xmalloc.h" #include "xsprintf.h" /* cc65 */ #include "anonname.h" #include "asmlabel.h" #include "codegen.h" #include "declare.h" #include "error.h" #include "expr.h" #include "function.h" #include "global.h" #include "loadexpr.h" #include "locals.h" #include "stackptr.h" #include "standard.h" #include "symtab.h" #include "typeconv.h" #include "input.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ static unsigned AllocLabel (void (*UseSeg) ()) /* Switch to a segment, define a local label and return it */ { unsigned Label; /* Switch to the segment */ UseSeg (); /* Define the variable label */ Label = GetLocalLabel (); g_defdatalabel (Label); /* Return the label */ return Label; } static void AllocStorage (unsigned Label, void (*UseSeg) (), unsigned Size) /* Reserve Size bytes of BSS storage prefixed by a local label. */ { /* Switch to the segment */ UseSeg (); /* Define the variable label */ g_defdatalabel (Label); /* Reserve space for the data */ g_res (Size); } static void ParseRegisterDecl (Declaration* Decl, int Reg) /* Parse the declaration of a register variable. Reg is the offset of the ** variable in the register bank. */ { SymEntry* Sym; /* Determine if this is a compound variable */ int IsCompound = IsClassStruct (Decl->Type) || IsTypeArray (Decl->Type); /* Get the size of the variable */ unsigned Size = SizeOf (Decl->Type); /* Save the current contents of the register variable on stack */ F_AllocLocalSpace (CurrentFunc); g_save_regvars (Reg, Size); /* Add the symbol to the symbol table. We do that now, because for register ** variables the current stack pointer is implicitly used as location for ** the save area. */ Sym = AddLocalSym (Decl->Ident, Decl->Type, Decl->StorageClass, Reg); /* Check for an optional initialization */ if (CurTok.Tok == TOK_ASSIGN) { ExprDesc Expr; /* Skip the '=' */ NextToken (); /* Special handling for compound types */ if (IsCompound) { /* Switch to read only data and define a label for the ** initialization data. */ unsigned InitLabel = AllocLabel (g_userodata); /* Parse the initialization generating a memory image of the ** data in the RODATA segment. The function does return the size ** of the initialization data, which may be greater than the ** actual size of the type, if the type is a structure with a ** flexible array member that has been initialized. Since we must ** know the size of the data in advance for register variables, ** we cannot allow that here. */ if (ParseInit (Sym->Type) != Size) { Error ("Cannot initialize flexible array members of storage class 'register'"); } /* Generate code to copy this data into the variable space */ g_initregister (InitLabel, Reg, Size); } else { /* Parse the expression */ hie1 (&Expr); /* Convert it to the target type */ TypeConversion (&Expr, Sym->Type); /* Load the value into the primary */ LoadExpr (CF_NONE, &Expr); /* Store the value into the variable */ g_putstatic (CF_REGVAR | TypeOf (Sym->Type), Reg, 0); } /* Mark the variable as referenced */ Sym->Flags |= SC_REF; } /* Cannot allocate a variable of zero size */ if (Size == 0) { Error ("Variable '%s' has unknown size", Decl->Ident); } } static void ParseAutoDecl (Declaration* Decl) /* Parse the declaration of an auto variable. */ { unsigned Flags; SymEntry* Sym; /* Determine if this is a compound variable */ int IsCompound = IsClassStruct (Decl->Type) || IsTypeArray (Decl->Type); /* Get the size of the variable */ unsigned Size = SizeOf (Decl->Type); /* Check if this is a variable on the stack or in static memory */ if (IS_Get (&StaticLocals) == 0) { /* Add the symbol to the symbol table. The stack offset we use here ** may get corrected later. */ Sym = AddLocalSym (Decl->Ident, Decl->Type, Decl->StorageClass, F_GetStackPtr (CurrentFunc) - (int) Size); /* Check for an optional initialization */ if (CurTok.Tok == TOK_ASSIGN) { ExprDesc Expr; /* Skip the '=' */ NextToken (); /* Special handling for compound types */ if (IsCompound) { /* Switch to read only data and define a label for the ** initialization data. */ unsigned InitLabel = AllocLabel (g_userodata); /* Parse the initialization generating a memory image of the ** data in the RODATA segment. The function will return the ** actual size of the initialization data, which may be ** greater than the size of the variable if it is a struct ** that contains a flexible array member and we're not in ** ANSI mode. */ Size = ParseInit (Sym->Type); /* Now reserve space for the variable on the stack and correct ** the offset in the symbol table entry. */ Sym->V.Offs = F_ReserveLocalSpace (CurrentFunc, Size); /* Next, allocate the space on the stack. This means that the ** variable is now located at offset 0 from the current sp. */ F_AllocLocalSpace (CurrentFunc); /* Generate code to copy the initialization data into the ** variable space */ g_initauto (InitLabel, Size); } else { /* Allocate previously reserved local space */ F_AllocLocalSpace (CurrentFunc); /* Setup the type flags for the assignment */ Flags = (Size == SIZEOF_CHAR)? CF_FORCECHAR : CF_NONE; /* Parse the expression */ hie1 (&Expr); /* Convert it to the target type */ TypeConversion (&Expr, Sym->Type); /* If the value is not const, load it into the primary. ** Otherwise pass the information to the code generator. */ if (ED_IsConstAbsInt (&Expr)) { Flags |= CF_CONST; } else { LoadExpr (CF_NONE, &Expr); ED_MakeRVal (&Expr); } /* Push the value */ g_push (Flags | TypeOf (Sym->Type), Expr.IVal); } /* Mark the variable as referenced */ Sym->Flags |= SC_REF; /* Make note of auto variables initialized in current block. ** We abuse the Collection somewhat by using it to store line ** numbers. */ CollReplace (&CurrentFunc->LocalsBlockStack, (void *)(long)GetCurrentLine (), CollCount (&CurrentFunc->LocalsBlockStack) - 1); } else { /* Non-initialized local variable. Just keep track of ** the space needed. */ F_ReserveLocalSpace (CurrentFunc, Size); } } else { unsigned DataLabel; /* Static local variables. */ Decl->StorageClass = (Decl->StorageClass & ~SC_AUTO) | SC_STATIC; /* Generate a label, but don't define it */ DataLabel = GetLocalLabel (); /* Add the symbol to the symbol table. */ Sym = AddLocalSym (Decl->Ident, Decl->Type, Decl->StorageClass, DataLabel); /* Allow assignments */ if (CurTok.Tok == TOK_ASSIGN) { ExprDesc Expr; /* Skip the '=' */ NextToken (); if (IsCompound) { /* Switch to read only data and define a label for the ** initialization data. */ unsigned InitLabel = AllocLabel (g_userodata); /* Parse the initialization generating a memory image of the ** data in the RODATA segment. */ Size = ParseInit (Sym->Type); /* Allocate space for the variable */ AllocStorage (DataLabel, g_usebss, Size); /* Generate code to copy this data into the variable space */ g_initstatic (InitLabel, DataLabel, Size); } else { /* Allocate space for the variable */ AllocStorage (DataLabel, g_usebss, Size); /* Parse the expression */ hie1 (&Expr); /* Convert it to the target type */ TypeConversion (&Expr, Sym->Type); /* Load the value into the primary */ LoadExpr (CF_NONE, &Expr); /* Store the value into the variable */ g_putstatic (TypeOf (Sym->Type), DataLabel, 0); } /* Mark the variable as referenced */ Sym->Flags |= SC_REF; } else { /* No assignment - allocate a label and space for the variable */ AllocStorage (DataLabel, g_usebss, Size); } } /* Cannot allocate a variable of zero size */ if (Size == 0) { Error ("Variable '%s' has unknown size", Decl->Ident); } } static void ParseStaticDecl (Declaration* Decl) /* Parse the declaration of a static variable. */ { unsigned Size; /* Generate a label, but don't define it */ unsigned DataLabel = GetLocalLabel (); /* Add the symbol to the symbol table. */ SymEntry* Sym = AddLocalSym (Decl->Ident, Decl->Type, Decl->StorageClass, DataLabel); /* Static data */ if (CurTok.Tok == TOK_ASSIGN) { /* Initialization ahead, switch to data segment and define the label. ** For arrays, we need to check the elements of the array for ** constness, not the array itself. */ if (IsQualConst (GetBaseElementType (Sym->Type))) { g_userodata (); } else { g_usedata (); } g_defdatalabel (DataLabel); /* Skip the '=' */ NextToken (); /* Allow initialization of static vars */ Size = ParseInit (Sym->Type); /* Mark the variable as referenced */ Sym->Flags |= SC_REF; } else { /* Get the size of the variable */ Size = SizeOf (Decl->Type); /* Allocate a label and space for the variable in the BSS segment */ AllocStorage (DataLabel, g_usebss, Size); } /* Cannot allocate a variable of zero size */ if (Size == 0) { Error ("Variable '%s' has unknown size", Decl->Ident); } } static void ParseOneDecl (const DeclSpec* Spec) /* Parse one variable declaration */ { Declaration Decl; /* Declaration data structure */ /* Read the declaration */ ParseDecl (Spec, &Decl, DM_NEED_IDENT); /* Set the correct storage class for functions */ if ((Decl.StorageClass & SC_FUNC) == SC_FUNC) { /* Function prototypes are always external */ if ((Decl.StorageClass & SC_EXTERN) == 0) { Warning ("Function must be extern"); } Decl.StorageClass |= SC_EXTERN; } /* If we don't have a name, this was flagged as an error earlier. ** To avoid problems later, use an anonymous name here. */ if (Decl.Ident[0] == '\0') { AnonName (Decl.Ident, "param"); } /* If the symbol is not marked as external, it will be defined now */ if ((Decl.StorageClass & SC_EXTERN) == 0) { Decl.StorageClass |= SC_DEF; } /* Handle anything that needs storage (no functions, no typdefs) */ if ((Decl.StorageClass & SC_FUNC) != SC_FUNC && (Decl.StorageClass & SC_TYPEMASK) != SC_TYPEDEF) { /* If we have a register variable, try to allocate a register and ** convert the declaration to "auto" if this is not possible. */ int Reg = 0; /* Initialize to avoid gcc complains */ if ((Decl.StorageClass & SC_REGISTER) != 0 && (Reg = F_AllocRegVar (CurrentFunc, Decl.Type)) < 0) { /* No space for this register variable, convert to auto */ Decl.StorageClass = (Decl.StorageClass & ~SC_REGISTER) | SC_AUTO; } /* Check the variable type */ if ((Decl.StorageClass & SC_REGISTER) == SC_REGISTER) { /* Register variable */ ParseRegisterDecl (&Decl, Reg); } else if ((Decl.StorageClass & SC_AUTO) == SC_AUTO) { /* Auto variable */ ParseAutoDecl (&Decl); } else if ((Decl.StorageClass & SC_EXTERN) == SC_EXTERN) { /* External identifier - may not get initialized */ if (CurTok.Tok == TOK_ASSIGN) { Error ("Cannot initialize externals"); } /* Add the external symbol to the symbol table */ AddLocalSym (Decl.Ident, Decl.Type, Decl.StorageClass, 0); } else if ((Decl.StorageClass & SC_STATIC) == SC_STATIC) { /* Static variable */ ParseStaticDecl (&Decl); } else { Internal ("Invalid storage class in ParseOneDecl: %04X", Decl.StorageClass); } } else { /* Add the symbol to the symbol table */ AddLocalSym (Decl.Ident, Decl.Type, Decl.StorageClass, 0); } } void DeclareLocals (void) /* Declare local variables and types. */ { /* Remember the current stack pointer */ int InitialStack = StackPtr; /* A place to store info about potential initializations of auto variables */ CollAppend (&CurrentFunc->LocalsBlockStack, 0); /* Loop until we don't find any more variables */ while (1) { /* Check variable declarations. We need to distinguish between a ** default int type and the end of variable declarations. So we ** will do the following: If there is no explicit storage class ** specifier *and* no explicit type given, *and* no type qualifiers ** have been read, it is assumed that we have reached the end of ** declarations. */ DeclSpec Spec; ParseDeclSpec (&Spec, SC_AUTO, T_INT); if ((Spec.Flags & DS_DEF_STORAGE) != 0 && /* No storage spec */ (Spec.Flags & DS_DEF_TYPE) != 0 && /* No type given */ GetQualifier (Spec.Type) == T_QUAL_NONE) { /* No type qualifier */ break; } /* Accept type only declarations */ if (CurTok.Tok == TOK_SEMI) { /* Type declaration only */ CheckEmptyDecl (&Spec); NextToken (); continue; } /* Parse a comma separated variable list */ while (1) { /* Parse one declaration */ ParseOneDecl (&Spec); /* Check if there is more */ if (CurTok.Tok == TOK_COMMA) { /* More to come */ NextToken (); } else { /* Done */ break; } } /* A semicolon must follow */ ConsumeSemi (); } /* Be sure to allocate any reserved space for locals */ F_AllocLocalSpace (CurrentFunc); /* No auto variables were inited. No new block on the stack then. */ if (CollLast (&CurrentFunc->LocalsBlockStack) == NULL) { CollPop (&CurrentFunc->LocalsBlockStack); } /* In case we've allocated local variables in this block, emit a call to ** the stack checking routine if stack checks are enabled. */ if (IS_Get (&CheckStack) && InitialStack != StackPtr) { g_cstackcheck (); } } ����cc65-2.18/src/cc65/locals.h�������������������������������������������������������������������������0000664�0000000�0000000�00000006372�13473601511�0015172�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* locals.h */ /* */ /* Local variable handling for the cc65 C compiler */ /* */ /* */ /* */ /* (C) 2000-2001 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef LOCALS_H #define LOCALS_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ void InitRegVars (void); /* Initialize register variable control data */ void DoneRegVars (void); /* Free the register variables */ void DeclareLocals (void); /* Declare local variables and types. */ void RestoreRegVars (int HaveResult); /* Restore the register variables for the local function if there are any. ** The parameter tells us if there is a return value in ax, in that case, ** the accumulator must be saved across the restore. */ /* End of locals.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/loop.c���������������������������������������������������������������������������0000664�0000000�0000000�00000007601�13473601511�0014655�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* loop.c */ /* */ /* Loop management */ /* */ /* */ /* */ /* (C) 1998-2004 Ullrich von Bassewitz */ /* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "check.h" #include "xmalloc.h" /* cc65 */ #include "error.h" #include "loop.h" #include "stackptr.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* The root */ static LoopDesc* LoopStack = 0; /*****************************************************************************/ /* Code */ /*****************************************************************************/ LoopDesc* AddLoop (unsigned BreakLabel, unsigned ContinueLabel) /* Create and add a new loop descriptor. */ { /* Allocate a new struct */ LoopDesc* L = xmalloc (sizeof (LoopDesc)); /* Fill in the data */ L->StackPtr = StackPtr; L->BreakLabel = BreakLabel; L->ContinueLabel = ContinueLabel; /* Insert it into the list */ L->Next = LoopStack; LoopStack = L; /* Return a pointer to the struct */ return L; } LoopDesc* CurrentLoop (void) /* Return a pointer to the descriptor of the current loop */ { return LoopStack; } void DelLoop (void) /* Remove the current loop */ { LoopDesc* L = LoopStack; CHECK (L != 0); LoopStack = LoopStack->Next; xfree (L); } �������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/loop.h���������������������������������������������������������������������������0000664�0000000�0000000�00000006713�13473601511�0014665�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* loop.h */ /* */ /* Loop management */ /* */ /* */ /* */ /* (C) 1998-2004 Ullrich von Bassewitz */ /* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef LOOP_H #define LOOP_H /*****************************************************************************/ /* data */ /*****************************************************************************/ typedef struct LoopDesc LoopDesc; struct LoopDesc { LoopDesc* Next; unsigned StackPtr; unsigned BreakLabel; unsigned ContinueLabel; }; /*****************************************************************************/ /* code */ /*****************************************************************************/ LoopDesc* AddLoop (unsigned BreakLabel, unsigned ContinueLabel); /* Create and add a new loop descriptor. */ LoopDesc* CurrentLoop (void); /* Return a pointer to the descriptor of the current loop */ void DelLoop (void); /* Remove the current loop */ /* End of loop.h */ #endif �����������������������������������������������������cc65-2.18/src/cc65/macrotab.c�����������������������������������������������������������������������0000664�0000000�0000000�00000020724�13473601511�0015475�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* macrotab.h */ /* */ /* Preprocessor macro table for the cc65 C compiler */ /* */ /* */ /* */ /* (C) 2000-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> /* common */ #include "hashfunc.h" #include "xmalloc.h" /* cc65 */ #include "error.h" #include "macrotab.h" /*****************************************************************************/ /* data */ /*****************************************************************************/ /* The macro hash table */ #define MACRO_TAB_SIZE 211 static Macro* MacroTab[MACRO_TAB_SIZE]; /*****************************************************************************/ /* code */ /*****************************************************************************/ Macro* NewMacro (const char* Name) /* Allocate a macro structure with the given name. The structure is not ** inserted into the macro table. */ { /* Get the length of the macro name */ unsigned Len = strlen(Name); /* Allocate the structure */ Macro* M = (Macro*) xmalloc (sizeof(Macro) + Len); /* Initialize the data */ M->Next = 0; M->Expanding = 0; M->ArgCount = -1; /* Flag: Not a function like macro */ M->MaxArgs = 0; InitCollection (&M->FormalArgs); SB_Init (&M->Replacement); M->Variadic = 0; memcpy (M->Name, Name, Len+1); /* Return the new macro */ return M; } void FreeMacro (Macro* M) /* Delete a macro definition. The function will NOT remove the macro from the ** table, use UndefineMacro for that. */ { unsigned I; for (I = 0; I < CollCount (&M->FormalArgs); ++I) { xfree (CollAtUnchecked (&M->FormalArgs, I)); } DoneCollection (&M->FormalArgs); SB_Done (&M->Replacement); xfree (M); } void DefineNumericMacro (const char* Name, long Val) /* Define a macro for a numeric constant */ { char Buf[64]; /* Make a string from the number */ sprintf (Buf, "%ld", Val); /* Handle as text macro */ DefineTextMacro (Name, Buf); } void DefineTextMacro (const char* Name, const char* Val) /* Define a macro for a textual constant */ { /* Create a new macro */ Macro* M = NewMacro (Name); /* Set the value as replacement text */ SB_CopyStr (&M->Replacement, Val); /* Insert the macro into the macro table */ InsertMacro (M); } void InsertMacro (Macro* M) /* Insert the given macro into the macro table. */ { /* Get the hash value of the macro name */ unsigned Hash = HashStr (M->Name) % MACRO_TAB_SIZE; /* Insert the macro */ M->Next = MacroTab[Hash]; MacroTab[Hash] = M; } int UndefineMacro (const char* Name) /* Search for the macro with the given name and remove it from the macro ** table if it exists. Return 1 if a macro was found and deleted, return ** 0 otherwise. */ { /* Get the hash value of the macro name */ unsigned Hash = HashStr (Name) % MACRO_TAB_SIZE; /* Search the hash chain */ Macro* L = 0; Macro* M = MacroTab[Hash]; while (M) { if (strcmp (M->Name, Name) == 0) { /* Found it */ if (L == 0) { /* First in chain */ MacroTab[Hash] = M->Next; } else { L->Next = M->Next; } /* Delete the macro */ FreeMacro (M); /* Done */ return 1; } /* Next macro */ L = M; M = M->Next; } /* Not found */ return 0; } Macro* FindMacro (const char* Name) /* Find a macro with the given name. Return the macro definition or NULL */ { /* Get the hash value of the macro name */ unsigned Hash = HashStr (Name) % MACRO_TAB_SIZE; /* Search the hash chain */ Macro* M = MacroTab[Hash]; while (M) { if (strcmp (M->Name, Name) == 0) { /* Found it */ return M; } /* Next macro */ M = M->Next; } /* Not found */ return 0; } int FindMacroArg (Macro* M, const char* Arg) /* Search for a formal macro argument. If found, return the index of the ** argument. If the argument was not found, return -1. */ { unsigned I; for (I = 0; I < CollCount (&M->FormalArgs); ++I) { if (strcmp (CollAtUnchecked (&M->FormalArgs, I), Arg) == 0) { /* Found */ return I; } } /* Not found */ return -1; } void AddMacroArg (Macro* M, const char* Arg) /* Add a formal macro argument. */ { /* Check if we have a duplicate macro argument, but add it anyway. ** Beware: Don't use FindMacroArg here, since the actual argument array ** may not be initialized. */ unsigned I; for (I = 0; I < CollCount (&M->FormalArgs); ++I) { if (strcmp (CollAtUnchecked (&M->FormalArgs, I), Arg) == 0) { /* Found */ Error ("Duplicate macro parameter: '%s'", Arg); break; } } /* Add the new argument */ CollAppend (&M->FormalArgs, xstrdup (Arg)); ++M->ArgCount; } int MacroCmp (const Macro* M1, const Macro* M2) /* Compare two macros and return zero if both are identical. */ { int I; /* Argument count must be identical */ if (M1->ArgCount != M2->ArgCount) { return 1; } /* Compare the arguments */ for (I = 0; I < M1->ArgCount; ++I) { if (strcmp (CollConstAt (&M1->FormalArgs, I), CollConstAt (&M2->FormalArgs, I)) != 0) { return 1; } } /* Compare the replacement */ return SB_Compare (&M1->Replacement, &M2->Replacement); } void PrintMacroStats (FILE* F) /* Print macro statistics to the given text file. */ { unsigned I; Macro* M; fprintf (F, "\n\nMacro Hash Table Summary\n"); for (I = 0; I < MACRO_TAB_SIZE; ++I) { fprintf (F, "%3u : ", I); M = MacroTab [I]; if (M) { while (M) { fprintf (F, "%s ", M->Name); M = M->Next; } fprintf (F, "\n"); } else { fprintf (F, "empty\n"); } } } ��������������������������������������������cc65-2.18/src/cc65/macrotab.h�����������������������������������������������������������������������0000664�0000000�0000000�00000012460�13473601511�0015500�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* macrotab.h */ /* */ /* Preprocessor macro table for the cc65 C compiler */ /* */ /* */ /* */ /* (C) 2000-2005, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef MACROTAB_H #define MACROTAB_H /* common */ #include "coll.h" #include "inline.h" #include "strbuf.h" /*****************************************************************************/ /* data */ /*****************************************************************************/ /* Structure describing a macro */ typedef struct Macro Macro; struct Macro { Macro* Next; /* Next macro with same hash value */ int Expanding; /* Are we currently expanding this macro? */ int ArgCount; /* Number of parameters, -1 = no parens */ unsigned MaxArgs; /* Size of formal argument list */ Collection FormalArgs; /* Formal argument list (char*) */ StrBuf Replacement; /* Replacement text */ unsigned char Variadic; /* C99 variadic macro */ char Name[1]; /* Name, dynamically allocated */ }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ Macro* NewMacro (const char* Name); /* Allocate a macro structure with the given name. The structure is not ** inserted into the macro table. */ void FreeMacro (Macro* M); /* Delete a macro definition. The function will NOT remove the macro from the ** table, use UndefineMacro for that. */ void DefineNumericMacro (const char* Name, long Val); /* Define a macro for a numeric constant */ void DefineTextMacro (const char* Name, const char* Val); /* Define a macro for a textual constant */ void InsertMacro (Macro* M); /* Insert the given macro into the macro table. */ int UndefineMacro (const char* Name); /* Search for the macro with the given name and remove it from the macro ** table if it exists. Return 1 if a macro was found and deleted, return ** 0 otherwise. */ Macro* FindMacro (const char* Name); /* Find a macro with the given name. Return the macro definition or NULL */ #if defined(HAVE_INLINE) INLINE int IsMacro (const char* Name) /* Return true if the given name is the name of a macro, return false otherwise */ { return FindMacro (Name) != 0; } #else # define IsMacro(Name) (FindMacro (Name) != 0) #endif int FindMacroArg (Macro* M, const char* Arg); /* Search for a formal macro argument. If found, return the index of the ** argument. If the argument was not found, return -1. */ void AddMacroArg (Macro* M, const char* Arg); /* Add a formal macro argument. */ int MacroCmp (const Macro* M1, const Macro* M2); /* Compare two macros and return zero if both are identical. */ void PrintMacroStats (FILE* F); /* Print macro statistics to the given text file. */ /* End of macrotab.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/main.c���������������������������������������������������������������������������0000664�0000000�0000000�00000074560�13473601511�0014640�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* main.c */ /* */ /* cc65 main program */ /* */ /* */ /* */ /* (C) 2000-2015, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <errno.h> /* common */ #include "abend.h" #include "chartype.h" #include "cmdline.h" #include "cpu.h" #include "debugflag.h" #include "fname.h" #include "mmodel.h" #include "print.h" #include "segnames.h" #include "strbuf.h" #include "target.h" #include "tgttrans.h" #include "version.h" #include "xmalloc.h" /* cc65 */ #include "asmcode.h" #include "compile.h" #include "codeopt.h" #include "error.h" #include "global.h" #include "incpath.h" #include "input.h" #include "macrotab.h" #include "output.h" #include "scanner.h" #include "segments.h" #include "standard.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void Usage (void) /* Print usage information to stderr */ { printf ("Usage: %s [options] file\n" "Short options:\n" " -Cl\t\t\t\tMake local variables static\n" " -Dsym[=defn]\t\t\tDefine a symbol\n" " -E\t\t\t\tStop after the preprocessing stage\n" " -I dir\t\t\tSet an include directory search path\n" " -O\t\t\t\tOptimize code\n" " -Oi\t\t\t\tOptimize code, inline more code\n" " -Or\t\t\t\tEnable register variables\n" " -Os\t\t\t\tInline some standard functions\n" " -T\t\t\t\tInclude source as comment\n" " -V\t\t\t\tPrint the compiler version number\n" " -W warning[,...]\t\tSuppress warnings\n" " -d\t\t\t\tDebug mode\n" " -g\t\t\t\tAdd debug info to object file\n" " -h\t\t\t\tHelp (this text)\n" " -j\t\t\t\tDefault characters are signed\n" " -mm model\t\t\tSet the memory model\n" " -o name\t\t\tName the output file\n" " -r\t\t\t\tEnable register variables\n" " -t sys\t\t\tSet the target system\n" " -v\t\t\t\tIncrease verbosity\n" "\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" " --codesize x\t\t\tAccept larger code by factor x\n" " --cpu type\t\t\tSet cpu type (6502, 65c02)\n" " --create-dep name\t\tCreate a make dependency file\n" " --create-full-dep name\tCreate a full make dependency file\n" " --data-name seg\t\tSet the name of the DATA segment\n" " --debug\t\t\tDebug mode\n" " --debug-info\t\t\tAdd debug info to object file\n" " --debug-opt name\t\tDebug optimization steps\n" " --dep-target target\t\tUse this dependency target\n" " --disable-opt name\t\tDisable an optimization step\n" " --eagerly-inline-funcs\tEagerly inline some known functions\n" " --enable-opt name\t\tEnable an optimization step\n" " --help\t\t\tHelp (this text)\n" " --include-dir dir\t\tSet an include directory search path\n" " --inline-stdfuncs\t\tInline some standard functions\n" " --list-opt-steps\t\tList all optimizer steps and exit\n" " --list-warnings\t\tList available warning types for -W\n" " --local-strings\t\tEmit string literals immediately\n" " --memory-model model\t\tSet the memory model\n" " --register-space b\t\tSet space available for register variables\n" " --register-vars\t\tEnable register variables\n" " --rodata-name seg\t\tSet the name of the RODATA segment\n" " --signed-chars\t\tDefault characters are signed\n" " --standard std\t\tLanguage standard (c89, c99, cc65)\n" " --static-locals\t\tMake local variables static\n" " --target sys\t\t\tSet the target system\n" " --verbose\t\t\tIncrease verbosity\n" " --version\t\t\tPrint the compiler version number\n" " --writable-strings\t\tMake string literals writable\n", ProgName); } static void cbmsys (const char* sys) /* Define a CBM system */ { DefineNumericMacro ("__CBM__", 1); DefineNumericMacro (sys, 1); } static void SetSys (const char* Sys) /* Define a target system */ { switch (Target = FindTarget (Sys)) { case TGT_NONE: break; case TGT_MODULE: AbEnd ("Cannot use 'module' as a target for the compiler"); break; case TGT_ATARI2600: DefineNumericMacro ("__ATARI2600__", 1); break; case TGT_ATARI5200: DefineNumericMacro ("__ATARI5200__", 1); break; case TGT_ATARI: DefineNumericMacro ("__ATARI__", 1); break; case TGT_ATARIXL: DefineNumericMacro ("__ATARI__", 1); DefineNumericMacro ("__ATARIXL__", 1); break; case TGT_C16: cbmsys ("__C16__"); break; case TGT_C64: cbmsys ("__C64__"); break; case TGT_VIC20: cbmsys ("__VIC20__"); break; case TGT_C128: cbmsys ("__C128__"); break; case TGT_PLUS4: cbmsys ("__C16__"); DefineNumericMacro ("__PLUS4__", 1); break; case TGT_CBM510: cbmsys ("__CBM510__"); break; case TGT_CBM610: cbmsys ("__CBM610__"); break; case TGT_PET: cbmsys ("__PET__"); break; case TGT_BBC: DefineNumericMacro ("__BBC__", 1); break; case TGT_APPLE2: DefineNumericMacro ("__APPLE2__", 1); break; case TGT_APPLE2ENH: DefineNumericMacro ("__APPLE2__", 1); DefineNumericMacro ("__APPLE2ENH__", 1); break; case TGT_GAMATE: DefineNumericMacro ("__GAMATE__", 1); break; case TGT_GEOS_CBM: /* Do not handle as a CBM system */ DefineNumericMacro ("__GEOS__", 1); DefineNumericMacro ("__GEOS_CBM__", 1); break; case TGT_CREATIVISION: DefineNumericMacro ("__CREATIVISION__", 1); break; case TGT_GEOS_APPLE: DefineNumericMacro ("__GEOS__", 1); DefineNumericMacro ("__GEOS_APPLE__", 1); break; case TGT_LUNIX: DefineNumericMacro ("__LUNIX__", 1); break; case TGT_ATMOS: DefineNumericMacro ("__ATMOS__", 1); break; case TGT_TELESTRAT: DefineNumericMacro ("__TELESTRAT__", 1); break; case TGT_NES: DefineNumericMacro ("__NES__", 1); break; case TGT_SUPERVISION: DefineNumericMacro ("__SUPERVISION__", 1); break; case TGT_LYNX: DefineNumericMacro ("__LYNX__", 1); break; case TGT_SIM6502: DefineNumericMacro ("__SIM6502__", 1); break; case TGT_SIM65C02: 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); } /* Initialize the translation tables for the target system */ TgtTranslateInit (); } static void FileNameOption (const char* Opt, const char* Arg, StrBuf* Name) /* Handle an option that remembers a file name for later */ { /* Cannot have the option twice */ if (SB_NotEmpty (Name)) { AbEnd ("Cannot use option '%s' twice", Opt); } /* A typo in OptTab[] might allow a NULL Arg */ if (Arg == 0) { Internal ("Typo in OptTab[]; option '%s' should require an argument", Opt); } /* Remember the file name for later */ SB_CopyStr (Name, Arg); SB_Terminate (Name); } static void DefineSym (const char* Def) /* Define a symbol on the command line */ { const char* P = Def; /* The symbol must start with a character or underline */ if (Def [0] != '_' && !IsAlpha (Def [0])) { InvDef (Def); } /* Check the symbol name */ while (IsAlNum (*P) || *P == '_') { ++P; } /* Do we have a value given? */ if (*P != '=') { if (*P != '\0') { InvDef (Def); } /* No value given. Define the macro with the value 1 */ DefineNumericMacro (Def, 1); } else { /* We have a value, P points to the '=' character. Since the argument ** is const, create a copy and replace the '=' in the copy by a zero ** terminator. */ char* Q; unsigned Len = strlen (Def)+1; char* S = (char*) xmalloc (Len); memcpy (S, Def, Len); Q = S + (P - Def); *Q++ = '\0'; /* Define this as a macro */ DefineTextMacro (S, Q); /* Release the allocated memory */ xfree (S); } } static void CheckSegName (const char* Seg) /* Abort if the given name is not a valid segment name */ { /* Print an error and abort if the name is not ok */ if (!ValidSegName (Seg)) { AbEnd ("Segment name '%s' is invalid", Seg); } } static void OptAddSource (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Add source lines as comments in generated assembler file */ { AddSource = 1; } 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 */ { /* Check for a valid name */ CheckSegName (Arg); /* Set the name */ SetSegName (SEG_BSS, Arg); } static void OptCheckStack (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Handle the --check-stack option */ { IS_Set (&CheckStack, 1); } static void OptCodeName (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --code-name option */ { /* Check for a valid name */ CheckSegName (Arg); /* Set the name */ SetSegName (SEG_CODE, Arg); } static void OptCodeSize (const char* Opt, const char* Arg) /* Handle the --codesize option */ { unsigned Factor; char BoundsCheck; /* Numeric argument expected */ if (sscanf (Arg, "%u%c", &Factor, &BoundsCheck) != 1 || Factor < 10 || Factor > 1000) { AbEnd ("Argument for %s is invalid", Opt); } IS_Set (&CodeSizeFactor, Factor); } static void OptCreateDep (const char* Opt, const char* Arg) /* Handle the --create-dep option */ { FileNameOption (Opt, Arg, &DepName); } static void OptCreateFullDep (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --create-full-dep option */ { FileNameOption (Opt, Arg, &FullDepName); } static void OptCPU (const char* Opt, const char* Arg) /* Handle the --cpu option */ { /* Find the CPU from the given name */ CPU = FindCPU (Arg); if (CPU != CPU_6502 && CPU != CPU_6502X && CPU != CPU_65SC02 && CPU != CPU_65C02 && CPU != CPU_65816 && CPU != CPU_HUC6280) { AbEnd ("Invalid argument for %s: '%s'", Opt, Arg); } } static void OptDataName (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --data-name option */ { /* Check for a valid name */ CheckSegName (Arg); /* Set the name */ SetSegName (SEG_DATA, Arg); } static void OptDebug (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Compiler debug mode */ { ++Debug; } static void OptDebugInfo (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Add debug info to the object file */ { DebugInfo = 1; } static void OptDebugOpt (const char* Opt attribute ((unused)), const char* Arg) /* Debug optimization steps */ { char Buf [128]; char* Line; /* Open the file */ FILE* F = fopen (Arg, "r"); if (F == 0) { AbEnd ("Cannot open '%s': %s", Arg, strerror (errno)); } /* Read line by line, ignore empty lines and switch optimization ** steps on/off. */ while (fgets (Buf, sizeof (Buf), F) != 0) { /* Remove trailing control chars. This will also remove the ** trailing newline. */ unsigned Len = strlen (Buf); while (Len > 0 && IsControl (Buf[Len-1])) { --Len; } Buf[Len] = '\0'; /* Get a pointer to the buffer and remove leading white space */ Line = Buf; while (IsBlank (*Line)) { ++Line; } /* Check the first character and enable/disable the step or ** ignore the line */ switch (*Line) { case '\0': case '#': case ';': /* Empty or comment line */ continue; case '-': DisableOpt (Line+1); break; case '+': ++Line; /* FALLTHROUGH */ default: EnableOpt (Line); break; } } /* Close the file, no error check here since we were just reading and ** this is only a debug function. */ (void) fclose (F); } static void OptDebugOptOutput (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Output optimization steps */ { DebugOptOutput = 1; } static void OptDepTarget (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --dep-target option */ { FileNameOption (Opt, Arg, &DepTarget); } static void OptDisableOpt (const char* Opt attribute ((unused)), const char* Arg) /* Disable an optimization step */ { DisableOpt (Arg); } static void OptEagerlyInlineFuncs (const char* Opt attribute((unused)), const char* Arg attribute((unused))) /* Eagerly inline some known functions */ { IS_Set (&InlineStdFuncs, 1); IS_Set (&EagerlyInlineFuncs, 1); } static void OptEnableOpt (const char* Opt attribute ((unused)), const char* Arg) /* Enable an optimization step */ { EnableOpt (Arg); } static void OptHelp (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Print usage information and exit */ { Usage (); exit (EXIT_SUCCESS); } static void OptIncludeDir (const char* Opt attribute ((unused)), const char* Arg) /* Add an include search path */ { AddSearchPath (SysIncSearchPath, Arg); AddSearchPath (UsrIncSearchPath, Arg); } static void OptInlineStdFuncs (const char* Opt attribute((unused)), const char* Arg attribute((unused))) /* Inline some standard functions */ { IS_Set (&InlineStdFuncs, 1); } static void OptListOptSteps (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* List all optimizer steps */ { /* List the optimizer steps */ ListOptSteps (stdout); /* Terminate */ exit (EXIT_SUCCESS); } static void OptListWarnings (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* List all warning types */ { /* List the warnings */ ListWarnings (stdout); /* Terminate */ exit (EXIT_SUCCESS); } static void OptLocalStrings (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Emit string literals immediately */ { IS_Set (&LocalStrings, 1); } static void OptMemoryModel (const char* Opt, const char* Arg) /* Set the memory model */ { mmodel_t M; /* Check the current memory model */ if (MemoryModel != MMODEL_UNKNOWN) { AbEnd ("Cannot use option '%s' twice", Opt); } /* Translate the memory model name and check it */ M = FindMemoryModel (Arg); if (M == MMODEL_UNKNOWN) { AbEnd ("Unknown memory model: %s", Arg); } else if (M == MMODEL_HUGE) { AbEnd ("Unsupported memory model: %s", Arg); } /* Set the memory model */ SetMemoryModel (M); } static void OptRegisterSpace (const char* Opt, const char* Arg) /* Handle the --register-space option */ { /* Numeric argument expected */ if (sscanf (Arg, "%u", &RegisterSpace) != 1 || RegisterSpace > 256) { AbEnd ("Argument for option %s is invalid", Opt); } } static void OptRegisterVars (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Handle the --register-vars option */ { IS_Set (&EnableRegVars, 1); } static void OptRodataName (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --rodata-name option */ { /* Check for a valid name */ CheckSegName (Arg); /* Set the name */ SetSegName (SEG_RODATA, Arg); } static void OptSignedChars (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Make default characters signed */ { IS_Set (&SignedChars, 1); } static void OptStandard (const char* Opt, const char* Arg) /* Handle the --standard option */ { /* Find the standard from the given name */ standard_t Std = FindStandard (Arg); if (Std == STD_UNKNOWN) { AbEnd ("Invalid argument for %s: '%s'", Opt, Arg); } else if (IS_Get (&Standard) != STD_UNKNOWN) { AbEnd ("Option %s given more than once", Opt); } else { IS_Set (&Standard, Std); } } static void OptStaticLocals (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Place local variables in static storage */ { IS_Set (&StaticLocals, 1); } static void OptTarget (const char* Opt attribute ((unused)), const char* Arg) /* Set the target system */ { SetSys (Arg); } static void OptVerbose (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Increase verbosity */ { ++Verbosity; } static void OptVersion (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Print the compiler version */ { fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ()); exit (EXIT_SUCCESS); } static void OptWarning (const char* Opt attribute ((unused)), const char* Arg) /* Handle the -W option */ { StrBuf W = AUTO_STRBUF_INITIALIZER; /* Arg is a list of suboptions, separated by commas */ while (Arg) { const char* Pos; int Enabled = 1; IntStack* S; /* The suboption may be prefixed with '-' or '+' */ if (*Arg == '-') { Enabled = 0; ++Arg; } else if (*Arg == '+') { /* This is the default */ ++Arg; } /* Get the next suboption */ Pos = strchr (Arg, ','); if (Pos) { SB_CopyBuf (&W, Arg, Pos - Arg); Arg = Pos + 1; } else { SB_CopyStr (&W, Arg); Arg = 0; } SB_Terminate (&W); /* Search for the warning */ S = FindWarning (SB_GetConstBuf (&W)); if (S == 0) { InvArg (Opt, SB_GetConstBuf (&W)); } IS_Set (S, Enabled); } /* Free allocated memory */ SB_Done (&W); } static void OptWritableStrings (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Make string literals writable */ { IS_Set (&WritableStrings, 1); } 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 }, { "--codesize", 1, OptCodeSize }, { "--cpu", 1, OptCPU }, { "--create-dep", 1, OptCreateDep }, { "--create-full-dep", 1, OptCreateFullDep }, { "--data-name", 1, OptDataName }, { "--debug", 0, OptDebug }, { "--debug-info", 0, OptDebugInfo }, { "--debug-opt", 1, OptDebugOpt }, { "--debug-opt-output", 0, OptDebugOptOutput }, { "--dep-target", 1, OptDepTarget }, { "--disable-opt", 1, OptDisableOpt }, { "--eagerly-inline-funcs", 0, OptEagerlyInlineFuncs }, { "--enable-opt", 1, OptEnableOpt }, { "--help", 0, OptHelp }, { "--include-dir", 1, OptIncludeDir }, { "--inline-stdfuncs", 0, OptInlineStdFuncs }, { "--list-opt-steps", 0, OptListOptSteps }, { "--list-warnings", 0, OptListWarnings }, { "--local-strings", 0, OptLocalStrings }, { "--memory-model", 1, OptMemoryModel }, { "--register-space", 1, OptRegisterSpace }, { "--register-vars", 0, OptRegisterVars }, { "--rodata-name", 1, OptRodataName }, { "--signed-chars", 0, OptSignedChars }, { "--standard", 1, OptStandard }, { "--static-locals", 0, OptStaticLocals }, { "--target", 1, OptTarget }, { "--verbose", 0, OptVerbose }, { "--version", 0, OptVersion }, { "--writable-strings", 0, OptWritableStrings }, }; unsigned I; /* Initialize the input file name */ const char* InputFile = 0; /* Initialize the cmdline module */ InitCmdLine (&argc, &argv, "cc65"); /* Initialize the default segment names */ InitSegNames (); /* Initialize the include search paths */ InitIncludePaths (); /* Parse the command line */ I = 1; while (I < ArgCount) { const char* P; /* Get the argument */ const char* Arg = ArgVec[I]; /* Check for an option */ if (Arg[0] == '-') { switch (Arg[1]) { case '-': LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0])); break; case 'd': OptDebug (Arg, 0); break; case 'h': case '?': OptHelp (Arg, 0); break; case 'g': OptDebugInfo (Arg, 0); break; case 'j': OptSignedChars (Arg, 0); break; case 'o': SetOutputName (GetArg (&I, 2)); break; case 'r': OptRegisterVars (Arg, 0); break; case 't': OptTarget (Arg, GetArg (&I, 2)); break; case 'u': OptCreateDep (Arg, 0); break; case 'v': OptVerbose (Arg, 0); break; case 'C': P = Arg + 2; while (*P) { switch (*P++) { case 'l': OptStaticLocals (Arg, 0); break; default: UnknownOption (Arg); break; } } break; case 'D': DefineSym (GetArg (&I, 2)); break; case 'E': PreprocessOnly = 1; break; case 'I': OptIncludeDir (Arg, GetArg (&I, 2)); break; case 'O': IS_Set (&Optimize, 1); P = Arg + 2; while (*P) { switch (*P++) { case 'i': IS_Set (&CodeSizeFactor, 200); break; case 'r': IS_Set (&EnableRegVars, 1); break; case 's': IS_Set (&InlineStdFuncs, 1); break; default: UnknownOption (Arg); break; } } break; case 'T': OptAddSource (Arg, 0); break; case 'V': OptVersion (Arg, 0); break; case 'W': OptWarning (Arg, GetArg (&I, 2)); break; default: UnknownOption (Arg); break; } } else { if (InputFile) { fprintf (stderr, "additional file specs ignored\n"); } else { InputFile = Arg; } } /* Next argument */ ++I; } /* Did we have a file spec on the command line? */ if (InputFile == 0) { AbEnd ("No input files"); } /* Add the default include search paths. */ FinishIncludePaths (); /* Create the output file name if it was not explicitly given */ MakeDefaultOutputName (InputFile); /* If no CPU given, use the default CPU for the target */ if (CPU == CPU_UNKNOWN) { if (Target != TGT_UNKNOWN) { CPU = GetTargetProperties (Target)->DefaultCPU; } else { CPU = CPU_6502; } } /* If no memory model was given, use the default */ if (MemoryModel == MMODEL_UNKNOWN) { SetMemoryModel (MMODEL_NEAR); } /* If no language standard was given, use the default one */ if (IS_Get (&Standard) == STD_UNKNOWN) { IS_Set (&Standard, STD_DEFAULT); } /* Go! */ Compile (InputFile); /* Create the output file if we didn't had any errors */ if (PreprocessOnly == 0 && (ErrorCount == 0 || Debug)) { /* Emit literals, externals, do cleanup and optimizations */ FinishCompile (); /* Open the file */ OpenOutputFile (); /* Write the output to the file */ WriteAsmOutput (); Print (stdout, 1, "Wrote output to '%s'\n", OutputFilename); /* Close the file, check for errors */ CloseOutputFile (); /* Create dependencies if requested */ CreateDependencies (); } /* Return an apropriate exit code */ return (ErrorCount > 0)? EXIT_FAILURE : EXIT_SUCCESS; } ������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/opcodes.c������������������������������������������������������������������������0000664�0000000�0000000�00000107751�13473601511�0015347�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* opcodes.c */ /* */ /* Opcode and addressing mode definitions */ /* */ /* */ /* */ /* (C) 2001-2004 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include "stdlib.h" #include <string.h> #include <ctype.h> /* common */ #include "check.h" #include "cpu.h" /* cc65 */ #include "codeinfo.h" #include "error.h" #include "opcodes.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Opcode description table */ const OPCDesc OPCTable[OP65_COUNT] = { /* 65XX opcodes */ { OP65_ADC, /* opcode */ "adc", /* mnemonic */ 0, /* size */ REG_A, /* use */ REG_A, /* chg */ OF_SETF /* flags */ }, { OP65_AND, /* opcode */ "and", /* mnemonic */ 0, /* size */ REG_A, /* use */ REG_A, /* chg */ OF_SETF /* flags */ }, { OP65_ASL, /* opcode */ "asl", /* mnemonic */ 0, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_SETF | OF_NOIMP /* flags */ }, { OP65_BCC, /* opcode */ "bcc", /* mnemonic */ 2, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_CBRA /* flags */ }, { OP65_BCS, /* opcode */ "bcs", /* mnemonic */ 2, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_CBRA /* flags */ }, { OP65_BEQ, /* opcode */ "beq", /* mnemonic */ 2, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_CBRA | OF_ZBRA | OF_FBRA /* flags */ }, { OP65_BIT, /* opcode */ "bit", /* mnemonic */ 0, /* size */ REG_A, /* use */ REG_NONE, /* chg */ OF_SETF /* flags */ }, { OP65_BMI, /* opcode */ "bmi", /* mnemonic */ 2, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_CBRA | OF_FBRA /* flags */ }, { OP65_BNE, /* opcode */ "bne", /* mnemonic */ 2, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_CBRA | OF_ZBRA | OF_FBRA /* flags */ }, { OP65_BPL, /* opcode */ "bpl", /* mnemonic */ 2, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_CBRA | OF_FBRA /* flags */ }, { OP65_BRA, /* opcode */ "bra", /* mnemonic */ 2, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_UBRA /* flags */ }, { OP65_BRK, /* opcode */ "brk", /* mnemonic */ 1, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_NONE /* flags */ }, { OP65_BVC, /* opcode */ "bvc", /* mnemonic */ 2, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_CBRA /* flags */ }, { OP65_BVS, /* opcode */ "bvs", /* mnemonic */ 2, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_CBRA /* flags */ }, { OP65_CLC, /* opcode */ "clc", /* mnemonic */ 1, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_NONE /* flags */ }, { OP65_CLD, /* opcode */ "cld", /* mnemonic */ 1, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_NONE /* flags */ }, { OP65_CLI, /* opcode */ "cli", /* mnemonic */ 1, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_NONE /* flags */ }, { OP65_CLV, /* opcode */ "clv", /* mnemonic */ 1, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_NONE /* flags */ }, { OP65_CMP, /* opcode */ "cmp", /* mnemonic */ 0, /* size */ REG_A, /* use */ REG_NONE, /* chg */ OF_SETF | OF_CMP /* flags */ }, { OP65_CPX, /* opcode */ "cpx", /* mnemonic */ 0, /* size */ REG_X, /* use */ REG_NONE, /* chg */ OF_SETF | OF_CMP /* flags */ }, { OP65_CPY, /* opcode */ "cpy", /* mnemonic */ 0, /* size */ REG_Y, /* use */ REG_NONE, /* chg */ OF_SETF | OF_CMP /* flags */ }, { OP65_DEA, /* opcode */ "dea", /* mnemonic */ 1, /* size */ REG_A, /* use */ REG_A, /* chg */ OF_REG_INCDEC | OF_SETF /* flags */ }, { OP65_DEC, /* opcode */ "dec", /* mnemonic */ 0, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_SETF | OF_NOIMP /* flags */ }, { OP65_DEX, /* opcode */ "dex", /* mnemonic */ 1, /* size */ REG_X, /* use */ REG_X, /* chg */ OF_REG_INCDEC | OF_SETF /* flags */ }, { OP65_DEY, /* opcode */ "dey", /* mnemonic */ 1, /* size */ REG_Y, /* use */ REG_Y, /* chg */ OF_REG_INCDEC | OF_SETF /* flags */ }, { OP65_EOR, /* opcode */ "eor", /* mnemonic */ 0, /* size */ REG_A, /* use */ REG_A, /* chg */ OF_SETF /* flags */ }, { OP65_INA, /* opcode */ "ina", /* mnemonic */ 1, /* size */ REG_A, /* use */ REG_A, /* chg */ OF_REG_INCDEC | OF_SETF /* flags */ }, { OP65_INC, /* opcode */ "inc", /* mnemonic */ 0, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_SETF | OF_NOIMP /* flags */ }, { OP65_INX, /* opcode */ "inx", /* mnemonic */ 1, /* size */ REG_X, /* use */ REG_X, /* chg */ OF_REG_INCDEC | OF_SETF /* flags */ }, { OP65_INY, /* opcode */ "iny", /* mnemonic */ 1, /* size */ REG_Y, /* use */ REG_Y, /* chg */ OF_REG_INCDEC | OF_SETF /* flags */ }, { OP65_JCC, /* opcode */ "jcc", /* mnemonic */ 5, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_CBRA | OF_LBRA /* flags */ }, { OP65_JCS, /* opcode */ "jcs", /* mnemonic */ 5, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_CBRA | OF_LBRA /* flags */ }, { OP65_JEQ, /* opcode */ "jeq", /* mnemonic */ 5, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_CBRA | OF_LBRA | OF_ZBRA | OF_FBRA /* flags */ }, { OP65_JMI, /* opcode */ "jmi", /* mnemonic */ 5, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_CBRA | OF_LBRA | OF_FBRA /* flags */ }, { OP65_JMP, /* opcode */ "jmp", /* mnemonic */ 3, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_UBRA | OF_LBRA /* flags */ }, { OP65_JNE, /* opcode */ "jne", /* mnemonic */ 5, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_CBRA | OF_LBRA | OF_ZBRA | OF_FBRA /* flags */ }, { OP65_JPL, /* opcode */ "jpl", /* mnemonic */ 5, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_CBRA | OF_LBRA | OF_FBRA /* flags */ }, { OP65_JSR, /* opcode */ "jsr", /* mnemonic */ 3, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_CALL /* flags */ }, { OP65_JVC, /* opcode */ "jvc", /* mnemonic */ 5, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_CBRA | OF_LBRA /* flags */ }, { OP65_JVS, /* opcode */ "jvs", /* mnemonic */ 5, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_CBRA | OF_LBRA /* flags */ }, { OP65_LDA, /* opcode */ "lda", /* mnemonic */ 0, /* size */ REG_NONE, /* use */ REG_A, /* chg */ OF_LOAD | OF_SETF /* flags */ }, { OP65_LDX, /* opcode */ "ldx", /* mnemonic */ 0, /* size */ REG_NONE, /* use */ REG_X, /* chg */ OF_LOAD | OF_SETF /* flags */ }, { OP65_LDY, /* opcode */ "ldy", /* mnemonic */ 0, /* size */ REG_NONE, /* use */ REG_Y, /* chg */ OF_LOAD | OF_SETF /* flags */ }, { OP65_LSR, /* opcode */ "lsr", /* mnemonic */ 0, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_SETF | OF_NOIMP /* flags */ }, { OP65_NOP, /* opcode */ "nop", /* mnemonic */ 1, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_NONE /* flags */ }, { OP65_ORA, /* opcode */ "ora", /* mnemonic */ 0, /* size */ REG_A, /* use */ REG_A, /* chg */ OF_SETF /* flags */ }, { OP65_PHA, /* opcode */ "pha", /* mnemonic */ 1, /* size */ REG_A, /* use */ REG_NONE, /* chg */ OF_NONE /* flags */ }, { OP65_PHP, /* opcode */ "php", /* mnemonic */ 1, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_NONE /* flags */ }, { OP65_PHX, /* opcode */ "phx", /* mnemonic */ 1, /* size */ REG_X, /* use */ REG_NONE, /* chg */ OF_NONE /* flags */ }, { OP65_PHY, /* opcode */ "phy", /* mnemonic */ 1, /* size */ REG_Y, /* use */ REG_NONE, /* chg */ OF_NONE /* flags */ }, { OP65_PLA, /* opcode */ "pla", /* mnemonic */ 1, /* size */ REG_NONE, /* use */ REG_A, /* chg */ OF_SETF /* flags */ }, { OP65_PLP, /* opcode */ "plp", /* mnemonic */ 1, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_NONE /* flags */ }, { OP65_PLX, /* opcode */ "plx", /* mnemonic */ 1, /* size */ REG_NONE, /* use */ REG_X, /* chg */ OF_SETF /* flags */ }, { OP65_PLY, /* opcode */ "ply", /* mnemonic */ 1, /* size */ REG_NONE, /* use */ REG_Y, /* chg */ OF_SETF /* flags */ }, { OP65_ROL, /* opcode */ "rol", /* mnemonic */ 0, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_SETF | OF_NOIMP /* flags */ }, { OP65_ROR, /* opcode */ "ror", /* mnemonic */ 0, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_SETF | OF_NOIMP /* flags */ }, /* Mark RTI as "uses all registers but doesn't change them", so the ** optimizer won't remove preceeding loads. */ { OP65_RTI, /* opcode */ "rti", /* mnemonic */ 1, /* size */ REG_AXY, /* use */ REG_NONE, /* chg */ OF_RET /* flags */ }, { OP65_RTS, /* opcode */ "rts", /* mnemonic */ 1, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_RET /* flags */ }, { OP65_SBC, /* opcode */ "sbc", /* mnemonic */ 0, /* size */ REG_A, /* use */ REG_A, /* chg */ OF_SETF /* flags */ }, { OP65_SEC, /* opcode */ "sec", /* mnemonic */ 1, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_NONE /* flags */ }, { OP65_SED, /* opcode */ "sed", /* mnemonic */ 1, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_NONE /* flags */ }, { OP65_SEI, /* opcode */ "sei", /* mnemonic */ 1, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_NONE /* flags */ }, { OP65_STA, /* opcode */ "sta", /* mnemonic */ 0, /* size */ REG_A, /* use */ REG_NONE, /* chg */ OF_STORE /* flags */ }, { OP65_STX, /* opcode */ "stx", /* mnemonic */ 0, /* size */ REG_X, /* use */ REG_NONE, /* chg */ OF_STORE /* flags */ }, { OP65_STY, /* opcode */ "sty", /* mnemonic */ 0, /* size */ REG_Y, /* use */ REG_NONE, /* chg */ OF_STORE /* flags */ }, { OP65_STZ, /* opcode */ "stz", /* mnemonic */ 0, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ OF_STORE /* flags */ }, { OP65_TAX, /* opcode */ "tax", /* mnemonic */ 1, /* size */ REG_A, /* use */ REG_X, /* chg */ OF_XFR | OF_SETF /* flags */ }, { OP65_TAY, /* opcode */ "tay", /* mnemonic */ 1, /* size */ REG_A, /* use */ REG_Y, /* chg */ OF_XFR | OF_SETF /* flags */ }, { OP65_TRB, /* opcode */ "trb", /* mnemonic */ 0, /* size */ REG_A, /* use */ REG_NONE, /* chg */ OF_SETF /* flags */ }, { OP65_TSB, /* opcode */ "tsb", /* mnemonic */ 0, /* size */ REG_A, /* use */ REG_NONE, /* chg */ OF_SETF /* flags */ }, { OP65_TSX, /* opcode */ "tsx", /* mnemonic */ 1, /* size */ REG_NONE, /* use */ REG_X, /* chg */ OF_XFR | OF_SETF /* flags */ }, { OP65_TXA, /* opcode */ "txa", /* mnemonic */ 1, /* size */ REG_X, /* use */ REG_A, /* chg */ OF_XFR | OF_SETF /* flags */ }, { OP65_TXS, /* opcode */ "txs", /* mnemonic */ 1, /* size */ REG_X, /* use */ REG_NONE, /* chg */ OF_XFR /* flags */ }, { OP65_TYA, /* opcode */ "tya", /* mnemonic */ 1, /* size */ REG_Y, /* use */ REG_A, /* chg */ OF_XFR | OF_SETF /* flags */ }, }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ static int FindCmp (const void* Key, const void* Desc) /* Compare function for FindOpcode */ { return strcmp (Key, ((OPCDesc*)Desc)->Mnemo); } const OPCDesc* FindOP65 (const char* M) /* Find the given opcode and return the opcode number. If the opcode was not ** found, return NULL. */ { unsigned I; unsigned Len; /* Check the length of the given string, then copy it into local ** storage, converting it to upper case. */ char Mnemo[sizeof (OPCTable[0].Mnemo)]; Len = strlen (M); if (Len >= sizeof (OPCTable[0].Mnemo)) { /* Invalid length means invalid opcode */ return 0; } for (I = 0; I < Len; ++I) { Mnemo[I] = tolower (M[I]); } Mnemo[I] = '\0'; /* Search for the mnemonic in the table and return the result */ return bsearch (Mnemo, OPCTable, OP65_COUNT, sizeof (OPCTable[0]), FindCmp ); } unsigned GetInsnSize (opc_t OPC, am_t AM) /* Return the size of the given instruction */ { /* Get the opcode desc and check the size given there */ const OPCDesc* D = &OPCTable[OPC]; if (D->Size != 0) { return D->Size; } /* Check the addressing mode. */ switch (AM) { case AM65_IMP: return 1; case AM65_ACC: return 1; case AM65_IMM: return 2; case AM65_ZP: return 2; case AM65_ZPX: return 2; case AM65_ABS: return 3; case AM65_ABSX: return 3; case AM65_ABSY: return 3; case AM65_ZPX_IND: return 2; case AM65_ZP_INDY: return 2; case AM65_ZP_IND: return 2; default: Internal ("Invalid addressing mode"); return 0; } } unsigned char GetAMUseInfo (am_t AM) /* Get usage info for the given addressing mode (addressing modes that use ** index registers return REG_r info for these registers). */ { /* Check the addressing mode. */ switch (AM) { case AM65_ACC: return REG_A; case AM65_ZPX: return REG_X; case AM65_ABSX: return REG_X; case AM65_ABSY: return REG_Y; case AM65_ZPX_IND: return REG_X; case AM65_ZP_INDY: return REG_Y; default: return REG_NONE; } } opc_t GetInverseBranch (opc_t OPC) /* Return a branch that reverse the condition of the branch given in OPC */ { switch (OPC) { case OP65_BCC: return OP65_BCS; case OP65_BCS: return OP65_BCC; case OP65_BEQ: return OP65_BNE; case OP65_BMI: return OP65_BPL; case OP65_BNE: return OP65_BEQ; case OP65_BPL: return OP65_BMI; case OP65_BVC: return OP65_BVS; case OP65_BVS: return OP65_BVC; case OP65_JCC: return OP65_JCS; case OP65_JCS: return OP65_JCC; case OP65_JEQ: return OP65_JNE; case OP65_JMI: return OP65_JPL; case OP65_JNE: return OP65_JEQ; case OP65_JPL: return OP65_JMI; case OP65_JVC: return OP65_JVS; case OP65_JVS: return OP65_JVC; default: Internal ("GetInverseBranch: Invalid opcode: %d", OPC); return 0; } } opc_t MakeShortBranch (opc_t OPC) /* Return the short version of the given branch. If the branch is already ** a short branch, return the opcode unchanged. */ { switch (OPC) { case OP65_BCC: case OP65_JCC: return OP65_BCC; case OP65_BCS: case OP65_JCS: return OP65_BCS; case OP65_BEQ: case OP65_JEQ: return OP65_BEQ; case OP65_BMI: case OP65_JMI: return OP65_BMI; case OP65_BNE: case OP65_JNE: return OP65_BNE; case OP65_BPL: case OP65_JPL: return OP65_BPL; case OP65_BVC: case OP65_JVC: return OP65_BVC; case OP65_BVS: case OP65_JVS: return OP65_BVS; case OP65_BRA: case OP65_JMP: return (CPUIsets[CPU] & CPU_ISET_65SC02)? OP65_BRA : OP65_JMP; default: Internal ("MakeShortBranch: Invalid opcode: %d", OPC); return 0; } } opc_t MakeLongBranch (opc_t OPC) /* Return the long version of the given branch. If the branch is already ** a long branch, return the opcode unchanged. */ { switch (OPC) { case OP65_BCC: case OP65_JCC: return OP65_JCC; case OP65_BCS: case OP65_JCS: return OP65_JCS; case OP65_BEQ: case OP65_JEQ: return OP65_JEQ; case OP65_BMI: case OP65_JMI: return OP65_JMI; case OP65_BNE: case OP65_JNE: return OP65_JNE; case OP65_BPL: case OP65_JPL: return OP65_JPL; case OP65_BVC: case OP65_JVC: return OP65_JVC; case OP65_BVS: case OP65_JVS: return OP65_JVS; case OP65_BRA: case OP65_JMP: return OP65_JMP; default: Internal ("MakeLongBranch: Invalid opcode: %d", OPC); return 0; } } bc_t GetBranchCond (opc_t OPC) /* Get the condition for the conditional branch in OPC */ { switch (OPC) { case OP65_BCC: return BC_CC; case OP65_BCS: return BC_CS; case OP65_BEQ: return BC_EQ; case OP65_BMI: return BC_MI; case OP65_BNE: return BC_NE; case OP65_BPL: return BC_PL; case OP65_BVC: return BC_VC; case OP65_BVS: return BC_VS; case OP65_JCC: return BC_CC; case OP65_JCS: return BC_CS; case OP65_JEQ: return BC_EQ; case OP65_JMI: return BC_MI; case OP65_JNE: return BC_NE; case OP65_JPL: return BC_PL; case OP65_JVC: return BC_VC; case OP65_JVS: return BC_VS; default: Internal ("GetBranchCond: Invalid opcode: %d", OPC); return 0; } } bc_t GetInverseCond (bc_t BC) /* Return the inverse condition of the given one */ { switch (BC) { case BC_CC: return BC_CS; case BC_CS: return BC_CC; case BC_EQ: return BC_NE; case BC_MI: return BC_PL; case BC_NE: return BC_EQ; case BC_PL: return BC_MI; case BC_VC: return BC_VS; case BC_VS: return BC_VC; default: Internal ("GetInverseCond: Invalid condition: %d", BC); return 0; } } �����������������������cc65-2.18/src/cc65/opcodes.h������������������������������������������������������������������������0000664�0000000�0000000�00000020124�13473601511�0015340�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* opcodes.h */ /* */ /* Opcode and addressing mode definitions */ /* */ /* */ /* */ /* (C) 2001-2004 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef OPCODES_H #define OPCODES_H /* common */ #include "inline.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* 65XX opcodes */ typedef enum { OP65_ADC, OP65_AND, OP65_ASL, OP65_BCC, OP65_BCS, OP65_BEQ, OP65_BIT, OP65_BMI, OP65_BNE, OP65_BPL, OP65_BRA, OP65_BRK, OP65_BVC, OP65_BVS, OP65_CLC, OP65_CLD, OP65_CLI, OP65_CLV, OP65_CMP, OP65_CPX, OP65_CPY, OP65_DEA, OP65_DEC, OP65_DEX, OP65_DEY, OP65_EOR, OP65_INA, OP65_INC, OP65_INX, OP65_INY, OP65_JCC, OP65_JCS, OP65_JEQ, OP65_JMI, OP65_JMP, OP65_JNE, OP65_JPL, OP65_JSR, OP65_JVC, OP65_JVS, OP65_LDA, OP65_LDX, OP65_LDY, OP65_LSR, OP65_NOP, OP65_ORA, OP65_PHA, OP65_PHP, OP65_PHX, OP65_PHY, OP65_PLA, OP65_PLP, OP65_PLX, OP65_PLY, OP65_ROL, OP65_ROR, OP65_RTI, OP65_RTS, OP65_SBC, OP65_SEC, OP65_SED, OP65_SEI, OP65_STA, OP65_STX, OP65_STY, OP65_STZ, OP65_TAX, OP65_TAY, OP65_TRB, OP65_TSB, OP65_TSX, OP65_TXA, OP65_TXS, OP65_TYA, /* Number of opcodes available */ OP65_COUNT } opc_t; /* 65XX addressing modes */ typedef enum { AM65_IMP, /* implicit */ AM65_ACC, /* accumulator */ AM65_IMM, /* immediate */ AM65_ZP, /* zeropage */ AM65_ZPX, /* zeropage,X */ AM65_ZPY, /* zeropage,Y */ AM65_ABS, /* absolute */ AM65_ABSX, /* absolute,X */ AM65_ABSY, /* absolute,Y */ AM65_ZPX_IND, /* (zeropage,x) */ AM65_ZP_INDY, /* (zeropage),y */ AM65_ZP_IND, /* (zeropage) */ AM65_BRA /* branch */ } am_t; /* Branch conditions */ typedef enum { BC_CC, BC_CS, BC_EQ, BC_MI, BC_NE, BC_PL, BC_VC, BC_VS } bc_t; /* Opcode info */ #define OF_NONE 0x0000U /* No additional information */ #define OF_UBRA 0x0001U /* Unconditional branch */ #define OF_CBRA 0x0002U /* Conditional branch */ #define OF_ZBRA 0x0004U /* Branch on zero flag condition */ #define OF_FBRA 0x0008U /* Branch on cond set by a load */ #define OF_LBRA 0x0010U /* Jump/branch is long */ #define OF_RET 0x0020U /* Return from function */ #define OF_LOAD 0x0040U /* Register load */ #define OF_STORE 0x0080U /* Register store */ #define OF_XFR 0x0100U /* Transfer instruction */ #define OF_CALL 0x0200U /* A subroutine call */ #define OF_REG_INCDEC 0x0400U /* A register increment or decrement */ #define OF_SETF 0x0800U /* Insn will set all load flags (not carry) */ #define OF_CMP 0x1000U /* A compare A/X/Y instruction */ #define OF_NOIMP 0x2000U /* Implicit addressing mode is actually A */ /* Combined infos */ #define OF_BRA (OF_UBRA | OF_CBRA) /* Operation is a jump/branch */ #define OF_DEAD (OF_UBRA | OF_RET) /* Dead end - no exec behind this point */ /* Opcode description */ typedef struct { opc_t OPC; /* Opcode */ char Mnemo[9]; /* Mnemonic */ unsigned char Size; /* Size, 0 = check addressing mode */ unsigned short Use; /* Registers used by this insn */ unsigned short Chg; /* Registers changed by this insn */ unsigned short Info; /* Additional information */ } OPCDesc; /* Opcode description table */ extern const OPCDesc OPCTable[OP65_COUNT]; /*****************************************************************************/ /* Code */ /*****************************************************************************/ const OPCDesc* FindOP65 (const char* OPC); /* Find the given opcode and return the opcode description. If the opcode was ** not found, NULL is returned. */ unsigned GetInsnSize (opc_t OPC, am_t AM); /* Return the size of the given instruction */ #if defined(HAVE_INLINE) INLINE const OPCDesc* GetOPCDesc (opc_t OPC) /* Get an opcode description */ { /* Return the description */ return &OPCTable [OPC]; } #else # define GetOPCDesc(OPC) (&OPCTable [(OPC)]) #endif #if defined(HAVE_INLINE) INLINE unsigned GetOPCInfo (opc_t OPC) /* Get opcode information */ { /* Return the info */ return OPCTable[OPC].Info; } #else # define GetOPCInfo(OPC) (OPCTable[(OPC)].Info) #endif unsigned char GetAMUseInfo (am_t AM); /* Get usage info for the given addressing mode (addressing modes that use ** index registers return REG_r info for these registers). */ opc_t GetInverseBranch (opc_t OPC); /* Return a branch that reverse the condition of the branch given in OPC */ opc_t MakeShortBranch (opc_t OPC); /* Return the short version of the given branch. If the branch is already ** a short branch, return the opcode unchanged. */ opc_t MakeLongBranch (opc_t OPC); /* Return the long version of the given branch. If the branch is already ** a long branch, return the opcode unchanged. */ bc_t GetBranchCond (opc_t OPC); /* Get the condition for the conditional branch in OPC */ bc_t GetInverseCond (bc_t BC); /* Return the inverse condition of the given one */ /* End of opcodes.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/output.c�������������������������������������������������������������������������0000664�0000000�0000000�00000013323�13473601511�0015242�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* output.c */ /* */ /* Output file handling */ /* */ /* */ /* */ /* (C) 2009-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdarg.h> #include <string.h> #include <errno.h> /* common */ #include "check.h" #include "fname.h" #include "print.h" #include "xmalloc.h" /* cc65 */ #include "error.h" #include "global.h" #include "output.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Name of the output file. Dynamically allocated and read only. */ const char* OutputFilename = 0; /* Output file handle */ FILE* OutputFile = 0; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void SetOutputName (const char* Name) /* Sets the name of the output file. */ { OutputFilename = Name; } void MakeDefaultOutputName (const char* InputFilename) /* If the name of the output file is empty or NULL, the name of the output ** file is derived from the input file by adjusting the file name extension. */ { if (OutputFilename == 0 || *OutputFilename == '\0') { /* We don't have an output file for now */ const char* Ext = PreprocessOnly? ".i" : ".s"; OutputFilename = MakeFilename (InputFilename, Ext); } } void OpenOutputFile () /* Open the output file. Will call Fatal() in case of failures. */ { /* Output file must not be open and we must have a name*/ PRECONDITION (OutputFile == 0 && OutputFilename != 0); /* Open the file */ OutputFile = fopen (OutputFilename, "w"); if (OutputFile == 0) { Fatal ("Cannot open output file '%s': %s", OutputFilename, strerror (errno)); } Print (stdout, 1, "Opened output file '%s'\n", OutputFilename); } void OpenDebugOutputFile (const char* Name) /* Open an output file for debugging purposes. Will call Fatal() in case of ** failures. */ { /* Output file must not be open and we must have a name*/ PRECONDITION (OutputFile == 0); /* Open the file */ OutputFile = fopen (Name, "w"); if (OutputFile == 0) { Fatal ("Cannot open debug output file '%s': %s", Name, strerror (errno)); } Print (stdout, 1, "Opened debug output file '%s'\n", Name); } void CloseOutputFile () /* Close the output file. Will call Fatal() in case of failures. */ { /* Output file must be open */ PRECONDITION (OutputFile != 0); /* Close the file, check for errors */ if (fclose (OutputFile) != 0) { remove (OutputFilename); Fatal ("Cannot write to output file (disk full?)"); } Print (stdout, 1, "Closed output file '%s'\n", OutputFilename); OutputFile = 0; } int WriteOutput (const char* Format, ...) /* Write to the output file using printf like formatting. Returns the number ** of chars written. */ { va_list ap; int CharCount; /* Must have an output file */ PRECONDITION (OutputFile != 0); /* Output formatted */ va_start (ap, Format); CharCount = vfprintf (OutputFile, Format, ap); va_end (ap); /* Return the number of chars written */ return CharCount; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/output.h�������������������������������������������������������������������������0000664�0000000�0000000�00000010110�13473601511�0015236�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* output.h */ /* */ /* Output file handling */ /* */ /* */ /* */ /* (C) 2009-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef OUTPUT_H #define OUTPUT_H #include <stdio.h> /* common */ #include "attrib.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Name of the output file. Dynamically allocated and read only. */ extern const char* OutputFilename; /* Output file handle. Use WriteOutput if possible. Read only. */ extern FILE* OutputFile; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void SetOutputName (const char* Name); /* Sets the name of the output file. */ void MakeDefaultOutputName (const char* InputFilename); /* If the name of the output file is empty or NULL, the name of the output ** file is derived from the input file by adjusting the file name extension. */ void OpenOutputFile (); /* Open the output file. Will call Fatal() in case of failures. */ void OpenDebugOutputFile (const char* Name); /* Open an output file for debugging purposes. Will call Fatal() in case of ** failures. */ void CloseOutputFile (); /* Close the output file. Will call Fatal() in case of failures. */ int WriteOutput (const char* Format, ...) attribute ((format (printf, 1, 2))); /* Write to the output file using printf like formatting. Returns the number ** of chars written. */ /* End of output.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/pragma.c�������������������������������������������������������������������������0000664�0000000�0000000�00000063017�13473601511�0015156�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* pragma.c */ /* */ /* Pragma handling for the cc65 C compiler */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdlib.h> #include <string.h> /* common */ #include "chartype.h" #include "segnames.h" #include "tgttrans.h" /* cc65 */ #include "codegen.h" #include "error.h" #include "expr.h" #include "global.h" #include "litpool.h" #include "scanner.h" #include "scanstrbuf.h" #include "symtab.h" #include "pragma.h" #include "wrappedcall.h" /*****************************************************************************/ /* data */ /*****************************************************************************/ /* Tokens for the #pragmas */ typedef enum { PRAGMA_ILLEGAL = -1, PRAGMA_ALIGN, PRAGMA_ALLOW_EAGER_INLINE, PRAGMA_BSS_NAME, PRAGMA_BSSSEG, /* obsolete */ PRAGMA_CHARMAP, PRAGMA_CHECK_STACK, PRAGMA_CHECKSTACK, /* obsolete */ PRAGMA_CODE_NAME, PRAGMA_CODESEG, /* obsolete */ PRAGMA_CODESIZE, PRAGMA_DATA_NAME, PRAGMA_DATASEG, /* obsolete */ PRAGMA_INLINE_STDFUNCS, PRAGMA_LOCAL_STRINGS, PRAGMA_MESSAGE, PRAGMA_OPTIMIZE, PRAGMA_REGISTER_VARS, PRAGMA_REGVARADDR, PRAGMA_REGVARS, /* obsolete */ PRAGMA_RODATA_NAME, PRAGMA_RODATASEG, /* obsolete */ PRAGMA_SIGNED_CHARS, PRAGMA_SIGNEDCHARS, /* obsolete */ PRAGMA_STATIC_LOCALS, PRAGMA_STATICLOCALS, /* obsolete */ PRAGMA_WARN, PRAGMA_WRAPPED_CALL, PRAGMA_WRITABLE_STRINGS, PRAGMA_ZPSYM, PRAGMA_COUNT } pragma_t; /* Pragma table */ static const struct Pragma { const char* Key; /* Keyword */ pragma_t Tok; /* Token */ } Pragmas[PRAGMA_COUNT] = { { "align", PRAGMA_ALIGN }, { "allow-eager-inline", PRAGMA_ALLOW_EAGER_INLINE }, { "bss-name", PRAGMA_BSS_NAME }, { "bssseg", PRAGMA_BSSSEG }, /* obsolete */ { "charmap", PRAGMA_CHARMAP }, { "check-stack", PRAGMA_CHECK_STACK }, { "checkstack", PRAGMA_CHECKSTACK }, /* obsolete */ { "code-name", PRAGMA_CODE_NAME }, { "codeseg", PRAGMA_CODESEG }, /* obsolete */ { "codesize", PRAGMA_CODESIZE }, { "data-name", PRAGMA_DATA_NAME }, { "dataseg", PRAGMA_DATASEG }, /* obsolete */ { "inline-stdfuncs", PRAGMA_INLINE_STDFUNCS }, { "local-strings", PRAGMA_LOCAL_STRINGS }, { "message", PRAGMA_MESSAGE }, { "optimize", PRAGMA_OPTIMIZE }, { "register-vars", PRAGMA_REGISTER_VARS }, { "regvaraddr", PRAGMA_REGVARADDR }, { "regvars", PRAGMA_REGVARS }, /* obsolete */ { "rodata-name", PRAGMA_RODATA_NAME }, { "rodataseg", PRAGMA_RODATASEG }, /* obsolete */ { "signed-chars", PRAGMA_SIGNED_CHARS }, { "signedchars", PRAGMA_SIGNEDCHARS }, /* obsolete */ { "static-locals", PRAGMA_STATIC_LOCALS }, { "staticlocals", PRAGMA_STATICLOCALS }, /* obsolete */ { "warn", PRAGMA_WARN }, { "wrapped-call", PRAGMA_WRAPPED_CALL }, { "writable-strings", PRAGMA_WRITABLE_STRINGS }, { "zpsym", PRAGMA_ZPSYM }, }; /* Result of ParsePushPop */ typedef enum { PP_NONE, PP_POP, PP_PUSH, PP_ERROR, } PushPopResult; /*****************************************************************************/ /* Helper functions */ /*****************************************************************************/ static void PragmaErrorSkip (void) /* Called in case of an error, skips tokens until the closing paren or a ** semicolon is reached. */ { static const token_t TokenList[] = { TOK_RPAREN, TOK_SEMI }; SkipTokens (TokenList, sizeof(TokenList) / sizeof(TokenList[0])); } static int CmpKey (const void* Key, const void* Elem) /* Compare function for bsearch */ { return strcmp ((const char*) Key, ((const struct Pragma*) Elem)->Key); } static pragma_t FindPragma (const StrBuf* Key) /* Find a pragma and return the token. Return PRAGMA_ILLEGAL if the keyword is ** not a valid pragma. */ { struct Pragma* P; P = bsearch (SB_GetConstBuf (Key), Pragmas, PRAGMA_COUNT, sizeof (Pragmas[0]), CmpKey); return P? P->Tok : PRAGMA_ILLEGAL; } static int GetComma (StrBuf* B) /* Expects and skips a comma in B. Prints an error and returns zero if no ** comma is found. Return a value <> 0 otherwise. */ { SB_SkipWhite (B); if (SB_Get (B) != ',') { Error ("Comma expected"); return 0; } SB_SkipWhite (B); return 1; } static int GetString (StrBuf* B, StrBuf* S) /* Expects and skips a string in B. Prints an error and returns zero if no ** string is found. Returns a value <> 0 otherwise. */ { if (!SB_GetString (B, S)) { Error ("String literal expected"); return 0; } return 1; } static int GetNumber (StrBuf* B, long* Val) /* Expects and skips a number in B. Prints an eror and returns zero if no ** number is found. Returns a value <> 0 otherwise. */ { if (!SB_GetNumber (B, Val)) { Error ("Constant integer expected"); return 0; } return 1; } static IntStack* GetWarning (StrBuf* B) /* Get a warning name from the string buffer. Returns a pointer to the intstack ** that holds the state of the warning, and NULL in case of errors. The ** function will output error messages in case of problems. */ { IntStack* S = 0; StrBuf W = AUTO_STRBUF_INITIALIZER; /* The warning name is a symbol but the '-' char is allowed within */ if (SB_GetSym (B, &W, "-")) { /* Map the warning name to an IntStack that contains its state */ S = FindWarning (SB_GetConstBuf (&W)); /* Handle errors */ if (S == 0) { Error ("Pragma expects a warning name as first argument"); } } /* Deallocate the string */ SB_Done (&W); /* Done */ return S; } static int HasStr (StrBuf* B, const char* E) /* Checks if E follows in B. If so, skips it and returns true */ { unsigned Len = strlen (E); if (SB_GetLen (B) - SB_GetIndex (B) >= Len) { if (strncmp (SB_GetConstBuf (B) + SB_GetIndex (B), E, Len) == 0) { /* Found */ SB_SkipMultiple (B, Len); return 1; } } return 0; } static PushPopResult ParsePushPop (StrBuf* B) /* Check for and parse the "push" and "pop" keywords. In case of "push", a ** following comma is expected and skipped. */ { StrBuf Ident = AUTO_STRBUF_INITIALIZER; PushPopResult Res = PP_NONE; /* Remember the current string index, so we can go back in case of errors */ unsigned Index = SB_GetIndex (B); /* Try to read an identifier */ if (SB_GetSym (B, &Ident, 0)) { /* Check if we have a first argument named "pop" */ if (SB_CompareStr (&Ident, "pop") == 0) { Res = PP_POP; /* Check if we have a first argument named "push" */ } else if (SB_CompareStr (&Ident, "push") == 0) { Res = PP_PUSH; /* Skip the following comma */ if (!GetComma (B)) { /* Error already flagged by GetComma */ Res = PP_ERROR; } } else { /* Unknown keyword, roll back */ SB_SetIndex (B, Index); } } /* Free the string buffer and return the result */ SB_Done (&Ident); return Res; } static void PopInt (IntStack* S) /* Pops an integer from an IntStack. Prints an error if the stack is empty */ { if (IS_GetCount (S) < 2) { Error ("Cannot pop, stack is empty"); } else { IS_Drop (S); } } static void PushInt (IntStack* S, long Val) /* Pushes an integer onto an IntStack. Prints an error if the stack is full */ { if (IS_IsFull (S)) { Error ("Cannot push: stack overflow"); } else { IS_Push (S, Val); } } static int BoolKeyword (StrBuf* Ident) /* Check if the identifier in Ident is a keyword for a boolean value. Currently ** accepted are true/false/on/off. */ { if (SB_CompareStr (Ident, "true") == 0) { return 1; } if (SB_CompareStr (Ident, "on") == 0) { return 1; } if (SB_CompareStr (Ident, "false") == 0) { return 0; } if (SB_CompareStr (Ident, "off") == 0) { return 0; } /* Error */ Error ("Pragma argument must be one of 'on', 'off', 'true' or 'false'"); return 0; } /*****************************************************************************/ /* Pragma handling functions */ /*****************************************************************************/ static void StringPragma (StrBuf* B, void (*Func) (const char*)) /* Handle a pragma that expects a string parameter */ { StrBuf S = AUTO_STRBUF_INITIALIZER; /* We expect a string here */ if (GetString (B, &S)) { /* Call the given function with the string argument */ Func (SB_GetConstBuf (&S)); } /* Call the string buf destructor */ SB_Done (&S); } static void SegNamePragma (StrBuf* B, segment_t Seg) /* Handle a pragma that expects a segment name parameter */ { const char* Name; StrBuf S = AUTO_STRBUF_INITIALIZER; int Push = 0; /* Check for the "push" or "pop" keywords */ switch (ParsePushPop (B)) { case PP_NONE: break; case PP_PUSH: Push = 1; break; case PP_POP: /* Pop the old value and output it */ PopSegName (Seg); /* BSS variables are output at the end of the compilation. Don't ** bother to change their segment, now. */ if (Seg != SEG_BSS) { g_segname (Seg); } /* Done */ goto ExitPoint; case PP_ERROR: /* Bail out */ goto ExitPoint; default: Internal ("Invalid result from ParsePushPop"); } /* A string argument must follow */ if (!GetString (B, &S)) { goto ExitPoint; } /* Get the string */ Name = SB_GetConstBuf (&S); /* Check if the name is valid */ if (ValidSegName (Name)) { /* Set the new name */ if (Push) { PushSegName (Seg, Name); } else { SetSegName (Seg, Name); } /* BSS variables are output at the end of the compilation. Don't ** bother to change their segment, now. */ if (Seg != SEG_BSS) { g_segname (Seg); } } else { /* Segment name is invalid */ Error ("Illegal segment name: '%s'", Name); } ExitPoint: /* Call the string buf destructor */ SB_Done (&S); } static void WrappedCallPragma (StrBuf* B) /* Handle the wrapped-call pragma */ { StrBuf S = AUTO_STRBUF_INITIALIZER; const char *Name; long Val; SymEntry *Entry; /* Check for the "push" or "pop" keywords */ switch (ParsePushPop (B)) { case PP_NONE: Error ("Push or pop required"); break; case PP_PUSH: break; case PP_POP: PopWrappedCall(); /* Done */ goto ExitPoint; case PP_ERROR: /* Bail out */ goto ExitPoint; default: Internal ("Invalid result from ParsePushPop"); } /* A symbol argument must follow */ if (!SB_GetSym (B, &S, NULL)) { goto ExitPoint; } /* Skip the following comma */ if (!GetComma (B)) { /* Error already flagged by GetComma */ Error ("Value required for wrapped-call identifier"); goto ExitPoint; } if (!GetNumber (B, &Val)) { Error ("Value required for wrapped-call identifier"); goto ExitPoint; } if (Val < 0 || Val > 255) { Error ("Identifier must be between 0-255"); goto ExitPoint; } /* Get the string */ Name = SB_GetConstBuf (&S); Entry = FindSym(Name); /* Check if the name is valid */ if (Entry && Entry->Flags & SC_FUNC) { PushWrappedCall(Entry, (unsigned char) Val); Entry->Flags |= SC_REF; Entry->V.F.Func->Flags |= FD_CALL_WRAPPER; } else { /* Segment name is invalid */ Error ("Wrapped-call target does not exist or is not a function"); } ExitPoint: /* Call the string buf destructor */ SB_Done (&S); } static void CharMapPragma (StrBuf* B) /* Change the character map */ { long Index, C; /* Read the character index */ if (!GetNumber (B, &Index)) { return; } if (Index < 0 || Index > 255) { Error ("Character index out of range"); return; } /* Comma follows */ if (!GetComma (B)) { return; } /* Read the character code */ if (!GetNumber (B, &C)) { return; } if (C < 0 || C > 255) { Error ("Character code out of range"); return; } /* Warn about remapping character code 0x00 ** (except when remapping it back to itself). */ if (Index + C != 0 && IS_Get (&WarnRemapZero)) { if (Index == 0) { Warning ("Remapping from 0 is dangerous with string functions"); } else if (C == 0) { Warning ("Remapping to 0 can make string functions stop unexpectedly"); } } /* Remap the character */ TgtTranslateSet ((unsigned) Index, (unsigned char) C); } static void WarnPragma (StrBuf* B) /* Enable/disable warnings */ { long Val; int Push; /* A warning name must follow */ IntStack* S = GetWarning (B); if (S == 0) { return; } /* Comma follows */ if (!GetComma (B)) { return; } /* Check for the "push" or "pop" keywords */ switch (ParsePushPop (B)) { case PP_NONE: Push = 0; break; case PP_PUSH: Push = 1; break; case PP_POP: /* Pop the old value and bail out */ PopInt (S); return; case PP_ERROR: /* Bail out */ return; default: Internal ("Invalid result from ParsePushPop"); } /* Boolean argument follows */ if (HasStr (B, "true") || HasStr (B, "on")) { Val = 1; } else if (HasStr (B, "false") || HasStr (B, "off")) { Val = 0; } else if (!SB_GetNumber (B, &Val)) { Error ("Invalid pragma argument"); return; } /* Set/push the new value */ if (Push) { PushInt (S, Val); } else { IS_Set (S, Val); } } static void FlagPragma (StrBuf* B, IntStack* Stack) /* Handle a pragma that expects a boolean paramater */ { StrBuf Ident = AUTO_STRBUF_INITIALIZER; long Val; int Push; /* Try to read an identifier */ int IsIdent = SB_GetSym (B, &Ident, 0); /* Check if we have a first argument named "pop" */ if (IsIdent && SB_CompareStr (&Ident, "pop") == 0) { PopInt (Stack); /* No other arguments allowed */ return; } /* Check if we have a first argument named "push" */ if (IsIdent && SB_CompareStr (&Ident, "push") == 0) { Push = 1; if (!GetComma (B)) { goto ExitPoint; } IsIdent = SB_GetSym (B, &Ident, 0); } else { Push = 0; } /* Boolean argument follows */ if (IsIdent) { Val = BoolKeyword (&Ident); } else if (!GetNumber (B, &Val)) { goto ExitPoint; } /* Set/push the new value */ if (Push) { PushInt (Stack, Val); } else { IS_Set (Stack, Val); } ExitPoint: /* Free the identifier */ SB_Done (&Ident); } static void IntPragma (StrBuf* B, IntStack* Stack, long Low, long High) /* Handle a pragma that expects an int paramater */ { long Val; int Push; /* Check for the "push" or "pop" keywords */ switch (ParsePushPop (B)) { case PP_NONE: Push = 0; break; case PP_PUSH: Push = 1; break; case PP_POP: /* Pop the old value and bail out */ PopInt (Stack); return; case PP_ERROR: /* Bail out */ return; default: Internal ("Invalid result from ParsePushPop"); } /* Integer argument follows */ if (!GetNumber (B, &Val)) { return; } /* Check the argument */ if (Val < Low || Val > High) { Error ("Pragma argument out of bounds (%ld-%ld)", Low, High); return; } /* Set/push the new value */ if (Push) { PushInt (Stack, Val); } else { IS_Set (Stack, Val); } } static void MakeMessage (const char* Message) { fprintf (stderr, "%s(%u): Note: %s\n", GetInputName (CurTok.LI), GetInputLine (CurTok.LI), Message); } static void ParsePragma (void) /* Parse the contents of the _Pragma statement */ { pragma_t Pragma; StrBuf Ident = AUTO_STRBUF_INITIALIZER; /* Create a string buffer from the string literal */ StrBuf B = AUTO_STRBUF_INITIALIZER; SB_Append (&B, GetLiteralStrBuf (CurTok.SVal)); /* Skip the string token */ NextToken (); /* Get the pragma name from the string */ SB_SkipWhite (&B); if (!SB_GetSym (&B, &Ident, "-")) { Error ("Invalid pragma"); goto ExitPoint; } /* Search for the name */ Pragma = FindPragma (&Ident); /* Do we know this pragma? */ if (Pragma == PRAGMA_ILLEGAL) { /* According to the ANSI standard, we're not allowed to generate errors ** for unknown pragmas, but warn about them if enabled (the default). */ if (IS_Get (&WarnUnknownPragma)) { Warning ("Unknown pragma '%s'", SB_GetConstBuf (&Ident)); } goto ExitPoint; } /* Check for an open paren */ SB_SkipWhite (&B); if (SB_Get (&B) != '(') { Error ("'(' expected"); goto ExitPoint; } /* Skip white space before the argument */ SB_SkipWhite (&B); /* Switch for the different pragmas */ switch (Pragma) { case PRAGMA_ALIGN: IntPragma (&B, &DataAlignment, 1, 4096); break; case PRAGMA_ALLOW_EAGER_INLINE: FlagPragma (&B, &EagerlyInlineFuncs); break; case PRAGMA_BSSSEG: Warning ("#pragma bssseg is obsolete, please use #pragma bss-name instead"); /* FALLTHROUGH */ case PRAGMA_BSS_NAME: SegNamePragma (&B, SEG_BSS); break; case PRAGMA_CHARMAP: CharMapPragma (&B); break; case PRAGMA_CHECKSTACK: Warning ("#pragma checkstack is obsolete, please use #pragma check-stack instead"); /* FALLTHROUGH */ case PRAGMA_CHECK_STACK: FlagPragma (&B, &CheckStack); break; case PRAGMA_CODESEG: Warning ("#pragma codeseg is obsolete, please use #pragma code-name instead"); /* FALLTHROUGH */ case PRAGMA_CODE_NAME: SegNamePragma (&B, SEG_CODE); break; case PRAGMA_CODESIZE: IntPragma (&B, &CodeSizeFactor, 10, 1000); break; case PRAGMA_DATASEG: Warning ("#pragma dataseg is obsolete, please use #pragma data-name instead"); /* FALLTHROUGH */ case PRAGMA_DATA_NAME: SegNamePragma (&B, SEG_DATA); break; case PRAGMA_INLINE_STDFUNCS: FlagPragma (&B, &InlineStdFuncs); break; case PRAGMA_LOCAL_STRINGS: FlagPragma (&B, &LocalStrings); break; case PRAGMA_MESSAGE: StringPragma (&B, MakeMessage); break; case PRAGMA_OPTIMIZE: FlagPragma (&B, &Optimize); break; case PRAGMA_REGVARADDR: FlagPragma (&B, &AllowRegVarAddr); break; case PRAGMA_REGVARS: Warning ("#pragma regvars is obsolete, please use #pragma register-vars instead"); /* FALLTHROUGH */ case PRAGMA_REGISTER_VARS: FlagPragma (&B, &EnableRegVars); break; case PRAGMA_RODATASEG: Warning ("#pragma rodataseg is obsolete, please use #pragma rodata-name instead"); /* FALLTHROUGH */ case PRAGMA_RODATA_NAME: SegNamePragma (&B, SEG_RODATA); break; case PRAGMA_SIGNEDCHARS: Warning ("#pragma signedchars is obsolete, please use #pragma signed-chars instead"); /* FALLTHROUGH */ case PRAGMA_SIGNED_CHARS: FlagPragma (&B, &SignedChars); break; case PRAGMA_STATICLOCALS: Warning ("#pragma staticlocals is obsolete, please use #pragma static-locals instead"); /* FALLTHROUGH */ case PRAGMA_STATIC_LOCALS: FlagPragma (&B, &StaticLocals); break; case PRAGMA_WRAPPED_CALL: WrappedCallPragma(&B); break; case PRAGMA_WARN: WarnPragma (&B); break; case PRAGMA_WRITABLE_STRINGS: FlagPragma (&B, &WritableStrings); break; case PRAGMA_ZPSYM: StringPragma (&B, MakeZPSym); break; default: Internal ("Invalid pragma"); } /* Closing paren expected */ SB_SkipWhite (&B); if (SB_Get (&B) != ')') { Error ("')' expected"); goto ExitPoint; } SB_SkipWhite (&B); /* Allow an optional semicolon to be compatible with the old syntax */ if (SB_Peek (&B) == ';') { SB_Skip (&B); SB_SkipWhite (&B); } /* Make sure nothing follows */ if (SB_Peek (&B) != '\0') { Error ("Unexpected input following pragma directive"); } ExitPoint: /* Release the string buffers */ SB_Done (&B); SB_Done (&Ident); } void DoPragma (void) /* Handle pragmas. These come always in form of the new C99 _Pragma() operator. */ { /* Skip the token itself */ NextToken (); /* We expect an opening paren */ if (!ConsumeLParen ()) { return; } /* String literal */ if (CurTok.Tok != TOK_SCONST) { /* Print a diagnostic */ Error ("String literal expected"); /* Try some smart error recovery: Skip tokens until we reach the ** enclosing paren, or a semicolon. */ PragmaErrorSkip (); } else { /* Parse the _Pragma statement */ ParsePragma (); } /* Closing paren needed */ ConsumeRParen (); } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/pragma.h�������������������������������������������������������������������������0000664�0000000�0000000�00000005645�13473601511�0015166�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* pragma.h */ /* */ /* Pragma handling for the cc65 C compiler */ /* */ /* */ /* */ /* (C) 1998-2002, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* 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 PRAGMA_H #define PRAGMA_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ void DoPragma (void); /* Handle pragmas. These come always in form of the new C99 _Pragma() operator. */ /* End of pragma.h */ #endif �������������������������������������������������������������������������������������������cc65-2.18/src/cc65/preproc.c������������������������������������������������������������������������0000664�0000000�0000000�00000117024�13473601511�0015357�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* preproc.c */ /* */ /* cc65 preprocessor */ /* */ /* */ /* */ /* (C) 1998-2010, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <errno.h> /* common */ #include "chartype.h" #include "check.h" #include "inline.h" #include "print.h" #include "xmalloc.h" /* cc65 */ #include "codegen.h" #include "error.h" #include "expr.h" #include "global.h" #include "ident.h" #include "incpath.h" #include "input.h" #include "lineinfo.h" #include "macrotab.h" #include "preproc.h" #include "scanner.h" #include "standard.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Set when the preprocessor calls expr() recursively */ unsigned char Preprocessing = 0; /* Management data for #if */ #define MAX_IFS 64 #define IFCOND_NONE 0x00U #define IFCOND_SKIP 0x01U #define IFCOND_ELSE 0x02U #define IFCOND_NEEDTERM 0x04U static unsigned char IfStack[MAX_IFS]; static int IfIndex = -1; /* Buffer for macro expansion */ static StrBuf* MLine; /* Structure used when expanding macros */ typedef struct MacroExp MacroExp; struct MacroExp { Collection ActualArgs; /* Actual arguments */ StrBuf Replacement; /* Replacement with arguments substituted */ Macro* M; /* The macro we're handling */ }; /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ static unsigned Pass1 (StrBuf* Source, StrBuf* Target); /* Preprocessor pass 1. Remove whitespace. Handle old and new style comments ** and the "defined" operator. */ static void MacroReplacement (StrBuf* Source, StrBuf* Target); /* Perform macro replacement. */ /*****************************************************************************/ /* Low level preprocessor token handling */ /*****************************************************************************/ /* Types of preprocessor tokens */ typedef enum { PP_ILLEGAL = -1, PP_DEFINE, PP_ELIF, PP_ELSE, PP_ENDIF, PP_ERROR, PP_IF, PP_IFDEF, PP_IFNDEF, PP_INCLUDE, PP_LINE, PP_PRAGMA, PP_UNDEF, PP_WARNING, } pptoken_t; /* Preprocessor keyword to token mapping table */ static const struct PPToken { const char* Key; /* Keyword */ pptoken_t Tok; /* Token */ } PPTokens[] = { { "define", PP_DEFINE }, { "elif", PP_ELIF }, { "else", PP_ELSE }, { "endif", PP_ENDIF }, { "error", PP_ERROR }, { "if", PP_IF }, { "ifdef", PP_IFDEF }, { "ifndef", PP_IFNDEF }, { "include", PP_INCLUDE }, { "line", PP_LINE }, { "pragma", PP_PRAGMA }, { "undef", PP_UNDEF }, { "warning", PP_WARNING }, }; /* Number of preprocessor tokens */ #define PPTOKEN_COUNT (sizeof(PPTokens) / sizeof(PPTokens[0])) static int CmpToken (const void* Key, const void* Elem) /* Compare function for bsearch */ { return strcmp ((const char*) Key, ((const struct PPToken*) Elem)->Key); } static pptoken_t FindPPToken (const char* Ident) /* Find a preprocessor token and return it. Return PP_ILLEGAL if the identifier ** is not a valid preprocessor token. */ { struct PPToken* P; P = bsearch (Ident, PPTokens, PPTOKEN_COUNT, sizeof (PPTokens[0]), CmpToken); return P? P->Tok : PP_ILLEGAL; } /*****************************************************************************/ /* struct MacroExp */ /*****************************************************************************/ static MacroExp* InitMacroExp (MacroExp* E, Macro* M) /* Initialize a MacroExp structure */ { InitCollection (&E->ActualArgs); SB_Init (&E->Replacement); E->M = M; return E; } static void DoneMacroExp (MacroExp* E) /* Cleanup after use of a MacroExp structure */ { unsigned I; /* Delete the list with actual arguments */ for (I = 0; I < CollCount (&E->ActualArgs); ++I) { FreeStrBuf (CollAtUnchecked (&E->ActualArgs, I)); } DoneCollection (&E->ActualArgs); SB_Done (&E->Replacement); } static void ME_AppendActual (MacroExp* E, StrBuf* Arg) /* Add a copy of Arg to the list of actual macro arguments. ** NOTE: This function will clear Arg! */ { /* Create a new string buffer */ StrBuf* A = NewStrBuf (); /* Move the contents of Arg to A */ SB_Move (A, Arg); /* Add A to the actual arguments */ CollAppend (&E->ActualArgs, A); } static StrBuf* ME_GetActual (MacroExp* E, unsigned Index) /* Return an actual macro argument with the given index */ { return CollAt (&E->ActualArgs, Index); } static int ME_ArgIsVariadic (const MacroExp* E) /* Return true if the next actual argument we will add is a variadic one */ { return (E->M->Variadic && E->M->ArgCount == (int) CollCount (&E->ActualArgs) + 1); } /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void Stringize (StrBuf* Source, StrBuf* Target) /* Stringize the given string: Add double quotes at start and end and preceed ** each occurance of " and \ by a backslash. */ { char C; /* Add a starting quote */ SB_AppendChar (Target, '\"'); /* Replace any characters inside the string may not be part of a string ** unescaped. */ while ((C = SB_Get (Source)) != '\0') { switch (C) { case '\"': case '\\': SB_AppendChar (Target, '\\'); /* FALLTHROUGH */ default: SB_AppendChar (Target, C); break; } } /* Add the closing quote */ SB_AppendChar (Target, '\"'); } static void OldStyleComment (void) /* Remove an old style C comment from line. */ { /* Remember the current line number, so we can output better error ** messages if the comment is not terminated in the current file. */ unsigned StartingLine = GetCurrentLine(); /* Skip the start of comment chars */ NextChar (); NextChar (); /* Skip the comment */ while (CurC != '*' || NextC != '/') { if (CurC == '\0') { if (NextLine () == 0) { PPError ("End-of-file reached in comment starting at line %u", StartingLine); return; } } else { if (CurC == '/' && NextC == '*') { PPWarning ("'/*' found inside a comment"); } NextChar (); } } /* Skip the end of comment chars */ NextChar (); NextChar (); } 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 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. */ do { NextChar (); } while (CurC != '\n' && CurC != '\0'); if (CurC == '\n') { NextChar (); } } static int SkipWhitespace (int SkipLines) /* Skip white space in the input stream. Do also skip newlines if SkipLines ** is true. Return zero if nothing was skipped, otherwise return a ** value != zero. */ { int Skipped = 0; while (1) { if (IsSpace (CurC)) { NextChar (); Skipped = 1; } else if (CurC == '\0' && SkipLines) { /* End of line, read next */ if (NextLine () != 0) { Skipped = 1; } else { /* End of input */ break; } } else { /* No more white space */ break; } } return Skipped; } static void CopyQuotedString (StrBuf* Target) /* Copy a single or double quoted string from the input to Target. */ { /* Remember the quote character, copy it to the target buffer and skip it */ char Quote = CurC; SB_AppendChar (Target, CurC); NextChar (); /* Copy the characters inside the string */ while (CurC != '\0' && CurC != Quote) { /* Keep an escaped char */ if (CurC == '\\') { SB_AppendChar (Target, CurC); NextChar (); } /* Copy the character */ SB_AppendChar (Target, CurC); NextChar (); } /* If we had a terminating quote, copy it */ if (CurC != '\0') { SB_AppendChar (Target, CurC); NextChar (); } } /*****************************************************************************/ /* Macro stuff */ /*****************************************************************************/ static int MacName (char* Ident) /* Get a macro symbol name into Ident. If we have an error, print a ** diagnostic message and clear the line. */ { if (IsSym (Ident) == 0) { PPError ("Identifier expected"); ClearLine (); return 0; } else { return 1; } } static void ReadMacroArgs (MacroExp* E) /* Identify the arguments to a macro call */ { unsigned Parens; /* Number of open parenthesis */ StrBuf Arg = STATIC_STRBUF_INITIALIZER; /* Read the actual macro arguments */ Parens = 0; while (1) { if (CurC == '(') { /* Nested parenthesis */ SB_AppendChar (&Arg, CurC); NextChar (); ++Parens; } else if (IsQuote (CurC)) { /* Quoted string - just copy */ CopyQuotedString (&Arg); } else if (CurC == ',' || CurC == ')') { if (Parens) { /* Comma or right paren inside nested parenthesis */ if (CurC == ')') { --Parens; } SB_AppendChar (&Arg, CurC); NextChar (); } else if (CurC == ',' && ME_ArgIsVariadic (E)) { /* It's a comma, but we're inside a variadic macro argument, so ** just copy it and proceed. */ SB_AppendChar (&Arg, CurC); NextChar (); } else { /* End of actual argument. Remove whitespace from the end. */ while (IsSpace (SB_LookAtLast (&Arg))) { SB_Drop (&Arg, 1); } /* If this is not the single empty argument for a macro with ** an empty argument list, remember it. */ if (CurC != ')' || SB_NotEmpty (&Arg) || E->M->ArgCount > 0) { ME_AppendActual (E, &Arg); } /* Check for end of macro param list */ if (CurC == ')') { NextChar (); break; } /* Start the next param */ NextChar (); SB_Clear (&Arg); } } else if (SkipWhitespace (1)) { /* Squeeze runs of blanks within an arg */ if (SB_NotEmpty (&Arg)) { SB_AppendChar (&Arg, ' '); } } else if (CurC == '/' && NextC == '*') { if (SB_NotEmpty (&Arg)) { SB_AppendChar (&Arg, ' '); } OldStyleComment (); } else if (IS_Get (&Standard) >= STD_C99 && CurC == '/' && NextC == '/') { if (SB_NotEmpty (&Arg)) { SB_AppendChar (&Arg, ' '); } NewStyleComment (); } else if (CurC == '\0') { /* End of input inside macro argument list */ PPError ("Unterminated argument list invoking macro '%s'", E->M->Name); ClearLine (); break; } else { /* Just copy the character */ SB_AppendChar (&Arg, CurC); NextChar (); } } /* Deallocate string buf resources */ SB_Done (&Arg); } static void MacroArgSubst (MacroExp* E) /* Argument substitution according to ISO/IEC 9899:1999 (E), 6.10.3.1ff */ { ident Ident; int ArgIdx; StrBuf* OldSource; StrBuf* Arg; int HaveSpace; /* Remember the current input and switch to the macro replacement. */ int OldIndex = SB_GetIndex (&E->M->Replacement); SB_Reset (&E->M->Replacement); OldSource = InitLine (&E->M->Replacement); /* Argument handling loop */ while (CurC != '\0') { /* If we have an identifier, check if it's a macro */ if (IsSym (Ident)) { /* Check if it's a macro argument */ if ((ArgIdx = FindMacroArg (E->M, Ident)) >= 0) { /* A macro argument. Get the corresponding actual argument. */ Arg = ME_GetActual (E, ArgIdx); /* Copy any following whitespace */ HaveSpace = SkipWhitespace (0); /* If a ## operator follows, we have to insert the actual ** argument as is, otherwise it must be macro replaced. */ if (CurC == '#' && NextC == '#') { /* ### Add placemarker if necessary */ SB_Append (&E->Replacement, Arg); } else { /* Replace the formal argument by a macro replaced copy ** of the actual. */ SB_Reset (Arg); MacroReplacement (Arg, &E->Replacement); /* If we skipped whitespace before, re-add it now */ if (HaveSpace) { SB_AppendChar (&E->Replacement, ' '); } } } else { /* An identifier, keep it */ SB_AppendStr (&E->Replacement, Ident); } } else if (CurC == '#' && NextC == '#') { /* ## operator. */ NextChar (); NextChar (); SkipWhitespace (0); /* Since we need to concatenate the token sequences, remove ** any whitespace that was added to target, since it must come ** from the input. */ while (IsSpace (SB_LookAtLast (&E->Replacement))) { SB_Drop (&E->Replacement, 1); } /* If the next token is an identifier which is a macro argument, ** replace it, otherwise do nothing. */ if (IsSym (Ident)) { /* Check if it's a macro argument */ if ((ArgIdx = FindMacroArg (E->M, Ident)) >= 0) { /* Get the corresponding actual argument and add it. */ SB_Append (&E->Replacement, ME_GetActual (E, ArgIdx)); } else { /* Just an ordinary identifier - add as is */ SB_AppendStr (&E->Replacement, Ident); } } } else if (CurC == '#' && E->M->ArgCount >= 0) { /* A # operator within a macro expansion of a function like ** macro. Read the following identifier and check if it's a ** macro parameter. */ NextChar (); SkipWhitespace (0); if (!IsSym (Ident) || (ArgIdx = FindMacroArg (E->M, Ident)) < 0) { PPError ("'#' is not followed by a macro parameter"); } else { /* Make a valid string from Replacement */ Arg = ME_GetActual (E, ArgIdx); SB_Reset (Arg); Stringize (Arg, &E->Replacement); } } else if (IsQuote (CurC)) { CopyQuotedString (&E->Replacement); } else { SB_AppendChar (&E->Replacement, CurC); NextChar (); } } #if 0 /* Remove whitespace from the end of the line */ while (IsSpace (SB_LookAtLast (&E->Replacement))) { SB_Drop (&E->Replacement, 1); } #endif /* Switch back the input */ InitLine (OldSource); SB_SetIndex (&E->M->Replacement, OldIndex); } static void MacroCall (StrBuf* Target, Macro* M) /* Process a function like macro */ { MacroExp E; /* Eat the left paren */ NextChar (); /* Initialize our MacroExp structure */ InitMacroExp (&E, M); /* Read the actual macro arguments */ ReadMacroArgs (&E); /* Compare formal and actual argument count */ if (CollCount (&E.ActualArgs) != (unsigned) M->ArgCount) { StrBuf Arg = STATIC_STRBUF_INITIALIZER; /* Argument count mismatch */ PPError ("Macro argument count mismatch"); /* Be sure to make enough empty arguments available */ while (CollCount (&E.ActualArgs) < (unsigned) M->ArgCount) { ME_AppendActual (&E, &Arg); } } /* Replace macro arguments handling the # and ## operators */ MacroArgSubst (&E); /* Do macro replacement on the macro that already has the parameters ** substituted. */ M->Expanding = 1; MacroReplacement (&E.Replacement, Target); M->Expanding = 0; /* Free memory allocated for the macro expansion structure */ DoneMacroExp (&E); } static void ExpandMacro (StrBuf* Target, Macro* M) /* Expand a macro into Target */ { #if 0 static unsigned V = 0; printf ("Expanding %s(%u)\n", M->Name, ++V); #endif /* Check if this is a function like macro */ if (M->ArgCount >= 0) { int Whitespace = SkipWhitespace (1); if (CurC != '(') { /* Function like macro but no parameter list */ SB_AppendStr (Target, M->Name); if (Whitespace) { SB_AppendChar (Target, ' '); } } else { /* Function like macro */ MacroCall (Target, M); } } else { MacroExp E; InitMacroExp (&E, M); /* Handle # and ## operators for object like macros */ MacroArgSubst (&E); /* Do macro replacement on the macro that already has the parameters ** substituted. */ M->Expanding = 1; MacroReplacement (&E.Replacement, Target); M->Expanding = 0; /* Free memory allocated for the macro expansion structure */ DoneMacroExp (&E); } #if 0 printf ("Done with %s(%u)\n", M->Name, V--); #endif } static void DefineMacro (void) /* Handle a macro definition. */ { ident Ident; Macro* M; Macro* Existing; int C89; /* Read the macro name */ SkipWhitespace (0); if (!MacName (Ident)) { return; } /* Remember if we're in C89 mode */ C89 = (IS_Get (&Standard) == STD_C89); /* Get an existing macro definition with this name */ Existing = FindMacro (Ident); /* Create a new macro definition */ M = NewMacro (Ident); /* Check if this is a function like macro */ if (CurC == '(') { /* Skip the left paren */ NextChar (); /* Set the marker that this is a function like macro */ M->ArgCount = 0; /* Read the formal parameter list */ while (1) { /* Skip white space and check for end of parameter list */ SkipWhitespace (0); if (CurC == ')') { break; } /* The next token must be either an identifier, or - if not in ** C89 mode - the ellipsis. */ if (!C89 && CurC == '.') { /* Ellipsis */ NextChar (); if (CurC != '.' || NextC != '.') { PPError ("'...' expected"); ClearLine (); return; } NextChar (); NextChar (); /* Remember that the macro is variadic and use __VA_ARGS__ as ** the argument name. */ AddMacroArg (M, "__VA_ARGS__"); M->Variadic = 1; } else { /* Must be macro argument name */ if (MacName (Ident) == 0) { return; } /* __VA_ARGS__ is only allowed in C89 mode */ if (!C89 && strcmp (Ident, "__VA_ARGS__") == 0) { PPWarning ("'__VA_ARGS__' can only appear in the expansion " "of a C99 variadic macro"); } /* Add the macro argument */ AddMacroArg (M, Ident); } /* If we had an ellipsis, or the next char is not a comma, we've ** reached the end of the macro argument list. */ SkipWhitespace (0); if (M->Variadic || CurC != ',') { break; } NextChar (); } /* Check for a right paren and eat it if we find one */ if (CurC != ')') { PPError ("')' expected"); ClearLine (); return; } NextChar (); } /* Skip whitespace before the macro replacement */ SkipWhitespace (0); /* Insert the macro into the macro table and allocate the ActualArgs array */ InsertMacro (M); /* Remove whitespace and comments from the line, store the preprocessed ** line into the macro replacement buffer. */ Pass1 (Line, &M->Replacement); /* Remove whitespace from the end of the line */ while (IsSpace (SB_LookAtLast (&M->Replacement))) { SB_Drop (&M->Replacement, 1); } #if 0 printf ("%s: <%.*s>\n", M->Name, SB_GetLen (&M->Replacement), SB_GetConstBuf (&M->Replacement)); #endif /* If we have an existing macro, check if the redefinition is identical. ** Print a diagnostic if not. */ if (Existing && MacroCmp (M, Existing) != 0) { PPError ("Macro redefinition is not identical"); } } /*****************************************************************************/ /* Preprocessing */ /*****************************************************************************/ static unsigned Pass1 (StrBuf* Source, StrBuf* Target) /* Preprocessor pass 1. Remove whitespace. Handle old and new style comments ** and the "defined" operator. */ { unsigned IdentCount; ident Ident; int HaveParen; /* Switch to the new input source */ StrBuf* OldSource = InitLine (Source); /* Loop removing ws and comments */ IdentCount = 0; while (CurC != '\0') { if (SkipWhitespace (0)) { /* Squeeze runs of blanks */ if (!IsSpace (SB_LookAtLast (Target))) { SB_AppendChar (Target, ' '); } } else if (IsSym (Ident)) { if (Preprocessing && strcmp (Ident, "defined") == 0) { /* Handle the "defined" operator */ SkipWhitespace (0); HaveParen = 0; if (CurC == '(') { HaveParen = 1; NextChar (); SkipWhitespace (0); } if (IsSym (Ident)) { SB_AppendChar (Target, IsMacro (Ident)? '1' : '0'); if (HaveParen) { SkipWhitespace (0); if (CurC != ')') { PPError ("')' expected"); } else { NextChar (); } } } else { PPError ("Identifier expected"); SB_AppendChar (Target, '0'); } } else { ++IdentCount; SB_AppendStr (Target, Ident); } } else if (IsQuote (CurC)) { CopyQuotedString (Target); } else if (CurC == '/' && NextC == '*') { if (!IsSpace (SB_LookAtLast (Target))) { SB_AppendChar (Target, ' '); } OldStyleComment (); } else if (IS_Get (&Standard) >= STD_C99 && CurC == '/' && NextC == '/') { if (!IsSpace (SB_LookAtLast (Target))) { SB_AppendChar (Target, ' '); } NewStyleComment (); } else { SB_AppendChar (Target, CurC); NextChar (); } } /* Switch back to the old source */ InitLine (OldSource); /* Return the number of identifiers found in the line */ return IdentCount; } static void MacroReplacement (StrBuf* Source, StrBuf* Target) /* Perform macro replacement. */ { ident Ident; Macro* M; /* Remember the current input and switch to Source */ StrBuf* OldSource = InitLine (Source); /* Loop substituting macros */ while (CurC != '\0') { /* If we have an identifier, check if it's a macro */ if (IsSym (Ident)) { /* Check if it's a macro */ if ((M = FindMacro (Ident)) != 0 && !M->Expanding) { /* It's a macro, expand it */ ExpandMacro (Target, M); } else { /* An identifier, keep it */ SB_AppendStr (Target, Ident); } } else if (IsQuote (CurC)) { CopyQuotedString (Target); } else if (IsSpace (CurC)) { if (!IsSpace (SB_LookAtLast (Target))) { SB_AppendChar (Target, CurC); } NextChar (); } else { SB_AppendChar (Target, CurC); NextChar (); } } /* Switch back the input */ InitLine (OldSource); } static void PreprocessLine (void) /* Translate one line. */ { /* Trim whitespace and remove comments. The function returns the number of ** identifiers found. If there were any, we will have to check for macros. */ SB_Clear (MLine); if (Pass1 (Line, MLine) > 0) { MLine = InitLine (MLine); SB_Reset (Line); SB_Clear (MLine); MacroReplacement (Line, MLine); } /* Read from the new line */ SB_Reset (MLine); MLine = InitLine (MLine); } static int PushIf (int Skip, int Invert, int Cond) /* Push a new if level onto the if stack */ { /* Check for an overflow of the if stack */ if (IfIndex >= MAX_IFS-1) { PPError ("Too many nested #if clauses"); return 1; } /* Push the #if condition */ ++IfIndex; if (Skip) { IfStack[IfIndex] = IFCOND_SKIP | IFCOND_NEEDTERM; return 1; } else { IfStack[IfIndex] = IFCOND_NONE | IFCOND_NEEDTERM; return (Invert ^ Cond); } } static void DoError (void) /* Print an error */ { SkipWhitespace (0); if (CurC == '\0') { PPError ("Invalid #error directive"); } else { PPError ("#error: %s", SB_GetConstBuf (Line) + SB_GetIndex (Line)); } /* Clear the rest of line */ ClearLine (); } static int DoIf (int Skip) /* Process #if directive */ { ExprDesc Expr; /* We're about to abuse the compiler expression parser to evaluate the ** #if expression. Save the current tokens to come back here later. ** NOTE: Yes, this is a hack, but it saves a complete separate expression ** evaluation for the preprocessor. */ Token SavedCurTok = CurTok; Token SavedNextTok = NextTok; /* Make sure the line infos for the tokens won't get removed */ if (SavedCurTok.LI) { UseLineInfo (SavedCurTok.LI); } if (SavedNextTok.LI) { UseLineInfo (SavedNextTok.LI); } /* Switch into special preprocessing mode */ Preprocessing = 1; /* Expand macros in this line */ PreprocessLine (); /* Add two semicolons as sentinels to the line, so the following ** expression evaluation will eat these two tokens but nothing from ** the following line. */ SB_AppendStr (Line, ";;"); SB_Terminate (Line); /* Load CurTok and NextTok with tokens from the new input */ NextToken (); NextToken (); /* Call the expression parser */ ConstExpr (hie1, &Expr); /* End preprocessing mode */ Preprocessing = 0; /* Reset the old tokens */ CurTok = SavedCurTok; NextTok = SavedNextTok; /* Set the #if condition according to the expression result */ return PushIf (Skip, 1, Expr.IVal != 0); } static int DoIfDef (int skip, int flag) /* Process #ifdef if flag == 1, or #ifndef if flag == 0. */ { ident Ident; SkipWhitespace (0); if (MacName (Ident) == 0) { return 0; } else { return PushIf (skip, flag, IsMacro(Ident)); } } static void DoInclude (void) /* Open an include file. */ { char RTerm; InputType IT; StrBuf Filename = STATIC_STRBUF_INITIALIZER; /* Preprocess the remainder of the line */ PreprocessLine (); /* Skip blanks */ SkipWhitespace (0); /* Get the next char and check for a valid file name terminator. Setup ** the include directory spec (SYS/USR) by looking at the terminator. */ switch (CurC) { case '\"': RTerm = '\"'; IT = IT_USRINC; break; case '<': RTerm = '>'; IT = IT_SYSINC; break; default: PPError ("'\"' or '<' expected"); goto Done; } NextChar (); /* Get a copy of the filename */ while (CurC != '\0' && CurC != RTerm) { SB_AppendChar (&Filename, CurC); NextChar (); } SB_Terminate (&Filename); /* Check if we got a terminator */ if (CurC == RTerm) { /* Open the include file */ OpenIncludeFile (SB_GetConstBuf (&Filename), IT); } else if (CurC == '\0') { /* No terminator found */ PPError ("#include expects \"FILENAME\" or <FILENAME>"); } Done: /* Free the allocated filename data */ SB_Done (&Filename); /* Clear the remaining line so the next input will come from the new ** file (if open) */ ClearLine (); } static void DoPragma (void) /* Handle a #pragma line by converting the #pragma preprocessor directive into ** the _Pragma() compiler operator. */ { /* Skip blanks following the #pragma directive */ SkipWhitespace (0); /* Copy the remainder of the line into MLine removing comments and ws */ SB_Clear (MLine); Pass1 (Line, MLine); /* Convert the directive into the operator */ SB_CopyStr (Line, "_Pragma ("); SB_Reset (MLine); Stringize (MLine, Line); SB_AppendChar (Line, ')'); /* Initialize reading from line */ SB_Reset (Line); InitLine (Line); } static void DoUndef (void) /* Process the #undef directive */ { ident Ident; SkipWhitespace (0); if (MacName (Ident)) { UndefineMacro (Ident); } } static void DoWarning (void) /* Print a warning */ { SkipWhitespace (0); if (CurC == '\0') { PPError ("Invalid #warning directive"); } else { PPWarning ("#warning: %s", SB_GetConstBuf (Line) + SB_GetIndex (Line)); } /* Clear the rest of line */ ClearLine (); } void Preprocess (void) /* Preprocess a line */ { int Skip; ident Directive; /* Create the output buffer if we don't already have one */ if (MLine == 0) { MLine = NewStrBuf (); } /* Skip white space at the beginning of the line */ SkipWhitespace (0); /* Check for stuff to skip */ Skip = 0; while (CurC == '\0' || CurC == '#' || Skip) { /* Check for preprocessor lines lines */ if (CurC == '#') { NextChar (); SkipWhitespace (0); if (CurC == '\0') { /* Ignore the empty preprocessor directive */ continue; } if (!IsSym (Directive)) { PPError ("Preprocessor directive expected"); ClearLine (); } else { switch (FindPPToken (Directive)) { case PP_DEFINE: if (!Skip) { DefineMacro (); } break; case PP_ELIF: if (IfIndex >= 0) { if ((IfStack[IfIndex] & IFCOND_ELSE) == 0) { /* Handle as #else/#if combination */ if ((IfStack[IfIndex] & IFCOND_SKIP) == 0) { Skip = !Skip; } IfStack[IfIndex] |= IFCOND_ELSE; Skip = DoIf (Skip); /* #elif doesn't need a terminator */ IfStack[IfIndex] &= ~IFCOND_NEEDTERM; } else { PPError ("Duplicate #else/#elif"); } } else { PPError ("Unexpected #elif"); } break; case PP_ELSE: if (IfIndex >= 0) { if ((IfStack[IfIndex] & IFCOND_ELSE) == 0) { if ((IfStack[IfIndex] & IFCOND_SKIP) == 0) { Skip = !Skip; } IfStack[IfIndex] |= IFCOND_ELSE; } else { PPError ("Duplicate #else"); } } else { PPError ("Unexpected '#else'"); } break; case PP_ENDIF: if (IfIndex >= 0) { /* Remove any clauses on top of stack that do not ** need a terminating #endif. */ while (IfIndex >= 0 && (IfStack[IfIndex] & IFCOND_NEEDTERM) == 0) { --IfIndex; } /* Stack may not be empty here or something is wrong */ CHECK (IfIndex >= 0); /* Remove the clause that needs a terminator */ Skip = (IfStack[IfIndex--] & IFCOND_SKIP) != 0; } else { PPError ("Unexpected '#endif'"); } break; case PP_ERROR: if (!Skip) { DoError (); } break; case PP_IF: Skip = DoIf (Skip); break; case PP_IFDEF: Skip = DoIfDef (Skip, 1); break; case PP_IFNDEF: Skip = DoIfDef (Skip, 0); break; case PP_INCLUDE: if (!Skip) { DoInclude (); } break; case PP_LINE: /* Should do something in C99 at least, but we ignore it */ if (!Skip) { ClearLine (); } break; case PP_PRAGMA: if (!Skip) { DoPragma (); goto Done; } break; case PP_UNDEF: if (!Skip) { DoUndef (); } break; case PP_WARNING: /* #warning is a non standard extension */ if (IS_Get (&Standard) > STD_C99) { if (!Skip) { DoWarning (); } } else { if (!Skip) { PPError ("Preprocessor directive expected"); } ClearLine (); } break; default: if (!Skip) { PPError ("Preprocessor directive expected"); } ClearLine (); } } } if (NextLine () == 0) { if (IfIndex >= 0) { PPError ("'#endif' expected"); } return; } SkipWhitespace (0); } PreprocessLine (); Done: if (Verbosity > 1 && SB_NotEmpty (Line)) { printf ("%s(%u): %.*s\n", GetCurrentFile (), GetCurrentLine (), (int) SB_GetLen (Line), SB_GetConstBuf (Line)); } } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/preproc.h������������������������������������������������������������������������0000664�0000000�0000000�00000006307�13473601511�0015365�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* preproc.h */ /* */ /* C preprocessor */ /* */ /* */ /* */ /* (C) 1998-2004 Ullrich von Bassewitz */ /* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef PREPROC_H #define PREPROC_H /*****************************************************************************/ /* data */ /*****************************************************************************/ /* Set when the preprocessor calls ConstExpr() recursively */ extern unsigned char Preprocessing; /*****************************************************************************/ /* code */ /*****************************************************************************/ void Preprocess (void); /* Preprocess a line */ /* End of preproc.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/reginfo.c������������������������������������������������������������������������0000664�0000000�0000000�00000011724�13473601511�0015336�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* reginfo.c */ /* */ /* 6502 register tracking info */ /* */ /* */ /* */ /* (C) 2001-2003 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "xmalloc.h" /* cc65 */ #include "reginfo.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void RC_Invalidate (RegContents* C) /* Invalidate all registers */ { C->RegA = UNKNOWN_REGVAL; C->RegX = UNKNOWN_REGVAL; C->RegY = UNKNOWN_REGVAL; C->SRegLo = UNKNOWN_REGVAL; C->SRegHi = UNKNOWN_REGVAL; C->Ptr1Lo = UNKNOWN_REGVAL; C->Ptr1Hi = UNKNOWN_REGVAL; C->Tmp1 = UNKNOWN_REGVAL; } void RC_InvalidateZP (RegContents* C) /* Invalidate all ZP registers */ { C->SRegLo = UNKNOWN_REGVAL; C->SRegHi = UNKNOWN_REGVAL; C->Ptr1Lo = UNKNOWN_REGVAL; C->Ptr1Hi = UNKNOWN_REGVAL; C->Tmp1 = UNKNOWN_REGVAL; } static void RC_Dump1 (FILE* F, const char* Desc, short Val) /* Dump one register value */ { if (RegValIsKnown (Val)) { fprintf (F, "%s=$%02X ", Desc, Val); } else { fprintf (F, "%s=$XX ", Desc); } } void RC_Dump (FILE* F, const RegContents* RC) /* Dump the contents of the given RegContents struct */ { RC_Dump1 (F, "A", RC->RegA); RC_Dump1 (F, "X", RC->RegX); RC_Dump1 (F, "Y", RC->RegY); RC_Dump1 (F, "SREG", RC->SRegLo); RC_Dump1 (F, "SREG+1", RC->SRegHi); RC_Dump1 (F, "PTR1", RC->Ptr1Lo); RC_Dump1 (F, "PTR1+1", RC->Ptr1Hi); RC_Dump1 (F, "TMP1", RC->Tmp1); fprintf (F, "\n"); } RegInfo* NewRegInfo (const RegContents* RC) /* Allocate a new register info, initialize and return it. If RC is not ** a NULL pointer, it is used to initialize both, the input and output ** registers. If the pointer is NULL, all registers are set to unknown. */ { /* Allocate memory */ RegInfo* RI = xmalloc (sizeof (RegInfo)); /* Initialize the registers */ if (RC) { RI->In = *RC; RI->Out = *RC; RI->Out2 = *RC; } else { RC_Invalidate (&RI->In); RC_Invalidate (&RI->Out); RC_Invalidate (&RI->Out2); } /* Return the new struct */ return RI; } void FreeRegInfo (RegInfo* RI) /* Free a RegInfo struct */ { xfree (RI); } void DumpRegInfo (const char* Desc, const RegInfo* RI) /* Dump the register info for debugging */ { fprintf (stdout, "%s:\n", Desc); fprintf (stdout, "In: "); RC_Dump (stdout, &RI->In); fprintf (stdout, "Out: "); RC_Dump (stdout, &RI->Out); } ��������������������������������������������cc65-2.18/src/cc65/reginfo.h������������������������������������������������������������������������0000664�0000000�0000000�00000011441�13473601511�0015337�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* reginfo.h */ /* */ /* 6502 register tracking info */ /* */ /* */ /* */ /* (C) 2001-2003 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef REGINFO_H #define REGINFO_H #include <stdio.h> /* ### */ /* common */ #include "inline.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Encoding for an unknown register value */ #define UNKNOWN_REGVAL -1 /* Register contents */ typedef struct RegContents RegContents; struct RegContents { short RegA; short RegX; short RegY; short SRegLo; short SRegHi; short Ptr1Lo; short Ptr1Hi; short Tmp1; }; /* Register change info */ typedef struct RegInfo RegInfo; struct RegInfo { RegContents In; /* Incoming register values */ RegContents Out; /* Outgoing register values */ RegContents Out2; /* Alternative outgoing reg values for branches */ }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void RC_Invalidate (RegContents* C); /* Invalidate all registers */ void RC_InvalidateZP (RegContents* C); /* Invalidate all ZP registers */ void RC_Dump (FILE* F, const RegContents* RC); /* Dump the contents of the given RegContents struct */ #if defined(HAVE_INLINE) INLINE int RegValIsKnown (short Val) /* Return true if the register value is known */ { return (Val >= 0); } #else # define RegValIsKnown(S) ((S) >= 0) #endif #if defined(HAVE_INLINE) INLINE int RegValIsUnknown (short Val) /* Return true if the register value is not known */ { return (Val < 0); } #else # define RegValIsUnknown(S) ((S) < 0) #endif RegInfo* NewRegInfo (const RegContents* RC); /* Allocate a new register info, initialize and return it. If RC is not ** a NULL pointer, it is used to initialize both, the input and output ** registers. If the pointer is NULL, all registers are set to unknown. */ void FreeRegInfo (RegInfo* RI); /* Free a RegInfo struct */ void DumpRegInfo (const char* Desc, const RegInfo* RI); /* Dump the register info for debugging */ /* End of reginfo.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/scanner.c������������������������������������������������������������������������0000664�0000000�0000000�00000077616�13473601511�0015352�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* scanner.c */ /* */ /* Source file line info structure */ /* */ /* */ /* */ /* (C) 1998-2010, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <ctype.h> #include <math.h> /* common */ #include "chartype.h" #include "fp.h" #include "tgttrans.h" /* cc65 */ #include "datatype.h" #include "error.h" #include "function.h" #include "global.h" #include "hexval.h" #include "ident.h" #include "input.h" #include "litpool.h" #include "preproc.h" #include "scanner.h" #include "standard.h" #include "symtab.h" /*****************************************************************************/ /* data */ /*****************************************************************************/ Token CurTok; /* The current token */ Token NextTok; /* The next token */ /* Token types */ enum { TT_C89 = 0x01 << STD_C89, /* Token valid in C89 */ TT_C99 = 0x01 << STD_C99, /* Token valid in C99 */ TT_CC65 = 0x01 << STD_CC65 /* Token valid in cc65 */ }; /* Token table */ static const struct Keyword { char* Key; /* Keyword name */ unsigned char Tok; /* The token */ unsigned char Std; /* Token supported in which standards? */ } Keywords [] = { { "_Pragma", TOK_PRAGMA, TT_C89 | TT_C99 | TT_CC65 }, /* !! */ { "__AX__", TOK_AX, TT_C89 | TT_C99 | TT_CC65 }, { "__A__", TOK_A, TT_C89 | TT_C99 | TT_CC65 }, { "__EAX__", TOK_EAX, TT_C89 | TT_C99 | TT_CC65 }, { "__X__", TOK_X, TT_C89 | TT_C99 | TT_CC65 }, { "__Y__", TOK_Y, TT_C89 | TT_C99 | TT_CC65 }, { "__asm__", TOK_ASM, TT_C89 | TT_C99 | TT_CC65 }, { "__attribute__", TOK_ATTRIBUTE, TT_C89 | TT_C99 | TT_CC65 }, { "__cdecl__", TOK_CDECL, TT_C89 | TT_C99 | TT_CC65 }, { "__far__", TOK_FAR, TT_C89 | TT_C99 | TT_CC65 }, { "__fastcall__", TOK_FASTCALL, TT_C89 | TT_C99 | TT_CC65 }, { "__inline__", TOK_INLINE, TT_C89 | TT_C99 | TT_CC65 }, { "__near__", TOK_NEAR, TT_C89 | TT_C99 | TT_CC65 }, { "asm", TOK_ASM, TT_CC65 }, { "auto", TOK_AUTO, TT_C89 | TT_C99 | TT_CC65 }, { "break", TOK_BREAK, TT_C89 | TT_C99 | TT_CC65 }, { "case", TOK_CASE, TT_C89 | TT_C99 | TT_CC65 }, { "cdecl", TOK_CDECL, TT_CC65 }, { "char", TOK_CHAR, TT_C89 | TT_C99 | TT_CC65 }, { "const", TOK_CONST, TT_C89 | TT_C99 | TT_CC65 }, { "continue", TOK_CONTINUE, TT_C89 | TT_C99 | TT_CC65 }, { "default", TOK_DEFAULT, TT_C89 | TT_C99 | TT_CC65 }, { "do", TOK_DO, TT_C89 | TT_C99 | TT_CC65 }, { "double", TOK_DOUBLE, TT_C89 | TT_C99 | TT_CC65 }, { "else", TOK_ELSE, TT_C89 | TT_C99 | TT_CC65 }, { "enum", TOK_ENUM, TT_C89 | TT_C99 | TT_CC65 }, { "extern", TOK_EXTERN, TT_C89 | TT_C99 | TT_CC65 }, { "far", TOK_FAR, TT_CC65 }, { "fastcall", TOK_FASTCALL, TT_CC65 }, { "float", TOK_FLOAT, TT_C89 | TT_C99 | TT_CC65 }, { "for", TOK_FOR, TT_C89 | TT_C99 | TT_CC65 }, { "goto", TOK_GOTO, TT_C89 | TT_C99 | TT_CC65 }, { "if", TOK_IF, TT_C89 | TT_C99 | TT_CC65 }, { "inline", TOK_INLINE, TT_C99 | TT_CC65 }, { "int", TOK_INT, TT_C89 | TT_C99 | TT_CC65 }, { "long", TOK_LONG, TT_C89 | TT_C99 | TT_CC65 }, { "near", TOK_NEAR, TT_CC65 }, { "register", TOK_REGISTER, TT_C89 | TT_C99 | TT_CC65 }, { "restrict", TOK_RESTRICT, TT_C99 | TT_CC65 }, { "return", TOK_RETURN, TT_C89 | TT_C99 | TT_CC65 }, { "short", TOK_SHORT, TT_C89 | TT_C99 | TT_CC65 }, { "signed", TOK_SIGNED, TT_C89 | TT_C99 | TT_CC65 }, { "sizeof", TOK_SIZEOF, TT_C89 | TT_C99 | TT_CC65 }, { "static", TOK_STATIC, TT_C89 | TT_C99 | TT_CC65 }, { "struct", TOK_STRUCT, TT_C89 | TT_C99 | TT_CC65 }, { "switch", TOK_SWITCH, TT_C89 | TT_C99 | TT_CC65 }, { "typedef", TOK_TYPEDEF, TT_C89 | TT_C99 | TT_CC65 }, { "union", TOK_UNION, TT_C89 | TT_C99 | TT_CC65 }, { "unsigned", TOK_UNSIGNED, TT_C89 | TT_C99 | TT_CC65 }, { "void", TOK_VOID, TT_C89 | TT_C99 | TT_CC65 }, { "volatile", TOK_VOLATILE, TT_C89 | TT_C99 | TT_CC65 }, { "while", TOK_WHILE, TT_C89 | TT_C99 | TT_CC65 }, }; #define KEY_COUNT (sizeof (Keywords) / sizeof (Keywords [0])) /* Stuff for determining the type of an integer constant */ #define IT_INT 0x01 #define IT_UINT 0x02 #define IT_LONG 0x04 #define IT_ULONG 0x08 /*****************************************************************************/ /* code */ /*****************************************************************************/ static int CmpKey (const void* Key, const void* Elem) /* Compare function for bsearch */ { return strcmp ((const char*) Key, ((const struct Keyword*) Elem)->Key); } static token_t FindKey (const char* Key) /* Find a keyword and return the token. Return IDENT if the token is not a ** keyword. */ { struct Keyword* K; K = bsearch (Key, Keywords, KEY_COUNT, sizeof (Keywords [0]), CmpKey); if (K && (K->Std & (0x01 << IS_Get (&Standard))) != 0) { return K->Tok; } else { return TOK_IDENT; } } static int SkipWhite (void) /* Skip white space in the input stream, reading and preprocessing new lines ** if necessary. Return 0 if end of file is reached, return 1 otherwise. */ { while (1) { while (CurC == '\0') { if (NextLine () == 0) { return 0; } Preprocess (); } if (IsSpace (CurC)) { NextChar (); } else { return 1; } } } int TokIsFuncSpec (const Token* T) /* Return true if the token is a function specifier */ { return (T->Tok == TOK_INLINE) || (T->Tok == TOK_FASTCALL) || (T->Tok == TOK_CDECL) || (T->Tok == TOK_NEAR) || (T->Tok == TOK_FAR); } void SymName (char* S) /* Read a symbol from the input stream. The first character must have been ** checked before calling this function. The buffer is expected to be at ** least of size MAX_IDENTLEN+1. */ { unsigned Len = 0; do { if (Len < MAX_IDENTLEN) { ++Len; *S++ = CurC; } NextChar (); } while (IsIdent (CurC) || IsDigit (CurC)); *S = '\0'; } int IsSym (char* S) /* If a symbol follows, read it and return 1, otherwise return 0 */ { if (IsIdent (CurC)) { SymName (S); return 1; } else { return 0; } } static void UnknownChar (char C) /* Error message for unknown character */ { Error ("Invalid input character with code %02X", C & 0xFF); NextChar (); /* Skip */ } static void SetTok (int tok) /* Set NextTok.Tok and bump line ptr */ { NextTok.Tok = tok; NextChar (); } static int ParseChar (void) /* Parse a character. Converts escape chars into character codes. */ { int C; int HadError; int Count; /* Check for escape chars */ if (CurC == '\\') { NextChar (); switch (CurC) { case '?': C = '\?'; break; case 'a': C = '\a'; break; case 'b': C = '\b'; break; case 'f': C = '\f'; break; case 'r': C = '\r'; break; case 'n': C = '\n'; break; case 't': C = '\t'; break; case 'v': C = '\v'; break; case '\"': C = '\"'; break; case '\'': C = '\''; break; case '\\': C = '\\'; break; case 'x': case 'X': /* Hex character constant */ if (!IsXDigit (NextC)) { Error ("\\x used with no following hex digits"); C = ' '; } else { HadError = 0; C = 0; while (IsXDigit (NextC)) { if ((C << 4) >= 256) { if (!HadError) { Error ("Hex character constant out of range"); HadError = 1; } } else { C = (C << 4) | HexVal (NextC); } NextChar (); } } break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': /* Octal constant */ Count = 1; C = HexVal (CurC); while (IsODigit (NextC) && Count++ < 3) { C = (C << 3) | HexVal (NextC); NextChar (); } if (C >= 256) Error ("Octal character constant out of range"); break; default: C = CurC; Error ("Illegal escaped character: 0x%02X", CurC); break; } } else { C = CurC; } /* Skip the character read */ NextChar (); /* Do correct sign extension */ return SignExtendChar (C); } static void CharConst (void) /* Parse a character constant. */ { int C; /* Skip the quote */ NextChar (); /* Get character */ C = ParseChar (); /* Check for closing quote */ if (CurC != '\'') { Error ("'\'' expected"); } else { /* Skip the quote */ NextChar (); } /* Setup values and attributes */ NextTok.Tok = TOK_CCONST; /* Translate into target charset */ NextTok.IVal = SignExtendChar (TgtTranslateChar (C)); /* Character constants have type int */ NextTok.Type = type_int; } static void StringConst (void) /* Parse a quoted string */ { /* String buffer */ StrBuf S = AUTO_STRBUF_INITIALIZER; /* Assume next token is a string constant */ NextTok.Tok = TOK_SCONST; /* Concatenate strings. If at least one of the concenated strings is a wide ** character literal, the whole string is a wide char literal, otherwise ** it's a normal string literal. */ while (1) { /* Check if this is a normal or a wide char string */ if (CurC == 'L' && NextC == '\"') { /* Wide character literal */ NextTok.Tok = TOK_WCSCONST; NextChar (); NextChar (); } else if (CurC == '\"') { /* Skip the quote char */ NextChar (); } else { /* No string */ break; } /* Read until end of string */ while (CurC != '\"') { if (CurC == '\0') { Error ("Unexpected newline"); break; } SB_AppendChar (&S, ParseChar ()); } /* Skip closing quote char if there was one */ NextChar (); /* Skip white space, read new input */ SkipWhite (); } /* Terminate the string */ SB_AppendChar (&S, '\0'); /* Add the whole string to the literal pool */ NextTok.SVal = AddLiteralStr (&S); /* Free the buffer */ SB_Done (&S); } static void NumericConst (void) /* Parse a numeric constant */ { unsigned Base; /* Temporary number base */ unsigned Prefix; /* Base according to prefix */ StrBuf S = STATIC_STRBUF_INITIALIZER; int IsFloat; char C; unsigned DigitVal; unsigned long IVal; /* Value */ /* Check for a leading hex or octal prefix and determine the possible ** integer types. */ if (CurC == '0') { /* Gobble 0 and examine next char */ NextChar (); if (toupper (CurC) == 'X') { Base = Prefix = 16; NextChar (); /* gobble "x" */ } else { Base = 10; /* Assume 10 for now - see below */ Prefix = 8; /* Actual prefix says octal */ } } else { Base = Prefix = 10; } /* Because floating point numbers don't have octal prefixes (a number ** with a leading zero is decimal), we first have to read the number ** before converting it, so we can determine if it's a float or an ** integer. */ while (IsXDigit (CurC) && HexVal (CurC) < Base) { SB_AppendChar (&S, CurC); NextChar (); } SB_Terminate (&S); /* The following character tells us if we have an integer or floating ** point constant. Note: Hexadecimal floating point constants aren't ** supported in C89. */ IsFloat = (CurC == '.' || (Base == 10 && toupper (CurC) == 'E') || (Base == 16 && toupper (CurC) == 'P' && IS_Get (&Standard) >= STD_C99)); /* If we don't have a floating point type, an octal prefix results in an ** octal base. */ if (!IsFloat && Prefix == 8) { Base = 8; } /* Since we do now know the correct base, convert the remembered input ** into a number. */ SB_Reset (&S); IVal = 0; while ((C = SB_Get (&S)) != '\0') { DigitVal = HexVal (C); if (DigitVal >= Base) { Error ("Numeric constant contains digits beyond the radix"); } IVal = (IVal * Base) + DigitVal; } /* We don't need the string buffer any longer */ SB_Done (&S); /* Distinguish between integer and floating point constants */ if (!IsFloat) { unsigned Types; int HaveSuffix; /* Check for a suffix and determine the possible types */ HaveSuffix = 1; if (toupper (CurC) == 'U') { /* Unsigned type */ NextChar (); if (toupper (CurC) != 'L') { Types = IT_UINT | IT_ULONG; } else { NextChar (); Types = IT_ULONG; } } else if (toupper (CurC) == 'L') { /* Long type */ NextChar (); if (toupper (CurC) != 'U') { Types = IT_LONG | IT_ULONG; } else { NextChar (); Types = IT_ULONG; } } else { HaveSuffix = 0; if (Prefix == 10) { /* Decimal constants are of any type but uint */ Types = IT_INT | IT_LONG | IT_ULONG; } else { /* Octal or hex constants are of any type */ Types = IT_INT | IT_UINT | IT_LONG | IT_ULONG; } } /* Check the range to determine the type */ if (IVal > 0x7FFF) { /* Out of range for int */ Types &= ~IT_INT; /* If the value is in the range 0x8000..0xFFFF, unsigned int is not ** allowed, and we don't have a type specifying suffix, emit a ** warning, because the constant is of type long. */ if (IVal <= 0xFFFF && (Types & IT_UINT) == 0 && !HaveSuffix) { Warning ("Constant is long"); } } if (IVal > 0xFFFF) { /* Out of range for unsigned int */ Types &= ~IT_UINT; } if (IVal > 0x7FFFFFFF) { /* Out of range for long int */ Types &= ~IT_LONG; } /* Now set the type string to the smallest type in types */ if (Types & IT_INT) { NextTok.Type = type_int; } else if (Types & IT_UINT) { NextTok.Type = type_uint; } else if (Types & IT_LONG) { NextTok.Type = type_long; } else { NextTok.Type = type_ulong; } /* Set the value and the token */ NextTok.IVal = IVal; NextTok.Tok = TOK_ICONST; } else { /* Float constant */ Double FVal = FP_D_FromInt (IVal); /* Convert to double */ /* Check for a fractional part and read it */ if (CurC == '.') { Double Scale; /* Skip the dot */ NextChar (); /* Read fractional digits */ Scale = FP_D_Make (1.0); while (IsXDigit (CurC) && (DigitVal = HexVal (CurC)) < Base) { /* Get the value of this digit */ Double FracVal = FP_D_Div (FP_D_FromInt (DigitVal * Base), Scale); /* Add it to the float value */ FVal = FP_D_Add (FVal, FracVal); /* Scale base */ Scale = FP_D_Mul (Scale, FP_D_FromInt (DigitVal)); /* Skip the digit */ NextChar (); } } /* Check for an exponent and read it */ if ((Base == 16 && toupper (CurC) == 'F') || (Base == 10 && toupper (CurC) == 'E')) { unsigned Digits; unsigned Exp; /* Skip the exponent notifier */ NextChar (); /* Read an optional sign */ if (CurC == '-') { NextChar (); } else if (CurC == '+') { NextChar (); } /* Read exponent digits. Since we support only 32 bit floats ** with a maximum exponent of +-/127, we read the exponent ** part as integer with up to 3 digits and drop the remainder. ** This avoids an overflow of Exp. The exponent is always ** decimal, even for hex float consts. */ Digits = 0; Exp = 0; while (IsDigit (CurC)) { if (++Digits <= 3) { Exp = Exp * 10 + HexVal (CurC); } NextChar (); } /* Check for errors: We must have exponent digits, and not more ** than three. */ if (Digits == 0) { Error ("Floating constant exponent has no digits"); } else if (Digits > 3) { Warning ("Floating constant exponent is too large"); } /* Scale the exponent and adjust the value accordingly */ if (Exp) { FVal = FP_D_Mul (FVal, FP_D_Make (pow (10, Exp))); } } /* Check for a suffix and determine the type of the constant */ if (toupper (CurC) == 'F') { NextChar (); NextTok.Type = type_float; } else { NextTok.Type = type_double; } /* Set the value and the token */ NextTok.FVal = FVal; NextTok.Tok = TOK_FCONST; } } void NextToken (void) /* Get next token from input stream */ { ident token; /* We have to skip white space here before shifting tokens, since the ** tokens and the current line info is invalid at startup and will get ** initialized by reading the first time from the file. Remember if ** we were at end of input and handle that later. */ int GotEOF = (SkipWhite() == 0); /* Current token is the lookahead token */ if (CurTok.LI) { ReleaseLineInfo (CurTok.LI); } CurTok = NextTok; /* When reading the first time from the file, the line info in NextTok, ** which was copied to CurTok is invalid. Since the information from ** the token is used for error messages, we must make it valid. */ if (CurTok.LI == 0) { CurTok.LI = UseLineInfo (GetCurLineInfo ()); } /* Remember the starting position of the next token */ NextTok.LI = UseLineInfo (GetCurLineInfo ()); /* Now handle end of input. */ if (GotEOF) { /* End of file reached */ NextTok.Tok = TOK_CEOF; return; } /* Determine the next token from the lookahead */ if (IsDigit (CurC) || (CurC == '.' && IsDigit (NextC))) { /* A number */ NumericConst (); return; } /* Check for wide character literals */ if (CurC == 'L' && NextC == '\"') { StringConst (); return; } /* Check for keywords and identifiers */ if (IsSym (token)) { /* Check for a keyword */ if ((NextTok.Tok = FindKey (token)) != TOK_IDENT) { /* Reserved word found */ return; } /* No reserved word, check for special symbols */ if (token[0] == '_' && token[1] == '_') { /* Special symbols */ if (strcmp (token+2, "FILE__") == 0) { NextTok.SVal = AddLiteral (GetCurrentFile()); NextTok.Tok = TOK_SCONST; return; } else if (strcmp (token+2, "LINE__") == 0) { NextTok.Tok = TOK_ICONST; NextTok.IVal = GetCurrentLine(); NextTok.Type = type_int; return; } else if (strcmp (token+2, "func__") == 0) { /* __func__ is only defined in functions */ if (CurrentFunc) { NextTok.SVal = AddLiteral (F_GetFuncName (CurrentFunc)); NextTok.Tok = TOK_SCONST; return; } } } /* No reserved word but identifier */ strcpy (NextTok.Ident, token); NextTok.Tok = TOK_IDENT; return; } /* Monstrous switch statement ahead... */ switch (CurC) { case '!': NextChar (); if (CurC == '=') { SetTok (TOK_NE); } else { NextTok.Tok = TOK_BOOL_NOT; } break; case '\"': StringConst (); break; case '%': NextChar (); if (CurC == '=') { SetTok (TOK_MOD_ASSIGN); } else { NextTok.Tok = TOK_MOD; } break; case '&': NextChar (); switch (CurC) { case '&': SetTok (TOK_BOOL_AND); break; case '=': SetTok (TOK_AND_ASSIGN); break; default: NextTok.Tok = TOK_AND; } break; case '\'': CharConst (); break; case '(': SetTok (TOK_LPAREN); break; case ')': SetTok (TOK_RPAREN); break; case '*': NextChar (); if (CurC == '=') { SetTok (TOK_MUL_ASSIGN); } else { NextTok.Tok = TOK_STAR; } break; case '+': NextChar (); switch (CurC) { case '+': SetTok (TOK_INC); break; case '=': SetTok (TOK_PLUS_ASSIGN); break; default: NextTok.Tok = TOK_PLUS; } break; case ',': SetTok (TOK_COMMA); break; case '-': NextChar (); switch (CurC) { case '-': SetTok (TOK_DEC); break; case '=': SetTok (TOK_MINUS_ASSIGN); break; case '>': SetTok (TOK_PTR_REF); break; default: NextTok.Tok = TOK_MINUS; } break; case '.': NextChar (); if (CurC == '.') { NextChar (); if (CurC == '.') { SetTok (TOK_ELLIPSIS); } else { UnknownChar (CurC); } } else { NextTok.Tok = TOK_DOT; } break; case '/': NextChar (); if (CurC == '=') { SetTok (TOK_DIV_ASSIGN); } else { NextTok.Tok = TOK_DIV; } break; case ':': SetTok (TOK_COLON); break; case ';': SetTok (TOK_SEMI); break; case '<': NextChar (); switch (CurC) { case '=': SetTok (TOK_LE); break; case '<': NextChar (); if (CurC == '=') { SetTok (TOK_SHL_ASSIGN); } else { NextTok.Tok = TOK_SHL; } break; default: NextTok.Tok = TOK_LT; } break; case '=': NextChar (); if (CurC == '=') { SetTok (TOK_EQ); } else { NextTok.Tok = TOK_ASSIGN; } break; case '>': NextChar (); switch (CurC) { case '=': SetTok (TOK_GE); break; case '>': NextChar (); if (CurC == '=') { SetTok (TOK_SHR_ASSIGN); } else { NextTok.Tok = TOK_SHR; } break; default: NextTok.Tok = TOK_GT; } break; case '?': SetTok (TOK_QUEST); break; case '[': SetTok (TOK_LBRACK); break; case ']': SetTok (TOK_RBRACK); break; case '^': NextChar (); if (CurC == '=') { SetTok (TOK_XOR_ASSIGN); } else { NextTok.Tok = TOK_XOR; } break; case '{': SetTok (TOK_LCURLY); break; case '|': NextChar (); switch (CurC) { case '|': SetTok (TOK_BOOL_OR); break; case '=': SetTok (TOK_OR_ASSIGN); break; default: NextTok.Tok = TOK_OR; } break; case '}': SetTok (TOK_RCURLY); break; case '~': SetTok (TOK_COMP); break; default: UnknownChar (CurC); } } void SkipTokens (const token_t* TokenList, unsigned TokenCount) /* Skip tokens until we reach TOK_CEOF or a token in the given token list. ** This routine is used for error recovery. */ { while (CurTok.Tok != TOK_CEOF) { /* Check if the current token is in the token list */ unsigned I; for (I = 0; I < TokenCount; ++I) { if (CurTok.Tok == TokenList[I]) { /* Found a token in the list */ return; } } /* Not in the list: Skip it */ NextToken (); } } int Consume (token_t Token, const char* ErrorMsg) /* Eat token if it is the next in the input stream, otherwise print an error ** message. Returns true if the token was found and false otherwise. */ { if (CurTok.Tok == Token) { NextToken (); return 1; } else { Error ("%s", ErrorMsg); return 0; } } int ConsumeColon (void) /* Check for a colon and skip it. */ { return Consume (TOK_COLON, "':' expected"); } int ConsumeSemi (void) /* Check for a semicolon and skip it. */ { /* Try do be smart about typos... */ if (CurTok.Tok == TOK_SEMI) { NextToken (); return 1; } else { Error ("';' expected"); if (CurTok.Tok == TOK_COLON || CurTok.Tok == TOK_COMMA) { NextToken (); } return 0; } } int ConsumeComma (void) /* Check for a comma and skip it. */ { /* Try do be smart about typos... */ if (CurTok.Tok == TOK_COMMA) { NextToken (); return 1; } else { Error ("',' expected"); if (CurTok.Tok == TOK_SEMI) { NextToken (); } return 0; } } int ConsumeLParen (void) /* Check for a left parenthesis and skip it */ { return Consume (TOK_LPAREN, "'(' expected"); } int ConsumeRParen (void) /* Check for a right parenthesis and skip it */ { return Consume (TOK_RPAREN, "')' expected"); } int ConsumeLBrack (void) /* Check for a left bracket and skip it */ { return Consume (TOK_LBRACK, "'[' expected"); } int ConsumeRBrack (void) /* Check for a right bracket and skip it */ { return Consume (TOK_RBRACK, "']' expected"); } int ConsumeLCurly (void) /* Check for a left curly brace and skip it */ { return Consume (TOK_LCURLY, "'{' expected"); } int ConsumeRCurly (void) /* Check for a right curly brace and skip it */ { return Consume (TOK_RCURLY, "'}' expected"); } ������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/scanner.h������������������������������������������������������������������������0000664�0000000�0000000�00000020727�13473601511�0015346�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* scanner.h */ /* */ /* Source file line info structure */ /* */ /* */ /* */ /* (C) 1998-2010, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef SCANNER_H #define SCANNER_H /* common */ #include "fp.h" /* cc65 */ #include "datatype.h" #include "ident.h" #include "lineinfo.h" /*****************************************************************************/ /* Token definitions */ /*****************************************************************************/ typedef enum token_t { TOK_INVALID, TOK_CEOF, /* Storage specifiers */ TOK_FIRST_STORAGE_CLASS, TOK_AUTO = TOK_FIRST_STORAGE_CLASS, TOK_EXTERN, TOK_REGISTER, TOK_STATIC, TOK_TYPEDEF, TOK_LAST_STORAGE_CLASS = TOK_TYPEDEF, /* Tokens denoting type qualifiers */ TOK_FIRST_TYPEQUAL, TOK_CONST = TOK_FIRST_TYPEQUAL, TOK_VOLATILE, TOK_RESTRICT, TOK_LAST_TYPEQUAL = TOK_RESTRICT, /* Function specifiers */ TOK_INLINE, TOK_FASTCALL, TOK_CDECL, /* Tokens denoting types */ TOK_FIRST_TYPE, TOK_ENUM = TOK_FIRST_TYPE, TOK_CHAR, TOK_INT, TOK_DOUBLE, TOK_FLOAT, TOK_LONG, TOK_UNSIGNED, TOK_SIGNED, TOK_SHORT, TOK_STRUCT, TOK_UNION, TOK_VOID, TOK_LAST_TYPE = TOK_VOID, /* Control statements */ TOK_DO, TOK_FOR, TOK_GOTO, TOK_IF, TOK_RETURN, TOK_SWITCH, TOK_WHILE, TOK_ASM, TOK_CASE, TOK_DEFAULT, TOK_BREAK, TOK_CONTINUE, TOK_ELSE, TOK_ELLIPSIS, TOK_SIZEOF, TOK_IDENT, TOK_SEMI, /* Primary operators */ TOK_LBRACK, TOK_LPAREN, TOK_DOT, TOK_PTR_REF, TOK_LCURLY, TOK_RBRACK, TOK_COMP, TOK_INC, TOK_PLUS_ASSIGN, TOK_PLUS, TOK_COMMA, TOK_DEC, TOK_MINUS_ASSIGN, TOK_RCURLY, TOK_MINUS, TOK_MUL_ASSIGN, TOK_STAR, TOK_MUL = TOK_STAR, /* Alias */ TOK_DIV_ASSIGN, TOK_DIV, TOK_BOOL_AND, TOK_AND_ASSIGN, TOK_AND, TOK_NE, TOK_BOOL_NOT, TOK_BOOL_OR, TOK_OR_ASSIGN, TOK_OR, TOK_EQ, TOK_ASSIGN, /* Inequalities */ TOK_LE, TOK_LT, TOK_GE, TOK_GT, TOK_SHL_ASSIGN, TOK_SHL, TOK_SHR_ASSIGN, TOK_SHR, TOK_XOR_ASSIGN, TOK_XOR, TOK_MOD_ASSIGN, TOK_MOD, TOK_QUEST, TOK_COLON, TOK_RPAREN, TOK_SCONST, TOK_ICONST, TOK_CCONST, TOK_FCONST, TOK_WCSCONST, TOK_ATTRIBUTE, TOK_FAR, TOK_NEAR, TOK_A, TOK_X, TOK_Y, TOK_AX, TOK_EAX, TOK_PRAGMA } token_t; /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Forward for struct Literal */ struct Literal; /* Token stuff */ typedef struct Token Token; struct Token { token_t Tok; /* The token itself */ long IVal; /* The integer attribute */ Double FVal; /* The float attribute */ struct Literal* SVal; /* String literal is any */ ident Ident; /* Identifier if IDENT */ LineInfo* LI; /* Source line where the token comes from */ Type* Type; /* Type if integer or float constant */ }; extern Token CurTok; /* The current token */ extern Token NextTok; /* The next token */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ #if defined(HAVE_INLINE) INLINE int TokIsStorageClass (const Token* T) /* Return true if the token is a storage class specifier */ { return (T->Tok >= TOK_FIRST_STORAGE_CLASS && T->Tok <= TOK_LAST_STORAGE_CLASS); } #else # define TokIsStorageClass(T) \ ((T)->Tok >= TOK_FIRST_STORAGE_CLASS && (T)->Tok <= TOK_LAST_STORAGE_CLASS) #endif #if defined(HAVE_INLINE) INLINE int TokIsType (const Token* T) /* Return true if the token is a type */ { return (T->Tok >= TOK_FIRST_TYPE && T->Tok <= TOK_LAST_TYPE); } #else # define TokIsType(T) ((T)->Tok >= TOK_FIRST_TYPE && (T)->Tok <= TOK_LAST_TYPE) #endif #if defined(HAVE_INLINE) INLINE int TokIsTypeQual (const Token* T) /* Return true if the token is a type qualifier */ { return (T->Tok >= TOK_FIRST_TYPEQUAL && T->Tok <= TOK_LAST_TYPEQUAL); } #else # define TokIsTypeQual(T) ((T)->Tok >= TOK_FIRST_TYPEQUAL && (T)->Tok <= TOK_LAST_TYPEQUAL) #endif int TokIsFuncSpec (const Token* T); /* Return true if the token is a function specifier */ void SymName (char* S); /* Read a symbol from the input stream. The first character must have been ** checked before calling this function. The buffer is expected to be at ** least of size MAX_IDENTLEN+1. */ int IsSym (char* S); /* If a symbol follows, read it and return 1, otherwise return 0 */ void NextToken (void); /* Get next token from input stream */ void SkipTokens (const token_t* TokenList, unsigned TokenCount); /* Skip tokens until we reach TOK_CEOF or a token in the given token list. ** This routine is used for error recovery. */ int Consume (token_t Token, const char* ErrorMsg); /* Eat token if it is the next in the input stream, otherwise print an error ** message. Returns true if the token was found and false otherwise. */ int ConsumeColon (void); /* Check for a colon and skip it. */ int ConsumeSemi (void); /* Check for a semicolon and skip it. */ int ConsumeComma (void); /* Check for a comma and skip it. */ int ConsumeLParen (void); /* Check for a left parenthesis and skip it */ int ConsumeRParen (void); /* Check for a right parenthesis and skip it */ int ConsumeLBrack (void); /* Check for a left bracket and skip it */ int ConsumeRBrack (void); /* Check for a right bracket and skip it */ int ConsumeLCurly (void); /* Check for a left curly brace and skip it */ int ConsumeRCurly (void); /* Check for a right curly brace and skip it */ /* End of scanner.h */ #endif �����������������������������������������cc65-2.18/src/cc65/scanstrbuf.c���������������������������������������������������������������������0000664�0000000�0000000�00000024105�13473601511�0016054�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* scanstrbuf.c */ /* */ /* Small scanner for input from a StrBuf */ /* */ /* */ /* */ /* (C) 2002-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "chartype.h" #include "tgttrans.h" /* cc65 */ #include "datatype.h" #include "error.h" #include "hexval.h" #include "ident.h" #include "scanstrbuf.h" /*****************************************************************************/ /* Helper functions */ /*****************************************************************************/ static int ParseChar (StrBuf* B) /* Parse a character. Converts \n into EOL, etc. */ { unsigned I; unsigned Val; int C; /* Check for escape chars */ if ((C = SB_Get (B)) == '\\') { switch (SB_Peek (B)) { case '?': C = '?'; SB_Skip (B); break; case 'a': C = '\a'; SB_Skip (B); break; case 'b': C = '\b'; SB_Skip (B); break; case 'f': C = '\f'; SB_Skip (B); break; case 'r': C = '\r'; SB_Skip (B); break; case 'n': C = '\n'; SB_Skip (B); break; case 't': C = '\t'; SB_Skip (B); break; case 'v': C = '\v'; SB_Skip (B); break; case '\"': C = '\"'; SB_Skip (B); break; case '\'': C = '\''; SB_Skip (B); break; case '\\': C = '\\'; SB_Skip (B); break; case 'x': case 'X': /* Hex character constant */ SB_Skip (B); C = HexVal (SB_Get (B)) << 4; C |= HexVal (SB_Get (B)); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': /* Octal constant */ I = 0; Val = SB_Get (B) - '0'; while (SB_Peek (B) >= '0' && SB_Peek (B) <= '7' && ++I <= 3) { Val = (Val << 3) | (SB_Get (B) - '0'); } C = (int) Val; if (Val > 256) { Error ("Character constant out of range"); C = ' '; } break; default: Error ("Illegal character constant 0x%02X", SB_Get (B)); C = ' '; break; } } /* Return the character */ return C; } /*****************************************************************************/ /* Code */ /*****************************************************************************/ void SB_SkipWhite (StrBuf* B) /* Skip whitespace in the string buffer */ { while (IsBlank (SB_Peek (B))) { SB_Skip (B); } } int SB_GetSym (StrBuf* B, StrBuf* Ident, const char* SpecialChars) /* Get a symbol from the string buffer. If SpecialChars is not NULL, it ** points to a string that contains characters allowed within the string in ** addition to letters, digits and the underline. Note: The identifier must ** still begin with a letter. ** Returns 1 if a symbol was found and 0 otherwise but doesn't output any ** errors. */ { /* Handle a NULL argument for SpecialChars transparently */ if (SpecialChars == 0) { SpecialChars = ""; } /* Clear Ident */ SB_Clear (Ident); if (IsIdent (SB_Peek (B))) { char C = SB_Peek (B); do { SB_AppendChar (Ident, C); SB_Skip (B); C = SB_Peek (B); } while (IsIdent (C) || IsDigit (C) || (C != '\0' && strchr (SpecialChars, C) != 0)); SB_Terminate (Ident); return 1; } else { return 0; } } int SB_GetString (StrBuf* B, StrBuf* S) /* Get a string from the string buffer. Returns 1 if a string was found and 0 ** otherwise. Errors are only output in case of invalid strings (missing end ** of string). */ { char C; /* Clear S */ SB_Clear (S); /* A string starts with quote marks */ if (SB_Peek (B) == '\"') { /* String follows, be sure to concatenate strings */ while (SB_Peek (B) == '\"') { /* Skip the quote char */ SB_Skip (B); /* Read the actual string contents */ while ((C = SB_Peek (B)) != '\"') { if (C == '\0') { Error ("Unexpected end of string"); break; } SB_AppendChar (S, ParseChar (B)); } /* Skip the closing quote char if there was one */ SB_Skip (B); /* Skip white space, read new input */ SB_SkipWhite (B); } /* Terminate the string */ SB_Terminate (S); /* Success */ return 1; } else { /* Not a string */ SB_Terminate (S); return 0; } } int SB_GetNumber (StrBuf* B, long* Val) /* Get a number from the string buffer. Accepted formats are decimal, octal, ** hex and character constants. Numeric constants may be preceeded by a ** minus or plus sign. The function returns 1 if a number was found and ** zero otherwise. Errors are only output for invalid numbers. */ { int Sign; char C; unsigned Base; unsigned DigitVal; /* Initialize Val */ *Val = 0; /* Handle character constants */ if (SB_Peek (B) == '\'') { /* Character constant */ SB_Skip (B); *Val = SignExtendChar (TgtTranslateChar (ParseChar (B))); if (SB_Peek (B) != '\'') { Error ("'\'' expected"); return 0; } else { /* Skip the quote */ SB_Skip (B); return 1; } } /* Check for a sign. A sign must be followed by a digit, otherwise it's ** not a number */ Sign = 1; switch (SB_Peek (B)) { case '-': Sign = -1; /* FALLTHROUGH */ case '+': if (!IsDigit (SB_LookAt (B, SB_GetIndex (B) + 1))) { return 0; } SB_Skip (B); break; } /* We must have a digit now, otherwise its not a number */ C = SB_Peek (B); if (!IsDigit (C)) { return 0; } /* Determine the base */ if (C == '0') { /* Hex or octal */ SB_Skip (B); if (tolower (SB_Peek (B)) == 'x') { SB_Skip (B); Base = 16; if (!IsXDigit (SB_Peek (B))) { Error ("Invalid hexadecimal number"); return 0; } } else { Base = 8; } } else { Base = 10; } /* Read the number */ while (IsXDigit (C = SB_Peek (B)) && (DigitVal = HexVal (C)) < Base) { *Val = (*Val * Base) + DigitVal; SB_Skip (B); } /* Allow optional 'U' and 'L' modifiers */ C = SB_Peek (B); if (C == 'u' || C == 'U') { SB_Skip (B); C = SB_Peek (B); if (C == 'l' || C == 'L') { SB_Skip (B); } } else if (C == 'l' || C == 'L') { SB_Skip (B); C = SB_Peek (B); if (C == 'u' || C == 'U') { SB_Skip (B); } } /* Success, value read is in Val */ *Val *= Sign; return 1; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/scanstrbuf.h���������������������������������������������������������������������0000664�0000000�0000000�00000007561�13473601511�0016070�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* scanstrbuf.h */ /* */ /* Small scanner for input from a StrBuf */ /* */ /* */ /* */ /* (C) 2002-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef SCANSTRBUF_H #define SCANSTRBUF_H /* common */ #include "strbuf.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void SB_SkipWhite (StrBuf* B); /* Skip whitespace in the string buffer */ int SB_GetSym (StrBuf* B, StrBuf* Ident, const char* SpecialChars); /* Get a symbol from the string buffer. If SpecialChars is not NULL, it ** points to a string that contains characters allowed within the string in ** addition to letters, digits and the underline. Note: The identifier must ** still begin with a letter. ** Returns 1 if a symbol was found and 0 otherwise but doesn't output any ** errors. */ int SB_GetString (StrBuf* B, StrBuf* S); /* Get a string from the string buffer. Returns 1 if a string was found and 0 ** otherwise. Errors are only output in case of invalid strings (missing end ** of string). */ int SB_GetNumber (StrBuf* B, long* Val); /* Get a number from the string buffer. Accepted formats are decimal, octal, ** hex and character constants. Numeric constants may be preceeded by a ** minus or plus sign. The function returns 1 if a number was found and ** zero otherwise. Errors are only output for invalid numbers. */ /* End of scanstrbuf.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/segments.c�����������������������������������������������������������������������0000664�0000000�0000000�00000020654�13473601511�0015534�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* segments.c */ /* */ /* Lightweight segment management stuff */ /* */ /* */ /* */ /* (C) 2001-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdarg.h> #include <string.h> /* common */ #include "chartype.h" #include "check.h" #include "coll.h" #include "scanner.h" #include "segnames.h" #include "strstack.h" #include "xmalloc.h" /* cc65 */ #include "codeent.h" #include "codeseg.h" #include "dataseg.h" #include "error.h" #include "textseg.h" #include "segments.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Pointer to the current segment list. Output goes here. */ Segments* CS = 0; /* Pointer to the global segment list */ Segments* GS = 0; /* Actual names for the segments */ static StrStack SegmentNames[SEG_COUNT]; /* We're using a collection for the stack instead of a linked list. Since ** functions may not be nested (at least in the current implementation), the ** maximum stack depth is 2, so there is not really a need for a better ** implementation. */ static Collection SegmentStack = STATIC_COLLECTION_INITIALIZER; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void InitSegNames (void) /* Initialize the segment names */ { SS_Push (&SegmentNames[SEG_BSS], SEGNAME_BSS); SS_Push (&SegmentNames[SEG_CODE], SEGNAME_CODE); SS_Push (&SegmentNames[SEG_DATA], SEGNAME_DATA); SS_Push (&SegmentNames[SEG_RODATA], SEGNAME_RODATA); } void SetSegName (segment_t Seg, const char* Name) /* Set a new name for a segment */ { SS_Set (&SegmentNames[Seg], Name); } void PushSegName (segment_t Seg, const char* Name) /* Push the current segment name and set a new name for a segment */ { if (SS_IsFull (&SegmentNames[Seg])) { Error ("Segment name stack overflow"); } else { SS_Push (&SegmentNames[Seg], Name); } } void PopSegName (segment_t Seg) /* Restore a segment name from the segment name stack */ { if (SS_GetCount (&SegmentNames[Seg]) < 2) { Error ("Segment name stack is empty"); } else { SS_Drop (&SegmentNames[Seg]); } } const char* GetSegName (segment_t Seg) /* Get the name of the given segment */ { return SS_Get (&SegmentNames[Seg]); } static Segments* NewSegments (SymEntry* Func) /* Initialize a Segments structure (set all fields to NULL) */ { /* Allocate memory */ Segments* S = xmalloc (sizeof (Segments)); /* Initialize the fields */ S->Text = NewTextSeg (Func); S->Code = NewCodeSeg (GetSegName (SEG_CODE), Func); S->Data = NewDataSeg (GetSegName (SEG_DATA), Func); S->ROData = NewDataSeg (GetSegName (SEG_RODATA), Func); S->BSS = NewDataSeg (GetSegName (SEG_BSS), Func); S->CurDSeg = SEG_DATA; /* Return the new struct */ return S; } Segments* PushSegments (SymEntry* Func) /* Make the new segment list current but remember the old one */ { /* Push the current pointer onto the stack */ CollAppend (&SegmentStack, CS); /* Create a new Segments structure */ CS = NewSegments (Func); /* Return the new struct */ return CS; } void PopSegments (void) /* Pop the old segment list (make it current) */ { /* Must have something on the stack */ PRECONDITION (CollCount (&SegmentStack) > 0); /* Pop the last segment and set it as current */ CS = CollPop (&SegmentStack); } void CreateGlobalSegments (void) /* Create the global segments and remember them in GS */ { GS = PushSegments (0); } void UseDataSeg (segment_t DSeg) /* For the current segment list, use the data segment DSeg */ { /* Check the input */ PRECONDITION (CS && DSeg != SEG_CODE); /* Set the new segment to use */ CS->CurDSeg = DSeg; } struct DataSeg* GetDataSeg (void) /* Return the current data segment */ { PRECONDITION (CS != 0); switch (CS->CurDSeg) { case SEG_BSS: return CS->BSS; case SEG_DATA: return CS->Data; case SEG_RODATA: return CS->ROData; default: FAIL ("Invalid data segment"); return 0; } } void AddTextLine (const char* Format, ...) /* Add a line of code to the current text segment */ { va_list ap; va_start (ap, Format); CHECK (CS != 0); TS_AddVLine (CS->Text, Format, ap); va_end (ap); } void AddCodeLine (const char* Format, ...) /* Add a line of code to the current code segment */ { va_list ap; va_start (ap, Format); CHECK (CS != 0); CS_AddVLine (CS->Code, CurTok.LI, Format, ap); va_end (ap); } void AddCode (opc_t OPC, am_t AM, const char* Arg, struct CodeLabel* JumpTo) /* Add a code entry to the current code segment */ { CHECK (CS != 0); CS_AddEntry (CS->Code, NewCodeEntry (OPC, AM, Arg, JumpTo, CurTok.LI)); } void AddDataLine (const char* Format, ...) /* Add a line of data to the current data segment */ { va_list ap; va_start (ap, Format); CHECK (CS != 0); DS_AddVLine (GetDataSeg(), Format, ap); va_end (ap); } int HaveGlobalCode (void) /* Return true if the global code segment contains entries (which is an error) */ { return (CS_GetEntryCount (GS->Code) > 0); } void RemoveGlobalCode (void) /* Remove all code from the global code segment. Used for error recovery. */ { CS_DelEntries (GS->Code, 0, CS_GetEntryCount (GS->Code)); } void OutputSegments (const Segments* S) /* Output the given segments to the output file */ { /* Output the function prologue if the segments came from a function */ CS_OutputPrologue (S->Code); /* Output the text segment */ TS_Output (S->Text); /* Output the three data segments */ DS_Output (S->Data); DS_Output (S->ROData); DS_Output (S->BSS); /* Output the code segment */ CS_Output (S->Code); /* Output the code segment epiloque */ CS_OutputEpilogue (S->Code); } ������������������������������������������������������������������������������������cc65-2.18/src/cc65/segments.h�����������������������������������������������������������������������0000664�0000000�0000000�00000013663�13473601511�0015543�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* segments.h */ /* */ /* Segment management */ /* */ /* */ /* */ /* (C) 2000-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef SEGMENTS_H #define SEGMENTS_H #include <stdio.h> /* common */ #include "attrib.h" /* cc65 */ #include "opcodes.h" /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ struct CodeEntry; struct CodeLabel; struct CodeSeg; struct DataSeg; struct TextSeg; struct SymEntry; /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Segment types */ typedef enum segment_t { SEG_CODE, SEG_RODATA, SEG_DATA, SEG_BSS, SEG_COUNT } segment_t; /* A list of all segments used when generating code */ typedef struct Segments Segments; struct Segments { struct TextSeg* Text; /* Text segment */ struct CodeSeg* Code; /* Code segment */ struct DataSeg* Data; /* Data segment */ struct DataSeg* ROData; /* Readonly data segment */ struct DataSeg* BSS; /* Segment for uninitialized data */ segment_t CurDSeg; /* Current data segment */ }; /* Pointer to the current segment list. Output goes here. */ extern Segments* CS; /* Pointer to the global segment list */ extern Segments* GS; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void InitSegNames (void); /* Initialize the segment names */ void SetSegName (segment_t Seg, const char* Name); /* Set a new name for a segment */ void PushSegName (segment_t Seg, const char* Name); /* Push the current segment name and set a new name for a segment */ void PopSegName (segment_t Seg); /* Restore a segment name from the segment name stack */ const char* GetSegName (segment_t Seg); /* Get the name of the given segment */ Segments* PushSegments (struct SymEntry* Func); /* Make the new segment list current but remember the old one */ void PopSegments (void); /* Pop the old segment list (make it current) */ void CreateGlobalSegments (void); /* Create the global segments and remember them in GS */ void UseDataSeg (segment_t DSeg); /* For the current segment list, use the data segment DSeg */ struct DataSeg* GetDataSeg (void); /* Return the current data segment */ void AddTextLine (const char* Format, ...) attribute ((format (printf, 1, 2))); /* Add a line to the current text segment */ void AddCodeLine (const char* Format, ...) attribute ((format (printf, 1, 2))); /* Add a line of code to the current code segment */ void AddCode (opc_t OPC, am_t AM, const char* Arg, struct CodeLabel* JumpTo); /* Add a code entry to the current code segment */ void AddDataLine (const char* Format, ...) attribute ((format (printf, 1, 2))); /* Add a line of data to the current data segment */ int HaveGlobalCode (void); /* Return true if the global code segment contains entries (which is an error) */ void RemoveGlobalCode (void); /* Remove all code from the global code segment. Used for error recovery. */ void OutputSegments (const Segments* S); /* Output the given segments to the output file */ /* End of segments.h */ #endif �����������������������������������������������������������������������������cc65-2.18/src/cc65/shiftexpr.c����������������������������������������������������������������������0000664�0000000�0000000�00000021473�13473601511�0015723�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* shiftexpr.c */ /* */ /* Parse the << and >> operators */ /* */ /* */ /* */ /* (C) 2004-2006 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* cc65 */ #include "asmcode.h" #include "codegen.h" #include "datatype.h" #include "error.h" #include "expr.h" #include "exprdesc.h" #include "loadexpr.h" #include "scanner.h" #include "shiftexpr.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /*****************************************************************************/ /* Code */ /*****************************************************************************/ void ShiftExpr (struct ExprDesc* Expr) /* Parse the << and >> operators. */ { ExprDesc Expr2; CodeMark Mark1; CodeMark Mark2; token_t Tok; /* The operator token */ Type* EffType; /* Effective lhs type */ Type* ResultType; /* Type of the result */ unsigned ExprBits; /* Bits of the lhs operand */ unsigned GenFlags; /* Generator flags */ unsigned ltype; int rconst; /* Operand is a constant */ /* Evaluate the lhs */ ExprWithCheck (hie8, Expr); while (CurTok.Tok == TOK_SHL || CurTok.Tok == TOK_SHR) { /* All operators that call this function expect an int on the lhs */ if (!IsClassInt (Expr->Type)) { Error ("Integer expression expected"); ED_MakeConstAbsInt (Expr, 1); } /* Remember the operator token, then skip it */ Tok = CurTok.Tok; NextToken (); /* Get the type of the result */ ResultType = EffType = IntPromotion (Expr->Type); /* Prepare the code generator flags */ GenFlags = TypeOf (ResultType); /* Calculate the number of bits the lhs operand has */ ExprBits = SizeOf (ResultType) * 8; /* Get the lhs on stack */ GetCodePos (&Mark1); ltype = TypeOf (Expr->Type); if (ED_IsConstAbs (Expr)) { /* Constant value */ GetCodePos (&Mark2); g_push (ltype | CF_CONST, Expr->IVal); } else { /* Value not constant */ LoadExpr (CF_NONE, Expr); GetCodePos (&Mark2); g_push (ltype, 0); } /* Get the right hand side */ ExprWithCheck (hie8, &Expr2); /* Check the type of the rhs */ if (!IsClassInt (Expr2.Type)) { Error ("Integer expression expected"); ED_MakeConstAbsInt (&Expr2, 1); } /* Check for a constant right side expression */ rconst = ED_IsConstAbs (&Expr2); if (!rconst) { /* Not constant, load into the primary */ LoadExpr (CF_NONE, &Expr2); } else { /* The rhs is a constant numeric value. */ GenFlags |= CF_CONST; /* Remove the code that pushes the rhs onto the stack. */ RemoveCode (&Mark2); /* If the shift count is greater or equal than the bit count of ** the operand, the behaviour is undefined according to the ** standard. */ if (Expr2.IVal < 0 || Expr2.IVal >= (long) ExprBits) { Warning ("Shift count too large for operand type"); Expr2.IVal &= ExprBits - 1; } /* If the shift count is zero, nothing happens */ if (Expr2.IVal == 0) { /* Result is already in Expr, remove the generated code */ RemoveCode (&Mark1); /* Done */ goto Next; } /* If the left hand side is a constant, the result is constant */ if (ED_IsConstAbs (Expr)) { /* Evaluate the result */ switch (Tok) { case TOK_SHL: Expr->IVal <<= Expr2.IVal; break; case TOK_SHR: Expr->IVal >>= Expr2.IVal; break; default: /* Shutup gcc */ break; } /* Both operands are constant, remove the generated code */ RemoveCode (&Mark1); /* Done */ goto Next; } /* If we're shifting an integer or unsigned to the right, the ** lhs has a const address, and the shift count is larger than 8, ** we can load just the high byte as a char with the correct ** signedness, and reduce the shift count by 8. If the remaining ** shift count is zero, we're done. */ if (Tok == TOK_SHR && IsTypeInt (Expr->Type) && ED_IsLVal (Expr) && (ED_IsLocConst (Expr) || ED_IsLocStack (Expr)) && Expr2.IVal >= 8) { Type* OldType; /* Increase the address by one and decrease the shift count */ ++Expr->IVal; Expr2.IVal -= 8; /* Replace the type of the expression temporarily by the ** corresponding char type. */ OldType = Expr->Type; if (IsSignUnsigned (Expr->Type)) { Expr->Type = type_uchar; } else { Expr->Type = type_schar; } /* Remove the generated load code */ RemoveCode (&Mark1); /* Generate again code for the load, this time with the new type */ LoadExpr (CF_NONE, Expr); /* Reset the type */ Expr->Type = OldType; /* If the shift count is now zero, we're done */ if (Expr2.IVal == 0) { /* Be sure to mark the value as in the primary */ goto MakeRVal; } } } /* Generate code */ switch (Tok) { case TOK_SHL: g_asl (GenFlags, Expr2.IVal); break; case TOK_SHR: g_asr (GenFlags, Expr2.IVal); break; default: break; } MakeRVal: /* We have a rvalue in the primary now */ ED_MakeRValExpr (Expr); Next: /* Set the type of the result */ Expr->Type = ResultType; } } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/shiftexpr.h����������������������������������������������������������������������0000664�0000000�0000000�00000006315�13473601511�0015726�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* shiftexpr.h */ /* */ /* Parse the << and >> operators */ /* */ /* */ /* */ /* (C) 2004 Ullrich von Bassewitz */ /* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef SHIFTEXPR_H #define SHIFTEXPR_H /* common */ #include "intstack.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Forward */ struct ExprDesc; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void ShiftExpr (struct ExprDesc* Expr); /* Parse the << and >> operators. */ /* End of shiftexpr.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/stackptr.c�����������������������������������������������������������������������0000664�0000000�0000000�00000006526�13473601511�0015544�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* stackptr.c */ /* */ /* Manage the parameter stack pointer */ /* */ /* */ /* */ /* (C) 2004-2006 Ullrich von Bassewitz */ /* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* cc65 */ #include "stackptr.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Compiler relative stackpointer */ int StackPtr = 0; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void SP_Push (const Type* T) /* Adjust the stackpointer for a push of an argument of the given type */ { StackPtr -= SizeOf (T); } void SP_Pop (const Type* T) /* Adjust the stackpointer for a pop of an argument of the given type */ { StackPtr += SizeOf (T); } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/stackptr.h�����������������������������������������������������������������������0000664�0000000�0000000�00000006545�13473601511�0015552�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* stackptr.h */ /* */ /* Manage the parameter stack pointer */ /* */ /* */ /* */ /* (C) 2004-2006 Ullrich von Bassewitz */ /* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef STACKPTR_H #define STACKPTR_H /* cc65 */ #include "datatype.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Compiler relative stackpointer */ extern int StackPtr; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void SP_Push (const Type* T); /* Adjust the stackpointer for a push of an argument of the given type */ void SP_Pop (const Type* T); /* Adjust the stackpointer for a pop of an argument of the given type */ /* End of stackptr.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/standard.c�����������������������������������������������������������������������0000664�0000000�0000000�00000007316�13473601511�0015507�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* standard.c */ /* */ /* Language standard definitions */ /* */ /* */ /* */ /* (C) 2004 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* cc65 */ #include "standard.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Current language standard, will be set to STD_DEFAULT on startup */ IntStack Standard = INTSTACK(STD_UNKNOWN); /* Table mapping names to standards, sorted by standard. */ static const char* const StdNames[STD_COUNT] = { "c89", "c99", "cc65" }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ standard_t FindStandard (const char* Name) /* Find a standard by name. Returns one of the constants defined above. ** STD_UNKNOWN is returned if Name doesn't match a standard. */ { unsigned I; /* Check for a standard string */ for (I = 0; I < STD_COUNT; ++I) { if (strcmp (StdNames [I], Name) == 0) { return (standard_t)I; } } /* Not found */ return STD_UNKNOWN; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/standard.h�����������������������������������������������������������������������0000664�0000000�0000000�00000007242�13473601511�0015512�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* standard.h */ /* */ /* Language standard definitions */ /* */ /* */ /* */ /* (C) 2004 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef STANDARD_H #define STANDARD_H /* common */ #include "intstack.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Supported standards. */ typedef enum standard_t { STD_UNKNOWN = -1, STD_C89, STD_C99, STD_CC65, /* Special constants */ STD_COUNT, /* Number of supported standards */ STD_DEFAULT = STD_CC65 /* Default standard if none given */ } standard_t; /* Current language standard */ extern IntStack Standard; /* Language standard */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ standard_t FindStandard (const char* Name); /* Find a standard by name. Returns one of the constants defined above. ** STD_UNKNOWN is returned if Name doesn't match a standard. */ /* End of standard.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/stdfunc.c������������������������������������������������������������������������0000664�0000000�0000000�00000145110�13473601511�0015350�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* stdfunc.c */ /* */ /* Handle inlining of known functions for the cc65 compiler */ /* */ /* */ /* */ /* (C) 1998-2010 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdlib.h> #include <string.h> /* common */ #include "attrib.h" #include "check.h" /* cc65 */ #include "asmcode.h" #include "asmlabel.h" #include "codegen.h" #include "error.h" #include "funcdesc.h" #include "global.h" #include "litpool.h" #include "loadexpr.h" #include "scanner.h" #include "stackptr.h" #include "stdfunc.h" #include "stdnames.h" #include "typeconv.h" /*****************************************************************************/ /* Function forwards */ /*****************************************************************************/ static void StdFunc_memcpy (FuncDesc*, ExprDesc*); static void StdFunc_memset (FuncDesc*, ExprDesc*); static void StdFunc_strcmp (FuncDesc*, ExprDesc*); static void StdFunc_strcpy (FuncDesc*, ExprDesc*); static void StdFunc_strlen (FuncDesc*, ExprDesc*); /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Table with all known functions and their handlers. Must be sorted ** alphabetically! */ static struct StdFuncDesc { const char* Name; void (*Handler) (FuncDesc*, ExprDesc*); } StdFuncs[] = { { "memcpy", StdFunc_memcpy }, { "memset", StdFunc_memset }, { "strcmp", StdFunc_strcmp }, { "strcpy", StdFunc_strcpy }, { "strlen", StdFunc_strlen }, }; #define FUNC_COUNT (sizeof (StdFuncs) / sizeof (StdFuncs[0])) typedef struct ArgDesc ArgDesc; struct ArgDesc { const Type* ArgType; /* Required argument type */ ExprDesc Expr; /* Argument expression */ const Type* Type; /* The original type before conversion */ CodeMark Load; /* Start of argument load code */ CodeMark Push; /* Start of argument push code */ CodeMark End; /* End of the code for calculation+push */ unsigned Flags; /* Code generation flags */ }; /*****************************************************************************/ /* Helper functions */ /*****************************************************************************/ static int CmpFunc (const void* Key, const void* Elem) /* Compare function for bsearch */ { return strcmp ((const char*) Key, ((const struct StdFuncDesc*) Elem)->Name); } static long ArrayElementCount (const ArgDesc* Arg) /* Check if the type of the given argument is an array. If so, and if the ** element count is known, return it. In all other cases, return UNSPECIFIED. */ { long Count; if (IsTypeArray (Arg->Type)) { Count = GetElementCount (Arg->Type); if (Count == FLEXIBLE) { /* Treat as unknown */ Count = UNSPECIFIED; } } else { Count = UNSPECIFIED; } return Count; } static void ParseArg (ArgDesc* Arg, Type* Type) /* Parse one argument but do not push it onto the stack. Make all fields in ** Arg valid. */ { /* We have a prototype, so chars may be pushed as chars */ Arg->Flags = CF_FORCECHAR; /* Remember the required argument type */ Arg->ArgType = Type; /* Read the expression we're going to pass to the function */ MarkedExprWithCheck (hie1, &Arg->Expr); /* Remember the actual argument type */ Arg->Type = Arg->Expr.Type; /* Convert this expression to the expected type */ TypeConversion (&Arg->Expr, Type); /* Remember the following code position */ GetCodePos (&Arg->Load); /* If the value is a constant, set the flag, otherwise load it into the ** primary register. */ if (ED_IsConstAbsInt (&Arg->Expr) && ED_CodeRangeIsEmpty (&Arg->Expr)) { /* Remember that we have a constant value */ Arg->Flags |= CF_CONST; } else { /* Load into the primary */ LoadExpr (CF_NONE, &Arg->Expr); } /* Remember the following code position */ GetCodePos (&Arg->Push); GetCodePos (&Arg->End); /* Use the type of the argument for the push */ Arg->Flags |= TypeOf (Arg->Expr.Type); } void AddCmpCodeIfSizeNot256 (const char* Code, long Size) /* Add a line of Assembly code that compares an index register ** only if it isn't comparing to #<256. (If the next line ** is "bne", then this will avoid a redundant line.) */ { if (Size != 256) { AddCodeLine (Code, (unsigned int)Size); } } /*****************************************************************************/ /* memcpy */ /*****************************************************************************/ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr) /* Handle the memcpy function */ { /* Argument types: (void*, const void*, size_t) */ static Type Arg1Type[] = { TYPE(T_PTR), TYPE(T_VOID), TYPE(T_END) }; static Type Arg2Type[] = { TYPE(T_PTR), TYPE(T_VOID|T_QUAL_CONST), TYPE(T_END) }; static Type Arg3Type[] = { TYPE(T_SIZE_T), TYPE(T_END) }; ArgDesc Arg1, Arg2, Arg3; unsigned ParamSize = 0; unsigned Label; int Offs; /* Argument #1 */ ParseArg (&Arg1, Arg1Type); g_push (Arg1.Flags, Arg1.Expr.IVal); GetCodePos (&Arg1.End); ParamSize += SizeOf (Arg1Type); ConsumeComma (); /* Argument #2 */ ParseArg (&Arg2, Arg2Type); g_push (Arg2.Flags, Arg2.Expr.IVal); GetCodePos (&Arg2.End); ParamSize += SizeOf (Arg2Type); ConsumeComma (); /* Argument #3. Since memcpy is a fastcall function, we must load the ** arg into the primary if it is not already there. This parameter is ** also ignored for the calculation of the parameter size, since it is ** not passed via the stack. */ ParseArg (&Arg3, Arg3Type); if (Arg3.Flags & CF_CONST) { LoadExpr (CF_NONE, &Arg3.Expr); } /* Emit the actual function call. This will also cleanup the stack. */ g_call (CF_FIXARGC, Func_memcpy, ParamSize); if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal == 0) { /* memcpy has been called with a count argument of zero */ Warning ("Call to memcpy has no effect"); /* Remove all of the generated code but the load of the first ** argument, which is what memcpy returns. */ RemoveCode (&Arg1.Push); /* Set the function result to the first argument */ *Expr = Arg1.Expr; /* Bail out, no need for further improvements */ goto ExitPoint; } if (IS_Get (&InlineStdFuncs)) { /* We've generated the complete code for the function now and know the ** types of all parameters. Check for situations where better code can ** be generated. If such a situation is detected, throw away the ** generated, and emit better code. */ if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 && ((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) || (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) && ((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) || (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)))) { int Reg1 = ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr); int Reg2 = ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr); /* Drop the generated code */ RemoveCode (&Arg1.Expr.Start); /* We need a label */ Label = GetLocalLabel (); /* Generate memcpy code */ if (Arg3.Expr.IVal <= 129) { AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal-1)); g_defcodelabel (Label); if (Reg2) { AddCodeLine ("lda (%s),y", ED_GetLabelName (&Arg2.Expr, 0)); } else { AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg2.Expr, 0)); } if (Reg1) { AddCodeLine ("sta (%s),y", ED_GetLabelName (&Arg1.Expr, 0)); } else { AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0)); } AddCodeLine ("dey"); AddCodeLine ("bpl %s", LocalLabelName (Label)); } else { AddCodeLine ("ldy #$00"); g_defcodelabel (Label); if (Reg2) { AddCodeLine ("lda (%s),y", ED_GetLabelName (&Arg2.Expr, 0)); } else { AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg2.Expr, 0)); } if (Reg1) { AddCodeLine ("sta (%s),y", ED_GetLabelName (&Arg1.Expr, 0)); } else { AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0)); } AddCodeLine ("iny"); AddCmpCodeIfSizeNot256 ("cpy #$%02X", Arg3.Expr.IVal); AddCodeLine ("bne %s", LocalLabelName (Label)); } /* memcpy returns the address, so the result is actually identical ** to the first argument. */ *Expr = Arg1.Expr; /* Bail out, no need for further processing */ goto ExitPoint; } if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 && ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr) && ED_IsRVal (&Arg1.Expr) && ED_IsLocStack (&Arg1.Expr) && (Arg1.Expr.IVal - StackPtr) + Arg3.Expr.IVal < 256) { /* It is possible to just use one index register even if the stack ** offset is not zero, by adjusting the offset to the constant ** address accordingly. But we cannot do this if the data in ** question is in the register space or at an absolute address less ** than 256. Register space is zero page, which means that the ** address calculation could overflow in the linker. */ int AllowOneIndex = !ED_IsLocRegister (&Arg2.Expr) && !(ED_IsLocAbs (&Arg2.Expr) && Arg2.Expr.IVal < 256); /* Calculate the real stack offset */ Offs = ED_GetStackOffs (&Arg1.Expr, 0); /* Drop the generated code */ RemoveCode (&Arg1.Expr.Start); /* We need a label */ Label = GetLocalLabel (); /* Generate memcpy code */ if (Arg3.Expr.IVal <= 129 && !AllowOneIndex) { if (Offs == 0) { AddCodeLine ("ldy #$%02X", (unsigned char) (Offs + Arg3.Expr.IVal - 1)); g_defcodelabel (Label); AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg2.Expr, -Offs)); AddCodeLine ("sta (sp),y"); AddCodeLine ("dey"); AddCodeLine ("bpl %s", LocalLabelName (Label)); } else { AddCodeLine ("ldx #$%02X", (unsigned char) (Arg3.Expr.IVal-1)); AddCodeLine ("ldy #$%02X", (unsigned char) (Offs + Arg3.Expr.IVal - 1)); g_defcodelabel (Label); AddCodeLine ("lda %s,x", ED_GetLabelName (&Arg2.Expr, 0)); AddCodeLine ("sta (sp),y"); AddCodeLine ("dey"); AddCodeLine ("dex"); AddCodeLine ("bpl %s", LocalLabelName (Label)); } } else { if (Offs == 0 || AllowOneIndex) { AddCodeLine ("ldy #$%02X", (unsigned char) Offs); g_defcodelabel (Label); AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg2.Expr, -Offs)); AddCodeLine ("sta (sp),y"); AddCodeLine ("iny"); AddCmpCodeIfSizeNot256 ("cpy #$%02X", Offs + Arg3.Expr.IVal); AddCodeLine ("bne %s", LocalLabelName (Label)); } else { AddCodeLine ("ldx #$00"); AddCodeLine ("ldy #$%02X", (unsigned char) Offs); g_defcodelabel (Label); AddCodeLine ("lda %s,x", ED_GetLabelName (&Arg2.Expr, 0)); AddCodeLine ("sta (sp),y"); AddCodeLine ("iny"); AddCodeLine ("inx"); AddCmpCodeIfSizeNot256 ("cpx #$%02X", Arg3.Expr.IVal); AddCodeLine ("bne %s", LocalLabelName (Label)); } } /* memcpy returns the address, so the result is actually identical ** to the first argument. */ *Expr = Arg1.Expr; /* Bail out, no need for further processing */ goto ExitPoint; } if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 && ED_IsRVal (&Arg2.Expr) && ED_IsLocStack (&Arg2.Expr) && (Arg2.Expr.IVal - StackPtr) + Arg3.Expr.IVal < 256 && ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) { /* It is possible to just use one index register even if the stack ** offset is not zero, by adjusting the offset to the constant ** address accordingly. But we cannot do this if the data in ** question is in the register space or at an absolute address less ** than 256. Register space is zero page, which means that the ** address calculation could overflow in the linker. */ int AllowOneIndex = !ED_IsLocRegister (&Arg1.Expr) && !(ED_IsLocAbs (&Arg1.Expr) && Arg1.Expr.IVal < 256); /* Calculate the real stack offset */ Offs = ED_GetStackOffs (&Arg2.Expr, 0); /* Drop the generated code */ RemoveCode (&Arg1.Expr.Start); /* We need a label */ Label = GetLocalLabel (); /* Generate memcpy code */ if (Arg3.Expr.IVal <= 129 && !AllowOneIndex) { if (Offs == 0) { AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal - 1)); g_defcodelabel (Label); AddCodeLine ("lda (sp),y"); AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0)); AddCodeLine ("dey"); AddCodeLine ("bpl %s", LocalLabelName (Label)); } else { AddCodeLine ("ldx #$%02X", (unsigned char) (Arg3.Expr.IVal-1)); AddCodeLine ("ldy #$%02X", (unsigned char) (Offs + Arg3.Expr.IVal - 1)); g_defcodelabel (Label); AddCodeLine ("lda (sp),y"); AddCodeLine ("sta %s,x", ED_GetLabelName (&Arg1.Expr, 0)); AddCodeLine ("dey"); AddCodeLine ("dex"); AddCodeLine ("bpl %s", LocalLabelName (Label)); } } else { if (Offs == 0 || AllowOneIndex) { AddCodeLine ("ldy #$%02X", (unsigned char) Offs); g_defcodelabel (Label); AddCodeLine ("lda (sp),y"); AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, -Offs)); AddCodeLine ("iny"); AddCmpCodeIfSizeNot256 ("cpy #$%02X", Offs + Arg3.Expr.IVal); AddCodeLine ("bne %s", LocalLabelName (Label)); } else { AddCodeLine ("ldx #$00"); AddCodeLine ("ldy #$%02X", (unsigned char) Offs); g_defcodelabel (Label); AddCodeLine ("lda (sp),y"); AddCodeLine ("sta %s,x", ED_GetLabelName (&Arg1.Expr, 0)); AddCodeLine ("iny"); AddCodeLine ("inx"); AddCmpCodeIfSizeNot256 ("cpx #$%02X", Arg3.Expr.IVal); AddCodeLine ("bne %s", LocalLabelName (Label)); } } /* memcpy returns the address, so the result is actually identical ** to the first argument. */ *Expr = Arg1.Expr; /* Bail out, no need for further processing */ goto ExitPoint; } if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 && ED_IsRVal (&Arg2.Expr) && ED_IsLocStack (&Arg2.Expr) && (Offs = ED_GetStackOffs (&Arg2.Expr, 0)) == 0) { /* Drop the generated code but leave the load of the first argument*/ RemoveCode (&Arg1.Push); /* We need a label */ Label = GetLocalLabel (); /* Generate memcpy code */ AddCodeLine ("sta ptr1"); AddCodeLine ("stx ptr1+1"); if (Arg3.Expr.IVal <= 129) { AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal - 1)); g_defcodelabel (Label); AddCodeLine ("lda (sp),y"); AddCodeLine ("sta (ptr1),y"); AddCodeLine ("dey"); AddCodeLine ("bpl %s", LocalLabelName (Label)); } else { AddCodeLine ("ldy #$00"); g_defcodelabel (Label); AddCodeLine ("lda (sp),y"); AddCodeLine ("sta (ptr1),y"); AddCodeLine ("iny"); AddCmpCodeIfSizeNot256 ("cpy #$%02X", Arg3.Expr.IVal); AddCodeLine ("bne %s", LocalLabelName (Label)); } /* Reload result - X hasn't changed by the code above */ AddCodeLine ("lda ptr1"); /* The function result is an rvalue in the primary register */ ED_MakeRValExpr (Expr); Expr->Type = GetFuncReturn (Expr->Type); /* Bail out, no need for further processing */ goto ExitPoint; } } /* The function result is an rvalue in the primary register */ ED_MakeRValExpr (Expr); Expr->Type = GetFuncReturn (Expr->Type); ExitPoint: /* We expect the closing brace */ ConsumeRParen (); } /*****************************************************************************/ /* memset */ /*****************************************************************************/ static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr) /* Handle the memset function */ { /* Argument types: (void*, int, size_t) */ static Type Arg1Type[] = { TYPE(T_PTR), TYPE(T_VOID), TYPE(T_END) }; static Type Arg2Type[] = { TYPE(T_INT), TYPE(T_END) }; static Type Arg3Type[] = { TYPE(T_SIZE_T), TYPE(T_END) }; ArgDesc Arg1, Arg2, Arg3; int MemSet = 1; /* Use real memset if true */ unsigned ParamSize = 0; unsigned Label; /* Argument #1 */ ParseArg (&Arg1, Arg1Type); g_push (Arg1.Flags, Arg1.Expr.IVal); GetCodePos (&Arg1.End); ParamSize += SizeOf (Arg1Type); ConsumeComma (); /* Argument #2. This argument is special in that we will call another ** function if it is a constant zero. */ ParseArg (&Arg2, Arg2Type); if ((Arg2.Flags & CF_CONST) != 0 && Arg2.Expr.IVal == 0) { /* Don't call memset, call bzero instead */ MemSet = 0; } else { /* Push the argument */ g_push (Arg2.Flags, Arg2.Expr.IVal); GetCodePos (&Arg2.End); ParamSize += SizeOf (Arg2Type); } ConsumeComma (); /* Argument #3. Since memset is a fastcall function, we must load the ** arg into the primary if it is not already there. This parameter is ** also ignored for the calculation of the parameter size, since it is ** not passed via the stack. */ ParseArg (&Arg3, Arg3Type); if (Arg3.Flags & CF_CONST) { LoadExpr (CF_NONE, &Arg3.Expr); } /* Emit the actual function call. This will also cleanup the stack. */ g_call (CF_FIXARGC, MemSet? Func_memset : Func__bzero, ParamSize); if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal == 0) { /* memset has been called with a count argument of zero */ Warning ("Call to memset has no effect"); /* Remove all of the generated code but the load of the first ** argument, which is what memset returns. */ RemoveCode (&Arg1.Push); /* Set the function result to the first argument */ *Expr = Arg1.Expr; /* Bail out, no need for further improvements */ goto ExitPoint; } if (IS_Get (&InlineStdFuncs)) { /* We've generated the complete code for the function now and know the ** types of all parameters. Check for situations where better code can ** be generated. If such a situation is detected, throw away the ** generated, and emit better code. ** Note: Lots of improvements would be possible here, but I will ** concentrate on the most common case: memset with arguments 2 and 3 ** being constant numerical values. Some checks have shown that this ** covers nearly 90% of all memset calls. */ if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 && ED_IsConstAbsInt (&Arg2.Expr) && ((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) || (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)))) { int Reg = ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr); /* Drop the generated code */ RemoveCode (&Arg1.Expr.Start); /* We need a label */ Label = GetLocalLabel (); /* Generate memset code */ if (Arg3.Expr.IVal <= 129) { AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal-1)); AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal); g_defcodelabel (Label); if (Reg) { AddCodeLine ("sta (%s),y", ED_GetLabelName (&Arg1.Expr, 0)); } else { AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0)); } AddCodeLine ("dey"); AddCodeLine ("bpl %s", LocalLabelName (Label)); } else { AddCodeLine ("ldy #$00"); AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal); g_defcodelabel (Label); if (Reg) { AddCodeLine ("sta (%s),y", ED_GetLabelName (&Arg1.Expr, 0)); } else { AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0)); } AddCodeLine ("iny"); AddCmpCodeIfSizeNot256 ("cpy #$%02X", Arg3.Expr.IVal); AddCodeLine ("bne %s", LocalLabelName (Label)); } /* memset returns the address, so the result is actually identical ** to the first argument. */ *Expr = Arg1.Expr; /* Bail out, no need for further processing */ goto ExitPoint; } if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 && ED_IsConstAbsInt (&Arg2.Expr) && ED_IsRVal (&Arg1.Expr) && ED_IsLocStack (&Arg1.Expr) && (Arg1.Expr.IVal - StackPtr) + Arg3.Expr.IVal < 256) { /* Calculate the real stack offset */ int Offs = ED_GetStackOffs (&Arg1.Expr, 0); /* Drop the generated code */ RemoveCode (&Arg1.Expr.Start); /* We need a label */ Label = GetLocalLabel (); /* Generate memset code */ AddCodeLine ("ldy #$%02X", (unsigned char) Offs); AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal); g_defcodelabel (Label); AddCodeLine ("sta (sp),y"); AddCodeLine ("iny"); AddCmpCodeIfSizeNot256 ("cpy #$%02X", Offs + Arg3.Expr.IVal); AddCodeLine ("bne %s", LocalLabelName (Label)); /* memset returns the address, so the result is actually identical ** to the first argument. */ *Expr = Arg1.Expr; /* Bail out, no need for further processing */ goto ExitPoint; } if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 && ED_IsConstAbsInt (&Arg2.Expr) && (Arg2.Expr.IVal != 0 || IS_Get (&CodeSizeFactor) > 200)) { /* Remove all of the generated code but the load of the first ** argument. */ RemoveCode (&Arg1.Push); /* We need a label */ Label = GetLocalLabel (); /* Generate code */ AddCodeLine ("sta ptr1"); AddCodeLine ("stx ptr1+1"); if (Arg3.Expr.IVal <= 129) { AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal-1)); AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal); g_defcodelabel (Label); AddCodeLine ("sta (ptr1),y"); AddCodeLine ("dey"); AddCodeLine ("bpl %s", LocalLabelName (Label)); } else { AddCodeLine ("ldy #$00"); AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal); g_defcodelabel (Label); AddCodeLine ("sta (ptr1),y"); AddCodeLine ("iny"); AddCmpCodeIfSizeNot256 ("cpy #$%02X", Arg3.Expr.IVal); AddCodeLine ("bne %s", LocalLabelName (Label)); } /* Load the function result pointer into a/x (x is still valid). This ** code will get removed by the optimizer if it is not used later. */ AddCodeLine ("lda ptr1"); /* The function result is an rvalue in the primary register */ ED_MakeRValExpr (Expr); Expr->Type = GetFuncReturn (Expr->Type); /* Bail out, no need for further processing */ goto ExitPoint; } } /* The function result is an rvalue in the primary register */ ED_MakeRValExpr (Expr); Expr->Type = GetFuncReturn (Expr->Type); ExitPoint: /* We expect the closing brace */ ConsumeRParen (); } /*****************************************************************************/ /* strcmp */ /*****************************************************************************/ static void StdFunc_strcmp (FuncDesc* F attribute ((unused)), ExprDesc* Expr) /* Handle the strcmp function */ { /* Argument types: (const char*, const char*) */ static Type Arg1Type[] = { TYPE(T_PTR), TYPE(T_CHAR|T_QUAL_CONST), TYPE(T_END) }; static Type Arg2Type[] = { TYPE(T_PTR), TYPE(T_CHAR|T_QUAL_CONST), TYPE(T_END) }; ArgDesc Arg1, Arg2; unsigned ParamSize = 0; long ECount1; long ECount2; int IsArray; int Offs; /* Setup the argument type string */ Arg1Type[1].C = GetDefaultChar () | T_QUAL_CONST; Arg2Type[1].C = GetDefaultChar () | T_QUAL_CONST; /* Argument #1 */ ParseArg (&Arg1, Arg1Type); g_push (Arg1.Flags, Arg1.Expr.IVal); ParamSize += SizeOf (Arg1Type); ConsumeComma (); /* Argument #2. */ ParseArg (&Arg2, Arg2Type); /* Since strcmp is a fastcall function, we must load the ** arg into the primary if it is not already there. This parameter is ** also ignored for the calculation of the parameter size, since it is ** not passed via the stack. */ if (Arg2.Flags & CF_CONST) { LoadExpr (CF_NONE, &Arg2.Expr); } /* Emit the actual function call. This will also cleanup the stack. */ g_call (CF_FIXARGC, Func_strcmp, ParamSize); /* Get the element counts of the arguments. Then get the larger of the ** two into ECount1. This removes FLEXIBLE and UNSPECIFIED automatically */ ECount1 = ArrayElementCount (&Arg1); ECount2 = ArrayElementCount (&Arg2); if (ECount2 > ECount1) { ECount1 = ECount2; } if (IS_Get (&InlineStdFuncs)) { /* If the second argument is the empty string literal, we can generate ** more efficient code. */ if (ED_IsLocLiteral (&Arg2.Expr) && IS_Get (&WritableStrings) == 0 && GetLiteralSize (Arg2.Expr.LVal) == 1 && GetLiteralStr (Arg2.Expr.LVal)[0] == '\0') { /* Drop the generated code so we have the first argument in the ** primary */ RemoveCode (&Arg1.Push); /* We don't need the literal any longer */ ReleaseLiteral (Arg2.Expr.LVal); /* We do now have Arg1 in the primary. Load the first character from ** this string and cast to int. This is the function result. */ IsArray = IsTypeArray (Arg1.Type) && ED_IsRVal (&Arg1.Expr); if (IsArray && ED_IsLocStack (&Arg1.Expr) && (Offs = ED_GetStackOffs (&Arg1.Expr, 0) < 256)) { /* Drop the generated code */ RemoveCode (&Arg1.Load); /* Generate code */ AddCodeLine ("ldy #$%02X", Offs); AddCodeLine ("ldx #$00"); AddCodeLine ("lda (sp),y"); } else if (IsArray && ED_IsLocConst (&Arg1.Expr)) { /* Drop the generated code */ RemoveCode (&Arg1.Load); /* Generate code */ AddCodeLine ("ldx #$00"); AddCodeLine ("lda %s", ED_GetLabelName (&Arg1.Expr, 0)); } else { /* Drop part of the generated code so we have the first argument ** in the primary */ RemoveCode (&Arg1.Push); /* Fetch the first char */ g_getind (CF_CHAR | CF_UNSIGNED, 0); } } else if ((IS_Get (&CodeSizeFactor) >= 165) && ((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) || (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) && ((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) || (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr))) && (IS_Get (&EagerlyInlineFuncs) || (ECount1 > 0 && ECount1 < 256))) { unsigned Entry, Loop, Fin; /* Labels */ const char* Load; const char* Compare; if (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)) { Load = "lda (%s),y"; } else { Load = "lda %s,y"; } if (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr)) { Compare = "cmp (%s),y"; } else { Compare = "cmp %s,y"; } /* Drop the generated code */ RemoveCode (&Arg1.Expr.Start); /* We need labels */ Entry = GetLocalLabel (); Loop = GetLocalLabel (); Fin = GetLocalLabel (); /* Generate strcmp code */ AddCodeLine ("ldy #$00"); AddCodeLine ("beq %s", LocalLabelName (Entry)); g_defcodelabel (Loop); AddCodeLine ("tax"); AddCodeLine ("beq %s", LocalLabelName (Fin)); AddCodeLine ("iny"); g_defcodelabel (Entry); AddCodeLine (Load, ED_GetLabelName (&Arg1.Expr, 0)); AddCodeLine (Compare, ED_GetLabelName (&Arg2.Expr, 0)); AddCodeLine ("beq %s", LocalLabelName (Loop)); AddCodeLine ("ldx #$01"); AddCodeLine ("bcs %s", LocalLabelName (Fin)); AddCodeLine ("ldx #$FF"); g_defcodelabel (Fin); } else if ((IS_Get (&CodeSizeFactor) > 190) && ((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) || (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) && (IS_Get (&EagerlyInlineFuncs) || (ECount1 > 0 && ECount1 < 256))) { unsigned Entry, Loop, Fin; /* Labels */ const char* Compare; if (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr)) { Compare = "cmp (%s),y"; } else { Compare = "cmp %s,y"; } /* Drop the generated code */ RemoveCode (&Arg1.Push); /* We need labels */ Entry = GetLocalLabel (); Loop = GetLocalLabel (); Fin = GetLocalLabel (); /* Store Arg1 into ptr1 */ AddCodeLine ("sta ptr1"); AddCodeLine ("stx ptr1+1"); /* Generate strcmp code */ AddCodeLine ("ldy #$00"); AddCodeLine ("beq %s", LocalLabelName (Entry)); g_defcodelabel (Loop); AddCodeLine ("tax"); AddCodeLine ("beq %s", LocalLabelName (Fin)); AddCodeLine ("iny"); g_defcodelabel (Entry); AddCodeLine ("lda (ptr1),y"); AddCodeLine (Compare, ED_GetLabelName (&Arg2.Expr, 0)); AddCodeLine ("beq %s", LocalLabelName (Loop)); AddCodeLine ("ldx #$01"); AddCodeLine ("bcs %s", LocalLabelName (Fin)); AddCodeLine ("ldx #$FF"); g_defcodelabel (Fin); } } /* The function result is an rvalue in the primary register */ ED_MakeRValExpr (Expr); Expr->Type = GetFuncReturn (Expr->Type); /* We expect the closing brace */ ConsumeRParen (); } /*****************************************************************************/ /* strcpy */ /*****************************************************************************/ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr) /* Handle the strcpy function */ { /* Argument types: (char*, const char*) */ static Type Arg1Type[] = { TYPE(T_PTR), TYPE(T_CHAR), TYPE(T_END) }; static Type Arg2Type[] = { TYPE(T_PTR), TYPE(T_CHAR|T_QUAL_CONST), TYPE(T_END) }; ArgDesc Arg1, Arg2; unsigned ParamSize = 0; long ECount; unsigned L1; /* Setup the argument type string */ Arg1Type[1].C = GetDefaultChar (); Arg2Type[1].C = GetDefaultChar () | T_QUAL_CONST; /* Argument #1 */ ParseArg (&Arg1, Arg1Type); g_push (Arg1.Flags, Arg1.Expr.IVal); GetCodePos (&Arg1.End); ParamSize += SizeOf (Arg1Type); ConsumeComma (); /* Argument #2. Since strcpy is a fastcall function, we must load the ** arg into the primary if it is not already there. This parameter is ** also ignored for the calculation of the parameter size, since it is ** not passed via the stack. */ ParseArg (&Arg2, Arg2Type); if (Arg2.Flags & CF_CONST) { LoadExpr (CF_NONE, &Arg2.Expr); } /* Emit the actual function call. This will also cleanup the stack. */ g_call (CF_FIXARGC, Func_strcpy, ParamSize); /* Get the element count of argument 1 if it is an array */ ECount = ArrayElementCount (&Arg1); if (IS_Get (&InlineStdFuncs)) { /* We've generated the complete code for the function now and know the ** types of all parameters. Check for situations where better code can ** be generated. If such a situation is detected, throw away the ** generated, and emit better code. */ if (((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) || (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) && ((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) || (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr))) && (IS_Get (&EagerlyInlineFuncs) || (ECount != UNSPECIFIED && ECount < 256))) { const char* Load; const char* Store; if (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr)) { Load = "lda (%s),y"; } else { Load = "lda %s,y"; } if (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)) { Store = "sta (%s),y"; } else { Store = "sta %s,y"; } /* Drop the generated code */ RemoveCode (&Arg1.Expr.Start); /* We need labels */ L1 = GetLocalLabel (); /* Generate strcpy code */ AddCodeLine ("ldy #$FF"); g_defcodelabel (L1); AddCodeLine ("iny"); AddCodeLine (Load, ED_GetLabelName (&Arg2.Expr, 0)); AddCodeLine (Store, ED_GetLabelName (&Arg1.Expr, 0)); AddCodeLine ("bne %s", LocalLabelName (L1)); /* strcpy returns argument #1 */ *Expr = Arg1.Expr; /* Bail out, no need for further processing */ goto ExitPoint; } if (ED_IsRVal (&Arg2.Expr) && ED_IsLocStack (&Arg2.Expr) && StackPtr >= -255 && ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) { /* It is possible to just use one index register even if the stack ** offset is not zero, by adjusting the offset to the constant ** address accordingly. But we cannot do this if the data in ** question is in the register space or at an absolute address less ** than 256. Register space is zero page, which means that the ** address calculation could overflow in the linker. */ int AllowOneIndex = !ED_IsLocRegister (&Arg1.Expr) && !(ED_IsLocAbs (&Arg1.Expr) && Arg1.Expr.IVal < 256); /* Calculate the real stack offset */ int Offs = ED_GetStackOffs (&Arg2.Expr, 0); /* Drop the generated code */ RemoveCode (&Arg1.Expr.Start); /* We need labels */ L1 = GetLocalLabel (); /* Generate strcpy code */ AddCodeLine ("ldy #$%02X", (unsigned char) (Offs - 1)); if (Offs == 0 || AllowOneIndex) { g_defcodelabel (L1); AddCodeLine ("iny"); AddCodeLine ("lda (sp),y"); AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, -Offs)); } else { AddCodeLine ("ldx #$FF"); g_defcodelabel (L1); AddCodeLine ("iny"); AddCodeLine ("inx"); AddCodeLine ("lda (sp),y"); AddCodeLine ("sta %s,x", ED_GetLabelName (&Arg1.Expr, 0)); } AddCodeLine ("bne %s", LocalLabelName (L1)); /* strcpy returns argument #1 */ *Expr = Arg1.Expr; /* Bail out, no need for further processing */ goto ExitPoint; } if (ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr) && ED_IsRVal (&Arg1.Expr) && ED_IsLocStack (&Arg1.Expr) && StackPtr >= -255) { /* It is possible to just use one index register even if the stack ** offset is not zero, by adjusting the offset to the constant ** address accordingly. But we cannot do this if the data in ** question is in the register space or at an absolute address less ** than 256. Register space is zero page, which means that the ** address calculation could overflow in the linker. */ int AllowOneIndex = !ED_IsLocRegister (&Arg2.Expr) && !(ED_IsLocAbs (&Arg2.Expr) && Arg2.Expr.IVal < 256); /* Calculate the real stack offset */ int Offs = ED_GetStackOffs (&Arg1.Expr, 0); /* Drop the generated code */ RemoveCode (&Arg1.Expr.Start); /* We need labels */ L1 = GetLocalLabel (); /* Generate strcpy code */ AddCodeLine ("ldy #$%02X", (unsigned char) (Offs - 1)); if (Offs == 0 || AllowOneIndex) { g_defcodelabel (L1); AddCodeLine ("iny"); AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg2.Expr, -Offs)); AddCodeLine ("sta (sp),y"); } else { AddCodeLine ("ldx #$FF"); g_defcodelabel (L1); AddCodeLine ("iny"); AddCodeLine ("inx"); AddCodeLine ("lda %s,x", ED_GetLabelName (&Arg2.Expr, 0)); AddCodeLine ("sta (sp),y"); } AddCodeLine ("bne %s", LocalLabelName (L1)); /* strcpy returns argument #1 */ *Expr = Arg1.Expr; /* Bail out, no need for further processing */ goto ExitPoint; } } /* The function result is an rvalue in the primary register */ ED_MakeRValExpr (Expr); Expr->Type = GetFuncReturn (Expr->Type); ExitPoint: /* We expect the closing brace */ ConsumeRParen (); } /*****************************************************************************/ /* strlen */ /*****************************************************************************/ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr) /* Handle the strlen function */ { static Type ArgType[] = { TYPE(T_PTR), TYPE(T_CHAR|T_QUAL_CONST), TYPE(T_END) }; ExprDesc Arg; int IsArray; int IsPtr; int IsByteIndex; long ECount; unsigned L; /* Setup the argument type string */ ArgType[1].C = GetDefaultChar () | T_QUAL_CONST; /* Evaluate the parameter */ hie1 (&Arg); /* Check if the argument is an array. If so, remember the element count. ** Otherwise set the element count to undefined. */ IsArray = IsTypeArray (Arg.Type); if (IsArray) { ECount = GetElementCount (Arg.Type); if (ECount == FLEXIBLE) { /* Treat as unknown */ ECount = UNSPECIFIED; } IsPtr = 0; } else { ECount = UNSPECIFIED; IsPtr = IsTypePtr (Arg.Type); } /* Check if the elements of an array can be addressed by a byte sized ** index. This is true if the size of the array is known and less than ** 256. */ IsByteIndex = (ECount != UNSPECIFIED && ECount < 256); /* Do type conversion */ TypeConversion (&Arg, ArgType); if (IS_Get (&Optimize)) { /* If the expression is a literal, and if string literals are read ** only, we can calculate the length of the string and remove it ** from the literal pool. Otherwise we have to calculate the length ** at runtime. */ if (ED_IsLocLiteral (&Arg) && IS_Get (&WritableStrings) == 0) { /* Constant string literal */ ED_MakeConstAbs (Expr, GetLiteralSize (Arg.LVal) - 1, type_size_t); /* We don't need the literal any longer */ ReleaseLiteral (Arg.LVal); /* Bail out, no need for further improvements */ goto ExitPoint; } } if (IS_Get (&InlineStdFuncs)) { /* We will inline strlen for arrays with constant addresses, if either ** requested on the command line, or the array is smaller than 256, ** so the inlining is considered safe. */ if (ED_IsLocConst (&Arg) && IsArray && (IS_Get (&EagerlyInlineFuncs) || IsByteIndex)) { /* Generate the strlen code */ L = GetLocalLabel (); AddCodeLine ("ldy #$FF"); g_defcodelabel (L); AddCodeLine ("iny"); AddCodeLine ("ldx %s,y", ED_GetLabelName (&Arg, 0)); AddCodeLine ("bne %s", LocalLabelName (L)); AddCodeLine ("tya"); /* The function result is an rvalue in the primary register */ ED_MakeRValExpr (Expr); Expr->Type = type_size_t; /* Bail out, no need for further processing */ goto ExitPoint; } /* We will inline strlen for arrays on the stack, if the array is ** completely within the reach of a byte sized index register. */ if (ED_IsLocStack (&Arg) && IsArray && IsByteIndex && (Arg.IVal - StackPtr) + ECount < 256) { /* Calculate the true stack offset */ int Offs = ED_GetStackOffs (&Arg, 0); /* Generate the strlen code */ L = GetLocalLabel (); AddCodeLine ("ldx #$FF"); AddCodeLine ("ldy #$%02X", (unsigned char) (Offs-1)); g_defcodelabel (L); AddCodeLine ("inx"); AddCodeLine ("iny"); AddCodeLine ("lda (sp),y"); AddCodeLine ("bne %s", LocalLabelName (L)); AddCodeLine ("txa"); AddCodeLine ("ldx #$00"); /* The function result is an rvalue in the primary register */ ED_MakeRValExpr (Expr); Expr->Type = type_size_t; /* Bail out, no need for further processing */ goto ExitPoint; } /* strlen for a string that is pointed to by a register variable will only ** get inlined if requested on the command line, since we cannot know how ** big the buffer actually is, so inlining is not always safe. */ if (ED_IsLocRegister (&Arg) && ED_IsLVal (&Arg) && IsPtr && IS_Get (&EagerlyInlineFuncs)) { /* Generate the strlen code */ L = GetLocalLabel (); AddCodeLine ("ldy #$FF"); g_defcodelabel (L); AddCodeLine ("iny"); AddCodeLine ("lda (%s),y", ED_GetLabelName (&Arg, 0)); AddCodeLine ("bne %s", LocalLabelName (L)); AddCodeLine ("tax"); AddCodeLine ("tya"); /* The function result is an rvalue in the primary register */ ED_MakeRValExpr (Expr); Expr->Type = type_size_t; /* Bail out, no need for further processing */ goto ExitPoint; } /* Last check: We will inline a generic strlen routine if inlining was ** requested on the command line, and the code size factor is more than ** 400 (code is 13 bytes vs. 3 for a jsr call). */ if (IS_Get (&CodeSizeFactor) > 400 && IS_Get (&EagerlyInlineFuncs)) { /* Load the expression into the primary */ LoadExpr (CF_NONE, &Arg); /* Inline the function */ L = GetLocalLabel (); AddCodeLine ("sta ptr1"); AddCodeLine ("stx ptr1+1"); AddCodeLine ("ldy #$FF"); g_defcodelabel (L); AddCodeLine ("iny"); AddCodeLine ("lda (ptr1),y"); AddCodeLine ("bne %s", LocalLabelName (L)); AddCodeLine ("tax"); AddCodeLine ("tya"); /* The function result is an rvalue in the primary register */ ED_MakeRValExpr (Expr); Expr->Type = type_size_t; /* Bail out, no need for further processing */ goto ExitPoint; } } /* Load the expression into the primary */ LoadExpr (CF_NONE, &Arg); /* Call the strlen function */ AddCodeLine ("jsr _%s", Func_strlen); /* The function result is an rvalue in the primary register */ ED_MakeRValExpr (Expr); Expr->Type = type_size_t; ExitPoint: /* We expect the closing brace */ ConsumeRParen (); } /*****************************************************************************/ /* Code */ /*****************************************************************************/ int FindStdFunc (const char* Name) /* Determine if the given function is a known standard function that may be ** called in a special way. If so, return the index, otherwise return -1. */ { /* Look into the table for known names */ struct StdFuncDesc* D = bsearch (Name, StdFuncs, FUNC_COUNT, sizeof (StdFuncs[0]), CmpFunc); /* Return the function index or -1 */ if (D == 0) { return -1; } else { return D - StdFuncs; } } void HandleStdFunc (int Index, FuncDesc* F, ExprDesc* lval) /* Generate code for a known standard function. */ { struct StdFuncDesc* D; /* Get a pointer to the table entry */ CHECK (Index >= 0 && Index < (int)FUNC_COUNT); D = StdFuncs + Index; /* Call the handler function */ D->Handler (F, lval); } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/stdfunc.h������������������������������������������������������������������������0000664�0000000�0000000�00000006625�13473601511�0015364�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* stdfunc.h */ /* */ /* Handle inlining of known functions for the cc65 compiler */ /* */ /* */ /* */ /* (C) 1998-2004 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef STDFUNC_H #define STDFUNC_H /* cc65 */ #include "expr.h" #include "symtab.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void AddCmpCodeIfSizeNot256 (const char* Code, long Size); /* Add a line of Assembly code that compares an index register ** only if it isn't comparing to #<256. (If the next line ** is "bne", then this will avoid a redundant line.) */ int FindStdFunc (const char* Name); /* Determine if the given function is a known standard function that may be ** called in a special way. If so, return the index, otherwise return -1. */ void HandleStdFunc (int Index, struct FuncDesc* F, ExprDesc* lval); /* Generate code for a known standard function. */ /* End of stdfunc.h */ #endif �����������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/stdnames.c�����������������������������������������������������������������������0000664�0000000�0000000�00000006334�13473601511�0015524�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* stdnames.c */ /* */ /* Assembler names for standard functions in the library */ /* */ /* */ /* */ /* (C) 2004-2010, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* cc65 */ #include "stdnames.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ const char Func__bzero[] = "_bzero"; /* Asm name of "_bzero" */ const char Func_memcpy[] = "memcpy"; /* Asm name of "memcpy" */ const char Func_memset[] = "memset"; /* Asm name of "memset" */ const char Func_strcmp[] = "strcmp"; /* Asm name of "strcmp" */ const char Func_strcpy[] = "strcpy"; /* Asm name of "strcpy" */ const char Func_strlen[] = "strlen"; /* Asm name of "strlen" */ ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/stdnames.h�����������������������������������������������������������������������0000664�0000000�0000000�00000006324�13473601511�0015530�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* stdnames.h */ /* */ /* Assembler names for standard functions in the library */ /* */ /* */ /* */ /* (C) 2004-2010, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef STDNAMES_H #define STDNAMES_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ extern const char Func__bzero[]; /* Asm name of "_bzero" */ extern const char Func_memcpy[]; /* Asm name of "memcpy" */ extern const char Func_memset[]; /* Asm name of "memset" */ extern const char Func_strcmp[]; /* Asm name of "strcmp" */ extern const char Func_strcpy[]; /* Asm name of "strcpy" */ extern const char Func_strlen[]; /* Asm name of "strlen" */ /* End of stdnames.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/stmt.c���������������������������������������������������������������������������0000664�0000000�0000000�00000044212�13473601511�0014672�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* stmt.c */ /* */ /* Parse a statement */ /* */ /* */ /* */ /* (C) 1998-2010, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> /* common */ #include "coll.h" #include "xmalloc.h" /* cc65 */ #include "asmcode.h" #include "asmlabel.h" #include "codegen.h" #include "datatype.h" #include "error.h" #include "expr.h" #include "function.h" #include "global.h" #include "goto.h" #include "litpool.h" #include "loadexpr.h" #include "locals.h" #include "loop.h" #include "pragma.h" #include "scanner.h" #include "stackptr.h" #include "stmt.h" #include "swstmt.h" #include "symtab.h" #include "testexpr.h" #include "typeconv.h" /*****************************************************************************/ /* Helper functions */ /*****************************************************************************/ static int CheckLabelWithoutStatement (void) /* Called from Statement() after a label definition. Will check for a ** following closing curly brace. This means that a label is not followed ** by a statement which is required by the standard. Output an error if so. */ { if (CurTok.Tok == TOK_RCURLY) { Error ("Label at end of compound statement"); return 1; } else { return 0; } } static void CheckTok (token_t Tok, const char* Msg, int* PendingToken) /* Helper function for Statement. Will check for Tok and print Msg if not ** found. If PendingToken is NULL, it will the skip the token, otherwise ** it will store one to PendingToken. */ { if (CurTok.Tok != Tok) { Error ("%s", Msg); } else if (PendingToken) { *PendingToken = 1; } else { NextToken (); } } static void CheckSemi (int* PendingToken) /* Helper function for Statement. Will check for a semicolon and print an ** error message if not found (plus some error recovery). If PendingToken is ** NULL, it will the skip the token, otherwise it will store one to ** PendingToken. ** This function is a special version of CheckTok with the addition of the ** error recovery. */ { int HaveToken = (CurTok.Tok == TOK_SEMI); if (!HaveToken) { Error ("';' expected"); /* Try to be smart about errors */ if (CurTok.Tok == TOK_COLON || CurTok.Tok == TOK_COMMA) { HaveToken = 1; } } if (HaveToken) { if (PendingToken) { *PendingToken = 1; } else { NextToken (); } } } static void SkipPending (int PendingToken) /* Skip the pending token if we have one */ { if (PendingToken) { NextToken (); } } /*****************************************************************************/ /* Code */ /*****************************************************************************/ static int IfStatement (void) /* Handle an 'if' statement */ { unsigned Label1; unsigned TestResult; int GotBreak; /* Skip the if */ NextToken (); /* Generate a jump label and parse the condition */ Label1 = GetLocalLabel (); TestResult = TestInParens (Label1, 0); /* Parse the if body */ GotBreak = Statement (0); /* Else clause present? */ if (CurTok.Tok != TOK_ELSE) { g_defcodelabel (Label1); /* Since there's no else clause, we're not sure, if the a break ** statement is really executed. */ return 0; } else { /* Generate a jump around the else branch */ unsigned Label2 = GetLocalLabel (); g_jump (Label2); /* Skip the else */ NextToken (); /* If the if expression was always true, the code in the else branch ** is never executed. Output a warning if this is the case. */ if (TestResult == TESTEXPR_TRUE) { Warning ("Unreachable code"); } /* Define the target for the first test */ g_defcodelabel (Label1); /* Total break only if both branches had a break. */ GotBreak &= Statement (0); /* Generate the label for the else clause */ g_defcodelabel (Label2); /* Done */ return GotBreak; } } static void DoStatement (void) /* Handle the 'do' statement */ { /* Get the loop control labels */ unsigned LoopLabel = GetLocalLabel (); unsigned BreakLabel = GetLocalLabel (); unsigned ContinueLabel = GetLocalLabel (); /* Skip the while token */ NextToken (); /* Add the loop to the loop stack */ AddLoop (BreakLabel, ContinueLabel); /* Define the loop label */ g_defcodelabel (LoopLabel); /* Parse the loop body */ Statement (0); /* Output the label for a continue */ g_defcodelabel (ContinueLabel); /* Parse the end condition */ Consume (TOK_WHILE, "'while' expected"); TestInParens (LoopLabel, 1); ConsumeSemi (); /* Define the break label */ g_defcodelabel (BreakLabel); /* Remove the loop from the loop stack */ DelLoop (); } static void WhileStatement (void) /* Handle the 'while' statement */ { int PendingToken; CodeMark CondCodeStart; /* Start of condition evaluation code */ CodeMark CondCodeEnd; /* End of condition evaluation code */ CodeMark Here; /* "Here" location of code */ /* Get the loop control labels */ unsigned LoopLabel = GetLocalLabel (); unsigned BreakLabel = GetLocalLabel (); unsigned CondLabel = GetLocalLabel (); /* Skip the while token */ NextToken (); /* Add the loop to the loop stack. In case of a while loop, the condition ** label is used for continue statements. */ AddLoop (BreakLabel, CondLabel); /* We will move the code that evaluates the while condition to the end of ** the loop, so generate a jump here. */ g_jump (CondLabel); /* Remember the current position */ GetCodePos (&CondCodeStart); /* Test the loop condition */ TestInParens (LoopLabel, 1); /* Remember the end of the condition evaluation code */ GetCodePos (&CondCodeEnd); /* Define the head label */ g_defcodelabel (LoopLabel); /* Loop body */ Statement (&PendingToken); /* Emit the while condition label */ g_defcodelabel (CondLabel); /* Move the test code here */ GetCodePos (&Here); MoveCode (&CondCodeStart, &CondCodeEnd, &Here); /* Exit label */ g_defcodelabel (BreakLabel); /* Eat remaining tokens that were delayed because of line info ** correctness */ SkipPending (PendingToken); /* Remove the loop from the loop stack */ DelLoop (); } static void ReturnStatement (void) /* Handle the 'return' statement */ { ExprDesc Expr; NextToken (); if (CurTok.Tok != TOK_SEMI) { /* Evaluate the return expression */ hie0 (&Expr); /* If we return something in a void function, print an error and ** ignore the value. Otherwise convert the value to the type of the ** return. */ if (F_HasVoidReturn (CurrentFunc)) { Error ("Returning a value in function with return type void"); } else { /* Convert the return value to the type of the function result */ TypeConversion (&Expr, F_GetReturnType (CurrentFunc)); /* Load the value into the primary */ LoadExpr (CF_NONE, &Expr); } } else if (!F_HasVoidReturn (CurrentFunc) && !F_HasOldStyleIntRet (CurrentFunc)) { Error ("Function '%s' must return a value", F_GetFuncName (CurrentFunc)); } /* Mark the function as having a return statement */ F_ReturnFound (CurrentFunc); /* Cleanup the stack in case we're inside a block with locals */ g_space (StackPtr - F_GetTopLevelSP (CurrentFunc)); /* Output a jump to the function exit code */ g_jump (F_GetRetLab (CurrentFunc)); } static void BreakStatement (void) /* Handle the 'break' statement */ { LoopDesc* L; /* Skip the break */ NextToken (); /* Get the current loop descriptor */ L = CurrentLoop (); /* Check if we are inside a loop */ if (L == 0) { /* Error: No current loop */ Error ("'break' statement not within loop or switch"); return; } /* Correct the stack pointer if needed */ g_space (StackPtr - L->StackPtr); /* Jump to the exit label of the loop */ g_jump (L->BreakLabel); } static void ContinueStatement (void) /* Handle the 'continue' statement */ { LoopDesc* L; /* Skip the continue */ NextToken (); /* Get the current loop descriptor */ L = CurrentLoop (); if (L) { /* Search for a loop that has a continue label. */ do { if (L->ContinueLabel) { break; } L = L->Next; } while (L); } /* Did we find it? */ if (L == 0) { Error ("'continue' statement not within a loop"); return; } /* Correct the stackpointer if needed */ g_space (StackPtr - L->StackPtr); /* Jump to next loop iteration */ g_jump (L->ContinueLabel); } static void ForStatement (void) /* Handle a 'for' statement */ { ExprDesc lval1; ExprDesc lval3; int HaveIncExpr; CodeMark IncExprStart; CodeMark IncExprEnd; int PendingToken; /* Get several local labels needed later */ unsigned TestLabel = GetLocalLabel (); unsigned BreakLabel = GetLocalLabel (); unsigned IncLabel = GetLocalLabel (); unsigned BodyLabel = GetLocalLabel (); /* Skip the FOR token */ NextToken (); /* Add the loop to the loop stack. A continue jumps to the start of the ** the increment condition. */ AddLoop (BreakLabel, IncLabel); /* Skip the opening paren */ ConsumeLParen (); /* Parse the initializer expression */ if (CurTok.Tok != TOK_SEMI) { Expression0 (&lval1); } ConsumeSemi (); /* Label for the test expressions */ g_defcodelabel (TestLabel); /* Parse the test expression */ if (CurTok.Tok != TOK_SEMI) { Test (BodyLabel, 1); g_jump (BreakLabel); } else { g_jump (BodyLabel); } ConsumeSemi (); /* Remember the start of the increment expression */ GetCodePos (&IncExprStart); /* Label for the increment expression */ g_defcodelabel (IncLabel); /* Parse the increment expression */ HaveIncExpr = (CurTok.Tok != TOK_RPAREN); if (HaveIncExpr) { Expression0 (&lval3); } /* Jump to the test */ g_jump (TestLabel); /* Remember the end of the increment expression */ GetCodePos (&IncExprEnd); /* Skip the closing paren */ ConsumeRParen (); /* Loop body */ g_defcodelabel (BodyLabel); Statement (&PendingToken); /* If we had an increment expression, move the code to the bottom of ** the loop. In this case we don't need to jump there at the end of ** the loop body. */ if (HaveIncExpr) { CodeMark Here; GetCodePos (&Here); MoveCode (&IncExprStart, &IncExprEnd, &Here); } else { /* Jump back to the increment expression */ g_jump (IncLabel); } /* Skip a pending token if we have one */ SkipPending (PendingToken); /* Declare the break label */ g_defcodelabel (BreakLabel); /* Remove the loop from the loop stack */ DelLoop (); } static int CompoundStatement (void) /* Compound statement. Allow any number of statements inside braces. The ** function returns true if the last statement was a break or return. */ { int GotBreak; /* Remember the stack at block entry */ int OldStack = StackPtr; unsigned OldBlockStackSize = CollCount (&CurrentFunc->LocalsBlockStack); /* Enter a new lexical level */ EnterBlockLevel (); /* Parse local variable declarations if any */ DeclareLocals (); /* Now process statements in this block */ GotBreak = 0; while (CurTok.Tok != TOK_RCURLY) { if (CurTok.Tok != TOK_CEOF) { GotBreak = Statement (0); } else { break; } } /* Clean up the stack. */ if (!GotBreak) { g_space (StackPtr - OldStack); } /* If the segment had autoinited variables, let's pop it of a stack ** of such blocks. */ if (OldBlockStackSize != CollCount (&CurrentFunc->LocalsBlockStack)) { CollPop (&CurrentFunc->LocalsBlockStack); } StackPtr = OldStack; /* Emit references to imports/exports for this block */ EmitExternals (); /* Leave the lexical level */ LeaveBlockLevel (); return GotBreak; } int Statement (int* PendingToken) /* Statement parser. Returns 1 if the statement does a return/break, returns ** 0 otherwise. If the PendingToken pointer is not NULL, the function will ** not skip the terminating token of the statement (closing brace or ** semicolon), but store true if there is a pending token, and false if there ** is none. The token is always checked, so there is no need for the caller to ** check this token, it must be skipped, however. If the argument pointer is ** NULL, the function will skip the token. */ { ExprDesc Expr; int GotBreak; CodeMark Start, End; /* Assume no pending token */ if (PendingToken) { *PendingToken = 0; } /* Check for a label. A label is always part of a statement, it does not ** replace one. */ while (CurTok.Tok == TOK_IDENT && NextTok.Tok == TOK_COLON) { /* Handle the label */ DoLabel (); if (CheckLabelWithoutStatement ()) { return 0; } } switch (CurTok.Tok) { case TOK_LCURLY: NextToken (); GotBreak = CompoundStatement (); CheckTok (TOK_RCURLY, "'{' expected", PendingToken); return GotBreak; case TOK_IF: return IfStatement (); case TOK_WHILE: WhileStatement (); break; case TOK_DO: DoStatement (); break; case TOK_SWITCH: SwitchStatement (); break; case TOK_RETURN: ReturnStatement (); CheckSemi (PendingToken); return 1; case TOK_BREAK: BreakStatement (); CheckSemi (PendingToken); return 1; case TOK_CONTINUE: ContinueStatement (); CheckSemi (PendingToken); return 1; case TOK_FOR: ForStatement (); break; case TOK_GOTO: GotoStatement (); CheckSemi (PendingToken); return 1; case TOK_SEMI: /* Ignore it */ CheckSemi (PendingToken); break; case TOK_PRAGMA: DoPragma (); break; case TOK_CASE: CaseLabel (); CheckLabelWithoutStatement (); break; case TOK_DEFAULT: DefaultLabel (); CheckLabelWithoutStatement (); break; default: /* Remember the current code position */ GetCodePos (&Start); /* Actual statement */ ExprWithCheck (hie0, &Expr); /* Load the result only if it is an lvalue and the type is ** marked as volatile. Otherwise the load is useless. */ if (ED_IsLVal (&Expr) && IsQualVolatile (Expr.Type)) { LoadExpr (CF_NONE, &Expr); } /* If the statement didn't generate code, and is not of type ** void, emit a warning. */ GetCodePos (&End); if (CodeRangeIsEmpty (&Start, &End) && !IsTypeVoid (Expr.Type) && IS_Get (&WarnNoEffect)) { Warning ("Statement has no effect"); } CheckSemi (PendingToken); } return 0; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/stmt.h���������������������������������������������������������������������������0000664�0000000�0000000�00000006516�13473601511�0014704�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* stmt.h */ /* */ /* Parse a statement */ /* */ /* */ /* */ /* (C) 1998-2008 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef STMT_H #define STMT_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ int Statement (int* PendingToken); /* Statement parser. Returns 1 if the statement does a return/break, returns ** 0 otherwise. If the PendingToken pointer is not NULL, the function will ** not skip the terminating token of the statement (closing brace or ** semicolon), but store true if there is a pending token, and false if there ** is none. The token is always checked, so there is no need for the caller to ** check this token, it must be skipped, however. If the argument pointer is ** NULL, the function will skip the token. */ /* End of stmt.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/swstmt.c�������������������������������������������������������������������������0000664�0000000�0000000�00000024626�13473601511�0015253�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* swstmt.c */ /* */ /* Parse the switch statement */ /* */ /* */ /* */ /* (C) 1998-2008 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <limits.h> /* common */ #include "coll.h" #include "xmalloc.h" /* cc65 */ #include "asmcode.h" #include "asmlabel.h" #include "casenode.h" #include "codegen.h" #include "datatype.h" #include "error.h" #include "expr.h" #include "global.h" #include "loop.h" #include "scanner.h" #include "stmt.h" #include "swstmt.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ typedef struct SwitchCtrl SwitchCtrl; struct SwitchCtrl { Collection* Nodes; /* CaseNode tree */ TypeCode ExprType; /* Basic switch expression type */ unsigned Depth; /* Number of bytes the selector type has */ unsigned DefaultLabel; /* Label for the default branch */ }; /* Pointer to current switch control struct */ static SwitchCtrl* Switch = 0; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void SwitchStatement (void) /* Handle a switch statement for chars with a cmp cascade for the selector */ { ExprDesc SwitchExpr; /* Switch statement expression */ CodeMark CaseCodeStart; /* Start of code marker */ CodeMark SwitchCodeStart;/* Start of switch code */ CodeMark SwitchCodeEnd; /* End of switch code */ unsigned ExitLabel; /* Exit label */ unsigned SwitchCodeLabel;/* Label for the switch code */ int HaveBreak = 0; /* True if the last statement had a break */ int RCurlyBrace; /* True if last token is right curly brace */ SwitchCtrl* OldSwitch; /* Pointer to old switch control data */ SwitchCtrl SwitchData; /* New switch data */ /* Eat the "switch" token */ NextToken (); /* Read the switch expression and load it into the primary. It must have ** integer type. */ ConsumeLParen (); Expression0 (&SwitchExpr); if (!IsClassInt (SwitchExpr.Type)) { Error ("Switch quantity is not an integer"); /* To avoid any compiler errors, make the expression a valid int */ ED_MakeConstAbsInt (&SwitchExpr, 1); } ConsumeRParen (); /* Add a jump to the switch code. This jump is usually unnecessary, ** because the switch code will moved up just behind the switch ** expression. However, in rare cases, there's a label at the end of ** the switch expression. This label will not get moved, so the code ** jumps around the switch code, and after moving the switch code, ** things look really weird. If we add a jump here, we will never have ** a label attached to the current code position, and the jump itself ** will get removed by the optimizer if it is unnecessary. */ SwitchCodeLabel = GetLocalLabel (); g_jump (SwitchCodeLabel); /* Remember the current code position. We will move the switch code ** to this position later. */ GetCodePos (&CaseCodeStart); /* Setup the control structure, save the old and activate the new one */ SwitchData.Nodes = NewCollection (); SwitchData.ExprType = UnqualifiedType (SwitchExpr.Type[0].C); SwitchData.Depth = SizeOf (SwitchExpr.Type); SwitchData.DefaultLabel = 0; OldSwitch = Switch; Switch = &SwitchData; /* Get the exit label for the switch statement */ ExitLabel = GetLocalLabel (); /* Create a loop so we may use break. */ AddLoop (ExitLabel, 0); /* Parse the following statement, which may actually be a compound ** statement if there is a curly brace at the current input position */ HaveBreak = Statement (&RCurlyBrace); /* Check if we had any labels */ if (CollCount (SwitchData.Nodes) == 0 && SwitchData.DefaultLabel == 0) { Warning ("No case labels"); } /* If the last statement did not have a break, we may have an open ** label (maybe from an if or similar). Emitting code and then moving ** this code to the top will also move the label to the top which is ** wrong. So if the last statement did not have a break (which would ** carry the label), add a jump to the exit. If it is useless, the ** optimizer will remove it later. */ if (!HaveBreak) { g_jump (ExitLabel); } /* Remember the current position */ GetCodePos (&SwitchCodeStart); /* Output the switch code label */ g_defcodelabel (SwitchCodeLabel); /* Generate code */ if (SwitchData.DefaultLabel == 0) { /* No default label, use switch exit */ SwitchData.DefaultLabel = ExitLabel; } g_switch (SwitchData.Nodes, SwitchData.DefaultLabel, SwitchData.Depth); /* Move the code to the front */ GetCodePos (&SwitchCodeEnd); MoveCode (&SwitchCodeStart, &SwitchCodeEnd, &CaseCodeStart); /* Define the exit label */ g_defcodelabel (ExitLabel); /* Exit the loop */ DelLoop (); /* Switch back to the enclosing switch statement if any */ Switch = OldSwitch; /* Free the case value tree */ FreeCaseNodeColl (SwitchData.Nodes); /* If the case statement was terminated by a closing curly ** brace, skip it now. */ if (RCurlyBrace) { NextToken (); } } void CaseLabel (void) /* Handle a case sabel */ { ExprDesc CaseExpr; /* Case label expression */ long Val; /* Case label value */ unsigned CodeLabel; /* Code label for this case */ /* Skip the "case" token */ NextToken (); /* Read the selector expression */ ConstAbsIntExpr (hie1, &CaseExpr); Val = CaseExpr.IVal; /* Now check if we're inside a switch statement */ if (Switch != 0) { /* Check the range of the expression */ switch (Switch->ExprType) { case T_SCHAR: /* Signed char */ if (Val < -128 || Val > 127) { Error ("Range error"); } break; case T_UCHAR: if (Val < 0 || Val > 255) { Error ("Range error"); } break; case T_SHORT: case T_INT: if (Val < -32768 || Val > 32767) { Error ("Range error"); } break; case T_USHORT: case T_UINT: if (Val < 0 || Val > 65535) { Error ("Range error"); } break; case T_LONG: case T_ULONG: break; default: Internal ("Invalid type: %06lX", Switch->ExprType); } /* Insert the case selector into the selector table */ CodeLabel = InsertCaseValue (Switch->Nodes, Val, Switch->Depth); /* Define this label */ g_defcodelabel (CodeLabel); } else { /* case keyword outside a switch statement */ Error ("Case label not within a switch statement"); } /* Skip the colon */ ConsumeColon (); } void DefaultLabel (void) /* Handle a default label */ { /* Default case */ NextToken (); /* Now check if we're inside a switch statement */ if (Switch != 0) { /* Check if we do already have a default branch */ if (Switch->DefaultLabel == 0) { /* Generate and emit the default label */ Switch->DefaultLabel = GetLocalLabel (); g_defcodelabel (Switch->DefaultLabel); } else { /* We had the default label already */ Error ("Multiple default labels in one switch"); } } else { /* case keyword outside a switch statement */ Error ("'default' label not within a switch statement"); } /* Skip the colon */ ConsumeColon (); } ����������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/swstmt.h�������������������������������������������������������������������������0000664�0000000�0000000�00000005745�13473601511�0015261�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* swstmt.h */ /* */ /* Parse the switch statement */ /* */ /* */ /* */ /* (C) 1998-2008 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef SWSTMT_H #define SWSTMT_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ void SwitchStatement (void); /* Handle a 'switch' statement */ void CaseLabel (void); /* Handle a case label */ void DefaultLabel (void); /* Handle a default label */ /* End of swstmt.h */ #endif ���������������������������cc65-2.18/src/cc65/symentry.c�����������������������������������������������������������������������0000664�0000000�0000000�00000020705�13473601511�0015576�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* symentry.c */ /* */ /* Symbol table entries for the cc65 C compiler */ /* */ /* */ /* */ /* (C) 2000-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* common */ #include "xmalloc.h" /* cc65 */ #include "anonname.h" #include "declare.h" #include "error.h" #include "symentry.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ SymEntry* NewSymEntry (const char* Name, unsigned Flags) /* Create a new symbol table with the given name */ { /* Get the length of the name */ unsigned Len = strlen (Name); /* Allocate memory for the symbol entry */ SymEntry* E = xmalloc (sizeof (SymEntry) + Len); /* Initialize the entry */ E->NextHash = 0; E->PrevSym = 0; E->NextSym = 0; E->Link = 0; E->Owner = 0; E->Flags = Flags; E->Type = 0; E->Attr = 0; E->AsmName = 0; E->V.BssName = 0; memcpy (E->Name, Name, Len+1); /* Return the new entry */ return E; } void FreeSymEntry (SymEntry* E) /* Free a symbol entry */ { unsigned i; TypeFree (E->Type); xfree (E->AsmName); if (E->Flags & SC_LABEL) { for (i = 0; i < CollCount (E->V.L.DefsOrRefs); i++) { xfree (CollAt (E->V.L.DefsOrRefs, i)); } DoneCollection (E->V.L.DefsOrRefs); } xfree (E); } void DumpSymEntry (FILE* F, const SymEntry* E) /* Dump the given symbol table entry to the file in readable form */ { static const struct { const char* Name; unsigned Val; } Flags [] = { /* Beware: Order is important! */ { "SC_TYPEDEF", SC_TYPEDEF }, { "SC_BITFIELD", SC_BITFIELD }, { "SC_STRUCTFIELD", SC_STRUCTFIELD }, { "SC_UNION", SC_UNION }, { "SC_STRUCT", SC_STRUCT }, { "SC_AUTO", SC_AUTO }, { "SC_REGISTER", SC_REGISTER }, { "SC_STATIC", SC_STATIC }, { "SC_EXTERN", SC_EXTERN }, { "SC_ENUM", SC_ENUM }, { "SC_CONST", SC_CONST }, { "SC_LABEL", SC_LABEL }, { "SC_PARAM", SC_PARAM }, { "SC_FUNC", SC_FUNC }, { "SC_STORAGE", SC_STORAGE }, { "SC_DEF", SC_DEF }, { "SC_REF", SC_REF }, { "SC_ZEROPAGE", SC_ZEROPAGE }, }; unsigned I; unsigned SymFlags; /* Print the name */ fprintf (F, "%s:\n", E->Name); /* 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:"); 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); } } if (SymFlags != 0) { fprintf (F, " 0x%05X", SymFlags); } fprintf (F, "\n"); /* Print the type */ fprintf (F, " Type: "); if (E->Type) { PrintType (F, E->Type); } else { fprintf (F, "(none)"); } fprintf (F, "\n"); } int SymIsOutputFunc (const SymEntry* Sym) /* Return true if this is a function that must be output */ { /* Symbol must be a function which is defined and either extern or ** static and referenced. */ return IsTypeFunc (Sym->Type) && SymIsDef (Sym) && (Sym->Flags & (SC_REF | SC_EXTERN)); } const DeclAttr* SymGetAttr (const SymEntry* Sym, DeclAttrType AttrType) /* Return an attribute for this symbol or NULL if the attribute does not exist */ { /* Beware: We may not even have a collection */ if (Sym->Attr) { unsigned I; for (I = 0; I < CollCount (Sym->Attr); ++I) { /* Get the next attribute */ const DeclAttr* A = CollConstAt (Sym->Attr, I); /* If this is the one we're searching for, return it */ if (A->AttrType == AttrType) { return A; } } } /* Not found */ return 0; } void SymUseAttr (SymEntry* Sym, struct Declaration* D) /* Use the attributes from the declaration for this symbol */ { /* We cannot specify attributes twice */ if ((Sym->Flags & SC_HAVEATTR) != 0) { if (D->Attributes != 0) { Error ("Attributes must be specified in the first declaration"); } return; } /* Move the attributes */ Sym->Attr = D->Attributes; D->Attributes = 0; Sym->Flags |= SC_HAVEATTR; } void SymSetAsmName (SymEntry* Sym) /* Set the assembler name for an external symbol from the name of the symbol */ { unsigned Len; /* Cannot be used to change the name */ PRECONDITION (Sym->AsmName == 0); /* The assembler name starts with an underline */ Len = strlen (Sym->Name); Sym->AsmName = xmalloc (Len + 2); Sym->AsmName[0] = '_'; memcpy (Sym->AsmName+1, Sym->Name, Len+1); } void CvtRegVarToAuto (SymEntry* Sym) /* Convert a register variable to an auto variable */ { /* Change the storage class */ Sym->Flags = (Sym->Flags & ~(SC_REGISTER | SC_STATIC | SC_EXTERN)) | SC_AUTO; /* Transfer the stack offset from register save area to actual offset */ Sym->V.Offs = Sym->V.R.SaveOffs; } void ChangeSymType (SymEntry* Entry, Type* T) /* Change the type of the given symbol */ { TypeFree (Entry->Type); Entry->Type = TypeDup (T); } void ChangeAsmName (SymEntry* Entry, const char* NewAsmName) /* Change the assembler name of the symbol */ { xfree (Entry->AsmName); Entry->AsmName = xstrdup (NewAsmName); } int HasAnonName (const SymEntry* Entry) /* Return true if the symbol entry has an anonymous name */ { return IsAnonName (Entry->Name); } �����������������������������������������������������������cc65-2.18/src/cc65/symentry.h�����������������������������������������������������������������������0000664�0000000�0000000�00000025562�13473601511�0015611�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* symentry.h */ /* */ /* Symbol table entries for the cc65 C compiler */ /* */ /* */ /* */ /* (C) 2000-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef SYMENTRY_H #define SYMENTRY_H #include <stdio.h> /* common */ #include "coll.h" #include "inline.h" /* cc65 */ #include "datatype.h" #include "declattr.h" /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ struct Segments; struct LiteralPool; struct CodeEntry; /*****************************************************************************/ /* struct SymEntry */ /*****************************************************************************/ /* Storage classes and flags */ #define SC_AUTO 0x0001U /* Auto variable */ #define SC_REGISTER 0x0002U /* Register variable */ #define SC_STATIC 0x0004U /* Static */ #define SC_EXTERN 0x0008U /* Extern linkage */ #define SC_ENUM 0x0030U /* An enum */ #define SC_CONST 0x0020U /* A numeric constant with a type */ #define SC_LABEL 0x0040U /* A goto label */ #define SC_PARAM 0x0080U /* A function parameter */ #define SC_FUNC 0x0100U /* A function */ #define SC_DEFTYPE 0x0200U /* Parameter has default type (=int, old style) */ #define SC_STORAGE 0x0400U /* Symbol with associated storage */ #define SC_DEFAULT 0x0800U /* Flag: default storage class was used */ #define SC_DEF 0x1000U /* Symbol is defined */ #define SC_REF 0x2000U /* Symbol is referenced */ #define SC_TYPE 0x4000U /* This is a type, struct, typedef, etc. */ #define SC_STRUCT 0x4001U /* Struct */ #define SC_UNION 0x4002U /* Union */ #define SC_STRUCTFIELD 0x4003U /* Struct or union field */ #define SC_BITFIELD 0x4004U /* A bit-field inside a struct or union */ #define SC_TYPEDEF 0x4005U /* A typedef */ #define SC_TYPEMASK 0x400FU /* Mask for above types */ #define SC_ZEROPAGE 0x8000U /* Symbol marked as zeropage */ #define SC_HAVEATTR 0x10000U /* Symbol has attributes */ #define SC_GOTO 0x20000U #define SC_SPADJUSTMENT 0x40000U #define SC_GOTO_IND 0x80000U /* Indirect goto */ /* Label definition or reference */ typedef struct DefOrRef DefOrRef; struct DefOrRef { unsigned Line; long LocalsBlockId; unsigned Flags; int StackPtr; unsigned Depth; unsigned LateSP_Label; }; /* Symbol table entry */ typedef struct SymEntry SymEntry; struct SymEntry { SymEntry* NextHash; /* Next entry in hash list */ SymEntry* PrevSym; /* Previous symbol in dl list */ SymEntry* NextSym; /* Next symbol double linked list */ SymEntry* Link; /* General purpose single linked list */ struct SymTable* Owner; /* Symbol table the symbol is in */ unsigned Flags; /* Symbol flags */ Type* Type; /* Symbol type */ Collection* Attr; /* Attribute list if any */ char* AsmName; /* Assembler name if any */ /* Data that differs for the different symbol types */ union { /* Offset for locals or struct members */ int Offs; /* Label name for static symbols */ struct { unsigned Label; Collection *DefsOrRefs; struct CodeEntry *IndJumpFrom; } L; /* Value of SP adjustment needed after forward 'goto' */ unsigned short SPAdjustment; /* Register bank offset and offset of the saved copy on stack for ** register variables. */ struct { int RegOffs; int SaveOffs; } R; /* Value for constants (including enums) */ long ConstVal; /* Data for structs/unions */ struct { struct SymTable* SymTab; /* Member symbol table */ unsigned Size; /* Size of the union/struct */ } S; /* Data for bit fields */ struct { unsigned Offs; /* Byte offset into struct */ unsigned BitOffs; /* Bit offset into storage unit */ unsigned BitWidth; /* Width in bits */ } B; /* Data for functions */ struct { struct FuncDesc* Func; /* Function descriptor */ struct Segments* Seg; /* Segments for this function */ struct LiteralPool* LitPool; /* Literal pool for this function */ } F; /* Segment name for tentantive global definitions */ const char* BssName; } V; char Name[1]; /* Name, dynamically allocated */ }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ SymEntry* NewSymEntry (const char* Name, unsigned Flags); /* Create a new symbol table with the given name */ void FreeSymEntry (SymEntry* E); /* Free a symbol entry */ void DumpSymEntry (FILE* F, const SymEntry* E); /* Dump the given symbol table entry to the file in readable form */ #if defined(HAVE_INLINE) INLINE int SymIsBitField (const SymEntry* Sym) /* Return true if the given entry is a bit-field entry */ { return ((Sym->Flags & SC_BITFIELD) == SC_BITFIELD); } #else # define SymIsBitField(Sym) (((Sym)->Flags & SC_BITFIELD) == SC_BITFIELD) #endif #if defined(HAVE_INLINE) INLINE int SymIsTypeDef (const SymEntry* Sym) /* Return true if the given entry is a typedef entry */ { return ((Sym->Flags & SC_TYPEDEF) == SC_TYPEDEF); } #else # define SymIsTypeDef(Sym) (((Sym)->Flags & SC_TYPEDEF) == SC_TYPEDEF) #endif #if defined(HAVE_INLINE) INLINE int SymIsDef (const SymEntry* Sym) /* Return true if the given entry is defined */ { return ((Sym->Flags & SC_DEF) == SC_DEF); } #else # define SymIsDef(Sym) (((Sym)->Flags & SC_DEF) == SC_DEF) #endif #if defined(HAVE_INLINE) INLINE int SymIsRef (const SymEntry* Sym) /* Return true if the given entry is referenced */ { return ((Sym->Flags & SC_REF) == SC_REF); } #else # define SymIsRef(Sym) (((Sym)->Flags & SC_REF) == SC_REF) #endif #if defined(HAVE_INLINE) INLINE int SymIsRegVar (const SymEntry* Sym) /* Return true if the given entry is a register variable */ /* ### HACK! Fix the ugly type flags! */ { return ((Sym->Flags & (SC_REGISTER|SC_TYPE)) == SC_REGISTER); } #else # define SymIsRegVar(Sym) (((Sym)->Flags & (SC_REGISTER|SC_TYPE)) == SC_REGISTER) #endif int SymIsOutputFunc (const SymEntry* Sym); /* Return true if this is a function that must be output */ #if defined(HAVE_INLINE) INLINE const char* SymGetAsmName (const SymEntry* Sym) /* Return the assembler label name for the symbol (beware: may be NULL!) */ { return Sym->AsmName; } #else # define SymGetAsmName(Sym) ((Sym)->AsmName) #endif const DeclAttr* SymGetAttr (const SymEntry* Sym, DeclAttrType AttrType); /* Return an attribute for this symbol or NULL if the attribute does not exist */ #if defined(HAVE_INLINE) INLINE int SymHasAttr (const SymEntry* Sym, DeclAttrType A) /* Return true if the symbol has the given attribute */ { return (SymGetAttr (Sym, A) != 0); } #else # define SymHasAttr(Sym, A) (SymGetAttr (Sym, A) != 0) #endif void SymUseAttr (SymEntry* Sym, struct Declaration* D); /* Use the attributes from the declaration for this symbol */ void SymSetAsmName (SymEntry* Sym); /* Set the assembler name for an external symbol from the name of the symbol */ void CvtRegVarToAuto (SymEntry* Sym); /* Convert a register variable to an auto variable */ void ChangeSymType (SymEntry* Entry, Type* T); /* Change the type of the given symbol */ void ChangeAsmName (SymEntry* Entry, const char* NewAsmName); /* Change the assembler name of the symbol */ int HasAnonName (const SymEntry* Entry); /* Return true if the symbol entry has an anonymous name */ /* End of symentry.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/symtab.c�������������������������������������������������������������������������0000664�0000000�0000000�00000101246�13473601511�0015203�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* symtab.c */ /* */ /* Symbol table management for the cc65 C compiler */ /* */ /* */ /* */ /* (C) 2000-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> /* common */ #include "check.h" #include "debugflag.h" #include "hashfunc.h" #include "xmalloc.h" /* cc65 */ #include "asmcode.h" #include "asmlabel.h" #include "codegen.h" #include "datatype.h" #include "declare.h" #include "error.h" #include "funcdesc.h" #include "global.h" #include "stackptr.h" #include "symentry.h" #include "typecmp.h" #include "symtab.h" #include "function.h" #include "input.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* An empty symbol table */ SymTable EmptySymTab = { 0, /* PrevTab */ 0, /* SymHead */ 0, /* SymTail */ 0, /* SymCount */ 1, /* Size */ { 0 } /* Tab[1] */ }; /* Symbol table sizes */ #define SYMTAB_SIZE_GLOBAL 211U #define SYMTAB_SIZE_FUNCTION 29U #define SYMTAB_SIZE_BLOCK 13U #define SYMTAB_SIZE_STRUCT 19U #define SYMTAB_SIZE_LABEL 7U /* The current and root symbol tables */ static unsigned LexicalLevel = 0; /* For safety checks */ static SymTable* SymTab0 = 0; static SymTable* SymTab = 0; static SymTable* TagTab0 = 0; static SymTable* TagTab = 0; static SymTable* LabelTab = 0; static SymTable* SPAdjustTab = 0; /*****************************************************************************/ /* struct SymTable */ /*****************************************************************************/ static SymTable* NewSymTable (unsigned Size) /* Create and return a symbol table for the given lexical level */ { unsigned I; /* Allocate memory for the table */ SymTable* S = xmalloc (sizeof (SymTable) + (Size-1) * sizeof (SymEntry*)); /* Initialize the symbol table structure */ S->PrevTab = 0; S->SymHead = 0; S->SymTail = 0; S->SymCount = 0; S->Size = Size; for (I = 0; I < Size; ++I) { S->Tab[I] = 0; } /* Return the symbol table */ return S; } static void FreeSymTable (SymTable* S) /* Free the given symbo table including all symbols */ { /* Free all symbols */ SymEntry* Sym = S->SymHead; while (Sym) { SymEntry* NextSym = Sym->NextSym; FreeSymEntry (Sym); Sym = NextSym; } /* Free the table itself */ xfree (S); } /*****************************************************************************/ /* Check symbols in a table */ /*****************************************************************************/ static void CheckSymTable (SymTable* Tab) /* Check a symbol table for open references, unused symbols ... */ { SymEntry* Entry = Tab->SymHead; while (Entry) { /* Get the storage flags for tne entry */ unsigned Flags = Entry->Flags; /* Ignore typedef entries */ if (!SymIsTypeDef (Entry)) { /* Check if the symbol is one with storage, and it if it was ** defined but not used. */ if (((Flags & SC_AUTO) || (Flags & SC_STATIC)) && (Flags & SC_EXTERN) == 0) { if (SymIsDef (Entry) && !SymIsRef (Entry) && !SymHasAttr (Entry, atUnused)) { if (Flags & SC_PARAM) { if (IS_Get (&WarnUnusedParam)) { Warning ("Parameter '%s' is never used", Entry->Name); } } else { if (IS_Get (&WarnUnusedVar)) { Warning ("'%s' is defined but never used", Entry->Name); } } } } /* If the entry is a label, check if it was defined in the function */ if (Flags & SC_LABEL) { if (!SymIsDef (Entry)) { /* Undefined label */ Error ("Undefined label: '%s'", Entry->Name); } else if (!SymIsRef (Entry)) { /* Defined but not used */ if (IS_Get (&WarnUnusedLabel)) { Warning ("'%s' is defined but never used", Entry->Name); } } } } /* Next entry */ Entry = Entry->NextSym; } } /*****************************************************************************/ /* Handling of lexical levels */ /*****************************************************************************/ unsigned GetLexicalLevel (void) /* Return the current lexical level */ { return LexicalLevel; } void EnterGlobalLevel (void) /* Enter the program global lexical level */ { /* Safety */ PRECONDITION (++LexicalLevel == LEX_LEVEL_GLOBAL); /* Create and assign the symbol table */ SymTab0 = SymTab = NewSymTable (SYMTAB_SIZE_GLOBAL); /* Create and assign the tag table */ TagTab0 = TagTab = NewSymTable (SYMTAB_SIZE_GLOBAL); /* Create and assign the table of SP adjustment symbols */ SPAdjustTab = NewSymTable (SYMTAB_SIZE_GLOBAL); } void LeaveGlobalLevel (void) /* Leave the program global lexical level */ { /* Safety */ PRECONDITION (LexicalLevel-- == LEX_LEVEL_GLOBAL); /* Check the tables */ CheckSymTable (SymTab0); /* Dump the tables if requested */ if (Debug) { PrintSymTable (SymTab0, stdout, "Global symbol table"); PrintSymTable (TagTab0, stdout, "Global tag table"); } /* Don't delete the symbol and struct tables! */ SymTab = 0; TagTab = 0; } void EnterFunctionLevel (void) /* Enter function lexical level */ { SymTable* S; /* New lexical level */ ++LexicalLevel; /* Get a new symbol table and make it current */ S = NewSymTable (SYMTAB_SIZE_FUNCTION); S->PrevTab = SymTab; SymTab = S; /* Get a new tag table and make it current */ S = NewSymTable (SYMTAB_SIZE_FUNCTION); S->PrevTab = TagTab; TagTab = S; /* Create and assign a new label table */ S = NewSymTable (SYMTAB_SIZE_LABEL); S->PrevTab = LabelTab; LabelTab = S; } void RememberFunctionLevel (struct FuncDesc* F) /* Remember the symbol tables for the level and leave the level without checks */ { /* Leave the lexical level */ --LexicalLevel; /* Remember the tables */ F->SymTab = SymTab; F->TagTab = TagTab; /* Don't delete the tables */ SymTab = SymTab->PrevTab; TagTab = TagTab->PrevTab; LabelTab = LabelTab->PrevTab; } void ReenterFunctionLevel (struct FuncDesc* F) /* Reenter the function lexical level using the existing tables from F */ { /* New lexical level */ ++LexicalLevel; /* Make the tables current again */ F->SymTab->PrevTab = SymTab; SymTab = F->SymTab; F->TagTab->PrevTab = TagTab; TagTab = F->TagTab; /* Create and assign a new label table */ LabelTab = NewSymTable (SYMTAB_SIZE_LABEL); } void LeaveFunctionLevel (void) /* Leave function lexical level */ { /* Leave the lexical level */ --LexicalLevel; /* Check the tables */ CheckSymTable (SymTab); CheckSymTable (LabelTab); /* Drop the label table if it is empty */ if (LabelTab->SymCount == 0) { FreeSymTable (LabelTab); } /* Don't delete the tables */ SymTab = SymTab->PrevTab; TagTab = TagTab->PrevTab; LabelTab = 0; } void EnterBlockLevel (void) /* Enter a nested block in a function */ { SymTable* S; /* New lexical level */ ++LexicalLevel; /* Get a new symbol table and make it current */ S = NewSymTable (SYMTAB_SIZE_BLOCK); S->PrevTab = SymTab; SymTab = S; /* Get a new tag table and make it current */ S = NewSymTable (SYMTAB_SIZE_BLOCK); S->PrevTab = TagTab; TagTab = S; } void LeaveBlockLevel (void) /* Leave a nested block in a function */ { /* Leave the lexical level */ --LexicalLevel; /* Check the tables */ CheckSymTable (SymTab); /* Don't delete the tables */ SymTab = SymTab->PrevTab; TagTab = TagTab->PrevTab; } void EnterStructLevel (void) /* Enter a nested block for a struct definition */ { SymTable* S; /* Get a new symbol table and make it current. Note: Structs and enums ** nested in struct scope are NOT local to the struct but visible in the ** outside scope. So we will NOT create a new struct or enum table. */ S = NewSymTable (SYMTAB_SIZE_BLOCK); S->PrevTab = SymTab; SymTab = S; } void LeaveStructLevel (void) /* Leave a nested block for a struct definition */ { /* Don't delete the table */ SymTab = SymTab->PrevTab; } /*****************************************************************************/ /* Find functions */ /*****************************************************************************/ static SymEntry* FindSymInTable (const SymTable* T, const char* Name, unsigned Hash) /* Search for an entry in one table */ { /* Get the start of the hash chain */ SymEntry* E = T->Tab [Hash % T->Size]; while (E) { /* Compare the name */ if (strcmp (E->Name, Name) == 0) { /* Found */ return E; } /* Not found, next entry in hash chain */ E = E->NextHash; } /* Not found */ return 0; } static SymEntry* FindSymInTree (const SymTable* Tab, const char* Name) /* Find the symbol with the given name in the table tree that starts with T */ { /* Get the hash over the name */ unsigned Hash = HashStr (Name); /* Check all symbol tables for the symbol */ while (Tab) { /* Try to find the symbol in this table */ SymEntry* E = FindSymInTable (Tab, Name, Hash); /* Bail out if we found it */ if (E != 0) { return E; } /* Repeat the search in the next higher lexical level */ Tab = Tab->PrevTab; } /* Not found */ return 0; } SymEntry* FindSym (const char* Name) /* Find the symbol with the given name */ { return FindSymInTree (SymTab, Name); } SymEntry* FindGlobalSym (const char* Name) /* Find the symbol with the given name in the global symbol table only */ { return FindSymInTable (SymTab0, Name, HashStr (Name)); } SymEntry* FindLocalSym (const char* Name) /* Find the symbol with the given name in the current symbol table only */ { return FindSymInTable (SymTab, Name, HashStr (Name)); } SymEntry* FindTagSym (const char* Name) /* Find the symbol with the given name in the tag table */ { return FindSymInTree (TagTab, Name); } SymEntry* FindStructField (const Type* T, const char* Name) /* Find a struct field in the fields list */ { SymEntry* Field = 0; /* The given type may actually be a pointer to struct */ if (IsTypePtr (T)) { ++T; } /* Non-structs do not have any struct fields... */ if (IsClassStruct (T)) { /* Get a pointer to the struct/union type */ const SymEntry* Struct = GetSymEntry (T); CHECK (Struct != 0); /* Now search in the struct symbol table. Beware: The table may not ** exist. */ if (Struct->V.S.SymTab) { Field = FindSymInTable (Struct->V.S.SymTab, Name, HashStr (Name)); } } return Field; } /*****************************************************************************/ /* Add stuff to the symbol table */ /*****************************************************************************/ static void AddSymEntry (SymTable* T, SymEntry* S) /* Add a symbol to a symbol table */ { /* Get the hash value for the name */ unsigned Hash = HashStr (S->Name) % T->Size; /* Insert the symbol into the list of all symbols in this level */ if (T->SymTail) { T->SymTail->NextSym = S; } S->PrevSym = T->SymTail; T->SymTail = S; if (T->SymHead == 0) { /* First symbol */ T->SymHead = S; } ++T->SymCount; /* Insert the symbol into the hash chain */ S->NextHash = T->Tab[Hash]; T->Tab[Hash] = S; /* Tell the symbol in which table it is */ S->Owner = T; } SymEntry* AddStructSym (const char* Name, unsigned Type, unsigned Size, SymTable* Tab) /* Add a struct/union entry and return it */ { SymEntry* Entry; /* Type must be struct or union */ PRECONDITION (Type == SC_STRUCT || Type == SC_UNION); /* Do we have an entry with this name already? */ Entry = FindSymInTable (TagTab, Name, HashStr (Name)); if (Entry) { /* We do have an entry. This may be a forward, so check it. */ if ((Entry->Flags & SC_TYPEMASK) != Type) { /* Existing symbol is not a struct */ Error ("Symbol '%s' is already different kind", Name); } else if (Size > 0 && Entry->V.S.Size > 0) { /* Both structs are definitions. */ Error ("Multiple definition for '%s'", Name); } else { /* Define the struct size if it is given */ if (Size > 0) { Entry->V.S.SymTab = Tab; Entry->V.S.Size = Size; } } } else { /* Create a new entry */ Entry = NewSymEntry (Name, Type); /* Set the struct data */ Entry->V.S.SymTab = Tab; Entry->V.S.Size = Size; /* Add it to the current table */ AddSymEntry (TagTab, Entry); } /* Return the entry */ return Entry; } SymEntry* AddBitField (const char* Name, unsigned Offs, unsigned BitOffs, unsigned Width) /* Add a bit field to the local symbol table and return the symbol entry */ { /* Do we have an entry with this name already? */ SymEntry* Entry = FindSymInTable (SymTab, Name, HashStr (Name)); if (Entry) { /* We have a symbol with this name already */ Error ("Multiple definition for '%s'", Name); } else { /* Create a new entry */ Entry = NewSymEntry (Name, SC_BITFIELD); /* Set the symbol attributes. Bit-fields are always of type unsigned */ Entry->Type = type_uint; Entry->V.B.Offs = Offs; Entry->V.B.BitOffs = BitOffs; Entry->V.B.BitWidth = Width; /* Add the entry to the symbol table */ AddSymEntry (SymTab, Entry); } /* Return the entry */ return Entry; } SymEntry* AddConstSym (const char* Name, const Type* T, unsigned Flags, long Val) /* Add an constant symbol to the symbol table and return it */ { /* Enums must be inserted in the global symbol table */ SymTable* Tab = ((Flags & SC_ENUM) == SC_ENUM)? SymTab0 : SymTab; /* Do we have an entry with this name already? */ SymEntry* Entry = FindSymInTable (Tab, Name, HashStr (Name)); if (Entry) { if ((Entry->Flags & SC_CONST) != SC_CONST) { Error ("Symbol '%s' is already different kind", Name); } else { Error ("Multiple definition for '%s'", Name); } return Entry; } /* Create a new entry */ Entry = NewSymEntry (Name, Flags); /* Enum values are ints */ Entry->Type = TypeDup (T); /* Set the enum data */ Entry->V.ConstVal = Val; /* Add the entry to the symbol table */ AddSymEntry (Tab, Entry); /* Return the entry */ return Entry; } DefOrRef* AddDefOrRef (SymEntry* E, unsigned Flags) /* Add definition or reference to the SymEntry and preserve its attributes */ { DefOrRef *DOR; DOR = xmalloc (sizeof (DefOrRef)); CollAppend (E->V.L.DefsOrRefs, DOR); DOR->Line = GetCurrentLine (); DOR->LocalsBlockId = (long)CollLast (&CurrentFunc->LocalsBlockStack); DOR->Flags = Flags; DOR->StackPtr = StackPtr; DOR->Depth = CollCount (&CurrentFunc->LocalsBlockStack); DOR->LateSP_Label = GetLocalLabel (); return DOR; } unsigned short FindSPAdjustment (const char* Name) /* Search for an entry in the table of SP adjustments */ { SymEntry* Entry = FindSymInTable (SPAdjustTab, Name, HashStr (Name)); if (!Entry) { Internal ("No SP adjustment label entry found"); } return Entry->V.SPAdjustment; } SymEntry* AddLabelSym (const char* Name, unsigned Flags) /* Add a goto label to the label table */ { unsigned i; DefOrRef *DOR, *NewDOR; /* We juggle it so much that a shortcut will help with clarity */ Collection *AIC = &CurrentFunc->LocalsBlockStack; /* Do we have an entry with this name already? */ SymEntry* Entry = FindSymInTable (LabelTab, Name, HashStr (Name)); if (Entry) { if (SymIsDef (Entry) && (Flags & SC_DEF) != 0) { /* Trying to define the label more than once */ Error ("Label '%s' is defined more than once", Name); } NewDOR = AddDefOrRef (Entry, Flags); /* Walk through all occurrences of the label so far and evaluate ** their relationship with the one passed to the function. */ for (i = 0; i < CollCount (Entry->V.L.DefsOrRefs); i++) { DOR = CollAt (Entry->V.L.DefsOrRefs, i); if ((DOR->Flags & SC_DEF) && (Flags & SC_REF) && (Flags & (SC_GOTO|SC_GOTO_IND))) { /* We're processing a goto and here is its destination label. ** This means the difference between SP values is already known, ** so we simply emit the SP adjustment code. */ if (StackPtr != DOR->StackPtr) { g_space (StackPtr - DOR->StackPtr); } /* Are we jumping into a block with initalization of an object that ** has automatic storage duration? Let's emit a warning. */ if ((long)CollLast (AIC) != DOR->LocalsBlockId && (CollCount (AIC) < DOR->Depth || (long)CollAt (AIC, DOR->Depth - 1) != DOR->LocalsBlockId)) { Warning ("Goto at line %d to label %s jumps into a block with " "initialization of an object that has automatic storage duration", GetCurrentLine (), Name); } } if ((DOR->Flags & SC_REF) && (DOR->Flags & (SC_GOTO|SC_GOTO_IND)) && (Flags & SC_DEF)) { /* We're processing a label, let's update all gotos encountered ** so far */ if (DOR->Flags & SC_GOTO) { SymEntry *E; g_userodata (); g_defdatalabel (DOR->LateSP_Label); g_defdata (CF_CONST | CF_INT, StackPtr - DOR->StackPtr, 0); /* Optimizer will need the information about the value of SP adjustment ** later, so let's preserve it. */ E = NewSymEntry (LocalLabelName (DOR->LateSP_Label), SC_SPADJUSTMENT); E->V.SPAdjustment = StackPtr - DOR->StackPtr; AddSymEntry (SPAdjustTab, E); } /* Are we jumping into a block with initalization of an object that ** has automatic storage duration? Let's emit a warning. */ if ((long)CollLast (AIC) != DOR->LocalsBlockId && (CollCount (AIC) >= DOR->Depth || (long)CollLast (AIC) >= (long)DOR->Line)) Warning ("Goto at line %d to label %s jumps into a block with " "initialization of an object that has automatic storage duration", DOR->Line, Name); } } Entry->Flags |= Flags; } else { /* Create a new entry */ Entry = NewSymEntry (Name, SC_LABEL | Flags); /* Set a new label number */ Entry->V.L.Label = GetLocalLabel (); Entry->V.L.IndJumpFrom = NULL; /* Create Collection for label definition and references */ Entry->V.L.DefsOrRefs = NewCollection (); NewDOR = AddDefOrRef (Entry, Flags); /* Generate the assembler name of the label */ Entry->AsmName = xstrdup (LocalLabelName (Entry->V.L.Label)); /* Add the entry to the label table */ AddSymEntry (LabelTab, Entry); } /* We are processing a goto, but the label has not yet been defined */ if (!SymIsDef (Entry) && (Flags & SC_REF) && (Flags & SC_GOTO)) { g_lateadjustSP (NewDOR->LateSP_Label); } /* Return the entry */ return Entry; } SymEntry* AddLocalSym (const char* Name, const Type* T, unsigned Flags, int Offs) /* Add a local symbol and return the symbol entry */ { /* Do we have an entry with this name already? */ SymEntry* Entry = FindSymInTable (SymTab, Name, HashStr (Name)); if (Entry) { /* We have a symbol with this name already */ Error ("Multiple definition for '%s'", Name); } else { /* Create a new entry */ Entry = NewSymEntry (Name, Flags); /* Set the symbol attributes */ Entry->Type = TypeDup (T); if ((Flags & SC_AUTO) == SC_AUTO) { Entry->V.Offs = Offs; } else if ((Flags & SC_REGISTER) == SC_REGISTER) { Entry->V.R.RegOffs = Offs; Entry->V.R.SaveOffs = StackPtr; } else if ((Flags & SC_EXTERN) == SC_EXTERN) { Entry->V.L.Label = Offs; SymSetAsmName (Entry); } else if ((Flags & SC_STATIC) == SC_STATIC) { /* Generate the assembler name from the label number */ Entry->V.L.Label = Offs; Entry->AsmName = xstrdup (LocalLabelName (Entry->V.L.Label)); } else if ((Flags & SC_STRUCTFIELD) == SC_STRUCTFIELD) { Entry->V.Offs = Offs; } else { Internal ("Invalid flags in AddLocalSym: %04X", Flags); } /* Add the entry to the symbol table */ AddSymEntry (SymTab, Entry); } /* Return the entry */ return Entry; } SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags) /* Add an external or global symbol to the symbol table and return the entry */ { /* There is some special handling for functions, so check if it is one */ int IsFunc = IsTypeFunc (T); /* Functions must be inserted in the global symbol table */ SymTable* Tab = IsFunc? SymTab0 : SymTab; /* Do we have an entry with this name already? */ SymEntry* Entry = FindSymInTable (Tab, Name, HashStr (Name)); if (Entry) { Type* EType; /* If the existing symbol is an enumerated constant, ** then avoid a compiler crash. See GitHub issue #728. */ if (Entry->Flags & SC_ENUM) { Fatal ("Can't redeclare enum constant '%s' as global variable", Name); } /* We have a symbol with this name already */ if (Entry->Flags & SC_TYPE) { Error ("Multiple definition for '%s'", Name); return Entry; } /* Get the type string of the existing symbol */ EType = Entry->Type; /* If we are handling arrays, the old entry or the new entry may be an ** incomplete declaration. Accept this, and if the exsting entry is ** incomplete, complete it. */ if (IsTypeArray (T) && IsTypeArray (EType)) { /* Get the array sizes */ long Size = GetElementCount (T); long ESize = GetElementCount (EType); if ((Size != UNSPECIFIED && ESize != UNSPECIFIED && Size != ESize) || TypeCmp (T + 1, EType + 1) < TC_EQUAL) { /* Types not identical: Conflicting types */ Error ("Conflicting types for '%s'", Name); return Entry; } else { /* Check if we have a size in the existing definition */ if (ESize == UNSPECIFIED) { /* Existing, size not given, use size from new def */ SetElementCount (EType, Size); } } } else { /* New type must be identical */ if (TypeCmp (EType, T) < TC_EQUAL) { Error ("Conflicting types for '%s'", Name); return Entry; } /* In case of a function, use the new type descriptor, since it ** contains pointers to the new symbol tables that are needed if ** an actual function definition follows. Be sure not to use the ** new descriptor if it contains a function declaration with an ** empty parameter list. */ if (IsFunc) { /* Get the function descriptor from the new type */ FuncDesc* F = GetFuncDesc (T); /* Use this new function descriptor if it doesn't contain ** an empty parameter list. */ if ((F->Flags & FD_EMPTY) == 0) { Entry->V.F.Func = F; SetFuncDesc (EType, F); } } } /* 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_STORAGE)) == 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; } else { /* Create a new entry */ Entry = NewSymEntry (Name, Flags); /* Set the symbol attributes */ Entry->Type = TypeDup (T); /* If this is a function, set the function descriptor and clear ** additional fields. */ if (IsFunc) { Entry->V.F.Func = GetFuncDesc (Entry->Type); Entry->V.F.Seg = 0; } /* Add the assembler name of the symbol */ SymSetAsmName (Entry); /* Add the entry to the symbol table */ AddSymEntry (Tab, Entry); } /* Return the entry */ return Entry; } /*****************************************************************************/ /* Code */ /*****************************************************************************/ SymTable* GetSymTab (void) /* Return the current symbol table */ { return SymTab; } SymTable* GetGlobalSymTab (void) /* Return the global symbol table */ { return SymTab0; } SymTable* GetLabelSymTab (void) /* Return the global symbol table */ { return LabelTab; } int SymIsLocal (SymEntry* Sym) /* Return true if the symbol is defined in the highest lexical level */ { return (Sym->Owner == SymTab || Sym->Owner == TagTab); } void MakeZPSym (const char* Name) /* Mark the given symbol as zero page symbol */ { /* Get the symbol table entry */ SymEntry* Entry = FindSymInTable (SymTab, Name, HashStr (Name)); /* Mark the symbol as zeropage */ if (Entry) { Entry->Flags |= SC_ZEROPAGE; } else { Error ("Undefined symbol: '%s'", Name); } } void PrintSymTable (const SymTable* Tab, FILE* F, const char* Header, ...) /* Write the symbol table to the given file */ { unsigned Len; const SymEntry* Entry; /* Print the header */ va_list ap; va_start (ap, Header); fputc ('\n', F); Len = vfprintf (F, Header, ap); va_end (ap); fputc ('\n', F); /* Underline the header */ while (Len--) { fputc ('=', F); } fputc ('\n', F); /* Dump the table */ Entry = Tab->SymHead; if (Entry == 0) { fprintf (F, "(empty)\n"); } else { while (Entry) { DumpSymEntry (F, Entry); Entry = Entry->NextSym; } } fprintf (F, "\n\n\n"); } void EmitExternals (void) /* Write import/export statements for external symbols */ { SymEntry* Entry; Entry = SymTab->SymHead; while (Entry) { unsigned Flags = Entry->Flags; if (Flags & SC_EXTERN) { /* Only defined or referenced externs */ if (SymIsRef (Entry) && !SymIsDef (Entry)) { /* An import */ g_defimport (Entry->Name, Flags & SC_ZEROPAGE); } else if (SymIsDef (Entry)) { /* An export */ g_defexport (Entry->Name, Flags & SC_ZEROPAGE); } } Entry = Entry->NextSym; } } void EmitDebugInfo (void) /* Emit debug infos for the locals of the current scope */ { const char* Head; const SymEntry* Sym; /* Output info for locals if enabled */ if (DebugInfo) { /* For cosmetic reasons in the output file, we will insert two tabs ** on global level and just one on local level. */ if (LexicalLevel == LEX_LEVEL_GLOBAL) { Head = "\t.dbg\t\tsym"; } else { Head = "\t.dbg\tsym"; } Sym = SymTab->SymHead; while (Sym) { if ((Sym->Flags & (SC_CONST|SC_TYPE)) == 0) { if (Sym->Flags & SC_AUTO) { AddTextLine ("%s, \"%s\", \"00\", auto, %d", Head, Sym->Name, Sym->V.Offs); } else if (Sym->Flags & SC_REGISTER) { AddTextLine ("%s, \"%s\", \"00\", register, \"regbank\", %d", Head, Sym->Name, Sym->V.R.RegOffs); } else if (SymIsRef (Sym) && !SymIsDef (Sym)) { AddTextLine ("%s, \"%s\", \"00\", %s, \"%s\"", Head, Sym->Name, (Sym->Flags & SC_EXTERN)? "extern" : "static", Sym->AsmName); } } Sym = Sym->NextSym; } } } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/symtab.h�������������������������������������������������������������������������0000664�0000000�0000000�00000017115�13473601511�0015211�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* symtab.h */ /* */ /* Symbol table management for the cc65 C compiler */ /* */ /* */ /* */ /* (C) 2000-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef SYMTAB_H #define SYMTAB_H #include <stdio.h> #include "datatype.h" #include "symentry.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Symbol table */ typedef struct SymTable SymTable; struct SymTable { SymTable* PrevTab; /* Pointer to higher level symbol table */ SymEntry* SymHead; /* Double linked list of symbols */ SymEntry* SymTail; /* Double linked list of symbols */ unsigned SymCount; /* Count of symbols in this table */ unsigned Size; /* Size of table */ SymEntry* Tab[1]; /* Actual table, dynamically allocated */ }; /* An empty symbol table */ extern SymTable EmptySymTab; /* Forwards */ struct FuncDesc; /* Predefined lexical levels */ #define LEX_LEVEL_GLOBAL 1U #define LEX_LEVEL_FUNCTION 2U /*****************************************************************************/ /* Handling of lexical levels */ /*****************************************************************************/ unsigned GetLexicalLevel (void); /* Return the current lexical level */ void EnterGlobalLevel (void); /* Enter the program global lexical level */ void LeaveGlobalLevel (void); /* Leave the program global lexical level */ void EnterFunctionLevel (void); /* Enter function lexical level */ void RememberFunctionLevel (struct FuncDesc* F); /* Remember the symbol tables for the level and leave the level without checks */ void ReenterFunctionLevel (struct FuncDesc* F); /* Reenter the function lexical level using the existing tables from F */ void LeaveFunctionLevel (void); /* Leave function lexical level */ void EnterBlockLevel (void); /* Enter a nested block in a function */ void LeaveBlockLevel (void); /* Leave a nested block in a function */ void EnterStructLevel (void); /* Enter a nested block for a struct definition */ void LeaveStructLevel (void); /* Leave a nested block for a struct definition */ /*****************************************************************************/ /* Find functions */ /*****************************************************************************/ SymEntry* FindSym (const char* Name); /* Find the symbol with the given name */ SymEntry* FindGlobalSym (const char* Name); /* Find the symbol with the given name in the global symbol table only */ SymEntry* FindLocalSym (const char* Name); /* Find the symbol with the given name in the current symbol table only */ SymEntry* FindTagSym (const char* Name); /* Find the symbol with the given name in the tag table */ SymEntry* FindStructField (const Type* TypeArray, const char* Name); /* Find a struct field in the fields list */ unsigned short FindSPAdjustment (const char* Name); /* Search for an entry in the table of SP adjustments */ /*****************************************************************************/ /* Add stuff to the symbol table */ /*****************************************************************************/ SymEntry* AddStructSym (const char* Name, unsigned Type, unsigned Size, SymTable* Tab); /* Add a struct/union entry and return it */ SymEntry* AddBitField (const char* Name, unsigned Offs, unsigned BitOffs, unsigned Width); /* Add a bit field to the local symbol table and return the symbol entry */ SymEntry* AddConstSym (const char* Name, const Type* T, unsigned Flags, long Val); /* Add an constant symbol to the symbol table and return it */ SymEntry* AddLabelSym (const char* Name, unsigned Flags); /* Add a goto label to the symbol table */ SymEntry* AddLocalSym (const char* Name, const Type* T, unsigned Flags, int Offs); /* Add a local symbol and return the symbol entry */ SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags); /* Add an external or global symbol to the symbol table and return the entry */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ SymTable* GetSymTab (void); /* Return the current symbol table */ SymTable* GetGlobalSymTab (void); /* Return the global symbol table */ SymTable* GetLabelSymTab (void); /* Return the label symbol table */ int SymIsLocal (SymEntry* Sym); /* Return true if the symbol is defined in the highest lexical level */ void MakeZPSym (const char* Name); /* Mark the given symbol as zero page symbol */ void PrintSymTable (const SymTable* Tab, FILE* F, const char* Header, ...); /* Write the symbol table to the given file */ void EmitExternals (void); /* Write import/export statements for external symbols */ void EmitDebugInfo (void); /* Emit debug infos for the locals of the current scope */ /* End of symtab.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/testexpr.c�����������������������������������������������������������������������0000664�0000000�0000000�00000011361�13473601511�0015560�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* testexpr.c */ /* */ /* Test an expression and jump */ /* */ /* */ /* */ /* (C) 2004 Ullrich von Bassewitz */ /* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* cc65 */ #include "codegen.h" #include "error.h" #include "expr.h" #include "loadexpr.h" #include "scanner.h" #include "testexpr.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned Test (unsigned Label, int Invert) /* Evaluate a boolean test expression and jump depending on the result of ** the test and on Invert. The function returns one of the TESTEXPR_xx codes ** defined above. If the jump is always true, a warning is output. */ { ExprDesc Expr; unsigned Result; /* Read a boolean expression */ BoolExpr (hie0, &Expr); /* Check for a constant expression */ if (ED_IsConstAbs (&Expr)) { /* Result is constant, so we know the outcome */ Result = (Expr.IVal != 0); /* Constant rvalue */ if (!Invert && Expr.IVal == 0) { g_jump (Label); Warning ("Unreachable code"); } else if (Invert && Expr.IVal != 0) { g_jump (Label); } } else { /* Result is unknown */ Result = TESTEXPR_UNKNOWN; /* If the expr hasn't set condition codes, set the force-test flag */ if (!ED_IsTested (&Expr)) { ED_MarkForTest (&Expr); } /* Load the value into the primary register */ LoadExpr (CF_FORCECHAR, &Expr); /* Generate the jump */ if (Invert) { g_truejump (CF_NONE, Label); } else { g_falsejump (CF_NONE, Label); } } /* Return the result */ return Result; } unsigned TestInParens (unsigned Label, int Invert) /* Evaluate a boolean test expression in parenthesis and jump depending on ** the result of the test * and on Invert. The function returns one of the ** TESTEXPR_xx codes defined above. If the jump is always true, a warning is ** output. */ { unsigned Result; /* Eat the parenthesis */ ConsumeLParen (); /* Do the test */ Result = Test (Label, Invert); /* Check for the closing brace */ ConsumeRParen (); /* Return the result of the expression */ return Result; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/testexpr.h�����������������������������������������������������������������������0000664�0000000�0000000�00000007475�13473601511�0015600�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* test.h */ /* */ /* Test an expression and jump */ /* */ /* */ /* */ /* (C) 2004 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef TESTEXPR_H #define TESTEXPR_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ #define TESTEXPR_UNKNOWN 0 /* Result of expression unknown */ #define TESTEXPR_TRUE 1 /* Expression yields true */ #define TESTEXPR_FALSE 2 /* Expression yields false */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned Test (unsigned Label, int Invert); /* Evaluate a boolean test expression and jump depending on the result of ** the test and on Invert. The function returns one of the TESTEXPR_xx codes ** defined above. If the jump is always true, a warning is output. */ unsigned TestInParens (unsigned Label, int Invert); /* Evaluate a boolean test expression in parenthesis and jump depending on ** the result of the test * and on Invert. The function returns one of the ** TESTEXPR_xx codes defined above. If the jump is always true, a warning is ** output. */ /* End of testexpr.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/textseg.c������������������������������������������������������������������������0000664�0000000�0000000�00000010457�13473601511�0015372�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* textseg.c */ /* */ /* Text segment structure */ /* */ /* */ /* */ /* (C) 2001-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* Note: This is NOT some sort of code segment, it is used to store lines of ** output that are textual (not real code) instead. */ /* common */ #include "xmalloc.h" #include "xsprintf.h" /* cc65 */ #include "output.h" #include "textseg.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ TextSeg* NewTextSeg (SymEntry* Func) /* Create a new text segment, initialize and return it */ { /* Allocate memory for the structure */ TextSeg* S = xmalloc (sizeof (TextSeg)); /* Initialize the fields */ S->Func = Func; InitCollection (&S->Lines); /* Return the new struct */ return S; } void TS_AddVLine (TextSeg* S, const char* Format, va_list ap) /* Add a line to the given text segment */ { /* Format the line */ char Buf [256]; xvsprintf (Buf, sizeof (Buf), Format, ap); /* Add a copy to the data segment */ CollAppend (&S->Lines, xstrdup (Buf)); } void TS_AddLine (TextSeg* S, const char* Format, ...) /* Add a line to the given text segment */ { va_list ap; va_start (ap, Format); TS_AddVLine (S, Format, ap); va_end (ap); } void TS_Output (const TextSeg* S) /* Output the text segment data to the output file */ { unsigned I; /* Get the number of entries in this segment */ unsigned Count = CollCount (&S->Lines); /* If the segment is actually empty, bail out */ if (Count == 0) { return; } /* Output all entries */ for (I = 0; I < Count; ++I) { WriteOutput ("%s\n", (const char*) CollConstAt (&S->Lines, I)); } /* Add an additional newline after the segment output */ WriteOutput ("\n"); } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/textseg.h������������������������������������������������������������������������0000664�0000000�0000000�00000007645�13473601511�0015404�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* textseg.h */ /* */ /* Text segment structure */ /* */ /* */ /* */ /* (C) 2001-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* Note: This is NOT some sort of code segment, it is used to store lines of ** output that are textual (not real code) instead. */ #ifndef TEXTSEG_H #define TEXTSEG_H #include <stdarg.h> /* common */ #include "attrib.h" #include "coll.h" /* cc65 */ #include "symentry.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ typedef struct TextSeg TextSeg; struct TextSeg { SymEntry* Func; /* Owner function */ Collection Lines; /* List of text lines */ }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ TextSeg* NewTextSeg (SymEntry* Func); /* Create a new text segment, initialize and return it */ void TS_AddVLine (TextSeg* S, const char* Format, va_list ap) attribute ((format(printf,2,0))); /* Add a line to the given text segment */ void TS_AddLine (TextSeg* S, const char* Format, ...) attribute ((format(printf,2,3))); /* Add a line to the given text segment */ void TS_Output (const TextSeg* S); /* Output the text segment data to the output file */ /* End of textseg.h */ #endif �������������������������������������������������������������������������������������������cc65-2.18/src/cc65/typecmp.c������������������������������������������������������������������������0000664�0000000�0000000�00000036407�13473601511�0015373�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* typecmp.c */ /* */ /* Type compare function for the cc65 C compiler */ /* */ /* */ /* */ /* (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 */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* cc65 */ #include "funcdesc.h" #include "global.h" #include "symtab.h" #include "typecmp.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void SetResult (typecmp_t* Result, typecmp_t Val) /* Set a new result value if it is less than the existing one */ { if (Val < *Result) { /* printf ("SetResult = %d\n", Val); */ *Result = Val; } } static int ParamsHaveDefaultPromotions (const FuncDesc* F) /* Check if any of the parameters of function F has a default promotion. In ** this case, the function is not compatible with an empty parameter name list ** declaration. */ { /* Get the symbol table */ const SymTable* Tab = F->SymTab; /* Get the first parameter in the list */ const SymEntry* Sym = Tab->SymHead; /* Walk over all parameters */ while (Sym && (Sym->Flags & SC_PARAM)) { /* If this is an integer type, check if the promoted type is equal ** to the original type. If not, we have a default promotion. */ if (IsClassInt (Sym->Type)) { if (IntPromotion (Sym->Type) != Sym->Type) { return 1; } } /* Get the pointer to the next param */ Sym = Sym->NextSym; } /* No default promotions in the parameter list */ return 0; } static int EqualFuncParams (const FuncDesc* F1, const FuncDesc* F2) /* Compare two function symbol tables regarding function parameters. Return 1 ** if they are equal and 0 otherwise. */ { /* Get the symbol tables */ const SymTable* Tab1 = F1->SymTab; const SymTable* Tab2 = F2->SymTab; /* Compare the parameter lists */ const SymEntry* Sym1 = Tab1->SymHead; const SymEntry* Sym2 = Tab2->SymHead; /* Compare the fields */ while (Sym1 && (Sym1->Flags & SC_PARAM) && Sym2 && (Sym2->Flags & SC_PARAM)) { /* Get the symbol types */ Type* Type1 = Sym1->Type; Type* Type2 = Sym2->Type; /* If either of both functions is old style, apply the default ** promotions to the parameter type. */ if (F1->Flags & FD_OLDSTYLE) { if (IsClassInt (Type1)) { Type1 = IntPromotion (Type1); } } if (F2->Flags & FD_OLDSTYLE) { if (IsClassInt (Type2)) { Type2 = IntPromotion (Type2); } } /* Compare this field */ if (TypeCmp (Type1, Type2) < TC_EQUAL) { /* Field types not equal */ return 0; } /* Get the pointers to the next fields */ Sym1 = Sym1->NextSym; Sym2 = Sym2->NextSym; } /* Check both pointers against NULL or a non parameter to compare the ** field count */ return (Sym1 == 0 || (Sym1->Flags & SC_PARAM) == 0) && (Sym2 == 0 || (Sym2->Flags & SC_PARAM) == 0); } static int EqualSymTables (SymTable* Tab1, SymTable* Tab2) /* Compare two symbol tables. Return 1 if they are equal and 0 otherwise */ { /* Compare the parameter lists */ SymEntry* Sym1 = Tab1->SymHead; SymEntry* Sym2 = Tab2->SymHead; /* Compare the fields */ while (Sym1 && Sym2) { /* Compare the names of this field */ if (!HasAnonName (Sym1) || !HasAnonName (Sym2)) { if (strcmp (Sym1->Name, Sym2->Name) != 0) { /* Names are not identical */ return 0; } } /* Compare the types of this field */ if (TypeCmp (Sym1->Type, Sym2->Type) < TC_EQUAL) { /* Field types not equal */ return 0; } /* Get the pointers to the next fields */ Sym1 = Sym1->NextSym; Sym2 = Sym2->NextSym; } /* Check both pointers against NULL to compare the field count */ return (Sym1 == 0 && Sym2 == 0); } static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) /* Recursively compare two types. */ { unsigned Indirections; unsigned ElementCount; SymEntry* Sym1; SymEntry* Sym2; SymTable* Tab1; SymTable* Tab2; FuncDesc* F1; FuncDesc* F2; /* Initialize stuff */ Indirections = 0; ElementCount = 0; /* Compare two types. Determine, where they differ */ while (lhs->C != T_END) { TypeCode LeftType, RightType; TypeCode LeftSign, RightSign; TypeCode LeftQual, RightQual; long LeftCount, RightCount; /* Check if the end of the type string is reached */ if (rhs->C == T_END) { /* End of comparison reached */ return; } /* Get the raw left and right types, signs and qualifiers */ LeftType = GetType (lhs); RightType = GetType (rhs); LeftSign = GetSignedness (lhs); RightSign = GetSignedness (rhs); LeftQual = GetQualifier (lhs); RightQual = GetQualifier (rhs); /* If the left type is a pointer and the right is an array, both ** are compatible. */ if (LeftType == T_TYPE_PTR && RightType == T_TYPE_ARRAY) { RightType = T_TYPE_PTR; } /* If the raw types are not identical, the types are incompatible */ if (LeftType != RightType) { SetResult (Result, TC_INCOMPATIBLE); return; } /* On indirection level zero, a qualifier or sign difference is ** accepted. The types are no longer equal, but compatible. */ if (LeftSign != RightSign) { if (ElementCount == 0) { SetResult (Result, TC_SIGN_DIFF); } else { SetResult (Result, TC_INCOMPATIBLE); 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 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 ** const one to the left, same for volatile. */ if ((LeftQual & T_QUAL_CONST) < (RightQual & T_QUAL_CONST) || (LeftQual & T_QUAL_VOLATILE) < (RightQual & T_QUAL_VOLATILE)) { SetResult (Result, TC_QUAL_DIFF); } else { SetResult (Result, TC_STRICT_COMPATIBLE); } if (LeftType != T_TYPE_FUNC || (LeftQual & T_QUAL_CCONV) == (RightQual & T_QUAL_CCONV)) { break; } /* else fall through */ default: SetResult (Result, TC_INCOMPATIBLE); return; } } /* Check for special type elements */ switch (LeftType) { case T_TYPE_PTR: ++Indirections; break; case T_TYPE_FUNC: /* Compare the function descriptors */ F1 = GetFuncDesc (lhs); F2 = GetFuncDesc (rhs); /* If one of both functions has an empty parameter list (which ** does also mean, it is not a function definition, because the ** flag is reset in this case), it is considered equal to any ** other definition, provided that the other has no default ** promotions in the parameter list. If none of both parameter ** lists is empty, we have to check the parameter lists and ** other attributes. */ if (F1->Flags & FD_EMPTY) { if ((F2->Flags & FD_EMPTY) == 0) { if (ParamsHaveDefaultPromotions (F2)) { /* Flags differ */ SetResult (Result, TC_INCOMPATIBLE); return; } } } else if (F2->Flags & FD_EMPTY) { if (ParamsHaveDefaultPromotions (F1)) { /* Flags differ */ SetResult (Result, TC_INCOMPATIBLE); return; } } else { /* Check the remaining flags */ if ((F1->Flags & ~FD_IGNORE) != (F2->Flags & ~FD_IGNORE)) { /* Flags differ */ SetResult (Result, TC_INCOMPATIBLE); return; } /* Compare the parameter lists */ if (EqualFuncParams (F1, F2) == 0) { /* Parameter list is not identical */ SetResult (Result, TC_INCOMPATIBLE); return; } } /* Keep on and compare the return type */ break; case T_TYPE_ARRAY: /* Check member count */ LeftCount = GetElementCount (lhs); RightCount = GetElementCount (rhs); if (LeftCount != UNSPECIFIED && RightCount != UNSPECIFIED && LeftCount != RightCount) { /* Member count given but different */ SetResult (Result, TC_INCOMPATIBLE); return; } break; case T_TYPE_STRUCT: case T_TYPE_UNION: /* Compare the fields recursively. To do that, we fetch the ** pointer to the struct definition from the type, and compare ** the fields. */ Sym1 = GetSymEntry (lhs); Sym2 = GetSymEntry (rhs); /* If one symbol has a name, the names must be identical */ if (!HasAnonName (Sym1) || !HasAnonName (Sym2)) { if (strcmp (Sym1->Name, Sym2->Name) != 0) { /* Names are not identical */ SetResult (Result, TC_INCOMPATIBLE); return; } } /* Get the field tables from the struct entry */ Tab1 = Sym1->V.S.SymTab; Tab2 = Sym2->V.S.SymTab; /* One or both structs may be forward definitions. In this case, ** the symbol tables are both non existant. Assume that the ** structs are equal in this case. */ if (Tab1 != 0 && Tab2 != 0) { if (EqualSymTables (Tab1, Tab2) == 0) { /* Field lists are not equal */ SetResult (Result, TC_INCOMPATIBLE); return; } } /* Structs are equal */ break; } /* Next type string element */ ++lhs; ++rhs; ++ElementCount; } /* Check if end of rhs reached */ if (rhs->C == T_END) { SetResult (Result, TC_EQUAL); } else { SetResult (Result, TC_INCOMPATIBLE); } } typecmp_t TypeCmp (const Type* lhs, const Type* rhs) /* Compare two types and return the result */ { /* Assume the types are identical */ typecmp_t Result = TC_IDENTICAL; #if 0 printf ("Left : "); PrintRawType (stdout, lhs); printf ("Right: "); PrintRawType (stdout, rhs); #endif /* Recursively compare the types if they aren't identical */ if (rhs != lhs) { DoCompare (lhs, rhs, &Result); } /* Return the result */ return Result; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/typecmp.h������������������������������������������������������������������������0000664�0000000�0000000�00000007266�13473601511�0015401�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* typecmp.h */ /* */ /* Type compare function for the cc65 C compiler */ /* */ /* */ /* */ /* (C) 1998-2000 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 TYPECMP_H #define TYPECMP_H #include "datatype.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Degree of type compatibility. Must be in ascending order */ typedef enum { TC_INCOMPATIBLE, /* Distinct types */ TC_SIGN_DIFF, /* Signedness differs */ TC_COMPATIBLE = TC_SIGN_DIFF, /* Compatible types */ TC_QUAL_DIFF, /* Types differ in qualifier of pointer */ TC_STRICT_COMPATIBLE, /* Strict compatibility */ TC_EQUAL, /* Types are equal */ TC_IDENTICAL /* Types are identical */ } typecmp_t; /*****************************************************************************/ /* Code */ /*****************************************************************************/ typecmp_t TypeCmp (const Type* lhs, const Type* rhs); /* Compare two types and return the result */ /* End of typecmp.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/typeconv.c�����������������������������������������������������������������������0000664�0000000�0000000�00000024133�13473601511�0015552�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* typeconv.c */ /* */ /* Handle type conversions */ /* */ /* */ /* */ /* (C) 2002-2008 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "shift.h" /* cc65 */ #include "codegen.h" #include "datatype.h" #include "declare.h" #include "error.h" #include "expr.h" #include "loadexpr.h" #include "scanner.h" #include "typecmp.h" #include "typeconv.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void DoConversion (ExprDesc* Expr, const Type* NewType) /* Emit code to convert the given expression to a new type. */ { Type* OldType; unsigned OldSize; unsigned NewSize; /* Remember the old type */ OldType = Expr->Type; /* If we're converting to void, we're done. Note: This does also cover a ** conversion void -> void. */ if (IsTypeVoid (NewType)) { ED_MakeRVal (Expr); /* Never an lvalue */ goto ExitPoint; } /* Don't allow casts from void to something else. */ if (IsTypeVoid (OldType)) { Error ("Cannot convert from 'void' to something else"); goto ExitPoint; } /* Get the sizes of the types. Since we've excluded void types, checking ** for known sizes makes sense here. */ OldSize = CheckedSizeOf (OldType); NewSize = CheckedSizeOf (NewType); /* lvalue? */ if (ED_IsLVal (Expr)) { /* We have an lvalue. If the new size is smaller than the old one, ** we don't need to do anything. The compiler will generate code ** to load only the portion of the value that is actually needed. ** This works only on a little endian architecture, but that's ** what we support. ** If both sizes are equal, do also leave the value alone. ** If the new size is larger, we must convert the value. */ if (NewSize > OldSize) { /* Load the value into the primary */ LoadExpr (CF_NONE, Expr); /* Emit typecast code */ g_typecast (TypeOf (NewType), TypeOf (OldType) | CF_FORCECHAR); /* Value is now in primary and an rvalue */ ED_MakeRValExpr (Expr); } } else if (ED_IsLocAbs (Expr)) { /* A cast of a constant numeric value to another type. Be sure ** to handle sign extension correctly. */ /* Get the current and new size of the value */ unsigned OldBits = OldSize * 8; unsigned NewBits = NewSize * 8; /* Check if the new datatype will have a smaller range. If it ** has a larger range, things are OK, since the value is ** internally already represented by a long. */ if (NewBits <= OldBits) { /* Cut the value to the new size */ Expr->IVal &= (0xFFFFFFFFUL >> (32 - NewBits)); /* If the new type is signed, sign extend the value */ if (IsSignSigned (NewType)) { if (Expr->IVal & (0x01UL << (NewBits-1))) { /* Beware: Use the safe shift routine here. */ Expr->IVal |= shl_l (~0UL, NewBits); } } } } else { /* The value is not a constant. If the sizes of the types are ** not equal, add conversion code. Be sure to convert chars ** correctly. */ if (OldSize != NewSize) { /* Load the value into the primary */ LoadExpr (CF_NONE, Expr); /* Emit typecast code. */ g_typecast (TypeOf (NewType), TypeOf (OldType) | CF_FORCECHAR); /* Value is now a rvalue in the primary */ ED_MakeRValExpr (Expr); } } ExitPoint: /* The expression has always the new type */ ReplaceType (Expr, NewType); } void TypeConversion (ExprDesc* Expr, Type* NewType) /* Do an automatic conversion of the given expression to the new type. Output ** warnings or errors where this automatic conversion is suspicious or ** impossible. */ { #if 0 /* Debugging */ printf ("Expr:\n=======================================\n"); PrintExprDesc (stdout, Expr); printf ("Type:\n=======================================\n"); PrintType (stdout, NewType); printf ("\n"); PrintRawType (stdout, NewType); #endif /* First, do some type checking */ if (IsTypeVoid (NewType) || IsTypeVoid (Expr->Type)) { /* If one of the sides are of type void, output a more apropriate ** error message. */ Error ("Illegal type"); } /* If Expr is a function, convert it to pointer to function */ if (IsTypeFunc(Expr->Type)) { Expr->Type = PointerTo (Expr->Type); } /* If both types are equal, no conversion is needed */ if (TypeCmp (Expr->Type, NewType) >= TC_EQUAL) { /* We're already done */ return; } /* Check for conversion problems */ if (IsClassInt (NewType)) { /* Handle conversions to int type */ if (IsClassPtr (Expr->Type)) { /* Pointer -> int conversion. Convert array to pointer */ if (IsTypeArray (Expr->Type)) { Expr->Type = ArrayToPtr (Expr->Type); } Warning ("Converting pointer to integer without a cast"); } else if (!IsClassInt (Expr->Type) && !IsClassFloat (Expr->Type)) { Error ("Incompatible types"); } } else if (IsClassFloat (NewType)) { if (!IsClassFloat (Expr->Type) && !IsClassInt (Expr->Type)) { Error ("Incompatible types"); } } else if (IsClassPtr (NewType)) { /* Handle conversions to pointer type */ if (IsClassPtr (Expr->Type)) { /* Convert array to pointer */ if (IsTypeArray (Expr->Type)) { Expr->Type = ArrayToPtr (Expr->Type); } /* Pointer to pointer assignment is valid, if: ** - both point to the same types, or ** - the rhs pointer is a void pointer, or ** - the lhs pointer is a void pointer. */ if (!IsTypeVoid (Indirect (NewType)) && !IsTypeVoid (Indirect (Expr->Type))) { /* Compare the types */ switch (TypeCmp (NewType, Expr->Type)) { case TC_INCOMPATIBLE: Error ("Incompatible pointer types at '%s'", (Expr->Sym? Expr->Sym->Name : "Unknown")); break; case TC_QUAL_DIFF: Error ("Pointer types differ in type qualifiers"); break; default: /* Ok */ break; } } } else if (IsClassInt (Expr->Type)) { /* Int to pointer assignment is valid only for constant zero */ if (!ED_IsConstAbsInt (Expr) || Expr->IVal != 0) { Warning ("Converting integer to pointer without a cast"); } } else { Error ("Incompatible types"); } } else { /* Invalid automatic conversion */ Error ("Incompatible types"); } /* Do the actual conversion */ DoConversion (Expr, NewType); } void TypeCast (ExprDesc* Expr) /* Handle an explicit cast. */ { Type NewType[MAXTYPELEN]; /* Skip the left paren */ NextToken (); /* Read the type */ ParseType (NewType); /* Closing paren */ ConsumeRParen (); /* Read the expression we have to cast */ hie10 (Expr); /* Convert functions and arrays to "pointer to" object */ Expr->Type = PtrConversion (Expr->Type); /* Convert the value. */ DoConversion (Expr, NewType); } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/typeconv.h�����������������������������������������������������������������������0000664�0000000�0000000�00000006202�13473601511�0015554�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* typeconv.h */ /* */ /* Handle type conversions */ /* */ /* */ /* */ /* (C) 2002-2008 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef TYPECONV_H #define TYPECONV_H /* cc65 */ #include "exprdesc.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void TypeConversion (ExprDesc* Expr, Type* NewType); /* Do an automatic conversion of the given expression to the new type. Output ** warnings or errors where this automatic conversion is suspicious or ** impossible. */ void TypeCast (ExprDesc* Expr); /* Handle an explicit cast. */ /* End of typeconv.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/util.c���������������������������������������������������������������������������0000664�0000000�0000000�00000006077�13473601511�0014667�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* util.c */ /* */ /* Utility functions for the cc65 C compiler */ /* */ /* */ /* */ /* (C) 1998-2004 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include "util.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ int PowerOf2 (unsigned long Val) /* Return the exponent if val is a power of two. Return -1 if val is not a ** power of two. */ { int I; unsigned long Mask = 0x0001; for (I = 0; I < 32; ++I) { if (Val == Mask) { return I; } Mask <<= 1; } return -1; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/util.h���������������������������������������������������������������������������0000664�0000000�0000000�00000005667�13473601511�0014700�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* util.h */ /* */ /* Utility functions for the cc65 C compiler */ /* */ /* */ /* */ /* (C) 1998-2004 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef UTIL_H #define UTIL_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ int PowerOf2 (unsigned long Val); /* Return the exponent if val is a power of two. Return -1 if val is not a ** power of two. */ /* End of util.h */ #endif �������������������������������������������������������������������������cc65-2.18/src/cc65/wrappedcall.c��������������������������������������������������������������������0000664�0000000�0000000�00000007440�13473601511�0016203�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* wrappedcall.c */ /* */ /* WrappedCall management */ /* */ /* */ /* */ /* (C) 2017, Mega Cat Studios */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdarg.h> #include <string.h> /* common */ #include "chartype.h" #include "check.h" #include "coll.h" #include "scanner.h" #include "intptrstack.h" #include "xmalloc.h" /* cc65 */ #include "codeent.h" #include "error.h" #include "wrappedcall.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* WrappedCalls */ static IntPtrStack WrappedCalls; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void PushWrappedCall (void *Ptr, unsigned char Val) /* Push the current WrappedCall */ { if (IPS_IsFull (&WrappedCalls)) { Error ("WrappedCall stack overflow"); } else { IPS_Push (&WrappedCalls, Val, Ptr); } } void PopWrappedCall (void) /* Remove the current WrappedCall */ { if (IPS_GetCount (&WrappedCalls) < 1) { Error ("WrappedCall stack is empty"); } else { IPS_Drop (&WrappedCalls); } } void GetWrappedCall (void **Ptr, unsigned char *Val) /* Get the current WrappedCall */ { if (IPS_GetCount (&WrappedCalls) < 1) { *Ptr = NULL; *Val = 0; } else { long Temp; IPS_Get (&WrappedCalls, &Temp, Ptr); *Val = (unsigned char) Temp; } } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cc65/wrappedcall.h��������������������������������������������������������������������0000664�0000000�0000000�00000005652�13473601511�0016213�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* wrappedcall.h */ /* */ /* Wrapped-call management */ /* */ /* */ /* */ /* (C) 2017, Mega Cat Studios */ /* */ /* */ /* 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 WRAPPEDCALL_H #define WRAPPEDCALL_H #include <stdio.h> /* common */ #include "attrib.h" /* cc65 */ #include "opcodes.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void PushWrappedCall (void *Ptr, unsigned char Val); /* Push the current WrappedCall */ void PopWrappedCall (void); /* Pop the current WrappedCall */ void GetWrappedCall (void **Ptr, unsigned char *Val); /* Get the current WrappedCall, if any */ /* End of wrappedcall.h */ #endif ��������������������������������������������������������������������������������������cc65-2.18/src/chrcvt65.vcxproj����������������������������������������������������������������������0000664�0000000�0000000�00000010346�13473601511�0016061�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> <ProjectConfiguration Include="Release|Win32"> <Configuration>Release</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> </ItemGroup> <PropertyGroup Label="Globals"> <ProjectGuid>{1C7A3FEF-DD0B-4B10-BC33-C3BE29BF67CC}</ProjectGuid> <Keyword>Win32Proj</Keyword> <RootNamespace>chrcvt65</RootNamespace> <WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <UseDebugLibraries>true</UseDebugLibraries> <PlatformToolset>v141</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <UseDebugLibraries>false</UseDebugLibraries> <WholeProgramOptimization>true</WholeProgramOptimization> <PlatformToolset>v141</PlatformToolset> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <PropertyGroup Label="UserMacros" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <LinkIncremental>true</LinkIncremental> <OutDir>$(SolutionDir)..\bin\</OutDir> <IntDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</IntDir> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <OutDir>$(SolutionDir)..\bin\</OutDir> <IntDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</IntDir> </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ClCompile> <PrecompiledHeader> </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> <Link> <SubSystem>Console</SubSystem> <GenerateDebugInformation>true</GenerateDebugInformation> <AdditionalDependencies>$(IntDir)..\..\common\$(Configuration)\common.lib</AdditionalDependencies> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ClCompile> <WarningLevel>Level3</WarningLevel> <PrecompiledHeader> </PrecompiledHeader> <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> <Link> <SubSystem>Console</SubSystem> <GenerateDebugInformation>false</GenerateDebugInformation> <AdditionalDependencies>$(IntDir)..\..\common\$(Configuration)\common.lib</AdditionalDependencies> </Link> </ItemDefinitionGroup> <ItemGroup> <ClCompile Include="chrcvt65\error.c" /> <ClCompile Include="chrcvt65\main.c" /> </ItemGroup> <ItemGroup> <ClInclude Include="chrcvt65\error.h" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> </Project>������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/chrcvt65/�����������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014440�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/chrcvt65/error.c����������������������������������������������������������������������0000664�0000000�0000000�00000007112�13473601511�0015736�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* error.c */ /* */ /* Error handling for the chrcvt65 vector font converter */ /* */ /* */ /* */ /* (C) 1998-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include "error.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Warning (const char* Format, ...) /* Print a warning message */ { va_list ap; va_start (ap, Format); fprintf (stderr, "Warning: "); vfprintf (stderr, Format, ap); putc ('\n', stderr); va_end (ap); } void Error (const char* Format, ...) /* Print an error message and die */ { va_list ap; va_start (ap, Format); fprintf (stderr, "Error: "); vfprintf (stderr, Format, ap); putc ('\n', stderr); va_end (ap); exit (EXIT_FAILURE); } void Internal (const char* Format, ...) /* Print an internal error message and die */ { va_list ap; va_start (ap, Format); fprintf (stderr, "Internal error: "); vfprintf (stderr, Format, ap); putc ('\n', stderr); va_end (ap); exit (EXIT_FAILURE); } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/chrcvt65/error.h����������������������������������������������������������������������0000664�0000000�0000000�00000006276�13473601511�0015755�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* error.h */ /* */ /* Error handling for the chrcvt65 vector font converter */ /* */ /* */ /* */ /* (C) 1998-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef ERROR_H #define ERROR_H /* common */ #include "attrib.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Warning (const char* Format, ...) attribute((format(printf,1,2))); /* Print a warning message */ void Error (const char* Format, ...) attribute((noreturn, format(printf,1,2))); /* Print an error message and die */ void Internal (const char* Format, ...) attribute((noreturn, format(printf,1,2))); /* Print an internal error message and die */ /* End of error.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/chrcvt65/main.c�����������������������������������������������������������������������0000664�0000000�0000000�00000044426�13473601511�0015542�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* main.c */ /* */ /* Main program of the chrcvt65 vector font converter */ /* */ /* */ /* */ /* (C) 2000-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> /* common */ #include "cmdline.h" #include "fname.h" #include "print.h" #include "strbuf.h" #include "xmalloc.h" #include "version.h" /* chrcvt65 */ #include "error.h" /* ** The following is a corrected doc from the BGI font editor toolkit: ** ** BGI Stroke File Format ** ** The structure of Borland .CHR (stroke) files is as follows: ** ** ; offset 0h is a Borland header: ** ; ** HeaderSize equ 080h ** DataSize equ (size of font file) ** descr equ "Triplex font" ** fname equ "TRIP" ** MajorVersion equ 1 ** MinorVersion equ 0 ** ** db 'PK',8,8 ** db 'BGI ',descr,' V' ** db MajorVersion+'0' ** db (MinorVersion / 10)+'0',(MinorVersion mod 10)+'0' ** db ' - 19 October 1987',0DH,0AH ** db 'Copyright (c) 1987 Borland International', 0dh,0ah ** db 0,1ah ; null & ctrl-Z = end ** ** dw HeaderSize ; size of header ** db fname ; font name ** dw DataSize ; font file size ** db MajorVersion,MinorVersion ; version #'s ** db 1,0 ; minimal version #'s ** ** db (HeaderSize - $) DUP (0) ; pad out to header size ** ** At offset 80h starts data for the file: ** ** ; 80h '+' flags stroke file type ** ; 81h-82h number chars in font file (n) ** ; 83h undefined ** ; 84h ASCII value of first char in file ** ; 85h-86h offset to stroke definitions (8+3n) ** ; 87h scan flag (normally 0) ** ; 88h distance from origin to top of capital ** ; 89h distance from origin to baseline ** ; 8Ah distance from origin to bottom descender ** ; 8Bh-8Fh undefined ** ; 90h offsets to individual character definitions ** ; 90h+2n width table (one word per character) ** ; 90h+3n start of character definitions ** ; ** The individual character definitions consist of a variable number of words ** describing the operations required to render a character. Each word ** consists of an (x,y) coordinate pair and a two-bit opcode, encoded as shown ** here: ** ** Byte 1 7 6 5 4 3 2 1 0 bit # ** op1 <seven bit signed X coord> ** ** Byte 2 7 6 5 4 3 2 1 0 bit # ** op2 <seven bit signed Y coord> ** ** ** Opcodes ** ** op1=0 op2=0 End of character definition. ** op1=1 op2=0 Move the pointer to (x,y) ** op1=1 op2=1 Draw from current pointer to (x,y) */ /* The target file format is designed to be read by a cc65 compiled program ** more easily. It should not be necessary to load the whole file into a ** buffer to parse it, or seek within the file. Also using less memory if ** possible would be fine. Therefore we use the following structure: ** ** Header portion: ** .byte $54, $43, $48, $00 ; "TCH" version ** .word <size of data portion> ** Data portion: ** .byte <top> ; Baseline to top ** .byte <bottom> ; Baseline to bottom ** .byte <height> ; Maximum char height ** .byte <width>, ... ; $5F width bytes ** .word <char definition offset>, ... ; $5F char def offsets ** Character definitions: ** .word <converted opcode>, ... ** .byte $80 ** ** The baseline of the character is assume to be at position zero. top and ** bottom are both positive values. The former extends in positive, the other ** in negative direction of the baseline. height contains the sum of top and ** bottom and is stored here just for easier handling. ** ** The opcodes get converted for easier handling: END is marked by bit 7 ** set in the first byte. The second byte of this opcode is not needed. ** Bit 7 of the second byte marks a MOVE (bit 7 = 0) or DRAW (bit 7 = 1). ** ** The number of characters is fixed to $20..$7E (space to tilde), so character ** widths and offsets can be stored in fixed size preallocated tables. The ** space for the character definitions is allocated on the heap, it's size ** is stored in the header. ** ** Above structure allows a program to read the header portion of the file, ** validate it, then read the remainder of the file into memory in one chunk. ** The character definition offsets will then be converted into pointers by ** adding the character definition base pointer to each. */ /*****************************************************************************/ /* Data */ /*****************************************************************************/ static unsigned FilesProcessed = 0; /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void Usage (void) /* Print usage information and exit */ { fprintf (stderr, "Usage: %s [options] file [options] [file]\n" "Short options:\n" " -h\t\t\tHelp (this text)\n" " -v\t\t\tBe more verbose\n" " -V\t\t\tPrint the version number and exit\n" "\n" "Long options:\n" " --help\t\tHelp (this text)\n" " --verbose\t\tBe more verbose\n" " --version\t\tPrint the version number and exit\n", ProgName); } static void OptHelp (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Print usage information and exit */ { Usage (); exit (EXIT_SUCCESS); } static void OptVerbose (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Increase verbosity */ { ++Verbosity; } static void OptVersion (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Print the assembler version */ { fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ()); exit(EXIT_SUCCESS); } static void ConvertChar (StrBuf* Data, const unsigned char* Buf, int Remaining) /* Convert data for one character. Original data is in Buf, converted data ** will be placed in Data. */ { /* Convert all drawing vectors for this character */ while (1) { unsigned Op; /* Check if we have enough data left */ if (Remaining < 2) { Error ("End of file while parsing character definitions"); } /* Get the next op word */ Op = (Buf[0] + (Buf[1] << 8)) & 0x8080; /* Check the opcode */ switch (Op) { case 0x0000: /* End */ if (SB_IsEmpty (Data)) { /* No ops. We need to add an empty one */ SB_AppendChar (Data, 0x00); SB_AppendChar (Data, 0x00); } /* Add an end marker to the last op in the buffer */ SB_GetBuf (Data)[SB_GetLen (Data) - 2] |= 0x80; return; case 0x0080: /* Move */ SB_AppendChar (Data, Buf[0] & 0x7F); SB_AppendChar (Data, Buf[1] & 0x7F); break; case 0x8000: /* Invalid opcode */ Error ("Input file contains invalid opcode 0x8000"); break; case 0x8080: /* Draw */ SB_AppendChar (Data, Buf[0] & 0x7F); SB_AppendChar (Data, Buf[1] | 0x80); break; } /* Next Op */ Buf += 2; Remaining -= 2; } } static void ConvertFile (const char* Input, const char* Output) /* Convert one vector font file */ { /* The header of a BGI vector font file */ static const unsigned char ChrHeader[] = { /* According to the Borland docs, the following should work, but it ** doesn't. Seems like there are fonts that work, but don't have the ** "BGI" string in the header. So we use just the PK\b\b mark as ** a header. ** ** 0x50, 0x4B, 0x08, 0x08, 0x42, 0x47, 0x49, 0x20 */ 0x50, 0x4B, 0x08, 0x08 }; /* The header of a TGI vector font file */ unsigned char TchHeader[] = { 0x54, 0x43, 0x48, 0x00, /* "TCH" version */ 0x00, 0x00, /* size of char definitions */ 0x00, /* Top */ 0x00, /* Baseline */ 0x00, /* Bottom */ }; long Size; unsigned char* Buf; unsigned char* MsgEnd; unsigned FirstChar; unsigned CharCount; unsigned LastChar; unsigned Char; unsigned Offs; const unsigned char* OffsetBuf; const unsigned char* WidthBuf; const unsigned char* VectorBuf; StrBuf Offsets = AUTO_STRBUF_INITIALIZER; StrBuf VectorData = AUTO_STRBUF_INITIALIZER; /* Try to open the file for reading */ FILE* F = fopen (Input, "rb"); if (F == 0) { Error ("Cannot open input file '%s': %s", Input, strerror (errno)); } /* Seek to the end and determine the size */ fseek (F, 0, SEEK_END); Size = ftell (F); /* Seek back to the start of the file */ fseek (F, 0, SEEK_SET); /* Check if the size is reasonable */ if (Size > 32*1024) { Error ("Input file '%s' is too large (max = 32k)", Input); } else if (Size < 0x100) { Error ("Input file '%s' is too small to be a vector font file", Input); } /* Allocate memory for the file */ Buf = xmalloc ((size_t) Size); /* Read the file contents into the buffer */ if (fread (Buf, 1, (size_t) Size, F) != (size_t) Size) { Error ("Error reading from input file '%s'", Input); } /* Close the file */ (void) fclose (F); /* Verify the header */ if (memcmp (Buf, ChrHeader, sizeof (ChrHeader)) != 0) { Error ("Invalid format for '%s': invalid header", Input); } MsgEnd = memchr (Buf + sizeof (ChrHeader), 0x1A, 0x80); if (MsgEnd == 0) { Error ("Invalid format for '%s': description not found", Input); } if (MsgEnd[1] != 0x80 || MsgEnd[2] != 0x00) { Error ("Invalid format for '%s': wrong header size", Input); } /* We expect the file to hold chars from 0x20 (space) to 0x7E (tilde) */ FirstChar = Buf[0x84]; CharCount = Buf[0x81] + (Buf[0x82] << 8); LastChar = FirstChar + CharCount - 1; if (FirstChar > 0x20 || LastChar < 0x7E) { Print (stderr, 1, "FirstChar = $%04X, CharCount = %u\n", FirstChar, CharCount); Error ("File '%s' doesn't contain the chars we need", Input); } else if (LastChar >= 0x100) { Error ("File '%s' contains too many character definitions", Input); } /* Print the copyright from the header */ Print (stderr, 1, "%.*s\n", (int) (MsgEnd - Buf - 4), Buf+4); /* Get pointers to the width table, the offset table and the vector data ** table. The first two corrected for 0x20 as first entry. */ OffsetBuf = Buf + 0x90 + ((0x20 - FirstChar) * 2); WidthBuf = Buf + 0x90 + (CharCount * 2) + (0x20 - FirstChar); VectorBuf = Buf + 0x90 + (CharCount * 3); /* Convert the characters */ for (Char = 0x20; Char <= 0x7E; ++Char, OffsetBuf += 2) { int Remaining; /* Add the offset to the offset table */ Offs = SB_GetLen (&VectorData); SB_AppendChar (&Offsets, Offs & 0xFF); SB_AppendChar (&Offsets, (Offs >> 8) & 0xFF); /* Get the offset of the vector data in the BGI data buffer */ Offs = OffsetBuf[0] + (OffsetBuf[1] << 8); /* Calculate the remaining data in the buffer for this character */ Remaining = Size - (Offs + (VectorBuf - Buf)); /* Check if the offset is valid */ if (Remaining <= 0) { Error ("Invalid data offset in input file '%s'", Input); } /* Convert the vector data and place it into the buffer */ ConvertChar (&VectorData, VectorBuf + Offs, Remaining); } /* Complete the TCH header */ Offs = 3 + 0x5F + 2*0x5F + SB_GetLen (&VectorData); TchHeader[4] = Offs & 0xFF; TchHeader[5] = (Offs >> 8) & 0xFF; TchHeader[6] = Buf[0x88]; TchHeader[7] = (unsigned char) -(signed char)(Buf[0x8A]); TchHeader[8] = TchHeader[6] + TchHeader[7]; /* The baseline must be zero, otherwise we cannot convert */ if (Buf[0x89] != 0) { Error ("Baseline of font in '%s' is not zero", Input); } /* If the output file is NULL, use the name of the input file with ".tch" ** appended. */ if (Output == 0) { Output = MakeFilename (Input, ".tch"); } /* Open the output file */ F = fopen (Output, "wb"); if (F == 0) { Error ("Cannot open output file '%s': %s", Output, strerror (errno)); } /* Write the header to the output file */ if (fwrite (TchHeader, 1, sizeof (TchHeader), F) != sizeof (TchHeader)) { Error ("Error writing to '%s' (disk full?)", Output); } /* Write the width table to the output file */ if (fwrite (WidthBuf, 1, 0x5F, F) != 0x5F) { Error ("Error writing to '%s' (disk full?)", Output); } /* Write the offsets to the output file */ if (fwrite (SB_GetConstBuf (&Offsets), 1, 0x5F * 2, F) != 0x5F * 2) { Error ("Error writing to '%s' (disk full?)", Output); } /* Write the data to the output file */ Offs = SB_GetLen (&VectorData); if (fwrite (SB_GetConstBuf (&VectorData), 1, Offs, F) != Offs) { Error ("Error writing to '%s' (disk full?)", Output); } /* Close the output file */ if (fclose (F) != 0) { Error ("Error closing to '%s': %s", Output, strerror (errno)); } /* Done */ } int main (int argc, char* argv []) /* Assembler main program */ { /* Program long options */ static const LongOpt OptTab[] = { { "--help", 0, OptHelp }, { "--verbose", 0, OptVerbose }, { "--version", 0, OptVersion }, }; unsigned I; /* Initialize the cmdline module */ InitCmdLine (&argc, &argv, "chrcvt65"); /* Check the parameters */ I = 1; while (I < ArgCount) { /* Get the argument */ const char* Arg = ArgVec[I]; /* Check for an option */ if (Arg [0] == '-') { switch (Arg [1]) { case '-': LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0])); break; case 'h': OptHelp (Arg, 0); break; case 'v': OptVerbose (Arg, 0); break; case 'V': OptVersion (Arg, 0); break; default: UnknownOption (Arg); break; } } else { /* Filename. Dump it. */ ConvertFile (Arg, 0); ++FilesProcessed; } /* Next argument */ ++I; } /* Print a message if we did not process any files */ if (FilesProcessed == 0) { fprintf (stderr, "%s: No input files\n", ProgName); } /* Success */ return EXIT_SUCCESS; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cl65.vcxproj��������������������������������������������������������������������������0000664�0000000�0000000�00000010636�13473601511�0015170�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> <ProjectConfiguration Include="Release|Win32"> <Configuration>Release</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> </ItemGroup> <PropertyGroup Label="Globals"> <ProjectGuid>{F657912F-050A-488B-B203-50ED5715CDD7}</ProjectGuid> <Keyword>Win32Proj</Keyword> <RootNamespace>cl65</RootNamespace> <WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <UseDebugLibraries>true</UseDebugLibraries> <PlatformToolset>v141</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <UseDebugLibraries>false</UseDebugLibraries> <WholeProgramOptimization>true</WholeProgramOptimization> <PlatformToolset>v141</PlatformToolset> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <PropertyGroup Label="UserMacros" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <LinkIncremental>true</LinkIncremental> <OutDir>$(SolutionDir)..\bin\</OutDir> <IntDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</IntDir> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <OutDir>$(SolutionDir)..\bin\</OutDir> <IntDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</IntDir> </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ClCompile> <PrecompiledHeader> </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> <Link> <SubSystem>Console</SubSystem> <GenerateDebugInformation>true</GenerateDebugInformation> <AdditionalDependencies>$(IntDir)..\..\common\$(Configuration)\common.lib</AdditionalDependencies> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ClCompile> <WarningLevel>Level3</WarningLevel> <PrecompiledHeader> </PrecompiledHeader> <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> <Link> <SubSystem>Console</SubSystem> <GenerateDebugInformation>false</GenerateDebugInformation> <AdditionalDependencies>$(IntDir)..\..\common\$(Configuration)\common.lib</AdditionalDependencies> </Link> </ItemDefinitionGroup> <ItemGroup> <ClCompile Include="cl65\error.c" /> <ClCompile Include="cl65\global.c" /> <ClCompile Include="cl65\main.c" /> </ItemGroup> <ItemGroup> <ClInclude Include="cl65\error.h" /> <ClInclude Include="cl65\global.h" /> </ItemGroup> <ItemGroup> <None Include="cl65\spawn-amiga.inc" /> <None Include="cl65\spawn-unix.inc" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> </Project>��������������������������������������������������������������������������������������������������cc65-2.18/src/cl65/���������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0013545�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cl65/error.c��������������������������������������������������������������������������0000664�0000000�0000000�00000007256�13473601511�0015054�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* global.c */ /* */ /* Error handling for the cl65 compile and link utility */ /* */ /* */ /* */ /* (C) 1998 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> /* common */ #include "cmdline.h" /* cl65 */ #include "global.h" #include "error.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Warning (const char* Format, ...) /* Print a warning message */ { va_list ap; va_start (ap, Format); fprintf (stderr, "%s: ", ProgName); vfprintf (stderr, Format, ap); putc ('\n', stderr); va_end (ap); } void Error (const char* Format, ...) /* Print an error message and die */ { va_list ap; va_start (ap, Format); fprintf (stderr, "%s: ", ProgName); vfprintf (stderr, Format, ap); putc ('\n', stderr); va_end (ap); exit (EXIT_FAILURE); } void Internal (const char* Format, ...) /* Print an internal error message and die */ { va_list ap; va_start (ap, Format); fprintf (stderr, "%s: Internal error: ", ProgName); vfprintf (stderr, Format, ap); putc ('\n', stderr); va_end (ap); exit (EXIT_FAILURE); } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cl65/error.h��������������������������������������������������������������������������0000664�0000000�0000000�00000006227�13473601511�0015056�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* global.h */ /* */ /* Error handling for the cl65 compile and link utility */ /* */ /* */ /* */ /* (C) 1998-2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef ERROR_H #define ERROR_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Warning (const char* Format, ...) attribute((format(printf,1,2))); /* Print a warning message */ void Error (const char* Format, ...) attribute((noreturn, format(printf,1,2))); /* Print an error message and die */ void Internal (const char* Format, ...) attribute((noreturn, format(printf,1,2))); /* Print an internal error message and die */ /* End of error.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cl65/global.c�������������������������������������������������������������������������0000664�0000000�0000000�00000005517�13473601511�0015161�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* global.c */ /* */ /* Global variables for the cl65 compile and link utility */ /* */ /* */ /* */ /* (C) 1998-2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include "global.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ unsigned char Debug = 0; /* Debug mode enabled? */ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cl65/global.h�������������������������������������������������������������������������0000664�0000000�0000000�00000005576�13473601511�0015173�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* global.h */ /* */ /* Global variables for the cl65 compile and link utility */ /* */ /* */ /* */ /* (C) 1998-2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 GLOBAL_H #define GLOBAL_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ extern unsigned char Debug; /* Debug mode enabled? */ /* End of global.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cl65/main.c���������������������������������������������������������������������������0000664�0000000�0000000�00000140762�13473601511�0014647�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* main.c */ /* */ /* Main module for the cl65 compile-and-link utility */ /* */ /* */ /* */ /* (C) 1999-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* Check out if we have a spawn() function on the system, or if we must use ** our own. */ #if defined(_WIN32) # define HAVE_SPAWN 1 #else # define NEED_SPAWN 1 #endif /* GCC strictly follows http://c-faq.com/ansi/constmismatch.html and issues an ** 'incompatible pointer type' warning - that can't be suppressed via #pragma. ** The spawnvp() prototype of MinGW (http://www.mingw.org/) differs from the ** one of MinGW-w64 (http://mingw-w64.sourceforge.net/) regarding constness. ** So there's no alternative to actually distinguish these environments :-( */ #define SPAWN_ARGV_CONST_CAST #if defined(__MINGW32__) # include <_mingw.h> # if !defined(__MINGW64_VERSION_MAJOR) # undef SPAWN_ARGV_CONST_CAST # define SPAWN_ARGV_CONST_CAST (const char* const *) # endif #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <errno.h> #if defined(HAVE_SPAWN) # include <process.h> #endif /* common */ #include "attrib.h" #include "cmdline.h" #include "filetype.h" #include "fname.h" #include "mmodel.h" #include "searchpath.h" #include "strbuf.h" #include "target.h" #include "version.h" #include "xmalloc.h" /* cl65 */ #include "global.h" #include "error.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Struct that describes a command */ typedef struct CmdDesc CmdDesc; struct CmdDesc { char* Name; /* The command name */ unsigned ArgCount; /* Count of arguments */ unsigned ArgMax; /* Maximum count of arguments */ char** Args; /* The arguments */ unsigned FileCount; /* Count of files to translate */ unsigned FileMax; /* Maximum count of files */ char** Files; /* The files */ }; /* Command descriptors for the different programs */ static CmdDesc CC65 = { 0, 0, 0, 0, 0, 0, 0 }; static CmdDesc CA65 = { 0, 0, 0, 0, 0, 0, 0 }; static CmdDesc CO65 = { 0, 0, 0, 0, 0, 0, 0 }; static CmdDesc LD65 = { 0, 0, 0, 0, 0, 0, 0 }; static CmdDesc GRC = { 0, 0, 0, 0, 0, 0, 0 }; /* Variables controlling the steps we're doing */ static int DoLink = 1; static int DoAssemble = 1; /* The name of the output file, NULL if none given */ static const char* OutputName = 0; /* The name of the linker configuration file if given */ static const char* LinkerConfig = 0; /* The name of the first input file. This will be used to construct the ** executable file name if no explicit name is given. */ static const char* FirstInput = 0; /* The names of the files for dependency generation */ static const char* DepName = 0; static const char* FullDepName = 0; /* Remember if we should link a module */ static int Module = 0; /* Extension used for a module */ #define MODULE_EXT ".o65" /* Name of the target specific runtime library */ static char* TargetLib = 0; static int NoTargetLib = 0; /*****************************************************************************/ /* Include the system specific spawn function */ /*****************************************************************************/ #if defined(NEED_SPAWN) # if defined(_AMIGA) # include "spawn-amiga.inc" # else # include "spawn-unix.inc" # endif #endif /*****************************************************************************/ /* Credential functions */ /*****************************************************************************/ static void DisableAssembling (void) { DoAssemble = 0; } static void DisableLinking (void) { DoLink = 0; } static void DisableAssemblingAndLinking (void) { DisableAssembling (); DisableLinking (); } /*****************************************************************************/ /* Command structure handling */ /*****************************************************************************/ static char* CmdAllocArg (const char* Arg, unsigned Len) /* Alloc (potentially quoted) argument */ { char* Alloc; /* The Microsoft docs say on spawnvp(): ** Spaces embedded in strings may cause unexpected behavior; for example, ** passing _spawn the string "hi there" will result in the new process getting ** two arguments, "hi" and "there". If the intent was to have the new process ** open a file named "hi there", the process would fail. You can avoid this by ** quoting the string: "\"hi there\"". */ #if defined(_WIN32) /* Quote argument if it contains space(s) */ if (memchr (Arg, ' ', Len)) { Alloc = xmalloc (Len + 3); Alloc[0] = '"'; memcpy (Alloc + 1, Arg, Len); Alloc[Len + 1] = '"'; Alloc[Len + 2] = '\0'; } else #endif { Alloc = xmalloc (Len + 1); memcpy (Alloc, Arg, Len); Alloc[Len] = '\0'; } return Alloc; } static void CmdExpand (CmdDesc* Cmd) /* Expand the argument vector */ { unsigned NewMax = Cmd->ArgMax + 10; char** NewArgs = xmalloc (NewMax * sizeof (char*)); memcpy (NewArgs, Cmd->Args, Cmd->ArgMax * sizeof (char*)); xfree (Cmd->Args); Cmd->Args = NewArgs; Cmd->ArgMax = NewMax; } static void CmdAddArg (CmdDesc* Cmd, const char* Arg) /* Add a new argument to the command */ { /* Expand the argument vector if needed */ if (Cmd->ArgCount >= Cmd->ArgMax) { CmdExpand (Cmd); } /* Add a copy of the new argument, allow a NULL pointer */ if (Arg) { Cmd->Args[Cmd->ArgCount++] = CmdAllocArg (Arg, strlen (Arg)); } else { Cmd->Args[Cmd->ArgCount++] = 0; } } static void CmdAddArg2 (CmdDesc* Cmd, const char* Arg1, const char* Arg2) /* Add a new argument pair to the command */ { CmdAddArg (Cmd, Arg1); CmdAddArg (Cmd, Arg2); } static void CmdAddArgList (CmdDesc* Cmd, const char* ArgList) /* Add a list of arguments separated by commas */ { const char* Arg = ArgList; const char* P = Arg; while (1) { if (*P == '\0' || *P == ',') { /* End of argument, add it */ unsigned Len = P - Arg; /* Expand the argument vector if needed */ if (Cmd->ArgCount >= Cmd->ArgMax) { CmdExpand (Cmd); } /* Add the new argument */ Cmd->Args[Cmd->ArgCount++] = CmdAllocArg (Arg, Len); /* If the argument was terminated by a comma, skip it, otherwise ** we're done. */ if (*P == ',') { /* Start over at next char */ Arg = ++P; } else { break; } } else { /* Skip other chars */ ++P; } } } static void CmdDelArgs (CmdDesc* Cmd, unsigned LastValid) /* Remove all arguments with an index greater than LastValid */ { while (Cmd->ArgCount > LastValid) { Cmd->ArgCount--; xfree (Cmd->Args [Cmd->ArgCount]); Cmd->Args [Cmd->ArgCount] = 0; } } static void CmdAddFile (CmdDesc* Cmd, const char* File) /* Add a new file to the command */ { /* Expand the file vector if needed */ if (Cmd->FileCount == Cmd->FileMax) { unsigned NewMax = Cmd->FileMax + 10; char** NewFiles = xmalloc (NewMax * sizeof (char*)); memcpy (NewFiles, Cmd->Files, Cmd->FileMax * sizeof (char*)); xfree (Cmd->Files); Cmd->Files = NewFiles; Cmd->FileMax = NewMax; } /* If the file name is not NULL (which is legal and is used to terminate ** the file list), check if the file name does already exist in the file ** list and print a warning if so. Regardless of the search result, add ** the file. */ if (File) { unsigned I; for (I = 0; I < Cmd->FileCount; ++I) { if (strcmp (Cmd->Files[I], File) == 0) { /* Duplicate file */ Warning ("Duplicate file in argument list: '%s'", File); /* No need to search further */ break; } } /* Add the file */ Cmd->Files [Cmd->FileCount++] = xstrdup (File); } else { /* Add a NULL pointer */ Cmd->Files [Cmd->FileCount++] = 0; } } static void CmdInit (CmdDesc* Cmd, const char* Path, const char* Name) /* Initialize the command using the given path and name of the executable */ { char* FullName; FullName = (char*) xmalloc (strlen (Path) + strlen (Name) + 1); strcpy (FullName, Path); strcat (FullName, Name); /* Remember the command */ Cmd->Name = xstrdup (FullName); /* Use the command name as first argument */ CmdAddArg (Cmd, FullName); xfree (FullName); } static void CmdSetOutput (CmdDesc* Cmd, const char* File) /* Set the output file in a command desc */ { CmdAddArg2 (Cmd, "-o", File); } static void CmdSetTarget (CmdDesc* Cmd, target_t Target) /* Set the output file in a command desc */ { CmdAddArg2 (Cmd, "-t", GetTargetName (Target)); } static void CmdPrint (CmdDesc* Cmd, FILE* F) /* Output the command line encoded in the command desc */ { unsigned I; for (I = 0; I < Cmd->ArgCount && Cmd->Args[I] != 0; ++I) { fprintf (F, "%s ", Cmd->Args[I]); } } /*****************************************************************************/ /* Target handling */ /*****************************************************************************/ static void SetTargetFiles (void) /* Set the target system files */ { /* Get a pointer to the system name and its length */ const char* TargetName = GetTargetName (Target); unsigned TargetNameLen = strlen (TargetName); /* Set the library file */ TargetLib = xmalloc (TargetNameLen + 4 + 1); memcpy (TargetLib, TargetName, TargetNameLen); strcpy (TargetLib + TargetNameLen, ".lib"); } /*****************************************************************************/ /* Subprocesses */ /*****************************************************************************/ static void ExecProgram (CmdDesc* Cmd) /* Execute a subprocess with the given name/parameters. Exit on errors. */ { int Status; /* If in debug mode, output the command line we will execute */ if (Debug) { printf ("Executing: "); CmdPrint (Cmd, stdout); printf ("\n"); } /* Call the program */ Status = spawnvp (P_WAIT, Cmd->Name, SPAWN_ARGV_CONST_CAST Cmd->Args); /* Check the result code */ if (Status < 0) { /* Error executing the program */ Error ("Cannot execute '%s': %s", Cmd->Name, strerror (errno)); } else if (Status != 0) { /* Called program had an error */ exit (Status); } } static void Link (void) /* Link the resulting executable */ { unsigned I; /* Since linking is always the final step, if we have an output file name ** given, set it here. If we don't have an explicit output name given, ** try to build one from the name of the first input file. */ if (OutputName) { CmdSetOutput (&LD65, OutputName); } else if (FirstInput && FindExt (FirstInput)) { /* Only if ext present! */ const char* Extension = Module? MODULE_EXT : ""; char* Output = MakeFilename (FirstInput, Extension); CmdSetOutput (&LD65, Output); xfree (Output); } /* If we have a linker config file given, add it to the command line. ** Otherwise pass the target to the linker if we have one. */ if (LinkerConfig) { if (Module) { Error ("Cannot use -C and --module together"); } CmdAddArg2 (&LD65, "-C", LinkerConfig); } else if (Module) { CmdSetTarget (&LD65, TGT_MODULE); } else { CmdSetTarget (&LD65, Target); } /* Add all object files as parameters */ for (I = 0; I < LD65.FileCount; ++I) { CmdAddArg (&LD65, LD65.Files [I]); } /* Add the target library if it is not disabled */ if (!NoTargetLib) { /* Determine which target library is needed */ SetTargetFiles (); if (TargetLib) { CmdAddArg (&LD65, TargetLib); } } /* Terminate the argument list with a NULL pointer */ CmdAddArg (&LD65, 0); /* Call the linker */ ExecProgram (&LD65); } static void AssembleFile (const char* File, unsigned ArgCount) /* Common routine to assemble a file. Will be called by Assemble() and ** AssembleIntermediate(). Adds options common for both routines and ** assembles the file. Will remove excess arguments after assembly. */ { /* Set the target system */ CmdSetTarget (&CA65, Target); /* Check if this is the last processing step */ if (DoLink) { /* We're linking later. Add the output file of the assembly ** the the file list of the linker. The name of the output ** file is that of the input file with ".s" replaced by ".o". */ char* ObjName = MakeFilename (File, ".o"); CmdAddFile (&LD65, ObjName); xfree (ObjName); } else { /* This is the final step. If an output name is given, set it */ if (OutputName) { CmdSetOutput (&CA65, OutputName); } } /* Add the file as argument for the assembler */ CmdAddArg (&CA65, File); /* Add a NULL pointer to terminate the argument list */ CmdAddArg (&CA65, 0); /* Run the assembler */ ExecProgram (&CA65); /* Remove the excess arguments */ CmdDelArgs (&CA65, ArgCount); } static void AssembleIntermediate (const char* SourceFile) /* Assemble an intermediate file which was generated by a previous processing ** step with SourceFile as input. The -dep options won't be added and ** the intermediate assembler file is removed after assembly. */ { /* Generate the name of the assembler output file from the source file ** name. It's the same name with the extension replaced by ".s" */ char* AsmName = MakeFilename (SourceFile, ".s"); /* Assemble the intermediate assembler file */ AssembleFile (AsmName, CA65.ArgCount); /* Remove the input file */ if (remove (AsmName) < 0) { Warning ("Cannot remove temporary file '%s': %s", AsmName, strerror (errno)); } /* Free the assembler file name which was allocated from the heap */ xfree (AsmName); } static void Assemble (const char* File) /* Assemble the given file */ { /* Remember the current assembler argument count */ unsigned ArgCount = CA65.ArgCount; /* We aren't assembling an intermediate file, but one requested by the ** user. So add a few options here if they were given on the command ** line. */ if (DepName && *DepName) { CmdAddArg2 (&CA65, "--create-dep", DepName); } if (FullDepName && *FullDepName) { CmdAddArg2 (&CA65, "--create-full-dep", FullDepName); } /* Use the common routine */ AssembleFile (File, ArgCount); } static void Compile (const char* File) /* Compile the given file */ { /* Remember the current compiler argument count */ unsigned ArgCount = CC65.ArgCount; /* Set the target system */ CmdSetTarget (&CC65, Target); /* Check if this is the final step */ if (DoAssemble) { /* We will assemble this file later. If a dependency file is to be ** generated, set the dependency target to be the final object file, ** not the intermediate assembler file. But beware: There may be an ** output name specified for the assembler. */ if (DepName || FullDepName) { /* Was an output name for the assembler specified? */ if (!DoLink && OutputName) { /* Use this name as the dependency target */ CmdAddArg2 (&CC65, "--dep-target", OutputName); } else { /* Use the object file name as the dependency target */ char* ObjName = MakeFilename (File, ".o"); CmdAddArg2 (&CC65, "--dep-target", ObjName); xfree (ObjName); } } } else { /* If we won't assemble, this is the final step. In this case, set ** the output name if it was given. */ if (OutputName) { CmdSetOutput (&CC65, OutputName); } } /* Add the file as argument for the compiler */ CmdAddArg (&CC65, File); /* Add a NULL pointer to terminate the argument list */ CmdAddArg (&CC65, 0); /* Run the compiler */ ExecProgram (&CC65); /* Remove the excess arguments */ CmdDelArgs (&CC65, ArgCount); /* If this is not the final step, assemble the generated file, then ** remove it */ if (DoAssemble) { /* Assemble the intermediate file and remove it */ AssembleIntermediate (File); } } static void CompileRes (const char* File) /* Compile the given geos resource file */ { /* Remember the current assembler argument count */ unsigned ArgCount = GRC.ArgCount; /* Resource files need an geos-apple or geos-cbm target but this ** is checked within grc65. */ CmdSetTarget (&GRC, Target); /* Add the file as argument for the resource compiler */ CmdAddArg (&GRC, File); /* Add a NULL pointer to terminate the argument list */ CmdAddArg (&GRC, 0); /* Run the compiler */ ExecProgram (&GRC); /* Remove the excess arguments */ CmdDelArgs (&GRC, ArgCount); /* If this is not the final step, assemble the generated file, then ** remove it */ if (DoAssemble) { /* Assemble the intermediate file and remove it */ AssembleIntermediate (File); } } static void ConvertO65 (const char* File) /* Convert an o65 object file into an assembler file */ { /* Remember the current converter argument count */ unsigned ArgCount = CO65.ArgCount; /* If we won't assemble, this is the final step. In this case, set the ** output name. */ if (!DoAssemble && OutputName) { CmdSetOutput (&CO65, OutputName); } /* Add the file as argument for the object file converter */ CmdAddArg (&CO65, File); /* Add a NULL pointer to terminate the argument list */ CmdAddArg (&CO65, 0); /* Run the converter */ ExecProgram (&CO65); /* Remove the excess arguments */ CmdDelArgs (&CO65, ArgCount); /* If this is not the final step, assemble the generated file, then ** remove it */ if (DoAssemble) { /* Assemble the intermediate file and remove it */ AssembleIntermediate (File); } } /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void Usage (void) /* Print usage information and exit */ { printf ("Usage: %s [options] file [...]\n" "Short options:\n" " -c\t\t\t\tCompile and assemble, but don't link\n" " -d\t\t\t\tDebug mode\n" " -g\t\t\t\tAdd debug info\n" " -h\t\t\t\tHelp (this text)\n" " -l name\t\t\tCreate an assembler listing file\n" " -m name\t\t\tCreate a map file\n" " -mm model\t\t\tSet the memory model\n" " -o name\t\t\tName the output file\n" " -r\t\t\t\tEnable register variables\n" " -t sys\t\t\tSet the target system\n" " -u sym\t\t\tForce an import of symbol 'sym'\n" " -v\t\t\t\tVerbose mode\n" " -vm\t\t\t\tVerbose map file\n" " -C name\t\t\tUse linker config file\n" " -Cl\t\t\t\tMake local variables static\n" " -D sym[=defn]\t\t\tDefine a preprocessor symbol\n" " -E\t\t\t\tStop after the preprocessing stage\n" " -I dir\t\t\tSet a compiler include directory path\n" " -L path\t\t\tSpecify a library search path\n" " -Ln name\t\t\tCreate a VICE label file\n" " -O\t\t\t\tOptimize code\n" " -Oi\t\t\t\tOptimize code, inline runtime functions\n" " -Or\t\t\t\tOptimize code, honour the register keyword\n" " -Os\t\t\t\tOptimize code, inline known C functions\n" " -S\t\t\t\tCompile, but don't assemble and link\n" " -T\t\t\t\tInclude source as comment\n" " -V\t\t\t\tPrint the version number\n" " -W name[,...]\t\t\tSuppress compiler warnings\n" " -Wa options\t\t\tPass options to the assembler\n" " -Wc options\t\t\tPass options to the compiler\n" " -Wl options\t\t\tPass options to the linker\n" "\n" "Long options:\n" " --add-source\t\t\tInclude source as comment\n" " --all-cdecl\t\t\tMake functions default to __cdecl__\n" " --asm-args options\t\tPass options to the assembler\n" " --asm-define sym[=v]\t\tDefine an assembler symbol\n" " --asm-include-dir dir\t\tSet an assembler include directory\n" " --bin-include-dir dir\t\tSet an assembler binary include directory\n" " --bss-label name\t\tDefine and export a BSS segment label\n" " --bss-name seg\t\tSet the name of the BSS segment\n" " --cc-args options\t\tPass options to the compiler\n" " --cfg-path path\t\tSpecify a config file search path\n" " --check-stack\t\t\tGenerate stack overflow checks\n" " --code-label name\t\tDefine and export a CODE segment label\n" " --code-name seg\t\tSet the name of the CODE segment\n" " --codesize x\t\t\tAccept larger code by factor x\n" " --config name\t\t\tUse linker config file\n" " --cpu type\t\t\tSet CPU type\n" " --create-dep name\t\tCreate a make dependency file\n" " --create-full-dep name\tCreate a full make dependency file\n" " --data-label name\t\tDefine and export a DATA segment label\n" " --data-name seg\t\tSet the name of the DATA segment\n" " --debug\t\t\tDebug mode\n" " --debug-info\t\t\tAdd debug info\n" " --feature name\t\tSet an emulation feature\n" " --force-import sym\t\tForce an import of symbol 'sym'\n" " --help\t\t\tHelp (this text)\n" " --include-dir dir\t\tSet a compiler include directory path\n" " --ld-args options\t\tPass options to the linker\n" " --lib file\t\t\tLink this library\n" " --lib-path path\t\tSpecify a library search path\n" " --list-targets\t\tList all available targets\n" " --listing name\t\tCreate an assembler listing file\n" " --list-bytes n\t\tNumber of bytes per assembler listing line\n" " --mapfile name\t\tCreate a map file\n" " --memory-model model\t\tSet the memory model\n" " --module\t\t\tLink as a module\n" " --module-id id\t\tSpecify a module ID for the linker\n" " --no-target-lib\t\tDon't link the target library\n" " --o65-model model\t\tOverride the o65 model\n" " --obj file\t\t\tLink this object file\n" " --obj-path path\t\tSpecify an object file search path\n" " --print-target-path\t\tPrint the target file path\n" " --register-space b\t\tSet space available for register variables\n" " --register-vars\t\tEnable register variables\n" " --rodata-name seg\t\tSet the name of the RODATA segment\n" " --signed-chars\t\tDefault characters are signed\n" " --standard std\t\tLanguage standard (c89, c99, cc65)\n" " --start-addr addr\t\tSet the default start address\n" " --static-locals\t\tMake local variables static\n" " --target sys\t\t\tSet the target system\n" " --version\t\t\tPrint the version number\n" " --verbose\t\t\tVerbose mode\n" " --zeropage-label name\t\tDefine and export a ZEROPAGE segment label\n" " --zeropage-name seg\t\tSet the name of the ZEROPAGE segment\n", ProgName); } static void OptAddSource (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Strict source code as comments to the generated asm code */ { CmdAddArg (&CC65, "-T"); } static void OptAllCDecl (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Make functions default to __cdecl__ */ { CmdAddArg (&CC65, "--all-cdecl"); } static void OptAsmArgs (const char* Opt attribute ((unused)), const char* Arg) /* Pass arguments to the assembler */ { CmdAddArgList (&CA65, Arg); } static void OptAsmDefine (const char* Opt attribute ((unused)), const char* Arg) /* Define an assembler symbol (assembler) */ { CmdAddArg2 (&CA65, "-D", Arg); } static void OptAsmIncludeDir (const char* Opt attribute ((unused)), const char* Arg) /* Include directory (assembler) */ { CmdAddArg2 (&CA65, "-I", Arg); } static void OptBinIncludeDir (const char* Opt attribute ((unused)), const char* Arg) /* Binary include directory (assembler) */ { CmdAddArg2 (&CA65, "--bin-include-dir", Arg); } static void OptBssLabel (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --bss-label option */ { CmdAddArg2 (&CO65, "--bss-label", Arg); } static void OptBssName (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --bss-name option */ { CmdAddArg2 (&CC65, "--bss-name", Arg); CmdAddArg2 (&CO65, "--bss-name", Arg); } static void OptCCArgs (const char* Opt attribute ((unused)), const char* Arg) /* Pass arguments to the compiler */ { CmdAddArgList (&CC65, Arg); } static void OptCfgPath (const char* Opt attribute ((unused)), const char* Arg) /* Config file search path (linker) */ { CmdAddArg2 (&LD65, "--cfg-path", Arg); } static void OptCheckStack (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Handle the --check-stack option */ { CmdAddArg (&CC65, "--check-stack"); } static void OptCodeLabel (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --code-label option */ { CmdAddArg2 (&CO65, "--code-label", Arg); } static void OptCodeName (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --code-name option */ { CmdAddArg2 (&CC65, "--code-name", Arg); CmdAddArg2 (&CO65, "--code-name", Arg); } static void OptCodeSize (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --codesize option */ { CmdAddArg2 (&CC65, "--codesize", Arg); } static void OptConfig (const char* Opt attribute ((unused)), const char* Arg) /* Config file (linker) */ { if (LinkerConfig) { Error ("Cannot specify -C/--config twice"); } LinkerConfig = Arg; } static void OptCPU (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --cpu option */ { /* Add the cpu type to the assembler and compiler */ CmdAddArg2 (&CA65, "--cpu", Arg); CmdAddArg2 (&CC65, "--cpu", Arg); } static void OptCreateDep (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --create-dep option */ { /* Add the file name to the compiler */ CmdAddArg2 (&CC65, "--create-dep", Arg); /* Remember the file name for the assembler */ DepName = Arg; } static void OptCreateFullDep (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --create-full-dep option */ { /* Add the file name to the compiler */ CmdAddArg2 (&CC65, "--create-full-dep", Arg); /* Remember the file name for the assembler */ FullDepName = Arg; } static void OptDataLabel (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --data-label option */ { CmdAddArg2 (&CO65, "--data-label", Arg); } static void OptDataName (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --data-name option */ { CmdAddArg2 (&CC65, "--data-name", Arg); CmdAddArg2 (&CO65, "--data-name", Arg); } static void OptDebug (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Debug mode (compiler and cl65 utility) */ { CmdAddArg (&CC65, "-d"); CmdAddArg (&CO65, "-d"); Debug = 1; } static void OptDebugInfo (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Debug Info - add to compiler and assembler */ { CmdAddArg (&CC65, "-g"); CmdAddArg (&CA65, "-g"); CmdAddArg (&CO65, "-g"); } static void OptFeature (const char* Opt attribute ((unused)), const char* Arg) /* Emulation features for the assembler */ { CmdAddArg2 (&CA65, "--feature", Arg); } static void OptForceImport (const char* Opt attribute ((unused)), const char* Arg) /* Emulation features for the assembler */ { CmdAddArg2 (&LD65, "-u", Arg); } static void OptHelp (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Print help - cl65 */ { Usage (); exit (EXIT_SUCCESS); } static void OptIncludeDir (const char* Opt attribute ((unused)), const char* Arg) /* Include directory (compiler) */ { CmdAddArg2 (&CC65, "-I", Arg); } static void OptLdArgs (const char* Opt attribute ((unused)), const char* Arg) /* Pass arguments to the linker */ { CmdAddArgList (&LD65, Arg); } static void OptLib (const char* Opt attribute ((unused)), const char* Arg) /* Library file follows (linker) */ { CmdAddArg2 (&LD65, "--lib", Arg); } static void OptLibPath (const char* Opt attribute ((unused)), const char* Arg) /* Library search path (linker) */ { CmdAddArg2 (&LD65, "--lib-path", Arg); } static void OptListBytes (const char* Opt attribute ((unused)), const char* Arg) /* Set the maximum number of bytes per asm listing line */ { CmdAddArg2 (&CA65, "--list-bytes", Arg); } static void OptListing (const char* Opt attribute ((unused)), const char* Arg) /* Create an assembler listing */ { CmdAddArg2 (&CA65, "-l", Arg); } static void OptListTargets (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* List all targets */ { target_t T; /* List the targets */ for (T = TGT_NONE; T < TGT_COUNT; ++T) { printf ("%s\n", GetTargetName (T)); } /* Terminate */ exit (EXIT_SUCCESS); } static void OptMapFile (const char* Opt attribute ((unused)), const char* Arg) /* Create a map file */ { /* Create a map file (linker) */ CmdAddArg2 (&LD65, "-m", Arg); } static void OptMemoryModel (const char* Opt attribute ((unused)), const char* Arg) /* Set the memory model */ { mmodel_t MemoryModel = FindMemoryModel (Arg); if (MemoryModel == MMODEL_UNKNOWN) { Error ("Unknown memory model: %s", Arg); } else if (MemoryModel == MMODEL_HUGE) { Error ("Unsupported memory model: %s", Arg); } else { CmdAddArg2 (&CA65, "-mm", Arg); CmdAddArg2 (&CC65, "-mm", Arg); } } static void OptModule (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Link as a module */ { Module = 1; } static void OptModuleId (const char* Opt attribute ((unused)), const char* Arg) /* Specify a module if for the linker */ { /* Pass it straight to the linker */ CmdAddArg2 (&LD65, "--module-id", Arg); } static void OptNoTargetLib (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Disable the target library */ { NoTargetLib = 1; } static void OptO65Model (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --o65-model option */ { CmdAddArg2 (&CO65, "-m", Arg); } static void OptObj (const char* Opt attribute ((unused)), const char* Arg) /* Object file follows (linker) */ { CmdAddArg2 (&LD65, "--obj", Arg); } static void OptObjPath (const char* Opt attribute ((unused)), const char* Arg) /* Object file search path (linker) */ { CmdAddArg2 (&LD65, "--obj-path", Arg); } static void OptPrintTargetPath (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Print the target file path */ { char* TargetPath; SearchPaths* TargetPaths = NewSearchPath (); AddSubSearchPathFromEnv (TargetPaths, "CC65_HOME", "target"); #if defined(CL65_TGT) && !defined(_WIN32) AddSearchPath (TargetPaths, STRINGIZE (CL65_TGT)); #endif AddSubSearchPathFromWinBin (TargetPaths, "target"); TargetPath = GetSearchPath (TargetPaths, 0); while (*TargetPath) { if (*TargetPath == ' ') { /* Escape spaces */ putchar ('\\'); } putchar (*TargetPath++); } putchar ('\n'); exit (EXIT_SUCCESS); } static void OptRegisterSpace (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --register-space option */ { CmdAddArg2 (&CC65, "--register-space", Arg); } static void OptRegisterVars (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Handle the --register-vars option */ { CmdAddArg (&CC65, "-r"); } static void OptRodataName (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --rodata-name option */ { CmdAddArg2 (&CC65, "--rodata-name", Arg); } static void OptSignedChars (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Make default characters signed */ { CmdAddArg (&CC65, "-j"); } static void OptStandard (const char* Opt attribute ((unused)), const char* Arg) /* Set the language standard */ { CmdAddArg2 (&CC65, "--standard", Arg); } static void OptStartAddr (const char* Opt attribute ((unused)), const char* Arg) /* Set the default start address */ { CmdAddArg2 (&LD65, "-S", Arg); } static void OptStaticLocals (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Place local variables in static storage */ { CmdAddArg (&CC65, "-Cl"); } static void OptTarget (const char* Opt attribute ((unused)), const char* Arg) /* Set the target system */ { Target = FindTarget (Arg); if (Target == TGT_UNKNOWN) { Error ("No such target system: '%s'", Arg); } else if (Target == TGT_MODULE) { Error ("Cannot use 'module' as target, use --module instead"); } } static void OptVerbose (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Verbose mode (compiler, assembler, linker) */ { CmdAddArg (&CC65, "-v"); CmdAddArg (&CA65, "-v"); CmdAddArg (&CO65, "-v"); CmdAddArg (&LD65, "-v"); } static void OptVersion (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Print version number */ { fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ()); exit(EXIT_SUCCESS); } static void OptZeropageLabel (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --zeropage-label option */ { CmdAddArg2 (&CO65, "--zeropage-label", Arg); } static void OptZeropageName (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --zeropage-name option */ { CmdAddArg2 (&CO65, "--zeropage-name", Arg); } int main (int argc, char* argv []) /* Utility main program */ { /* Program long options */ static const LongOpt OptTab[] = { { "--add-source", 0, OptAddSource }, { "--all-cdecl", 0, OptAllCDecl }, { "--asm-args", 1, OptAsmArgs }, { "--asm-define", 1, OptAsmDefine }, { "--asm-include-dir", 1, OptAsmIncludeDir }, { "--bin-include-dir", 1, OptBinIncludeDir }, { "--bss-label", 1, OptBssLabel }, { "--bss-name", 1, OptBssName }, { "--cc-args", 1, OptCCArgs }, { "--cfg-path", 1, OptCfgPath }, { "--check-stack", 0, OptCheckStack }, { "--code-label", 1, OptCodeLabel }, { "--code-name", 1, OptCodeName }, { "--codesize", 1, OptCodeSize }, { "--config", 1, OptConfig }, { "--cpu", 1, OptCPU }, { "--create-dep", 1, OptCreateDep }, { "--create-full-dep", 1, OptCreateFullDep }, { "--data-label", 1, OptDataLabel }, { "--data-name", 1, OptDataName }, { "--debug", 0, OptDebug }, { "--debug-info", 0, OptDebugInfo }, { "--feature", 1, OptFeature }, { "--force-import", 1, OptForceImport }, { "--help", 0, OptHelp }, { "--include-dir", 1, OptIncludeDir }, { "--ld-args", 1, OptLdArgs }, { "--lib", 1, OptLib }, { "--lib-path", 1, OptLibPath }, { "--list-targets", 0, OptListTargets }, { "--listing", 1, OptListing }, { "--list-bytes", 1, OptListBytes }, { "--mapfile", 1, OptMapFile }, { "--memory-model", 1, OptMemoryModel }, { "--module", 0, OptModule }, { "--module-id", 1, OptModuleId }, { "--no-target-lib", 0, OptNoTargetLib }, { "--o65-model", 1, OptO65Model }, { "--obj", 1, OptObj }, { "--obj-path", 1, OptObjPath }, { "--print-target-path", 0, OptPrintTargetPath}, { "--register-space", 1, OptRegisterSpace }, { "--register-vars", 0, OptRegisterVars }, { "--rodata-name", 1, OptRodataName }, { "--signed-chars", 0, OptSignedChars }, { "--standard", 1, OptStandard }, { "--start-addr", 1, OptStartAddr }, { "--static-locals", 0, OptStaticLocals }, { "--target", 1, OptTarget }, { "--verbose", 0, OptVerbose }, { "--version", 0, OptVersion }, { "--zeropage-label", 1, OptZeropageLabel }, { "--zeropage-name", 1, OptZeropageName }, }; char* CmdPath; unsigned I; /* Initialize the cmdline module */ InitCmdLine (&argc, &argv, "cl65"); /* Initialize the command descriptors */ if (argc == 0) { CmdPath = xstrdup (""); } else { char* Ptr; CmdPath = xstrdup (argv[0]); Ptr = strrchr (CmdPath, '/'); if (Ptr == 0) { Ptr = strrchr (CmdPath, '\\'); } if (Ptr == 0) { *CmdPath = '\0'; } else { *(Ptr + 1) = '\0'; } } CmdInit (&CC65, CmdPath, "cc65"); CmdInit (&CA65, CmdPath, "ca65"); CmdInit (&CO65, CmdPath, "co65"); CmdInit (&LD65, CmdPath, "ld65"); CmdInit (&GRC, CmdPath, "grc65"); xfree (CmdPath); /* Our default target is the C64 instead of "none" */ Target = TGT_C64; /* Check the parameters */ I = 1; while (I < ArgCount) { /* Get the argument */ const char* Arg = ArgVec[I]; /* Check for an option */ if (Arg [0] == '-') { switch (Arg [1]) { case '-': LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0])); break; case 'C': if (Arg[2] == 'l' && Arg[3] == '\0') { /* Make local variables static */ OptStaticLocals (Arg, 0); } else { /* Specify linker config file */ OptConfig (Arg, GetArg (&I, 2)); } break; case 'D': /* Define a preprocessor symbol (compiler) */ CmdAddArg2 (&CC65, "-D", GetArg (&I, 2)); break; case 'I': /* Include directory (compiler) */ OptIncludeDir (Arg, GetArg (&I, 2)); break; case 'L': if (Arg[2] == 'n' && Arg[3] == '\0') { /* VICE label file (linker) */ CmdAddArg2 (&LD65, "-Ln", GetArg (&I, 3)); } else { /* Library search path (linker) */ OptLibPath (Arg, GetArg (&I, 2)); } break; case 'O': /* Optimize code (compiler, also covers -Oi and others) */ CmdAddArg (&CC65, Arg); break; case 'S': /* Dont assemble and link the created files */ DisableAssemblingAndLinking (); break; case 'T': /* Include source as comment (compiler) */ OptAddSource (Arg, 0); break; case 'V': /* Print version number */ OptVersion (Arg, 0); break; case 'E': /* Forward -E to compiler */ CmdAddArg (&CC65, Arg); DisableAssemblingAndLinking (); break; case 'W': if (Arg[2] == 'a' && Arg[3] == '\0') { /* -Wa: Pass options to assembler */ OptAsmArgs (Arg, GetArg (&I, 3)); } else if (Arg[2] == 'c' && Arg[3] == '\0') { /* -Wc: Pass options to compiler */ /* Remember -Wc sub arguments in cc65 arg struct */ OptCCArgs (Arg, GetArg (&I, 3)); } else if (Arg[2] == 'l' && Arg[3] == '\0') { /* -Wl: Pass options to linker */ OptLdArgs (Arg, GetArg (&I, 3)); } else { /* Anything else: Suppress warnings (compiler) */ CmdAddArg2 (&CC65, "-W", GetArg (&I, 2)); } break; case 'c': /* Don't link the resulting files */ DisableLinking (); break; case 'd': /* Debug mode (compiler) */ OptDebug (Arg, 0); break; case 'g': /* Debugging - add to compiler and assembler */ OptDebugInfo (Arg, 0); break; case 'h': case '?': /* Print help - cl65 */ OptHelp (Arg, 0); break; case 'j': /* Default characters are signed */ OptSignedChars (Arg, 0); break; case 'l': /* Create an assembler listing */ OptListing (Arg, GetArg (&I, 2)); break; case 'm': /* Create a map file (linker) */ OptMapFile (Arg, GetArg (&I, 2)); break; case 'o': /* Name the output file */ OutputName = GetArg (&I, 2); break; case 'r': /* Enable register variables */ OptRegisterVars (Arg, 0); break; case 't': /* Set target system - compiler, assembler and linker */ OptTarget (Arg, GetArg (&I, 2)); break; case 'u': /* Force an import (linker) */ OptForceImport (Arg, GetArg (&I, 2)); break; case 'v': if (Arg [2] == 'm') { /* Verbose map file (linker) */ CmdAddArg (&LD65, "-vm"); } else { /* Verbose mode (compiler, assembler, linker) */ OptVerbose (Arg, 0); } break; default: UnknownOption (Arg); } } else { /* Remember the first file name */ if (FirstInput == 0) { FirstInput = Arg; } /* Determine the file type by the extension */ switch (GetFileType (Arg)) { case FILETYPE_C: /* Compile the file */ Compile (Arg); break; case FILETYPE_ASM: /* Assemble the file */ if (DoAssemble) { Assemble (Arg); } break; case FILETYPE_OBJ: case FILETYPE_LIB: /* Add to the linker files */ CmdAddFile (&LD65, Arg); break; case FILETYPE_GR: /* Add to the resource compiler files */ CompileRes (Arg); break; case FILETYPE_O65: /* Add the the object file converter files */ ConvertO65 (Arg); break; default: Error ("Don't know what to do with '%s'", Arg); } } /* Next argument */ ++I; } /* Check if we had any input files */ if (FirstInput == 0) { Warning ("No input files"); } /* Link the given files if requested and if we have any */ if (DoLink && LD65.FileCount > 0) { Link (); } /* Return an apropriate exit code */ return EXIT_SUCCESS; } ��������������cc65-2.18/src/cl65/spawn-amiga.inc������������������������������������������������������������������0000664�0000000�0000000�00000007506�13473601511�0016454�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* spawn-amiga.inc */ /* */ /* Execute other external programs (Amiga version) */ /* */ /* */ /* */ /* (C) 2002 Wolfgang Hosemann */ /* EMail: whose@t-online.de */ /* */ /* */ /* 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. */ /* */ /*****************************************************************************/ /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Mode argument for spawn. This value is ignored by the function and only ** provided for DOS/Windows compatibility. */ #ifndef P_WAIT #define P_WAIT 0 #endif /*****************************************************************************/ /* Code */ /*****************************************************************************/ int spawnvp (int Mode attribute ((unused)), const char* File attribute ((unused)), char* const argv []) /* 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; /* Build the command line */ while (*argv) { SB_AppendStr (&Command, *argv++); SB_AppendChar (&Command, ' '); } /* Terminate the command line */ SB_Terminate (&Command); /* Invoke the shell to execute the command */ Status = system (SB_GetConstBuf (&Command)); /* Free the string buf data */ SB_Done (&Command); /* Return the result */ return Status; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/cl65/spawn-unix.inc�������������������������������������������������������������������0000664�0000000�0000000�00000010670�13473601511�0016355�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* spawn-unix.inc */ /* */ /* Execute other external programs (Unix version) */ /* */ /* */ /* */ /* (C) 1999-2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <unistd.h> #include <string.h> #include <errno.h> #include <sys/types.h> #include <sys/wait.h> /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Mode argument for spawn. This value is ignored by the function and only ** provided for DOS/Windows compatibility. */ #ifndef P_WAIT #define P_WAIT 0 #endif /*****************************************************************************/ /* Code */ /*****************************************************************************/ int spawnvp (int Mode attribute ((unused)), const char* File, char* const argv []) /* 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; /* Fork */ int pid = fork (); if (pid < 0) { /* Error forking */ Error ("Cannot fork: %s", strerror (errno)); } else if (pid == 0) { /* The son - exec the program */ if (execvp (File, argv) < 0) { Error ("Cannot exec '%s': %s", File, strerror (errno)); } } else { /* The father: Wait for the subprocess to terminate */ if (waitpid (pid, &Status, 0) < 0) { Error ("Failure waiting for subprocess: %s", strerror (errno)); } /* Examine the child status */ if (!WIFEXITED (Status)) { Error ("Subprocess '%s' aborted by signal %d", File, WTERMSIG (Status)); } } /* Only the father goes here, we place a return here regardless of that ** to avoid compiler warnings. */ return WEXITSTATUS (Status); } ������������������������������������������������������������������������cc65-2.18/src/co65.vcxproj��������������������������������������������������������������������������0000664�0000000�0000000�00000011164�13473601511�0015170�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> <ProjectConfiguration Include="Release|Win32"> <Configuration>Release</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> </ItemGroup> <PropertyGroup Label="Globals"> <ProjectGuid>{F5DB5D1A-05BC-48FE-B346-4E96DD522AA2}</ProjectGuid> <Keyword>Win32Proj</Keyword> <RootNamespace>co65</RootNamespace> <WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <UseDebugLibraries>true</UseDebugLibraries> <PlatformToolset>v141</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <UseDebugLibraries>false</UseDebugLibraries> <WholeProgramOptimization>true</WholeProgramOptimization> <PlatformToolset>v141</PlatformToolset> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <PropertyGroup Label="UserMacros" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <LinkIncremental>true</LinkIncremental> <OutDir>$(SolutionDir)..\bin\</OutDir> <IntDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</IntDir> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <OutDir>$(SolutionDir)..\bin\</OutDir> <IntDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</IntDir> </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ClCompile> <PrecompiledHeader> </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> <Link> <SubSystem>Console</SubSystem> <GenerateDebugInformation>true</GenerateDebugInformation> <AdditionalDependencies>$(IntDir)..\..\common\$(Configuration)\common.lib</AdditionalDependencies> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ClCompile> <WarningLevel>Level3</WarningLevel> <PrecompiledHeader> </PrecompiledHeader> <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> <Link> <SubSystem>Console</SubSystem> <GenerateDebugInformation>false</GenerateDebugInformation> <AdditionalDependencies>$(IntDir)..\..\common\$(Configuration)\common.lib</AdditionalDependencies> </Link> </ItemDefinitionGroup> <ItemGroup> <ClCompile Include="co65\convert.c" /> <ClCompile Include="co65\error.c" /> <ClCompile Include="co65\fileio.c" /> <ClCompile Include="co65\global.c" /> <ClCompile Include="co65\main.c" /> <ClCompile Include="co65\model.c" /> <ClCompile Include="co65\o65.c" /> </ItemGroup> <ItemGroup> <ClInclude Include="co65\convert.h" /> <ClInclude Include="co65\error.h" /> <ClInclude Include="co65\fileio.h" /> <ClInclude Include="co65\global.h" /> <ClInclude Include="co65\model.h" /> <ClInclude Include="co65\o65.h" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> </Project>������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/co65/���������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0013550�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/co65/convert.c������������������������������������������������������������������������0000664�0000000�0000000�00000037351�13473601511�0015405�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* convert.c */ /* */ /* Actual conversion routines for the co65 object file converter */ /* */ /* */ /* */ /* (C) 2003-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> #include <errno.h> /* common */ #include "debugflag.h" #include "print.h" #include "version.h" #include "xmalloc.h" #include "xsprintf.h" /* co65 */ #include "error.h" #include "global.h" #include "model.h" #include "o65.h" #include "convert.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void PrintO65Stats (const O65Data* D) /* Print information about the O65 file if --verbose is given */ { Print (stdout, 1, "Size of text segment: %5lu\n", D->Header.tlen); Print (stdout, 1, "Size of data segment: %5lu\n", D->Header.dlen); Print (stdout, 1, "Size of bss segment: %5lu\n", D->Header.blen); Print (stdout, 1, "Size of zeropage segment: %5lu\n", D->Header.zlen); Print (stdout, 1, "Number of imports: %5u\n", CollCount (&D->Imports)); Print (stdout, 1, "Number of exports: %5u\n", CollCount (&D->Exports)); Print (stdout, 1, "Number of text segment relocations: %5u\n", CollCount (&D->TextReloc)); Print (stdout, 1, "Number of data segment relocations: %5u\n", CollCount (&D->DataReloc)); } static void SetupSegLabels (FILE* F) /* Setup the segment label names */ { if (BssLabel) { fprintf (F, ".export\t\t%s\n", BssLabel); } else { BssLabel = xstrdup ("BSS"); } if (CodeLabel) { fprintf (F, ".export\t\t%s\n", CodeLabel); } else { CodeLabel = xstrdup ("CODE"); } if (DataLabel) { fprintf (F, ".export\t\t%s\n", DataLabel); } else { DataLabel = xstrdup ("DATA"); } if (ZeropageLabel) { fprintf (F, ".export\t\t%s\n", ZeropageLabel); } else { ZeropageLabel = xstrdup ("ZEROPAGE"); } } static const char* LabelPlusOffs (const char* Label, long Offs) /* Generate "Label+xxx" in a static buffer and return a pointer to the buffer */ { static char Buf[256]; xsprintf (Buf, sizeof (Buf), "%s%+ld", Label, Offs); return Buf; } static const char* RelocExpr (const O65Data* D, unsigned char SegID, unsigned long Val, const O65Reloc* R) /* Generate the segment relative relocation expression. R is only used if the ** expression contains am import, and may be NULL if this is an error (which ** is then flagged). */ { const O65Import* Import; switch (SegID) { case O65_SEGID_UNDEF: if (R) { if (R->SymIdx >= CollCount (&D->Imports)) { Error ("Import index out of range (input file corrupt)"); } Import = CollConstAt (&D->Imports, R->SymIdx); return LabelPlusOffs (Import->Name, Val); } else { Error ("Relocation references an import which is not allowed here"); return 0; } break; case O65_SEGID_TEXT: return LabelPlusOffs (CodeLabel, Val - D->Header.tbase); case O65_SEGID_DATA: return LabelPlusOffs (DataLabel, Val - D->Header.dbase); case O65_SEGID_BSS: return LabelPlusOffs (BssLabel, Val - D->Header.bbase); case O65_SEGID_ZP: return LabelPlusOffs (ZeropageLabel, Val - D->Header.zbase); case O65_SEGID_ABS: return LabelPlusOffs ("", Val); default: Internal ("Cannot handle this segment reference in reloc entry"); } /* NOTREACHED */ return 0; } static void ConvertImports (FILE* F, const O65Data* D) /* Convert the imports */ { unsigned I; if (CollCount (&D->Imports) > 0) { for (I = 0; I < CollCount (&D->Imports); ++I) { /* Get the next import */ const O65Import* Import = CollConstAt (&D->Imports, I); /* Import it by name */ fprintf (F, ".import\t%s\n", Import->Name); } fprintf (F, "\n"); } } static void ConvertExports (FILE* F, const O65Data* D) /* Convert the exports */ { unsigned I; if (CollCount (&D->Exports) > 0) { for (I = 0; I < CollCount (&D->Exports); ++I) { /* Get the next import */ const O65Export* Export = CollConstAt (&D->Exports, I); /* First define it */ fprintf (F, "%s = %s\n", Export->Name, RelocExpr (D, Export->SegID, Export->Val, 0)); /* Then export it by name */ fprintf (F, ".export\t%s\n", Export->Name); } fprintf (F, "\n"); } } static void ConvertSeg (FILE* F, const O65Data* D, const Collection* Relocs, const unsigned char* Data, unsigned long Size) /* Convert one segment */ { const O65Reloc* R; unsigned RIdx; unsigned long Byte; /* Get the pointer to the first relocation entry if there are any */ R = (CollCount (Relocs) > 0)? CollConstAt (Relocs, 0) : 0; /* Initialize for the loop */ RIdx = 0; Byte = 0; /* Walk over the segment data */ while (Byte < Size) { if (R && R->Offs == Byte) { /* We've reached an entry that must be relocated */ unsigned long Val; switch (R->Type) { case O65_RTYPE_WORD: if (Byte >= Size - 1) { Error ("Found WORD relocation, but not enough bytes left"); } else { Val = (Data[Byte+1] << 8) + Data[Byte]; Byte += 2; fprintf (F, "\t.word\t%s\n", RelocExpr (D, R->SegID, Val, R)); } break; case O65_RTYPE_HIGH: Val = (Data[Byte++] << 8) + R->Val; fprintf (F, "\t.byte\t>(%s)\n", RelocExpr (D, R->SegID, Val, R)); break; case O65_RTYPE_LOW: Val = Data[Byte++]; fprintf (F, "\t.byte\t<(%s)\n", RelocExpr (D, R->SegID, Val, R)); break; case O65_RTYPE_SEGADDR: if (Byte >= Size - 2) { Error ("Found SEGADDR relocation, but not enough bytes left"); } else { Val = (((unsigned long) Data[Byte+2]) << 16) + (((unsigned long) Data[Byte+1]) << 8) + (((unsigned long) Data[Byte+0]) << 0) + R->Val; Byte += 3; fprintf (F, "\t.faraddr\t%s\n", RelocExpr (D, R->SegID, Val, R)); } break; case O65_RTYPE_SEG: /* FALLTHROUGH for now */ default: Internal ("Cannot handle relocation type %d at %lu", R->Type, Byte); } /* Get the next relocation entry */ if (++RIdx < CollCount (Relocs)) { R = CollConstAt (Relocs, RIdx); } else { R = 0; } } else { /* Just a constant value */ fprintf (F, "\t.byte\t$%02X\n", Data[Byte++]); } } fprintf (F, "\n"); } static void ConvertCodeSeg (FILE* F, const O65Data* D) /* Do code segment conversion */ { /* Header */ fprintf (F, ";\n; CODE SEGMENT\n;\n" ".segment\t\"%s\"\n" "%s:\n", CodeSeg, CodeLabel); /* Segment data */ ConvertSeg (F, D, &D->TextReloc, D->Text, D->Header.tlen); } static void ConvertDataSeg (FILE* F, const O65Data* D) /* Do data segment conversion */ { /* Header */ fprintf (F, ";\n; DATA SEGMENT\n;\n" ".segment\t\"%s\"\n" "%s:\n", DataSeg, DataLabel); /* Segment data */ ConvertSeg (F, D, &D->DataReloc, D->Data, D->Header.dlen); } static void ConvertBssSeg (FILE* F, const O65Data* D) /* Do bss segment conversion */ { /* Header */ fprintf (F, ";\n; BSS SEGMENT\n;\n" ".segment\t\"%s\"\n" "%s:\n", BssSeg, BssLabel); /* Segment data */ fprintf (F, "\t.res\t%lu\n", D->Header.blen); fprintf (F, "\n"); } static void ConvertZeropageSeg (FILE* F, const O65Data* D) /* Do zeropage segment conversion */ { /* Header */ fprintf (F, ";\n; ZEROPAGE SEGMENT\n;\n"); if (Model == O65_MODEL_CC65_MODULE) { /* o65 files of type cc65-module are linked together with a definition ** file for the zero page, but the zero page is not allocated in the ** module itself, but the locations are mapped to the zp locations of ** the main file. */ fprintf (F, ".import\t__ZP_START__\t\t; Linker generated symbol\n"); fprintf (F, "%s = __ZP_START__\n", ZeropageLabel); } else { /* Header */ fprintf (F, ".segment\t\"%s\": zeropage\n%s:\n", ZeropageSeg, ZeropageLabel); /* Segment data */ fprintf (F, "\t.res\t%lu\n", D->Header.zlen); } fprintf (F, "\n"); } void Convert (const O65Data* D) /* Convert the o65 file in D using the given output file. */ { FILE* F; unsigned I; char* Author = 0; /* For now, we do only accept o65 files generated by the ld65 linker which ** have a specific format. */ if (!Debug && D->Header.mode != O65_MODE_CC65) { Error ("Cannot convert o65 files of this type"); } /* Output statistics */ PrintO65Stats (D); /* Walk through the options and print them if verbose mode is enabled. ** Check for a os=cc65 option and bail out if we didn't find one (for ** now - later we switch to special handling). */ for (I = 0; I < CollCount (&D->Options); ++I) { /* Get the next option */ const O65Option* O = CollConstAt (&D->Options, I); /* Check the type of the option */ switch (O->Type) { case O65_OPT_FILENAME: Print (stdout, 1, "O65 filename option: '%s'\n", GetO65OptionText (O)); break; case O65_OPT_OS: if (O->Len == 2) { Warning ("Operating system option without data found"); } else { Print (stdout, 1, "O65 operating system option: '%s'\n", GetO65OSName (O->Data[0])); switch (O->Data[0]) { case O65_OS_CC65_MODULE: if (Model != O65_MODEL_NONE && Model != O65_MODEL_CC65_MODULE) { Warning ("Wrong o65 model for input file specified"); } else { Model = O65_MODEL_CC65_MODULE; } break; } } break; case O65_OPT_ASM: Print (stdout, 1, "O65 assembler option: '%s'\n", GetO65OptionText (O)); break; case O65_OPT_AUTHOR: if (Author) { xfree (Author); } Author = xstrdup (GetO65OptionText (O)); Print (stdout, 1, "O65 author option: '%s'\n", Author); break; case O65_OPT_TIMESTAMP: Print (stdout, 1, "O65 timestamp option: '%s'\n", GetO65OptionText (O)); break; default: Warning ("Found unknown option, type %d, length %d", O->Type, O->Len); break; } } /* If we shouldn't generate output, we're done here */ if (NoOutput) { return; } /* Open the output file */ F = fopen (OutputName, "w"); if (F == 0) { Error ("Cannot open '%s': %s", OutputName, strerror (errno)); } /* Create a header */ fprintf (F, ";\n; File generated by co65 v %s using model '%s'\n;\n", GetVersionAsString (), GetModelName (Model)); /* Select the CPU */ if ((D->Header.mode & O65_CPU_MASK) == O65_CPU_65816) { fprintf (F, ".p816\n"); } /* Object file options */ fprintf (F, ".fopt\t\tcompiler,\"co65 v %s\"\n", GetVersionAsString ()); if (Author) { fprintf (F, ".fopt\t\tauthor, \"%s\"\n", Author); xfree (Author); Author = 0; } /* Several other assembler options */ fprintf (F, ".case\t\ton\n"); fprintf (F, ".debuginfo\t%s\n", (DebugInfo != 0)? "on" : "off"); /* Setup/export the segment labels */ SetupSegLabels (F); /* End of header */ fprintf (F, "\n"); /* Imported identifiers */ ConvertImports (F, D); /* Exported identifiers */ ConvertExports (F, D); /* Code segment */ ConvertCodeSeg (F, D); /* Data segment */ ConvertDataSeg (F, D); /* BSS segment */ ConvertBssSeg (F, D); /* Zero page segment */ ConvertZeropageSeg (F, D); /* End of data */ fprintf (F, ".end\n"); fclose (F); } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/co65/convert.h������������������������������������������������������������������������0000664�0000000�0000000�00000006247�13473601511�0015412�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* convert.h */ /* */ /* Actual conversion routines for the co65 object file converter */ /* */ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef CONVERT_H #define CONVERT_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Forward definition */ struct O65Data; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Convert (const struct O65Data* D); /* Convert the o65 file in D */ /* End of convert.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/co65/error.c��������������������������������������������������������������������������0000664�0000000�0000000�00000007244�13473601511�0015054�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* error.c */ /* */ /* Error handling for the co65 object file converter */ /* */ /* */ /* */ /* (C) 1998-2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> /* common */ #include "cmdline.h" /* co65 */ #include "error.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Warning (const char* Format, ...) /* Print a warning message */ { va_list ap; va_start (ap, Format); fprintf (stderr, "%s: Warning: ", ProgName); vfprintf (stderr, Format, ap); putc ('\n', stderr); va_end (ap); } void Error (const char* Format, ...) /* Print an error message and die */ { va_list ap; va_start (ap, Format); fprintf (stderr, "%s: Error: ", ProgName); vfprintf (stderr, Format, ap); putc ('\n', stderr); va_end (ap); exit (EXIT_FAILURE); } void Internal (const char* Format, ...) /* Print an internal error message and die */ { va_list ap; va_start (ap, Format); fprintf (stderr, "%s: Internal error: ", ProgName); vfprintf (stderr, Format, ap); putc ('\n', stderr); va_end (ap); exit (EXIT_FAILURE); } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/co65/error.h��������������������������������������������������������������������������0000664�0000000�0000000�00000006273�13473601511�0015062�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* error.h */ /* */ /* Error handling for the co65 object file converter */ /* */ /* */ /* */ /* (C) 1998-2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef ERROR_H #define ERROR_H /* common */ #include "attrib.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Warning (const char* Format, ...) attribute((format(printf,1,2))); /* Print a warning message */ void Error (const char* Format, ...) attribute((noreturn, format(printf,1,2))); /* Print an error message and die */ void Internal (const char* Format, ...) attribute((noreturn, format(printf,1,2))); /* Print an internal error message and die */ /* End of error.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/co65/fileio.c�������������������������������������������������������������������������0000664�0000000�0000000�00000007457�13473601511�0015200�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* fileio.c */ /* */ /* Binary file I/O for the co65 object file converter */ /* */ /* */ /* */ /* (C) 1998-2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* common */ #include "xmalloc.h" /* ld65 */ #include "error.h" #include "fileio.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned Read8 (FILE* F) /* Read an 8 bit value from the file */ { int C = getc (F); if (C == EOF) { Error ("Read error (file corrupt?)"); } return C; } unsigned Read16 (FILE* F) /* Read a 16 bit value from the file */ { unsigned Lo = Read8 (F); unsigned Hi = Read8 (F); return (Hi << 8) | Lo; } unsigned long Read24 (FILE* F) /* Read a 24 bit value from the file */ { unsigned long Lo = Read16 (F); unsigned long Hi = Read8 (F); return (Hi << 16) | Lo; } unsigned long Read32 (FILE* F) /* Read a 32 bit value from the file */ { unsigned long Lo = Read16 (F); unsigned long Hi = Read16 (F); return (Hi << 16) | Lo; } void* ReadData (FILE* F, void* Data, unsigned Size) /* Read data from the file */ { /* Explicitly allow reading zero bytes */ if (Size > 0) { if (fread (Data, 1, Size, F) != Size) { Error ("Read error (file corrupt?)"); } } return Data; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/co65/fileio.h�������������������������������������������������������������������������0000664�0000000�0000000�00000006341�13473601511�0015174�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* fileio.h */ /* */ /* Binary file I/O for the co65 object file converter */ /* */ /* */ /* */ /* (C) 1998-2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef FILEIO_H #define FILEIO_H #include <stdio.h> /* common */ #include "filepos.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned Read8 (FILE* F); /* Read an 8 bit value from the file */ unsigned Read16 (FILE* F); /* Read a 16 bit value from the file */ unsigned long Read24 (FILE* F); /* Read a 24 bit value from the file */ unsigned long Read32 (FILE* F); /* Read a 32 bit value from the file */ void* ReadData (FILE* F, void* Data, unsigned Size); /* Read data from the file */ /* End of fileio.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/co65/global.c�������������������������������������������������������������������������0000664�0000000�0000000�00000007637�13473601511�0015171�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* global.c */ /* */ /* Global variables for the co65 object file converter */ /* */ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "segnames.h" /* co65 */ #include "global.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* File names */ const char* InputName = 0; /* Name of input file */ const char* OutputName = 0; /* Name of output file */ /* Default extensions */ const char AsmExt[] = ".s"; /* Default assembler extension */ /* Segment names */ const char* CodeSeg = SEGNAME_CODE; /* Name of the code segment */ const char* DataSeg = SEGNAME_DATA; /* Name of the data segment */ const char* BssSeg = SEGNAME_BSS; /* Name of the bss segment */ const char* ZeropageSeg = SEGNAME_ZEROPAGE; /* Name of the zeropage segment */ /* Labels */ const char* CodeLabel = 0; /* Label for the code segment */ const char* DataLabel = 0; /* Label for the data segment */ const char* BssLabel = 0; /* Label for the bss segment */ const char* ZeropageLabel = 0; /* Label for the zeropage segment */ /* Flags */ unsigned char DebugInfo = 0; /* Enable debug info */ unsigned char NoOutput = 0; /* Suppress the actual conversion */ �������������������������������������������������������������������������������������������������cc65-2.18/src/co65/global.h�������������������������������������������������������������������������0000664�0000000�0000000�00000007553�13473601511�0015173�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* global.h */ /* */ /* Global variables for the co65 object file converter */ /* */ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef GLOBAL_H #define GLOBAL_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* File names */ extern const char* InputName; /* Name of input file */ extern const char* OutputName; /* Name of output file */ /* Default extensions */ extern const char AsmExt[]; /* Default assembler extension */ /* Segment names */ extern const char* CodeSeg; /* Name of the code segment */ extern const char* DataSeg; /* Name of the data segment */ extern const char* BssSeg; /* Name of the bss segment */ extern const char* ZeropageSeg; /* Name of the zeropage segment */ /* Labels */ extern const char* CodeLabel; /* Label for the code segment */ extern const char* DataLabel; /* Label for the data segment */ extern const char* BssLabel; /* Label for the bss segment */ extern const char* ZeropageLabel; /* Label for the zeropage segment */ /* Flags */ extern unsigned char DebugInfo; /* Enable debug info */ extern unsigned char NoOutput; /* Suppress the actual conversion */ /* End of global.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/co65/main.c���������������������������������������������������������������������������0000664�0000000�0000000�00000027421�13473601511�0014646�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* main.c */ /* */ /* Main program for the co65 object file converter */ /* */ /* */ /* */ /* (C) 2003-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <time.h> /* common */ #include "chartype.h" #include "cmdline.h" #include "debugflag.h" #include "fname.h" #include "print.h" #include "segnames.h" #include "version.h" #include "xmalloc.h" #include "xsprintf.h" /* co65 */ #include "convert.h" #include "error.h" #include "global.h" #include "model.h" #include "o65.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void Usage (void) /* Print usage information and exit */ { printf ("Usage: %s [options] file\n" "Short options:\n" " -V\t\t\tPrint the version number\n" " -g\t\t\tAdd debug info to object file\n" " -h\t\t\tHelp (this text)\n" " -m model\t\tOverride the o65 model\n" " -n\t\t\tDon't generate an output file\n" " -o name\t\tName the output file\n" " -v\t\t\tIncrease verbosity\n" "\n" "Long options:\n" " --bss-label name\tDefine and export a BSS segment label\n" " --bss-name seg\tSet the name of the BSS segment\n" " --code-label name\tDefine and export a CODE segment label\n" " --code-name seg\tSet the name of the CODE segment\n" " --data-label name\tDefine and export a DATA segment label\n" " --data-name seg\tSet the name of the DATA segment\n" " --debug-info\t\tAdd debug info to object file\n" " --help\t\tHelp (this text)\n" " --no-output\t\tDon't generate an output file\n" " --o65-model model\tOverride the o65 model\n" " --verbose\t\tIncrease verbosity\n" " --version\t\tPrint the version number\n" " --zeropage-label name\tDefine and export a ZEROPAGE segment label\n" " --zeropage-name seg\tSet the name of the ZEROPAGE segment\n", ProgName); } static void CheckLabelName (const char* Label) /* Check if the given label is a valid label name */ { const char* L = Label; if (strlen (L) < 256 && (IsAlpha (*L) || *L== '_')) { while (*++L) { if (!IsAlNum (*L) && *L != '_') { break; } } } if (*L) { Error ("Label name '%s' is invalid", Label); } } static void CheckSegName (const char* Seg) /* Abort if the given name is not a valid segment name */ { /* Print an error and abort if the name is not ok */ if (!ValidSegName (Seg)) { Error ("Segment name '%s' is invalid", Seg); } } static void OptBssLabel (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --bss-label option */ { /* Check for a label name */ CheckLabelName (Arg); /* Set the label */ BssLabel = xstrdup (Arg); } static void OptBssName (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --bss-name option */ { /* Check for a valid name */ CheckSegName (Arg); /* Set the name */ BssSeg = xstrdup (Arg); } static void OptCodeLabel (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --code-label option */ { /* Check for a label name */ CheckLabelName (Arg); /* Set the label */ CodeLabel = xstrdup (Arg); } static void OptCodeName (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --code-name option */ { /* Check for a valid name */ CheckSegName (Arg); /* Set the name */ CodeSeg = xstrdup (Arg); } static void OptDataLabel (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --data-label option */ { /* Check for a label name */ CheckLabelName (Arg); /* Set the label */ DataLabel = xstrdup (Arg); } static void OptDataName (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --data-name option */ { /* Check for a valid name */ CheckSegName (Arg); /* Set the name */ DataSeg = xstrdup (Arg); } static void OptDebug (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Enable debugging code */ { ++Debug; } static void OptDebugInfo (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Add debug info to the object file */ { DebugInfo = 1; } static void OptHelp (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Print usage information and exit */ { Usage (); exit (EXIT_SUCCESS); } static void OptNoOutput (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Handle the --no-output option */ { NoOutput = 1; } static void OptO65Model (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --o65-model option */ { /* Search for the model name */ Model = FindModel (Arg); if (Model == O65_MODEL_INVALID) { Error ("Unknown o65 model '%s'", Arg); } } static void OptVerbose (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Increase verbosity */ { ++Verbosity; } static void OptVersion (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Print the assembler version */ { fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ()); exit(EXIT_SUCCESS); } static void OptZeropageLabel (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --zeropage-label option */ { /* Check for a label name */ CheckLabelName (Arg); /* Set the label */ ZeropageLabel = xstrdup (Arg); } static void OptZeropageName (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --zeropage-name option */ { /* Check for a valid name */ CheckSegName (Arg); /* Set the name */ ZeropageSeg = xstrdup (Arg); } static void DoConversion (void) /* Do file conversion */ { /* Read the o65 file into memory */ O65Data* D = ReadO65File (InputName); /* Do the conversion */ Convert (D); /* Free the o65 module data */ /* ### */ } int main (int argc, char* argv []) /* Converter main program */ { /* Program long options */ static const LongOpt OptTab[] = { { "--bss-label", 1, OptBssLabel }, { "--bss-name", 1, OptBssName }, { "--code-label", 1, OptCodeLabel }, { "--code-name", 1, OptCodeName }, { "--data-label", 1, OptDataLabel }, { "--data-name", 1, OptDataName }, { "--debug", 0, OptDebug }, { "--debug-info", 0, OptDebugInfo }, { "--help", 0, OptHelp }, { "--no-output", 0, OptNoOutput }, { "--o65-model", 1, OptO65Model }, { "--verbose", 0, OptVerbose }, { "--version", 0, OptVersion }, { "--zeropage-label", 1, OptZeropageLabel }, { "--zeropage-name", 1, OptZeropageName }, }; unsigned I; /* Initialize the cmdline module */ InitCmdLine (&argc, &argv, "co65"); /* Check the parameters */ I = 1; while (I < ArgCount) { /* Get the argument */ const char* Arg = ArgVec [I]; /* Check for an option */ if (Arg [0] == '-') { switch (Arg [1]) { case '-': LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0])); break; case 'g': OptDebugInfo (Arg, 0); break; case 'h': OptHelp (Arg, 0); break; case 'm': OptO65Model (Arg, GetArg (&I, 2)); break; case 'n': OptNoOutput (Arg, 0); break; case 'o': OutputName = GetArg (&I, 2); break; case 'v': OptVerbose (Arg, 0); break; case 'V': OptVersion (Arg, 0); break; default: UnknownOption (Arg); break; } } else { /* Filename. Check if we already had one */ if (InputName) { Error ("Don't know what to do with '%s'", Arg); } else { InputName = Arg; } } /* Next argument */ ++I; } /* Do we have an input file? */ if (InputName == 0) { Error ("No input file"); } /* Generate the name of the output file if none was specified */ if (OutputName == 0) { OutputName = MakeFilename (InputName, AsmExt); } /* Do the conversion */ DoConversion (); /* Return an apropriate exit code */ return EXIT_SUCCESS; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/co65/model.c��������������������������������������������������������������������������0000664�0000000�0000000�00000007511�13473601511�0015020�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* model.c */ /* */ /* o65 model definitions for the co65 object file converter */ /* */ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "strutil.h" /* co65 */ #include "error.h" #include "model.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Current model */ O65Model Model = O65_MODEL_NONE; /* Name table */ static const char* const NameTable[O65_MODEL_COUNT] = { "none", "os/a65", "lunix", "cc65-module" }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ const char* GetModelName (O65Model M) /* Map the model to its name. */ { if (M < 0 || M >= O65_MODEL_COUNT) { Internal ("O65 Model %d not found", M); } return NameTable[M]; } O65Model FindModel (const char* ModelName) /* Map a model name to its identifier. Return O65_MODEL_INVALID if the name ** could not be found. Case is ignored when comparing names. */ { O65Model M; for (M = O65_MODEL_NONE; M < O65_MODEL_COUNT; ++M) { if (StrCaseCmp (ModelName, NameTable[M]) == 0) { return M; } } return O65_MODEL_INVALID; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/co65/model.h��������������������������������������������������������������������������0000664�0000000�0000000�00000007302�13473601511�0015023�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* model.h */ /* */ /* o65 model definitions for the co65 object file converter */ /* */ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef MODEL_H #define MODEL_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Supported models */ typedef enum { O65_MODEL_INVALID = -1, /* Invalid model */ O65_MODEL_NONE, /* No model given */ O65_MODEL_OSA65, /* Not implemented */ O65_MODEL_LUNIX, /* Not implemented */ O65_MODEL_CC65_MODULE, O65_MODEL_COUNT /* Number of available models */ } O65Model; /* Current model */ extern O65Model Model; /*****************************************************************************/ /* Code */ /*****************************************************************************/ const char* GetModelName (O65Model M); /* Map the model to its name. */ O65Model FindModel (const char* ModelName); /* Map a model name to its identifier. Return O65_MODEL_INVALID if the name ** could not be found. Case is ignored when comparing names. */ /* End of model.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/co65/o65.c����������������������������������������������������������������������������0000664�0000000�0000000�00000031755�13473601511�0014340�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* o65.h */ /* */ /* Definitions and code for the o65 file format */ /* */ /* */ /* */ /* (C) 2002-2004 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> #include <errno.h> /* common */ #include "chartype.h" #include "xmalloc.h" /* co65 */ #include "error.h" #include "fileio.h" #include "o65.h" /*****************************************************************************/ /* struct O65Data */ /*****************************************************************************/ static O65Data* NewO65Data (void) /* Create, initialize and return a new O65Data struct */ { /* Allocate memory */ O65Data* D = xmalloc (sizeof (O65Data)); /* Initialize the fields as needed */ D->Options = AUTO_COLLECTION_INITIALIZER; D->Text = 0; D->Data = 0; D->TextReloc = AUTO_COLLECTION_INITIALIZER; D->DataReloc = AUTO_COLLECTION_INITIALIZER; D->Imports = AUTO_COLLECTION_INITIALIZER; D->Exports = AUTO_COLLECTION_INITIALIZER; /* Return the new struct */ return D; } /*****************************************************************************/ /* Code */ /*****************************************************************************/ static unsigned long ReadO65Size (FILE* F, const O65Header* H) /* Read a size variable (16 or 32 bit, depending on the mode word in the ** header) from the o65 file. */ { unsigned long Size = 0; /* Initialize to avoid warnings */ switch (H->mode & O65_SIZE_MASK) { case O65_SIZE_32BIT: Size = Read32 (F); break; case O65_SIZE_16BIT: Size = Read16 (F); break; default: Internal ("Invalid size field value in o65 header"); } return Size; } static void ReadO65Header (FILE* F, O65Header* H) /* Read an o65 header from the given file. The function will call Error if ** something is wrong. */ { static const char Magic[3] = { O65_MAGIC_0, O65_MAGIC_1, O65_MAGIC_2 /* "o65" */ }; /* Read the marker and check it */ ReadData (F, H->marker, sizeof (H->marker)); if (H->marker[0] != O65_MARKER_0 || H->marker[1] != O65_MARKER_1) { Error ("Not an o65 object file: Invalid marker %02X %02X", H->marker[0], H->marker[1]); } /* Read the magic and check it */ ReadData (F, H->magic, sizeof (H->magic)); if (memcmp (H->magic, Magic, sizeof (H->magic)) != 0) { Error ("Not an o65 object file: Invalid magic %02X %02X %02X", H->magic[0], H->magic[1], H->magic[2]); } /* Read the version number and check it */ H->version = Read8 (F); if (H->version != O65_VERSION) { Error ("Invalid o65 version number: %02X", H->version); } /* Read the mode word */ H->mode = Read16 (F); /* Read the remainder of the header */ H->tbase = ReadO65Size (F, H); H->tlen = ReadO65Size (F, H); H->dbase = ReadO65Size (F, H); H->dlen = ReadO65Size (F, H); H->bbase = ReadO65Size (F, H); H->blen = ReadO65Size (F, H); H->zbase = ReadO65Size (F, H); H->zlen = ReadO65Size (F, H); H->stack = ReadO65Size (F, H); } static O65Option* ReadO65Option (FILE* F) /* Read the next O65 option from the given file. The option is stored into a ** dynamically allocated O65Option struct which is returned. On end of options, ** NULL is returned. On error, Error is called which terminates the program. */ { O65Option* O; /* Read the length of the option and bail out on end of options */ unsigned char Len = Read8 (F); if (Len == 0) { return 0; } if (Len < 2) { Error ("Found option with length < 2 (input file corrupt)"); } Len -= 2; /* Allocate a new O65Option structure of the needed size */ O = xmalloc (sizeof (*O) - sizeof (O->Data) + Len); /* Assign the length and read the remaining option data */ O->Len = Len; O->Type = Read8 (F); ReadData (F, O->Data, Len); /* Return the new struct */ return O; } static O65Import* ReadO65Import (FILE* F) /* Read an o65 import from the file */ { O65Import* I; /* Allow identifiers up to 511 bytes */ char Buf[512]; /* Read the identifier */ unsigned Len = 0; char C; do { C = Read8 (F); if (Len >= sizeof (Buf)) { Error ("Imported identifier exceeds maximum size (%u)", (unsigned) sizeof (Buf)); } Buf[Len++] = C; } while (C != '\0'); /* Allocate an import structure and initialize it */ I = xmalloc (sizeof (*I) - sizeof (I->Name) + Len); memcpy (I->Name, Buf, Len); /* Return the new struct */ return I; } static void ReadO65RelocInfo (FILE* F, const O65Data* D, Collection* Reloc) /* Read relocation data for one segment */ { /* Relocation starts at (start address - 1) */ unsigned long Offs = (unsigned long) -1L; while (1) { O65Reloc* R; /* Read the next relocation offset */ unsigned char C = Read8 (F); if (C == 0) { /* End of relocation table */ break; } /* Create a new relocation entry */ R = xmalloc (sizeof (*R)); /* Handle overflow bytes */ while (C == 0xFF) { Offs += 0xFE; C = Read8 (F); } /* Calculate the final offset */ R->Offs = (Offs += C); /* Read typebyte and segment id */ C = Read8 (F); R->Type = (C & O65_RTYPE_MASK); R->SegID = (C & O65_SEGID_MASK); /* Read an additional relocation value if there is one */ R->SymIdx = (R->SegID == O65_SEGID_UNDEF)? ReadO65Size (F, &D->Header) : 0; switch (R->Type) { case O65_RTYPE_HIGH: if ((D->Header.mode & O65_RELOC_MASK) == O65_RELOC_BYTE) { /* Low byte follows */ R->Val = Read8 (F); } else { /* Low byte is zero */ R->Val = 0; } break; case O65_RTYPE_SEG: /* Low 16 byte of the segment address follow */ R->Val = Read16 (F); break; default: R->Val = 0; break; } /* Insert this relocation entry into the collection */ CollAppend (Reloc, R); } } static O65Export* ReadO65Export (FILE* F, const O65Header* H) /* Read an o65 export from the file */ { O65Export* E; /* Allow identifiers up to 511 bytes */ char Buf[512]; /* Read the identifier */ unsigned Len = 0; char C; do { C = Read8 (F); if (Len >= sizeof (Buf)) { Error ("Exported identifier exceeds maximum size (%u)", (unsigned) sizeof (Buf)); } Buf[Len++] = C; } while (C != '\0'); /* Allocate an export structure and initialize it */ E = xmalloc (sizeof (*E) - sizeof (E->Name) + Len); memcpy (E->Name, Buf, Len); E->SegID = Read8 (F); E->Val = ReadO65Size (F, H); /* Return the new struct */ return E; } static O65Data* ReadO65Data (FILE* F) /* Read a complete o65 file into dynamically allocated memory and return the ** created O65Data struct. */ { unsigned long Count; O65Option* O; /* Create the struct we're going to return */ O65Data* D = NewO65Data (); /* Read the header */ ReadO65Header (F, &D->Header); /* Read the options */ while ((O = ReadO65Option (F)) != 0) { CollAppend (&D->Options, O); } /* Allocate space for the text segment and read it */ D->Text = xmalloc (D->Header.tlen); ReadData (F, D->Text, D->Header.tlen); /* Allocate space for the data segment and read it */ D->Data = xmalloc (D->Header.dlen); ReadData (F, D->Data, D->Header.dlen); /* Read the undefined references list */ Count = ReadO65Size (F, &D->Header); while (Count--) { CollAppend (&D->Imports, ReadO65Import (F)); } /* Read the relocation tables for text and data segment */ ReadO65RelocInfo (F, D, &D->TextReloc); ReadO65RelocInfo (F, D, &D->DataReloc); /* Read the exported globals list */ Count = ReadO65Size (F, &D->Header); while (Count--) { CollAppend (&D->Exports, ReadO65Export (F, &D->Header)); } /* Return the o65 data read from the file */ return D; } O65Data* ReadO65File (const char* Name) /* Read a complete o65 file into dynamically allocated memory and return the ** created O65Data struct. */ { O65Data* D; /* Open the o65 input file */ FILE* F = fopen (Name, "rb"); if (F == 0) { Error ("Cannot open '%s': %s", Name, strerror (errno)); } /* Read the file data */ D = ReadO65Data (F); /* Close the input file. Ignore errors since we were only reading */ fclose (F); /* Return the data read */ return D; } const char* GetO65OSName (unsigned char OS) /* Return the name of the operating system given by OS */ { switch (OS) { case O65_OS_OSA65: return "OS/A65"; case O65_OS_LUNIX: return "Lunix"; case O65_OS_CC65_MODULE: return "cc65 module"; default: return "unknown"; } } const char* GetO65OptionText (const O65Option* O) /* Return the data of the given option as a readable text. The function returns ** a pointer to a static buffer that is reused on the next call, so if in doubt, ** make a copy (and no, the function is not thread safe). */ { static char Buf[256]; unsigned I, J; /* Get the length of the text */ unsigned Len = 0; while (Len < O->Len && O->Data[Len] != '\0') { ++Len; } /* Copy into the buffer converting non readable characters */ I = J = 0; while (I < sizeof (Buf) - 1 && J < Len) { if (!IsControl (O->Data[J])) { Buf[I++] = O->Data[J]; } else { Buf[I++] = '\\'; if (I >= sizeof (Buf) - 4) { --I; break; } switch (O->Data[J]) { case '\t': Buf[I++] = 't'; break; case '\b': Buf[I++] = 'b'; break; case '\n': Buf[I++] = 'n'; break; case '\r': Buf[I++] = 'r'; break; case '\v': Buf[I++] = 'v'; break; default: sprintf (Buf + I, "x%02X", O->Data[J]); I += 3; break; } } ++J; } /* Terminate the string and return it */ Buf[I] = '\0'; return Buf; } �������������������cc65-2.18/src/co65/o65.h����������������������������������������������������������������������������0000664�0000000�0000000�00000022737�13473601511�0014345�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* o65.h */ /* */ /* Definitions and code for the o65 file format */ /* */ /* */ /* */ /* (C) 2002-2003 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* This files exports structures and constants to handle the o65 relocatable ** file format as defined by Andre Fachat. See the original document under ** ** http://www.6502.org/users/andre/o65/fileformat.html ** ** for more information. */ #ifndef _O65_H #define _O65_H /* common */ #include "coll.h" /*****************************************************************************/ /* Defines */ /*****************************************************************************/ /* Define a structure for the o65 file header */ typedef struct O65Header O65Header; struct O65Header { char marker[2]; /* Non-C64 marker */ char magic[3]; /* o65 magic */ char version; /* Version number */ unsigned mode; /* Mode word */ unsigned long tbase; /* Original text (code) segment address */ unsigned long tlen; /* Size of text (code) segment */ unsigned long dbase; /* Original data segment address */ unsigned long dlen; /* Size of data segment */ unsigned long bbase; /* Original bss segment address */ unsigned long blen; /* Size of bss segment */ unsigned long zbase; /* Original zp segment address */ unsigned long zlen; /* Size of zp segment */ unsigned long stack; /* Stacksize needed */ }; /* o65 option */ typedef struct O65Option O65Option; struct O65Option { unsigned char Len; /* Option length */ unsigned char Type; /* Option type */ unsigned char Data[1]; /* Option data (dynamically allocated) */ }; /* o65 relocation entry */ typedef struct O65Reloc O65Reloc; struct O65Reloc { unsigned long Offs; /* Offset in segment */ unsigned char Type; /* Relocation type */ unsigned char SegID; /* Segment ID */ unsigned Val; /* Any offset value needed for relocation */ unsigned long SymIdx; /* Index into list of imported symbols */ }; /* o65 import */ typedef struct O65Import O65Import; struct O65Import { char Name[1]; /* Name of the import (dynamically allocated) */ }; /* o65 export */ typedef struct O65Export O65Export; struct O65Export { unsigned char SegID; /* Segment ID */ unsigned long Val; /* Relocation value */ char Name[1]; /* Name of the export (dynamically allocated) */ }; /* Complete o65 file data */ typedef struct O65Data O65Data; struct O65Data { O65Header Header; /* File header */ Collection Options; /* O65 options */ unsigned char* Text; /* Text segment data (unrelocated) */ unsigned char* Data; /* Data segment data (unrelocated) */ Collection TextReloc; /* Relocation entries for the text segment */ Collection DataReloc; /* Relocation entries for the data segment */ Collection Imports; /* Imported symbols */ Collection Exports; /* Exported symbols */ }; /* Marker, magic and version number */ #define O65_MARKER_0 0x01 #define O65_MARKER_1 0x00 #define O65_MAGIC_0 0x6F /* 'o' */ #define O65_MAGIC_1 0x36 /* '6' */ #define O65_MAGIC_2 0x35 /* '5' */ #define O65_VERSION 0x00 /* Defines for the mode word */ #define O65_CPU_65816 0x8000 /* Executable is for 65816 */ #define O65_CPU_6502 0x0000 /* Executable is for the 6502 */ #define O65_CPU_MASK 0x8000 /* Mask to extract CPU type */ #define O65_RELOC_PAGE 0x4000 /* Page wise relocation */ #define O65_RELOC_BYTE 0x0000 /* Byte wise relocation */ #define O65_RELOC_MASK 0x4000 /* Mask to extract relocation type */ #define O65_SIZE_32BIT 0x2000 /* All size words are 32bit */ #define O65_SIZE_16BIT 0x0000 /* All size words are 16bit */ #define O65_SIZE_MASK 0x2000 /* Mask to extract size */ #define O65_FTYPE_OBJ 0x1000 /* Object file */ #define O65_FTYPE_EXE 0x0000 /* Executable file */ #define O65_FTYPE_MASK 0x1000 /* Mask to extract type */ #define O65_ADDR_SIMPLE 0x0800 /* Simple addressing */ #define O65_ADDR_DEFAULT 0x0000 /* Default addressing */ #define O65_ADDR_MASK 0x0800 /* Mask to extract addressing */ #define O65_ALIGN_1 0x0000 /* Bytewise alignment */ #define O65_ALIGN_2 0x0001 /* Align words */ #define O65_ALIGN_4 0x0002 /* Align longwords */ #define O65_ALIGN_256 0x0003 /* Align pages (256 bytes) */ #define O65_ALIGN_MASK 0x0003 /* Mask to extract alignment */ /* The mode word as generated by the ld65 linker */ #define O65_MODE_CC65 (O65_CPU_6502 | \ O65_RELOC_BYTE | \ O65_SIZE_16BIT | \ O65_FTYPE_EXE | \ O65_ADDR_SIMPLE | \ O65_ALIGN_1) /* The four o65 segment types. */ #define O65_SEGID_UNDEF 0x00 #define O65_SEGID_ABS 0x01 #define O65_SEGID_TEXT 0x02 #define O65_SEGID_DATA 0x03 #define O65_SEGID_BSS 0x04 #define O65_SEGID_ZP 0x05 #define O65_SEGID_MASK 0x07 /* Relocation type codes */ #define O65_RTYPE_WORD 0x80 #define O65_RTYPE_HIGH 0x40 #define O65_RTYPE_LOW 0x20 #define O65_RTYPE_SEGADDR 0xC0 #define O65_RTYPE_SEG 0xA0 #define O65_RTYPE_MASK 0xE0 /* Segment IDs */ #define O65_SEGID_UNDEF 0x00 #define O65_SEGID_ABS 0x01 #define O65_SEGID_TEXT 0x02 #define O65_SEGID_DATA 0x03 #define O65_SEGID_BSS 0x04 #define O65_SEGID_ZP 0x05 #define O65_SEGID_MASK 0x07 /* Option tags */ #define O65_OPT_FILENAME 0 #define O65_OPT_OS 1 #define O65_OPT_ASM 2 #define O65_OPT_AUTHOR 3 #define O65_OPT_TIMESTAMP 4 /* Operating system codes for O65_OPT_OS */ #define O65_OS_OSA65 1 #define O65_OS_LUNIX 2 #define O65_OS_CC65_MODULE 3 /*****************************************************************************/ /* Code */ /*****************************************************************************/ O65Data* ReadO65File (const char* Name); /* Read a complete o65 file into dynamically allocated memory and return the ** created O65Data struct. */ const char* GetO65OSName (unsigned char OS); /* Return the name of the operating system given by OS */ const char* GetO65OptionText (const O65Option* O); /* Return the data of the given option as a readable text. The function returns ** a pointer to a static buffer that is reused on the next call, so if in doubt, ** make a copy (and no, the function is not thread safe). */ /* End of o65.h */ #endif ���������������������������������cc65-2.18/src/common.vcxproj������������������������������������������������������������������������0000664�0000000�0000000�00000020531�13473601511�0015702�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> <ProjectConfiguration Include="Release|Win32"> <Configuration>Release</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> </ItemGroup> <ItemGroup> <ClInclude Include="common\abend.h" /> <ClInclude Include="common\addrsize.h" /> <ClInclude Include="common\alignment.h" /> <ClInclude Include="common\assertion.h" /> <ClInclude Include="common\attrib.h" /> <ClInclude Include="common\bitops.h" /> <ClInclude Include="common\cddefs.h" /> <ClInclude Include="common\chartype.h" /> <ClInclude Include="common\check.h" /> <ClInclude Include="common\cmdline.h" /> <ClInclude Include="common\coll.h" /> <ClInclude Include="common\cpu.h" /> <ClInclude Include="common\debugflag.h" /> <ClInclude Include="common\exprdefs.h" /> <ClInclude Include="common\fileid.h" /> <ClInclude Include="common\filepos.h" /> <ClInclude Include="common\filestat.h" /> <ClInclude Include="common\filetime.h" /> <ClInclude Include="common\filetype.h" /> <ClInclude Include="common\fname.h" /> <ClInclude Include="common\fp.h" /> <ClInclude Include="common\fragdefs.h" /> <ClInclude Include="common\gentype.h" /> <ClInclude Include="common\hashfunc.h" /> <ClInclude Include="common\hashtab.h" /> <ClInclude Include="common\hlldbgsym.h" /> <ClInclude Include="common\inline.h" /> <ClInclude Include="common\intptrstack.h" /> <ClInclude Include="common\intstack.h" /> <ClInclude Include="common\inttypes.h" /> <ClInclude Include="common\libdefs.h" /> <ClInclude Include="common\lidefs.h" /> <ClInclude Include="common\matchpat.h" /> <ClInclude Include="common\mmodel.h" /> <ClInclude Include="common\objdefs.h" /> <ClInclude Include="common\optdefs.h" /> <ClInclude Include="common\print.h" /> <ClInclude Include="common\scopedefs.h" /> <ClInclude Include="common\searchpath.h" /> <ClInclude Include="common\segdefs.h" /> <ClInclude Include="common\segnames.h" /> <ClInclude Include="common\shift.h" /> <ClInclude Include="common\strbuf.h" /> <ClInclude Include="common\strpool.h" /> <ClInclude Include="common\strstack.h" /> <ClInclude Include="common\strutil.h" /> <ClInclude Include="common\symdefs.h" /> <ClInclude Include="common\target.h" /> <ClInclude Include="common\tgttrans.h" /> <ClInclude Include="common\va_copy.h" /> <ClInclude Include="common\version.h" /> <ClInclude Include="common\xmalloc.h" /> <ClInclude Include="common\xsprintf.h" /> </ItemGroup> <ItemGroup> <ClCompile Include="common\abend.c" /> <ClCompile Include="common\addrsize.c" /> <ClCompile Include="common\alignment.c" /> <ClCompile Include="common\assertion.c" /> <ClCompile Include="common\bitops.c" /> <ClCompile Include="common\chartype.c" /> <ClCompile Include="common\check.c" /> <ClCompile Include="common\cmdline.c" /> <ClCompile Include="common\coll.c" /> <ClCompile Include="common\cpu.c" /> <ClCompile Include="common\debugflag.c" /> <ClCompile Include="common\exprdefs.c" /> <ClCompile Include="common\fileid.c" /> <ClCompile Include="common\filepos.c" /> <ClCompile Include="common\filestat.c" /> <ClCompile Include="common\filetime.c" /> <ClCompile Include="common\filetype.c" /> <ClCompile Include="common\fname.c" /> <ClCompile Include="common\fp.c" /> <ClCompile Include="common\gentype.c" /> <ClCompile Include="common\hashfunc.c" /> <ClCompile Include="common\hashtab.c" /> <ClCompile Include="common\intptrstack.c" /> <ClCompile Include="common\intstack.c" /> <ClCompile Include="common\matchpat.c" /> <ClCompile Include="common\mmodel.c" /> <ClCompile Include="common\print.c" /> <ClCompile Include="common\searchpath.c" /> <ClCompile Include="common\segnames.c" /> <ClCompile Include="common\shift.c" /> <ClCompile Include="common\strbuf.c" /> <ClCompile Include="common\strpool.c" /> <ClCompile Include="common\strstack.c" /> <ClCompile Include="common\strutil.c" /> <ClCompile Include="common\target.c" /> <ClCompile Include="common\tgttrans.c" /> <ClCompile Include="common\version.c" /> <ClCompile Include="common\xmalloc.c" /> <ClCompile Include="common\xsprintf.c" /> </ItemGroup> <PropertyGroup Label="Globals"> <ProjectGuid>{71DC1F68-BFC4-478C-8655-C8E9C9654D2B}</ProjectGuid> <Keyword>Win32Proj</Keyword> <RootNamespace>common</RootNamespace> <WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <ConfigurationType>StaticLibrary</ConfigurationType> <UseDebugLibraries>true</UseDebugLibraries> <PlatformToolset>v141</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <UseDebugLibraries>false</UseDebugLibraries> <WholeProgramOptimization>true</WholeProgramOptimization> <ConfigurationType>StaticLibrary</ConfigurationType> <PlatformToolset>v141</PlatformToolset> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <PropertyGroup Label="UserMacros" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <IntDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</IntDir> <OutDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</OutDir> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <IntDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</IntDir> <OutDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</OutDir> </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ClCompile> <PrecompiledHeader> </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_LIB;_DEBUG</PreprocessorDefinitions> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> <Link> <SubSystem>Windows</SubSystem> <GenerateDebugInformation>true</GenerateDebugInformation> </Link> <Lib /> <Lib> <OutputFile>$(IntDir)$(TargetName)$(TargetExt)</OutputFile> </Lib> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ClCompile> <WarningLevel>Level3</WarningLevel> <PrecompiledHeader> </PrecompiledHeader> <FunctionLevelLinking>true</FunctionLevelLinking> <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_LIB;NDEBUG</PreprocessorDefinitions> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> <Link> <SubSystem>Windows</SubSystem> <GenerateDebugInformation>true</GenerateDebugInformation> <EnableCOMDATFolding>true</EnableCOMDATFolding> <OptimizeReferences>true</OptimizeReferences> </Link> <Lib /> <Lib> <OutputFile>$(IntDir)$(TargetName)$(TargetExt)</OutputFile> </Lib> </ItemDefinitionGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> </Project>�����������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/�������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014264�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/abend.c������������������������������������������������������������������������0000664�0000000�0000000�00000006471�13473601511�0015511�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* abend.c */ /* */ /* Abnormal program end */ /* */ /* */ /* */ /* (C) 2000 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include "cmdline.h" #include "abend.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void AbEnd (const char* Format, ...) /* Print a message preceeded by the program name and terminate the program ** with an error exit code. */ { va_list ap; /* Print the program name */ fprintf (stderr, "%s: ", ProgName); /* Format the given message and print it */ va_start (ap, Format); vfprintf (stderr, Format, ap); va_end (ap); /* Add a newline */ fprintf (stderr, "\n"); /* Terminate the program */ exit (EXIT_FAILURE); } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/abend.h������������������������������������������������������������������������0000664�0000000�0000000�00000006016�13473601511�0015511�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* abend.h */ /* */ /* Abnormal program end */ /* */ /* */ /* */ /* (C) 2000 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 ABEND_H #define ABEND_H #include "attrib.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void AbEnd (const char* Format, ...) attribute ((format (printf, 1, 2), noreturn)); /* Print a message preceeded by the program name and terminate the program ** with an error exit code. */ /* End of abend.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/addrsize.c���������������������������������������������������������������������0000664�0000000�0000000�00000010454�13473601511�0016241�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* addrsize.c */ /* */ /* Address size definitions */ /* */ /* */ /* */ /* (C) 2003-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "addrsize.h" #include "strutil.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ const char* AddrSizeToStr (unsigned char AddrSize) /* Return the name for an address size specifier */ { switch (AddrSize) { case ADDR_SIZE_DEFAULT: return "default"; case ADDR_SIZE_ZP: return "zeropage"; case ADDR_SIZE_ABS: return "absolute"; case ADDR_SIZE_FAR: return "far"; case ADDR_SIZE_LONG: return "long"; default: return "unknown"; } } unsigned char AddrSizeFromStr (const char* Str) /* Return the address size for a given string. Returns ADDR_SIZE_INVALID if ** the string cannot be mapped to an address size. */ { static const struct { const char* Name; unsigned char AddrSize; } AddrSizeTable[] = { { "abs", ADDR_SIZE_ABS }, { "absolute", ADDR_SIZE_ABS }, { "default", ADDR_SIZE_DEFAULT }, { "direct", ADDR_SIZE_ZP }, { "dword", ADDR_SIZE_LONG }, { "far", ADDR_SIZE_FAR }, { "long", ADDR_SIZE_LONG }, { "near", ADDR_SIZE_ABS }, { "zeropage", ADDR_SIZE_ZP }, { "zp", ADDR_SIZE_ZP }, }; unsigned I; for (I = 0; I < sizeof (AddrSizeTable) / sizeof (AddrSizeTable[0]); ++I) { if (StrCaseCmp (Str, AddrSizeTable[I].Name) == 0) { /* Found */ return AddrSizeTable[I].AddrSize; } } /* Not found */ return ADDR_SIZE_INVALID; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/addrsize.h���������������������������������������������������������������������0000664�0000000�0000000�00000007062�13473601511�0016247�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* addrsize.h */ /* */ /* Address size definitions */ /* */ /* */ /* */ /* (C) 2003-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef ADDRSIZE_H #define ADDRSIZE_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ #define ADDR_SIZE_INVALID 0xFF #define ADDR_SIZE_DEFAULT 0x00 #define ADDR_SIZE_ZP 0x01 #define ADDR_SIZE_ABS 0x02 #define ADDR_SIZE_FAR 0x03 #define ADDR_SIZE_LONG 0x04 /*****************************************************************************/ /* Code */ /*****************************************************************************/ const char* AddrSizeToStr (unsigned char AddrSize); /* Return the name for an address size specifier */ unsigned char AddrSizeFromStr (const char* Str); /* Return the address size for a given string. Returns ADDR_SIZE_INVALID if ** the string cannot be mapped to an address size. */ /* End of addrsize.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/alignment.c��������������������������������������������������������������������0000664�0000000�0000000�00000015115�13473601511�0016411�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* alignment.c */ /* */ /* Address aligment */ /* */ /* */ /* */ /* (C) 2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* 70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "alignment.h" #include "check.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* To factorize an alignment, we will use the following prime table. It lists ** all primes up to 256, which means we're able to factorize alignments up to ** 0x10000. This is checked in the code. */ static const unsigned char Primes[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251 }; #define PRIME_COUNT (sizeof (Primes) / sizeof (Primes[0])) #define LAST_PRIME ((unsigned long)Primes[PRIME_COUNT-1]) /* A number together with its prime factors */ typedef struct FactorizedNumber FactorizedNumber; struct FactorizedNumber { unsigned long Value; /* The actual number */ unsigned long Remainder; /* Remaining prime */ unsigned char Powers[PRIME_COUNT]; /* Powers of the factors */ }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void Initialize (FactorizedNumber* F, unsigned long Value) /* Initialize a FactorizedNumber structure */ { unsigned I; F->Value = Value; F->Remainder = 1; for (I = 0; I < PRIME_COUNT; ++I) { F->Powers[I] = 0; } } static void Factorize (unsigned long Value, FactorizedNumber* F) /* Factorize a value between 1 and 0x10000 that is in F */ { unsigned I; /* Initialize F */ Initialize (F, Value); /* If the value is 1 we're already done */ if (Value == 1) { return; } /* Be sure we can factorize */ CHECK (Value <= MAX_ALIGNMENT && Value != 0); /* Handle factor 2 separately for speed */ while ((Value & 0x01UL) == 0UL) { ++F->Powers[0]; Value >>= 1; } /* Factorize. */ I = 1; /* Skip 2 because it was handled above */ while (Value > 1) { unsigned long Tmp = Value / Primes[I]; if (Tmp * Primes[I] == Value) { /* This is a factor */ ++F->Powers[I]; Value = Tmp; } else { /* This is not a factor, try next one */ if (++I >= PRIME_COUNT) { break; } } } /* If something is left, it must be a remaining prime */ F->Remainder = Value; } unsigned long LeastCommonMultiple (unsigned long Left, unsigned long Right) /* Calculate the least common multiple of two numbers and return ** the result. */ { unsigned I; FactorizedNumber L, R; unsigned long Res; /* Factorize the two numbers */ Factorize (Left, &L); Factorize (Right, &R); /* Generate the result from the factors. ** Some thoughts on range problems: Since the largest numbers we can ** factorize are 2^16 (0x10000), the only numbers that could produce an ** overflow when using 32 bits are exactly these. But the LCM for 2^16 ** and 2^16 is 2^16 so this will never happen and we're safe. */ Res = L.Remainder * R.Remainder; for (I = 0; I < PRIME_COUNT; ++I) { unsigned P = (L.Powers[I] > R.Powers[I])? L.Powers[I] : R.Powers[I]; while (P--) { Res *= Primes[I]; } } /* Return the calculated lcm */ return Res; } unsigned long AlignAddr (unsigned long Addr, unsigned long Alignment) /* Align an address to the given alignment */ { return ((Addr + Alignment - 1) / Alignment) * Alignment; } unsigned long AlignCount (unsigned long Addr, unsigned long Alignment) /* Calculate how many bytes must be inserted to align Addr to Alignment */ { return AlignAddr (Addr, Alignment) - Addr; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/alignment.h��������������������������������������������������������������������0000664�0000000�0000000�00000007511�13473601511�0016417�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* alignment.h */ /* */ /* Address aligment */ /* */ /* */ /* */ /* (C) 2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* 70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef ALIGNMENT_H #define ALIGNMENT_H /* common */ #include "inline.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Maximum possible alignment. Beware: To increase the possible alignment it ** is not enough to bump this value. Check the code inside. */ #define MAX_ALIGNMENT 0x10000UL /* The following value marks what is considered a "large alignment" and worth ** a warning if not suppressed. */ #define LARGE_ALIGNMENT 0x101UL /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned long LeastCommonMultiple (unsigned long Left, unsigned long Right); /* Calculate the least common multiple of two numbers and return ** the result. */ unsigned long AlignAddr (unsigned long Addr, unsigned long Alignment); /* Align an address to the given alignment */ unsigned long AlignCount (unsigned long Addr, unsigned long Alignment); /* Calculate how many bytes must be inserted to align Addr to Alignment */ /* End of alignment.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/assertion.c��������������������������������������������������������������������0000664�0000000�0000000�00000006206�13473601511�0016443�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* assertion.c */ /* */ /* Definitions for linker assertions */ /* */ /* */ /* */ /* (C) 2003-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include "assertion.h" #include "attrib.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ int AssertAtLinkTime (AssertAction A attribute ((unused))) /* Return true if this assertion should be evaluated at link time */ { /* Currently all assertions are evaluated at link time */ return 1; } int AssertAtAsmTime (AssertAction A) /* Return true if this assertion should be evaluated at assembly time */ { return (A & 0x02U) == 0; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/assertion.h��������������������������������������������������������������������0000664�0000000�0000000�00000007210�13473601511�0016444�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* assertion.h */ /* */ /* Definitions for linker assertions */ /* */ /* */ /* */ /* (C) 2003-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef ASSERTION_H #define ASSERTION_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Assertion actions. The second two are linker only (not evaluated by ca65) */ typedef enum { ASSERT_ACT_WARN = 0x00U, /* Print a warning */ ASSERT_ACT_ERROR = 0x01U, /* Print an error */ ASSERT_ACT_LDWARN = 0x02U, /* Print a warning (linker only) */ ASSERT_ACT_LDERROR = 0x03U, /* Print an error (linker only) */ } AssertAction; /*****************************************************************************/ /* Code */ /*****************************************************************************/ int AssertAtLinkTime (AssertAction A); /* Return true if this assertion should be evaluated at link time */ int AssertAtAsmTime (AssertAction A); /* Return true if this assertion should be evaluated at assembly time */ /* End of assertion.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/attrib.h�����������������������������������������������������������������������0000664�0000000�0000000�00000005637�13473601511�0015735�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* attrib.h */ /* */ /* Handle gcc attributes */ /* */ /* */ /* */ /* (C) 2000-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef ATTRIB_H #define ATTRIB_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ #if defined(__GNUC__) # define attribute(a) __attribute__(a) #else # define attribute(a) #endif /* End of attrib.h */ #endif �������������������������������������������������������������������������������������������������cc65-2.18/src/common/bitops.c�����������������������������������������������������������������������0000664�0000000�0000000�00000010407�13473601511�0015732�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* bitops.c */ /* */ /* Single bit operations */ /* */ /* */ /* */ /* (C) 1998 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include "bitops.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned BitFind (unsigned long Val) /* Find the first bit that is set in Val. Val must *not* be zero */ { unsigned long Mask; unsigned Bit; /* Search for the bits */ Mask = 1; Bit = 0; while (1) { if (Val & Mask) { return Bit; } Mask <<= 1; ++Bit; } } void BitSet (void* Data, unsigned Bit) /* Set a bit in a char array */ { /* Make a char pointer */ unsigned char* D = Data; /* Set the bit */ D [Bit / 8] |= 0x01 << (Bit % 8); } void BitReset (void* Data, unsigned Bit) /* Reset a bit in a char array */ { /* Make a char pointer */ unsigned char* D = Data; /* Set the bit */ D [Bit / 8] &= ~(0x01 << (Bit % 8)); } int BitIsSet (void* Data, unsigned Bit) /* Check if a bit is set in a char array */ { /* Make a char pointer */ unsigned char* D = Data; /* Check the bit state */ return (D [Bit / 8] & (0x01 << (Bit % 8))) != 0; } int BitIsReset (void* Data, unsigned Bit) /* Check if a bit is reset in a char array */ { /* Make a char pointer */ unsigned char* D = Data; /* Check the bit state */ return (D [Bit / 8] & (0x01 << (Bit % 8))) == 0; } void BitMerge (void* Target, const void* Source, unsigned Size) /* Merge the bits of two char arrays (that is, do an or for the full array) */ { /* Make char arrays */ unsigned char* T = Target; const unsigned char* S = Source; /* Merge the arrays */ while (Size--) { *T++ |= *S++; } } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/bitops.h�����������������������������������������������������������������������0000664�0000000�0000000�00000006720�13473601511�0015742�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* bitops.h */ /* */ /* Single bit operations */ /* */ /* */ /* */ /* (C) 1998 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 BITOPS_H #define BITOPS_H #include "attrib.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned BitFind (unsigned long Val) attribute ((const)); /* Find the first bit that is set in Val. Val must *not* be zero */ void BitSet (void* Data, unsigned Bit); /* Set a bit in a char array */ void BitReset (void* Data, unsigned Bit); /* Reset a bit in a char array */ int BitIsSet (void* Data, unsigned Bit) attribute ((const)); /* Check if a bit is set in a char array */ int BitIsReset (void* Data, unsigned Bit) attribute ((const)); /* Check if a bit is reset in a char array */ void BitMerge (void* Target, const void* Source, unsigned Size); /* Merge the bits of two char arrays (that is, do an or for the full array) */ /* End of bitops.h */ #endif ������������������������������������������������cc65-2.18/src/common/cddefs.h�����������������������������������������������������������������������0000664�0000000�0000000�00000010036�13473601511�0015665�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* cddefs.h */ /* */ /* Definitions for module constructor/destructors */ /* */ /* */ /* */ /* (C) 2000-2004 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef CDDEFS_H #define CDDEFS_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* ConDes types. Count is only 7 because we want to encode 0..count in 3 bits */ #define CD_TYPE_COUNT 7 /* Number of table types */ #define CD_TYPE_MIN 0 /* Minimum numeric type value */ #define CD_TYPE_MAX 6 /* Maximum numeric type value */ /* ConDes priorities, zero is no valid priority and used to mark an empty ** (missing) decl for this type throughout the code. */ #define CD_PRIO_NONE 0 /* No priority (no decl) */ #define CD_PRIO_MIN 1 /* Lowest priority */ #define CD_PRIO_DEF 7 /* Default priority */ #define CD_PRIO_MAX 32 /* Highest priority */ /* Predefined types */ #define CD_TYPE_CON 0 /* Constructor */ #define CD_TYPE_DES 1 /* Destructor */ #define CD_TYPE_INT 2 /* Interruptor */ /* When part of an export in an object file, type and priority are encoded in ** one byte. In this case, the following macros access the fields: */ #define CD_GET_TYPE(v) (((v) >> 5) & 0x07) #define CD_GET_PRIO(v) (((v) & 0x1F) + 1) /* Macro to build the byte value: */ #define CD_BUILD(type,prio) ((((type) & 0x07) << 5) | (((prio) - 1) & 0x1F)) /* End of cddefs.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/chartype.c���������������������������������������������������������������������0000664�0000000�0000000�00000011061�13473601511�0016246�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* chartype.c */ /* */ /* Character classification functions */ /* */ /* */ /* */ /* (C) 2000-2004 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include "chartype.h" /* This module contains replacements for functions in ctype.h besides other ** functions. There is a problem with using ctype.h directly: ** The parameter must have a value of "unsigned char" or EOF. ** So on platforms where a char is signed, this may give problems or at ** least warnings. The wrapper functions below will have an "char" parameter ** but handle it correctly. They will NOT work for EOF, but this is not a ** problem, since EOF is always handled separately. */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ int IsAlpha (char C) /* Check for a letter */ { return (C >= 'a' && C <= 'z') || (C >= 'A' && C <= 'Z'); } int IsAlNum (char C) /* Check for letter or digit */ { return (C >= 'a' && C <= 'z') || (C >= 'A' && C <= 'Z') || (C >= '0' && C <= '9'); } int IsAscii (char C) /* Check for an ASCII character */ { return (C & ~0x7F) == 0; } int IsBlank (char C) /* Check for a space or tab */ { return (C == ' ' || C == '\t'); } int IsSpace (char C) /* Check for any white space characters */ { return (C == ' ' || C == '\n' || C == '\r' || C == '\t' || C == '\v' || C == '\f'); } int IsDigit (char C) /* Check for a digit */ { return (C >= '0' && C <= '9'); } int IsLower (char C) /* Check for a lower case char */ { return (C >= 'a' && C <= 'z'); } int IsUpper (char C) /* Check for upper case characters */ { return (C >= 'A' && C <= 'Z'); } int IsBDigit (char C) /* Check for binary digits (0/1) */ { return (C == '0' || C == '1'); } int IsODigit (char C) /* Check for octal digits (0..7) */ { return (C >= '0' && C <= '7'); } int IsXDigit (char C) /* Check for hexadecimal digits */ { return (C >= 'a' && C <= 'f') || (C >= 'A' && C <= 'F') || (C >= '0' && C <= '9'); } int IsQuote (char C) /* Check for a single or double quote */ { return (C == '"' || C == '\''); } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/chartype.h���������������������������������������������������������������������0000664�0000000�0000000�00000010305�13473601511�0016253�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* chartype.h */ /* */ /* Character classification functions */ /* */ /* */ /* */ /* (C) 2000-2004 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef CHARTYPE_H #define CHARTYPE_H #include <ctype.h> /* common */ #include "inline.h" /* This module contains replacements for functions in ctype.h besides other ** functions. There is a problem with using ctype.h directly: ** The parameter must have a value of "unsigned char" or EOF. ** So on platforms where a char is signed, this may give problems or at ** least warnings. The wrapper functions below will have an "char" parameter ** but handle it correctly. They will NOT work for EOF, but this is not a ** problem, since EOF is always handled separately. */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ int IsAlpha (char C); /* Check for a letter */ int IsAlNum (char C); /* Check for letter or digit */ int IsAscii (char C); /* Check for an ASCII character */ int IsBlank (char C); /* Check for a space or tab */ #if defined(HAVE_INLINE) INLINE int IsControl (char C) /* Check for control chars */ { return iscntrl ((unsigned char) C); } #else # define IsControl(C) iscntrl (C) #endif int IsSpace (char C); /* Check for any white space characters */ int IsDigit (char C); /* Check for a digit */ int IsLower (char C); /* Check for a lower case char */ int IsUpper (char C); /* Check for upper case characters */ int IsBDigit (char C); /* Check for binary digits (0/1) */ int IsODigit (char C); /* Check for octal digits (0..7) */ int IsXDigit (char C); /* Check for hexadecimal digits */ int IsQuote (char C); /* Check for a single or double quote */ /* End of chartype.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/check.c������������������������������������������������������������������������0000664�0000000�0000000�00000007714�13473601511�0015516�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* check.c */ /* */ /* Assert like macros */ /* */ /* */ /* */ /* (C) 1998-2001 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdlib.h> #include "abend.h" #include "check.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Predefined messages */ const char* MsgInternalError = "Internal error: "; const char* MsgPrecondition = "Precondition violated: "; const char* MsgCheckFailed = "Check failed: "; const char* MsgProgramAborted = "Program aborted: "; static void DefaultCheckFailed (const char* msg, const char* cond, const char* file, unsigned line) attribute ((noreturn)); void (*CheckFailed) (const char* Msg, const char* Cond, const char* File, unsigned Line) attribute ((noreturn)) = DefaultCheckFailed; /* Function pointer that is called from check if the condition code is true. */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void DefaultCheckFailed (const char* Msg, const char* Cond, const char* File, unsigned Line) { /* Output a diagnostic and abort */ AbEnd ("%s%s, file '%s', line %u", Msg, Cond, File, Line); } ����������������������������������������������������cc65-2.18/src/common/check.h������������������������������������������������������������������������0000664�0000000�0000000�00000010434�13473601511�0015514�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* check.h */ /* */ /* Assert like macros */ /* */ /* */ /* */ /* (C) 1998-2001 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef CHECK_H #define CHECK_H #include "attrib.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ extern const char* MsgInternalError; /* "Internal error: " */ extern const char* MsgPrecondition; /* "Precondition violated: " */ extern const char* MsgCheckFailed; /* "Check failed: " */ extern const char* MsgProgramAborted; /* "Program aborted: " */ extern void (*CheckFailed) (const char* Msg, const char* Cond, const char* File, unsigned Line) attribute ((noreturn)); /* Function pointer that is called from check if the condition code is true. */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ #define FAIL(s) CheckFailed (MsgInternalError, s, __FILE__, __LINE__) /* Fail macro. Is used if something evil happens, calls checkfailed directly. */ #define ABORT(s) CheckFailed (MsgProgramAborted, s, __FILE__, __LINE__) /* Use this one instead of FAIL if there is no internal program error but an ** error condition that is caused by the user or operating system (FAIL and ** ABORT are essentially the same but the message differs). */ #define PRECONDITION(c) \ ((void) ((c)? 0 : (CheckFailed (MsgPrecondition, #c, __FILE__, __LINE__), 0))) #define CHECK(c) \ ((void) ((c)? 0 : (CheckFailed (MsgCheckFailed, #c, __FILE__, __LINE__), 0))) /* End of check.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/cmdline.c����������������������������������������������������������������������0000664�0000000�0000000�00000022411�13473601511�0016043�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* cmdline.c */ /* */ /* Helper functions for command line parsing */ /* */ /* */ /* */ /* (C) 2000-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> #include <errno.h> /* common */ #include "abend.h" #include "chartype.h" #include "fname.h" #include "xmalloc.h" #include "cmdline.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Program name - is set after call to InitCmdLine */ const char* ProgName; /* The program argument vector */ char** ArgVec = 0; unsigned ArgCount = 0; /* Struct to pass the command line */ typedef struct { char** Vec; /* The argument vector */ unsigned Count; /* Actual number of arguments */ unsigned Size; /* Number of argument allocated */ } CmdLine; /*****************************************************************************/ /* Helper functions */ /*****************************************************************************/ static void NewCmdLine (CmdLine* L) /* Initialize a CmdLine struct */ { /* Initialize the struct */ L->Size = 8; L->Count = 0; L->Vec = xmalloc (L->Size * sizeof (L->Vec[0])); } static void AddArg (CmdLine* L, char* Arg) /* Add one argument to the list */ { if (L->Size <= L->Count) { /* No space left, reallocate */ unsigned NewSize = L->Size * 2; char** NewVec = xmalloc (NewSize * sizeof (L->Vec[0])); memcpy (NewVec, L->Vec, L->Count * sizeof (L->Vec[0])); xfree (L->Vec); L->Vec = NewVec; L->Size = NewSize; } /* We have space left, add a copy of the argument */ L->Vec[L->Count++] = Arg; } static void ExpandFile (CmdLine* L, const char* Name) /* Add the contents of a file to the command line. Each line is a separate ** argument with leading and trailing whitespace removed. */ { char Buf [256]; /* Try to open the file for reading */ FILE* F = fopen (Name, "r"); if (F == 0) { AbEnd ("Cannot open \"%s\": %s", Name, strerror (errno)); } /* File is open, read all lines */ while (fgets (Buf, sizeof (Buf), F) != 0) { /* Get a pointer to the buffer */ const char* B = Buf; /* Skip trailing whitespace (this will also kill the newline that is ** appended by fgets(). */ unsigned Len = strlen (Buf); while (Len > 0 && IsSpace (Buf [Len-1])) { --Len; } Buf [Len] = '\0'; /* Skip leading spaces */ while (IsSpace (*B)) { ++B; } /* Skip empty lines to work around problems with some editors */ if (*B == '\0') { continue; } /* Add anything not empty to the command line */ AddArg (L, xstrdup (B)); } /* Close the file, ignore errors here since we had the file open for ** reading only. */ (void) fclose (F); } /*****************************************************************************/ /* Code */ /*****************************************************************************/ 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. */ { CmdLine L; int I; /* Get the program name from argv[0] but strip a path */ if ((*aArgVec)[0] == 0) { /* Use the default name given */ ProgName = aProgName; } else { /* Strip a path */ ProgName = FindName ((*aArgVec)[0]); if (ProgName[0] == '\0') { /* Use the default */ ProgName = aProgName; } } /* Make a CmdLine struct */ NewCmdLine (&L); /* Walk over the parameters and add them to the CmdLine struct. Add a ** special handling for arguments preceeded by the '@' sign - these are ** actually files containing arguments. */ for (I = 0; I <= *aArgCount; ++I) { /* Get the next argument */ char* Arg = (*aArgVec)[I]; /* Is this a file argument? */ if (Arg && Arg[0] == '@') { /* Expand the file */ ExpandFile (&L, Arg+1); } else { /* No file, just add a copy */ AddArg (&L, Arg); } } /* Store the new argument list in a safe place... */ ArgCount = L.Count - 1; ArgVec = L.Vec; /* ...and pass back the changed data also */ *aArgCount = L.Count - 1; *aArgVec = L.Vec; } void UnknownOption (const char* Opt) /* Print an error about an unknown option and die. */ { AbEnd ("Unknown option: %s", Opt); } void NeedArg (const char* Opt) /* Print an error about a missing option argument and exit. */ { AbEnd ("Option requires an argument: %s", Opt); } void InvArg (const char* Opt, const char* Arg) /* Print an error about an invalid option argument and exit. */ { AbEnd ("Invalid argument for %s: '%s'", Opt, Arg); } void InvDef (const char* Def) /* Print an error about an invalid definition and die */ { AbEnd ("Invalid definition: '%s'", Def); } const char* GetArg (unsigned* ArgNum, unsigned Len) /* Get an argument for a short option. The argument may be appended to the ** option itself or may be separate. Len is the length of the option string. */ { const char* Arg = ArgVec[*ArgNum]; if (Arg[Len] != '\0') { /* Argument appended */ return Arg + Len; } else { /* Separate argument */ Arg = ArgVec[*ArgNum + 1]; if (Arg == 0) { /* End of arguments */ NeedArg (ArgVec[*ArgNum]); } ++(*ArgNum); return Arg; } } void LongOption (unsigned* ArgNum, const LongOpt* OptTab, unsigned OptCount) /* Handle a long command line option */ { /* Get the option and the argument (which may be zero) */ const char* Opt = ArgVec[*ArgNum]; /* Search the table for a match */ while (OptCount) { if (strcmp (Opt, OptTab->Option) == 0) { /* Found, call the function */ if (OptTab->ArgCount > 0) { /* We need an argument, check if we have one */ const char* Arg = ArgVec[++(*ArgNum)]; if (Arg == 0) { NeedArg (Opt); } OptTab->Func (Opt, Arg); } else { OptTab->Func (Opt, 0); } /* Done */ return; } /* Next table entry */ --OptCount; ++OptTab; } /* Invalid option */ UnknownOption (Opt); } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/cmdline.h����������������������������������������������������������������������0000664�0000000�0000000�00000011020�13473601511�0016042�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* cmdline.h */ /* */ /* Helper functions for command line parsing */ /* */ /* */ /* */ /* (C) 2000-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef CMDLINE_H #define CMDLINE_H #include "attrib.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Program name - is set after call to InitCmdLine */ extern const char* ProgName; /* The program argument vector */ extern char** ArgVec; extern unsigned ArgCount; /* Structure defining a long option */ typedef struct LongOpt LongOpt; struct LongOpt { const char* Option; unsigned ArgCount; void (*Func) (const char* Opt, const char* Arg); }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ 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. */ void UnknownOption (const char* Opt) attribute ((noreturn)); /* Print an error about an unknown option and die. */ void NeedArg (const char* Opt) attribute ((noreturn)); /* Print an error about a missing option argument and exit. */ void InvArg (const char* Opt, const char* Arg) attribute ((noreturn)); /* Print an error about an invalid option argument and exit. */ void InvDef (const char* Def) attribute ((noreturn)); /* Print an error about an invalid definition and die */ const char* GetArg (unsigned* ArgNum, unsigned Len); /* Get an argument for a short option. The argument may be appended to the ** option itself or may be separate. Len is the length of the option string. */ void LongOption (unsigned* ArgNum, const LongOpt* OptTab, unsigned OptCount); /* Handle a long command line option */ /* End of cmdline.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/coll.c�������������������������������������������������������������������������0000664�0000000�0000000�00000033675�13473601511�0015377�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* coll.c */ /* */ /* Collection (dynamic array) */ /* */ /* */ /* */ /* (C) 2000-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdlib.h> #include <string.h> /* common */ #include "check.h" #include "xmalloc.h" /* cc65 */ #include "coll.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* An empty collection */ const Collection EmptyCollection = STATIC_COLLECTION_INITIALIZER; /*****************************************************************************/ /* Code */ /*****************************************************************************/ Collection* InitCollection (Collection* C) /* Initialize a collection and return it. */ { /* Intialize the fields. */ C->Count = 0; C->Size = 0; C->Items = 0; /* Return the new struct */ return C; } void DoneCollection (Collection* C) /* Free the data for a collection. This will not free the data contained in ** the collection. */ { /* Free the pointer array */ xfree (C->Items); } Collection* NewCollection (void) /* Create and return a new collection with the given initial size */ { /* Allocate memory, intialize the collection and return it */ return InitCollection (xmalloc (sizeof (Collection))); } void FreeCollection (Collection* C) /* Free a collection */ { /* Free the data */ DoneCollection (C); /* Free the structure itself */ xfree (C); } void CollGrow (Collection* C, unsigned Size) /* Grow the collection C so it is able to hold Size items without a resize ** being necessary. This can be called for performance reasons if the number ** of items to be placed in the collection is known in advance. */ { void** NewItems; /* Ignore the call if the collection is already large enough */ if (Size <= C->Size) { return; } /* Grow the collection */ C->Size = Size; NewItems = xmalloc (C->Size * sizeof (void*)); memcpy (NewItems, C->Items, C->Count * sizeof (void*)); xfree (C->Items); C->Items = NewItems; } void CollInsert (Collection* C, void* Item, unsigned Index) /* Insert the data at the given position in the collection */ { /* Check for invalid indices */ PRECONDITION (Index <= C->Count); /* Grow the array if necessary */ if (C->Count >= C->Size) { /* Must grow */ CollGrow (C, (C->Size == 0)? 4 : C->Size * 2); } /* Move the existing elements if needed */ if (C->Count != Index) { memmove (C->Items+Index+1, C->Items+Index, (C->Count-Index) * sizeof (void*)); } ++C->Count; /* Store the new item */ C->Items[Index] = Item; } #if !defined(HAVE_INLINE) void CollAppend (Collection* C, void* Item) /* Append an item to the end of the collection */ { /* Insert the item at the end of the current list */ CollInsert (C, Item, C->Count); } #endif #if !defined(HAVE_INLINE) void* CollAt (const Collection* C, unsigned Index) /* Return the item at the given index */ { /* Check the index */ PRECONDITION (Index < C->Count); /* Return the element */ return C->Items[Index]; } #endif #if !defined(HAVE_INLINE) const void* CollConstAt (const Collection* C, unsigned Index) /* Return the item at the given index */ { /* Check the index */ PRECONDITION (Index < C->Count); /* Return the element */ return C->Items[Index]; } #endif #if !defined(HAVE_INLINE) void* CollLast (Collection* C) /* Return the last item in a collection */ { /* We must have at least one entry */ PRECONDITION (C->Count > 0); /* Return the element */ return C->Items[C->Count-1]; } #endif #if !defined(HAVE_INLINE) const void* CollConstLast (const Collection* C) /* Return the last item in a collection */ { /* We must have at least one entry */ PRECONDITION (C->Count > 0); /* Return the element */ return C->Items[C->Count-1]; } #endif #if !defined(HAVE_INLINE) void* CollPop (Collection* C) /* Remove the last segment from the stack and return it. Calls FAIL if the ** collection is empty. */ { /* We must have at least one entry */ PRECONDITION (C->Count > 0); /* Return the element */ return C->Items[--C->Count]; } #endif int CollIndex (Collection* C, const void* Item) /* Return the index of the given item in the collection. Return -1 if the ** item was not found in the collection. */ { /* Linear search */ unsigned I; for (I = 0; I < C->Count; ++I) { if (Item == C->Items[I]) { /* Found */ return (int)I; } } /* Not found */ return -1; } void CollDelete (Collection* C, unsigned Index) /* Remove the item with the given index from the collection. This will not ** free the item itself, just the pointer. All items with higher indices ** will get moved to a lower position. */ { /* Check the index */ PRECONDITION (Index < C->Count); /* Remove the item pointer */ --C->Count; memmove (C->Items+Index, C->Items+Index+1, (C->Count-Index) * sizeof (void*)); } void CollDeleteItem (Collection* C, const void* Item) /* Delete the item pointer from the collection. The item must be in the ** collection, otherwise FAIL will be called. */ { /* Get the index of the entry */ int Index = CollIndex (C, Item); CHECK (Index >= 0); /* Delete the item with this index */ --C->Count; memmove (C->Items+Index, C->Items+Index+1, (C->Count-Index) * sizeof (void*)); } #if !defined(HAVE_INLINE) void CollReplace (Collection* C, void* Item, unsigned Index) /* Replace the item at the given position. The old item will not be freed, ** just the pointer will get replaced. */ { /* Check the index */ PRECONDITION (Index < C->Count); /* Replace the item pointer */ C->Items[Index] = Item; } #endif void CollReplaceExpand (Collection* C, void* Item, unsigned Index) /* If Index is a valid index for the collection, replace the item at this ** position by the one passed. If the collection is too small, expand it, ** filling unused pointers with NULL, then add the new item at the given ** position. */ { if (Index < C->Count) { /* Collection is already large enough */ C->Items[Index] = Item; } else { /* Must expand the collection */ unsigned Size = C->Size; if (Size == 0) { Size = 4; } while (Index >= Size) { Size *= 2; } CollGrow (C, Size); /* Fill up unused slots with NULL */ while (C->Count < Index) { C->Items[C->Count++] = 0; } /* Fill in the item */ C->Items[C->Count++] = Item; } } void CollMove (Collection* C, unsigned OldIndex, unsigned NewIndex) /* Move an item from one position in the collection to another. OldIndex ** is the current position of the item, NewIndex is the new index before ** the function has done it's work. Existing entries with indices NewIndex ** and up might be moved one position upwards. */ { /* Get the item; and, remove it from the collection */ void* Item = CollAt (C, OldIndex); CollDelete (C, OldIndex); /* Correct NewIndex if needed */ if (NewIndex > OldIndex) { /* Position has changed with removal */ --NewIndex; } /* Now, insert it at the new position */ CollInsert (C, Item, NewIndex); } void CollMoveMultiple (Collection* C, unsigned Start, unsigned Count, unsigned Target) /* Move a range of items from one position to another. Start is the index ** of the first item to move, Count is the number of items and Target is ** the index of the target item. The item with the index Start will later ** have the index Target. All items with indices Target and above are moved ** to higher indices. */ { void** TmpItems; unsigned Bytes; /* Check the range */ PRECONDITION (Start < C->Count && Start + Count <= C->Count && Target <= C->Count); /* Check for trivial parameters */ if (Count == 0 || Start == Target) { return; } /* Calculate the raw memory space used by the items to move */ Bytes = Count * sizeof (void*); /* Allocate temporary storage for the items */ TmpItems = xmalloc (Bytes); /* Copy the items we have to move to the temporary storage */ memcpy (TmpItems, C->Items + Start, Bytes); /* Check if the range has to be moved upwards or downwards. Move the ** existing items to their final location, so that the space needed ** for the items now in temporary storage is unoccupied. */ if (Target < Start) { /* Move downwards */ unsigned BytesToMove = (Start - Target) * sizeof (void*); memmove (C->Items+Target+Count, C->Items+Target, BytesToMove); } else if (Target < Start + Count) { /* Target is inside range */ FAIL ("Not supported"); } else { /* Move upwards */ unsigned ItemsToMove = (Target - Start - Count); unsigned BytesToMove = ItemsToMove * sizeof (void*); memmove (C->Items+Start, C->Items+Target-ItemsToMove, BytesToMove); /* Adjust the target index */ Target -= Count; } /* Move the old items to their final location */ memcpy (C->Items + Target, TmpItems, Bytes); /* Delete the temporary item space */ xfree (TmpItems); } static void QuickSort (Collection* C, int Lo, int Hi, int (*Compare) (void*, const void*, const void*), void* Data) /* Internal recursive sort function. */ { /* Get a pointer to the items */ void** Items = C->Items; /* Quicksort */ while (Hi > Lo) { int I = Lo + 1; int J = Hi; while (I <= J) { while (I <= J && Compare (Data, Items[Lo], Items[I]) >= 0) { ++I; } while (I <= J && Compare (Data, Items[Lo], Items[J]) < 0) { --J; } if (I <= J) { /* Swap I and J */ void* Tmp = Items[I]; Items[I] = Items[J]; Items[J] = Tmp; ++I; --J; } } if (J != Lo) { /* Swap J and Lo */ void* Tmp = Items[J]; Items[J] = Items[Lo]; Items[Lo] = Tmp; } if (J > (Hi + Lo) / 2) { QuickSort (C, J + 1, Hi, Compare, Data); Hi = J - 1; } else { QuickSort (C, Lo, J - 1, Compare, Data); Lo = J + 1; } } } void CollTransfer (Collection* Dest, const Collection* Source) /* Transfer all items from Source to Dest. Anything already in Dest is left ** untouched. The items in Source are not changed and are therefore in both ** Collections on return. */ { /* Be sure there's enough room in Dest */ CollGrow (Dest, Dest->Count + Source->Count); /* Copy the items */ memcpy (Dest->Items + Dest->Count, Source->Items, Source->Count * sizeof (Source->Items[0])); /* Bump the counter */ Dest->Count += Source->Count; } void CollSort (Collection* C, int (*Compare) (void*, const void*, const void*), void* Data) /* Sort the collection using the given compare function. The data pointer is ** passed as *first* element to the compare function, it's not used by the ** sort function itself. The other two pointer passed to the Compare function ** are pointers to objects. */ { if (C->Count > 1) { QuickSort (C, 0, C->Count-1, Compare, Data); } } �������������������������������������������������������������������cc65-2.18/src/common/coll.h�������������������������������������������������������������������������0000664�0000000�0000000�00000024136�13473601511�0015374�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* coll.h */ /* */ /* Collection (dynamic array) */ /* */ /* */ /* */ /* (C) 2000-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef COLL_H #define COLL_H /* common */ #include "attrib.h" #include "check.h" #include "inline.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* An array of pointers that grows if needed */ typedef struct Collection Collection; struct Collection { unsigned Count; /* Number of items in the list */ unsigned Size; /* Size of allocated array */ void** Items; /* Array with dynamic size */ }; /* An empty collection */ extern const Collection EmptyCollection; /* Initializer for static collections */ #define STATIC_COLLECTION_INITIALIZER { 0, 0, 0 } /* Initializer for auto collections */ #define AUTO_COLLECTION_INITIALIZER EmptyCollection /*****************************************************************************/ /* Code */ /*****************************************************************************/ Collection* InitCollection (Collection* C); /* Initialize a collection and return it. */ void DoneCollection (Collection* C); /* Free the data for a collection. This will not free the data contained in ** the collection. */ Collection* NewCollection (void); /* Create and return a new collection */ void FreeCollection (Collection* C); /* Free a collection */ void CollGrow (Collection* C, unsigned Size); /* Grow the collection C so it is able to hold Size items without a resize ** being necessary. This can be called for performance reasons if the number ** of items to be placed in the collection is known in advance. */ #if defined(HAVE_INLINE) INLINE unsigned CollCount (const Collection* C) /* Return the number of items in the collection */ { return C->Count; } #else # define CollCount(C) (C)->Count #endif void CollInsert (Collection* C, void* Item, unsigned Index); /* Insert the data at the given position in the collection */ #if defined(HAVE_INLINE) INLINE void CollAppend (Collection* C, void* Item) /* Append an item to the end of the collection */ { /* Insert the item at the end of the current list */ CollInsert (C, Item, C->Count); } #else void CollAppend (Collection* C, void* Item); /* Append an item to the end of the collection */ #endif #if defined(HAVE_INLINE) INLINE void* CollAt (const Collection* C, unsigned Index) /* Return the item at the given index */ { /* Check the index */ PRECONDITION (Index < C->Count); /* Return the element */ return C->Items[Index]; } #else void* CollAt (const Collection* C, unsigned Index); /* Return the item at the given index */ #endif #if defined(HAVE_INLINE) INLINE void* CollAtUnchecked (const Collection* C, unsigned Index) /* Return the item at the given index */ { /* Return the element */ return C->Items[Index]; } #else # define CollAtUnchecked(C, Index) ((C)->Items[(Index)]) #endif #if defined(HAVE_INLINE) INLINE const void* CollConstAt (const Collection* C, unsigned Index) /* Return the item at the given index */ { /* Check the index */ PRECONDITION (Index < C->Count); /* Return the element */ return C->Items[Index]; } #else const void* CollConstAt (const Collection* C, unsigned Index); /* Return the item at the given index */ #endif #if defined(HAVE_INLINE) INLINE void* CollLast (Collection* C) /* Return the last item in a collection */ { /* We must have at least one entry */ PRECONDITION (C->Count > 0); /* Return the element */ return C->Items[C->Count-1]; } #else void* CollLast (Collection* C); /* Return the last item in a collection */ #endif #if defined(HAVE_INLINE) INLINE const void* CollConstLast (const Collection* C) /* Return the last item in a collection */ { /* We must have at least one entry */ PRECONDITION (C->Count > 0); /* Return the element */ return C->Items[C->Count-1]; } #else const void* CollConstLast (const Collection* C); /* Return the last item in a collection */ #endif #if defined(HAVE_INLINE) INLINE void* CollPop (Collection* C) /* Remove the last segment from the stack and return it. Calls FAIL if the ** collection is empty. */ { /* We must have at least one entry */ PRECONDITION (C->Count > 0); /* Return the element */ return C->Items[--C->Count]; } #else void* CollPop (Collection* C); /* Remove the last segment from the stack and return it. Calls FAIL if the ** collection is empty. */ #endif int CollIndex (Collection* C, const void* Item); /* Return the index of the given item in the collection. Return -1 if the ** item was not found in the collection. */ void CollDelete (Collection* C, unsigned Index); /* Remove the item with the given index from the collection. This will not ** free the item itself, just the pointer. All items with higher indices ** will get moved to a lower position. */ void CollDeleteItem (Collection* C, const void* Item); /* Delete the item pointer from the collection. The item must be in the ** collection, otherwise FAIL will be called. */ #if defined(HAVE_INLINE) INLINE void CollDeleteAll (Collection* C) /* Delete all items from the given collection. This will not free the items ** itself, it will only remove the pointers. */ { /* This one is easy... */ C->Count = 0; } #else # define CollDeleteAll(C) ((C)->Count = 0) #endif #if defined(HAVE_INLINE) INLINE void CollReplace (Collection* C, void* Item, unsigned Index) /* Replace the item at the given position. The old item will not be freed, ** just the pointer will get replaced. */ { /* Check the index */ PRECONDITION (Index < C->Count); /* Replace the item pointer */ C->Items[Index] = Item; } #else void CollReplace (Collection* C, void* Item, unsigned Index); /* Replace the item at the given position. The old item will not be freed, ** just the pointer will get replaced. */ #endif void CollReplaceExpand (Collection* C, void* Item, unsigned Index); /* If Index is a valid index for the collection, replace the item at this ** position by the one passed. If the collection is too small, expand it, ** filling unused pointers with NULL, then add the new item at the given ** position. */ void CollMove (Collection* C, unsigned OldIndex, unsigned NewIndex); /* Move an item from one position in the collection to another. OldIndex ** is the current position of the item, NewIndex is the new index before ** the function has done it's work. Existing entries with indices NewIndex ** and up might be moved one position upwards. */ void CollMoveMultiple (Collection* C, unsigned Start, unsigned Count, unsigned Target); /* Move a range of items from one position to another. Start is the index ** of the first item to move, Count is the number of items and Target is ** the index of the target item. The item with the index Start will later ** have the index Target. All items with indices Target and above are moved ** to higher indices. */ void CollTransfer (Collection* Dest, const Collection* Source); /* Transfer all items from Source to Dest. Anything already in Dest is left ** untouched. The items in Source are not changed and are therefore in both ** Collections on return. */ void CollSort (Collection* C, int (*Compare) (void*, const void*, const void*), void* Data); /* Sort the collection using the given compare function. The data pointer is ** passed as *first* element to the compare function, it's not used by the ** sort function itself. The other two pointer passed to the Compare function ** are pointers to objects. */ /* End of coll.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/cpu.c��������������������������������������������������������������������������0000664�0000000�0000000�00000011744�13473601511�0015226�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* cpu.c */ /* */ /* CPU specifications */ /* */ /* */ /* */ /* (C) 2003-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "addrsize.h" #include "check.h" #include "cpu.h" #include "strutil.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* CPU used */ cpu_t CPU = CPU_UNKNOWN; /* Table with target names */ const char* CPUNames[CPU_COUNT] = { "none", "6502", "6502X", "65SC02", "65C02", "65816", "sweet16", "huc6280", "m740", "4510", }; /* Tables with CPU instruction sets */ const unsigned CPUIsets[CPU_COUNT] = { CPU_ISET_NONE, CPU_ISET_6502, CPU_ISET_6502 | CPU_ISET_6502X, CPU_ISET_6502 | CPU_ISET_65SC02, CPU_ISET_6502 | CPU_ISET_65SC02 | CPU_ISET_65C02, CPU_ISET_6502 | CPU_ISET_65SC02 | CPU_ISET_65C02 | CPU_ISET_65816, CPU_ISET_SWEET16, CPU_ISET_6502 | CPU_ISET_65SC02 | CPU_ISET_65C02 | CPU_ISET_HUC6280, CPU_ISET_6502 | CPU_ISET_M740, CPU_ISET_6502 | CPU_ISET_65SC02 | CPU_ISET_65C02 | CPU_ISET_4510, }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ int ValidAddrSizeForCPU (unsigned char AddrSize) /* Check if the given address size is valid for the current CPU */ { switch (AddrSize) { case ADDR_SIZE_DEFAULT: /* Always supported */ return 1; case ADDR_SIZE_ZP: /* Not supported by None and Sweet16 */ return (CPU != CPU_NONE && CPU != CPU_SWEET16); case ADDR_SIZE_ABS: /* Not supported by None */ return (CPU != CPU_NONE); case ADDR_SIZE_FAR: /* Only supported by 65816 */ return (CPU == CPU_65816); case ADDR_SIZE_LONG: /* Not supported by any CPU */ return 0; default: FAIL ("Invalid address size"); /* NOTREACHED */ return 0; } } cpu_t FindCPU (const char* Name) /* Find a CPU by name and return the target id. CPU_UNKNOWN is returned if ** the given name is no valid target. */ { unsigned I; /* Check all CPU names */ for (I = 0; I < CPU_COUNT; ++I) { if (StrCaseCmp (CPUNames [I], Name) == 0) { return (cpu_t)I; } } /* Not found */ return CPU_UNKNOWN; } ����������������������������cc65-2.18/src/common/cpu.h��������������������������������������������������������������������������0000664�0000000�0000000�00000010750�13473601511�0015227�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* cpu.h */ /* */ /* CPU specifications */ /* */ /* */ /* */ /* (C) 2003-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef CPU_H #define CPU_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* CPUs */ typedef enum { CPU_UNKNOWN = -1, /* Not specified or invalid target */ CPU_NONE, /* No CPU - for assembler */ CPU_6502, CPU_6502X, /* "Extended", that is: with illegal opcodes */ CPU_65SC02, CPU_65C02, CPU_65816, CPU_SWEET16, CPU_HUC6280, /* Used in PC engine */ CPU_M740, /* Mitsubishi 740 series MCUs */ CPU_4510, /* CPU of C65 */ CPU_COUNT /* Number of different CPUs */ } cpu_t; /* CPU instruction sets */ enum { CPU_ISET_NONE = 1 << CPU_NONE, CPU_ISET_6502 = 1 << CPU_6502, CPU_ISET_6502X = 1 << CPU_6502X, CPU_ISET_65SC02 = 1 << CPU_65SC02, CPU_ISET_65C02 = 1 << CPU_65C02, CPU_ISET_65816 = 1 << CPU_65816, CPU_ISET_SWEET16 = 1 << CPU_SWEET16, CPU_ISET_HUC6280 = 1 << CPU_HUC6280, CPU_ISET_M740 = 1 << CPU_M740, CPU_ISET_4510 = 1 << CPU_4510, }; /* CPU used */ extern cpu_t CPU; /* Table with CPU names */ extern const char* CPUNames[CPU_COUNT]; /* Table with CPU the instruction sets */ extern const unsigned CPUIsets[CPU_COUNT]; /*****************************************************************************/ /* Code */ /*****************************************************************************/ int ValidAddrSizeForCPU (unsigned char AddrSize); /* Check if the given address size is valid for the current CPU */ cpu_t FindCPU (const char* Name); /* Find a CPU by name and return the target id. CPU_UNKNOWN is returned if ** the given name is no valid target. */ /* End of cpu.h */ #endif ������������������������cc65-2.18/src/common/debugflag.c��������������������������������������������������������������������0000664�0000000�0000000�00000005554�13473601511�0016361�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* debugflag.c */ /* */ /* Global debug flag */ /* */ /* */ /* */ /* (C) 2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "debugflag.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ unsigned char Debug = 0; /* Debug mode */ ����������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/debugflag.h��������������������������������������������������������������������0000664�0000000�0000000�00000005631�13473601511�0016362�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* debugflag.h */ /* */ /* Global debug flag */ /* */ /* */ /* */ /* (C) 2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef DEBUGFLAG_H #define DEBUGFLAG_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ extern unsigned char Debug; /* Debug mode */ /* End of debugflag.h */ #endif �������������������������������������������������������������������������������������������������������cc65-2.18/src/common/exprdefs.c���������������������������������������������������������������������0000664�0000000�0000000�00000014761�13473601511�0016261�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* exprdefs.c */ /* */ /* Expression tree definitions */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include "abend.h" #include "exprdefs.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void InternalDumpExpr (const ExprNode* Expr, const ExprNode* (*ResolveSym) (const struct SymEntry*)) /* Dump an expression in RPN to stdout */ { if (Expr == 0) { return; } InternalDumpExpr (Expr->Left, ResolveSym); InternalDumpExpr (Expr->Right, ResolveSym); switch (Expr->Op) { case EXPR_LITERAL: case EXPR_ULABEL: printf (" $%04lX", Expr->V.IVal); break; case EXPR_SYMBOL: printf (" SYM("); if (ResolveSym && (Expr = ResolveSym (Expr->V.Sym)) != 0) { InternalDumpExpr (Expr, ResolveSym); } printf (") "); break; case EXPR_SECTION: printf (" SEC"); break; case EXPR_SEGMENT: printf (" SEG"); break; case EXPR_MEMAREA: printf (" MEM"); break; case EXPR_PLUS: printf (" +"); break; case EXPR_MINUS: printf (" -"); break; case EXPR_MUL: printf (" *"); break; case EXPR_DIV: printf (" /"); break; case EXPR_MOD: printf (" MOD"); break; case EXPR_OR: printf (" OR"); break; case EXPR_XOR: printf (" XOR"); break; case EXPR_AND: printf (" AND"); break; case EXPR_SHL: printf (" SHL"); break; case EXPR_SHR: printf (" SHR"); break; case EXPR_EQ: printf (" ="); break; case EXPR_NE: printf ("<>"); break; case EXPR_LT: printf (" <"); break; case EXPR_GT: printf (" >"); break; case EXPR_LE: printf (" <="); break; case EXPR_GE: printf (" >="); break; case EXPR_BOOLAND: printf (" BOOL_AND"); break; case EXPR_BOOLOR: printf (" BOOL_OR"); break; case EXPR_BOOLXOR: printf (" BOOL_XOR"); break; case EXPR_MAX: printf (" MAX"); break; case EXPR_MIN: printf (" MIN"); break; case EXPR_UNARY_MINUS: printf (" NEG"); break; case EXPR_NOT: printf (" ~"); break; case EXPR_SWAP: printf (" SWAP"); break; case EXPR_BOOLNOT: printf (" BOOL_NOT"); break; case EXPR_BANK: printf (" BANK"); break; case EXPR_BYTE0: printf (" BYTE0"); break; case EXPR_BYTE1: printf (" BYTE1"); break; case EXPR_BYTE2: printf (" BYTE2"); break; case EXPR_BYTE3: printf (" BYTE3"); break; case EXPR_WORD0: printf (" WORD0"); break; case EXPR_WORD1: printf (" WORD1"); break; case EXPR_FARADDR: printf (" FARADDR"); break; case EXPR_DWORD: printf (" DWORD"); break; case EXPR_NEARADDR: printf (" NEARADDR"); break; default: AbEnd ("Unknown Op type: %u", Expr->Op); } } void DumpExpr (const ExprNode* Expr, const ExprNode* (*ResolveSym) (const struct SymEntry*)) /* Dump an expression tree to stdout */ { InternalDumpExpr (Expr, ResolveSym); printf ("\n"); } ���������������cc65-2.18/src/common/exprdefs.h���������������������������������������������������������������������0000664�0000000�0000000�00000016232�13473601511�0016261�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* exprdefs.h */ /* */ /* Expression tree definitions */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef EXPRDEFS_H #define EXPRDEFS_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Expression type masks */ #define EXPR_TYPEMASK 0xC0 #define EXPR_BINARYNODE 0x00 #define EXPR_UNARYNODE 0x40 #define EXPR_LEAFNODE 0x80 /* Type of expression nodes */ #define EXPR_NULL 0x00 /* Internal error or NULL node */ /* Leaf node codes */ #define EXPR_LITERAL (EXPR_LEAFNODE | 0x01) #define EXPR_SYMBOL (EXPR_LEAFNODE | 0x02) #define EXPR_SECTION (EXPR_LEAFNODE | 0x03) #define EXPR_SEGMENT (EXPR_LEAFNODE | 0x04) /* Linker only */ #define EXPR_MEMAREA (EXPR_LEAFNODE | 0x05) /* Linker only */ #define EXPR_ULABEL (EXPR_LEAFNODE | 0x06) /* Assembler only */ /* Binary operations, left and right hand sides are valid */ #define EXPR_PLUS (EXPR_BINARYNODE | 0x01) #define EXPR_MINUS (EXPR_BINARYNODE | 0x02) #define EXPR_MUL (EXPR_BINARYNODE | 0x03) #define EXPR_DIV (EXPR_BINARYNODE | 0x04) #define EXPR_MOD (EXPR_BINARYNODE | 0x05) #define EXPR_OR (EXPR_BINARYNODE | 0x06) #define EXPR_XOR (EXPR_BINARYNODE | 0x07) #define EXPR_AND (EXPR_BINARYNODE | 0x08) #define EXPR_SHL (EXPR_BINARYNODE | 0x09) #define EXPR_SHR (EXPR_BINARYNODE | 0x0A) #define EXPR_EQ (EXPR_BINARYNODE | 0x0B) #define EXPR_NE (EXPR_BINARYNODE | 0x0C) #define EXPR_LT (EXPR_BINARYNODE | 0x0D) #define EXPR_GT (EXPR_BINARYNODE | 0x0E) #define EXPR_LE (EXPR_BINARYNODE | 0x0F) #define EXPR_GE (EXPR_BINARYNODE | 0x10) #define EXPR_BOOLAND (EXPR_BINARYNODE | 0x11) #define EXPR_BOOLOR (EXPR_BINARYNODE | 0x12) #define EXPR_BOOLXOR (EXPR_BINARYNODE | 0x13) #define EXPR_MAX (EXPR_BINARYNODE | 0x14) #define EXPR_MIN (EXPR_BINARYNODE | 0x15) /* Unary operations, right hand side is empty */ #define EXPR_UNARY_MINUS (EXPR_UNARYNODE | 0x01) #define EXPR_NOT (EXPR_UNARYNODE | 0x02) #define EXPR_SWAP (EXPR_UNARYNODE | 0x03) #define EXPR_BOOLNOT (EXPR_UNARYNODE | 0x04) #define EXPR_BANK (EXPR_UNARYNODE | 0x05) #define EXPR_BYTE0 (EXPR_UNARYNODE | 0x08) #define EXPR_BYTE1 (EXPR_UNARYNODE | 0x09) #define EXPR_BYTE2 (EXPR_UNARYNODE | 0x0A) #define EXPR_BYTE3 (EXPR_UNARYNODE | 0x0B) #define EXPR_WORD0 (EXPR_UNARYNODE | 0x0C) #define EXPR_WORD1 (EXPR_UNARYNODE | 0x0D) #define EXPR_FARADDR (EXPR_UNARYNODE | 0x0E) #define EXPR_DWORD (EXPR_UNARYNODE | 0x0F) #define EXPR_NEARADDR (EXPR_UNARYNODE | 0x10) /* The expression node itself */ typedef struct ExprNode ExprNode; struct ExprNode { unsigned char Op; /* Operand/Type */ ExprNode* Left; /* Left leaf */ ExprNode* Right; /* Right leaf */ struct ObjData* Obj; /* Object file reference (linker) */ union { long IVal; /* If this is a int value */ struct SymEntry* Sym; /* If this is a symbol */ unsigned SecNum; /* If this is a section and Obj != 0 */ unsigned ImpNum; /* If this is an import and Obj != 0 */ struct Import* Imp; /* If this is an import and Obj == 0 */ struct MemoryArea* Mem; /* If this is a memory area */ struct Segment* Seg; /* If this is a segment */ struct Section* Sec; /* If this is a section and Obj == 0 */ } V; }; /* Macros to determine the expression type */ #define EXPR_NODETYPE(Op) ((Op) & EXPR_TYPEMASK) #define EXPR_IS_LEAF(Op) (EXPR_NODETYPE (Op) == EXPR_LEAFNODE) #define EXPR_IS_UNARY(Op) (EXPR_NODETYPE (Op) == EXPR_UNARYNODE) #define EXPR_IS_BINARY(OP) (EXPR_NODETYPE (Op) == EXPR_BINARYNODE) /*****************************************************************************/ /* Code */ /*****************************************************************************/ void DumpExpr (const ExprNode* Expr, const ExprNode* (*ResolveSym) (const struct SymEntry*)); /* Dump an expression tree to stdout */ /* End of exprdefs.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/fileid.c�����������������������������������������������������������������������0000664�0000000�0000000�00000007262�13473601511�0015673�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* fileid.c */ /* */ /* Determine the id of a file type by extension */ /* */ /* */ /* */ /* (C) 2003-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdlib.h> #include <string.h> /* common */ #include "fileid.h" #include "fname.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ int CompareFileId (const void* Key, const void* Id) /* Compare function used when calling bsearch with a table of FileIds */ { return strcmp (Key, ((const FileId*) Id)->Ext); } const FileId* GetFileId (const char* Name, const FileId* Table, unsigned Count) /* Determine the id of the given file by looking at file extension of the name. ** The table passed to the function must be sorted alphabetically. If the ** extension is found, a pointer to the matching table entry is returned. If ** no matching table entry was found, the function returns NULL. */ { /* Determine the file type by the extension */ const char* Ext = FindExt (Name); /* Do we have an extension? */ if (Ext == 0) { return 0; } /* Search for a table entry and return it */ return bsearch (Ext+1, Table, Count, sizeof (FileId), CompareFileId); } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/fileid.h�����������������������������������������������������������������������0000664�0000000�0000000�00000007430�13473601511�0015675�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* fileid.h */ /* */ /* Determine the id of a file type by extension */ /* */ /* */ /* */ /* (C) 2003-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef FILEID_H #define FILEID_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* An entry for a table that maps extensions to some sort of identifier. Such ** a table - sorted alphabetically - is passed to GetFileId. */ typedef struct FileId FileId; struct FileId { const char Ext[4]; int Id; }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ int CompareFileId (const void* Key, const void* Id); /* Compare function used when calling bsearch with a table of FileIds */ const FileId* GetFileId (const char* Name, const FileId* Table, unsigned Count); /* Determine the id of the given file by looking at file extension of the name. ** The table passed to the function must be sorted alphabetically. If the ** extension is found, a pointer to the matching table entry is returned. If ** no matching table entry was found, the function returns NULL. */ /* End of fileid.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/filepos.c����������������������������������������������������������������������0000664�0000000�0000000�00000007054�13473601511�0016077�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* filepos.c */ /* */ /* File position data structure */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "filepos.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void InitFilePos (FilePos* P) /* Initialize the file position (set all fields to zero) */ { P->Line = 0; P->Col = 0; P->Name = 0; } int CompareFilePos (const FilePos* P1, const FilePos* P2) /* Compare two file positions. Return zero if both are equal, return a value ** > 0 if P1 is greater and P2, and a value < 0 if P1 is less than P2. The ** compare rates file index over line over column. */ { if (P1->Name > P2->Name) { return 1; } else if (P1->Name < P2->Name) { return -1; } else if (P1->Line > P2->Line) { return 1; } else if (P1->Line < P2->Line) { return -1; } else if (P1->Col > P2->Col) { return 1; } else if (P1->Col < P2->Col) { return -1; } else { return 0; } } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/filepos.h����������������������������������������������������������������������0000664�0000000�0000000�00000007320�13473601511�0016100�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* filepos.h */ /* */ /* File position data structure */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef FILEPOS_H #define FILEPOS_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Type of a file position */ typedef struct FilePos FilePos; struct FilePos { unsigned Line; /* Line */ unsigned Col; /* Column */ unsigned Name; /* File */ }; /* Initializer for a FilePos */ #define STATIC_FILEPOS_INITIALIZER { 0, 0, 0 } /*****************************************************************************/ /* Code */ /*****************************************************************************/ void InitFilePos (FilePos* P); /* Initialize the file position (set all fields to zero) */ int CompareFilePos (const FilePos* P1, const FilePos* P2); /* Compare two file positions. Return zero if both are equal, return a value ** > 0 if P1 is greater and P2, and a value < 0 if P1 is less than P2. The ** compare rates file index over line over column. */ /* End of filepos.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/filestat.c���������������������������������������������������������������������0000664�0000000�0000000�00000013146�13473601511�0016250�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* filestat.c */ /* */ /* Replacement for Windows code */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* This module works around bugs in the time conversion code supplied by ** Microsoft. See here for a description of the problem: ** http://www.codeproject.com/KB/datetime/dstbugs.aspx ** Please let me note that I find it absolutely unacceptable to just declare ** buggy behaviour like this "works as designed" as Microsoft does. The ** problems did even make it into .NET, where the DateTime builtin data type ** has exactly the same problems as described in the article above. */ #include <sys/types.h> #include <sys/stat.h> #if defined(_WIN32) # include <errno.h> # include <windows.h> #endif /* common */ #include "filestat.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ #if defined(_WIN32) static time_t FileTimeToUnixTime (const FILETIME* T) /* Calculate a unix time_t value from a FILETIME. FILETIME contains a 64 bit ** value with point zero at 1600-01-01 00:00:00 and counting 100ns intervals. ** time_t is in seconds since 1970-01-01 00:00:00. */ { /* Offset between 1600-01-01 and the Epoch in seconds. Watcom C has no ** way to express a number > 32 bit (known to me) but is able to do ** calculations with 64 bit integers, so we need to do it this way. */ static const ULARGE_INTEGER Offs = { { 0xB6109100UL, 0x00000020UL } }; ULARGE_INTEGER V; V.LowPart = T->dwLowDateTime; V.HighPart = T->dwHighDateTime; return (V.QuadPart / 10000000U) - Offs.QuadPart; } int FileStat (const char* Path, struct stat* Buf) /* Replacement function for stat() */ { HANDLE H; BY_HANDLE_FILE_INFORMATION Info; /* First call stat() */ int Error = stat (Path, Buf); if (Error != 0) { return Error; } /* Open the file using backup semantics, so we won't change atime. Then ** retrieve the correct times in UTC and replace the ones in Buf. Return ** EACCES in case of errors to avoid the hassle of translating windows ** error codes to standard ones. */ H = CreateFile (Path, GENERIC_READ, FILE_SHARE_READ, 0, /* Security attributes */ OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); /* Template file */ if (H != INVALID_HANDLE_VALUE) { if (GetFileInformationByHandle (H, &Info)) { Buf->st_ctime = FileTimeToUnixTime (&Info.ftCreationTime); Buf->st_atime = FileTimeToUnixTime (&Info.ftLastAccessTime); Buf->st_mtime = FileTimeToUnixTime (&Info.ftLastWriteTime); } else { Error = EACCES; } (void) CloseHandle (H); } else { Error = EACCES; } /* Done */ return Error; } #else int FileStat (const char* Path, struct stat* Buf) /* Replacement function for stat() */ { /* Just call the function which works without errors */ return stat (Path, Buf); } #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/filestat.h���������������������������������������������������������������������0000664�0000000�0000000�00000006662�13473601511�0016262�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* filestat.h */ /* */ /* Replacement for Windows code */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* This module works around bugs in the time conversion code supplied by ** Microsoft. See here for a description of the problem: ** http://www.codeproject.com/KB/datetime/dstbugs.aspx ** Please let me note that I find it absolutely unacceptable to just declare ** buggy behaviour like this "works as designed" as Microsoft does. The ** problems did even make it into .NET, where the DateTime builtin data type ** has exactly the same problems as described in the article above. */ #ifndef FILESTAT_H #define FILESTAT_H #include <sys/types.h> #include <sys/stat.h> /*****************************************************************************/ /* Code */ /*****************************************************************************/ int FileStat (const char* Path, struct stat* Buf); /* Replacement function for stat() */ /* End of filestat.h */ #endif ������������������������������������������������������������������������������cc65-2.18/src/common/filetime.c���������������������������������������������������������������������0000664�0000000�0000000�00000012725�13473601511�0016235�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* filetime.c */ /* */ /* Replacement for Windows code */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* This module works around bugs in the time conversion code supplied by ** Microsoft. The problem described here: ** http://www.codeproject.com/KB/datetime/dstbugs.aspx ** is also true when setting file times via utime(), so we need a ** replacement */ #if defined(_WIN32) # include <errno.h> # include <windows.h> #else # include <sys/types.h> /* FreeBSD needs this */ # include <utime.h> #endif /* common */ #include "filetime.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ #if defined(_WIN32) static FILETIME* UnixTimeToFileTime (time_t T, FILETIME* FT) /* Calculate a FILETIME value from a time_t. FILETIME contains a 64 bit ** value with point zero at 1600-01-01 00:00:00 and counting 100ns intervals. ** time_t is in seconds since 1970-01-01 00:00:00. */ { /* Offset between 1600-01-01 and the Epoch in seconds. Watcom C has no ** way to express a number > 32 bit (known to me) but is able to do ** calculations with 64 bit integers, so we need to do it this way. */ static const ULARGE_INTEGER Offs = { { 0xB6109100UL, 0x00000020UL } }; ULARGE_INTEGER V; V.QuadPart = ((unsigned __int64) T + Offs.QuadPart) * 10000000U; FT->dwLowDateTime = V.LowPart; FT->dwHighDateTime = V.HighPart; return FT; } int SetFileTimes (const char* Path, time_t T) /* Set the time of last modification and the time of last access of a file to ** the given time T. This calls utime() for system where it works, and applies ** workarounds for all others (which in fact means "WINDOWS"). */ { HANDLE H; FILETIME FileTime; int Error = EACCES; /* Assume an error */ /* Open the file */ H = CreateFile (Path, GENERIC_WRITE, FILE_SHARE_READ, 0, /* Security attributes */ OPEN_EXISTING, 0, /* File flags */ 0); /* Template file */ if (H != INVALID_HANDLE_VALUE) { /* Set access and modification time */ UnixTimeToFileTime (T, &FileTime); if (SetFileTime (H, 0, &FileTime, &FileTime)) { /* Done */ Error = 0; } /* Close the handle */ (void) CloseHandle (H); } /* Return the error code */ return Error; } #else int SetFileTimes (const char* Path, time_t T) /* Set the time of last modification and the time of last access of a file to ** the given time T. This calls utime() for system where it works, and applies ** workarounds for all others (which in fact means "WINDOWS"). */ { struct utimbuf U; /* Set access and modification time */ U.actime = T; U.modtime = T; return utime (Path, &U); } #endif �������������������������������������������cc65-2.18/src/common/filetime.h���������������������������������������������������������������������0000664�0000000�0000000�00000006550�13473601511�0016241�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* filetime.h */ /* */ /* Replacement for Windows code */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* This module works around bugs in the time conversion code supplied by ** Microsoft. The problem described here: ** http://www.codeproject.com/KB/datetime/dstbugs.aspx ** is also true when setting file times via utime(), so we need a ** replacement */ #ifndef FILETIME_H #define FILETIME_H #include <time.h> /*****************************************************************************/ /* Code */ /*****************************************************************************/ int SetFileTimes (const char* Path, time_t T); /* Set the time of last modification and the time of last access of a file to ** the given time T. This calls utime() for system where it works, and applies ** workarounds for all others (which in fact means "WINDOWS"). */ /* End of filestat.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/filetype.c���������������������������������������������������������������������0000664�0000000�0000000�00000011175�13473601511�0016256�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* filetype.c */ /* */ /* Determine the type of a file */ /* */ /* */ /* */ /* (C) 2003-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdlib.h> #include <string.h> /* common */ #include "fileid.h" #include "filetype.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ static const FileId TypeTable[] = { /* Upper case stuff for obsolete operating systems */ { "A", FILETYPE_LIB }, { "A65", FILETYPE_ASM }, { "ASM", FILETYPE_ASM }, { "C", FILETYPE_C }, { "EMD", FILETYPE_O65 }, { "GRC", FILETYPE_GR }, { "JOY", FILETYPE_O65 }, { "LIB", FILETYPE_LIB }, { "MOU", FILETYPE_O65 }, { "O", FILETYPE_OBJ }, { "O65", FILETYPE_O65 }, { "OBJ", FILETYPE_OBJ }, { "S", FILETYPE_ASM }, { "SER", FILETYPE_O65 }, { "TGI", FILETYPE_O65 }, { "a", FILETYPE_LIB }, { "a65", FILETYPE_ASM }, { "asm", FILETYPE_ASM }, { "c", FILETYPE_C }, { "emd", FILETYPE_O65 }, { "grc", FILETYPE_GR }, { "joy", FILETYPE_O65 }, { "lib", FILETYPE_LIB }, { "mou", FILETYPE_O65 }, { "o", FILETYPE_OBJ }, { "o65", FILETYPE_O65 }, { "obj", FILETYPE_OBJ }, { "s", FILETYPE_ASM }, { "ser", FILETYPE_O65 }, { "tgi", FILETYPE_O65 }, }; #define FILETYPE_COUNT (sizeof (TypeTable) / sizeof (TypeTable[0])) /*****************************************************************************/ /* Code */ /*****************************************************************************/ FILETYPE GetFileType (const char* Name) /* Determine the type of the given file by looking at the name. If the file ** type could not be determined, the function returns FILETYPE_UNKOWN. */ { /* Search for a table entry */ const FileId* F = GetFileId (Name, TypeTable, FILETYPE_COUNT); /* Return the result */ return F? F->Id : FILETYPE_UNKNOWN; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/filetype.h���������������������������������������������������������������������0000664�0000000�0000000�00000007230�13473601511�0016260�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* filetype.h */ /* */ /* Determine the type of a file */ /* */ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef FILETYPE_H #define FILETYPE_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* File types */ typedef enum { FILETYPE_UNKNOWN = -1, /* Unknown file type */ FILETYPE_C, /* C source file */ FILETYPE_ASM, /* Assembler file */ FILETYPE_OBJ, /* Object file */ FILETYPE_LIB, /* Library file */ FILETYPE_GR, /* GEOS resource file */ FILETYPE_O65 /* O65 object file */ } FILETYPE; /*****************************************************************************/ /* Code */ /*****************************************************************************/ FILETYPE GetFileType (const char* Name); /* Determine the type of the given file by looking at the name. If the file ** type could not be determined, the function returns FILETYPE_UNKOWN. */ /* End of filetype.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/fname.c������������������������������������������������������������������������0000664�0000000�0000000�00000011024�13473601511�0015514�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* fname.c */ /* */ /* File name handling utilities */ /* */ /* */ /* */ /* (C) 2000-2003 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> #include "xmalloc.h" #include "fname.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ const char* FindExt (const char* Name) /* Return a pointer to the file extension in Name or NULL if there is none */ { const char* S; /* Get the length of the name */ unsigned Len = strlen (Name); if (Len < 2) { return 0; } /* Get a pointer to the last character */ S = Name + Len - 1; /* Search for the dot, beware of subdirectories */ while (S >= Name && *S != '.' && *S != '\\' && *S != '/') { --S; } /* Did we find an extension? */ if (*S == '.') { return S; } else { return 0; } } const char* FindName (const char* Path) /* Return a pointer to the file name in Path. If there is no path leading to ** the file, the function returns Path as name. */ { /* Get the length of the name */ int Len = strlen (Path); /* Search for the path separator */ while (Len > 0 && Path[Len-1] != '\\' && Path[Len-1] != '/') { --Len; } /* Return the name or path */ return Path + Len; } char* MakeFilename (const char* Origin, const char* Ext) /* Make a new file name from Origin and Ext. If Origin has an extension, it ** is removed and Ext is appended. If Origin has no extension, Ext is simply ** appended. The result is placed in a malloc'ed buffer and returned. ** The function may be used to create "foo.o" from "foo.s". */ { char* Out; const char* P = FindExt (Origin); if (P == 0) { /* No dot, add the extension */ Out = xmalloc (strlen (Origin) + strlen (Ext) + 1); strcpy (Out, Origin); strcat (Out, Ext); } else { Out = xmalloc (P - Origin + strlen (Ext) + 1); memcpy (Out, Origin, P - Origin); strcpy (Out + (P - Origin), Ext); } return Out; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/fname.h������������������������������������������������������������������������0000664�0000000�0000000�00000006662�13473601511�0015535�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* fname.h */ /* */ /* File name handling utilities */ /* */ /* */ /* */ /* (C) 2000-2003 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef FNAME_H #define FNAME_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ const char* FindExt (const char* Name); /* Return a pointer to the file extension in Name or NULL if there is none */ const char* FindName (const char* Path); /* Return a pointer to the file name in Path. If there is no path leading to ** the file, the function returns Path as name. */ char* MakeFilename (const char* Origin, const char* Ext); /* Make a new file name from Origin and Ext. If Origin has an extension, it ** is removed and Ext is appended. If Origin has no extension, Ext is simply ** appended. The result is placed in a malloc'ed buffer and returned. ** The function may be used to create "foo.o" from "foo.s". */ /* End of fname.h */ #endif ������������������������������������������������������������������������������cc65-2.18/src/common/fp.c���������������������������������������������������������������������������0000664�0000000�0000000�00000013641�13473601511�0015042�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* fp.c */ /* */ /* Floating point support */ /* */ /* */ /* */ /* (C) 2008 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* The compiler must use the same floating point arithmetic as the target ** platform, otherwise expressions will yield a different result when ** evaluated in the compiler or on the target platform. Since writing a target ** and source library is almost double the work, we will at least add the ** hooks here, and define functions for a plug in library that may be added ** at a later time. Currently we use the builtin data types of the compiler ** that translates cc65. */ #include <string.h> /* common */ #include "fp.h" #include "xmalloc.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ #define F_SIZE sizeof(float) #define D_SIZE sizeof(float) /* NOT double! */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ size_t FP_F_Size (void) /* Return the size of the data type float */ { return F_SIZE; } unsigned char* FP_F_Data (Float Val) /* Return the raw data of a float in a malloc'ed buffer. Free after use. */ { return memcpy (xmalloc (F_SIZE), &Val.V, F_SIZE); } Float FP_F_Make (float Val) /* Make a floating point variable from a float value */ { Float D; D.V = Val; return D; } Float FP_F_FromInt (long Val) /* Convert an integer into a floating point variable */ { Float D; D.V = (float) Val; return D; } float FP_F_ToFloat (Float Val) /* Convert a Float into a native float */ { return Val.V; } Float FP_F_Add (Float Left, Float Right) /* Add two floats */ { Float D; D.V = Left.V + Right.V; return D; } Float FP_F_Sub (Float Left, Float Right) /* Subtract two floats */ { Float D; D.V = Left.V - Right.V; return D; } Float FP_F_Mul (Float Left, Float Right) /* Multiplicate two floats */ { Float D; D.V = Left.V * Right.V; return D; } Float FP_F_Div (Float Left, Float Right) /* Divide two floats */ { Float D; D.V = Left.V / Right.V; return D; } size_t FP_D_Size (void) /* Return the size of the data type double */ { return D_SIZE; } unsigned char* FP_D_Data (Double Val) /* Return the raw data of a double in a malloc'ed buffer. Free after use. */ { float F = (float) Val.V; return memcpy (xmalloc (F_SIZE), &F, F_SIZE); } Double FP_D_Make (double Val) /* Make a floating point variable from a float value */ { Double D; D.V = Val; return D; } Double FP_D_FromInt (long Val) /* Convert an integer into a floating point variable */ { Double D; D.V = Val; return D; } double FP_D_ToFloat (Double Val) /* Convert a Double into a native double */ { return Val.V; } Double FP_D_Add (Double Left, Double Right) /* Add two floats */ { Double D; D.V = Left.V + Right.V; return D; } Double FP_D_Sub (Double Left, Double Right) /* Subtract two floats */ { Double D; D.V = Left.V - Right.V; return D; } Double FP_D_Mul (Double Left, Double Right) /* Multiplicate two floats */ { Double D; D.V = Left.V * Right.V; return D; } Double FP_D_Div (Double Left, Double Right) /* Divide two floats */ { Double D; D.V = Left.V / Right.V; return D; } �����������������������������������������������������������������������������������������������cc65-2.18/src/common/fp.h���������������������������������������������������������������������������0000664�0000000�0000000�00000012214�13473601511�0015042�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* fp.h */ /* */ /* Floating point support */ /* */ /* */ /* */ /* (C) 2008 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* The compiler must use the same floating point arithmetic as the target ** platform, otherwise expressions will yield a different result when ** evaluated in the compiler or on the target platform. Since writing a target ** and source library is almost double the work, we will at least add the ** hooks here, and define functions for a plug in library that may be added ** at a later time. Currently we use the builtin data types of the compiler ** that translates cc65. ** ** BEWARE: This code will currently only work on little endian systems! */ #ifndef FP_H #define FP_H #include <stddef.h> /*****************************************************************************/ /* Data */ /*****************************************************************************/ typedef union Float Float; union Float { float V; }; typedef union Double Double; union Double { double V; }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ size_t FP_F_Size (void); /* Return the size of the data type float */ unsigned char* FP_F_Data (Float Val); /* Return the raw data of a float in a malloc'ed buffer. Free after use. */ Float FP_F_Make (float Val); /* Make a floating point variable from a float value */ Float FP_F_FromInt (long Val); /* Convert an integer into a floating point variable */ float FP_F_ToFloat (Float Val); /* Convert a Float into a native float */ Float FP_F_Add (Float Left, Float Right); /* Add two floats */ Float FP_F_Sub (Float Left, Float Right); /* Subtract two floats */ Float FP_F_Mul (Float Left, Float Right); /* Multiplicate two floats */ Float FP_F_Div (Float Left, Float Right); /* Divide two floats */ size_t FP_D_Size (void); /* Return the size of the data type double */ unsigned char* FP_D_Data (Double Val); /* Return the raw data of a double in a malloc'ed buffer. Free after use. */ Double FP_D_Make (double Val); /* Make a floating point variable from a float value */ Double FP_D_FromInt (long Val); /* Convert an integer into a floating point variable */ double FP_D_ToFloat (Double Val); /* Convert a Double into a native double */ Double FP_D_Add (Double Left, Double Right); /* Add two floats */ Double FP_D_Sub (Double Left, Double Right); /* Subtract two floats */ Double FP_D_Mul (Double Left, Double Right); /* Multiplicate two floats */ Double FP_D_Div (Double Left, Double Right); /* Divide two floats */ /* End of fp.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/fragdefs.h���������������������������������������������������������������������0000664�0000000�0000000�00000007427�13473601511�0016230�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* fragdefs.h */ /* */ /* Fragment definitions for the bin65 binary utils */ /* */ /* */ /* */ /* (C) 1998-2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef FRAGDEFS_H #define FRAGDEFS_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Masks for the fragment type byte */ #define FRAG_TYPEMASK 0x38 /* Mask the type of the fragment */ #define FRAG_BYTEMASK 0x07 /* Mask for byte count */ /* Fragment types */ #define FRAG_LITERAL 0x00 /* Literal data */ #define FRAG_EXPR 0x08 /* Expression */ #define FRAG_EXPR8 (FRAG_EXPR | 1) /* 8 bit expression */ #define FRAG_EXPR16 (FRAG_EXPR | 2) /* 16 bit expression */ #define FRAG_EXPR24 (FRAG_EXPR | 3) /* 24 bit expression */ #define FRAG_EXPR32 (FRAG_EXPR | 4) /* 32 bit expression */ #define FRAG_SEXPR 0x10 /* Signed expression */ #define FRAG_SEXPR8 (FRAG_SEXPR | 1)/* 8 bit signed expression */ #define FRAG_SEXPR16 (FRAG_SEXPR | 2)/* 16 bit signed expression */ #define FRAG_SEXPR24 (FRAG_SEXPR | 3)/* 24 bit signed expression */ #define FRAG_SEXPR32 (FRAG_SEXPR | 4)/* 32 bit signed expression */ #define FRAG_FILL 0x20 /* Fill bytes */ /* End of fragdefs.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/gentype.c����������������������������������������������������������������������0000664�0000000�0000000�00000011607�13473601511�0016110�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* gentype.c */ /* */ /* Generic data type encoding */ /* */ /* */ /* */ /* (C) 2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "check.h" #include "gentype.h" #include "strbuf.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void GT_AddArray (StrBuf* Type, unsigned ArraySize) /* Add an array with the given size to the type string in Type. This will ** NOT add the element type! */ { unsigned SizeBytes; /* Remember the current position */ unsigned Pos = SB_GetLen (Type); /* Add a dummy array token */ SB_AppendChar (Type, GT_TYPE_ARRAY); /* Add the size. */ SizeBytes = 0; do { SB_AppendChar (Type, ArraySize & 0xFF); ArraySize >>= 8; ++SizeBytes; } while (ArraySize); /* Write the correct array token */ SB_GetBuf (Type)[Pos] = GT_ARRAY (SizeBytes); } unsigned GT_GetElementCount (StrBuf* Type) /* Retrieve the element count of an array stored in Type at the current index ** position. Note: Index must point to the array token itself, since the size ** of the element count is encoded there. The index position will get moved ** past the array. */ { /* Get the number of bytes for the element count */ unsigned SizeBytes = GT_GET_SIZE (SB_Get (Type)); /* Read the size */ unsigned Size = 0; const char* Buf = SB_GetConstBuf (Type) + SB_GetLen (Type); while (SizeBytes--) { Size <<= 8; Size |= Buf[SizeBytes]; } /* Return it */ return Size; } const char* GT_AsString (const StrBuf* Type, StrBuf* String) /* Convert the type into a readable representation. The target string buffer ** will be zero terminated and a pointer to the contents are returned. */ { static const char HexTab[16] = "0123456789ABCDEF"; unsigned I; /* Convert Type into readable hex. String will have twice then length ** plus a terminator. */ SB_Realloc (String, 2 * SB_GetLen (Type) + 1); SB_Clear (String); for (I = 0; I < SB_GetLen (Type); ++I) { unsigned char C = SB_AtUnchecked (Type, I); SB_AppendChar (String, HexTab[(C & 0xF0) >> 4]); SB_AppendChar (String, HexTab[(C & 0x0F) >> 0]); } /* Terminate the string so it can be used with string functions */ SB_Terminate (String); /* Return the contents of String */ return SB_GetConstBuf (String); } �������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/gentype.h����������������������������������������������������������������������0000664�0000000�0000000�00000015711�13473601511�0016115�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* gentype.h */ /* */ /* Generic data type encoding */ /* */ /* */ /* */ /* (C) 2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* This module implements a specification for a "generic data type". It is ** called generic, because it doesn't mimic a high level language. Instead it ** tries to desrcibe the type as representation on the machine. ** The reasoning behing this type is to allow a debugger to represent the ** data to the user, independent of the actual source. ** C data types may be mapped to generic ones, but attributes like const or ** volatile are (of course) lost. ** ** The data type is stored in a char array; and, can be terminated by a zero ** (see definition of GT_END below). The latter is not really necessary; but, ** allows handling of types using the usual string functions. This is in fact ** one of the advantages of the chosen implementation: ** String buffers may be used to dynamically build types. Types may be stored ** as strings in the string pool of an object file. And a string pool may be ** used to remove duplicates and reference types using unique ids. */ #ifndef GENTYPE_H #define GENTYPE_H /* common */ #include "strbuf.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Size of a data type */ #define GT_SIZE_1 0x00U #define GT_SIZE_2 0x01U #define GT_SIZE_3 0x02U #define GT_SIZE_4 0x03U #define GT_SIZE_MASK 0x07U #define GT_GET_SIZE(x) (((x) & GT_SIZE_MASK) + 1U) /* Sign of the data type */ #define GT_UNSIGNED 0x00U #define GT_SIGNED 0x08U #define GT_SIGN_MASK 0x08U #define GT_HAS_SIGN(x) (((x) & GT_SIZE_MASK) == GT_SIGNED) /* Byte order */ #define GT_LITTLE_ENDIAN 0x00U #define GT_BIG_ENDIAN 0x10U #define GT_BYTEORDER_MASK 0x10U #define GT_IS_LITTLE_ENDIAN(x) (((x) & GT_BYTEORDER_MASK) == GT_LITTLE_ENDIAN) #define GT_IS_BIG_ENDIAN(x) (((x) & GT_BYTEORDER_MASK) == GT_BIG_ENDIAN) /* Type of the data. */ #define GT_TYPE_VOID 0x00U #define GT_TYPE_INT 0x20U #define GT_TYPE_PTR 0x40U #define GT_TYPE_FLOAT 0x60U #define GT_TYPE_ARRAY 0x80U #define GT_TYPE_FUNC 0xA0U #define GT_TYPE_STRUCT 0xC0U #define GT_TYPE_UNION 0xE0U #define GT_TYPE_MASK 0xE0U #define GT_GET_TYPE(x) ((x) & GT_TYPE_MASK) #define GT_IS_INTEGER(x) (GT_GET_TYPE(x) == GT_TYPE_INTEGER) #define GT_IS_POINTER(x) (GT_GET_TYPE(x) == GT_TYPE_POINTER) #define GT_IS_FLOAT(x) (GT_GET_TYPE(x) == GT_TYPE_FLOAT) #define GT_IS_ARRAY(x) (GT_GET_TYPE(x) == GT_TYPE_ARRAY) #define GT_IS_FUNCTION(x) (GT_GET_TYPE(x) == GT_TYPE_FUNCTION) #define GT_IS_STRUCT(x) (GT_GET_TYPE(x) == GT_TYPE_STRUCT) #define GT_IS_UNION(x) (GT_GET_TYPE(x) == GT_TYPE_UNION) /* Combined values for the 6502 family */ #define GT_VOID (GT_TYPE_VOID) #define GT_BYTE (GT_TYPE_INT | GT_LITTLE_ENDIAN | GT_UNSIGNED | GT_SIZE_1) #define GT_WORD (GT_TYPE_INT | GT_LITTLE_ENDIAN | GT_UNSIGNED | GT_SIZE_2) #define GT_DWORD (GT_TYPE_INT | GT_LITTLE_ENDIAN | GT_UNSIGNED | GT_SIZE_4) #define GT_DBYTE (GT_TYPE_PTR | GT_BIG_ENDIAN | GT_UNSIGNED | GT_SIZE_2) #define GT_PTR (GT_TYPE_PTR | GT_LITTLE_ENDIAN | GT_UNSIGNED | GT_SIZE_2) #define GT_FAR_PTR (GT_TYPE_PTR | GT_LITTLE_ENDIAN | GT_UNSIGNED | GT_SIZE_3) #define GT_ARRAY(size) (GT_TYPE_ARRAY | ((size) - 1)) /*****************************************************************************/ /* Code */ /*****************************************************************************/ void GT_AddArray (StrBuf* Type, unsigned ArraySize); /* Add an array with the given size to the type string in Type. This will ** NOT add the element type! */ unsigned GT_GetElementCount (StrBuf* Type); /* Retrieve the element count of an array stored in Type at the current index ** position. Note: Index must point to the array token itself, since the size ** of the element count is encoded there. The index position will get moved ** past the array. */ const char* GT_AsString (const StrBuf* Type, StrBuf* String); /* Convert the type into a readable representation. The target string buffer ** will be zero terminated and a pointer to the contents are returned. */ /* End of gentype.h */ #endif �������������������������������������������������������cc65-2.18/src/common/hashfunc.c���������������������������������������������������������������������0000664�0000000�0000000�00000007444�13473601511�0016240�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* hashfunc.c */ /* */ /* Hash functions */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "hashfunc.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned HashInt (unsigned V) /* Return a hash value for the given integer. The function uses Robert ** Jenkins' 32 bit integer hash function taken from ** http://www.concentric.net/~ttwang/tech/inthash.htm ** For 16 bit integers, the function may be suboptimal. */ { V = (V + 0x7ed55d16) + (V << 12); V = (V ^ 0xc761c23c) ^ (V >> 19); V = (V + 0x165667b1) + (V << 5); V = (V + 0xd3a2646c) ^ (V << 9); V = (V + 0xfd7046c5) + (V << 3); V = (V ^ 0xb55a4f09) ^ (V >> 16); return V; } unsigned HashStr (const char* S) /* Return a hash value for the given string */ { unsigned L, H; /* Do the hash */ H = L = 0; while (*S) { H = ((H << 3) ^ ((unsigned char) *S++)) + L++; } return H; } unsigned HashBuf (const StrBuf* S) /* Return a hash value for the given string buffer */ { unsigned I, L, H; /* Do the hash */ H = L = 0; for (I = 0; I < SB_GetLen (S); ++I) { H = ((H << 3) ^ ((unsigned char) SB_AtUnchecked (S, I))) + L++; } return H; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/hashfunc.h���������������������������������������������������������������������0000664�0000000�0000000�00000006263�13473601511�0016243�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* hashfunc.h */ /* */ /* Hash functions */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef HASHFUNC_H #define HASHFUNC_H /* common */ #include "attrib.h" #include "strbuf.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned HashInt (unsigned V) attribute ((const)); /* Return a hash value for the given integer. */ unsigned HashStr (const char* S) attribute ((const)); /* Return a hash value for the given string */ unsigned HashBuf (const StrBuf* S) attribute ((const)); /* Return a hash value for the given string buffer */ /* End of hashfunc.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/hashtab.c����������������������������������������������������������������������0000664�0000000�0000000�00000017240�13473601511�0016046�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* hashtab.c */ /* */ /* Generic hash table */ /* */ /* */ /* */ /* (C) 2003-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "check.h" #include "hashtab.h" #include "xmalloc.h" /*****************************************************************************/ /* struct HashTable */ /*****************************************************************************/ HashTable* InitHashTable (HashTable* T, unsigned Slots, const HashFunctions* Func) /* Initialize a hash table and return it */ { /* Initialize the fields */ T->Slots = Slots; T->Count = 0; T->Table = 0; T->Func = Func; /* Return the initialized table */ return T; } void DoneHashTable (HashTable* T) /* Destroy the contents of a hash table. Note: This will not free the entries ** in the table! */ { /* Just free the array with the table pointers */ xfree (T->Table); } void FreeHashTable (HashTable* T) /* Free a hash table. Note: This will not free the entries in the table! */ { if (T) { /* Free the contents */ DoneHashTable (T); /* Free the table structure itself */ xfree (T); } } static void HT_Alloc (HashTable* T) /* Allocate table memory */ { unsigned I; /* Allocate memory */ T->Table = xmalloc (T->Slots * sizeof (T->Table[0])); /* Initialize the table */ for (I = 0; I < T->Slots; ++I) { T->Table[I] = 0; } } HashNode* HT_FindHash (const HashTable* T, const void* Key, unsigned Hash) /* Find the node with the given key. Differs from HT_Find in that the hash ** for the key is precalculated and passed to the function. */ { HashNode* N; /* If we don't have a table, there's nothing to find */ if (T->Table == 0) { return 0; } /* Search for the entry in the given chain */ N = T->Table[Hash % T->Slots]; while (N) { /* First compare the full hash, to avoid calling the compare function ** if it is not really necessary. */ if (N->Hash == Hash && T->Func->Compare (Key, T->Func->GetKey (N)) == 0) { /* Found */ break; } /* Not found, next entry */ N = N->Next; } /* Return what we found */ return N; } void* HT_Find (const HashTable* T, const void* Key) /* Find the entry with the given key and return it */ { /* Search for the entry */ return HT_FindHash (T, Key, T->Func->GenHash (Key)); } void HT_Insert (HashTable* T, void* Entry) /* Insert an entry into the given hash table */ { HashNode* N; unsigned RHash; /* If we don't have a table, we need to allocate it now */ if (T->Table == 0) { HT_Alloc (T); } /* The first member of Entry is also the hash node */ N = Entry; /* Generate the hash over the node key. */ N->Hash = T->Func->GenHash (T->Func->GetKey (N)); /* Calculate the reduced hash */ RHash = N->Hash % T->Slots; /* Insert the entry into the correct chain */ N->Next = T->Table[RHash]; T->Table[RHash] = N; /* One more entry */ ++T->Count; } void HT_Remove (HashTable* T, void* Entry) /* Remove an entry from the given hash table */ { /* The first member of Entry is also the hash node */ HashNode* N = Entry; /* Calculate the reduced hash, which is also the slot number */ unsigned Slot = N->Hash % T->Slots; /* Remove the entry from the single linked list */ HashNode** Q = &T->Table[Slot]; while (1) { /* If the pointer is NULL, the node is not in the table which we will ** consider a serious error. */ CHECK (*Q != 0); if (*Q == N) { /* Found - remove it */ *Q = N->Next; --T->Count; break; } /* Next node */ Q = &(*Q)->Next; } } void HT_Walk (HashTable* T, int (*F) (void* Entry, void* Data), void* Data) /* Walk over all nodes of a hash table, optionally deleting entries from the ** table. For each node, the user supplied function F is called, passing a ** pointer to the entry, and the data pointer passed to HT_Walk by the caller. ** If F returns true, the node is deleted from the hash table otherwise it's ** left in place. While deleting the node, the node is not accessed, so it is ** safe for F to free the memory associcated with the entry. */ { unsigned I; /* If we don't have a table there are no entries to walk over */ if (T->Table == 0) { return; } /* Walk over all chains */ for (I = 0; I < T->Slots; ++I) { /* Get the pointer to the first entry of the hash chain */ HashNode** Cur = &T->Table[I]; /* Walk over all entries in this chain */ while (*Cur) { /* Fetch the next node in chain now, because F() may delete it */ HashNode* Next = (*Cur)->Next; /* Call the user function. N is also the pointer to the entry. If ** the function returns true, the entry is to be deleted. */ if (F (*Cur, Data)) { /* Delete the node from the chain */ *Cur = Next; --T->Count; } else { /* Next node in chain */ Cur = &(*Cur)->Next; } } } } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/hashtab.h����������������������������������������������������������������������0000664�0000000�0000000�00000015737�13473601511�0016064�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* hashtab.h */ /* */ /* Generic hash table */ /* */ /* */ /* */ /* (C) 2003-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef HASHTAB_H #define HASHTAB_H /* common */ #include "inline.h" #include "xmalloc.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Hash table node. NOTE: This structure must be the first member of a struct ** that is hashed by the module. Having it first allows to omit a pointer to ** the entry itself, because the C standard guarantees that a pointer to a ** struct can be converted to its first member. */ typedef struct HashNode HashNode; struct HashNode { HashNode* Next; /* Next entry in hash list */ unsigned Hash; /* The full hash value */ }; #define STATIC_HASHNODE_INITIALIZER { 0, 0, 0 } /* Hash table functions */ typedef struct HashFunctions HashFunctions; struct HashFunctions { unsigned (*GenHash) (const void* Key); /* Generate the hash over a key. */ const void* (*GetKey) (const void* Entry); /* Given a pointer to the user entry data, return a pointer to the key */ int (*Compare) (const void* Key1, const void* Key2); /* Compare two keys. The function must return a value less than zero if ** Key1 is smaller than Key2, zero if both are equal, and a value greater ** than zero if Key1 is greater then Key2. */ }; /* Hash table */ typedef struct HashTable HashTable; struct HashTable { unsigned Slots; /* Number of table slots */ unsigned Count; /* Number of table entries */ HashNode** Table; /* Table, dynamically allocated */ const HashFunctions* Func; /* Table functions */ }; #define STATIC_HASHTABLE_INITIALIZER(Slots, Func) { Slots, 0, 0, Func } /*****************************************************************************/ /* struct HashNode */ /*****************************************************************************/ #if defined(HAVE_INLINE) INLINE void InitHashNode (HashNode* N) /* Initialize a hash node. */ { N->Next = 0; } #else #define InitHashNode(N) do { (N)->Next = 0; } while (0) #endif /*****************************************************************************/ /* struct HashTable */ /*****************************************************************************/ HashTable* InitHashTable (HashTable* T, unsigned Slots, const HashFunctions* Func); /* Initialize a hash table and return it */ void DoneHashTable (HashTable* T); /* Destroy the contents of a hash table. Note: This will not free the entries ** in the table! */ #if defined(HAVE_INLINE) INLINE HashTable* NewHashTable (unsigned Slots, const HashFunctions* Func) /* Create a new hash table and return it. */ { /* Allocate memory, initialize and return it */ return InitHashTable (xmalloc (sizeof (HashTable)), Slots, Func); } #else #define NewHashTable(Slots, Func) InitHashTable(xmalloc (sizeof (HashTable)), Slots, Func) #endif void FreeHashTable (HashTable* T); /* Free a hash table. Note: This will not free the entries in the table! */ #if defined(HAVE_INLINE) INLINE unsigned HT_GetCount (const HashTable* T) /* Return the number of items in the table. */ { return T->Count; } #else #define HT_GetCount(T) ((T)->Count) #endif HashNode* HT_FindHash (const HashTable* T, const void* Key, unsigned Hash); /* Find the node with the given key. Differs from HT_Find in that the hash ** for the key is precalculated and passed to the function. */ void* HT_Find (const HashTable* T, const void* Key); /* Find the entry with the given key and return it */ void HT_Insert (HashTable* T, void* Entry); /* Insert an entry into the given hash table */ void HT_Remove (HashTable* T, void* Entry); /* Remove an entry from the given hash table */ void HT_Walk (HashTable* T, int (*F) (void* Entry, void* Data), void* Data); /* Walk over all nodes of a hash table, optionally deleting entries from the ** table. For each node, the user supplied function F is called, passing a ** pointer to the entry, and the data pointer passed to HT_Walk by the caller. ** If F returns true, the node is deleted from the hash table otherwise it's ** left in place. While deleting the node, the node is not accessed, so it is ** safe for F to free the memory associcated with the entry. */ /* End of hashtab.h */ #endif ���������������������������������cc65-2.18/src/common/hlldbgsym.h��������������������������������������������������������������������0000664�0000000�0000000�00000007713�13473601511�0016432�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* hlldbgsym.h */ /* */ /* Definitions for high level language debug symbols */ /* */ /* */ /* */ /* (C) 2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* This module contains definitions for high level language symbols passed ** down from the C compiler. They're collected in the assembler and written to ** the object file in binary form, then again read by the linker and finally ** placed in the debug info file. */ #ifndef HLLDBGSYM_H #define HLLDBGSYM_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Flag bits that tell something about the symbol */ #define HLL_TYPE_FUNC 0x0000U /* Function */ #define HLL_TYPE_SYM 0x0001U /* Symbol */ #define HLL_TYPE_MASK 0x0007U #define HLL_GET_TYPE(x) ((x) & HLL_TYPE_MASK) #define HLL_IS_FUNC(x) (HLL_GET_TYPE(x) == HLL_TYPE_FUNC) #define HLL_IS_SYM(x) (HLL_GET_TYPE(x) == HLL_TYPE_SYM) /* Storage class */ #define HLL_SC_AUTO 0x0000U /* On stack */ #define HLL_SC_REG 0x0008U /* Register */ #define HLL_SC_STATIC 0x0010U /* Static linkage */ #define HLL_SC_EXTERN 0x0018U /* External linkage */ #define HLL_SC_MASK 0x0078U #define HLL_GET_SC(x) ((x) & HLL_SC_MASK) /* Other information */ #define HLL_DATA_SYM 0x0080U /* Attached asm symbol */ #define HLL_HAS_SYM(x) (((x) & HLL_DATA_SYM) != 0) /* End of hlldbgsyms.h */ #endif �����������������������������������������������������cc65-2.18/src/common/inline.h�����������������������������������������������������������������������0000664�0000000�0000000�00000005671�13473601511�0015724�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* inline.h */ /* */ /* Definitions to use the inline compiler feature */ /* */ /* */ /* */ /* (C) 2001-2005 Ullrich von Bassewitz */ /* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef INLINE_H #define INLINE_H /*****************************************************************************/ /* Defines */ /*****************************************************************************/ #if defined(__GNUC__) && !defined(DISABLE_INLINE) # define HAVE_INLINE 1 # define INLINE static __inline__ #endif /* End of inline.h */ #endif �����������������������������������������������������������������������cc65-2.18/src/common/intptrstack.c������������������������������������������������������������������0000664�0000000�0000000�00000007074�13473601511�0017006�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* intptrstack.c */ /* */ /* Integer+ptr stack used for program settings */ /* */ /* */ /* */ /* (C) 2017, Mega Cat Studios */ /* */ /* */ /* 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. */ /* */ /*****************************************************************************/ /* common */ #include "check.h" #include "intptrstack.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void IPS_Get (const IntPtrStack* S, long *Val, void **Ptr) /* Get the value on top of an int stack */ { PRECONDITION (S->Count > 0); if (Val) *Val = S->Stack[S->Count-1].val; if (Ptr) *Ptr = S->Stack[S->Count-1].ptr; } void IPS_Set (IntPtrStack* S, long Val, void *Ptr) /* Set the value on top of an int stack */ { PRECONDITION (S->Count > 0); S->Stack[S->Count-1].val = Val; S->Stack[S->Count-1].ptr = Ptr; } void IPS_Drop (IntPtrStack* S) /* Drop a value from an int stack */ { PRECONDITION (S->Count > 0); --S->Count; } void IPS_Push (IntPtrStack* S, long Val, void *Ptr) /* Push a value onto an int stack */ { PRECONDITION (S->Count < sizeof (S->Stack) / sizeof (S->Stack[0])); S->Stack[S->Count].val = Val; S->Stack[S->Count++].ptr = Ptr; } void IPS_Pop (IntPtrStack* S, long *Val, void **Ptr) /* Pop a value from an int stack */ { PRECONDITION (S->Count > 0); if (Val) *Val = S->Stack[--S->Count].val; if (Ptr) *Ptr = S->Stack[S->Count].ptr; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/intptrstack.h������������������������������������������������������������������0000664�0000000�0000000�00000011042�13473601511�0017001�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* intptrstack.h */ /* */ /* Integer+ptr stack used for program settings */ /* */ /* */ /* */ /* (C) 2017, Mega Cat Studios */ /* */ /* */ /* 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 INTPTRSTACK_H #define INTPTRSTACK_H #include "inline.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ typedef struct IntPtrStack IntPtrStack; struct IntPtrInner { long val; void *ptr; }; struct IntPtrStack { unsigned Count; struct IntPtrInner Stack[8]; }; /* An initializer for an empty int stack */ #define STATIC_INTPTRSTACK_INITIALIZER { 0, { 0, 0 }, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} } } /* Declare an int stack with the given value as first element */ #define INTPTRSTACK(Val, Ptr) { 1, { {Val, Ptr}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} } } /*****************************************************************************/ /* Code */ /*****************************************************************************/ #if defined(HAVE_INLINE) INLINE int IPS_IsFull (const IntPtrStack* S) /* Return true if there is no space left on the given int stack */ { return (S->Count >= sizeof (S->Stack) / sizeof (S->Stack[0])); } #else # define IPS_IsFull(S) ((S)->Count >= sizeof ((S)->Stack) / sizeof ((S)->Stack[0])) #endif #if defined(HAVE_INLINE) INLINE int IPS_IsEmpty (const IntPtrStack* S) /* Return true if there are no values on the given int stack */ { return (S->Count == 0); } #else # define IPS_IsEmpty(S) ((S)->Count == 0) #endif #if defined(HAVE_INLINE) INLINE unsigned IPS_GetCount (const IntPtrStack* S) /* Return the number of elements on the given int stack */ { return S->Count; } #else # define IPS_GetCount(S) (S)->Count #endif void IPS_Get (const IntPtrStack* S, long *Val, void **Ptr); /* Get the value on top of an int stack */ void IPS_Set (IntPtrStack* S, long Val, void *Ptr); /* Set the value on top of an int stack */ void IPS_Drop (IntPtrStack* S); /* Drop a value from an int stack */ void IPS_Push (IntPtrStack* S, long Val, void *Ptr); /* Push a value onto an int stack */ void IPS_Pop (IntPtrStack* S, long *Val, void **Ptr); /* Pop a value from an int stack */ /* End of IntPtrStack.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/intstack.c���������������������������������������������������������������������0000664�0000000�0000000�00000007017�13473601511�0016255�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* intstack.c */ /* */ /* Integer stack used for program settings */ /* */ /* */ /* */ /* (C) 2004-2010, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "check.h" #include "intstack.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ long IS_Get (const IntStack* S) /* Get the value on top of an int stack */ { PRECONDITION (S->Count > 0); return S->Stack[S->Count-1]; } void IS_Set (IntStack* S, long Val) /* Set the value on top of an int stack */ { PRECONDITION (S->Count > 0); S->Stack[S->Count-1] = Val; } void IS_Drop (IntStack* S) /* Drop a value from an int stack */ { PRECONDITION (S->Count > 0); --S->Count; } void IS_Push (IntStack* S, long Val) /* Push a value onto an int stack */ { PRECONDITION (S->Count < sizeof (S->Stack) / sizeof (S->Stack[0])); S->Stack[S->Count++] = Val; } long IS_Pop (IntStack* S) /* Pop a value from an int stack */ { PRECONDITION (S->Count > 0); return S->Stack[--S->Count]; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/intstack.h���������������������������������������������������������������������0000664�0000000�0000000�00000010770�13473601511�0016262�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* intstack.h */ /* */ /* Integer stack used for program settings */ /* */ /* */ /* */ /* (C) 2004-2010, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef INTSTACK_H #define INTSTACK_H #include "inline.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ typedef struct IntStack IntStack; struct IntStack { unsigned Count; long Stack[8]; }; /* An initializer for an empty int stack */ #define STATIC_INTSTACK_INITIALIZER { 0, { 0, 0, 0, 0, 0, 0, 0, 0 } } /* Declare an int stack with the given value as first element */ #define INTSTACK(Val) { 1, { Val, 0, 0, 0, 0, 0, 0, 0 } } /*****************************************************************************/ /* Code */ /*****************************************************************************/ #if defined(HAVE_INLINE) INLINE int IS_IsFull (const IntStack* S) /* Return true if there is no space left on the given int stack */ { return (S->Count >= sizeof (S->Stack) / sizeof (S->Stack[0])); } #else # define IS_IsFull(S) ((S)->Count >= sizeof ((S)->Stack) / sizeof ((S)->Stack[0])) #endif #if defined(HAVE_INLINE) INLINE int IS_IsEmpty (const IntStack* S) /* Return true if there are no values on the given int stack */ { return (S->Count == 0); } #else # define IS_IsEmpty(S) ((S)->Count == 0) #endif #if defined(HAVE_INLINE) INLINE unsigned IS_GetCount (const IntStack* S) /* Return the number of elements on the given int stack */ { return S->Count; } #else # define IS_GetCount(S) (S)->Count #endif long IS_Get (const IntStack* S); /* Get the value on top of an int stack */ void IS_Set (IntStack* S, long Val); /* Set the value on top of an int stack */ void IS_Drop (IntStack* S); /* Drop a value from an int stack */ void IS_Push (IntStack* S, long Val); /* Push a value onto an int stack */ long IS_Pop (IntStack* S); /* Pop a value from an int stack */ /* End of intstack.h */ #endif ��������cc65-2.18/src/common/inttypes.h���������������������������������������������������������������������0000664�0000000�0000000�00000006332�13473601511�0016320�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* inttypes.h */ /* */ /* Define integer types */ /* */ /* */ /* */ /* (C) 2004 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef INTTYPES_H #define INTTYPES_H /* If we have <stdint.h>, include it; otherwise, adapt types from <stddef.h>. ** gcc and msvc don't define __STDC_VERSION__ without special flags, so check ** for them explicitly. Undefined symbols are replaced by zero; so, checks for ** defined(__GNUC__) and defined(_MSC_VER) aren't necessary. */ #if (__STDC_VERSION__ >= 199901) || (__GNUC__ >= 3) || (_MSC_VER >= 1600) #include <stdint.h> #else /* Assume that ptrdiff_t and size_t are wide enough to hold pointers. ** Assume that they are the widest type. */ #include <stddef.h> typedef ptrdiff_t intptr_t; typedef size_t uintptr_t; typedef ptrdiff_t intmax_t; typedef size_t uintmax_t; #endif /* End of inttypes.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/libdefs.h����������������������������������������������������������������������0000664�0000000�0000000�00000006510�13473601511�0016047�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* libdefs.h */ /* */ /* Library file definitions */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef LIBDEFS_H #define LIBDEFS_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Defines for magic and version */ #define LIB_MAGIC 0x7A55616E #define LIB_VERSION 0x000D /* Size of an library file header */ #define LIB_HDR_SIZE 12 /* Header structure for the library */ typedef struct LibHeader LibHeader; struct LibHeader { unsigned long Magic; /* 32: Magic number */ unsigned Version; /* 16: Version number */ unsigned Flags; /* 16: flags */ unsigned long IndexOffs; /* 32: Offset to directory */ }; /* End of libdefs.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/lidefs.h�����������������������������������������������������������������������0000664�0000000�0000000�00000006563�13473601511�0015715�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* lidefs.h */ /* */ /* Definitions for line information */ /* */ /* */ /* */ /* (C) 2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* 70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef LIDEFS_H #define LIDEFS_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Types of line infos. */ #define LI_TYPE_ASM 0U /* Normal assembler source */ #define LI_TYPE_EXT 1U /* Externally supplied line info */ #define LI_TYPE_MACRO 2U /* Macro expansion */ #define LI_TYPE_MACPARAM 3U /* Macro parameter expansion */ /* Make a combined value from type and count */ #define LI_MAKE_TYPE(T,C) ((T) | (((unsigned)(C)) << 2U)) /* Extract type and count from a type field */ #define LI_GET_TYPE(T) ((T) & 0x03U) #define LI_GET_COUNT(T) ((unsigned)(T) >> 2) /* End of lidefs.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/matchpat.c���������������������������������������������������������������������0000664�0000000�0000000�00000020351�13473601511�0016232�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* matchpat.c */ /* */ /* Unix shell like pattern matching */ /* */ /* */ /* */ /* (C) 2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* common */ #include "matchpat.h" /*****************************************************************************/ /* Character bit set implementation */ /*****************************************************************************/ typedef unsigned char CharSet[32]; /* 256 bits */ /* Clear a character set */ #define CS_CLEAR(CS) memset (CS, 0, sizeof (CharSet)) /* Set all characters in the set */ #define CS_SETALL(CS) memset (CS, 0xFF, sizeof (CharSet)) /* Add one char to the set */ #define CS_ADD(CS, C) ((CS)[(C) >> 3] |= (0x01 << ((C) & 0x07))) /* Check if a character is a member of the set */ #define CS_CONTAINS(CS, C) ((CS)[(C) >> 3] & (0x01 << ((C) & 0x07))) /* Invert a character set */ #define CS_INVERT(CS) \ do { \ unsigned I; \ for (I = 0; I < sizeof (CharSet); ++I) { \ CS[I] ^= 0xFF; \ } \ } while (0) /*****************************************************************************/ /* Code */ /*****************************************************************************/ /* Escape character */ #define ESCAPE_CHAR '\\' /* Utility macro used in RecursiveMatch */ #define IncPattern() Pattern++; \ if (*Pattern == '\0') { \ return 0; \ } static int RealChar (const unsigned char* Pattern) /* Return the next character from Pattern. If the next character is the ** escape character, skip it and return the following. */ { if (*Pattern == ESCAPE_CHAR) { Pattern++; return (*Pattern == '\0') ? -1 : *Pattern; } else { return *Pattern; } } static int RecursiveMatch (const unsigned char* Source, const unsigned char* Pattern) /* A recursive pattern matcher */ { CharSet CS; while (1) { if (*Pattern == '\0') { /* Reached the end of Pattern, what about Source? */ return (*Source == '\0') ? 1 : 0; } else if (*Pattern == '*') { if (*++Pattern == '\0') { /* A trailing '*' is always a match */ return 1; } /* Check the rest of the string */ while (*Source) { if (RecursiveMatch (Source++, Pattern)) { /* Match! */ return 1; } } /* No match... */ return 0; } else if (*Source == '\0') { /* End of Source reached, no match */ return 0; } else { /* Check a single char. Build a set of all possible characters in ** CS, then check if the current char of Source is contained in ** there. */ CS_CLEAR (CS); /* Clear the character set */ if (*Pattern == '?') { /* All chars are allowed */ CS_SETALL (CS); ++Pattern; /* Skip '?' */ } else if (*Pattern == ESCAPE_CHAR) { /* Use the next char as is */ IncPattern (); CS_ADD (CS, *Pattern); ++Pattern; /* Skip the character */ } else if (*Pattern == '[') { /* A set follows */ int Invert = 0; IncPattern (); if (*Pattern == '!') { IncPattern (); Invert = 1; } while (*Pattern != ']') { int C1; if ((C1 = RealChar (Pattern)) == -1) { return 0; } IncPattern (); if (*Pattern != '-') { CS_ADD (CS, C1); } else { int C2; unsigned char C; IncPattern (); if ((C2 = RealChar (Pattern)) == -1) { return 0; } IncPattern (); for (C = C1; C <= C2; C++) { CS_ADD (CS, C); } } } /* Skip ']' */ ++Pattern; if (Invert) { /* Reverse all bits in the set */ CS_INVERT (CS); } } else { /* Include the char in the charset, then skip it */ CS_ADD (CS, *Pattern); ++Pattern; } if (!CS_CONTAINS (CS, *Source)) { /* No match */ return 0; } ++Source; } } } int MatchPattern (const char* Source, const char* Pattern) /* Match the string in Source against Pattern. Pattern may contain the ** wildcards '*', '?', '[abcd]' '[ab-d]', '[!abcd]', '[!ab-d]'. The ** function returns a value of zero if Source does not match Pattern, ** otherwise a non zero value is returned. If Pattern contains an invalid ** wildcard pattern (e.g. 'A[x'), the function returns zero. */ { /* Handle the trivial cases */ if (Pattern == 0 || *Pattern == '\0') { return (Source == 0 || *Source == '\0'); } /* Do the real thing */ return RecursiveMatch ((const unsigned char*) Source, (const unsigned char*) Pattern); } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/matchpat.h���������������������������������������������������������������������0000664�0000000�0000000�00000006360�13473601511�0016243�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* matchpat.h */ /* */ /* Unix shell like pattern matching */ /* */ /* */ /* */ /* (C) 2002 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 MATCHPAT_H #define MATCHPAT_H #include "attrib.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ int MatchPattern (const char* Source, const char* Pattern); /* Match the string in Source against Pattern. Pattern may contain the ** wildcards '*', '?', '[abcd]' '[ab-d]', '[!abcd]', '[!ab-d]'. The ** function returns a value of zero if Source does not match Pattern, ** otherwise a non zero value is returned. If Pattern contains an invalid ** wildcard pattern (e.g. 'A[x'), the function returns zero. */ /* End of matchpat.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/mmodel.c�����������������������������������������������������������������������0000664�0000000�0000000�00000011240�13473601511�0015703�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* mmodel.c */ /* */ /* Memory model definitions */ /* */ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* common */ #include "addrsize.h" #include "mmodel.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Memory model in use */ mmodel_t MemoryModel = MMODEL_UNKNOWN; /* Table with memory model names */ static const char* MemoryModelNames[MMODEL_COUNT] = { "near", "far", "huge", }; /* Address sizes for the segments */ unsigned char CodeAddrSize = ADDR_SIZE_ABS; unsigned char DataAddrSize = ADDR_SIZE_ABS; unsigned char ZpAddrSize = ADDR_SIZE_ZP; /*****************************************************************************/ /* Code */ /*****************************************************************************/ mmodel_t FindMemoryModel (const char* Name) /* Find a memory model by name. Return MMODEL_UNKNOWN for an unknown name. */ { unsigned I; /* Check all CPU names */ for (I = 0; I < MMODEL_COUNT; ++I) { if (strcmp (MemoryModelNames[I], Name) == 0) { return (mmodel_t)I; } } /* Not found */ return MMODEL_UNKNOWN; } void SetMemoryModel (mmodel_t Model) /* Set the memory model updating the MemoryModel variables and the address ** sizes for the segments. */ { /* Remember the memory model */ MemoryModel = Model; /* Set the address sizes for the segments */ switch (MemoryModel) { case MMODEL_NEAR: /* Code: near, data: near */ CodeAddrSize = ADDR_SIZE_ABS; DataAddrSize = ADDR_SIZE_ABS; break; case MMODEL_FAR: /* Code: far, data: near */ CodeAddrSize = ADDR_SIZE_FAR; DataAddrSize = ADDR_SIZE_ABS; break; case MMODEL_HUGE: /* Code: far, data: far */ CodeAddrSize = ADDR_SIZE_FAR; DataAddrSize = ADDR_SIZE_FAR; break; default: break; } /* Zeropage is always zeropage */ ZpAddrSize = ADDR_SIZE_ZP; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/mmodel.h�����������������������������������������������������������������������0000664�0000000�0000000�00000007475�13473601511�0015727�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* mmodel.h */ /* */ /* Memory model definitions */ /* */ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef MMODEL_H #define MMODEL_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Memory models */ typedef enum { MMODEL_UNKNOWN = -1, MMODEL_NEAR, /* Code: near, data: near */ MMODEL_FAR, /* Code: far, data: near */ MMODEL_HUGE, /* Code: far, data: far */ MMODEL_COUNT /* Number of memory models */ } mmodel_t; /* Memory model in use */ extern mmodel_t MemoryModel; /* Address sizes for the segments */ extern unsigned char CodeAddrSize; extern unsigned char DataAddrSize; extern unsigned char ZpAddrSize; /*****************************************************************************/ /* Code */ /*****************************************************************************/ mmodel_t FindMemoryModel (const char* Name); /* Find a memory model by name. Return MMODEL_UNKNOWN for an unknown name. */ void SetMemoryModel (mmodel_t Model); /* Set the memory model updating the MemoryModel variables and the address ** sizes for the segments. */ /* End of mmodel.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/objdefs.h����������������������������������������������������������������������0000664�0000000�0000000�00000011671�13473601511�0016057�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* objdefs.h */ /* */ /* Object file definitions */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef OBJDEFS_H #define OBJDEFS_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Defines for magic and version */ #define OBJ_MAGIC 0x616E7A55 #define OBJ_VERSION 0x0011 /* Size of an object file header */ #define OBJ_HDR_SIZE (24*4) /* Flag bits */ #define OBJ_FLAGS_DBGINFO 0x0001 /* File has debug info */ #define OBJ_HAS_DBGINFO(x) (((x) & OBJ_FLAGS_DBGINFO) != 0) /* Header structure */ typedef struct ObjHeader ObjHeader; struct ObjHeader { unsigned long Magic; /* 32: Magic number */ unsigned Version; /* 16: Version number */ unsigned Flags; /* 16: flags */ unsigned long OptionOffs; /* 32: Offset to option table */ unsigned long OptionSize; /* 32: Size of options */ unsigned long FileOffs; /* 32: Offset to file table */ unsigned long FileSize; /* 32: Size of files */ unsigned long SegOffs; /* 32: Offset to segment table */ unsigned long SegSize; /* 32: Size of segment table */ unsigned long ImportOffs; /* 32: Offset to import list */ unsigned long ImportSize; /* 32: Size of import list */ unsigned long ExportOffs; /* 32: Offset to export list */ unsigned long ExportSize; /* 32: Size of export list */ unsigned long DbgSymOffs; /* 32: Offset to list of debug symbols */ unsigned long DbgSymSize; /* 32: Size of debug symbols */ unsigned long LineInfoOffs; /* 32: Offset to list of line infos */ unsigned long LineInfoSize; /* 32: Size of line infos */ unsigned long StrPoolOffs; /* 32: Offset to string pool */ unsigned long StrPoolSize; /* 32: Size of string pool */ unsigned long AssertOffs; /* 32: Offset to assertion table */ unsigned long AssertSize; /* 32: Size of assertion table */ unsigned long ScopeOffs; /* 32: Offset into scope table */ unsigned long ScopeSize; /* 32: Size of scope table */ unsigned long SpanOffs; /* 32: Offset into span table */ unsigned long SpanSize; /* 32: Size of span table */ }; /* End of objdefs.h */ #endif �����������������������������������������������������������������������cc65-2.18/src/common/optdefs.h����������������������������������������������������������������������0000664�0000000�0000000�00000007332�13473601511�0016106�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* optdefs.h */ /* */ /* Definitions for object file options */ /* */ /* */ /* */ /* (C) 1998-2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef OPTDEFS_H #define OPTDEFS_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Type of options */ #define OPT_ARGMASK 0xC0 /* Mask for argument */ #define OPT_ARGSTR 0x00 /* String argument */ #define OPT_ARGNUM 0x40 /* Numerical argument */ #define OPT_COMMENT (OPT_ARGSTR+0) /* Generic comment */ #define OPT_AUTHOR (OPT_ARGSTR+1) /* Author specification */ #define OPT_TRANSLATOR (OPT_ARGSTR+2) /* Translator specification */ #define OPT_COMPILER (OPT_ARGSTR+3) /* Compiler specification */ #define OPT_OS (OPT_ARGSTR+4) /* Operating system specification */ #define OPT_DATETIME (OPT_ARGNUM+0) /* Date/time of translation */ /* Structure to encode options */ typedef struct Option Option; struct Option { Option* Next; /* For list of options */ unsigned char Type; /* Type of option */ unsigned long Val; /* Value attribute or string index */ }; /* End of optdefs.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/print.c������������������������������������������������������������������������0000664�0000000�0000000�00000006655�13473601511�0015600�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* print.c */ /* */ /* Program output */ /* */ /* */ /* */ /* (C) 2001 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdarg.h> /* common */ #include "print.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ unsigned char Verbosity = 0; /* Verbose operation flag */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Print (FILE* F, unsigned V, const char* Format, ...) /* Output according to Verbosity */ { va_list ap; /* Check the verbosity */ if (V > Verbosity) { /* Don't output this message */ return; } /* Output */ va_start (ap, Format); vfprintf (F, Format, ap); va_end (ap); } �����������������������������������������������������������������������������������cc65-2.18/src/common/print.h������������������������������������������������������������������������0000664�0000000�0000000�00000006467�13473601511�0015606�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* print.h */ /* */ /* Program output */ /* */ /* */ /* */ /* (C) 2001 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 PRINT_H #define PRINT_H #include <stdio.h> /* common */ #include "attrib.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ extern unsigned char Verbosity; /* Verbose operation flag */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Print (FILE* F, unsigned V, const char* Format, ...) attribute ((format (printf, 3, 4))); /* Output according to Verbosity */ /* End of print.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/scopedefs.h��������������������������������������������������������������������0000664�0000000�0000000�00000007471�13473601511�0016421�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* symdefs.h */ /* */ /* Scope definitions for the bin65 binary utils */ /* */ /* */ /* */ /* (C) 2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef SCOPEDEFS_H #define SCOPEDEFS_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Size of scope available? */ #define SCOPE_SIZELESS 0x00U /* No scope size available */ #define SCOPE_SIZE 0x01U /* Scope has a size */ #define SCOPE_MASK_SIZE 0x01U /* Size mask */ #define SCOPE_HAS_SIZE(x) (((x) & SCOPE_MASK_SIZE) == SCOPE_SIZE) /* Does the scope has a label? */ #define SCOPE_UNLABELED 0x00U /* Scope has no label */ #define SCOPE_LABELED 0x02U /* Scope has a label */ #define SCOPE_MASK_LABEL 0x02U /* Label size */ #define SCOPE_HAS_LABEL(x) (((x) & SCOPE_MASK_LABEL) == SCOPE_LABELED) /* Scope types */ enum { SCOPE_GLOBAL, /* Global level */ SCOPE_FILE, /* File level */ SCOPE_SCOPE, /* .SCOPE/.PROC */ SCOPE_HAS_DATA = SCOPE_SCOPE, /* Last scope that contains data */ SCOPE_STRUCT, /* .STRUCT/.UNION */ SCOPE_ENUM, /* .ENUM */ SCOPE_UNDEF = 0xFF }; /* End of scopedefs.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/searchpath.c�������������������������������������������������������������������0000664�0000000�0000000�00000020276�13473601511�0016561�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* searchpath.h */ /* */ /* Handling of search paths */ /* */ /* */ /* */ /* (C) 2000-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdlib.h> #include <string.h> #if defined(_WIN32) # include <windows.h> #endif #if defined(_MSC_VER) /* Microsoft compiler */ # include <io.h> #else /* Anyone else */ # include <unistd.h> #endif /* common */ #include "coll.h" #include "searchpath.h" #include "strbuf.h" #include "xmalloc.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ static char* CleanupPath (const char* Path) /* Prepare and return a clean copy of Path */ { unsigned Len; char* NewPath; /* Get the length of the path */ Len = strlen (Path); /* Check for a trailing path separator and remove it */ if (Len > 0 && (Path[Len-1] == '\\' || Path[Len-1] == '/')) { --Len; } /* Allocate memory for the new string */ NewPath = (char*) xmalloc (Len + 1); /* Copy the path and terminate it, then return the copy */ memcpy (NewPath, Path, Len); NewPath [Len] = '\0'; return NewPath; } static void Add (SearchPaths* P, const char* New) /* Cleanup a new search path and add it to the list */ { /* Add a clean copy of the path to the collection */ CollAppend (P, CleanupPath (New)); } SearchPaths* NewSearchPath (void) /* Create a new, empty search path list */ { return NewCollection (); } void AddSearchPath (SearchPaths* P, const char* NewPath) /* Add a new search path to the end of an existing list */ { /* Allow a NULL path */ if (NewPath) { Add (P, NewPath); } } void AddSearchPathFromEnv (SearchPaths* P, const char* EnvVar) /* Add a search path from an environment variable to the end of an existing ** list. */ { AddSearchPath (P, getenv (EnvVar)); } void AddSubSearchPathFromEnv (SearchPaths* P, const char* EnvVar, const char* SubDir) /* Add a search path from an environment variable, adding a subdirectory to ** the environment variable value. */ { StrBuf Dir = AUTO_STRBUF_INITIALIZER; const char* EnvVal = getenv (EnvVar); if (EnvVal == 0) { /* Not found */ return; } /* Copy the environment variable to the buffer */ SB_CopyStr (&Dir, EnvVal); /* Add a path separator if necessary */ if (SB_NotEmpty (&Dir)) { if (SB_LookAtLast (&Dir) != '\\' && SB_LookAtLast (&Dir) != '/') { SB_AppendChar (&Dir, '/'); } } /* Add the subdirectory and terminate the string */ SB_AppendStr (&Dir, SubDir); SB_Terminate (&Dir); /* Add the search path */ AddSearchPath (P, SB_GetConstBuf (&Dir)); /* Free the temp buffer */ SB_Done (&Dir); } void AddSubSearchPathFromWinBin (SearchPaths* P, const char* SubDir) { /* Windows only: ** Add a search path from the running binary, adding a subdirectory to ** the parent directory of the directory containing the binary. */ #if defined(_WIN32) char Dir[_MAX_PATH]; char* Ptr; if (GetModuleFileName (NULL, Dir, _MAX_PATH) == 0) { return; } /* Remove binary name */ Ptr = strrchr (Dir, '\\'); if (Ptr == 0) { return; } *Ptr = '\0'; /* Check for 'bin' directory */ Ptr = strrchr (Dir, '\\'); if (Ptr == 0) { return; } if (strcmp (Ptr++, "\\bin") != 0) { return; } /* Append SubDir */ strcpy (Ptr, SubDir); /* Add the search path */ AddSearchPath (P, Dir); #else (void) P; (void) SubDir; #endif } int PushSearchPath (SearchPaths* P, const char* NewPath) /* Add a new search path to the head of an existing search path list, provided ** that it's not already there. If the path is already at the first position, ** return zero, otherwise return a non zero value. */ { /* Generate a clean copy of NewPath */ char* Path = CleanupPath (NewPath); /* If we have paths, check if Path is already at position zero */ if (CollCount (P) > 0 && strcmp (CollConstAt (P, 0), Path) == 0) { /* Match. Delete the copy and return to the caller */ xfree (Path); return 0; } /* Insert a clean copy of the path at position 0, return success */ CollInsert (P, Path, 0); return 1; } void PopSearchPath (SearchPaths* P) /* Remove a search path from the head of an existing search path list */ { /* Remove the path at position 0 */ xfree (CollAt (P, 0)); CollDelete (P, 0); } char* GetSearchPath (SearchPaths* P, unsigned Index) /* Return the search path at the given index, if the index is valid, return an ** empty string otherwise. */ { if (Index < CollCount (P)) return CollAtUnchecked (P, Index); return ""; } char* SearchFile (const SearchPaths* P, const char* File) /* Search for a file in a list of directories. Return a pointer to a malloced ** area that contains the complete path, if found, return 0 otherwise. */ { char* Name = 0; StrBuf PathName = AUTO_STRBUF_INITIALIZER; /* Start the search */ unsigned I; for (I = 0; I < CollCount (P); ++I) { /* Copy the next path element into the buffer */ SB_CopyStr (&PathName, CollConstAt (P, I)); /* Add a path separator and the filename */ if (SB_NotEmpty (&PathName)) { SB_AppendChar (&PathName, '/'); } SB_AppendStr (&PathName, File); SB_Terminate (&PathName); /* Check if this file exists */ if (access (SB_GetBuf (&PathName), 0) == 0) { /* The file exists, we're done */ Name = xstrdup (SB_GetBuf (&PathName)); break; } } /* Cleanup and return the result of the search */ SB_Done (&PathName); return Name; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/searchpath.h�������������������������������������������������������������������0000664�0000000�0000000�00000011477�13473601511�0016571�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* searchpath.h */ /* */ /* Handling of search paths */ /* */ /* */ /* */ /* (C) 2000-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* Exports facilities to search files in a list of directories. */ #ifndef SEARCHPATH_H #define SEARCHPATH_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Convert argument to C string */ #define _STRINGIZE(arg) #arg #define STRINGIZE(arg) _STRINGIZE(arg) /* A search path is a pointer to the list */ typedef struct Collection SearchPaths; /*****************************************************************************/ /* Code */ /*****************************************************************************/ SearchPaths* NewSearchPath (void); /* Create a new, empty search path list */ void AddSearchPath (SearchPaths* P, const char* NewPath); /* Add a new search path to the end of an existing list */ void AddSearchPathFromEnv (SearchPaths* P, const char* EnvVar); /* Add a search path from an environment variable to the end of an existing ** list. */ void AddSubSearchPathFromEnv (SearchPaths* P, const char* EnvVar, const char* SubDir); /* Add a search path from an environment variable, adding a subdirectory to ** the environment variable value. */ void AddSubSearchPathFromWinBin (SearchPaths* P, const char* SubDir); /* Windows only: ** Add a search path from the running binary, adding a subdirectory to ** the parent directory of the directory containing the binary. */ int PushSearchPath (SearchPaths* P, const char* NewPath); /* Add a new search path to the head of an existing search path list, provided ** that it's not already there. If the path is already at the first position, ** return zero, otherwise return a non zero value. */ void PopSearchPath (SearchPaths* P); /* Remove a search path from the head of an existing search path list */ char* GetSearchPath (SearchPaths* P, unsigned Index); /* Return the search path at the given index, if the index is valid, return an ** empty string otherwise. */ char* SearchFile (const SearchPaths* P, const char* File); /* Search for a file in a list of directories. Return a pointer to a malloced ** area that contains the complete path, if found, return 0 otherwise. */ /* End of searchpath.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/segdefs.h����������������������������������������������������������������������0000664�0000000�0000000�00000005570�13473601511�0016064�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* segdefs.h */ /* */ /* Constants and flags for segments */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef SEGDEFS_H #define SEGDEFS_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Segment flags */ #define SEG_FLAG_NONE 0x00 /* End of segdefs.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/segnames.c���������������������������������������������������������������������0000664�0000000�0000000�00000006404�13473601511�0016236�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* segnames.h */ /* */ /* Default segment names */ /* */ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* common */ #include "chartype.h" #include "segnames.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ int ValidSegName (const char* Name) /* Return true if the given segment name is valid, return false otherwise */ { /* Must start with '_' or a letter */ if ((*Name != '_' && !IsAlpha(*Name)) || strlen(Name) > 80) { return 0; } /* Can have letters, digits or the underline */ while (*++Name) { if (*Name != '_' && !IsAlNum(*Name)) { return 0; } } /* Name is ok */ return 1; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/segnames.h���������������������������������������������������������������������0000664�0000000�0000000�00000006613�13473601511�0016245�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* segnames.h */ /* */ /* Default segment names */ /* */ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef SEGNAMES_H #define SEGNAMES_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Default segment names */ #define SEGNAME_NULL "NULL" #define SEGNAME_ZEROPAGE "ZEROPAGE" #define SEGNAME_DATA "DATA" #define SEGNAME_BSS "BSS" #define SEGNAME_RODATA "RODATA" #define SEGNAME_CODE "CODE" /*****************************************************************************/ /* Code */ /*****************************************************************************/ int ValidSegName (const char* Name); /* Return true if the given segment name is valid, return false otherwise */ /* End of segnames.h */ #endif ���������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/shift.c������������������������������������������������������������������������0000664�0000000�0000000�00000011042�13473601511�0015543�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* shift.c */ /* */ /* Safe shift routines */ /* */ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* According to the C standard, shifting a data type by the number of bits it ** has causes undefined behaviour. So ** ** unsigned long l = 1; ** unsigned u =32; ** l <<= u; ** ** may be illegal. The functions in this module behave safely in that respect, ** and they use proper casting to distinguish signed from unsigned shifts. ** They are not a general purpose replacement for the shift operator! */ #include <limits.h> /* common */ #include "shift.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ long asl_l (long l, unsigned count) /* Arithmetic shift left l by count. */ { while (1) { if (count >= CHAR_BIT * sizeof (l)) { l <<= (CHAR_BIT * sizeof (l) - 1); count -= (CHAR_BIT * sizeof (l) - 1); } else { l <<= count; break; } } return l; } long asr_l (long l, unsigned count) /* Arithmetic shift right l by count */ { while (1) { if (count >= CHAR_BIT * sizeof (l)) { l >>= (CHAR_BIT * sizeof (l) - 1); count -= (CHAR_BIT * sizeof (l) - 1); } else { l >>= count; break; } } return l; } unsigned long shl_l (unsigned long l, unsigned count) /* Logical shift left l by count */ { while (1) { if (count >= CHAR_BIT * sizeof (l)) { l <<= (CHAR_BIT * sizeof (l) - 1); count -= (CHAR_BIT * sizeof (l) - 1); } else { l <<= count; break; } } return l; } unsigned long shr_l (unsigned long l, unsigned count) /* Logical shift right l by count */ { while (1) { if (count >= CHAR_BIT * sizeof (l)) { l >>= (CHAR_BIT * sizeof (l) - 1); count -= (CHAR_BIT * sizeof (l) - 1); } else { l >>= count; break; } } return l; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/shift.h������������������������������������������������������������������������0000664�0000000�0000000�00000007112�13473601511�0015553�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* shift.h */ /* */ /* Safe shift routines */ /* */ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* According to the C standard, shifting a data type by the number of bits it ** has causes undefined behaviour. So ** ** unsigned long l = 1; ** unsigned u =32; ** l <<= u; ** ** may be illegal. The functions in this module behave safely in that respect, ** and they use proper casting to distinguish signed from unsigned shifts. ** They are not a general purpose replacement for the shift operator! */ #ifndef SHIFT_H #define SHIFT_H #include <limits.h> /*****************************************************************************/ /* Code */ /*****************************************************************************/ long asl_l (long l, unsigned count); /* Arithmetic shift left l by count. */ long asr_l (long l, unsigned count); /* Arithmetic shift right l by count */ unsigned long shl_l (unsigned long l, unsigned count); /* Logical shift left l by count */ unsigned long shr_l (unsigned long l, unsigned count); /* Logical shift right l by count */ /* End of shift.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/strbuf.c�����������������������������������������������������������������������0000664�0000000�0000000�00000032024�13473601511�0015736�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* strbuf.c */ /* */ /* Variable sized string buffers */ /* */ /* */ /* */ /* (C) 2001-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> #include <ctype.h> /* common */ #include "chartype.h" #include "strbuf.h" #include "va_copy.h" #include "xmalloc.h" #include "xsprintf.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* An empty string buf */ const StrBuf EmptyStrBuf = STATIC_STRBUF_INITIALIZER; /*****************************************************************************/ /* Code */ /*****************************************************************************/ #if !defined(HAVE_INLINE) StrBuf* SB_Init (StrBuf* B) /* Initialize a string buffer */ { *B = EmptyStrBuf; return B; } #endif StrBuf* SB_InitFromString (StrBuf* B, const char* S) /* Initialize a string buffer from a literal string. Beware: The buffer won't ** store a copy but a pointer to the actual string. */ { B->Allocated = 0; B->Len = strlen (S); B->Index = 0; B->Buf = (char*) S; return B; } void SB_Done (StrBuf* B) /* Free the data of a string buffer (but not the struct itself) */ { if (B->Allocated) { xfree (B->Buf); } } StrBuf* NewStrBuf (void) /* Allocate, initialize and return a new StrBuf */ { /* Allocate a new string buffer */ StrBuf* B = xmalloc (sizeof (StrBuf)); /* Initialize the struct... */ SB_Init (B); /* ...and return it */ return B; } void FreeStrBuf (StrBuf* B) /* Free a string buffer */ { /* Allow NULL pointers */ if (B) { SB_Done (B); xfree (B); } } void SB_Realloc (StrBuf* B, unsigned NewSize) /* Reallocate the string buffer space, make sure at least NewSize bytes are ** available. */ { /* Get the current size, use a minimum of 8 bytes */ unsigned NewAllocated = B->Allocated; if (NewAllocated == 0) { NewAllocated = 8; } /* Round up to the next power of two */ while (NewAllocated < NewSize) { NewAllocated *= 2; } /* Reallocate the buffer. Beware: The allocated size may be zero while the ** length is not. This means that we have a buffer that wasn't allocated ** on the heap. */ if (B->Allocated) { /* Just reallocate the block */ B->Buf = xrealloc (B->Buf, NewAllocated); } else { /* Allocate a new block and copy */ B->Buf = memcpy (xmalloc (NewAllocated), B->Buf, B->Len); } /* Remember the new block size */ B->Allocated = NewAllocated; } static void SB_CheapRealloc (StrBuf* B, unsigned NewSize) /* Reallocate the string buffer space, make sure at least NewSize bytes are ** available. This function won't copy the old buffer contents over to the new ** buffer and may be used if the old contents are overwritten later. */ { /* Get the current size, use a minimum of 8 bytes */ unsigned NewAllocated = B->Allocated; if (NewAllocated == 0) { NewAllocated = 8; } /* Round up to the next power of two */ while (NewAllocated < NewSize) { NewAllocated *= 2; } /* Free the old buffer if there is one */ if (B->Allocated) { xfree (B->Buf); } /* Allocate a fresh block */ B->Buf = xmalloc (NewAllocated); /* Remember the new block size */ B->Allocated = NewAllocated; } #if !defined(HAVE_INLINE) char SB_At (const StrBuf* B, unsigned Index) /* Get a character from the buffer */ { PRECONDITION (Index < B->Len); return B->Buf[Index]; } #endif void SB_Drop (StrBuf* B, unsigned Count) /* Drop characters from the end of the string. */ { PRECONDITION (Count <= B->Len); B->Len -= Count; if (B->Index > B->Len) { B->Index = B->Len; } } void SB_Terminate (StrBuf* B) /* Zero terminate the given string buffer. NOTE: The terminating zero is not ** accounted for in B->Len, if you want that, you have to use AppendChar! */ { unsigned NewLen = B->Len + 1; if (NewLen > B->Allocated) { SB_Realloc (B, NewLen); } B->Buf[B->Len] = '\0'; } void SB_CopyBuf (StrBuf* Target, const char* Buf, unsigned Size) /* Copy Buf to Target, discarding the old contents of Target */ { if (Size) { if (Target->Allocated < Size) { SB_CheapRealloc (Target, Size); } memcpy (Target->Buf, Buf, Size); } Target->Len = Size; } #if !defined(HAVE_INLINE) void SB_CopyStr (StrBuf* Target, const char* S) /* Copy S to Target, discarding the old contents of Target */ { SB_CopyBuf (Target, S, strlen (S)); } #endif #if !defined(HAVE_INLINE) void SB_Copy (StrBuf* Target, const StrBuf* Source) /* Copy Source to Target, discarding the old contents of Target */ { SB_CopyBuf (Target, Source->Buf, Source->Len); Target->Index = Source->Index; } #endif void SB_AppendChar (StrBuf* B, int C) /* Append a character to a string buffer */ { unsigned NewLen = B->Len + 1; if (NewLen > B->Allocated) { SB_Realloc (B, NewLen); } B->Buf[B->Len] = (char) C; B->Len = NewLen; } void SB_AppendBuf (StrBuf* B, const char* S, unsigned Size) /* Append a character buffer to the end of the string buffer */ { unsigned NewLen = B->Len + Size; if (NewLen > B->Allocated) { SB_Realloc (B, NewLen); } memcpy (B->Buf + B->Len, S, Size); B->Len = NewLen; } #if !defined(HAVE_INLINE) void SB_AppendStr (StrBuf* B, const char* S) /* Append a string to the end of the string buffer */ { SB_AppendBuf (B, S, strlen (S)); } #endif #if !defined(HAVE_INLINE) void SB_Append (StrBuf* Target, const StrBuf* Source) /* Append the contents of Source to Target */ { SB_AppendBuf (Target, Source->Buf, Source->Len); } #endif #if !defined(HAVE_INLINE) void SB_Cut (StrBuf* B, unsigned Len) /* Cut the contents of B at the given length. If the current length of the ** buffer is smaller than Len, nothing will happen. */ { if (Len < B->Len) { B->Len = Len; } } #endif void SB_Slice (StrBuf* Target, const StrBuf* Source, unsigned Start, unsigned Len) /* Copy a slice from Source into Target. The current contents of Target are ** destroyed. If Start is greater than the length of Source, or if Len ** characters aren't available, the result will be a buffer with less than Len ** bytes. */ { /* Calculate the length of the resulting buffer */ if (Start >= Source->Len) { /* Target will be empty */ SB_Clear (Target); return; } if (Start + Len > Source->Len) { Len = Source->Len - Start; } /* Make sure we have enough room in the target string buffer */ if (Len > Target->Allocated) { SB_Realloc (Target, Len); } /* Copy the slice */ memcpy (Target->Buf, Source->Buf + Start, Len); Target->Len = Len; } void SB_Move (StrBuf* Target, StrBuf* Source) /* Move the complete contents of Source to target. This will delete the old ** contents of Target, and Source will be empty after the call. */ { /* Free the target string */ if (Target->Allocated) { xfree (Target->Buf); } /* Move all data from Source to Target */ *Target = *Source; /* Clear Source */ SB_Init (Source); } void SB_ToLower (StrBuf* S) /* Convert all characters in S to lower case */ { unsigned I; char* B = S->Buf; for (I = 0; I < S->Len; ++I, ++B) { if (IsUpper (*B)) { *B = tolower (*B); } } } void SB_ToUpper (StrBuf* S) /* Convert all characters in S to upper case */ { unsigned I; char* B = S->Buf; for (I = 0; I < S->Len; ++I, ++B) { if (IsLower (*B)) { *B = toupper (*B); } } } int SB_Compare (const StrBuf* S1, const StrBuf* S2) /* Do a lexical compare of S1 and S2. See strcmp for result codes. */ { int Result; if (S1->Len < S2->Len) { Result = memcmp (S1->Buf, S2->Buf, S1->Len); if (Result == 0) { /* S1 considered lesser because it's shorter */ Result = -1; } } else if (S1->Len > S2->Len) { Result = memcmp (S1->Buf, S2->Buf, S2->Len); if (Result == 0) { /* S2 considered lesser because it's shorter */ Result = 1; } } else { Result = memcmp (S1->Buf, S2->Buf, S1->Len); } return Result; } int SB_CompareStr (const StrBuf* S1, const char* S2) /* Do a lexical compare of S1 and S2. See strcmp for result codes. */ { int Result; unsigned S2Len = strlen (S2); if (S1->Len < S2Len) { Result = memcmp (S1->Buf, S2, S1->Len); if (Result == 0) { /* S1 considered lesser because it's shorter */ Result = -1; } } else if (S1->Len > S2Len) { Result = memcmp (S1->Buf, S2, S2Len); if (Result == 0) { /* S2 considered lesser because it's shorter */ Result = 1; } } else { Result = memcmp (S1->Buf, S2, S1->Len); } return Result; } void SB_VPrintf (StrBuf* S, const char* Format, va_list ap) /* printf function with S as target. The function is safe, which means that ** the current contents of S are discarded, and are allocated again with ** a matching size for the output. The function will call FAIL when problems ** are detected (anything that let xsnprintf return -1). */ { va_list tmp; int SizeNeeded; /* Since we must determine the space needed anyway, we will try with ** the currently allocated memory. If the call succeeds, we've saved ** an allocation. If not, we have to reallocate and try again. */ va_copy (tmp, ap); SizeNeeded = xvsnprintf (S->Buf, S->Allocated, Format, tmp); va_end (tmp); /* Check the result, the xvsnprintf function should not fail */ CHECK (SizeNeeded >= 0); /* Check if we must reallocate */ if ((unsigned) SizeNeeded >= S->Allocated) { /* Must retry. Use CheapRealloc to avoid copying */ SB_CheapRealloc (S, SizeNeeded + 1); /* Account for '\0' */ (void) xvsnprintf (S->Buf, S->Allocated, Format, ap); } /* Update string buffer variables */ S->Len = SizeNeeded; S->Index = 0; } void SB_Printf (StrBuf* S, const char* Format, ...) /* vprintf function with S as target. The function is safe, which means that ** the current contents of S are discarded, and are allocated again with ** a matching size for the output. The function will call FAIL when problems ** are detected (anything that let xsnprintf return -1). */ { va_list ap; va_start (ap, Format); SB_VPrintf (S, Format, ap); va_end (ap); } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/strbuf.h�����������������������������������������������������������������������0000664�0000000�0000000�00000031432�13473601511�0015745�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* strbuf.h */ /* */ /* Variable sized string buffers */ /* */ /* */ /* */ /* (C) 2001-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef STRBUF_H #define STRBUF_H #include <stdarg.h> #include <string.h> /* common */ #include "attrib.h" #include "check.h" #include "inline.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ typedef struct StrBuf StrBuf; struct StrBuf { char* Buf; /* Pointer to buffer */ unsigned Len; /* Length of the string */ unsigned Index; /* Used for reading (Get and friends) */ unsigned Allocated; /* Size of allocated memory */ }; /* An empty string buf */ extern const StrBuf EmptyStrBuf; /* Initializer for static string bufs */ #define STATIC_STRBUF_INITIALIZER { 0, 0, 0, 0 } /* Initializer for auto string bufs */ #define AUTO_STRBUF_INITIALIZER { 0, 0, 0, 0 } /* Initialize with a string literal (beware: evaluates str twice!) */ #define LIT_STRBUF_INITIALIZER(str) { (char*)str, sizeof(str)-1, 0, 0 } /*****************************************************************************/ /* Code */ /*****************************************************************************/ #if defined(HAVE_INLINE) INLINE StrBuf* SB_Init (StrBuf* B) /* Initialize a string buffer */ { *B = EmptyStrBuf; return B; } #else StrBuf* SB_Init (StrBuf* B); #endif StrBuf* SB_InitFromString (StrBuf* B, const char* S); /* Initialize a string buffer from a literal string. Beware: The buffer won't ** store a copy but a pointer to the actual string. A buffer initialized with ** this routine may be "forgotten" without calling SB_Done, since no memory ** has been allocated. */ void SB_Done (StrBuf* B); /* Free the data of a string buffer (but not the struct itself) */ StrBuf* NewStrBuf (void); /* Allocate, initialize and return a new StrBuf */ void FreeStrBuf (StrBuf* B); /* Free a string buffer */ void SB_Realloc (StrBuf* B, unsigned NewSize); /* Reallocate the string buffer space, make sure at least NewSize bytes are ** available. */ #if defined(HAVE_INLINE) INLINE unsigned SB_GetLen (const StrBuf* B) /* Return the length of the buffer contents */ { return B->Len; } #else # define SB_GetLen(B) (B)->Len #endif #if defined(HAVE_INLINE) INLINE unsigned SB_GetIndex (const StrBuf* B) /* Return the user index of the string buffer */ { return B->Index; } #else # define SB_GetIndex(B) (B)->Index #endif #if defined(HAVE_INLINE) INLINE void SB_SetIndex (StrBuf* B, unsigned Index) /* Set the user index of the string buffer */ { B->Index = Index; } #else # define SB_SetIndex(B, Idx) ((B)->Index = (Idx)) #endif #if defined(HAVE_INLINE) INLINE const char* SB_GetConstBuf (const StrBuf* B) /* Return a buffer pointer */ { return B->Buf; } #else # define SB_GetConstBuf(B) (B)->Buf #endif #if defined(HAVE_INLINE) INLINE char* SB_GetBuf (StrBuf* B) /* Return a buffer pointer */ { return B->Buf; } #else # define SB_GetBuf(B) (B)->Buf #endif #if defined(HAVE_INLINE) INLINE char SB_At (const StrBuf* B, unsigned Index) /* Get a character from the buffer */ { PRECONDITION (Index < B->Len); return B->Buf[Index]; } #else char SB_At (const StrBuf* B, unsigned Index); /* Get a character from the buffer */ #endif #if defined(HAVE_INLINE) INLINE char SB_AtUnchecked (const StrBuf* B, unsigned Index) /* Get a character from the buffer */ { return B->Buf[Index]; } #else # define SB_AtUnchecked(B, Index) ((B)->Buf[Index]) #endif #if defined(HAVE_INLINE) INLINE int SB_IsEmpty (const StrBuf* B) /* Return true if the string buffer is empty */ { return (B->Len == 0); } #else # define SB_IsEmpty(B) ((B)->Len == 0) #endif #if defined(HAVE_INLINE) INLINE int SB_NotEmpty (const StrBuf* B) /* Return true if the string buffer is not empty */ { return (B->Len > 0); } #else # define SB_NotEmpty(B) ((B)->Len > 0) #endif #if defined(HAVE_INLINE) INLINE void SB_Clear (StrBuf* B) /* Clear the string buffer (make it empty) */ { B->Len = B->Index = 0; } #else # define SB_Clear(B) ((B)->Len = (B)->Index = 0) #endif #if defined(HAVE_INLINE) INLINE void SB_Reset (StrBuf* B) /* Reset the string buffer index to zero */ { B->Index = 0; } #else # define SB_Reset(B) ((B)->Index = 0) #endif #if defined(HAVE_INLINE) INLINE char SB_Get (StrBuf* B) /* Return the next character from the string incrementing Index. Returns NUL ** if the end of the string is reached. */ { return (B->Index < B->Len)? B->Buf[B->Index++] : '\0'; } #else # define SB_Get(B) (((B)->Index < (B)->Len)? (B)->Buf[(B)->Index++] : '\0') #endif #if defined(HAVE_INLINE) INLINE char SB_Peek (const StrBuf* B) /* Look at the next character from the string without incrementing Index. ** Returns NUL if the end of the string is reached. */ { return (B->Index < B->Len)? B->Buf[B->Index] : '\0'; } #else # define SB_Peek(B) (((B)->Index < (B)->Len)? (B)->Buf[(B)->Index] : '\0') #endif #if defined(HAVE_INLINE) INLINE char SB_LookAt (const StrBuf* B, unsigned Index) /* Look at a specific character from the string. Returns NUL if the given ** index is greater than the size of the string. */ { return (Index < B->Len)? B->Buf[Index] : '\0'; } #else # define SB_LookAt(B,Index) (((Index) < (B)->Len)? (B)->Buf[(Index)] : '\0') #endif #if defined(HAVE_INLINE) INLINE char SB_LookAtLast (const StrBuf* B) /* Look at the last character from the string. Returns NUL if the string buffer ** is empty. */ { return (B->Len > 0)? B->Buf[B->Len-1] : '\0'; } #else # define SB_LookAtLast(B) (((B)->Len > 0)? (B)->Buf[(B)->Len-1] : '\0') #endif #if defined(HAVE_INLINE) INLINE void SB_Skip (StrBuf* B) /* Skip the next character in the string buffer if this is possible. */ { if (B->Index < B->Len) { ++B->Index; } } #else # define SB_Skip(B) do { if ((B)->Index < (B)->Len) ++(B)->Index; } while (0) #endif #if defined(HAVE_INLINE) INLINE void SB_SkipMultiple (StrBuf* B, unsigned Count) /* Skip a number of characters in the string buffer if this is possible. */ { if ((B->Index += Count) > B->Len) { B->Index = B->Len; } } #else # define SB_SkipMultiple(B, Count) \ do { if (((B)->Index += (Count)) > (B)->Len) (B)->Index = (B)->Len; } while (0) #endif void SB_Drop (StrBuf* B, unsigned Count); /* Drop characters from the end of the string. */ void SB_Terminate (StrBuf* B); /* Zero terminate the given string buffer. NOTE: The terminating zero is not ** accounted for in B->Len, if you want that, you have to use AppendChar! */ void SB_CopyBuf (StrBuf* Target, const char* Buf, unsigned Size); /* Copy Buf to Target, discarding the old contents of Target */ #if defined(HAVE_INLINE) INLINE void SB_CopyStr (StrBuf* Target, const char* S) /* Copy S to Target, discarding the old contents of Target */ { SB_CopyBuf (Target, S, strlen (S)); } #else void SB_CopyStr (StrBuf* Target, const char* S); /* Copy S to Target, discarding the old contents of Target */ #endif #if defined(HAVE_INLINE) INLINE void SB_Copy (StrBuf* Target, const StrBuf* Source) /* Copy Source to Target, discarding the old contents of Target */ { SB_CopyBuf (Target, Source->Buf, Source->Len); Target->Index = Source->Index; } #else void SB_Copy (StrBuf* Target, const StrBuf* Source); /* Copy Source to Target, discarding the old contents of Target */ #endif void SB_AppendChar (StrBuf* B, int C); /* Append a character to a string buffer */ void SB_AppendBuf (StrBuf* B, const char* S, unsigned Size); /* Append a character buffer to the end of the string buffer */ #if defined(HAVE_INLINE) INLINE void SB_AppendStr (StrBuf* B, const char* S) /* Append a string to the end of the string buffer */ { SB_AppendBuf (B, S, strlen (S)); } #else void SB_AppendStr (StrBuf* B, const char* S); /* Append a string to the end of the string buffer */ #endif #if defined(HAVE_INLINE) INLINE void SB_Append (StrBuf* Target, const StrBuf* Source) /* Append the contents of Source to Target */ { SB_AppendBuf (Target, Source->Buf, Source->Len); } #else void SB_Append (StrBuf* Target, const StrBuf* Source); /* Append the contents of Source to Target */ #endif #if defined(HAVE_INLINE) INLINE void SB_Cut (StrBuf* B, unsigned Len) /* Cut the contents of B at the given length. If the current length of the ** buffer is smaller than Len, nothing will happen. */ { if (Len < B->Len) { B->Len = Len; } } #else void SB_Cut (StrBuf* B, unsigned Len); /* Cut the contents of B at the given length. If the current length of the ** buffer is smaller than Len, nothing will happen. */ #endif void SB_Slice (StrBuf* Target, const StrBuf* Source, unsigned Start, unsigned Len); /* Copy a slice from Source into Target. The current contents of Target are ** destroyed. If Start is greater than the length of Source, or if Len ** characters aren't available, the result will be a buffer with less than Len ** bytes. */ void SB_Move (StrBuf* Target, StrBuf* Source); /* Move the complete contents of Source to target. This will delete the old ** contents of Target, and Source will be empty after the call. */ void SB_ToLower (StrBuf* S); /* Convert all characters in S to lower case */ void SB_ToUpper (StrBuf* S); /* Convert all characters in S to upper case */ int SB_Compare (const StrBuf* S1, const StrBuf* S2); /* Do a lexical compare of S1 and S2. See strcmp for result codes. */ int SB_CompareStr (const StrBuf* S1, const char* S2); /* Do a lexical compare of S1 and S2. See strcmp for result codes. */ void SB_VPrintf (StrBuf* S, const char* Format, va_list ap) attribute ((format (printf, 2, 0))); /* printf function with S as target. The function is safe, which means that ** the current contents of S are discarded, and are allocated again with ** a matching size for the output. The function will call FAIL when problems ** are detected (anything that let xsnprintf return -1). */ void SB_Printf (StrBuf* S, const char* Format, ...) attribute ((format (printf, 2, 3))); /* vprintf function with S as target. The function is safe, which means that ** the current contents of S are discarded, and are allocated again with ** a matching size for the output. The function will call FAIL when problems ** are detected (anything that let xsnprintf return -1). */ /* End of strbuf.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/strpool.c����������������������������������������������������������������������0000664�0000000�0000000�00000021654�13473601511�0016142�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* strpool.c */ /* */ /* A string pool */ /* */ /* */ /* */ /* (C) 2003-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* A string pool is used to store identifiers and other strings. Each string ** stored in the pool has a unique id, which may be used to access the string ** in the pool. Identical strings are stored only once in the pool and have ** identical ids. This means that instead of comparing strings, just the ** string pool ids must be compared. */ #include <string.h> /* common */ #include "coll.h" #include "hashfunc.h" #include "hashtab.h" #include "strbuf.h" #include "strpool.h" #include "xmalloc.h" /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ static unsigned HT_GenHash (const void* Key); /* Generate the hash over a key. */ static const void* HT_GetKey (const void* Entry); /* Given a pointer to the user entry data, return a pointer to the key */ static int HT_Compare (const void* Key1, const void* Key2); /* Compare two keys. The function must return a value less than zero if ** Key1 is smaller than Key2, zero if both are equal, and a value greater ** than zero if Key1 is greater then Key2. */ /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* A string pool entry */ struct StringPoolEntry { HashNode Node; /* Node for the hash table */ unsigned Id; /* The numeric string id */ StrBuf Buf; /* The string itself */ }; /* A string pool */ struct StringPool { Collection Entries; /* Entries sorted by number */ unsigned TotalSize; /* Total size of all string data */ HashTable Tab; /* Hash table */ }; /* Hash table functions */ static const HashFunctions HashFunc = { HT_GenHash, HT_GetKey, HT_Compare }; /*****************************************************************************/ /* struct StringPoolEntry */ /*****************************************************************************/ static StringPoolEntry* NewStringPoolEntry (const StrBuf* S, unsigned Id) /* Create a new string pool entry and return it. */ { /* Allocate memory */ StringPoolEntry* E = xmalloc (sizeof (StringPoolEntry)); /* Initialize the fields */ InitHashNode (&E->Node); E->Id = Id; SB_Init (&E->Buf); SB_Copy (&E->Buf, S); /* Always zero terminate the string */ SB_Terminate (&E->Buf); /* Return the new entry */ return E; } /*****************************************************************************/ /* Hash table functions */ /*****************************************************************************/ static unsigned HT_GenHash (const void* Key) /* Generate the hash over a key. */ { return HashBuf (Key); } static const void* HT_GetKey (const void* Entry) /* Given a pointer to the user entry data, return a pointer to the index */ { return &((const StringPoolEntry*) Entry)->Buf; } static int HT_Compare (const void* Key1, const void* Key2) /* Compare two keys. The function must return a value less than zero if ** Key1 is smaller than Key2, zero if both are equal, and a value greater ** than zero if Key1 is greater then Key2. */ { return SB_Compare (Key1, Key2); } /*****************************************************************************/ /* Code */ /*****************************************************************************/ StringPool* NewStringPool (unsigned HashSlots) /* Allocate, initialize and return a new string pool */ { /* Allocate memory */ StringPool* P = xmalloc (sizeof (*P)); /* Initialize the fields */ P->Entries = EmptyCollection; P->TotalSize = 0; InitHashTable (&P->Tab, HashSlots, &HashFunc); /* Return a pointer to the new pool */ return P; } void FreeStringPool (StringPool* P) /* Free a string pool */ { unsigned I; /* Free all entries and clear the entry collection */ for (I = 0; I < CollCount (&P->Entries); ++I) { /* Get a pointer to the entry */ StringPoolEntry* E = CollAtUnchecked (&P->Entries, I); /* Free string buffer memory */ SB_Done (&E->Buf); /* Free the memory for the entry itself */ xfree (E); } CollDeleteAll (&P->Entries); /* Free the hash table */ DoneHashTable (&P->Tab); /* Free the string pool itself */ xfree (P); } const StrBuf* SP_Get (const StringPool* P, unsigned Index) /* Return a string from the pool. Index must exist, otherwise FAIL is called. */ { /* Get the collection entry */ const StringPoolEntry* E = CollConstAt (&P->Entries, Index); /* Return the string from the entry */ return &E->Buf; } unsigned SP_Add (StringPool* P, const StrBuf* S) /* Add a string buffer to the buffer and return the index. If the string does ** already exist in the pool, SP_AddBuf will just return the index of the ** existing string. */ { /* Search for a matching entry in the hash table */ StringPoolEntry* E = HT_Find (&P->Tab, S); /* Did we find it? */ if (E == 0) { /* We didn't find the entry, so create a new one */ E = NewStringPoolEntry (S, CollCount (&P->Entries)); /* Insert the new entry into the entries collection */ CollAppend (&P->Entries, E); /* Insert the new entry into the hash table */ HT_Insert (&P->Tab, E); /* Add up the string size */ P->TotalSize += SB_GetLen (&E->Buf); } /* Return the id of the entry */ return E->Id; } unsigned SP_AddStr (StringPool* P, const char* S) /* Add a string to the buffer and return the index. If the string does already ** exist in the pool, SP_Add will just return the index of the existing string. */ { unsigned Id; /* First make a string buffer, then add it. This is some overhead, but the ** routine will probably go. */ StrBuf Buf; Id = SP_Add (P, SB_InitFromString (&Buf, S)); /* Return the id of the new entry */ return Id; } unsigned SP_GetCount (const StringPool* P) /* Return the number of strings in the pool */ { return CollCount (&P->Entries); } ������������������������������������������������������������������������������������cc65-2.18/src/common/strpool.h����������������������������������������������������������������������0000664�0000000�0000000�00000010634�13473601511�0016143�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* strpool.h */ /* */ /* A string pool */ /* */ /* */ /* */ /* (C) 2003-2008 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* A string pool is used to store identifiers and other strings. Each string ** stored in the pool has a unique ID, which may be used to access the string ** in the pool. Identical strings are only stored once in the pool and have ** identical IDs. This means that instead of comparing strings, just the ** string pool IDs must be compared. */ #ifndef STRPOOL_H #define STRPOOL_H /* common */ #include "hashtab.h" #include "strbuf.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Opaque string pool entry */ typedef struct StringPoolEntry StringPoolEntry; /* A string pool */ typedef struct StringPool StringPool; /*****************************************************************************/ /* Code */ /*****************************************************************************/ StringPool* NewStringPool (unsigned HashSlots); /* Allocate, initialize and return a new string pool */ void FreeStringPool (StringPool* P); /* Free a string pool */ const StrBuf* SP_Get (const StringPool* P, unsigned Index); /* Return a string from the pool. Index must exist, otherwise FAIL is called. */ unsigned SP_Add (StringPool* P, const StrBuf* S); /* Add a string buffer to the buffer and return the index. If the string does ** already exist in the pool, SP_AddBuf will just return the index of the ** existing string. */ unsigned SP_AddStr (StringPool* P, const char* S); /* Add a string to the buffer and return the index. If the string does already ** exist in the pool, SP_Add will just return the index of the existing string. */ unsigned SP_GetCount (const StringPool* P); /* Return the number of strings in the pool */ /* End of strpool.h */ #endif ����������������������������������������������������������������������������������������������������cc65-2.18/src/common/strstack.c���������������������������������������������������������������������0000664�0000000�0000000�00000007006�13473601511�0016271�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* strstack.c */ /* */ /* String stack used for program settings */ /* */ /* */ /* */ /* (C) 2004 Ullrich von Bassewitz */ /* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "check.h" #include "strstack.h" #include "xmalloc.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ const char* SS_Get (const StrStack* S) /* Get the value on top of a string stack */ { CHECK (S->Count > 0); return S->Stack[S->Count-1]; } void SS_Set (StrStack* S, const char* Val) /* Set the value on top of a string stack */ { CHECK (S->Count > 0); xfree (S->Stack[S->Count-1]); S->Stack[S->Count-1] = xstrdup (Val); } void SS_Drop (StrStack* S) /* Drop a value from a string stack */ { CHECK (S->Count > 1); xfree (S->Stack[--S->Count]); } void SS_Push (StrStack* S, const char* Val) /* Push a value onto a string stack */ { CHECK (S->Count < sizeof (S->Stack) / sizeof (S->Stack[0])); S->Stack[S->Count++] = xstrdup (Val); } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/strstack.h���������������������������������������������������������������������0000664�0000000�0000000�00000010116�13473601511�0016272�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* strstack.h */ /* */ /* String stack used for program settings */ /* */ /* */ /* */ /* (C) 2004 Ullrich von Bassewitz */ /* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef STRSTACK_H #define STRSTACK_H #include "inline.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ typedef struct StrStack StrStack; struct StrStack { unsigned Count; char* Stack[8]; }; /* Declare an empty string stack */ #define STRSTACK() { 0 }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ #if defined(HAVE_INLINE) INLINE int SS_IsFull (const StrStack* S) /* Return true if there is no space left on the given string stack */ { return (S->Count >= sizeof (S->Stack) / sizeof (S->Stack[0])); } #else # define SS_IsFull(S) ((S)->Count >= sizeof ((S)->Stack) / sizeof ((S)->Stack[0])) #endif #if defined(HAVE_INLINE) INLINE unsigned SS_GetCount (const StrStack* S) /* Return the number of elements on the given string stack */ { return S->Count; } #else # define SS_GetCount(S) (S)->Count #endif const char* SS_Get (const StrStack* S); /* Get the value on top of a string stack */ void SS_Set (StrStack* S, const char* Val); /* Set the value on top of a string stack */ void SS_Drop (StrStack* S); /* Drop a value from a string stack */ void SS_Push (StrStack* S, const char* Val); /* Push a value onto a string stack */ /* End of strstack.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/strutil.c����������������������������������������������������������������������0000664�0000000�0000000�00000007063�13473601511�0016144�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* strutil.h */ /* */ /* String utility functions */ /* */ /* */ /* */ /* (C) 2001-2003 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> #include <ctype.h> /* common */ #include "strutil.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ char* StrCopy (char* Dest, size_t DestSize, const char* Source) /* Copy Source to Dest honouring the maximum size of the target buffer. In ** constrast to strncpy, the resulting string will always be NUL terminated. ** The function returns the pointer to the destintation buffer. */ { size_t Len = strlen (Source); if (Len >= DestSize) { memcpy (Dest, Source, DestSize-1); Dest[DestSize-1] = '\0'; } else { memcpy (Dest, Source, Len+1); } return Dest; } int StrCaseCmp (const char* S1, const char* S2) /* Compare two strings ignoring case */ { int Diff; while ((Diff = toupper (*S1) - toupper (*S2)) == 0 && *S1) { ++S1; ++S2; } return Diff; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/strutil.h����������������������������������������������������������������������0000664�0000000�0000000�00000006314�13473601511�0016147�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* strutil.h */ /* */ /* String utility functions */ /* */ /* */ /* */ /* (C) 2001-2003 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef STRUTIL_H #define STRUTIL_H #include <stdlib.h> /*****************************************************************************/ /* Code */ /*****************************************************************************/ char* StrCopy (char* Dest, size_t DestSize, const char* Source); /* Copy Source to Dest honouring the maximum size of the target buffer. In ** constrast to strncpy, the resulting string will always be NUL terminated. ** The function returns the pointer to the destintation buffer. */ int StrCaseCmp (const char* S1, const char* S2); /* Compare two strings ignoring case */ /* End of strutil.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/symdefs.h����������������������������������������������������������������������0000664�0000000�0000000�00000011527�13473601511�0016115�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* symdefs.h */ /* */ /* Symbol definitions for the bin65 binary utils */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* Object file tags for imports and exports */ #ifndef SYMDEFS_H #define SYMDEFS_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Number of module constructor/destructor declarations for an export */ #define SYM_CONDES_MASK 0x0007U #define SYM_IS_CONDES(x) (((x) & SYM_CONDES_MASK) != 0) #define SYM_GET_CONDES_COUNT(x) ((x) & SYM_CONDES_MASK) #define SYM_INC_CONDES_COUNT(x) ((x)++) /* Size of symbol available? */ #define SYM_SIZELESS 0x0000U /* No symbol size available */ #define SYM_SIZE 0x0008U /* Symbol has a size */ #define SYM_MASK_SIZE 0x0008U /* Size mask */ #define SYM_HAS_SIZE(x) (((x) & SYM_MASK_SIZE) == SYM_SIZE) /* Symbol value type */ #define SYM_CONST 0x0000U /* Mask bit for const values */ #define SYM_EXPR 0x0010U /* Mask bit for expr values */ #define SYM_MASK_VAL 0x0010U /* Value mask */ #define SYM_IS_CONST(x) (((x) & SYM_MASK_VAL) == SYM_CONST) #define SYM_IS_EXPR(x) (((x) & SYM_MASK_VAL) == SYM_EXPR) /* Symbol usage */ #define SYM_EQUATE 0x0000U /* Mask bit for an equate */ #define SYM_LABEL 0x0020U /* Mask bit for a label */ #define SYM_MASK_LABEL 0x0020U /* Value mask */ #define SYM_IS_EQUATE(x) (((x) & SYM_MASK_LABEL) == SYM_EQUATE) #define SYM_IS_LABEL(x) (((x) & SYM_MASK_LABEL) == SYM_LABEL) /* Symbol type */ #define SYM_STD 0x0000U /* Standard symbol */ #define SYM_CHEAP_LOCAL 0x0040U /* Cheap local symbol */ #define SYM_MASK_TYPE 0x0040U /* Value mask */ #define SYM_IS_STD(x) (((x) & SYM_MASK_TYPE) == SYM_STD) #define SYM_IS_CHEAP_LOCAL (((x) & SYM_MASK_TYPE) == SYM_CHEAP_LOCAL) /* Export */ #define SYM_EXPORT 0x0080U /* Export */ #define SYM_MASK_EXPORT 0x0080U /* Value mask */ #define SYM_IS_EXPORT(x) (((x) & SYM_MASK_EXPORT) == SYM_EXPORT) /* Import */ #define SYM_IMPORT 0x0100U /* Import */ #define SYM_MASK_IMPORT 0x0100U /* Value mask */ #define SYM_IS_IMPORT(x) (((x) & SYM_MASK_IMPORT) == SYM_IMPORT) /* End of symdefs.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/target.c�����������������������������������������������������������������������0000664�0000000�0000000�00000034016�13473601511�0015722�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* target.c */ /* */ /* Target specification */ /* */ /* */ /* */ /* (C) 2000-2015, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdlib.h> #include <string.h> /* common */ #include "chartype.h" #include "check.h" #include "target.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Translation table with direct (no) translation */ 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, 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,0x7C,0x7D,0x7E,0x7F, 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 -> 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, 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,0x7C,0x7D,0x7E,0x7F, 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 -> 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, 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F, 0x40,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,0x5B,0xBF,0x5D,0x5E,0xA4, 0xAD,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,0xB3,0xDD,0xAB,0xB1,0xDF, 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, 0x90,0x91,0x92,0x0C,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, 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,0x7C,0x7D,0x7E,0x7F, 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, }; /* One entry in the target map */ typedef struct TargetEntry TargetEntry; struct TargetEntry { char Name[13]; /* Target name */ target_t Id; /* Target id */ }; /* Table that maps target names to ids. Sorted alphabetically for bsearch. ** Allows multiple entries for one target id (target name aliases). */ static const TargetEntry TargetMap[] = { { "apple2", TGT_APPLE2 }, { "apple2enh", TGT_APPLE2ENH }, { "atari", TGT_ATARI }, { "atari2600", TGT_ATARI2600 }, { "atari5200", TGT_ATARI5200 }, { "atarixl", TGT_ATARIXL }, { "atmos", TGT_ATMOS }, { "bbc", TGT_BBC }, { "c128", TGT_C128 }, { "c16", TGT_C16 }, { "c64", TGT_C64 }, { "c65", TGT_C65 }, { "cbm510", TGT_CBM510 }, { "cbm610", TGT_CBM610 }, { "creativision", TGT_CREATIVISION }, { "gamate", TGT_GAMATE }, { "geos", TGT_GEOS_CBM }, { "geos-apple", TGT_GEOS_APPLE }, { "geos-cbm", TGT_GEOS_CBM }, { "lunix", TGT_LUNIX }, { "lynx", TGT_LYNX }, { "module", TGT_MODULE }, { "nes", TGT_NES }, { "none", TGT_NONE }, { "osic1p", TGT_OSIC1P }, { "pce", TGT_PCENGINE }, { "pet", TGT_PET }, { "plus4", TGT_PLUS4 }, { "sim6502", TGT_SIM6502 }, { "sim65c02", TGT_SIM65C02 }, { "supervision", TGT_SUPERVISION }, { "telestrat", TGT_TELESTRAT }, { "vic20", TGT_VIC20 }, }; #define MAP_ENTRY_COUNT (sizeof (TargetMap) / sizeof (TargetMap[0])) /* Table with target properties by target id */ static const TargetProperties PropertyTable[TGT_COUNT] = { { "none", CPU_6502, BINFMT_BINARY, CTNone }, { "module", CPU_6502, BINFMT_O65, CTNone }, { "atari", CPU_6502, BINFMT_BINARY, CTAtari }, { "atari2600", CPU_6502, BINFMT_BINARY, CTNone }, { "atari5200", CPU_6502, BINFMT_BINARY, CTAtari }, { "atarixl", CPU_6502, BINFMT_BINARY, CTAtari }, { "vic20", CPU_6502, BINFMT_BINARY, CTPET }, { "c16", CPU_6502, BINFMT_BINARY, CTPET }, { "c64", CPU_6502, BINFMT_BINARY, CTPET }, { "c128", CPU_6502, BINFMT_BINARY, CTPET }, { "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 }, { "apple2enh", CPU_65C02, BINFMT_BINARY, CTNone }, { "geos-cbm", CPU_6502, BINFMT_BINARY, CTNone }, { "creativision", CPU_6502, BINFMT_BINARY, CTNone }, { "geos-apple", CPU_65C02, BINFMT_BINARY, CTNone }, { "lunix", CPU_6502, BINFMT_O65, CTNone }, { "atmos", CPU_6502, BINFMT_BINARY, CTNone }, { "telestrat", CPU_6502, BINFMT_BINARY, CTNone }, { "nes", CPU_6502, BINFMT_BINARY, CTNone }, { "supervision", CPU_65SC02, BINFMT_BINARY, CTNone }, { "lynx", CPU_65SC02, BINFMT_BINARY, CTNone }, { "sim6502", CPU_6502, BINFMT_BINARY, CTNone }, { "sim65c02", CPU_65C02, BINFMT_BINARY, CTNone }, { "pce", CPU_HUC6280, BINFMT_BINARY, CTNone }, { "gamate", CPU_6502, BINFMT_BINARY, CTNone }, { "c65", CPU_4510, BINFMT_BINARY, CTPET }, }; /* Target system */ target_t Target = TGT_NONE; /*****************************************************************************/ /* Code */ /*****************************************************************************/ static int Compare (const void* Key, const void* Entry) /* Compare function for bsearch */ { return strcmp ((const char*) Key, ((const TargetEntry*)Entry)->Name); } target_t FindTarget (const char* Name) /* Find a target by name and return the target id. TGT_UNKNOWN is returned if ** the given name is no valid target. */ { /* Search for the name in the map */ const TargetEntry* T; T = bsearch (Name, TargetMap, MAP_ENTRY_COUNT, sizeof (TargetMap[0]), Compare); /* Return the target id */ return (T == 0)? TGT_UNKNOWN : T->Id; } const TargetProperties* GetTargetProperties (target_t Target) /* Return the properties for a target */ { /* Must have a valid target id */ PRECONDITION (Target >= 0 && Target < TGT_COUNT); /* Return the array entry */ return &PropertyTable[Target]; } const char* GetTargetName (target_t Target) /* Return the name of a target */ { /* Return the array entry */ return GetTargetProperties (Target)->Name; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/target.h�����������������������������������������������������������������������0000664�0000000�0000000�00000011601�13473601511�0015722�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* target.h */ /* */ /* Target specification */ /* */ /* */ /* */ /* (C) 2000-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef TARGET_H #define TARGET_H /* common */ #include "cpu.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Supported target systems */ typedef enum { TGT_UNKNOWN = -1, /* Not specified or invalid target */ TGT_NONE, TGT_MODULE, TGT_ATARI, TGT_ATARI2600, TGT_ATARI5200, TGT_ATARIXL, TGT_VIC20, TGT_C16, TGT_C64, TGT_C128, TGT_PLUS4, TGT_CBM510, TGT_CBM610, TGT_OSIC1P, TGT_PET, TGT_BBC, TGT_APPLE2, TGT_APPLE2ENH, TGT_GEOS_CBM, TGT_CREATIVISION, TGT_GEOS_APPLE, TGT_LUNIX, TGT_ATMOS, TGT_TELESTRAT, TGT_NES, TGT_SUPERVISION, TGT_LYNX, TGT_SIM6502, TGT_SIM65C02, TGT_PCENGINE, TGT_GAMATE, TGT_C65, TGT_COUNT /* Number of target systems */ } target_t; /* Collection of target properties */ typedef struct TargetProperties TargetProperties; struct TargetProperties { const char Name[13]; /* Name of the target */ cpu_t DefaultCPU; /* Default CPU for this target */ unsigned char BinFmt; /* Default binary format for this target */ const unsigned char* CharMap; /* Character translation table */ }; /* Target system */ extern target_t Target; /* Types of available output formats */ #define BINFMT_DEFAULT 0 /* Default (binary) */ #define BINFMT_BINARY 1 /* Straight binary format */ #define BINFMT_O65 2 /* Andre Fachats o65 format */ #define BINFMT_ATARIEXE 3 /* Standard Atari binary load */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ target_t FindTarget (const char* Name); /* Find a target by name and return the target id. TGT_UNKNOWN is returned if ** the given name is no valid target. */ const TargetProperties* GetTargetProperties (target_t Target); /* Return the properties for a target */ const char* GetTargetName (target_t Target); /* Return the name of a target */ /* End of target.h */ #endif �������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/tgttrans.c���������������������������������������������������������������������0000664�0000000�0000000�00000013040�13473601511�0016274�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* tgttrans.c */ /* */ /* Character set translation */ /* */ /* */ /* */ /* (C) 2000-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* common */ #include "check.h" #include "target.h" #include "tgttrans.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Translation table actually used. Default is no translation */ static unsigned char Tab[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,0x7C,0x7D,0x7E,0x7F, 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, }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void TgtTranslateInit (void) /* Initialize the translation tables */ { /* Copy the translation for the selected target */ memcpy (Tab, GetTargetProperties (Target)->CharMap, sizeof (Tab)); } int TgtTranslateChar (int C) /* Translate one character from the source character set into the target ** system character set. */ { /* Translate */ return Tab[C & 0xFF]; } void TgtTranslateBuf (void* Buf, unsigned Len) /* Translate a buffer of the given length from the source character set into ** the target system character set. */ { /* Translate */ unsigned char* B = (unsigned char*)Buf; while (Len--) { *B = Tab[*B]; ++B; } } void TgtTranslateStrBuf (StrBuf* Buf) /* Translate a string buffer from the source character set into the target ** system character set. */ { TgtTranslateBuf (SB_GetBuf (Buf), SB_GetLen (Buf)); } void TgtTranslateSet (unsigned Index, unsigned char C) /* Set the translation code for the given character */ { CHECK (Index < sizeof (Tab)); Tab[Index] = C; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/tgttrans.h���������������������������������������������������������������������0000664�0000000�0000000�00000006724�13473601511�0016314�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* tgttrans.h */ /* */ /* Character set translation */ /* */ /* */ /* */ /* (C) 2000-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef TGTTRANS_H #define TGTTRANS_H /* common */ #include "strbuf.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void TgtTranslateInit (void); /* Initialize the translation tables */ int TgtTranslateChar (int C); /* Translate one character from the source character set into the target ** system character set. */ void TgtTranslateBuf (void* Buf, unsigned Len); /* Translate a buffer of the given length from the source character set into ** the target system character set. */ void TgtTranslateStrBuf (StrBuf* Buf); /* Translate a string buffer from the source character set into the target ** system character set. */ void TgtTranslateSet (unsigned Index, unsigned char C); /* Set the translation code for the given character */ /* End of tgttrans.h */ #endif ��������������������������������������������cc65-2.18/src/common/va_copy.h����������������������������������������������������������������������0000664�0000000�0000000�00000006337�13473601511�0016106�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* va_copy.h */ /* */ /* va_copy macro for systems that don't have it */ /* */ /* */ /* */ /* (C) 2004 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef VA_COPY_H #define VA_COPY_H #include <stdarg.h> /* No action if we have a working va_copy */ #if !defined(va_copy) /* The watcom compiler doesn't have va_copy and a problematic va_list definition */ #if defined(__WATCOMC__) #define va_copy(dest,src) memcpy((dest), (src), sizeof (va_list)) #endif /* GNU C has a builtin function */ #if defined(__GNUC__) #define va_copy(dest,src) __va_copy(dest, src) #endif /* MS VC allows for assignment */ #if defined(_MSC_VER) #define va_copy(dest,src) ((dest) = (src)) #endif /* If va_copy is not defined now, we have a problem */ #if !defined(va_copy) #error "Need a working va_copy!" #endif #endif /* End of va_copy.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/version.c����������������������������������������������������������������������0000664�0000000�0000000�00000007173�13473601511�0016125�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* version.c */ /* */ /* Version information for the cc65 compiler package */ /* */ /* */ /* */ /* (C) 1998-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "xsprintf.h" #include "searchpath.h" #include "version.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ #define VER_MAJOR 2U #define VER_MINOR 18U /*****************************************************************************/ /* Code */ /*****************************************************************************/ const char* GetVersionAsString (void) /* Returns the version number as a string in a static buffer */ { static char Buf[60]; #if defined(GIT_SHA) xsnprintf (Buf, sizeof (Buf), "%u.%u - Git %s", VER_MAJOR, VER_MINOR, STRINGIZE (GIT_SHA)); #else xsnprintf (Buf, sizeof (Buf), "%u.%u", VER_MAJOR, VER_MINOR); #endif return Buf; } unsigned GetVersionAsNumber (void) /* Returns the version number as a combined unsigned for use in a #define */ { return ((VER_MAJOR * 0x100) + (VER_MINOR * 0x10)); } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/version.h����������������������������������������������������������������������0000664�0000000�0000000�00000006030�13473601511�0016121�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* version.h */ /* */ /* Version information for the cc65 compiler package */ /* */ /* */ /* */ /* (C) 1998-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef VERSION_H #define VERSION_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ const char* GetVersionAsString (void); /* Returns the version number as a string in a static buffer */ unsigned GetVersionAsNumber (void); /* Returns the version number as a combined unsigned for use in a #define */ /* End of version.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/xmalloc.c����������������������������������������������������������������������0000664�0000000�0000000�00000010604�13473601511�0016070�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* xmalloc.c */ /* */ /* Memory allocation subroutines */ /* */ /* */ /* */ /* (C) 2000-2006 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdlib.h> #include <string.h> /* common */ #include "abend.h" #include "debugflag.h" #include "xmalloc.h" /*****************************************************************************/ /* code */ /*****************************************************************************/ void* xmalloc (size_t Size) /* Allocate memory, check for out of memory condition. Do some debugging */ { void* P = 0; /* Allow zero sized requests and return NULL in this case */ if (Size) { /* Allocate memory */ P = malloc (Size); /* Check for errors */ if (P == 0) { AbEnd ("Out of memory - requested block size = %lu", (unsigned long) Size); } } /* Return a pointer to the block */ return P; } void* xrealloc (void* P, size_t Size) /* Reallocate a memory block, check for out of memory */ { /* Reallocate the block */ void* N = realloc (P, Size); /* Check for errors */ if (N == 0 && Size != 0) { AbEnd ("Out of memory in realloc - requested block size = %lu", (unsigned long) Size); } /* Return the pointer to the new block */ return N; } void xfree (void* Block) /* Free the block, do some debugging */ { free (Block); } char* xstrdup (const char* S) /* Duplicate a string on the heap. The function checks for out of memory */ { /* Allow dup'ing of NULL strings */ if (S) { /* Get the length of the string */ unsigned Len = strlen (S) + 1; /* Allocate memory and return a copy */ return memcpy (xmalloc (Len), S, Len); } else { /* Return a NULL pointer */ return 0; } } void* xdup (const void* Buf, size_t Size) /* Create a copy of Buf on the heap and return a pointer to it. */ { return memcpy (xmalloc (Size), Buf, Size); } ����������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/xmalloc.h����������������������������������������������������������������������0000664�0000000�0000000�00000006476�13473601511�0016111�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* xmalloc.h */ /* */ /* Memory allocation subroutines */ /* */ /* */ /* */ /* (C) 2000-2006 Ullrich von Bassewitz */ /* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef XMALLOC_H #define XMALLOC_H #include <stddef.h> /*****************************************************************************/ /* Code */ /*****************************************************************************/ void* xmalloc (size_t Size); /* Allocate memory, check for out of memory condition. Do some debugging */ void* xrealloc (void* P, size_t Size); /* Reallocate a memory block, check for out of memory */ void xfree (void* Block); /* Free the block, do some debugging */ char* xstrdup (const char* S); /* Duplicate a string on the heap. The function checks for out of memory */ void* xdup (const void* Buf, size_t Size); /* Create a copy of Buf on the heap and return a pointer to it. */ /* End of xmalloc.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/common/xsprintf.c���������������������������������������������������������������������0000664�0000000�0000000�00000047756�13473601511�0016330�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* xsprintf.c */ /* */ /* Replacement sprintf function */ /* */ /* */ /* */ /* (C) 2000-2004 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stddef.h> #include <string.h> #include <limits.h> /* common */ #include "chartype.h" #include "check.h" #include "inttypes.h" #include "strbuf.h" #include "va_copy.h" #include "xsprintf.h" /*****************************************************************************/ /* vsnprintf */ /*****************************************************************************/ /* The following is a very basic vsnprintf like function called xvsnprintf. It ** features only the basic format specifiers (especially the floating point ** stuff is missing), but may be extended if required. Reason for supplying ** my own implementation is that vsnprintf is standard but not implemented by ** older compilers, and some that implement it, don't adhere to the standard ** (for example Microsoft with its _vsnprintf). */ typedef struct { /* Variable argument list pointer */ va_list ap; /* Output buffer */ char* Buf; size_t BufSize; size_t BufFill; /* Argument string buffer and string buffer pointer. The string buffer ** must be big enough to hold a converted integer of the largest type ** including an optional sign and terminating zero. */ char ArgBuf[256]; int ArgLen; /* Flags */ enum { fNone = 0x0000, fMinus = 0x0001, fPlus = 0x0002, fSpace = 0x0004, fHash = 0x0008, fZero = 0x0010, fWidth = 0x0020, fPrec = 0x0040, fUnsigned = 0x0080, fUpcase = 0x0100 } Flags; /* Conversion base and table */ unsigned Base; const char* CharTable; /* Field width */ int Width; /* Precision */ int Prec; /* Length modifier */ enum { lmChar, lmShort, lmInt, lmLong, lmIntMax, lmSizeT, lmPtrDiffT, lmLongDouble, /* Unsupported modifiers */ lmLongLong = lmLong, /* Default length is integer */ lmDefault = lmInt } LengthMod; } PrintfCtrl; static void AddChar (PrintfCtrl* P, char C) /* Store one character in the output buffer if there's enough room. */ { if (++P->BufFill <= P->BufSize) { *P->Buf++ = C; } } static void AddPadding (PrintfCtrl* P, char C, unsigned Count) /* Add some amount of padding */ { while (Count--) { AddChar (P, C); } } static intmax_t NextIVal (PrintfCtrl*P) /* Read the next integer value from the variable argument list */ { switch (P->LengthMod) { case lmChar: return (char) va_arg (P->ap, int); case lmShort: return (short) va_arg (P->ap, int); case lmInt: return (int) va_arg (P->ap, int); case lmLong: return (long) va_arg (P->ap, long); case lmIntMax: return va_arg (P->ap, intmax_t); case lmSizeT: return (uintmax_t) va_arg (P->ap, size_t); case lmPtrDiffT: return (long) va_arg (P->ap, ptrdiff_t); default: FAIL ("Invalid type size in NextIVal"); return 0; } } static uintmax_t NextUVal (PrintfCtrl*P) /* Read the next unsigned integer value from the variable argument list */ { switch (P->LengthMod) { case lmChar: return (unsigned char) va_arg (P->ap, unsigned); case lmShort: return (unsigned short) va_arg (P->ap, unsigned); case lmInt: return (unsigned int) va_arg (P->ap, unsigned int); case lmLong: return (unsigned long) va_arg (P->ap, unsigned long); case lmIntMax: return va_arg (P->ap, uintmax_t); case lmSizeT: return va_arg (P->ap, size_t); case lmPtrDiffT: return (intmax_t) va_arg (P->ap, ptrdiff_t); default: FAIL ("Invalid type size in NextUVal"); return 0; } } static void ToStr (PrintfCtrl* P, uintmax_t Val) /* Convert the given value to a (reversed) string */ { char* S = P->ArgBuf; while (Val) { *S++ = P->CharTable[Val % P->Base]; Val /= P->Base; } P->ArgLen = S - P->ArgBuf; } static void FormatInt (PrintfCtrl* P, uintmax_t Val) /* Convert the integer value */ { char Lead[5]; unsigned LeadCount = 0; unsigned PrecPadding; unsigned WidthPadding; unsigned I; /* Determine the translation table */ P->CharTable = (P->Flags & fUpcase)? "0123456789ABCDEF" : "0123456789abcdef"; /* Check if the value is negative */ if ((P->Flags & fUnsigned) == 0 && ((intmax_t) Val) < 0) { Val = -((intmax_t) Val); Lead[LeadCount++] = '-'; } else if ((P->Flags & fPlus) != 0) { Lead[LeadCount++] = '+'; } else if ((P->Flags & fSpace) != 0) { Lead[LeadCount++] = ' '; } /* Convert the value into a (reversed string). */ ToStr (P, Val); /* The default precision for all integer conversions is one. This means ** that the fPrec flag is always set and does not need to be checked ** later on. */ if ((P->Flags & fPrec) == 0) { P->Flags |= fPrec; P->Prec = 1; } /* Determine the leaders for alternative forms */ if ((P->Flags & fHash) != 0) { if (P->Base == 16) { /* Start with 0x */ Lead[LeadCount++] = '0'; Lead[LeadCount++] = (P->Flags & fUpcase)? 'X' : 'x'; } else if (P->Base == 8) { /* Alternative form for 'o': always add a leading zero. */ if (P->Prec <= P->ArgLen) { Lead[LeadCount++] = '0'; } } } /* Determine the amount of precision padding needed */ if (P->ArgLen < P->Prec) { PrecPadding = P->Prec - P->ArgLen; } else { PrecPadding = 0; } /* Determine the width padding needed */ if ((P->Flags & fWidth) != 0) { int CurWidth = LeadCount + PrecPadding + P->ArgLen; if (CurWidth < P->Width) { WidthPadding = P->Width - CurWidth; } else { WidthPadding = 0; } } else { WidthPadding = 0; } /* Output left space padding if any */ if ((P->Flags & (fMinus | fZero)) == 0 && WidthPadding > 0) { AddPadding (P, ' ', WidthPadding); WidthPadding = 0; } /* Leader */ for (I = 0; I < LeadCount; ++I) { AddChar (P, Lead[I]); } /* Left zero padding if any */ if ((P->Flags & fZero) != 0 && WidthPadding > 0) { AddPadding (P, '0', WidthPadding); WidthPadding = 0; } /* Precision padding */ if (PrecPadding > 0) { AddPadding (P, '0', PrecPadding); } /* The number itself. Beware: It's reversed! */ while (P->ArgLen > 0) { AddChar (P, P->ArgBuf[--P->ArgLen]); } /* Right width padding if any */ if (WidthPadding > 0) { AddPadding (P, ' ', WidthPadding); } } static void FormatStr (PrintfCtrl* P, const char* Val) /* Convert the string */ { unsigned WidthPadding; /* Get the string length limited to the precision. Beware: We cannot use ** strlen here, because if a precision is given, the string may not be ** zero terminated. */ int Len; if ((P->Flags & fPrec) != 0) { const char* S = memchr (Val, '\0', P->Prec); if (S == 0) { /* Not zero terminated */ Len = P->Prec; } else { /* Terminating zero found */ Len = S - Val; } } else { Len = strlen (Val); } /* Determine the width padding needed */ if ((P->Flags & fWidth) != 0 && P->Width > Len) { WidthPadding = P->Width - Len; } else { WidthPadding = 0; } /* Output left padding */ if ((P->Flags & fMinus) != 0 && WidthPadding > 0) { AddPadding (P, ' ', WidthPadding); WidthPadding = 0; } /* Output the string */ while (Len--) { AddChar (P, *Val++); } /* Output right padding if any */ if (WidthPadding > 0) { AddPadding (P, ' ', WidthPadding); } } static void StoreOffset (PrintfCtrl* P) /* Store the current output offset (%n format spec) */ { switch (P->LengthMod) { case lmChar: *va_arg (P->ap, int*) = P->BufFill; break; case lmShort: *va_arg (P->ap, int*) = P->BufFill; break; case lmInt: *va_arg (P->ap, int*) = P->BufFill; break; case lmLong: *va_arg (P->ap, long*) = P->BufFill; break; case lmIntMax: *va_arg (P->ap, intmax_t*) = P->BufFill; break; case lmSizeT: *va_arg (P->ap, size_t*) = P->BufFill; break; case lmPtrDiffT: *va_arg (P->ap, ptrdiff_t*) = P->BufFill; break; default: FAIL ("Invalid size modifier for %n format spec. in xvsnprintf()"); } } int xvsnprintf (char* Buf, size_t Size, const char* Format, va_list ap) /* A basic vsnprintf implementation. Does currently only support integer ** formats. */ { PrintfCtrl P; int Done; char F; char SBuf[2]; const char* SPtr; int UseStrBuf = 0; /* Initialize the control structure */ va_copy (P.ap, ap); P.Buf = Buf; P.BufSize = Size; P.BufFill = 0; /* Parse the format string */ while ((F = *Format++) != '\0') { if (F != '%') { /* Not a format specifier, just copy */ AddChar (&P, F); continue; } /* Check for %% */ if (*Format == '%') { ++Format; AddChar (&P, '%'); continue; } /* It's a format specifier. Check for flags. */ F = *Format++; P.Flags = fNone; Done = 0; while (F != '\0' && !Done) { switch (F) { case '-': P.Flags |= fMinus; F = *Format++; break; case '+': P.Flags |= fPlus; F = *Format++; break; case ' ': P.Flags |= fSpace; F = *Format++; break; case '#': P.Flags |= fHash; F = *Format++; break; case '0': P.Flags |= fZero; F = *Format++; break; default: Done = 1; break; } } /* Optional field width */ if (F == '*') { P.Width = va_arg (P.ap, int); /* A negative field width argument is taken as a - flag followed ** by a positive field width. */ if (P.Width < 0) { P.Flags |= fMinus; P.Width = -P.Width; } F = *Format++; P.Flags |= fWidth; } else if (IsDigit (F)) { P.Width = F - '0'; while (1) { F = *Format++; if (!IsDigit (F)) { break; } P.Width = P.Width * 10 + (F - '0'); } P.Flags |= fWidth; } /* Optional precision */ if (F == '.') { F = *Format++; P.Flags |= fPrec; if (F == '*') { P.Prec = va_arg (P.ap, int); /* A negative precision argument is taken as if the precision ** were omitted. */ if (P.Prec < 0) { P.Flags &= ~fPrec; } F = *Format++; /* Skip the '*' */ } else if (IsDigit (F)) { P.Prec = F - '0'; while (1) { F = *Format++; if (!IsDigit (F)) { break; } P.Prec = P.Prec * 10 + (F - '0'); } } else if (F == '-') { /* A negative precision argument is taken as if the precision ** were omitted. */ F = *Format++; /* Skip the minus */ while (IsDigit (F = *Format++)) ; P.Flags &= ~fPrec; } else { P.Prec = 0; } } /* Optional length modifier */ P.LengthMod = lmDefault; switch (F) { case 'h': F = *Format++; if (F == 'h') { F = *Format++; P.LengthMod = lmChar; } else { P.LengthMod = lmShort; } break; case 'l': F = *Format++; if (F == 'l') { F = *Format++; P.LengthMod = lmLongLong; } else { P.LengthMod = lmLong; } break; case 'j': P.LengthMod = lmIntMax; F = *Format++; break; case 'z': P.LengthMod = lmSizeT; F = *Format++; break; case 't': P.LengthMod = lmPtrDiffT; F = *Format++; break; case 'L': P.LengthMod = lmLongDouble; F = *Format++; break; } /* If the space and + flags both appear, the space flag is ignored */ if ((P.Flags & (fSpace | fPlus)) == (fSpace | fPlus)) { P.Flags &= ~fSpace; } /* If the 0 and - flags both appear, the 0 flag is ignored */ if ((P.Flags & (fZero | fMinus)) == (fZero | fMinus)) { P.Flags &= ~fZero; } /* If a precision is specified, the 0 flag is ignored */ if (P.Flags & fPrec) { P.Flags &= ~fZero; } /* Conversion specifier */ switch (F) { case 'd': case 'i': P.Base = 10; FormatInt (&P, NextIVal (&P)); break; case 'o': P.Flags |= fUnsigned; P.Base = 8; FormatInt (&P, NextUVal (&P)); break; case 'u': P.Flags |= fUnsigned; P.Base = 10; FormatInt (&P, NextUVal (&P)); break; case 'X': P.Flags |= (fUnsigned | fUpcase); /* FALLTHROUGH */ case 'x': P.Base = 16; FormatInt (&P, NextUVal (&P)); break; case 'c': SBuf[0] = (char) va_arg (P.ap, int); SBuf[1] = '\0'; FormatStr (&P, SBuf); break; case 's': SPtr = va_arg (P.ap, const char*); CHECK (SPtr != 0); FormatStr (&P, SPtr); break; case 'p': /* See comment at top of header file */ if (UseStrBuf) { /* Argument is StrBuf */ const StrBuf* S = va_arg (P.ap, const StrBuf*); CHECK (S != 0); /* Handle the length by using a precision */ if ((P.Flags & fPrec) != 0) { /* Precision already specified, use length of string ** if less. */ if ((unsigned) P.Prec > SB_GetLen (S)) { P.Prec = SB_GetLen (S); } } else { /* No precision, add it */ P.Flags |= fPrec; P.Prec = SB_GetLen (S); } FormatStr (&P, SB_GetConstBuf (S)); UseStrBuf = 0; /* Reset flag */ } else { /* Use hex format for pointers */ P.Flags |= (fUnsigned | fPrec); P.Prec = ((sizeof (void*) * CHAR_BIT) + 3) / 4; P.Base = 16; FormatInt (&P, (uintptr_t) va_arg (P.ap, void*)); } break; case 'm': /* See comment at top of header file */ UseStrBuf = 1; break; case 'n': StoreOffset (&P); break; default: /* Invalid format spec */ FAIL ("Invalid format specifier in xvsnprintf"); } } /* We don't need P.ap any longer */ va_end (P.ap); /* Terminate the output string and return the number of chars that had ** been written if the buffer was large enough. ** Beware: The terminating zero is not counted for the function result! */ AddChar (&P, '\0'); return P.BufFill - 1; } int xsnprintf (char* Buf, size_t Size, const char* Format, ...) /* A basic snprintf implementation. Does currently only support integer ** formats. */ { int Res; va_list ap; va_start (ap, Format); Res = xvsnprintf (Buf, Size, Format, ap); va_end (ap); return Res; } /*****************************************************************************/ /* Code */ /*****************************************************************************/ int xsprintf (char* Buf, size_t BufSize, const char* Format, ...) /* Replacement function for sprintf */ { int Res; va_list ap; va_start (ap, Format); Res = xvsprintf (Buf, BufSize, Format, ap); va_end (ap); return Res; } int xvsprintf (char* Buf, size_t BufSize, const char* Format, va_list ap) /* Replacement function for sprintf */ { int Res = xvsnprintf (Buf, BufSize, Format, ap); CHECK (Res >= 0 && (unsigned) (Res+1) < BufSize); return Res; } ������������������cc65-2.18/src/common/xsprintf.h���������������������������������������������������������������������0000664�0000000�0000000�00000010307�13473601511�0016313�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* xsprintf.h */ /* */ /* Replacement sprintf function */ /* */ /* */ /* */ /* (C) 2000-2008 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* We need a way to output a StrBuf, but on the other side, we don't want to ** switch off gcc's printf format string checking. So we cheat as follows: ** %m (which is a gcc extension and doesn't take an argument) switches %p ** between outputting a pointer and a string buf. This works just one time, ** so each StrBuf needs in fact a %m%p spec. There's no way to apply a width ** and precision to such a StrBuf, but *not* using %p would bring up a warning ** about a wrong argument type each time. Maybe gcc will one day allow custom ** format specifiers and we can change this ... */ #ifndef XSPRINTF_H #define XSPRINTF_H #include <stdlib.h> #include <stdarg.h> #include "attrib.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ int xvsnprintf (char* Buf, size_t Size, const char* Format, va_list ap) attribute ((format (printf, 3, 0))); /* A basic vsnprintf implementation. Does currently only support integer ** formats. */ int xsnprintf (char* Buf, size_t Size, const char* Format, ...) attribute ((format (printf, 3, 4))); /* A basic snprintf implementation. Does currently only support integer ** formats. */ int xsprintf (char* Buf, size_t BufSize, const char* Format, ...) attribute ((format (printf, 3, 4))); /* Replacement function for sprintf. Will FAIL on errors. */ int xvsprintf (char* Buf, size_t BufSize, const char* Format, va_list ap) attribute ((format (printf, 3, 0))); /* Replacement function for sprintf. Will FAIL on errors. */ /* End of xsprintf.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65.vcxproj��������������������������������������������������������������������������0000664�0000000�0000000�00000014021�13473601511�0015146�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> <ProjectConfiguration Include="Release|Win32"> <Configuration>Release</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> </ItemGroup> <PropertyGroup Label="Globals"> <ProjectGuid>{0BCFB793-2B25-40E2-B265-75848824AC4C}</ProjectGuid> <Keyword>Win32Proj</Keyword> <RootNamespace>da65</RootNamespace> <WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <UseDebugLibraries>true</UseDebugLibraries> <PlatformToolset>v141</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <UseDebugLibraries>false</UseDebugLibraries> <WholeProgramOptimization>true</WholeProgramOptimization> <PlatformToolset>v141</PlatformToolset> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <PropertyGroup Label="UserMacros" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <LinkIncremental>true</LinkIncremental> <OutDir>$(SolutionDir)..\bin\</OutDir> <IntDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</IntDir> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <OutDir>$(SolutionDir)..\bin\</OutDir> <IntDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</IntDir> </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ClCompile> <PrecompiledHeader> </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> <Link> <SubSystem>Console</SubSystem> <GenerateDebugInformation>true</GenerateDebugInformation> <AdditionalDependencies>$(IntDir)..\..\common\$(Configuration)\common.lib</AdditionalDependencies> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ClCompile> <WarningLevel>Level3</WarningLevel> <PrecompiledHeader> </PrecompiledHeader> <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> <Link> <SubSystem>Console</SubSystem> <GenerateDebugInformation>false</GenerateDebugInformation> <AdditionalDependencies>$(IntDir)..\..\common\$(Configuration)\common.lib</AdditionalDependencies> </Link> </ItemDefinitionGroup> <ItemGroup> <ClCompile Include="da65\asminc.c" /> <ClCompile Include="da65\attrtab.c" /> <ClCompile Include="da65\code.c" /> <ClCompile Include="da65\comments.c" /> <ClCompile Include="da65\data.c" /> <ClCompile Include="da65\error.c" /> <ClCompile Include="da65\global.c" /> <ClCompile Include="da65\handler.c" /> <ClCompile Include="da65\infofile.c" /> <ClCompile Include="da65\labels.c" /> <ClCompile Include="da65\main.c" /> <ClCompile Include="da65\opc4510.c" /> <ClCompile Include="da65\opc6502.c" /> <ClCompile Include="da65\opc6502x.c" /> <ClCompile Include="da65\opc65816.c" /> <ClCompile Include="da65\opc65c02.c" /> <ClCompile Include="da65\opc65sc02.c" /> <ClCompile Include="da65\opchuc6280.c" /> <ClCompile Include="da65\opcm740.c" /> <ClCompile Include="da65\opctable.c" /> <ClCompile Include="da65\output.c" /> <ClCompile Include="da65\scanner.c" /> <ClCompile Include="da65\segment.c" /> </ItemGroup> <ItemGroup> <ClInclude Include="da65\asminc.h" /> <ClInclude Include="da65\attrtab.h" /> <ClInclude Include="da65\code.h" /> <ClInclude Include="da65\comments.h" /> <ClInclude Include="da65\data.h" /> <ClInclude Include="da65\error.h" /> <ClInclude Include="da65\global.h" /> <ClInclude Include="da65\handler.h" /> <ClInclude Include="da65\infofile.h" /> <ClInclude Include="da65\labels.h" /> <ClInclude Include="da65\opc4510.h" /> <ClInclude Include="da65\opc6502.h" /> <ClInclude Include="da65\opc6502x.h" /> <ClInclude Include="da65\opc65816.h" /> <ClInclude Include="da65\opc65c02.h" /> <ClInclude Include="da65\opc65sc02.h" /> <ClInclude Include="da65\opcdesc.h" /> <ClInclude Include="da65\opchuc6280.h" /> <ClInclude Include="da65\opcm740.h" /> <ClInclude Include="da65\opctable.h" /> <ClInclude Include="da65\output.h" /> <ClInclude Include="da65\scanner.h" /> <ClInclude Include="da65\segment.h" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> </Project>���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/���������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0013533�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/asminc.c�������������������������������������������������������������������������0000664�0000000�0000000�00000016243�13473601511�0015157�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* asminc.c */ /* */ /* Read an assembler include file containing symbols */ /* */ /* */ /* */ /* (C) 2005-2008 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <errno.h> /* common */ #include "chartype.h" #include "strbuf.h" /* da65 */ #include "asminc.h" #include "comments.h" #include "error.h" #include "labels.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ static char* SkipWhitespace (char* L) /* Ignore white space in L */ { while (IsBlank (*L)) { ++L; } return L; } unsigned DigitVal (unsigned char C) /* Return the value of the given digit */ { if (IsDigit (C)) { return C - '0'; } else { return tolower (C) - 'a' + 10; } } void AsmInc (const char* Filename, char CommentStart, int IgnoreUnknown) /* Read an assembler include file */ { char Buf[1024]; char* L; const char* Comment; unsigned Line; unsigned Len; long Val; unsigned DVal; int Sign; unsigned Base; unsigned Digits; StrBuf Ident = STATIC_STRBUF_INITIALIZER; /* Try to open the file for reading */ FILE* F = fopen (Filename, "r"); if (F == 0) { Error ("Cannot open asm include file \"%s\": %s", Filename, strerror (errno)); } /* Read line by line, check for NAME = VALUE lines */ Line = 0; while ((L = fgets (Buf, sizeof (Buf), F)) != 0) { /* One more line read */ ++Line; /* Ignore leading white space */ while (IsBlank (*L)) { ++L; } /* Remove trailing whitespace */ Len = strlen (L); while (Len > 0 && IsSpace (L[Len-1])) { --Len; } L[Len] = '\0'; /* If the line is empty or starts with a comment char, ignore it */ if (*L == '\0' || *L == CommentStart) { continue; } /* Read an identifier */ SB_Clear (&Ident); if (IsAlpha (*L) || *L == '_') { SB_AppendChar (&Ident, *L++); while (IsAlNum (*L) || *L == '_') { SB_AppendChar (&Ident, *L++); } SB_Terminate (&Ident); } else { if (!IgnoreUnknown) { Error ("%s(%u): Syntax error", Filename, Line); } continue; } /* Ignore white space */ L = SkipWhitespace (L); /* Check for := or = */ if (*L == '=') { ++L; } else if (*L == ':' && *++L == '=') { ++L; } else { if (!IgnoreUnknown) { Error ("%s(%u): Missing '='", Filename, Line); } continue; } /* Allow white space once again */ L = SkipWhitespace (L); /* A number follows. Read the sign. */ if (*L == '-') { Sign = -1; ++L; } else { Sign = 1; if (*L == '+') { ++L; } } /* Determine the base of the number. Allow $ and % as prefixes for ** hex and binary numbers respectively. */ if (*L == '$') { Base = 16; ++L; } else if (*L == '%') { Base = 2; ++L; } else { Base = 10; } /* Decode the number */ Digits = 0; Val = 0; while (IsXDigit (*L) && (DVal = DigitVal (*L)) < Base) { Val = (Val * Base) + DVal; ++Digits; ++L; } /* Must have at least one digit */ if (Digits == 0) { if (!IgnoreUnknown) { Error ("%s(%u): Error in number format", Filename, Line); } continue; } /* Skip whitespace again */ L = SkipWhitespace (L); /* Check for a comment */ if (*L == CommentStart) { Comment = SkipWhitespace (L+1); if (*Comment == '\0') { Comment = 0; } } else { Comment = 0; } /* Check for a comment character or end of line */ if (*L != CommentStart && *L != '\0') { if (!IgnoreUnknown) { Error ("%s(%u): Trailing garbage", Filename, Line); } continue; } /* Apply the sign */ Val *= Sign; /* Define the symbol and the comment */ AddExtLabel (Val, SB_GetConstBuf (&Ident)); SetComment (Val, Comment); } /* Delete the string buffer contents */ SB_Done (&Ident); /* Close the include file ignoring errors (we were just reading). */ (void) fclose (F); } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/asminc.h�������������������������������������������������������������������������0000664�0000000�0000000�00000005653�13473601511�0015167�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* asminc.h */ /* */ /* Read an assembler include file containing symbols */ /* */ /* */ /* */ /* (C) 2005 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef ASMINC_H #define ASMINC_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ void AsmInc (const char* Filename, char CommentStart, int IgnoreUnknown); /* Read an assembler include file */ /* End of asminc.h */ #endif �������������������������������������������������������������������������������������cc65-2.18/src/da65/attrtab.c������������������������������������������������������������������������0000664�0000000�0000000�00000013205�13473601511�0015341�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* attrtab.c */ /* */ /* Disassembler attribute table */ /* */ /* */ /* */ /* (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 */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* da65 */ #include "error.h" #include "attrtab.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Attribute table */ static unsigned short AttrTab[0x10000]; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void AddrCheck (unsigned Addr) /* Check if the given address has a valid range */ { if (Addr >= 0x10000) { Error ("Address out of range: %08X", 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 */ { while (Start <= End) { if (AttrTab[Start++] & atSegment) { return 1; } } return 0; } int IsSegmentEnd (unsigned Addr) /* Return true if a segment ends at the given address */ { return (GetAttr (Addr) & atSegmentEnd) != 0x0000; } int IsSegmentStart (unsigned Addr) /* Return true if a segment starts at the given address */ { return (GetAttr (Addr) & atSegmentStart) != 0x0000; } unsigned GetGranularity (attr_t Style) /* Get the granularity for the given style */ { switch (Style) { case atDefault: return 1; case atCode: return 1; case atIllegal: return 1; case atByteTab: return 1; case atDByteTab: return 2; case atWordTab: return 2; case atDWordTab: return 4; case atAddrTab: return 2; case atRtsTab: return 2; case atTextTab: return 1; case atSkip: default: Internal ("GetGraularity called for style = %d", Style); return 0; } } void MarkRange (unsigned Start, unsigned End, attr_t Attr) /* Mark a range with the given attribute */ { /* Do it easy here... */ while (Start <= End) { MarkAddr (Start++, Attr); } } void MarkAddr (unsigned Addr, attr_t Attr) /* Mark an address with an attribute */ { /* Check the given address */ AddrCheck (Addr); /* We must not have more than one style bit */ if (Attr & atStyleMask) { if (AttrTab[Addr] & atStyleMask) { Error ("Duplicate style for address %04X", Addr); } } /* Set the style */ AttrTab[Addr] |= Attr; } attr_t GetStyleAttr (unsigned Addr) /* Return the style attribute for the given address */ { /* Check the given address */ AddrCheck (Addr); /* Return the attribute */ return (AttrTab[Addr] & atStyleMask); } attr_t GetLabelAttr (unsigned Addr) /* Return the label attribute for the given address */ { /* Check the given address */ AddrCheck (Addr); /* Return the attribute */ return (AttrTab[Addr] & atLabelMask); } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/attrtab.h������������������������������������������������������������������������0000664�0000000�0000000�00000012075�13473601511�0015352�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* attrtab.h */ /* */ /* Disassembler attribute table */ /* */ /* */ /* */ /* (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 */ /* 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 ATTRTAB_H #define ATTRTAB_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ 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 */ /* 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 */ atLabelDefined = 0x0100, /* True if we defined the label */ atStyleMask = 0x000F, /* Output style */ atLabelMask = 0x00F0, /* Label information */ /* Segment */ atSegment = 0x0100, /* Code is in a segment */ atSegmentEnd = 0x0200, /* Segment end */ atSegmentStart = 0x0400, /* Segment start */ } attr_t; /*****************************************************************************/ /* Code */ /*****************************************************************************/ 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 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 */ void MarkRange (unsigned Start, unsigned End, attr_t Attr); /* Mark a range with the given attribute */ void MarkAddr (unsigned Addr, attr_t Attr); /* Mark an address with an attribute */ attr_t GetStyleAttr (unsigned Addr); /* Return the style attribute for the given address */ attr_t GetLabelAttr (unsigned Addr); /* Return the label attribute for the given address */ /* End of attrtab.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/code.c���������������������������������������������������������������������������0000664�0000000�0000000�00000015631�13473601511�0014617�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* code.c */ /* */ /* Binary code management */ /* */ /* */ /* */ /* (C) 2000-2003 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> #include <errno.h> /* common */ #include "check.h" /* da65 */ #include "code.h" #include "error.h" #include "global.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ unsigned char CodeBuf [0x10000]; /* Code buffer */ unsigned long CodeStart; /* Start address */ unsigned long CodeEnd; /* End address */ unsigned long PC; /* Current PC */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ void LoadCode (void) /* Load the code from the given file */ { long Count, MaxCount, Size; FILE* F; PRECONDITION (StartAddr < 0x10000); /* Open the file */ F = fopen (InFile, "rb"); if (F == 0) { Error ("Cannot open '%s': %s", InFile, strerror (errno)); } /* Seek to the end to get the size of the file */ if (fseek (F, 0, SEEK_END) != 0) { Error ("Cannot seek on file '%s': %s", InFile, strerror (errno)); } Size = ftell (F); /* The input offset must be smaller than the size */ if (InputOffs >= 0) { if (InputOffs >= Size) { Error ("Input offset is greater than file size"); } } else { /* Use a zero offset */ InputOffs = 0; } /* Seek to the input offset and correct size to contain the remainder of ** the file. */ if (fseek (F, InputOffs, SEEK_SET) != 0) { Error ("Cannot seek on file '%s': %s", InFile, strerror (errno)); } Size -= InputOffs; /* Limit the size to the maximum input size if one is given */ if (InputSize >= 0) { if (InputSize > Size) { Error ("Input size is greater than what is available"); } Size = InputSize; } /* If the start address was not given, set it so that the code loads to ** 0x10000 - Size. This is a reasonable default assuming that the file ** is a ROM that contains the hardware vectors at $FFFA. */ if (StartAddr < 0) { if (Size > 0x10000) { StartAddr = 0; } else { StartAddr = 0x10000 - Size; } } /* Calculate the maximum code size */ MaxCount = 0x10000 - StartAddr; /* Check if the size is larger than what we can read */ if (Size == 0) { Error ("Nothing to read from input file '%s'", InFile); } if (Size > MaxCount) { Warning ("File '%s' is too large, ignoring %ld bytes", InFile, Size - MaxCount); } else if (MaxCount > Size) { MaxCount = (unsigned) Size; } /* Read from the file and remember the number of bytes read */ Count = fread (CodeBuf + StartAddr, 1, MaxCount, F); if (ferror (F) || Count != MaxCount) { Error ("Error reading from '%s': %s", InFile, strerror (errno)); } /* Close the file */ fclose (F); /* Set the buffer variables */ CodeStart = PC = StartAddr; CodeEnd = CodeStart + Count - 1; /* CodeEnd is inclusive */ } unsigned char GetCodeByte (unsigned Addr) /* Get a byte from the given address */ { PRECONDITION (Addr <= CodeEnd); return CodeBuf [Addr]; } unsigned GetCodeDByte (unsigned Addr) /* Get a dbyte from the given address */ { unsigned Lo = GetCodeByte (Addr); unsigned Hi = GetCodeByte (Addr+1); return (Lo <<8) | Hi; } unsigned GetCodeWord (unsigned Addr) /* Get a word from the given address */ { unsigned Lo = GetCodeByte (Addr); unsigned Hi = GetCodeByte (Addr+1); return Lo | (Hi << 8); } unsigned long GetCodeDWord (unsigned Addr) /* Get a dword from the given address */ { unsigned long Lo = GetCodeWord (Addr); unsigned long Hi = GetCodeWord (Addr+2); return Lo | (Hi << 16); } unsigned GetRemainingBytes (void) /* Return the number of remaining code bytes */ { if (CodeEnd >= PC) { return (CodeEnd - PC + 1); } else { return 0; } } int CodeLeft (void) /* Return true if there are code bytes left */ { return (PC <= CodeEnd); } void ResetCode (void) /* Reset the code input to start over for the next pass */ { PC = CodeStart; } �������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/code.h���������������������������������������������������������������������������0000664�0000000�0000000�00000007651�13473601511�0014627�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* code.h */ /* */ /* Binary code management */ /* */ /* */ /* */ /* (C) 2000-2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef CODE_H #define CODE_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ extern unsigned char CodeBuf [0x10000]; /* Code buffer */ extern unsigned long CodeStart; /* Start address */ extern unsigned long CodeEnd; /* End address */ extern unsigned long PC; /* Current PC */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ void LoadCode (void); /* Load the code from the given file */ unsigned char GetCodeByte (unsigned Addr); /* Get a byte from the given address */ unsigned GetCodeDByte (unsigned Addr); /* Get a dbyte from the given address */ unsigned GetCodeWord (unsigned Addr); /* Get a word from the given address */ unsigned long GetCodeDWord (unsigned Addr); /* Get a dword from the given address */ unsigned GetRemainingBytes (void); /* Return the number of remaining code bytes */ int CodeLeft (void); /* Return true if there are code bytes left */ void ResetCode (void); /* Reset the code input to start over for the next pass */ /* End of code.h */ #endif ���������������������������������������������������������������������������������������cc65-2.18/src/da65/comments.c�����������������������������������������������������������������������0000664�0000000�0000000�00000007354�13473601511�0015535�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* comments.c */ /* */ /* Comment management for da65 */ /* */ /* */ /* */ /* (C) 2006 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "xmalloc.h" /* da65 */ #include "attrtab.h" #include "comments.h" #include "error.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Comment table */ static const char* CommentTab[0x10000]; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void SetComment (unsigned Addr, const char* Comment) /* Set a comment for the given address */ { /* Check the given address */ AddrCheck (Addr); /* If we do already have a comment, warn and ignore the new one */ if (CommentTab[Addr]) { Warning ("Duplicate comment for address $%04X", Addr); } else { CommentTab[Addr] = xstrdup (Comment); } } const char* GetComment (unsigned Addr) /* Return the comment for an address */ { /* Check the given address */ AddrCheck (Addr); /* Return the label if any */ return CommentTab[Addr]; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/comments.h�����������������������������������������������������������������������0000664�0000000�0000000�00000006013�13473601511�0015531�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* comments.h */ /* */ /* Comment management for da65 */ /* */ /* */ /* */ /* (C) 2006 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef COMMENTS_H #define COMMENTS_H #include "attrtab.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void SetComment (unsigned Addr, const char* Comment); /* Set a comment for the given address */ const char* GetComment (unsigned Addr); /* Return the comment for an address */ /* End of comments.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/data.c���������������������������������������������������������������������������0000664�0000000�0000000�00000026205�13473601511�0014615�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* data.c */ /* */ /* Data output routines */ /* */ /* */ /* */ /* (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 */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* da65 */ #include "attrtab.h" #include "code.h" #include "error.h" #include "global.h" #include "labels.h" #include "output.h" #include "data.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ static unsigned GetSpan (attr_t Style) /* Get the number of bytes for a given style */ { /* Get the number of bytes still available */ unsigned RemainingBytes = GetRemainingBytes (); /* Count how many bytes are available. This number is limited by the ** number of remaining bytes, a label, a segment change, or the end of ** the given Style attribute. */ unsigned Count = 1; while (Count < RemainingBytes) { attr_t Attr; if (MustDefLabel(PC+Count)) { break; } Attr = GetAttr (PC+Count); if ((Attr & atStyleMask) != Style) { break; } if ((Attr & (atSegmentStart | atSegmentEnd))) { break; } ++Count; } /* Return the number of bytes */ return Count; } static unsigned DoTable (attr_t Style, unsigned MemberSize, void (*TableFunc) (unsigned)) /* Output a table of bytes */ { unsigned BytesLeft; /* Count how many bytes may be output. */ unsigned Count = GetSpan (Style); /* If the count is less than the member size, print a row of Count data ** bytes. We assume here that there is no member with a size that is less ** than BytesPerLine. */ if (Count < MemberSize) { DataByteLine (Count); PC += Count; return Count; } /* Make Count an even number of multiples of MemberSize */ Count &= ~(MemberSize-1); /* Output as many data bytes lines as needed */ BytesLeft = Count; while (BytesLeft > 0) { /* Calculate the number of bytes for the next line */ unsigned Chunk = (BytesLeft > BytesPerLine)? BytesPerLine : BytesLeft; /* Output a line with these bytes */ TableFunc (Chunk); /* Next line */ BytesLeft -= Chunk; PC += Chunk; } /* If the next line is not the same style, add a separator */ if (CodeLeft() && GetStyleAttr (PC) != Style) { SeparatorLine (); } /* Return the number of bytes output */ return Count; } unsigned ByteTable (void) /* Output a table of bytes */ { /* Call the low level function */ return DoTable (atByteTab, 1, DataByteLine); } unsigned DByteTable (void) /* Output a table of dbytes */ { /* Call the low level function */ return DoTable (atDByteTab, 2, DataDByteLine); } unsigned WordTable (void) /* Output a table of words */ { /* Call the low level function */ return DoTable (atWordTab, 2, DataWordLine); } unsigned DWordTable (void) /* Output a table of double words */ { /* Call the low level function */ return DoTable (atDWordTab, 4, DataDWordLine); } unsigned AddrTable (void) /* Output a table of addresses */ { unsigned long BytesLeft = GetRemainingBytes (); unsigned long Start = PC; /* Loop while table bytes left and we don't need to create a label at the ** current position. */ while (BytesLeft && GetStyleAttr (PC) == atAddrTab) { unsigned Addr; /* If just one byte is left, define it and bail out */ if (BytesLeft == 1 || GetStyleAttr (PC+1) != atAddrTab) { DataByteLine (1); ++PC; break; } /* More than one byte left. Define a forward label if necessary */ ForwardLabel (1); /* Now get the address from the PC */ Addr = GetCodeWord (PC); /* In pass 1, define a label, in pass 2 output the line */ if (Pass == 1) { if (!HaveLabel (Addr)) { AddIntLabel (Addr); } } else { const char* Label = GetLabel (Addr, PC); if (Label == 0) { /* OOPS! Should not happen */ Internal ("OOPS - Label for address 0x%06X disappeard!", Addr); } Indent (MCol); Output (".addr"); Indent (ACol); Output ("%s", Label); LineComment (PC, 2); LineFeed (); } /* Next table entry */ PC += 2; BytesLeft -= 2; /* If we must define a label here, bail out */ if (BytesLeft && MustDefLabel (PC)) { break; } } /* If the next line is not an address table line, add a separator */ if (CodeLeft() && GetStyleAttr (PC) != atAddrTab) { SeparatorLine (); } /* Return the number of bytes output */ return PC - Start; } unsigned RtsTable (void) /* Output a table of RTS addresses (address - 1) */ { unsigned long BytesLeft = GetRemainingBytes (); unsigned long Start = PC; /* Loop while table bytes left and we don't need to create a label at the ** current position. */ while (BytesLeft && GetStyleAttr (PC) == atRtsTab) { unsigned Addr; /* If just one byte is left, define it and bail out */ if (BytesLeft == 1 || GetStyleAttr (PC+1) != atRtsTab) { DataByteLine (1); ++PC; break; } /* More than one byte left. Define a forward label if necessary */ ForwardLabel (1); /* Now get the address from the PC */ Addr = (GetCodeWord (PC) + 1) & 0xFFFF; /* In pass 1, define a label, in pass 2 output the line */ if (Pass == 1) { if (!HaveLabel (Addr)) { AddIntLabel (Addr); } } else { const char* Label = GetLabel (Addr, PC); if (Label == 0) { /* OOPS! Should not happen */ Internal ("OOPS - Label for address 0x%06X disappeard!", Addr); } Indent (MCol); Output (".word"); Indent (ACol); Output ("%s-1", Label); LineComment (PC, 2); LineFeed (); } /* Next table entry */ PC += 2; BytesLeft -= 2; /* If we must define a label here, bail out */ if (BytesLeft && MustDefLabel (PC)) { break; } } /* If the next line is not a return address table line, add a separator */ if (CodeLeft() && GetStyleAttr (PC) != atRtsTab) { SeparatorLine (); } /* Return the number of bytes output */ return PC - Start; } unsigned TextTable (void) /* Output a table of text messages */ { /* Count how many bytes may be output. */ unsigned ByteCount = GetSpan (atTextTab); /* Output as many data bytes lines as needed. */ unsigned BytesLeft = ByteCount; while (BytesLeft > 0) { unsigned I; /* Count the number of characters that can be output as such */ unsigned Count = 0; while (Count < BytesLeft && Count < BytesPerLine*4-1) { unsigned char C = GetCodeByte (PC + Count); if (C >= 0x20 && C <= 0x7E && C != '\"') { ++Count; } else { break; } } /* If we have text, output it */ if (Count > 0) { unsigned CBytes; Indent (MCol); Output (".byte"); Indent (ACol); Output ("\""); for (I = 0; I < Count; ++I) { Output ("%c", GetCodeByte (PC+I)); } Output ("\""); CBytes = Count; while (CBytes > 0) { unsigned Chunk = CBytes; if (Chunk > BytesPerLine) { Chunk = BytesPerLine; } LineComment (PC, Chunk); LineFeed (); CBytes -= Chunk; PC += Chunk; } BytesLeft -= Count; } /* Count the number of bytes that must be output as bytes */ Count = 0; while (Count < BytesLeft && Count < BytesPerLine) { unsigned char C = GetCodeByte (PC + Count); if (C < 0x20 || C > 0x7E || C == '\"') { ++Count; } else { break; } } /* If we have raw output bytes, print them */ if (Count > 0) { DataByteLine (Count); PC += Count; BytesLeft -= Count; } } /* If the next line is not a byte table line, add a separator */ if (CodeLeft() && GetStyleAttr (PC) != atTextTab) { SeparatorLine (); } /* Return the number of bytes output */ return ByteCount; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/data.h���������������������������������������������������������������������������0000664�0000000�0000000�00000006366�13473601511�0014630�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* data.h */ /* */ /* Data output routines */ /* */ /* */ /* */ /* (C) 2000 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 DATA_H #define DATA_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ unsigned ByteTable (void); /* Output a table of bytes */ unsigned DByteTable (void); /* Output a table of dbytes */ unsigned WordTable (void); /* Output a table of words */ unsigned DWordTable (void); /* Output a table of double words */ unsigned AddrTable (void); /* Output a table of addresses */ unsigned RtsTable (void); /* Output a table of RTS addresses (address - 1) */ unsigned TextTable (void); /* Output a table of text messages */ /* End of data.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/error.c��������������������������������������������������������������������������0000664�0000000�0000000�00000007122�13473601511�0015032�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* error.c */ /* */ /* Error handling */ /* */ /* */ /* */ /* (C) 2000 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> /* da65 */ #include "error.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Warning (const char* Format, ...) /* Print a warning message */ { va_list ap; va_start (ap, Format); fprintf (stderr, "Warning: "); vfprintf (stderr, Format, ap); putc ('\n', stderr); va_end (ap); } void Error (const char* Format, ...) /* Print an error message and die */ { va_list ap; va_start (ap, Format); fprintf (stderr, "Error: "); vfprintf (stderr, Format, ap); putc ('\n', stderr); va_end (ap); exit (EXIT_FAILURE); } void Internal (const char* Format, ...) /* Print an internal error message and die */ { va_list ap; va_start (ap, Format); fprintf (stderr, "Internal error: "); vfprintf (stderr, Format, ap); putc ('\n', stderr); va_end (ap); exit (EXIT_FAILURE); } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/error.h��������������������������������������������������������������������������0000664�0000000�0000000�00000006273�13473601511�0015045�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* error.h */ /* */ /* Error handling */ /* */ /* */ /* */ /* (C) 2000-2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef ERROR_H #define ERROR_H /* common */ #include "attrib.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Warning (const char* Format, ...) attribute((format(printf,1,2))); /* Print a warning message */ void Error (const char* Format, ...) attribute((noreturn, format(printf,1,2))); /* Print an error message and die */ void Internal (const char* Format, ...) attribute((noreturn, format(printf,1,2))); /* Print an internal error message and die */ /* End of error.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/global.c�������������������������������������������������������������������������0000664�0000000�0000000�00000011167�13473601511�0015145�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* global.c */ /* */ /* Global variables for the da65 disassembler */ /* */ /* */ /* */ /* (C) 2000-2006 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include "global.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* File names */ const char* InFile = 0; /* Name of input file */ const char* OutFile = 0; /* Name of output file */ /* Default extensions */ const char OutExt[] = ".dis"; /* Output file extension */ const char CfgExt[] = ".cfg"; /* Config file extension */ /* Flags and other command line stuff */ unsigned char DebugInfo = 0; /* Add debug info to the object file */ unsigned char FormFeeds = 0; /* Add form feeds to the output? */ unsigned char UseHexOffs = 0; /* Use hexadecimal label offsets */ unsigned char PassCount = 2; /* How many passed do we do? */ signed char NewlineAfterJMP = -1; /* Add a newline after a JMP insn? */ signed char NewlineAfterRTS = -1; /* Add a newline after a RTS insn? */ long StartAddr = -1L; /* Start/load address of the program */ unsigned char SyncLines = 0; /* Accept line markers in the info file */ long InputOffs = -1L; /* Offset into input file */ long InputSize = -1L; /* Number of bytes to read from input */ /* Stuff needed by many routines */ unsigned Pass = 0; /* Disassembler pass */ char Now[128]; /* Current time as string */ /* Comments */ unsigned Comments = 0; /* Add which comments to the output? */ /* Page formatting */ unsigned PageLength = 0; /* Length of a listing page */ unsigned LBreak = 7; /* Linefeed if labels exceed this limit */ unsigned MCol = 9; /* Mnemonic column */ unsigned ACol = 17; /* Argument column */ unsigned CCol = 49; /* Comment column */ unsigned TCol = 81; /* Text bytes column */ unsigned BytesPerLine = 8; /* Max. number of data bytes per line */ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/global.h�������������������������������������������������������������������������0000664�0000000�0000000�00000012071�13473601511�0015145�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* global.h */ /* */ /* Global variables for the da65 disassembler */ /* */ /* */ /* */ /* (C) 2000-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef GLOBAL_H #define GLOBAL_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* File stuff */ extern const char* InFile; /* Name of input file */ extern const char* OutFile; /* Name of output file */ /* Default extensions */ extern const char OutExt[]; /* Output file extension */ extern const char CfgExt[]; /* Config file extension */ /* Flags and other command line stuff */ extern unsigned char DebugInfo; /* Add debug info to the object file */ extern unsigned char FormFeeds; /* Add form feeds to the output? */ extern unsigned char UseHexOffs; /* Use hexadecimal label offsets */ extern unsigned char PassCount; /* How many passed do we do? */ extern signed char NewlineAfterJMP;/* Add a newline after a JMP insn? */ extern signed char NewlineAfterRTS;/* Add a newline after a RTS insn? */ extern long StartAddr; /* Start/load address of the program */ extern unsigned char SyncLines; /* Accept line markers in the info file */ extern long InputOffs; /* Offset into input file */ extern long InputSize; /* Number of bytes to read from input */ /* Stuff needed by many routines */ extern unsigned Pass; /* Disassembler pass */ extern char Now[128]; /* Current time as string */ /* Comments */ #define MIN_COMMENTS 0 #define MAX_COMMENTS 4 extern unsigned Comments; /* Add which comments to the output? */ /* Page formatting */ #define MIN_PAGE_LEN 32 #define MAX_PAGE_LEN 127 extern unsigned PageLength; /* Length of a listing page */ /* Linefeed if labels exceed this limit */ #define MIN_LABELBREAK 1 #define MAX_LABELBREAK 128 extern unsigned LBreak; /* Mnemonic column */ #define MIN_MCOL 1 #define MAX_MCOL 127 extern unsigned MCol; /* Argument column */ #define MIN_ACOL 1 #define MAX_ACOL 127 extern unsigned ACol; /* Comment column */ #define MIN_CCOL 1 #define MAX_CCOL 127 extern unsigned CCol; /* Text bytes column */ #define MIN_TCOL 1 #define MAX_TCOL 127 extern unsigned TCol; /* Max. number of data bytes per line */ #define MIN_BYTESPERLINE 1 #define MAX_BYTESPERLINE 127 extern unsigned BytesPerLine; /* End of global.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/handler.c������������������������������������������������������������������������0000664�0000000�0000000�00000044346�13473601511�0015327�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* handler.c */ /* */ /* Opcode handler functions for the disassembler */ /* */ /* */ /* */ /* (C) 2000-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdarg.h> /* common */ #include "xmalloc.h" #include "xsprintf.h" /* da65 */ #include "attrtab.h" #include "code.h" #include "error.h" #include "global.h" #include "handler.h" #include "labels.h" #include "opctable.h" #include "output.h" static unsigned short SubroutineParamSize[0x10000]; /*****************************************************************************/ /* Helper functions */ /*****************************************************************************/ static void Mnemonic (const char* M) /* Indent and output a mnemonic */ { Indent (MCol); Output ("%s", M); } static void OneLine (const OpcDesc* D, const char* Arg, ...) attribute ((format(printf, 2, 3))); static void OneLine (const OpcDesc* D, const char* Arg, ...) /* Output one line with the given mnemonic and argument */ { char Buf [256]; va_list ap; /* Mnemonic */ Mnemonic (D->Mnemo); /* Argument */ va_start (ap, Arg); xvsprintf (Buf, sizeof (Buf), Arg, ap); va_end (ap); Indent (ACol); Output ("%s", Buf); /* Add the code stuff as comment */ LineComment (PC, D->Size); /* End the line */ LineFeed (); } static const char* GetAbsOverride (unsigned Flags, unsigned Addr) /* If the instruction requires an abs override modifier, return the necessary ** string, otherwise return the empty string. */ { if ((Flags & flAbsOverride) != 0 && Addr < 0x100) { return "a:"; } else { return ""; } } static const char* GetAddrArg (unsigned Flags, unsigned Addr) /* Return an address argument - a label if we have one, or the address itself */ { const char* Label = 0; if (Flags & flUseLabel) { Label = GetLabel (Addr, PC); } if (Label) { return Label; } else { static char Buf [32]; if (Addr < 0x100) { xsprintf (Buf, sizeof (Buf), "$%02X", Addr); } else { xsprintf (Buf, sizeof (Buf), "$%04X", Addr); } return Buf; } } static void GenerateLabel (unsigned Flags, unsigned Addr) /* Generate a label in pass one if requested */ { /* Generate labels in pass #1, and only if we don't have a label already */ if (Pass == 1 && !HaveLabel (Addr) && /* Check if we must create a label */ ((Flags & flGenLabel) != 0 || ((Flags & flUseLabel) != 0 && Addr >= CodeStart && Addr <= CodeEnd))) { /* As a special case, handle ranges with tables or similar. Within ** such a range with a granularity > 1, do only generate dependent ** labels for all addresses but the first one. Be sure to generate ** a label for the start of the range, however. */ attr_t Style = GetStyleAttr (Addr); unsigned Granularity = GetGranularity (Style); if (Granularity == 1) { /* Just add the label */ AddIntLabel (Addr); } else { /* THIS CODE IS A MESS AND WILL FAIL ON SEVERAL CONDITIONS! ### */ /* Search for the start of the range or the last non dependent ** label in the range. */ unsigned Offs; attr_t LabelAttr; unsigned LabelAddr = Addr; while (LabelAddr > CodeStart) { if (Style != GetStyleAttr (LabelAddr-1)) { /* End of range reached */ break; } --LabelAddr; LabelAttr = GetLabelAttr (LabelAddr); if ((LabelAttr & (atIntLabel|atExtLabel)) != 0) { /* The address has an internal or external label */ break; } } /* If the proposed label address doesn't have a label, define one */ if ((GetLabelAttr (LabelAddr) & (atIntLabel|atExtLabel)) == 0) { AddIntLabel (LabelAddr); } /* Create the label */ Offs = Addr - LabelAddr; if (Offs == 0) { AddIntLabel (Addr); } else { AddDepLabel (Addr, atIntLabel, GetLabelName (LabelAddr), Offs); } } } } /*****************************************************************************/ /* Code */ /*****************************************************************************/ void OH_Illegal (const OpcDesc* D attribute ((unused))) { DataByteLine (1); } void OH_Accumulator (const OpcDesc* D) { OneLine (D, "a"); } void OH_Implicit (const OpcDesc* D) { Mnemonic (D->Mnemo); LineComment (PC, D->Size); LineFeed (); } void OH_Immediate (const OpcDesc* D) { OneLine (D, "#$%02X", GetCodeByte (PC+1)); } void OH_ImmediateWord (const OpcDesc* D) { OneLine (D, "#$%04X", GetCodeWord (PC+1)); } void OH_Direct (const OpcDesc* D) { /* Get the operand */ unsigned Addr = GetCodeByte (PC+1); /* Generate a label in pass 1 */ GenerateLabel (D->Flags, Addr); /* Output the line */ OneLine (D, "%s", GetAddrArg (D->Flags, Addr)); } void OH_DirectX (const OpcDesc* D) { /* Get the operand */ unsigned Addr = GetCodeByte (PC+1); /* Generate a label in pass 1 */ GenerateLabel (D->Flags, Addr); /* Output the line */ OneLine (D, "%s,x", GetAddrArg (D->Flags, Addr)); } void OH_DirectY (const OpcDesc* D) { /* Get the operand */ unsigned Addr = GetCodeByte (PC+1); /* Generate a label in pass 1 */ GenerateLabel (D->Flags, Addr); /* Output the line */ OneLine (D, "%s,y", GetAddrArg (D->Flags, Addr)); } void OH_Absolute (const OpcDesc* D) { /* Get the operand */ unsigned Addr = GetCodeWord (PC+1); /* Generate a label in pass 1 */ GenerateLabel (D->Flags, Addr); /* Output the line */ OneLine (D, "%s%s", GetAbsOverride (D->Flags, Addr), GetAddrArg (D->Flags, Addr)); } void OH_AbsoluteX (const OpcDesc* D) { /* Get the operand */ unsigned Addr = GetCodeWord (PC+1); /* Generate a label in pass 1 */ GenerateLabel (D->Flags, Addr); /* Output the line */ OneLine (D, "%s%s,x", GetAbsOverride (D->Flags, Addr), GetAddrArg (D->Flags, Addr)); } void OH_AbsoluteY (const OpcDesc* D) { /* Get the operand */ unsigned Addr = GetCodeWord (PC+1); /* Generate a label in pass 1 */ GenerateLabel (D->Flags, Addr); /* Output the line */ OneLine (D, "%s%s,y", GetAbsOverride (D->Flags, Addr), GetAddrArg (D->Flags, Addr)); } void OH_AbsoluteLong (const OpcDesc* D attribute ((unused))) { Error ("Not implemented"); } void OH_AbsoluteLongX (const OpcDesc* D attribute ((unused))) { Error ("Not implemented"); } void OH_Relative (const OpcDesc* D) { /* Get the operand */ signed char Offs = GetCodeByte (PC+1); /* Calculate the target address */ unsigned Addr = (((int) PC+2) + Offs) & 0xFFFF; /* Generate a label in pass 1 */ GenerateLabel (D->Flags, Addr); /* Output the line */ OneLine (D, "%s", GetAddrArg (D->Flags, Addr)); } void OH_RelativeLong (const OpcDesc* D attribute ((unused))) { Error ("Not implemented"); } void OH_RelativeLong4510 (const OpcDesc* D attribute ((unused))) { /* Get the operand */ signed short Offs = GetCodeWord (PC+1); /* Calculate the target address */ unsigned Addr = (((int) PC+2) + Offs) & 0xFFFF; /* Generate a label in pass 1 */ GenerateLabel (D->Flags, Addr); /* Output the line */ OneLine (D, "%s", GetAddrArg (D->Flags, Addr)); } void OH_DirectIndirect (const OpcDesc* D) { /* Get the operand */ unsigned Addr = GetCodeByte (PC+1); /* Generate a label in pass 1 */ GenerateLabel (D->Flags, Addr); /* Output the line */ OneLine (D, "(%s)", GetAddrArg (D->Flags, Addr)); } void OH_DirectIndirectY (const OpcDesc* D) { /* Get the operand */ unsigned Addr = GetCodeByte (PC+1); /* Generate a label in pass 1 */ GenerateLabel (D->Flags, Addr); /* Output the line */ OneLine (D, "(%s),y", GetAddrArg (D->Flags, Addr)); } void OH_DirectIndirectZ (const OpcDesc* D) { /* Get the operand */ unsigned Addr = GetCodeByte (PC+1); /* Generate a label in pass 1 */ GenerateLabel (D->Flags, Addr); /* Output the line */ OneLine (D, "(%s),z", GetAddrArg (D->Flags, Addr)); } void OH_DirectXIndirect (const OpcDesc* D) { /* Get the operand */ unsigned Addr = GetCodeByte (PC+1); /* Generate a label in pass 1 */ GenerateLabel (D->Flags, Addr); /* Output the line */ OneLine (D, "(%s,x)", GetAddrArg (D->Flags, Addr)); } void OH_AbsoluteIndirect (const OpcDesc* D) { /* Get the operand */ unsigned Addr = GetCodeWord (PC+1); /* Generate a label in pass 1 */ GenerateLabel (D->Flags, Addr); /* Output the line */ OneLine (D, "(%s)", GetAddrArg (D->Flags, Addr)); } void OH_BitBranch (const OpcDesc* D) { char* BranchLabel; /* Get the operands */ unsigned char TestAddr = GetCodeByte (PC+1); signed char BranchOffs = GetCodeByte (PC+2); /* Calculate the target address for the branch */ unsigned BranchAddr = (((int) PC+3) + BranchOffs) & 0xFFFF; /* Generate labels in pass 1. The bit branch codes are special in that ** they don't really match the remainder of the 6502 instruction set (they ** are a Rockwell addon), so we must pass additional flags as direct ** value to the second GenerateLabel call. */ GenerateLabel (D->Flags, TestAddr); GenerateLabel (flLabel, BranchAddr); /* Make a copy of an operand, so that ** the other operand can't overwrite it. ** [GetAddrArg() uses a statically-stored buffer.] */ BranchLabel = xstrdup (GetAddrArg (flLabel, BranchAddr)); /* Output the line */ OneLine (D, "%s,%s", GetAddrArg (D->Flags, TestAddr), BranchLabel); xfree (BranchLabel); } void OH_ImmediateDirect (const OpcDesc* D) { /* Get the operand */ unsigned Addr = GetCodeByte (PC+2); /* Generate a label in pass 1 */ GenerateLabel (D->Flags, Addr); /* Output the line */ OneLine (D, "#$%02X,%s", GetCodeByte (PC+1), GetAddrArg (D->Flags, Addr)); } void OH_ImmediateDirectX (const OpcDesc* D) { /* Get the operand */ unsigned Addr = GetCodeByte (PC+2); /* Generate a label in pass 1 */ GenerateLabel (D->Flags, Addr); /* Output the line */ OneLine (D, "#$%02X,%s,x", GetCodeByte (PC+1), GetAddrArg (D->Flags, Addr)); } void OH_ImmediateAbsolute (const OpcDesc* D) { /* Get the operand */ unsigned Addr = GetCodeWord (PC+2); /* Generate a label in pass 1 */ GenerateLabel (D->Flags, Addr); /* Output the line */ OneLine (D, "#$%02X,%s%s", GetCodeByte (PC+1), GetAbsOverride (D->Flags, Addr), GetAddrArg (D->Flags, Addr)); } void OH_ImmediateAbsoluteX (const OpcDesc* D) { /* Get the operand */ unsigned Addr = GetCodeWord (PC+2); /* Generate a label in pass 1 */ GenerateLabel (D->Flags, Addr); /* Output the line */ OneLine (D, "#$%02X,%s%s,x", GetCodeByte (PC+1), GetAbsOverride (D->Flags, Addr), GetAddrArg (D->Flags, Addr)); } void OH_StackRelative (const OpcDesc* D attribute ((unused))) { Error ("Not implemented"); } void OH_DirectIndirectLongX (const OpcDesc* D attribute ((unused))) { Error ("Not implemented"); } void OH_StackRelativeIndirectY (const OpcDesc* D attribute ((unused))) { /* Output the line */ OneLine (D, "($%02X,s),y", GetCodeByte (PC+1)); } void OH_StackRelativeIndirectY4510 (const OpcDesc* D attribute ((unused))) { /* Output the line */ OneLine (D, "($%02X,sp),y", GetCodeByte (PC+1)); } void OH_DirectIndirectLong (const OpcDesc* D attribute ((unused))) { Error ("Not implemented"); } void OH_DirectIndirectLongY (const OpcDesc* D attribute ((unused))) { Error ("Not implemented"); } void OH_BlockMove (const OpcDesc* D) { char* DstLabel; /* Get source operand */ unsigned Src = GetCodeWord (PC+1); /* Get destination operand */ unsigned Dst = GetCodeWord (PC+3); /* Generate a label in pass 1 */ GenerateLabel (D->Flags, Src); GenerateLabel (D->Flags, Dst); /* Make a copy of an operand, so that ** the other operand can't overwrite it. ** [GetAddrArg() uses a statically-stored buffer.] */ DstLabel = xstrdup (GetAddrArg (D->Flags, Dst)); /* Output the line */ OneLine (D, "%s%s,%s%s,$%04X", GetAbsOverride (D->Flags, Src), GetAddrArg (D->Flags, Src), GetAbsOverride (D->Flags, Dst), DstLabel, GetCodeWord (PC+5)); xfree (DstLabel); } void OH_AbsoluteXIndirect (const OpcDesc* D attribute ((unused))) { /* Get the operand */ unsigned Addr = GetCodeWord (PC+1); /* Generate a label in pass 1 */ GenerateLabel (D->Flags, Addr); /* Output the line */ OneLine (D, "(%s,x)", GetAddrArg (D->Flags, Addr)); } void OH_DirectImmediate (const OpcDesc* D) { /* Get the operand */ unsigned Addr = GetCodeByte (PC+1); /* Generate a label in pass 1 */ GenerateLabel (D->Flags, Addr); /* Output the line */ OneLine (D, "%s, #$%02X", GetAddrArg (D->Flags, Addr), GetCodeByte (PC+2)); } void OH_ZeroPageBit (const OpcDesc* D) { unsigned Bit = GetCodeByte (PC) >> 5; unsigned Addr = GetCodeByte (PC+1); /* Generate a label in pass 1 */ GenerateLabel (D->Flags, Addr); /* Output the line */ OneLine (D, "%01X,%s", Bit, GetAddrArg (D->Flags, Addr)); } void OH_AccumulatorBit (const OpcDesc* D) { unsigned Bit = GetCodeByte (PC) >> 5; /* Output the line */ OneLine (D, "%01X,a", Bit); } void OH_AccumulatorBitBranch (const OpcDesc* D) { unsigned Bit = GetCodeByte (PC) >> 5; signed char BranchOffs = GetCodeByte (PC+1); /* Calculate the target address for the branch */ unsigned BranchAddr = (((int) PC+3) + BranchOffs) & 0xFFFF; /* Generate labels in pass 1 */ GenerateLabel (flLabel, BranchAddr); /* Output the line */ OneLine (D, "%01X,a,%s", Bit, GetAddrArg (flLabel, BranchAddr)); } void OH_JmpDirectIndirect (const OpcDesc* D) { OH_DirectIndirect (D); if (NewlineAfterJMP) { LineFeed (); } SeparatorLine (); } void OH_SpecialPage (const OpcDesc* D) { /* Get the operand */ unsigned Addr = 0xFF00 + GetCodeByte (PC+1); /* Generate a label in pass 1 */ GenerateLabel (D->Flags, Addr); /* OneLine (D, "$FF%02X", (CodeByte (PC+1)); */ OneLine (D, "%s", GetAddrArg (D->Flags, Addr)); } void OH_Rts (const OpcDesc* D) { OH_Implicit (D); if (NewlineAfterRTS) { LineFeed (); } SeparatorLine(); } void OH_JmpAbsolute (const OpcDesc* D) { OH_Absolute (D); if (NewlineAfterJMP) { LineFeed (); } SeparatorLine (); } void OH_JmpAbsoluteIndirect (const OpcDesc* D) { OH_AbsoluteIndirect (D); if (NewlineAfterJMP) { LineFeed (); } SeparatorLine (); } void OH_JmpAbsoluteXIndirect (const OpcDesc* D) { OH_AbsoluteXIndirect (D); if (NewlineAfterJMP) { LineFeed (); } SeparatorLine (); } void OH_JsrAbsolute (const OpcDesc* D) { unsigned ParamSize = SubroutineParamSize[GetCodeWord (PC+1)]; OH_Absolute (D); if (ParamSize > 0) { unsigned RemainingBytes; unsigned BytesLeft; PC += D->Size; RemainingBytes = GetRemainingBytes (); if (RemainingBytes < ParamSize) { ParamSize = RemainingBytes; } BytesLeft = ParamSize; while (BytesLeft > 0) { unsigned Chunk = (BytesLeft > BytesPerLine) ? BytesPerLine : BytesLeft; DataByteLine (Chunk); BytesLeft -= Chunk; PC += Chunk; } PC -= D->Size; } } void SetSubroutineParamSize (unsigned Addr, unsigned Size) { SubroutineParamSize[Addr] = Size; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/handler.h������������������������������������������������������������������������0000664�0000000�0000000�00000011516�13473601511�0015325�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* handler.h */ /* */ /* Opcode handler functions for the disassembler */ /* */ /* */ /* */ /* (C) 2000-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef HANDLER_H #define HANDLER_H /* common */ #include "attrib.h" /* da65 */ #include "opctable.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ /* Generic handlers */ void OH_Illegal (const OpcDesc* D attribute ((unused))); void OH_Accumulator (const OpcDesc*); void OH_Implicit (const OpcDesc*); void OH_Immediate (const OpcDesc*); void OH_ImmediateWord (const OpcDesc*); void OH_Direct (const OpcDesc*); void OH_DirectX (const OpcDesc*); void OH_DirectY (const OpcDesc*); void OH_Absolute (const OpcDesc*); void OH_AbsoluteX (const OpcDesc*); void OH_AbsoluteY (const OpcDesc*); void OH_AbsoluteLong (const OpcDesc*); void OH_AbsoluteLongX (const OpcDesc*); void OH_Relative (const OpcDesc*); void OH_RelativeLong (const OpcDesc*); void OH_RelativeLong4510 (const OpcDesc*); void OH_DirectIndirect (const OpcDesc*); void OH_DirectIndirectY (const OpcDesc*); void OH_DirectIndirectZ (const OpcDesc*); void OH_DirectXIndirect (const OpcDesc*); void OH_AbsoluteIndirect (const OpcDesc*); void OH_BitBranch (const OpcDesc*); void OH_ImmediateDirect (const OpcDesc*); void OH_ImmediateDirectX (const OpcDesc*); void OH_ImmediateAbsolute (const OpcDesc*); void OH_ImmediateAbsoluteX (const OpcDesc*); void OH_StackRelative (const OpcDesc*); void OH_DirectIndirectLongX (const OpcDesc*); void OH_StackRelativeIndirectY (const OpcDesc*); void OH_StackRelativeIndirectY4510 (const OpcDesc*); void OH_DirectIndirectLong (const OpcDesc*); void OH_DirectIndirectLongY (const OpcDesc*); void OH_BlockMove (const OpcDesc*); void OH_AbsoluteXIndirect (const OpcDesc*); /* Mitsubishi 740 */ void OH_DirectImmediate (const OpcDesc*); void OH_ZeroPageBit (const OpcDesc*); void OH_AccumulatorBit (const OpcDesc*); void OH_AccumulatorBitBranch (const OpcDesc*); void OH_JmpDirectIndirect (const OpcDesc* D); void OH_SpecialPage (const OpcDesc*); /* Handlers for special instructions */ void OH_Rts (const OpcDesc*); void OH_JmpAbsolute (const OpcDesc*); void OH_JmpAbsoluteIndirect (const OpcDesc* D); void OH_JmpAbsoluteXIndirect (const OpcDesc* D); void OH_JsrAbsolute (const OpcDesc*); void SetSubroutineParamSize (unsigned Addr, unsigned Size); /* End of handler.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/infofile.c�����������������������������������������������������������������������0000664�0000000�0000000�00000063004�13473601511�0015475�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* infofile.h */ /* */ /* Disassembler info file handling */ /* */ /* */ /* */ /* (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 */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> #include <limits.h> #if defined(_MSC_VER) /* Microsoft compiler */ # include <io.h> #else /* Anyone else */ # include <unistd.h> #endif /* common */ #include "cpu.h" #include "xmalloc.h" /* da65 */ #include "asminc.h" #include "attrtab.h" #include "comments.h" #include "error.h" #include "global.h" #include "infofile.h" #include "labels.h" #include "opctable.h" #include "scanner.h" #include "segment.h" #include "handler.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void AddAttr (const char* Name, unsigned* Set, unsigned Attr) /* Add an attribute to the set and check that it is not given twice */ { if (*Set & Attr) { /* Attribute is already in the set */ InfoError ("%s given twice", Name); } *Set |= Attr; } static void AsmIncSection (void) /* Parse a asminc section */ { static const IdentTok LabelDefs[] = { { "COMMENTSTART", INFOTOK_COMMENTSTART }, { "FILE", INFOTOK_FILE }, { "IGNOREUNKNOWN", INFOTOK_IGNOREUNKNOWN }, }; /* Locals - initialize to avoid gcc warnings */ char* Name = 0; int CommentStart = EOF; int IgnoreUnknown = -1; /* Skip the token */ InfoNextTok (); /* Expect the opening curly brace */ InfoConsumeLCurly (); /* Look for section tokens */ while (InfoTok != INFOTOK_RCURLY) { /* Convert to special token */ InfoSpecialToken (LabelDefs, ENTRY_COUNT (LabelDefs), "Asminc directive"); /* Look at the token */ switch (InfoTok) { case INFOTOK_COMMENTSTART: InfoNextTok (); if (CommentStart != EOF) { InfoError ("Commentstart already given"); } InfoAssureChar (); CommentStart = (char) InfoIVal; InfoNextTok (); break; case INFOTOK_FILE: InfoNextTok (); if (Name) { InfoError ("File name already given"); } InfoAssureStr (); if (InfoSVal[0] == '\0') { InfoError ("File name may not be empty"); } Name = xstrdup (InfoSVal); InfoNextTok (); break; case INFOTOK_IGNOREUNKNOWN: InfoNextTok (); if (IgnoreUnknown != -1) { InfoError ("Ignoreunknown already specified"); } InfoBoolToken (); IgnoreUnknown = (InfoTok != INFOTOK_FALSE); InfoNextTok (); break; default: Internal ("Unexpected token: %u", InfoTok); } /* Directive is followed by a semicolon */ InfoConsumeSemi (); } /* Check for the necessary data and assume defaults */ if (Name == 0) { InfoError ("File name is missing"); } if (CommentStart == EOF) { CommentStart = ';'; } if (IgnoreUnknown == -1) { IgnoreUnknown = 0; } /* Open the file and read the symbol definitions */ AsmInc (Name, CommentStart, IgnoreUnknown); /* Delete the dynamically allocated memory for Name */ xfree (Name); /* Consume the closing brace */ InfoConsumeRCurly (); } static void GlobalSection (void) /* Parse a global section */ { static const IdentTok GlobalDefs[] = { { "ARGUMENTCOL", INFOTOK_ARGUMENT_COLUMN }, { "ARGUMENTCOLUMN", INFOTOK_ARGUMENT_COLUMN }, { "COMMENTCOL", INFOTOK_COMMENT_COLUMN }, { "COMMENTCOLUMN", INFOTOK_COMMENT_COLUMN }, { "COMMENTS", INFOTOK_COMMENTS }, { "CPU", INFOTOK_CPU }, { "HEXOFFS", INFOTOK_HEXOFFS }, { "INPUTNAME", INFOTOK_INPUTNAME }, { "INPUTOFFS", INFOTOK_INPUTOFFS }, { "INPUTSIZE", INFOTOK_INPUTSIZE }, { "LABELBREAK", INFOTOK_LABELBREAK }, { "MNEMONICCOL", INFOTOK_MNEMONIC_COLUMN }, { "MNEMONICCOLUMN", INFOTOK_MNEMONIC_COLUMN }, { "NEWLINEAFTERJMP", INFOTOK_NL_AFTER_JMP }, { "NEWLINEAFTERRTS", INFOTOK_NL_AFTER_RTS }, { "OUTPUTNAME", INFOTOK_OUTPUTNAME }, { "PAGELENGTH", INFOTOK_PAGELENGTH }, { "STARTADDR", INFOTOK_STARTADDR }, { "TEXTCOL", INFOTOK_TEXT_COLUMN }, { "TEXTCOLUMN", INFOTOK_TEXT_COLUMN }, }; /* Skip the token */ InfoNextTok (); /* Expect the opening curly brace */ InfoConsumeLCurly (); /* Look for section tokens */ while (InfoTok != INFOTOK_RCURLY) { /* Convert to special token */ InfoSpecialToken (GlobalDefs, ENTRY_COUNT (GlobalDefs), "Global directive"); /* Look at the token */ switch (InfoTok) { case INFOTOK_ARGUMENT_COLUMN: InfoNextTok (); InfoAssureInt (); InfoRangeCheck (MIN_ACOL, MAX_ACOL); ACol = InfoIVal; InfoNextTok (); break; case INFOTOK_COMMENT_COLUMN: InfoNextTok (); InfoAssureInt (); InfoRangeCheck (MIN_CCOL, MAX_CCOL); CCol = InfoIVal; InfoNextTok (); break; case INFOTOK_COMMENTS: InfoNextTok (); InfoAssureInt (); InfoRangeCheck (MIN_COMMENTS, MAX_COMMENTS); Comments = InfoIVal; InfoNextTok (); break; case INFOTOK_CPU: InfoNextTok (); InfoAssureStr (); if (CPU != CPU_UNKNOWN) { InfoError ("CPU already specified"); } CPU = FindCPU (InfoSVal); SetOpcTable (CPU); InfoNextTok (); break; case INFOTOK_HEXOFFS: InfoNextTok (); InfoBoolToken (); switch (InfoTok) { case INFOTOK_FALSE: UseHexOffs = 0; break; case INFOTOK_TRUE: UseHexOffs = 1; break; } InfoNextTok (); break; case INFOTOK_INPUTNAME: InfoNextTok (); InfoAssureStr (); if (InFile) { InfoError ("Input file name already given"); } InFile = xstrdup (InfoSVal); InfoNextTok (); break; case INFOTOK_INPUTOFFS: InfoNextTok (); InfoAssureInt (); InputOffs = InfoIVal; InfoNextTok (); break; case INFOTOK_INPUTSIZE: InfoNextTok (); InfoAssureInt (); InfoRangeCheck (1, 0x10000); InputSize = InfoIVal; InfoNextTok (); break; case INFOTOK_LABELBREAK: InfoNextTok (); InfoAssureInt (); InfoRangeCheck (0, UCHAR_MAX); LBreak = (unsigned char) InfoIVal; InfoNextTok (); break; case INFOTOK_MNEMONIC_COLUMN: InfoNextTok (); InfoAssureInt (); InfoRangeCheck (MIN_MCOL, MAX_MCOL); MCol = InfoIVal; InfoNextTok (); break; case INFOTOK_NL_AFTER_JMP: InfoNextTok (); if (NewlineAfterJMP != -1) { InfoError ("NLAfterJMP already specified"); } InfoBoolToken (); NewlineAfterJMP = (InfoTok != INFOTOK_FALSE); InfoNextTok (); break; case INFOTOK_NL_AFTER_RTS: InfoNextTok (); InfoBoolToken (); if (NewlineAfterRTS != -1) { InfoError ("NLAfterRTS already specified"); } NewlineAfterRTS = (InfoTok != INFOTOK_FALSE); InfoNextTok (); break; case INFOTOK_OUTPUTNAME: InfoNextTok (); InfoAssureStr (); if (OutFile) { InfoError ("Output file name already given"); } OutFile = xstrdup (InfoSVal); InfoNextTok (); break; case INFOTOK_PAGELENGTH: InfoNextTok (); InfoAssureInt (); if (InfoIVal != 0) { InfoRangeCheck (MIN_PAGE_LEN, MAX_PAGE_LEN); } PageLength = InfoIVal; InfoNextTok (); break; case INFOTOK_STARTADDR: InfoNextTok (); InfoAssureInt (); InfoRangeCheck (0x0000, 0xFFFF); StartAddr = InfoIVal; InfoNextTok (); break; case INFOTOK_TEXT_COLUMN: InfoNextTok (); InfoAssureInt (); InfoRangeCheck (MIN_TCOL, MAX_TCOL); TCol = InfoIVal; InfoNextTok (); break; default: Internal ("Unexpected token: %u", InfoTok); } /* Directive is followed by a semicolon */ InfoConsumeSemi (); } /* Consume the closing brace */ InfoConsumeRCurly (); } static void LabelSection (void) /* Parse a label section */ { static const IdentTok LabelDefs[] = { { "COMMENT", INFOTOK_COMMENT }, { "ADDR", INFOTOK_ADDR }, { "NAME", INFOTOK_NAME }, { "SIZE", INFOTOK_SIZE }, { "PARAMSIZE", INFOTOK_PARAMSIZE }, }; /* Locals - initialize to avoid gcc warnings */ char* Name = 0; char* Comment = 0; long Value = -1; long Size = -1; long ParamSize = -1; /* Skip the token */ InfoNextTok (); /* Expect the opening curly brace */ InfoConsumeLCurly (); /* Look for section tokens */ while (InfoTok != INFOTOK_RCURLY) { /* Convert to special token */ InfoSpecialToken (LabelDefs, ENTRY_COUNT (LabelDefs), "Label attribute"); /* Look at the token */ switch (InfoTok) { case INFOTOK_ADDR: InfoNextTok (); if (Value >= 0) { InfoError ("Value already given"); } InfoAssureInt (); InfoRangeCheck (0, 0xFFFF); Value = InfoIVal; InfoNextTok (); break; case INFOTOK_COMMENT: InfoNextTok (); if (Comment) { InfoError ("Comment already given"); } InfoAssureStr (); if (InfoSVal[0] == '\0') { InfoError ("Comment may not be empty"); } Comment = xstrdup (InfoSVal); InfoNextTok (); break; case INFOTOK_NAME: InfoNextTok (); if (Name) { InfoError ("Name already given"); } InfoAssureStr (); Name = xstrdup (InfoSVal); InfoNextTok (); break; case INFOTOK_SIZE: InfoNextTok (); if (Size >= 0) { InfoError ("Size already given"); } InfoAssureInt (); InfoRangeCheck (1, 0x10000); Size = InfoIVal; InfoNextTok (); break; case INFOTOK_PARAMSIZE: InfoNextTok (); if (ParamSize >= 0) { InfoError ("ParamSize already given"); } InfoAssureInt (); InfoRangeCheck (1, 0x10000); ParamSize = InfoIVal; InfoNextTok (); break; default: Internal ("Unexpected token: %u", InfoTok); } /* Directive is followed by a semicolon */ InfoConsumeSemi (); } /* Did we get the necessary data */ if (Name == 0) { InfoError ("Label name is missing"); } if (Name[0] == '\0' && Size > 1) { InfoError ("Unnamed labels must not have a size > 1"); } if (Value < 0) { InfoError ("Label value is missing"); } if (Size < 0) { /* Use default */ Size = 1; } if (Value + Size > 0x10000) { InfoError ("Invalid size (address out of range)"); } if (HaveLabel ((unsigned) Value)) { InfoError ("Label for address $%04lX already defined", Value); } /* Define the label(s) */ if (Name[0] == '\0') { /* Size has already beed checked */ AddUnnamedLabel (Value); } else { AddExtLabelRange ((unsigned) Value, Name, Size); } if (ParamSize >= 0) { SetSubroutineParamSize ((unsigned) Value, (unsigned) ParamSize); } /* Define the comment */ if (Comment) { SetComment (Value, Comment); } /* Delete the dynamically allocated memory for Name and Comment */ xfree (Name); xfree (Comment); /* Consume the closing brace */ InfoConsumeRCurly (); } static void RangeSection (void) /* Parse a range section */ { static const IdentTok RangeDefs[] = { { "COMMENT", INFOTOK_COMMENT }, { "END", INFOTOK_END }, { "NAME", INFOTOK_NAME }, { "START", INFOTOK_START }, { "TYPE", INFOTOK_TYPE }, }; static const IdentTok TypeDefs[] = { { "ADDRTABLE", INFOTOK_ADDRTAB }, { "BYTETABLE", INFOTOK_BYTETAB }, { "CODE", INFOTOK_CODE }, { "DBYTETABLE", INFOTOK_DBYTETAB }, { "DWORDTABLE", INFOTOK_DWORDTAB }, { "RTSTABLE", INFOTOK_RTSTAB }, { "SKIP", INFOTOK_SKIP }, { "TEXTTABLE", INFOTOK_TEXTTAB }, { "WORDTABLE", INFOTOK_WORDTAB }, }; /* Which values did we get? */ enum { tNone = 0x00, tStart = 0x01, tEnd = 0x02, tType = 0x04, tName = 0x08, tComment= 0x10, tNeeded = (tStart | tEnd | tType) }; unsigned Attributes = tNone; /* Locals - initialize to avoid gcc warnings */ unsigned Start = 0; unsigned End = 0; unsigned char Type = 0; char* Name = 0; char* Comment = 0; unsigned MemberSize = 0; /* Skip the token */ InfoNextTok (); /* Expect the opening curly brace */ InfoConsumeLCurly (); /* Look for section tokens */ while (InfoTok != INFOTOK_RCURLY) { /* Convert to special token */ InfoSpecialToken (RangeDefs, ENTRY_COUNT (RangeDefs), "Range attribute"); /* Look at the token */ switch (InfoTok) { case INFOTOK_COMMENT: AddAttr ("COMMENT", &Attributes, tComment); InfoNextTok (); InfoAssureStr (); if (InfoSVal[0] == '\0') { InfoError ("Comment may not be empty"); } Comment = xstrdup (InfoSVal); Attributes |= tComment; InfoNextTok (); break; case INFOTOK_END: AddAttr ("END", &Attributes, tEnd); InfoNextTok (); InfoAssureInt (); InfoRangeCheck (0x0000, 0xFFFF); End = InfoIVal; InfoNextTok (); break; case INFOTOK_NAME: AddAttr ("NAME", &Attributes, tName); InfoNextTok (); InfoAssureStr (); if (InfoSVal[0] == '\0') { InfoError ("Name may not be empty"); } Name = xstrdup (InfoSVal); Attributes |= tName; InfoNextTok (); break; case INFOTOK_START: AddAttr ("START", &Attributes, tStart); InfoNextTok (); InfoAssureInt (); InfoRangeCheck (0x0000, 0xFFFF); Start = InfoIVal; InfoNextTok (); break; case INFOTOK_TYPE: AddAttr ("TYPE", &Attributes, tType); InfoNextTok (); InfoSpecialToken (TypeDefs, ENTRY_COUNT (TypeDefs), "TYPE"); switch (InfoTok) { case INFOTOK_ADDRTAB: Type = atAddrTab; MemberSize = 2; break; case INFOTOK_BYTETAB: Type = atByteTab; MemberSize = 1; break; case INFOTOK_CODE: Type = atCode; MemberSize = 1; break; case INFOTOK_DBYTETAB: Type = atDByteTab; MemberSize = 2; break; case INFOTOK_DWORDTAB: Type = atDWordTab; MemberSize = 4; break; case INFOTOK_RTSTAB: Type = atRtsTab; MemberSize = 2; break; case INFOTOK_SKIP: Type = atSkip; MemberSize = 1; break; case INFOTOK_TEXTTAB: Type = atTextTab; MemberSize = 1; break; case INFOTOK_WORDTAB: Type = atWordTab; MemberSize = 2; break; } InfoNextTok (); break; default: Internal ("Unexpected token: %u", InfoTok); } /* Directive is followed by a semicolon */ InfoConsumeSemi (); } /* Did we get all required values? */ if ((Attributes & tNeeded) != tNeeded) { InfoError ("Required values missing from this section"); } /* Start must be less than end */ if (Start > End) { InfoError ("Start value must not be greater than end value"); } /* Check the granularity */ if (((End - Start + 1) % MemberSize) != 0) { InfoError ("Type of range needs a granularity of %u", MemberSize); } /* Set the range */ MarkRange (Start, End, Type); /* Do we have a label? */ if (Attributes & tName) { /* Define a label for the table */ AddExtLabel (Start, Name); /* Set the comment if we have one */ if (Comment) { SetComment (Start, Comment); } /* Delete name and comment */ xfree (Name); xfree (Comment); } /* Consume the closing brace */ InfoConsumeRCurly (); } static void SegmentSection (void) /* Parse a segment section */ { static const IdentTok LabelDefs[] = { { "END", INFOTOK_END }, { "NAME", INFOTOK_NAME }, { "START", INFOTOK_START }, }; /* Locals - initialize to avoid gcc warnings */ long End = -1; long Start = -1; char* Name = 0; /* Skip the token */ InfoNextTok (); /* Expect the opening curly brace */ InfoConsumeLCurly (); /* Look for section tokens */ while (InfoTok != INFOTOK_RCURLY) { /* Convert to special token */ InfoSpecialToken (LabelDefs, ENTRY_COUNT (LabelDefs), "Segment attribute"); /* Look at the token */ switch (InfoTok) { case INFOTOK_END: InfoNextTok (); if (End >= 0) { InfoError ("Value already given"); } InfoAssureInt (); InfoRangeCheck (0, 0xFFFF); End = InfoIVal; InfoNextTok (); break; case INFOTOK_NAME: InfoNextTok (); if (Name) { InfoError ("Name already given"); } InfoAssureStr (); Name = xstrdup (InfoSVal); InfoNextTok (); break; case INFOTOK_START: InfoNextTok (); if (Start >= 0) { InfoError ("Value already given"); } InfoAssureInt (); InfoRangeCheck (0, 0xFFFF); Start = InfoIVal; InfoNextTok (); break; default: Internal ("Unexpected token: %u", InfoTok); } /* Directive is followed by a semicolon */ InfoConsumeSemi (); } /* Did we get the necessary data, and is it correct? */ if (Name == 0 || Name[0] == '\0') { InfoError ("Segment name is missing"); } if (End < 0) { InfoError ("End address is missing"); } if (Start < 0) { InfoError ("Start address is missing"); } 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 must not overlap"); } /* Remember the segment data */ AddAbsSegment ((unsigned) Start, (unsigned) End, Name); /* Delete the dynamically allocated memory for Name */ xfree (Name); /* Consume the closing brace */ InfoConsumeRCurly (); } static void InfoParse (void) /* Parse the config file */ { static const IdentTok Globals[] = { { "ASMINC", INFOTOK_ASMINC }, { "GLOBAL", INFOTOK_GLOBAL }, { "LABEL", INFOTOK_LABEL }, { "RANGE", INFOTOK_RANGE }, { "SEGMENT", INFOTOK_SEGMENT }, }; while (InfoTok != INFOTOK_EOF) { /* Convert an identifier into a token */ InfoSpecialToken (Globals, ENTRY_COUNT (Globals), "Config directive"); /* Check the token */ switch (InfoTok) { case INFOTOK_ASMINC: AsmIncSection (); break; case INFOTOK_GLOBAL: GlobalSection (); break; case INFOTOK_LABEL: LabelSection (); break; case INFOTOK_RANGE: RangeSection (); break; case INFOTOK_SEGMENT: SegmentSection (); break; default: Internal ("Unexpected token: %u", InfoTok); } /* Semicolon expected */ InfoConsumeSemi (); } } void ReadInfoFile (void) /* Read the info file */ { /* Check if we have a info file given */ if (InfoAvail()) { /* Open the config file */ InfoOpenInput (); /* Parse the config file */ InfoParse (); /* Close the file */ InfoCloseInput (); } } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/infofile.h�����������������������������������������������������������������������0000664�0000000�0000000�00000005565�13473601511�0015512�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* infofile.h */ /* */ /* Disassembler info file handling */ /* */ /* */ /* */ /* (C) 2000-2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef INFOFILE_H #define INFOFILE_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ void ReadInfoFile (void); /* Read the info file */ /* End of infofile.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/labels.c�������������������������������������������������������������������������0000664�0000000�0000000�00000027770�13473601511�0015156�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* labels.c */ /* */ /* Label management for da65 */ /* */ /* */ /* */ /* (C) 2006-2007 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> /* common */ #include "xmalloc.h" #include "xsprintf.h" /* da65 */ #include "attrtab.h" #include "code.h" #include "comments.h" #include "error.h" #include "global.h" #include "labels.h" #include "output.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Symbol table */ static const char* SymTab[0x10000]; /*****************************************************************************/ /* Code */ /*****************************************************************************/ static const char* MakeLabelName (unsigned Addr) /* Make the default label name from the given address and return it in a ** static buffer. */ { static char LabelBuf [32]; xsprintf (LabelBuf, sizeof (LabelBuf), "L%04X", Addr); return LabelBuf; } static void AddLabel (unsigned Addr, attr_t Attr, const char* Name) /* Add a label */ { /* Get an existing label attribute */ attr_t ExistingAttr = GetLabelAttr (Addr); /* Must not have two symbols for one address */ if (ExistingAttr != atNoLabel) { /* Allow redefinition if identical. Beware: Unnamed labels don't ** have a name (you guessed that, didn't you?). */ if (ExistingAttr == Attr && ((Name == 0 && SymTab[Addr] == 0) || (Name != 0 && SymTab[Addr] != 0 && strcmp (SymTab[Addr], Name) == 0))) { return; } Error ("Duplicate label for address $%04X: %s/%s", Addr, SymTab[Addr], Name); } /* Create a new label (xstrdup will return NULL if input NULL) */ SymTab[Addr] = xstrdup (Name); /* Remember the attribute */ MarkAddr (Addr, Attr); } void AddIntLabel (unsigned Addr) /* Add an internal label using the address to generate the name. */ { AddLabel (Addr, atIntLabel, MakeLabelName (Addr)); } void AddExtLabel (unsigned Addr, const char* Name) /* Add an external label */ { AddLabel (Addr, atExtLabel, Name); } void AddUnnamedLabel (unsigned Addr) /* Add an unnamed label */ { AddLabel (Addr, atUnnamedLabel, 0); } void AddDepLabel (unsigned Addr, attr_t Attr, const char* BaseName, unsigned Offs) /* Add a dependent label at the given address using "basename+Offs" as the new ** name. */ { /* Allocate memory for the dependent label name */ unsigned NameLen = strlen (BaseName); char* DepName = xmalloc (NameLen + 7); /* "+$ABCD\0" */ /* Create the new name in the buffer */ if (UseHexOffs) { sprintf (DepName, "%s+$%02X", BaseName, Offs); } else { sprintf (DepName, "%s+%u", BaseName, Offs); } /* Define the labels */ AddLabel (Addr, Attr | atDepLabel, DepName); /* Free the name buffer */ xfree (DepName); } static void AddLabelRange (unsigned Addr, attr_t Attr, const char* Name, unsigned Count) /* Add a label for a range. The first entry gets the label "Name" while the ** others get "Name+offs". */ { /* Define the label */ AddLabel (Addr, Attr, Name); /* Define dependent labels if necessary */ if (Count > 1) { unsigned Offs; /* Setup the format string */ const char* Format = UseHexOffs? "$%02X" : "%u"; /* Allocate memory for the dependent label names */ unsigned NameLen = strlen (Name); char* DepName = xmalloc (NameLen + 7); /* "+$ABCD" */ char* DepOffs = DepName + NameLen + 1; /* Copy the original name into the buffer */ memcpy (DepName, Name, NameLen); DepName[NameLen] = '+'; /* Define the labels */ for (Offs = 1; Offs < Count; ++Offs) { sprintf (DepOffs, Format, Offs); AddLabel (Addr + Offs, Attr | atDepLabel, DepName); } /* Free the name buffer */ xfree (DepName); } } void AddIntLabelRange (unsigned Addr, const char* Name, unsigned Count) /* Add an internal label for a range. The first entry gets the label "Name" ** while the others get "Name+offs". */ { /* Define the label range */ AddLabelRange (Addr, atIntLabel, Name, Count); } void AddExtLabelRange (unsigned Addr, const char* Name, unsigned Count) /* Add an external label for a range. The first entry gets the label "Name" ** while the others get "Name+offs". */ { /* Define the label range */ AddLabelRange (Addr, atExtLabel, Name, Count); } int HaveLabel (unsigned Addr) /* Check if there is a label for the given address */ { /* Check for a label */ return (GetLabelAttr (Addr) != atNoLabel); } int MustDefLabel (unsigned Addr) /* Return true if we must define a label for this address, that is, if there ** is a label at this address, and it is an external or internal label. */ { /* Get the label attribute */ attr_t A = GetLabelAttr (Addr); /* Check for an internal, external, or unnamed label */ return (A == atExtLabel || A == atIntLabel || A == atUnnamedLabel); } const char* GetLabelName (unsigned Addr) /* Return the label name for an address */ { /* Get the label attribute */ attr_t A = GetLabelAttr (Addr); /* Special case unnamed labels, because these don't have a named stored in ** the symbol table to save space. */ if (A == atUnnamedLabel) { return ""; } else { /* Return the label if any */ return SymTab[Addr]; } } const char* GetLabel (unsigned Addr, unsigned RefFrom) /* Return the label name for an address, as it is used in a label reference. ** RefFrom is the address the label is referenced from. This is needed in case ** of unnamed labels, to determine the name. */ { static const char* const FwdLabels[] = { ":+", ":++", ":+++", ":++++", ":+++++", ":++++++", ":+++++++", ":++++++++", ":+++++++++", ":++++++++++" }; static const char* const BackLabels[] = { ":-", ":--", ":---", ":----", ":-----", ":------", ":-------", ":--------", ":---------", ":----------" }; /* Get the label attribute */ attr_t A = GetLabelAttr (Addr); /* Special case unnamed labels, because these don't have a named stored in ** the symbol table to save space. */ if (A == atUnnamedLabel) { unsigned Count = 0; /* Search forward or backward depending in which direction the label ** is. */ if (Addr <= RefFrom) { /* Search backwards */ unsigned I = RefFrom; while (Addr < I) { --I; A = GetLabelAttr (I); if (A == atUnnamedLabel) { ++Count; if (Count >= sizeof (BackLabels) / sizeof (BackLabels[0])) { Error ("Too many unnamed labels between label at " "$%04X and reference at $%04X", Addr, RefFrom); } } } /* Return the label name */ return BackLabels[Count-1]; } else { /* Search forwards */ unsigned I = RefFrom; while (Addr > I) { ++I; A = GetLabelAttr (I); if (A == atUnnamedLabel) { ++Count; if (Count >= sizeof (FwdLabels) / sizeof (FwdLabels[0])) { Error ("Too many unnamed labels between label at " "$%04X and reference at $%04X", Addr, RefFrom); } } } /* Return the label name */ return FwdLabels[Count-1]; } } else { /* Return the label if any */ return SymTab[Addr]; } } void ForwardLabel (unsigned Offs) /* If necessary, output a forward label, one that is within the next few ** bytes and is therefore output as "label = * + x". */ { /* Calculate the actual address */ unsigned long Addr = PC + Offs; /* Get the type of the label */ attr_t A = GetLabelAttr (Addr); /* If there is no label, or just a dependent one, bail out */ if (A == atNoLabel || (A & atDepLabel) != 0) { return; } /* An unnamed label cannot be output as a forward declaration, so this is ** an error. */ if (A == atUnnamedLabel) { Error ("Cannot define unnamed label at address $%04lX", Addr); } /* Output the label */ DefForward (GetLabelName (Addr), GetComment (Addr), Offs); } static void DefOutOfRangeLabel (unsigned long Addr) /* Define one label that is outside code range. */ { switch (GetLabelAttr (Addr)) { case atIntLabel: case atExtLabel: DefConst (SymTab[Addr], GetComment (Addr), Addr); break; case atUnnamedLabel: Error ("Cannot define unnamed label at address $%04lX", Addr); break; default: break; } } void DefOutOfRangeLabels (void) /* Output any labels that are out of the loaded code range */ { unsigned long Addr; SeparatorLine (); /* Low range */ Addr = 0; while (Addr < CodeStart) { DefOutOfRangeLabel (Addr++); } /* Skip areas in code range */ while (Addr <= CodeEnd) { if (GetStyleAttr (Addr) == atSkip) { DefOutOfRangeLabel (Addr); } ++Addr; } /* High range */ while (Addr < 0x10000) { DefOutOfRangeLabel (Addr++); } SeparatorLine (); } ��������cc65-2.18/src/da65/labels.h�������������������������������������������������������������������������0000664�0000000�0000000�00000010753�13473601511�0015154�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* labels.h */ /* */ /* Label management for da65 */ /* */ /* */ /* */ /* (C) 2006 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef LABELS_H #define LABELS_H #include "attrtab.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void AddIntLabel (unsigned Addr); /* Add an internal label using the address to generate the name. */ void AddExtLabel (unsigned Addr, const char* Name); /* Add an external label */ void AddUnnamedLabel (unsigned Addr); /* Add an unnamed label */ void AddDepLabel (unsigned Addr, attr_t Attr, const char* BaseName, unsigned Offs); /* Add a dependent label at the given address using "base name+Offs" as the new ** name. */ void AddIntLabelRange (unsigned Addr, const char* Name, unsigned Count); /* Add an internal label for a range. The first entry gets the label "Name" ** while the others get "Name+offs". */ void AddExtLabelRange (unsigned Addr, const char* Name, unsigned Count); /* Add an external label for a range. The first entry gets the label "Name" ** while the others get "Name+offs". */ int HaveLabel (unsigned Addr); /* Check if there is a label for the given address */ int MustDefLabel (unsigned Addr); /* Return true if we must define a label for this address, that is, if there ** is a label at this address, and it is an external or internal label. */ const char* GetLabelName (unsigned Addr); /* Return the label name for an address */ const char* GetLabel (unsigned Addr, unsigned RefFrom); /* Return the label name for an address, as it is used in a label reference. ** RefFrom is the address the label is referenced from. This is needed in case ** of unnamed labels, to determine the name. */ void ForwardLabel (unsigned Offs); /* If necessary, output a forward label, one that is within the next few ** bytes and is therefore output as "label = * + x". */ void DefOutOfRangeLabels (void); /* Output any labels that are out of the loaded code range */ /* End of labels.h */ #endif ���������������������cc65-2.18/src/da65/main.c���������������������������������������������������������������������������0000664�0000000�0000000�00000045433�13473601511�0014634�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* main.c */ /* */ /* Main program for the da65 disassembler */ /* */ /* */ /* */ /* (C) 1998-2014, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <limits.h> #include <time.h> /* common */ #include "abend.h" #include "cmdline.h" #include "cpu.h" #include "fname.h" #include "print.h" #include "version.h" /* da65 */ #include "attrtab.h" #include "code.h" #include "comments.h" #include "data.h" #include "error.h" #include "global.h" #include "infofile.h" #include "labels.h" #include "opctable.h" #include "output.h" #include "scanner.h" #include "segment.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void Usage (void) /* Print usage information and exit */ { printf ("Usage: %s [options] [inputfile]\n" "Short options:\n" " -g\t\t\tAdd debug info to object file\n" " -h\t\t\tHelp (this text)\n" " -i name\t\tSpecify an info file\n" " -o name\t\tName the output file\n" " -v\t\t\tIncrease verbosity\n" " -F\t\t\tAdd formfeeds to the output\n" " -S addr\t\tSet the start/load address\n" " -s\t\t\tAccept line markers in the info file\n" " -V\t\t\tPrint the disassembler version\n" "\n" "Long options:\n" " --argument-column n\tSpecify argument start column\n" " --comment-column n\tSpecify comment start column\n" " --comments n\t\tSet the comment level for the output\n" " --cpu type\t\tSet cpu type\n" " --debug-info\t\tAdd debug info to object file\n" " --formfeeds\t\tAdd formfeeds to the output\n" " --help\t\tHelp (this text)\n" " --hexoffs\t\tUse hexadecimal label offsets\n" " --info name\t\tSpecify an info file\n" " --label-break n\tAdd newline if label exceeds length n\n" " --mnemonic-column n\tSpecify mnemonic start column\n" " --pagelength n\tSet the page length for the listing\n" " --start-addr addr\tSet the start/load address\n" " --sync-lines\t\tAccept line markers in the info file\n" " --text-column n\tSpecify text start column\n" " --verbose\t\tIncrease verbosity\n" " --version\t\tPrint the disassembler version\n", ProgName); } static void RangeCheck (const char* Opt, unsigned long Val, unsigned long Min, unsigned long Max) /* Do a range check for the given option and abort if there's a range ** error. */ { if (Val < Min || Val > Max) { Error ("Argument for %s outside valid range (%ld-%ld)", Opt, Min, Max); } } static unsigned long CvtNumber (const char* Arg, const char* Number) /* Convert a number from a string. Allow '$' and '0x' prefixes for hex ** numbers. */ { unsigned long Val; int Converted; char BoundsCheck; /* Convert */ if (*Number == '$') { ++Number; Converted = sscanf (Number, "%lx%c", &Val, &BoundsCheck); } else { Converted = sscanf (Number, "%li%c", (long*)&Val, &BoundsCheck); } /* Check if we do really have a number */ if (Converted != 1) { Error ("Invalid number given in argument: %s\n", Arg); } /* Return the result */ return Val; } static void OptArgumentColumn (const char* Opt, const char* Arg) /* Handle the --argument-column option */ { /* Convert the argument to a number */ unsigned long Val = CvtNumber (Opt, Arg); /* Check for a valid range */ RangeCheck (Opt, Val, MIN_ACOL, MAX_ACOL); /* Use the value */ ACol = (unsigned char) Val; } static void OptBytesPerLine (const char* Opt, const char* Arg) /* Handle the --bytes-per-line option */ { /* Convert the argument to a number */ unsigned long Val = CvtNumber (Opt, Arg); /* Check for a valid range */ RangeCheck (Opt, Val, MIN_BYTESPERLINE, MAX_BYTESPERLINE); /* Use the value */ BytesPerLine = (unsigned char) Val; } static void OptCommentColumn (const char* Opt, const char* Arg) /* Handle the --comment-column option */ { /* Convert the argument to a number */ unsigned long Val = CvtNumber (Opt, Arg); /* Check for a valid range */ RangeCheck (Opt, Val, MIN_CCOL, MAX_CCOL); /* Use the value */ CCol = (unsigned char) Val; } static void OptComments (const char* Opt, const char* Arg) /* Handle the --comments option */ { /* Convert the argument to a number */ unsigned long Val = CvtNumber (Opt, Arg); /* Check for a valid range */ RangeCheck (Opt, Val, MIN_COMMENTS, MAX_COMMENTS); /* Use the value */ Comments = (unsigned char) Val; } static void OptCPU (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --cpu option */ { /* Find the CPU from the given name */ CPU = FindCPU (Arg); SetOpcTable (CPU); } static void OptDebugInfo (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Add debug info to the object file */ { DebugInfo = 1; } static void OptFormFeeds (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Add form feeds to the output */ { FormFeeds = 1; } static void OptHelp (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Print usage information and exit */ { Usage (); exit (EXIT_SUCCESS); } static void OptHexOffs (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Handle the --hexoffs option */ { UseHexOffs = 1; } static void OptInfo (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --info option */ { InfoSetName (Arg); } static void OptLabelBreak (const char* Opt, const char* Arg) /* Handle the --label-break option */ { /* Convert the argument to a number */ unsigned long Val = CvtNumber (Opt, Arg); /* Check for a valid range */ RangeCheck (Opt, Val, MIN_LABELBREAK, MAX_LABELBREAK); /* Use the value */ LBreak = (unsigned char) Val; } static void OptMnemonicColumn (const char* Opt, const char* Arg) /* Handle the --mnemonic-column option */ { /* Convert the argument to a number */ unsigned long Val = CvtNumber (Opt, Arg); /* Check for a valid range */ RangeCheck (Opt, Val, MIN_MCOL, MAX_MCOL); /* Use the value */ MCol = (unsigned char) Val; } static void OptPageLength (const char* Opt attribute ((unused)), const char* Arg) /* Handle the --pagelength option */ { int Len = atoi (Arg); if (Len != 0) { RangeCheck (Opt, Len, MIN_PAGE_LEN, MAX_PAGE_LEN); } PageLength = Len; } static void OptStartAddr (const char* Opt, const char* Arg) /* Set the default start address */ { StartAddr = CvtNumber (Opt, Arg); } static void OptSyncLines (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Handle the --sync-lines option */ { SyncLines = 1; } static void OptTextColumn (const char* Opt, const char* Arg) /* Handle the --text-column option */ { /* Convert the argument to a number */ unsigned long Val = CvtNumber (Opt, Arg); /* Check for a valid range */ RangeCheck (Opt, Val, MIN_TCOL, MAX_TCOL); /* Use the value */ TCol = (unsigned char) Val; } static void OptVerbose (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Increase verbosity */ { ++Verbosity; } static void OptVersion (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Print the disassembler version */ { fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ()); exit(EXIT_SUCCESS); } static void OneOpcode (unsigned RemainingBytes) /* Disassemble one opcode */ { unsigned I; unsigned OldPC = PC; /* Get the opcode from the current address */ unsigned char OPC = GetCodeByte (PC); /* Get the opcode description for the opcode byte */ const OpcDesc* D = &OpcTable[OPC]; /* 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. */ if (Style != atSkip && MustDefLabel (PC)) { const char* Comment = GetComment (PC); if (Comment) { UserComment (Comment); } DefLabel (GetLabelName (PC)); } /* Check... ** - ...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 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) { Style = atIllegal; MarkAddr (PC, Style); } else if (D->Flags & flIllegal) { Style = atIllegal; MarkAddr (PC, Style); } else { 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; } } } } /* Disassemble the line */ switch (Style) { case atDefault: D->Handler (D); PC += D->Size; break; case atCode: /* Beware: If we don't have enough bytes left to disassemble the ** following insn, fall through to byte mode. */ if (D->Size <= RemainingBytes) { /* Output labels within the next insn */ for (I = 1; I < D->Size; ++I) { ForwardLabel (I); } /* Output the insn */ D->Handler (D); PC += D->Size; break; } /* FALLTHROUGH */ case atByteTab: ByteTable (); break; case atDByteTab: DByteTable (); break; case atWordTab: WordTable (); break; case atDWordTab: DWordTable (); break; case atAddrTab: AddrTable (); break; case atRtsTab: RtsTable (); break; case atTextTab: TextTable (); break; case atSkip: ++PC; break; default: DataByteLine (1); ++PC; break; } /* Change back to the default CODE segment if ** a named segment stops at the current address. */ for (I = PC - OldPC; I > 0; --I) { if (IsSegmentEnd (PC - I)) { EndSegment (); break; } } } static void OnePass (void) /* Make one pass through the code */ { unsigned Count; /* Disassemble until nothing left */ while ((Count = GetRemainingBytes()) > 0) { OneOpcode (Count); } } static void Disassemble (void) /* Disassemble the code */ { /* Pass 1 */ Pass = 1; OnePass (); Output ("---------------------------"); LineFeed (); /* Pass 2 */ Pass = 2; ResetCode (); OutputSettings (); DefOutOfRangeLabels (); OnePass (); } int main (int argc, char* argv []) /* Assembler main program */ { /* Program long options */ static const LongOpt OptTab[] = { { "--argument-column", 1, OptArgumentColumn }, { "--bytes-per-line", 1, OptBytesPerLine }, { "--comment-column", 1, OptCommentColumn }, { "--comments", 1, OptComments }, { "--cpu", 1, OptCPU }, { "--debug-info", 0, OptDebugInfo }, { "--formfeeds", 0, OptFormFeeds }, { "--help", 0, OptHelp }, { "--hexoffs", 0, OptHexOffs }, { "--info", 1, OptInfo }, { "--label-break", 1, OptLabelBreak }, { "--mnemonic-column", 1, OptMnemonicColumn }, { "--pagelength", 1, OptPageLength }, { "--start-addr", 1, OptStartAddr }, { "--sync-lines", 0, OptSyncLines }, { "--text-column", 1, OptTextColumn }, { "--verbose", 0, OptVerbose }, { "--version", 0, OptVersion }, }; unsigned I; time_t T; /* Initialize the cmdline module */ InitCmdLine (&argc, &argv, "da65"); /* Check the parameters */ I = 1; while (I < ArgCount) { /* Get the argument */ const char* Arg = ArgVec[I]; /* Check for an option */ if (Arg [0] == '-') { switch (Arg [1]) { case '-': LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0])); break; case 'g': OptDebugInfo (Arg, 0); break; case 'h': OptHelp (Arg, 0); break; case 'i': OptInfo (Arg, GetArg (&I, 2)); break; case 'o': OutFile = GetArg (&I, 2); break; case 'v': OptVerbose (Arg, 0); break; case 'S': OptStartAddr (Arg, GetArg (&I, 2)); break; case 's': OptSyncLines (Arg, 0); break; case 'V': OptVersion (Arg, 0); break; default: UnknownOption (Arg); break; } } else { /* Filename. Check if we already had one */ if (InFile) { fprintf (stderr, "%s: Don't know what to do with '%s'\n", ProgName, Arg); exit (EXIT_FAILURE); } else { InFile = Arg; } } /* Next argument */ ++I; } /* Try to read the info file */ ReadInfoFile (); /* Must have an input file */ if (InFile == 0) { AbEnd ("No input file"); } /* Check the formatting options for reasonable values. Note: We will not ** really check that they make sense, just that they aren't complete ** garbage. */ if (MCol >= ACol) { AbEnd ("mnemonic-column value must be smaller than argument-column value"); } if (ACol >= CCol) { AbEnd ("argument-column value must be smaller than comment-column value"); } if (CCol >= TCol) { AbEnd ("comment-column value must be smaller than text-column value"); } /* If no CPU given, use the default CPU */ if (CPU == CPU_UNKNOWN) { CPU = CPU_6502; } /* Get the current time and convert it to string so it can be used in ** the output page headers. */ T = time (0); strftime (Now, sizeof (Now), "%Y-%m-%d %H:%M:%S", localtime (&T)); /* Load the input file */ LoadCode (); /* Open the output file */ OpenOutput (OutFile); /* Disassemble the code */ Disassemble (); /* Close the output file */ CloseOutput (); /* Done */ return EXIT_SUCCESS; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/opc4510.c������������������������������������������������������������������������0000664�0000000�0000000�00000061571�13473601511�0015004�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* opc4510.c */ /* */ /* 4510 opcode description table */ /* */ /* */ /* */ /* (C) 2003-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* da65 */ #include "handler.h" #include "opc4510.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Descriptions for all opcodes */ const OpcDesc OpcTable_4510[256] = { { "brk", 1, flNone, OH_Implicit }, /* $00 */ { "ora", 2, flUseLabel, OH_DirectXIndirect }, /* $01 */ { "cle", 1, flNone, OH_Implicit }, /* $02 */ { "see", 1, flNone, OH_Implicit }, /* $03 */ { "tsb", 2, flUseLabel, OH_Direct }, /* $04 */ { "ora", 2, flUseLabel, OH_Direct }, /* $05 */ { "asl", 2, flUseLabel, OH_Direct }, /* $06 */ { "rmb0", 2, flUseLabel, OH_Direct }, /* $07 */ { "php", 1, flNone, OH_Implicit }, /* $08 */ { "ora", 2, flNone, OH_Immediate }, /* $09 */ { "asl", 1, flNone, OH_Accumulator }, /* $0a */ { "tsy", 1, flNone, OH_Implicit }, /* $0b */ { "tsb", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0c */ { "ora", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0d */ { "asl", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0e */ { "bbr0", 3, flUseLabel, OH_BitBranch }, /* $0f */ { "bpl", 2, flLabel, OH_Relative }, /* $10 */ { "ora", 2, flUseLabel, OH_DirectIndirectY }, /* $11 */ { "ora", 2, flUseLabel, OH_DirectIndirectZ }, /* $12 */ { "lbpl", 3, flLabel, OH_RelativeLong4510 }, /* $13 */ { "trb", 2, flUseLabel, OH_Direct }, /* $14 */ { "ora", 2, flUseLabel, OH_DirectX }, /* $15 */ { "asl", 2, flUseLabel, OH_DirectX }, /* $16 */ { "rmb1", 2, flUseLabel, OH_Direct }, /* $17 */ { "clc", 1, flNone, OH_Implicit }, /* $18 */ { "ora", 3, flUseLabel, OH_AbsoluteY }, /* $19 */ { "inc", 1, flNone, OH_Accumulator }, /* $1a */ { "inz", 1, flNone, OH_Implicit }, /* $1b */ { "trb", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $1c */ { "ora", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1d */ { "asl", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1e */ { "bbr1", 3, flUseLabel, OH_BitBranch }, /* $1f */ { "jsr", 3, flLabel, OH_Absolute }, /* $20 */ { "and", 2, flUseLabel, OH_DirectXIndirect }, /* $21 */ { "jsr", 3, flLabel, OH_JmpAbsoluteIndirect }, /* $22 */ { "jsr", 3, flLabel, OH_JmpAbsoluteXIndirect }, /* $23 */ { "bit", 2, flUseLabel, OH_Direct }, /* $24 */ { "and", 2, flUseLabel, OH_Direct }, /* $25 */ { "rol", 2, flUseLabel, OH_Direct }, /* $26 */ { "rmb2", 2, flUseLabel, OH_Direct }, /* $27 */ { "plp", 1, flNone, OH_Implicit }, /* $28 */ { "and", 2, flNone, OH_Immediate }, /* $29 */ { "rol", 1, flNone, OH_Accumulator }, /* $2a */ { "tys", 1, flNone, OH_Implicit }, /* $2b */ { "bit", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2c */ { "and", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2d */ { "rol", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2e */ { "bbr2", 3, flUseLabel, OH_BitBranch }, /* $2f */ { "bmi", 2, flLabel, OH_Relative }, /* $30 */ { "and", 2, flUseLabel, OH_DirectIndirectY }, /* $31 */ { "and", 2, flUseLabel, OH_DirectIndirectZ }, /* $32 */ { "lbmi", 3, flLabel, OH_RelativeLong4510 }, /* $33 */ { "bit", 2, flUseLabel, OH_DirectX }, /* $34 */ { "and", 2, flUseLabel, OH_DirectX }, /* $35 */ { "rol", 2, flUseLabel, OH_DirectX }, /* $36 */ { "rmb3", 2, flUseLabel, OH_Direct }, /* $37 */ { "sec", 1, flNone, OH_Implicit }, /* $38 */ { "and", 3, flUseLabel, OH_AbsoluteY }, /* $39 */ { "dec", 1, flNone, OH_Accumulator }, /* $3a */ { "dez", 1, flNone, OH_Implicit }, /* $3b */ { "bit", 3, flUseLabel, OH_AbsoluteX }, /* $3c */ { "and", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $3d */ { "rol", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $3e */ { "bbr3", 3, flUseLabel, OH_BitBranch }, /* $3f */ { "rti", 1, flNone, OH_Rts }, /* $40 */ { "eor", 2, flUseLabel, OH_DirectXIndirect }, /* $41 */ { "neg", 1, flNone, OH_Implicit }, /* $42 */ { "asr", 1, flNone, OH_Accumulator }, /* $43 */ { "asr", 2, flUseLabel, OH_Direct }, /* $44 */ { "eor", 2, flUseLabel, OH_Direct }, /* $45 */ { "lsr", 2, flUseLabel, OH_Direct }, /* $46 */ { "rmb4", 2, flUseLabel, OH_Direct }, /* $47 */ { "pha", 1, flNone, OH_Implicit }, /* $48 */ { "eor", 2, flNone, OH_Immediate }, /* $49 */ { "lsr", 1, flNone, OH_Accumulator }, /* $4a */ { "taz", 1, flNone, OH_Implicit }, /* $4b */ { "jmp", 3, flLabel, OH_JmpAbsolute }, /* $4c */ { "eor", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $4d */ { "lsr", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $4e */ { "bbr4", 3, flUseLabel, OH_BitBranch }, /* $4f */ { "bvc", 2, flLabel, OH_Relative }, /* $50 */ { "eor", 2, flUseLabel, OH_DirectIndirectY }, /* $51 */ { "eor", 2, flUseLabel, OH_DirectIndirectZ }, /* $52 */ { "lbvc", 3, flLabel, OH_RelativeLong4510 }, /* $53 */ { "asr", 2, flUseLabel, OH_DirectX }, /* $54 */ { "eor", 2, flUseLabel, OH_DirectX }, /* $55 */ { "lsr", 2, flUseLabel, OH_DirectX }, /* $56 */ { "rmb5", 2, flUseLabel, OH_Direct }, /* $57 */ { "cli", 1, flNone, OH_Implicit }, /* $58 */ { "eor", 3, flUseLabel, OH_AbsoluteY }, /* $59 */ { "phy", 1, flNone, OH_Implicit }, /* $5a */ { "tab", 1, flNone, OH_Implicit }, /* $5b */ { "map", 1, flNone, OH_Implicit }, /* $5c */ { "eor", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $5d */ { "lsr", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $5e */ { "bbr5", 3, flUseLabel, OH_BitBranch }, /* $5f */ { "rts", 1, flNone, OH_Rts }, /* $60 */ { "adc", 2, flUseLabel, OH_DirectXIndirect }, /* $61 */ { "rtn", 2, flNone, OH_Immediate }, /* $62 */ { "bsr", 3, flLabel, OH_RelativeLong4510 }, /* $63 */ { "stz", 2, flUseLabel, OH_Direct }, /* $64 */ { "adc", 2, flUseLabel, OH_Direct }, /* $65 */ { "ror", 2, flUseLabel, OH_Direct }, /* $66 */ { "rmb6", 2, flUseLabel, OH_Direct, }, /* $67 */ { "pla", 1, flNone, OH_Implicit }, /* $68 */ { "adc", 2, flNone, OH_Immediate }, /* $69 */ { "ror", 1, flNone, OH_Accumulator }, /* $6a */ { "tza", 1, flNone, OH_Implicit }, /* $6b */ { "jmp", 3, flLabel, OH_JmpAbsoluteIndirect }, /* $6c */ { "adc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $6d */ { "ror", 3, flUseLabel, OH_Absolute }, /* $6e */ { "bbr6", 3, flUseLabel, OH_BitBranch }, /* $6f */ { "bvs", 2, flLabel, OH_Relative }, /* $70 */ { "adc", 2, flUseLabel, OH_DirectIndirectY }, /* $71 */ { "adc", 2, flUseLabel, OH_DirectIndirectZ }, /* $72 */ { "lbvs", 3, flLabel, OH_RelativeLong4510 }, /* $73 */ { "stz", 2, flUseLabel, OH_DirectX }, /* $74 */ { "adc", 2, flUseLabel, OH_DirectX }, /* $75 */ { "ror", 2, flUseLabel, OH_DirectX }, /* $76 */ { "rmb7", 2, flUseLabel, OH_Direct }, /* $77 */ { "sei", 1, flNone, OH_Implicit }, /* $78 */ { "adc", 3, flUseLabel, OH_AbsoluteY }, /* $79 */ { "ply", 1, flNone, OH_Implicit }, /* $7a */ { "tba", 1, flNone, OH_Implicit }, /* $7b */ { "jmp", 3, flLabel, OH_AbsoluteXIndirect }, /* $7c */ { "adc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $7d */ { "ror", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $7e */ { "bbr7", 3, flUseLabel, OH_BitBranch }, /* $7f */ { "bra", 2, flLabel, OH_Relative }, /* $80 */ { "sta", 2, flUseLabel, OH_DirectXIndirect }, /* $81 */ { "sta", 2, flNone, OH_StackRelativeIndirectY4510}, /* $82 */ { "lbra", 3, flLabel, OH_RelativeLong4510 }, /* $83 */ { "sty", 2, flUseLabel, OH_Direct }, /* $84 */ { "sta", 2, flUseLabel, OH_Direct }, /* $85 */ { "stx", 2, flUseLabel, OH_Direct }, /* $86 */ { "smb0", 2, flUseLabel, OH_Direct }, /* $87 */ { "dey", 1, flNone, OH_Implicit }, /* $88 */ { "bit", 2, flNone, OH_Immediate }, /* $89 */ { "txa", 1, flNone, OH_Implicit }, /* $8a */ { "sty", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $8b */ { "sty", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8c */ { "sta", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8d */ { "stx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8e */ { "bbs0", 3, flUseLabel, OH_BitBranch }, /* $8f */ { "bcc", 2, flLabel, OH_Relative }, /* $90 */ { "sta", 2, flUseLabel, OH_DirectIndirectY }, /* $91 */ { "sta", 2, flUseLabel, OH_DirectIndirectZ }, /* $92 */ { "lbcc", 3, flLabel, OH_RelativeLong4510 }, /* $93 */ { "sty", 2, flUseLabel, OH_DirectX }, /* $94 */ { "sta", 2, flUseLabel, OH_DirectX }, /* $95 */ { "stx", 2, flUseLabel, OH_DirectY }, /* $96 */ { "smb1", 2, flUseLabel, OH_Direct }, /* $97 */ { "tya", 1, flNone, OH_Implicit }, /* $98 */ { "sta", 3, flUseLabel, OH_AbsoluteY }, /* $99 */ { "txs", 1, flNone, OH_Implicit }, /* $9a */ { "stx", 3, flUseLabel|flAbsOverride, OH_AbsoluteY }, /* $9b */ { "stz", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $9c */ { "sta", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $9d */ { "stz", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $9e */ { "bbs1", 3, flUseLabel, OH_BitBranch }, /* $9f */ { "ldy", 2, flNone, OH_Immediate }, /* $a0 */ { "lda", 2, flUseLabel, OH_DirectXIndirect }, /* $a1 */ { "ldx", 2, flNone, OH_Immediate }, /* $a2 */ { "ldz", 2, flNone, OH_Immediate }, /* $a3 */ { "ldy", 2, flUseLabel, OH_Direct }, /* $a4 */ { "lda", 2, flUseLabel, OH_Direct }, /* $a5 */ { "ldx", 2, flUseLabel, OH_Direct }, /* $a6 */ { "smb2", 2, flUseLabel, OH_Direct }, /* $a7 */ { "tay", 1, flNone, OH_Implicit }, /* $a8 */ { "lda", 2, flNone, OH_Immediate }, /* $a9 */ { "tax", 1, flNone, OH_Implicit }, /* $aa */ { "ldz", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ab */ { "ldy", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ac */ { "lda", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ad */ { "ldx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ae */ { "bbs2", 3, flUseLabel, OH_BitBranch }, /* $af */ { "bcs", 2, flLabel, OH_Relative }, /* $b0 */ { "lda", 2, flUseLabel, OH_DirectIndirectY }, /* $b1 */ { "lda", 2, flUseLabel, OH_DirectIndirectZ }, /* $b2 */ { "lbcs", 3, flLabel, OH_RelativeLong4510 }, /* $b3 */ { "ldy", 2, flUseLabel, OH_DirectX }, /* $b4 */ { "lda", 2, flUseLabel, OH_DirectX }, /* $b5 */ { "ldx", 2, flUseLabel, OH_DirectY }, /* $b6 */ { "smb3", 2, flUseLabel, OH_Direct }, /* $b7 */ { "clv", 1, flNone, OH_Implicit }, /* $b8 */ { "lda", 3, flUseLabel, OH_AbsoluteY }, /* $b9 */ { "tsx", 1, flNone, OH_Implicit }, /* $ba */ { "ldz", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $bb */ { "ldy", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $bc */ { "lda", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $bd */ { "ldx", 3, flUseLabel|flAbsOverride, OH_AbsoluteY }, /* $be */ { "bbs3", 3, flUseLabel, OH_BitBranch }, /* $bf */ { "cpy", 2, flNone, OH_Immediate }, /* $c0 */ { "cmp", 2, flUseLabel, OH_DirectXIndirect }, /* $c1 */ { "cpz", 2, flNone, OH_Immediate }, /* $c2 */ { "dew", 2, flUseLabel, OH_Direct }, /* $c3 */ { "cpy", 2, flUseLabel, OH_Direct }, /* $c4 */ { "cmp", 2, flUseLabel, OH_Direct }, /* $c5 */ { "dec", 2, flUseLabel, OH_Direct }, /* $c6 */ { "smb4", 2, flUseLabel, OH_Direct }, /* $c7 */ { "iny", 1, flNone, OH_Implicit }, /* $c8 */ { "cmp", 2, flNone, OH_Immediate }, /* $c9 */ { "dex", 1, flNone, OH_Implicit }, /* $ca */ { "asw", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $cb */ { "cpy", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $cc */ { "cmp", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $cd */ { "dec", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ce */ { "bbs4", 3, flUseLabel, OH_BitBranch }, /* $cf */ { "bne", 2, flLabel, OH_Relative }, /* $d0 */ { "cmp", 2, flUseLabel, OH_DirectIndirectY }, /* $d1 */ { "cmp", 2, flUseLabel, OH_DirectIndirectZ }, /* $d2 */ { "lbne", 3, flLabel, OH_RelativeLong4510 }, /* $d3 */ { "cpz", 2, flUseLabel, OH_Direct }, /* $d4 */ { "cmp", 2, flUseLabel, OH_DirectX }, /* $d5 */ { "dec", 2, flUseLabel, OH_DirectX }, /* $d6 */ { "smb5", 2, flUseLabel, OH_Direct }, /* $d7 */ { "cld", 1, flNone, OH_Implicit }, /* $d8 */ { "cmp", 3, flUseLabel, OH_AbsoluteY }, /* $d9 */ { "phx", 1, flNone, OH_Implicit }, /* $da */ { "phz", 1, flNone, OH_Implicit }, /* $db */ { "cpz", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $dc */ { "cmp", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $dd */ { "dec", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $de */ { "bbs5", 3, flUseLabel, OH_BitBranch }, /* $df */ { "cpx", 2, flNone, OH_Immediate }, /* $e0 */ { "sbc", 2, flUseLabel, OH_DirectXIndirect }, /* $e1 */ { "lda", 2, flNone, OH_StackRelativeIndirectY4510}, /* $e2 */ { "inw", 2, flUseLabel, OH_Direct }, /* $e3 */ { "cpx", 2, flUseLabel, OH_Direct }, /* $e4 */ { "sbc", 2, flUseLabel, OH_Direct }, /* $e5 */ { "inc", 2, flUseLabel, OH_Direct }, /* $e6 */ { "smb6", 2, flUseLabel, OH_Direct }, /* $e7 */ { "inx", 1, flNone, OH_Implicit }, /* $e8 */ { "sbc", 2, flNone, OH_Immediate }, /* $e9 */ { "eom", 1, flNone, OH_Implicit }, /* $ea */ { "row", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $eb */ { "cpx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ec */ { "sbc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ed */ { "inc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ee */ { "bbs6", 3, flUseLabel, OH_BitBranch }, /* $ef */ { "beq", 2, flLabel, OH_Relative }, /* $f0 */ { "sbc", 2, flUseLabel, OH_DirectIndirectY }, /* $f1 */ { "sbc", 2, flUseLabel, OH_DirectIndirectZ }, /* $f2 */ { "lbeq", 3, flLabel, OH_RelativeLong4510 }, /* $f3 */ { "phw", 3, flNone, OH_ImmediateWord }, /* $f4 */ { "sbc", 2, flUseLabel, OH_DirectX }, /* $f5 */ { "inc", 2, flUseLabel, OH_DirectX }, /* $f6 */ { "smb7", 2, flUseLabel, OH_Direct }, /* $f7 */ { "sed", 1, flNone, OH_Implicit }, /* $f8 */ { "sbc", 3, flUseLabel, OH_AbsoluteY }, /* $f9 */ { "plx", 1, flNone, OH_Implicit }, /* $fa */ { "plz", 1, flNone, OH_Implicit }, /* $fb */ { "phw", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $fc */ { "sbc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fd */ { "inc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fe */ { "bbs7", 3, flUseLabel, OH_BitBranch }, /* $ff */ }; ���������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/opc4510.h������������������������������������������������������������������������0000664�0000000�0000000�00000005643�13473601511�0015007�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* opc4510.h */ /* */ /* 4510 opcode description table */ /* */ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef OPC4510_H #define OPC4510_H #include "opcdesc.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Descriptions for all opcodes */ extern const OpcDesc OpcTable_4510[256]; /* End of opc4510.h */ #endif ���������������������������������������������������������������������������������������������cc65-2.18/src/da65/opc6502.c������������������������������������������������������������������������0000664�0000000�0000000�00000057571�13473601511�0015014�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* opc6502.c */ /* */ /* 6502 opcode description table */ /* */ /* */ /* */ /* (C) 2003-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* da65 */ #include "handler.h" #include "opc6502.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Descriptions for all opcodes */ const OpcDesc OpcTable_6502[256] = { { "brk", 1, flNone, OH_Implicit }, /* $00 */ { "ora", 2, flUseLabel, OH_DirectXIndirect }, /* $01 */ { "", 1, flIllegal, OH_Illegal, }, /* $02 */ { "", 1, flIllegal, OH_Illegal, }, /* $03 */ { "", 1, flIllegal, OH_Illegal, }, /* $04 */ { "ora", 2, flUseLabel, OH_Direct }, /* $05 */ { "asl", 2, flUseLabel, OH_Direct }, /* $06 */ { "", 1, flIllegal, OH_Illegal, }, /* $07 */ { "php", 1, flNone, OH_Implicit }, /* $08 */ { "ora", 2, flNone, OH_Immediate }, /* $09 */ { "asl", 1, flNone, OH_Accumulator }, /* $0a */ { "", 1, flIllegal, OH_Illegal, }, /* $0b */ { "", 1, flIllegal, OH_Illegal, }, /* $0c */ { "ora", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0d */ { "asl", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0e */ { "", 1, flIllegal, OH_Illegal, }, /* $0f */ { "bpl", 2, flLabel, OH_Relative }, /* $10 */ { "ora", 2, flUseLabel, OH_DirectIndirectY }, /* $11 */ { "", 1, flIllegal, OH_Illegal, }, /* $12 */ { "", 1, flIllegal, OH_Illegal, }, /* $13 */ { "", 1, flIllegal, OH_Illegal, }, /* $14 */ { "ora", 2, flUseLabel, OH_DirectX }, /* $15 */ { "asl", 2, flUseLabel, OH_DirectX }, /* $16 */ { "", 1, flIllegal, OH_Illegal, }, /* $17 */ { "clc", 1, flNone, OH_Implicit }, /* $18 */ { "ora", 3, flUseLabel, OH_AbsoluteY }, /* $19 */ { "", 1, flIllegal, OH_Illegal, }, /* $1a */ { "", 1, flIllegal, OH_Illegal, }, /* $1b */ { "", 1, flIllegal, OH_Illegal, }, /* $1c */ { "ora", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1d */ { "asl", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1e */ { "", 1, flIllegal, OH_Illegal, }, /* $1f */ { "jsr", 3, flLabel, OH_JsrAbsolute }, /* $20 */ { "and", 2, flUseLabel, OH_DirectXIndirect }, /* $21 */ { "", 1, flIllegal, OH_Illegal, }, /* $22 */ { "", 1, flIllegal, OH_Illegal, }, /* $23 */ { "bit", 2, flUseLabel, OH_Direct }, /* $24 */ { "and", 2, flUseLabel, OH_Direct }, /* $25 */ { "rol", 2, flUseLabel, OH_Direct }, /* $26 */ { "", 1, flIllegal, OH_Illegal, }, /* $27 */ { "plp", 1, flNone, OH_Implicit }, /* $28 */ { "and", 2, flNone, OH_Immediate }, /* $29 */ { "rol", 1, flNone, OH_Accumulator }, /* $2a */ { "", 1, flIllegal, OH_Illegal, }, /* $2b */ { "bit", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2c */ { "and", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2d */ { "rol", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2e */ { "", 1, flIllegal, OH_Illegal, }, /* $2f */ { "bmi", 2, flLabel, OH_Relative }, /* $30 */ { "and", 2, flUseLabel, OH_DirectIndirectY }, /* $31 */ { "", 1, flIllegal, OH_Illegal, }, /* $32 */ { "", 1, flIllegal, OH_Illegal, }, /* $33 */ { "", 1, flIllegal, OH_Illegal, }, /* $34 */ { "and", 2, flUseLabel, OH_DirectX }, /* $35 */ { "rol", 2, flUseLabel, OH_DirectX }, /* $36 */ { "", 1, flIllegal, OH_Illegal, }, /* $37 */ { "sec", 1, flNone, OH_Implicit }, /* $38 */ { "and", 3, flUseLabel, OH_AbsoluteY }, /* $39 */ { "", 1, flIllegal, OH_Illegal, }, /* $3a */ { "", 1, flIllegal, OH_Illegal, }, /* $3b */ { "", 1, flIllegal, OH_Illegal, }, /* $3c */ { "and", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $3d */ { "rol", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $3e */ { "", 1, flIllegal, OH_Illegal, }, /* $3f */ { "rti", 1, flNone, OH_Rts }, /* $40 */ { "eor", 2, flUseLabel, OH_DirectXIndirect }, /* $41 */ { "", 1, flIllegal, OH_Illegal, }, /* $42 */ { "", 1, flIllegal, OH_Illegal, }, /* $43 */ { "", 1, flIllegal, OH_Illegal, }, /* $44 */ { "eor", 2, flUseLabel, OH_Direct }, /* $45 */ { "lsr", 2, flUseLabel, OH_Direct }, /* $46 */ { "", 1, flIllegal, OH_Illegal, }, /* $47 */ { "pha", 1, flNone, OH_Implicit }, /* $48 */ { "eor", 2, flNone, OH_Immediate }, /* $49 */ { "lsr", 1, flNone, OH_Accumulator }, /* $4a */ { "", 1, flIllegal, OH_Illegal, }, /* $4b */ { "jmp", 3, flLabel, OH_JmpAbsolute }, /* $4c */ { "eor", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $4d */ { "lsr", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $4e */ { "", 1, flIllegal, OH_Illegal, }, /* $4f */ { "bvc", 2, flLabel, OH_Relative }, /* $50 */ { "eor", 2, flUseLabel, OH_DirectIndirectY }, /* $51 */ { "", 1, flIllegal, OH_Illegal, }, /* $52 */ { "", 1, flIllegal, OH_Illegal, }, /* $53 */ { "", 1, flIllegal, OH_Illegal, }, /* $54 */ { "eor", 2, flUseLabel, OH_DirectX }, /* $55 */ { "lsr", 2, flUseLabel, OH_DirectX }, /* $56 */ { "", 1, flIllegal, OH_Illegal, }, /* $57 */ { "cli", 1, flNone, OH_Implicit }, /* $58 */ { "eor", 3, flUseLabel, OH_AbsoluteY }, /* $59 */ { "", 1, flIllegal, OH_Illegal, }, /* $5a */ { "", 1, flIllegal, OH_Illegal, }, /* $5b */ { "", 1, flIllegal, OH_Illegal, }, /* $5c */ { "eor", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $5d */ { "lsr", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $5e */ { "", 1, flIllegal, OH_Illegal, }, /* $5f */ { "rts", 1, flNone, OH_Rts }, /* $60 */ { "adc", 2, flUseLabel, OH_DirectXIndirect }, /* $61 */ { "", 1, flIllegal, OH_Illegal, }, /* $62 */ { "", 1, flIllegal, OH_Illegal, }, /* $63 */ { "", 1, flIllegal, OH_Illegal, }, /* $64 */ { "adc", 2, flUseLabel, OH_Direct }, /* $65 */ { "ror", 2, flUseLabel, OH_Direct }, /* $66 */ { "", 1, flIllegal, OH_Illegal, }, /* $67 */ { "pla", 1, flNone, OH_Implicit }, /* $68 */ { "adc", 2, flNone, OH_Immediate }, /* $69 */ { "ror", 1, flNone, OH_Accumulator }, /* $6a */ { "", 1, flIllegal, OH_Illegal, }, /* $6b */ { "jmp", 3, flLabel, OH_JmpAbsoluteIndirect }, /* $6c */ { "adc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $6d */ { "ror", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $6e */ { "", 1, flIllegal, OH_Illegal, }, /* $6f */ { "bvs", 2, flLabel, OH_Relative }, /* $70 */ { "adc", 2, flUseLabel, OH_DirectIndirectY }, /* $71 */ { "", 1, flIllegal, OH_Illegal, }, /* $72 */ { "", 1, flIllegal, OH_Illegal, }, /* $73 */ { "", 1, flIllegal, OH_Illegal, }, /* $74 */ { "adc", 2, flUseLabel, OH_DirectX }, /* $75 */ { "ror", 2, flUseLabel, OH_DirectX }, /* $76 */ { "", 1, flIllegal, OH_Illegal, }, /* $77 */ { "sei", 1, flNone, OH_Implicit }, /* $78 */ { "adc", 3, flUseLabel, OH_AbsoluteY }, /* $79 */ { "", 1, flIllegal, OH_Illegal, }, /* $7a */ { "", 1, flIllegal, OH_Illegal, }, /* $7b */ { "", 1, flIllegal, OH_Illegal, }, /* $7c */ { "adc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $7d */ { "ror", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $7e */ { "", 1, flIllegal, OH_Illegal, }, /* $7f */ { "", 1, flIllegal, OH_Illegal, }, /* $80 */ { "sta", 2, flUseLabel, OH_DirectXIndirect }, /* $81 */ { "", 1, flIllegal, OH_Illegal, }, /* $82 */ { "", 1, flIllegal, OH_Illegal, }, /* $83 */ { "sty", 2, flUseLabel, OH_Direct }, /* $84 */ { "sta", 2, flUseLabel, OH_Direct }, /* $85 */ { "stx", 2, flUseLabel, OH_Direct }, /* $86 */ { "", 1, flIllegal, OH_Illegal, }, /* $87 */ { "dey", 1, flNone, OH_Implicit }, /* $88 */ { "", 1, flIllegal, OH_Illegal, }, /* $89 */ { "txa", 1, flNone, OH_Implicit }, /* $8a */ { "", 1, flIllegal, OH_Illegal, }, /* $8b */ { "sty", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8c */ { "sta", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8d */ { "stx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8e */ { "", 1, flIllegal, OH_Illegal, }, /* $8f */ { "bcc", 2, flLabel, OH_Relative }, /* $90 */ { "sta", 2, flUseLabel, OH_DirectIndirectY }, /* $91 */ { "", 1, flIllegal, OH_Illegal, }, /* $92 */ { "", 1, flIllegal, OH_Illegal, }, /* $93 */ { "sty", 2, flUseLabel, OH_DirectX }, /* $94 */ { "sta", 2, flUseLabel, OH_DirectX }, /* $95 */ { "stx", 2, flUseLabel, OH_DirectY }, /* $96 */ { "", 1, flIllegal, OH_Illegal, }, /* $97 */ { "tya", 1, flNone, OH_Implicit }, /* $98 */ { "sta", 3, flUseLabel, OH_AbsoluteY }, /* $99 */ { "txs", 1, flNone, OH_Implicit }, /* $9a */ { "", 1, flIllegal, OH_Illegal, }, /* $9b */ { "", 1, flIllegal, OH_Illegal, }, /* $9c */ { "sta", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $9d */ { "", 1, flIllegal, OH_Illegal, }, /* $9e */ { "", 1, flIllegal, OH_Illegal, }, /* $9f */ { "ldy", 2, flNone, OH_Immediate }, /* $a0 */ { "lda", 2, flUseLabel, OH_DirectXIndirect }, /* $a1 */ { "ldx", 2, flNone, OH_Immediate }, /* $a2 */ { "", 1, flIllegal, OH_Illegal, }, /* $a3 */ { "ldy", 2, flUseLabel, OH_Direct }, /* $a4 */ { "lda", 2, flUseLabel, OH_Direct }, /* $a5 */ { "ldx", 2, flUseLabel, OH_Direct }, /* $a6 */ { "", 1, flIllegal, OH_Illegal, }, /* $a7 */ { "tay", 1, flNone, OH_Implicit }, /* $a8 */ { "lda", 2, flNone, OH_Immediate }, /* $a9 */ { "tax", 1, flNone, OH_Implicit }, /* $aa */ { "", 1, flIllegal, OH_Illegal, }, /* $ab */ { "ldy", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ac */ { "lda", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ad */ { "ldx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ae */ { "", 1, flIllegal, OH_Illegal, }, /* $af */ { "bcs", 2, flLabel, OH_Relative }, /* $b0 */ { "lda", 2, flUseLabel, OH_DirectIndirectY }, /* $b1 */ { "", 1, flIllegal, OH_Illegal, }, /* $b2 */ { "", 1, flIllegal, OH_Illegal, }, /* $b3 */ { "ldy", 2, flUseLabel, OH_DirectX }, /* $b4 */ { "lda", 2, flUseLabel, OH_DirectX }, /* $b5 */ { "ldx", 2, flUseLabel, OH_DirectY }, /* $b6 */ { "", 1, flIllegal, OH_Illegal, }, /* $b7 */ { "clv", 1, flNone, OH_Implicit }, /* $b8 */ { "lda", 3, flUseLabel, OH_AbsoluteY }, /* $b9 */ { "tsx", 1, flNone, OH_Implicit }, /* $ba */ { "", 1, flIllegal, OH_Illegal, }, /* $bb */ { "ldy", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $bc */ { "lda", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $bd */ { "ldx", 3, flUseLabel|flAbsOverride, OH_AbsoluteY }, /* $be */ { "", 1, flIllegal, OH_Illegal, }, /* $bf */ { "cpy", 2, flNone, OH_Immediate }, /* $c0 */ { "cmp", 2, flUseLabel, OH_DirectXIndirect }, /* $c1 */ { "", 1, flIllegal, OH_Illegal, }, /* $c2 */ { "", 1, flIllegal, OH_Illegal, }, /* $c3 */ { "cpy", 2, flUseLabel, OH_Direct }, /* $c4 */ { "cmp", 2, flUseLabel, OH_Direct }, /* $c5 */ { "dec", 2, flUseLabel, OH_Direct }, /* $c6 */ { "", 1, flIllegal, OH_Illegal, }, /* $c7 */ { "iny", 1, flNone, OH_Implicit }, /* $c8 */ { "cmp", 2, flNone, OH_Immediate }, /* $c9 */ { "dex", 1, flNone, OH_Implicit }, /* $ca */ { "", 1, flIllegal, OH_Illegal, }, /* $cb */ { "cpy", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $cc */ { "cmp", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $cd */ { "dec", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ce */ { "", 1, flIllegal, OH_Illegal, }, /* $cf */ { "bne", 2, flLabel, OH_Relative }, /* $d0 */ { "cmp", 2, flUseLabel, OH_DirectIndirectY }, /* $d1 */ { "", 1, flIllegal, OH_Illegal, }, /* $d2 */ { "", 1, flIllegal, OH_Illegal, }, /* $d3 */ { "", 1, flIllegal, OH_Illegal, }, /* $d4 */ { "cmp", 2, flUseLabel, OH_DirectX }, /* $d5 */ { "dec", 2, flUseLabel, OH_DirectX }, /* $d6 */ { "", 1, flIllegal, OH_Illegal, }, /* $d7 */ { "cld", 1, flNone, OH_Implicit }, /* $d8 */ { "cmp", 3, flUseLabel, OH_AbsoluteY }, /* $d9 */ { "", 1, flIllegal, OH_Illegal, }, /* $da */ { "", 1, flIllegal, OH_Illegal, }, /* $db */ { "", 1, flIllegal, OH_Illegal, }, /* $dc */ { "cmp", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $dd */ { "dec", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $de */ { "", 1, flIllegal, OH_Illegal, }, /* $df */ { "cpx", 2, flNone, OH_Immediate }, /* $e0 */ { "sbc", 2, flUseLabel, OH_DirectXIndirect }, /* $e1 */ { "", 1, flIllegal, OH_Illegal, }, /* $e2 */ { "", 1, flIllegal, OH_Illegal, }, /* $e3 */ { "cpx", 2, flUseLabel, OH_Direct }, /* $e4 */ { "sbc", 2, flUseLabel, OH_Direct }, /* $e5 */ { "inc", 2, flUseLabel, OH_Direct }, /* $e6 */ { "", 1, flIllegal, OH_Illegal, }, /* $e7 */ { "inx", 1, flNone, OH_Implicit }, /* $e8 */ { "sbc", 2, flNone, OH_Immediate }, /* $e9 */ { "nop", 1, flNone, OH_Implicit }, /* $ea */ { "", 1, flIllegal, OH_Illegal, }, /* $eb */ { "cpx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ec */ { "sbc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ed */ { "inc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ee */ { "", 1, flIllegal, OH_Illegal, }, /* $ef */ { "beq", 2, flLabel, OH_Relative }, /* $f0 */ { "sbc", 2, flUseLabel, OH_DirectIndirectY }, /* $f1 */ { "", 1, flIllegal, OH_Illegal, }, /* $f2 */ { "", 1, flIllegal, OH_Illegal, }, /* $f3 */ { "", 1, flIllegal, OH_Illegal, }, /* $f4 */ { "sbc", 2, flUseLabel, OH_DirectX }, /* $f5 */ { "inc", 2, flUseLabel, OH_DirectX }, /* $f6 */ { "", 1, flIllegal, OH_Illegal, }, /* $f7 */ { "sed", 1, flNone, OH_Implicit }, /* $f8 */ { "sbc", 3, flUseLabel, OH_AbsoluteY }, /* $f9 */ { "", 1, flIllegal, OH_Illegal, }, /* $fa */ { "", 1, flIllegal, OH_Illegal, }, /* $fb */ { "", 1, flIllegal, OH_Illegal, }, /* $fc */ { "sbc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fd */ { "inc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fe */ { "", 1, flIllegal, OH_Illegal, }, /* $ff */ }; ���������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/opc6502.h������������������������������������������������������������������������0000664�0000000�0000000�00000005643�13473601511�0015012�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* opc6502.h */ /* */ /* 6502 opcode description table */ /* */ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef OPC6502_H #define OPC6502_H #include "opcdesc.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Descriptions for all opcodes */ extern const OpcDesc OpcTable_6502[256]; /* End of opc6502.h */ #endif ���������������������������������������������������������������������������������������������cc65-2.18/src/da65/opc6502x.c�����������������������������������������������������������������������0000664�0000000�0000000�00000057734�13473601511�0015205�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* opc6502.c */ /* */ /* 6502 opcode description table with NMOS illegals */ /* */ /* */ /* */ /* (C) 2003-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* da65 */ #include "handler.h" #include "opc6502x.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Descriptions for all opcodes. Base table from opc6502.c with illegal ** opcodes from http://www.oxyron.de/html/opcodes02.html */ const OpcDesc OpcTable_6502X[256] = { { "brk", 1, flNone, OH_Implicit }, /* $00 */ { "ora", 2, flUseLabel, OH_DirectXIndirect }, /* $01 */ { "jam", 1, flNone, OH_Implicit }, /* $02 */ { "slo", 2, flUseLabel, OH_DirectXIndirect }, /* $03 */ { "nop", 2, flUseLabel, OH_Direct }, /* $04 */ { "ora", 2, flUseLabel, OH_Direct }, /* $05 */ { "asl", 2, flUseLabel, OH_Direct }, /* $06 */ { "slo", 2, flUseLabel, OH_Direct }, /* $07 */ { "php", 1, flNone, OH_Implicit }, /* $08 */ { "ora", 2, flNone, OH_Immediate }, /* $09 */ { "asl", 1, flNone, OH_Accumulator }, /* $0a */ { "anc", 2, flNone, OH_Immediate }, /* $0b */ { "nop", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0c */ { "ora", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0d */ { "asl", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0e */ { "slo", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0f */ { "bpl", 2, flLabel, OH_Relative }, /* $10 */ { "ora", 2, flUseLabel, OH_DirectIndirectY }, /* $11 */ { "jam", 1, flNone, OH_Implicit }, /* $12 */ { "slo", 2, flUseLabel, OH_DirectIndirectY }, /* $13 */ { "nop", 2, flUseLabel, OH_DirectX }, /* $14 */ { "ora", 2, flUseLabel, OH_DirectX }, /* $15 */ { "asl", 2, flUseLabel, OH_DirectX }, /* $16 */ { "slo", 2, flUseLabel, OH_DirectX }, /* $17 */ { "clc", 1, flNone, OH_Implicit }, /* $18 */ { "ora", 3, flUseLabel, OH_AbsoluteY }, /* $19 */ { "nop", 1, flNone, OH_Implicit }, /* $1a */ { "slo", 3, flUseLabel, OH_AbsoluteY }, /* $1b */ { "nop", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1c */ { "ora", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1d */ { "asl", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1e */ { "slo", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1f */ { "jsr", 3, flLabel, OH_Absolute }, /* $20 */ { "and", 2, flUseLabel, OH_DirectXIndirect }, /* $21 */ { "jam", 1, flNone, OH_Implicit, }, /* $22 */ { "rla", 2, flUseLabel, OH_DirectXIndirect }, /* $23 */ { "bit", 2, flUseLabel, OH_Direct }, /* $24 */ { "and", 2, flUseLabel, OH_Direct }, /* $25 */ { "rol", 2, flUseLabel, OH_Direct }, /* $26 */ { "rla", 2, flUseLabel, OH_Direct }, /* $27 */ { "plp", 1, flNone, OH_Implicit }, /* $28 */ { "and", 2, flNone, OH_Immediate }, /* $29 */ { "rol", 1, flNone, OH_Accumulator }, /* $2a */ { "anc", 2, flNone, OH_Immediate }, /* $2b */ { "bit", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2c */ { "and", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2d */ { "rol", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2e */ { "rla", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2f */ { "bmi", 2, flLabel, OH_Relative }, /* $30 */ { "and", 2, flUseLabel, OH_DirectIndirectY }, /* $31 */ { "jam", 1, flNone, OH_Implicit }, /* $32 */ { "rla", 2, flUseLabel, OH_DirectIndirectY }, /* $33 */ { "nop", 2, flUseLabel, OH_DirectX }, /* $34 */ { "and", 2, flUseLabel, OH_DirectX }, /* $35 */ { "rol", 2, flUseLabel, OH_DirectX }, /* $36 */ { "rla", 2, flUseLabel, OH_DirectX }, /* $37 */ { "sec", 1, flNone, OH_Implicit }, /* $38 */ { "and", 3, flUseLabel, OH_AbsoluteY }, /* $39 */ { "nop", 1, flNone, OH_Implicit }, /* $3a */ { "rla", 3, flUseLabel, OH_AbsoluteY }, /* $3b */ { "nop", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $3c */ { "and", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $3d */ { "rol", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $3e */ { "rla", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $3f */ { "rti", 1, flNone, OH_Rts }, /* $40 */ { "eor", 2, flUseLabel, OH_DirectXIndirect }, /* $41 */ { "jam", 1, flNone, OH_Implicit }, /* $42 */ { "sre", 2, flUseLabel, OH_DirectXIndirect }, /* $43 */ { "nop", 2, flUseLabel, OH_Direct }, /* $44 */ { "eor", 2, flUseLabel, OH_Direct }, /* $45 */ { "lsr", 2, flUseLabel, OH_Direct }, /* $46 */ { "sre", 2, flUseLabel, OH_Direct }, /* $47 */ { "pha", 1, flNone, OH_Implicit }, /* $48 */ { "eor", 2, flNone, OH_Immediate }, /* $49 */ { "lsr", 1, flNone, OH_Accumulator }, /* $4a */ { "alr", 2, flNone, OH_Immediate }, /* $4b */ { "jmp", 3, flLabel, OH_JmpAbsolute }, /* $4c */ { "eor", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $4d */ { "lsr", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $4e */ { "sre", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $4f */ { "bvc", 2, flLabel, OH_Relative }, /* $50 */ { "eor", 2, flUseLabel, OH_DirectIndirectY }, /* $51 */ { "jam", 1, flNone, OH_Implicit }, /* $52 */ { "sre", 2, flUseLabel, OH_DirectIndirectY }, /* $53 */ { "nop", 2, flUseLabel, OH_DirectX }, /* $54 */ { "eor", 2, flUseLabel, OH_DirectX }, /* $55 */ { "lsr", 2, flUseLabel, OH_DirectX }, /* $56 */ { "sre", 2, flUseLabel, OH_DirectX }, /* $57 */ { "cli", 1, flNone, OH_Implicit }, /* $58 */ { "eor", 3, flUseLabel, OH_AbsoluteY }, /* $59 */ { "nop", 1, flNone, OH_Implicit }, /* $5a */ { "sre", 3, flUseLabel, OH_AbsoluteY }, /* $5b */ { "nop", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $5c */ { "eor", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $5d */ { "lsr", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $5e */ { "sre", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $5f */ { "rts", 1, flNone, OH_Rts }, /* $60 */ { "adc", 2, flUseLabel, OH_DirectXIndirect }, /* $61 */ { "jam", 1, flNone, OH_Implicit }, /* $62 */ { "rra", 2, flUseLabel, OH_DirectXIndirect }, /* $63 */ { "nop", 2, flUseLabel, OH_Direct }, /* $64 */ { "adc", 2, flUseLabel, OH_Direct }, /* $65 */ { "ror", 2, flUseLabel, OH_Direct }, /* $66 */ { "rra", 2, flUseLabel, OH_Direct }, /* $67 */ { "pla", 1, flNone, OH_Implicit }, /* $68 */ { "adc", 2, flNone, OH_Immediate }, /* $69 */ { "ror", 1, flNone, OH_Accumulator }, /* $6a */ { "arr", 2, flNone, OH_Immediate }, /* $6b */ { "jmp", 3, flLabel, OH_JmpAbsoluteIndirect }, /* $6c */ { "adc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $6d */ { "ror", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $6e */ { "rra", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $6f */ { "bvs", 2, flLabel, OH_Relative }, /* $70 */ { "adc", 2, flUseLabel, OH_DirectIndirectY }, /* $71 */ { "jam", 1, flNone, OH_Implicit }, /* $72 */ { "rra", 2, flUseLabel, OH_DirectIndirectY }, /* $73 */ { "nop", 2, flUseLabel, OH_DirectX }, /* $74 */ { "adc", 2, flUseLabel, OH_DirectX }, /* $75 */ { "ror", 2, flUseLabel, OH_DirectX }, /* $76 */ { "rra", 2, flUseLabel, OH_DirectX }, /* $77 */ { "sei", 1, flNone, OH_Implicit }, /* $78 */ { "adc", 3, flUseLabel, OH_AbsoluteY }, /* $79 */ { "nop", 1, flNone, OH_Implicit }, /* $7a */ { "rra", 3, flUseLabel, OH_AbsoluteY }, /* $7b */ { "nop", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $7c */ { "adc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $7d */ { "ror", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $7e */ { "rra", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $7f */ { "nop", 2, flNone, OH_Immediate }, /* $80 */ { "sta", 2, flUseLabel, OH_DirectXIndirect }, /* $81 */ { "nop", 2, flNone, OH_Immediate }, /* $82 */ { "sax", 2, flUseLabel, OH_DirectXIndirect }, /* $83 */ { "sty", 2, flUseLabel, OH_Direct }, /* $84 */ { "sta", 2, flUseLabel, OH_Direct }, /* $85 */ { "stx", 2, flUseLabel, OH_Direct }, /* $86 */ { "sax", 2, flUseLabel, OH_Direct }, /* $87 */ { "dey", 1, flNone, OH_Implicit }, /* $88 */ { "nop", 2, flNone, OH_Immediate }, /* $89 */ { "txa", 1, flNone, OH_Implicit }, /* $8a */ { "xaa", 2, flNone, OH_Immediate }, /* $8b */ { "sty", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8c */ { "sta", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8d */ { "stx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8e */ { "sax", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8f */ { "bcc", 2, flLabel, OH_Relative }, /* $90 */ { "sta", 2, flUseLabel, OH_DirectIndirectY }, /* $91 */ { "jam", 1, flNone, OH_Implicit }, /* $92 */ { "ahx", 2, flUseLabel, OH_DirectIndirectY }, /* $93 */ { "sty", 2, flUseLabel, OH_DirectX }, /* $94 */ { "sta", 2, flUseLabel, OH_DirectX }, /* $95 */ { "stx", 2, flUseLabel, OH_DirectY }, /* $96 */ { "sax", 2, flUseLabel, OH_DirectY }, /* $97 */ { "tya", 1, flNone, OH_Implicit }, /* $98 */ { "sta", 3, flUseLabel, OH_AbsoluteY }, /* $99 */ { "txs", 1, flNone, OH_Implicit }, /* $9a */ { "tas", 3, flUseLabel, OH_AbsoluteY }, /* $9b */ { "shy", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $9c */ { "sta", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $9d */ { "shx", 3, flUseLabel, OH_AbsoluteY }, /* $9e */ { "ahx", 3, flUseLabel, OH_AbsoluteY }, /* $9f */ { "ldy", 2, flNone, OH_Immediate }, /* $a0 */ { "lda", 2, flUseLabel, OH_DirectXIndirect }, /* $a1 */ { "ldx", 2, flNone, OH_Immediate }, /* $a2 */ { "lax", 2, flUseLabel, OH_DirectXIndirect }, /* $a3 */ { "ldy", 2, flUseLabel, OH_Direct }, /* $a4 */ { "lda", 2, flUseLabel, OH_Direct }, /* $a5 */ { "ldx", 2, flUseLabel, OH_Direct }, /* $a6 */ { "lax", 2, flUseLabel, OH_Direct }, /* $a7 */ { "tay", 1, flNone, OH_Implicit }, /* $a8 */ { "lda", 2, flNone, OH_Immediate }, /* $a9 */ { "tax", 1, flNone, OH_Implicit }, /* $aa */ { "lax", 2, flNone, OH_Immediate }, /* $ab */ { "ldy", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ac */ { "lda", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ad */ { "ldx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ae */ { "lax", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $af */ { "bcs", 2, flLabel, OH_Relative }, /* $b0 */ { "lda", 2, flUseLabel, OH_DirectIndirectY }, /* $b1 */ { "jam", 1, flNone, OH_Implicit }, /* $b2 */ { "lax", 2, flUseLabel, OH_DirectIndirectY }, /* $b3 */ { "ldy", 2, flUseLabel, OH_DirectX }, /* $b4 */ { "lda", 2, flUseLabel, OH_DirectX }, /* $b5 */ { "ldx", 2, flUseLabel, OH_DirectY }, /* $b6 */ { "lax", 2, flUseLabel, OH_DirectY }, /* $b7 */ { "clv", 1, flNone, OH_Implicit }, /* $b8 */ { "lda", 3, flUseLabel, OH_AbsoluteY }, /* $b9 */ { "tsx", 1, flNone, OH_Implicit }, /* $ba */ { "las", 3, flUseLabel, OH_AbsoluteY }, /* $bb */ { "ldy", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $bc */ { "lda", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $bd */ { "ldx", 3, flUseLabel|flAbsOverride, OH_AbsoluteY }, /* $be */ { "lax", 3, flUseLabel|flAbsOverride, OH_AbsoluteY }, /* $bf */ { "cpy", 2, flNone, OH_Immediate }, /* $c0 */ { "cmp", 2, flUseLabel, OH_DirectXIndirect }, /* $c1 */ { "nop", 2, flNone, OH_Immediate }, /* $c2 */ { "dcp", 2, flUseLabel, OH_DirectXIndirect }, /* $c3 */ { "cpy", 2, flUseLabel, OH_Direct }, /* $c4 */ { "cmp", 2, flUseLabel, OH_Direct }, /* $c5 */ { "dec", 2, flUseLabel, OH_Direct }, /* $c6 */ { "dcp", 2, flUseLabel, OH_Direct }, /* $c7 */ { "iny", 1, flNone, OH_Implicit }, /* $c8 */ { "cmp", 2, flNone, OH_Immediate }, /* $c9 */ { "dex", 1, flNone, OH_Implicit }, /* $ca */ { "axs", 2, flNone, OH_Immediate }, /* $cb */ { "cpy", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $cc */ { "cmp", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $cd */ { "dec", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ce */ { "dcp", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $cf */ { "bne", 2, flLabel, OH_Relative }, /* $d0 */ { "cmp", 2, flUseLabel, OH_DirectIndirectY }, /* $d1 */ { "jam", 1, flNone, OH_Implicit }, /* $d2 */ { "dcp", 2, flUseLabel, OH_DirectIndirectY }, /* $d3 */ { "nop", 2, flUseLabel, OH_DirectX }, /* $d4 */ { "cmp", 2, flUseLabel, OH_DirectX }, /* $d5 */ { "dec", 2, flUseLabel, OH_DirectX }, /* $d6 */ { "dcp", 2, flUseLabel, OH_DirectX }, /* $d7 */ { "cld", 1, flNone, OH_Implicit }, /* $d8 */ { "cmp", 3, flUseLabel, OH_AbsoluteY }, /* $d9 */ { "nop", 1, flNone, OH_Implicit }, /* $da */ { "dcp", 3, flUseLabel, OH_AbsoluteY }, /* $db */ { "nop", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $dc */ { "cmp", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $dd */ { "dec", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $de */ { "dcp", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $df */ { "cpx", 2, flNone, OH_Immediate }, /* $e0 */ { "sbc", 2, flUseLabel, OH_DirectXIndirect }, /* $e1 */ { "nop", 2, flNone, OH_Immediate }, /* $e2 */ { "isc", 2, flUseLabel, OH_DirectXIndirect }, /* $e3 */ { "cpx", 2, flUseLabel, OH_Direct }, /* $e4 */ { "sbc", 2, flUseLabel, OH_Direct }, /* $e5 */ { "inc", 2, flUseLabel, OH_Direct }, /* $e6 */ { "isc", 2, flUseLabel, OH_Direct }, /* $e7 */ { "inx", 1, flNone, OH_Implicit }, /* $e8 */ { "sbc", 2, flNone, OH_Immediate }, /* $e9 */ { "nop", 1, flNone, OH_Implicit }, /* $ea */ { "sbc", 2, flNone, OH_Immediate }, /* $eb */ { "cpx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ec */ { "sbc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ed */ { "inc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ee */ { "isc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ef */ { "beq", 2, flLabel, OH_Relative }, /* $f0 */ { "sbc", 2, flUseLabel, OH_DirectIndirectY }, /* $f1 */ { "jam", 1, flNone, OH_Implicit }, /* $f2 */ { "isc", 2, flUseLabel, OH_DirectIndirectY }, /* $f3 */ { "nop", 2, flUseLabel, OH_DirectX }, /* $f4 */ { "sbc", 2, flUseLabel, OH_DirectX }, /* $f5 */ { "inc", 2, flUseLabel, OH_DirectX }, /* $f6 */ { "isc", 2, flUseLabel, OH_DirectX }, /* $f7 */ { "sed", 1, flNone, OH_Implicit }, /* $f8 */ { "sbc", 3, flUseLabel, OH_AbsoluteY }, /* $f9 */ { "nop", 1, flNone, OH_Implicit }, /* $fa */ { "isc", 3, flUseLabel, OH_AbsoluteY }, /* $fb */ { "nop", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fc */ { "sbc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fd */ { "inc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fe */ { "isc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $ff */ }; ������������������������������������cc65-2.18/src/da65/opc6502x.h�����������������������������������������������������������������������0000664�0000000�0000000�00000005674�13473601511�0015206�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* opc6502.h */ /* */ /* 6502 opcode description table with NMOS illegals */ /* */ /* */ /* */ /* (C) 2003-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef OPC6502X_H #define OPC6502X_H #include "opcdesc.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Descriptions for all opcodes */ extern const OpcDesc OpcTable_6502X[256]; /* End of opc6502x.h */ #endif ��������������������������������������������������������������������cc65-2.18/src/da65/opc65816.c�����������������������������������������������������������������������0000664�0000000�0000000�00000057573�13473601511�0015113�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* opc65816.c */ /* */ /* 65816 opcode description table */ /* */ /* */ /* */ /* (C) 2003-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* da65 */ #include "handler.h" #include "opc65816.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Descriptions for all opcodes */ const OpcDesc OpcTable_65816[256] = { { "brk", 1, flNone, OH_Implicit }, /* $00 */ { "ora", 2, flUseLabel, OH_DirectXIndirect }, /* $01 */ { "cop", 2, flNone, OH_Implicit }, /* $02 */ { "ora", 2, flNone, OH_StackRelative }, /* $03 */ { "tsb", 2, flUseLabel, OH_Direct }, /* $04 */ { "ora", 2, flUseLabel, OH_Direct }, /* $05 */ { "asl", 2, flUseLabel, OH_Direct }, /* $06 */ { "ora", 2, flUseLabel, OH_DirectIndirectLong }, /* $07 */ { "php", 1, flNone, OH_Implicit }, /* $08 */ { "ora", 2, flNone, OH_Immediate }, /* $09 */ { "asl", 1, flNone, OH_Accumulator }, /* $0a */ { "phd", 1, flNone, OH_Implicit }, /* $0b */ { "tsb", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0c */ { "ora", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0d */ { "asl", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0e */ { "ora", 4, flUseLabel, OH_AbsoluteLong }, /* $0f */ { "bpl", 2, flLabel, OH_Relative }, /* $10 */ { "ora", 2, flUseLabel, OH_DirectIndirectY }, /* $11 */ { "ora", 2, flUseLabel, OH_DirectIndirect }, /* $12 */ { "ora", 2, flNone, OH_StackRelativeIndirectY}, /* $13 */ { "trb", 2, flUseLabel, OH_Direct }, /* $14 */ { "ora", 2, flUseLabel, OH_DirectX }, /* $15 */ { "asl", 2, flUseLabel, OH_DirectX }, /* $16 */ { "ora", 2, flUseLabel, OH_DirectIndirectLongY }, /* $17 */ { "clc", 1, flNone, OH_Implicit }, /* $18 */ { "ora", 3, flUseLabel, OH_AbsoluteY }, /* $19 */ { "inc", 1, flNone, OH_Accumulator }, /* $1a */ { "tcs", 1, flNone, OH_Implicit }, /* $1b */ { "trb", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $1c */ { "ora", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1d */ { "asl", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1e */ { "ora", 4, flUseLabel, OH_AbsoluteLongX }, /* $1f */ { "jsr", 3, flLabel, OH_JsrAbsolute }, /* $20 */ { "and", 2, flUseLabel, OH_DirectXIndirect }, /* $21 */ { "jsl", 3, flLabel, OH_AbsoluteLong }, /* $22 */ { "and", 2, flNone, OH_StackRelative }, /* $23 */ { "bit", 2, flUseLabel, OH_Direct }, /* $24 */ { "and", 2, flUseLabel, OH_Direct }, /* $25 */ { "rol", 2, flUseLabel, OH_Direct }, /* $26 */ { "and", 2, flUseLabel, OH_DirectIndirectLong }, /* $27 */ { "plp", 1, flNone, OH_Implicit }, /* $28 */ { "and", 2, flNone, OH_Immediate }, /* $29 */ { "rol", 1, flNone, OH_Accumulator }, /* $2a */ { "pld", 1, flNone, OH_Implicit }, /* $2b */ { "bit", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2c */ { "and", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2d */ { "rol", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2e */ { "and", 4, flUseLabel, OH_AbsoluteLong }, /* $2f */ { "bmi", 2, flLabel, OH_Relative }, /* $30 */ { "and", 2, flUseLabel, OH_DirectIndirectY }, /* $31 */ { "and", 2, flUseLabel, OH_DirectIndirect }, /* $32 */ { "and", 2, flNone, OH_StackRelativeIndirectY}, /* $33 */ { "bit", 2, flUseLabel, OH_DirectX }, /* $34 */ { "and", 2, flUseLabel, OH_DirectX }, /* $35 */ { "rol", 2, flUseLabel, OH_DirectX }, /* $36 */ { "and", 2, flUseLabel, OH_DirectIndirectLongY }, /* $37 */ { "sec", 1, flNone, OH_Implicit }, /* $38 */ { "and", 3, flUseLabel, OH_AbsoluteY }, /* $39 */ { "dec", 1, flNone, OH_Accumulator }, /* $3a */ { "tsc", 1, flNone, OH_Implicit }, /* $3b */ { "bit", 3, flUseLabel, OH_AbsoluteX }, /* $3c */ { "and", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $3d */ { "rol", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $3e */ { "and", 4, flUseLabel, OH_AbsoluteLongX }, /* $3f */ { "rti", 1, flNone, OH_Rts }, /* $40 */ { "eor", 2, flUseLabel, OH_DirectXIndirect }, /* $41 */ { "wdm", 2, flNone, OH_Implicit }, /* $42 */ { "eor", 2, flNone, OH_StackRelative }, /* $43 */ { "mvp", 3, flNone, OH_BlockMove }, /* $44 */ { "eor", 2, flUseLabel, OH_Direct }, /* $45 */ { "lsr", 2, flUseLabel, OH_Direct }, /* $46 */ { "eor", 2, flUseLabel, OH_DirectIndirectLong }, /* $47 */ { "pha", 1, flNone, OH_Implicit }, /* $48 */ { "eor", 2, flNone, OH_Immediate }, /* $49 */ { "lsr", 1, flNone, OH_Accumulator }, /* $4a */ { "phk", 1, flNone, OH_Implicit }, /* $4b */ { "jmp", 3, flLabel, OH_JmpAbsolute }, /* $4c */ { "eor", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $4d */ { "lsr", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $4e */ { "eor", 4, flUseLabel, OH_AbsoluteLong }, /* $4f */ { "bvc", 2, flLabel, OH_Relative }, /* $50 */ { "eor", 2, flUseLabel, OH_DirectIndirectY }, /* $51 */ { "eor", 2, flUseLabel, OH_DirectIndirect }, /* $52 */ { "eor", 2, flNone, OH_StackRelativeIndirectY}, /* $53 */ { "mvn", 3, flNone, OH_BlockMove }, /* $54 */ { "eor", 2, flUseLabel, OH_DirectX }, /* $55 */ { "lsr", 2, flUseLabel, OH_DirectX }, /* $56 */ { "eor", 2, flUseLabel, OH_DirectIndirectLongY }, /* $57 */ { "cli", 1, flNone, OH_Implicit }, /* $58 */ { "eor", 3, flUseLabel, OH_AbsoluteY }, /* $59 */ { "phy", 1, flNone, OH_Implicit }, /* $5a */ { "tcd", 1, flNone, OH_Implicit }, /* $5b */ { "jml", 4, flLabel, OH_AbsoluteLong }, /* $5c */ { "eor", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $5d */ { "lsr", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $5e */ { "eor", 4, flUseLabel, OH_AbsoluteLongX }, /* $5f */ { "rts", 1, flNone, OH_Rts }, /* $60 */ { "adc", 2, flUseLabel, OH_DirectXIndirect }, /* $61 */ { "per", 3, flLabel, OH_RelativeLong }, /* $62 */ { "adc", 2, flNone, OH_StackRelative }, /* $63 */ { "stz", 2, flUseLabel, OH_Direct }, /* $64 */ { "adc", 2, flUseLabel, OH_Direct }, /* $65 */ { "ror", 2, flUseLabel, OH_Direct }, /* $66 */ { "adc", 2, flUseLabel, OH_DirectIndirectLong }, /* $67 */ { "pla", 1, flNone, OH_Implicit }, /* $68 */ { "adc", 2, flNone, OH_Immediate }, /* $69 */ { "ror", 1, flNone, OH_Accumulator }, /* $6a */ { "rtl", 1, flNone, OH_Implicit }, /* $6b */ { "jmp", 3, flLabel, OH_JmpAbsoluteIndirect }, /* $6c */ { "adc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $6d */ { "ror", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $6e */ { "adc", 4, flUseLabel, OH_AbsoluteLong }, /* $6f */ { "bvs", 2, flLabel, OH_Relative }, /* $70 */ { "adc", 2, flUseLabel, OH_DirectIndirectY }, /* $71 */ { "adc", 2, flUseLabel, OH_DirectIndirect }, /* $72 */ { "adc", 2, flNone, OH_StackRelativeIndirectY}, /* $73 */ { "stz", 2, flUseLabel, OH_DirectX }, /* $74 */ { "adc", 2, flUseLabel, OH_DirectX }, /* $75 */ { "ror", 2, flUseLabel, OH_DirectX }, /* $76 */ { "adc", 2, flUseLabel, OH_DirectIndirectLongY }, /* $77 */ { "sei", 1, flNone, OH_Implicit }, /* $78 */ { "adc", 3, flUseLabel, OH_AbsoluteY }, /* $79 */ { "ply", 1, flNone, OH_Implicit }, /* $7a */ { "tdc", 1, flNone, OH_Implicit }, /* $7b */ { "jmp", 3, flLabel, OH_AbsoluteXIndirect }, /* $7c */ { "adc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $7d */ { "ror", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $7e */ { "adc", 4, flUseLabel, OH_AbsoluteLongX }, /* $7f */ { "bra", 2, flLabel, OH_Relative }, /* $80 */ { "sta", 2, flUseLabel, OH_DirectXIndirect }, /* $81 */ { "brl", 3, flLabel, OH_RelativeLong }, /* $82 */ { "sta", 2, flNone, OH_StackRelative }, /* $83 */ { "sty", 2, flUseLabel, OH_Direct }, /* $84 */ { "sta", 2, flUseLabel, OH_Direct }, /* $85 */ { "stx", 2, flUseLabel, OH_Direct }, /* $86 */ { "sta", 2, flUseLabel, OH_DirectIndirectLong }, /* $87 */ { "dey", 1, flNone, OH_Implicit }, /* $88 */ { "bit", 2, flNone, OH_Immediate }, /* $89 */ { "txa", 1, flNone, OH_Implicit }, /* $8a */ { "phb", 1, flNone, OH_Implicit }, /* $8b */ { "sty", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8c */ { "sta", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8d */ { "stx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8e */ { "sta", 4, flUseLabel, OH_AbsoluteLong }, /* $8f */ { "bcc", 2, flLabel, OH_Relative }, /* $90 */ { "sta", 2, flUseLabel, OH_DirectIndirectY }, /* $91 */ { "sta", 2, flUseLabel, OH_DirectIndirect }, /* $92 */ { "sta", 2, flNone, OH_StackRelativeIndirectY}, /* $93 */ { "sty", 2, flUseLabel, OH_DirectX }, /* $94 */ { "sta", 2, flUseLabel, OH_DirectX }, /* $95 */ { "stx", 2, flUseLabel, OH_DirectY }, /* $96 */ { "sta", 2, flUseLabel, OH_DirectIndirectLongY }, /* $97 */ { "tya", 1, flNone, OH_Implicit }, /* $98 */ { "sta", 3, flUseLabel, OH_AbsoluteY }, /* $99 */ { "txs", 1, flNone, OH_Implicit }, /* $9a */ { "txy", 1, flNone, OH_Implicit }, /* $9b */ { "stz", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $9c */ { "sta", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $9d */ { "stz", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $9e */ { "sta", 4, flUseLabel, OH_AbsoluteLongX }, /* $9f */ { "ldy", 2, flNone, OH_Immediate }, /* $a0 */ { "lda", 2, flUseLabel, OH_DirectXIndirect }, /* $a1 */ { "ldx", 2, flNone, OH_Immediate }, /* $a2 */ { "lda", 2, flNone, OH_StackRelative }, /* $a3 */ { "ldy", 2, flUseLabel, OH_Direct }, /* $a4 */ { "lda", 2, flUseLabel, OH_Direct }, /* $a5 */ { "ldx", 2, flUseLabel, OH_Direct }, /* $a6 */ { "lda", 2, flUseLabel, OH_DirectIndirectLong }, /* $a7 */ { "tay", 1, flNone, OH_Implicit }, /* $a8 */ { "lda", 2, flNone, OH_Immediate }, /* $a9 */ { "tax", 1, flNone, OH_Implicit }, /* $aa */ { "plb", 1, flNone, OH_Implicit }, /* $ab */ { "ldy", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ac */ { "lda", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ad */ { "ldx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ae */ { "lda", 4, flUseLabel, OH_AbsoluteLong }, /* $af */ { "bcs", 2, flLabel, OH_Relative }, /* $b0 */ { "lda", 2, flUseLabel, OH_DirectIndirectY }, /* $b1 */ { "lda", 2, flUseLabel, OH_DirectIndirect }, /* $b2 */ { "lda", 2, flNone, OH_StackRelativeIndirectY}, /* $b3 */ { "ldy", 2, flUseLabel, OH_DirectX }, /* $b4 */ { "lda", 2, flUseLabel, OH_DirectX }, /* $b5 */ { "ldx", 2, flUseLabel, OH_DirectY }, /* $b6 */ { "lda", 2, flUseLabel, OH_DirectIndirectLongY }, /* $b7 */ { "clv", 1, flNone, OH_Implicit }, /* $b8 */ { "lda", 3, flUseLabel, OH_AbsoluteY }, /* $b9 */ { "tsx", 1, flNone, OH_Implicit }, /* $ba */ { "tyx", 1, flNone, OH_Implicit }, /* $bb */ { "ldy", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $bc */ { "lda", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $bd */ { "ldx", 3, flUseLabel|flAbsOverride, OH_AbsoluteY }, /* $be */ { "lda", 4, flUseLabel, OH_AbsoluteLongX }, /* $bf */ { "cpy", 2, flNone, OH_Immediate }, /* $c0 */ { "cmp", 2, flUseLabel, OH_DirectXIndirect }, /* $c1 */ { "rep", 2, flNone, OH_Immediate }, /* $c2 */ { "cmp", 2, flNone, OH_StackRelative }, /* $c3 */ { "cpy", 2, flUseLabel, OH_Direct }, /* $c4 */ { "cmp", 2, flUseLabel, OH_Direct }, /* $c5 */ { "dec", 2, flUseLabel, OH_Direct }, /* $c6 */ { "cmp", 2, flUseLabel, OH_DirectIndirectLong }, /* $c7 */ { "iny", 1, flNone, OH_Implicit }, /* $c8 */ { "cmp", 2, flNone, OH_Immediate }, /* $c9 */ { "dex", 1, flNone, OH_Implicit }, /* $ca */ { "wai", 1, flNone, OH_Implicit }, /* $cb */ { "cpy", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $cc */ { "cmp", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $cd */ { "dec", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ce */ { "cmp", 4, flUseLabel, OH_AbsoluteLong }, /* $cf */ { "bne", 2, flLabel, OH_Relative }, /* $d0 */ { "cmp", 2, flUseLabel, OH_DirectIndirectY }, /* $d1 */ { "cmp", 2, flUseLabel, OH_DirectIndirect }, /* $d2 */ { "cmp", 2, flNone, OH_StackRelativeIndirectY}, /* $d3 */ { "pei", 2, flUseLabel, OH_Direct }, /* $d4 */ { "cmp", 2, flUseLabel, OH_DirectX }, /* $d5 */ { "dec", 2, flUseLabel, OH_DirectX }, /* $d6 */ { "cmp", 2, flUseLabel, OH_DirectIndirectLongY }, /* $d7 */ { "cld", 1, flNone, OH_Implicit }, /* $d8 */ { "cmp", 3, flUseLabel, OH_AbsoluteY }, /* $d9 */ { "phx", 1, flNone, OH_Implicit }, /* $da */ { "stp", 1, flNone, OH_Implicit }, /* $db */ { "jml", 3, flLabel, OH_AbsoluteIndirect }, /* $dc */ { "cmp", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $dd */ { "dec", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $de */ { "cmp", 4, flUseLabel, OH_AbsoluteLongX }, /* $df */ { "cpx", 2, flNone, OH_Immediate }, /* $e0 */ { "sbc", 2, flUseLabel, OH_DirectXIndirect }, /* $e1 */ { "sep", 2, flNone, OH_Immediate }, /* $e2 */ { "sbc", 2, flNone, OH_StackRelative }, /* $e3 */ { "cpx", 2, flUseLabel, OH_Direct }, /* $e4 */ { "sbc", 2, flUseLabel, OH_Direct }, /* $e5 */ { "inc", 2, flUseLabel, OH_Direct }, /* $e6 */ { "sbc", 2, flUseLabel, OH_DirectIndirectLong }, /* $e7 */ { "inx", 1, flNone, OH_Implicit }, /* $e8 */ { "sbc", 2, flNone, OH_Immediate }, /* $e9 */ { "nop", 1, flNone, OH_Implicit }, /* $ea */ { "xba", 1, flNone, OH_Implicit }, /* $eb */ { "cpx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ec */ { "sbc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ed */ { "inc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ee */ { "sbc", 4, flUseLabel, OH_AbsoluteLong }, /* $ef */ { "beq", 2, flLabel, OH_Relative }, /* $f0 */ { "sbc", 2, flUseLabel, OH_DirectIndirectY }, /* $f1 */ { "sbc", 2, flUseLabel, OH_DirectIndirect }, /* $f2 */ { "sbc", 2, flNone, OH_StackRelativeIndirectY}, /* $f3 */ { "pea", 3, flUseLabel, OH_Absolute }, /* $f4 */ { "sbc", 2, flUseLabel, OH_DirectX }, /* $f5 */ { "inc", 2, flUseLabel, OH_DirectX }, /* $f6 */ { "sbc", 2, flUseLabel, OH_DirectIndirectLongY }, /* $f7 */ { "sed", 1, flNone, OH_Implicit }, /* $f8 */ { "sbc", 3, flUseLabel, OH_AbsoluteY }, /* $f9 */ { "plx", 1, flNone, OH_Implicit }, /* $fa */ { "xce", 1, flNone, OH_Implicit }, /* $fb */ { "jsr", 3, flLabel, OH_AbsoluteXIndirect }, /* $fc */ { "sbc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fd */ { "inc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fe */ { "sbc", 4, flUseLabel, OH_AbsoluteLongX }, /* $ff */ }; �������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/opc65816.h�����������������������������������������������������������������������0000664�0000000�0000000�00000005647�13473601511�0015113�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* opc65816.h */ /* */ /* 65816 opcode description table */ /* */ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef OPC65816_H #define OPC65816_H #include "opcdesc.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Descriptions for all opcodes */ extern const OpcDesc OpcTable_65816[256]; /* End of opc65816.h */ #endif �����������������������������������������������������������������������������������������cc65-2.18/src/da65/opc65c02.c�����������������������������������������������������������������������0000664�0000000�0000000�00000057573�13473601511�0015161�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* opc65c02.c */ /* */ /* 65C02 opcode description table */ /* */ /* */ /* */ /* (C) 2003-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* da65 */ #include "handler.h" #include "opc65c02.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Descriptions for all opcodes */ const OpcDesc OpcTable_65C02[256] = { { "brk", 1, flNone, OH_Implicit }, /* $00 */ { "ora", 2, flUseLabel, OH_DirectXIndirect }, /* $01 */ { "", 1, flIllegal, OH_Illegal, }, /* $02 */ { "", 1, flIllegal, OH_Illegal, }, /* $03 */ { "tsb", 2, flUseLabel, OH_Direct }, /* $04 */ { "ora", 2, flUseLabel, OH_Direct }, /* $05 */ { "asl", 2, flUseLabel, OH_Direct }, /* $06 */ { "rmb0", 2, flUseLabel, OH_Direct, }, /* $07 */ { "php", 1, flNone, OH_Implicit }, /* $08 */ { "ora", 2, flNone, OH_Immediate }, /* $09 */ { "asl", 1, flNone, OH_Accumulator }, /* $0a */ { "", 1, flIllegal, OH_Illegal, }, /* $0b */ { "tsb", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0c */ { "ora", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0d */ { "asl", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0e */ { "bbr0", 3, flUseLabel, OH_BitBranch }, /* $0f */ { "bpl", 2, flLabel, OH_Relative }, /* $10 */ { "ora", 2, flUseLabel, OH_DirectIndirectY }, /* $11 */ { "ora", 2, flUseLabel, OH_DirectIndirect }, /* $12 */ { "", 1, flIllegal, OH_Illegal, }, /* $13 */ { "trb", 2, flUseLabel, OH_Direct }, /* $14 */ { "ora", 2, flUseLabel, OH_DirectX }, /* $15 */ { "asl", 2, flUseLabel, OH_DirectX }, /* $16 */ { "rmb1", 2, flUseLabel, OH_Direct, }, /* $17 */ { "clc", 1, flNone, OH_Implicit }, /* $18 */ { "ora", 3, flUseLabel, OH_AbsoluteY }, /* $19 */ { "inc", 1, flNone, OH_Accumulator }, /* $1a */ { "", 1, flIllegal, OH_Illegal, }, /* $1b */ { "trb", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $1c */ { "ora", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1d */ { "asl", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1e */ { "bbr1", 3, flUseLabel, OH_BitBranch }, /* $1f */ { "jsr", 3, flLabel, OH_JsrAbsolute }, /* $20 */ { "and", 2, flUseLabel, OH_DirectXIndirect }, /* $21 */ { "", 1, flIllegal, OH_Illegal, }, /* $22 */ { "", 1, flIllegal, OH_Illegal, }, /* $23 */ { "bit", 2, flUseLabel, OH_Direct }, /* $24 */ { "and", 2, flUseLabel, OH_Direct }, /* $25 */ { "rol", 2, flUseLabel, OH_Direct }, /* $26 */ { "rmb2", 2, flUseLabel, OH_Direct, }, /* $27 */ { "plp", 1, flNone, OH_Implicit }, /* $28 */ { "and", 2, flNone, OH_Immediate }, /* $29 */ { "rol", 1, flNone, OH_Accumulator }, /* $2a */ { "", 1, flIllegal, OH_Illegal, }, /* $2b */ { "bit", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2c */ { "and", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2d */ { "rol", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2e */ { "bbr2", 3, flUseLabel, OH_BitBranch }, /* $2f */ { "bmi", 2, flLabel, OH_Relative }, /* $30 */ { "and", 2, flUseLabel, OH_DirectIndirectY }, /* $31 */ { "and", 2, flUseLabel, OH_DirectIndirect, }, /* $32 */ { "", 1, flIllegal, OH_Illegal, }, /* $33 */ { "bit", 2, flUseLabel, OH_DirectX }, /* $34 */ { "and", 2, flUseLabel, OH_DirectX }, /* $35 */ { "rol", 2, flUseLabel, OH_DirectX }, /* $36 */ { "rmb3", 2, flUseLabel, OH_Direct, }, /* $37 */ { "sec", 1, flNone, OH_Implicit }, /* $38 */ { "and", 3, flUseLabel, OH_AbsoluteY }, /* $39 */ { "dec", 1, flNone, OH_Accumulator }, /* $3a */ { "", 1, flIllegal, OH_Illegal, }, /* $3b */ { "bit", 3, flUseLabel, OH_AbsoluteX }, /* $3c */ { "and", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $3d */ { "rol", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $3e */ { "bbr3", 3, flUseLabel, OH_BitBranch }, /* $3f */ { "rti", 1, flNone, OH_Rts }, /* $40 */ { "eor", 2, flUseLabel, OH_DirectXIndirect }, /* $41 */ { "", 1, flIllegal, OH_Illegal, }, /* $42 */ { "", 1, flIllegal, OH_Illegal, }, /* $43 */ { "", 1, flIllegal, OH_Illegal, }, /* $44 */ { "eor", 2, flUseLabel, OH_Direct }, /* $45 */ { "lsr", 2, flUseLabel, OH_Direct }, /* $46 */ { "rmb4", 2, flUseLabel, OH_Direct, }, /* $47 */ { "pha", 1, flNone, OH_Implicit }, /* $48 */ { "eor", 2, flNone, OH_Immediate }, /* $49 */ { "lsr", 1, flNone, OH_Accumulator }, /* $4a */ { "", 1, flIllegal, OH_Illegal, }, /* $4b */ { "jmp", 3, flLabel, OH_JmpAbsolute }, /* $4c */ { "eor", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $4d */ { "lsr", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $4e */ { "bbr4", 3, flUseLabel, OH_BitBranch }, /* $4f */ { "bvc", 2, flLabel, OH_Relative }, /* $50 */ { "eor", 2, flUseLabel, OH_DirectIndirectY }, /* $51 */ { "eor", 2, flUseLabel, OH_DirectIndirect }, /* $52 */ { "", 1, flIllegal, OH_Illegal, }, /* $53 */ { "", 1, flIllegal, OH_Illegal, }, /* $54 */ { "eor", 2, flUseLabel, OH_DirectX }, /* $55 */ { "lsr", 2, flUseLabel, OH_DirectX }, /* $56 */ { "rmb5", 2, flUseLabel, OH_Direct, }, /* $57 */ { "cli", 1, flNone, OH_Implicit }, /* $58 */ { "eor", 3, flUseLabel, OH_AbsoluteY }, /* $59 */ { "phy", 1, flNone, OH_Implicit }, /* $5a */ { "", 1, flIllegal, OH_Illegal, }, /* $5b */ { "", 1, flIllegal, OH_Illegal, }, /* $5c */ { "eor", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $5d */ { "lsr", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $5e */ { "bbr5", 3, flUseLabel, OH_BitBranch }, /* $5f */ { "rts", 1, flNone, OH_Rts }, /* $60 */ { "adc", 2, flUseLabel, OH_DirectXIndirect }, /* $61 */ { "", 1, flIllegal, OH_Illegal, }, /* $62 */ { "", 1, flIllegal, OH_Illegal, }, /* $63 */ { "stz", 2, flUseLabel, OH_Direct }, /* $64 */ { "adc", 2, flUseLabel, OH_Direct }, /* $65 */ { "ror", 2, flUseLabel, OH_Direct }, /* $66 */ { "rmb6", 2, flUseLabel, OH_Direct, }, /* $67 */ { "pla", 1, flNone, OH_Implicit }, /* $68 */ { "adc", 2, flNone, OH_Immediate }, /* $69 */ { "ror", 1, flNone, OH_Accumulator }, /* $6a */ { "", 1, flIllegal, OH_Illegal, }, /* $6b */ { "jmp", 3, flLabel, OH_JmpAbsoluteIndirect }, /* $6c */ { "adc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $6d */ { "ror", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $6e */ { "bbr6", 3, flUseLabel, OH_BitBranch }, /* $6f */ { "bvs", 2, flLabel, OH_Relative }, /* $70 */ { "adc", 2, flUseLabel, OH_DirectIndirectY }, /* $71 */ { "adc", 2, flUseLabel, OH_DirectIndirect, }, /* $72 */ { "", 1, flIllegal, OH_Illegal, }, /* $73 */ { "stz", 2, flUseLabel, OH_DirectX }, /* $74 */ { "adc", 2, flUseLabel, OH_DirectX }, /* $75 */ { "ror", 2, flUseLabel, OH_DirectX }, /* $76 */ { "rmb7", 2, flUseLabel, OH_Direct, }, /* $77 */ { "sei", 1, flNone, OH_Implicit }, /* $78 */ { "adc", 3, flUseLabel, OH_AbsoluteY }, /* $79 */ { "ply", 1, flNone, OH_Implicit }, /* $7a */ { "", 1, flIllegal, OH_Illegal, }, /* $7b */ { "jmp", 3, flLabel, OH_AbsoluteXIndirect }, /* $7c */ { "adc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $7d */ { "ror", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $7e */ { "bbr7", 3, flUseLabel, OH_BitBranch }, /* $7f */ { "bra", 2, flLabel, OH_Relative }, /* $80 */ { "sta", 2, flUseLabel, OH_DirectXIndirect }, /* $81 */ { "", 1, flIllegal, OH_Illegal, }, /* $82 */ { "", 1, flIllegal, OH_Illegal, }, /* $83 */ { "sty", 2, flUseLabel, OH_Direct }, /* $84 */ { "sta", 2, flUseLabel, OH_Direct }, /* $85 */ { "stx", 2, flUseLabel, OH_Direct }, /* $86 */ { "smb0", 2, flUseLabel, OH_Direct, }, /* $87 */ { "dey", 1, flNone, OH_Implicit }, /* $88 */ { "bit", 2, flNone, OH_Immediate }, /* $89 */ { "txa", 1, flNone, OH_Implicit }, /* $8a */ { "", 1, flIllegal, OH_Illegal, }, /* $8b */ { "sty", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8c */ { "sta", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8d */ { "stx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8e */ { "bbs0", 3, flUseLabel, OH_BitBranch }, /* $8f */ { "bcc", 2, flLabel, OH_Relative }, /* $90 */ { "sta", 2, flUseLabel, OH_DirectIndirectY }, /* $91 */ { "sta", 2, flUseLabel, OH_DirectIndirect }, /* $92 */ { "", 1, flIllegal, OH_Illegal, }, /* $93 */ { "sty", 2, flUseLabel, OH_DirectX }, /* $94 */ { "sta", 2, flUseLabel, OH_DirectX }, /* $95 */ { "stx", 2, flUseLabel, OH_DirectY }, /* $96 */ { "smb1", 2, flUseLabel, OH_Direct, }, /* $97 */ { "tya", 1, flNone, OH_Implicit }, /* $98 */ { "sta", 3, flUseLabel, OH_AbsoluteY }, /* $99 */ { "txs", 1, flNone, OH_Implicit }, /* $9a */ { "", 1, flIllegal, OH_Illegal, }, /* $9b */ { "stz", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $9c */ { "sta", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $9d */ { "stz", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $9e */ { "bbs1", 3, flUseLabel, OH_BitBranch }, /* $9f */ { "ldy", 2, flNone, OH_Immediate }, /* $a0 */ { "lda", 2, flUseLabel, OH_DirectXIndirect }, /* $a1 */ { "ldx", 2, flNone, OH_Immediate }, /* $a2 */ { "", 1, flIllegal, OH_Illegal, }, /* $a3 */ { "ldy", 2, flUseLabel, OH_Direct }, /* $a4 */ { "lda", 2, flUseLabel, OH_Direct }, /* $a5 */ { "ldx", 2, flUseLabel, OH_Direct }, /* $a6 */ { "smb2", 2, flUseLabel, OH_Direct, }, /* $a7 */ { "tay", 1, flNone, OH_Implicit }, /* $a8 */ { "lda", 2, flNone, OH_Immediate }, /* $a9 */ { "tax", 1, flNone, OH_Implicit }, /* $aa */ { "", 1, flIllegal, OH_Illegal, }, /* $ab */ { "ldy", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ac */ { "lda", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ad */ { "ldx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ae */ { "bbs2", 3, flUseLabel, OH_BitBranch }, /* $af */ { "bcs", 2, flLabel, OH_Relative }, /* $b0 */ { "lda", 2, flUseLabel, OH_DirectIndirectY }, /* $b1 */ { "lda", 2, flUseLabel, OH_DirectIndirect }, /* $b2 */ { "", 1, flIllegal, OH_Illegal, }, /* $b3 */ { "ldy", 2, flUseLabel, OH_DirectX }, /* $b4 */ { "lda", 2, flUseLabel, OH_DirectX }, /* $b5 */ { "ldx", 2, flUseLabel, OH_DirectY }, /* $b6 */ { "smb3", 2, flUseLabel, OH_Direct, }, /* $b7 */ { "clv", 1, flNone, OH_Implicit }, /* $b8 */ { "lda", 3, flUseLabel, OH_AbsoluteY }, /* $b9 */ { "tsx", 1, flNone, OH_Implicit }, /* $ba */ { "", 1, flIllegal, OH_Illegal, }, /* $bb */ { "ldy", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $bc */ { "lda", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $bd */ { "ldx", 3, flUseLabel|flAbsOverride, OH_AbsoluteY }, /* $be */ { "bbs3", 3, flUseLabel, OH_BitBranch }, /* $bf */ { "cpy", 2, flNone, OH_Immediate }, /* $c0 */ { "cmp", 2, flUseLabel, OH_DirectXIndirect }, /* $c1 */ { "", 1, flIllegal, OH_Illegal, }, /* $c2 */ { "", 1, flIllegal, OH_Illegal, }, /* $c3 */ { "cpy", 2, flUseLabel, OH_Direct }, /* $c4 */ { "cmp", 2, flUseLabel, OH_Direct }, /* $c5 */ { "dec", 2, flUseLabel, OH_Direct }, /* $c6 */ { "smb4", 2, flUseLabel, OH_Direct, }, /* $c7 */ { "iny", 1, flNone, OH_Implicit }, /* $c8 */ { "cmp", 2, flNone, OH_Immediate }, /* $c9 */ { "dex", 1, flNone, OH_Implicit }, /* $ca */ { "wai", 1, flNone, OH_Implicit }, /* $cb */ { "cpy", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $cc */ { "cmp", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $cd */ { "dec", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ce */ { "bbs4", 3, flUseLabel, OH_BitBranch }, /* $cf */ { "bne", 2, flLabel, OH_Relative }, /* $d0 */ { "cmp", 2, flUseLabel, OH_DirectIndirectY }, /* $d1 */ { "cmp", 2, flUseLabel, OH_DirectIndirect }, /* $d2 */ { "", 1, flIllegal, OH_Illegal, }, /* $d3 */ { "", 1, flIllegal, OH_Illegal, }, /* $d4 */ { "cmp", 2, flUseLabel, OH_DirectX }, /* $d5 */ { "dec", 2, flUseLabel, OH_DirectX }, /* $d6 */ { "smb5", 2, flUseLabel, OH_Direct, }, /* $d7 */ { "cld", 1, flNone, OH_Implicit }, /* $d8 */ { "cmp", 3, flUseLabel, OH_AbsoluteY }, /* $d9 */ { "phx", 1, flNone, OH_Implicit }, /* $da */ { "stp", 1, flNone, OH_Implicit }, /* $db */ { "", 1, flIllegal, OH_Illegal, }, /* $dc */ { "cmp", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $dd */ { "dec", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $de */ { "bbs5", 3, flUseLabel, OH_BitBranch }, /* $df */ { "cpx", 2, flNone, OH_Immediate }, /* $e0 */ { "sbc", 2, flUseLabel, OH_DirectXIndirect }, /* $e1 */ { "", 1, flIllegal, OH_Illegal, }, /* $e2 */ { "", 1, flIllegal, OH_Illegal, }, /* $e3 */ { "cpx", 2, flUseLabel, OH_Direct }, /* $e4 */ { "sbc", 2, flUseLabel, OH_Direct }, /* $e5 */ { "inc", 2, flUseLabel, OH_Direct }, /* $e6 */ { "smb6", 2, flUseLabel, OH_Direct, }, /* $e7 */ { "inx", 1, flNone, OH_Implicit }, /* $e8 */ { "sbc", 2, flNone, OH_Immediate }, /* $e9 */ { "nop", 1, flNone, OH_Implicit }, /* $ea */ { "", 1, flIllegal, OH_Illegal, }, /* $eb */ { "cpx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ec */ { "sbc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ed */ { "inc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ee */ { "bbs6", 3, flUseLabel, OH_BitBranch }, /* $ef */ { "beq", 2, flLabel, OH_Relative }, /* $f0 */ { "sbc", 2, flUseLabel, OH_DirectIndirectY }, /* $f1 */ { "sbc", 2, flUseLabel, OH_DirectIndirect }, /* $f2 */ { "", 1, flIllegal, OH_Illegal, }, /* $f3 */ { "", 1, flIllegal, OH_Illegal, }, /* $f4 */ { "sbc", 2, flUseLabel, OH_DirectX }, /* $f5 */ { "inc", 2, flUseLabel, OH_DirectX }, /* $f6 */ { "smb7", 2, flUseLabel, OH_Direct, }, /* $f7 */ { "sed", 1, flNone, OH_Implicit }, /* $f8 */ { "sbc", 3, flUseLabel, OH_AbsoluteY }, /* $f9 */ { "plx", 1, flNone, OH_Implicit }, /* $fa */ { "", 1, flIllegal, OH_Illegal, }, /* $fb */ { "", 1, flIllegal, OH_Illegal, }, /* $fc */ { "sbc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fd */ { "inc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fe */ { "bbs7", 3, flUseLabel, OH_BitBranch }, /* $ff */ }; �������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/opc65c02.h�����������������������������������������������������������������������0000664�0000000�0000000�00000005647�13473601511�0015161�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* opc65c02.h */ /* */ /* 65C02 opcode description table */ /* */ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef OPC65C02_H #define OPC65C02_H #include "opcdesc.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Descriptions for all opcodes */ extern const OpcDesc OpcTable_65C02[256]; /* End of opc65c02.h */ #endif �����������������������������������������������������������������������������������������cc65-2.18/src/da65/opc65sc02.c����������������������������������������������������������������������0000664�0000000�0000000�00000057575�13473601511�0015346�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* opc65sc02.c */ /* */ /* 65SC02 opcode description table */ /* */ /* */ /* */ /* (C) 2003-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* da65 */ #include "handler.h" #include "opc65sc02.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Descriptions for all opcodes */ const OpcDesc OpcTable_65SC02[256] = { { "brk", 1, flNone, OH_Implicit }, /* $00 */ { "ora", 2, flUseLabel, OH_DirectXIndirect }, /* $01 */ { "", 1, flIllegal, OH_Illegal, }, /* $02 */ { "", 1, flIllegal, OH_Illegal, }, /* $03 */ { "tsb", 2, flUseLabel, OH_Direct }, /* $04 */ { "ora", 2, flUseLabel, OH_Direct }, /* $05 */ { "asl", 2, flUseLabel, OH_Direct }, /* $06 */ { "", 1, flIllegal, OH_Illegal, }, /* $07 */ { "php", 1, flNone, OH_Implicit }, /* $08 */ { "ora", 2, flNone, OH_Immediate }, /* $09 */ { "asl", 1, flNone, OH_Accumulator }, /* $0a */ { "", 1, flIllegal, OH_Illegal, }, /* $0b */ { "tsb", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0c */ { "ora", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0d */ { "asl", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0e */ { "", 1, flIllegal, OH_Illegal, }, /* $0f */ { "bpl", 2, flLabel, OH_Relative }, /* $10 */ { "ora", 2, flUseLabel, OH_DirectIndirectY }, /* $11 */ { "ora", 2, flUseLabel, OH_DirectIndirect }, /* $12 */ { "", 1, flIllegal, OH_Illegal, }, /* $13 */ { "trb", 2, flUseLabel, OH_Direct }, /* $14 */ { "ora", 2, flUseLabel, OH_DirectX }, /* $15 */ { "asl", 2, flUseLabel, OH_DirectX }, /* $16 */ { "", 1, flIllegal, OH_Illegal, }, /* $17 */ { "clc", 1, flNone, OH_Implicit }, /* $18 */ { "ora", 3, flUseLabel, OH_AbsoluteY }, /* $19 */ { "inc", 1, flNone, OH_Accumulator }, /* $1a */ { "", 1, flIllegal, OH_Illegal, }, /* $1b */ { "trb", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $1c */ { "ora", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1d */ { "asl", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1e */ { "", 1, flIllegal, OH_Illegal, }, /* $1f */ { "jsr", 3, flLabel, OH_JsrAbsolute }, /* $20 */ { "and", 2, flUseLabel, OH_DirectXIndirect }, /* $21 */ { "", 1, flIllegal, OH_Illegal, }, /* $22 */ { "", 1, flIllegal, OH_Illegal, }, /* $23 */ { "bit", 2, flUseLabel, OH_Direct }, /* $24 */ { "and", 2, flUseLabel, OH_Direct }, /* $25 */ { "rol", 2, flUseLabel, OH_Direct }, /* $26 */ { "", 1, flIllegal, OH_Illegal, }, /* $27 */ { "plp", 1, flNone, OH_Implicit }, /* $28 */ { "and", 2, flNone, OH_Immediate }, /* $29 */ { "rol", 1, flNone, OH_Accumulator }, /* $2a */ { "", 1, flIllegal, OH_Illegal, }, /* $2b */ { "bit", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2c */ { "and", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2d */ { "rol", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2e */ { "", 1, flIllegal, OH_Illegal, }, /* $2f */ { "bmi", 2, flLabel, OH_Relative }, /* $30 */ { "and", 2, flUseLabel, OH_DirectIndirectY }, /* $31 */ { "and", 2, flUseLabel, OH_DirectIndirect, }, /* $32 */ { "", 1, flIllegal, OH_Illegal, }, /* $33 */ { "bit", 2, flUseLabel, OH_DirectX }, /* $34 */ { "and", 2, flUseLabel, OH_DirectX }, /* $35 */ { "rol", 2, flUseLabel, OH_DirectX }, /* $36 */ { "", 1, flIllegal, OH_Illegal, }, /* $37 */ { "sec", 1, flNone, OH_Implicit }, /* $38 */ { "and", 3, flUseLabel, OH_AbsoluteY }, /* $39 */ { "dec", 1, flNone, OH_Accumulator }, /* $3a */ { "", 1, flIllegal, OH_Illegal, }, /* $3b */ { "bit", 3, flUseLabel, OH_AbsoluteX }, /* $3c */ { "and", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $3d */ { "rol", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $3e */ { "", 1, flIllegal, OH_Illegal, }, /* $3f */ { "rti", 1, flNone, OH_Rts }, /* $40 */ { "eor", 2, flUseLabel, OH_DirectXIndirect }, /* $41 */ { "", 1, flIllegal, OH_Illegal, }, /* $42 */ { "", 1, flIllegal, OH_Illegal, }, /* $43 */ { "", 1, flIllegal, OH_Illegal, }, /* $44 */ { "eor", 2, flUseLabel, OH_Direct }, /* $45 */ { "lsr", 2, flUseLabel, OH_Direct }, /* $46 */ { "", 1, flIllegal, OH_Illegal, }, /* $47 */ { "pha", 1, flNone, OH_Implicit }, /* $48 */ { "eor", 2, flNone, OH_Immediate }, /* $49 */ { "lsr", 1, flNone, OH_Accumulator }, /* $4a */ { "", 1, flIllegal, OH_Illegal, }, /* $4b */ { "jmp", 3, flLabel, OH_JmpAbsolute }, /* $4c */ { "eor", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $4d */ { "lsr", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $4e */ { "", 1, flIllegal, OH_Illegal, }, /* $4f */ { "bvc", 2, flLabel, OH_Relative }, /* $50 */ { "eor", 2, flUseLabel, OH_DirectIndirectY }, /* $51 */ { "eor", 2, flUseLabel, OH_DirectIndirect }, /* $52 */ { "", 1, flIllegal, OH_Illegal, }, /* $53 */ { "", 1, flIllegal, OH_Illegal, }, /* $54 */ { "eor", 2, flUseLabel, OH_DirectX }, /* $55 */ { "lsr", 2, flUseLabel, OH_DirectX }, /* $56 */ { "", 1, flIllegal, OH_Illegal, }, /* $57 */ { "cli", 1, flNone, OH_Implicit }, /* $58 */ { "eor", 3, flUseLabel, OH_AbsoluteY }, /* $59 */ { "phy", 1, flNone, OH_Implicit }, /* $5a */ { "", 1, flIllegal, OH_Illegal, }, /* $5b */ { "", 1, flIllegal, OH_Illegal, }, /* $5c */ { "eor", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $5d */ { "lsr", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $5e */ { "", 1, flIllegal, OH_Illegal, }, /* $5f */ { "rts", 1, flNone, OH_Rts }, /* $60 */ { "adc", 2, flUseLabel, OH_DirectXIndirect }, /* $61 */ { "", 1, flIllegal, OH_Illegal, }, /* $62 */ { "", 1, flIllegal, OH_Illegal, }, /* $63 */ { "stz", 2, flUseLabel, OH_Direct }, /* $64 */ { "adc", 2, flUseLabel, OH_Direct }, /* $65 */ { "ror", 2, flUseLabel, OH_Direct }, /* $66 */ { "", 1, flIllegal, OH_Illegal, }, /* $67 */ { "pla", 1, flNone, OH_Implicit }, /* $68 */ { "adc", 2, flNone, OH_Immediate }, /* $69 */ { "ror", 1, flNone, OH_Accumulator }, /* $6a */ { "", 1, flIllegal, OH_Illegal, }, /* $6b */ { "jmp", 3, flLabel, OH_JmpAbsoluteIndirect }, /* $6c */ { "adc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $6d */ { "ror", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $6e */ { "", 1, flIllegal, OH_Illegal, }, /* $6f */ { "bvs", 2, flLabel, OH_Relative }, /* $70 */ { "adc", 2, flUseLabel, OH_DirectIndirectY }, /* $71 */ { "adc", 2, flUseLabel, OH_DirectIndirect, }, /* $72 */ { "", 1, flIllegal, OH_Illegal, }, /* $73 */ { "stz", 2, flUseLabel, OH_DirectX }, /* $74 */ { "adc", 2, flUseLabel, OH_DirectX }, /* $75 */ { "ror", 2, flUseLabel, OH_DirectX }, /* $76 */ { "", 1, flIllegal, OH_Illegal, }, /* $77 */ { "sei", 1, flNone, OH_Implicit }, /* $78 */ { "adc", 3, flUseLabel, OH_AbsoluteY }, /* $79 */ { "ply", 1, flNone, OH_Implicit }, /* $7a */ { "", 1, flIllegal, OH_Illegal, }, /* $7b */ { "jmp", 3, flLabel, OH_AbsoluteXIndirect }, /* $7c */ { "adc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $7d */ { "ror", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $7e */ { "", 1, flIllegal, OH_Illegal, }, /* $7f */ { "bra", 2, flLabel, OH_Relative }, /* $80 */ { "sta", 2, flUseLabel, OH_DirectXIndirect }, /* $81 */ { "", 1, flIllegal, OH_Illegal, }, /* $82 */ { "", 1, flIllegal, OH_Illegal, }, /* $83 */ { "sty", 2, flUseLabel, OH_Direct }, /* $84 */ { "sta", 2, flUseLabel, OH_Direct }, /* $85 */ { "stx", 2, flUseLabel, OH_Direct }, /* $86 */ { "", 1, flIllegal, OH_Illegal, }, /* $87 */ { "dey", 1, flNone, OH_Implicit }, /* $88 */ { "bit", 2, flNone, OH_Immediate }, /* $89 */ { "txa", 1, flNone, OH_Implicit }, /* $8a */ { "", 1, flIllegal, OH_Illegal, }, /* $8b */ { "sty", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8c */ { "sta", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8d */ { "stx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8e */ { "", 1, flIllegal, OH_Illegal, }, /* $8f */ { "bcc", 2, flLabel, OH_Relative }, /* $90 */ { "sta", 2, flUseLabel, OH_DirectIndirectY }, /* $91 */ { "sta", 2, flUseLabel, OH_DirectIndirect }, /* $92 */ { "", 1, flIllegal, OH_Illegal, }, /* $93 */ { "sty", 2, flUseLabel, OH_DirectX }, /* $94 */ { "sta", 2, flUseLabel, OH_DirectX }, /* $95 */ { "stx", 2, flUseLabel, OH_DirectY }, /* $96 */ { "", 1, flIllegal, OH_Illegal, }, /* $97 */ { "tya", 1, flNone, OH_Implicit }, /* $98 */ { "sta", 3, flUseLabel, OH_AbsoluteY }, /* $99 */ { "txs", 1, flNone, OH_Implicit }, /* $9a */ { "", 1, flIllegal, OH_Illegal, }, /* $9b */ { "stz", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $9c */ { "sta", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $9d */ { "stz", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $9e */ { "", 1, flIllegal, OH_Illegal, }, /* $9f */ { "ldy", 2, flNone, OH_Immediate }, /* $a0 */ { "lda", 2, flUseLabel, OH_DirectXIndirect }, /* $a1 */ { "ldx", 2, flNone, OH_Immediate }, /* $a2 */ { "", 1, flIllegal, OH_Illegal, }, /* $a3 */ { "ldy", 2, flUseLabel, OH_Direct }, /* $a4 */ { "lda", 2, flUseLabel, OH_Direct }, /* $a5 */ { "ldx", 2, flUseLabel, OH_Direct }, /* $a6 */ { "", 1, flIllegal, OH_Illegal, }, /* $a7 */ { "tay", 1, flNone, OH_Implicit }, /* $a8 */ { "lda", 2, flNone, OH_Immediate }, /* $a9 */ { "tax", 1, flNone, OH_Implicit }, /* $aa */ { "", 1, flIllegal, OH_Illegal, }, /* $ab */ { "ldy", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ac */ { "lda", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ad */ { "ldx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ae */ { "", 1, flIllegal, OH_Illegal, }, /* $af */ { "bcs", 2, flLabel, OH_Relative }, /* $b0 */ { "lda", 2, flUseLabel, OH_DirectIndirectY }, /* $b1 */ { "lda", 2, flUseLabel, OH_DirectIndirect }, /* $b2 */ { "", 1, flIllegal, OH_Illegal, }, /* $b3 */ { "ldy", 2, flUseLabel, OH_DirectX }, /* $b4 */ { "lda", 2, flUseLabel, OH_DirectX }, /* $b5 */ { "ldx", 2, flUseLabel, OH_DirectY }, /* $b6 */ { "", 1, flIllegal, OH_Illegal, }, /* $b7 */ { "clv", 1, flNone, OH_Implicit }, /* $b8 */ { "lda", 3, flUseLabel, OH_AbsoluteY }, /* $b9 */ { "tsx", 1, flNone, OH_Implicit }, /* $ba */ { "", 1, flIllegal, OH_Illegal, }, /* $bb */ { "ldy", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $bc */ { "lda", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $bd */ { "ldx", 3, flUseLabel|flAbsOverride, OH_AbsoluteY }, /* $be */ { "", 1, flIllegal, OH_Illegal, }, /* $bf */ { "cpy", 2, flNone, OH_Immediate }, /* $c0 */ { "cmp", 2, flUseLabel, OH_DirectXIndirect }, /* $c1 */ { "", 1, flIllegal, OH_Illegal, }, /* $c2 */ { "", 1, flIllegal, OH_Illegal, }, /* $c3 */ { "cpy", 2, flUseLabel, OH_Direct }, /* $c4 */ { "cmp", 2, flUseLabel, OH_Direct }, /* $c5 */ { "dec", 2, flUseLabel, OH_Direct }, /* $c6 */ { "", 1, flIllegal, OH_Illegal, }, /* $c7 */ { "iny", 1, flNone, OH_Implicit }, /* $c8 */ { "cmp", 2, flNone, OH_Immediate }, /* $c9 */ { "dex", 1, flNone, OH_Implicit }, /* $ca */ { "", 1, flIllegal, OH_Illegal, }, /* $cb */ { "cpy", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $cc */ { "cmp", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $cd */ { "dec", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ce */ { "", 1, flIllegal, OH_Illegal, }, /* $cf */ { "bne", 2, flLabel, OH_Relative }, /* $d0 */ { "cmp", 2, flUseLabel, OH_DirectIndirectY }, /* $d1 */ { "cmp", 2, flUseLabel, OH_DirectIndirect }, /* $d2 */ { "", 1, flIllegal, OH_Illegal, }, /* $d3 */ { "", 1, flIllegal, OH_Illegal, }, /* $d4 */ { "cmp", 2, flUseLabel, OH_DirectX }, /* $d5 */ { "dec", 2, flUseLabel, OH_DirectX }, /* $d6 */ { "", 1, flIllegal, OH_Illegal, }, /* $d7 */ { "cld", 1, flNone, OH_Implicit }, /* $d8 */ { "cmp", 3, flUseLabel, OH_AbsoluteY }, /* $d9 */ { "phx", 1, flNone, OH_Implicit }, /* $da */ { "", 1, flIllegal, OH_Illegal, }, /* $db */ { "", 1, flIllegal, OH_Illegal, }, /* $dc */ { "cmp", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $dd */ { "dec", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $de */ { "", 1, flIllegal, OH_Illegal, }, /* $df */ { "cpx", 2, flNone, OH_Immediate }, /* $e0 */ { "sbc", 2, flUseLabel, OH_DirectXIndirect }, /* $e1 */ { "", 1, flIllegal, OH_Illegal, }, /* $e2 */ { "", 1, flIllegal, OH_Illegal, }, /* $e3 */ { "cpx", 2, flUseLabel, OH_Direct }, /* $e4 */ { "sbc", 2, flUseLabel, OH_Direct }, /* $e5 */ { "inc", 2, flUseLabel, OH_Direct }, /* $e6 */ { "", 1, flIllegal, OH_Illegal, }, /* $e7 */ { "inx", 1, flNone, OH_Implicit }, /* $e8 */ { "sbc", 2, flNone, OH_Immediate }, /* $e9 */ { "nop", 1, flNone, OH_Implicit }, /* $ea */ { "", 1, flIllegal, OH_Illegal, }, /* $eb */ { "cpx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ec */ { "sbc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ed */ { "inc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ee */ { "", 1, flIllegal, OH_Illegal, }, /* $ef */ { "beq", 2, flLabel, OH_Relative }, /* $f0 */ { "sbc", 2, flUseLabel, OH_DirectIndirectY }, /* $f1 */ { "sbc", 2, flUseLabel, OH_DirectIndirect }, /* $f2 */ { "", 1, flIllegal, OH_Illegal, }, /* $f3 */ { "", 1, flIllegal, OH_Illegal, }, /* $f4 */ { "sbc", 2, flUseLabel, OH_DirectX }, /* $f5 */ { "inc", 2, flUseLabel, OH_DirectX }, /* $f6 */ { "", 1, flIllegal, OH_Illegal, }, /* $f7 */ { "sed", 1, flNone, OH_Implicit }, /* $f8 */ { "sbc", 3, flUseLabel, OH_AbsoluteY }, /* $f9 */ { "plx", 1, flNone, OH_Implicit }, /* $fa */ { "", 1, flIllegal, OH_Illegal, }, /* $fb */ { "", 1, flIllegal, OH_Illegal, }, /* $fc */ { "sbc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fd */ { "inc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fe */ { "", 1, flIllegal, OH_Illegal, }, /* $ff */ }; �����������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/opc65sc02.h����������������������������������������������������������������������0000664�0000000�0000000�00000005653�13473601511�0015341�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* opc65sc02.h */ /* */ /* 65SC02 opcode description table */ /* */ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef OPC65SC02_H #define OPC65SC02_H #include "opcdesc.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Descriptions for all opcodes */ extern const OpcDesc OpcTable_65SC02[256]; /* End of opc65sc02.h */ #endif �������������������������������������������������������������������������������������cc65-2.18/src/da65/opcdesc.h������������������������������������������������������������������������0000664�0000000�0000000�00000007611�13473601511�0015331�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* opcdesc.h */ /* */ /* Disassembler description for one opcode */ /* */ /* */ /* */ /* (C) 2000-2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef OPCDESC_H #define OPCDESC_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Constants for Flags */ enum { flNone = 0x00, /* No flags given */ flNoLabel = 0x00, /* Don't use a label */ flGenLabel = 0x01, /* Generate a label */ flUseLabel = 0x02, /* Use a label if there is one */ flLabel = flUseLabel|flGenLabel, /* Generate and use a label */ flIllegal = 0x10, /* Illegal instruction */ flAbsOverride = 0x20, /* Need a: override */ flFarOverride = 0x40 /* Need f: override */ }; /* Forward/typedef for struct OpcDesc */ typedef struct OpcDesc OpcDesc; /* Type of pointer to a function that handles opcode output */ typedef void (*OpcHandler) (const OpcDesc*); /* Description for one opcode */ struct OpcDesc { char Mnemo [6]; /* Mnemonic */ unsigned char Size; /* Size of this command */ unsigned char Flags; /* Flags */ OpcHandler Handler; /* Handler routine */ }; /* End of opcdesc.h */ #endif �����������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/opchuc6280.c���������������������������������������������������������������������0000664�0000000�0000000�00000057577�13473601511�0015525�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* opchuc6280.c */ /* */ /* HuC6280 opcode description table */ /* */ /* */ /* */ /* (C) 2003-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* da65 */ #include "handler.h" #include "opchuc6280.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Descriptions for all opcodes */ const OpcDesc OpcTable_HuC6280[256] = { { "brk", 1, flNone, OH_Implicit }, /* $00 */ { "ora", 2, flUseLabel, OH_DirectXIndirect }, /* $01 */ { "sxy", 1, flNone, OH_Implicit, }, /* $02 */ { "st0", 2, flNone, OH_Immediate, }, /* $03 */ { "tsb", 2, flUseLabel, OH_Direct }, /* $04 */ { "ora", 2, flUseLabel, OH_Direct }, /* $05 */ { "asl", 2, flUseLabel, OH_Direct }, /* $06 */ { "rmb0", 2, flUseLabel, OH_Direct, }, /* $07 */ { "php", 1, flNone, OH_Implicit }, /* $08 */ { "ora", 2, flNone, OH_Immediate }, /* $09 */ { "asl", 1, flNone, OH_Accumulator }, /* $0a */ { "", 1, flIllegal, OH_Illegal, }, /* $0b */ { "tsb", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0c */ { "ora", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0d */ { "asl", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0e */ { "bbr0", 3, flUseLabel, OH_BitBranch }, /* $0f */ { "bpl", 2, flLabel, OH_Relative }, /* $10 */ { "ora", 2, flUseLabel, OH_DirectIndirectY }, /* $11 */ { "ora", 2, flUseLabel, OH_DirectIndirect }, /* $12 */ { "st1", 2, flNone, OH_Immediate, }, /* $13 */ { "trb", 2, flUseLabel, OH_Direct }, /* $14 */ { "ora", 2, flUseLabel, OH_DirectX }, /* $15 */ { "asl", 2, flUseLabel, OH_DirectX }, /* $16 */ { "rmb1", 2, flUseLabel, OH_Direct, }, /* $17 */ { "clc", 1, flNone, OH_Implicit }, /* $18 */ { "ora", 3, flUseLabel, OH_AbsoluteY }, /* $19 */ { "inc", 1, flNone, OH_Accumulator }, /* $1a */ { "", 1, flIllegal, OH_Illegal, }, /* $1b */ { "trb", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $1c */ { "ora", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1d */ { "asl", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1e */ { "bbr1", 3, flUseLabel, OH_BitBranch }, /* $1f */ { "jsr", 3, flLabel, OH_Absolute }, /* $20 */ { "and", 2, flUseLabel, OH_DirectXIndirect }, /* $21 */ { "sax", 1, flNone, OH_Implicit, }, /* $22 */ { "st2", 2, flNone, OH_Immediate, }, /* $23 */ { "bit", 2, flUseLabel, OH_Direct }, /* $24 */ { "and", 2, flUseLabel, OH_Direct }, /* $25 */ { "rol", 2, flUseLabel, OH_Direct }, /* $26 */ { "rmb2", 2, flUseLabel, OH_Direct, }, /* $27 */ { "plp", 1, flNone, OH_Implicit }, /* $28 */ { "and", 2, flNone, OH_Immediate }, /* $29 */ { "rol", 1, flNone, OH_Accumulator }, /* $2a */ { "", 1, flIllegal, OH_Illegal, }, /* $2b */ { "bit", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2c */ { "and", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2d */ { "rol", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2e */ { "bbr2", 3, flUseLabel, OH_BitBranch }, /* $2f */ { "bmi", 2, flLabel, OH_Relative }, /* $30 */ { "and", 2, flUseLabel, OH_DirectIndirectY }, /* $31 */ { "and", 2, flUseLabel, OH_DirectIndirect, }, /* $32 */ { "", 1, flIllegal, OH_Illegal, }, /* $33 */ { "bit", 2, flUseLabel, OH_DirectX }, /* $34 */ { "and", 2, flUseLabel, OH_DirectX }, /* $35 */ { "rol", 2, flUseLabel, OH_DirectX }, /* $36 */ { "rmb3", 2, flUseLabel, OH_Direct, }, /* $37 */ { "sec", 1, flNone, OH_Implicit }, /* $38 */ { "and", 3, flUseLabel, OH_AbsoluteY }, /* $39 */ { "dec", 1, flNone, OH_Accumulator }, /* $3a */ { "", 1, flIllegal, OH_Illegal, }, /* $3b */ { "bit", 3, flUseLabel, OH_AbsoluteX }, /* $3c */ { "and", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $3d */ { "rol", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $3e */ { "bbr3", 3, flUseLabel, OH_BitBranch }, /* $3f */ { "rti", 1, flNone, OH_Rts }, /* $40 */ { "eor", 2, flUseLabel, OH_DirectXIndirect }, /* $41 */ { "say", 1, flNone, OH_Implicit, }, /* $42 */ { "tma", 2, flNone, OH_Immediate, }, /* $43 */ { "bsr", 2, flLabel, OH_Relative, }, /* $44 */ { "eor", 2, flUseLabel, OH_Direct }, /* $45 */ { "lsr", 2, flUseLabel, OH_Direct }, /* $46 */ { "rmb4", 2, flUseLabel, OH_Direct, }, /* $47 */ { "pha", 1, flNone, OH_Implicit }, /* $48 */ { "eor", 2, flNone, OH_Immediate }, /* $49 */ { "lsr", 1, flNone, OH_Accumulator }, /* $4a */ { "", 1, flIllegal, OH_Illegal, }, /* $4b */ { "jmp", 3, flLabel, OH_JmpAbsolute }, /* $4c */ { "eor", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $4d */ { "lsr", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $4e */ { "bbr4", 3, flUseLabel, OH_BitBranch }, /* $4f */ { "bvc", 2, flLabel, OH_Relative }, /* $50 */ { "eor", 2, flUseLabel, OH_DirectIndirectY }, /* $51 */ { "eor", 2, flUseLabel, OH_DirectIndirect }, /* $52 */ { "tam", 2, flNone, OH_Immediate, }, /* $53 */ { "csl", 1, flNone, OH_Implicit, }, /* $54 */ { "eor", 2, flUseLabel, OH_DirectX }, /* $55 */ { "lsr", 2, flUseLabel, OH_DirectX }, /* $56 */ { "rmb5", 2, flUseLabel, OH_Direct, }, /* $57 */ { "cli", 1, flNone, OH_Implicit }, /* $58 */ { "eor", 3, flUseLabel, OH_AbsoluteY }, /* $59 */ { "phy", 1, flNone, OH_Implicit }, /* $5a */ { "", 1, flIllegal, OH_Illegal, }, /* $5b */ { "", 1, flIllegal, OH_Illegal, }, /* $5c */ { "eor", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $5d */ { "lsr", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $5e */ { "bbr5", 3, flUseLabel, OH_BitBranch }, /* $5f */ { "rts", 1, flNone, OH_Rts }, /* $60 */ { "adc", 2, flUseLabel, OH_DirectXIndirect }, /* $61 */ { "cla", 1, flNone, OH_Implicit, }, /* $62 */ { "", 1, flIllegal, OH_Illegal, }, /* $63 */ { "stz", 2, flUseLabel, OH_Direct }, /* $64 */ { "adc", 2, flUseLabel, OH_Direct }, /* $65 */ { "ror", 2, flUseLabel, OH_Direct }, /* $66 */ { "rmb6", 2, flUseLabel, OH_Direct, }, /* $67 */ { "pla", 1, flNone, OH_Implicit }, /* $68 */ { "adc", 2, flNone, OH_Immediate }, /* $69 */ { "ror", 1, flNone, OH_Accumulator }, /* $6a */ { "", 1, flIllegal, OH_Illegal, }, /* $6b */ { "jmp", 3, flLabel, OH_JmpAbsoluteIndirect }, /* $6c */ { "adc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $6d */ { "ror", 3, flUseLabel, OH_Absolute }, /* $6e */ { "bbr6", 3, flUseLabel, OH_BitBranch }, /* $6f */ { "bvs", 2, flLabel, OH_Relative }, /* $70 */ { "adc", 2, flUseLabel, OH_DirectIndirectY }, /* $71 */ { "adc", 2, flUseLabel, OH_DirectIndirect, }, /* $72 */ { "tii", 7, flNone, OH_BlockMove, }, /* $73 */ { "stz", 2, flUseLabel, OH_DirectX }, /* $74 */ { "adc", 2, flUseLabel, OH_DirectX }, /* $75 */ { "ror", 2, flUseLabel, OH_DirectX }, /* $76 */ { "rmb7", 2, flUseLabel, OH_Direct, }, /* $77 */ { "sei", 1, flNone, OH_Implicit }, /* $78 */ { "adc", 3, flUseLabel, OH_AbsoluteY }, /* $79 */ { "ply", 1, flNone, OH_Implicit }, /* $7a */ { "", 1, flIllegal, OH_Illegal, }, /* $7b */ { "jmp", 3, flLabel, OH_JmpAbsoluteXIndirect }, /* $7c */ { "adc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $7d */ { "ror", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $7e */ { "bbr7", 3, flUseLabel, OH_BitBranch }, /* $7f */ { "bra", 2, flLabel, OH_Relative }, /* $80 */ { "sta", 2, flUseLabel, OH_DirectXIndirect }, /* $81 */ { "clx", 1, flNone, OH_Implicit, }, /* $82 */ { "tst", 3, flNone, OH_ImmediateDirect, }, /* $83 */ { "sty", 2, flUseLabel, OH_Direct }, /* $84 */ { "sta", 2, flUseLabel, OH_Direct }, /* $85 */ { "stx", 2, flUseLabel, OH_Direct }, /* $86 */ { "smb0", 2, flUseLabel, OH_Direct, }, /* $87 */ { "dey", 1, flNone, OH_Implicit }, /* $88 */ { "bit", 2, flNone, OH_Immediate }, /* $89 */ { "txa", 1, flNone, OH_Implicit }, /* $8a */ { "", 1, flIllegal, OH_Illegal, }, /* $8b */ { "sty", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8c */ { "sta", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8d */ { "stx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8e */ { "bbs0", 3, flUseLabel, OH_BitBranch }, /* $8f */ { "bcc", 2, flLabel, OH_Relative }, /* $90 */ { "sta", 2, flUseLabel, OH_DirectIndirectY }, /* $91 */ { "sta", 2, flUseLabel, OH_DirectIndirect }, /* $92 */ { "tst", 4, flNone, OH_ImmediateAbsolute, }, /* $93 */ { "sty", 2, flUseLabel, OH_DirectX }, /* $94 */ { "sta", 2, flUseLabel, OH_DirectX }, /* $95 */ { "stx", 2, flUseLabel, OH_DirectY }, /* $96 */ { "smb1", 2, flUseLabel, OH_Direct, }, /* $97 */ { "tya", 1, flNone, OH_Implicit }, /* $98 */ { "sta", 3, flUseLabel, OH_AbsoluteY }, /* $99 */ { "txs", 1, flNone, OH_Implicit }, /* $9a */ { "", 1, flIllegal, OH_Illegal, }, /* $9b */ { "stz", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $9c */ { "sta", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $9d */ { "stz", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $9e */ { "bbs1", 3, flUseLabel, OH_BitBranch }, /* $9f */ { "ldy", 2, flNone, OH_Immediate }, /* $a0 */ { "lda", 2, flUseLabel, OH_DirectXIndirect }, /* $a1 */ { "ldx", 2, flNone, OH_Immediate }, /* $a2 */ { "tst", 3, flNone, OH_ImmediateDirectX, }, /* $a3 */ { "ldy", 2, flUseLabel, OH_Direct }, /* $a4 */ { "lda", 2, flUseLabel, OH_Direct }, /* $a5 */ { "ldx", 2, flUseLabel, OH_Direct }, /* $a6 */ { "smb2", 2, flUseLabel, OH_Direct, }, /* $a7 */ { "tay", 1, flNone, OH_Implicit }, /* $a8 */ { "lda", 2, flNone, OH_Immediate }, /* $a9 */ { "tax", 1, flNone, OH_Implicit }, /* $aa */ { "", 1, flIllegal, OH_Illegal, }, /* $ab */ { "ldy", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ac */ { "lda", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ad */ { "ldx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ae */ { "bbs2", 3, flUseLabel, OH_BitBranch }, /* $af */ { "bcs", 2, flLabel, OH_Relative }, /* $b0 */ { "lda", 2, flUseLabel, OH_DirectIndirectY }, /* $b1 */ { "lda", 2, flUseLabel, OH_DirectIndirect }, /* $b2 */ { "tst", 4, flNone, OH_ImmediateAbsoluteX, }, /* $b3 */ { "ldy", 2, flUseLabel, OH_DirectX }, /* $b4 */ { "lda", 2, flUseLabel, OH_DirectX }, /* $b5 */ { "ldx", 2, flUseLabel, OH_DirectY }, /* $b6 */ { "smb3", 2, flUseLabel, OH_Direct, }, /* $b7 */ { "clv", 1, flNone, OH_Implicit }, /* $b8 */ { "lda", 3, flUseLabel, OH_AbsoluteY }, /* $b9 */ { "tsx", 1, flNone, OH_Implicit }, /* $ba */ { "", 1, flIllegal, OH_Illegal, }, /* $bb */ { "ldy", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $bc */ { "lda", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $bd */ { "ldx", 3, flUseLabel|flAbsOverride, OH_AbsoluteY }, /* $be */ { "bbs3", 3, flUseLabel, OH_BitBranch }, /* $bf */ { "cpy", 2, flNone, OH_Immediate }, /* $c0 */ { "cmp", 2, flUseLabel, OH_DirectXIndirect }, /* $c1 */ { "cly", 1, flNone, OH_Implicit, }, /* $c2 */ { "tdd", 7, flNone, OH_BlockMove, }, /* $c3 */ { "cpy", 2, flUseLabel, OH_Direct }, /* $c4 */ { "cmp", 2, flUseLabel, OH_Direct }, /* $c5 */ { "dec", 2, flUseLabel, OH_Direct }, /* $c6 */ { "smb4", 2, flUseLabel, OH_Direct, }, /* $c7 */ { "iny", 1, flNone, OH_Implicit }, /* $c8 */ { "cmp", 2, flNone, OH_Immediate }, /* $c9 */ { "dex", 1, flNone, OH_Implicit }, /* $ca */ { "", 1, flIllegal, OH_Illegal, }, /* $cb */ { "cpy", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $cc */ { "cmp", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $cd */ { "dec", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ce */ { "bbs4", 3, flUseLabel, OH_BitBranch }, /* $cf */ { "bne", 2, flLabel, OH_Relative }, /* $d0 */ { "cmp", 2, flUseLabel, OH_DirectIndirectY }, /* $d1 */ { "cmp", 2, flUseLabel, OH_DirectIndirect }, /* $d2 */ { "tin", 7, flNone, OH_BlockMove, }, /* $d3 */ { "csh", 1, flNone, OH_Implicit, }, /* $d4 */ { "cmp", 2, flUseLabel, OH_DirectX }, /* $d5 */ { "dec", 2, flUseLabel, OH_DirectX }, /* $d6 */ { "smb5", 2, flUseLabel, OH_Direct, }, /* $d7 */ { "cld", 1, flNone, OH_Implicit }, /* $d8 */ { "cmp", 3, flUseLabel, OH_AbsoluteY }, /* $d9 */ { "phx", 1, flNone, OH_Implicit }, /* $da */ { "", 1, flIllegal, OH_Illegal, }, /* $db */ { "", 1, flIllegal, OH_Illegal, }, /* $dc */ { "cmp", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $dd */ { "dec", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $de */ { "bbs5", 3, flUseLabel, OH_BitBranch }, /* $df */ { "cpx", 2, flNone, OH_Immediate }, /* $e0 */ { "sbc", 2, flUseLabel, OH_DirectXIndirect }, /* $e1 */ { "", 1, flIllegal, OH_Illegal, }, /* $e2 */ { "tia", 7, flNone, OH_BlockMove, }, /* $e3 */ { "cpx", 2, flUseLabel, OH_Direct }, /* $e4 */ { "sbc", 2, flUseLabel, OH_Direct }, /* $e5 */ { "inc", 2, flUseLabel, OH_Direct }, /* $e6 */ { "smb6", 2, flUseLabel, OH_Direct, }, /* $e7 */ { "inx", 1, flNone, OH_Implicit }, /* $e8 */ { "sbc", 2, flNone, OH_Immediate }, /* $e9 */ { "nop", 1, flNone, OH_Implicit }, /* $ea */ { "", 1, flIllegal, OH_Illegal, }, /* $eb */ { "cpx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ec */ { "sbc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ed */ { "inc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ee */ { "bbs6", 3, flUseLabel, OH_BitBranch }, /* $ef */ { "beq", 2, flLabel, OH_Relative }, /* $f0 */ { "sbc", 2, flUseLabel, OH_DirectIndirectY }, /* $f1 */ { "sbc", 2, flUseLabel, OH_DirectIndirect }, /* $f2 */ { "tai", 7, flNone, OH_BlockMove, }, /* $f3 */ { "set", 1, flNone, OH_Implicit, }, /* $f4 */ { "sbc", 2, flUseLabel, OH_DirectX }, /* $f5 */ { "inc", 2, flUseLabel, OH_DirectX }, /* $f6 */ { "smb7", 2, flUseLabel, OH_Direct, }, /* $f7 */ { "sed", 1, flNone, OH_Implicit }, /* $f8 */ { "sbc", 3, flUseLabel, OH_AbsoluteY }, /* $f9 */ { "plx", 1, flNone, OH_Implicit }, /* $fa */ { "", 1, flIllegal, OH_Illegal, }, /* $fb */ { "", 1, flIllegal, OH_Illegal, }, /* $fc */ { "sbc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fd */ { "inc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fe */ { "bbs7", 3, flUseLabel, OH_BitBranch }, /* $ff */ }; ���������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/opchuc6280.h���������������������������������������������������������������������0000664�0000000�0000000�00000005657�13473601511�0015522�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* opchuc6280.h */ /* */ /* HuC6280 opcode description table */ /* */ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ /* R?merstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef OPCHUC6280_H #define OPCHUC6280_H #include "opcdesc.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Descriptions for all opcodes */ extern const OpcDesc OpcTable_HuC6280[256]; /* End of opchuc6280.h */ #endif ���������������������������������������������������������������������������������cc65-2.18/src/da65/opcm740.c������������������������������������������������������������������������0000664�0000000�0000000�00000057711�13473601511�0015103�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* opcm740.c */ /* */ /* Mitsubishi 740 series opcode description table */ /* */ /* A contribution from Chris Baird */ /* EMail: cjb@brushtail.apana.org.au */ /* */ /* (C) 2003-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* da65 */ #include "handler.h" #include "opcm740.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Descriptions for all opcodes */ const OpcDesc OpcTable_M740[256] = { { "brk", 1, flNone, OH_Implicit }, /* $00 */ { "ora", 2, flUseLabel, OH_DirectXIndirect }, /* $01 */ { "jsr", 2, flLabel, OH_JmpDirectIndirect }, /* $02 */ { "bbs", 2, flUseLabel, OH_AccumulatorBitBranch }, /* $03 */ { "", 1, flIllegal, OH_Illegal }, /* $04 */ { "ora", 2, flUseLabel, OH_Direct }, /* $05 */ { "asl", 2, flUseLabel, OH_Direct }, /* $06 */ { "bbs", 3, flUseLabel, OH_ZeroPageBit }, /* $07 */ { "php", 1, flNone, OH_Implicit }, /* $08 */ { "ora", 2, flNone, OH_Immediate }, /* $09 */ { "asl", 1, flNone, OH_Accumulator }, /* $0a */ { "seb", 1, flNone, OH_AccumulatorBit }, /* $0b */ { "", 1, flIllegal, OH_Illegal, }, /* $0c */ { "ora", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0d */ { "asl", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0e */ { "seb", 2, flUseLabel, OH_ZeroPageBit }, /* $0f */ { "bpl", 2, flLabel, OH_Relative }, /* $10 */ { "ora", 2, flUseLabel, OH_DirectIndirectY }, /* $11 */ { "clt", 1, flNone, OH_Implicit }, /* $12 */ { "bbc", 2, flUseLabel, OH_AccumulatorBitBranch }, /* $13 */ { "", 1, flIllegal, OH_Illegal }, /* $14 */ { "ora", 2, flUseLabel, OH_DirectX }, /* $15 */ { "asl", 2, flUseLabel, OH_DirectX }, /* $16 */ { "bbc", 3, flUseLabel, OH_ZeroPageBit }, /* $17 */ { "clc", 1, flNone, OH_Implicit }, /* $18 */ { "ora", 3, flUseLabel, OH_AbsoluteY }, /* $19 */ { "dec", 1, flNone, OH_Accumulator }, /* $1a */ { "clb", 1, flNone, OH_AccumulatorBit }, /* $1b */ { "", 1, flIllegal, OH_Illegal }, /* $1c */ { "ora", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1d */ { "asl", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1e */ { "clb", 2, flUseLabel, OH_ZeroPageBit }, /* $1f */ { "jsr", 3, flLabel, OH_Absolute }, /* $20 */ { "and", 2, flUseLabel, OH_DirectXIndirect }, /* $21 */ { "jsr", 2, flLabel, OH_SpecialPage }, /* $22 */ { "bbs", 2, flUseLabel, OH_AccumulatorBitBranch }, /* $23 */ { "bit", 2, flUseLabel, OH_Direct }, /* $24 */ { "and", 2, flUseLabel, OH_Direct }, /* $25 */ { "rol", 2, flUseLabel, OH_Direct }, /* $26 */ { "bbs", 3, flUseLabel, OH_ZeroPageBit }, /* $27 */ { "plp", 1, flNone, OH_Implicit }, /* $28 */ { "and", 2, flNone, OH_Immediate }, /* $29 */ { "rol", 1, flNone, OH_Accumulator }, /* $2a */ { "seb", 1, flNone, OH_AccumulatorBit }, /* $2b */ { "bit", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2c */ { "and", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2d */ { "rol", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2e */ { "seb", 2, flUseLabel, OH_ZeroPageBit }, /* $2f */ { "bmi", 2, flLabel, OH_Relative }, /* $30 */ { "and", 2, flUseLabel, OH_DirectIndirectY }, /* $31 */ { "set", 1, flNone, OH_Implicit }, /* $32 */ { "bbc", 2, flUseLabel, OH_AccumulatorBitBranch }, /* $33 */ { "", 1, flIllegal, OH_Illegal }, /* $34 */ { "and", 2, flUseLabel, OH_DirectX }, /* $35 */ { "rol", 2, flUseLabel, OH_DirectX }, /* $36 */ { "bbc", 3, flUseLabel, OH_ZeroPageBit }, /* $37 */ { "sec", 1, flNone, OH_Implicit }, /* $38 */ { "and", 3, flUseLabel, OH_AbsoluteY }, /* $39 */ { "inc", 1, flNone, OH_Accumulator }, /* $3a */ { "clb", 1, flNone, OH_AccumulatorBit }, /* $3b */ { "ldm", 3, flLabel, OH_DirectImmediate }, /* $3c */ { "and", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $3d */ { "rol", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $3e */ { "clb", 2, flUseLabel, OH_ZeroPageBit }, /* $3f */ { "rti", 1, flNone, OH_Rts }, /* $40 */ { "eor", 2, flUseLabel, OH_DirectXIndirect }, /* $41 */ { "stp", 1, flNone, OH_Implicit }, /* $42 */ { "bbs", 2, flUseLabel, OH_AccumulatorBitBranch }, /* $43 */ { "com", 2, flUseLabel, OH_Direct }, /* $44 */ { "eor", 2, flUseLabel, OH_Direct }, /* $45 */ { "lsr", 2, flUseLabel, OH_Direct }, /* $46 */ { "bbs", 3, flUseLabel, OH_ZeroPageBit }, /* $47 */ { "pha", 1, flNone, OH_Implicit }, /* $48 */ { "eor", 2, flNone, OH_Immediate }, /* $49 */ { "lsr", 1, flNone, OH_Accumulator }, /* $4a */ { "seb", 1, flNone, OH_AccumulatorBit }, /* $4b */ { "jmp", 3, flLabel, OH_JmpAbsolute }, /* $4c */ { "eor", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $4d */ { "lsr", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $4e */ { "seb", 2, flUseLabel, OH_ZeroPageBit }, /* $4f */ { "bvc", 2, flLabel, OH_Relative }, /* $50 */ { "eor", 2, flUseLabel, OH_DirectIndirectY }, /* $51 */ { "", 1, flIllegal, OH_Illegal }, /* $52 */ { "bbc", 2, flUseLabel, OH_AccumulatorBitBranch }, /* $53 */ { "", 1, flIllegal, OH_Illegal }, /* $54 */ { "eor", 2, flUseLabel, OH_DirectX }, /* $55 */ { "lsr", 2, flUseLabel, OH_DirectX }, /* $56 */ { "bbc", 3, flUseLabel, OH_ZeroPageBit }, /* $57 */ { "cli", 1, flNone, OH_Implicit }, /* $58 */ { "eor", 3, flUseLabel, OH_AbsoluteY }, /* $59 */ { "", 1, flIllegal, OH_Illegal }, /* $5a */ { "clb", 1, flNone, OH_AccumulatorBit }, /* $5b */ { "", 1, flIllegal, OH_Illegal }, /* $5c */ { "eor", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $5d */ { "lsr", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $5e */ { "clb", 2, flUseLabel, OH_ZeroPageBit }, /* $5f */ { "rts", 1, flNone, OH_Rts }, /* $60 */ { "adc", 2, flUseLabel, OH_DirectXIndirect }, /* $61 */ { "mul", 2, flUseLabel, OH_DirectX }, /* $62 */ { "bbs", 2, flUseLabel, OH_AccumulatorBitBranch }, /* $63 */ { "tst", 2, flUseLabel, OH_Direct }, /* $64 */ { "adc", 2, flUseLabel, OH_Direct }, /* $65 */ { "ror", 2, flUseLabel, OH_Direct }, /* $66 */ { "bbs", 3, flUseLabel, OH_ZeroPageBit }, /* $67 */ { "pla", 1, flNone, OH_Implicit }, /* $68 */ { "adc", 2, flNone, OH_Immediate }, /* $69 */ { "ror", 1, flNone, OH_Accumulator }, /* $6a */ { "seb", 1, flNone, OH_AccumulatorBit }, /* $6b */ { "jmp", 3, flLabel, OH_JmpAbsoluteIndirect }, /* $6c */ { "adc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $6d */ { "ror", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $6e */ { "seb", 2, flUseLabel, OH_ZeroPageBit }, /* $6f */ { "bvs", 2, flLabel, OH_Relative }, /* $70 */ { "adc", 2, flUseLabel, OH_DirectIndirectY }, /* $71 */ { "", 1, flIllegal, OH_Illegal }, /* $72 */ { "bbc", 2, flUseLabel, OH_AccumulatorBitBranch }, /* $73 */ { "", 1, flIllegal, OH_Illegal }, /* $74 */ { "adc", 2, flUseLabel, OH_DirectX }, /* $75 */ { "ror", 2, flUseLabel, OH_DirectX }, /* $76 */ { "bbc", 3, flUseLabel, OH_ZeroPageBit }, /* $77 */ { "sei", 1, flNone, OH_Implicit }, /* $78 */ { "adc", 3, flUseLabel, OH_AbsoluteY }, /* $79 */ { "", 1, flIllegal, OH_Illegal }, /* $7a */ { "clb", 1, flNone, OH_AccumulatorBit }, /* $7b */ { "", 1, flIllegal, OH_Illegal }, /* $7c */ { "adc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $7d */ { "ror", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $7e */ { "clb", 2, flUseLabel, OH_ZeroPageBit }, /* $7f */ { "bra", 2, flLabel, OH_Relative }, /* $80 */ { "sta", 2, flUseLabel, OH_DirectXIndirect }, /* $81 */ { "rrf", 2, flLabel, OH_Direct }, /* $82 */ { "bbs", 2, flUseLabel, OH_AccumulatorBitBranch }, /* $83 */ { "sty", 2, flUseLabel, OH_Direct }, /* $84 */ { "sta", 2, flUseLabel, OH_Direct }, /* $85 */ { "stx", 2, flUseLabel, OH_Direct }, /* $86 */ { "bbs", 3, flUseLabel, OH_ZeroPageBit }, /* $87 */ { "dey", 1, flNone, OH_Implicit }, /* $88 */ { "", 1, flIllegal, OH_Illegal }, /* $89 */ { "txa", 1, flNone, OH_Implicit }, /* $8a */ { "seb", 1, flNone, OH_AccumulatorBit }, /* $8b */ { "sty", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8c */ { "sta", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8d */ { "stx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8e */ { "seb", 2, flUseLabel, OH_ZeroPageBit }, /* $8f */ { "bcc", 2, flLabel, OH_Relative }, /* $90 */ { "sta", 2, flUseLabel, OH_DirectIndirectY }, /* $91 */ { "", 1, flIllegal, OH_Illegal }, /* $92 */ { "bbc", 2, flUseLabel, OH_AccumulatorBitBranch }, /* $93 */ { "sty", 2, flUseLabel, OH_DirectX }, /* $94 */ { "sta", 2, flUseLabel, OH_DirectX }, /* $95 */ { "stx", 2, flUseLabel, OH_DirectY }, /* $96 */ { "bbc", 3, flUseLabel, OH_ZeroPageBit }, /* $97 */ { "tya", 1, flNone, OH_Implicit }, /* $98 */ { "sta", 3, flUseLabel, OH_AbsoluteY }, /* $99 */ { "txs", 1, flNone, OH_Implicit }, /* $9a */ { "clb", 1, flNone, OH_AccumulatorBit }, /* $9b */ { "", 1, flIllegal, OH_Illegal }, /* $9c */ { "sta", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $9d */ { "", 1, flIllegal, OH_Illegal }, /* $9e */ { "clb", 2, flUseLabel, OH_ZeroPageBit }, /* $9f */ { "ldy", 2, flNone, OH_Immediate }, /* $a0 */ { "lda", 2, flUseLabel, OH_DirectXIndirect }, /* $a1 */ { "ldx", 2, flNone, OH_Immediate }, /* $a2 */ { "bbs", 2, flUseLabel, OH_AccumulatorBitBranch }, /* $a3 */ { "ldy", 2, flUseLabel, OH_Direct }, /* $a4 */ { "lda", 2, flUseLabel, OH_Direct }, /* $a5 */ { "ldx", 2, flUseLabel, OH_Direct }, /* $a6 */ { "bbs", 3, flUseLabel, OH_ZeroPageBit }, /* $a7 */ { "tay", 1, flNone, OH_Implicit }, /* $a8 */ { "lda", 2, flNone, OH_Immediate }, /* $a9 */ { "tax", 1, flNone, OH_Implicit }, /* $aa */ { "seb", 1, flNone, OH_AccumulatorBit }, /* $ab */ { "ldy", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ac */ { "lda", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ad */ { "ldx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ae */ { "seb", 2, flUseLabel, OH_ZeroPageBit }, /* $af */ { "bcs", 2, flLabel, OH_Relative }, /* $b0 */ { "lda", 2, flUseLabel, OH_DirectIndirectY }, /* $b1 */ { "jmp", 2, flLabel, OH_JmpDirectIndirect }, /* $b2 */ { "bbc", 2, flUseLabel, OH_AccumulatorBitBranch }, /* $b3 */ { "ldy", 2, flUseLabel, OH_DirectX }, /* $b4 */ { "lda", 2, flUseLabel, OH_DirectX }, /* $b5 */ { "ldx", 2, flUseLabel, OH_DirectY }, /* $b6 */ { "bbc", 3, flUseLabel, OH_ZeroPageBit }, /* $b7 */ { "clv", 1, flNone, OH_Implicit }, /* $b8 */ { "lda", 3, flUseLabel, OH_AbsoluteY }, /* $b9 */ { "tsx", 1, flNone, OH_Implicit }, /* $ba */ { "clb", 1, flNone, OH_AccumulatorBit }, /* $bb */ { "ldy", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $bc */ { "lda", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $bd */ { "ldx", 3, flUseLabel|flAbsOverride, OH_AbsoluteY }, /* $be */ { "clb", 2, flUseLabel, OH_ZeroPageBit }, /* $bf */ { "cpy", 2, flNone, OH_Immediate }, /* $c0 */ { "cmp", 2, flUseLabel, OH_DirectXIndirect }, /* $c1 */ { "wit", 1, flNone, OH_Implicit, }, /* $c2 */ { "bbs", 2, flUseLabel, OH_AccumulatorBitBranch }, /* $c3 */ { "cpy", 2, flUseLabel, OH_Direct }, /* $c4 */ { "cmp", 2, flUseLabel, OH_Direct }, /* $c5 */ { "dec", 2, flUseLabel, OH_Direct }, /* $c6 */ { "bbs", 3, flUseLabel, OH_ZeroPageBit }, /* $c7 */ { "iny", 1, flNone, OH_Implicit }, /* $c8 */ { "cmp", 2, flNone, OH_Immediate }, /* $c9 */ { "dex", 1, flNone, OH_Implicit }, /* $ca */ { "seb", 1, flNone, OH_AccumulatorBit }, /* $cb */ { "cpy", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $cc */ { "cmp", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $cd */ { "dec", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ce */ { "seb", 2, flUseLabel, OH_ZeroPageBit }, /* $cf */ { "bne", 2, flLabel, OH_Relative }, /* $d0 */ { "cmp", 2, flUseLabel, OH_DirectIndirectY }, /* $d1 */ { "", 1, flIllegal, OH_Illegal }, /* $d2 */ { "bbc", 2, flUseLabel, OH_AccumulatorBitBranch }, /* $d3 */ { "", 1, flIllegal, OH_Illegal }, /* $d4 */ { "cmp", 2, flUseLabel, OH_DirectX }, /* $d5 */ { "dec", 2, flUseLabel, OH_DirectX }, /* $d6 */ { "bbc", 3, flUseLabel, OH_ZeroPageBit }, /* $d7 */ { "cld", 1, flNone, OH_Implicit }, /* $d8 */ { "cmp", 3, flUseLabel, OH_AbsoluteY }, /* $d9 */ { "", 1, flIllegal, OH_Illegal }, /* $da */ { "clb", 1, flNone, OH_AccumulatorBit }, /* $db */ { "", 1, flIllegal, OH_Illegal }, /* $dc */ { "cmp", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $dd */ { "dec", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $de */ { "clb", 2, flUseLabel, OH_ZeroPageBit }, /* $df */ { "cpx", 2, flNone, OH_Immediate }, /* $e0 */ { "sbc", 2, flUseLabel, OH_DirectXIndirect }, /* $e1 */ { "div", 2, flUseLabel, OH_DirectX }, /* $e2 */ { "bbs", 2, flUseLabel, OH_AccumulatorBitBranch }, /* $e3 */ { "cpx", 2, flUseLabel, OH_Direct }, /* $e4 */ { "sbc", 2, flUseLabel, OH_Direct }, /* $e5 */ { "inc", 2, flUseLabel, OH_Direct }, /* $e6 */ { "bbs", 3, flUseLabel, OH_ZeroPageBit }, /* $e7 */ { "inx", 1, flNone, OH_Implicit }, /* $e8 */ { "sbc", 2, flNone, OH_Immediate }, /* $e9 */ { "nop", 1, flNone, OH_Implicit }, /* $ea */ { "seb", 1, flNone, OH_AccumulatorBit }, /* $eb */ { "cpx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ec */ { "sbc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ed */ { "inc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ee */ { "seb", 2, flUseLabel, OH_ZeroPageBit }, /* $ef */ { "beq", 2, flLabel, OH_Relative }, /* $f0 */ { "sbc", 2, flUseLabel, OH_DirectIndirectY }, /* $f1 */ { "", 1, flIllegal, OH_Illegal }, /* $f2 */ { "bbc", 2, flUseLabel, OH_AccumulatorBitBranch }, /* $f3 */ { "", 1, flIllegal, OH_Illegal }, /* $f4 */ { "sbc", 2, flUseLabel, OH_DirectX }, /* $f5 */ { "inc", 2, flUseLabel, OH_DirectX }, /* $f6 */ { "bbc", 3, flUseLabel, OH_ZeroPageBit }, /* $f7 */ { "sed", 1, flNone, OH_Implicit }, /* $f8 */ { "sbc", 3, flUseLabel, OH_AbsoluteY }, /* $f9 */ { "", 1, flIllegal, OH_Illegal }, /* $fa */ { "clb", 1, flNone, OH_AccumulatorBit }, /* $fb */ { "", 1, flIllegal, OH_Illegal }, /* $fc */ { "sbc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fd */ { "inc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fe */ { "clb", 2, flUseLabel, OH_ZeroPageBit }, /* $ff */ }; �������������������������������������������������������cc65-2.18/src/da65/opcm740.h������������������������������������������������������������������������0000664�0000000�0000000�00000005763�13473601511�0015110�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* opcm740.h */ /* */ /* Mitsubishi 740 series opcode description table */ /* */ /* A contribution from Chris Baird */ /* EMail: cjb@brushtail.apana.org.au */ /* */ /* (C) 2003-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef OPCM740_H #define OPCM740_H #include "opcdesc.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Descriptions for all opcodes */ extern const OpcDesc OpcTable_M740[256]; /* End of opcm740.h */ #endif �������������cc65-2.18/src/da65/opctable.c�����������������������������������������������������������������������0000664�0000000�0000000�00000007574�13473601511�0015505�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* opctable.c */ /* */ /* Disassembler opcode description table */ /* */ /* */ /* */ /* (C) 2000-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* da65 */ #include "error.h" #include "opc4510.h" #include "opc6502.h" #include "opc6502x.h" #include "opc65816.h" #include "opc65c02.h" #include "opc65sc02.h" #include "opchuc6280.h" #include "opcm740.h" #include "opctable.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Descriptions for all opcodes */ const OpcDesc* OpcTable = OpcTable_6502; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void SetOpcTable (cpu_t CPU) /* Set the correct opcode table for the given CPU */ { switch (CPU) { case CPU_6502: OpcTable = OpcTable_6502; break; case CPU_6502X: OpcTable = OpcTable_6502X; break; case CPU_65SC02: OpcTable = OpcTable_65SC02; break; case CPU_65C02: OpcTable = OpcTable_65C02; break; case CPU_HUC6280: OpcTable = OpcTable_HuC6280; break; case CPU_M740: OpcTable = OpcTable_M740; break; case CPU_4510: OpcTable = OpcTable_4510; break; default: Error ("Unsupported CPU"); } } ������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/opctable.h�����������������������������������������������������������������������0000664�0000000�0000000�00000006424�13473601511�0015503�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* opctable.h */ /* */ /* Disassembler opcode description table */ /* */ /* */ /* */ /* (C) 2000-2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef OPCTABLE_H #define OPCTABLE_H /* common */ #include "cpu.h" /* da65 */ #include "opcdesc.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Descriptions for all opcodes */ extern const OpcDesc* OpcTable; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void SetOpcTable (cpu_t CPU); /* Set the correct opcode table for the given CPU */ /* End of opctable.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/output.c�������������������������������������������������������������������������0000664�0000000�0000000�00000023672�13473601511�0015251�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* output.c */ /* */ /* Disassembler output routines */ /* */ /* */ /* */ /* (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 */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdarg.h> #include <string.h> #include <ctype.h> #include <errno.h> /* common */ #include "addrsize.h" #include "cpu.h" #include "version.h" /* da65 */ #include "code.h" #include "error.h" #include "global.h" #include "output.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ static FILE* F = 0; /* Output stream */ 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 */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void PageHeader (void) /* Print a page header */ { fprintf (F, "; da65 V%s\n" "; Created: %s\n" "; Input file: %s\n" "; Page: %u\n\n", GetVersionAsString (), Now, InFile, Page); } void OpenOutput (const char* Name) /* Open the given file for output */ { /* If we have a name given, open the output file, otherwise use stdout */ if (Name != 0) { F = fopen (Name, "w"); if (F == 0) { Error ("Cannot open '%s': %s", Name, strerror (errno)); } } else { F = stdout; } /* Output the header and initialize stuff */ PageHeader (); Line = 5; Col = 1; } void CloseOutput (void) /* Close the output file */ { if (F != stdout && fclose (F) != 0) { Error ("Error closing output file: %s", strerror (errno)); } } void Output (const char* Format, ...) /* Write to the output file */ { if (Pass == PassCount) { va_list ap; va_start (ap, Format); Col += vfprintf (F, Format, ap); va_end (ap); } } void Indent (unsigned N) /* Make sure the current line column is at position N (zero based) */ { if (Pass == PassCount) { while (Col < N) { fputc (' ', F); ++Col; } } } void LineFeed (void) /* Add a linefeed to the output file */ { if (Pass == PassCount) { fputc ('\n', F); if (PageLength > 0 && ++Line >= PageLength) { if (FormFeeds) { fputc ('\f', F); } ++Page; PageHeader (); Line = 5; } Col = 1; } } void DefLabel (const char* Name) /* Define a label with the given name */ { Output ("%s:", Name); /* If the label is longer than the configured maximum, or if it runs into ** the opcode column, start a new line. */ if (Col > LBreak+2 || Col > MCol) { LineFeed (); } } void DefForward (const char* Name, const char* Comment, unsigned Offs) /* Define a label as "* + x", where x is the offset relative to the ** current PC. */ { if (Pass == PassCount) { /* Flush existing output if necessary */ if (Col > 1) { LineFeed (); } /* Output the forward definition */ Output ("%s", Name); Indent (ACol); if (UseHexOffs) { Output (":= * + $%04X", Offs); } else { Output (":= * + %u", Offs); } if (Comment) { Indent (CCol); Output ("; %s", Comment); } LineFeed (); } } void DefConst (const char* Name, const char* Comment, unsigned Addr) /* Define an address constant */ { if (Pass == PassCount) { Output ("%s", Name); Indent (ACol); Output (":= $%04X", Addr); if (Comment) { Indent (CCol); Output ("; %s", Comment); } LineFeed (); } } void DataByteLine (unsigned ByteCount) /* Output a line with bytes */ { unsigned I; Indent (MCol); Output (".byte"); Indent (ACol); for (I = 0; I < ByteCount; ++I) { if (I > 0) { Output (",$%02X", CodeBuf[PC+I]); } else { Output ("$%02X", CodeBuf[PC+I]); } } LineComment (PC, ByteCount); LineFeed (); } void DataDByteLine (unsigned ByteCount) /* Output a line with dbytes */ { unsigned I; Indent (MCol); Output (".dbyt"); Indent (ACol); for (I = 0; I < ByteCount; I += 2) { if (I > 0) { Output (",$%04X", GetCodeDByte (PC+I)); } else { Output ("$%04X", GetCodeDByte (PC+I)); } } LineComment (PC, ByteCount); LineFeed (); } void DataWordLine (unsigned ByteCount) /* Output a line with words */ { unsigned I; Indent (MCol); Output (".word"); Indent (ACol); for (I = 0; I < ByteCount; I += 2) { if (I > 0) { Output (",$%04X", GetCodeWord (PC+I)); } else { Output ("$%04X", GetCodeWord (PC+I)); } } LineComment (PC, ByteCount); LineFeed (); } void DataDWordLine (unsigned ByteCount) /* Output a line with dwords */ { unsigned I; Indent (MCol); Output (".dword"); Indent (ACol); for (I = 0; I < ByteCount; I += 4) { if (I > 0) { Output (",$%08lX", GetCodeDWord (PC+I)); } else { Output ("$%08lX", GetCodeDWord (PC+I)); } } LineComment (PC, ByteCount); LineFeed (); } void SeparatorLine (void) /* Print a separator line */ { if (Pass == PassCount && Comments >= 1) { Output ("; ----------------------------------------------------------------------------"); LineFeed (); } } 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 */ { Output ("; %s", Comment); LineFeed (); } void LineComment (unsigned PC, unsigned Count) /* Add a line comment with the PC and data bytes */ { unsigned I; if (Pass == PassCount && Comments >= 2) { Indent (CCol); Output ("; %04X", PC); if (Comments >= 3) { for (I = 0; I < Count; ++I) { Output (" %02X", CodeBuf [PC+I]); } if (Comments >= 4) { Indent (TCol); for (I = 0; I < Count; ++I) { unsigned char C = CodeBuf [PC+I]; if (!isprint (C)) { C = '.'; } Output ("%c", C); } } } } } void OutputSettings (void) /* Output CPU and other settings */ { LineFeed (); Indent (MCol); Output (".setcpu"); Indent (ACol); Output ("\"%s\"", CPUNames[CPU]); LineFeed (); LineFeed (); } ����������������������������������������������������������������������cc65-2.18/src/da65/output.h�������������������������������������������������������������������������0000664�0000000�0000000�00000010517�13473601511�0015250�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* output.h */ /* */ /* Disassembler output routines */ /* */ /* */ /* */ /* (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 */ /* 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 OUTPUT_H #define OUTPUT_H /* common */ #include "attrib.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void OpenOutput (const char* Name); /* Open the given file for output */ void CloseOutput (void); /* Close the output file */ void Output (const char* Format, ...) attribute ((format(printf, 1, 2))); /* Write to the output file */ void Indent (unsigned N); /* Make sure the current line column is at position N (zero based) */ void LineFeed (void); /* Add a linefeed to the output file */ void DefLabel (const char* Name); /* Define a label with the given name */ void DefForward (const char* Name, const char* Comment, unsigned Offs); /* Define a label as "* + x", where x is the offset relative to the ** current PC. */ void DefConst (const char* Name, const char* Comment, unsigned Addr); /* Define an address constant */ void OneDataByte (void); /* Output a .byte line with the current code byte */ void DataByteLine (unsigned ByteCount); /* Output a line with bytes */ void DataDByteLine (unsigned ByteCount); /* Output a line with dbytes */ void DataWordLine (unsigned ByteCount); /* Output a line with words */ void DataDWordLine (unsigned ByteCount); /* Output a line with dwords */ 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 */ void LineComment (unsigned PC, unsigned Count); /* Add a line comment with the PC and data bytes */ void OutputSettings (void); /* Output CPU and other settings */ /* End of output.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/scanner.c������������������������������������������������������������������������0000664�0000000�0000000�00000041531�13473601511�0015334�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* scanner.c */ /* */ /* Configuration file scanner for the da65 disassembler */ /* */ /* */ /* */ /* (C) 2000-2005 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdarg.h> #include <stdio.h> #include <string.h> #include <errno.h> /* common */ #include "chartype.h" #include "xsprintf.h" #include "xmalloc.h" #include "strbuf.h" /* ld65 */ #include "global.h" #include "error.h" #include "scanner.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Current token and attributes */ unsigned InfoTok; char InfoSVal [CFG_MAX_IDENT_LEN+1]; long InfoIVal; /* Error location */ unsigned InfoErrorLine; unsigned InfoErrorCol; /* Input sources for the configuration */ static const char* InfoFile = 0; /* Other input stuff */ static int C = ' '; static unsigned InputLine = 1; static unsigned InputCol = 0; static FILE* InputFile = 0; static char* InputSrcName = 0; /*****************************************************************************/ /* Error handling */ /*****************************************************************************/ void InfoWarning (const char* Format, ...) /* Print a warning message adding file name and line number of the config file */ { char Buf [512]; va_list ap; va_start (ap, Format); xvsprintf (Buf, sizeof (Buf), Format, ap); va_end (ap); fprintf (stderr, "%s(%u): Warning: %s\n", InputSrcName, InfoErrorLine, Buf); } void InfoError (const char* Format, ...) /* Print an error message adding file name and line number of the config file */ { char Buf [512]; va_list ap; va_start (ap, Format); xvsprintf (Buf, sizeof (Buf), Format, ap); va_end (ap); fprintf (stderr, "%s(%u): Error: %s\n", InputSrcName, InfoErrorLine, Buf); exit (EXIT_FAILURE); } /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void NextChar (void) /* Read the next character from the input file */ { /* Read from the file */ C = getc (InputFile); /* Count columns */ if (C != EOF) { ++InputCol; } /* Count lines */ if (C == '\n') { ++InputLine; InputCol = 0; } } static unsigned DigitVal (int C) /* Return the value for a numeric digit */ { if (IsDigit (C)) { return C - '0'; } else { return toupper (C) - 'A' + 10; } } static void SkipBlanks (int SingleLine) { while (C != EOF && (!SingleLine || C != '\n') && IsSpace (C)) { NextChar (); } } static long GetDecimalToken (void) { long Value = 0; while (C != EOF && IsDigit (C)) { Value = Value * 10 + DigitVal (C); NextChar (); } return Value; } static int GetEncodedChar (char* Buf, unsigned* IPtr, unsigned Size) { char Decoded = 0; int Count; if (C == EOF) { return -1; } else if (C != '\\') { Decoded = C; NextChar (); goto Store; } NextChar (); /* consume '\\' */ if (C == EOF) { return -1; } else if (IsODigit (C)) { Count = 3; do { Decoded = Decoded * 8 + DigitVal (C); NextChar (); --Count; } while (Count > 0 && C != EOF && IsODigit (C)); } else if (C == 'x') { NextChar (); /* consume 'x' */ Count = 2; while (Count > 0 && C != EOF && IsXDigit (C)) { Decoded = Decoded * 16 + DigitVal (C); NextChar (); --Count; } } else { switch (C) { case '"': case '\'': case '\\': Decoded = C; break; case 't': Decoded = '\t'; break; case 'r': Decoded = '\r'; break; case 'n': Decoded = '\n'; break; default: return -1; } NextChar (); } Store: if (*IPtr < Size - 1) { Buf [(*IPtr)++] = Decoded; } Buf [*IPtr] = 0; return 0; } static void LineMarkerOrComment () /* Handle a line beginning with '#'. Possible interpretations are: ** - #line <lineno> ["<filename>"] (C preprocessor input) ** - # <lineno> "<filename>" [<flag>]... (gcc preprocessor output) ** - #<comment> */ { unsigned long LineNo = 0; int LineDirective = 0; StrBuf SrcNameBuf = AUTO_STRBUF_INITIALIZER; /* Skip the first "# " */ NextChar (); SkipBlanks (1); /* Check "line" */ if (C == 'l') { char MaybeLine [6]; unsigned I; for (I = 0; I < sizeof MaybeLine - 1 && C != EOF && IsAlNum (C); ++I) { MaybeLine [I] = C; NextChar (); } MaybeLine [I] = 0; if (strcmp (MaybeLine, "line") != 0) { goto NotMarker; } LineDirective = 1; SkipBlanks (1); } /* Get line number */ if (C == EOF || !IsDigit (C)) { goto NotMarker; } LineNo = GetDecimalToken (); SkipBlanks (1); /* Get the source file name */ if (C != '\"') { /* The source file name is missing */ if (LineDirective && C == '\n') { /* got #line <lineno> */ NextChar (); InputLine = LineNo; goto Last; } else { goto NotMarker; } } NextChar (); while (C != EOF && C != '\n' && C != '\"') { char DecodeBuf [2]; unsigned I = 0; if (GetEncodedChar (DecodeBuf, &I, sizeof DecodeBuf) < 0) { goto BadMarker; } SB_AppendBuf (&SrcNameBuf, DecodeBuf, I); } if (C != '\"') { goto BadMarker; } NextChar (); /* Ignore until the end of line */ while (C != EOF && C != '\n') { NextChar (); } /* Accepted a line marker */ SB_Terminate (&SrcNameBuf); xfree (InputSrcName); InputSrcName = SB_GetBuf (&SrcNameBuf); SB_Init (&SrcNameBuf); InputLine = (unsigned)LineNo; NextChar (); goto Last; BadMarker: InfoWarning ("Bad line marker"); NotMarker: while (C != EOF && C != '\n') { NextChar (); } NextChar (); Last: SB_Done (&SrcNameBuf); } void InfoNextTok (void) /* Read the next token from the input stream */ { unsigned I; char DecodeBuf [2]; Again: /* Skip whitespace */ SkipBlanks (0); /* Remember the current position */ InfoErrorLine = InputLine; InfoErrorCol = InputCol; /* Identifier? */ if (C == '_' || IsAlpha (C)) { /* Read the identifier */ I = 0; while (C == '_' || IsAlNum (C)) { if (I < CFG_MAX_IDENT_LEN) { InfoSVal [I++] = C; } NextChar (); } InfoSVal [I] = '\0'; InfoTok = INFOTOK_IDENT; return; } /* Hex number? */ if (C == '$') { NextChar (); if (!IsXDigit (C)) { InfoError ("Hex digit expected"); } InfoIVal = 0; while (IsXDigit (C)) { InfoIVal = InfoIVal * 16 + DigitVal (C); NextChar (); } InfoTok = INFOTOK_INTCON; return; } /* Decimal number? */ if (IsDigit (C)) { InfoIVal = GetDecimalToken (); InfoTok = INFOTOK_INTCON; return; } /* Other characters */ switch (C) { case '{': NextChar (); InfoTok = INFOTOK_LCURLY; break; case '}': NextChar (); InfoTok = INFOTOK_RCURLY; break; case ';': NextChar (); InfoTok = INFOTOK_SEMI; break; case '.': NextChar (); InfoTok = INFOTOK_DOT; break; case ',': NextChar (); InfoTok = INFOTOK_COMMA; break; case '=': NextChar (); InfoTok = INFOTOK_EQ; break; case ':': NextChar (); InfoTok = INFOTOK_COLON; break; case '\"': NextChar (); I = 0; InfoSVal[0] = '\0'; while (C != EOF && C != '\"') { if (GetEncodedChar (InfoSVal, &I, sizeof InfoSVal) < 0) { if (C == EOF) { InfoError ("Unterminated string"); } else { InfoError ("Invalid escape char: %c", C); } } } if (C != '\"') { InfoError ("Unterminated string"); } NextChar (); InfoTok = INFOTOK_STRCON; break; case '\'': NextChar (); if (C == EOF || IsControl (C) || C == '\'') { InfoError ("Invalid character constant"); } if (GetEncodedChar (DecodeBuf, &I, sizeof DecodeBuf) < 0 || I != 1) { InfoError ("Invalid character constant"); } InfoIVal = DecodeBuf [0]; if (C != '\'') { InfoError ("Unterminated character constant"); } NextChar (); InfoTok = INFOTOK_CHARCON; break; case '#': /* # lineno "sourcefile" or # comment */ if (SyncLines && InputCol == 1) { LineMarkerOrComment (); } else { do { NextChar (); } while (C != EOF && C != '\n'); NextChar (); } if (C != EOF) { goto Again; } InfoTok = INFOTOK_EOF; break; case '/': /* C++ style comment */ NextChar (); if (C != '/') { InfoError ("Invalid token '/'"); } do { NextChar (); } while (C != '\n' && C != EOF); if (C != EOF) { goto Again; } InfoTok = INFOTOK_EOF; break; case EOF: InfoTok = INFOTOK_EOF; break; default: InfoError ("Invalid character '%c'", C); } } void InfoConsume (unsigned T, const char* Msg) /* Skip a token, print an error message if not found */ { if (InfoTok != T) { InfoError (Msg); } InfoNextTok (); } void InfoConsumeLCurly (void) /* Consume a left curly brace */ { InfoConsume (INFOTOK_LCURLY, "'{' expected"); } void InfoConsumeRCurly (void) /* Consume a right curly brace */ { InfoConsume (INFOTOK_RCURLY, "'}' expected"); } void InfoConsumeSemi (void) /* Consume a semicolon */ { InfoConsume (INFOTOK_SEMI, "';' expected"); } void InfoConsumeColon (void) /* Consume a colon */ { InfoConsume (INFOTOK_COLON, "':' expected"); } void InfoOptionalComma (void) /* Consume a comma if there is one */ { if (InfoTok == INFOTOK_COMMA) { InfoNextTok (); } } void InfoOptionalAssign (void) /* Consume an equal sign if there is one */ { if (InfoTok == INFOTOK_EQ) { InfoNextTok (); } } void InfoAssureInt (void) /* Make sure the next token is an integer */ { if (InfoTok != INFOTOK_INTCON) { InfoError ("Integer constant expected"); } } void InfoAssureStr (void) /* Make sure the next token is a string constant */ { if (InfoTok != INFOTOK_STRCON) { InfoError ("String constant expected"); } } void InfoAssureChar (void) /* Make sure the next token is a char constant */ { if (InfoTok != INFOTOK_STRCON) { InfoError ("Character constant expected"); } } void InfoAssureIdent (void) /* Make sure the next token is an identifier */ { if (InfoTok != INFOTOK_IDENT) { InfoError ("Identifier expected"); } } void InfoRangeCheck (long Lo, long Hi) /* Check the range of InfoIVal */ { if (InfoIVal < Lo || InfoIVal > Hi) { InfoError ("Range error"); } } void InfoSpecialToken (const IdentTok* Table, unsigned Size, const char* Name) /* Map an identifier to one of the special tokens in the table */ { unsigned I; /* We need an identifier */ if (InfoTok == INFOTOK_IDENT) { /* Make it upper case */ I = 0; while (InfoSVal [I]) { InfoSVal [I] = toupper (InfoSVal [I]); ++I; } /* Linear search */ for (I = 0; I < Size; ++I) { if (strcmp (InfoSVal, Table [I].Ident) == 0) { InfoTok = Table [I].Tok; return; } } } /* Not found or no identifier */ InfoError ("%s expected", Name); } void InfoBoolToken (void) /* Map an identifier or integer to a boolean token */ { static const IdentTok Booleans [] = { { "YES", INFOTOK_TRUE }, { "NO", INFOTOK_FALSE }, { "TRUE", INFOTOK_TRUE }, { "FALSE", INFOTOK_FALSE }, { "ON", INFOTOK_TRUE }, { "OFF", INFOTOK_FALSE }, }; /* If we have an identifier, map it to a boolean token */ if (InfoTok == INFOTOK_IDENT) { InfoSpecialToken (Booleans, ENTRY_COUNT (Booleans), "Boolean"); } else { /* We expected an integer here */ if (InfoTok != INFOTOK_INTCON) { InfoError ("Boolean value expected"); } InfoTok = (InfoIVal == 0)? INFOTOK_FALSE : INFOTOK_TRUE; } } void InfoSetName (const char* Name) /* Set a name for a config file */ { InfoFile = Name; xfree(InputSrcName); InputSrcName = xstrdup(Name); } int InfoAvail () /* Return true if we have an info file given */ { return (InfoFile != 0); } void InfoOpenInput (void) /* Open the input file */ { /* Open the file */ InputFile = fopen (InfoFile, "r"); if (InputFile == 0) { Error ("Cannot open '%s': %s", InfoFile, strerror (errno)); } /* Initialize variables */ C = ' '; InputLine = 1; InputCol = 0; /* Start the ball rolling ... */ InfoNextTok (); } void InfoCloseInput (void) /* Close the input file if we have one */ { /* Close the input file if we had one */ if (InputFile) { (void) fclose (InputFile); InputFile = 0; } } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/scanner.h������������������������������������������������������������������������0000664�0000000�0000000�00000015311�13473601511�0015336�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* scanner.h */ /* */ /* Configuration file scanner for the da65 disassembler */ /* */ /* */ /* */ /* (C) 2000-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef SCANNER_H #define SCANNER_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Info file tokens */ typedef enum token_t { INFOTOK_NONE, INFOTOK_INTCON, INFOTOK_STRCON, INFOTOK_CHARCON, INFOTOK_IDENT, INFOTOK_LCURLY, INFOTOK_RCURLY, INFOTOK_SEMI, INFOTOK_COMMA, INFOTOK_EQ, INFOTOK_COLON, INFOTOK_DOT, INFOTOK_EOF, /* Special tokens */ INFOTOK_GLOBAL, INFOTOK_RANGE, INFOTOK_LABEL, INFOTOK_ASMINC, INFOTOK_SEGMENT, /* Global section */ INFOTOK_ARGUMENT_COLUMN, INFOTOK_COMMENT_COLUMN, INFOTOK_COMMENTS, INFOTOK_CPU, INFOTOK_HEXOFFS, INFOTOK_INPUTNAME, INFOTOK_INPUTOFFS, INFOTOK_INPUTSIZE, INFOTOK_LABELBREAK, INFOTOK_MNEMONIC_COLUMN, INFOTOK_NL_AFTER_JMP, INFOTOK_NL_AFTER_RTS, INFOTOK_OUTPUTNAME, INFOTOK_PAGELENGTH, INFOTOK_STARTADDR, INFOTOK_TEXT_COLUMN, /* Range section */ INFOTOK_START, INFOTOK_END, INFOTOK_TYPE, INFOTOK_CODE, INFOTOK_BYTETAB, INFOTOK_DBYTETAB, INFOTOK_WORDTAB, INFOTOK_DWORDTAB, INFOTOK_ADDRTAB, INFOTOK_RTSTAB, INFOTOK_TEXTTAB, INFOTOK_SKIP, /* Label section */ INFOTOK_NAME, INFOTOK_COMMENT, INFOTOK_ADDR, INFOTOK_SIZE, INFOTOK_PARAMSIZE, /* ASMINC section */ INFOTOK_FILE, INFOTOK_COMMENTSTART, INFOTOK_IGNOREUNKNOWN, /* */ INFOTOK_TRUE, INFOTOK_FALSE } token_t; /* Mapping table entry, special identifier --> token */ typedef struct IdentTok IdentTok; struct IdentTok { const char* Ident; /* Identifier */ token_t Tok; /* Token for identifier */ }; #define ENTRY_COUNT(s) (sizeof (s) / sizeof (s [0])) /* Current token and attributes */ #define CFG_MAX_IDENT_LEN 255 extern unsigned InfoTok; extern char InfoSVal[CFG_MAX_IDENT_LEN+1]; extern long InfoIVal; /* Error location */ extern unsigned InfoErrorLine; extern unsigned InfoErrorCol; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void InfoWarning (const char* Format, ...); /* Print a warning message adding file name and line number of the config file */ void InfoError (const char* Format, ...); /* Print an error message adding file name and line number of the config file */ void InfoNextTok (void); /* Read the next token from the input stream */ void InfoConsume (unsigned T, const char* Msg); /* Skip a token, print an error message if not found */ void InfoConsumeLCurly (void); /* Consume a left curly brace */ void InfoConsumeRCurly (void); /* Consume a right curly brace */ void InfoConsumeSemi (void); /* Consume a semicolon */ void InfoConsumeColon (void); /* Consume a colon */ void InfoOptionalComma (void); /* Consume a comma if there is one */ void InfoOptionalAssign (void); /* Consume an equal sign if there is one */ void InfoAssureInt (void); /* Make sure the next token is an integer */ void InfoAssureStr (void); /* Make sure the next token is a string constant */ void InfoAssureChar (void); /* Make sure the next token is a char constant */ void InfoAssureIdent (void); /* Make sure the next token is an identifier */ void InfoRangeCheck (long Lo, long Hi); /* Check the range of InfoIVal */ void InfoSpecialToken (const IdentTok* Table, unsigned Size, const char* Name); /* Map an identifier to one of the special tokens in the table */ void InfoBoolToken (void); /* Map an identifier or integer to a boolean token */ void InfoSetName (const char* Name); /* Set a name for a config file */ const char* InfoGetName (void); /* Get the name of the config file */ int InfoAvail (); /* Return true if we have an info file given */ void InfoOpenInput (void); /* Open the input file if we have one */ void InfoCloseInput (void); /* Close the input file if we have one */ /* End of scanner.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/segment.c������������������������������������������������������������������������0000664�0000000�0000000�00000012133�13473601511�0015341�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* segment.c */ /* */ /* Segment handling for da65 */ /* */ /* */ /* */ /* (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 */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* common */ #include "addrsize.h" #include "xmalloc.h" /* da65 */ #include "attrtab.h" #include "segment.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Hash definitions */ #define HASH_SIZE 53 /* Segment definition */ typedef struct Segment Segment; struct Segment { Segment* NextStart; /* Pointer to next segment */ unsigned long Start; unsigned AddrSize; char Name[1]; /* Name, dynamically allocated */ }; /* 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 */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ void AddAbsSegment (unsigned Start, unsigned End, const char* Name) /* Add an absolute segment to the segment table */ { /* Get the length of the name */ unsigned Len = strlen (Name); /* Create a new segment */ Segment* S = xmalloc (sizeof (Segment) + Len); /* Fill in the data */ S->Start = Start; S->AddrSize = ADDR_SIZE_ABS; memcpy (S->Name, Name, Len + 1); /* Insert the segment into the hash table */ S->NextStart = StartTab[Start % HASH_SIZE]; StartTab[Start % HASH_SIZE] = S; /* Mark start and end of the segment */ 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; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/da65/segment.h������������������������������������������������������������������������0000664�0000000�0000000�00000006246�13473601511�0015356�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* segment.h */ /* */ /* Segment handling for da65 */ /* */ /* */ /* */ /* (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 */ /* 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 SEGMENT_H #define SEGMENT_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ void AddAbsSegment (unsigned Start, unsigned End, const char* Name); /* Add an absolute segment to the segment table */ char* GetSegmentStartName (unsigned Addr); /* Return the name of the segment which starts at the given address */ unsigned GetSegmentAddrSize (unsigned Addr); /* Return the address size of the segment which starts at the given address */ /* End of segment.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/dbginfo/������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014404�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/dbginfo/dbginfo.c���������������������������������������������������������������������0000664�0000000�0000000�00000630516�13473601511�0016173�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* dbginfo.c */ /* */ /* cc65 debug info handling */ /* */ /* */ /* */ /* (C) 2010-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <ctype.h> #include <limits.h> #include <assert.h> #include <errno.h> #include "dbginfo.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Use this for debugging - beware, lots of output */ #define DEBUG 0 /* Version numbers of the debug format we understand */ #define VER_MAJOR 2U #define VER_MINOR 0U /* Dynamic strings */ typedef struct StrBuf StrBuf; struct StrBuf { char* Buf; /* Pointer to buffer */ unsigned Len; /* Length of the string */ unsigned Allocated; /* Size of allocated memory */ }; /* Initializer for a string buffer */ #define STRBUF_INITIALIZER { 0, 0, 0 } /* An array of unsigneds/pointers that grows if needed. C guarantees that a ** pointer to a union correctly converted points to each of its members. ** So what we do here is using union entries that contain an unsigned ** (used to store ids until they're resolved) and pointers to actual items ** in storage. */ typedef union CollEntry CollEntry; union CollEntry { void* Ptr; unsigned Id; }; typedef struct Collection Collection; struct Collection { unsigned Count; /* Number of items in the list */ unsigned Size; /* Size of allocated array */ CollEntry* Items; /* Array with dynamic size */ }; /* Initializer for static collections */ #define COLLECTION_INITIALIZER { 0, 0, 0 } /* Span info management. The following table has as many entries as there ** are addresses active in spans. Each entry lists the spans for this address. */ typedef struct SpanInfoListEntry SpanInfoListEntry; struct SpanInfoListEntry { cc65_addr Addr; /* Unique address */ unsigned Count; /* Number of SpanInfos for this address */ void* Data; /* Either SpanInfo* or SpanInfo** */ }; typedef struct SpanInfoList SpanInfoList; struct SpanInfoList { unsigned Count; /* Number of entries */ SpanInfoListEntry* List; /* Dynamic array with entries */ }; /* Input tokens */ typedef enum { TOK_INVALID, /* Invalid token */ TOK_EOF, /* End of file reached */ TOK_INTCON, /* Integer constant */ TOK_STRCON, /* String constant */ TOK_EQUAL, /* = */ TOK_COMMA, /* , */ TOK_MINUS, /* - */ TOK_PLUS, /* + */ TOK_EOL, /* \n */ TOK_FIRST_KEYWORD, TOK_ABSOLUTE = TOK_FIRST_KEYWORD, /* ABSOLUTE keyword */ TOK_ADDRSIZE, /* ADDRSIZE keyword */ TOK_AUTO, /* AUTO keyword */ TOK_COUNT, /* COUNT keyword */ TOK_CSYM, /* CSYM keyword */ TOK_DEF, /* DEF keyword */ TOK_ENUM, /* ENUM keyword */ TOK_EQUATE, /* EQUATE keyword */ TOK_EXPORT, /* EXPORT keyword */ TOK_EXTERN, /* EXTERN keyword */ TOK_FILE, /* FILE keyword */ TOK_FUNC, /* FUNC keyword */ TOK_GLOBAL, /* GLOBAL keyword */ TOK_ID, /* ID keyword */ TOK_IMPORT, /* IMPORT keyword */ TOK_INFO, /* INFO keyword */ TOK_LABEL, /* LABEL keyword */ TOK_LIBRARY, /* LIBRARY keyword */ TOK_LINE, /* LINE keyword */ TOK_LONG, /* LONG_keyword */ TOK_MAJOR, /* MAJOR keyword */ TOK_MINOR, /* MINOR keyword */ TOK_MODULE, /* MODULE keyword */ TOK_MTIME, /* MTIME keyword */ TOK_NAME, /* NAME keyword */ TOK_OFFS, /* OFFS keyword */ TOK_OUTPUTNAME, /* OUTPUTNAME keyword */ TOK_OUTPUTOFFS, /* OUTPUTOFFS keyword */ TOK_PARENT, /* PARENT keyword */ TOK_REF, /* REF keyword */ TOK_REGISTER, /* REGISTER keyword */ TOK_RO, /* RO keyword */ TOK_RW, /* RW keyword */ TOK_SC, /* SC keyword */ TOK_SCOPE, /* SCOPE keyword */ TOK_SEGMENT, /* SEGMENT keyword */ TOK_SIZE, /* SIZE keyword */ TOK_SPAN, /* SPAN keyword */ TOK_START, /* START keyword */ TOK_STATIC, /* STATIC keyword */ TOK_STRUCT, /* STRUCT keyword */ TOK_SYM, /* SYM keyword */ TOK_TYPE, /* TYPE keyword */ TOK_VALUE, /* VALUE keyword */ TOK_VAR, /* VAR keyword */ TOK_VERSION, /* VERSION keyword */ TOK_ZEROPAGE, /* ZEROPAGE keyword */ TOK_LAST_KEYWORD = TOK_ZEROPAGE, TOK_IDENT, /* To catch unknown keywords */ } Token; /* Data structure containing information from the debug info file. A pointer ** to this structure is passed as handle to callers from the outside. */ typedef struct DbgInfo DbgInfo; struct DbgInfo { /* First we have all items in collections sorted by id. The ids are ** continous, so an access by id is almost as cheap as an array access. ** The collections are also used when the objects are deleted, so they're ** actually the ones that "own" the items. */ Collection CSymInfoById; /* C symbol infos sorted by id */ Collection FileInfoById; /* File infos sorted by id */ Collection LibInfoById; /* Library infos sorted by id */ Collection LineInfoById; /* Line infos sorted by id */ Collection ModInfoById; /* Module infos sorted by id */ Collection ScopeInfoById; /* Scope infos sorted by id */ Collection SegInfoById; /* Segment infos sorted by id */ Collection SpanInfoById; /* Span infos sorted by id */ Collection SymInfoById; /* Symbol infos sorted by id */ Collection TypeInfoById; /* Type infos sorted by id */ /* Collections with other sort criteria */ Collection CSymFuncByName; /* C functions sorted by name */ Collection FileInfoByName; /* File infos sorted by name */ Collection ModInfoByName; /* Module info sorted by name */ Collection ScopeInfoByName;/* Scope infos sorted by name */ Collection SegInfoByName; /* Segment infos sorted by name */ Collection SymInfoByName; /* Symbol infos sorted by name */ Collection SymInfoByVal; /* Symbol infos sorted by value */ /* Other stuff */ SpanInfoList SpanInfoByAddr; /* Span infos sorted by unique address */ /* Info data */ unsigned long MemUsage; /* Memory usage for the data */ unsigned MajorVersion; /* Major version number of loaded file */ unsigned MinorVersion; /* Minor version number of loaded file */ char FileName[1]; /* Name of input file */ }; /* Data used when parsing the debug info file */ typedef struct InputData InputData; struct InputData { const char* FileName; /* Name of input file */ cc65_line Line; /* Current line number */ unsigned Col; /* Current column number */ cc65_line SLine; /* Line number at start of token */ unsigned SCol; /* Column number at start of token */ unsigned Errors; /* Number of errors */ FILE* F; /* Input file */ int C; /* Input character */ Token Tok; /* Token from input stream */ unsigned long IVal; /* Integer constant */ StrBuf SVal; /* String constant */ cc65_errorfunc Error; /* Function called in case of errors */ DbgInfo* Info; /* Pointer to debug info */ }; /* Typedefs for the item structures. Do also serve as forwards */ typedef struct CSymInfo CSymInfo; typedef struct FileInfo FileInfo; typedef struct LibInfo LibInfo; typedef struct LineInfo LineInfo; typedef struct ModInfo ModInfo; typedef struct ScopeInfo ScopeInfo; typedef struct SegInfo SegInfo; typedef struct SpanInfo SpanInfo; typedef struct SymInfo SymInfo; typedef struct TypeInfo TypeInfo; /* Internally used c symbol info struct */ struct CSymInfo { unsigned Id; /* Id of file */ unsigned short Kind; /* Kind of C symbol */ unsigned short SC; /* Storage class of C symbol */ int Offs; /* Offset */ union { unsigned Id; /* Id of attached asm symbol */ SymInfo* Info; /* Pointer to attached asm symbol */ } Sym; union { unsigned Id; /* Id of type */ TypeInfo* Info; /* Pointer to type */ } Type; union { unsigned Id; /* Id of scope */ ScopeInfo* Info; /* Pointer to scope */ } Scope; char Name[1]; /* Name of file with full path */ }; /* Internally used file info struct */ struct FileInfo { unsigned Id; /* Id of file */ unsigned long Size; /* Size of file */ unsigned long MTime; /* Modification time */ Collection ModInfoByName; /* Modules in which this file is used */ Collection LineInfoByLine; /* Line infos sorted by line */ char Name[1]; /* Name of file with full path */ }; /* Internally used library info struct */ struct LibInfo { unsigned Id; /* Id of library */ char Name[1]; /* Name of library with path */ }; /* Internally used line info struct */ struct LineInfo { unsigned Id; /* Id of line info */ cc65_line Line; /* Line number */ union { unsigned Id; /* Id of file */ FileInfo* Info; /* Pointer to file info */ } File; cc65_line_type Type; /* Type of line */ unsigned Count; /* Nesting counter for macros */ Collection SpanInfoList; /* List of spans for this line */ }; /* Internally used module info struct */ struct ModInfo { unsigned Id; /* Id of library */ union { unsigned Id; /* Id of main source file */ FileInfo* Info; /* Pointer to file info */ } File; union { unsigned Id; /* Id of library if any */ LibInfo* Info; /* Pointer to library info */ } Lib; ScopeInfo* MainScope; /* Pointer to main scope */ Collection CSymFuncByName; /* C functions by name */ Collection FileInfoByName; /* Files for this module */ Collection ScopeInfoByName;/* Scopes for this module */ char Name[1]; /* Name of module with path */ }; /* Internally used scope info struct */ struct ScopeInfo { unsigned Id; /* Id of scope */ cc65_scope_type Type; /* Type of scope */ cc65_size Size; /* Size of scope */ union { unsigned Id; /* Id of module */ ModInfo* Info; /* Pointer to module info */ } Mod; union { unsigned Id; /* Id of parent scope */ ScopeInfo* Info; /* Pointer to parent scope */ } Parent; union { unsigned Id; /* Id of label symbol */ SymInfo* Info; /* Pointer to label symbol */ } Label; CSymInfo* CSymFunc; /* C function for this scope */ Collection SpanInfoList; /* List of spans for this scope */ Collection SymInfoByName; /* Symbols in this scope */ Collection* CSymInfoByName; /* C symbols for this scope */ Collection* ChildScopeList; /* Child scopes of this scope */ char Name[1]; /* Name of scope */ }; /* Internally used segment info struct */ struct SegInfo { unsigned Id; /* Id of segment */ cc65_addr Start; /* Start address of segment */ cc65_size Size; /* Size of segment */ char* OutputName; /* Name of output file */ unsigned long OutputOffs; /* Offset in output file */ char Name[1]; /* Name of segment */ }; /* Internally used span info struct */ struct SpanInfo { unsigned Id; /* Id of span */ cc65_addr Start; /* Start of span */ cc65_addr End; /* End of span */ union { unsigned Id; /* Id of segment */ SegInfo* Info; /* Pointer to segment */ } Seg; union { unsigned Id; /* Id of type */ TypeInfo* Info; /* Pointer to type */ } Type; Collection* ScopeInfoList; /* Scopes for this span */ Collection* LineInfoList; /* Lines for this span */ }; /* Internally used symbol info struct */ struct SymInfo { unsigned Id; /* Id of symbol */ cc65_symbol_type Type; /* Type of symbol */ long Value; /* Value of symbol */ cc65_size Size; /* Size of symbol */ union { unsigned Id; /* Id of export if any */ SymInfo* Info; /* Pointer to export if any */ } Exp; union { unsigned Id; /* Id of segment if any */ SegInfo* Info; /* Pointer to segment if any */ } Seg; union { unsigned Id; /* Id of symbol scope */ ScopeInfo* Info; /* Pointer to symbol scope */ } Scope; union { unsigned Id; /* Parent symbol if any */ SymInfo* Info; /* Pointer to parent symbol if any */ } Parent; CSymInfo* CSym; /* Corresponding C symbol */ Collection* ImportList; /* List of imports if this is an export */ Collection* CheapLocals; /* List of cheap local symbols */ Collection DefLineInfoList;/* Line info of symbol definition */ Collection RefLineInfoList;/* Line info of symbol references */ char Name[1]; /* Name of symbol */ }; /* Internally used type info struct */ struct TypeInfo { unsigned Id; /* Id of type */ cc65_typedata Data[1]; /* Data, dynamically allocated */ }; /* A structure used when parsing a type string into a set of cc65_typedata ** structures. */ typedef struct TypeParseData TypeParseData; struct TypeParseData { TypeInfo* Info; unsigned ItemCount; unsigned ItemIndex; cc65_typedata* ItemData; const StrBuf* Type; unsigned Pos; unsigned Error; }; /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ static void NextToken (InputData* D); /* Read the next token from the input stream */ /*****************************************************************************/ /* Memory allocation */ /*****************************************************************************/ static void* xmalloc (size_t Size) /* Allocate memory, check for out of memory condition. Do some debugging */ { void* P = 0; /* Allow zero sized requests and return NULL in this case */ if (Size) { /* Allocate memory */ P = malloc (Size); /* Check for errors */ assert (P != 0); } /* Return a pointer to the block */ return P; } static void* xrealloc (void* P, size_t Size) /* Reallocate a memory block, check for out of memory */ { /* Reallocate the block */ void* N = realloc (P, Size); /* Check for errors */ assert (N != 0 || Size == 0); /* Return the pointer to the new block */ return N; } static void xfree (void* Block) /* Free the block, do some debugging */ { free (Block); } /*****************************************************************************/ /* Dynamic strings */ /*****************************************************************************/ static void SB_Done (StrBuf* B) /* Free the data of a string buffer (but not the struct itself) */ { if (B->Allocated) { xfree (B->Buf); } } static void SB_Realloc (StrBuf* B, unsigned NewSize) /* Reallocate the string buffer space, make sure at least NewSize bytes are ** available. */ { /* Get the current size, use a minimum of 8 bytes */ unsigned NewAllocated = B->Allocated; if (NewAllocated == 0) { NewAllocated = 8; } /* Round up to the next power of two */ while (NewAllocated < NewSize) { NewAllocated *= 2; } /* Reallocate the buffer. Beware: The allocated size may be zero while the ** length is not. This means that we have a buffer that wasn't allocated ** on the heap. */ if (B->Allocated) { /* Just reallocate the block */ B->Buf = xrealloc (B->Buf, NewAllocated); } else { /* Allocate a new block and copy */ B->Buf = memcpy (xmalloc (NewAllocated), B->Buf, B->Len); } /* Remember the new block size */ B->Allocated = NewAllocated; } static void SB_CheapRealloc (StrBuf* B, unsigned NewSize) /* Reallocate the string buffer space, make sure at least NewSize bytes are ** available. This function won't copy the old buffer contents over to the new ** buffer and may be used if the old contents are overwritten later. */ { /* Get the current size, use a minimum of 8 bytes */ unsigned NewAllocated = B->Allocated; if (NewAllocated == 0) { NewAllocated = 8; } /* Round up to the next power of two */ while (NewAllocated < NewSize) { NewAllocated *= 2; } /* Free the old buffer if there is one */ if (B->Allocated) { xfree (B->Buf); } /* Allocate a fresh block */ B->Buf = xmalloc (NewAllocated); /* Remember the new block size */ B->Allocated = NewAllocated; } static unsigned SB_GetLen (const StrBuf* B) /* Return the length of the buffer contents */ { return B->Len; } static char* SB_GetBuf (StrBuf* B) /* Return a buffer pointer */ { return B->Buf; } static const char* SB_GetConstBuf (const StrBuf* B) /* Return a buffer pointer */ { return B->Buf; } static char SB_At (const StrBuf* B, unsigned Pos) /* Return the character from a specific position */ { assert (Pos <= B->Len); return B->Buf[Pos]; } static void SB_Terminate (StrBuf* B) /* Zero terminate the given string buffer. NOTE: The terminating zero is not ** accounted for in B->Len, if you want that, you have to use AppendChar! */ { unsigned NewLen = B->Len + 1; if (NewLen > B->Allocated) { SB_Realloc (B, NewLen); } B->Buf[B->Len] = '\0'; } static void SB_Clear (StrBuf* B) /* Clear the string buffer (make it empty) */ { B->Len = 0; } static void SB_CopyBuf (StrBuf* Target, const char* Buf, unsigned Size) /* Copy Buf to Target, discarding the old contents of Target */ { if (Size) { if (Target->Allocated < Size) { SB_CheapRealloc (Target, Size); } memcpy (Target->Buf, Buf, Size); } Target->Len = Size; } static void SB_Copy (StrBuf* Target, const StrBuf* Source) /* Copy Source to Target, discarding the old contents of Target */ { SB_CopyBuf (Target, Source->Buf, Source->Len); } static void SB_AppendChar (StrBuf* B, int C) /* Append a character to a string buffer */ { unsigned NewLen = B->Len + 1; if (NewLen > B->Allocated) { SB_Realloc (B, NewLen); } B->Buf[B->Len] = (char) C; B->Len = NewLen; } static char* SB_StrDup (const StrBuf* B) /* Return the contents of B as a dynamically allocated string. The string ** will always be NUL terminated. */ { /* Allocate memory */ char* S = xmalloc (B->Len + 1); /* Copy the string */ memcpy (S, B->Buf, B->Len); /* Terminate it */ S[B->Len] = '\0'; /* And return the result */ return S; } /*****************************************************************************/ /* Collections */ /*****************************************************************************/ static Collection* CollInit (Collection* C) /* Initialize a collection and return it. */ { /* Intialize the fields. */ C->Count = 0; C->Size = 0; C->Items = 0; /* Return the new struct */ return C; } static Collection* CollNew (void) /* Allocate a new collection, initialize and return it */ { return CollInit (xmalloc (sizeof (Collection))); } static void CollDone (Collection* C) /* Free the data for a collection. This will not free the data contained in ** the collection. */ { /* Free the pointer array */ xfree (C->Items); /* Clear the fields, so the collection may be reused (or CollDone called) ** again */ C->Count = 0; C->Size = 0; C->Items = 0; } static void CollFree (Collection* C) /* Free a dynamically allocated collection */ { /* Accept NULL pointers */ if (C) { xfree (C->Items); xfree (C); } } static unsigned CollCount (const Collection* C) /* Return the number of items in the collection. Return 0 if C is NULL. */ { return C? C->Count : 0; } static void CollMove (Collection* Source, Collection* Target) /* Move all data from one collection to another. This function will first free ** the data in the target collection, and - after the move - clear the data ** from the source collection. */ { /* Free the target collection data */ xfree (Target->Items); /* Now copy the whole bunch over */ *Target = *Source; /* Empty Source */ Source->Count = 0; Source->Size = 0; Source->Items = 0; } static void CollGrow (Collection* C, unsigned Size) /* Grow the collection C so it is able to hold Size items without a resize ** being necessary. This can be called for performance reasons if the number ** of items to be placed in the collection is known in advance. */ { CollEntry* NewItems; /* Ignore the call if the collection is already large enough */ if (Size <= C->Size) { return; } /* Grow the collection */ C->Size = Size; NewItems = xmalloc (C->Size * sizeof (CollEntry)); memcpy (NewItems, C->Items, C->Count * sizeof (CollEntry)); xfree (C->Items); C->Items = NewItems; } static void CollPrepareInsert (Collection* C, unsigned Index) /* Prepare for insertion of the data at a given position in the collection */ { /* Check for invalid indices */ assert (Index <= C->Count); /* Grow the array if necessary */ if (C->Count >= C->Size) { /* Must grow */ CollGrow (C, (C->Size == 0)? 1 : C->Size * 2); } /* Move the existing elements if needed */ if (C->Count != Index) { memmove (C->Items+Index+1, C->Items+Index, (C->Count-Index) * sizeof (void*)); } ++C->Count; } static void CollInsert (Collection* C, void* Item, unsigned Index) /* Insert the data at the given position in the collection */ { /* Prepare for insertion (free the given slot) */ CollPrepareInsert (C, Index); /* Store the new item */ C->Items[Index].Ptr = Item; } static void CollInsertId (Collection* C, unsigned Id, unsigned Index) /* Insert the data at the given position in the collection */ { /* Prepare for insertion (free the given slot) */ CollPrepareInsert (C, Index); /* Store the new item */ C->Items[Index].Id = Id; } static void CollReplace (Collection* C, void* Item, unsigned Index) /* Replace the item at the given position by a new one */ { /* Check the index */ assert (Index < C->Count); /* Replace the element */ C->Items[Index].Ptr = Item; } static void CollReplaceExpand (Collection* C, void* Item, unsigned Index) /* If Index is a valid index for the collection, replace the item at this ** position by the one passed. If the collection is too small, expand it, ** filling unused pointers with NULL, then add the new item at the given ** position. */ { if (Index < C->Count) { /* Collection is already large enough */ C->Items[Index].Ptr = Item; } else { /* Must expand the collection */ unsigned Size = C->Size; if (Size == 0) { Size = 2; } while (Index >= Size) { Size *= 2; } CollGrow (C, Size); /* Fill up unused slots with NULL */ while (C->Count < Index) { C->Items[C->Count++].Ptr = 0; } /* Fill in the item */ C->Items[C->Count++].Ptr = Item; } } static void CollAppend (Collection* C, void* Item) /* Append an item to the end of the collection */ { /* Insert the item at the end of the current list */ CollInsert (C, Item, C->Count); } static void CollAppendId (Collection* C, unsigned Id) /* Append an id to the end of the collection */ { /* Insert the id at the end of the current list */ CollInsertId (C, Id, C->Count); } static void* CollAt (const Collection* C, unsigned Index) /* Return the item at the given index */ { /* Check the index */ assert (Index < C->Count); /* Return the element */ return C->Items[Index].Ptr; } static unsigned CollIdAt (const Collection* C, unsigned Index) /* Return the id at the given index */ { /* Check the index */ assert (Index < C->Count); /* Return the element */ return C->Items[Index].Id; } static void CollQuickSort (Collection* C, int Lo, int Hi, int (*Compare) (const void*, const void*)) /* Internal recursive sort function. */ { /* Get a pointer to the items */ CollEntry* Items = C->Items; /* Quicksort */ while (Hi > Lo) { int I = Lo + 1; int J = Hi; while (I <= J) { while (I <= J && Compare (Items[Lo].Ptr, Items[I].Ptr) >= 0) { ++I; } while (I <= J && Compare (Items[Lo].Ptr, Items[J].Ptr) < 0) { --J; } if (I <= J) { /* Swap I and J */ CollEntry Tmp = Items[I]; Items[I] = Items[J]; Items[J] = Tmp; ++I; --J; } } if (J != Lo) { /* Swap J and Lo */ CollEntry Tmp = Items[J]; Items[J] = Items[Lo]; Items[Lo] = Tmp; } if (J > (Hi + Lo) / 2) { CollQuickSort (C, J + 1, Hi, Compare); Hi = J - 1; } else { CollQuickSort (C, Lo, J - 1, Compare); Lo = J + 1; } } } static void CollSort (Collection* C, int (*Compare) (const void*, const void*)) /* Sort the collection using the given compare function. */ { if (C->Count > 1) { CollQuickSort (C, 0, C->Count-1, Compare); } } /*****************************************************************************/ /* Debugging stuff */ /*****************************************************************************/ #if DEBUG /* Output */ #define DBGPRINT(format, ...) printf ((format), __VA_ARGS__) static void DumpFileInfo (Collection* FileInfos) /* Dump a list of file infos */ { unsigned I; /* File info */ for (I = 0; I < CollCount (FileInfos); ++I) { const FileInfo* FI = CollAt (FileInfos, I); printf ("File info %u:\n" " Name: %s\n" " Size: %lu\n" " MTime: %lu\n", FI->Id, FI->Name, (unsigned long) FI->Size, (unsigned long) FI->MTime); } } static void DumpOneLineInfo (unsigned Num, LineInfo* LI) /* Dump one line info entry */ { printf (" Index: %u\n" " File: %s\n" " Line: %lu\n" " Range: 0x%06lX-0x%06lX\n" " Type: %u\n" " Count: %u\n", Num, LI->File.Info->Name, (unsigned long) LI->Line, (unsigned long) LI->Start, (unsigned long) LI->End, LI->Type, LI->Count); } static void DumpSpanInfo (SpanInfoList* L) /* Dump a list of span infos */ { unsigned I, J; /* Line info */ for (I = 0; I < L->Count; ++I) { const SpanInfoListEntry* E = &L->List[I]; printf ("Addr: %lu\n", (unsigned long) E->Addr); if (E->Count == 1) { DumpOneLineInfo (0, E->Data); } else { for (J = 0; J < E->Count; ++J) { DumpOneLineInfo (J, ((LineInfo**) E->Data)[J]); } } } } static void DumpData (InputData* D) /* Dump internal data to stdout for debugging */ { /* Dump data */ DumpFileInfo (&D->Info->FileInfoById); DumpLineInfo (&D->Info->LineInfoByAddr); } #else /* No output */ #ifdef __WATCOMC__ static void DBGPRINT(const char* format, ...) {} #else #define DBGPRINT(format, ...) #endif #endif /*****************************************************************************/ /* Helper functions */ /*****************************************************************************/ static unsigned GetId (const void* Data) /* Return the id of one of the info structures. All structures have the Id ** field as first member, and the C standard allows converting a union pointer ** to the data type of the first member, so this is safe and portable. */ { if (Data) { return *(const unsigned*)Data; } else { return CC65_INV_ID; } } static unsigned HexValue (char C) /* Convert the ascii representation of a hex nibble into the hex nibble */ { if (isdigit (C)) { return C - '0'; } else if (islower (C)) { return C - 'a' + 10; } else { return C - 'A' + 10; } } static void ParseError (InputData* D, cc65_error_severity Type, const char* Msg, ...) /* Call the user supplied parse error function */ { va_list ap; int MsgSize; cc65_parseerror* E; /* Test-format the error message so we know how much space to allocate */ va_start (ap, Msg); MsgSize = vsnprintf (0, 0, Msg, ap); va_end (ap); /* Allocate memory */ E = xmalloc (sizeof (*E) + MsgSize); /* Write data to E */ E->type = Type; E->name = D->FileName; E->line = D->SLine; E->column = D->SCol; va_start (ap, Msg); vsnprintf (E->errormsg, MsgSize+1, Msg, ap); va_end (ap); /* Call the caller:-) */ D->Error (E); /* Free the data structure */ xfree (E); /* Count errors */ if (Type == CC65_ERROR) { ++D->Errors; } } static void SkipLine (InputData* D) /* Error recovery routine. Skip tokens until EOL or EOF is reached */ { while (D->Tok != TOK_EOL && D->Tok != TOK_EOF) { NextToken (D); } } static void UnexpectedToken (InputData* D) /* Call ParseError with a message about an unexpected input token */ { ParseError (D, CC65_ERROR, "Unexpected input token %d", D->Tok); SkipLine (D); } static void UnknownKeyword (InputData* D) /* Print a warning about an unknown keyword in the file. Try to do smart ** recovery, so if later versions of the debug information add additional ** keywords, this code may be able to at least ignore them. */ { /* Output a warning */ ParseError (D, CC65_WARNING, "Unknown keyword \"%s\" - skipping", SB_GetConstBuf (&D->SVal)); /* Skip the identifier */ NextToken (D); /* If an equal sign follows, ignore anything up to the next line end ** or comma. If a comma or line end follows, we're already done. If ** we have none of both, we ignore the remainder of the line. */ if (D->Tok == TOK_EQUAL) { NextToken (D); while (D->Tok != TOK_COMMA && D->Tok != TOK_EOL && D->Tok != TOK_EOF) { NextToken (D); } } else if (D->Tok != TOK_COMMA && D->Tok != TOK_EOL && D->Tok != TOK_EOF) { SkipLine (D); } } /*****************************************************************************/ /* C symbol info */ /*****************************************************************************/ static CSymInfo* NewCSymInfo (const StrBuf* Name) /* Create a new CSymInfo struct and return it */ { /* Allocate memory */ CSymInfo* S = xmalloc (sizeof (CSymInfo) + SB_GetLen (Name)); /* Initialize it */ memcpy (S->Name, SB_GetConstBuf (Name), SB_GetLen (Name) + 1); /* Return it */ return S; } static void FreeCSymInfo (CSymInfo* S) /* Free a CSymInfo struct */ { /* Free the structure itself */ xfree (S); } static cc65_csyminfo* new_cc65_csyminfo (unsigned Count) /* Allocate and return a cc65_csyminfo struct that is able to hold Count ** entries. Initialize the count field of the returned struct. */ { cc65_csyminfo* S = xmalloc (sizeof (*S) - sizeof (S->data[0]) + Count * sizeof (S->data[0])); S->count = Count; return S; } static void CopyCSymInfo (cc65_csymdata* D, const CSymInfo* S) /* Copy data from a CSymInfo struct to a cc65_csymdata struct */ { D->csym_id = S->Id; D->csym_kind = S->Kind; D->csym_sc = S->SC; D->csym_offs = S->Offs; D->type_id = GetId (S->Type.Info); D->symbol_id = GetId (S->Sym.Info); D->scope_id = GetId (S->Scope.Info); D->csym_name = S->Name; } static int CompareCSymInfoByName (const void* L, const void* R) /* Helper function to sort c symbol infos in a collection by name */ { /* Sort by symbol name, then by id */ int Res = strcmp (((const CSymInfo*) L)->Name, ((const CSymInfo*) R)->Name); if (Res == 0) { Res = (int)((const CSymInfo*) L)->Id - (int)((const CSymInfo*) R)->Id; } return Res; } /*****************************************************************************/ /* File info */ /*****************************************************************************/ static FileInfo* NewFileInfo (const StrBuf* Name) /* Create a new FileInfo struct and return it */ { /* Allocate memory */ FileInfo* F = xmalloc (sizeof (FileInfo) + SB_GetLen (Name)); /* Initialize it */ CollInit (&F->ModInfoByName); CollInit (&F->LineInfoByLine); memcpy (F->Name, SB_GetConstBuf (Name), SB_GetLen (Name) + 1); /* Return it */ return F; } static void FreeFileInfo (FileInfo* F) /* Free a FileInfo struct */ { /* Delete the collections */ CollDone (&F->ModInfoByName); CollDone (&F->LineInfoByLine); /* Free the file info structure itself */ xfree (F); } static cc65_sourceinfo* new_cc65_sourceinfo (unsigned Count) /* Allocate and return a cc65_sourceinfo struct that is able to hold Count ** entries. Initialize the count field of the returned struct. */ { cc65_sourceinfo* S = xmalloc (sizeof (*S) - sizeof (S->data[0]) + Count * sizeof (S->data[0])); S->count = Count; return S; } static void CopyFileInfo (cc65_sourcedata* D, const FileInfo* F) /* Copy data from a FileInfo struct to a cc65_sourcedata struct */ { D->source_id = F->Id; D->source_name = F->Name; D->source_size = F->Size; D->source_mtime = F->MTime; } static int CompareFileInfoByName (const void* L, const void* R) /* Helper function to sort file infos in a collection by name */ { /* Sort by file name. If names are equal, sort by timestamp, ** then sort by size. Which means, identical files will go ** together. */ int Res = strcmp (((const FileInfo*) L)->Name, ((const FileInfo*) R)->Name); if (Res != 0) { return Res; } if (((const FileInfo*) L)->MTime > ((const FileInfo*) R)->MTime) { return 1; } else if (((const FileInfo*) L)->MTime < ((const FileInfo*) R)->MTime) { return -1; } if (((const FileInfo*) L)->Size > ((const FileInfo*) R)->Size) { return 1; } else if (((const FileInfo*) L)->Size < ((const FileInfo*) R)->Size) { return -1; } else { return 0; } } /*****************************************************************************/ /* Library info */ /*****************************************************************************/ static LibInfo* NewLibInfo (const StrBuf* Name) /* Create a new LibInfo struct, intialize and return it */ { /* Allocate memory */ LibInfo* L = xmalloc (sizeof (LibInfo) + SB_GetLen (Name)); /* Initialize the name */ memcpy (L->Name, SB_GetConstBuf (Name), SB_GetLen (Name) + 1); /* Return it */ return L; } static void FreeLibInfo (LibInfo* L) /* Free a LibInfo struct */ { xfree (L); } static cc65_libraryinfo* new_cc65_libraryinfo (unsigned Count) /* Allocate and return a cc65_libraryinfo struct that is able to hold Count ** entries. Initialize the count field of the returned struct. */ { cc65_libraryinfo* L = xmalloc (sizeof (*L) - sizeof (L->data[0]) + Count * sizeof (L->data[0])); L->count = Count; return L; } static void CopyLibInfo (cc65_librarydata* D, const LibInfo* L) /* Copy data from a LibInfo struct to a cc65_librarydata struct */ { D->library_id = L->Id; D->library_name = L->Name; } /*****************************************************************************/ /* Line info */ /*****************************************************************************/ static LineInfo* NewLineInfo (void) /* Create a new LineInfo struct and return it */ { /* Allocate memory */ LineInfo* L = xmalloc (sizeof (LineInfo)); /* Initialize and return it */ CollInit (&L->SpanInfoList); return L; } static void FreeLineInfo (LineInfo* L) /* Free a LineInfo struct */ { CollDone (&L->SpanInfoList); xfree (L); } static cc65_lineinfo* new_cc65_lineinfo (unsigned Count) /* Allocate and return a cc65_lineinfo struct that is able to hold Count ** entries. Initialize the count field of the returned struct. */ { cc65_lineinfo* L = xmalloc (sizeof (*L) - sizeof (L->data[0]) + Count * sizeof (L->data[0])); L->count = Count; return L; } static void CopyLineInfo (cc65_linedata* D, const LineInfo* L) /* Copy data from a LineInfo struct to a cc65_linedata struct */ { D->line_id = L->Id; D->source_id = L->File.Info->Id; D->source_line = L->Line; D->line_type = L->Type; D->count = L->Count; } static int CompareLineInfoByLine (const void* L, const void* R) /* Helper function to sort line infos in a collection by line. */ { int Left = ((const LineInfo*) L)->Line; int Right = ((const LineInfo*) R)->Line; return Left - Right; } /*****************************************************************************/ /* Module info */ /*****************************************************************************/ static ModInfo* NewModInfo (const StrBuf* Name) /* Create a new ModInfo struct, intialize and return it */ { /* Allocate memory */ ModInfo* M = xmalloc (sizeof (ModInfo) + SB_GetLen (Name)); /* Initialize it */ M->MainScope = 0; CollInit (&M->CSymFuncByName); CollInit (&M->FileInfoByName); CollInit (&M->ScopeInfoByName); memcpy (M->Name, SB_GetConstBuf (Name), SB_GetLen (Name) + 1); /* Return it */ return M; } static void FreeModInfo (ModInfo* M) /* Free a ModInfo struct */ { /* Free the collections */ CollDone (&M->CSymFuncByName); CollDone (&M->FileInfoByName); CollDone (&M->ScopeInfoByName); /* Free the structure itself */ xfree (M); } static cc65_moduleinfo* new_cc65_moduleinfo (unsigned Count) /* Allocate and return a cc65_moduleinfo struct that is able to hold Count ** entries. Initialize the count field of the returned struct. */ { cc65_moduleinfo* M = xmalloc (sizeof (*M) - sizeof (M->data[0]) + Count * sizeof (M->data[0])); M->count = Count; return M; } static void CopyModInfo (cc65_moduledata* D, const ModInfo* M) /* Copy data from a ModInfo struct to a cc65_moduledata struct */ { D->module_id = M->Id; D->module_name = M->Name; D->source_id = M->File.Info->Id; D->library_id = GetId (M->Lib.Info); D->scope_id = GetId (M->MainScope); } static int CompareModInfoByName (const void* L, const void* R) /* Helper function to sort module infos in a collection by name */ { /* Compare module name */ return strcmp (((const ModInfo*) L)->Name, ((const ModInfo*) R)->Name); } /*****************************************************************************/ /* Scope info */ /*****************************************************************************/ static ScopeInfo* NewScopeInfo (const StrBuf* Name) /* Create a new ScopeInfo struct, intialize and return it */ { /* Allocate memory */ ScopeInfo* S = xmalloc (sizeof (ScopeInfo) + SB_GetLen (Name)); /* Initialize the fields as necessary */ S->CSymFunc = 0; CollInit (&S->SpanInfoList); CollInit (&S->SymInfoByName); S->CSymInfoByName = 0; S->ChildScopeList = 0; memcpy (S->Name, SB_GetConstBuf (Name), SB_GetLen (Name) + 1); /* Return it */ return S; } static void FreeScopeInfo (ScopeInfo* S) /* Free a ScopeInfo struct */ { CollDone (&S->SpanInfoList); CollDone (&S->SymInfoByName); CollFree (S->CSymInfoByName); CollFree (S->ChildScopeList); xfree (S); } static cc65_scopeinfo* new_cc65_scopeinfo (unsigned Count) /* Allocate and return a cc65_scopeinfo struct that is able to hold Count ** entries. Initialize the count field of the returned struct. */ { cc65_scopeinfo* S = xmalloc (sizeof (*S) - sizeof (S->data[0]) + Count * sizeof (S->data[0])); S->count = Count; return S; } static void CopyScopeInfo (cc65_scopedata* D, const ScopeInfo* S) /* Copy data from a ScopeInfo struct to a cc65_scopedata struct */ { D->scope_id = S->Id; D->scope_name = S->Name; D->scope_type = S->Type; D->scope_size = S->Size; D->parent_id = GetId (S->Parent.Info); D->symbol_id = GetId (S->Label.Info); D->module_id = S->Mod.Info->Id; } static int CompareScopeInfoByName (const void* L, const void* R) /* Helper function to sort scope infos in a collection by name */ { const ScopeInfo* Left = L; const ScopeInfo* Right = R; /* Compare scope name, then id */ int Res = strcmp (Left->Name, Right->Name); if (Res == 0) { Res = (int)Left->Id - (int)Right->Id; } return Res; } /*****************************************************************************/ /* Segment info */ /*****************************************************************************/ static SegInfo* NewSegInfo (const StrBuf* Name, unsigned Id, cc65_addr Start, cc65_addr Size, const StrBuf* OutputName, unsigned long OutputOffs) /* Create a new SegInfo struct and return it */ { /* Allocate memory */ SegInfo* S = xmalloc (sizeof (SegInfo) + SB_GetLen (Name)); /* Initialize it */ S->Id = Id; S->Start = Start; S->Size = Size; if (SB_GetLen (OutputName) > 0) { /* Output file given */ S->OutputName = SB_StrDup (OutputName); S->OutputOffs = OutputOffs; } else { /* No output file given */ S->OutputName = 0; S->OutputOffs = 0; } memcpy (S->Name, SB_GetConstBuf (Name), SB_GetLen (Name) + 1); /* Return it */ return S; } static void FreeSegInfo (SegInfo* S) /* Free a SegInfo struct */ { xfree (S->OutputName); xfree (S); } static cc65_segmentinfo* new_cc65_segmentinfo (unsigned Count) /* Allocate and return a cc65_segmentinfo struct that is able to hold Count ** entries. Initialize the count field of the returned struct. */ { cc65_segmentinfo* S = xmalloc (sizeof (*S) - sizeof (S->data[0]) + Count * sizeof (S->data[0])); S->count = Count; return S; } static void CopySegInfo (cc65_segmentdata* D, const SegInfo* S) /* Copy data from a SegInfo struct to a cc65_segmentdata struct */ { D->segment_id = S->Id; D->segment_name = S->Name; D->segment_start = S->Start; D->segment_size = S->Size; D->output_name = S->OutputName; D->output_offs = S->OutputOffs; } static int CompareSegInfoByName (const void* L, const void* R) /* Helper function to sort segment infos in a collection by name */ { /* Sort by file name */ return strcmp (((const SegInfo*) L)->Name, ((const SegInfo*) R)->Name); } /*****************************************************************************/ /* Span info */ /*****************************************************************************/ static SpanInfo* NewSpanInfo (void) /* Create a new SpanInfo struct, intialize and return it */ { /* Allocate memory */ SpanInfo* S = xmalloc (sizeof (SpanInfo)); /* Initialize and return it */ S->ScopeInfoList = 0; S->LineInfoList = 0; return S; } static void FreeSpanInfo (SpanInfo* S) /* Free a SpanInfo struct */ { CollFree (S->ScopeInfoList); CollFree (S->LineInfoList); xfree (S); } static cc65_spaninfo* new_cc65_spaninfo (unsigned Count) /* Allocate and return a cc65_spaninfo struct that is able to hold Count ** entries. Initialize the count field of the returned struct. */ { cc65_spaninfo* S = xmalloc (sizeof (*S) - sizeof (S->data[0]) + Count * sizeof (S->data[0])); S->count = Count; return S; } static void CopySpanInfo (cc65_spandata* D, const SpanInfo* S) /* Copy data from a SpanInfo struct to a cc65_spandata struct */ { D->span_id = S->Id; D->span_start = S->Start; D->span_end = S->End; D->segment_id = S->Seg.Info->Id; D->type_id = GetId (S->Type.Info); D->scope_count = CollCount (S->ScopeInfoList); D->line_count = CollCount (S->LineInfoList); } static int CompareSpanInfoByAddr (const void* L, const void* R) /* Helper function to sort span infos in a collection by address. Span infos ** with smaller start address are considered smaller. If start addresses are ** equal, line spans with smaller end address are considered smaller. This ** means, that when CompareSpanInfoByAddr is used for sorting, a range with ** identical start addresses will have smaller spans first, followed by ** larger spans. */ { /* Sort by start of span */ if (((const SpanInfo*) L)->Start > ((const SpanInfo*) R)->Start) { return 1; } else if (((const SpanInfo*) L)->Start < ((const SpanInfo*) R)->Start) { return -1; } else if (((const SpanInfo*) L)->End > ((const SpanInfo*) R)->End) { return 1; } else if (((const SpanInfo*) L)->End < ((const SpanInfo*) R)->End) { return -1; } else { return 0; } } /*****************************************************************************/ /* Symbol info */ /*****************************************************************************/ static SymInfo* NewSymInfo (const StrBuf* Name) /* Create a new SymInfo struct, intialize and return it */ { /* Allocate memory */ SymInfo* S = xmalloc (sizeof (SymInfo) + SB_GetLen (Name)); /* Initialize it as necessary */ S->CSym = 0; S->ImportList = 0; S->CheapLocals = 0; CollInit (&S->DefLineInfoList); CollInit (&S->RefLineInfoList); memcpy (S->Name, SB_GetConstBuf (Name), SB_GetLen (Name) + 1); /* Return it */ return S; } static void FreeSymInfo (SymInfo* S) /* Free a SymInfo struct */ { CollFree (S->ImportList); CollFree (S->CheapLocals); CollDone (&S->DefLineInfoList); CollDone (&S->RefLineInfoList); xfree (S); } static cc65_symbolinfo* new_cc65_symbolinfo (unsigned Count) /* Allocate and return a cc65_symbolinfo struct that is able to hold Count ** entries. Initialize the count field of the returned struct. */ { cc65_symbolinfo* S = xmalloc (sizeof (*S) - sizeof (S->data[0]) + Count * sizeof (S->data[0])); S->count = Count; return S; } static void CopySymInfo (cc65_symboldata* D, const SymInfo* S) /* Copy data from a SymInfo struct to a cc65_symboldata struct */ { SegInfo* Seg; D->symbol_id = S->Id; D->symbol_name = S->Name; D->symbol_type = S->Type; D->symbol_size = S->Size; /* If this is an import, it doesn't have a value or segment. Use the data ** from the matching export instead. */ if (S->Exp.Info) { /* This is an import, because it has a matching export */ D->export_id = S->Exp.Info->Id; D->symbol_value = S->Exp.Info->Value; Seg = S->Exp.Info->Seg.Info; } else { D->export_id = CC65_INV_ID; D->symbol_value = S->Value; Seg = S->Seg.Info; } if (Seg) { D->segment_id = Seg->Id; } else { D->segment_id = CC65_INV_ID; } D->scope_id = S->Scope.Info->Id; if (S->Parent.Info) { D->parent_id = S->Parent.Info->Id; } else { D->parent_id = CC65_INV_ID; } } static int CompareSymInfoByName (const void* L, const void* R) /* Helper function to sort symbol infos in a collection by name */ { /* Sort by symbol name */ return strcmp (((const SymInfo*) L)->Name, ((const SymInfo*) R)->Name); } static int CompareSymInfoByVal (const void* L, const void* R) /* Helper function to sort symbol infos in a collection by value */ { /* Sort by symbol value. If both are equal, sort by symbol name so it ** looks nice when such a list is returned. */ if (((const SymInfo*) L)->Value > ((const SymInfo*) R)->Value) { return 1; } else if (((const SymInfo*) L)->Value < ((const SymInfo*) R)->Value) { return -1; } else { return CompareSymInfoByName (L, R); } } /*****************************************************************************/ /* Type info */ /*****************************************************************************/ /* The following definitions are actually just taken from gentype.h */ /* Size of a data type */ #define GT_SIZE_1 0x00U #define GT_SIZE_2 0x01U #define GT_SIZE_3 0x02U #define GT_SIZE_4 0x03U #define GT_SIZE_MASK 0x07U #define GT_GET_SIZE(x) (((x) & GT_SIZE_MASK) + 1U) /* Sign of the data type */ #define GT_UNSIGNED 0x00U #define GT_SIGNED 0x08U #define GT_SIGN_MASK 0x08U #define GT_HAS_SIGN(x) (((x) & GT_SIZE_MASK) == GT_SIGNED) /* Byte order */ #define GT_LITTLE_ENDIAN 0x00U #define GT_BIG_ENDIAN 0x10U #define GT_BYTEORDER_MASK 0x10U #define GT_IS_LITTLE_ENDIAN(x) (((x) & GT_BYTEORDER_MASK) == GT_LITTLE_ENDIAN) #define GT_IS_BIG_ENDIAN(x) (((x) & GT_BYTEORDER_MASK) == GT_BIG_ENDIAN) /* Type of the data. */ #define GT_TYPE_VOID 0x00U #define GT_TYPE_INT 0x20U #define GT_TYPE_PTR 0x40U #define GT_TYPE_FLOAT 0x60U #define GT_TYPE_ARRAY 0x80U #define GT_TYPE_FUNC 0xA0U #define GT_TYPE_STRUCT 0xC0U #define GT_TYPE_UNION 0xE0U #define GT_TYPE_MASK 0xE0U #define GT_GET_TYPE(x) ((x) & GT_TYPE_MASK) #define GT_IS_INTEGER(x) (GT_GET_TYPE(x) == GT_TYPE_INTEGER) #define GT_IS_POINTER(x) (GT_GET_TYPE(x) == GT_TYPE_POINTER) #define GT_IS_FLOAT(x) (GT_GET_TYPE(x) == GT_TYPE_FLOAT) #define GT_IS_ARRAY(x) (GT_GET_TYPE(x) == GT_TYPE_ARRAY) #define GT_IS_FUNCTION(x) (GT_GET_TYPE(x) == GT_TYPE_FUNCTION) #define GT_IS_STRUCT(x) (GT_GET_TYPE(x) == GT_TYPE_STRUCT) #define GT_IS_UNION(x) (GT_GET_TYPE(x) == GT_TYPE_UNION) /* Combined values for the 6502 family */ #define GT_VOID (GT_TYPE_VOID) #define GT_BYTE (GT_TYPE_INT | GT_LITTLE_ENDIAN | GT_UNSIGNED | GT_SIZE_1) #define GT_WORD (GT_TYPE_INT | GT_LITTLE_ENDIAN | GT_UNSIGNED | GT_SIZE_2) #define GT_DWORD (GT_TYPE_INT | GT_LITTLE_ENDIAN | GT_UNSIGNED | GT_SIZE_4) #define GT_DBYTE (GT_TYPE_PTR | GT_BIG_ENDIAN | GT_UNSIGNED | GT_SIZE_2) #define GT_PTR (GT_TYPE_PTR | GT_LITTLE_ENDIAN | GT_UNSIGNED | GT_SIZE_2) #define GT_FAR_PTR (GT_TYPE_PTR | GT_LITTLE_ENDIAN | GT_UNSIGNED | GT_SIZE_3) #define GT_ARRAY(size) (GT_TYPE_ARRAY | ((size) - 1)) static void FreeTypeInfo (TypeInfo* T) /* Free a TypeInfo struct */ { xfree (T); } static void InitTypeParseData (TypeParseData* P, const StrBuf* Type, unsigned ItemCount) /* Initialize a TypeParseData structure */ { P->Info = xmalloc (sizeof (*P->Info) - sizeof (P->Info->Data[0]) + ItemCount * sizeof (P->Info->Data[0])); P->ItemCount = ItemCount; P->ItemIndex = 0; P->ItemData = P->Info->Data; P->Type = Type; P->Pos = 0; P->Error = 0; } static cc65_typedata* TypeFromString (TypeParseData* P) /* Parse a type string and return a set of typedata structures. Will be called ** recursively. Will set P->Error and return NULL in case of problems. */ { cc65_typedata* Data; unsigned char B; unsigned I; unsigned Count; /* Allocate a new entry */ if (P->ItemIndex >= P->ItemCount) { P->Error = 1; return 0; } Data = &P->ItemData[P->ItemIndex++]; /* Assume no following node */ Data->next = 0; /* Get the next char, then skip it */ if (P->Pos >= SB_GetLen (P->Type)) { P->Error = 1; return 0; } B = SB_At (P->Type, P->Pos++); switch (B) { /* We only handle those that are currently in use */ case GT_VOID: Data->what = CC65_TYPE_VOID; Data->size = 0; break; case GT_BYTE: Data->what = CC65_TYPE_BYTE; Data->size = GT_GET_SIZE (B); break; case GT_WORD: Data->what = CC65_TYPE_WORD; Data->size = GT_GET_SIZE (B); break; case GT_DWORD: Data->what = CC65_TYPE_DWORD; Data->size = GT_GET_SIZE (B); break; case GT_DBYTE: Data->what = CC65_TYPE_DBYTE; Data->size = GT_GET_SIZE (B); break; case GT_PTR: Data->what = CC65_TYPE_PTR; Data->data.ptr.ind_type = TypeFromString (P); Data->size = GT_GET_SIZE (B); break; case GT_FAR_PTR: Data->what = CC65_TYPE_FARPTR; Data->data.ptr.ind_type = TypeFromString (P); Data->size = GT_GET_SIZE (B); break; default: if (GT_GET_TYPE (B) == GT_TYPE_ARRAY) { Count = 0; I = GT_GET_SIZE (B); if (I == 0 || I > 4) { P->Error = 1; break; } P->Pos += I; if (P->Pos > SB_GetLen (P->Type)) { P->Error = 1; break; } while (I) { Count <<= 8; Count |= (unsigned char) SB_At (P->Type, P->Pos - I); --I; } Data->what = CC65_TYPE_ARRAY; Data->data.array.ele_count = Count; Data->data.array.ele_type = TypeFromString (P); if (!P->Error) { Data->size = Data->data.array.ele_count * Data->data.array.ele_type->size; } } else { /* OOPS! */ P->Error = 1; } break; } /* Return our structure or NULL in case of errors */ return P->Error? 0 : Data; } static TypeInfo* ParseTypeString (InputData* D, StrBuf* Type) /* Check if the string T contains a valid type string. Convert it from readable ** to binary. Calculate how many cc65_typedata structures are necessary when it ** is converted. Convert the string into a set of cc65_typedata structures and ** return them. */ { unsigned I; unsigned Count; const char* A; char* B; TypeParseData P; /* The length must not be zero and divideable by two */ unsigned Length = SB_GetLen (Type); if (Length < 2 || (Length & 0x01) != 0) { ParseError (D, CC65_ERROR, "Type value has invalid length"); return 0; } /* The string must consist completely of hex digit chars */ A = SB_GetConstBuf (Type); for (I = 0; I < Length; ++I) { if (!isxdigit (A[I])) { ParseError (D, CC65_ERROR, "Type value contains invalid characters"); return 0; } } /* Convert the type to binary */ B = SB_GetBuf (Type); while (A < SB_GetConstBuf (Type) + Length) { /* Since we know, there are only hex digits, there can't be any errors */ *B++ = (HexValue (A[0]) << 4) | HexValue (A[1]); A += 2; } Type->Len = (Length /= 2); /* Get a pointer to the type data, then count the number of cc65_typedata ** items needed. */ A = SB_GetConstBuf (Type); Count = 0; I = 0; while (I < Length) { switch (A[I]) { /* We only handle those that are currently in use */ case GT_VOID: case GT_BYTE: case GT_WORD: case GT_DWORD: case GT_DBYTE: case GT_PTR: case GT_FAR_PTR: ++Count; ++I; break; default: if (GT_GET_TYPE (A[I]) == GT_TYPE_ARRAY) { ++Count; I += GT_GET_SIZE (A[I]) + 1; } else { /* Unknown type in type string */ ParseError (D, CC65_ERROR, "Unkown type in type value"); return 0; } break; } } /* Check that we're even */ if (I != Length) { ParseError (D, CC65_ERROR, "Syntax error in type in type value"); return 0; } /* Initialize the data structure for parsing the type string */ InitTypeParseData (&P, Type, Count); /* Parse the type string and check for errors */ if (TypeFromString (&P) == 0 || P.ItemCount != P.ItemIndex) { ParseError (D, CC65_ERROR, "Error parsing the type value"); FreeTypeInfo (P.Info); return 0; } /* Return the result of the parse operation */ return P.Info; } /*****************************************************************************/ /* SpanInfoList */ /*****************************************************************************/ static void InitSpanInfoList (SpanInfoList* L) /* Initialize a span info list */ { L->Count = 0; L->List = 0; } static void CreateSpanInfoList (SpanInfoList* L, Collection* SpanInfos) /* Create a SpanInfoList from a Collection with span infos. The collection ** must be sorted by ascending start addresses. */ { unsigned I, J; SpanInfo* S; SpanInfoListEntry* List; unsigned StartIndex; cc65_addr Start; cc65_addr Addr; cc65_addr End; /* Initialize and check if there's something to do */ L->Count = 0; L->List = 0; if (CollCount (SpanInfos) == 0) { /* No entries */ return; } /* Step 1: Determine the number of unique address entries needed */ S = CollAt (SpanInfos, 0); L->Count += (S->End - S->Start) + 1; End = S->End; for (I = 1; I < CollCount (SpanInfos); ++I) { /* Get next entry */ S = CollAt (SpanInfos, I); /* Check for additional unique addresses in this span info */ if (S->Start > End) { L->Count += (S->End - S->Start) + 1; End = S->End; } else if (S->End > End) { L->Count += (S->End - End); End = S->End; } } /* Step 2: Allocate memory and initialize it */ L->List = List = xmalloc (L->Count * sizeof (*List)); for (I = 0; I < L->Count; ++I) { List[I].Count = 0; List[I].Data = 0; } /* Step 3: Determine the number of entries per unique address */ List = L->List; S = CollAt (SpanInfos, 0); StartIndex = 0; Start = S->Start; End = S->End; for (J = StartIndex, Addr = S->Start; Addr <= S->End; ++J, ++Addr) { List[J].Addr = Addr; ++List[J].Count; } for (I = 1; I < CollCount (SpanInfos); ++I) { /* Get next entry */ S = CollAt (SpanInfos, I); /* Determine the start index of the next range. Line infos are sorted ** by ascending start address, so the start address of the next entry ** is always larger than the previous one - we don't need to check ** that. */ if (S->Start <= End) { /* Range starts within out already known linear range */ StartIndex += (unsigned) (S->Start - Start); Start = S->Start; if (S->End > End) { End = S->End; } } else { /* Range starts after the already known */ StartIndex += (unsigned) (End - Start) + 1; Start = S->Start; End = S->End; } for (J = StartIndex, Addr = S->Start; Addr <= S->End; ++J, ++Addr) { List[J].Addr = Addr; ++List[J].Count; } } /* Step 4: Allocate memory for the indirect tables */ for (I = 0, List = L->List; I < L->Count; ++I, ++List) { /* For a count of 1, we store the pointer to the lineinfo for this ** address in the Data pointer directly. For counts > 1, we allocate ** an array of pointers and reset the counter, so we can use it as ** an index later. This is dangerous programming since it disables ** all possible checks! */ if (List->Count > 1) { List->Data = xmalloc (List->Count * sizeof (SpanInfo*)); List->Count = 0; } } /* Step 5: Enter the data into the table */ List = L->List; S = CollAt (SpanInfos, 0); StartIndex = 0; Start = S->Start; End = S->End; for (J = StartIndex, Addr = S->Start; Addr <= S->End; ++J, ++Addr) { assert (List[J].Addr == Addr); if (List[J].Count == 1 && List[J].Data == 0) { List[J].Data = S; } else { ((SpanInfo**) List[J].Data)[List[J].Count++] = S; } } for (I = 1; I < CollCount (SpanInfos); ++I) { /* Get next entry */ S = CollAt (SpanInfos, I); /* Determine the start index of the next range. Line infos are sorted ** by ascending start address, so the start address of the next entry ** is always larger than the previous one - we don't need to check ** that. */ if (S->Start <= End) { /* Range starts within out already known linear range */ StartIndex += (unsigned) (S->Start - Start); Start = S->Start; if (S->End > End) { End = S->End; } } else { /* Range starts after the already known */ StartIndex += (unsigned) (End - Start) + 1; Start = S->Start; End = S->End; } for (J = StartIndex, Addr = S->Start; Addr <= S->End; ++J, ++Addr) { assert (List[J].Addr == Addr); if (List[J].Count == 1 && List[J].Data == 0) { List[J].Data = S; } else { ((SpanInfo**) List[J].Data)[List[J].Count++] = S; } } } } static void DoneSpanInfoList (SpanInfoList* L) /* Delete the contents of a span info list */ { unsigned I; /* Delete the span info and the indirect data */ for (I = 0; I < L->Count; ++I) { /* Get a pointer to the entry */ SpanInfoListEntry* E = &L->List[I]; /* Check for indirect memory */ if (E->Count > 1) { /* SpanInfo addressed indirectly */ xfree (E->Data); } } /* Delete the list */ xfree (L->List); } /*****************************************************************************/ /* Debug info */ /*****************************************************************************/ static DbgInfo* NewDbgInfo (const char* FileName) /* Create a new DbgInfo struct and return it */ { /* Get the length of the name */ unsigned Len = strlen (FileName); /* Allocate memory */ DbgInfo* Info = xmalloc (sizeof (DbgInfo) + Len); /* Initialize it */ CollInit (&Info->CSymInfoById); CollInit (&Info->FileInfoById); CollInit (&Info->LibInfoById); CollInit (&Info->LineInfoById); CollInit (&Info->ModInfoById); CollInit (&Info->ScopeInfoById); CollInit (&Info->SegInfoById); CollInit (&Info->SpanInfoById); CollInit (&Info->SymInfoById); CollInit (&Info->TypeInfoById); CollInit (&Info->CSymFuncByName); CollInit (&Info->FileInfoByName); CollInit (&Info->ModInfoByName); CollInit (&Info->ScopeInfoByName); CollInit (&Info->SegInfoByName); CollInit (&Info->SymInfoByName); CollInit (&Info->SymInfoByVal); InitSpanInfoList (&Info->SpanInfoByAddr); Info->MemUsage = 0; Info->MajorVersion = 0; Info->MinorVersion = 0; memcpy (&Info->FileName, FileName, Len+1); /* Return it */ return Info; } static void FreeDbgInfo (DbgInfo* Info) /* Free a DbgInfo struct */ { unsigned I; /* First, free the items in the collections */ for (I = 0; I < CollCount (&Info->CSymInfoById); ++I) { FreeCSymInfo (CollAt (&Info->CSymInfoById, I)); } for (I = 0; I < CollCount (&Info->FileInfoById); ++I) { FreeFileInfo (CollAt (&Info->FileInfoById, I)); } for (I = 0; I < CollCount (&Info->LibInfoById); ++I) { FreeLibInfo (CollAt (&Info->LibInfoById, I)); } for (I = 0; I < CollCount (&Info->LineInfoById); ++I) { FreeLineInfo (CollAt (&Info->LineInfoById, I)); } for (I = 0; I < CollCount (&Info->ModInfoById); ++I) { FreeModInfo (CollAt (&Info->ModInfoById, I)); } for (I = 0; I < CollCount (&Info->ScopeInfoById); ++I) { FreeScopeInfo (CollAt (&Info->ScopeInfoById, I)); } for (I = 0; I < CollCount (&Info->SegInfoById); ++I) { FreeSegInfo (CollAt (&Info->SegInfoById, I)); } for (I = 0; I < CollCount (&Info->SpanInfoById); ++I) { FreeSpanInfo (CollAt (&Info->SpanInfoById, I)); } for (I = 0; I < CollCount (&Info->SymInfoById); ++I) { FreeSymInfo (CollAt (&Info->SymInfoById, I)); } for (I = 0; I < CollCount (&Info->TypeInfoById); ++I) { FreeTypeInfo (CollAt (&Info->TypeInfoById, I)); } /* Free the memory used by the id collections */ CollDone (&Info->CSymInfoById); CollDone (&Info->FileInfoById); CollDone (&Info->LibInfoById); CollDone (&Info->LineInfoById); CollDone (&Info->ModInfoById); CollDone (&Info->ScopeInfoById); CollDone (&Info->SegInfoById); CollDone (&Info->SpanInfoById); CollDone (&Info->SymInfoById); CollDone (&Info->TypeInfoById); /* Free the memory used by the other collections */ CollDone (&Info->CSymFuncByName); CollDone (&Info->FileInfoByName); CollDone (&Info->ModInfoByName); CollDone (&Info->ScopeInfoByName); CollDone (&Info->SegInfoByName); CollDone (&Info->SymInfoByName); CollDone (&Info->SymInfoByVal); /* Free span info */ DoneSpanInfoList (&Info->SpanInfoByAddr); /* Free the structure itself */ xfree (Info); } /*****************************************************************************/ /* Scanner and parser */ /*****************************************************************************/ static int DigitVal (int C) /* Return the value for a numeric digit. Return -1 if C is invalid */ { if (isdigit (C)) { return C - '0'; } else if (isxdigit (C)) { return toupper (C) - 'A' + 10; } else { return -1; } } static void NextChar (InputData* D) /* Read the next character from the input. Count lines and columns */ { /* Check if we've encountered EOF before */ if (D->C >= 0) { if (D->C == '\n') { ++D->Line; D->Col = 0; } D->C = fgetc (D->F); ++D->Col; } } static void NextToken (InputData* D) /* Read the next token from the input stream */ { static const struct KeywordEntry { const char Keyword[12]; Token Tok; } KeywordTable[] = { { "abs", TOK_ABSOLUTE }, { "addrsize", TOK_ADDRSIZE }, { "auto", TOK_AUTO }, { "count", TOK_COUNT }, { "csym", TOK_CSYM }, { "def", TOK_DEF }, { "enum", TOK_ENUM }, { "equ", TOK_EQUATE }, { "exp", TOK_EXPORT }, { "ext", TOK_EXTERN }, { "file", TOK_FILE }, { "func", TOK_FUNC }, { "global", TOK_GLOBAL }, { "id", TOK_ID }, { "imp", TOK_IMPORT }, { "info", TOK_INFO }, { "lab", TOK_LABEL }, { "lib", TOK_LIBRARY }, { "line", TOK_LINE }, { "long", TOK_LONG }, { "major", TOK_MAJOR }, { "minor", TOK_MINOR }, { "mod", TOK_MODULE }, { "mtime", TOK_MTIME }, { "name", TOK_NAME }, { "offs", TOK_OFFS }, { "oname", TOK_OUTPUTNAME }, { "ooffs", TOK_OUTPUTOFFS }, { "parent", TOK_PARENT }, { "ref", TOK_REF }, { "reg", TOK_REGISTER }, { "ro", TOK_RO }, { "rw", TOK_RW }, { "sc", TOK_SC }, { "scope", TOK_SCOPE }, { "seg", TOK_SEGMENT }, { "size", TOK_SIZE }, { "span", TOK_SPAN }, { "start", TOK_START }, { "static", TOK_STATIC }, { "struct", TOK_STRUCT }, { "sym", TOK_SYM }, { "type", TOK_TYPE }, { "val", TOK_VALUE }, { "var", TOK_VAR }, { "version", TOK_VERSION }, { "zp", TOK_ZEROPAGE }, }; /* Skip whitespace */ while (D->C == ' ' || D->C == '\t' || D->C == '\r') { NextChar (D); } /* Remember the current position as start of the next token */ D->SLine = D->Line; D->SCol = D->Col; /* Identifier? */ if (D->C == '_' || isalpha (D->C)) { const struct KeywordEntry* Entry; /* Read the identifier */ SB_Clear (&D->SVal); while (D->C == '_' || isalnum (D->C)) { SB_AppendChar (&D->SVal, D->C); NextChar (D); } SB_Terminate (&D->SVal); /* Search the identifier in the keyword table */ Entry = bsearch (SB_GetConstBuf (&D->SVal), KeywordTable, sizeof (KeywordTable) / sizeof (KeywordTable[0]), sizeof (KeywordTable[0]), (int (*)(const void*, const void*)) strcmp); if (Entry == 0) { D->Tok = TOK_IDENT; } else { D->Tok = Entry->Tok; } return; } /* Number? */ if (isdigit (D->C)) { int Base = 10; int Val; if (D->C == '0') { NextChar (D); if (toupper (D->C) == 'X') { NextChar (D); Base = 16; } else { Base = 8; } } else { Base = 10; } D->IVal = 0; while ((Val = DigitVal (D->C)) >= 0 && Val < Base) { D->IVal = D->IVal * Base + Val; NextChar (D); } D->Tok = TOK_INTCON; return; } /* Other characters */ switch (D->C) { case '-': NextChar (D); D->Tok = TOK_MINUS; break; case '+': NextChar (D); D->Tok = TOK_PLUS; break; case ',': NextChar (D); D->Tok = TOK_COMMA; break; case '=': NextChar (D); D->Tok = TOK_EQUAL; break; case '\"': SB_Clear (&D->SVal); NextChar (D); while (1) { if (D->C == '\n' || D->C == EOF) { ParseError (D, CC65_ERROR, "Unterminated string constant"); break; } if (D->C == '\"') { NextChar (D); break; } SB_AppendChar (&D->SVal, D->C); NextChar (D); } SB_Terminate (&D->SVal); D->Tok = TOK_STRCON; break; case '\n': NextChar (D); D->Tok = TOK_EOL; break; case EOF: D->Tok = TOK_EOF; break; default: ParseError (D, CC65_ERROR, "Invalid input character '%c'", D->C); } } static int TokenIsKeyword (Token Tok) /* Return true if the given token is a keyword */ { return (Tok >= TOK_FIRST_KEYWORD && Tok <= TOK_LAST_KEYWORD); } static int TokenFollows (InputData* D, Token Tok, const char* Name) /* Check for a specific token that follows. */ { if (D->Tok != Tok) { ParseError (D, CC65_ERROR, "%s expected", Name); SkipLine (D); return 0; } else { return 1; } } static int IntConstFollows (InputData* D) /* Check for an integer constant */ { return TokenFollows (D, TOK_INTCON, "Integer constant"); } static int StrConstFollows (InputData* D) /* Check for a string literal */ { return TokenFollows (D, TOK_STRCON, "String literal"); } static int Consume (InputData* D, Token Tok, const char* Name) /* Check for a token and consume it. Return true if the token was comsumed, ** return false otherwise. */ { if (TokenFollows (D, Tok, Name)) { NextToken (D); return 1; } else { return 0; } } static int ConsumeEqual (InputData* D) /* Consume an equal sign */ { return Consume (D, TOK_EQUAL, "'='"); } static void ConsumeEOL (InputData* D) /* Consume an end-of-line token, if we aren't at end-of-file */ { if (D->Tok != TOK_EOF) { if (D->Tok != TOK_EOL) { ParseError (D, CC65_ERROR, "Extra tokens in line"); SkipLine (D); } NextToken (D); } } static void ParseCSym (InputData* D) /* Parse a CSYM line */ { /* Most of the following variables are initialized with a value that is ** overwritten later. This is just to avoid compiler warnings. */ unsigned Id = 0; StrBuf Name = STRBUF_INITIALIZER; int Offs = 0; cc65_csym_sc SC = CC65_CSYM_AUTO; unsigned ScopeId = 0; unsigned SymId = CC65_INV_ID; unsigned TypeId = CC65_INV_ID; CSymInfo* S; enum { ibNone = 0x0000, ibId = 0x0001, ibOffs = 0x0002, ibName = 0x0004, ibSC = 0x0008, ibScopeId = 0x0010, ibSymId = 0x0020, ibType = 0x0040, ibRequired = ibId | ibName | ibSC | ibScopeId | ibType, } InfoBits = ibNone; /* Skip the CSYM token */ NextToken (D); /* More stuff follows */ while (1) { Token Tok; /* Something we know? */ if (D->Tok != TOK_ID && D->Tok != TOK_NAME && D->Tok != TOK_OFFS && D->Tok != TOK_SC && D->Tok != TOK_SCOPE && D->Tok != TOK_SYM && D->Tok != TOK_TYPE) { /* Try smart error recovery */ if (D->Tok == TOK_IDENT || TokenIsKeyword (D->Tok)) { UnknownKeyword (D); continue; } /* Done */ break; } /* Remember the token, skip it, check for equal */ Tok = D->Tok; NextToken (D); if (!ConsumeEqual (D)) { goto ErrorExit; } /* Check what the token was */ switch (Tok) { case TOK_ID: if (!IntConstFollows (D)) { goto ErrorExit; } Id = D->IVal; NextToken (D); InfoBits |= ibId; break; case TOK_NAME: if (!StrConstFollows (D)) { goto ErrorExit; } SB_Copy (&Name, &D->SVal); SB_Terminate (&Name); InfoBits |= ibName; NextToken (D); break; case TOK_OFFS: Offs = 1; if (D->Tok == TOK_MINUS) { Offs = -1; NextToken (D); } if (!IntConstFollows (D)) { goto ErrorExit; } Offs *= (int) D->IVal; InfoBits |= ibOffs; NextToken (D); break; case TOK_SC: switch (D->Tok) { case TOK_AUTO: SC = CC65_CSYM_AUTO; break; case TOK_EXTERN: SC = CC65_CSYM_EXTERN; break; case TOK_REGISTER: SC = CC65_CSYM_REG; break; case TOK_STATIC: SC = CC65_CSYM_STATIC; break; default: ParseError (D, CC65_ERROR, "Invalid storage class token"); break; } InfoBits |= ibSC; NextToken (D); break; case TOK_SCOPE: if (!IntConstFollows (D)) { goto ErrorExit; } ScopeId = D->IVal; NextToken (D); InfoBits |= ibScopeId; break; case TOK_SYM: if (!IntConstFollows (D)) { goto ErrorExit; } SymId = D->IVal; NextToken (D); InfoBits |= ibSymId; break; case TOK_TYPE: if (!IntConstFollows (D)) { goto ErrorExit; } TypeId = D->IVal; NextToken (D); InfoBits |= ibType; break; default: /* NOTREACHED */ UnexpectedToken (D); goto ErrorExit; } /* Comma or done */ if (D->Tok != TOK_COMMA) { break; } NextToken (D); } /* Check for end of line */ if (D->Tok != TOK_EOL && D->Tok != TOK_EOF) { UnexpectedToken (D); SkipLine (D); goto ErrorExit; } /* Check for required and/or matched information */ if ((InfoBits & ibRequired) != ibRequired) { ParseError (D, CC65_ERROR, "Required attributes missing"); goto ErrorExit; } /* Symbol only valid if storage class not auto */ if (((InfoBits & ibSymId) != 0) && (SC == CC65_CSYM_AUTO)) { ParseError (D, CC65_ERROR, "Only non auto symbols can have a symbol attached"); goto ErrorExit; } /* Create the symbol info */ S = NewCSymInfo (&Name); S->Id = Id; S->Kind = CC65_CSYM_VAR; S->SC = SC; S->Offs = Offs; S->Sym.Id = SymId; S->Type.Id = TypeId; S->Scope.Id = ScopeId; /* Remember it */ CollReplaceExpand (&D->Info->CSymInfoById, S, Id); ErrorExit: /* Entry point in case of errors */ SB_Done (&Name); return; } static void ParseFile (InputData* D) /* Parse a FILE line */ { unsigned Id = 0; unsigned long Size = 0; unsigned long MTime = 0; Collection ModIds = COLLECTION_INITIALIZER; StrBuf Name = STRBUF_INITIALIZER; FileInfo* F; enum { ibNone = 0x00, ibId = 0x01, ibName = 0x02, ibSize = 0x04, ibMTime = 0x08, ibModId = 0x10, ibRequired = ibId | ibName | ibSize | ibMTime | ibModId, } InfoBits = ibNone; /* Skip the FILE token */ NextToken (D); /* More stuff follows */ while (1) { Token Tok; /* Something we know? */ if (D->Tok != TOK_ID && D->Tok != TOK_MODULE && D->Tok != TOK_MTIME && D->Tok != TOK_NAME && D->Tok != TOK_SIZE) { /* Try smart error recovery */ if (D->Tok == TOK_IDENT || TokenIsKeyword (D->Tok)) { UnknownKeyword (D); continue; } /* Done */ break; } /* Remember the token, skip it, check for equal */ Tok = D->Tok; NextToken (D); if (!ConsumeEqual (D)) { goto ErrorExit; } /* Check what the token was */ switch (Tok) { case TOK_ID: if (!IntConstFollows (D)) { goto ErrorExit; } Id = D->IVal; InfoBits |= ibId; NextToken (D); break; case TOK_MTIME: if (!IntConstFollows (D)) { goto ErrorExit; } MTime = D->IVal; NextToken (D); InfoBits |= ibMTime; break; case TOK_MODULE: while (1) { if (!IntConstFollows (D)) { goto ErrorExit; } CollAppendId (&ModIds, (unsigned) D->IVal); NextToken (D); if (D->Tok != TOK_PLUS) { break; } NextToken (D); } InfoBits |= ibModId; break; case TOK_NAME: if (!StrConstFollows (D)) { goto ErrorExit; } SB_Copy (&Name, &D->SVal); SB_Terminate (&Name); InfoBits |= ibName; NextToken (D); break; case TOK_SIZE: if (!IntConstFollows (D)) { goto ErrorExit; } Size = D->IVal; NextToken (D); InfoBits |= ibSize; break; default: /* NOTREACHED */ UnexpectedToken (D); goto ErrorExit; } /* Comma or done */ if (D->Tok != TOK_COMMA) { break; } NextToken (D); } /* Check for end of line */ if (D->Tok != TOK_EOL && D->Tok != TOK_EOF) { UnexpectedToken (D); SkipLine (D); goto ErrorExit; } /* Check for required information */ if ((InfoBits & ibRequired) != ibRequired) { ParseError (D, CC65_ERROR, "Required attributes missing"); goto ErrorExit; } /* Create the file info and remember it */ F = NewFileInfo (&Name); F->Id = Id; F->Size = Size; F->MTime = MTime; CollMove (&ModIds, &F->ModInfoByName); CollReplaceExpand (&D->Info->FileInfoById, F, Id); CollAppend (&D->Info->FileInfoByName, F); ErrorExit: /* Entry point in case of errors */ CollDone (&ModIds); SB_Done (&Name); return; } static void ParseInfo (InputData* D) /* Parse an INFO line */ { /* Skip the INFO token */ NextToken (D); /* More stuff follows */ while (1) { Token Tok; /* Something we know? */ if (D->Tok != TOK_CSYM && D->Tok != TOK_FILE && D->Tok != TOK_LIBRARY && D->Tok != TOK_LINE && D->Tok != TOK_MODULE && D->Tok != TOK_SCOPE && D->Tok != TOK_SEGMENT && D->Tok != TOK_SPAN && D->Tok != TOK_SYM && D->Tok != TOK_TYPE) { /* Try smart error recovery */ if (D->Tok == TOK_IDENT || TokenIsKeyword (D->Tok)) { UnknownKeyword (D); continue; } /* Done */ break; } /* Remember the token, skip it, check for equal, check for an integer ** constant. */ Tok = D->Tok; NextToken (D); if (!ConsumeEqual (D)) { goto ErrorExit; } if (!IntConstFollows (D)) { goto ErrorExit; } /* Check what the token was */ switch (Tok) { case TOK_CSYM: CollGrow (&D->Info->CSymInfoById, D->IVal); break; case TOK_FILE: CollGrow (&D->Info->FileInfoById, D->IVal); CollGrow (&D->Info->FileInfoByName, D->IVal); break; case TOK_LIBRARY: CollGrow (&D->Info->LibInfoById, D->IVal); break; case TOK_LINE: CollGrow (&D->Info->LineInfoById, D->IVal); break; case TOK_MODULE: CollGrow (&D->Info->ModInfoById, D->IVal); CollGrow (&D->Info->ModInfoByName, D->IVal); break; case TOK_SCOPE: CollGrow (&D->Info->ScopeInfoById, D->IVal); CollGrow (&D->Info->ScopeInfoByName, D->IVal); break; case TOK_SEGMENT: CollGrow (&D->Info->SegInfoById, D->IVal); CollGrow (&D->Info->SegInfoByName, D->IVal); break; case TOK_SPAN: CollGrow (&D->Info->SpanInfoById, D->IVal); break; case TOK_SYM: CollGrow (&D->Info->SymInfoById, D->IVal); CollGrow (&D->Info->SymInfoByName, D->IVal); CollGrow (&D->Info->SymInfoByVal, D->IVal); break; case TOK_TYPE: CollGrow (&D->Info->TypeInfoById, D->IVal); break; default: /* NOTREACHED */ UnexpectedToken (D); goto ErrorExit; } /* Skip the number */ NextToken (D); /* Comma or done */ if (D->Tok != TOK_COMMA) { break; } NextToken (D); } /* Check for end of line */ if (D->Tok != TOK_EOL && D->Tok != TOK_EOF) { UnexpectedToken (D); SkipLine (D); goto ErrorExit; } ErrorExit: /* Entry point in case of errors */ return; } static void ParseLibrary (InputData* D) /* Parse a LIBRARY line */ { unsigned Id = 0; StrBuf Name = STRBUF_INITIALIZER; LibInfo* L; enum { ibNone = 0x00, ibId = 0x01, ibName = 0x02, ibRequired = ibId | ibName, } InfoBits = ibNone; /* Skip the LIBRARY token */ NextToken (D); /* More stuff follows */ while (1) { Token Tok; /* Something we know? */ if (D->Tok != TOK_ID && D->Tok != TOK_NAME) { /* Try smart error recovery */ if (D->Tok == TOK_IDENT || TokenIsKeyword (D->Tok)) { UnknownKeyword (D); continue; } /* Done */ break; } /* Remember the token, skip it, check for equal */ Tok = D->Tok; NextToken (D); if (!ConsumeEqual (D)) { goto ErrorExit; } /* Check what the token was */ switch (Tok) { case TOK_ID: if (!IntConstFollows (D)) { goto ErrorExit; } Id = D->IVal; InfoBits |= ibId; NextToken (D); break; case TOK_NAME: if (!StrConstFollows (D)) { goto ErrorExit; } SB_Copy (&Name, &D->SVal); SB_Terminate (&Name); InfoBits |= ibName; NextToken (D); break; default: /* NOTREACHED */ UnexpectedToken (D); goto ErrorExit; } /* Comma or done */ if (D->Tok != TOK_COMMA) { break; } NextToken (D); } /* Check for end of line */ if (D->Tok != TOK_EOL && D->Tok != TOK_EOF) { UnexpectedToken (D); SkipLine (D); goto ErrorExit; } /* Check for required information */ if ((InfoBits & ibRequired) != ibRequired) { ParseError (D, CC65_ERROR, "Required attributes missing"); goto ErrorExit; } /* Create the library info and remember it */ L = NewLibInfo (&Name); L->Id = Id; CollReplaceExpand (&D->Info->LibInfoById, L, Id); ErrorExit: /* Entry point in case of errors */ SB_Done (&Name); return; } static void ParseLine (InputData* D) /* Parse a LINE line */ { unsigned Id = CC65_INV_ID; unsigned FileId = CC65_INV_ID; Collection SpanIds = COLLECTION_INITIALIZER; cc65_line Line = 0; cc65_line_type Type = CC65_LINE_ASM; unsigned Count = 0; LineInfo* L; enum { ibNone = 0x00, ibCount = 0x01, ibFileId = 0x02, ibId = 0x04, ibLine = 0x08, ibSpanId = 0x20, ibType = 0x40, ibRequired = ibFileId | ibId | ibLine, } InfoBits = ibNone; /* Skip the LINE token */ NextToken (D); /* More stuff follows */ while (1) { Token Tok; /* Something we know? */ if (D->Tok != TOK_COUNT && D->Tok != TOK_FILE && D->Tok != TOK_ID && D->Tok != TOK_LINE && D->Tok != TOK_SPAN && D->Tok != TOK_TYPE) { /* Try smart error recovery */ if (D->Tok == TOK_IDENT || TokenIsKeyword (D->Tok)) { UnknownKeyword (D); continue; } /* Done */ break; } /* Remember the token, skip it, check for equal */ Tok = D->Tok; NextToken (D); if (!ConsumeEqual (D)) { goto ErrorExit; } /* Check what the token was */ switch (Tok) { case TOK_FILE: if (!IntConstFollows (D)) { goto ErrorExit; } FileId = D->IVal; InfoBits |= ibFileId; NextToken (D); break; case TOK_ID: if (!IntConstFollows (D)) { goto ErrorExit; } Id = D->IVal; InfoBits |= ibId; NextToken (D); break; case TOK_LINE: if (!IntConstFollows (D)) { goto ErrorExit; } Line = (cc65_line) D->IVal; NextToken (D); InfoBits |= ibLine; break; case TOK_SPAN: while (1) { if (!IntConstFollows (D)) { goto ErrorExit; } CollAppendId (&SpanIds, (unsigned) D->IVal); NextToken (D); if (D->Tok != TOK_PLUS) { break; } NextToken (D); } InfoBits |= ibSpanId; break; case TOK_TYPE: if (!IntConstFollows (D)) { goto ErrorExit; } Type = (cc65_line_type) D->IVal; InfoBits |= ibType; NextToken (D); break; case TOK_COUNT: if (!IntConstFollows (D)) { goto ErrorExit; } Count = D->IVal; InfoBits |= ibCount; NextToken (D); break; default: /* NOTREACHED */ UnexpectedToken (D); goto ErrorExit; } /* Comma or done */ if (D->Tok != TOK_COMMA) { break; } NextToken (D); } /* Check for end of line */ if (D->Tok != TOK_EOL && D->Tok != TOK_EOF) { UnexpectedToken (D); SkipLine (D); goto ErrorExit; } /* Check for required information */ if ((InfoBits & ibRequired) != ibRequired) { ParseError (D, CC65_ERROR, "Required attributes missing"); goto ErrorExit; } /* Create the line info and remember it */ L = NewLineInfo (); L->Id = Id; L->Line = Line; L->File.Id = FileId; L->Type = Type; L->Count = Count; CollMove (&SpanIds, &L->SpanInfoList); CollReplaceExpand (&D->Info->LineInfoById, L, Id); ErrorExit: /* Entry point in case of errors */ CollDone (&SpanIds); return; } static void ParseModule (InputData* D) /* Parse a MODULE line */ { /* Most of the following variables are initialized with a value that is ** overwritten later. This is just to avoid compiler warnings. */ unsigned Id = CC65_INV_ID; StrBuf Name = STRBUF_INITIALIZER; unsigned FileId = CC65_INV_ID; unsigned LibId = CC65_INV_ID; ModInfo* M; enum { ibNone = 0x000, ibFileId = 0x001, ibId = 0x002, ibName = 0x004, ibLibId = 0x008, ibRequired = ibId | ibName | ibFileId, } InfoBits = ibNone; /* Skip the MODULE token */ NextToken (D); /* More stuff follows */ while (1) { Token Tok; /* Something we know? */ if (D->Tok != TOK_FILE && D->Tok != TOK_ID && D->Tok != TOK_NAME && D->Tok != TOK_LIBRARY) { /* Try smart error recovery */ if (D->Tok == TOK_IDENT || TokenIsKeyword (D->Tok)) { UnknownKeyword (D); continue; } /* Done */ break; } /* Remember the token, skip it, check for equal */ Tok = D->Tok; NextToken (D); if (!ConsumeEqual (D)) { goto ErrorExit; } /* Check what the token was */ switch (Tok) { case TOK_FILE: if (!IntConstFollows (D)) { goto ErrorExit; } FileId = D->IVal; InfoBits |= ibFileId; NextToken (D); break; case TOK_ID: if (!IntConstFollows (D)) { goto ErrorExit; } Id = D->IVal; InfoBits |= ibId; NextToken (D); break; case TOK_NAME: if (!StrConstFollows (D)) { goto ErrorExit; } SB_Copy (&Name, &D->SVal); SB_Terminate (&Name); InfoBits |= ibName; NextToken (D); break; case TOK_LIBRARY: if (!IntConstFollows (D)) { goto ErrorExit; } LibId = D->IVal; InfoBits |= ibLibId; NextToken (D); break; default: /* NOTREACHED */ UnexpectedToken (D); goto ErrorExit; } /* Comma or done */ if (D->Tok != TOK_COMMA) { break; } NextToken (D); } /* Check for end of line */ if (D->Tok != TOK_EOL && D->Tok != TOK_EOF) { UnexpectedToken (D); SkipLine (D); goto ErrorExit; } /* Check for required and/or matched information */ if ((InfoBits & ibRequired) != ibRequired) { ParseError (D, CC65_ERROR, "Required attributes missing"); goto ErrorExit; } /* Create the scope info */ M = NewModInfo (&Name); M->File.Id = FileId; M->Id = Id; M->Lib.Id = LibId; /* ... and remember it */ CollReplaceExpand (&D->Info->ModInfoById, M, Id); CollAppend (&D->Info->ModInfoByName, M); ErrorExit: /* Entry point in case of errors */ SB_Done (&Name); return; } static void ParseScope (InputData* D) /* Parse a SCOPE line */ { /* Most of the following variables are initialized with a value that is ** overwritten later. This is just to avoid compiler warnings. */ unsigned Id = CC65_INV_ID; cc65_scope_type Type = CC65_SCOPE_MODULE; cc65_size Size = 0; StrBuf Name = STRBUF_INITIALIZER; unsigned ModId = CC65_INV_ID; unsigned ParentId = CC65_INV_ID; Collection SpanIds = COLLECTION_INITIALIZER; unsigned SymId = CC65_INV_ID; ScopeInfo* S; enum { ibNone = 0x000, ibId = 0x001, ibModId = 0x002, ibName = 0x004, ibParentId = 0x008, ibSize = 0x010, ibSpanId = 0x020, ibSymId = 0x040, ibType = 0x080, ibRequired = ibId | ibModId | ibName, } InfoBits = ibNone; /* Skip the SCOPE token */ NextToken (D); /* More stuff follows */ while (1) { Token Tok; /* Something we know? */ if (D->Tok != TOK_ID && D->Tok != TOK_MODULE && D->Tok != TOK_NAME && D->Tok != TOK_PARENT && D->Tok != TOK_SIZE && D->Tok != TOK_SPAN && D->Tok != TOK_SYM && D->Tok != TOK_TYPE) { /* Try smart error recovery */ if (D->Tok == TOK_IDENT || TokenIsKeyword (D->Tok)) { UnknownKeyword (D); continue; } /* Done */ break; } /* Remember the token, skip it, check for equal */ Tok = D->Tok; NextToken (D); if (!ConsumeEqual (D)) { goto ErrorExit; } /* Check what the token was */ switch (Tok) { case TOK_ID: if (!IntConstFollows (D)) { goto ErrorExit; } Id = D->IVal; InfoBits |= ibId; NextToken (D); break; case TOK_MODULE: if (!IntConstFollows (D)) { goto ErrorExit; } ModId = D->IVal; InfoBits |= ibModId; NextToken (D); break; case TOK_NAME: if (!StrConstFollows (D)) { goto ErrorExit; } SB_Copy (&Name, &D->SVal); SB_Terminate (&Name); InfoBits |= ibName; NextToken (D); break; case TOK_PARENT: if (!IntConstFollows (D)) { goto ErrorExit; } ParentId = D->IVal; NextToken (D); InfoBits |= ibParentId; break; case TOK_SIZE: if (!IntConstFollows (D)) { goto ErrorExit; } Size = (cc65_size) D->IVal; InfoBits |= ibSize; NextToken (D); break; case TOK_SPAN: while (1) { if (!IntConstFollows (D)) { goto ErrorExit; } CollAppendId (&SpanIds, (unsigned) D->IVal); NextToken (D); if (D->Tok != TOK_PLUS) { break; } NextToken (D); } InfoBits |= ibSpanId; break; case TOK_SYM: if (!IntConstFollows (D)) { goto ErrorExit; } SymId = D->IVal; NextToken (D); InfoBits |= ibSymId; break; case TOK_TYPE: switch (D->Tok) { case TOK_GLOBAL: Type = CC65_SCOPE_GLOBAL; break; case TOK_FILE: Type = CC65_SCOPE_MODULE; break; case TOK_SCOPE: Type = CC65_SCOPE_SCOPE; break; case TOK_STRUCT: Type = CC65_SCOPE_STRUCT; break; case TOK_ENUM: Type = CC65_SCOPE_ENUM; break; default: ParseError (D, CC65_ERROR, "Unknown value for attribute \"type\""); SkipLine (D); goto ErrorExit; } NextToken (D); InfoBits |= ibType; break; default: /* NOTREACHED */ UnexpectedToken (D); goto ErrorExit; } /* Comma or done */ if (D->Tok != TOK_COMMA) { break; } NextToken (D); } /* Check for end of line */ if (D->Tok != TOK_EOL && D->Tok != TOK_EOF) { UnexpectedToken (D); SkipLine (D); goto ErrorExit; } /* Check for required and/or matched information */ if ((InfoBits & ibRequired) != ibRequired) { ParseError (D, CC65_ERROR, "Required attributes missing"); goto ErrorExit; } /* Create the scope info ... */ S = NewScopeInfo (&Name); S->Id = Id; S->Type = Type; S->Size = Size; S->Mod.Id = ModId; S->Parent.Id = ParentId; S->Label.Id = SymId; CollMove (&SpanIds, &S->SpanInfoList); /* ... and remember it */ CollReplaceExpand (&D->Info->ScopeInfoById, S, Id); CollAppend (&D->Info->ScopeInfoByName, S); ErrorExit: /* Entry point in case of errors */ CollDone (&SpanIds); SB_Done (&Name); return; } static void ParseSegment (InputData* D) /* Parse a SEGMENT line */ { unsigned Id = 0; cc65_addr Start = 0; cc65_addr Size = 0; StrBuf Name = STRBUF_INITIALIZER; StrBuf OutputName = STRBUF_INITIALIZER; unsigned long OutputOffs = 0; SegInfo* S; enum { ibNone = 0x000, ibAddrSize = 0x001, ibId = 0x002, ibOutputName= 0x004, ibOutputOffs= 0x008, ibName = 0x010, ibSize = 0x020, ibStart = 0x040, ibType = 0x080, ibRequired = ibId | ibName | ibStart | ibSize | ibAddrSize | ibType, } InfoBits = ibNone; /* Skip the SEGMENT token */ NextToken (D); /* More stuff follows */ while (1) { Token Tok; /* Something we know? */ if (D->Tok != TOK_ADDRSIZE && D->Tok != TOK_ID && D->Tok != TOK_NAME && D->Tok != TOK_OUTPUTNAME && D->Tok != TOK_OUTPUTOFFS && D->Tok != TOK_SIZE && D->Tok != TOK_START && D->Tok != TOK_TYPE) { /* Try smart error recovery */ if (D->Tok == TOK_IDENT || TokenIsKeyword (D->Tok)) { UnknownKeyword (D); continue; } /* Done */ break; } /* Remember the token, skip it, check for equal */ Tok = D->Tok; NextToken (D); if (!ConsumeEqual (D)) { goto ErrorExit; } /* Check what the token was */ switch (Tok) { case TOK_ADDRSIZE: NextToken (D); InfoBits |= ibAddrSize; break; case TOK_ID: if (!IntConstFollows (D)) { goto ErrorExit; } Id = D->IVal; InfoBits |= ibId; NextToken (D); break; case TOK_NAME: if (!StrConstFollows (D)) { goto ErrorExit; } SB_Copy (&Name, &D->SVal); SB_Terminate (&Name); InfoBits |= ibName; NextToken (D); break; case TOK_OUTPUTNAME: if (!StrConstFollows (D)) { goto ErrorExit; } SB_Copy (&OutputName, &D->SVal); SB_Terminate (&OutputName); InfoBits |= ibOutputName; NextToken (D); break; case TOK_OUTPUTOFFS: if (!IntConstFollows (D)) { goto ErrorExit; } OutputOffs = D->IVal; NextToken (D); InfoBits |= ibOutputOffs; break; case TOK_SIZE: if (!IntConstFollows (D)) { goto ErrorExit; } Size = D->IVal; NextToken (D); InfoBits |= ibSize; break; case TOK_START: if (!IntConstFollows (D)) { goto ErrorExit; } Start = (cc65_addr) D->IVal; NextToken (D); InfoBits |= ibStart; break; case TOK_TYPE: NextToken (D); InfoBits |= ibType; break; default: /* NOTREACHED */ UnexpectedToken (D); goto ErrorExit; } /* Comma or done */ if (D->Tok != TOK_COMMA) { break; } NextToken (D); } /* Check for end of line */ if (D->Tok != TOK_EOL && D->Tok != TOK_EOF) { UnexpectedToken (D); SkipLine (D); goto ErrorExit; } /* Check for required and/or matched information */ if ((InfoBits & ibRequired) != ibRequired) { ParseError (D, CC65_ERROR, "Required attributes missing"); goto ErrorExit; } InfoBits &= (ibOutputName | ibOutputOffs); if (InfoBits != ibNone && InfoBits != (ibOutputName | ibOutputOffs)) { ParseError (D, CC65_ERROR, "Attributes \"outputname\" and \"outputoffs\" must be paired"); goto ErrorExit; } /* Fix OutputOffs if not given */ if (InfoBits == ibNone) { OutputOffs = 0; } /* Create the segment info and remember it */ S = NewSegInfo (&Name, Id, Start, Size, &OutputName, OutputOffs); CollReplaceExpand (&D->Info->SegInfoById, S, Id); CollAppend (&D->Info->SegInfoByName, S); ErrorExit: /* Entry point in case of errors */ SB_Done (&Name); SB_Done (&OutputName); return; } static void ParseSpan (InputData* D) /* Parse a SPAN line */ { unsigned Id = 0; cc65_addr Start = 0; cc65_addr Size = 0; unsigned SegId = CC65_INV_ID; unsigned TypeId = CC65_INV_ID; SpanInfo* S; enum { ibNone = 0x000, ibId = 0x01, ibSegId = 0x02, ibSize = 0x04, ibStart = 0x08, ibType = 0x10, ibRequired = ibId | ibSegId | ibSize | ibStart, } InfoBits = ibNone; /* Skip the SEGMENT token */ NextToken (D); /* More stuff follows */ while (1) { Token Tok; /* Something we know? */ if (D->Tok != TOK_ID && D->Tok != TOK_SEGMENT && D->Tok != TOK_SIZE && D->Tok != TOK_START && D->Tok != TOK_TYPE) { /* Try smart error recovery */ if (D->Tok == TOK_IDENT || TokenIsKeyword (D->Tok)) { UnknownKeyword (D); continue; } /* Done */ break; } /* Remember the token, skip it, check for equal */ Tok = D->Tok; NextToken (D); if (!ConsumeEqual (D)) { goto ErrorExit; } /* Check what the token was */ switch (Tok) { case TOK_ID: if (!IntConstFollows (D)) { goto ErrorExit; } Id = D->IVal; InfoBits |= ibId; NextToken (D); break; case TOK_SEGMENT: if (!IntConstFollows (D)) { goto ErrorExit; } SegId = D->IVal; InfoBits |= ibSegId; NextToken (D); break; case TOK_SIZE: if (!IntConstFollows (D)) { goto ErrorExit; } Size = D->IVal; NextToken (D); InfoBits |= ibSize; break; case TOK_START: if (!IntConstFollows (D)) { goto ErrorExit; } Start = (cc65_addr) D->IVal; NextToken (D); InfoBits |= ibStart; break; case TOK_TYPE: if (!IntConstFollows (D)) { goto ErrorExit; } TypeId = D->IVal; NextToken (D); InfoBits |= ibType; break; default: /* NOTREACHED */ UnexpectedToken (D); goto ErrorExit; } /* Comma or done */ if (D->Tok != TOK_COMMA) { break; } NextToken (D); } /* Check for end of line */ if (D->Tok != TOK_EOL && D->Tok != TOK_EOF) { UnexpectedToken (D); SkipLine (D); goto ErrorExit; } /* Check for required and/or matched information */ if ((InfoBits & ibRequired) != ibRequired) { ParseError (D, CC65_ERROR, "Required attributes missing"); goto ErrorExit; } /* Create the span info and remember it */ S = NewSpanInfo (); S->Id = Id; S->Start = Start; S->End = Start + Size - 1; S->Seg.Id = SegId; S->Type.Id = TypeId; CollReplaceExpand (&D->Info->SpanInfoById, S, Id); ErrorExit: /* Entry point in case of errors */ return; } static void ParseSym (InputData* D) /* Parse a SYM line */ { /* Most of the following variables are initialized with a value that is ** overwritten later. This is just to avoid compiler warnings. */ Collection DefLineIds = COLLECTION_INITIALIZER; unsigned ExportId = CC65_INV_ID; unsigned FileId = CC65_INV_ID; unsigned Id = CC65_INV_ID; StrBuf Name = STRBUF_INITIALIZER; unsigned ParentId = CC65_INV_ID; Collection RefLineIds = COLLECTION_INITIALIZER; unsigned ScopeId = CC65_INV_ID; unsigned SegId = CC65_INV_ID; cc65_size Size = 0; cc65_symbol_type Type = CC65_SYM_EQUATE; long Value = 0; SymInfo* S; enum { ibNone = 0x0000, ibAddrSize = 0x0001, ibDefLineId = 0x0002, ibExportId = 0x0004, ibFileId = 0x0008, ibId = 0x0010, ibParentId = 0x0020, ibRefLineId = 0x0040, ibScopeId = 0x0080, ibSegId = 0x0100, ibSize = 0x0200, ibName = 0x0400, ibType = 0x0800, ibValue = 0x1000, ibRequired = ibAddrSize | ibId | ibName, } InfoBits = ibNone; /* Skip the SYM token */ NextToken (D); /* More stuff follows */ while (1) { Token Tok; /* Something we know? */ if (D->Tok != TOK_ADDRSIZE && D->Tok != TOK_DEF && D->Tok != TOK_EXPORT && D->Tok != TOK_FILE && D->Tok != TOK_ID && D->Tok != TOK_NAME && D->Tok != TOK_PARENT && D->Tok != TOK_REF && D->Tok != TOK_SCOPE && D->Tok != TOK_SEGMENT && D->Tok != TOK_SIZE && D->Tok != TOK_TYPE && D->Tok != TOK_VALUE) { /* Try smart error recovery */ if (D->Tok == TOK_IDENT || TokenIsKeyword (D->Tok)) { UnknownKeyword (D); continue; } /* Done */ break; } /* Remember the token, skip it, check for equal */ Tok = D->Tok; NextToken (D); if (!ConsumeEqual (D)) { goto ErrorExit; } /* Check what the token was */ switch (Tok) { case TOK_ADDRSIZE: NextToken (D); InfoBits |= ibAddrSize; break; case TOK_DEF: while (1) { if (!IntConstFollows (D)) { goto ErrorExit; } CollAppendId (&DefLineIds, (unsigned) D->IVal); NextToken (D); if (D->Tok != TOK_PLUS) { break; } NextToken (D); } InfoBits |= ibDefLineId; break; case TOK_EXPORT: if (!IntConstFollows (D)) { goto ErrorExit; } ExportId = D->IVal; InfoBits |= ibExportId; NextToken (D); break; case TOK_FILE: if (!IntConstFollows (D)) { goto ErrorExit; } FileId = D->IVal; InfoBits |= ibFileId; NextToken (D); break; case TOK_ID: if (!IntConstFollows (D)) { goto ErrorExit; } Id = D->IVal; NextToken (D); InfoBits |= ibId; break; case TOK_NAME: if (!StrConstFollows (D)) { goto ErrorExit; } SB_Copy (&Name, &D->SVal); SB_Terminate (&Name); InfoBits |= ibName; NextToken (D); break; case TOK_PARENT: if (!IntConstFollows (D)) { goto ErrorExit; } ParentId = D->IVal; NextToken (D); InfoBits |= ibParentId; break; case TOK_REF: while (1) { if (!IntConstFollows (D)) { goto ErrorExit; } CollAppendId (&RefLineIds, (unsigned) D->IVal); NextToken (D); if (D->Tok != TOK_PLUS) { break; } NextToken (D); } InfoBits |= ibRefLineId; break; case TOK_SCOPE: if (!IntConstFollows (D)) { goto ErrorExit; } ScopeId = D->IVal; NextToken (D); InfoBits |= ibScopeId; break; case TOK_SEGMENT: if (!IntConstFollows (D)) { goto ErrorExit; } SegId = (unsigned) D->IVal; InfoBits |= ibSegId; NextToken (D); break; case TOK_SIZE: if (!IntConstFollows (D)) { goto ErrorExit; } Size = (cc65_size) D->IVal; InfoBits |= ibSize; NextToken (D); break; case TOK_TYPE: switch (D->Tok) { case TOK_EQUATE: Type = CC65_SYM_EQUATE; break; case TOK_IMPORT: Type = CC65_SYM_IMPORT; break; case TOK_LABEL: Type = CC65_SYM_LABEL; break; default: ParseError (D, CC65_ERROR, "Unknown value for attribute \"type\""); SkipLine (D); goto ErrorExit; } NextToken (D); InfoBits |= ibType; break; case TOK_VALUE: if (!IntConstFollows (D)) { goto ErrorExit; } Value = D->IVal; InfoBits |= ibValue; NextToken (D); break; default: /* NOTREACHED */ UnexpectedToken (D); goto ErrorExit; } /* Comma or done */ if (D->Tok != TOK_COMMA) { break; } NextToken (D); } /* Check for end of line */ if (D->Tok != TOK_EOL && D->Tok != TOK_EOF) { UnexpectedToken (D); SkipLine (D); goto ErrorExit; } /* Check for required and/or matched information */ if ((InfoBits & ibRequired) != ibRequired) { ParseError (D, CC65_ERROR, "Required attributes missing"); goto ErrorExit; } if ((InfoBits & (ibScopeId | ibParentId)) == 0 || (InfoBits & (ibScopeId | ibParentId)) == (ibScopeId | ibParentId)) { ParseError (D, CC65_ERROR, "Only one of \"parent\", \"scope\" must be specified"); goto ErrorExit; } /* Create the symbol info */ S = NewSymInfo (&Name); S->Id = Id; S->Type = Type; S->Value = Value; S->Size = Size; S->Exp.Id = ExportId; S->Seg.Id = SegId; S->Scope.Id = ScopeId; S->Parent.Id = ParentId; CollMove (&DefLineIds, &S->DefLineInfoList); CollMove (&RefLineIds, &S->RefLineInfoList); /* Remember it */ CollReplaceExpand (&D->Info->SymInfoById, S, Id); CollAppend (&D->Info->SymInfoByName, S); CollAppend (&D->Info->SymInfoByVal, S); ErrorExit: /* Entry point in case of errors */ CollDone (&DefLineIds); CollDone (&RefLineIds); SB_Done (&Name); return; } static void ParseType (InputData* D) /* Parse a TYPE line */ { /* Most of the following variables are initialized with a value that is ** overwritten later. This is just to avoid compiler warnings. */ unsigned Id = CC65_INV_ID; StrBuf Value = STRBUF_INITIALIZER; TypeInfo* T; enum { ibNone = 0x0000, ibId = 0x01, ibValue = 0x02, ibRequired = ibId | ibValue, } InfoBits = ibNone; /* Skip the SYM token */ NextToken (D); /* More stuff follows */ while (1) { Token Tok; /* Something we know? */ if (D->Tok != TOK_ID && D->Tok != TOK_VALUE) { /* Try smart error recovery */ if (D->Tok == TOK_IDENT || TokenIsKeyword (D->Tok)) { UnknownKeyword (D); continue; } /* Done */ break; } /* Remember the token, skip it, check for equal */ Tok = D->Tok; NextToken (D); if (!ConsumeEqual (D)) { goto ErrorExit; } /* Check what the token was */ switch (Tok) { case TOK_ID: if (!IntConstFollows (D)) { goto ErrorExit; } Id = D->IVal; NextToken (D); InfoBits |= ibId; break; case TOK_VALUE: if (!StrConstFollows (D)) { goto ErrorExit; } SB_Copy (&Value, &D->SVal); InfoBits |= ibValue; NextToken (D); break; default: /* NOTREACHED */ UnexpectedToken (D); goto ErrorExit; } /* Comma or done */ if (D->Tok != TOK_COMMA) { break; } NextToken (D); } /* Check for end of line */ if (D->Tok != TOK_EOL && D->Tok != TOK_EOF) { UnexpectedToken (D); SkipLine (D); goto ErrorExit; } /* Check for required and/or matched information */ if ((InfoBits & ibRequired) != ibRequired) { ParseError (D, CC65_ERROR, "Required attributes missing"); goto ErrorExit; } /* Parse the type string to create the type info */ T = ParseTypeString (D, &Value); if (T == 0) { goto ErrorExit; } T->Id = Id; /* Remember it */ CollReplaceExpand (&D->Info->TypeInfoById, T, Id); ErrorExit: /* Entry point in case of errors */ SB_Done (&Value); return; } static void ParseVersion (InputData* D) /* Parse a VERSION line */ { enum { ibNone = 0x00, ibMajor = 0x01, ibMinor = 0x02, ibRequired = ibMajor | ibMinor, } InfoBits = ibNone; /* Skip the VERSION token */ NextToken (D); /* More stuff follows */ while (D->Tok != TOK_EOL && D->Tok != TOK_EOF) { switch (D->Tok) { case TOK_MAJOR: NextToken (D); if (!ConsumeEqual (D)) { goto ErrorExit; } if (!IntConstFollows (D)) { goto ErrorExit; } D->Info->MajorVersion = D->IVal; NextToken (D); InfoBits |= ibMajor; break; case TOK_MINOR: NextToken (D); if (!ConsumeEqual (D)) { goto ErrorExit; } if (!IntConstFollows (D)) { goto ErrorExit; } D->Info->MinorVersion = D->IVal; NextToken (D); InfoBits |= ibMinor; break; case TOK_IDENT: /* Try to skip unknown keywords that may have been added by ** a later version. */ UnknownKeyword (D); break; default: UnexpectedToken (D); SkipLine (D); goto ErrorExit; } /* Comma follows before next attribute */ if (D->Tok == TOK_COMMA) { NextToken (D); } else if (D->Tok == TOK_EOL || D->Tok == TOK_EOF) { break; } else { UnexpectedToken (D); goto ErrorExit; } } /* Check for required information */ if ((InfoBits & ibRequired) != ibRequired) { ParseError (D, CC65_ERROR, "Required attributes missing"); goto ErrorExit; } ErrorExit: /* Entry point in case of errors */ return; } /*****************************************************************************/ /* Data processing */ /*****************************************************************************/ static int FindCSymInfoByName (const Collection* CSymInfos, const char* Name, unsigned* Index) /* Find the C symbol info with a given file name. The function returns true if ** the name was found. In this case, Index contains the index of the first item ** that matches. If the item wasn't found, the function returns false and ** Index contains the insert position for Name. */ { /* Do a binary search */ int Lo = 0; int Hi = (int) CollCount (CSymInfos) - 1; int Found = 0; while (Lo <= Hi) { /* Mid of range */ int Cur = (Lo + Hi) / 2; /* Get item */ const CSymInfo* CurItem = CollAt (CSymInfos, Cur); /* Compare */ int Res = strcmp (CurItem->Name, Name); /* Found? */ if (Res < 0) { Lo = Cur + 1; } else { Hi = Cur - 1; /* Since we may have duplicates, repeat the search until we've ** the first item that has a match. */ if (Res == 0) { Found = 1; } } } /* Pass back the index. This is also the insert position */ *Index = Lo; return Found; } static int FindFileInfoByName (const Collection* FileInfos, const char* Name, unsigned* Index) /* Find the FileInfo for a given file name. The function returns true if the ** name was found. In this case, Index contains the index of the first item ** that matches. If the item wasn't found, the function returns false and ** Index contains the insert position for Name. */ { /* Do a binary search */ int Lo = 0; int Hi = (int) CollCount (FileInfos) - 1; int Found = 0; while (Lo <= Hi) { /* Mid of range */ int Cur = (Lo + Hi) / 2; /* Get item */ const FileInfo* CurItem = CollAt (FileInfos, Cur); /* Compare */ int Res = strcmp (CurItem->Name, Name); /* Found? */ if (Res < 0) { Lo = Cur + 1; } else { Hi = Cur - 1; /* Since we may have duplicates, repeat the search until we've ** the first item that has a match. */ if (Res == 0) { Found = 1; } } } /* Pass back the index. This is also the insert position */ *Index = Lo; return Found; } static SpanInfoListEntry* FindSpanInfoByAddr (const SpanInfoList* L, cc65_addr Addr) /* Find the index of a SpanInfo for a given address. Returns 0 if no such ** SpanInfo was found. */ { /* Do a binary search */ int Lo = 0; int Hi = (int) L->Count - 1; while (Lo <= Hi) { /* Mid of range */ int Cur = (Lo + Hi) / 2; /* Get item */ SpanInfoListEntry* CurItem = &L->List[Cur]; /* Found? */ if (CurItem->Addr > Addr) { Hi = Cur - 1; } else if (CurItem->Addr < Addr) { Lo = Cur + 1; } else { /* Found */ return CurItem; } } /* Not found */ return 0; } static LineInfo* FindLineInfoByLine (const Collection* LineInfos, cc65_line Line) /* Find the LineInfo for a given line number. The function returns the line ** info or NULL if none was found. */ { /* Do a binary search */ int Lo = 0; int Hi = (int) CollCount (LineInfos) - 1; while (Lo <= Hi) { /* Mid of range */ int Cur = (Lo + Hi) / 2; /* Get item */ LineInfo* CurItem = CollAt (LineInfos, Cur); /* Found? */ if (Line > CurItem->Line) { Lo = Cur + 1; } else if (Line < CurItem->Line) { Hi = Cur - 1; } else { /* Found */ return CurItem; } } /* Not found */ return 0; } static SegInfo* FindSegInfoByName (const Collection* SegInfos, const char* Name) /* Find the SegInfo for a given segment name. The function returns the segment ** info or NULL if none was found. */ { /* Do a binary search */ int Lo = 0; int Hi = (int) CollCount (SegInfos) - 1; while (Lo <= Hi) { /* Mid of range */ int Cur = (Lo + Hi) / 2; /* Get item */ SegInfo* CurItem = CollAt (SegInfos, Cur); /* Compare */ int Res = strcmp (CurItem->Name, Name); /* Found? */ if (Res < 0) { Lo = Cur + 1; } else if (Res > 0) { Hi = Cur - 1; } else { /* Found */ return CurItem; } } /* Not found */ return 0; } static int FindScopeInfoByName (const Collection* ScopeInfos, const char* Name, unsigned* Index) /* Find the ScopeInfo for a given scope name. The function returns true if the ** name was found. In this case, Index contains the index of the first item ** that matches. If the item wasn't found, the function returns false and ** Index contains the insert position for Name. */ { /* Do a binary search */ int Lo = 0; int Hi = (int) CollCount (ScopeInfos) - 1; int Found = 0; while (Lo <= Hi) { /* Mid of range */ int Cur = (Lo + Hi) / 2; /* Get item */ const ScopeInfo* CurItem = CollAt (ScopeInfos, Cur); /* Compare */ int Res = strcmp (CurItem->Name, Name); /* Found? */ if (Res < 0) { Lo = Cur + 1; } else { Hi = Cur - 1; /* Since we may have duplicates, repeat the search until we've ** the first item that has a match. */ if (Res == 0) { Found = 1; } } } /* Pass back the index. This is also the insert position */ *Index = Lo; return Found; } static int FindSymInfoByName (const Collection* SymInfos, const char* Name, unsigned* Index) /* Find the SymInfo for a given file name. The function returns true if the ** name was found. In this case, Index contains the index of the first item ** that matches. If the item wasn't found, the function returns false and ** Index contains the insert position for Name. */ { /* Do a binary search */ int Lo = 0; int Hi = (int) CollCount (SymInfos) - 1; int Found = 0; while (Lo <= Hi) { /* Mid of range */ int Cur = (Lo + Hi) / 2; /* Get item */ const SymInfo* CurItem = CollAt (SymInfos, Cur); /* Compare */ int Res = strcmp (CurItem->Name, Name); /* Found? */ if (Res < 0) { Lo = Cur + 1; } else { Hi = Cur - 1; /* Since we may have duplicates, repeat the search until we've ** the first item that has a match. */ if (Res == 0) { Found = 1; } } } /* Pass back the index. This is also the insert position */ *Index = Lo; return Found; } static int FindSymInfoByValue (const Collection* SymInfos, long Value, unsigned* Index) /* Find the SymInfo for a given value. The function returns true if the ** value was found. In this case, Index contains the index of the first item ** that matches. If the item wasn't found, the function returns false and ** Index contains the insert position for the given value. */ { /* Do a binary search */ int Lo = 0; int Hi = (int) CollCount (SymInfos) - 1; int Found = 0; while (Lo <= Hi) { /* Mid of range */ int Cur = (Lo + Hi) / 2; /* Get item */ SymInfo* CurItem = CollAt (SymInfos, Cur); /* Found? */ if (Value > CurItem->Value) { Lo = Cur + 1; } else { Hi = Cur - 1; /* Since we may have duplicates, repeat the search until we've ** the first item that has a match. */ if (Value == CurItem->Value) { Found = 1; } } } /* Pass back the index. This is also the insert position */ *Index = Lo; return Found; } static void ProcessCSymInfo (InputData* D) /* Postprocess c symbol infos */ { unsigned I; /* Walk over all c symbols. Resolve the ids and add the c symbols to the ** corresponding asm symbols. */ for (I = 0; I < CollCount (&D->Info->CSymInfoById); ++I) { /* Get this c symbol info */ CSymInfo* S = CollAt (&D->Info->CSymInfoById, I); /* Resolve the asm symbol */ if (S->Sym.Id == CC65_INV_ID) { S->Sym.Info = 0; } else if (S->Sym.Id >= CollCount (&D->Info->SymInfoById)) { ParseError (D, CC65_ERROR, "Invalid symbol id %u for c symbol with id %u", S->Sym.Id, S->Id); S->Sym.Info = 0; } else { S->Sym.Info = CollAt (&D->Info->SymInfoById, S->Sym.Id); /* For normal (=static) symbols, add a backlink to the symbol but ** check that there is not more than one. */ if (S->SC != CC65_CSYM_AUTO && S->SC != CC65_CSYM_REG) { if (S->Sym.Info->CSym) { ParseError (D, CC65_ERROR, "Asm symbol id %u has more than one C symbol attached", S->Sym.Info->Id); S->Sym.Info = 0; } else { S->Sym.Info->CSym = S; } } } /* Resolve the type */ if (S->Type.Id >= CollCount (&D->Info->TypeInfoById)) { ParseError (D, CC65_ERROR, "Invalid type id %u for c symbol with id %u", S->Type.Id, S->Id); S->Type.Info = 0; } else { S->Type.Info = CollAt (&D->Info->TypeInfoById, S->Type.Id); } /* Resolve the scope */ if (S->Scope.Id >= CollCount (&D->Info->ScopeInfoById)) { ParseError (D, CC65_ERROR, "Invalid scope id %u for c symbol with id %u", S->Scope.Id, S->Id); S->Scope.Info = 0; } else { S->Scope.Info = CollAt (&D->Info->ScopeInfoById, S->Scope.Id); /* Add the c symbol to the list of all c symbols for this scope */ if (S->Scope.Info->CSymInfoByName == 0) { S->Scope.Info->CSymInfoByName = CollNew (); } CollAppend (S->Scope.Info->CSymInfoByName, S); /* If the scope has an owner symbol, it's a .PROC scope. If this ** symbol is identical to the one attached to the C symbol, this ** is actuallay a C function and the scope is the matching scope. ** Remember the C symbol in the scope in this case. ** Beware: Scopes haven't been postprocessed, so we don't have a ** pointer but just an id. */ if (S->Sym.Info && S->Scope.Info->Label.Id == S->Sym.Info->Id) { /* This scope is our function scope */ S->Scope.Info->CSymFunc = S; /* Add it to the list of all c functions */ CollAppend (&D->Info->CSymFuncByName, S); } } } /* Walk over all scopes and sort the c symbols by name. */ for (I = 0; I < CollCount (&D->Info->ScopeInfoById); ++I) { /* Get this scope */ ScopeInfo* S = CollAt (&D->Info->ScopeInfoById, I); /* Ignore scopes without C symbols */ if (CollCount (S->CSymInfoByName) > 1) { /* Sort the c symbols for this scope by name */ CollSort (S->CSymInfoByName, CompareCSymInfoByName); } } /* Sort the main list of all C functions by name */ CollSort (&D->Info->CSymFuncByName, CompareCSymInfoByName); } static void ProcessFileInfo (InputData* D) /* Postprocess file infos */ { /* Walk over all file infos and resolve the module ids */ unsigned I; for (I = 0; I < CollCount (&D->Info->FileInfoById); ++I) { /* Get this file info */ FileInfo* F = CollAt (&D->Info->FileInfoById, I); /* Resolve the module ids */ unsigned J; for (J = 0; J < CollCount (&F->ModInfoByName); ++J) { /* Get the id of this module */ unsigned ModId = CollIdAt (&F->ModInfoByName, J); if (ModId >= CollCount (&D->Info->ModInfoById)) { ParseError (D, CC65_ERROR, "Invalid module id %u for file with id %u", ModId, F->Id); CollReplace (&F->ModInfoByName, 0, J); } else { /* Get a pointer to the module */ ModInfo* M = CollAt (&D->Info->ModInfoById, ModId); /* Replace the id by the pointer */ CollReplace (&F->ModInfoByName, M, J); /* Insert a backpointer into the module */ CollAppend (&M->FileInfoByName, F); } } /* If we didn't have any errors, sort the modules by name */ if (D->Errors == 0) { CollSort (&F->ModInfoByName, CompareModInfoByName); } } /* Now walk over all modules and sort the file infos by name */ for (I = 0; I < CollCount (&D->Info->ModInfoById); ++I) { /* Get this module info */ ModInfo* M = CollAt (&D->Info->ModInfoById, I); /* Sort the files by name */ CollSort (&M->FileInfoByName, CompareFileInfoByName); } /* Sort the file infos by name, so we can do a binary search */ CollSort (&D->Info->FileInfoByName, CompareFileInfoByName); } static void ProcessLineInfo (InputData* D) /* Postprocess line infos */ { unsigned I, J; /* Get pointers to the collections */ Collection* LineInfos = &D->Info->LineInfoById; Collection* FileInfos = &D->Info->FileInfoById; /* Walk over the line infos and replace the id numbers of file and segment ** with pointers to the actual structs. Add the line info to each file ** where it is defined. Resolve the spans and add backpointers to the ** spans. */ for (I = 0; I < CollCount (LineInfos); ++I) { /* Get LineInfo struct */ LineInfo* L = CollAt (LineInfos, I); /* Replace the file id by a pointer to the FileInfo. Add a back ** pointer */ if (L->File.Id >= CollCount (FileInfos)) { ParseError (D, CC65_ERROR, "Invalid file id %u for line with id %u", L->File.Id, L->Id); L->File.Info = 0; } else { L->File.Info = CollAt (FileInfos, L->File.Id); CollAppend (&L->File.Info->LineInfoByLine, L); } /* Resolve the spans ids */ for (J = 0; J < CollCount (&L->SpanInfoList); ++J) { /* Get the id of this span */ unsigned SpanId = CollIdAt (&L->SpanInfoList, J); if (SpanId >= CollCount (&D->Info->SpanInfoById)) { ParseError (D, CC65_ERROR, "Invalid span id %u for line with id %u", SpanId, L->Id); CollReplace (&L->SpanInfoList, 0, J); } else { /* Get a pointer to the span */ SpanInfo* SP = CollAt (&D->Info->SpanInfoById, SpanId); /* Replace the id by the pointer */ CollReplace (&L->SpanInfoList, SP, J); /* Insert a backpointer into the span */ if (SP->LineInfoList == 0) { SP->LineInfoList = CollNew (); } CollAppend (SP->LineInfoList, L); } } } /* Walk over all files and sort the line infos for each file so we can ** do a binary search later. */ for (I = 0; I < CollCount (FileInfos); ++I) { /* Get a pointer to this file info */ FileInfo* F = CollAt (FileInfos, I); /* Sort the line infos for this file */ CollSort (&F->LineInfoByLine, CompareLineInfoByLine); } } static void ProcessModInfo (InputData* D) /* Postprocess module infos */ { unsigned I; /* Walk over all scopes and resolve the ids */ for (I = 0; I < CollCount (&D->Info->ModInfoById); ++I) { /* Get this module info */ ModInfo* M = CollAt (&D->Info->ModInfoById, I); /* Resolve the main file */ if (M->File.Id >= CollCount (&D->Info->FileInfoById)) { ParseError (D, CC65_ERROR, "Invalid file id %u for module with id %u", M->File.Id, M->Id); M->File.Info = 0; } else { M->File.Info = CollAt (&D->Info->FileInfoById, M->File.Id); } /* Resolve the library */ if (M->Lib.Id == CC65_INV_ID) { M->Lib.Info = 0; } else if (M->Lib.Id >= CollCount (&D->Info->LibInfoById)) { ParseError (D, CC65_ERROR, "Invalid library id %u for module with id %u", M->Lib.Id, M->Id); M->Lib.Info = 0; } else { M->Lib.Info = CollAt (&D->Info->LibInfoById, M->Lib.Id); } } /* Sort the collection that contains the module info by name */ CollSort (&D->Info->ModInfoByName, CompareModInfoByName); } static void ProcessScopeInfo (InputData* D) /* Postprocess scope infos */ { unsigned I, J; /* Walk over all scopes. Resolve the ids and add the scopes to the list ** of scopes for a module. */ for (I = 0; I < CollCount (&D->Info->ScopeInfoById); ++I) { /* Get this scope info */ ScopeInfo* S = CollAt (&D->Info->ScopeInfoById, I); /* Resolve the module */ if (S->Mod.Id >= CollCount (&D->Info->ModInfoById)) { ParseError (D, CC65_ERROR, "Invalid module id %u for scope with id %u", S->Mod.Id, S->Id); S->Mod.Info = 0; } else { S->Mod.Info = CollAt (&D->Info->ModInfoById, S->Mod.Id); /* Add the scope to the list of scopes for this module */ CollAppend (&S->Mod.Info->ScopeInfoByName, S); /* If this is a main scope, add a pointer to the corresponding ** module. */ if (S->Parent.Id == CC65_INV_ID) { /* No parent means main scope */ S->Mod.Info->MainScope = S; } /* If this is the scope that implements a C function, add the ** function to the list of all functions in this module. */ if (S->CSymFunc) { CollAppend (&S->Mod.Info->CSymFuncByName, S->CSymFunc); } } /* Resolve the parent scope */ if (S->Parent.Id == CC65_INV_ID) { S->Parent.Info = 0; } else if (S->Parent.Id >= CollCount (&D->Info->ScopeInfoById)) { ParseError (D, CC65_ERROR, "Invalid parent scope id %u for scope with id %u", S->Parent.Id, S->Id); S->Parent.Info = 0; } else { S->Parent.Info = CollAt (&D->Info->ScopeInfoById, S->Parent.Id); /* Set a backpointer in the parent */ if (S->Parent.Info->ChildScopeList == 0) { S->Parent.Info->ChildScopeList = CollNew (); } CollAppend (S->Parent.Info->ChildScopeList, S); } /* Resolve the label */ if (S->Label.Id == CC65_INV_ID) { S->Label.Info = 0; } else if (S->Label.Id >= CollCount (&D->Info->SymInfoById)) { ParseError (D, CC65_ERROR, "Invalid label id %u for scope with id %u", S->Label.Id, S->Id); S->Label.Info = 0; } else { S->Label.Info = CollAt (&D->Info->SymInfoById, S->Label.Id); } /* Resolve the spans ids */ for (J = 0; J < CollCount (&S->SpanInfoList); ++J) { /* Get the id of this span */ unsigned SpanId = CollIdAt (&S->SpanInfoList, J); if (SpanId >= CollCount (&D->Info->SpanInfoById)) { ParseError (D, CC65_ERROR, "Invalid span id %u for scope with id %u", SpanId, S->Id); CollReplace (&S->SpanInfoList, 0, J); } else { /* Get a pointer to the span */ SpanInfo* SP = CollAt (&D->Info->SpanInfoById, SpanId); /* Replace the id by the pointer */ CollReplace (&S->SpanInfoList, SP, J); /* Insert a backpointer into the span */ if (SP->ScopeInfoList == 0) { SP->ScopeInfoList = CollNew (); } CollAppend (SP->ScopeInfoList, S); } } } /* Walk over all modules. If a module doesn't have scopes, it wasn't ** compiled with debug info which is ok. If it has debug info, it must ** also have a main scope. If there are scopes, sort them by name. Do ** also sort C functions in this module by name. */ for (I = 0; I < CollCount (&D->Info->ModInfoById); ++I) { /* Get this module */ ModInfo* M = CollAt (&D->Info->ModInfoById, I); /* Ignore modules without any scopes (no debug info) */ if (CollCount (&M->ScopeInfoByName) == 0) { continue; } /* Must have a main scope */ if (M->MainScope == 0) { ParseError (D, CC65_ERROR, "Module with id %u has no main scope", M->Id); } /* Sort the scopes for this module by name */ CollSort (&M->ScopeInfoByName, CompareScopeInfoByName); /* Sort the C functions in this module by name */ CollSort (&M->CSymFuncByName, CompareCSymInfoByName); } /* Sort the scope infos */ CollSort (&D->Info->ScopeInfoByName, CompareScopeInfoByName); } static void ProcessSegInfo (InputData* D) /* Postprocess segment infos */ { /* Sort the segment infos by name */ CollSort (&D->Info->SegInfoByName, CompareSegInfoByName); } static void ProcessSpanInfo (InputData* D) /* Postprocess span infos */ { unsigned I; /* Temporary collection with span infos sorted by address */ Collection SpanInfoByAddr = COLLECTION_INITIALIZER; /* Resize the temporary collection */ CollGrow (&SpanInfoByAddr, CollCount (&D->Info->SpanInfoById)); /* Walk over all spans and resolve the ids */ for (I = 0; I < CollCount (&D->Info->SpanInfoById); ++I) { /* Get this span info */ SpanInfo* S = CollAt (&D->Info->SpanInfoById, I); /* Resolve the segment and relocate the span */ if (S->Seg.Id >= CollCount (&D->Info->SegInfoById)) { ParseError (D, CC65_ERROR, "Invalid segment id %u for span with id %u", S->Seg.Id, S->Id); S->Seg.Info = 0; } else { S->Seg.Info = CollAt (&D->Info->SegInfoById, S->Seg.Id); S->Start += S->Seg.Info->Start; S->End += S->Seg.Info->Start; } /* Resolve the type if we have it */ if (S->Type.Id == CC65_INV_ID) { S->Type.Info = 0; } else if (S->Type.Id >= CollCount (&D->Info->TypeInfoById)) { ParseError (D, CC65_ERROR, "Invalid type id %u for span with id %u", S->Type.Id, S->Id); S->Type.Info = 0; } else { S->Type.Info = CollAt (&D->Info->TypeInfoById, S->Type.Id); } /* Append this span info to the temporary collection that is later ** sorted by address. */ CollAppend (&SpanInfoByAddr, S); } /* Sort the collection with all span infos by address */ CollSort (&SpanInfoByAddr, CompareSpanInfoByAddr); /* Create the span info list from the span info collection */ CreateSpanInfoList (&D->Info->SpanInfoByAddr, &SpanInfoByAddr); /* Remove the temporary collection */ CollDone (&SpanInfoByAddr); } static void ProcessSymInfo (InputData* D) /* Postprocess symbol infos */ { unsigned I, J; /* Walk over the symbols and resolve the references */ for (I = 0; I < CollCount (&D->Info->SymInfoById); ++I) { /* Get the symbol info */ SymInfo* S = CollAt (&D->Info->SymInfoById, I); /* Resolve export */ if (S->Exp.Id == CC65_INV_ID) { S->Exp.Info = 0; } else if (S->Exp.Id >= CollCount (&D->Info->SymInfoById)) { ParseError (D, CC65_ERROR, "Invalid export id %u for symbol with id %u", S->Exp.Id, S->Id); S->Exp.Info = 0; } else { S->Exp.Info = CollAt (&D->Info->SymInfoById, S->Exp.Id); /* Add a backpointer, so the export knows its imports */ if (S->Exp.Info->ImportList == 0) { S->Exp.Info->ImportList = CollNew (); } CollAppend (S->Exp.Info->ImportList, S); } /* Resolve segment */ if (S->Seg.Id == CC65_INV_ID) { S->Seg.Info = 0; } else if (S->Seg.Id >= CollCount (&D->Info->SegInfoById)) { ParseError (D, CC65_ERROR, "Invalid segment id %u for symbol with id %u", S->Seg.Id, S->Id); S->Seg.Info = 0; } else { S->Seg.Info = CollAt (&D->Info->SegInfoById, S->Seg.Id); } /* Resolve the scope */ if (S->Scope.Id == CC65_INV_ID) { S->Scope.Info = 0; } else if (S->Scope.Id >= CollCount (&D->Info->ScopeInfoById)) { ParseError (D, CC65_ERROR, "Invalid scope id %u for symbol with id %u", S->Scope.Id, S->Id); S->Scope.Info = 0; } else { S->Scope.Info = CollAt (&D->Info->ScopeInfoById, S->Scope.Id); /* Place a backpointer to the symbol in the scope */ CollAppend (&S->Scope.Info->SymInfoByName, S); } /* Resolve the parent for cheap locals */ if (S->Parent.Id == CC65_INV_ID) { S->Parent.Info = 0; } else if (S->Parent.Id >= CollCount (&D->Info->SymInfoById)) { ParseError (D, CC65_ERROR, "Invalid parent id %u for symbol with id %u", S->Parent.Id, S->Id); S->Parent.Info = 0; } else { S->Parent.Info = CollAt (&D->Info->SymInfoById, S->Parent.Id); /* Place a backpointer to the cheap local into the parent */ if (S->Parent.Info->CheapLocals == 0) { S->Parent.Info->CheapLocals = CollNew (); } CollAppend (S->Parent.Info->CheapLocals, S); } /* Resolve the line infos for the symbol definition */ for (J = 0; J < CollCount (&S->DefLineInfoList); ++J) { /* Get the id of this line info */ unsigned LineId = CollIdAt (&S->DefLineInfoList, J); if (LineId >= CollCount (&D->Info->LineInfoById)) { ParseError (D, CC65_ERROR, "Invalid line id %u for symbol with id %u", LineId, S->Id); CollReplace (&S->DefLineInfoList, 0, J); } else { /* Get a pointer to the line info */ LineInfo* LI = CollAt (&D->Info->LineInfoById, LineId); /* Replace the id by the pointer */ CollReplace (&S->DefLineInfoList, LI, J); } } /* Resolve the line infos for symbol references */ for (J = 0; J < CollCount (&S->RefLineInfoList); ++J) { /* Get the id of this line info */ unsigned LineId = CollIdAt (&S->RefLineInfoList, J); if (LineId >= CollCount (&D->Info->LineInfoById)) { ParseError (D, CC65_ERROR, "Invalid line id %u for symbol with id %u", LineId, S->Id); CollReplace (&S->RefLineInfoList, 0, J); } else { /* Get a pointer to the line info */ LineInfo* LI = CollAt (&D->Info->LineInfoById, LineId); /* Replace the id by the pointer */ CollReplace (&S->RefLineInfoList, LI, J); } } } /* Second run. Resolve scopes for cheap locals */ for (I = 0; I < CollCount (&D->Info->SymInfoById); ++I) { /* Get the symbol info */ SymInfo* S = CollAt (&D->Info->SymInfoById, I); /* Resolve the scope */ if (S->Scope.Info == 0) { /* No scope - must have a parent */ if (S->Parent.Info == 0) { ParseError (D, CC65_ERROR, "Symbol with id %u has no parent and no scope", S->Id); } else if (S->Parent.Info->Scope.Info == 0) { ParseError (D, CC65_ERROR, "Symbol with id %u has parent %u without a scope", S->Id, S->Parent.Info->Id); } else { S->Scope.Info = S->Parent.Info->Scope.Info; } } } /* Walk over the scopes and sort the symbols in the scope by name */ for (I = 0; I < CollCount (&D->Info->ScopeInfoById); ++I) { /* Get the scope info */ ScopeInfo* S = CollAt (&D->Info->ScopeInfoById, I); /* Sort the symbols in this scope by name */ CollSort (&S->SymInfoByName, CompareSymInfoByName); } /* Sort the symbol infos */ CollSort (&D->Info->SymInfoByName, CompareSymInfoByName); CollSort (&D->Info->SymInfoByVal, CompareSymInfoByVal); } /*****************************************************************************/ /* Debug info files */ /*****************************************************************************/ cc65_dbginfo cc65_read_dbginfo (const char* FileName, cc65_errorfunc ErrFunc) /* Parse the debug info file with the given name. On success, the function ** will return a pointer to an opaque cc65_dbginfo structure, that must be ** passed to the other functions in this module to retrieve information. ** errorfunc is called in case of warnings and errors. If the file cannot be ** read successfully, NULL is returned. */ { /* Data structure used to control scanning and parsing */ InputData D = { 0, /* Name of input file */ 1, /* Line number */ 0, /* Input file */ 0, /* Line at start of current token */ 0, /* Column at start of current token */ 0, /* Number of errors */ 0, /* Input file */ ' ', /* Input character */ TOK_INVALID, /* Input token */ 0, /* Integer constant */ STRBUF_INITIALIZER, /* String constant */ 0, /* Function called in case of errors */ 0, /* Pointer to debug info */ }; D.FileName = FileName; D.Error = ErrFunc; /* Open the input file */ D.F = fopen (FileName, "rt"); if (D.F == 0) { /* Cannot open */ ParseError (&D, CC65_ERROR, "Cannot open input file \"%s\": %s", FileName, strerror (errno)); return 0; } /* Create a new debug info struct */ D.Info = NewDbgInfo (FileName); /* Prime the pump */ NextToken (&D); /* The first line in the file must specify version information */ if (D.Tok != TOK_VERSION) { ParseError (&D, CC65_ERROR, "\"version\" keyword missing in first line - this is not " "a valid debug info file"); goto CloseAndExit; } /* Parse the version directive */ ParseVersion (&D); /* Do several checks on the version number */ if (D.Info->MajorVersion < VER_MAJOR) { ParseError ( &D, CC65_ERROR, "This is an old version of the debug info format that is no " "longer supported. Version found = %u.%u, version supported " "= %u.%u", D.Info->MajorVersion, D.Info->MinorVersion, VER_MAJOR, VER_MINOR ); goto CloseAndExit; } else if (D.Info->MajorVersion == VER_MAJOR && D.Info->MinorVersion > VER_MINOR) { ParseError ( &D, CC65_ERROR, "This is a slightly newer version of the debug info format. " "It might work, but you may get errors about unknown keywords " "and similar. Version found = %u.%u, version supported = %u.%u", D.Info->MajorVersion, D.Info->MinorVersion, VER_MAJOR, VER_MINOR ); } else if (D.Info->MajorVersion > VER_MAJOR) { ParseError ( &D, CC65_WARNING, "The format of this debug info file is newer than what we " "know. Will proceed but probably fail. Version found = %u.%u, " "version supported = %u.%u", D.Info->MajorVersion, D.Info->MinorVersion, VER_MAJOR, VER_MINOR ); } ConsumeEOL (&D); /* Parse lines */ while (D.Tok != TOK_EOF) { switch (D.Tok) { case TOK_CSYM: ParseCSym (&D); break; case TOK_FILE: ParseFile (&D); break; case TOK_INFO: ParseInfo (&D); break; case TOK_LIBRARY: ParseLibrary (&D); break; case TOK_LINE: ParseLine (&D); break; case TOK_MODULE: ParseModule (&D); break; case TOK_SCOPE: ParseScope (&D); break; case TOK_SEGMENT: ParseSegment (&D); break; case TOK_SPAN: ParseSpan (&D); break; case TOK_SYM: ParseSym (&D); break; case TOK_TYPE: ParseType (&D); break; case TOK_IDENT: /* Output a warning, then skip the line with the unknown ** keyword that may have been added by a later version. */ ParseError (&D, CC65_WARNING, "Unknown keyword \"%s\" - skipping", SB_GetConstBuf (&D.SVal)); SkipLine (&D); break; default: UnexpectedToken (&D); } /* EOL or EOF must follow */ ConsumeEOL (&D); } CloseAndExit: /* Close the file */ fclose (D.F); /* Free memory allocated for SVal */ SB_Done (&D.SVal); /* In case of errors, delete the debug info already allocated and ** return NULL */ if (D.Errors > 0) { /* Free allocated stuff */ FreeDbgInfo (D.Info); return 0; } /* We do now have all the information from the input file. Do ** postprocessing. Beware: Some of the following postprocessing ** depends on the order of the calls. */ ProcessCSymInfo (&D); ProcessFileInfo (&D); ProcessLineInfo (&D); ProcessModInfo (&D); ProcessScopeInfo (&D); ProcessSegInfo (&D); ProcessSpanInfo (&D); ProcessSymInfo (&D); #if DEBUG /* Debug output */ DumpData (&D); #endif /* Return the debug info struct that was created */ return D.Info; } void cc65_free_dbginfo (cc65_dbginfo Handle) /* Free debug information read from a file */ { if (Handle) { FreeDbgInfo ((DbgInfo*) Handle); } } /*****************************************************************************/ /* C symbols */ /*****************************************************************************/ const cc65_csyminfo* cc65_get_csymlist (cc65_dbginfo Handle) /* Return a list of all c symbols */ { const DbgInfo* Info; cc65_csyminfo* S; unsigned I; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Allocate memory for the data structure returned to the caller */ S = new_cc65_csyminfo (CollCount (&Info->CSymInfoById)); /* Fill in the data */ for (I = 0; I < CollCount (&Info->CSymInfoById); ++I) { /* Copy the data */ CopyCSymInfo (S->data + I, CollAt (&Info->CSymInfoById, I)); } /* Return the result */ return S; } const cc65_csyminfo* cc65_csym_byid (cc65_dbginfo Handle, unsigned Id) /* Return information about a c symbol with a specific id. The function ** returns NULL if the id is invalid (no such c symbol) and otherwise a ** cc65_csyminfo structure with one entry that contains the requested ** symbol information. */ { const DbgInfo* Info; cc65_csyminfo* S; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Check if the id is valid */ if (Id >= CollCount (&Info->CSymInfoById)) { return 0; } /* Allocate memory for the data structure returned to the caller */ S = new_cc65_csyminfo (1); /* Fill in the data */ CopyCSymInfo (S->data, CollAt (&Info->CSymInfoById, Id)); /* Return the result */ return S; } const cc65_csyminfo* cc65_cfunc_bymodule (cc65_dbginfo Handle, unsigned ModId) /* Return the list of C functions (not symbols!) for a specific module. If ** the module id is invalid, the function will return NULL, otherwise a ** (possibly empty) c symbol list. */ { const DbgInfo* Info; const ModInfo* M; cc65_csyminfo* D; unsigned I; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Check if the module id is valid */ if (ModId >= CollCount (&Info->ModInfoById)) { return 0; } /* Get a pointer to the module info */ M = CollAt (&Info->ModInfoById, ModId); /* Allocate memory for the data structure returned to the caller */ D = new_cc65_csyminfo (CollCount (&M->CSymFuncByName)); /* Fill in the data */ for (I = 0; I < CollCount (&M->CSymFuncByName); ++I) { CopyCSymInfo (D->data + I, CollAt (&M->CSymFuncByName, I)); } /* Return the result */ return D; } const cc65_csyminfo* cc65_cfunc_byname (cc65_dbginfo Handle, const char* Name) /* Return a list of all C functions with the given name that have a ** definition. */ { const DbgInfo* Info; unsigned Index; unsigned Count; const CSymInfo* S; cc65_csyminfo* D; unsigned I; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Search for a function with the given name */ if (!FindCSymInfoByName (&Info->CSymFuncByName, Name, &Index)) { return 0; } /* Count functions with this name */ Count = 1; I = Index; while (1) { if (++I >= CollCount (&Info->CSymFuncByName)) { break; } S = CollAt (&Info->CSymFuncByName, I); if (strcmp (S->Name, Name) != 0) { /* Next symbol has another name */ break; } ++Count; } /* Allocate memory for the data structure returned to the caller */ D = new_cc65_csyminfo (Count); /* Fill in the data */ for (I = 0; I < Count; ++I, ++Index) { CopyCSymInfo (D->data + I, CollAt (&Info->CSymFuncByName, Index)); } /* Return the result */ return D; } const cc65_csyminfo* cc65_csym_byscope (cc65_dbginfo Handle, unsigned ScopeId) /* Return all C symbols for a scope. The function will return NULL if the ** given id is invalid. */ { const DbgInfo* Info; const ScopeInfo* S; cc65_csyminfo* D; unsigned I; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Check if the scope id is valid */ if (ScopeId >= CollCount (&Info->ScopeInfoById)) { return 0; } /* Get a pointer to the scope */ S = CollAt (&Info->ScopeInfoById, ScopeId); /* Allocate memory for the data structure returned to the caller */ D = new_cc65_csyminfo (CollCount (S->CSymInfoByName)); /* Fill in the data */ for (I = 0; I < CollCount (S->CSymInfoByName); ++I) { CopyCSymInfo (D->data + I, CollAt (S->CSymInfoByName, I)); } /* Return the result */ return D; } void cc65_free_csyminfo (cc65_dbginfo Handle, const cc65_csyminfo* Info) /* Free a c symbol info record */ { /* Just for completeness, check the handle */ assert (Handle != 0); /* Just free the memory */ xfree ((cc65_csyminfo*) Info); } /*****************************************************************************/ /* Libraries */ /*****************************************************************************/ const cc65_libraryinfo* cc65_get_librarylist (cc65_dbginfo Handle) /* Return a list of all libraries */ { const DbgInfo* Info; cc65_libraryinfo* D; unsigned I; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Allocate memory for the data structure returned to the caller */ D = new_cc65_libraryinfo (CollCount (&Info->LibInfoById)); /* Fill in the data */ for (I = 0; I < CollCount (&Info->LibInfoById); ++I) { /* Copy the data */ CopyLibInfo (D->data + I, CollAt (&Info->LibInfoById, I)); } /* Return the result */ return D; } const cc65_libraryinfo* cc65_library_byid (cc65_dbginfo Handle, unsigned Id) /* Return information about a library with a specific id. The function ** returns NULL if the id is invalid (no such library) and otherwise a ** cc65_libraryinfo structure with one entry that contains the requested ** library information. */ { const DbgInfo* Info; cc65_libraryinfo* D; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Check if the id is valid */ if (Id >= CollCount (&Info->LibInfoById)) { return 0; } /* Allocate memory for the data structure returned to the caller */ D = new_cc65_libraryinfo (1); /* Fill in the data */ CopyLibInfo (D->data, CollAt (&Info->LibInfoById, Id)); /* Return the result */ return D; } void cc65_free_libraryinfo (cc65_dbginfo Handle, const cc65_libraryinfo* Info) /* Free a library info record */ { /* Just for completeness, check the handle */ assert (Handle != 0); /* Just free the memory */ xfree ((cc65_libraryinfo*) Info); } /*****************************************************************************/ /* Line info */ /*****************************************************************************/ const cc65_lineinfo* cc65_line_byid (cc65_dbginfo Handle, unsigned Id) /* Return information about a line with a specific id. The function ** returns NULL if the id is invalid (no such line) and otherwise a ** cc65_lineinfo structure with one entry that contains the requested ** module information. */ { const DbgInfo* Info; cc65_lineinfo* D; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Check if the id is valid */ if (Id >= CollCount (&Info->LineInfoById)) { return 0; } /* Allocate memory for the data structure returned to the caller */ D = new_cc65_lineinfo (1); /* Fill in the data */ CopyLineInfo (D->data, CollAt (&Info->LineInfoById, Id)); /* Return the result */ return D; } const cc65_lineinfo* cc65_line_bynumber (cc65_dbginfo Handle, unsigned FileId, cc65_line Line) /* Return line information for a source file/line number combination. The ** function returns NULL if no line information was found. */ { const DbgInfo* Info; const FileInfo* F; cc65_lineinfo* D; LineInfo* L = 0; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Check if the source file id is valid */ if (FileId >= CollCount (&Info->FileInfoById)) { return 0; } /* Get the file */ F = CollAt (&Info->FileInfoById, FileId); /* Search in the file for the given line */ L = FindLineInfoByLine (&F->LineInfoByLine, Line); /* Bail out if we didn't find the line */ if (L == 0) { return 0; } /* Prepare the struct we will return to the caller */ D = new_cc65_lineinfo (1); /* Copy the data */ CopyLineInfo (D->data, L); /* Return the allocated struct */ return D; } const cc65_lineinfo* cc65_line_bysource (cc65_dbginfo Handle, unsigned FileId) /* Return line information for a source file. The function returns NULL if the ** file id is invalid. */ { const DbgInfo* Info; const FileInfo* F; cc65_lineinfo* D; unsigned I; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Check if the source file id is valid */ if (FileId >= CollCount (&Info->FileInfoById)) { return 0; } /* Get the file */ F = CollAt (&Info->FileInfoById, FileId); /* Prepare the struct we will return to the caller */ D = new_cc65_lineinfo (CollCount (&F->LineInfoByLine)); /* Fill in the data */ for (I = 0; I < CollCount (&F->LineInfoByLine); ++I) { /* Copy the data */ CopyLineInfo (D->data + I, CollAt (&F->LineInfoByLine, I)); } /* Return the allocated struct */ return D; } const cc65_lineinfo* cc65_line_bysymdef (cc65_dbginfo Handle, unsigned SymId) /* Return line information for the definition of a symbol. The function ** returns NULL if the symbol id is invalid, otherwise a list of line infos. */ { const DbgInfo* Info; const SymInfo* S; cc65_lineinfo* D; unsigned I; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Check if the symbol id is valid */ if (SymId >= CollCount (&Info->SymInfoById)) { return 0; } /* Get the symbol */ S = CollAt (&Info->SymInfoById, SymId); /* Prepare the struct we will return to the caller */ D = new_cc65_lineinfo (CollCount (&S->DefLineInfoList)); /* Fill in the data */ for (I = 0; I < CollCount (&S->DefLineInfoList); ++I) { /* Copy the data */ CopyLineInfo (D->data + I, CollAt (&S->DefLineInfoList, I)); } /* Return the allocated struct */ return D; } const cc65_lineinfo* cc65_line_bysymref (cc65_dbginfo Handle, unsigned SymId) /* Return line information for all references of a symbol. The function ** returns NULL if the symbol id is invalid, otherwise a list of line infos. */ { const DbgInfo* Info; const SymInfo* S; cc65_lineinfo* D; unsigned I; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Check if the symbol id is valid */ if (SymId >= CollCount (&Info->SymInfoById)) { return 0; } /* Get the symbol */ S = CollAt (&Info->SymInfoById, SymId); /* Prepare the struct we will return to the caller */ D = new_cc65_lineinfo (CollCount (&S->RefLineInfoList)); /* Fill in the data */ for (I = 0; I < CollCount (&S->RefLineInfoList); ++I) { /* Copy the data */ CopyLineInfo (D->data + I, CollAt (&S->RefLineInfoList, I)); } /* Return the allocated struct */ return D; } const cc65_lineinfo* cc65_line_byspan (cc65_dbginfo Handle, unsigned SpanId) /* Return line information for a a span. The function returns NULL if the ** span id is invalid, otherwise a list of line infos. */ { const DbgInfo* Info; const SpanInfo* S; cc65_lineinfo* D; unsigned I; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Check if the span id is valid */ if (SpanId >= CollCount (&Info->SpanInfoById)) { return 0; } /* Get the span */ S = CollAt (&Info->SpanInfoById, SpanId); /* Prepare the struct we will return to the caller */ D = new_cc65_lineinfo (CollCount (S->LineInfoList)); /* Fill in the data. Since S->LineInfoList may be NULL, we will use the ** count field of the returned data struct instead. */ for (I = 0; I < D->count; ++I) { /* Copy the data */ CopyLineInfo (D->data + I, CollAt (S->LineInfoList, I)); } /* Return the allocated struct */ return D; } void cc65_free_lineinfo (cc65_dbginfo Handle, const cc65_lineinfo* Info) /* Free line info returned by one of the other functions */ { /* Just for completeness, check the handle */ assert (Handle != 0); /* Just free the memory */ xfree ((cc65_lineinfo*) Info); } /*****************************************************************************/ /* Modules */ /*****************************************************************************/ const cc65_moduleinfo* cc65_get_modulelist (cc65_dbginfo Handle) /* Return a list of all modules */ { const DbgInfo* Info; cc65_moduleinfo* D; unsigned I; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Allocate memory for the data structure returned to the caller */ D = new_cc65_moduleinfo (CollCount (&Info->ModInfoById)); /* Fill in the data */ for (I = 0; I < CollCount (&Info->ModInfoById); ++I) { /* Copy the data */ CopyModInfo (D->data + I, CollAt (&Info->ModInfoById, I)); } /* Return the result */ return D; } const cc65_moduleinfo* cc65_module_byid (cc65_dbginfo Handle, unsigned Id) /* Return information about a module with a specific id. The function ** returns NULL if the id is invalid (no such module) and otherwise a ** cc65_moduleinfo structure with one entry that contains the requested ** module information. */ { const DbgInfo* Info; cc65_moduleinfo* D; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Check if the id is valid */ if (Id >= CollCount (&Info->ModInfoById)) { return 0; } /* Allocate memory for the data structure returned to the caller */ D = new_cc65_moduleinfo (1); /* Fill in the data */ CopyModInfo (D->data, CollAt (&Info->ModInfoById, Id)); /* Return the result */ return D; } void cc65_free_moduleinfo (cc65_dbginfo Handle, const cc65_moduleinfo* Info) /* Free a module info record */ { /* Just for completeness, check the handle */ assert (Handle != 0); /* Just free the memory */ xfree ((cc65_moduleinfo*) Info); } /*****************************************************************************/ /* Spans */ /*****************************************************************************/ const cc65_spaninfo* cc65_get_spanlist (cc65_dbginfo Handle) /* Return a list of all spans */ { const DbgInfo* Info; cc65_spaninfo* D; unsigned I; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Allocate memory for the data structure returned to the caller */ D = new_cc65_spaninfo (CollCount (&Info->SpanInfoById)); /* Fill in the data */ for (I = 0; I < CollCount (&Info->SpanInfoById); ++I) { /* Copy the data */ CopySpanInfo (D->data + I, CollAt (&Info->SpanInfoById, I)); } /* Return the result */ return D; } const cc65_spaninfo* cc65_span_byid (cc65_dbginfo Handle, unsigned Id) /* Return information about a span with a specific id. The function ** returns NULL if the id is invalid (no such span) and otherwise a ** cc65_spaninfo structure with one entry that contains the requested ** span information. */ { const DbgInfo* Info; cc65_spaninfo* D; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Check if the id is valid */ if (Id >= CollCount (&Info->SpanInfoById)) { return 0; } /* Allocate memory for the data structure returned to the caller */ D = new_cc65_spaninfo (1); /* Fill in the data */ CopySpanInfo (D->data, CollAt (&Info->SpanInfoById, Id)); /* Return the result */ return D; } const cc65_spaninfo* cc65_span_byaddr (cc65_dbginfo Handle, unsigned long Addr) /* Return span information for the given address. The function returns NULL ** if no spans were found for this address. */ { const DbgInfo* Info; SpanInfoListEntry* E; cc65_spaninfo* D = 0; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Search for spans that cover this address */ E = FindSpanInfoByAddr (&Info->SpanInfoByAddr, Addr); /* Do we have spans? */ if (E != 0) { unsigned I; /* Prepare the struct we will return to the caller */ D = new_cc65_spaninfo (E->Count); if (E->Count == 1) { CopySpanInfo (D->data, E->Data); } else { for (I = 0; I < D->count; ++I) { /* Copy data */ CopySpanInfo (D->data + I, ((SpanInfo**) E->Data)[I]); } } } /* Return the struct we've created */ return D; } const cc65_spaninfo* cc65_span_byline (cc65_dbginfo Handle, unsigned LineId) /* Return span information for the given source line. The function returns NULL ** if the line id is invalid, otherwise the spans for this line (possibly zero). */ { const DbgInfo* Info; const LineInfo* L; cc65_spaninfo* D; unsigned I; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Check if the line id is valid */ if (LineId >= CollCount (&Info->LineInfoById)) { return 0; } /* Get the line with this id */ L = CollAt (&Info->LineInfoById, LineId); /* Allocate memory for the data structure returned to the caller */ D = new_cc65_spaninfo (CollCount (&L->SpanInfoList)); /* Fill in the data */ for (I = 0; I < CollCount (&L->SpanInfoList); ++I) { /* Copy the data */ CopySpanInfo (D->data + I, CollAt (&L->SpanInfoList, I)); } /* Return the result */ return D; } const cc65_spaninfo* cc65_span_byscope (cc65_dbginfo Handle, unsigned ScopeId) /* Return span information for the given scope. The function returns NULL if ** the scope id is invalid, otherwise the spans for this scope (possibly zero). */ { const DbgInfo* Info; const ScopeInfo* S; cc65_spaninfo* D; unsigned I; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Check if the scope id is valid */ if (ScopeId >= CollCount (&Info->ScopeInfoById)) { return 0; } /* Get the scope with this id */ S = CollAt (&Info->ScopeInfoById, ScopeId); /* Allocate memory for the data structure returned to the caller */ D = new_cc65_spaninfo (CollCount (&S->SpanInfoList)); /* Fill in the data */ for (I = 0; I < CollCount (&S->SpanInfoList); ++I) { /* Copy the data */ CopySpanInfo (D->data + I, CollAt (&S->SpanInfoList, I)); } /* Return the result */ return D; } void cc65_free_spaninfo (cc65_dbginfo Handle, const cc65_spaninfo* Info) /* Free a span info record */ { /* Just for completeness, check the handle */ assert (Handle != 0); /* Just free the memory */ xfree ((cc65_spaninfo*) Info); } /*****************************************************************************/ /* Source files */ /*****************************************************************************/ const cc65_sourceinfo* cc65_get_sourcelist (cc65_dbginfo Handle) /* Return a list of all source files */ { const DbgInfo* Info; cc65_sourceinfo* D; unsigned I; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Allocate memory for the data structure returned to the caller. */ D = new_cc65_sourceinfo (CollCount (&Info->FileInfoById)); /* Fill in the data */ for (I = 0; I < CollCount (&Info->FileInfoById); ++I) { /* Copy the data */ CopyFileInfo (D->data + I, CollAt (&Info->FileInfoById, I)); } /* Return the result */ return D; } const cc65_sourceinfo* cc65_source_byid (cc65_dbginfo Handle, unsigned Id) /* Return information about a source file with a specific id. The function ** returns NULL if the id is invalid (no such source file) and otherwise a ** cc65_sourceinfo structure with one entry that contains the requested ** source file information. */ { const DbgInfo* Info; cc65_sourceinfo* D; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Check if the id is valid */ if (Id >= CollCount (&Info->FileInfoById)) { return 0; } /* Allocate memory for the data structure returned to the caller */ D = new_cc65_sourceinfo (1); /* Fill in the data */ CopyFileInfo (D->data, CollAt (&Info->FileInfoById, Id)); /* Return the result */ return D; } const cc65_sourceinfo* cc65_source_bymodule (cc65_dbginfo Handle, unsigned Id) /* Return information about the source files used to build a module. The ** function returns NULL if the module id is invalid (no such module) and ** otherwise a cc65_sourceinfo structure with one entry per source file. */ { const DbgInfo* Info; const ModInfo* M; cc65_sourceinfo* D; unsigned I; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Check if the module id is valid */ if (Id >= CollCount (&Info->ModInfoById)) { return 0; } /* Get a pointer to the module info */ M = CollAt (&Info->ModInfoById, Id); /* Allocate memory for the data structure returned to the caller */ D = new_cc65_sourceinfo (CollCount (&M->FileInfoByName)); /* Fill in the data */ for (I = 0; I < CollCount (&M->FileInfoByName); ++I) { CopyFileInfo (D->data + I, CollAt (&M->FileInfoByName, I)); } /* Return the result */ return D; } void cc65_free_sourceinfo (cc65_dbginfo Handle, const cc65_sourceinfo* Info) /* Free a source info record */ { /* Just for completeness, check the handle */ assert (Handle != 0); /* Free the memory */ xfree ((cc65_sourceinfo*) Info); } /*****************************************************************************/ /* Scopes */ /*****************************************************************************/ const cc65_scopeinfo* cc65_get_scopelist (cc65_dbginfo Handle) /* Return a list of all scopes in the debug information */ { const DbgInfo* Info; cc65_scopeinfo* D; unsigned I; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Allocate memory for the data structure returned to the caller */ D = new_cc65_scopeinfo (CollCount (&Info->ScopeInfoById)); /* Fill in the data */ for (I = 0; I < CollCount (&Info->ScopeInfoById); ++I) { /* Copy the data */ CopyScopeInfo (D->data + I, CollAt (&Info->ScopeInfoById, I)); } /* Return the result */ return D; } const cc65_scopeinfo* cc65_scope_byid (cc65_dbginfo Handle, unsigned Id) /* Return the scope with a given id. The function returns NULL if no scope ** with this id was found. */ { const DbgInfo* Info; cc65_scopeinfo* D; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Check if the id is valid */ if (Id >= CollCount (&Info->ScopeInfoById)) { return 0; } /* Allocate memory for the data structure returned to the caller */ D = new_cc65_scopeinfo (1); /* Fill in the data */ CopyScopeInfo (D->data, CollAt (&Info->ScopeInfoById, Id)); /* Return the result */ return D; } const cc65_scopeinfo* cc65_scope_bymodule (cc65_dbginfo Handle, unsigned ModId) /* Return the list of scopes for one module. The function returns NULL if no ** scope with the given id was found. */ { const DbgInfo* Info; const ModInfo* M; cc65_scopeinfo* D; unsigned I; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Check if the module id is valid */ if (ModId >= CollCount (&Info->ModInfoById)) { return 0; } /* Get a pointer to the module info */ M = CollAt (&Info->ModInfoById, ModId); /* Allocate memory for the data structure returned to the caller */ D = new_cc65_scopeinfo (CollCount (&M->ScopeInfoByName)); /* Fill in the data */ for (I = 0; I < CollCount (&M->ScopeInfoByName); ++I) { CopyScopeInfo (D->data + I, CollAt (&M->ScopeInfoByName, I)); } /* Return the result */ return D; } const cc65_scopeinfo* cc65_scope_byname (cc65_dbginfo Handle, const char* Name) /* Return the list of scopes with a given name. Returns NULL if no scope with ** the given name was found, otherwise a non empty scope list. */ { const DbgInfo* Info; unsigned Index; const ScopeInfo* S; cc65_scopeinfo* D; unsigned Count; unsigned I; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Search for the first item with the given name */ if (!FindScopeInfoByName (&Info->ScopeInfoByName, Name, &Index)) { /* Not found */ return 0; } /* Count scopes with this name */ Count = 1; I = Index; while (1) { if (++I >= CollCount (&Info->ScopeInfoByName)) { break; } S = CollAt (&Info->ScopeInfoByName, I); if (strcmp (S->Name, Name) != 0) { /* Next symbol has another name */ break; } ++Count; } /* Allocate memory for the data structure returned to the caller */ D = new_cc65_scopeinfo (Count); /* Fill in the data */ for (I = 0; I < Count; ++I, ++Index) { CopyScopeInfo (D->data + I, CollAt (&Info->ScopeInfoByName, Index)); } /* Return the result */ return D; } const cc65_scopeinfo* cc65_scope_byspan (cc65_dbginfo Handle, unsigned SpanId) /* Return scope information for a a span. The function returns NULL if the ** span id is invalid, otherwise a list of line scopes. */ { const DbgInfo* Info; const SpanInfo* S; cc65_scopeinfo* D; unsigned I; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Check if the span id is valid */ if (SpanId >= CollCount (&Info->SpanInfoById)) { return 0; } /* Get the span */ S = CollAt (&Info->SpanInfoById, SpanId); /* Prepare the struct we will return to the caller */ D = new_cc65_scopeinfo (CollCount (S->ScopeInfoList)); /* Fill in the data. Since D->ScopeInfoList may be NULL, we will use the ** count field of the returned data struct instead. */ for (I = 0; I < D->count; ++I) { /* Copy the data */ CopyScopeInfo (D->data + I, CollAt (S->ScopeInfoList, I)); } /* Return the allocated struct */ return D; } const cc65_scopeinfo* cc65_childscopes_byid (cc65_dbginfo Handle, unsigned Id) /* Return the direct child scopes of a scope with a given id. The function ** returns NULL if no scope with this id was found, otherwise a list of the ** direct childs. */ { const DbgInfo* Info; cc65_scopeinfo* D; const ScopeInfo* S; unsigned I; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Check if the id is valid */ if (Id >= CollCount (&Info->ScopeInfoById)) { return 0; } /* Get the scope */ S = CollAt (&Info->ScopeInfoById, Id); /* Allocate memory for the data structure returned to the caller */ D = new_cc65_scopeinfo (CollCount (S->ChildScopeList)); /* Fill in the data */ for (I = 0; I < D->count; ++I) { CopyScopeInfo (D->data + I, CollAt (S->ChildScopeList, I)); } /* Return the result */ return D; } void cc65_free_scopeinfo (cc65_dbginfo Handle, const cc65_scopeinfo* Info) /* Free a scope info record */ { /* Just for completeness, check the handle */ assert (Handle != 0); /* Free the memory */ xfree ((cc65_scopeinfo*) Info); } /*****************************************************************************/ /* Segments */ /*****************************************************************************/ const cc65_segmentinfo* cc65_get_segmentlist (cc65_dbginfo Handle) /* Return a list of all segments referenced in the debug information */ { const DbgInfo* Info; cc65_segmentinfo* D; unsigned I; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Allocate memory for the data structure returned to the caller */ D = new_cc65_segmentinfo (CollCount (&Info->SegInfoById)); /* Fill in the data */ for (I = 0; I < CollCount (&Info->SegInfoById); ++I) { /* Copy the data */ CopySegInfo (D->data + I, CollAt (&Info->SegInfoById, I)); } /* Return the result */ return D; } const cc65_segmentinfo* cc65_segment_byid (cc65_dbginfo Handle, unsigned Id) /* Return information about a segment with a specific id. The function returns ** NULL if the id is invalid (no such segment) and otherwise a segmentinfo ** structure with one entry that contains the requested segment information. */ { const DbgInfo* Info; cc65_segmentinfo* D; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Check if the id is valid */ if (Id >= CollCount (&Info->SegInfoById)) { return 0; } /* Allocate memory for the data structure returned to the caller */ D = new_cc65_segmentinfo (1); /* Fill in the data */ CopySegInfo (D->data, CollAt (&Info->SegInfoById, Id)); /* Return the result */ return D; } const cc65_segmentinfo* cc65_segment_byname (cc65_dbginfo Handle, const char* Name) /* Return information about a segment with a specific name. The function ** returns NULL if no segment with this name exists and otherwise a ** cc65_segmentinfo structure with one entry that contains the requested ** information. */ { const DbgInfo* Info; const SegInfo* S; cc65_segmentinfo* D; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Search for the segment */ S = FindSegInfoByName (&Info->SegInfoByName, Name); if (S == 0) { return 0; } /* Allocate memory for the data structure returned to the caller */ D = new_cc65_segmentinfo (1); /* Fill in the data */ CopySegInfo (D->data, S); /* Return the result */ return D; } void cc65_free_segmentinfo (cc65_dbginfo Handle, const cc65_segmentinfo* Info) /* Free a segment info record */ { /* Just for completeness, check the handle */ assert (Handle != 0); /* Free the memory */ xfree ((cc65_segmentinfo*) Info); } /*****************************************************************************/ /* Symbols */ /*****************************************************************************/ const cc65_symbolinfo* cc65_symbol_byid (cc65_dbginfo Handle, unsigned Id) /* Return the symbol with a given id. The function returns NULL if no symbol ** with this id was found. */ { const DbgInfo* Info; cc65_symbolinfo* D; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Check if the id is valid */ if (Id >= CollCount (&Info->SymInfoById)) { return 0; } /* Allocate memory for the data structure returned to the caller */ D = new_cc65_symbolinfo (1); /* Fill in the data */ CopySymInfo (D->data, CollAt (&Info->SymInfoById, Id)); /* Return the result */ return D; } const cc65_symbolinfo* cc65_symbol_byname (cc65_dbginfo Handle, const char* Name) /* Return a list of symbols with a given name. The function returns NULL if ** no symbol with this name was found. */ { const DbgInfo* Info; cc65_symbolinfo* D; unsigned I; unsigned Index; unsigned Count; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Search for the symbol */ if (!FindSymInfoByName (&Info->SymInfoByName, Name, &Index)) { /* Not found */ return 0; } /* Index contains the position. Count how many symbols with this name ** we have. Skip the first one, since we have at least one. */ Count = 1; while ((unsigned) Index + Count < CollCount (&Info->SymInfoByName)) { const SymInfo* S = CollAt (&Info->SymInfoByName, (unsigned) Index + Count); if (strcmp (S->Name, Name) != 0) { break; } ++Count; } /* Allocate memory for the data structure returned to the caller */ D = new_cc65_symbolinfo (Count); /* Fill in the data */ for (I = 0; I < Count; ++I) { /* Copy the data */ CopySymInfo (D->data + I, CollAt (&Info->SymInfoByName, Index++)); } /* Return the result */ return D; } const cc65_symbolinfo* cc65_symbol_byscope (cc65_dbginfo Handle, unsigned ScopeId) /* Return a list of symbols in the given scope. This includes cheap local ** symbols, but not symbols in subscopes. The function returns NULL if the ** scope id is invalid (no such scope) and otherwise a - possibly empty - ** symbol list. */ { const DbgInfo* Info; cc65_symbolinfo* D; const ScopeInfo* S; unsigned I; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Check if the id is valid */ if (ScopeId >= CollCount (&Info->ScopeInfoById)) { return 0; } /* Get the scope */ S = CollAt (&Info->ScopeInfoById, ScopeId); /* Allocate memory for the data structure returned to the caller */ D = new_cc65_symbolinfo (CollCount (&S->SymInfoByName)); /* Fill in the data */ for (I = 0; I < CollCount (&S->SymInfoByName); ++I) { /* Copy the data */ CopySymInfo (D->data + I, CollAt (&S->SymInfoByName, I)); } /* Return the result */ return D; } const cc65_symbolinfo* cc65_symbol_inrange (cc65_dbginfo Handle, cc65_addr Start, cc65_addr End) /* Return a list of labels in the given range. End is inclusive. The function ** return NULL if no symbols within the given range are found. Non label ** symbols are ignored and not returned. */ { const DbgInfo* Info; Collection SymInfoList = COLLECTION_INITIALIZER; cc65_symbolinfo* D; unsigned I; unsigned Index; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Search for the symbol. Because we're searching for a range, we cannot ** make use of the function result. */ FindSymInfoByValue (&Info->SymInfoByVal, Start, &Index); /* Start from the given index, check all symbols until the end address is ** reached. Place all symbols into SymInfoList for later. */ for (I = Index; I < CollCount (&Info->SymInfoByVal); ++I) { /* Get the item */ SymInfo* Item = CollAt (&Info->SymInfoByVal, I); /* The collection is sorted by address, so if we get a value larger ** than the end address, we're done. */ if (Item->Value > (long) End) { break; } /* Ignore non-labels (this will also ignore imports) */ if (Item->Type != CC65_SYM_LABEL) { continue; } /* Ok, remember this one */ CollAppend (&SymInfoList, Item); } /* If we don't have any labels within the range, bail out. No memory has ** been allocated for SymInfoList. */ if (CollCount (&SymInfoList) == 0) { return 0; } /* Allocate memory for the data structure returned to the caller */ D = new_cc65_symbolinfo (CollCount (&SymInfoList)); /* Fill in the data */ for (I = 0; I < CollCount (&SymInfoList); ++I) { /* Copy the data */ CopySymInfo (D->data + I, CollAt (&SymInfoList, I)); } /* Free the collection */ CollDone (&SymInfoList); /* Return the result */ return D; } void cc65_free_symbolinfo (cc65_dbginfo Handle, const cc65_symbolinfo* Info) /* Free a symbol info record */ { /* Just for completeness, check the handle */ assert (Handle != 0); /* Free the memory */ xfree ((cc65_symbolinfo*) Info); } /*****************************************************************************/ /* Types */ /*****************************************************************************/ const cc65_typedata* cc65_type_byid (cc65_dbginfo Handle, unsigned Id) /* Return the data for the type with the given id. The function returns NULL ** if no type with this id was found. */ { const DbgInfo* Info; const TypeInfo* T; /* Check the parameter */ assert (Handle != 0); /* The handle is actually a pointer to a debug info struct */ Info = Handle; /* Check if the id is valid */ if (Id >= CollCount (&Info->TypeInfoById)) { return 0; } /* Get the type info with the given id */ T = CollAt (&Info->TypeInfoById, Id); /* We do already have the type data. Return it. */ return T->Data; } void cc65_free_typedata (cc65_dbginfo Handle, const cc65_typedata* data) /* Free a symbol info record */ { /* Just for completeness, check the handle and the data*/ assert (Handle != 0 && data != 0); /* Nothing to do */ } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/dbginfo/dbginfo.h���������������������������������������������������������������������0000664�0000000�0000000�00000065657�13473601511�0016210�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* dbginfo.h */ /* */ /* cc65 debug info handling */ /* */ /* */ /* */ /* (C) 2010-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef DBGINFO_H #define DBGINFO_H /* Allow usage from C++ */ #ifdef __cplusplus extern "C" { #endif /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Data types used for addresses, sizes and line numbers. Change to "unsigned ** long" if you ever want to run the code on a 16-bit machine. */ typedef unsigned cc65_line; /* Used to store line numbers */ typedef unsigned cc65_addr; /* Used to store (65xx) addresses */ typedef unsigned cc65_size; /* Used to store (65xx) sizes */ /* A value that is used to mark invalid ids */ #define CC65_INV_ID (~0U) /*****************************************************************************/ /* Debug info files */ /*****************************************************************************/ /* Severity for cc65_parseerror */ typedef enum { CC65_WARNING, CC65_ERROR, } cc65_error_severity; /* Warnings/errors in cc65_read_dbginfo are passed via this struct */ typedef struct cc65_parseerror cc65_parseerror; struct cc65_parseerror { cc65_error_severity type; /* Type of error */ const char* name; /* Name of input file */ cc65_line line; /* Error line */ unsigned column; /* Error column */ char errormsg[1]; /* Error message */ }; /* Function that is called in case of parse errors */ typedef void (*cc65_errorfunc) (const cc65_parseerror*); /* Pointer to an opaque data structure containing information from the debug ** info file. Actually a handle to the data in the file. */ typedef const void* cc65_dbginfo; cc65_dbginfo cc65_read_dbginfo (const char* filename, cc65_errorfunc errorfunc); /* Parse the debug info file with the given name. On success, the function ** will return a pointer to an opaque cc65_dbginfo structure, that must be ** passed to the other functions in this module to retrieve information. ** errorfunc is called in case of warnings and errors. If the file cannot be ** read successfully, NULL is returned. */ void cc65_free_dbginfo (cc65_dbginfo Handle); /* Free debug information read from a file */ /*****************************************************************************/ /* C Symbols */ /*****************************************************************************/ /* C symbol kinds */ typedef enum { CC65_CSYM_FUNC, CC65_CSYM_VAR } cc65_csym_kind; /* C object storage classes */ typedef enum { CC65_CSYM_AUTO, /* Auto = on stack */ CC65_CSYM_REG, /* Register = in register bank */ CC65_CSYM_STATIC, /* Static = static storage */ CC65_CSYM_EXTERN /* Extern = static storage + external visibility */ } cc65_csym_sc; /* C symbol information */ typedef struct cc65_csymdata cc65_csymdata; struct cc65_csymdata { unsigned csym_id; /* The internal c symbol id */ unsigned char csym_kind; /* Kind of c symbol */ unsigned char csym_sc; /* Storage class of c symbol */ int csym_offs; /* Offset for auto and register */ unsigned type_id; /* Id of the data type */ unsigned symbol_id; /* Attached asm symbol if any */ unsigned scope_id; /* Scope of c symbol */ const char* csym_name; /* Name of the symbol */ }; typedef struct cc65_csyminfo cc65_csyminfo; struct cc65_csyminfo { unsigned count; /* Number of data sets that follow */ cc65_csymdata data[1]; /* Data sets, number is dynamic */ }; const cc65_csyminfo* cc65_get_csymlist (cc65_dbginfo handle); /* Return a list of all c symbols */ const cc65_csyminfo* cc65_csym_byid (cc65_dbginfo handle, unsigned id); /* Return information about a c symbol with a specific id. The function ** returns NULL if the id is invalid (no such c symbol) and otherwise a ** cc65_csyminfo structure with one entry that contains the requested ** symbol information. */ const cc65_csyminfo* cc65_cfunc_bymodule (cc65_dbginfo handle, unsigned module_id); /* Return the list of C functions (not symbols!) for a specific module. If ** the module id is invalid, the function will return NULL, otherwise a ** (possibly empty) c symbol list. */ const cc65_csyminfo* cc65_cfunc_byname (cc65_dbginfo handle, const char* name); /* Return a list of all C functions with the given name that have a ** definition. */ const cc65_csyminfo* cc65_csym_byscope (cc65_dbginfo handle, unsigned scope_id); /* Return all C symbols for a scope. The function will return NULL if the ** given id is invalid. */ void cc65_free_csyminfo (cc65_dbginfo handle, const cc65_csyminfo* info); /* Free a c symbol info record */ /*****************************************************************************/ /* Libraries */ /*****************************************************************************/ /* Library information */ typedef struct cc65_librarydata cc65_librarydata; struct cc65_librarydata { unsigned library_id; /* The internal library id */ const char* library_name; /* Name of the library */ }; typedef struct cc65_libraryinfo cc65_libraryinfo; struct cc65_libraryinfo { unsigned count; /* Number of data sets that follow */ cc65_librarydata data[1]; /* Data sets, number is dynamic */ }; const cc65_libraryinfo* cc65_get_librarylist (cc65_dbginfo handle); /* Return a list of all libraries */ const cc65_libraryinfo* cc65_library_byid (cc65_dbginfo handle, unsigned id); /* Return information about a library with a specific id. The function ** returns NULL if the id is invalid (no such library) and otherwise a ** cc65_libraryinfo structure with one entry that contains the requested ** library information. */ void cc65_free_libraryinfo (cc65_dbginfo handle, const cc65_libraryinfo* info); /* Free a library info record */ /*****************************************************************************/ /* Line info */ /*****************************************************************************/ /* Type of line */ typedef enum { CC65_LINE_ASM, /* Assembler source */ CC65_LINE_EXT, /* Externally supplied (= C) */ CC65_LINE_MACRO, /* Macro expansion */ } cc65_line_type; /* Line information */ typedef struct cc65_linedata cc65_linedata; struct cc65_linedata { unsigned line_id; /* Internal id of this record */ unsigned source_id; /* Id of the source file */ cc65_line source_line; /* Line number */ cc65_line_type line_type; /* Type of line */ unsigned count; /* Nesting counter for macros */ }; typedef struct cc65_lineinfo cc65_lineinfo; struct cc65_lineinfo { unsigned count; /* Number of data sets that follow */ cc65_linedata data[1]; /* Data sets, number is dynamic */ }; const cc65_lineinfo* cc65_line_byid (cc65_dbginfo handle, unsigned id); /* Return information about a line with a specific id. The function ** returns NULL if the id is invalid (no such line) and otherwise a ** cc65_lineinfo structure with one entry that contains the requested ** module information. */ const cc65_lineinfo* cc65_line_bynumber (cc65_dbginfo handle, unsigned source_id, cc65_line line); /* Return line information for a source file/line number combination. The ** function returns NULL if no line information was found. */ const cc65_lineinfo* cc65_line_bysource (cc65_dbginfo Handle, unsigned source_id); /* Return line information for a source file. The function returns NULL if the ** file id is invalid. */ const cc65_lineinfo* cc65_line_bysymdef (cc65_dbginfo handle, unsigned symbol_id); /* Return line information for the definition of a symbol. The function ** returns NULL if the symbol id is invalid, otherwise a list of line infos. */ const cc65_lineinfo* cc65_line_bysymref (cc65_dbginfo handle, unsigned symbol_id); /* Return line information for all references of a symbol. The function ** returns NULL if the symbol id is invalid, otherwise a list of line infos. */ const cc65_lineinfo* cc65_line_byspan (cc65_dbginfo handle, unsigned span_id); /* Return line information for a a span. The function returns NULL if the ** span id is invalid, otherwise a list of line infos. */ void cc65_free_lineinfo (cc65_dbginfo handle, const cc65_lineinfo* info); /* Free line info returned by one of the other functions */ /*****************************************************************************/ /* Modules */ /*****************************************************************************/ /* Module information ** Notes: ** - scope_id contains CC65_INV_ID if the module was compiled without ** debug information. */ typedef struct cc65_moduledata cc65_moduledata; struct cc65_moduledata { unsigned module_id; /* The internal module id */ const char* module_name; /* Name of the module */ unsigned source_id; /* Id of the module main file */ unsigned library_id; /* Id of the library if any */ unsigned scope_id; /* Id of the main scope */ }; typedef struct cc65_moduleinfo cc65_moduleinfo; struct cc65_moduleinfo { unsigned count; /* Number of data sets that follow */ cc65_moduledata data[1]; /* Data sets, number is dynamic */ }; const cc65_moduleinfo* cc65_get_modulelist (cc65_dbginfo handle); /* Return a list of all modules */ const cc65_moduleinfo* cc65_module_byid (cc65_dbginfo handle, unsigned id); /* Return information about a module with a specific id. The function ** returns NULL if the id is invalid (no such module) and otherwise a ** cc65_moduleinfo structure with one entry that contains the requested ** module information. */ void cc65_free_moduleinfo (cc65_dbginfo handle, const cc65_moduleinfo* info); /* Free a module info record */ /*****************************************************************************/ /* Spans */ /*****************************************************************************/ /* Span information */ typedef struct cc65_spandata cc65_spandata; struct cc65_spandata { unsigned span_id; /* The internal span id */ cc65_addr span_start; /* Start of the span */ cc65_addr span_end; /* End of the span (inclusive!) */ unsigned segment_id; /* Id of the segment */ unsigned type_id; /* Id of the type of this span */ unsigned line_count; /* Number of lines attached */ unsigned scope_count; /* Number of scopes attached */ }; typedef struct cc65_spaninfo cc65_spaninfo; struct cc65_spaninfo { unsigned count; /* Number of data sets that follow */ cc65_spandata data[1]; /* Data sets, number is dynamic */ }; const cc65_spaninfo* cc65_get_spanlist (cc65_dbginfo handle); /* Return a list of all spans. BEWARE: Large! */ const cc65_spaninfo* cc65_span_byid (cc65_dbginfo handle, unsigned id); /* Return information about a span with a specific id. The function ** returns NULL if the id is invalid (no such span) and otherwise a ** cc65_spaninfo structure with one entry that contains the requested ** span information. */ const cc65_spaninfo* cc65_span_byaddr (cc65_dbginfo handle, unsigned long addr); /* Return span information for the given address. The function returns NULL ** if no spans were found for this address. */ const cc65_spaninfo* cc65_span_byline (cc65_dbginfo handle, unsigned line_id); /* Return span information for the given source line. The function returns NULL ** if the line id is invalid, otherwise the spans for this line (possibly zero). */ const cc65_spaninfo* cc65_span_byscope (cc65_dbginfo handle, unsigned scope_id); /* Return span information for the given scope. The function returns NULL if ** the scope id is invalid, otherwise the spans for this scope (possibly zero). */ void cc65_free_spaninfo (cc65_dbginfo handle, const cc65_spaninfo* info); /* Free a span info record */ /*****************************************************************************/ /* Source files */ /*****************************************************************************/ /* Source file information */ typedef struct cc65_sourcedata cc65_sourcedata; struct cc65_sourcedata { unsigned source_id; /* The internal file id */ const char* source_name; /* Name of the file */ unsigned long source_size; /* Size of file */ unsigned long source_mtime; /* Modification time */ }; typedef struct cc65_sourceinfo cc65_sourceinfo; struct cc65_sourceinfo { unsigned count; /* Number of data sets that follow */ cc65_sourcedata data[1]; /* Data sets, number is dynamic */ }; const cc65_sourceinfo* cc65_get_sourcelist (cc65_dbginfo handle); /* Return a list of all source files */ const cc65_sourceinfo* cc65_source_byid (cc65_dbginfo handle, unsigned id); /* Return information about a source file with a specific id. The function ** returns NULL if the id is invalid (no such source file) and otherwise a ** cc65_sourceinfo structure with one entry that contains the requested ** source file information. */ const cc65_sourceinfo* cc65_source_bymodule (cc65_dbginfo handle, unsigned module_id); /* Return information about the source files used to build a module. The ** function returns NULL if the module id is invalid (no such module) and ** otherwise a cc65_sourceinfo structure with one entry per source file. */ void cc65_free_sourceinfo (cc65_dbginfo handle, const cc65_sourceinfo* info); /* Free a source info record */ /*****************************************************************************/ /* Scopes */ /*****************************************************************************/ /* Scope information */ typedef enum { CC65_SCOPE_GLOBAL, /* Global scope */ CC65_SCOPE_MODULE, /* Module scope */ CC65_SCOPE_SCOPE, /* .PROC/.SCOPE */ CC65_SCOPE_STRUCT, /* .STRUCT */ CC65_SCOPE_ENUM, /* .ENUM */ } cc65_scope_type; typedef struct cc65_scopedata cc65_scopedata; struct cc65_scopedata { unsigned scope_id; /* Id of scope */ const char* scope_name; /* Name of scope */ cc65_scope_type scope_type; /* Type of scope */ cc65_size scope_size; /* Size of scope, 0 if unknown */ unsigned parent_id; /* Id of parent scope */ unsigned symbol_id; /* Id of scope symbol if any */ unsigned module_id; /* Id of the module */ }; typedef struct cc65_scopeinfo cc65_scopeinfo; struct cc65_scopeinfo { unsigned count; /* Number of data sets that follow */ cc65_scopedata data[1]; /* Data sets, number is dynamic */ }; const cc65_scopeinfo* cc65_get_scopelist (cc65_dbginfo handle); /* Return a list of all scopes in the debug information */ const cc65_scopeinfo* cc65_scope_byid (cc65_dbginfo handle, unsigned id); /* Return the scope with a given id. The function returns NULL if no scope ** with this id was found. */ const cc65_scopeinfo* cc65_scope_bymodule (cc65_dbginfo handle, unsigned module_id); /* Return the list of scopes for one module. The function returns NULL if no ** scope with the given id was found. */ const cc65_scopeinfo* cc65_scope_byname (cc65_dbginfo handle, const char* name); /* Return the list of scopes with a given name. Returns NULL if no scope with ** the given name was found, otherwise a non empty scope list. */ const cc65_scopeinfo* cc65_scope_byspan (cc65_dbginfo handle, unsigned span_id); /* Return scope information for a a span. The function returns NULL if the ** span id is invalid, otherwise a list of line scopes. */ const cc65_scopeinfo* cc65_childscopes_byid (cc65_dbginfo handle, unsigned id); /* Return the direct child scopes of a scope with a given id. The function ** returns NULL if no scope with this id was found, otherwise a list of the ** direct childs. */ void cc65_free_scopeinfo (cc65_dbginfo Handle, const cc65_scopeinfo* Info); /* Free a scope info record */ /*****************************************************************************/ /* Segments */ /*****************************************************************************/ /* Segment information. ** Notes: ** - output_name may be NULL if the data wasn't written to the output file ** (example: bss segment) ** - output_offs is invalid if there is no output_name, and may not be of ** much use in case of a relocatable output file */ typedef struct cc65_segmentdata cc65_segmentdata; struct cc65_segmentdata { unsigned segment_id; /* The internal segment id */ const char* segment_name; /* Name of the segment */ cc65_addr segment_start; /* Start address of segment */ cc65_size segment_size; /* Size of segment */ const char* output_name; /* Output file this seg was written to */ unsigned long output_offs; /* Offset of this seg in output file */ }; typedef struct cc65_segmentinfo cc65_segmentinfo; struct cc65_segmentinfo { unsigned count; /* Number of data sets that follow */ cc65_segmentdata data[1]; /* Data sets, number is dynamic */ }; const cc65_segmentinfo* cc65_get_segmentlist (cc65_dbginfo handle); /* Return a list of all segments referenced in the debug information */ const cc65_segmentinfo* cc65_segment_byid (cc65_dbginfo handle, unsigned id); /* Return information about a segment with a specific id. The function returns ** NULL if the id is invalid (no such segment) and otherwise a cc65_segmentinfo ** structure with one entry that contains the requested segment information. */ const cc65_segmentinfo* cc65_segment_byname (cc65_dbginfo handle, const char* name); /* Return information about a segment with a specific name. The function ** returns NULL if no segment with this name exists and otherwise a ** cc65_segmentinfo structure with one entry that contains the requested ** information. */ void cc65_free_segmentinfo (cc65_dbginfo handle, const cc65_segmentinfo* info); /* Free a segment info record */ /*****************************************************************************/ /* Symbols */ /*****************************************************************************/ /* Symbol information */ typedef enum { CC65_SYM_EQUATE, CC65_SYM_LABEL, /* Some sort of address */ CC65_SYM_IMPORT, /* An import */ } cc65_symbol_type; /* Notes: ** - If the symbol is segment relative, the segment id gives segment ** information, otherwise it contains CC65_INV_ID. ** - If the type is CC65_SYM_IMPORT, export_id may contain the id of the ** export. This is not the case if the module contaiing the export doesn't ** have debug information. ** - For an import, the fields symbol_value and segment_id are taken from ** the export, if it is available, since imports have no value or segments ** by itself. ** - For an import symbol_size doesn't have a meaning. ** - For normal symbols (not cheap locals) parent_id contains CC65_INV_ID, ** for cheap locals it contains the symbol id of the parent symbol. */ typedef struct cc65_symboldata cc65_symboldata; struct cc65_symboldata { unsigned symbol_id; /* Id of symbol */ const char* symbol_name; /* Name of symbol */ cc65_symbol_type symbol_type; /* Type of symbol */ cc65_size symbol_size; /* Size of symbol, 0 if unknown */ long symbol_value; /* Value of symbol */ unsigned export_id; /* For imports: Matching export */ unsigned segment_id; /* Id of segment if any */ unsigned scope_id; /* The scope this symbol is in */ unsigned parent_id; /* Parent symbol for cheap locals */ }; typedef struct cc65_symbolinfo cc65_symbolinfo; struct cc65_symbolinfo { unsigned count; /* Number of data sets that follow */ cc65_symboldata data[1]; /* Data sets, number is dynamic */ }; const cc65_symbolinfo* cc65_symbol_byid (cc65_dbginfo handle, unsigned id); /* Return the symbol with a given id. The function returns NULL if no symbol ** with this id was found. */ const cc65_symbolinfo* cc65_symbol_byname (cc65_dbginfo handle, const char* name); /* Return a list of symbols with a given name. The function returns NULL if ** no symbol with this name was found. */ const cc65_symbolinfo* cc65_symbol_byscope (cc65_dbginfo handle, unsigned scope_id); /* Return a list of symbols in the given scope. This includes cheap local ** symbols, but not symbols in subscopes. The function returns NULL if the ** scope id is invalid (no such scope) and otherwise a - possibly empty - ** symbol list. */ const cc65_symbolinfo* cc65_symbol_inrange (cc65_dbginfo handle, cc65_addr start, cc65_addr end); /* Return a list of labels in the given range. end is inclusive. The function ** return NULL if no symbols within the given range are found. Non label ** symbols are ignored and not returned. */ void cc65_free_symbolinfo (cc65_dbginfo handle, const cc65_symbolinfo* info); /* Free a symbol info record */ /*****************************************************************************/ /* Types */ /*****************************************************************************/ /* Type information */ typedef enum { CC65_TYPE_VOID, CC65_TYPE_BYTE, CC65_TYPE_WORD, CC65_TYPE_DBYTE, CC65_TYPE_DWORD, CC65_TYPE_PTR, CC65_TYPE_FARPTR, CC65_TYPE_ARRAY, /* The following ones are currently unavailable: */ CC65_TYPE_UNION, CC65_TYPE_STRUCT, CC65_TYPE_FUNC, } cc65_typetoken; /* A type is a linked list of typedata structures. In case of arrays, the ** structure will contain an element count and the element type. In case of ** pointers, the structure will contain the type of the data, the pointer ** points to (currently, there are only VOID pointers). ** The next pointer points to the next entry in the list. It is NULL if the ** end of the list is reached. */ typedef struct cc65_typedata cc65_typedata; struct cc65_typedata { cc65_typedata* next; /* Pointer to next entry */ cc65_typetoken what; /* What kind of type is it? */ cc65_size size; /* The size of the data */ /* Depending on "what", one of the members of this union follows */ union { /* In case of CC65_TYPE_PTR or CC65_TYPE_FARPTR */ struct { const cc65_typedata* ind_type; /* Type the pointer points to */ } ptr; /* In case of CC65_TYPE_ARRAY */ struct { cc65_size ele_count; /* Element count */ const cc65_typedata* ele_type; /* Element type */ } array; } data; }; const cc65_typedata* cc65_type_byid (cc65_dbginfo handle, unsigned id); /* Return the data for the type with the given id. The function returns NULL ** if no type with this id was found. */ void cc65_free_typedata (cc65_dbginfo Handle, const cc65_typedata* data); /* Free a symbol info record */ /* Allow usage from C++ */ #ifdef __cplusplus } #endif /* End of dbginfo.h */ #endif ���������������������������������������������������������������������������������cc65-2.18/src/dbginfo/dbgsh.c�����������������������������������������������������������������������0000664�0000000�0000000�00000134567�13473601511�0015657�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* dbgsh.c */ /* */ /* debug info test shell */ /* */ /* */ /* */ /* (C) 2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <time.h> #include <errno.h> /* common */ #include "attrib.h" #include "chartype.h" #include "cmdline.h" #include "coll.h" /* dbginfo */ #include "dbginfo.h" /*****************************************************************************/ /* Command handler forwards */ /*****************************************************************************/ static void CmdHelp (Collection* Args attribute ((unused))); /* Output a help text */ static void CmdLoad (Collection* Args); /* Load a debug info file */ static void CmdQuit (Collection* Args attribute ((unused))); /* Terminate the application */ static void CmdShow (Collection* Args); /* Show items from the debug info file */ static void CmdShowHelp (Collection* Args); /* Print help for the show command */ static void CmdShowChildScopes (Collection* Args); /* Show child scopes from the debug info file */ static void CmdShowCSymbol (Collection* Args); /* Show c symbols from the debug info file */ static void CmdShowFunction (Collection* Args); /* Show C functions from the debug info file */ static void CmdShowLibrary (Collection* Args); /* Show libraries from the debug info file */ static void CmdShowLine (Collection* Args); /* Show lines from the debug info file */ static void CmdShowModule (Collection* Args); /* Show modules from the debug info file */ static void CmdShowScope (Collection* Args); /* Show scopes from the debug info file */ static void CmdShowSegment (Collection* Args); /* Show segments from the debug info file */ static void CmdShowSource (Collection* Args); /* Show source files from the debug info file */ static void CmdShowSpan (Collection* Args); /* Show spans from the debug info file */ static void CmdShowSymbol (Collection* Args); /* Show symbols */ static void CmdShowSymDef (Collection* Args); /* Show lines from the debug info file */ static void CmdShowSymRef (Collection* Args); /* Show lines from the debug info file */ static void CmdShowType (Collection* Args); /* Show types from the debug info file */ static void CmdUnload (Collection* Args attribute ((unused))); /* Unload a debug info file */ /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Terminate flag - end program when set to true */ static int Terminate = 0; /* The debug file data */ static cc65_dbginfo Info = 0; /* Error and warning counters */ static unsigned FileErrors = 0; static unsigned FileWarnings = 0; /* Type of an id */ enum { InvalidId, CSymbolId, LibraryId, LineId, ModuleId, ScopeId, SegmentId, SourceId, SpanId, SymbolId, TypeId }; /* Structure that contains a command description */ typedef struct CmdEntry CmdEntry; struct CmdEntry { char Cmd[12]; const char* Help; int ArgCount; void (*Func) (Collection*); }; /* Table with main commands */ static const CmdEntry MainCmds[] = { { "exit", 0, 1, CmdQuit }, { "help", "Show available commands", 1, CmdHelp }, { "load", "Load a debug info file", 2, CmdLoad }, { "quit", "Terminate the shell", 1, CmdQuit }, { "show", "Show items from the info file", -2, CmdShow }, { "unload", "Unload a debug info file", 1, CmdUnload }, }; /* Table with show commands */ static const CmdEntry ShowCmds[] = { { "childscopes", "Show child scopes of other scopes.", -2, CmdShowChildScopes }, { "csym", 0, -1, CmdShowCSymbol }, { "csymbol", "Show c symbols.", -1, CmdShowCSymbol }, { "func", 0, -2, CmdShowFunction }, { "function", "Show c functions.", -2, CmdShowFunction }, { "help", "Show available subcommands.", 1, CmdShowHelp }, { "line", "Show line info. May be followed by one or more line ids.", -2, CmdShowLine }, { "library", "Show libraries. May be followed by one or more library ids.", -1, CmdShowLibrary }, { "module", "Show modules. May be followed by one or more module ids.", -1, CmdShowModule }, { "scope", "Show scopes. May be followed by one or more segment ids.", -1, CmdShowScope }, { "segment", "Show segments. May be followed by one or more segment ids.", -1, CmdShowSegment }, { "source", "Show sources. May be followed by one or more source file ids.", -1, CmdShowSource }, { "span", "Show spans. May be followed by one or more span ids.", -1, CmdShowSpan }, { "symbol", "Show symbols. May be followed by one or more symbol or scope ids.", -2, CmdShowSymbol }, { "symdef", "Show where a symbol was defined. May be followed by one or more symbol ids.", -2, CmdShowSymDef }, { "symref", "Show where a symbol was referenced. May be followed by one or more symbol ids.", -2, CmdShowSymRef }, { "type", "Show type information. May be followed by one or more type ids.", -2, CmdShowType }, }; /*****************************************************************************/ /* Helpers */ /*****************************************************************************/ static void NewLine (void) /* Output a newline */ { putchar ('\n'); } static void Print (const char* Format, ...) attribute((format(printf,1,2))); static void Print (const char* Format, ...) /* Print a piece of output (no linefeed added) */ { va_list ap; va_start (ap, Format); vprintf (Format, ap); va_end (ap); } static void PrintLine (const char* Format, ...) attribute((format(printf,1,2))); static void PrintLine (const char* Format, ...) /* Print one line of output. The linefeed is supplied by the function */ { va_list ap; va_start (ap, Format); vprintf (Format, ap); NewLine (); va_end (ap); } static void PrintSeparator (void) /* Print a separator line */ { PrintLine ("---------------------------------------------------------------------------"); } static void FileError (const cc65_parseerror* Info) /* Callback function - is called in case of errors */ { /* Output a message */ PrintLine ("%s:%s(%lu): %s", Info->type? "Error" : "Warning", Info->name, (unsigned long) Info->line, Info->errormsg); /* Bump the counters */ switch (Info->type) { case CC65_WARNING: ++FileWarnings; break; default: ++FileErrors; break; } } static const CmdEntry* FindCmd (const char* Cmd, const CmdEntry* Tab, unsigned Count) /* Search for a command in the given table */ { unsigned I; for (I = 0; I < Count; ++I, ++Tab) { if (strcmp (Cmd, Tab->Cmd) == 0) { return Tab; } } return 0; } static void ExecCmd (Collection* Args, const CmdEntry* Tab, unsigned Count) /* Search for the command in slot 0 of the given collection. If found, check ** the argument count, then execute it. If there are problems, output a ** diagnostic. */ { /* Search for the command, check number of args, then execute it */ const char* Cmd = CollAt (Args, 0); const CmdEntry* E = FindCmd (Cmd, Tab, Count); if (E == 0) { PrintLine ("No such command: %s", Cmd); return; } /* Check the number of arguments. Zero means that the function will check ** itself. A negative count means that the function needs at least ** abs(count) arguments. A positive count means that the function needs ** exactly this number of arguments. ** Note: The number includes the command itself. */ if (E->ArgCount > 0 && (int)CollCount (Args) != E->ArgCount) { /* Argument number mismatch */ switch (E->ArgCount) { case 1: PrintLine ("Command doesn't accept an argument"); return; case 2: PrintLine ("Command requires an argument"); return; default: PrintLine ("Command requires %d arguments", E->ArgCount-1); return; } } else if (E->ArgCount < 0 && (int)CollCount (Args) < -E->ArgCount) { /* Argument number mismatch */ switch (E->ArgCount) { case -2: PrintLine ("Command requires at least one argument"); return; default: PrintLine ("Command requires at least %d arguments", E->ArgCount-1); return; } } else { /* Remove the command from the argument list, then execute it */ CollDelete (Args, 0); E->Func (Args); } } static void PrintHelp (const CmdEntry* Tab, unsigned Count) /* Output help for one command table */ { while (Count--) { /* Ignore the commands without help text */ if (Tab->Help) { PrintLine ("%-*s%s", (int) sizeof (Tab->Cmd) + 2, Tab->Cmd, Tab->Help); } ++Tab; } } static unsigned FindIdType (const char* TypeName) /* Find an id type by its name. Returns the type or InvalidId. */ { static const struct { char Name[8]; unsigned Type; } TypeTab[] = { { "l", LineId }, { "lib", LibraryId }, { "library", LibraryId }, { "line", LineId }, { "m", ModuleId }, { "mod", ModuleId }, { "module", ModuleId }, { "s", SymbolId }, { "sc", ScopeId }, { "scope", ScopeId }, { "seg", SegmentId }, { "segment", SegmentId }, { "source", SourceId }, { "src", SourceId }, { "sp", SpanId }, { "span", SpanId }, { "sym", SymbolId }, { "symbol", SymbolId }, { "t", TypeId }, { "type", TypeId }, }; unsigned I; for (I = 0; I < sizeof(TypeTab) / sizeof(TypeTab[0]); ++I) { if (strcmp (TypeName, TypeTab[I].Name) == 0) { return TypeTab[I].Type; } } return InvalidId; } static int GetId (const char* S, unsigned* Id, unsigned* IdType) /* Parse a string for an id. If a valid id is found, it is placed in Id and ** the function returns true. If an optional type is found, it is placed in ** IdType, otherwise IdType is left unchanged. If no id is found, the ** function returns false. */ { char TypeBuf[20]; char C; if (sscanf (S, "%u%c", Id, &C) == 1) { /* Just an id found, return it */ return 1; } if (sscanf (S, "%19[a-z]:%u%c", TypeBuf, Id, &C) == 2) { *IdType = FindIdType (TypeBuf); return (*IdType != InvalidId); } /* Not a valid id */ return 0; } /*****************************************************************************/ /* Output functions for item lists */ /*****************************************************************************/ static void PrintAddr (cc65_addr Addr, unsigned FieldWidth) /* Output an address */ { Print ("$%06lX", (unsigned long) Addr); if (FieldWidth > 7) { Print ("%*s", FieldWidth - 7, ""); } } static void PrintNumber (long Num, unsigned Width, unsigned FieldWidth) /* Output a number */ { Print ("%*ld", Width, Num); if (FieldWidth > Width) { Print ("%*s", FieldWidth - Width, ""); } } static void PrintId (unsigned Id, unsigned FieldWidth) /* Output an id field */ { if (Id == CC65_INV_ID) { Print (" -"); } else { Print ("%4u", Id); } if (FieldWidth > 4) { Print ("%*s", FieldWidth - 4, ""); } } static void PrintSize (cc65_size Size, unsigned FieldWidth) /* Output a size */ { Print ("$%04lX", (unsigned long) Size); if (FieldWidth > 5) { Print ("%*s", FieldWidth - 5, ""); } } static void PrintTime (time_t T, unsigned FieldWidth) /* Output a time stamp of some sort */ { /* Convert to string */ char Buf[100]; unsigned Len = strftime (Buf, sizeof (Buf), "%Y-%m-%d %H:%M:%S", localtime (&T)); /* Output */ Print ("%s", Buf); if (FieldWidth > Len) { Print ("%*s", FieldWidth - Len, ""); } } static void PrintCSymbolHeader (void) /* Output a header for a list of C symbols */ { /* Header */ PrintLine (" id name type kind sc offs symbol scope"); PrintSeparator (); } static void PrintCSymbols (const cc65_csyminfo* S) /* Output a list of C symbols */ { unsigned I; const cc65_csymdata* D; /* Segments */ for (I = 0, D = S->data; I < S->count; ++I, ++D) { PrintId (D->csym_id, 6); Print ("%-28s", D->csym_name); PrintId (D->type_id, 6); PrintNumber (D->csym_kind, 4, 6); PrintNumber (D->csym_sc, 4, 6); PrintNumber (D->csym_offs, 4, 8); PrintId (D->symbol_id, 6); PrintId (D->scope_id, 0); NewLine (); } } static void PrintLibraryHeader (void) /* Output the header for a library list */ { PrintLine (" id name"); PrintSeparator (); } static void PrintLibraries (const cc65_libraryinfo* L) /* Output a list of libraries */ { unsigned I; const cc65_librarydata* D; /* Libraries */ for (I = 0, D = L->data; I < L->count; ++I, ++D) { PrintId (D->library_id, 8); Print ("%-24s", D->library_name); NewLine (); } } static void PrintLineHeader (void) /* Output a header for a line list */ { /* Header */ PrintLine (" id source line type count"); PrintSeparator (); } static void PrintLines (const cc65_lineinfo* L) /* Output a list of lines */ { unsigned I; const cc65_linedata* D; /* Lines */ for (I = 0, D = L->data; I < L->count; ++I, ++D) { PrintId (D->line_id, 8); PrintId (D->source_id, 8); PrintNumber (D->source_line, 6, 9); PrintNumber (D->line_type, 4, 6); PrintNumber (D->count, 3, 0); NewLine (); } } static void PrintModuleHeader (void) /* Output a header for a module list */ { /* Header */ PrintLine (" id name source library scope"); PrintSeparator (); } static void PrintModules (const cc65_moduleinfo* M) /* Output a list of modules */ { unsigned I; const cc65_moduledata* D; /* Modules */ for (I = 0, D = M->data; I < M->count; ++I, ++D) { PrintId (D->module_id, 8); Print ("%-24s", D->module_name); PrintId (D->source_id, 8); PrintId (D->library_id, 9); PrintId (D->scope_id, 6); NewLine (); } } static void PrintScopeHeader (void) /* Output a header for a list of scopes */ { /* Header */ PrintLine (" id name type size parent symbol module"); PrintSeparator (); } static void PrintScopes (const cc65_scopeinfo* S) /* Output a list of scopes */ { unsigned I; const cc65_scopedata* D; /* Segments */ for (I = 0, D = S->data; I < S->count; ++I, ++D) { PrintId (D->scope_id, 8); Print ("%-24s", D->scope_name); PrintNumber (D->scope_type, 4, 8); /* ## */ PrintSize (D->scope_size, 8); PrintId (D->parent_id, 8); PrintId (D->symbol_id, 8); PrintId (D->module_id, 0); NewLine (); } } static void PrintSegmentHeader (void) /* Output a header for a list of segments */ { /* Header */ PrintLine (" id name address size output file offs"); PrintSeparator (); } static void PrintSegments (const cc65_segmentinfo* S) /* Output a list of segments */ { unsigned I; const cc65_segmentdata* D; /* Segments */ for (I = 0, D = S->data; I < S->count; ++I, ++D) { PrintId (D->segment_id, 8); Print ("%-16s", D->segment_name); PrintAddr (D->segment_start, 9); PrintSize (D->segment_size, 7); Print ("%-16s", D->output_name? D->output_name : ""); PrintSize (D->output_offs, 6); NewLine (); } } static void PrintSourceHeader (void) /* Output a header for a list of source files */ { /* Header */ PrintLine (" id name size modification time"); PrintSeparator (); } static void PrintSources (const cc65_sourceinfo* S) /* Output a list of sources */ { unsigned I; const cc65_sourcedata* D; /* Segments */ for (I = 0, D = S->data; I < S->count; ++I, ++D) { PrintId (D->source_id, 8); Print ("%-30s", D->source_name); PrintNumber (D->source_size, 7, 9); PrintTime (D->source_mtime, 0); NewLine (); } } static void PrintSpanHeader (void) /* Output a header for a list of spans */ { /* Header */ PrintLine (" id start end seg type lines scopes"); PrintSeparator (); } static void PrintSpans (const cc65_spaninfo* S) /* Output a list of spans */ { unsigned I; const cc65_spandata* D; /* Segments */ for (I = 0, D = S->data; I < S->count; ++I, ++D) { PrintId (D->span_id, 7); PrintAddr (D->span_start, 8); PrintAddr (D->span_end, 9); PrintId (D->segment_id, 7); PrintId (D->type_id, 6); PrintNumber (D->line_count, 6, 7); PrintNumber (D->scope_count, 7, 0); NewLine (); } } static void PrintSymbolHeader (void) /* Output a header for a list of symbols */ { /* Header */ PrintLine (" id name type size value export seg scope parent"); PrintSeparator (); } static void PrintSymbols (const cc65_symbolinfo* S) /* Output a list of symbols */ { unsigned I; const cc65_symboldata* D; /* Segments */ for (I = 0, D = S->data; I < S->count; ++I, ++D) { PrintId (D->symbol_id, 6); Print ("%-24s", D->symbol_name); PrintNumber (D->symbol_type, 4, 6); PrintNumber (D->symbol_size, 4, 6); PrintNumber (D->symbol_value, 5, 7); PrintId (D->export_id, 7); PrintId (D->segment_id, 6); PrintId (D->scope_id, 6); PrintId (D->parent_id, 0); NewLine (); } } static void PrintTypeHeader (void) /* Output a header for a list of types */ { /* Header */ PrintLine (" id description"); PrintSeparator (); } static void PrintType (unsigned Id, const cc65_typedata* T) /* Output one type */ { /* Output the id */ PrintId (Id, 6); while (1) { switch (T->what) { case CC65_TYPE_VOID: Print ("VOID"); goto ExitPoint; case CC65_TYPE_BYTE: Print ("BYTE"); goto ExitPoint; case CC65_TYPE_WORD: Print ("WORD"); goto ExitPoint; case CC65_TYPE_DBYTE: Print ("DBYTE"); goto ExitPoint; case CC65_TYPE_DWORD: Print ("DWORD"); goto ExitPoint; case CC65_TYPE_FARPTR: Print ("FAR "); /* FALLTHROUGH */ case CC65_TYPE_PTR: Print ("POINTER TO "); T = T->data.ptr.ind_type; break; case CC65_TYPE_ARRAY: Print ("ARRAY[%u] OF ", T->data.array.ele_count); T = T->data.array.ele_type; break; default: /* Anything else is currently not implemented */ Print ("***NOT IMPLEMENTED***"); goto ExitPoint; } } ExitPoint: NewLine (); } /*****************************************************************************/ /* Debug file handling */ /*****************************************************************************/ static void UnloadFile (void) /* Unload the debug info file */ { if (Info) { cc65_free_dbginfo (Info); Info = 0; } } static int FileIsLoaded (void) /* Return true if the file is open and has loaded without errors: If not, ** print an error message and return false. */ { /* File open? */ if (Info == 0) { PrintLine ("No debug info file"); return 0; } /* Errors on load? */ if (FileErrors > 0) { PrintLine ("File had load errors!"); return 0; } /* Warnings on load? */ if (FileWarnings > 0) { PrintLine ("Beware - file had load warnings!"); } /* Ok */ return 1; } /*****************************************************************************/ /* Command handlers */ /*****************************************************************************/ static void CmdHelp (Collection* Args attribute ((unused))) /* Output a help text */ { PrintHelp (MainCmds, sizeof (MainCmds) / sizeof (MainCmds[0])); } static void CmdLoad (Collection* Args) /* Load a debug info file */ { /* Unload a loaded file */ UnloadFile (); /* Clear the counters */ FileErrors = 0; FileWarnings = 0; /* Open the debug info file */ Info = cc65_read_dbginfo (CollAt (Args, 0), FileError); /* Print a status */ if (FileErrors > 0) { PrintLine ("File loaded with %u errors", FileErrors); } else if (FileWarnings > 0) { PrintLine ("File loaded with %u warnings", FileWarnings); } else { PrintLine ("File loaded successfully"); } } static void CmdQuit (Collection* Args attribute ((unused))) /* Terminate the application */ { UnloadFile (); Terminate = 1; } static void CmdShow (Collection* Args) /* Show items from the debug info file */ { /* Search for the subcommand, check number of args, then execute it */ ExecCmd (Args, ShowCmds, sizeof (ShowCmds) / sizeof (ShowCmds[0])); } static void CmdShowHelp (Collection* Args attribute ((unused))) /* Print help for the show command */ { PrintHelp (ShowCmds, sizeof (ShowCmds) / sizeof (ShowCmds[0])); } static void CmdShowChildScopes (Collection* Args) /* Show child scopes from the debug info file */ { const cc65_scopeinfo* S; unsigned I; /* Be sure a file is loaded */ if (!FileIsLoaded ()) { return; } /* Output the header */ PrintScopeHeader (); /* Output child scopes for all arguments */ for (I = 0; I < CollCount (Args); ++I) { /* Parse the argument */ unsigned Id; unsigned IdType = ScopeId; if (GetId (CollConstAt (Args, I), &Id, &IdType)) { /* Fetch list depending on type */ switch (IdType) { case ScopeId: S = cc65_childscopes_byid (Info, Id); break; default: S = 0; PrintLine ("Invalid id type"); break; } } else { /* Invalid id */ S = 0; } /* Output the list */ if (S) { PrintScopes (S); cc65_free_scopeinfo (Info, S); } } } static void CmdShowCSymbol (Collection* Args) /* Show C symbols from the debug info file */ { const cc65_csyminfo* S; /* Be sure a file is loaded */ if (!FileIsLoaded ()) { return; } /* Output the header */ PrintCSymbolHeader (); /* No arguments means show all libraries */ if (CollCount (Args) == 0) { /* Fetch the list of c symbols */ S = cc65_get_csymlist (Info); /* Output the c symbols */ PrintCSymbols (S); /* Free the list */ cc65_free_csyminfo (Info, S); } else { /* Output c symbols for all arguments */ unsigned I; for (I = 0; I < CollCount (Args); ++I) { /* Parse the argument */ unsigned Id; unsigned IdType = CSymbolId; if (GetId (CollConstAt (Args, I), &Id, &IdType)) { /* Fetch list depending on type */ switch (IdType) { case CSymbolId: S = cc65_csym_byid (Info, Id); break; case ScopeId: S = cc65_csym_byscope (Info, Id); break; default: S = 0; PrintLine ("Invalid id type"); break; } } else { /* Invalid id */ S = 0; } /* Output the list */ if (S) { PrintCSymbols (S); cc65_free_csyminfo (Info, S); } } } } static void CmdShowFunction (Collection* Args) /* Show C functions from the debug info file */ { const cc65_csyminfo* S; unsigned I; /* Be sure a file is loaded */ if (!FileIsLoaded ()) { return; } /* Output the header */ PrintCSymbolHeader (); /* Output c symbols for all arguments */ for (I = 0; I < CollCount (Args); ++I) { /* Parse the argument */ unsigned Id; unsigned IdType = ModuleId; if (GetId (CollConstAt (Args, I), &Id, &IdType)) { /* Fetch list depending on type */ switch (IdType) { case ModuleId: S = cc65_cfunc_bymodule (Info, Id); break; default: S = 0; PrintLine ("Invalid id type"); break; } } else { /* An invalid id may be a function name */ S = cc65_cfunc_byname (Info, CollConstAt (Args, I)); } /* Output the list */ if (S) { PrintCSymbols (S); cc65_free_csyminfo (Info, S); } } } static void CmdShowLine (Collection* Args) /* Show lines from the debug info file */ { const cc65_lineinfo* L; unsigned I; /* Be sure a file is loaded */ if (!FileIsLoaded ()) { return; } /* Output the header */ PrintLineHeader (); for (I = 0; I < CollCount (Args); ++I) { /* Parse the argument */ unsigned Id; unsigned IdType = LineId; if (GetId (CollConstAt (Args, I), &Id, &IdType)) { /* Fetch list depending on type */ switch (IdType) { case LineId: L = cc65_line_byid (Info, Id); break; case SourceId: L = cc65_line_bysource (Info, Id); break; case SymbolId: /* ### not very clean */ L = cc65_line_bysymdef (Info, Id); if (L) { PrintLines (L); cc65_free_lineinfo (Info, L); } L = cc65_line_bysymref (Info, Id); break; default: L = 0; PrintLine ("Invalid id type"); break; } } else { /* Ignore the invalid id */ L = 0; } /* Output the list */ if (L) { PrintLines (L); cc65_free_lineinfo (Info, L); } } } static void CmdShowLibrary (Collection* Args) /* Show libraries from the debug info file */ { const cc65_libraryinfo* L; /* Be sure a file is loaded */ if (!FileIsLoaded ()) { return; } /* Output the header */ PrintLibraryHeader (); /* No arguments means show all libraries */ if (CollCount (Args) == 0) { /* Fetch the list of libraries */ L = cc65_get_librarylist (Info); /* Output the libraries */ PrintLibraries (L); /* Free the list */ cc65_free_libraryinfo (Info, L); } else { unsigned I; for (I = 0; I < CollCount (Args); ++I) { /* Parse the argument */ unsigned Id; unsigned IdType = LibraryId; if (GetId (CollConstAt (Args, I), &Id, &IdType)) { /* Fetch list depending on type */ switch (IdType) { case LibraryId: L = cc65_library_byid (Info, Id); break; default: L = 0; PrintLine ("Invalid id type"); break; } } else { /* Ignore the invalid id */ L = 0; } /* Output the list */ if (L) { PrintLibraries (L); cc65_free_libraryinfo (Info, L); } } } } static void CmdShowModule (Collection* Args) /* Show modules from the debug info file */ { const cc65_moduleinfo* M; /* Be sure a file is loaded */ if (!FileIsLoaded ()) { return; } /* Output the header */ PrintModuleHeader (); /* No arguments means show all modules */ if (CollCount (Args) == 0) { /* Fetch the list of modules */ M = cc65_get_modulelist (Info); /* Output the modules */ PrintModules (M); /* Free the list */ cc65_free_moduleinfo (Info, M); } else { unsigned I; for (I = 0; I < CollCount (Args); ++I) { /* Parse the argument */ unsigned Id; unsigned IdType = ModuleId; if (GetId (CollConstAt (Args, I), &Id, &IdType)) { /* Fetch list depending on type */ switch (IdType) { case ModuleId: M = cc65_module_byid (Info, Id); break; default: M = 0; PrintLine ("Invalid id type"); break; } } else { /* Ignore the invalid id */ M = 0; } /* Output the list */ if (M) { PrintModules (M); cc65_free_moduleinfo (Info, M); } } } } static void CmdShowScope (Collection* Args) /* Show scopes from the debug info file */ { const cc65_scopeinfo* S; /* Be sure a file is loaded */ if (!FileIsLoaded ()) { return; } /* Output the header */ PrintScopeHeader (); /* No arguments means show all modules */ if (CollCount (Args) == 0) { /* Fetch the list of segments */ S = cc65_get_scopelist (Info); /* Output the segments */ PrintScopes (S); /* Free the list */ cc65_free_scopeinfo (Info, S); } else { unsigned I; for (I = 0; I < CollCount (Args); ++I) { /* Parse the argument */ unsigned Id; unsigned IdType = ScopeId; if (GetId (CollConstAt (Args, I), &Id, &IdType)) { /* Fetch list depending on type */ switch (IdType) { case ModuleId: S = cc65_scope_bymodule (Info, Id); break; case ScopeId: S = cc65_scope_byid (Info, Id); break; default: S = 0; PrintLine ("Invalid id type"); break; } } else { /* An invalid id may be a scope name */ S = cc65_scope_byname (Info, CollConstAt (Args, I)); } /* Output the list */ if (S) { PrintScopes (S); cc65_free_scopeinfo (Info, S); } } } } static void CmdShowSegment (Collection* Args) /* Show segments from the debug info file */ { const cc65_segmentinfo* S; /* Be sure a file is loaded */ if (!FileIsLoaded ()) { return; } /* Output the header */ PrintSegmentHeader (); /* No arguments means show all modules */ if (CollCount (Args) == 0) { /* Fetch the list of segments */ S = cc65_get_segmentlist (Info); /* Output the segments */ PrintSegments (S); /* Free the list */ cc65_free_segmentinfo (Info, S); } else { unsigned I; for (I = 0; I < CollCount (Args); ++I) { /* Parse the argument */ unsigned Id; unsigned IdType = SegmentId; if (GetId (CollConstAt (Args, I), &Id, &IdType)) { /* Fetch list depending on type */ switch (IdType) { case SegmentId: S = cc65_segment_byid (Info, Id); break; default: S = 0; PrintLine ("Invalid id type"); break; } } else { /* An invalid id may be a segment name */ S = cc65_segment_byname (Info, CollConstAt (Args, I)); } /* Output the list */ if (S) { PrintSegments (S); cc65_free_segmentinfo (Info, S); } } } } static void CmdShowSource (Collection* Args) /* Show source files from the debug info file */ { const cc65_sourceinfo* S; /* Be sure a file is loaded */ if (!FileIsLoaded ()) { return; } /* Output the header */ PrintSourceHeader (); /* No arguments means show all modules */ if (CollCount (Args) == 0) { /* Fetch the list of source files */ S = cc65_get_sourcelist (Info); /* Output the source files */ PrintSources (S); /* Free the list */ cc65_free_sourceinfo (Info, S); } else { unsigned I; for (I = 0; I < CollCount (Args); ++I) { /* Parse the argument */ unsigned Id; unsigned IdType = SourceId; if (GetId (CollConstAt (Args, I), &Id, &IdType)) { /* Fetch list depending on type */ switch (IdType) { case ModuleId: S = cc65_source_bymodule (Info, Id); break; case SourceId: S = cc65_source_byid (Info, Id); break; default: S = 0; PrintLine ("Invalid id type"); break; } } else { /* Ignore the invalid id */ S = 0; } /* Output the list */ if (S) { PrintSources (S); cc65_free_sourceinfo (Info, S); } } } } static void CmdShowSpan (Collection* Args) /* Show spans from the debug info file */ { const cc65_spaninfo* S; unsigned I; /* Be sure a file is loaded */ if (!FileIsLoaded ()) { return; } /* Output the header */ PrintSpanHeader (); for (I = 0; I < CollCount (Args); ++I) { /* Parse the argument */ unsigned Id; unsigned IdType = SpanId; if (GetId (CollConstAt (Args, I), &Id, &IdType)) { /* Fetch list depending on type */ switch (IdType) { case LineId: S = cc65_span_byline (Info, Id); break; case ScopeId: S = cc65_span_byscope (Info, Id); break; case SpanId: S = cc65_span_byid (Info, Id); break; default: S = 0; PrintLine ("Invalid id type"); break; } } else { /* Ignore the invalid id */ S = 0; } /* Output the list */ if (S) { PrintSpans (S); cc65_free_spaninfo (Info, S); } } } static void CmdShowSymbol (Collection* Args) /* Show symbols from the debug info file */ { const cc65_symbolinfo* S; unsigned I; /* Be sure a file is loaded */ if (!FileIsLoaded ()) { return; } /* Output the header */ PrintSymbolHeader (); for (I = 0; I < CollCount (Args); ++I) { /* Parse the argument */ unsigned Id; unsigned IdType = SymbolId; if (GetId (CollConstAt (Args, I), &Id, &IdType)) { /* Fetch list depending on type */ switch (IdType) { case ScopeId: S = cc65_symbol_byscope (Info, Id); break; case SymbolId: S = cc65_symbol_byid (Info, Id); break; default: S = 0; PrintLine ("Invalid id type"); break; } } else { /* Ignore the invalid id */ S = 0; } /* Output the list */ if (S) { PrintSymbols (S); cc65_free_symbolinfo (Info, S); } } } static void CmdShowSymDef (Collection* Args) /* Show symbol definitions from the debug info file */ { const cc65_lineinfo* L; unsigned I; /* Be sure a file is loaded */ if (!FileIsLoaded ()) { return; } /* Output the header */ PrintLineHeader (); for (I = 0; I < CollCount (Args); ++I) { /* Parse the argument */ unsigned Id; unsigned IdType = SymbolId; if (GetId (CollConstAt (Args, I), &Id, &IdType)) { /* Fetch list depending on type */ switch (IdType) { case SymbolId: L = cc65_line_bysymdef (Info, Id); break; default: L = 0; PrintLine ("Invalid id type"); break; } } else { /* Ignore the invalid id */ L = 0; } /* Output the list */ if (L) { PrintLines (L); cc65_free_lineinfo (Info, L); } } } static void CmdShowSymRef (Collection* Args) /* Show symbol references from the debug info file */ { const cc65_lineinfo* L; unsigned I; /* Be sure a file is loaded */ if (!FileIsLoaded ()) { return; } /* Output the header */ PrintLineHeader (); for (I = 0; I < CollCount (Args); ++I) { /* Parse the argument */ unsigned Id; unsigned IdType = SymbolId; if (GetId (CollConstAt (Args, I), &Id, &IdType)) { /* Fetch list depending on type */ switch (IdType) { case SymbolId: L = cc65_line_bysymref (Info, Id); break; default: L = 0; PrintLine ("Invalid id type"); break; } } else { /* Ignore the invalid id */ L = 0; } /* Output the list */ if (L) { PrintLines (L); cc65_free_lineinfo (Info, L); } } } static void CmdShowType (Collection* Args) /* Show types from the debug info file */ { const cc65_typedata* T; const cc65_spaninfo* S; unsigned I; /* Be sure a file is loaded */ if (!FileIsLoaded ()) { return; } /* Output the header */ PrintTypeHeader (); for (I = 0; I < CollCount (Args); ++I) { /* Parse the argument */ unsigned Id; unsigned IdType = TypeId; if (GetId (CollConstAt (Args, I), &Id, &IdType)) { /* Fetch list depending on type */ switch (IdType) { case SpanId: S = cc65_span_byid (Info, Id); if (S == 0 || S->count == 0) { T = 0; break; } Id = S->data[0].type_id; /* FALLTHROUGH */ case TypeId: T = cc65_type_byid (Info, Id); break; default: T = 0; PrintLine ("Invalid id type"); break; } } else { /* Ignore the invalid id */ T = 0; } /* Output the list */ if (T) { PrintType (Id, T); cc65_free_typedata (Info, T); } } } static void CmdUnload (Collection* Args attribute ((unused))) /* Unload a debug info file */ { UnloadFile (); } /*****************************************************************************/ /* Code */ /*****************************************************************************/ static int Parse (char* CmdLine, Collection* Args) /* Parse the command line and store the arguments in Args. Return true if ok, ** false on error. */ { char* End; /* Clear the collection */ CollDeleteAll (Args); /* Parse the command line */ while (1) { /* Break out on end of line */ if (*CmdLine == '\0') { break; } /* Search for start of next command */ if (IsSpace (*CmdLine)) { ++CmdLine; continue; } /* Allow double quotes to terminate a command */ if (*CmdLine == '\"' || *CmdLine == '\'') { char Term = *CmdLine++; End = CmdLine; while (*End != Term) { if (*End == '\0') { PrintLine ("Unterminated argument"); return 0; } ++End; } *End++ = '\0'; } else { End = CmdLine; while (!IsSpace (*End)) { if (*End == '\0') { PrintLine ("Unterminated argument"); return 0; } ++End; } *End++ = '\0'; } CollAppend (Args, CmdLine); CmdLine = End; } /* Ok */ return 1; } int main (int argc, char* argv[]) /* Main program */ { char Input[256]; Collection Args = STATIC_COLLECTION_INITIALIZER; /* Initialize the command line */ InitCmdLine (&argc, &argv, "dbgsh"); /* If we have commands on the command line, execute them */ if (ArgCount > 1) { unsigned I; for (I = 1; I < ArgCount; ++I) { CollAppend (&Args, ArgVec[I]); } /* Search for the command, check number of args, then execute it */ ExecCmd (&Args, MainCmds, sizeof (MainCmds) / sizeof (MainCmds[0])); } /* Loop until program end */ while (!Terminate) { /* Output a prompt, then read the input */ Print ("dbgsh> "); fflush (stdout); if (fgets (Input, sizeof (Input), stdin) == 0) { PrintLine ("(EOF)"); break; } /* Parse the command line */ if (Parse (Input, &Args) == 0 || CollCount (&Args) == 0) { continue; } /* Search for the command, check number of args, then execute it */ ExecCmd (&Args, MainCmds, sizeof (MainCmds) / sizeof (MainCmds[0])); } /* Free arguments */ DoneCollection (&Args); return 0; } �����������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/grc65.vcxproj�������������������������������������������������������������������������0000664�0000000�0000000�00000010151�13473601511�0015335�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> <ProjectConfiguration Include="Release|Win32"> <Configuration>Release</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> </ItemGroup> <PropertyGroup Label="Globals"> <ProjectGuid>{E0FD0AB3-3BEE-496F-8108-A8E0F8933F39}</ProjectGuid> <Keyword>Win32Proj</Keyword> <RootNamespace>grc65</RootNamespace> <WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <UseDebugLibraries>true</UseDebugLibraries> <PlatformToolset>v141</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <UseDebugLibraries>false</UseDebugLibraries> <WholeProgramOptimization>true</WholeProgramOptimization> <PlatformToolset>v141</PlatformToolset> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <PropertyGroup Label="UserMacros" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <LinkIncremental>true</LinkIncremental> <OutDir>$(SolutionDir)..\bin\</OutDir> <IntDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</IntDir> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <OutDir>$(SolutionDir)..\bin\</OutDir> <IntDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</IntDir> </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ClCompile> <PrecompiledHeader> </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> <Link> <SubSystem>Console</SubSystem> <GenerateDebugInformation>true</GenerateDebugInformation> <AdditionalDependencies>$(IntDir)..\..\common\$(Configuration)\common.lib</AdditionalDependencies> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ClCompile> <WarningLevel>Level3</WarningLevel> <PrecompiledHeader> </PrecompiledHeader> <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> <Link> <SubSystem>Console</SubSystem> <GenerateDebugInformation>false</GenerateDebugInformation> <AdditionalDependencies>$(IntDir)..\..\common\$(Configuration)\common.lib</AdditionalDependencies> </Link> </ItemDefinitionGroup> <ItemGroup> <ClCompile Include="grc65\main.c" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> </Project>�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/grc65/��������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0013722�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/grc65/main.c��������������������������������������������������������������������������0000664�0000000�0000000�00000067322�13473601511�0015024�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* GEOS resource compiler by Maciej 'YTM/Elysium' Witkowiak see GEOSLib documentation for license info */ /* - make it work, then do it better - more or less comments? it was hard to code, should be even harder to understand =D - add loadable icons feature (binary - 63 bytes) */ /* - err, maybe free allocated memory, huh? (who cares, it's just a little prog...) */ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <errno.h> #include <time.h> /* common stuff */ #include "abend.h" #include "cmdline.h" #include "fname.h" #include "chartype.h" #include "target.h" #include "version.h" #include "xmalloc.h" /* I hope that no one will be able to create a .grc bigger than this... */ #define BLOODY_BIG_BUFFER 65000 struct menuitem { char *name; char *type; char *target; struct menuitem *next; }; struct menu { char *name; int top, left; int bot, right; char *type; struct menuitem *item; }; struct appheader { int year, month, day, hour, min; int mode; int dostype; int geostype; int structure; char *dosname; char *classname; char *version; char *author; char *info; char *icon; }; const char *mainToken[] = {"MENU", "HEADER", "ICON", "DIALOG", "MEMORY", ""}; const char *toggle[] = {"off", "no", "0", "on", "yes", "1", ""}; const char *hdrFTypes[] = {"APPLICATION", "AUTO_EXEC", "DESK_ACC", "ASSEMBLY", "DISK_DEVICE", "PRINTER", "SYSTEM", ""}; const char *hdrFields[] = {"author", "info", "date", "dostype", "mode", "structure", "icon", ""}; const char *hdrDOSTp[] = {"seq", "SEQ", "prg", "PRG", "usr", "USR", ""}; const char *hdrStructTp[] = {"seq", "SEQ", "vlir", "VLIR", ""}; const char *hdrModes[] = {"any", "40only", "80only", "c64only", ""}; const char *memFields[] = {"stacksize", "overlaysize", "overlaynums", "backbuffer", ""}; const int BSWTab[] = {0, 0x005, 0x007, 0x00b, 0x011, 0x017, 0x01d, 0x023, 0x025, 0x029, 0x02d, 0x033, 0x039, 0x03c, 0x041, 0x043, 0x04a, 0x04f, 0x052, 0x056, 0x05a, 0x05f, 0x063, 0x068, 0x06d, 0x072, 0x077, 0x079, 0x07c, 0x080, 0x084, 0x088, 0x08e, 0x094, 0x09a, 0x09f, 0x0a4, 0x0a9, 0x0ad, 0x0b1, 0x0b6, 0x0bc, 0x0be, 0x0c2, 0x0c8, 0x0cc, 0x0d4, 0x0da, 0x0e0, 0x0e5, 0x0eb, 0x0f0, 0x0f5, 0x0f9, 0x0fe, 0x104, 0x10c, 0x112, 0x118, 0x11e, 0x121, 0x129, 0x12c, 0x132, 0x13a, 0x13e, 0x143, 0x148, 0x14d, 0x152, 0x157, 0x15a, 0x15f, 0x164, 0x166, 0x168, 0x16d, 0x16f, 0x177, 0x17c, 0x182, 0x187, 0x18c, 0x18f, 0x193, 0x196, 0x19b, 0x1a1, 0x1a9, 0x1af, 0x1b4, 0x1ba, 0x1be, 0x1c0, 0x1c4, 0x1ca, 0x1d2, 0x1dd}; const unsigned char icon1[] = {255, 255, 255, 128, 0, 1, 128, 0, 1, 128, 0, 1, 128, 0, 1, 128, 0, 1, 128, 0, 1, 128, 0, 1, 128, 0, 1, 128, 0, 1, 128, 0, 1, 128, 0, 1, 128, 0, 1, 128, 0, 1, 128, 0, 1, 128, 0, 1, 128, 0, 1, 128, 0, 1, 128, 0, 1, 128, 0, 1, 255, 255, 255}; const char *outputCName = NULL; const char *outputSName = NULL; FILE *outputCFile, *outputSFile; int CFnum = 0, SFnum = 0; int apple = 0; char outputCMode[2] = "w"; char outputSMode[2] = "w"; static void Usage (void) { printf ( "Usage: %s [options] file\n" "Short options:\n" " -V\t\t\tPrint the version number\n" " -h\t\t\tHelp (this text)\n" " -o name\t\tName the C output file\n" " -s name\t\tName the asm output file\n" " -t sys\t\tSet the target system\n" "\n" "Long options:\n" " --help\t\tHelp (this text)\n" " --target sys\t\tSet the target system\n" " --version\t\tPrint the version number\n", ProgName); } static void OptHelp (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Print usage information and exit */ { Usage (); exit (EXIT_SUCCESS); } static void OptTarget (const char* Opt attribute ((unused)), const char* Arg) /* Set the target system */ { switch (FindTarget (Arg)) { case TGT_GEOS_CBM: apple = 0; break; case TGT_GEOS_APPLE: apple = 1; break; case TGT_UNKNOWN: AbEnd ("Unknown target system '%s'", Arg); break; default: /* Target is known but unsupported */ AbEnd ("Unsupported target system '%s'", Arg); break; } } static void OptVersion (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Print the program version */ { fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ()); exit(EXIT_SUCCESS); } static void printCHeader (void) { fprintf (outputCFile, "//\n" "//\tThis file was generated by the GEOS Resource Compiler\n" "//\n" "//\tDO NOT EDIT! Any changes will be lost!\n" "//\n" "//\tEdit proper resource file instead.\n" "//\n\n"); } static void printSHeader (void) { fprintf (outputSFile, ";\n" ";\tThis file was generated by the GEOS Resource Compiler\n" ";\n" ";\tDO NOT EDIT! Any changes will be lost!\n" ";\n" ";\tEdit proper resource file instead.\n" ";\n\n"); } static void openCFile (void) { if ((outputCFile = fopen (outputCName,outputCMode)) == 0) { AbEnd ("Can't open file %s for writing: %s", outputCName, strerror (errno)); } if (CFnum == 0) { outputCMode[0] = 'a'; printCHeader (); CFnum++; } } static void openSFile (void) { if ((outputSFile = fopen (outputSName, outputSMode)) == 0) { AbEnd ("Can't open file %s for writing: %s", outputSName, strerror (errno)); } if (SFnum == 0) { outputSMode[0] = 'a'; printSHeader (); SFnum++; } } static int findToken (const char * const *tokenTbl, const char *token) { /* takes as input table of tokens and token, returns position in table or -1 if not found */ int i; for (i = 0; tokenTbl[i][0]; i++) { if (strcmp (tokenTbl[i], token) == 0) { return i; } } return -1; } static char *nextPhrase (void) { return strtok (NULL, "\""); } static char *nextWord (void) { return strtok (NULL, " "); } static void setLen (char *name, unsigned len) { if (strlen (name) > len) { name[len] = '\0'; } } static void fillOut (char *name, int len, char *filler) { int a; setLen (name, len); fprintf (outputSFile, "\t.byte \"%s\"\n", name); a = strlen (name); if (a < len) { fprintf (outputSFile, "\t.res (%i - %i), %s\n", len, a, filler); } } static char *bintos (unsigned char a, char out[7]) { int i=0; for (; i < 8; i++) { out[7 - i] = ((a & 1) == 0) ? '0' : '1'; a = a >> 1; } out[i] = '\0'; return out; } static int getNameSize (const char *word) { /* count length of a word using BSW 9 font table */ int a = 0, i = 0; while (word[i] != '\0') { a += (BSWTab[word[i] - 31] - BSWTab[word[i] - 32]); i++; } return a; } static void DoMenu (void) { int a, size, tmpsize, item = 0; char *token; char namebuff[255] = ""; struct menu myMenu; struct menuitem *curItem, *newItem; openCFile (); myMenu.name = nextWord (); myMenu.left = atoi (nextWord ()); myMenu.top = atoi (nextWord ()); myMenu.type = nextWord (); if (strcmp (nextWord (), "{") != 0) { AbEnd ("Menu '%s' description has no opening bracket!", myMenu.name); } curItem = xmalloc (sizeof(struct menuitem)); myMenu.item = curItem; for (;;) { token = nextWord (); if (strcmp (token, "}") == 0) break; if (token[strlen (token) - 1] != '"') { strcpy (namebuff, token); do { token = nextWord (); strcat (namebuff, " "); strcat (namebuff, token); } while (token[strlen (token) - 1] != '"'); token = xmalloc (strlen (namebuff)); strcpy (token, namebuff); } curItem->name = token; curItem->type = nextWord (); curItem->target = nextWord (); newItem = xmalloc (sizeof(struct menuitem)); curItem->next = newItem; curItem = newItem; item++; } if (item == 0) AbEnd ("Menu '%s' has 0 items!", myMenu.name); if (item > 31) AbEnd ("Menu '%s' has too many items!", myMenu.name); curItem->next = NULL; /* count menu sizes */ size = 0; curItem = myMenu.item; if (strstr (myMenu.type, "HORIZONTAL") != NULL) { /* menu is HORIZONTAL, ysize=15, sum xsize of all items +~8?*/ myMenu.bot = myMenu.top + 15; for (a = 0; a != item; a++) { size += getNameSize (curItem->name); curItem = curItem->next; } } else { /* menu is VERTICAL, ysize=item*15, count largest xsize of all items +~8? */ myMenu.bot = myMenu.top + (14 * item); for (a = 0; a != item; a++) { tmpsize = getNameSize (curItem->name); size = (size > tmpsize) ? size : tmpsize; curItem = curItem->next; } } myMenu.right = myMenu.left + size - 1; curItem = myMenu.item; for (a = 0; a != item; a++) { /* print prototype only if MENU_ACTION or DYN_SUB_MENU are present in type */ if ((strstr (curItem->type, "MENU_ACTION") != NULL) || (strstr (curItem->type, "DYN_SUB_MENU") != NULL)) { fprintf (outputCFile, "void %s (void);\n", curItem->target); } curItem=curItem->next; } fprintf (outputCFile, "\n" "const void %s = {\n" "\t(char)%i, (char)%i,\n" "\t(int)%i, (int)%i,\n" "\t(char)(%i | %s),\n", myMenu.name, myMenu.top, myMenu.bot, myMenu.left, myMenu.right, item, myMenu.type); curItem = myMenu.item; for (a = 0; a != item; a++) { fprintf (outputCFile, "\t%s, (char)%s, (int)", curItem->name, curItem->type); if ((strstr (curItem->type, "SUB_MENU") != NULL) && (strstr (curItem->type, "DYN_SUB_MENU") == NULL)) { fprintf (outputCFile, "&"); } fprintf (outputCFile, "%s,\n", curItem->target); curItem = curItem->next; } fprintf (outputCFile, "};\n\n"); if (fclose (outputCFile) != 0) { AbEnd ("Error closing %s: %s", outputCName, strerror (errno)); } } static void DoHeader (void) { time_t t; struct tm *my_tm; struct appheader myHead; char *token; char i1[9], i2[9], i3[9]; int i; openSFile (); token = nextWord (); i = findToken (hdrFTypes, token); if (apple == 1) { switch (i) { case 0: myHead.geostype = 0x82; break; default: AbEnd ("Filetype '%s' is not supported yet", token); } } else { switch (i) { case 0: myHead.geostype = 6; break; case 1: myHead.geostype = 14; break; default: AbEnd ("Filetype '%s' is not supported yet", token); } } myHead.dosname = nextPhrase (); nextPhrase (); myHead.classname = nextPhrase (); nextPhrase (); myHead.version = nextPhrase (); /* put default values into myHead here */ myHead.author = "cc65"; myHead.info = "Program compiled with cc65 and GEOSLib."; myHead.dostype = 128; if (apple == 0) myHead.dostype += 3; myHead.structure = 0; myHead.mode = 0; myHead.icon = NULL; t = time (NULL); my_tm = localtime (&t); myHead.year = my_tm->tm_year % 100; myHead.month = my_tm->tm_mon + 1; myHead.day = my_tm->tm_mday; myHead.hour = my_tm->tm_hour; myHead.min = my_tm->tm_min; if (strcmp (nextWord (), "{") != 0) { AbEnd ("Header '%s' has no opening bracket!", myHead.dosname); } for (;;) { token = nextWord (); if (strcmp (token, "}") == 0) break; switch (findToken (hdrFields, token)) { case -1: AbEnd ("Unknown field '%s' in header '%s'", token, myHead.dosname); break; case 0: /* author */ myHead.author = nextPhrase (); break; case 1: /* info */ myHead.info = nextPhrase (); break; case 2: /* date */ myHead.year = atoi (nextWord ()); myHead.month = atoi (nextWord ()); myHead.day = atoi (nextWord ()); myHead.hour = atoi (nextWord ()); myHead.min = atoi (nextWord ()); break; case 3: /* dostype */ switch (i = findToken (hdrDOSTp, nextWord ())) { case -1: AbEnd ("Unknown dostype in header '%s'", myHead.dosname); break; default: if (apple == 0) myHead.dostype = i / 2 + 128 + 1; break; } break; case 4: /* mode */ switch (findToken (hdrModes, nextWord ())) { case -1: AbEnd ("Unknown mode in header '%s'", myHead.dosname); case 0: if (apple == 0) myHead.mode = 0x40; break; case 1: if (apple == 0) myHead.mode = 0x00; break; case 2: if (apple == 0) myHead.mode = 0xc0; break; case 3: if (apple == 0) myHead.mode = 0x80; break; } break; case 5: /* structure */ switch (findToken (hdrStructTp, nextWord ())) { case -1: AbEnd ("unknown structure type in header '%s'", myHead.dosname); case 0: case 1: myHead.structure = 0; break; case 2: case 3: myHead.structure = 1; break; } break; case 6: /* icon */ myHead.icon = nextPhrase (); break; } } /* OK, all information is gathered, do flushout */ fprintf (outputSFile, "\t\t.segment \"DIRENTRY\"\n\n"); if (apple == 1) { if (myHead.structure == 0) { fprintf (outputSFile, "\t.import __VLIR0_START__, __VLIR0_LAST__, __BSS_SIZE__\n\n"); } fprintf (outputSFile, "\t.byte %i << 4 | %u\n", myHead.structure + 2, (unsigned)strlen (myHead.dosname)); fillOut (myHead.dosname, 15, "0"); fprintf (outputSFile, "\t.byte $%02x\n" "\t.word 0\n" "\t.word 0\n" "\t.word %s\n" "\t.byte 0\n" "\t.word %i << 9 | %i << 5 | %i, %i << 8 | %i\n" "\t.byte 0\n" "\t.byte 0\n" "\t.byte 0\n" "\t.word 0\n" "\t.word %i << 9 | %i << 5 | %i, %i << 8 | %i\n" "\t.word 0\n\n", myHead.geostype, myHead.structure == 0 ? "__VLIR0_LAST__ - __VLIR0_START__ - __BSS_SIZE__" : "0", myHead.year, myHead.month, myHead.day, myHead.hour, myHead.min, myHead.year, myHead.month, myHead.day, myHead.hour, myHead.min); } else { fprintf (outputSFile, "\t.byte %i\n" "\t.word 0\n", myHead.dostype); fillOut (myHead.dosname, 16, "$a0"); fprintf (outputSFile, "\t.word 0\n" "\t.byte %i\n" "\t.byte %i\n" "\t.byte %i, %i, %i, %i, %i\n\n" "\t.word 0\n" "\t.byte \"PRG formatted GEOS file V1.0\"\n\n", myHead.structure, myHead.geostype, myHead.year, myHead.month, myHead.day, myHead.hour, myHead.min); } fprintf (outputSFile, "\t\t.segment \"FILEINFO\"\n\n" "\t.import __VLIR0_START__, __STARTUP_RUN__\n\n" "\t.byte 3, 21, 63 | $80\n"); if (myHead.icon != NULL) { fprintf (outputSFile, "\t.incbin \"%s\", 0, 63\n", myHead.icon); } else { for (i = 0; i != 63; i = i + 3) { fprintf (outputSFile, "\t.byte %%%s, %%%s, %%%s\n", bintos (icon1[i], i1), bintos (icon1[i+1], i2), bintos (icon1[i+2], i3)); } } fprintf (outputSFile, "\t.byte %i, %i, %i\n" "\t.word __VLIR0_START__, __VLIR0_START__ - 1, __STARTUP_RUN__\n\n", myHead.dostype, myHead.geostype, myHead.structure); fillOut (myHead.classname, 12, "$20"); fillOut (myHead.version, 4, "0"); fprintf (outputSFile, "\t.byte 0, 0, 0\n" "\t.byte %i\n\n", myHead.mode); setLen (myHead.author, 62); fprintf (outputSFile, "\t.byte \"%s\"\n" "\t.byte 0\n" "\t.res (63 - %i)\n\n", myHead.author, (int)(strlen (myHead.author) + 1)); setLen (myHead.info, 95); fprintf (outputSFile, "\t.byte \"%s\"\n" "\t.byte 0\n\n", myHead.info); if (fclose (outputSFile) != 0) { AbEnd ("Error closing %s: %s", outputSName, strerror (errno)); } } static void DoMemory (void) { char *token; int stacksize, overlaysize; int overlaytable[127]; int number, lastnumber; int backbuffer; openSFile (); stacksize = -1; overlaysize = -1; memset (overlaytable, 0, sizeof (overlaytable)); lastnumber = -1; backbuffer = -1; if (strcmp (nextWord (), "{") != 0) { AbEnd ("MEMORY description has no opening bracket!"); } token = NULL; for (;;) { if (token == NULL) token = nextWord (); if (strcmp (token, "}") == 0) break; switch (findToken (memFields, token)) { case -1: AbEnd ("Unknown field '%s' in MEMORY description", token); break; case 0: /* stacksize */ stacksize = strtol (nextWord (), NULL, 0); token = NULL; break; case 1: /* overlaysize */ overlaysize = strtol (nextWord (), NULL, 0); token = NULL; break; case 2: /* overlaynums */ do { token = nextWord (); if (IsDigit (token[0]) == 0) break; number = atoi (token); if (number < 0 || number > 126) { AbEnd ("Overlay number %i is out of range 0-126", number); } if (overlaytable[number] == 1) { AbEnd ("Overlay number %i is defined twice", number); } overlaytable[number] = 1; if (number > lastnumber) lastnumber = number; } while (IsDigit (token[0]) != 0); if (lastnumber == -1) { AbEnd ("There must be at least one overlay number"); } /* always include number 0 */ overlaytable[0] = 1; break; case 3: /* backbuffer */ switch (findToken (toggle, nextWord ())) { case -1: AbEnd ("Unknown value for 'backbuffer'"); break; case 0: case 1: case 2: backbuffer = 0; break; default: backbuffer = 1; break; } token = NULL; break; } } /* OK, all information is gathered, do flushout */ if (lastnumber != -1) { fprintf (outputSFile, "\t\t.segment \"RECORDS\"\n\n"); if (apple == 1) { for (number = 0; number <= lastnumber; number++) { fprintf (outputSFile, "\t.byte %s\n", overlaytable[number] == 1 ? "$00" : "$FF"); } fprintf (outputSFile, "\n"); for (number = 0; number <= lastnumber; number++) { if (overlaytable[number] == 1) { fprintf (outputSFile, "\t\t.segment \"VLIRIDX%i\"\n\n" "\t.import __VLIR%i_START__, __VLIR%i_LAST__%s\n\n" "\t.res 255\n" "\t.byte .lobyte (__VLIR%i_LAST__ - __VLIR%i_START__%s)\n" "\t.res 255\n" "\t.byte .hibyte (__VLIR%i_LAST__ - __VLIR%i_START__%s)\n\n", number, number, number, number == 0 ? ", __BSS_SIZE__" : "", number, number, number == 0 ? " - __BSS_SIZE__" : "", number, number, number == 0 ? " - __BSS_SIZE__" : ""); } } } else { for (number = 0; number <= lastnumber; number++) { if (overlaytable[number] == 1) { fprintf (outputSFile, "\t.import __VLIR%i_START__, __VLIR%i_LAST__%s\n", number, number, number == 0 ? ", __BSS_SIZE__" : ""); } } fprintf (outputSFile, "\n"); for (number = 0; number <= lastnumber; number++) { if (overlaytable[number] == 1) { fprintf (outputSFile, "\t.byte .lobyte ((__VLIR%i_LAST__ - __VLIR%i_START__%s - 1) / 254) + 1\n" "\t.byte .lobyte ((__VLIR%i_LAST__ - __VLIR%i_START__%s - 1) .MOD 254) + 2\n", number, number, number == 0 ? " - __BSS_SIZE__" : "", number, number, number == 0 ? " - __BSS_SIZE__" : ""); } else { fprintf (outputSFile, "\t.byte $00\n" "\t.byte $FF\n"); } } fprintf (outputSFile, "\n"); } openCFile (); fprintf (outputCFile, "extern void _OVERLAYADDR__[];\n" "extern void _OVERLAYSIZE__[];\n\n" "#define OVERLAY_ADDR (char*) _OVERLAYADDR__\n" "#define OVERLAY_SIZE (unsigned)_OVERLAYSIZE__\n\n"); if (fclose (outputCFile) != 0) { AbEnd ("Error closing %s: %s", outputCName, strerror (errno)); } } if (stacksize != -1) { fprintf (outputSFile, "\t.export __STACKSIZE__ : absolute = $%04x\n\n", stacksize); } if (overlaysize != -1) { fprintf (outputSFile, "\t.export __OVERLAYSIZE__ : absolute = $%04x\n\n", overlaysize); } if (backbuffer != -1) { fprintf (outputSFile, "\t.export __BACKBUFSIZE__ : absolute = $%04x\n\n", backbuffer ? 0x2000 : 0x0000); } if (fclose (outputSFile) != 0) { AbEnd ("Error closing %s: %s", outputSName, strerror (errno)); } } static char *filterInput (FILE *F, char *tbl) { /* loads file into buffer filtering it out */ int a, prevchar = -1, i = 0, bracket = 0, quote = 1; for (;;) { a = getc(F); if ((a == '\n') || (a == '\015')) a = ' '; if (a == ',' && quote) a = ' '; if (a == '\042') quote =! quote; if (quote) { if ((a == '{') || (a == '(')) bracket++; if ((a == '}') || (a == ')')) bracket--; } if (a == EOF) { tbl[i] = '\0'; tbl = xrealloc (tbl, i + 1); break; } if (IsSpace (a)) { if ((prevchar != ' ') && (prevchar != -1)) { tbl[i++] = ' '; prevchar = ' '; } } else { if (a == ';' && quote) { do { a = getc (F); } while (a != '\n'); fseek (F, -1, SEEK_CUR); } else { tbl[i++] = a; prevchar = a; } } } if (bracket != 0) AbEnd ("There are unclosed brackets!"); return tbl; } static void processFile (const char *filename) { FILE *F; char *str; char *token; int head = 0; /* number of processed HEADER sections */ int memory = 0; /* number of processed MEMORY sections */ if ((F = fopen (filename, "r")) == 0) { AbEnd ("Can't open file %s for reading: %s", filename, strerror (errno)); } str = filterInput (F, xmalloc (BLOODY_BIG_BUFFER)); token = strtok (str, " "); do { if (str != NULL) { switch (findToken (mainToken, token)) { case 0: DoMenu (); break; case 1: if (++head != 1) { AbEnd ("More than one HEADER section, aborting"); } else { DoHeader (); } break; case 2: break; /* icon not implemented yet */ case 3: break; /* dialog not implemented yet */ case 4: if (++memory != 1) { AbEnd ("More than one MEMORY section, aborting"); } else { DoMemory (); } break; default: AbEnd ("Unknown section '%s'", token); break; } } token = nextWord (); } while (token != NULL); } int main (int argc, char *argv[]) { /* Program long options */ static const LongOpt OptTab[] = { { "--help", 0, OptHelp}, { "--target", 1, OptTarget}, { "--version", 0, OptVersion}, }; unsigned ffile = 0; unsigned I; /* Initialize the cmdline module */ InitCmdLine (&argc, &argv, "grc65"); /* Check the parameters */ I = 1; while (I < ArgCount) { /* Get the argument */ const char* Arg = ArgVec [I]; /* Check for an option */ if (Arg[0] == '-') { switch (Arg[1]) { case '-': LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0])); break; case 'o': outputCName = GetArg (&I, 2); break; case 's': outputSName = GetArg (&I, 2); break; case 't': OptTarget (Arg, GetArg (&I, 2)); break; case 'h': case '?': OptHelp (Arg, 0); break; case 'V': OptVersion (Arg, 0); break; default: UnknownOption (Arg); } } else { ffile++; if (outputCName == NULL) outputCName = MakeFilename (Arg, ".h"); if (outputSName == NULL) outputSName = MakeFilename (Arg, ".s"); processFile (Arg); } /* Next argument */ ++I; } if (ffile == 0) AbEnd ("No input file"); return EXIT_SUCCESS; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65.vcxproj��������������������������������������������������������������������������0000664�0000000�0000000�00000015275�13473601511�0015175�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> <ProjectConfiguration Include="Release|Win32"> <Configuration>Release</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> </ItemGroup> <PropertyGroup Label="Globals"> <ProjectGuid>{26C749A0-814C-47A2-9D36-AE92AE932FE4}</ProjectGuid> <Keyword>Win32Proj</Keyword> <RootNamespace>ld65</RootNamespace> <WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <UseDebugLibraries>true</UseDebugLibraries> <PlatformToolset>v141</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <UseDebugLibraries>false</UseDebugLibraries> <WholeProgramOptimization>true</WholeProgramOptimization> <PlatformToolset>v141</PlatformToolset> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <PropertyGroup Label="UserMacros" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <LinkIncremental>true</LinkIncremental> <OutDir>$(SolutionDir)..\bin\</OutDir> <IntDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</IntDir> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <OutDir>$(SolutionDir)..\bin\</OutDir> <IntDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</IntDir> </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ClCompile> <PrecompiledHeader> </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> <Link> <SubSystem>Console</SubSystem> <GenerateDebugInformation>true</GenerateDebugInformation> <AdditionalDependencies>$(IntDir)..\..\common\$(Configuration)\common.lib</AdditionalDependencies> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ClCompile> <WarningLevel>Level3</WarningLevel> <PrecompiledHeader> </PrecompiledHeader> <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> <Link> <SubSystem>Console</SubSystem> <GenerateDebugInformation>false</GenerateDebugInformation> <AdditionalDependencies>$(IntDir)..\..\common\$(Configuration)\common.lib</AdditionalDependencies> </Link> </ItemDefinitionGroup> <ItemGroup> <ClInclude Include="ld65\asserts.h" /> <ClInclude Include="ld65\bin.h" /> <ClInclude Include="ld65\binfmt.h" /> <ClInclude Include="ld65\cfgexpr.h" /> <ClInclude Include="ld65\condes.h" /> <ClInclude Include="ld65\config.h" /> <ClInclude Include="ld65\dbgfile.h" /> <ClInclude Include="ld65\dbgsyms.h" /> <ClInclude Include="ld65\error.h" /> <ClInclude Include="ld65\exports.h" /> <ClInclude Include="ld65\expr.h" /> <ClInclude Include="ld65\extsyms.h" /> <ClInclude Include="ld65\fileinfo.h" /> <ClInclude Include="ld65\fileio.h" /> <ClInclude Include="ld65\filepath.h" /> <ClInclude Include="ld65\fragment.h" /> <ClInclude Include="ld65\global.h" /> <ClInclude Include="ld65\library.h" /> <ClInclude Include="ld65\lineinfo.h" /> <ClInclude Include="ld65\mapfile.h" /> <ClInclude Include="ld65\memarea.h" /> <ClInclude Include="ld65\o65.h" /> <ClInclude Include="ld65\objdata.h" /> <ClInclude Include="ld65\objfile.h" /> <ClInclude Include="ld65\scanner.h" /> <ClInclude Include="ld65\scopes.h" /> <ClInclude Include="ld65\segments.h" /> <ClInclude Include="ld65\span.h" /> <ClInclude Include="ld65\spool.h" /> <ClInclude Include="ld65\tpool.h" /> <ClInclude Include="ld65\xex.h" /> </ItemGroup> <ItemGroup> <ClCompile Include="ld65\asserts.c" /> <ClCompile Include="ld65\bin.c" /> <ClCompile Include="ld65\binfmt.c" /> <ClCompile Include="ld65\cfgexpr.c" /> <ClCompile Include="ld65\condes.c" /> <ClCompile Include="ld65\config.c" /> <ClCompile Include="ld65\dbgfile.c" /> <ClCompile Include="ld65\dbgsyms.c" /> <ClCompile Include="ld65\error.c" /> <ClCompile Include="ld65\exports.c" /> <ClCompile Include="ld65\expr.c" /> <ClCompile Include="ld65\extsyms.c" /> <ClCompile Include="ld65\fileinfo.c" /> <ClCompile Include="ld65\fileio.c" /> <ClCompile Include="ld65\filepath.c" /> <ClCompile Include="ld65\fragment.c" /> <ClCompile Include="ld65\global.c" /> <ClCompile Include="ld65\library.c" /> <ClCompile Include="ld65\lineinfo.c" /> <ClCompile Include="ld65\main.c" /> <ClCompile Include="ld65\mapfile.c" /> <ClCompile Include="ld65\memarea.c" /> <ClCompile Include="ld65\o65.c" /> <ClCompile Include="ld65\objdata.c" /> <ClCompile Include="ld65\objfile.c" /> <ClCompile Include="ld65\scanner.c" /> <ClCompile Include="ld65\scopes.c" /> <ClCompile Include="ld65\segments.c" /> <ClCompile Include="ld65\span.c" /> <ClCompile Include="ld65\spool.c" /> <ClCompile Include="ld65\tpool.c" /> <ClCompile Include="ld65\xex.c" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> </Project> �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/���������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0013546�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/asserts.c������������������������������������������������������������������������0000664�0000000�0000000�00000013766�13473601511�0015413�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* asserts.c */ /* */ /* Assertions for the ld65 linker */ /* */ /* */ /* */ /* (C) 2003-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "assertion.h" #include "coll.h" #include "xmalloc.h" /* ld65 */ #include "asserts.h" #include "error.h" #include "expr.h" #include "fileio.h" #include "lineinfo.h" #include "objdata.h" #include "spool.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Assertion struct decl */ struct Assertion { Collection LineInfos; /* File position of assertion */ ExprNode* Expr; /* Expression to evaluate */ AssertAction Action; /* What to do */ unsigned Msg; /* Message to print */ ObjData* Obj; /* Object file containing the assertion */ }; /* List with all assertions */ static Collection Assertions = STATIC_COLLECTION_INITIALIZER; /*****************************************************************************/ /* Code */ /*****************************************************************************/ Assertion* ReadAssertion (FILE* F, struct ObjData* O) /* Read an assertion from the given file */ { /* Allocate memory */ Assertion* A = xmalloc (sizeof (Assertion)); /* Read the fields from the file */ A->LineInfos = EmptyCollection; A->Expr = ReadExpr (F, O); A->Action = (AssertAction) ReadVar (F); A->Msg = MakeGlobalStringId (O, ReadVar (F)); ReadLineInfoList (F, O, &A->LineInfos); /* Set remaining fields */ A->Obj = O; /* Add the assertion to the global list */ CollAppend (&Assertions, A); /* Return the new struct */ return A; } void CheckAssertions (void) /* Check all assertions */ { unsigned I; /* Walk over all assertions */ for (I = 0; I < CollCount (&Assertions); ++I) { const LineInfo* LI; const char* Module; unsigned Line; /* Get the assertion */ Assertion* A = CollAtUnchecked (&Assertions, I); /* Ignore assertions that shouldn't be handled at link time */ if (!AssertAtLinkTime (A->Action)) { continue; } /* Retrieve the relevant line info for this assertion */ LI = CollConstAt (&A->LineInfos, 0); /* Get file name and line number from the source */ Module = GetSourceName (LI); Line = GetSourceLine (LI); /* If the expression is not constant, we're not able to handle it */ if (!IsConstExpr (A->Expr)) { Warning ("Cannot evaluate assertion in module '%s', line %u", Module, Line); } else if (GetExprVal (A->Expr) == 0) { /* Assertion failed */ const char* Message = GetString (A->Msg); switch (A->Action) { case ASSERT_ACT_WARN: case ASSERT_ACT_LDWARN: Warning ("%s(%u): %s", Module, Line, Message); break; case ASSERT_ACT_ERROR: case ASSERT_ACT_LDERROR: Error ("%s(%u): %s", Module, Line, Message); break; default: Internal ("Invalid assertion action (%u) in module '%s', " "line %u (file corrupt?)", A->Action, Module, Line); break; } } } } ����������cc65-2.18/src/ld65/asserts.h������������������������������������������������������������������������0000664�0000000�0000000�00000006576�13473601511�0015421�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* asserts.h */ /* */ /* Assertions for the ld65 linker */ /* */ /* */ /* */ /* (C) 2003-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef ASSERTS_H #define ASSERTS_H #include <stdio.h> /* common */ #include "filepos.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Assertion object forward decl */ typedef struct Assertion Assertion; /* ObjData forward decl */ struct ObjData; /*****************************************************************************/ /* Code */ /*****************************************************************************/ Assertion* ReadAssertion (FILE* F, struct ObjData* O); /* Read an assertion from the given file */ void CheckAssertions (void); /* Check all assertions */ /* End of asserts.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/bin.c����������������������������������������������������������������������������0000664�0000000�0000000�00000025640�13473601511�0014471�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* bin.c */ /* */ /* Module to handle the raw binary format */ /* */ /* */ /* */ /* (C) 1999-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> #include <errno.h> /* common */ #include "alignment.h" #include "print.h" #include "xmalloc.h" /* ld65 */ #include "bin.h" #include "config.h" #include "exports.h" #include "expr.h" #include "error.h" #include "global.h" #include "fileio.h" #include "lineinfo.h" #include "memarea.h" #include "segments.h" #include "spool.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ struct BinDesc { unsigned Undef; /* Count of undefined externals */ FILE* F; /* Output file */ const char* Filename; /* Name of output file */ }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ BinDesc* NewBinDesc (void) /* Create a new binary format descriptor */ { /* Allocate memory for a new BinDesc struct */ BinDesc* D = xmalloc (sizeof (BinDesc)); /* Initialize the fields */ D->Undef = 0; D->F = 0; D->Filename = 0; /* Return the created struct */ return D; } void FreeBinDesc (BinDesc* D) /* Free a binary format descriptor */ { xfree (D); } static unsigned BinWriteExpr (ExprNode* E, int Signed, unsigned Size, unsigned long Offs attribute ((unused)), void* Data) /* Called from SegWrite for an expression. Evaluate the expression, check the ** range and write the expression value to the file. */ { /* There's a predefined function to handle constant expressions */ return SegWriteConstExpr (((BinDesc*)Data)->F, E, Signed, Size); } static void PrintBoolVal (const char* Name, int B) /* Print a boolean value for debugging */ { Print (stdout, 2, " %s = %s\n", Name, B? "true" : "false"); } static void PrintNumVal (const char* Name, unsigned long V) /* Print a numerical value for debugging */ { Print (stdout, 2, " %s = 0x%lx\n", Name, V); } static void BinWriteMem (BinDesc* D, MemoryArea* M) /* Write the segments of one memory area to a file */ { unsigned I; /* Get the start address of this memory area */ unsigned long Addr = M->Start; /* Debugging: Check that the file offset is correct */ if (ftell (D->F) != (long)M->FileOffs) { Internal ("Invalid file offset for memory area %s: %ld/%lu", GetString (M->Name), ftell (D->F), M->FileOffs); } /* Walk over all segments in this memory area */ for (I = 0; I < CollCount (&M->SegList); ++I) { int DoWrite; /* Get the segment */ SegDesc* S = CollAtUnchecked (&M->SegList, I); /* Keep the user happy */ Print (stdout, 1, " Writing '%s'\n", GetString (S->Name)); /* Writes do only occur in the load area and not for BSS segments */ DoWrite = (S->Flags & SF_BSS) == 0 && /* No BSS segment */ S->Load == M && /* LOAD segment */ S->Seg->Dumped == 0; /* Not already written */ /* Output debugging stuff */ PrintBoolVal ("bss", S->Flags & SF_BSS); PrintBoolVal ("LoadArea", S->Load == M); PrintBoolVal ("Dumped", S->Seg->Dumped); PrintBoolVal ("DoWrite", DoWrite); PrintNumVal ("Address", Addr); PrintNumVal ("FileOffs", (unsigned long) ftell (D->F)); /* If this is the run memory area, we must apply run alignment. If ** this is not the run memory area but the load memory area (which ** means that both are different), we must apply load alignment. ** Beware: DoWrite may be true even if this is the run memory area, ** because it may be also the load memory area. */ if (S->Run == M) { /* Handle ALIGN and OFFSET/START */ if (S->Flags & SF_ALIGN) { /* Align the address */ unsigned long NewAddr = AlignAddr (Addr, S->RunAlignment); if (DoWrite || (M->Flags & MF_FILL) != 0) { WriteMult (D->F, M->FillVal, NewAddr - Addr); PrintNumVal ("SF_ALIGN", NewAddr - Addr); } Addr = NewAddr; } else if (S->Flags & (SF_OFFSET | SF_START)) { unsigned long NewAddr = S->Addr; if (S->Flags & SF_OFFSET) { /* It's an offset, not a fixed address, make an address */ NewAddr += M->Start; } if (DoWrite || (M->Flags & MF_FILL) != 0) { /* Seek in "overwrite" segments */ if (S->Flags & SF_OVERWRITE) { fseek (D->F, NewAddr - M->Start, SEEK_SET); } else { WriteMult (D->F, M->FillVal, NewAddr-Addr); PrintNumVal ("SF_OFFSET", NewAddr - Addr); } } Addr = NewAddr; } } else if (S->Load == M) { /* Handle ALIGN_LOAD */ if (S->Flags & SF_ALIGN_LOAD) { /* Align the address */ unsigned long NewAddr = AlignAddr (Addr, S->LoadAlignment); if (DoWrite || (M->Flags & MF_FILL) != 0) { WriteMult (D->F, M->FillVal, NewAddr - Addr); PrintNumVal ("SF_ALIGN_LOAD", NewAddr - Addr); } Addr = NewAddr; } } /* Now write the segment to disk if it is not a BSS type segment and ** if the memory area is the load area. */ if (DoWrite) { unsigned long P = ftell (D->F); SegWrite (D->Filename, D->F, S->Seg, BinWriteExpr, D); PrintNumVal ("Wrote", (unsigned long) (ftell (D->F) - P)); } else if (M->Flags & MF_FILL) { WriteMult (D->F, S->Seg->FillVal, S->Seg->Size); PrintNumVal ("Filled", (unsigned long) S->Seg->Size); } /* If this was the load memory area, mark the segment as dumped */ if (S->Load == M) { S->Seg->Dumped = 1; } /* Calculate the new address */ Addr += S->Seg->Size; } /* If a fill was requested, fill the remaining space */ if ((M->Flags & MF_FILL) != 0 && M->FillLevel < M->Size) { unsigned long ToFill = M->Size - M->FillLevel; Print (stdout, 2, " Filling 0x%lx bytes with 0x%02x\n", ToFill, M->FillVal); WriteMult (D->F, M->FillVal, ToFill); M->FillLevel = M->Size; } } static int BinUnresolved (unsigned Name attribute ((unused)), void* D) /* Called if an unresolved symbol is encountered */ { /* Unresolved symbols are an error in binary format. Bump the counter ** and return zero telling the caller that the symbol is indeed ** unresolved. */ ((BinDesc*) D)->Undef++; return 0; } void BinWriteTarget (BinDesc* D, struct File* F) /* Write a binary output file */ { unsigned I; /* Place the filename in the control structure */ D->Filename = GetString (F->Name); /* Check for unresolved symbols. The function BinUnresolved is called ** if we get an unresolved symbol. */ D->Undef = 0; /* Reset the counter */ CheckUnresolvedImports (BinUnresolved, D); if (D->Undef > 0) { /* We had unresolved symbols, cannot create output file */ Error ("%u unresolved external(s) found - cannot create output file", D->Undef); } /* Open the file */ D->F = fopen (D->Filename, "wb"); if (D->F == 0) { Error ("Cannot open '%s': %s", D->Filename, strerror (errno)); } /* Keep the user happy */ Print (stdout, 1, "Opened '%s'...\n", D->Filename); /* Dump all memory areas */ for (I = 0; I < CollCount (&F->MemoryAreas); ++I) { /* Get this entry */ MemoryArea* M = CollAtUnchecked (&F->MemoryAreas, I); Print (stdout, 1, " Dumping '%s'\n", GetString (M->Name)); BinWriteMem (D, M); } /* Close the file */ if (fclose (D->F) != 0) { Error ("Cannot write to '%s': %s", D->Filename, strerror (errno)); } /* Reset the file and filename */ D->F = 0; D->Filename = 0; } ������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/bin.h����������������������������������������������������������������������������0000664�0000000�0000000�00000006541�13473601511�0014475�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* bin.h */ /* */ /* Module to handle the raw binary format */ /* */ /* */ /* */ /* (C) 1999-2001 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef BIN_H #define BIN_H #include "config.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Structure describing the format */ typedef struct BinDesc BinDesc; /*****************************************************************************/ /* Code */ /*****************************************************************************/ BinDesc* NewBinDesc (void); /* Create a new binary format descriptor */ void FreeBinDesc (BinDesc* D); /* Free a binary format descriptor */ void BinWriteTarget (BinDesc* D, File* F); /* Write a binary output file */ /* End of bin.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/binfmt.c�������������������������������������������������������������������������0000664�0000000�0000000�00000007373�13473601511�0015203�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* binfmt.c */ /* */ /* Binary format definitions for the ld65 linker */ /* */ /* */ /* */ /* (C) 1999 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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. */ /* */ /*****************************************************************************/ /* common */ #include "target.h" /* ld65 */ #include "error.h" #include "binfmt.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Default format (depends on target system) */ unsigned char DefaultBinFmt = BINFMT_BINARY; /*****************************************************************************/ /* Code */ /*****************************************************************************/ int RelocatableBinFmt (unsigned Format) /* Return true if this is a relocatable format, return false otherwise */ { int Reloc = 0; /* Resolve the default format */ if (Format == BINFMT_DEFAULT) { Format = DefaultBinFmt; } /* Check the type */ switch (Format) { case BINFMT_BINARY: case BINFMT_ATARIEXE: Reloc = 0; break; case BINFMT_O65: Reloc = 1; break; default: Internal ("Invalid format specifier: %u", Format); } /* Return the flag */ return Reloc; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/binfmt.h�������������������������������������������������������������������������0000664�0000000�0000000�00000006371�13473601511�0015205�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* binfmt.h */ /* */ /* Binary format definitions for the ld65 linker */ /* */ /* */ /* */ /* (C) 1999 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 BINFMT_H #define BINFMT_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Default format (depends on target system) */ extern unsigned char DefaultBinFmt; /*****************************************************************************/ /* Code */ /*****************************************************************************/ int RelocatableBinFmt (unsigned Format); /* Return true if this is a relocatable format, return false otherwise */ /* End of binfmt.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/cfgexpr.c������������������������������������������������������������������������0000664�0000000�0000000�00000016510�13473601511�0015353�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* cfgexpr.c */ /* */ /* Simple expressions for use with in configuration file */ /* */ /* */ /* */ /* (C) 2005-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "addrsize.h" #include "strbuf.h" /* ld65 */ #include "cfgexpr.h" #include "error.h" #include "exports.h" #include "expr.h" #include "lineinfo.h" #include "scanner.h" #include "spool.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ static ExprNode* Factor (void) /* Read and return a factor */ { ExprNode* N = 0; /* Initialize to avoid compiler warnings */ Export* E; unsigned Name; switch (CfgTok) { case CFGTOK_IDENT: /* Get the name as an id */ Name = GetStrBufId (&CfgSVal); /* Check if we know the symbol already */ E = FindExport (Name); if (E != 0 && IsConstExport (E)) { N = LiteralExpr (GetExportVal (E), 0); } else { N = NewExprNode (0, EXPR_SYMBOL); N->V.Imp = InsertImport (GenImport (Name, ADDR_SIZE_ABS)); CollAppend (&N->V.Imp->RefLines, GenLineInfo (&CfgErrorPos)); } /* Skip the symbol name */ CfgNextTok (); break; case CFGTOK_INTCON: /* An integer constant */ N = LiteralExpr (CfgIVal, 0); CfgNextTok (); break; case CFGTOK_PLUS: /* Unary plus */ CfgNextTok (); N = Factor (); break; case CFGTOK_MINUS: /* Unary minus */ CfgNextTok (); N = NewExprNode (0, EXPR_UNARY_MINUS); N->Left = Factor (); break; case CFGTOK_LPAR: /* Left parenthesis */ CfgNextTok (); N = CfgExpr (); CfgConsume (CFGTOK_RPAR, "')' expected"); break; default: CfgError (&CfgErrorPos, "Invalid expression: %d", CfgTok); break; } /* Return the new expression node */ return N; } static ExprNode* Term (void) /* Multiplicative operators: * and / */ { /* Read left hand side */ ExprNode* Root = Factor (); /* Handle multiplicative operators */ while (CfgTok == CFGTOK_MUL || CfgTok == CFGTOK_DIV) { ExprNode* Left; ExprNode* Right; unsigned char Op; /* Remember the token, then skip it */ cfgtok_t Tok = CfgTok; CfgNextTok (); /* Move root to left side, then read right side */ Left = Root; Right = Factor (); /* Handle the operation */ switch (Tok) { case CFGTOK_MUL: Op = EXPR_MUL; break; case CFGTOK_DIV: Op = EXPR_DIV; break; default: Internal ("Unhandled token in Term: %d", Tok); } Root = NewExprNode (0, Op); Root->Left = Left; Root->Right = Right; } /* Return the expression tree we've created */ return Root; } static ExprNode* SimpleExpr (void) /* Additive operators: + and - */ { /* Read left hand side */ ExprNode* Root = Term (); /* Handle additive operators */ while (CfgTok == CFGTOK_PLUS || CfgTok == CFGTOK_MINUS) { ExprNode* Left; ExprNode* Right; unsigned char Op; /* Remember the token, then skip it */ cfgtok_t Tok = CfgTok; CfgNextTok (); /* Move root to left side, then read right side */ Left = Root; Right = Term (); /* Handle the operation */ switch (Tok) { case CFGTOK_PLUS: Op = EXPR_PLUS; break; case CFGTOK_MINUS: Op = EXPR_MINUS; break; default: Internal ("Unhandled token in SimpleExpr: %d", Tok); } Root = NewExprNode (0, Op); Root->Left = Left; Root->Right = Right; } /* Return the expression tree we've created */ return Root; } ExprNode* CfgExpr (void) /* Full expression */ { return SimpleExpr (); } long CfgConstExpr (void) /* Read an integer expression, make sure its constant and return its value */ { long Val; /* Parse the expression */ ExprNode* Expr = CfgExpr (); /* Check that it's const */ if (!IsConstExpr (Expr)) { CfgError (&CfgErrorPos, "Constant expression expected"); } /* Get the value */ Val = GetExprVal (Expr); /* Cleanup E */ FreeExpr (Expr); /* Return the value */ return Val; } long CfgCheckedConstExpr (long Min, long Max) /* Read an expression, make sure it's an int and in range, then return its ** value. */ { /* Get the value */ long Val = CfgConstExpr (); /* Check the range */ if (Val < Min || Val > Max) { CfgError (&CfgErrorPos, "Range error"); } /* Return the value */ return Val; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/cfgexpr.h������������������������������������������������������������������������0000664�0000000�0000000�00000006246�13473601511�0015365�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* cfgexpr.h */ /* */ /* Simple expressions for use with in configuration file */ /* */ /* */ /* */ /* (C) 2005-2010, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef CFGEXPR_H #define CFGEXPR_H /* common */ #include "exprdefs.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ ExprNode* CfgExpr (void); /* Read an integer expression and return its value */ long CfgConstExpr (void); /* Read an integer expression, make sure its constant and return its value */ long CfgCheckedConstExpr (long Min, long Max); /* Read an expression, make sure it's an int and in range, then return its ** value. */ /* End of cfgexpr.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/condes.c�������������������������������������������������������������������������0000664�0000000�0000000�00000030161�13473601511�0015166�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* condes.c */ /* */ /* Module constructor/destructor support */ /* */ /* */ /* */ /* (C) 2000-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* common */ #include "addrsize.h" #include "check.h" #include "coll.h" #include "filepos.h" #include "fragdefs.h" #include "xmalloc.h" /* ld65 */ #include "condes.h" #include "exports.h" #include "fragment.h" #include "segments.h" #include "spool.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Struct describing one condes type */ typedef struct ConDesDesc ConDesDesc; struct ConDesDesc { Collection ExpList; /* List of exported symbols */ unsigned SegName; /* Name of segment the table is in */ unsigned Label; /* Name of table label */ unsigned CountSym; /* Name of symbol for entry count */ unsigned char Order; /* Table order (increasing/decreasing) */ ConDesImport Import; /* Forced import if any */ }; /* Array for all types */ static ConDesDesc ConDes[CD_TYPE_COUNT] = { { STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing, { INVALID_STRING_ID, STATIC_FILEPOS_INITIALIZER, ADDR_SIZE_DEFAULT }, },{ STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing, { INVALID_STRING_ID, STATIC_FILEPOS_INITIALIZER, ADDR_SIZE_DEFAULT }, },{ STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing, { INVALID_STRING_ID, STATIC_FILEPOS_INITIALIZER, ADDR_SIZE_DEFAULT }, },{ STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing, { INVALID_STRING_ID, STATIC_FILEPOS_INITIALIZER, ADDR_SIZE_DEFAULT }, },{ STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing, { INVALID_STRING_ID, STATIC_FILEPOS_INITIALIZER, ADDR_SIZE_DEFAULT }, },{ STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing, { INVALID_STRING_ID, STATIC_FILEPOS_INITIALIZER, ADDR_SIZE_DEFAULT }, },{ STATIC_COLLECTION_INITIALIZER, INVALID_STRING_ID, INVALID_STRING_ID, INVALID_STRING_ID, cdIncreasing, { INVALID_STRING_ID, STATIC_FILEPOS_INITIALIZER, ADDR_SIZE_DEFAULT }, }, }; /*****************************************************************************/ /* Internally used function to create the condes tables */ /*****************************************************************************/ static int ConDesCompare (void* Data, const void* E1, const void* E2) /* Compare function to sort the exports */ { int Cmp; /* Data is actually a pointer to a ConDesDesc from the table, E1 and ** E2 are exports from the collection. Get the condes type and cast ** the void pointers to object pointers. */ ConDesDesc* CD = ((ConDesDesc*) Data); int Type = CD - ConDes; const Export* Exp1 = (const Export*) E1; const Export* Exp2 = (const Export*) E2; /* Get the priorities of the two exports */ unsigned Prio1 = Exp1->ConDes[Type]; unsigned Prio2 = Exp2->ConDes[Type]; /* Compare the priorities for this condes type */ if (Prio1 < Prio2) { Cmp = -1; } else if (Prio1 > Prio2) { Cmp = 1; } else { /* Use the name in this case */ Cmp = SB_Compare (GetStrBuf (Exp1->Name), GetStrBuf (Exp2->Name)); } /* Reverse the result for decreasing order */ if (CD->Order == cdIncreasing) { return Cmp; } else { return -Cmp; } } static void ConDesCreateOne (ConDesDesc* CD) /* Create one table if requested */ { Segment* Seg; /* Segment for table */ Section* Sec; /* Section for table */ unsigned Count; /* Number of exports */ unsigned I; /* Check if this table has a segment and table label defined. If not, ** creation was not requested in the config file - ignore it. */ if (CD->SegName == INVALID_STRING_ID || CD->Label == INVALID_STRING_ID) { return; } /* Check if there is an import for the table label. If not, there is no ** reference to the table and we would just waste memory creating the ** table. */ if (!IsUnresolved (CD->Label)) { return; } /* Sort the collection of exports according to priority */ CollSort (&CD->ExpList, ConDesCompare, CD); /* Get the segment for the table, create it if needed */ Seg = GetSegment (CD->SegName, ADDR_SIZE_ABS, 0); /* Create a new section for the table */ Sec = NewSection (Seg, 1, ADDR_SIZE_ABS); /* Walk over the exports and create a fragment for each one. We will use ** the exported expression without copying it, since it's cheap and there ** is currently no place where it gets changed (hope this will not hunt ** me later...). */ Count = CollCount (&CD->ExpList); for (I = 0; I < Count; ++I) { /* Get the export */ Export* E = CollAt (&CD->ExpList, I); /* Create the fragment */ Fragment* F = NewFragment (FRAG_EXPR, 2, Sec); /* Set the expression pointer */ F->Expr = E->Expr; } /* Define the table start as an export, offset into section is zero ** (the section only contains the table). */ CreateSectionExport (CD->Label, Sec, 0); /* If we have a CountSym name given AND if it is referenced, define it ** with the number of elements in the table. */ if (CD->CountSym) { CreateConstExport (CD->CountSym, Count); } } /*****************************************************************************/ /* Code */ /*****************************************************************************/ void ConDesAddExport (struct Export* E) /* Add the given export to the list of constructors/destructor */ { unsigned Type; /* Insert the export into all tables for which declarations exist */ for (Type = 0; Type < CD_TYPE_COUNT; ++Type) { unsigned Prio = E->ConDes[Type]; if (Prio != CD_PRIO_NONE) { CollAppend (&ConDes[Type].ExpList, E); } } } void ConDesSetSegName (unsigned Type, unsigned SegName) /* Set the segment name where the table should go */ { /* Check the parameters */ PRECONDITION (Type <= CD_TYPE_MAX && SegName != 0); /* Setting the segment name twice is bad */ CHECK (ConDes[Type].SegName == INVALID_STRING_ID); /* Set the name */ ConDes[Type].SegName = SegName; } const ConDesImport* ConDesGetImport (unsigned Type) /* Get the forced import for the given ConDes type. Returns NULL if there is ** no forced import for this type. */ { const ConDesImport* Import; /* Check the parameters */ PRECONDITION (Type <= CD_TYPE_MAX); /* Return the import */ Import = &ConDes[Type].Import; return (Import->Name != INVALID_STRING_ID)? Import : 0; } void ConDesSetImport (unsigned Type, const ConDesImport* Import) /* Set the forced import for the given ConDes type */ { /* Check the parameters */ PRECONDITION (Type <= CD_TYPE_MAX && Import != 0); /* Setting the import twice is bad */ CHECK (ConDes[Type].Import.Name == INVALID_STRING_ID); /* Set the import and its position */ ConDes[Type].Import = *Import; } void ConDesSetLabel (unsigned Type, unsigned Name) /* Set the label for the given ConDes type */ { /* Check the parameters */ PRECONDITION (Type <= CD_TYPE_MAX && Name != 0); /* Setting the label twice is bad */ CHECK (ConDes[Type].Label == INVALID_STRING_ID); /* Set the name */ ConDes[Type].Label = Name; } void ConDesSetCountSym (unsigned Type, unsigned Name) /* Set the name for the given ConDes count symbol */ { /* Check the parameters */ PRECONDITION (Type <= CD_TYPE_MAX && Name != 0); /* Setting the symbol twice is bad */ CHECK (ConDes[Type].CountSym == INVALID_STRING_ID); /* Set the name */ ConDes[Type].CountSym = Name; } void ConDesSetOrder (unsigned Type, ConDesOrder Order) /* Set the sorting oder for the given ConDes table */ { /* Check the parameters */ PRECONDITION (Type <= CD_TYPE_MAX); /* Set the order */ ConDes[Type].Order = Order; } int ConDesHasSegName (unsigned Type) /* Return true if a segment name is already defined for this ConDes type */ { /* Check the parameters */ PRECONDITION (Type <= CD_TYPE_MAX); return (ConDes[Type].SegName != INVALID_STRING_ID); } int ConDesHasLabel (unsigned Type) /* Return true if a label is already defined for this ConDes type */ { /* Check the parameters */ PRECONDITION (Type <= CD_TYPE_MAX); return (ConDes[Type].Label != INVALID_STRING_ID); } void ConDesCreate (void) /* Create the condes tables if requested */ { unsigned Type; /* Walk over the descriptor array and create a table for each entry */ for (Type = 0; Type < CD_TYPE_COUNT; ++Type) { ConDesCreateOne (ConDes + Type); } } void ConDesDump (void) /* Dump ConDes data to stdout for debugging */ { unsigned Type; for (Type = 0; Type < CD_TYPE_COUNT; ++Type) { Collection* ExpList = &ConDes[Type].ExpList; printf ("CONDES(%u): %u symbols\n", Type, CollCount (ExpList)); } } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/condes.h�������������������������������������������������������������������������0000664�0000000�0000000�00000011751�13473601511�0015177�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* condes.h */ /* */ /* Module constructor/destructor support */ /* */ /* */ /* */ /* (C) 2000-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef CONDES_H #define CONDES_H /* common */ #include "filepos.h" /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ struct Export; /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Order of the tables */ typedef enum { cdIncreasing, /* Increasing priority - default */ cdDecreasing /* Decreasing priority */ } ConDesOrder; /* Data for a forced condes import */ typedef struct ConDesImport ConDesImport; struct ConDesImport { unsigned Name; /* Name of the import */ FilePos Pos; /* Position of import in the config file */ unsigned AddrSize; /* Address size of the symbol */ }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void ConDesAddExport (struct Export* E); /* Add the given export to the list of constructors/destructor */ void ConDesSetSegName (unsigned Type, unsigned SegName); /* Set the segment name where the table should go */ const ConDesImport* ConDesGetImport (unsigned Type); /* Get the forced import for the given ConDes type. Returns NULL if there is ** no forced import for this type. */ void ConDesSetImport (unsigned Type, const ConDesImport* Import); /* Set the forced import for the given ConDes type */ void ConDesSetLabel (unsigned Type, unsigned Name); /* Set the label for the given ConDes type */ void ConDesSetCountSym (unsigned Type, unsigned Name); /* Set the name for the given ConDes count symbol */ void ConDesSetOrder (unsigned Type, ConDesOrder Order); /* Set the sorting oder for the given ConDes table */ int ConDesHasSegName (unsigned Type); /* Return true if a segment name is already defined for this ConDes type */ int ConDesHasLabel (unsigned Type); /* Return true if a label is already defined for this ConDes type */ void ConDesCreate (void); /* Create the condes tables if requested */ void ConDesDump (void); /* Dump ConDes data to stdout for debugging */ /* End of condes.h */ #endif �����������������������cc65-2.18/src/ld65/config.c�������������������������������������������������������������������������0000664�0000000�0000000�00000217611�13473601511�0015167�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* config.c */ /* */ /* Target configuration file for the ld65 linker */ /* */ /* */ /* */ /* (c) 1998-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* With contributions from: */ /* */ /* - "David M. Lloyd" <david.lloyd@redhat.com> */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> /* common */ #include "addrsize.h" #include "bitops.h" #include "check.h" #include "print.h" #include "segdefs.h" #include "target.h" #include "xmalloc.h" #include "xsprintf.h" /* ld65 */ #include "alignment.h" #include "bin.h" #include "binfmt.h" #include "cfgexpr.h" #include "condes.h" #include "config.h" #include "error.h" #include "exports.h" #include "expr.h" #include "global.h" #include "memarea.h" #include "o65.h" #include "objdata.h" #include "scanner.h" #include "spool.h" #include "xex.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Remember which sections we had encountered */ static enum { SE_NONE = 0x0000, SE_MEMORY = 0x0001, SE_SEGMENTS = 0x0002, SE_FEATURES = 0x0004, SE_FILES = 0x0008, SE_FORMATS = 0x0010, SE_SYMBOLS = 0x0020 } SectionsEncountered = SE_NONE; /* File list */ static Collection FileList = STATIC_COLLECTION_INITIALIZER; /* Memory list */ static Collection MemoryAreas = STATIC_COLLECTION_INITIALIZER; /* Memory attributes */ #define MA_START 0x0001 #define MA_SIZE 0x0002 #define MA_TYPE 0x0004 #define MA_FILE 0x0008 #define MA_DEFINE 0x0010 #define MA_FILL 0x0020 #define MA_FILLVAL 0x0040 #define MA_BANK 0x0080 /* Segment list */ static Collection SegDescList = STATIC_COLLECTION_INITIALIZER; /* Segment attributes */ #define SA_TYPE 0x0001 #define SA_LOAD 0x0002 #define SA_RUN 0x0004 #define SA_ALIGN 0x0008 #define SA_ALIGN_LOAD 0x0010 #define SA_DEFINE 0x0020 #define SA_OFFSET 0x0040 #define SA_START 0x0080 #define SA_OPTIONAL 0x0100 #define SA_FILLVAL 0x0200 /* Symbol types used in the CfgSymbol structure */ typedef enum { CfgSymExport, /* Not really used in struct CfgSymbol */ CfgSymImport, /* Dito */ CfgSymWeak, /* Like export but weak */ CfgSymO65Export, /* An o65 export */ CfgSymO65Import, /* An o65 import */ } CfgSymType; /* Symbol structure. It is used for o65 imports and exports, but also for ** symbols from the SYMBOLS sections (symbols defined in the config file or ** forced imports). */ typedef struct CfgSymbol CfgSymbol; struct CfgSymbol { CfgSymType Type; /* Type of symbol */ LineInfo* LI; /* Config file position */ unsigned Name; /* Symbol name */ ExprNode* Value; /* Symbol value if any */ unsigned AddrSize; /* Address size of symbol */ }; /* Collections with symbols */ static Collection CfgSymbols = STATIC_COLLECTION_INITIALIZER; /* Descriptor holding information about the binary formats */ static BinDesc* BinFmtDesc = 0; static O65Desc* O65FmtDesc = 0; static XexDesc* XexFmtDesc = 0; /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ static File* NewFile (unsigned Name); /* Create a new file descriptor and insert it into the list */ /*****************************************************************************/ /* List management */ /*****************************************************************************/ static File* FindFile (unsigned Name) /* Find a file with a given name. */ { unsigned I; for (I = 0; I < CollCount (&FileList); ++I) { File* F = CollAtUnchecked (&FileList, I); if (F->Name == Name) { return F; } } return 0; } static File* GetFile (unsigned Name) /* Get a file entry with the given name. Create a new one if needed. */ { File* F = FindFile (Name); if (F == 0) { /* Create a new one */ F = NewFile (Name); } return F; } static void FileInsert (File* F, MemoryArea* M) /* Insert the memory area into the files list */ { M->F = F; CollAppend (&F->MemoryAreas, M); } static MemoryArea* CfgFindMemory (unsigned Name) /* Find the memory are with the given name. Return NULL if not found */ { unsigned I; for (I = 0; I < CollCount (&MemoryAreas); ++I) { MemoryArea* M = CollAtUnchecked (&MemoryAreas, I); if (M->Name == Name) { return M; } } return 0; } static MemoryArea* CfgGetMemory (unsigned Name) /* Find the memory are with the given name. Print an error on an invalid name */ { MemoryArea* M = CfgFindMemory (Name); if (M == 0) { CfgError (&CfgErrorPos, "Invalid memory area '%s'", GetString (Name)); } return M; } static SegDesc* CfgFindSegDesc (unsigned Name) /* Find the segment descriptor with the given name, return NULL if not found. */ { unsigned I; for (I = 0; I < CollCount (&SegDescList); ++I) { SegDesc* S = CollAtUnchecked (&SegDescList, I); if (S->Name == Name) { /* Found */ return S; } } /* Not found */ return 0; } static void MemoryInsert (MemoryArea* M, SegDesc* S) /* Insert the segment descriptor into the memory area list */ { /* Insert the segment into the segment list of the memory area */ CollAppend (&M->SegList, S); } /*****************************************************************************/ /* Constructors/Destructors */ /*****************************************************************************/ static CfgSymbol* NewCfgSymbol (CfgSymType Type, unsigned Name) /* Create a new CfgSymbol structure with the given type and name. The ** current config file position is recorded in the returned struct. The ** created struct is inserted into the CfgSymbols collection and returned. */ { /* Allocate memory */ CfgSymbol* Sym = xmalloc (sizeof (CfgSymbol)); /* Initialize the fields */ Sym->Type = Type; Sym->LI = GenLineInfo (&CfgErrorPos); Sym->Name = Name; Sym->Value = 0; Sym->AddrSize = ADDR_SIZE_INVALID; /* Insert the symbol into the collection */ CollAppend (&CfgSymbols, Sym); /* Return the initialized struct */ return Sym; } static File* NewFile (unsigned Name) /* Create a new file descriptor and insert it into the list */ { /* Allocate memory */ File* F = xmalloc (sizeof (File)); /* Initialize the fields */ F->Name = Name; F->Flags = 0; F->Format = BINFMT_DEFAULT; F->Size = 0; InitCollection (&F->MemoryAreas); /* Insert the struct into the list */ CollAppend (&FileList, F); /* ...and return it */ return F; } static MemoryArea* CreateMemoryArea (const FilePos* Pos, unsigned Name) /* Create a new memory area and insert it into the list */ { /* Check for duplicate names */ MemoryArea* M = CfgFindMemory (Name); if (M) { CfgError (&CfgErrorPos, "Memory area '%s' defined twice", GetString (Name)); } /* Create a new memory area */ M = NewMemoryArea (Pos, Name); /* Insert the struct into the list ... */ CollAppend (&MemoryAreas, M); /* ...and return it */ return M; } static SegDesc* NewSegDesc (unsigned Name) /* Create a segment descriptor and insert it into the list */ { /* Check for duplicate names */ SegDesc* S = CfgFindSegDesc (Name); if (S) { CfgError (&CfgErrorPos, "Segment '%s' defined twice", GetString (Name)); } /* Allocate memory */ S = xmalloc (sizeof (SegDesc)); /* Initialize the fields */ S->Name = Name; S->LI = GenLineInfo (&CfgErrorPos); S->Seg = 0; S->Attr = 0; S->Flags = 0; S->FillVal = 0; S->RunAlignment = 1; S->LoadAlignment = 1; /* Insert the struct into the list ... */ CollAppend (&SegDescList, S); /* ...and return it */ return S; } static void FreeSegDesc (SegDesc* S) /* Free a segment descriptor */ { FreeLineInfo (S->LI); xfree (S); } /*****************************************************************************/ /* Config file parsing */ /*****************************************************************************/ static void FlagAttr (unsigned* Flags, unsigned Mask, const char* Name) /* Check if the item is already defined. Print an error if so. If not, set ** the marker that we have a definition now. */ { if (*Flags & Mask) { CfgError (&CfgErrorPos, "%s is already defined", Name); } *Flags |= Mask; } static void AttrCheck (unsigned Attr, unsigned Mask, const char* Name) /* Check that a mandatory attribute was given */ { if ((Attr & Mask) == 0) { CfgError (&CfgErrorPos, "%s attribute is missing", Name); } } static void ParseMemory (void) /* Parse a MEMORY section */ { static const IdentTok Attributes [] = { { "BANK", CFGTOK_BANK }, { "DEFINE", CFGTOK_DEFINE }, { "FILE", CFGTOK_FILE }, { "FILL", CFGTOK_FILL }, { "FILLVAL", CFGTOK_FILLVAL }, { "SIZE", CFGTOK_SIZE }, { "START", CFGTOK_START }, { "TYPE", CFGTOK_TYPE }, }; static const IdentTok Types [] = { { "RO", CFGTOK_RO }, { "RW", CFGTOK_RW }, }; while (CfgTok == CFGTOK_IDENT) { /* Create a new entry on the heap */ MemoryArea* M = CreateMemoryArea (&CfgErrorPos, GetStrBufId (&CfgSVal)); /* Skip the name and the following colon */ CfgNextTok (); CfgConsumeColon (); /* Read the attributes */ while (CfgTok == CFGTOK_IDENT) { /* Map the identifier to a token */ cfgtok_t AttrTok; CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); AttrTok = CfgTok; /* An optional assignment follows */ CfgNextTok (); CfgOptionalAssign (); /* Check which attribute was given */ switch (AttrTok) { case CFGTOK_BANK: FlagAttr (&M->Attr, MA_BANK, "BANK"); M->BankExpr = CfgExpr (); break; case CFGTOK_DEFINE: FlagAttr (&M->Attr, MA_DEFINE, "DEFINE"); /* Map the token to a boolean */ CfgBoolToken (); if (CfgTok == CFGTOK_TRUE) { M->Flags |= MF_DEFINE; } CfgNextTok (); break; case CFGTOK_FILE: FlagAttr (&M->Attr, MA_FILE, "FILE"); CfgAssureStr (); /* Get the file entry and insert the memory area */ FileInsert (GetFile (GetStrBufId (&CfgSVal)), M); CfgNextTok (); break; case CFGTOK_FILL: FlagAttr (&M->Attr, MA_FILL, "FILL"); /* Map the token to a boolean */ CfgBoolToken (); if (CfgTok == CFGTOK_TRUE) { M->Flags |= MF_FILL; } CfgNextTok (); break; case CFGTOK_FILLVAL: FlagAttr (&M->Attr, MA_FILLVAL, "FILLVAL"); M->FillVal = (unsigned char) CfgCheckedConstExpr (0, 0xFF); break; case CFGTOK_SIZE: FlagAttr (&M->Attr, MA_SIZE, "SIZE"); M->SizeExpr = CfgExpr (); break; case CFGTOK_START: FlagAttr (&M->Attr, MA_START, "START"); M->StartExpr = CfgExpr (); break; case CFGTOK_TYPE: FlagAttr (&M->Attr, MA_TYPE, "TYPE"); CfgSpecialToken (Types, ENTRY_COUNT (Types), "TYPE"); if (CfgTok == CFGTOK_RO) { M->Flags |= MF_RO; } CfgNextTok (); break; default: FAIL ("Unexpected attribute token"); } /* Skip an optional comma */ CfgOptionalComma (); } /* Skip the semicolon */ CfgConsumeSemi (); /* Check for mandatory parameters */ AttrCheck (M->Attr, MA_START, "START"); AttrCheck (M->Attr, MA_SIZE, "SIZE"); /* If we don't have a file name for output given, use the default ** file name. */ if ((M->Attr & MA_FILE) == 0) { FileInsert (GetFile (GetStringId (OutputName)), M); OutputNameUsed = 1; } } /* Remember we had this section */ SectionsEncountered |= SE_MEMORY; } static void ParseFiles (void) /* Parse a FILES section */ { static const IdentTok Attributes [] = { { "FORMAT", CFGTOK_FORMAT }, }; static const IdentTok Formats [] = { { "ATARI", CFGTOK_ATARIEXE }, { "O65", CFGTOK_O65 }, { "BIN", CFGTOK_BIN }, { "BINARY", CFGTOK_BIN }, }; /* The MEMORY section must preceed the FILES section */ if ((SectionsEncountered & SE_MEMORY) == 0) { CfgError (&CfgErrorPos, "MEMORY must precede FILES"); } /* Parse all files */ while (CfgTok != CFGTOK_RCURLY) { File* F; /* We expect a string value here */ CfgAssureStr (); /* Search for the file, it must exist */ F = FindFile (GetStrBufId (&CfgSVal)); if (F == 0) { CfgError (&CfgErrorPos, "File '%s' not found in MEMORY section", SB_GetConstBuf (&CfgSVal)); } /* Skip the token and the following colon */ CfgNextTok (); CfgConsumeColon (); /* Read the attributes */ while (CfgTok == CFGTOK_IDENT) { /* Map the identifier to a token */ cfgtok_t AttrTok; CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); AttrTok = CfgTok; /* An optional assignment follows */ CfgNextTok (); CfgOptionalAssign (); /* Check which attribute was given */ switch (AttrTok) { case CFGTOK_FORMAT: if (F->Format != BINFMT_DEFAULT) { /* We've set the format already! */ CfgError (&CfgErrorPos, "Cannot set a file format twice"); } /* Read the format token */ CfgSpecialToken (Formats, ENTRY_COUNT (Formats), "Format"); switch (CfgTok) { case CFGTOK_BIN: F->Format = BINFMT_BINARY; break; case CFGTOK_O65: F->Format = BINFMT_O65; break; case CFGTOK_ATARIEXE: F->Format = BINFMT_ATARIEXE; break; default: Error ("Unexpected format token"); } break; default: FAIL ("Unexpected attribute token"); } /* Skip the attribute value and an optional comma */ CfgNextTok (); CfgOptionalComma (); } /* Skip the semicolon */ CfgConsumeSemi (); } /* Remember we had this section */ SectionsEncountered |= SE_FILES; } static void ParseSegments (void) /* Parse a SEGMENTS section */ { static const IdentTok Attributes [] = { { "ALIGN", CFGTOK_ALIGN }, { "ALIGN_LOAD", CFGTOK_ALIGN_LOAD }, { "DEFINE", CFGTOK_DEFINE }, { "FILLVAL", CFGTOK_FILLVAL }, { "LOAD", CFGTOK_LOAD }, { "OFFSET", CFGTOK_OFFSET }, { "OPTIONAL", CFGTOK_OPTIONAL }, { "RUN", CFGTOK_RUN }, { "START", CFGTOK_START }, { "TYPE", CFGTOK_TYPE }, }; static const IdentTok Types [] = { { "RO", CFGTOK_RO }, { "RW", CFGTOK_RW }, { "BSS", CFGTOK_BSS }, { "ZP", CFGTOK_ZP }, { "OVERWRITE", CFGTOK_OVERWRITE }, }; unsigned Count; /* The MEMORY section must preceed the SEGMENTS section */ if ((SectionsEncountered & SE_MEMORY) == 0) { CfgError (&CfgErrorPos, "MEMORY must precede SEGMENTS"); } while (CfgTok == CFGTOK_IDENT) { SegDesc* S; /* Create a new entry on the heap */ S = NewSegDesc (GetStrBufId (&CfgSVal)); /* Skip the name and the following colon */ CfgNextTok (); CfgConsumeColon (); /* Read the attributes */ while (CfgTok == CFGTOK_IDENT) { /* Map the identifier to a token */ cfgtok_t AttrTok; CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); AttrTok = CfgTok; /* An optional assignment follows */ CfgNextTok (); CfgOptionalAssign (); /* Check which attribute was given */ switch (AttrTok) { case CFGTOK_ALIGN: FlagAttr (&S->Attr, SA_ALIGN, "ALIGN"); S->RunAlignment = (unsigned) CfgCheckedConstExpr (1, MAX_ALIGNMENT); S->Flags |= SF_ALIGN; break; case CFGTOK_ALIGN_LOAD: FlagAttr (&S->Attr, SA_ALIGN_LOAD, "ALIGN_LOAD"); S->LoadAlignment = (unsigned) CfgCheckedConstExpr (1, MAX_ALIGNMENT); S->Flags |= SF_ALIGN_LOAD; break; case CFGTOK_DEFINE: FlagAttr (&S->Attr, SA_DEFINE, "DEFINE"); /* Map the token to a boolean */ CfgBoolToken (); if (CfgTok == CFGTOK_TRUE) { S->Flags |= SF_DEFINE; } CfgNextTok (); break; case CFGTOK_FILLVAL: FlagAttr (&S->Attr, SA_FILLVAL, "FILLVAL"); S->FillVal = (unsigned char) CfgCheckedConstExpr (0, 0xFF); S->Flags |= SF_FILLVAL; break; case CFGTOK_LOAD: FlagAttr (&S->Attr, SA_LOAD, "LOAD"); S->Load = CfgGetMemory (GetStrBufId (&CfgSVal)); CfgNextTok (); break; case CFGTOK_OFFSET: FlagAttr (&S->Attr, SA_OFFSET, "OFFSET"); S->Addr = CfgCheckedConstExpr (1, 0x1000000); S->Flags |= SF_OFFSET; break; case CFGTOK_OPTIONAL: FlagAttr (&S->Attr, SA_OPTIONAL, "OPTIONAL"); CfgBoolToken (); if (CfgTok == CFGTOK_TRUE) { S->Flags |= SF_OPTIONAL; } CfgNextTok (); break; case CFGTOK_RUN: FlagAttr (&S->Attr, SA_RUN, "RUN"); S->Run = CfgGetMemory (GetStrBufId (&CfgSVal)); CfgNextTok (); break; case CFGTOK_START: FlagAttr (&S->Attr, SA_START, "START"); S->Addr = CfgCheckedConstExpr (1, 0x1000000); S->Flags |= SF_START; break; case CFGTOK_TYPE: FlagAttr (&S->Attr, SA_TYPE, "TYPE"); CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type"); switch (CfgTok) { case CFGTOK_RO: S->Flags |= SF_RO; break; case CFGTOK_RW: /* Default */ break; case CFGTOK_BSS: S->Flags |= SF_BSS; break; case CFGTOK_ZP: S->Flags |= (SF_BSS | SF_ZP); break; case CFGTOK_OVERWRITE: S->Flags |= (SF_OVERWRITE | SF_RO); break; default: Internal ("Unexpected token: %d", CfgTok); } CfgNextTok (); break; default: FAIL ("Unexpected attribute token"); } /* Skip an optional comma */ CfgOptionalComma (); } /* Check for mandatory parameters */ AttrCheck (S->Attr, SA_LOAD, "LOAD"); /* Set defaults for stuff not given */ if ((S->Attr & SA_RUN) == 0) { S->Attr |= SA_RUN; S->Run = S->Load; } /* An attribute of ALIGN_LOAD doesn't make sense if there are no ** separate run and load memory areas. */ if ((S->Flags & SF_ALIGN_LOAD) != 0 && (S->Load == S->Run)) { CfgWarning (&CfgErrorPos, "ALIGN_LOAD attribute specified, but no separate " "LOAD and RUN memory areas assigned"); /* Remove the flag */ S->Flags &= ~SF_ALIGN_LOAD; } /* If the segment is marked as BSS style, it may not have separate ** load and run memory areas, because it's is never written to disk. */ if ((S->Flags & SF_BSS) != 0 && (S->Load != S->Run)) { CfgWarning (&CfgErrorPos, "Segment with type 'bss' has both LOAD and RUN " "memory areas assigned"); } /* Don't allow read/write data to be put into a readonly area */ if ((S->Flags & SF_RO) == 0) { if (S->Run->Flags & MF_RO) { CfgError (&CfgErrorPos, "Cannot put r/w segment '%s' in r/o memory area '%s'", GetString (S->Name), GetString (S->Run->Name)); } } /* Only one of ALIGN, START and OFFSET may be used */ Count = ((S->Flags & SF_ALIGN) != 0) + ((S->Flags & SF_OFFSET) != 0) + ((S->Flags & SF_START) != 0); if (Count > 1) { CfgError (&CfgErrorPos, "Only one of ALIGN, START, OFFSET may be used"); } /* Skip the semicolon */ CfgConsumeSemi (); } /* Remember we had this section */ SectionsEncountered |= SE_SEGMENTS; } static void ParseO65 (void) /* Parse the o65 format section */ { static const IdentTok Attributes [] = { { "EXPORT", CFGTOK_EXPORT }, { "IMPORT", CFGTOK_IMPORT }, { "TYPE", CFGTOK_TYPE }, { "OS", CFGTOK_OS }, { "ID", CFGTOK_ID }, { "VERSION", CFGTOK_VERSION }, }; static const IdentTok Types [] = { { "SMALL", CFGTOK_SMALL }, { "LARGE", CFGTOK_LARGE }, }; static const IdentTok OperatingSystems [] = { { "LUNIX", CFGTOK_LUNIX }, { "OSA65", CFGTOK_OSA65 }, { "CC65", CFGTOK_CC65 }, { "OPENCBM", CFGTOK_OPENCBM }, }; /* Bitmask to remember the attributes we got already */ enum { atNone = 0x0000, atOS = 0x0001, atOSVersion = 0x0002, atType = 0x0004, atImport = 0x0008, atExport = 0x0010, atID = 0x0020, atVersion = 0x0040 }; unsigned AttrFlags = atNone; /* Remember the attributes read */ unsigned OS = 0; /* Initialize to keep gcc happy */ unsigned Version = 0; /* Read the attributes */ while (CfgTok == CFGTOK_IDENT) { /* Map the identifier to a token */ cfgtok_t AttrTok; CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); AttrTok = CfgTok; /* An optional assignment follows */ CfgNextTok (); CfgOptionalAssign (); /* Check which attribute was given */ switch (AttrTok) { case CFGTOK_EXPORT: /* Remember we had this token (maybe more than once) */ AttrFlags |= atExport; /* We expect an identifier */ CfgAssureIdent (); /* Remember it as an export for later */ NewCfgSymbol (CfgSymO65Export, GetStrBufId (&CfgSVal)); /* Eat the identifier token */ CfgNextTok (); break; case CFGTOK_IMPORT: /* Remember we had this token (maybe more than once) */ AttrFlags |= atImport; /* We expect an identifier */ CfgAssureIdent (); /* Remember it as an import for later */ NewCfgSymbol (CfgSymO65Import, GetStrBufId (&CfgSVal)); /* Eat the identifier token */ CfgNextTok (); break; case CFGTOK_TYPE: /* Cannot have this attribute twice */ FlagAttr (&AttrFlags, atType, "TYPE"); /* Get the type of the executable */ CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type"); switch (CfgTok) { case CFGTOK_SMALL: O65SetSmallModel (O65FmtDesc); break; case CFGTOK_LARGE: O65SetLargeModel (O65FmtDesc); break; default: CfgError (&CfgErrorPos, "Unexpected type token"); } /* Eat the attribute token */ CfgNextTok (); break; case CFGTOK_OS: /* Cannot use this attribute twice */ FlagAttr (&AttrFlags, atOS, "OS"); /* Get the operating system. It may be specified as name or ** as a number in the range 1..255. */ if (CfgTok == CFGTOK_INTCON) { CfgRangeCheck (O65OS_MIN, O65OS_MAX); OS = (unsigned) CfgIVal; } else { CfgSpecialToken (OperatingSystems, ENTRY_COUNT (OperatingSystems), "OS type"); switch (CfgTok) { case CFGTOK_LUNIX: OS = O65OS_LUNIX; break; case CFGTOK_OSA65: OS = O65OS_OSA65; break; case CFGTOK_CC65: OS = O65OS_CC65; break; case CFGTOK_OPENCBM: OS = O65OS_OPENCBM; break; default: CfgError (&CfgErrorPos, "Unexpected OS token"); } } CfgNextTok (); break; case CFGTOK_ID: /* Cannot have this attribute twice */ FlagAttr (&AttrFlags, atID, "ID"); /* We're expecting a number in the 0..$FFFF range*/ ModuleId = (unsigned) CfgCheckedConstExpr (0, 0xFFFF); break; case CFGTOK_VERSION: /* Cannot have this attribute twice */ FlagAttr (&AttrFlags, atVersion, "VERSION"); /* We're expecting a number in byte range */ Version = (unsigned) CfgCheckedConstExpr (0, 0xFF); break; default: FAIL ("Unexpected attribute token"); } /* Skip an optional comma */ CfgOptionalComma (); } /* Check if we have all mandatory attributes */ AttrCheck (AttrFlags, atOS, "OS"); /* Check for attributes that may not be combined */ if (OS == O65OS_CC65) { if ((AttrFlags & (atImport | atExport)) != 0 && ModuleId < 0x8000) { CfgError (&CfgErrorPos, "OS type CC65 may not have imports or exports for ids < $8000"); } } else { if (AttrFlags & atID) { CfgError (&CfgErrorPos, "Operating system does not support the ID attribute"); } } /* Set the O65 operating system to use */ O65SetOS (O65FmtDesc, OS, Version, ModuleId); } static void ParseXex (void) /* Parse the o65 format section */ { static const IdentTok Attributes [] = { { "RUNAD", CFGTOK_RUNAD }, { "INITAD", CFGTOK_INITAD }, }; /* Remember the attributes read */ /* Bitmask to remember the attributes we got already */ enum { atNone = 0x0000, atRunAd = 0x0001, }; unsigned AttrFlags = atNone; Import *RunAd = 0; Import *InitAd; MemoryArea *InitMem; /* Read the attributes */ while (CfgTok == CFGTOK_IDENT) { /* Map the identifier to a token */ cfgtok_t AttrTok; CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); AttrTok = CfgTok; /* An optional assignment follows */ CfgNextTok (); CfgOptionalAssign (); /* Check which attribute was given */ switch (AttrTok) { case CFGTOK_RUNAD: /* Cannot have this attribute twice */ FlagAttr (&AttrFlags, atRunAd, "RUNAD"); /* We expect an identifier */ CfgAssureIdent (); /* Generate an import for the symbol */ RunAd = InsertImport (GenImport (GetStrBufId (&CfgSVal), ADDR_SIZE_ABS)); /* Remember the file position */ CollAppend (&RunAd->RefLines, GenLineInfo (&CfgErrorPos)); /* Eat the identifier token */ CfgNextTok (); break; case CFGTOK_INITAD: /* We expect a memory area followed by a colon and an identifier */ CfgAssureIdent (); InitMem = CfgGetMemory (GetStrBufId (&CfgSVal)); CfgNextTok (); CfgConsumeColon (); CfgAssureIdent (); /* Generate an import for the symbol */ InitAd = InsertImport (GenImport (GetStrBufId (&CfgSVal), ADDR_SIZE_ABS)); /* Remember the file position */ CollAppend (&InitAd->RefLines, GenLineInfo (&CfgErrorPos)); /* Eat the identifier token */ CfgNextTok (); /* Add to XEX */ if (XexAddInitAd (XexFmtDesc, InitMem, InitAd)) CfgError (&CfgErrorPos, "INITAD already given for memory area"); break; default: FAIL ("Unexpected attribute token"); } /* Skip an optional comma */ CfgOptionalComma (); } /* Set the RUNAD import if we have one */ if ( RunAd ) XexSetRunAd (XexFmtDesc, RunAd); } static void ParseFormats (void) /* Parse a target format section */ { static const IdentTok Formats [] = { { "O65", CFGTOK_O65 }, { "BIN", CFGTOK_BIN }, { "BINARY", CFGTOK_BIN }, { "ATARI", CFGTOK_ATARIEXE }, }; while (CfgTok == CFGTOK_IDENT) { /* Map the identifier to a token */ cfgtok_t FormatTok; CfgSpecialToken (Formats, ENTRY_COUNT (Formats), "Format"); FormatTok = CfgTok; /* Skip the name and the following colon */ CfgNextTok (); CfgConsumeColon (); /* Parse the format options */ switch (FormatTok) { case CFGTOK_O65: ParseO65 (); break; case CFGTOK_ATARIEXE: ParseXex (); break; case CFGTOK_BIN: /* No attribibutes available */ break; default: Error ("Unexpected format token"); } /* Skip the semicolon */ CfgConsumeSemi (); } /* Remember we had this section */ SectionsEncountered |= SE_FORMATS; } static void ParseConDes (void) /* Parse the CONDES feature */ { static const IdentTok Attributes [] = { { "COUNT", CFGTOK_COUNT }, { "IMPORT", CFGTOK_IMPORT }, { "LABEL", CFGTOK_LABEL }, { "ORDER", CFGTOK_ORDER }, { "SEGMENT", CFGTOK_SEGMENT }, { "TYPE", CFGTOK_TYPE }, }; static const IdentTok Types [] = { { "CONSTRUCTOR", CFGTOK_CONSTRUCTOR }, { "DESTRUCTOR", CFGTOK_DESTRUCTOR }, { "INTERRUPTOR", CFGTOK_INTERRUPTOR }, }; static const IdentTok Orders [] = { { "DECREASING", CFGTOK_DECREASING }, { "INCREASING", CFGTOK_INCREASING }, }; /* Attribute values. */ unsigned Count = INVALID_STRING_ID; unsigned Label = INVALID_STRING_ID; unsigned SegName = INVALID_STRING_ID; ConDesImport Import; /* Initialize to avoid gcc warnings: */ int Type = -1; ConDesOrder Order = cdIncreasing; /* Bitmask to remember the attributes we got already */ enum { atNone = 0x0000, atCount = 0x0001, atImport = 0x0002, atLabel = 0x0004, atOrder = 0x0008, atSegName = 0x0010, atType = 0x0020, }; unsigned AttrFlags = atNone; /* Parse the attributes */ while (1) { /* Map the identifier to a token */ cfgtok_t AttrTok; CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); AttrTok = CfgTok; /* An optional assignment follows */ CfgNextTok (); CfgOptionalAssign (); /* Check which attribute was given */ switch (AttrTok) { case CFGTOK_COUNT: /* Don't allow this twice */ FlagAttr (&AttrFlags, atCount, "COUNT"); /* We expect an identifier */ CfgAssureIdent (); /* Remember the value for later */ Count = GetStrBufId (&CfgSVal); break; case CFGTOK_IMPORT: /* Don't allow this twice */ FlagAttr (&AttrFlags, atImport, "IMPORT"); /* We expect an identifier */ CfgAssureIdent (); /* Remember value and position for later */ Import.Name = GetStrBufId (&CfgSVal); Import.Pos = CfgErrorPos; Import.AddrSize = ADDR_SIZE_ABS; break; case CFGTOK_LABEL: /* Don't allow this twice */ FlagAttr (&AttrFlags, atLabel, "LABEL"); /* We expect an identifier */ CfgAssureIdent (); /* Remember the value for later */ Label = GetStrBufId (&CfgSVal); break; case CFGTOK_ORDER: /* Don't allow this twice */ FlagAttr (&AttrFlags, atOrder, "ORDER"); CfgSpecialToken (Orders, ENTRY_COUNT (Orders), "Order"); switch (CfgTok) { case CFGTOK_DECREASING: Order = cdDecreasing; break; case CFGTOK_INCREASING: Order = cdIncreasing; break; default: FAIL ("Unexpected order token"); } break; case CFGTOK_SEGMENT: /* Don't allow this twice */ FlagAttr (&AttrFlags, atSegName, "SEGMENT"); /* We expect an identifier */ CfgAssureIdent (); /* Remember the value for later */ SegName = GetStrBufId (&CfgSVal); break; case CFGTOK_TYPE: /* Don't allow this twice */ FlagAttr (&AttrFlags, atType, "TYPE"); /* The type may be given as id or numerical */ if (CfgTok == CFGTOK_INTCON) { CfgRangeCheck (CD_TYPE_MIN, CD_TYPE_MAX); Type = (int) CfgIVal; } else { CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type"); switch (CfgTok) { case CFGTOK_CONSTRUCTOR: Type = CD_TYPE_CON; break; case CFGTOK_DESTRUCTOR: Type = CD_TYPE_DES; break; case CFGTOK_INTERRUPTOR: Type = CD_TYPE_INT; break; default: FAIL ("Unexpected type token"); } } break; default: FAIL ("Unexpected attribute token"); } /* Skip the attribute value */ CfgNextTok (); /* Semicolon ends the ConDes decl, otherwise accept an optional comma */ if (CfgTok == CFGTOK_SEMI) { break; } else if (CfgTok == CFGTOK_COMMA) { CfgNextTok (); } } /* Check if we have all mandatory attributes */ AttrCheck (AttrFlags, atSegName, "SEGMENT"); AttrCheck (AttrFlags, atLabel, "LABEL"); AttrCheck (AttrFlags, atType, "TYPE"); /* Check if the condes has already attributes defined */ if (ConDesHasSegName(Type) || ConDesHasLabel(Type)) { CfgError (&CfgErrorPos, "CONDES attributes for type %d are already defined", Type); } /* Define the attributes */ ConDesSetSegName (Type, SegName); ConDesSetLabel (Type, Label); if (AttrFlags & atCount) { ConDesSetCountSym (Type, Count); } if (AttrFlags & atImport) { ConDesSetImport (Type, &Import); } if (AttrFlags & atOrder) { ConDesSetOrder (Type, Order); } } static void ParseStartAddress (void) /* Parse the STARTADDRESS feature */ { static const IdentTok Attributes [] = { { "DEFAULT", CFGTOK_DEFAULT }, }; /* Attribute values. */ unsigned long DefStartAddr = 0; /* Bitmask to remember the attributes we got already */ enum { atNone = 0x0000, atDefault = 0x0001 }; unsigned AttrFlags = atNone; /* Parse the attributes */ while (1) { /* Map the identifier to a token */ cfgtok_t AttrTok; CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); AttrTok = CfgTok; /* An optional assignment follows */ CfgNextTok (); CfgOptionalAssign (); /* Check which attribute was given */ switch (AttrTok) { case CFGTOK_DEFAULT: /* Don't allow this twice */ FlagAttr (&AttrFlags, atDefault, "DEFAULT"); /* We expect a numeric expression */ DefStartAddr = CfgCheckedConstExpr (0, 0xFFFFFF); break; default: FAIL ("Unexpected attribute token"); } /* Semicolon ends the ConDes decl, otherwise accept an optional comma */ if (CfgTok == CFGTOK_SEMI) { break; } else if (CfgTok == CFGTOK_COMMA) { CfgNextTok (); } } /* Check if we have all mandatory attributes */ AttrCheck (AttrFlags, atDefault, "DEFAULT"); /* If no start address was given on the command line, use the one given ** here */ if (!HaveStartAddr) { StartAddr = DefStartAddr; } } static void ParseFeatures (void) /* Parse a features section */ { static const IdentTok Features [] = { { "CONDES", CFGTOK_CONDES }, { "STARTADDRESS", CFGTOK_STARTADDRESS }, }; while (CfgTok == CFGTOK_IDENT) { /* Map the identifier to a token */ cfgtok_t FeatureTok; CfgSpecialToken (Features, ENTRY_COUNT (Features), "Feature"); FeatureTok = CfgTok; /* Skip the name and the following colon */ CfgNextTok (); CfgConsumeColon (); /* Parse the format options */ switch (FeatureTok) { case CFGTOK_CONDES: ParseConDes (); break; case CFGTOK_STARTADDRESS: ParseStartAddress (); break; default: FAIL ("Unexpected feature token"); } /* Skip the semicolon */ CfgConsumeSemi (); } /* Remember we had this section */ SectionsEncountered |= SE_FEATURES; } static void ParseSymbols (void) /* Parse a symbols section */ { static const IdentTok Attributes[] = { { "ADDRSIZE", CFGTOK_ADDRSIZE }, { "TYPE", CFGTOK_TYPE }, { "VALUE", CFGTOK_VALUE }, }; static const IdentTok AddrSizes [] = { { "ABS", CFGTOK_ABS }, { "ABSOLUTE", CFGTOK_ABS }, { "DIRECT", CFGTOK_ZP }, { "DWORD", CFGTOK_LONG }, { "FAR", CFGTOK_FAR }, { "LONG", CFGTOK_LONG }, { "NEAR", CFGTOK_ABS }, { "ZEROPAGE", CFGTOK_ZP }, { "ZP", CFGTOK_ZP }, }; static const IdentTok Types [] = { { "EXPORT", CFGTOK_EXPORT }, { "IMPORT", CFGTOK_IMPORT }, { "WEAK", CFGTOK_WEAK }, }; while (CfgTok == CFGTOK_IDENT) { /* Bitmask to remember the attributes we got already */ enum { atNone = 0x0000, atAddrSize = 0x0001, atType = 0x0002, atValue = 0x0004, }; unsigned AttrFlags = atNone; ExprNode* Value = 0; CfgSymType Type = CfgSymExport; unsigned char AddrSize = ADDR_SIZE_ABS; Import* Imp; Export* Exp; CfgSymbol* Sym; /* Remember the name */ unsigned Name = GetStrBufId (&CfgSVal); CfgNextTok (); /* New syntax - skip the colon */ CfgNextTok (); /* Parse the attributes */ while (1) { /* Map the identifier to a token */ cfgtok_t AttrTok; CfgSpecialToken (Attributes, ENTRY_COUNT (Attributes), "Attribute"); AttrTok = CfgTok; /* Skip the attribute name */ CfgNextTok (); /* An optional assignment follows */ CfgOptionalAssign (); /* Check which attribute was given */ switch (AttrTok) { case CFGTOK_ADDRSIZE: /* Don't allow this twice */ FlagAttr (&AttrFlags, atAddrSize, "ADDRSIZE"); /* Map the type to a token */ CfgSpecialToken (AddrSizes, ENTRY_COUNT (AddrSizes), "AddrSize"); switch (CfgTok) { case CFGTOK_ABS: AddrSize = ADDR_SIZE_ABS; break; case CFGTOK_FAR: AddrSize = ADDR_SIZE_FAR; break; case CFGTOK_LONG: AddrSize = ADDR_SIZE_LONG; break; case CFGTOK_ZP: AddrSize = ADDR_SIZE_ZP; break; default: Internal ("Unexpected token: %d", CfgTok); } CfgNextTok (); break; case CFGTOK_TYPE: /* Don't allow this twice */ FlagAttr (&AttrFlags, atType, "TYPE"); /* Map the type to a token */ CfgSpecialToken (Types, ENTRY_COUNT (Types), "Type"); switch (CfgTok) { case CFGTOK_EXPORT: Type = CfgSymExport; break; case CFGTOK_IMPORT: Type = CfgSymImport; break; case CFGTOK_WEAK: Type = CfgSymWeak; break; default: Internal ("Unexpected token: %d", CfgTok); } CfgNextTok (); break; case CFGTOK_VALUE: /* Don't allow this twice */ FlagAttr (&AttrFlags, atValue, "VALUE"); /* Value is an expression */ Value = CfgExpr (); break; default: FAIL ("Unexpected attribute token"); } /* Semicolon ends the decl, otherwise accept an optional comma */ if (CfgTok == CFGTOK_SEMI) { break; } else if (CfgTok == CFGTOK_COMMA) { CfgNextTok (); } } /* We must have a type */ AttrCheck (AttrFlags, atType, "TYPE"); /* Further actions depend on the type */ switch (Type) { case CfgSymExport: /* We must have a value */ AttrCheck (AttrFlags, atValue, "VALUE"); /* Create the export */ Exp = CreateExprExport (Name, Value, AddrSize); CollAppend (&Exp->DefLines, GenLineInfo (&CfgErrorPos)); break; case CfgSymImport: /* An import must not have a value */ if (AttrFlags & atValue) { CfgError (&CfgErrorPos, "Imports must not have a value"); } /* Generate the import */ Imp = InsertImport (GenImport (Name, AddrSize)); /* Remember the file position */ CollAppend (&Imp->RefLines, GenLineInfo (&CfgErrorPos)); break; case CfgSymWeak: /* We must have a value */ AttrCheck (AttrFlags, atValue, "VALUE"); /* Remember the symbol for later */ Sym = NewCfgSymbol (CfgSymWeak, Name); Sym->Value = Value; Sym->AddrSize = AddrSize; break; default: Internal ("Unexpected symbol type %d", Type); } /* Skip the semicolon */ CfgConsumeSemi (); } /* Remember we had this section */ SectionsEncountered |= SE_SYMBOLS; } static void ParseConfig (void) /* Parse the config file */ { static const IdentTok BlockNames [] = { { "MEMORY", CFGTOK_MEMORY }, { "FILES", CFGTOK_FILES }, { "SEGMENTS", CFGTOK_SEGMENTS }, { "FORMATS", CFGTOK_FORMATS }, { "FEATURES", CFGTOK_FEATURES }, { "SYMBOLS", CFGTOK_SYMBOLS }, }; cfgtok_t BlockTok; do { /* Read the block ident */ CfgSpecialToken (BlockNames, ENTRY_COUNT (BlockNames), "Block identifier"); BlockTok = CfgTok; CfgNextTok (); /* Expected a curly brace */ CfgConsume (CFGTOK_LCURLY, "'{' expected"); /* Read the block */ switch (BlockTok) { case CFGTOK_MEMORY: ParseMemory (); break; case CFGTOK_FILES: ParseFiles (); break; case CFGTOK_SEGMENTS: ParseSegments (); break; case CFGTOK_FORMATS: ParseFormats (); break; case CFGTOK_FEATURES: ParseFeatures (); break; case CFGTOK_SYMBOLS: ParseSymbols (); break; default: FAIL ("Unexpected block token"); } /* Skip closing brace */ CfgConsume (CFGTOK_RCURLY, "'}' expected"); } while (CfgTok != CFGTOK_EOF); } void CfgRead (void) /* Read the configuration */ { /* Create the descriptors for the binary formats */ BinFmtDesc = NewBinDesc (); O65FmtDesc = NewO65Desc (); XexFmtDesc = NewXexDesc (); /* If we have a config name given, open the file, otherwise we will read ** from a buffer. */ CfgOpenInput (); /* Parse the file */ ParseConfig (); /* Close the input file */ CfgCloseInput (); } /*****************************************************************************/ /* Config file processing */ /*****************************************************************************/ static void ProcessSegments (void) /* Process the SEGMENTS section */ { unsigned I; /* Walk over the list of segment descriptors */ I = 0; while (I < CollCount (&SegDescList)) { /* Get the next segment descriptor */ SegDesc* S = CollAtUnchecked (&SegDescList, I); /* Search for the actual segment in the input files. The function may ** return NULL (no such segment), this is checked later. */ S->Seg = SegFind (S->Name); /* If the segment is marked as BSS style, and if the segment exists ** in any of the object file, check that there's no initialized data ** in the segment. */ if ((S->Flags & SF_BSS) != 0 && S->Seg != 0 && !IsBSSType (S->Seg)) { CfgWarning (GetSourcePos (S->LI), "Segment '%s' with type 'bss' contains initialized data", GetString (S->Name)); } /* If this segment does exist in any of the object files, insert the ** segment into the load/run memory areas. Otherwise print a warning ** and discard it, because the segment pointer in the descriptor is ** invalid. */ if (S->Seg != 0) { /* Insert the segment into the memory area list */ MemoryInsert (S->Run, S); if (S->Load != S->Run) { /* We have separate RUN and LOAD areas */ MemoryInsert (S->Load, S); } /* Use the fill value from the config */ S->Seg->FillVal = S->FillVal; /* Process the next segment descriptor in the next run */ ++I; } else { /* Print a warning if the segment is not optional */ if ((S->Flags & SF_OPTIONAL) == 0) { CfgWarning (&CfgErrorPos, "Segment '%s' does not exist", GetString (S->Name)); } /* Discard the descriptor and remove it from the collection */ FreeSegDesc (S); CollDelete (&SegDescList, I); } } } static void ProcessSymbols (void) /* Process the SYMBOLS section */ { Export* E; /* Walk over all symbols */ unsigned I; for (I = 0; I < CollCount (&CfgSymbols); ++I) { /* Get the next symbol */ CfgSymbol* Sym = CollAtUnchecked (&CfgSymbols, I); /* Check what it is. */ switch (Sym->Type) { case CfgSymO65Export: /* Check if the export symbol is also defined as an import. */ if (O65GetImport (O65FmtDesc, Sym->Name) != 0) { CfgError ( GetSourcePos (Sym->LI), "Exported o65 symbol '%s' cannot also be an o65 import", GetString (Sym->Name) ); } /* Check if we have this symbol defined already. The entry ** routine will check this also, but we get a more verbose ** error message when checking it here. */ if (O65GetExport (O65FmtDesc, Sym->Name) != 0) { CfgError ( GetSourcePos (Sym->LI), "Duplicate exported o65 symbol: '%s'", GetString (Sym->Name) ); } /* Insert the symbol into the table */ O65SetExport (O65FmtDesc, Sym->Name); break; case CfgSymO65Import: /* Check if the import symbol is also defined as an export. */ if (O65GetExport (O65FmtDesc, Sym->Name) != 0) { CfgError ( GetSourcePos (Sym->LI), "Imported o65 symbol '%s' cannot also be an o65 export", GetString (Sym->Name) ); } /* Check if we have this symbol defined already. The entry ** routine will check this also, but we get a more verbose ** error message when checking it here. */ if (O65GetImport (O65FmtDesc, Sym->Name) != 0) { CfgError ( GetSourcePos (Sym->LI), "Duplicate imported o65 symbol: '%s'", GetString (Sym->Name) ); } /* Insert the symbol into the table */ O65SetImport (O65FmtDesc, Sym->Name); break; case CfgSymWeak: /* If the symbol is not defined until now, define it */ if ((E = FindExport (Sym->Name)) == 0 || IsUnresolvedExport (E)) { /* The symbol is undefined, generate an export */ E = CreateExprExport (Sym->Name, Sym->Value, Sym->AddrSize); CollAppend (&E->DefLines, Sym->LI); } break; default: Internal ("Unexpected symbol type %d", Sym->Type); break; } } } static void CreateRunDefines (SegDesc* S, unsigned long SegAddr) /* Create the defines for a RUN segment */ { Export* E; StrBuf Buf = STATIC_STRBUF_INITIALIZER; /* Define the run address of the segment */ SB_Printf (&Buf, "__%s_RUN__", GetString (S->Name)); E = CreateMemoryExport (GetStrBufId (&Buf), S->Run, SegAddr - S->Run->Start); CollAppend (&E->DefLines, S->LI); /* Define the size of the segment */ SB_Printf (&Buf, "__%s_SIZE__", GetString (S->Name)); E = CreateConstExport (GetStrBufId (&Buf), S->Seg->Size); CollAppend (&E->DefLines, S->LI); S->Flags |= SF_RUN_DEF; SB_Done (&Buf); } static void CreateLoadDefines (SegDesc* S, unsigned long SegAddr) /* Create the defines for a LOAD segment */ { Export* E; StrBuf Buf = STATIC_STRBUF_INITIALIZER; /* Define the load address of the segment */ SB_Printf (&Buf, "__%s_LOAD__", GetString (S->Name)); E = CreateMemoryExport (GetStrBufId (&Buf), S->Load, SegAddr - S->Load->Start); CollAppend (&E->DefLines, S->LI); S->Flags |= SF_LOAD_DEF; SB_Done (&Buf); } 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 everything went OK). ** In case of overflows, a short mapfile can be generated later, to ease the ** user's task of re-arranging segments. */ { unsigned Overflows = 0; unsigned I; /* Postprocess symbols. We must do that first, since weak symbols are ** defined here, which may be needed later. */ ProcessSymbols (); /* Postprocess segments */ ProcessSegments (); /* 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 that. */ for (I = 0; I < CollCount (&MemoryAreas); ++I) { unsigned J; unsigned long Addr; unsigned Overwrites = 0; /* Get the next memory area */ MemoryArea* M = CollAtUnchecked (&MemoryAreas, I); /* Remember the offset in the output file */ M->FileOffs = M->F->Size; /* Remember if this is a relocatable memory area */ M->Relocatable = RelocatableBinFmt (M->F->Format); /* Resolve the start address expression, remember the start address, ** and mark the memory area as placed. */ if (!IsConstExpr (M->StartExpr)) { CfgError (GetSourcePos (M->LI), "Start address of memory area '%s' is not constant", GetString (M->Name)); } Addr = M->Start = GetExprVal (M->StartExpr); M->Flags |= MF_PLACED; /* If requested, define the symbol for the start of the memory area. ** Doing it here means that the expression for the size of the area ** may reference this symbol. */ if (M->Flags & MF_DEFINE) { Export* E; StrBuf Buf = STATIC_STRBUF_INITIALIZER; /* Define the start of the memory area */ SB_Printf (&Buf, "__%s_START__", GetString (M->Name)); E = CreateMemoryExport (GetStrBufId (&Buf), M, 0); CollAppend (&E->DefLines, M->LI); SB_Done (&Buf); } /* Resolve the size expression */ if (!IsConstExpr (M->SizeExpr)) { CfgError (GetSourcePos (M->LI), "Size of memory area '%s' is not constant", GetString (M->Name)); } M->Size = GetExprVal (M->SizeExpr); /* 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; /* Take note of "overwrite" segments and make sure there are no ** other segment types following them in current memory region. */ if (S->Flags & SF_OVERWRITE) { if (S->Flags & (SF_OFFSET | SF_START)) { ++Overwrites; } else { CfgError (GetSourcePos (M->LI), "Segment '%s' of type 'overwrite' requires either" " 'Start' or 'Offset' attribute to be specified", GetString (S->Name)); } } else { if (Overwrites > 0) { CfgError (GetSourcePos (M->LI), "Segment '%s' is preceded by at least one segment" " of type 'overwrite'", GetString (S->Name)); } } /* 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. */ /* Check if the alignment for the segment from the linker ** config is a multiple for that of the segment. ** If START or OFFSET is provided instead of ALIGN, check ** if its address fits alignment requirements. */ unsigned long AlignedBy = (S->Flags & SF_START) ? S->Addr : (S->Flags & SF_OFFSET) ? (S->Addr + M->Start) : S->RunAlignment; if ((AlignedBy % S->Seg->Alignment) != 0) { /* Segment requires another alignment than configured ** in the linker. */ CfgWarning (GetSourcePos (S->LI), "Segment '%s' isn't aligned properly; the" " resulting executable might not be functional.", GetString (S->Name)); } if (S->Flags & SF_ALIGN) { /* Align the address */ unsigned long NewAddr = AlignAddr (Addr, S->RunAlignment); /* If the first segment placed in the memory area needs ** fill bytes for the alignment, emit a warning, since ** that is somewhat suspicious. */ if (M->FillLevel == 0 && NewAddr > Addr) { CfgWarning (GetSourcePos (S->LI), "The first segment in memory area '%s' " "needs fill bytes for alignment.", GetString (M->Name)); } /* Use the aligned address */ Addr = NewAddr; } 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 (S->Flags & SF_OVERWRITE) { if (NewAddr < M->Start) { CfgError (GetSourcePos (S->LI), "Segment '%s' begins before memory area '%s'", GetString (S->Name), GetString (M->Name)); } else { Addr = NewAddr; } } else { if (NewAddr < Addr) { /* Offset already too large */ ++Overflows; if (S->Flags & SF_OFFSET) { 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 { 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; } } } /* Set the start address of this segment, set the readonly flag ** in the segment, and remember if the segment is in a ** relocatable file or not. */ S->Seg->PC = Addr; S->Seg->ReadOnly = (S->Flags & SF_RO) != 0; /* Remember the run memory for this segment, which is also a ** flag that the segment has been placed. */ S->Seg->MemArea = M; } else if (S->Load == M) { /* 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 ** 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 ** overflow. */ M->FillLevel = Addr + S->Seg->Size - M->Start; if (M->FillLevel > M->Size && (M->Flags & MF_OVERFLOW) == 0) { ++Overflows; M->Flags |= MF_OVERFLOW; CfgWarning (GetSourcePos (M->LI), "Segment '%s' overflows memory area '%s' by %lu byte%c", 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 ** segment. */ if (S->Flags & SF_DEFINE) { if (S->Run == M && (S->Flags & SF_RUN_DEF) == 0) { CreateRunDefines (S, Addr); } if (S->Load == M && (S->Flags & SF_LOAD_DEF) == 0) { CreateLoadDefines (S, Addr); } } /* Calculate the new address */ Addr += S->Seg->Size; /* If this segment will go out to the file, or its place ** in the file will be filled, then increase the file size. */ if (S->Load == M && ((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 ** memory area */ if (M->Flags & MF_DEFINE) { Export* E; StrBuf Buf = STATIC_STRBUF_INITIALIZER; /* Define the size of the memory area */ SB_Printf (&Buf, "__%s_SIZE__", GetString (M->Name)); E = CreateConstExport (GetStrBufId (&Buf), M->Size); CollAppend (&E->DefLines, M->LI); /* Define the fill level of the memory area */ SB_Printf (&Buf, "__%s_LAST__", GetString (M->Name)); E = CreateMemoryExport (GetStrBufId (&Buf), M, M->FillLevel); CollAppend (&E->DefLines, M->LI); /* Define the file offset of the memory area. This isn't of much ** use for relocatable output files. */ if (!M->Relocatable) { SB_Printf (&Buf, "__%s_FILEOFFS__", GetString (M->Name)); E = CreateConstExport (GetStrBufId (&Buf), M->FileOffs); CollAppend (&E->DefLines, M->LI); } /* Throw away the string buffer */ SB_Done (&Buf); } /* 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); } } /* Return the number of memory area overflows */ return Overflows; } void CfgWriteTarget (void) /* Write the target file(s) */ { unsigned I; /* Walk through the files list */ for (I = 0; I < CollCount (&FileList); ++I) { /* Get this entry */ File* F = CollAtUnchecked (&FileList, I); /* We don't need to look at files with no memory areas */ if (CollCount (&F->MemoryAreas) > 0) { /* Is there an output file? */ if (SB_GetLen (GetStrBuf (F->Name)) > 0) { /* Assign a proper binary format */ if (F->Format == BINFMT_DEFAULT) { F->Format = DefaultBinFmt; } /* Call the apropriate routine for the binary format */ switch (F->Format) { case BINFMT_BINARY: BinWriteTarget (BinFmtDesc, F); break; case BINFMT_O65: O65WriteTarget (O65FmtDesc, F); break; case BINFMT_ATARIEXE: XexWriteTarget (XexFmtDesc, F); break; default: Internal ("Invalid binary format: %u", F->Format); } } else { /* No output file. Walk through the list and mark all segments ** loading into these memory areas in this file as dumped. */ unsigned J; for (J = 0; J < CollCount (&F->MemoryAreas); ++J) { unsigned K; /* Get this entry */ MemoryArea* M = CollAtUnchecked (&F->MemoryAreas, J); /* Debugging */ Print (stdout, 2, "Skipping '%s'...\n", GetString (M->Name)); /* Walk throught the segments */ for (K = 0; K < CollCount (&M->SegList); ++K) { SegDesc* S = CollAtUnchecked (&M->SegList, K); if (S->Load == M) { /* Load area - mark the segment as dumped */ S->Seg->Dumped = 1; } } } } } } } �����������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/config.h�������������������������������������������������������������������������0000664�0000000�0000000�00000013732�13473601511�0015172�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* config.h */ /* */ /* Target configuration file for the ld65 linker */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef CONFIG_H #define CONFIG_H /* common */ #include "coll.h" #include "filepos.h" /* ld65 */ #include "lineinfo.h" #include "segments.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Forward for struct MemoryArea */ struct MemoryArea; /* File list entry */ typedef struct File File; struct File { unsigned Name; /* Name index of the file */ unsigned Flags; unsigned Format; /* Output format */ unsigned long Size; /* Size of the generated file */ Collection MemoryAreas; /* List of memory areas in this file */ }; /* Segment descriptor entry */ typedef struct SegDesc SegDesc; struct SegDesc { unsigned Name; /* Index of the name */ LineInfo* LI; /* Position of definition */ Segment* Seg; /* Pointer to segment structure */ unsigned Attr; /* Attributes for segment */ unsigned Flags; /* Set of bitmapped flags */ unsigned char FillVal; /* Fill value for this segment */ struct MemoryArea* Load; /* Load memory section */ struct MemoryArea* Run; /* Run memory section */ unsigned long Addr; /* Start address or offset into segment */ unsigned long RunAlignment; /* Run area alignment if given */ unsigned long LoadAlignment; /* Load area alignment if given */ }; /* Segment flags */ #define SF_RO 0x0001 /* Read only segment */ #define SF_BSS 0x0002 /* Segment is BSS style segment */ #define SF_ZP 0x0004 /* Zeropage segment (o65 only) */ #define SF_DEFINE 0x0008 /* Define start and size */ #define SF_ALIGN 0x0010 /* Align segment in run area */ #define SF_ALIGN_LOAD 0x0020 /* Align segment in load area */ #define SF_OFFSET 0x0040 /* Segment has offset in memory */ #define SF_START 0x0080 /* Segment has fixed start address */ #define SF_OPTIONAL 0x0100 /* Segment is optional (must not exist) */ #define SF_RUN_DEF 0x0200 /* RUN symbols already defined */ #define SF_LOAD_DEF 0x0400 /* LOAD symbols already defined */ #define SF_FILLVAL 0x0800 /* Segment has separate fill value */ #define SF_OVERWRITE 0x1000 /* Segment can overwrite (part of) another one */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ void CfgRead (void); /* Read the configuration */ 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). ** In case of overflows, a short mapfile can be generated later, to ease the ** task of rearranging segments for the user. */ void CfgWriteTarget (void); /* Write the target file(s) */ /* End of config.h */ #endif ��������������������������������������cc65-2.18/src/ld65/dbgfile.c������������������������������������������������������������������������0000664�0000000�0000000�00000013351�13473601511�0015311�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* dbgfile.c */ /* */ /* Debug file creation for the ld65 linker */ /* */ /* */ /* */ /* (C) 2003-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> #include <errno.h> /* ld65 */ #include "dbgfile.h" #include "dbgsyms.h" #include "error.h" #include "fileinfo.h" #include "global.h" #include "library.h" #include "lineinfo.h" #include "scopes.h" #include "segments.h" #include "span.h" #include "tpool.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void AssignIds (void) /* Assign the base ids for debug info output. Within each module, many of the ** items are addressed by ids which are actually the indices of the items in ** the collections. To make them unique, we must assign a unique base to each ** range. */ { /* Walk over all modules */ unsigned I; unsigned HLLSymBaseId = 0; unsigned ScopeBaseId = 0; unsigned SpanBaseId = 0; unsigned SymBaseId = 0; for (I = 0; I < CollCount (&ObjDataList); ++I) { /* Get this module */ ObjData* O = CollAt (&ObjDataList, I); /* Assign the module id */ O->Id = I; /* Assign base ids */ O->HLLSymBaseId = HLLSymBaseId; O->ScopeBaseId = ScopeBaseId; O->SpanBaseId = SpanBaseId; O->SymBaseId = SymBaseId; /* Bump the base ids */ HLLSymBaseId += CollCount (&O->HLLDbgSyms); ScopeBaseId += CollCount (&O->Scopes); SpanBaseId += CollCount (&O->Spans); SymBaseId += CollCount (&O->DbgSyms); } /* Assign the ids to the file infos */ AssignFileInfoIds (); /* Assign the ids to line infos */ AssignLineInfoIds (); } void CreateDbgFile (void) /* Create a debug info file */ { /* Open the debug info file */ FILE* F = fopen (DbgFileName, "w"); if (F == 0) { Error ("Cannot create debug file '%s': %s", DbgFileName, strerror (errno)); } /* Output version information */ fprintf (F, "version\tmajor=2,minor=0\n"); /* Output a line with the item numbers so the debug info module is able ** to preallocate the required memory. */ fprintf ( F, "info\tcsym=%u,file=%u,lib=%u,line=%u,mod=%u,scope=%u,seg=%u,span=%u,sym=%u,type=%u\n", HLLDbgSymCount (), FileInfoCount (), LibraryCount (), LineInfoCount (), ObjDataCount (), ScopeCount (), SegmentCount (), SpanCount (), DbgSymCount (), TypeCount () ); /* Assign the ids to the items */ AssignIds (); /* Output high level language symbols */ PrintHLLDbgSyms (F); /* Output files */ PrintDbgFileInfo (F); /* Output libraries */ PrintDbgLibraries (F); /* Output line info */ PrintDbgLineInfo (F); /* Output modules */ PrintDbgModules (F); /* Output the segment info */ PrintDbgSegments (F); /* Output spans */ PrintDbgSpans (F); /* Output scopes */ PrintDbgScopes (F); /* Output symbols */ PrintDbgSyms (F); /* Output types */ PrintDbgTypes (F); /* Close the file */ if (fclose (F) != 0) { Error ("Error closing debug file '%s': %s", DbgFileName, strerror (errno)); } } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/dbgfile.h������������������������������������������������������������������������0000664�0000000�0000000�00000005571�13473601511�0015323�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* dbgfile.h */ /* */ /* Debug file creation for the ld65 linker */ /* */ /* */ /* */ /* (C) 2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef DBGFILE_H #define DBGFILE_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ void CreateDbgFile (void); /* Create a debug info file */ /* End of dbgfile.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/dbgsyms.c������������������������������������������������������������������������0000664�0000000�0000000�00000041574�13473601511�0015375�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* dbgsyms.c */ /* */ /* Debug symbol handling for the ld65 linker */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* common */ #include "addrsize.h" #include "attrib.h" #include "check.h" #include "hlldbgsym.h" #include "symdefs.h" #include "xmalloc.h" /* ld65 */ #include "dbgsyms.h" #include "error.h" #include "exports.h" #include "expr.h" #include "fileio.h" #include "global.h" #include "lineinfo.h" #include "objdata.h" #include "spool.h" #include "tpool.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Definition of the debug symbol structure */ struct DbgSym { unsigned Id; /* Id of debug symbol */ DbgSym* Next; /* Pool linear list link */ ObjData* Obj; /* Object file that exports the name */ Collection DefLines; /* Line infos for definition */ Collection RefLines; /* Line infos for references */ ExprNode* Expr; /* Expression (0 if not def'd) */ unsigned Size; /* Symbol size if any */ unsigned OwnerId; /* Id of parent/owner */ unsigned ImportId; /* Id of import if this is one */ unsigned Name; /* Name */ unsigned short Type; /* Type of symbol */ unsigned short AddrSize; /* Address size of symbol */ }; /* Structure used for a high level language function or symbol */ typedef struct HLLDbgSym HLLDbgSym; struct HLLDbgSym { unsigned Flags; /* See above */ unsigned Name; /* String id of name */ DbgSym* Sym; /* Assembler symbol */ int Offs; /* Offset if any */ unsigned Type; /* String id of type */ unsigned ScopeId; /* Parent scope */ }; /* We will collect all debug symbols in the following array and remove ** duplicates before outputing them into a label file. */ static DbgSym* DbgSymPool[256]; /*****************************************************************************/ /* Code */ /*****************************************************************************/ static DbgSym* NewDbgSym (unsigned Id, unsigned Type, unsigned char AddrSize, ObjData* O) /* Create a new DbgSym and return it */ { /* Allocate memory */ DbgSym* D = xmalloc (sizeof (DbgSym)); /* Initialize the fields */ D->Id = Id; D->Next = 0; D->Obj = O; D->DefLines = EmptyCollection; D->RefLines = EmptyCollection; D->Expr = 0; D->Size = 0; D->OwnerId = ~0U; D->ImportId = ~0U; D->Name = 0; D->Type = Type; D->AddrSize = AddrSize; /* Return the new entry */ return D; } static HLLDbgSym* NewHLLDbgSym (void) /* Create a new HLLDbgSym and return it */ { /* Allocate memory and return it */ return xmalloc (sizeof (HLLDbgSym)); } static DbgSym* GetDbgSym (DbgSym* D, long Val) /* Check if we find the same debug symbol in the table. If we find it, return ** a pointer to the other occurrence, if we didn't find it, return NULL. */ { /* Create the hash. We hash over the symbol value */ unsigned Hash = ((Val >> 24) & 0xFF) ^ ((Val >> 16) & 0xFF) ^ ((Val >> 8) & 0xFF) ^ ((Val >> 0) & 0xFF); /* Check for this symbol */ DbgSym* Sym = DbgSymPool[Hash]; while (Sym) { /* Is this symbol identical? */ if (Sym->Name == D->Name && EqualExpr (Sym->Expr, D->Expr)) { /* Found */ return Sym; } /* Next symbol */ Sym = Sym->Next; } /* This is the first symbol of it's kind */ return 0; } static void InsertDbgSym (DbgSym* D, long Val) /* Insert the symbol into the hashed symbol pool */ { /* Create the hash. We hash over the symbol value */ unsigned Hash = ((Val >> 24) & 0xFF) ^ ((Val >> 16) & 0xFF) ^ ((Val >> 8) & 0xFF) ^ ((Val >> 0) & 0xFF); /* Insert the symbol */ D->Next = DbgSymPool [Hash]; DbgSymPool [Hash] = D; } DbgSym* ReadDbgSym (FILE* F, ObjData* O, unsigned Id) /* Read a debug symbol from a file, insert and return it */ { /* Read the type and address size */ unsigned Type = ReadVar (F); unsigned char AddrSize = Read8 (F); /* Create a new debug symbol */ DbgSym* D = NewDbgSym (Id, Type, AddrSize, O); /* Read the id of the owner scope/symbol */ D->OwnerId = ReadVar (F); /* Read and assign the name */ D->Name = MakeGlobalStringId (O, ReadVar (F)); /* Read the value */ if (SYM_IS_EXPR (D->Type)) { D->Expr = ReadExpr (F, O); } else { D->Expr = LiteralExpr (Read32 (F), O); } /* Read the size */ if (SYM_HAS_SIZE (D->Type)) { D->Size = ReadVar (F); } /* If this is an import, the file contains its id */ if (SYM_IS_IMPORT (D->Type)) { D->ImportId = ReadVar (F); } /* If its an exports, there's also the export id, but we don't remember ** it but use it to let the export point back to us. */ if (SYM_IS_EXPORT (D->Type)) { /* Get the export from the export id, then set the our id */ GetObjExport (O, ReadVar (F))->DbgSymId = Id; } /* Last is the list of line infos for this symbol */ ReadLineInfoList (F, O, &D->DefLines); ReadLineInfoList (F, O, &D->RefLines); /* Return the new DbgSym */ return D; } HLLDbgSym* ReadHLLDbgSym (FILE* F, ObjData* O, unsigned Id attribute ((unused))) /* Read a hll debug symbol from a file, insert and return it */ { unsigned SC; /* Create a new HLLDbgSym */ HLLDbgSym* S = NewHLLDbgSym (); /* Read the data */ S->Flags = ReadVar (F); SC = HLL_GET_SC (S->Flags); S->Name = MakeGlobalStringId (O, ReadVar (F)); if (HLL_HAS_SYM (S->Flags)) { S->Sym = GetObjDbgSym (O, ReadVar (F)); } else { /* Auto variables aren't attached to asm symbols */ S->Sym = 0; } if (SC == HLL_SC_AUTO || SC == HLL_SC_REG) { S->Offs = ReadVar (F); } else { S->Offs = 0; } S->Type = GetTypeId (GetObjString (O, ReadVar (F))); S->ScopeId = ReadVar (F); /* Return the (now initialized) hll debug symbol */ return S; } static void ClearDbgSymTable (void) /* Clear the debug symbol table */ { unsigned I; for (I = 0; I < sizeof (DbgSymPool) / sizeof (DbgSymPool[0]); ++I) { DbgSym* Sym = DbgSymPool[I]; DbgSymPool[I] = 0; while (Sym) { DbgSym* NextSym = Sym->Next; Sym->Next = 0; Sym = NextSym; } } } static long GetDbgSymVal (const DbgSym* D) /* Get the value of this symbol */ { CHECK (D->Expr != 0); return GetExprVal (D->Expr); } static void PrintLineInfo (FILE* F, const Collection* LineInfos, const char* Format) /* Output an attribute with line infos */ { if (CollCount (LineInfos) > 0) { unsigned I; const LineInfo* LI = CollConstAt (LineInfos, 0); fprintf (F, Format, LI->Id); for (I = 1; I < CollCount (LineInfos); ++I) { LI = CollConstAt (LineInfos, I); fprintf (F, "+%u", LI->Id); } } } unsigned DbgSymCount (void) /* Return the total number of debug symbols */ { /* Walk over all object files */ unsigned I; unsigned Count = 0; for (I = 0; I < CollCount (&ObjDataList); ++I) { /* Get this object file */ const ObjData* O = CollAtUnchecked (&ObjDataList, I); /* Count debug symbols */ Count += CollCount (&O->DbgSyms); } return Count; } unsigned HLLDbgSymCount (void) /* Return the total number of high level language debug symbols */ { /* Walk over all object files */ unsigned I; unsigned Count = 0; for (I = 0; I < CollCount (&ObjDataList); ++I) { /* Get this object file */ const ObjData* O = CollAtUnchecked (&ObjDataList, I); /* Count debug symbols */ Count += CollCount (&O->HLLDbgSyms); } return Count; } void PrintDbgSyms (FILE* F) /* Print the debug symbols in a debug file */ { unsigned I, J; for (I = 0; I < CollCount (&ObjDataList); ++I) { /* Get the object file */ ObjData* O = CollAtUnchecked (&ObjDataList, I); /* Walk through all debug symbols in this module */ for (J = 0; J < CollCount (&O->DbgSyms); ++J) { /* Get the next debug symbol */ const DbgSym* S = CollConstAt (&O->DbgSyms, J); /* Emit the base data for the entry */ fprintf (F, "sym\tid=%u,name=\"%s\",addrsize=%s", O->SymBaseId + J, GetString (S->Name), AddrSizeToStr ((unsigned char) S->AddrSize)); /* Emit the size only if we know it */ if (S->Size != 0) { fprintf (F, ",size=%u", S->Size); } /* For cheap local symbols, add the owner symbol, for others, ** add the owner scope. */ if (SYM_IS_STD (S->Type)) { fprintf (F, ",scope=%u", O->ScopeBaseId + S->OwnerId); } else { fprintf (F, ",parent=%u", O->SymBaseId + S->OwnerId); } /* Output line infos */ PrintLineInfo (F, &S->DefLines, ",def=%u"); PrintLineInfo (F, &S->RefLines, ",ref=%u"); /* If this is an import, output the id of the matching export. ** If this is not an import, output its value and - if we have ** it - the segment. */ if (SYM_IS_IMPORT (S->Type)) { /* Get the import */ const Import* Imp = GetObjImport (O, S->ImportId); /* Get the export from the import */ const Export* Exp = Imp->Exp; /* Output the type */ fputs (",type=imp", F); /* If this is not a linker generated symbol, and the module ** that contains the export has debug info, output the debug ** symbol id for the export */ if (Exp->Obj && OBJ_HAS_DBGINFO (Exp->Obj->Header.Flags)) { fprintf (F, ",exp=%u", Exp->Obj->SymBaseId + Exp->DbgSymId); } } else { SegExprDesc D; /* Get the symbol value */ long Val = GetDbgSymVal (S); /* Output it */ fprintf (F, ",val=0x%lX", Val); /* Check for a segmented expression and add the segment id to ** the debug info if we have one. */ GetSegExprVal (S->Expr, &D); if (!D.TooComplex && D.Seg != 0) { fprintf (F, ",seg=%u", D.Seg->Id); } /* Output the type */ fprintf (F, ",type=%s", SYM_IS_LABEL (S->Type)? "lab" : "equ"); } /* Terminate the output line */ fputc ('\n', F); } } } void PrintHLLDbgSyms (FILE* F) /* Print the high level language debug symbols in a debug file */ { unsigned I, J; for (I = 0; I < CollCount (&ObjDataList); ++I) { /* Get the object file */ ObjData* O = CollAtUnchecked (&ObjDataList, I); /* Walk through all hll debug symbols in this module */ for (J = 0; J < CollCount (&O->HLLDbgSyms); ++J) { /* Get the next debug symbol */ const HLLDbgSym* S = CollConstAt (&O->HLLDbgSyms, J); /* Get the storage class */ unsigned SC = HLL_GET_SC (S->Flags); /* Output the base info */ fprintf (F, "csym\tid=%u,name=\"%s\",scope=%u,type=%u,sc=", O->HLLSymBaseId + J, GetString (S->Name), O->ScopeBaseId + S->ScopeId, S->Type); switch (SC) { case HLL_SC_AUTO: fputs ("auto", F); break; case HLL_SC_REG: fputs ("reg", F); break; case HLL_SC_STATIC: fputs ("static", F); break; case HLL_SC_EXTERN: fputs ("ext", F); break; default: Error ("Invalid storage class %u for hll symbol", SC); break; } /* Output the offset if it is not zero */ if (S->Offs) { fprintf (F, ",offs=%d", S->Offs); } /* For non auto symbols output the debug symbol id of the asm sym */ if (HLL_HAS_SYM (S->Flags)) { fprintf (F, ",sym=%u", O->SymBaseId + S->Sym->Id); } /* Terminate the output line */ fputc ('\n', F); } } } void PrintDbgSymLabels (FILE* F) /* Print the debug symbols in a VICE label file */ { unsigned I, J; /* Clear the symbol table */ ClearDbgSymTable (); /* Create labels from all modules we have linked into the output file */ for (I = 0; I < CollCount (&ObjDataList); ++I) { /* Get the object file */ ObjData* O = CollAtUnchecked (&ObjDataList, I); /* Walk through all debug symbols in this module */ for (J = 0; J < CollCount (&O->DbgSyms); ++J) { long Val; /* Get the next debug symbol */ DbgSym* D = CollAt (&O->DbgSyms, J); /* Emit this symbol only if it is a label (ignore equates and imports) */ if (SYM_IS_EQUATE (D->Type) || SYM_IS_IMPORT (D->Type)) { continue; } /* Get the symbol value */ Val = GetDbgSymVal (D); /* Lookup this symbol in the table. If it is found in the table, it was ** already written to the file, so don't emit it twice. If it is not in ** the table, insert and output it. */ if (GetDbgSym (D, Val) == 0) { /* Emit the VICE label line */ fprintf (F, "al %06lX .%s\n", Val, GetString (D->Name)); /* Insert the symbol into the table */ InsertDbgSym (D, Val); } } } } ������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/dbgsyms.h������������������������������������������������������������������������0000664�0000000�0000000�00000007706�13473601511�0015401�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* dbgsyms.h */ /* */ /* Debug symbol handling for the ld65 linker */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef DBGSYMS_H #define DBGSYMS_H #include <stdio.h> /* common */ #include "coll.h" #include "exprdefs.h" /* ld65 */ #include "objdata.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Forwards */ struct Scope; struct HLLDbgSym; /* Opaque debug symbol structure */ typedef struct DbgSym DbgSym; /*****************************************************************************/ /* Code */ /*****************************************************************************/ DbgSym* ReadDbgSym (FILE* F, ObjData* Obj, unsigned Id); /* Read a debug symbol from a file, insert and return it */ struct HLLDbgSym* ReadHLLDbgSym (FILE* F, ObjData* Obj, unsigned Id); /* Read a hll debug symbol from a file, insert and return it */ void PrintDbgSyms (FILE* F); /* Print the debug symbols in a debug file */ unsigned DbgSymCount (void); /* Return the total number of debug symbols */ unsigned HLLDbgSymCount (void); /* Return the total number of high level language debug symbols */ void PrintHLLDbgSyms (FILE* F); /* Print the high level language debug symbols in a debug file */ void PrintDbgSymLabels (FILE* F); /* Print the debug symbols in a VICE label file */ /* End of dbgsyms.h */ #endif ����������������������������������������������������������cc65-2.18/src/ld65/error.c��������������������������������������������������������������������������0000664�0000000�0000000�00000007661�13473601511�0015055�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* error.c */ /* */ /* Error handling for the ld65 linker */ /* */ /* */ /* */ /* (C) 1998-2008 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> /* common */ #include "cmdline.h" #include "strbuf.h" /* ld65 */ #include "error.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Warning (const char* Format, ...) /* Print a warning message */ { StrBuf S = STATIC_STRBUF_INITIALIZER; va_list ap; va_start (ap, Format); SB_VPrintf (&S, Format, ap); va_end (ap); SB_Terminate (&S); fprintf (stderr, "%s: Warning: %s\n", ProgName, SB_GetConstBuf (&S)); SB_Done (&S); } void Error (const char* Format, ...) /* Print an error message and die */ { StrBuf S = STATIC_STRBUF_INITIALIZER; va_list ap; va_start (ap, Format); SB_VPrintf (&S, Format, ap); va_end (ap); SB_Terminate (&S); fprintf (stderr, "%s: Error: %s\n", ProgName, SB_GetConstBuf (&S)); SB_Done (&S); exit (EXIT_FAILURE); } void Internal (const char* Format, ...) /* Print an internal error message and die */ { StrBuf S = STATIC_STRBUF_INITIALIZER; va_list ap; va_start (ap, Format); SB_VPrintf (&S, Format, ap); va_end (ap); SB_Terminate (&S); fprintf (stderr, "%s: Internal Error: %s\n", ProgName, SB_GetConstBuf (&S)); SB_Done (&S); exit (EXIT_FAILURE); } �������������������������������������������������������������������������������cc65-2.18/src/ld65/error.h��������������������������������������������������������������������������0000664�0000000�0000000�00000006273�13473601511�0015060�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* error.h */ /* */ /* Error handling for the ld65 linker */ /* */ /* */ /* */ /* (C) 1998-2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef ERROR_H #define ERROR_H /* common */ #include "attrib.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Warning (const char* Format, ...) attribute((format(printf,1,2))); /* Print a warning message */ void Error (const char* Format, ...) attribute((noreturn, format(printf,1,2))); /* Print an error message and die */ void Internal (const char* Format, ...) attribute((noreturn, format(printf,1,2))); /* Print an internal error message and die */ /* End of error.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/exports.c������������������������������������������������������������������������0000664�0000000�0000000�00000073156�13473601511�0015432�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* exports.c */ /* */ /* Exports handling for the ld65 linker */ /* */ /* */ /* */ /* (C) 1998-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> /* common */ #include "addrsize.h" #include "check.h" #include "hashfunc.h" #include "lidefs.h" #include "symdefs.h" #include "xmalloc.h" /* ld65 */ #include "condes.h" #include "error.h" #include "exports.h" #include "expr.h" #include "fileio.h" #include "global.h" #include "lineinfo.h" #include "memarea.h" #include "objdata.h" #include "spool.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Hash table */ #define HASHTAB_MASK 0x0FFFU #define HASHTAB_SIZE (HASHTAB_MASK + 1) static Export* HashTab[HASHTAB_SIZE]; /* Import management variables */ static unsigned ImpCount = 0; /* Import count */ static unsigned ImpOpen = 0; /* Count of open imports */ /* Export management variables */ static unsigned ExpCount = 0; /* Export count */ static Export** ExpPool = 0; /* Exports array */ /* Defines for the flags in Import */ #define IMP_INLIST 0x0001U /* Import is in exports list */ /* Defines for the flags in Export */ #define EXP_INLIST 0x0001U /* Export is in exports list */ #define EXP_USERMARK 0x0002U /* User setable flag */ /*****************************************************************************/ /* Import handling */ /*****************************************************************************/ static Export* NewExport (unsigned Type, unsigned char AddrSize, unsigned Name, ObjData* Obj); /* Create a new export and initialize it */ static Import* NewImport (unsigned char AddrSize, ObjData* Obj) /* Create a new import and initialize it */ { /* Allocate memory */ Import* I = xmalloc (sizeof (Import)); /* Initialize the fields */ I->Next = 0; I->Obj = Obj; I->DefLines = EmptyCollection; I->RefLines = EmptyCollection; I->Exp = 0; I->Name = INVALID_STRING_ID; I->Flags = 0; I->AddrSize = AddrSize; /* Return the new structure */ return I; } void FreeImport (Import* I) /* Free an import. NOTE: This won't remove the import from the exports table, ** so it may only be called for unused imports (imports from modules that ** aren't referenced). */ { /* Safety */ PRECONDITION ((I->Flags & IMP_INLIST) == 0); /* Free the line info collections */ DoneCollection (&I->DefLines); DoneCollection (&I->RefLines); /* Free the struct */ xfree (I); } Import* ReadImport (FILE* F, ObjData* Obj) /* Read an import from a file and return it */ { Import* I; /* Read the import address size */ unsigned char AddrSize = Read8 (F); /* Create a new import */ I = NewImport (AddrSize, Obj); /* Read the name */ I->Name = MakeGlobalStringId (Obj, ReadVar (F)); /* Read the line infos */ ReadLineInfoList (F, Obj, &I->DefLines); ReadLineInfoList (F, Obj, &I->RefLines); /* Check the address size */ if (I->AddrSize == ADDR_SIZE_DEFAULT || I->AddrSize > ADDR_SIZE_LONG) { /* Beware: This function may be called in cases where the object file ** is not read completely into memory. In this case, the file list is ** invalid. Be sure not to access it in this case. */ if (ObjHasFiles (I->Obj)) { const LineInfo* LI = GetImportPos (I); Error ("Invalid import size in for '%s', imported from %s(%u): 0x%02X", GetString (I->Name), GetSourceName (LI), GetSourceLine (LI), I->AddrSize); } else { Error ("Invalid import size in for '%s', imported from %s: 0x%02X", GetString (I->Name), GetObjFileName (I->Obj), I->AddrSize); } } /* Return the new import */ return I; } Import* GenImport (unsigned Name, unsigned char AddrSize) /* Generate a new import with the given name and address size and return it */ { /* Create a new import */ Import* I = NewImport (AddrSize, 0); /* Read the name */ I->Name = Name; /* Check the address size */ if (I->AddrSize == ADDR_SIZE_DEFAULT || I->AddrSize > ADDR_SIZE_LONG) { /* We have no object file information and no line info for a new ** import */ Error ("Invalid import size 0x%02X for symbol '%s'", I->AddrSize, GetString (I->Name)); } /* Return the new import */ return I; } Import* InsertImport (Import* I) /* Insert an import into the table, return I */ { Export* E; /* As long as the import is not inserted, V.Name is valid */ unsigned Name = I->Name; /* Create a hash value for the given name */ unsigned Hash = (Name & HASHTAB_MASK); /* Search through the list in that slot for a symbol with that name */ if (HashTab[Hash] == 0) { /* The slot is empty, we need to insert a dummy export */ E = HashTab[Hash] = NewExport (0, ADDR_SIZE_DEFAULT, Name, 0); ++ExpCount; } else { E = HashTab [Hash]; while (1) { if (E->Name == Name) { /* We have an entry, L points to it */ break; } if (E->Next == 0) { /* End of list an entry not found, insert a dummy */ E->Next = NewExport (0, ADDR_SIZE_DEFAULT, Name, 0); E = E->Next; /* Point to dummy */ ++ExpCount; /* One export more */ break; } else { E = E->Next; } } } /* Ok, E now points to a valid exports entry for the given import. Insert ** the import into the imports list and update the counters. */ I->Exp = E; I->Next = E->ImpList; E->ImpList = I; E->ImpCount++; ++ImpCount; /* Total import count */ if (E->Expr == 0) { /* This is a dummy export */ ++ImpOpen; } /* Mark the import so we know it's in the list */ I->Flags |= IMP_INLIST; /* Return the import to allow shorter code */ return I; } const LineInfo* GetImportPos (const Import* Imp) /* Return the basic line info of an import */ { /* Search in DefLines, then in RefLines */ const LineInfo* LI = GetAsmLineInfo (&Imp->DefLines); if (LI == 0) { LI = GetAsmLineInfo (&Imp->RefLines); } return LI; } /*****************************************************************************/ /* Code */ /*****************************************************************************/ static Export* NewExport (unsigned Type, unsigned char AddrSize, unsigned Name, ObjData* Obj) /* Create a new export and initialize it */ { unsigned I; /* Allocate memory */ Export* E = xmalloc (sizeof (Export)); /* Initialize the fields */ E->Name = Name; E->Next = 0; E->Flags = 0; E->Obj = Obj; E->ImpCount = 0; E->ImpList = 0; E->Expr = 0; E->Size = 0; E->DefLines = EmptyCollection; E->RefLines = EmptyCollection; E->DbgSymId = ~0U; E->Type = Type | SYM_EXPORT; E->AddrSize = AddrSize; for (I = 0; I < sizeof (E->ConDes) / sizeof (E->ConDes[0]); ++I) { E->ConDes[I] = CD_PRIO_NONE; } /* Return the new entry */ return E; } void FreeExport (Export* E) /* Free an export. NOTE: This won't remove the export from the exports table, ** so it may only be called for unused exports (exports from modules that ** aren't referenced). */ { /* Safety */ PRECONDITION ((E->Flags & EXP_INLIST) == 0); /* Free the line infos */ DoneCollection (&E->DefLines); DoneCollection (&E->RefLines); /* Free the export expression */ FreeExpr (E->Expr); /* Free the struct */ xfree (E); } Export* ReadExport (FILE* F, ObjData* O) /* Read an export from a file */ { unsigned ConDesCount; unsigned I; Export* E; /* Read the type */ unsigned Type = ReadVar (F); /* Read the address size */ unsigned char AddrSize = Read8 (F); /* Create a new export without a name */ E = NewExport (Type, AddrSize, INVALID_STRING_ID, O); /* Read the constructor/destructor decls if we have any */ ConDesCount = SYM_GET_CONDES_COUNT (Type); if (ConDesCount > 0) { unsigned char ConDes[CD_TYPE_COUNT]; /* Read the data into temp storage */ ReadData (F, ConDes, ConDesCount); /* Re-order the data. In the file, each decl is encoded into a byte ** which contains the type and the priority. In memory, we will use ** an array of types which contain the priority. */ for (I = 0; I < ConDesCount; ++I) { E->ConDes[CD_GET_TYPE (ConDes[I])] = CD_GET_PRIO (ConDes[I]); } } /* Read the name */ E->Name = MakeGlobalStringId (O, ReadVar (F)); /* Read the value */ if (SYM_IS_EXPR (Type)) { E->Expr = ReadExpr (F, O); } else { E->Expr = LiteralExpr (Read32 (F), O); } /* Read the size */ if (SYM_HAS_SIZE (Type)) { E->Size = ReadVar (F); } /* Last are the locations */ ReadLineInfoList (F, O, &E->DefLines); ReadLineInfoList (F, O, &E->RefLines); /* If this symbol is exported as a condes, and the condes type declares a ** forced import, add this import to the object module. */ for (I = 0; I < CD_TYPE_COUNT; ++I) { const ConDesImport* CDI; if (E->ConDes[I] != CD_PRIO_NONE && (CDI = ConDesGetImport (I)) != 0) { unsigned J; /* Generate a new import, and add it to the module's import list. */ Import* Imp = GenImport (CDI->Name, CDI->AddrSize); Imp->Obj = O; CollAppend (&O->Imports, Imp); /* Add line info for the export that is actually the condes that ** forces the import. Then, add line info for the config. file. ** The export's info is added first because the import pretends ** that it came from the object module instead of the config. file. */ for (J = 0; J < CollCount (&E->DefLines); ++J) { CollAppend (&Imp->RefLines, DupLineInfo (CollAt (&E->DefLines, J))); } CollAppend (&Imp->RefLines, GenLineInfo (&CDI->Pos)); } } /* Return the new export */ return E; } void InsertExport (Export* E) /* Insert an exported identifier and check if it's already in the list */ { Export* L; Export* Last; Import* Imp; unsigned Hash; /* Mark the export as inserted */ E->Flags |= EXP_INLIST; /* Insert the export into any condes tables if needed */ if (SYM_IS_CONDES (E->Type)) { ConDesAddExport (E); } /* Create a hash value for the given name */ Hash = (E->Name & HASHTAB_MASK); /* Search through the list in that slot */ if (HashTab[Hash] == 0) { /* The slot is empty */ HashTab[Hash] = E; ++ExpCount; } else { Last = 0; L = HashTab[Hash]; do { if (L->Name == E->Name) { /* This may be an unresolved external */ if (L->Expr == 0) { /* This *is* an unresolved external. Use the actual export ** in E instead of the dummy one in L. */ E->Next = L->Next; E->ImpCount = L->ImpCount; E->ImpList = L->ImpList; if (Last) { Last->Next = E; } else { HashTab[Hash] = E; } ImpOpen -= E->ImpCount; /* Decrease open imports now */ xfree (L); /* We must run through the import list and change the ** export pointer now. */ Imp = E->ImpList; while (Imp) { Imp->Exp = E; Imp = Imp->Next; } } else if (AllowMultDef == 0) { /* Duplicate entry, this is fatal unless allowed by the user */ Error ("Duplicate external identifier: '%s'", GetString (L->Name)); } return; } Last = L; L = L->Next; } while (L); /* Insert export at end of queue */ Last->Next = E; ++ExpCount; } } const LineInfo* GetExportPos (const Export* E) /* Return the basic line info of an export */ { /* Search in DefLines, then in RefLines */ const LineInfo* LI = GetAsmLineInfo (&E->DefLines); if (LI == 0) { LI = GetAsmLineInfo (&E->RefLines); } return LI; } Export* CreateConstExport (unsigned Name, long Value) /* Create an export for a literal date */ { /* Create a new export */ Export* E = NewExport (SYM_CONST|SYM_EQUATE, ADDR_SIZE_ABS, Name, 0); /* Assign the value */ E->Expr = LiteralExpr (Value, 0); /* Insert the export */ InsertExport (E); /* Return the new export */ return E; } Export* CreateExprExport (unsigned Name, ExprNode* Expr, unsigned char AddrSize) /* Create an export for an expression */ { /* Create a new export */ Export* E = NewExport (SYM_EXPR|SYM_EQUATE, AddrSize, Name, 0); /* Assign the value expression */ E->Expr = Expr; /* Insert the export */ InsertExport (E); /* Return the new export */ return E; } Export* CreateMemoryExport (unsigned Name, MemoryArea* Mem, unsigned long Offs) /* Create an relative export for a memory area offset */ { /* Create a new export */ Export* E = NewExport (SYM_EXPR | SYM_LABEL, ADDR_SIZE_ABS, Name, 0); /* Assign the value */ E->Expr = MemoryExpr (Mem, Offs, 0); /* Insert the export */ InsertExport (E); /* Return the new export */ return E; } Export* CreateSegmentExport (unsigned Name, Segment* Seg, unsigned long Offs) /* Create a relative export to a segment */ { /* Create a new export */ Export* E = NewExport (SYM_EXPR | SYM_LABEL, Seg->AddrSize, Name, 0); /* Assign the value */ E->Expr = SegmentExpr (Seg, Offs, 0); /* Insert the export */ InsertExport (E); /* Return the new export */ return E; } Export* CreateSectionExport (unsigned Name, Section* Sec, unsigned long Offs) /* Create a relative export to a section */ { /* Create a new export */ Export* E = NewExport (SYM_EXPR | SYM_LABEL, Sec->AddrSize, Name, 0); /* Assign the value */ E->Expr = SectionExpr (Sec, Offs, 0); /* Insert the export */ InsertExport (E); /* Return the new export */ return E; } Export* FindExport (unsigned Name) /* Check for an identifier in the list. Return 0 if not found, otherwise ** return a pointer to the export. */ { /* Get a pointer to the list with the symbols hash value */ Export* L = HashTab[Name & HASHTAB_MASK]; while (L) { /* Search through the list in that slot */ if (L->Name == Name) { /* Entry found */ return L; } L = L->Next; } /* Not found */ return 0; } int IsUnresolved (unsigned Name) /* Check if this symbol is an unresolved export */ { /* Find the export */ return IsUnresolvedExport (FindExport (Name)); } int IsUnresolvedExport (const Export* E) /* Return true if the given export is unresolved */ { /* Check if it's unresolved */ return E != 0 && E->Expr == 0; } int IsConstExport (const Export* E) /* Return true if the expression associated with this export is const */ { if (E->Expr == 0) { /* External symbols cannot be const */ return 0; } else { return IsConstExpr (E->Expr); } } long GetExportVal (const Export* E) /* Get the value of this export */ { if (E->Expr == 0) { /* OOPS */ Internal ("'%s' is an undefined external", GetString (E->Name)); } return GetExprVal (E->Expr); } static void CheckSymType (const Export* E) /* Check the types for one export */ { /* External with matching imports */ Import* I = E->ImpList; while (I) { if (E->AddrSize != I->AddrSize) { /* Export and import address sizes do not match */ StrBuf ExportLoc = STATIC_STRBUF_INITIALIZER; StrBuf ImportLoc = STATIC_STRBUF_INITIALIZER; const char* ExpAddrSize = AddrSizeToStr ((unsigned char) E->AddrSize); const char* ImpAddrSize = AddrSizeToStr ((unsigned char) I->AddrSize); const LineInfo* ExportLI = GetExportPos (E); const LineInfo* ImportLI = GetImportPos (I); /* Generate strings that describe the location of the im- and ** exports. This depends on the place from where they come: ** Object file or linker config. */ if (E->Obj) { /* The export comes from an object file */ SB_Printf (&ExportLoc, "%s, %s(%u)", GetString (E->Obj->Name), GetSourceName (ExportLI), GetSourceLine (ExportLI)); } else { SB_Printf (&ExportLoc, "%s(%u)", GetSourceName (ExportLI), GetSourceLine (ExportLI)); } if (I->Obj) { /* The import comes from an object file */ SB_Printf (&ImportLoc, "%s, %s(%u)", GetString (I->Obj->Name), GetSourceName (ImportLI), GetSourceLine (ImportLI)); } else if (ImportLI) { /* The import is linker generated and we have line ** information */ SB_Printf (&ImportLoc, "%s(%u)", GetSourceName (ImportLI), GetSourceLine (ImportLI)); } else { /* The import is linker generated and we don't have line ** information */ SB_Printf (&ImportLoc, "%s", GetObjFileName (I->Obj)); } /* Output the diagnostic */ Warning ("Address size mismatch for '%s': " "Exported from %s as '%s', " "import in %s as '%s'", GetString (E->Name), SB_GetConstBuf (&ExportLoc), ExpAddrSize, SB_GetConstBuf (&ImportLoc), ImpAddrSize); /* Free the temporary strings */ SB_Done (&ExportLoc); SB_Done (&ImportLoc); } I = I->Next; } } static void CheckSymTypes (void) /* Check for symbol tape mismatches */ { unsigned I; /* Print all open imports */ for (I = 0; I < ExpCount; ++I) { const Export* E = ExpPool [I]; if (E->Expr != 0 && E->ImpCount > 0) { /* External with matching imports */ CheckSymType (E); } } } static void PrintUnresolved (ExpCheckFunc F, void* Data) /* Print a list of unresolved symbols. On unresolved symbols, F is ** called (see the comments on ExpCheckFunc in the data section). */ { unsigned I; /* Print all open imports */ for (I = 0; I < ExpCount; ++I) { Export* E = ExpPool [I]; if (E->Expr == 0 && E->ImpCount > 0 && F (E->Name, Data) == 0) { /* Unresolved external */ Import* Imp = E->ImpList; fprintf (stderr, "Unresolved external '%s' referenced in:\n", GetString (E->Name)); while (Imp) { unsigned J; for (J = 0; J < CollCount (&Imp->RefLines); ++J) { const LineInfo* LI = CollConstAt (&Imp->RefLines, J); fprintf (stderr, " %s(%u)\n", GetSourceName (LI), GetSourceLine (LI)); } Imp = Imp->Next; } } } } static int CmpExpName (const void* K1, const void* K2) /* Compare function for qsort */ { return SB_Compare (GetStrBuf ((*(Export**)K1)->Name), GetStrBuf ((*(Export**)K2)->Name)); } static void CreateExportPool (void) /* Create an array with pointer to all exports */ { unsigned I, J; /* Allocate memory */ if (ExpPool) { xfree (ExpPool); } ExpPool = xmalloc (ExpCount * sizeof (Export*)); /* Walk through the list and insert the exports */ for (I = 0, J = 0; I < sizeof (HashTab) / sizeof (HashTab [0]); ++I) { Export* E = HashTab[I]; while (E) { CHECK (J < ExpCount); ExpPool[J++] = E; E = E->Next; } } /* Sort them by name */ qsort (ExpPool, ExpCount, sizeof (Export*), CmpExpName); } void CheckExports (void) /* Setup the list of all exports and check for export/import symbol type ** mismatches. */ { /* Create an export pool */ CreateExportPool (); /* Check for symbol type mismatches */ CheckSymTypes (); } void CheckUnresolvedImports (ExpCheckFunc F, void* Data) /* Check if there are any unresolved imports. On unresolved imports, F is ** called (see the comments on ExpCheckFunc in the data section). */ { /* Check for unresolved externals */ if (ImpOpen != 0) { /* Print all open imports */ PrintUnresolved (F, Data); } } static char GetAddrSizeCode (unsigned char AddrSize) /* Get a one char code for the address size */ { switch (AddrSize) { case ADDR_SIZE_ZP: return 'Z'; case ADDR_SIZE_ABS: return 'A'; case ADDR_SIZE_FAR: return 'F'; case ADDR_SIZE_LONG: return 'L'; default: Internal ("Invalid address size: %u", AddrSize); /* NOTREACHED */ return '-'; } } void PrintExportMapByName (FILE* F) /* Print an export map, sorted by symbol name, to the given file */ { unsigned I; unsigned Count; /* Print all exports */ Count = 0; for (I = 0; I < ExpCount; ++I) { const Export* E = ExpPool [I]; /* Print unreferenced symbols only if explictly requested */ if (VerboseMap || E->ImpCount > 0 || SYM_IS_CONDES (E->Type)) { fprintf (F, "%-25s %06lX %c%c%c%c ", GetString (E->Name), GetExportVal (E), E->ImpCount? 'R' : ' ', SYM_IS_LABEL (E->Type)? 'L' : 'E', GetAddrSizeCode ((unsigned char) E->AddrSize), SYM_IS_CONDES (E->Type)? 'I' : ' '); if (++Count == 2) { Count = 0; fprintf (F, "\n"); } } } fprintf (F, "\n"); } static int CmpExpValue (const void* I1, const void* I2) /* Compare function for qsort */ { long V1 = GetExportVal (ExpPool [*(unsigned *)I1]); long V2 = GetExportVal (ExpPool [*(unsigned *)I2]); return V1 < V2 ? -1 : V1 == V2 ? 0 : 1; } void PrintExportMapByValue (FILE* F) /* Print an export map, sorted by symbol value, to the given file */ { unsigned I; unsigned Count; unsigned *ExpValXlat; /* Create a translation table where the symbols are sorted by value. */ ExpValXlat = xmalloc (ExpCount * sizeof (unsigned)); for (I = 0; I < ExpCount; ++I) { /* Initialize table with current sort order. */ ExpValXlat [I] = I; } /* Sort them by value */ qsort (ExpValXlat, ExpCount, sizeof (unsigned), CmpExpValue); /* Print all exports */ Count = 0; for (I = 0; I < ExpCount; ++I) { const Export* E = ExpPool [ExpValXlat [I]]; /* Print unreferenced symbols only if explictly requested */ if (VerboseMap || E->ImpCount > 0 || SYM_IS_CONDES (E->Type)) { fprintf (F, "%-25s %06lX %c%c%c%c ", GetString (E->Name), GetExportVal (E), E->ImpCount? 'R' : ' ', SYM_IS_LABEL (E->Type)? 'L' : 'E', GetAddrSizeCode ((unsigned char) E->AddrSize), SYM_IS_CONDES (E->Type)? 'I' : ' '); if (++Count == 2) { Count = 0; fprintf (F, "\n"); } } } fprintf (F, "\n"); xfree (ExpValXlat); } void PrintImportMap (FILE* F) /* Print an import map to the given file */ { unsigned I; const Import* Imp; /* Loop over all exports */ for (I = 0; I < ExpCount; ++I) { /* Get the export */ const Export* Exp = ExpPool [I]; /* Print the symbol only if there are imports, or if a verbose map ** file is requested. */ if (VerboseMap || Exp->ImpCount > 0) { /* Print the export */ fprintf (F, "%s (%s):\n", GetString (Exp->Name), GetObjFileName (Exp->Obj)); /* Print all imports for this symbol */ Imp = Exp->ImpList; while (Imp) { /* Print the import. Beware: The import might be linker ** generated, in which case there is no object file and ** sometimes no line information. */ const LineInfo* LI = GetImportPos (Imp); if (LI) { fprintf (F, " %-25s %s(%u)\n", GetObjFileName (Imp->Obj), GetSourceName (LI), GetSourceLine (LI)); } else { fprintf (F, " %-25s\n", GetObjFileName (Imp->Obj)); } /* Next import */ Imp = Imp->Next; } } } fprintf (F, "\n"); } void PrintExportLabels (FILE* F) /* Print the exports in a VICE label file */ { unsigned I; /* Print all exports */ for (I = 0; I < ExpCount; ++I) { const Export* E = ExpPool [I]; fprintf (F, "al %06lX .%s\n", GetExportVal (E), GetString (E->Name)); } } void MarkExport (Export* E) /* Mark the export */ { E->Flags |= EXP_USERMARK; } void UnmarkExport (Export* E) /* Remove the mark from the export */ { E->Flags &= ~EXP_USERMARK; } int ExportHasMark (Export* E) /* Return true if the export has a mark */ { return (E->Flags & EXP_USERMARK) != 0; } void CircularRefError (const Export* E) /* Print an error about a circular reference using to define the given export */ { const LineInfo* LI = GetExportPos (E); Error ("Circular reference for symbol '%s', %s(%u)", GetString (E->Name), GetSourceName (LI), GetSourceLine (LI)); } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/exports.h������������������������������������������������������������������������0000664�0000000�0000000�00000021005�13473601511�0015421�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* exports.h */ /* */ /* Exports handing for the ld65 linker */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef EXPORTS_H #define EXPORTS_H #include <stdio.h> /* common */ #include "cddefs.h" #include "coll.h" #include "exprdefs.h" /* ld65 */ #include "config.h" #include "lineinfo.h" #include "memarea.h" #include "objdata.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Import symbol structure */ typedef struct Import Import; struct Import { Import* Next; /* Single linked list */ ObjData* Obj; /* Object file that imports the name */ Collection DefLines; /* Line infos of definition */ Collection RefLines; /* Line infos of reference */ struct Export* Exp; /* Matching export for this import */ unsigned Name; /* Name if not in table */ unsigned short Flags; /* Generic flags */ unsigned short AddrSize; /* Address size of import */ }; /* Export symbol structure */ typedef struct Export Export; struct Export { unsigned Name; /* Name */ Export* Next; /* Hash table link */ unsigned Flags; /* Generic flags */ ObjData* Obj; /* Object file that exports the name */ unsigned ImpCount; /* How many imports for this symbol? */ Import* ImpList; /* List of imports for this symbol */ ExprNode* Expr; /* Expression (0 if not def'd) */ unsigned Size; /* Size of the symbol if any */ Collection DefLines; /* Line infos of definition */ Collection RefLines; /* Line infos of reference */ unsigned DbgSymId; /* Id of debug symbol for this export */ unsigned short Type; /* Type of export */ unsigned short AddrSize; /* Address size of export */ unsigned char ConDes[CD_TYPE_COUNT]; /* Constructor/destructor decls */ }; /* Prototype of a function that is called if an undefined symbol is found. It ** may check if the symbol is an external symbol (for binary formats that ** support externals) and will return zero if the symbol could not be ** resolved, or a value != zero if the symbol could be resolved. The ** CheckExports routine will print out the missing symbol in the first case. */ typedef int (*ExpCheckFunc) (unsigned Name, void* Data); /*****************************************************************************/ /* Code */ /*****************************************************************************/ void FreeImport (Import* I); /* Free an import. NOTE: This won't remove the import from the exports table, ** so it may only be called for unused imports (imports from modules that ** aren't referenced). */ Import* ReadImport (FILE* F, ObjData* Obj); /* Read an import from a file and insert it into the table */ Import* GenImport (unsigned Name, unsigned char AddrSize); /* Generate a new import with the given name and address size and return it */ Import* InsertImport (Import* I); /* Insert an import into the table, return I */ const LineInfo* GetImportPos (const Import* I); /* Return the basic line info of an import */ void FreeExport (Export* E); /* Free an export. NOTE: This won't remove the export from the exports table, ** so it may only be called for unused exports (exports from modules that ** aren't referenced). */ Export* ReadExport (FILE* F, ObjData* Obj); /* Read an export from a file */ void InsertExport (Export* E); /* Insert an exported identifier and check if it's already in the list */ const LineInfo* GetExportPos (const Export* E); /* Return the basic line info of an export */ Export* CreateConstExport (unsigned Name, long Value); /* Create an export for a literal date */ Export* CreateExprExport (unsigned Name, ExprNode* Expr, unsigned char AddrSize); /* Create an export for an expression */ Export* CreateMemoryExport (unsigned Name, MemoryArea* Mem, unsigned long Offs); /* Create an relative export for a memory area offset */ Export* CreateSegmentExport (unsigned Name, Segment* Seg, unsigned long Offs); /* Create a relative export to a segment */ Export* CreateSectionExport (unsigned Name, Section* S, unsigned long Offs); /* Create a relative export to a section */ Export* FindExport (unsigned Name); /* Check for an identifier in the list. Return 0 if not found, otherwise ** return a pointer to the export. */ int IsUnresolved (unsigned Name); /* Check if this symbol is an unresolved export */ int IsUnresolvedExport (const Export* E); /* Return true if the given export is unresolved */ int IsConstExport (const Export* E); /* Return true if the expression associated with this export is const */ long GetExportVal (const Export* E); /* Get the value of this export */ void CheckExports (void); /* Setup the list of all exports and check for export/import symbol type ** mismatches. */ void CheckUnresolvedImports (ExpCheckFunc F, void* Data); /* Check if there are any unresolved imports. On unresolved imports, F is ** called (see the comments on ExpCheckFunc in the data section). */ void PrintExportMapByName (FILE* F); /* Print an export map to the given file (sorted by symbol name) */ void PrintExportMapByValue (FILE* F); /* Print an export map to the given file (sorted by export value) */ void PrintImportMap (FILE* F); /* Print an import map to the given file */ void PrintExportLabels (FILE* F); /* Print the exports in a VICE label file */ void MarkExport (Export* E); /* Mark the export */ void UnmarkExport (Export* E); /* Remove the mark from the export */ int ExportHasMark (Export* E); /* Return true if the export has a mark */ void CircularRefError (const Export* E); /* Print an error about a circular reference using to define the given export */ /* End of exports.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/expr.c���������������������������������������������������������������������������0000664�0000000�0000000�00000052022�13473601511�0014671�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* expr.c */ /* */ /* Expression evaluation for the ld65 linker */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "check.h" #include "exprdefs.h" #include "xmalloc.h" /* ld65 */ #include "global.h" #include "error.h" #include "fileio.h" #include "memarea.h" #include "segments.h" #include "expr.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ ExprNode* NewExprNode (ObjData* O, unsigned char Op) /* Create a new expression node */ { /* Allocate fresh memory */ ExprNode* N = xmalloc (sizeof (ExprNode)); N->Op = Op; N->Left = 0; N->Right = 0; N->Obj = O; N->V.IVal = 0; return N; } static void FreeExprNode (ExprNode* E) /* Free a node */ { /* Free the memory */ xfree (E); } void FreeExpr (ExprNode* Root) /* Free the expression, Root is pointing to. */ { if (Root) { FreeExpr (Root->Left); FreeExpr (Root->Right); FreeExprNode (Root); } } int IsConstExpr (ExprNode* Root) /* Return true if the given expression is a constant expression, that is, one ** with no references to external symbols. */ { int Const; Export* E; Section* S; MemoryArea* M; if (EXPR_IS_LEAF (Root->Op)) { switch (Root->Op) { case EXPR_LITERAL: return 1; case EXPR_SYMBOL: /* Get the referenced export */ E = GetExprExport (Root); /* If this export has a mark set, we've already encountered it. ** This means that the export is used to define it's own value, ** which in turn means, that we have a circular reference. */ if (ExportHasMark (E)) { CircularRefError (E); Const = 0; } else { MarkExport (E); Const = IsConstExport (E); UnmarkExport (E); } return Const; case EXPR_SECTION: /* A section expression is const if the segment it is in is ** not relocatable and already placed. */ S = GetExprSection (Root); M = S->Seg->MemArea; return M != 0 && (M->Flags & MF_PLACED) != 0 && !M->Relocatable; case EXPR_SEGMENT: /* A segment is const if it is not relocatable and placed */ M = Root->V.Seg->MemArea; return M != 0 && (M->Flags & MF_PLACED) != 0 && !M->Relocatable; case EXPR_MEMAREA: /* A memory area is const if it is not relocatable and placed */ return !Root->V.Mem->Relocatable && (Root->V.Mem->Flags & MF_PLACED); default: /* Anything else is not const */ return 0; } } else if (EXPR_IS_UNARY (Root->Op)) { SegExprDesc D; /* Special handling for the BANK pseudo function */ switch (Root->Op) { case EXPR_BANK: /* Get segment references for the expression */ GetSegExprVal (Root->Left, &D); /* The expression is const if the expression contains exactly ** one segment that is assigned to a memory area which has a ** bank attribute that is constant. */ return (D.TooComplex == 0 && D.Seg != 0 && D.Seg->MemArea != 0 && D.Seg->MemArea->BankExpr != 0 && IsConstExpr (D.Seg->MemArea->BankExpr)); default: /* All others handled normal */ return IsConstExpr (Root->Left); } } else { /* We must handle shortcut boolean expressions here */ switch (Root->Op) { case EXPR_BOOLAND: if (IsConstExpr (Root->Left)) { /* lhs is const, if it is zero, don't eval right */ if (GetExprVal (Root->Left) == 0) { return 1; } else { return IsConstExpr (Root->Right); } } else { /* lhs not const --> tree not const */ return 0; } break; case EXPR_BOOLOR: if (IsConstExpr (Root->Left)) { /* lhs is const, if it is not zero, don't eval right */ if (GetExprVal (Root->Left) != 0) { return 1; } else { return IsConstExpr (Root->Right); } } else { /* lhs not const --> tree not const */ return 0; } break; default: /* All others are handled normal */ return IsConstExpr (Root->Left) && IsConstExpr (Root->Right); } } } Import* GetExprImport (ExprNode* Expr) /* Get the import data structure for a symbol expression node */ { /* Check that this is really a symbol */ PRECONDITION (Expr->Op == EXPR_SYMBOL); /* If we have an object file, get the import from it, otherwise ** (internally generated expressions), get the import from the ** import pointer. */ if (Expr->Obj) { /* Return the Import */ return GetObjImport (Expr->Obj, Expr->V.ImpNum); } else { return Expr->V.Imp; } } Export* GetExprExport (ExprNode* Expr) /* Get the exported symbol for a symbol expression node */ { /* Check that this is really a symbol */ PRECONDITION (Expr->Op == EXPR_SYMBOL); /* Return the export for an import*/ return GetExprImport (Expr)->Exp; } Section* GetExprSection (ExprNode* Expr) /* Get the segment for a section expression node */ { /* Check that this is really a section node */ PRECONDITION (Expr->Op == EXPR_SECTION); /* If we have an object file, get the section from it, otherwise ** (internally generated expressions), get the section from the ** section pointer. */ if (Expr->Obj) { /* Return the export */ return CollAt (&Expr->Obj->Sections, Expr->V.SecNum); } else { return Expr->V.Sec; } } long GetExprVal (ExprNode* Expr) /* Get the value of a constant expression */ { long Right; long Left; long Val; Section* S; Export* E; SegExprDesc D; switch (Expr->Op) { case EXPR_LITERAL: return Expr->V.IVal; case EXPR_SYMBOL: /* Get the referenced export */ E = GetExprExport (Expr); /* If this export has a mark set, we've already encountered it. ** This means that the export is used to define it's own value, ** which in turn means, that we have a circular reference. */ if (ExportHasMark (E)) { CircularRefError (E); Val = 0; } else { MarkExport (E); Val = GetExportVal (E); UnmarkExport (E); } return Val; case EXPR_SECTION: S = GetExprSection (Expr); return S->Offs + S->Seg->PC; case EXPR_SEGMENT: return Expr->V.Seg->PC; case EXPR_MEMAREA: return Expr->V.Mem->Start; case EXPR_PLUS: return GetExprVal (Expr->Left) + GetExprVal (Expr->Right); case EXPR_MINUS: return GetExprVal (Expr->Left) - GetExprVal (Expr->Right); case EXPR_MUL: return GetExprVal (Expr->Left) * GetExprVal (Expr->Right); case EXPR_DIV: Left = GetExprVal (Expr->Left); Right = GetExprVal (Expr->Right); if (Right == 0) { Error ("Division by zero"); } return Left / Right; case EXPR_MOD: Left = GetExprVal (Expr->Left); Right = GetExprVal (Expr->Right); if (Right == 0) { Error ("Modulo operation with zero"); } return Left % Right; case EXPR_OR: return GetExprVal (Expr->Left) | GetExprVal (Expr->Right); case EXPR_XOR: return GetExprVal (Expr->Left) ^ GetExprVal (Expr->Right); case EXPR_AND: return GetExprVal (Expr->Left) & GetExprVal (Expr->Right); case EXPR_SHL: return GetExprVal (Expr->Left) << GetExprVal (Expr->Right); case EXPR_SHR: return GetExprVal (Expr->Left) >> GetExprVal (Expr->Right); case EXPR_EQ: return (GetExprVal (Expr->Left) == GetExprVal (Expr->Right)); case EXPR_NE: return (GetExprVal (Expr->Left) != GetExprVal (Expr->Right)); case EXPR_LT: return (GetExprVal (Expr->Left) < GetExprVal (Expr->Right)); case EXPR_GT: return (GetExprVal (Expr->Left) > GetExprVal (Expr->Right)); case EXPR_LE: return (GetExprVal (Expr->Left) <= GetExprVal (Expr->Right)); case EXPR_GE: return (GetExprVal (Expr->Left) >= GetExprVal (Expr->Right)); case EXPR_BOOLAND: return GetExprVal (Expr->Left) && GetExprVal (Expr->Right); case EXPR_BOOLOR: return GetExprVal (Expr->Left) || GetExprVal (Expr->Right); case EXPR_BOOLXOR: return (GetExprVal (Expr->Left) != 0) ^ (GetExprVal (Expr->Right) != 0); case EXPR_MAX: Left = GetExprVal (Expr->Left); Right = GetExprVal (Expr->Right); return (Left > Right)? Left : Right; case EXPR_MIN: Left = GetExprVal (Expr->Left); Right = GetExprVal (Expr->Right); return (Left < Right)? Left : Right; case EXPR_UNARY_MINUS: return -GetExprVal (Expr->Left); case EXPR_NOT: return ~GetExprVal (Expr->Left); case EXPR_SWAP: Left = GetExprVal (Expr->Left); return ((Left >> 8) & 0x00FF) | ((Left << 8) & 0xFF00); case EXPR_BOOLNOT: return !GetExprVal (Expr->Left); case EXPR_BANK: GetSegExprVal (Expr->Left, &D); if (D.TooComplex || D.Seg == 0) { Error ("Argument for .BANK is not segment relative or too complex"); } if (D.Seg->MemArea == 0) { Error ("Segment '%s' is referenced by .BANK but " "not assigned to a memory area", GetString (D.Seg->Name)); } if (D.Seg->MemArea->BankExpr == 0) { Error ("Memory area '%s' is referenced by .BANK but " "has no BANK attribute", GetString (D.Seg->MemArea->Name)); } return GetExprVal (D.Seg->MemArea->BankExpr); case EXPR_BYTE0: return GetExprVal (Expr->Left) & 0xFF; case EXPR_BYTE1: return (GetExprVal (Expr->Left) >> 8) & 0xFF; case EXPR_BYTE2: return (GetExprVal (Expr->Left) >> 16) & 0xFF; case EXPR_BYTE3: return (GetExprVal (Expr->Left) >> 24) & 0xFF; case EXPR_WORD0: return GetExprVal (Expr->Left) & 0xFFFF; case EXPR_WORD1: return (GetExprVal (Expr->Left) >> 16) & 0xFFFF; case EXPR_FARADDR: return GetExprVal (Expr->Left) & 0xFFFFFF; case EXPR_DWORD: return GetExprVal (Expr->Left) & 0xFFFFFFFF; case EXPR_NEARADDR: /* Assembler was expected to validate this truncation. */ return GetExprVal (Expr->Left) & 0xFFFF; default: Internal ("Unknown expression Op type: %u", Expr->Op); /* NOTREACHED */ return 0; } } static void GetSegExprValInternal (ExprNode* Expr, SegExprDesc* D, int Sign) /* Check if the given expression consists of a segment reference and only ** constant values, additions and subtractions. If anything else is found, ** set D->TooComplex to true. ** Internal, recursive routine. */ { Export* E; switch (Expr->Op) { case EXPR_LITERAL: D->Val += (Sign * Expr->V.IVal); break; case EXPR_SYMBOL: /* Get the referenced export */ E = GetExprExport (Expr); /* If this export has a mark set, we've already encountered it. ** This means that the export is used to define it's own value, ** which in turn means, that we have a circular reference. */ if (ExportHasMark (E)) { CircularRefError (E); } else { MarkExport (E); GetSegExprValInternal (E->Expr, D, Sign); UnmarkExport (E); } break; case EXPR_SECTION: if (D->Seg) { /* We cannot handle more than one segment reference in o65 */ D->TooComplex = 1; } else { /* Get the section from the expression */ Section* S = GetExprSection (Expr); /* Remember the segment reference */ D->Seg = S->Seg; /* Add the offset of the section to the constant value */ D->Val += Sign * (S->Offs + D->Seg->PC); } break; case EXPR_SEGMENT: if (D->Seg) { /* We cannot handle more than one segment reference in o65 */ D->TooComplex = 1; } else { /* Remember the segment reference */ D->Seg = Expr->V.Seg; /* Add the offset of the segment to the constant value */ D->Val += (Sign * D->Seg->PC); } break; case EXPR_PLUS: GetSegExprValInternal (Expr->Left, D, Sign); GetSegExprValInternal (Expr->Right, D, Sign); break; case EXPR_MINUS: GetSegExprValInternal (Expr->Left, D, Sign); GetSegExprValInternal (Expr->Right, D, -Sign); break; default: /* Expression contains illegal operators */ D->TooComplex = 1; break; } } void GetSegExprVal (ExprNode* Expr, SegExprDesc* D) /* Check if the given expression consists of a segment reference and only ** constant values, additions and subtractions. If anything else is found, ** set D->TooComplex to true. The function will initialize D. */ { /* Initialize the given structure */ D->Val = 0; D->TooComplex = 0; D->Seg = 0; /* Call our recursive calculation routine */ GetSegExprValInternal (Expr, D, 1); } ExprNode* LiteralExpr (long Val, ObjData* O) /* Return an expression tree that encodes the given literal value */ { ExprNode* Expr = NewExprNode (O, EXPR_LITERAL); Expr->V.IVal = Val; return Expr; } ExprNode* MemoryExpr (MemoryArea* Mem, long Offs, ObjData* O) /* Return an expression tree that encodes an offset into a memory area */ { ExprNode* Root; ExprNode* Expr = NewExprNode (O, EXPR_MEMAREA); Expr->V.Mem = Mem; if (Offs != 0) { Root = NewExprNode (O, EXPR_PLUS); Root->Left = Expr; Root->Right = LiteralExpr (Offs, O); } else { Root = Expr; } return Root; } ExprNode* SegmentExpr (Segment* Seg, long Offs, ObjData* O) /* Return an expression tree that encodes an offset into a segment */ { ExprNode* Root; ExprNode* Expr = NewExprNode (O, EXPR_SEGMENT); Expr->V.Seg = Seg; if (Offs != 0) { Root = NewExprNode (O, EXPR_PLUS); Root->Left = Expr; Root->Right = LiteralExpr (Offs, O); } else { Root = Expr; } return Root; } ExprNode* SectionExpr (Section* Sec, long Offs, ObjData* O) /* Return an expression tree that encodes an offset into a section */ { ExprNode* Root; ExprNode* Expr = NewExprNode (O, EXPR_SECTION); Expr->V.Sec = Sec; if (Offs != 0) { Root = NewExprNode (O, EXPR_PLUS); Root->Left = Expr; Root->Right = LiteralExpr (Offs, O); } else { Root = Expr; } return Root; } ExprNode* ReadExpr (FILE* F, ObjData* O) /* Read an expression from the given file */ { ExprNode* Expr; /* Read the node tag and handle NULL nodes */ unsigned char Op = Read8 (F); if (Op == EXPR_NULL) { return 0; } /* Create a new node */ Expr = NewExprNode (O, Op); /* Check the tag and handle the different expression types */ if (EXPR_IS_LEAF (Op)) { switch (Op) { case EXPR_LITERAL: Expr->V.IVal = Read32Signed (F); break; case EXPR_SYMBOL: /* Read the import number */ Expr->V.ImpNum = ReadVar (F); break; case EXPR_SECTION: /* Read the section number */ Expr->V.SecNum = ReadVar (F); break; default: Error ("Invalid expression op: %02X", Op); } } else { /* Not a leaf node */ Expr->Left = ReadExpr (F, O); Expr->Right = ReadExpr (F, O); } /* Return the tree */ return Expr; } int EqualExpr (ExprNode* E1, ExprNode* E2) /* Check if two expressions are identical. */ { /* If one pointer is NULL, both must be NULL */ if ((E1 == 0) ^ (E2 == 0)) { return 0; } if (E1 == 0) { return 1; } /* Both pointers not NULL, check OP */ if (E1->Op != E2->Op) { return 0; } /* OPs are identical, check data for leafs, or subtrees */ switch (E1->Op) { case EXPR_LITERAL: /* Value must be identical */ return (E1->V.IVal == E2->V.IVal); case EXPR_SYMBOL: /* Import must be identical */ return (GetExprImport (E1) == GetExprImport (E2)); case EXPR_SECTION: /* Section must be identical */ return (GetExprSection (E1) == GetExprSection (E2)); case EXPR_SEGMENT: /* Segment must be identical */ return (E1->V.Seg == E2->V.Seg); case EXPR_MEMAREA: /* Memory area must be identical */ return (E1->V.Mem == E2->V.Mem); default: /* Not a leaf node */ return EqualExpr (E1->Left, E2->Left) && EqualExpr (E1->Right, E2->Right); } } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/expr.h���������������������������������������������������������������������������0000664�0000000�0000000�00000012164�13473601511�0014701�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* expr.h */ /* */ /* Expression evaluation for the ld65 linker */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef EXPR_H #define EXPR_H /* common */ #include "exprdefs.h" /* ld65 */ #include "objdata.h" #include "exports.h" #include "config.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Structure for parsing segment based expression trees */ typedef struct SegExprDesc SegExprDesc; struct SegExprDesc { long Val; /* The offset value */ int TooComplex; /* Expression too complex */ Segment* Seg; /* Segment reference if any */ }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ ExprNode* NewExprNode (ObjData* O, unsigned char Op); /* Create a new expression node */ void FreeExpr (ExprNode* Root); /* Free the expression tree, Root is pointing to. */ int IsConstExpr (ExprNode* Root); /* Return true if the given expression is a constant expression, that is, one ** with no references to external symbols. */ Import* GetExprImport (ExprNode* Expr); /* Get the import data structure for a symbol expression node */ Export* GetExprExport (ExprNode* Expr); /* Get the exported symbol for a symbol expression node */ Section* GetExprSection (ExprNode* Expr); /* Get the segment for a section expression node */ long GetExprVal (ExprNode* Expr); /* Get the value of a constant expression */ void GetSegExprVal (ExprNode* Expr, SegExprDesc* D); /* Check if the given expression consists of a segment reference and only ** constant values, additions and subtractions. If anything else is found, ** set D->TooComplex to true. The function will initialize D. */ ExprNode* LiteralExpr (long Val, ObjData* O); /* Return an expression tree that encodes the given literal value */ ExprNode* MemoryExpr (MemoryArea* Mem, long Offs, ObjData* O); /* Return an expression tree that encodes an offset into the memory area */ ExprNode* SegmentExpr (Segment* Seg, long Offs, ObjData* O); /* Return an expression tree that encodes an offset into a segment */ ExprNode* SectionExpr (Section* Sec, long Offs, ObjData* O); /* Return an expression tree that encodes an offset into a section */ ExprNode* ReadExpr (FILE* F, ObjData* O); /* Read an expression from the given file */ int EqualExpr (ExprNode* E1, ExprNode* E2); /* Check if two expressions are identical. */ /* End of expr.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/extsyms.c������������������������������������������������������������������������0000664�0000000�0000000�00000015353�13473601511�0015435�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* extsyms.c */ /* */ /* Handle program external symbols for relocatable output formats */ /* */ /* */ /* */ /* (C) 1999-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* common */ #include "hashfunc.h" #include "xmalloc.h" /* ld65 */ #include "error.h" #include "extsyms.h" #include "spool.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Structure holding an external symbol */ struct ExtSym { unsigned Name; /* Name index */ ExtSym* List; /* Next entry in list of all symbols */ ExtSym* Next; /* Next entry in hash list */ unsigned Flags; /* Generic flags */ unsigned Num; /* Number of external symbol */ }; /* External symbol table structure */ #define HASHTAB_MASK 0x3FU #define HASHTAB_SIZE (HASHTAB_MASK + 1) struct ExtSymTab { ExtSym* Root; /* List of symbols */ ExtSym* Last; /* Pointer to last symbol */ unsigned Count; /* Number of symbols */ ExtSym* HashTab[HASHTAB_SIZE]; }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ ExtSym* NewExtSym (ExtSymTab* Tab, unsigned Name) /* Create a new external symbol and insert it into the table */ { /* Get the hash value of the string */ unsigned Hash = (Name & HASHTAB_MASK); /* Check for duplicates */ ExtSym* E = GetExtSym (Tab, Name); if (E != 0) { /* We do already have a symbol with this name */ Error ("Duplicate external symbol '%s'", GetString (Name)); } /* Allocate memory for the structure */ E = xmalloc (sizeof (ExtSym)); /* Initialize the structure */ E->Name = Name; E->List = 0; E->Flags = 0; E->Num = Tab->Count; /* Insert the entry into the list of all symbols */ if (Tab->Last == 0) { /* List is empty */ Tab->Root = E; } else { /* List not empty */ Tab->Last->List = E; } Tab->Last = E; ++Tab->Count; /* Insert the symbol into the hash table */ E->Next = Tab->HashTab[Hash]; Tab->HashTab[Hash] = E; /* Done, return the created entry */ return E; } static void FreeExtSym (ExtSym* E) /* Free an external symbol structure. Will not unlink the entry, so internal ** use only. */ { xfree (E); } ExtSymTab* NewExtSymTab (void) /* Create a new external symbol table */ { unsigned I; /* Allocate memory */ ExtSymTab* Tab = xmalloc (sizeof (ExtSymTab)); /* Initialize the fields */ Tab->Root = 0; Tab->Last = 0; Tab->Count = 0; for (I = 0; I < HASHTAB_SIZE; ++I) { Tab->HashTab [I] = 0; } /* Done, return the hash table */ return Tab; } void FreeExtSymTab (ExtSymTab* Tab) /* Free an external symbol structure */ { /* Free all entries */ while (Tab->Root) { ExtSym* E = Tab->Root; Tab->Root = E->Next; FreeExtSym (E); } /* Free the struct itself */ xfree (Tab); } ExtSym* GetExtSym (const ExtSymTab* Tab, unsigned Name) /* Return the entry for the external symbol with the given name. Return NULL ** if there is no such symbol. */ { /* Hash the name */ unsigned Hash = (Name & HASHTAB_MASK); /* Check the linked list */ ExtSym* E = Tab->HashTab[Hash]; while (E) { if (E->Name == Name) { /* Found it */ break; } E = E->Next; } /* Return the symbol we found */ return E; } unsigned ExtSymCount (const ExtSymTab* Tab) /* Return the number of symbols in the table */ { return Tab->Count; } const ExtSym* ExtSymList (const ExtSymTab* Tab) /* Return the start of the symbol list sorted by symbol number. Call ** ExtSymNext for the next symbol. */ { return Tab->Root; } unsigned ExtSymNum (const ExtSym* E) /* Return the number of an external symbol */ { return E->Num; } unsigned ExtSymName (const ExtSym* E) /* Return the symbol name index */ { return E->Name; } const ExtSym* ExtSymNext (const ExtSym* E) /* Return the next symbol in the list */ { return E->List; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/extsyms.h������������������������������������������������������������������������0000664�0000000�0000000�00000010176�13473601511�0015440�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* extsyms.h */ /* */ /* Handle program external symbols for relocatable output formats */ /* */ /* */ /* */ /* (C) 1999-2001 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* 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 EXTSYMS_H #define EXTSYMS_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Forward decl for structure holding an external symbol */ typedef struct ExtSym ExtSym; /* External symbol table structure */ typedef struct ExtSymTab ExtSymTab; /*****************************************************************************/ /* Code */ /*****************************************************************************/ ExtSym* NewExtSym (ExtSymTab* Tab, unsigned Name); /* Create a new external symbol and insert it into the list */ ExtSymTab* NewExtSymTab (void); /* Create a new external symbol table */ void FreeExtSymTab (ExtSymTab* Tab); /* Free an external symbol structure */ ExtSym* GetExtSym (const ExtSymTab* Tab, unsigned Name); /* Return the entry for the external symbol with the given name. Return NULL ** if there is no such symbol. */ unsigned ExtSymCount (const ExtSymTab* Tab); /* Return the number of symbols in the table */ const ExtSym* ExtSymList (const ExtSymTab* Tab); /* Return the start of the symbol list sorted by symbol number. Call ** ExtSymNext for the next symbol. */ unsigned ExtSymNum (const ExtSym* E); /* Return the number of an external symbol */ unsigned ExtSymName (const ExtSym* E); /* Return the symbol name index */ const ExtSym* ExtSymNext (const ExtSym* E); /* Return the next symbol in the list */ /* End of extsyms.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/fileinfo.c�����������������������������������������������������������������������0000664�0000000�0000000�00000020463�13473601511�0015512�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* fileinfo.c */ /* */ /* Source file info structure */ /* */ /* */ /* */ /* (C) 2001-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "coll.h" #include "xmalloc.h" /* ld65 */ #include "fileio.h" #include "fileinfo.h" #include "objdata.h" #include "spool.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* A list of all file infos without duplicates */ static Collection FileInfos = STATIC_COLLECTION_INITIALIZER; /*****************************************************************************/ /* Code */ /*****************************************************************************/ static int FindFileInfo (unsigned Name, unsigned* Index) /* Find the FileInfo for a given file name. The function returns true if the ** name was found. In this case, Index contains the index of the first item ** that matches. If the item wasn't found, the function returns false and ** Index contains the insert position for FileName. */ { /* Do a binary search */ int Lo = 0; int Hi = (int) CollCount (&FileInfos) - 1; int Found = 0; while (Lo <= Hi) { /* Mid of range */ int Cur = (Lo + Hi) / 2; /* Get item */ FileInfo* CurItem = CollAt (&FileInfos, Cur); /* Found? */ if (CurItem->Name < Name) { Lo = Cur + 1; } else { Hi = Cur - 1; /* Since we may have duplicates, repeat the search until we've ** the first item that has a match. */ if (CurItem->Name == Name) { Found = 1; } } } /* Pass back the index. This is also the insert position */ *Index = Lo; return Found; } static FileInfo* NewFileInfo (unsigned Name, unsigned long MTime, unsigned long Size) /* Allocate and initialize a new FileInfo struct and return it */ { /* Allocate memory */ FileInfo* FI = xmalloc (sizeof (FileInfo)); /* Initialize stuff */ FI->Id = ~0U; FI->Name = Name; FI->MTime = MTime; FI->Size = Size; FI->Modules = EmptyCollection; /* Return the new struct */ return FI; } static void FreeFileInfo (FileInfo* FI) /* Free a file info structure */ { /* Free the collection */ DoneCollection (&FI->Modules); /* Free memory for the structure */ xfree (FI); } FileInfo* ReadFileInfo (FILE* F, ObjData* O) /* Read a file info from a file and return it */ { FileInfo* FI; /* Read the fields from the file */ unsigned Name = MakeGlobalStringId (O, ReadVar (F)); unsigned long MTime = Read32 (F); unsigned long Size = ReadVar (F); /* Search for the first entry with this name */ unsigned Index; if (FindFileInfo (Name, &Index)) { /* We have at least one such entry. Try all of them and, if size and ** modification time matches, return the first match. When the loop ** is terminated without finding an entry, Index points one behind ** the last entry with the name, which is the perfect insert position. */ FI = CollAt (&FileInfos, Index); while (1) { /* Check size and modification time stamp */ if (FI->Size == Size && FI->MTime == MTime) { /* Remember that the modules uses this file info, then return it */ CollAppend (&FI->Modules, O); return FI; } /* Check the next one */ if (++Index >= CollCount (&FileInfos)) { /* Nothing left */ break; } FI = CollAt (&FileInfos, Index); /* Done if the name differs */ if (FI->Name != Name) { break; } } } /* Not found. Allocate a new FileInfo structure */ FI = NewFileInfo (Name, MTime, Size); /* Remember that this module uses the file info */ CollAppend (&FI->Modules, O); /* Insert the file info in our global list. Index points to the insert ** position. */ CollInsert (&FileInfos, FI, Index); /* Return the new struct */ return FI; } unsigned FileInfoCount (void) /* Return the total number of file infos */ { return CollCount (&FileInfos); } void AssignFileInfoIds (void) /* Remove unused file infos and assign the ids to the remaining ones */ { unsigned I, J; /* Print all file infos */ for (I = 0, J = 0; I < CollCount (&FileInfos); ++I) { /* Get the next file info */ FileInfo* FI = CollAtUnchecked (&FileInfos, I); /* If it's unused, free it, otherwise assign the id and keep it */ if (CollCount (&FI->Modules) == 0) { FreeFileInfo (FI); } else { FI->Id = J; CollReplace (&FileInfos, FI, J++); } } /* The new count is now in J */ FileInfos.Count = J; } void PrintDbgFileInfo (FILE* F) /* Output the file info to a debug info file */ { unsigned I, J; /* Print all file infos */ for (I = 0; I < CollCount (&FileInfos); ++I) { /* Get the file info */ const FileInfo* FI = CollAtUnchecked (&FileInfos, I); /* Base info */ fprintf (F, "file\tid=%u,name=\"%s\",size=%lu,mtime=0x%08lX,mod=", FI->Id, GetString (FI->Name), FI->Size, FI->MTime); /* Modules that use the file */ for (J = 0; J < CollCount (&FI->Modules); ++J) { /* Get the module */ const ObjData* O = CollConstAt (&FI->Modules, J); /* Output its id */ if (J > 0) { fprintf (F, "+%u", O->Id); } else { fprintf (F, "%u", O->Id); } } /* Terminate the output line */ fputc ('\n', F); } } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/fileinfo.h�����������������������������������������������������������������������0000664�0000000�0000000�00000007565�13473601511�0015527�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* fileinfo.h */ /* */ /* Source file info structure */ /* */ /* */ /* */ /* (C) 2001-2010, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef FILEINFO_H #define FILEINFO_H #include <stdio.h> /* common */ #include "coll.h" #include "filepos.h" /* ld65 */ #include "objdata.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ typedef struct FileInfo FileInfo; struct FileInfo { unsigned Id; /* Id of file for debug info */ unsigned Name; /* File name index */ unsigned long MTime; /* Time of last modification */ unsigned long Size; /* Size of the file */ Collection Modules; /* Modules that use this file */ }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ FileInfo* ReadFileInfo (FILE* F, ObjData* O); /* Read a file info from a file and return it */ unsigned FileInfoCount (void); /* Return the total number of file infos */ void AssignFileInfoIds (void); /* Assign the ids to the file infos */ void PrintDbgFileInfo (FILE* F); /* Output the file info to a debug info file */ /* End of fileinfo.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/fileio.c�������������������������������������������������������������������������0000664�0000000�0000000�00000020620�13473601511�0015161�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* fileio.c */ /* */ /* File I/O for the ld65 linker */ /* */ /* */ /* */ /* (C) 1998-2008 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> #include <errno.h> /* common */ #include "xmalloc.h" /* ld65 */ #include "error.h" #include "fileio.h" #include "spool.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void FileSetPos (FILE* F, unsigned long Pos) /* Seek to the given absolute position, fail on errors */ { if (fseek (F, Pos, SEEK_SET) != 0) { Error ("Cannot seek: %s", strerror (errno)); } } unsigned long FileGetPos (FILE* F) /* Return the current file position, fail on errors */ { long Pos = ftell (F); if (Pos < 0) { Error ("Error in ftell: %s", strerror (errno)); } return Pos; } void Write8 (FILE* F, unsigned Val) /* Write an 8 bit value to the file */ { if (putc (Val, F) == EOF) { Error ("Write error (disk full?)"); } } void Write16 (FILE* F, unsigned Val) /* Write a 16 bit value to the file */ { Write8 (F, (unsigned char) Val); Write8 (F, (unsigned char) (Val >> 8)); } void Write24 (FILE* F, unsigned long Val) /* Write a 24 bit value to the file */ { Write8 (F, (unsigned char) Val); Write8 (F, (unsigned char) (Val >> 8)); Write8 (F, (unsigned char) (Val >> 16)); } void Write32 (FILE* F, unsigned long Val) /* Write a 32 bit value to the file */ { Write8 (F, (unsigned char) Val); Write8 (F, (unsigned char) (Val >> 8)); Write8 (F, (unsigned char) (Val >> 16)); Write8 (F, (unsigned char) (Val >> 24)); } void WriteVal (FILE* F, unsigned long Val, unsigned Size) /* Write a value of the given size to the output file */ { switch (Size) { case 1: Write8 (F, Val); break; case 2: Write16 (F, Val); break; case 3: Write24 (F, Val); break; case 4: Write32 (F, Val); break; default: Internal ("WriteVal: Invalid size: %u", Size); } } void WriteVar (FILE* F, unsigned long V) /* Write a variable sized value to the file in special encoding */ { /* We will write the value to the file in 7 bit chunks. If the 8th bit ** is clear, we're done, if it is set, another chunk follows. This will ** allow us to encode smaller values with less bytes, at the expense of ** needing 5 bytes if a 32 bit value is written to file. */ do { unsigned char C = (V & 0x7F); V >>= 7; if (V) { C |= 0x80; } Write8 (F, C); } while (V != 0); } void WriteStr (FILE* F, const char* S) /* Write a string to the file */ { unsigned Len = strlen (S); WriteVar (F, Len); WriteData (F, S, Len); } void WriteData (FILE* F, const void* Data, unsigned Size) /* Write data to the file */ { if (fwrite (Data, 1, Size, F) != Size) { Error ("Write error (disk full?)"); } } void WriteMult (FILE* F, unsigned char Val, unsigned long Count) /* Write one byte several times to the file */ { while (Count--) { Write8 (F, Val); } } unsigned Read8 (FILE* F) /* Read an 8 bit value from the file */ { int C = getc (F); if (C == EOF) { long Pos = ftell (F); Error ("Read error at position %ld (file corrupt?)", Pos); } return C; } unsigned Read16 (FILE* F) /* Read a 16 bit value from the file */ { unsigned Lo = Read8 (F); unsigned Hi = Read8 (F); return (Hi << 8) | Lo; } unsigned long Read24 (FILE* F) /* Read a 24 bit value from the file */ { unsigned long Lo = Read16 (F); unsigned long Hi = Read8 (F); return (Hi << 16) | Lo; } unsigned long Read32 (FILE* F) /* Read a 32 bit value from the file */ { unsigned long Lo = Read16 (F); unsigned long Hi = Read16 (F); return (Hi << 16) | Lo; } long Read32Signed (FILE* F) /* Read a 32 bit value from the file. Sign extend the value. */ { /* Read a 32 bit value */ unsigned long V = Read32 (F); /* Sign extend the value */ if (V & 0x80000000UL) { /* Signed value */ V |= ~0xFFFFFFFFUL; } /* Return it as a long */ return (long) V; } unsigned long ReadVar (FILE* F) /* Read a variable size value from the file */ { /* The value was written to the file in 7 bit chunks LSB first. If there ** are more bytes, bit 8 is set, otherwise it is clear. */ unsigned char C; unsigned long V = 0; unsigned Shift = 0; do { /* Read one byte */ C = Read8 (F); /* Encode it into the target value */ V |= ((unsigned long)(C & 0x7F)) << Shift; /* Next value */ Shift += 7; } while (C & 0x80); /* Return the value read */ return V; } unsigned ReadStr (FILE* F) /* Read a string from the file, place it into the global string pool, and ** return its string id. */ { unsigned Id; StrBuf Buf = STATIC_STRBUF_INITIALIZER; /* Read the length */ unsigned Len = ReadVar (F); /* Expand the string buffer memory */ SB_Realloc (&Buf, Len); /* Read the string */ ReadData (F, SB_GetBuf (&Buf), Len); Buf.Len = Len; /* Insert it into the string pool and remember the id */ Id = GetStrBufId (&Buf); /* Free the memory buffer */ SB_Done (&Buf); /* Return the string id */ return Id; } FilePos* ReadFilePos (FILE* F, FilePos* Pos) /* Read a file position from the file */ { /* Read the data fields */ Pos->Line = ReadVar (F); Pos->Col = ReadVar (F); Pos->Name = ReadVar (F); return Pos; } void* ReadData (FILE* F, void* Data, unsigned Size) /* Read data from the file */ { /* Explicitly allow reading zero bytes */ if (Size > 0) { if (fread (Data, 1, Size, F) != Size) { long Pos = ftell (F); Error ("Read error at position %ld (file corrupt?)", Pos); } } return Data; } ����������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/fileio.h�������������������������������������������������������������������������0000664�0000000�0000000�00000011151�13473601511�0015165�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* fileio.h */ /* */ /* File I/O for the ld65 linker */ /* */ /* */ /* */ /* (C) 1998-2003 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef FILEIO_H #define FILEIO_H #include <stdio.h> /* common */ #include "filepos.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void FileSetPos (FILE* F, unsigned long Pos); /* Seek to the given absolute position, fail on errors */ unsigned long FileGetPos (FILE* F); /* Return the current file position, fail on errors */ void Write8 (FILE* F, unsigned Val); /* Write an 8 bit value to the file */ void Write16 (FILE* F, unsigned Val); /* Write a 16 bit value to the file */ void Write24 (FILE* F, unsigned long Val); /* Write a 24 bit value to the file */ void Write32 (FILE* F, unsigned long Val); /* Write a 32 bit value to the file */ void WriteVal (FILE* F, unsigned long Val, unsigned Size); /* Write a value of the given size to the output file */ void WriteVar (FILE* F, unsigned long V); /* Write a variable sized value to the file in special encoding */ void WriteStr (FILE* F, const char* S); /* Write a string to the file */ void WriteData (FILE* F, const void* Data, unsigned Size); /* Write data to the file */ void WriteMult (FILE* F, unsigned char Val, unsigned long Count); /* Write one byte several times to the file */ unsigned Read8 (FILE* F); /* Read an 8 bit value from the file */ unsigned Read16 (FILE* F); /* Read a 16 bit value from the file */ unsigned long Read24 (FILE* F); /* Read a 24 bit value from the file */ unsigned long Read32 (FILE* F); /* Read a 32 bit value from the file */ long Read32Signed (FILE* F); /* Read a 32 bit value from the file. Sign extend the value. */ unsigned long ReadVar (FILE* F); /* Read a variable size value from the file */ unsigned ReadStr (FILE* F); /* Read a string from the file, place it into the global string pool, and ** return its string id. */ FilePos* ReadFilePos (FILE* F, FilePos* Pos); /* Read a file position from the file */ void* ReadData (FILE* F, void* Data, unsigned Size); /* Read data from the file */ /* End of fileio.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/filepath.c�����������������������������������������������������������������������0000664�0000000�0000000�00000012011�13473601511�0015501�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* filepath.c */ /* */ /* File search path handling for ld65 */ /* */ /* */ /* */ /* (C) 2003-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* ld65 */ #include "filepath.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ SearchPaths* LibSearchPath; /* Library path */ SearchPaths* ObjSearchPath; /* Object file path */ SearchPaths* CfgSearchPath; /* Config file path */ SearchPaths* LibDefaultPath; /* Default Library path */ SearchPaths* ObjDefaultPath; /* Default Object file path */ SearchPaths* CfgDefaultPath; /* Default Config file path */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ void InitSearchPaths (void) /* Initialize the path search list */ { /* Create the search path lists */ LibSearchPath = NewSearchPath (); ObjSearchPath = NewSearchPath (); CfgSearchPath = NewSearchPath (); LibDefaultPath = NewSearchPath (); ObjDefaultPath = NewSearchPath (); CfgDefaultPath = NewSearchPath (); /* Always search all stuff in the current directory */ AddSearchPath (LibSearchPath, ""); AddSearchPath (ObjSearchPath, ""); AddSearchPath (CfgSearchPath, ""); /* Add specific paths from the environment. */ AddSearchPathFromEnv (LibDefaultPath, "LD65_LIB"); AddSearchPathFromEnv (ObjDefaultPath, "LD65_OBJ"); AddSearchPathFromEnv (CfgDefaultPath, "LD65_CFG"); /* Add paths relative to a main directory defined in an env. var. */ AddSubSearchPathFromEnv (LibDefaultPath, "CC65_HOME", "lib"); AddSubSearchPathFromEnv (ObjDefaultPath, "CC65_HOME", "lib"); AddSubSearchPathFromEnv (CfgDefaultPath, "CC65_HOME", "cfg"); /* Add some compiled-in search paths if defined at compile time. */ #if defined(LD65_LIB) && !defined(_WIN32) AddSearchPath (LibDefaultPath, STRINGIZE (LD65_LIB)); #endif #if defined(LD65_OBJ) && !defined(_WIN32) AddSearchPath (ObjDefaultPath, STRINGIZE (LD65_OBJ)); #endif #if defined(LD65_CFG) && !defined(_WIN32) AddSearchPath (CfgDefaultPath, STRINGIZE (LD65_CFG)); #endif /* Add paths relative to the parent directory of the Windows binary. */ AddSubSearchPathFromWinBin (LibDefaultPath, "lib"); AddSubSearchPathFromWinBin (ObjDefaultPath, "lib"); AddSubSearchPathFromWinBin (CfgDefaultPath, "cfg"); } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/filepath.h�����������������������������������������������������������������������0000664�0000000�0000000�00000007136�13473601511�0015522�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* filepath.h */ /* */ /* File search path handling for ld65 */ /* */ /* */ /* */ /* (C) 2003-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef FILEPATH_H #define FILEPATH_H /* common */ #include "searchpath.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ extern SearchPaths* LibSearchPath; /* Library path */ extern SearchPaths* ObjSearchPath; /* Object file path */ extern SearchPaths* CfgSearchPath; /* Config file path */ extern SearchPaths* LibDefaultPath; /* Default Library path */ extern SearchPaths* ObjDefaultPath; /* Default Object file path */ extern SearchPaths* CfgDefaultPath; /* Default Config file path */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ void InitSearchPaths (void); /* Initialize the path search list */ /* End of filepath.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/fragment.c�����������������������������������������������������������������������0000664�0000000�0000000�00000007725�13473601511�0015530�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* fragment.c */ /* */ /* Code/data fragment routines */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "fragdefs.h" #include "xmalloc.h" /* ld65 */ #include "error.h" #include "fragment.h" #include "objdata.h" #include "segments.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ Fragment* NewFragment (unsigned char Type, unsigned Size, Section* S) /* Create a new fragment and insert it into the section S */ { Fragment* F; /* Calculate the size of the memory block. LitBuf is only needed if the ** fragment contains literal data. */ unsigned FragSize = sizeof (Fragment) - 1; if (Type == FRAG_LITERAL) { FragSize += Size; } /* Allocate memory */ F = xmalloc (FragSize); /* Initialize the data */ F->Next = 0; F->Obj = 0; F->Sec = S; F->Size = Size; F->Expr = 0; F->LineInfos = EmptyCollection; F->Type = Type; /* Insert the code fragment into the section */ if (S->FragRoot == 0) { /* First fragment */ S->FragRoot = F; } else { S->FragLast->Next = F; } S->FragLast = F; /* Increment the size of the section by the size of the fragment */ S->Size += Size; /* Increment the size of the segment that contains the section */ S->Seg->Size += Size; /* Return the new fragment */ return F; } �������������������������������������������cc65-2.18/src/ld65/fragment.h�����������������������������������������������������������������������0000664�0000000�0000000�00000011404�13473601511�0015522�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* fragment.h */ /* */ /* Code/data fragment routines */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef FRAGMENT_H #define FRAGMENT_H /* common */ #include "coll.h" #include "filepos.h" /* Ld65 */ #include "lineinfo.h" /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ struct ObjData; struct Section; /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Fragment structure */ typedef struct Fragment Fragment; struct Fragment { Fragment* Next; /* Next fragment in list */ struct ObjData* Obj; /* Source of fragment */ struct Section* Sec; /* Section for this fragment */ unsigned Size; /* Size of data/expression */ struct ExprNode* Expr; /* Expression if FRAG_EXPR */ Collection LineInfos; /* Line info for this fragment */ unsigned char Type; /* Type of fragment */ unsigned char LitBuf [1]; /* Dynamically alloc'ed literal buffer */ }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ Fragment* NewFragment (unsigned char Type, unsigned Size, struct Section* S); /* Create a new fragment and insert it into the section S */ #if defined(HAVE_INLINE) INLINE const char* GetFragmentSourceName (const Fragment* F) /* Return the name of the source file for this fragment */ { return GetSourceNameFromList (&F->LineInfos); } #else # define GetFragmentSourceName(F) GetSourceNameFromList (&(F)->LineInfos) #endif #if defined(HAVE_INLINE) INLINE unsigned GetFragmentSourceLine (const Fragment* F) /* Return the source file line for this fragment */ { return GetSourceLineFromList (&F->LineInfos); } #else # define GetFragmentSourceLine(F) GetSourceLineFromList (&(F)->LineInfos) #endif /* End of fragment.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/global.c�������������������������������������������������������������������������0000664�0000000�0000000�00000006706�13473601511�0015163�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* global.c */ /* */ /* Global variables for the ld65 linker */ /* */ /* */ /* */ /* (C) 1998-2010, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include "global.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ const char* OutputName = "a.out"; /* Name of output file */ unsigned OutputNameUsed = 0; /* Output name was used by %O */ unsigned ModuleId = 0; /* Id for o65 module */ /* Start address */ unsigned char HaveStartAddr = 0; /* Start address not given */ unsigned long StartAddr = 0x200; /* Start address */ unsigned char VerboseMap = 0; /* Verbose map file */ unsigned char AllowMultDef = 0; /* Allow multiple definitions */ const char* MapFileName = 0; /* Name of the map file */ const char* LabelFileName = 0; /* Name of the label file */ const char* DbgFileName = 0; /* Name of the debug file */ ����������������������������������������������������������cc65-2.18/src/ld65/global.h�������������������������������������������������������������������������0000664�0000000�0000000�00000006751�13473601511�0015170�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* global.h */ /* */ /* Global variables for the ld65 linker */ /* */ /* */ /* */ /* (C) 1998-2010, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef GLOBAL_H #define GLOBAL_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ extern const char* OutputName; /* Name of output file */ extern unsigned OutputNameUsed; /* Output name was used by %O */ extern unsigned ModuleId; /* Id for o65 module */ extern unsigned char HaveStartAddr; /* True if start address was given */ extern unsigned long StartAddr; /* Start address */ extern unsigned char VerboseMap; /* Verbose map file */ extern unsigned char AllowMultDef; /* Allow multiple definitions */ extern const char* MapFileName; /* Name of the map file */ extern const char* LabelFileName; /* Name of the label file */ extern const char* DbgFileName; /* Name of the debug file */ /* End of global.h */ #endif �����������������������cc65-2.18/src/ld65/library.c������������������������������������������������������������������������0000664�0000000�0000000�00000040557�13473601511�0015371�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* library.c */ /* */ /* Library data structures and helpers for the ld65 linker */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> #include <errno.h> /* common */ #include "coll.h" #include "exprdefs.h" #include "libdefs.h" #include "objdefs.h" #include "symdefs.h" #include "xmalloc.h" /* ld65 */ #include "error.h" #include "exports.h" #include "fileio.h" #include "library.h" #include "objdata.h" #include "objfile.h" #include "spool.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Library data structure */ typedef struct Library Library; struct Library { unsigned Id; /* Id of library */ unsigned Name; /* String id of the name */ FILE* F; /* Open file stream */ LibHeader Header; /* Library header */ Collection Modules; /* Modules */ }; /* List of open libraries */ static Collection OpenLibs = STATIC_COLLECTION_INITIALIZER; /* List of used libraries */ static Collection LibraryList = STATIC_COLLECTION_INITIALIZER; /* Flag for library grouping */ static int Grouping = 0; /*****************************************************************************/ /* struct Library */ /*****************************************************************************/ static Library* NewLibrary (FILE* F, const char* Name) /* Create a new Library structure and return it */ { /* Allocate memory */ Library* L = xmalloc (sizeof (*L)); /* Initialize the fields */ L->Id = ~0U; L->Name = GetStringId (Name); L->F = F; L->Modules = EmptyCollection; /* Return the new struct */ return L; } static void CloseLibrary (Library* L) /* Close a library file and remove the list of modules */ { /* Close the library file */ if (fclose (L->F) != 0) { Error ("Error closing '%s': %s", GetString (L->Name), strerror (errno)); } L->F = 0; } static void FreeLibrary (Library* L) /* Free a library structure */ { /* Close the library */ CloseLibrary (L); /* Free the module index */ DoneCollection (&L->Modules); /* Free the library structure */ xfree (L); } /*****************************************************************************/ /* Reading file data structures */ /*****************************************************************************/ static void LibSeek (Library* L, unsigned long Offs) /* Do a seek in the library checking for errors */ { if (fseek (L->F, Offs, SEEK_SET) != 0) { Error ("Seek error in '%s' (%lu): %s", GetString (L->Name), Offs, strerror (errno)); } } static void LibReadHeader (Library* L) /* Read a library header */ { /* Read the remaining header fields (magic is already read) */ L->Header.Magic = LIB_MAGIC; L->Header.Version = Read16 (L->F); if (L->Header.Version != LIB_VERSION) { Error ("Wrong data version in '%s'", GetString (L->Name)); } L->Header.Flags = Read16 (L->F); L->Header.IndexOffs = Read32 (L->F); } static void LibReadObjHeader (Library* L, ObjData* O) /* Read the header of the object file checking the signature */ { O->Header.Magic = Read32 (L->F); if (O->Header.Magic != OBJ_MAGIC) { Error ("Object file '%s' in library '%s' is invalid", GetObjFileName (O), GetString (L->Name)); } O->Header.Version = Read16 (L->F); if (O->Header.Version != OBJ_VERSION) { Error ("Object file '%s' in library '%s' has wrong version", GetObjFileName (O), GetString (L->Name)); } O->Header.Flags = Read16 (L->F); O->Header.OptionOffs = Read32 (L->F); O->Header.OptionSize = Read32 (L->F); O->Header.FileOffs = Read32 (L->F); O->Header.FileSize = Read32 (L->F); O->Header.SegOffs = Read32 (L->F); O->Header.SegSize = Read32 (L->F); O->Header.ImportOffs = Read32 (L->F); O->Header.ImportSize = Read32 (L->F); O->Header.ExportOffs = Read32 (L->F); O->Header.ExportSize = Read32 (L->F); O->Header.DbgSymOffs = Read32 (L->F); O->Header.DbgSymSize = Read32 (L->F); O->Header.LineInfoOffs = Read32 (L->F); O->Header.LineInfoSize = Read32 (L->F); O->Header.StrPoolOffs = Read32 (L->F); O->Header.StrPoolSize = Read32 (L->F); O->Header.AssertOffs = Read32 (L->F); O->Header.AssertSize = Read32 (L->F); O->Header.ScopeOffs = Read32 (L->F); O->Header.ScopeSize = Read32 (L->F); O->Header.SpanOffs = Read32 (L->F); O->Header.SpanSize = Read32 (L->F); } static ObjData* ReadIndexEntry (Library* L) /* Read one entry in the index */ { /* Create a new entry and insert it into the list */ ObjData* O = NewObjData (); /* Remember from which library this module is */ O->Lib = L; /* Module name */ O->Name = ReadStr (L->F); /* Module flags/MTime/Start/Size */ O->Flags = Read16 (L->F); O->MTime = Read32 (L->F); O->Start = Read32 (L->F); Read32 (L->F); /* Skip Size */ /* Done */ return O; } static void ReadBasicData (Library* L, ObjData* O) /* Read basic data for an object file that is necessary to resolve external ** references. */ { /* Seek to the start of the object file and read the header */ LibSeek (L, O->Start); LibReadObjHeader (L, O); /* Read the string pool */ ObjReadStrPool (L->F, O->Start + O->Header.StrPoolOffs, O); /* Read the files list */ ObjReadFiles (L->F, O->Start + O->Header.FileOffs, O); /* Read the line infos */ ObjReadLineInfos (L->F, O->Start + O->Header.LineInfoOffs, O); /* Read the imports */ ObjReadImports (L->F, O->Start + O->Header.ImportOffs, O); /* Read the exports */ ObjReadExports (L->F, O->Start + O->Header.ExportOffs, O); } static void LibReadIndex (Library* L) /* Read the index of a library file */ { unsigned ModuleCount, I; /* Seek to the start of the index */ LibSeek (L, L->Header.IndexOffs); /* Read the object file count and allocate memory */ ModuleCount = ReadVar (L->F); CollGrow (&L->Modules, ModuleCount); /* Read all entries in the index */ while (ModuleCount--) { CollAppend (&L->Modules, ReadIndexEntry (L)); } /* Walk over the index and read basic data for all object files in the ** library. */ for (I = 0; I < CollCount (&L->Modules); ++I) { ReadBasicData (L, CollAtUnchecked (&L->Modules, I)); } } /*****************************************************************************/ /* High level stuff */ /*****************************************************************************/ static void LibCheckExports (ObjData* O) /* Check if the exports from this file can satisfy any import requests. If so, ** insert the imports and exports from this file and mark the file as added. */ { unsigned I; /* Check all exports */ for (I = 0; I < CollCount (&O->Exports); ++I) { const Export* E = CollConstAt (&O->Exports, I); if (IsUnresolved (E->Name)) { /* We need this module, insert the imports and exports */ O->Flags |= OBJ_REF; InsertObjGlobals (O); break; } } } static void LibOpen (FILE* F, const char* Name) /* Open the library for use */ { /* Create a new library structure */ Library* L = NewLibrary (F, Name); /* Read the remaining header fields (magic is already read) */ LibReadHeader (L); /* Seek to the index position and read the index */ LibReadIndex (L); /* Add the library to the list of open libraries */ CollAppend (&OpenLibs, L); } static void LibResolve (void) /* Resolve all externals from the list of all currently open libraries */ { unsigned I, J; unsigned Additions; /* Walk repeatedly over all open libraries until there's nothing more ** to add. */ do { Additions = 0; /* Walk over all libraries */ for (I = 0; I < CollCount (&OpenLibs); ++I) { /* Get the next library */ Library* L = CollAt (&OpenLibs, I); /* Walk through all modules in this library and check for each ** module if there are unresolved externals in existing modules ** that may be resolved by adding the module. */ for (J = 0; J < CollCount (&L->Modules); ++J) { /* Get the next module */ ObjData* O = CollAtUnchecked (&L->Modules, J); /* We only need to check this module if it wasn't added before */ if ((O->Flags & OBJ_REF) == 0) { LibCheckExports (O); if (O->Flags & OBJ_REF) { /* The routine added the file */ ++Additions; } } } } } while (Additions > 0); /* We do know now which modules must be added, so we can load the data ** for these modues into memory. Since we're walking over all modules ** anyway, we will also remove data for unneeded modules. */ for (I = 0; I < CollCount (&OpenLibs); ++I) { /* Get the next library */ Library* L = CollAt (&OpenLibs, I); /* Walk over all modules in this library and add the files list and ** sections for all referenced modules. */ J = 0; while (J < CollCount (&L->Modules)) { /* Get the object data */ ObjData* O = CollAtUnchecked (&L->Modules, J); /* Is this object file referenced? */ if (O->Flags & OBJ_REF) { /* Seek to the start of the debug info and read the debug info */ ObjReadDbgSyms (L->F, O->Start + O->Header.DbgSymOffs, O); /* Read the assertions from the object file */ ObjReadAssertions (L->F, O->Start + O->Header.AssertOffs, O); /* Seek to the start of the segment list and read the segments. ** This must be late, since the data here may reference other ** stuff. */ ObjReadSections (L->F, O->Start + O->Header.SegOffs, O); /* Read the scope table from the object file. Scopes reference ** segments, so we must read them after the sections. */ ObjReadScopes (L->F, O->Start + O->Header.ScopeOffs, O); /* Read the spans */ ObjReadSpans (L->F, O->Start + O->Header.SpanOffs, O); /* All references to strings are now resolved, so we can delete ** the module string pool. */ FreeObjStrings (O); /* Insert the object into the list of all used object files */ InsertObjData (O); /* Process next object file in library */ ++J; } else { /* Unreferenced object file, remove it */ FreeObjData (O); CollDelete (&L->Modules, J); } } /* If we have referenced modules in this library, assign it an id ** (which is the index in the library collection) and keep it. */ if (CollCount (&L->Modules) > 0) { CloseLibrary (L); L->Id = CollCount (&LibraryList); CollAppend (&LibraryList, L); } else { /* Delete the library */ FreeLibrary (L); CollDelete (&OpenLibs, I); } } /* We're done with all open libraries, clear the OpenLibs collection */ CollDeleteAll (&OpenLibs); } void LibAdd (FILE* F, const char* Name) /* Add files from the library to the list if there are references that could ** be satisfied. */ { /* Add the library to the list of open libraries */ LibOpen (F, Name); /* If there is no library group open, just resolve all open symbols and ** close the library. Otherwise we will do nothing because resolving will ** be done when the group is closed. */ if (!Grouping) { LibResolve (); } } void LibStartGroup (void) /* Start a library group. Objects within a library group may reference each ** other, and libraries are searched repeatedly until all references are ** satisfied. */ { /* We cannot already have a group open */ if (Grouping) { Error ("There's already a library group open"); } /* Start a new group */ Grouping = 1; } void LibEndGroup (void) /* End a library group and resolve all open references. Objects within a ** library group may reference each other, and libraries are searched ** repeatedly until all references are satisfied. */ { /* We must have a library group open */ if (!Grouping) { Error ("There's no library group open"); } /* Resolve symbols, end the group */ LibResolve (); Grouping = 0; } void LibCheckGroup (void) /* Check if there are open library groups */ { if (Grouping) { Error ("Library group was never closed"); } } const char* GetLibFileName (const Library* L) /* Get the name of a library */ { return GetString (L->Name); } unsigned GetLibId (const Library* L) /* Get the id of a library file. */ { return L->Id; } unsigned LibraryCount (void) /* Return the total number of libraries */ { return CollCount (&LibraryList); } void PrintDbgLibraries (FILE* F) /* Output the libraries to a debug info file */ { unsigned I; /* Output information about all libraries */ for (I = 0; I < CollCount (&LibraryList); ++I) { /* Get the library */ const Library* L = CollAtUnchecked (&LibraryList, I); /* Output the info */ fprintf (F, "lib\tid=%u,name=\"%s\"\n", L->Id, GetString (L->Name)); } } �������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/library.h������������������������������������������������������������������������0000664�0000000�0000000�00000010025�13473601511�0015361�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* library.h */ /* */ /* Library data structures and helpers for the ld65 linker */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef LIBRARY_H #define LIBRARY_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Opaque structure */ struct Library; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void LibAdd (FILE* F, const char* Name); /* Add files from the library to the list if there are references that could ** be satisfied. */ void LibStartGroup (void); /* Start a library group. Objects within a library group may reference each ** other, and libraries are searched repeatedly until all references are ** satisfied. */ void LibEndGroup (void); /* End a library group and resolve all open references. Objects within a ** library group may reference each other, and libraries are searched ** repeatedly until all references are satisfied. */ void LibCheckGroup (void); /* Check if there are open library groups */ const char* GetLibFileName (const struct Library* L); /* Get the name of a library */ unsigned GetLibId (const struct Library* L); /* Get the id of a library file. */ unsigned LibraryCount (void); /* Return the total number of libraries */ void PrintDbgLibraries (FILE* F); /* Output the libraries to a debug info file */ /* End of library.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/lineinfo.c�����������������������������������������������������������������������0000664�0000000�0000000�00000021225�13473601511�0015517�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* lineinfo.h */ /* */ /* Source file line info structure */ /* */ /* */ /* */ /* (C) 2001-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "check.h" #include "lidefs.h" #include "xmalloc.h" /* ld65 */ #include "error.h" #include "fileinfo.h" #include "fileio.h" #include "lineinfo.h" #include "objdata.h" #include "segments.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ static LineInfo* NewLineInfo (void) /* Create and return a new LineInfo struct with mostly empty fields */ { /* Allocate memory */ LineInfo* LI = xmalloc (sizeof (LineInfo)); /* Initialize the fields */ LI->Id = ~0U; LI->File = 0; LI->Type = LI_MAKE_TYPE (LI_TYPE_ASM, 0); LI->Pos.Name = INVALID_STRING_ID; LI->Pos.Line = 0; LI->Pos.Col = 0; LI->Spans = 0; /* Return the new struct */ return LI; } void FreeLineInfo (LineInfo* LI) /* Free a LineInfo structure. */ { /* Free the span list */ xfree (LI->Spans); /* Free the structure itself */ xfree (LI); } LineInfo* DupLineInfo (const LineInfo* LI) /* Creates a duplicate of a line info structure */ { /* Allocate memory */ LineInfo* New = xmalloc (sizeof (LineInfo)); /* Copy the fields (leave id invalid) */ New->Id = LI->Id; New->File = LI->File; New->Type = LI->Type; New->Pos = LI->Pos; New->Spans = DupSpanList (LI->Spans); /* Return the copy */ return New; } LineInfo* GenLineInfo (const FilePos* Pos) /* Generate a new (internally used) line info with the given information */ { /* Create a new LineInfo struct */ LineInfo* LI = NewLineInfo (); /* Initialize the fields in the new LineInfo */ LI->Pos = *Pos; /* Return the struct read */ return LI; } LineInfo* ReadLineInfo (FILE* F, ObjData* O) /* Read a line info from a file and return it */ { /* Create a new LineInfo struct */ LineInfo* LI = NewLineInfo (); /* Read/fill the fields in the new LineInfo */ LI->Pos.Line = ReadVar (F); LI->Pos.Col = ReadVar (F); LI->File = CollAt (&O->Files, ReadVar (F)); LI->Pos.Name = LI->File->Name; LI->Type = ReadVar (F); LI->Spans = ReadSpanList (F); /* Return the struct read */ return LI; } void ReadLineInfoList (FILE* F, ObjData* O, Collection* LineInfos) /* Read a list of line infos stored as a list of indices in the object file, ** make real line infos from them and place them into the passed collection. */ { /* Read the number of line info indices that follow */ unsigned LineInfoCount = ReadVar (F); /* Grow the collection as needed */ CollGrow (LineInfos, LineInfoCount); /* Read the line infos and resolve them */ while (LineInfoCount--) { /* Read an index */ unsigned LineInfoIndex = ReadVar (F); /* The line info index was written by the assembler and must ** therefore be part of the line infos read from the object file. */ if (LineInfoIndex >= CollCount (&O->LineInfos)) { Internal ("Invalid line info index %u in module '%s' - max is %u", LineInfoIndex, GetObjFileName (O), CollCount (&O->LineInfos)); } /* Add the line info to the collection */ CollAppend (LineInfos, CollAt (&O->LineInfos, LineInfoIndex)); } } const LineInfo* GetAsmLineInfo (const Collection* LineInfos) /* Find a line info of type LI_TYPE_ASM and count zero in the given collection ** and return it. Return NULL if no such line info was found. */ { unsigned I; /* Search for a line info of LI_TYPE_ASM */ for (I = 0; I < CollCount (LineInfos); ++I) { const LineInfo* LI = CollConstAt (LineInfos, I); if (LI->Type == LI_MAKE_TYPE (LI_TYPE_ASM, 0)) { return LI; } } /* Not found */ return 0; } unsigned LineInfoCount (void) /* Return the total number of line infos */ { /* Walk over all object files */ unsigned I; unsigned Count = 0; for (I = 0; I < CollCount (&ObjDataList); ++I) { /* Get this object file */ const ObjData* O = CollAtUnchecked (&ObjDataList, I); /* Count spans */ Count += CollCount (&O->LineInfos); } return Count; } void AssignLineInfoIds (void) /* Assign the ids to the line infos */ { unsigned I, J; /* Walk over all line infos */ unsigned Id = 0; for (I = 0; I < CollCount (&ObjDataList); ++I) { /* Get the object file */ ObjData* O = CollAtUnchecked (&ObjDataList, I); /* Output the line infos */ for (J = 0; J < CollCount (&O->LineInfos); ++J) { /* Get this line info */ LineInfo* LI = CollAtUnchecked (&O->LineInfos, J); /* Assign the id */ LI->Id = Id++; } } } void PrintDbgLineInfo (FILE* F) /* Output the line infos to a debug info file */ { unsigned I, J; /* Print line infos from all modules we have linked into the output file */ for (I = 0; I < CollCount (&ObjDataList); ++I) { /* Get the object file */ const ObjData* O = CollAtUnchecked (&ObjDataList, I); /* Output the line infos */ for (J = 0; J < CollCount (&O->LineInfos); ++J) { /* Get this line info */ const LineInfo* LI = CollConstAt (&O->LineInfos, J); /* Get the line info type and count */ unsigned Type = LI_GET_TYPE (LI->Type); unsigned Count = LI_GET_COUNT (LI->Type); /* Print the start of the line */ fprintf (F, "line\tid=%u,file=%u,line=%u", LI->Id, LI->File->Id, GetSourceLine (LI)); /* Print type if not LI_TYPE_ASM and count if not zero */ if (Type != LI_TYPE_ASM) { fprintf (F, ",type=%u", Type); } if (Count != 0) { fprintf (F, ",count=%u", Count); } /* Add spans if the line info has it */ PrintDbgSpanList (F, O, LI->Spans); /* Terminate line */ fputc ('\n', F); } } } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/lineinfo.h�����������������������������������������������������������������������0000664�0000000�0000000�00000015406�13473601511�0015530�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* lineinfo.h */ /* */ /* Source file line info structure */ /* */ /* */ /* */ /* (C) 2001-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef LINEINFO_H #define LINEINFO_H #include <stdio.h> /* common */ #include "coll.h" #include "filepos.h" /* ld65 */ #include "span.h" #include "spool.h" /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ struct ObjData; struct Segment; /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Structure holding line information. The Pos.Name field is always the ** global string id of the file name. If the line info was read from the ** object file, the File pointer is valid, otherwise it is NULL. */ typedef struct LineInfo LineInfo; struct LineInfo { unsigned Id; /* Line info id */ struct FileInfo* File; /* File struct for this line if any */ unsigned Type; /* Type of line info */ FilePos Pos; /* Position in file */ unsigned* Spans; /* Spans for this line */ }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ LineInfo* GenLineInfo (const FilePos* Pos); /* Generate a new (internally used) line info with the given information */ LineInfo* ReadLineInfo (FILE* F, struct ObjData* O); /* Read a line info from a file and return it */ void FreeLineInfo (LineInfo* LI); /* Free a LineInfo structure. */ LineInfo* DupLineInfo (const LineInfo* LI); /* Creates a duplicate of a line info structure */ void ReadLineInfoList (FILE* F, struct ObjData* O, Collection* LineInfos); /* Read a list of line infos stored as a list of indices in the object file, ** make real line infos from them and place them into the passed collection. */ const LineInfo* GetAsmLineInfo (const Collection* LineInfos); /* Find a line info of type LI_TYPE_ASM and count zero in the given collection ** and return it. Return NULL if no such line info was found. */ #if defined(HAVE_INLINE) INLINE const FilePos* GetSourcePos (const LineInfo* LI) /* Return the source file position from the given line info */ { return &LI->Pos; } #else # define GetSourcePos(LI) (&(LI)->Pos) #endif #if defined(HAVE_INLINE) INLINE const char* GetSourceName (const LineInfo* LI) /* Return the name of a source file from the given line info */ { return GetString (LI->Pos.Name); } #else # define GetSourceName(LI) (GetString ((LI)->Pos.Name)) #endif #if defined(HAVE_INLINE) INLINE unsigned GetSourceLine (const LineInfo* LI) /* Return the source file line from the given line info */ { return LI->Pos.Line; } #else # define GetSourceLine(LI) ((LI)->Pos.Line) #endif #if defined(HAVE_INLINE) INLINE unsigned GetSourceCol (const LineInfo* LI) /* Return the source file column from the given line info */ { return LI->Pos.Col; } #else # define GetSourceCol(LI) ((LI)->Pos.Col) #endif #if defined(HAVE_INLINE) INLINE const char* GetSourceNameFromList (const Collection* LineInfos) /* Return the name of a source file from a list of line infos */ { /* The relevant entry is in slot zero */ return GetSourceName (CollConstAt (LineInfos, 0)); } #else # define GetSourceNameFromList(LineInfos) \ GetSourceName ((const LineInfo*) CollConstAt ((LineInfos), 0)) #endif #if defined(HAVE_INLINE) INLINE unsigned GetSourceLineFromList (const Collection* LineInfos) /* Return the source file line from a list of line infos */ { /* The relevant entry is in slot zero */ return GetSourceLine (CollConstAt (LineInfos, 0)); } #else # define GetSourceLineFromList(LineInfos) \ GetSourceLine ((const LineInfo*) CollConstAt ((LineInfos), 0)) #endif unsigned LineInfoCount (void); /* Return the total number of line infos */ void AssignLineInfoIds (void); /* Assign the ids to the line infos */ void PrintDbgLineInfo (FILE* F); /* Output the line infos to a debug info file */ /* End of lineinfo.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/main.c���������������������������������������������������������������������������0000664�0000000�0000000�00000061606�13473601511�0014647�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* main.c */ /* */ /* Main program for the ld65 linker */ /* */ /* */ /* */ /* (C) 1998-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> /* common */ #include "addrsize.h" #include "chartype.h" #include "cmdline.h" #include "filetype.h" #include "libdefs.h" #include "objdefs.h" #include "print.h" #include "target.h" #include "version.h" #include "xmalloc.h" /* ld65 */ #include "asserts.h" #include "binfmt.h" #include "condes.h" #include "config.h" #include "dbgfile.h" #include "error.h" #include "exports.h" #include "fileio.h" #include "filepath.h" #include "global.h" #include "library.h" #include "mapfile.h" #include "objfile.h" #include "scanner.h" #include "segments.h" #include "spool.h" #include "tpool.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ static unsigned ObjFiles = 0; /* Count of object files linked */ static unsigned LibFiles = 0; /* Count of library files linked */ /* struct InputFile.Type definitions */ #define INPUT_FILES_FILE 0 /* Entry is a file (unknown type) */ #define INPUT_FILES_FILE_OBJ 1 /* Entry is a object file */ #define INPUT_FILES_FILE_LIB 2 /* Entry is a library file */ #define INPUT_FILES_SGROUP 3 /* Entry is 'StartGroup' */ #define INPUT_FILES_EGROUP 4 /* Entry is 'EndGroup' */ #define MAX_INPUTFILES 256 /* Array of inputs (libraries and object files) */ static struct InputFile { const char *FileName; unsigned Type; } *InputFiles; static unsigned InputFilesCount = 0; static const char *CmdlineCfgFile = NULL, *CmdlineTarget = NULL; /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void Usage (void) /* Print usage information and exit */ { printf ("Usage: %s [options] module ...\n" "Short options:\n" " -(\t\t\tStart a library group\n" " -)\t\t\tEnd a library group\n" " -C name\t\tUse linker config file\n" " -D sym=val\t\tDefine a symbol\n" " -L path\t\tSpecify a library search path\n" " -Ln name\t\tCreate a VICE label file\n" " -S addr\t\tSet the default start address\n" " -V\t\t\tPrint the linker version\n" " -h\t\t\tHelp (this text)\n" " -m name\t\tCreate a map file\n" " -o name\t\tName the default output file\n" " -t sys\t\tSet the target system\n" " -u sym\t\tForce an import of symbol 'sym'\n" " -v\t\t\tVerbose mode\n" " -vm\t\t\tVerbose map file\n" "\n" "Long options:\n" " --allow-multiple-definition\tAllow multiple definitions\n" " --cfg-path path\t\tSpecify a config file search path\n" " --config name\t\t\tUse linker config file\n" " --dbgfile name\t\tGenerate debug information\n" " --define sym=val\t\tDefine a symbol\n" " --end-group\t\t\tEnd a library group\n" " --force-import sym\t\tForce an import of symbol 'sym'\n" " --help\t\t\tHelp (this text)\n" " --lib file\t\t\tLink this library\n" " --lib-path path\t\tSpecify a library search path\n" " --mapfile name\t\tCreate a map file\n" " --module-id id\t\tSpecify a module id\n" " --obj file\t\t\tLink this object file\n" " --obj-path path\t\tSpecify an object file search path\n" " --start-addr addr\t\tSet the default start address\n" " --start-group\t\t\tStart a library group\n" " --target sys\t\t\tSet the target system\n" " --version\t\t\tPrint the linker version\n", ProgName); } static unsigned long CvtNumber (const char* Arg, const char* Number) /* Convert a number from a string. Allow '$' and '0x' prefixes for hex ** numbers. */ { unsigned long Val; int Converted; /* Convert */ if (*Number == '$') { ++Number; Converted = sscanf (Number, "%lx", &Val); } else { Converted = sscanf (Number, "%li", (long*)&Val); } /* Check if we do really have a number */ if (Converted != 1) { Error ("Invalid number given in argument: %s\n", Arg); } /* Return the result */ return Val; } static void LinkFile (const char* Name, FILETYPE Type) /* Handle one file */ { char* PathName; FILE* F; unsigned long Magic; /* If we don't know the file type, determine it from the extension */ if (Type == FILETYPE_UNKNOWN) { Type = GetFileType (Name); } /* For known file types, search the file in the directory list */ switch (Type) { case FILETYPE_LIB: PathName = SearchFile (LibSearchPath, Name); if (PathName == 0) { PathName = SearchFile (LibDefaultPath, Name); } break; case FILETYPE_OBJ: PathName = SearchFile (ObjSearchPath, Name); if (PathName == 0) { PathName = SearchFile (ObjDefaultPath, Name); } break; default: PathName = xstrdup (Name); /* Use the name as is */ break; } /* We must have a valid name now */ if (PathName == 0) { Error ("Input file '%s' not found", Name); } /* Try to open the file */ F = fopen (PathName, "rb"); if (F == 0) { Error ("Cannot open '%s': %s", PathName, strerror (errno)); } /* Read the magic word */ Magic = Read32 (F); /* Check the magic for known file types. The handling is somewhat weird ** since we may have given a file with a ".lib" extension, which was ** searched and found in a directory for library files, but we now find ** out (by looking at the magic) that it's indeed an object file. We just ** ignore the problem and hope no one will notice... */ switch (Magic) { case OBJ_MAGIC: ObjAdd (F, PathName); ++ObjFiles; break; case LIB_MAGIC: LibAdd (F, PathName); ++LibFiles; break; default: fclose (F); Error ("File '%s' has unknown type", PathName); } /* Free allocated memory. */ xfree (PathName); } static void DefineSymbol (const char* Def) /* Define a symbol from the command line */ { const char* P; long Val; StrBuf SymName = AUTO_STRBUF_INITIALIZER; /* The symbol must start with a character or underline */ if (Def [0] != '_' && !IsAlpha (Def [0])) { InvDef (Def); } P = Def; /* Copy the symbol, checking the remainder */ while (IsAlNum (*P) || *P == '_') { SB_AppendChar (&SymName, *P++); } SB_Terminate (&SymName); /* Do we have a value given? */ if (*P != '=') { InvDef (Def); } else { /* We have a value */ ++P; if (*P == '$') { ++P; if (sscanf (P, "%lx", &Val) != 1) { InvDef (Def); } } else { if (sscanf (P, "%li", &Val) != 1) { InvDef (Def); } } } /* Define the new symbol */ CreateConstExport (GetStringId (SB_GetConstBuf (&SymName)), Val); } static void OptCfgPath (const char* Opt attribute ((unused)), const char* Arg) /* Specify a config file search path */ { AddSearchPath (CfgSearchPath, Arg); } static void OptConfig (const char* Opt attribute ((unused)), const char* Arg) /* Define the config file */ { char* PathName; if (CfgAvail ()) { Error ("Cannot use -C/-t twice"); } /* Search for the file */ PathName = SearchFile (CfgSearchPath, Arg); if (PathName == 0) { PathName = SearchFile (CfgDefaultPath, Arg); } if (PathName == 0) { Error ("Cannot find config file '%s'", Arg); } /* Read the config */ CfgSetName (PathName); CfgRead (); } static void OptDbgFile (const char* Opt attribute ((unused)), const char* Arg) /* Give the name of the debug file */ { DbgFileName = Arg; } static void OptDefine (const char* Opt attribute ((unused)), const char* Arg) /* Define a symbol on the command line */ { DefineSymbol (Arg); } static void OptEndGroup (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* End a library group */ { LibEndGroup (); } static void OptForceImport (const char* Opt attribute ((unused)), const char* Arg) /* Force an import of a symbol */ { /* An optional address size may be specified */ const char* ColPos = strchr (Arg, ':'); if (ColPos == 0) { /* Use default address size (which for now is always absolute ** addressing) */ InsertImport (GenImport (GetStringId (Arg), ADDR_SIZE_ABS)); } else { char* A; /* Get the address size and check it */ unsigned char AddrSize = AddrSizeFromStr (ColPos+1); if (AddrSize == ADDR_SIZE_INVALID) { Error ("Invalid address size '%s'", ColPos+1); } /* Create a copy of the argument */ A = xstrdup (Arg); /* We need just the symbol */ A[ColPos - Arg] = '\0'; /* Generate the import */ InsertImport (GenImport (GetStringId (A), AddrSize)); /* Delete the copy of the argument */ xfree (A); } } static void OptHelp (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Print usage information and exit */ { Usage (); exit (EXIT_SUCCESS); } static void OptLib (const char* Opt attribute ((unused)), const char* Arg) /* Link a library */ { InputFiles[InputFilesCount].Type = INPUT_FILES_FILE_LIB; InputFiles[InputFilesCount].FileName = Arg; if (++InputFilesCount >= MAX_INPUTFILES) Error ("Too many input files"); } static void OptLibPath (const char* Opt attribute ((unused)), const char* Arg) /* Specify a library file search path */ { AddSearchPath (LibSearchPath, Arg); } static void OptMapFile (const char* Opt attribute ((unused)), const char* Arg) /* Give the name of the map file */ { if (MapFileName) { Error ("Cannot use -m twice"); } MapFileName = Arg; } static void OptModuleId (const char* Opt, const char* Arg) /* Specify a module id */ { unsigned long Id = CvtNumber (Opt, Arg); if (Id > 0xFFFFUL) { Error ("Range error in module id"); } ModuleId = (unsigned) Id; } static void OptObj (const char* Opt attribute ((unused)), const char* Arg) /* Link an object file */ { InputFiles[InputFilesCount].Type = INPUT_FILES_FILE_OBJ; InputFiles[InputFilesCount].FileName = Arg; if (++InputFilesCount >= MAX_INPUTFILES) Error ("Too many input files"); } static void OptObjPath (const char* Opt attribute ((unused)), const char* Arg) /* Specify an object file search path */ { AddSearchPath (ObjSearchPath, Arg); } static void OptOutputName (const char* Opt attribute ((unused)), const char* Arg) /* Give the name of the output file */ { static int OutputNameSeen = 0; if (OutputNameSeen) { Error ("Cannot use -o twice"); } OutputNameSeen = 1; OutputName = Arg; } static void OptStartAddr (const char* Opt, const char* Arg) /* Set the default start address */ { if (HaveStartAddr) { Error ("Cannot use -S twice"); } StartAddr = CvtNumber (Opt, Arg); HaveStartAddr = 1; } static void OptStartGroup (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Start a library group */ { LibStartGroup (); } static void OptTarget (const char* Opt attribute ((unused)), const char* Arg) /* Set the target system */ { StrBuf FileName = STATIC_STRBUF_INITIALIZER; char* PathName; /* Map the target name to a target id */ Target = FindTarget (Arg); if (Target == TGT_UNKNOWN) { Error ("Invalid target name: '%s'", Arg); } /* Set the target binary format */ DefaultBinFmt = GetTargetProperties (Target)->BinFmt; /* Build config file name from target name */ SB_CopyStr (&FileName, GetTargetName (Target)); SB_AppendStr (&FileName, ".cfg"); SB_Terminate (&FileName); /* Search for the file */ PathName = SearchFile (CfgSearchPath, SB_GetBuf (&FileName)); if (PathName == 0) { PathName = SearchFile (CfgDefaultPath, SB_GetBuf (&FileName)); } if (PathName == 0) { Error ("Cannot find config file '%s'", SB_GetBuf (&FileName)); } /* Free file name memory */ SB_Done (&FileName); /* Read the file */ CfgSetName (PathName); CfgRead (); } static void OptVersion (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Print the assembler version */ { fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ()); exit(EXIT_SUCCESS); } static void OptMultDef (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Set flag to allow multiple definitions of a global symbol */ { AllowMultDef = 1; } static void CmdlOptStartGroup (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Remember 'start group' occurrence in input files array */ { InputFiles[InputFilesCount].Type = INPUT_FILES_SGROUP; InputFiles[InputFilesCount].FileName = Arg; /* Unused */ if (++InputFilesCount >= MAX_INPUTFILES) Error ("Too many input files"); } static void CmdlOptEndGroup (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Remember 'end group' occurrence in input files array */ { InputFiles[InputFilesCount].Type = INPUT_FILES_EGROUP; InputFiles[InputFilesCount].FileName = Arg; /* Unused */ if (++InputFilesCount >= MAX_INPUTFILES) Error ("Too many input files"); } static void CmdlOptConfig (const char* Opt attribute ((unused)), const char* Arg) /* Set 'config file' command line parameter */ { if (CmdlineCfgFile || CmdlineTarget) { Error ("Cannot use -C/-t twice"); } CmdlineCfgFile = Arg; } static void CmdlOptTarget (const char* Opt attribute ((unused)), const char* Arg) /* Set 'target' command line parameter */ { if (CmdlineCfgFile || CmdlineTarget) { Error ("Cannot use -C/-t twice"); } CmdlineTarget = Arg; } static void ParseCommandLine(void) { /* Program long options */ static const LongOpt OptTab[] = { { "--allow-multiple-definition", 0, OptMultDef }, { "--cfg-path", 1, OptCfgPath }, { "--config", 1, CmdlOptConfig }, { "--dbgfile", 1, OptDbgFile }, { "--define", 1, OptDefine }, { "--end-group", 0, CmdlOptEndGroup }, { "--force-import", 1, OptForceImport }, { "--help", 0, OptHelp }, { "--lib", 1, OptLib }, { "--lib-path", 1, OptLibPath }, { "--mapfile", 1, OptMapFile }, { "--module-id", 1, OptModuleId }, { "--obj", 1, OptObj }, { "--obj-path", 1, OptObjPath }, { "--start-addr", 1, OptStartAddr }, { "--start-group", 0, CmdlOptStartGroup }, { "--target", 1, CmdlOptTarget }, { "--version", 0, OptVersion }, }; unsigned I; unsigned LabelFileGiven = 0; /* Allocate memory for input file array */ InputFiles = xmalloc (MAX_INPUTFILES * sizeof (struct InputFile)); /* Defer setting of config/target and input files until all options are parsed */ I = 1; while (I < ArgCount) { /* Get the argument */ const char* Arg = ArgVec[I]; /* Check for an option */ if (Arg [0] == '-') { /* An option */ switch (Arg [1]) { case '-': LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0])); break; case '(': CmdlOptStartGroup (Arg, 0); break; case ')': CmdlOptEndGroup (Arg, 0); break; case 'h': case '?': OptHelp (Arg, 0); break; case 'm': OptMapFile (Arg, GetArg (&I, 2)); break; case 'o': OptOutputName (NULL, GetArg (&I, 2)); break; case 't': CmdlOptTarget (Arg, GetArg (&I, 2)); break; case 'u': OptForceImport (Arg, GetArg (&I, 2)); break; case 'v': switch (Arg [2]) { case 'm': VerboseMap = 1; break; case '\0': ++Verbosity; break; default: UnknownOption (Arg); } break; case 'C': CmdlOptConfig (Arg, GetArg (&I, 2)); break; case 'D': OptDefine (Arg, GetArg (&I, 2)); break; case 'L': switch (Arg [2]) { case 'n': /* ## This one is obsolete and will go */ if (LabelFileGiven) { Error ("Cannot use -Ln twice"); } LabelFileGiven = 1; LabelFileName = GetArg (&I, 3); break; default: OptLibPath (Arg, GetArg (&I, 2)); break; } break; case 'S': OptStartAddr (Arg, GetArg (&I, 2)); break; case 'V': OptVersion (Arg, 0); break; default: UnknownOption (Arg); break; } } else { /* A filename */ InputFiles[InputFilesCount].Type = INPUT_FILES_FILE; InputFiles[InputFilesCount].FileName = Arg; if (++InputFilesCount >= MAX_INPUTFILES) Error ("Too many input files"); } /* Next argument */ ++I; } if (CmdlineTarget) { OptTarget (NULL, CmdlineTarget); } else if (CmdlineCfgFile) { OptConfig (NULL, CmdlineCfgFile); } /* Process input files */ for (I = 0; I < InputFilesCount; ++I) { switch (InputFiles[I].Type) { case INPUT_FILES_FILE: LinkFile (InputFiles[I].FileName, FILETYPE_UNKNOWN); break; case INPUT_FILES_FILE_LIB: LinkFile (InputFiles[I].FileName, FILETYPE_LIB); break; case INPUT_FILES_FILE_OBJ: LinkFile (InputFiles[I].FileName, FILETYPE_OBJ); break; case INPUT_FILES_SGROUP: OptStartGroup (NULL, 0); break; case INPUT_FILES_EGROUP: OptEndGroup (NULL, 0); break; default: abort (); } } /* Free memory used for input file array */ xfree (InputFiles); } int main (int argc, char* argv []) /* Linker main program */ { unsigned MemoryAreaOverflows; /* Initialize the cmdline module */ InitCmdLine (&argc, &argv, "ld65"); /* Initialize the input file search paths */ InitSearchPaths (); /* Initialize the string pool */ InitStrPool (); /* Initialize the type pool */ InitTypePool (); /* Parse the command line */ ParseCommandLine (); /* Check if we had any object files */ if (ObjFiles == 0) { Error ("No object files to link"); } /* Check if we have a valid configuration */ if (!CfgAvail ()) { Error ("Memory configuration missing"); } /* Check if we have open library groups */ LibCheckGroup (); /* Create the condes tables if requested */ ConDesCreate (); /* Process data from the config file. Assign start addresses for the ** segments, define linker symbols. The function will return the number ** of memory area overflows (zero on success). */ MemoryAreaOverflows = CfgProcess (); /* Check module assertions */ CheckAssertions (); /* Check for import/export mismatches */ CheckExports (); /* If we had a memory area overflow before, we cannot generate the output ** file. However, we will generate a short map file if requested, since ** this will help the user to rearrange segments and fix the overflow. */ if (MemoryAreaOverflows) { if (MapFileName) { CreateMapFile (SHORT_MAPFILE); } Error ("Cannot generate most of the files due to memory area overflow%c", (MemoryAreaOverflows > 1) ? 's' : ' '); } /* Create the output file */ CfgWriteTarget (); /* Check for segments not written to the output file */ CheckSegments (); /* If requested, create a map file and a label file for VICE */ if (MapFileName) { CreateMapFile (LONG_MAPFILE); } if (LabelFileName) { CreateLabelFile (); } if (DbgFileName) { CreateDbgFile (); } /* Dump the data for debugging */ if (Verbosity > 1) { SegDump (); ConDesDump (); } /* Return an apropriate exit code */ return EXIT_SUCCESS; } ��������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/mapfile.c������������������������������������������������������������������������0000664�0000000�0000000�00000013563�13473601511�0015337�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* mapfile.c */ /* */ /* Map file creation for the ld65 linker */ /* */ /* */ /* */ /* (C) 1998-2010, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> #include <errno.h> /* ld65 */ #include "config.h" #include "dbgsyms.h" #include "exports.h" #include "global.h" #include "error.h" #include "library.h" #include "mapfile.h" #include "objdata.h" #include "segments.h" #include "spool.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void CreateMapFile (int ShortMap) /* Create a map file. If ShortMap is true, only the segment lists are ** generated, not the import/export lists. */ { unsigned I; /* Open the map file */ FILE* F = fopen (MapFileName, "w"); if (F == 0) { Error ("Cannot create map file '%s': %s", MapFileName, strerror (errno)); } /* Write a modules list */ fprintf (F, "Modules list:\n" "-------------\n"); for (I = 0; I < CollCount (&ObjDataList); ++I) { unsigned J; /* Get the object file */ const ObjData* O = CollConstAt (&ObjDataList, I); /* Output the data */ if (O->Lib) { /* The file is from a library */ fprintf (F, "%s(%s):\n", GetLibFileName (O->Lib), GetObjFileName (O)); } else { fprintf (F, "%s:\n", GetObjFileName (O)); } for (J = 0; J < CollCount (&O->Sections); ++J) { const Section* S = CollConstAt (&O->Sections, J); /* Don't include zero sized sections if not explicitly ** requested */ if (VerboseMap || S->Size > 0) { fprintf (F, " %-17s Offs=%06lX Size=%06lX " "Align=%05lX Fill=%04lX\n", GetString (S->Seg->Name), S->Offs, S->Size, S->Alignment, S->Fill); } } } /* Write the segment list */ fprintf (F, "\n\n" "Segment list:\n" "-------------\n"); PrintSegmentMap (F); /* The remainder is not written for short map files */ if (!ShortMap) { /* Write the exports list by name */ fprintf (F, "\n\n" "Exports list by name:\n" "---------------------\n"); PrintExportMapByName (F); /* Write the exports list by value */ fprintf (F, "\n\n" "Exports list by value:\n" "----------------------\n"); PrintExportMapByValue (F); /* Write the imports list */ fprintf (F, "\n\n" "Imports list:\n" "-------------\n"); PrintImportMap (F); } /* Close the file */ if (fclose (F) != 0) { Error ("Error closing map file '%s': %s", MapFileName, strerror (errno)); } } void CreateLabelFile (void) /* Create a label file */ { /* Open the label file */ FILE* F = fopen (LabelFileName, "w"); if (F == 0) { Error ("Cannot create label file '%s': %s", LabelFileName, strerror (errno)); } /* Print the labels for the export symbols */ PrintExportLabels (F); /* Output the labels */ PrintDbgSymLabels (F); /* Close the file */ if (fclose (F) != 0) { Error ("Error closing label file '%s': %s", LabelFileName, strerror (errno)); } } ���������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/mapfile.h������������������������������������������������������������������������0000664�0000000�0000000�00000006562�13473601511�0015345�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* mapfile.h */ /* */ /* Map file creation for the ld65 linker */ /* */ /* */ /* */ /* (C) 1998-2005 Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef MAPFILE_H #define MAPFILE_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Constants that may be used as arguments for CreateMapFile */ enum { LONG_MAPFILE, SHORT_MAPFILE }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void CreateMapFile (int ShortMap); /* Create a map file. If ShortMap is true, only the segment lists are ** generated, not the import/export lists. */ void CreateLabelFile (void); /* Create a label file */ /* End of mapfile.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/memarea.c������������������������������������������������������������������������0000664�0000000�0000000�00000006741�13473601511�0015331�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* memarea.c */ /* */ /* Memory area definition for the ld65 linker */ /* */ /* */ /* */ /* (C) 2010-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "xmalloc.h" /* ld65 */ #include "memarea.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ MemoryArea* NewMemoryArea (const FilePos* Pos, unsigned Name) /* Create a new memory area and insert it into the list */ { /* Allocate memory */ MemoryArea* M = xmalloc (sizeof (MemoryArea)); /* Initialize the fields ... */ M->LI = GenLineInfo (Pos); M->Name = Name; M->Attr = 0; M->Flags = 0; M->FileOffs = ~0UL; M->StartExpr = 0; M->Start = 0; M->SizeExpr = 0; M->Size = 0; M->BankExpr = 0; M->FillLevel = 0; M->FillVal = 0; M->Relocatable = 0; M->SegList = EmptyCollection; M->F = 0; /* ...and return it */ return M; } �������������������������������cc65-2.18/src/ld65/memarea.h������������������������������������������������������������������������0000664�0000000�0000000�00000011425�13473601511�0015331�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* memarea.h */ /* */ /* Memory area definition for the ld65 linker */ /* */ /* */ /* */ /* (C) 2010-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef MEMAREA_H #define MEMAREA_H /* common */ #include "coll.h" /* ld65 */ #include "lineinfo.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Forwards for structures */ struct ExprNode; struct File; /* Memory area entry */ typedef struct MemoryArea MemoryArea; struct MemoryArea { LineInfo* LI; /* Where was the area was defined? */ unsigned Name; /* Name index of the memory area */ unsigned Attr; /* Which values are valid? */ unsigned Flags; /* Set of bitmapped flags */ unsigned long FileOffs; /* Offset in output file */ struct ExprNode* StartExpr; /* Expression for start address */ unsigned long Start; /* Start address */ struct ExprNode* SizeExpr; /* Expression for size */ unsigned long Size; /* Length of memory section */ struct ExprNode* BankExpr; /* Expression for bank */ unsigned long FillLevel; /* Actual fill level of segment */ unsigned char FillVal; /* Value used to fill rest of seg */ unsigned char Relocatable; /* Memory area is relocatable */ Collection SegList; /* List of segments for this area */ struct File* F; /* Output file for this area */ }; /* Memory flags */ #define MF_DEFINE 0x0001 /* Define start and size */ #define MF_FILL 0x0002 /* Fill segment */ #define MF_RO 0x0004 /* Read only memory area */ #define MF_OVERFLOW 0x0008 /* Memory area overflow */ #define MF_PLACED 0x0010 /* Memory area was placed */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ MemoryArea* NewMemoryArea (const FilePos* Pos, unsigned Name); /* Create a new memory area and insert it into the list */ /* End of memarea.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/o65.c����������������������������������������������������������������������������0000664�0000000�0000000�00000124443�13473601511�0014333�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* o65.c */ /* */ /* Module to handle the o65 binary format */ /* */ /* */ /* */ /* (C) 1999-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> #include <limits.h> #include <errno.h> #include <time.h> /* common */ #include "chartype.h" #include "check.h" #include "fname.h" #include "print.h" #include "version.h" #include "xmalloc.h" /* ld65 */ #include "error.h" #include "exports.h" #include "expr.h" #include "fileio.h" #include "global.h" #include "lineinfo.h" #include "memarea.h" #include "o65.h" #include "spool.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Header mode bits */ #define MF_CPU_65816 0x8000 /* Executable is for 65816 */ #define MF_CPU_6502 0x0000 /* Executable is for the 6502 */ #define MF_CPU_MASK 0x8000 /* Mask to extract CPU type */ #define MF_RELOC_PAGE 0x4000 /* Page wise relocation */ #define MF_RELOC_BYTE 0x0000 /* Byte wise relocation */ #define MF_RELOC_MASK 0x4000 /* Mask to extract relocation type */ #define MF_SIZE_32BIT 0x2000 /* All size words are 32bit */ #define MF_SIZE_16BIT 0x0000 /* All size words are 16bit */ #define MF_SIZE_MASK 0x2000 /* Mask to extract size */ #define MF_FTYPE_OBJ 0x1000 /* Object file */ #define MF_FTYPE_EXE 0x0000 /* Executable file */ #define MF_FTYPE_MASK 0x1000 /* Mask to extract type */ #define MF_ADDR_SIMPLE 0x0800 /* Simple addressing */ #define MF_ADDR_DEFAULT 0x0000 /* Default addressing */ #define MF_ADDR_MASK 0x0800 /* Mask to extract addressing */ #define MF_ALIGN_1 0x0000 /* Bytewise alignment */ #define MF_ALIGN_2 0x0001 /* Align words */ #define MF_ALIGN_4 0x0002 /* Align longwords */ #define MF_ALIGN_256 0x0003 /* Align pages (256 bytes) */ #define MF_ALIGN_MASK 0x0003 /* Mask to extract alignment */ /* The four o65 segment types. Note: These values are identical to the values ** needed for the segmentID in the o65 spec. */ #define O65SEG_UNDEF 0x00 #define O65SEG_ABS 0x01 #define O65SEG_TEXT 0x02 #define O65SEG_DATA 0x03 #define O65SEG_BSS 0x04 #define O65SEG_ZP 0x05 /* Relocation type codes for the o65 format */ #define O65RELOC_WORD 0x80 #define O65RELOC_HIGH 0x40 #define O65RELOC_LOW 0x20 #define O65RELOC_SEGADR 0xC0 #define O65RELOC_SEG 0xA0 #define O65RELOC_MASK 0xE0 /* O65 executable file header */ typedef struct O65Header O65Header; struct O65Header { unsigned Version; /* Version number for o65 format */ unsigned Mode; /* Mode word */ unsigned long TextBase; /* Base address of text segment */ unsigned long TextSize; /* Size of text segment */ unsigned long DataBase; /* Base of data segment */ unsigned long DataSize; /* Size of data segment */ unsigned long BssBase; /* Base of bss segment */ unsigned long BssSize; /* Size of bss segment */ unsigned long ZPBase; /* Base of zeropage segment */ unsigned long ZPSize; /* Size of zeropage segment */ unsigned long StackSize; /* Requested stack size */ }; /* An o65 option */ typedef struct O65Option O65Option; struct O65Option { O65Option* Next; /* Next in option list */ unsigned char Type; /* Type of option */ unsigned char Len; /* Data length */ unsigned char Data [1]; /* Data, dynamically allocated */ }; /* A o65 relocation table */ typedef struct O65RelocTab O65RelocTab; struct O65RelocTab { unsigned Size; /* Size of the table */ unsigned Fill; /* Amount used */ unsigned char* Buf; /* Buffer, dynamically allocated */ }; /* Structure describing the format */ struct O65Desc { O65Header Header; /* File header */ O65Option* Options; /* List of file options */ ExtSymTab* Exports; /* Table with exported symbols */ ExtSymTab* Imports; /* Table with imported symbols */ unsigned Undef; /* Count of undefined symbols */ FILE* F; /* The file we're writing to */ const char* Filename; /* Name of the output file */ O65RelocTab* TextReloc; /* Relocation table for text segment */ O65RelocTab* DataReloc; /* Relocation table for data segment */ unsigned TextCount; /* Number of segments assigned to .text */ SegDesc** TextSeg; /* Array of text segments */ unsigned DataCount; /* Number of segments assigned to .data */ SegDesc** DataSeg; /* Array of data segments */ unsigned BssCount; /* Number of segments assigned to .bss */ SegDesc** BssSeg; /* Array of bss segments */ unsigned ZPCount; /* Number of segments assigned to .zp */ SegDesc** ZPSeg; /* Array of zp segments */ /* Temporary data for writing segments */ unsigned long SegSize; O65RelocTab* CurReloc; long LastOffs; }; /* Structure for parsing expression trees */ typedef struct ExprDesc ExprDesc; struct ExprDesc { O65Desc* D; /* File format descriptor */ long Val; /* The offset value */ int TooComplex; /* Expression too complex */ MemoryArea* MemRef; /* Memory reference if any */ Segment* SegRef; /* Segment reference if any */ Section* SecRef; /* Section reference if any */ ExtSym* ExtRef; /* External reference if any */ }; /*****************************************************************************/ /* Helper functions */ /*****************************************************************************/ static ExprDesc* InitExprDesc (ExprDesc* ED, O65Desc* D) /* Initialize an ExprDesc structure for use with O65ParseExpr */ { ED->D = D; ED->Val = 0; ED->TooComplex = 0; ED->MemRef = 0; ED->SegRef = 0; ED->SecRef = 0; ED->ExtRef = 0; return ED; } static void WriteSize (const O65Desc* D, unsigned long Val) /* Write a "size" word to the file */ { switch (D->Header.Mode & MF_SIZE_MASK) { case MF_SIZE_16BIT: Write16 (D->F, (unsigned) Val); break; case MF_SIZE_32BIT: Write32 (D->F, Val); break; default: Internal ("Invalid size in header: %04X", D->Header.Mode); } } static unsigned O65SegType (const SegDesc* S) /* Map our own segment types into something o65 compatible */ { /* Check the segment type. Readonly segments are assign to the o65 ** text segment, writeable segments that contain data are assigned ** to data, bss and zp segments are handled respectively. ** Beware: Zeropage segments have the SF_BSS flag set, so be sure ** to check SF_ZP first. */ if (S->Flags & SF_RO) { return O65SEG_TEXT; } else if (S->Flags & SF_ZP) { return O65SEG_ZP; } else if (S->Flags & SF_BSS) { return O65SEG_BSS; } else { return O65SEG_DATA; } } static void CvtMemoryToSegment (ExprDesc* ED) /* Convert a memory area into a segment by searching the list of run segments ** in this memory area and assigning the nearest one. */ { /* Get the memory area from the expression */ MemoryArea* M = ED->MemRef; /* Remember the "nearest" segment and its offset */ Segment* Nearest = 0; unsigned long Offs = ULONG_MAX; /* Walk over all segments */ unsigned I; for (I = 0; I < CollCount (&M->SegList); ++I) { /* Get the segment and check if it's a run segment */ SegDesc* S = CollAtUnchecked (&M->SegList, I); if (S->Run == M) { unsigned long O; /* Get the segment from the segment descriptor */ Segment* Seg = S->Seg; /* Check the PC. */ if ((long) Seg->PC <= ED->Val && (O = (ED->Val - Seg->PC)) < Offs) { /* This is the nearest segment for now */ Offs = O; Nearest = Seg; /* If we found an exact match, don't look further */ if (Offs == 0) { break; } } } } /* If we found a segment, use it and adjust the offset */ if (Nearest) { ED->SegRef = Nearest; ED->MemRef = 0; ED->Val -= Nearest->PC; } } static const SegDesc* FindSeg (SegDesc** const List, unsigned Count, const Segment* S) /* Search for a segment in the given list of segment descriptors and return ** the descriptor for a segment if we found it, and NULL if not. */ { unsigned I; for (I = 0; I < Count; ++I) { if (List[I]->Seg == S) { /* Found */ return List[I]; } } /* Not found */ return 0; } static const SegDesc* O65FindSeg (const O65Desc* D, const Segment* S) /* Search for a segment in the segment lists and return it's segment descriptor */ { const SegDesc* SD; if ((SD = FindSeg (D->TextSeg, D->TextCount, S)) != 0) { return SD; } if ((SD = FindSeg (D->DataSeg, D->DataCount, S)) != 0) { return SD; } if ((SD = FindSeg (D->BssSeg, D->BssCount, S)) != 0) { return SD; } if ((SD = FindSeg (D->ZPSeg, D->ZPCount, S)) != 0) { return SD; } /* Not found */ return 0; } /*****************************************************************************/ /* Expression handling */ /*****************************************************************************/ static void O65ParseExpr (ExprNode* Expr, ExprDesc* D, int Sign) /* Extract and evaluate all constant factors in an subtree that has only ** additions and subtractions. If anything other than additions and ** subtractions are found, D->TooComplex is set to true. */ { Export* E; switch (Expr->Op) { case EXPR_LITERAL: D->Val += (Sign * Expr->V.IVal); break; case EXPR_SYMBOL: /* Get the referenced Export */ E = GetExprExport (Expr); /* If this export has a mark set, we've already encountered it. ** This means that the export is used to define it's own value, ** which in turn means, that we have a circular reference. */ if (ExportHasMark (E)) { CircularRefError (E); } else if (E->Expr == 0) { /* Dummy export, must be an o65 imported symbol */ ExtSym* S = O65GetImport (D->D, E->Name); CHECK (S != 0); if (D->ExtRef) { /* We cannot have more than one external reference in o65 */ D->TooComplex = 1; } else { /* Remember the external reference */ D->ExtRef = S; } } else { MarkExport (E); O65ParseExpr (E->Expr, D, Sign); UnmarkExport (E); } break; case EXPR_SECTION: if (D->SecRef) { /* We cannot handle more than one segment reference in o65 */ D->TooComplex = 1; } else { /* Remember the segment reference */ D->SecRef = GetExprSection (Expr); /* Add the offset of the section to the constant value */ D->Val += Sign * (D->SecRef->Offs + D->SecRef->Seg->PC); } break; case EXPR_SEGMENT: if (D->SegRef) { /* We cannot handle more than one segment reference in o65 */ D->TooComplex = 1; } else { /* Remember the segment reference */ D->SegRef = Expr->V.Seg; /* Add the offset of the segment to the constant value */ D->Val += (Sign * D->SegRef->PC); } break; case EXPR_MEMAREA: if (D->MemRef) { /* We cannot handle more than one memory reference in o65 */ D->TooComplex = 1; } else { /* Remember the memory area reference */ D->MemRef = Expr->V.Mem; /* Add the start address of the memory area to the constant ** value */ D->Val += (Sign * D->MemRef->Start); } break; case EXPR_PLUS: O65ParseExpr (Expr->Left, D, Sign); O65ParseExpr (Expr->Right, D, Sign); break; case EXPR_MINUS: O65ParseExpr (Expr->Left, D, Sign); O65ParseExpr (Expr->Right, D, -Sign); break; default: /* Expression contains illegal operators */ D->TooComplex = 1; break; } } /*****************************************************************************/ /* Relocation tables */ /*****************************************************************************/ static O65RelocTab* NewO65RelocTab (void) /* Create a new relocation table */ { /* Allocate a new structure */ O65RelocTab* R = xmalloc (sizeof (O65RelocTab)); /* Initialize the data */ R->Size = 0; R->Fill = 0; R->Buf = 0; /* Return the created struct */ return R; } static void FreeO65RelocTab (O65RelocTab* R) /* Free a relocation table */ { xfree (R->Buf); xfree (R); } static void O65RelocPutByte (O65RelocTab* R, unsigned B) /* Put the byte into the relocation table */ { /* Do we have enough space in the buffer? */ if (R->Fill == R->Size) { /* We need to grow the buffer */ if (R->Size) { R->Size *= 2; } else { R->Size = 1024; /* Initial size */ } R->Buf = xrealloc (R->Buf, R->Size); } /* Put the byte into the buffer */ R->Buf [R->Fill++] = (unsigned char) B; } static void O65RelocPutWord (O65RelocTab* R, unsigned W) /* Put a word into the relocation table */ { O65RelocPutByte (R, W); O65RelocPutByte (R, W >> 8); } static void O65WriteReloc (O65RelocTab* R, FILE* F) /* Write the relocation table to the given file */ { WriteData (F, R->Buf, R->Fill); } /*****************************************************************************/ /* Option handling */ /*****************************************************************************/ static O65Option* NewO65Option (unsigned Type, const void* Data, unsigned DataLen) /* Allocate and initialize a new option struct */ { O65Option* O; /* Check the length */ CHECK (DataLen <= 253); /* Allocate memory */ O = xmalloc (sizeof (O65Option) - 1 + DataLen); /* Initialize the structure */ O->Next = 0; O->Type = Type; O->Len = DataLen; memcpy (O->Data, Data, DataLen); /* Return the created struct */ return O; } static void FreeO65Option (O65Option* O) /* Free an O65Option struct */ { xfree (O); } /*****************************************************************************/ /* Subroutines to write o65 sections */ /*****************************************************************************/ static void O65WriteHeader (O65Desc* D) /* Write the header of the executable to the given file */ { static unsigned char Trailer [5] = { 0x01, 0x00, 0x6F, 0x36, 0x35 }; O65Option* O; /* Write the fixed header */ WriteData (D->F, Trailer, sizeof (Trailer)); Write8 (D->F, D->Header.Version); Write16 (D->F, D->Header.Mode); WriteSize (D, D->Header.TextBase); WriteSize (D, D->Header.TextSize); WriteSize (D, D->Header.DataBase); WriteSize (D, D->Header.DataSize); WriteSize (D, D->Header.BssBase); WriteSize (D, D->Header.BssSize); WriteSize (D, D->Header.ZPBase); WriteSize (D, D->Header.ZPSize); WriteSize (D, D->Header.StackSize); /* Write the options */ O = D->Options; while (O) { Write8 (D->F, O->Len + 2); /* Account for len and type bytes */ Write8 (D->F, O->Type); if (O->Len) { WriteData (D->F, O->Data, O->Len); } O = O->Next; } /* Write the end-of-options byte */ Write8 (D->F, 0); } static unsigned O65WriteExpr (ExprNode* E, int Signed, unsigned Size, unsigned long Offs, void* Data) /* Called from SegWrite for an expression. Evaluate the expression, check the ** range and write the expression value to the file, update the relocation ** table. */ { long Diff; unsigned RefCount; long BinVal; ExprNode* Expr; ExprDesc ED; unsigned char RelocType; /* Cast the Data pointer to its real type, an O65Desc */ O65Desc* D = (O65Desc*) Data; /* Check for a constant expression */ if (IsConstExpr (E)) { /* Write out the constant expression */ return SegWriteConstExpr (((O65Desc*)Data)->F, E, Signed, Size); } /* We have a relocatable expression that needs a relocation table entry. ** Calculate the number of bytes between this entry and the last one, and ** setup all necessary intermediate bytes in the relocation table. */ Offs += D->SegSize; /* Calulate full offset */ Diff = ((long) Offs) - D->LastOffs; while (Diff > 0xFE) { O65RelocPutByte (D->CurReloc, 0xFF); Diff -= 0xFE; } O65RelocPutByte (D->CurReloc, (unsigned char) Diff); /* Remember this offset for the next time */ D->LastOffs = Offs; /* Determine the expression to relocate */ Expr = E; if (E->Op == EXPR_BYTE0 || E->Op == EXPR_BYTE1 || E->Op == EXPR_BYTE2 || E->Op == EXPR_BYTE3 || E->Op == EXPR_WORD0 || E->Op == EXPR_WORD1 || E->Op == EXPR_FARADDR || E->Op == EXPR_DWORD || E->Op == EXPR_NEARADDR) { /* Use the real expression */ Expr = E->Left; } /* Recursively collect information about this expression */ O65ParseExpr (Expr, InitExprDesc (&ED, D), 1); /* We cannot handle more than one external reference */ RefCount = (ED.MemRef != 0) + (ED.SegRef != 0) + (ED.SecRef != 0) + (ED.ExtRef != 0); if (RefCount > 1) { ED.TooComplex = 1; } /* If we have a memory area reference, we need to convert it into a ** segment reference. If we cannot do that, we cannot handle the ** expression. */ if (ED.MemRef) { CvtMemoryToSegment (&ED); if (ED.SegRef == 0) { return SEG_EXPR_TOO_COMPLEX; } } /* Bail out if we cannot handle the expression */ if (ED.TooComplex) { return SEG_EXPR_TOO_COMPLEX; } /* Safety: Check that we have exactly one reference */ CHECK (RefCount == 1); /* Write out the offset that goes into the segment. */ BinVal = ED.Val; switch (E->Op) { case EXPR_BYTE0: BinVal &= 0xFF; break; case EXPR_BYTE1: BinVal = (BinVal >> 8) & 0xFF; break; case EXPR_BYTE2: BinVal = (BinVal >> 16) & 0xFF; break; case EXPR_BYTE3: BinVal = (BinVal >> 24) & 0xFF; break; case EXPR_WORD0: BinVal &= 0xFFFF; break; case EXPR_WORD1: BinVal = (BinVal >> 16) & 0xFFFF; break; case EXPR_FARADDR: BinVal &= 0xFFFFFFUL; break; case EXPR_DWORD: BinVal &= 0xFFFFFFFFUL; break; case EXPR_NEARADDR: BinVal &= 0xFFFF; break; } WriteVal (D->F, BinVal, Size); /* Determine the actual type of relocation entry needed from the ** information gathered about the expression. */ if (E->Op == EXPR_BYTE0) { RelocType = O65RELOC_LOW; } else if (E->Op == EXPR_BYTE1) { RelocType = O65RELOC_HIGH; } else if (E->Op == EXPR_BYTE2) { RelocType = O65RELOC_SEG; } else { switch (Size) { case 1: RelocType = O65RELOC_LOW; break; case 2: RelocType = O65RELOC_WORD; break; case 3: RelocType = O65RELOC_SEGADR; break; case 4: /* 4 byte expression not supported by o65 */ return SEG_EXPR_TOO_COMPLEX; default: Internal ("O65WriteExpr: Invalid expression size: %u", Size); RelocType = 0; /* Avoid gcc warnings */ } } /* Determine which segment we're referencing */ if (ED.SegRef || ED.SecRef) { const SegDesc* Seg; /* Segment or section reference. */ if (ED.SecRef) { /* Get segment from section */ ED.SegRef = ED.SecRef->Seg; } /* Search for the segment and map it to it's o65 segmentID */ Seg = O65FindSeg (D, ED.SegRef); if (Seg == 0) { /* For some reason, we didn't find this segment in the list of ** segments written to the o65 file. */ return SEG_EXPR_INVALID; } RelocType |= O65SegType (Seg); O65RelocPutByte (D->CurReloc, RelocType); /* Output additional data if needed */ switch (RelocType & O65RELOC_MASK) { case O65RELOC_HIGH: O65RelocPutByte (D->CurReloc, ED.Val & 0xFF); break; case O65RELOC_SEG: O65RelocPutWord (D->CurReloc, ED.Val & 0xFFFF); break; } } else if (ED.ExtRef) { /* Imported symbol */ RelocType |= O65SEG_UNDEF; O65RelocPutByte (D->CurReloc, RelocType); /* Put the number of the imported symbol into the table */ O65RelocPutWord (D->CurReloc, ExtSymNum (ED.ExtRef)); } else { /* OOPS - something bad happened */ Internal ("External reference not handled"); } /* Success */ return SEG_EXPR_OK; } static void O65WriteSeg (O65Desc* D, SegDesc** Seg, unsigned Count, int DoWrite) /* Write one segment to the o65 output file */ { SegDesc* S; unsigned I; /* Initialize variables */ D->SegSize = 0; D->LastOffs = -1; /* Write out all segments */ for (I = 0; I < Count; ++I) { /* Get the segment from the list node */ S = Seg [I]; /* Keep the user happy */ Print (stdout, 1, " Writing '%s'\n", GetString (S->Name)); /* Write this segment */ if (DoWrite) { SegWrite (D->Filename, D->F, S->Seg, O65WriteExpr, D); } /* Mark the segment as dumped */ S->Seg->Dumped = 1; /* Calculate the total size */ D->SegSize += S->Seg->Size; } /* Terminate the relocation table for this segment */ if (D->CurReloc) { O65RelocPutByte (D->CurReloc, 0); } /* Check the size of the segment for overflow */ if ((D->Header.Mode & MF_SIZE_MASK) == MF_SIZE_16BIT && D->SegSize > 0xFFFF) { Error ("Segment overflow in file '%s'", D->Filename); } } static void O65WriteTextSeg (O65Desc* D) /* Write the code segment to the o65 output file */ { /* Initialize variables */ D->CurReloc = D->TextReloc; /* Dump all text segments */ O65WriteSeg (D, D->TextSeg, D->TextCount, 1); /* Set the size of the segment */ D->Header.TextSize = D->SegSize; } static void O65WriteDataSeg (O65Desc* D) /* Write the data segment to the o65 output file */ { /* Initialize variables */ D->CurReloc = D->DataReloc; /* Dump all data segments */ O65WriteSeg (D, D->DataSeg, D->DataCount, 1); /* Set the size of the segment */ D->Header.DataSize = D->SegSize; } static void O65WriteBssSeg (O65Desc* D) /* "Write" the bss segments to the o65 output file. This will only update ** the relevant header fields. */ { /* Initialize variables */ D->CurReloc = 0; /* Dump all bss segments */ O65WriteSeg (D, D->BssSeg, D->BssCount, 0); /* Set the size of the segment */ D->Header.BssSize = D->SegSize; } static void O65WriteZPSeg (O65Desc* D) /* "Write" the zeropage segments to the o65 output file. This will only update ** the relevant header fields. */ { /* Initialize variables */ D->CurReloc = 0; /* Dump all zp segments */ O65WriteSeg (D, D->ZPSeg, D->ZPCount, 0); /* Set the size of the segment */ D->Header.ZPSize = D->SegSize; } static void O65WriteImports (O65Desc* D) /* Write the list of imported symbols to the O65 file */ { const ExtSym* S; /* Write the number of imports */ WriteSize (D, ExtSymCount (D->Imports)); /* Write out the symbol names, zero terminated */ S = ExtSymList (D->Imports); while (S) { /* Get the name */ const char* Name = GetString (ExtSymName (S)); /* And write it to the output file */ WriteData (D->F, Name, strlen (Name) + 1); /* Next symbol */ S = ExtSymNext (S); } } static void O65WriteTextReloc (O65Desc* D) /* Write the relocation for the text segment to the output file */ { O65WriteReloc (D->TextReloc, D->F); } static void O65WriteDataReloc (O65Desc* D) /* Write the relocation for the data segment to the output file */ { O65WriteReloc (D->DataReloc, D->F); } static void O65WriteExports (O65Desc* D) /* Write the list of exports */ { const ExtSym* S; /* Write the number of exports */ WriteSize (D, ExtSymCount (D->Exports)); /* Write out the symbol information */ S = ExtSymList (D->Exports); while (S) { ExprNode* Expr; unsigned char SegmentID; ExprDesc ED; /* Get the name */ unsigned NameIdx = ExtSymName (S); const char* Name = GetString (NameIdx); /* Get the export for this symbol. We've checked before that this ** export does really exist, so if it is unresolved, or if we don't ** find it, there is an error in the linker code. */ Export* E = FindExport (NameIdx); if (E == 0 || IsUnresolvedExport (E)) { Internal ("Unresolved export '%s' found in O65WriteExports", Name); } /* Get the expression for the symbol */ Expr = E->Expr; /* Recursively collect information about this expression */ O65ParseExpr (Expr, InitExprDesc (&ED, D), 1); /* We cannot handle expressions with imported symbols, or expressions ** with more than one segment reference here */ if (ED.ExtRef != 0 || (ED.SegRef != 0 && ED.SecRef != 0)) { ED.TooComplex = 1; } /* Bail out if we cannot handle the expression */ if (ED.TooComplex) { Error ("Expression for symbol '%s' is too complex", Name); } /* Determine the segment id for the expression */ if (ED.SegRef != 0 || ED.SecRef != 0) { const SegDesc* Seg; /* Segment or section reference */ if (ED.SecRef != 0) { ED.SegRef = ED.SecRef->Seg; /* Get segment from section */ } /* Search for the segment and map it to it's o65 segmentID */ Seg = O65FindSeg (D, ED.SegRef); if (Seg == 0) { /* For some reason, we didn't find this segment in the list of ** segments written to the o65 file. */ Error ("Segment for symbol '%s' is undefined", Name); } SegmentID = O65SegType (Seg); } else { /* Absolute value */ SegmentID = O65SEG_ABS; } /* Write the name to the output file */ WriteData (D->F, Name, strlen (Name) + 1); /* Output the segment id followed by the literal value */ Write8 (D->F, SegmentID); WriteSize (D, ED.Val); /* Next symbol */ S = ExtSymNext (S); } } /*****************************************************************************/ /* Public code */ /*****************************************************************************/ O65Desc* NewO65Desc (void) /* Create, initialize and return a new O65 descriptor struct */ { /* Allocate a new structure */ O65Desc* D = xmalloc (sizeof (O65Desc)); /* Initialize the header */ D->Header.Version = 0; D->Header.Mode = 0; D->Header.TextBase = 0; D->Header.TextSize = 0; D->Header.DataBase = 0; D->Header.DataSize = 0; D->Header.BssBase = 0; D->Header.BssSize = 0; D->Header.ZPBase = 0; D->Header.ZPSize = 0; D->Header.StackSize = 0; /* Let OS choose a good value */ /* Initialize other data */ D->Options = 0; D->Exports = NewExtSymTab (); D->Imports = NewExtSymTab (); D->Undef = 0; D->F = 0; D->Filename = 0; D->TextReloc = NewO65RelocTab (); D->DataReloc = NewO65RelocTab (); D->TextCount = 0; D->TextSeg = 0; D->DataCount = 0; D->DataSeg = 0; D->BssCount = 0; D->BssSeg = 0; D->ZPCount = 0; D->ZPSeg = 0; /* Return the created struct */ return D; } void FreeO65Desc (O65Desc* D) /* Delete the descriptor struct with cleanup */ { /* Free the segment arrays */ xfree (D->ZPSeg); xfree (D->BssSeg); xfree (D->DataSeg); xfree (D->TextSeg); /* Free the relocation tables */ FreeO65RelocTab (D->DataReloc); FreeO65RelocTab (D->TextReloc); /* Free the option list */ while (D->Options) { O65Option* O = D->Options; D->Options = D->Options->Next; FreeO65Option (O); } /* Free the external symbol tables */ FreeExtSymTab (D->Exports); FreeExtSymTab (D->Imports); /* Free the struct itself */ xfree (D); } void O65Set6502 (O65Desc* D) /* Enable 6502 mode */ { D->Header.Mode = (D->Header.Mode & ~MF_CPU_MASK) | MF_CPU_6502; } void O65Set65816 (O65Desc* D) /* Enable 816 mode */ { D->Header.Mode = (D->Header.Mode & ~MF_CPU_MASK) | MF_CPU_65816; } void O65SetSmallModel (O65Desc* D) /* Enable a small memory model executable */ { D->Header.Mode = (D->Header.Mode & ~MF_SIZE_MASK) | MF_SIZE_16BIT; } void O65SetLargeModel (O65Desc* D) /* Enable a large memory model executable */ { D->Header.Mode = (D->Header.Mode & ~MF_SIZE_MASK) | MF_SIZE_32BIT; } void O65SetAlignment (O65Desc* D, unsigned Alignment) /* Set the executable alignment */ { /* Remove all alignment bits from the mode word */ D->Header.Mode &= ~MF_ALIGN_MASK; /* Set the alignment bits */ switch (Alignment) { case 1: D->Header.Mode |= MF_ALIGN_1; break; case 2: D->Header.Mode |= MF_ALIGN_2; break; case 4: D->Header.Mode |= MF_ALIGN_4; break; case 256: D->Header.Mode |= MF_ALIGN_256; break; default: Error ("Invalid alignment for O65 format: %u", Alignment); } } void O65SetOption (O65Desc* D, unsigned Type, const void* Data, unsigned DataLen) /* Set an o65 header option */ { /* Create a new option structure */ O65Option* O = NewO65Option (Type, Data, DataLen); /* Insert it into the linked list */ O->Next = D->Options; D->Options = O; } void O65SetOS (O65Desc* D, unsigned OS, unsigned Version, unsigned Id) /* Set an option describing the target operating system */ { /* Setup the option data */ unsigned char Opt[4]; Opt[0] = OS; Opt[1] = Version; /* Write the correct option length */ switch (OS) { case O65OS_CC65: /* Set the 16 bit id */ Opt[2] = (unsigned char) Id; Opt[3] = (unsigned char) (Id >> 8); O65SetOption (D, O65OPT_OS, Opt, 4); break; default: /* No id for OS/A65, Lunix, and unknown OSes */ O65SetOption (D, O65OPT_OS, Opt, 2); break; } } ExtSym* O65GetImport (O65Desc* D, unsigned Ident) /* Return the imported symbol or NULL if not found */ { /* Retrieve the symbol from the table */ return GetExtSym (D->Imports, Ident); } void O65SetImport (O65Desc* D, unsigned Ident) /* Set an imported identifier */ { /* Insert the entry into the table */ NewExtSym (D->Imports, Ident); } ExtSym* O65GetExport (O65Desc* D, unsigned Ident) /* Return the exported symbol or NULL if not found */ { /* Retrieve the symbol from the table */ return GetExtSym (D->Exports, Ident); } void O65SetExport (O65Desc* D, unsigned Ident) /* Set an exported identifier */ { /* Get the export for this symbol and check if it does exist and is ** a resolved symbol. */ Export* E = FindExport (Ident); if (E == 0 || IsUnresolvedExport (E)) { Error ("Unresolved export: '%s'", GetString (Ident)); } /* Insert the entry into the table */ NewExtSym (D->Exports, Ident); } static void O65SetupSegments (O65Desc* D, File* F) /* Setup segment assignments */ { unsigned I; unsigned TextIdx, DataIdx, BssIdx, ZPIdx; /* Initialize the counters */ D->TextCount = 0; D->DataCount = 0; D->BssCount = 0; D->ZPCount = 0; /* Walk over the memory list */ for (I = 0; I < CollCount (&F->MemoryAreas); ++I) { /* Get this entry */ MemoryArea* M = CollAtUnchecked (&F->MemoryAreas, I); /* Walk through the segment list and count the segment types */ unsigned J; for (J = 0; J < CollCount (&M->SegList); ++J) { /* Get the segment */ SegDesc* S = CollAtUnchecked (&M->SegList, J); /* Check the segment type. */ switch (O65SegType (S)) { case O65SEG_TEXT: D->TextCount++; break; case O65SEG_DATA: D->DataCount++; break; case O65SEG_BSS: D->BssCount++; break; case O65SEG_ZP: D->ZPCount++; break; default: Internal ("Invalid return from O65SegType"); } } } /* Allocate memory according to the numbers */ D->TextSeg = xmalloc (D->TextCount * sizeof (SegDesc*)); D->DataSeg = xmalloc (D->DataCount * sizeof (SegDesc*)); D->BssSeg = xmalloc (D->BssCount * sizeof (SegDesc*)); D->ZPSeg = xmalloc (D->ZPCount * sizeof (SegDesc*)); /* Walk again through the list and setup the segment arrays */ TextIdx = DataIdx = BssIdx = ZPIdx = 0; for (I = 0; I < CollCount (&F->MemoryAreas); ++I) { /* Get this entry */ MemoryArea* M = CollAtUnchecked (&F->MemoryAreas, I); /* Walk over the segment list and check the segment types */ unsigned J; for (J = 0; J < CollCount (&M->SegList); ++J) { /* Get the segment */ SegDesc* S = CollAtUnchecked (&M->SegList, J); /* Check the segment type. */ switch (O65SegType (S)) { case O65SEG_TEXT: D->TextSeg [TextIdx++] = S; break; case O65SEG_DATA: D->DataSeg [DataIdx++] = S; break; case O65SEG_BSS: D->BssSeg [BssIdx++] = S; break; case O65SEG_ZP: D->ZPSeg [ZPIdx++] = S; break; default: Internal ("Invalid return from O65SegType"); } } } } static int O65Unresolved (unsigned Name, void* D) /* Called if an unresolved symbol is encountered */ { /* Check if the symbol is an imported o65 symbol */ if (O65GetImport (D, Name) != 0) { /* This is an external symbol, relax... */ return 1; } else { /* This is actually an unresolved external. Bump the counter */ ((O65Desc*) D)->Undef++; return 0; } } static void O65SetupHeader (O65Desc* D) /* Set additional stuff in the header */ { /* Set the base addresses of the segments */ if (D->TextCount > 0) { SegDesc* FirstSeg = D->TextSeg [0]; D->Header.TextBase = FirstSeg->Seg->PC; } if (D->DataCount > 0) { SegDesc* FirstSeg = D->DataSeg [0]; D->Header.DataBase = FirstSeg->Seg->PC; } if (D->BssCount > 0) { SegDesc* FirstSeg = D->BssSeg [0]; D->Header.BssBase = FirstSeg->Seg->PC; } if (D->ZPCount > 0) { SegDesc* FirstSeg = D->ZPSeg [0]; D->Header.ZPBase = FirstSeg->Seg->PC; } } static void O65UpdateHeader (O65Desc* D) /* Update mode word, currently only the "simple" bit */ { /* If we have byte wise relocation and an alignment of 1, and text ** and data are adjacent, we can set the "simple addressing" bit ** in the header. */ if ((D->Header.Mode & MF_RELOC_MASK) == MF_RELOC_BYTE && (D->Header.Mode & MF_ALIGN_MASK) == MF_ALIGN_1 && D->Header.TextBase + D->Header.TextSize == D->Header.DataBase && D->Header.DataBase + D->Header.DataSize == D->Header.BssBase) { D->Header.Mode = (D->Header.Mode & ~MF_ADDR_MASK) | MF_ADDR_SIMPLE; } } void O65WriteTarget (O65Desc* D, File* F) /* Write an o65 output file */ { char OptBuf [256]; /* Buffer for option strings */ unsigned OptLen; time_t T; const char* Name; /* Place the filename in the control structure */ D->Filename = GetString (F->Name); /* Check for unresolved symbols. The function O65Unresolved is called ** if we get an unresolved symbol. */ D->Undef = 0; /* Reset the counter */ CheckUnresolvedImports (O65Unresolved, D); if (D->Undef > 0) { /* We had unresolved symbols, cannot create output file */ Error ("%u unresolved external(s) found - cannot create output file", D->Undef); } /* Setup the segment arrays */ O65SetupSegments (D, F); /* Setup additional stuff in the header */ O65SetupHeader (D); /* Open the file */ D->F = fopen (D->Filename, "wb"); if (D->F == 0) { Error ("Cannot open '%s': %s", D->Filename, strerror (errno)); } /* Keep the user happy */ Print (stdout, 1, "Opened '%s'...\n", D->Filename); /* Define some more options: A timestamp, the linker version and the ** filename */ T = time (0); strcpy (OptBuf, ctime (&T)); OptLen = strlen (OptBuf); while (OptLen > 0 && IsControl (OptBuf[OptLen-1])) { --OptLen; } OptBuf[OptLen] = '\0'; O65SetOption (D, O65OPT_TIMESTAMP, OptBuf, OptLen + 1); sprintf (OptBuf, "ld65 V%s", GetVersionAsString ()); O65SetOption (D, O65OPT_ASM, OptBuf, strlen (OptBuf) + 1); Name = FindName (D->Filename); O65SetOption (D, O65OPT_FILENAME, Name, strlen (Name) + 1); /* Write the header */ O65WriteHeader (D); /* Write the text segment */ O65WriteTextSeg (D); /* Write the data segment */ O65WriteDataSeg (D); /* "Write" the bss segments */ O65WriteBssSeg (D); /* "Write" the zeropage segments */ O65WriteZPSeg (D); /* Write the undefined references list */ O65WriteImports (D); /* Write the text segment relocation table */ O65WriteTextReloc (D); /* Write the data segment relocation table */ O65WriteDataReloc (D); /* Write the list of exports */ O65WriteExports (D); /* Update header flags */ O65UpdateHeader (D); /* Seek back to the start and write the updated header */ fseek (D->F, 0, SEEK_SET); O65WriteHeader (D); /* Close the file */ if (fclose (D->F) != 0) { Error ("Cannot write to '%s': %s", D->Filename, strerror (errno)); } /* Reset the file and filename */ D->F = 0; D->Filename = 0; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/o65.h����������������������������������������������������������������������������0000664�0000000�0000000�00000011463�13473601511�0014335�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* o65.h */ /* */ /* Module to handle the o65 binary format */ /* */ /* */ /* */ /* (C) 1999-2005 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef O65_H #define O65_H #include <stdio.h> #include "extsyms.h" #include "config.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Structure describing the format */ typedef struct O65Desc O65Desc; /* Option tags */ #define O65OPT_FILENAME 0 #define O65OPT_OS 1 #define O65OPT_ASM 2 #define O65OPT_AUTHOR 3 #define O65OPT_TIMESTAMP 4 /* Operating system codes for O65OPT_OS */ #define O65OS_MIN 1 #define O65OS_OSA65 1 #define O65OS_LUNIX 2 #define O65OS_CC65 3 #define O65OS_OPENCBM 4 #define O65OS_MAX 255 /*****************************************************************************/ /* Code */ /*****************************************************************************/ O65Desc* NewO65Desc (void); /* Create, initialize and return a new O65 descriptor struct */ void FreeO65Desc (O65Desc* D); /* Delete the descriptor struct with cleanup */ void O65Set6502 (O65Desc* D); /* Enable 6502 mode */ void O65Set65816 (O65Desc* D); /* Enable 816 mode */ void O65SetSmallModel (O65Desc* D); /* Enable a small memory model executable */ void O65SetLargeModel (O65Desc* D); /* Enable a large memory model executable */ void O65SetAlignment (O65Desc* D, unsigned Align); /* Set the executable alignment */ void O65SetOption (O65Desc* D, unsigned Type, const void* Data, unsigned DataLen); /* Set an o65 header option */ void O65SetOS (O65Desc* D, unsigned OS, unsigned Version, unsigned Id); /* Set an option describing the target operating system */ ExtSym* O65GetImport (O65Desc* D, unsigned Ident); /* Return the imported symbol or NULL if not found */ void O65SetImport (O65Desc* D, unsigned Ident); /* Set an imported identifier */ ExtSym* O65GetExport (O65Desc* D, unsigned Ident); /* Return the exported symbol or NULL if not found */ void O65SetExport (O65Desc* D, unsigned Ident); /* Set an exported identifier */ void O65WriteTarget (O65Desc* D, File* F); /* Write an o65 output file */ /* End of o65.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/objdata.c������������������������������������������������������������������������0000664�0000000�0000000�00000022667�13473601511�0015333�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* objdata.c */ /* */ /* Handling object file data for the ld65 linker */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* common */ #include "check.h" #include "xmalloc.h" /* ld65 */ #include "error.h" #include "exports.h" #include "fileinfo.h" #include "library.h" #include "objdata.h" #include "spool.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Collection containing used ObjData objects */ Collection ObjDataList = STATIC_COLLECTION_INITIALIZER; /*****************************************************************************/ /* Code */ /*****************************************************************************/ ObjData* NewObjData (void) /* Allocate a new structure on the heap, insert it into the list, return it */ { /* Allocate memory */ ObjData* O = xmalloc (sizeof (ObjData)); /* Initialize the data */ O->Next = 0; O->Name = INVALID_STRING_ID; O->Lib = 0; O->MTime = 0; O->Start = 0; O->Flags = 0; O->HLLSymBaseId = 0; O->SymBaseId = 0; O->ScopeBaseId = 0; O->SpanBaseId = 0; O->Files = EmptyCollection; O->Sections = EmptyCollection; O->Exports = EmptyCollection; O->Imports = EmptyCollection; O->DbgSyms = EmptyCollection; O->HLLDbgSyms = EmptyCollection; O->LineInfos = EmptyCollection; O->StringCount = 0; O->Strings = 0; O->Assertions = EmptyCollection; O->Scopes = EmptyCollection; O->Spans = EmptyCollection; /* Return the new entry */ return O; } void FreeObjData (ObjData* O) /* Free an ObjData object. NOTE: This function works only for unused object ** data, that is, ObjData objects that aren't used because they aren't ** referenced. */ { unsigned I; for (I = 0; I < CollCount (&O->Files); ++I) { CollDeleteItem (&((FileInfo*) CollAtUnchecked (&O->Files, I))->Modules, O); } DoneCollection (&O->Files); DoneCollection (&O->Sections); for (I = 0; I < CollCount (&O->Exports); ++I) { FreeExport (CollAtUnchecked (&O->Exports, I)); } DoneCollection (&O->Exports); for (I = 0; I < CollCount (&O->Imports); ++I) { FreeImport (CollAtUnchecked (&O->Imports, I)); } DoneCollection (&O->Imports); DoneCollection (&O->DbgSyms); DoneCollection (&O->HLLDbgSyms); for (I = 0; I < CollCount (&O->LineInfos); ++I) { FreeLineInfo (CollAtUnchecked (&O->LineInfos, I)); } DoneCollection (&O->LineInfos); xfree (O->Strings); DoneCollection (&O->Assertions); DoneCollection (&O->Scopes); for (I = 0; I < CollCount (&O->Spans); ++I) { FreeSpan (CollAtUnchecked (&O->Spans, I)); } DoneCollection (&O->Spans); xfree (O); } void FreeObjStrings (ObjData* O) /* Free the module string data. Used once the object file is loaded completely ** when all strings are converted to global strings. */ { xfree (O->Strings); O->Strings = 0; } void InsertObjData (ObjData* O) /* Insert the ObjData object into the collection of used ObjData objects. */ { CollAppend (&ObjDataList, O); } void InsertObjGlobals (ObjData* O) /* Insert imports and exports from the object file into the global import and ** export lists. */ { unsigned I; /* Insert exports and imports */ for (I = 0; I < CollCount (&O->Exports); ++I) { InsertExport (CollAt (&O->Exports, I)); } for (I = 0; I < CollCount (&O->Imports); ++I) { InsertImport (CollAt (&O->Imports, I)); } } unsigned MakeGlobalStringId (const ObjData* O, unsigned Index) /* Convert a local string id into a global one and return it. */ { if (Index >= O->StringCount) { Error ("Invalid string index (%u) in module '%s'", Index, GetObjFileName (O)); } return O->Strings[Index]; } const char* GetObjFileName (const ObjData* O) /* Get the name of the object file. Return "[linker generated]" if the object ** file is NULL. */ { return O? GetString (O->Name) : "[linker generated]"; } const struct StrBuf* GetObjString (const ObjData* Obj, unsigned Id) /* Get a string from an object file checking for an invalid index */ { return GetStrBuf (MakeGlobalStringId (Obj, Id)); } struct Section* GetObjSection (const ObjData* O, unsigned Id) /* Get a section from an object file checking for a valid index */ { if (Id >= CollCount (&O->Sections)) { Error ("Invalid section index (%u) in module '%s'", Id, GetObjFileName (O)); } return CollAtUnchecked (&O->Sections, Id); } struct Import* GetObjImport (const ObjData* O, unsigned Id) /* Get an import from an object file checking for a valid index */ { if (Id >= CollCount (&O->Imports)) { Error ("Invalid import index (%u) in module '%s'", Id, GetObjFileName (O)); } return CollAtUnchecked (&O->Imports, Id); } struct Export* GetObjExport (const ObjData* O, unsigned Id) /* Get an export from an object file checking for a valid index */ { if (Id >= CollCount (&O->Exports)) { Error ("Invalid export index (%u) in module '%s'", Id, GetObjFileName (O)); } return CollAtUnchecked (&O->Exports, Id); } struct DbgSym* GetObjDbgSym (const ObjData* O, unsigned Id) /* Get a debug symbol from an object file checking for a valid index */ { if (Id >= CollCount (&O->DbgSyms)) { Error ("Invalid debug symbol index (%u) in module '%s'", Id, GetObjFileName (O)); } return CollAtUnchecked (&O->DbgSyms, Id); } struct Scope* GetObjScope (const ObjData* O, unsigned Id) /* Get a scope from an object file checking for a valid index */ { if (Id >= CollCount (&O->Scopes)) { Error ("Invalid scope index (%u) in module '%s'", Id, GetObjFileName (O)); } return CollAtUnchecked (&O->Scopes, Id); } unsigned ObjDataCount (void) /* Return the total number of modules */ { return CollCount (&ObjDataList); } void PrintDbgModules (FILE* F) /* Output the modules to a debug info file */ { unsigned I; /* Output modules */ for (I = 0; I < CollCount (&ObjDataList); ++I) { /* Get this object file */ const ObjData* O = CollConstAt (&ObjDataList, I); /* The main source file is the one at index zero */ const FileInfo* Source = CollConstAt (&O->Files, 0); /* Output the module line */ fprintf (F, "mod\tid=%u,name=\"%s\",file=%u", I, GetObjFileName (O), Source->Id); /* Add library if any */ if (O->Lib != 0) { fprintf (F, ",lib=%u", GetLibId (O->Lib)); } /* Terminate the output line */ fputc ('\n', F); } } �������������������������������������������������������������������������cc65-2.18/src/ld65/objdata.h������������������������������������������������������������������������0000664�0000000�0000000�00000016420�13473601511�0015326�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* objdata.h */ /* */ /* Handling object file data for the ld65 linker */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef OBJDATA_H #define OBJDATA_H /* common */ #include "coll.h" #include "inline.h" #include "objdefs.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Forwards */ struct Export; struct Import; struct Library; struct Scope; struct Section; struct StrBuf; /* Values for the Flags field */ #define OBJ_REF 0x0001 /* We have a reference to this file */ /* Internal structure holding object file data */ typedef struct ObjData ObjData; struct ObjData { ObjData* Next; /* Linked list of all objects */ unsigned Id; /* Id of this module */ unsigned Name; /* Module name */ struct Library* Lib; /* Library where module comes from */ unsigned long MTime; /* Time of last modification */ ObjHeader Header; /* Header of file */ unsigned long Start; /* Start offset of data in library */ unsigned Flags; unsigned HLLSymBaseId; /* Debug info base id for hll symbols */ unsigned SymBaseId; /* Debug info base id for symbols */ unsigned ScopeBaseId; /* Debug info base id for scopes */ unsigned SpanBaseId; /* Debug info base id for spans */ Collection Files; /* List of input files */ Collection Sections; /* List of all sections */ Collection Exports; /* List of all exports */ Collection Imports; /* List of all imports */ Collection DbgSyms; /* List of debug symbols */ Collection HLLDbgSyms; /* List of hll debug symbols */ Collection LineInfos; /* List of line infos */ unsigned StringCount; /* Count of strings */ unsigned* Strings; /* List of global string indices */ Collection Assertions; /* List of module assertions */ Collection Scopes; /* List of scopes */ Collection Spans; /* List of spans */ }; /* Collection containing used ObjData objects */ extern Collection ObjDataList; /*****************************************************************************/ /* Code */ /*****************************************************************************/ ObjData* NewObjData (void); /* Allocate a new structure on the heap, insert it into the list, return it */ void FreeObjData (ObjData* O); /* Free an ObjData object. NOTE: This function works only for unused object ** data, that is, ObjData objects that aren't used because they aren't ** referenced. */ void FreeObjStrings (ObjData* O); /* Free the module string data. Used once the object file is loaded completely ** when all strings are converted to global strings. */ void InsertObjData (ObjData* O); /* Insert the ObjData object into the collection of used ObjData objects. */ void InsertObjGlobals (ObjData* O); /* Insert imports and exports from the object file into the global import and ** export lists. */ unsigned MakeGlobalStringId (const ObjData* O, unsigned Index); /* Convert a local string id into a global one and return it. */ const char* GetObjFileName (const ObjData* O); /* Get the name of the object file. Return "[linker generated]" if the object ** file is NULL. */ #if defined(HAVE_INLINE) INLINE int ObjHasFiles (const ObjData* O) /* Return true if the files list does exist */ { return (O != 0 && CollCount (&O->Files) != 0); } #else # define ObjHasFiles(O) ((O) != 0 && CollCount (&(O)->Files) != 0) #endif const struct StrBuf* GetObjString (const ObjData* Obj, unsigned Id); /* Get a string from an object file checking for an invalid index */ struct Section* GetObjSection (const ObjData* Obj, unsigned Id); /* Get a section from an object file checking for a valid index */ struct Import* GetObjImport (const ObjData* Obj, unsigned Id); /* Get an import from an object file checking for a valid index */ struct Export* GetObjExport (const ObjData* Obj, unsigned Id); /* Get an export from an object file checking for a valid index */ struct DbgSym* GetObjDbgSym (const ObjData* Obj, unsigned Id); /* Get a debug symbol from an object file checking for a valid index */ struct Scope* GetObjScope (const ObjData* Obj, unsigned Id); /* Get a scope from an object file checking for a valid index */ unsigned ObjDataCount (void); /* Return the total number of modules */ void PrintDbgModules (FILE* F); /* Output the modules to a debug info file */ /* End of objdata.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/objfile.c������������������������������������������������������������������������0000664�0000000�0000000�00000026155�13473601511�0015335�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* objfile.c */ /* */ /* Object file handling for the ld65 linker */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* common */ #include "fname.h" #include "xmalloc.h" /* ld65 */ #include "asserts.h" #include "dbgsyms.h" #include "error.h" #include "exports.h" #include "fileinfo.h" #include "fileio.h" #include "lineinfo.h" #include "objdata.h" #include "objfile.h" #include "scopes.h" #include "segments.h" #include "spool.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ static unsigned GetModule (const char* Name) /* Get a module name index from the file name */ { /* Make a module name from the file name */ const char* Module = FindName (Name); if (*Module == 0) { Error ("Cannot make module name from '%s'", Name); } return GetStringId (Module); } static void ObjReadHeader (FILE* Obj, ObjHeader* H, const char* Name) /* Read the header of the object file checking the signature */ { H->Version = Read16 (Obj); if (H->Version != OBJ_VERSION) { Error ("Object file '%s' has wrong version, expected %08X, got %08X", Name, OBJ_VERSION, H->Version); } H->Flags = Read16 (Obj); H->OptionOffs = Read32 (Obj); H->OptionSize = Read32 (Obj); H->FileOffs = Read32 (Obj); H->FileSize = Read32 (Obj); H->SegOffs = Read32 (Obj); H->SegSize = Read32 (Obj); H->ImportOffs = Read32 (Obj); H->ImportSize = Read32 (Obj); H->ExportOffs = Read32 (Obj); H->ExportSize = Read32 (Obj); H->DbgSymOffs = Read32 (Obj); H->DbgSymSize = Read32 (Obj); H->LineInfoOffs = Read32 (Obj); H->LineInfoSize = Read32 (Obj); H->StrPoolOffs = Read32 (Obj); H->StrPoolSize = Read32 (Obj); H->AssertOffs = Read32 (Obj); H->AssertSize = Read32 (Obj); H->ScopeOffs = Read32 (Obj); H->ScopeSize = Read32 (Obj); H->SpanOffs = Read32 (Obj); H->SpanSize = Read32 (Obj); } void ObjReadFiles (FILE* F, unsigned long Pos, ObjData* O) /* Read the files list from a file at the given position */ { unsigned I; unsigned FileCount; /* Seek to the correct position */ FileSetPos (F, Pos); /* Read the data */ FileCount = ReadVar (F); CollGrow (&O->Files, FileCount); for (I = 0; I < FileCount; ++I) { CollAppend (&O->Files, ReadFileInfo (F, O)); } } void ObjReadSections (FILE* F, unsigned long Pos, ObjData* O) /* Read the section data from a file at the given position */ { unsigned I; unsigned SectionCount; /* Seek to the correct position */ FileSetPos (F, Pos); /* Read the data */ SectionCount = ReadVar (F); CollGrow (&O->Sections, SectionCount); for (I = 0; I < SectionCount; ++I) { CollAppend (&O->Sections, ReadSection (F, O)); } } void ObjReadImports (FILE* F, unsigned long Pos, ObjData* O) /* Read the imports from a file at the given position */ { unsigned I; unsigned ImportCount; /* Seek to the correct position */ FileSetPos (F, Pos); /* Read the data */ ImportCount = ReadVar (F); CollGrow (&O->Imports, ImportCount); for (I = 0; I < ImportCount; ++I) { CollAppend (&O->Imports, ReadImport (F, O)); } } void ObjReadExports (FILE* F, unsigned long Pos, ObjData* O) /* Read the exports from a file at the given position */ { unsigned I; unsigned ExportCount; /* Seek to the correct position */ FileSetPos (F, Pos); /* Read the data */ ExportCount = ReadVar (F); CollGrow (&O->Exports, ExportCount); for (I = 0; I < ExportCount; ++I) { CollAppend (&O->Exports, ReadExport (F, O)); } } void ObjReadDbgSyms (FILE* F, unsigned long Pos, ObjData* O) /* Read the debug symbols from a file at the given position */ { unsigned I; unsigned DbgSymCount; /* Seek to the correct position */ FileSetPos (F, Pos); /* Read the asm debug symbols */ DbgSymCount = ReadVar (F); CollGrow (&O->DbgSyms, DbgSymCount); for (I = 0; I < DbgSymCount; ++I) { CollAppend (&O->DbgSyms, ReadDbgSym (F, O, I)); } /* Read the hll debug symbols */ DbgSymCount = ReadVar (F); CollGrow (&O->HLLDbgSyms, DbgSymCount); for (I = 0; I < DbgSymCount; ++I) { CollAppend (&O->HLLDbgSyms, ReadHLLDbgSym (F, O, I)); } } void ObjReadLineInfos (FILE* F, unsigned long Pos, ObjData* O) /* Read the line infos from a file at the given position */ { unsigned I; unsigned LineInfoCount; /* Seek to the correct position */ FileSetPos (F, Pos); /* Read the data */ LineInfoCount = ReadVar (F); CollGrow (&O->LineInfos, LineInfoCount); for (I = 0; I < LineInfoCount; ++I) { CollAppend (&O->LineInfos, ReadLineInfo (F, O)); } } void ObjReadStrPool (FILE* F, unsigned long Pos, ObjData* O) /* Read the string pool from a file at the given position */ { unsigned I; /* Seek to the correct position */ FileSetPos (F, Pos); /* Read the data */ O->StringCount = ReadVar (F); O->Strings = xmalloc (O->StringCount * sizeof (O->Strings[0])); for (I = 0; I < O->StringCount; ++I) { O->Strings[I] = ReadStr (F); } } void ObjReadAssertions (FILE* F, unsigned long Pos, ObjData* O) /* Read the assertions from a file at the given offset */ { unsigned I; unsigned AssertionCount; /* Seek to the correct position */ FileSetPos (F, Pos); /* Read the data */ AssertionCount = ReadVar (F); CollGrow (&O->Assertions, AssertionCount); for (I = 0; I < AssertionCount; ++I) { CollAppend (&O->Assertions, ReadAssertion (F, O)); } } void ObjReadScopes (FILE* F, unsigned long Pos, ObjData* O) /* Read the scope table from a file at the given offset */ { unsigned I; unsigned ScopeCount; /* Seek to the correct position */ FileSetPos (F, Pos); /* Read the data */ ScopeCount = ReadVar (F); CollGrow (&O->Scopes, ScopeCount); for (I = 0; I < ScopeCount; ++I) { CollAppend (&O->Scopes, ReadScope (F, O, I)); } } void ObjReadSpans (FILE* F, unsigned long Pos, ObjData* O) /* Read the span table from a file at the given offset */ { unsigned I; unsigned SpanCount; /* Seek to the correct position */ FileSetPos (F, Pos); /* Read the data */ SpanCount = ReadVar (F); CollGrow (&O->Spans, SpanCount); for (I = 0; I < SpanCount; ++I) { CollAppend (&O->Spans, ReadSpan (F, O, I)); } } void ObjAdd (FILE* Obj, const char* Name) /* Add an object file to the module list */ { /* Create a new structure for the object file data */ ObjData* O = NewObjData (); /* The magic was already read and checked, so set it in the header */ O->Header.Magic = OBJ_MAGIC; /* Read and check the header */ ObjReadHeader (Obj, &O->Header, Name); /* Initialize the object module data structure */ O->Name = GetModule (Name); /* Read the string pool from the object file */ ObjReadStrPool (Obj, O->Header.StrPoolOffs, O); /* Read the files list from the object file */ ObjReadFiles (Obj, O->Header.FileOffs, O); /* Read the line infos from the object file */ ObjReadLineInfos (Obj, O->Header.LineInfoOffs, O); /* Read the imports list from the object file */ ObjReadImports (Obj, O->Header.ImportOffs, O); /* Read the object file exports and insert them into the exports list */ ObjReadExports (Obj, O->Header.ExportOffs, O); /* Read the object debug symbols from the object file */ ObjReadDbgSyms (Obj, O->Header.DbgSymOffs, O); /* Read the assertions from the object file */ ObjReadAssertions (Obj, O->Header.AssertOffs, O); /* Read the segment list from the object file. This must be late, since ** the expressions stored in the code may reference segments or imported ** symbols. */ ObjReadSections (Obj, O->Header.SegOffs, O); /* Read the scope table from the object file. Scopes reference segments, so ** we must read them after the sections. */ ObjReadScopes (Obj, O->Header.ScopeOffs, O); /* Read the spans from the object file */ ObjReadSpans (Obj, O->Header.SpanOffs, O); /* Mark this object file as needed */ O->Flags |= OBJ_REF; /* Done, close the file (we read it only, so no error check) */ fclose (Obj); /* Insert the imports and exports to the global lists */ InsertObjGlobals (O); /* Insert the object into the list of all used object files */ InsertObjData (O); /* All references to strings are now resolved, so we can delete the module ** string pool. */ FreeObjStrings (O); } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/objfile.h������������������������������������������������������������������������0000664�0000000�0000000�00000010270�13473601511�0015331�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* objfile.h */ /* */ /* Object file handling for the ld65 linker */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef OBJFILE_H #define OBJFILE_H #include <stdio.h> /* common */ #include "objdefs.h" /* ld65 */ #include "objdata.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void ObjReadFiles (FILE* F, unsigned long Pos, ObjData* O); /* Read the files list from a file at the given position */ void ObjReadSections (FILE* F, unsigned long Pos, ObjData* O); /* Read the section data from a file at the given position */ void ObjReadImports (FILE* F, unsigned long Pos, ObjData* O); /* Read the imports from a file at the given position */ void ObjReadExports (FILE* F, unsigned long Pos, ObjData* O); /* Read the exports from a file at the given position */ void ObjReadDbgSyms (FILE* F, unsigned long Pos, ObjData* O); /* Read the debug symbols from a file at the given position */ void ObjReadLineInfos (FILE* F, unsigned long Pos, ObjData* O); /* Read the line infos from a file at the given position */ void ObjReadStrPool (FILE* F, unsigned long Pos, ObjData* O); /* Read the string pool from a file at the given position */ void ObjReadAssertions (FILE* F, unsigned long Pos, ObjData* O); /* Read the assertions from a file at the given offset */ void ObjReadScopes (FILE* F, unsigned long Pos, ObjData* O); /* Read the scope table from a file at the given offset */ void ObjReadSpans (FILE* F, unsigned long Pos, ObjData* O); /* Read the span table from a file at the given offset */ void ObjAdd (FILE* F, const char* Name); /* Add an object file to the module list */ /* End of objfile.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/scanner.c������������������������������������������������������������������������0000664�0000000�0000000�00000034215�13473601511�0015350�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* scanner.c */ /* */ /* Configuration file scanner for the ld65 linker */ /* */ /* */ /* */ /* (C) 1998-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdarg.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <ctype.h> /* common */ #include "chartype.h" #include "strbuf.h" #include "xsprintf.h" /* ld65 */ #include "global.h" #include "error.h" #include "scanner.h" #include "spool.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Current token and attributes */ cfgtok_t CfgTok; StrBuf CfgSVal = STATIC_STRBUF_INITIALIZER; unsigned long CfgIVal; /* Error location */ FilePos CfgErrorPos; /* Input source for the configuration */ static const char* CfgName = 0; /* Other input stuff */ static int C = ' '; static FilePos InputPos; static FILE* InputFile = 0; /*****************************************************************************/ /* Error handling */ /*****************************************************************************/ void CfgWarning (const FilePos* Pos, const char* Format, ...) /* Print a warning message adding file name and line number of a given file */ { StrBuf Buf = STATIC_STRBUF_INITIALIZER; va_list ap; va_start (ap, Format); SB_VPrintf (&Buf, Format, ap); va_end (ap); Warning ("%s(%u): %s", GetString (Pos->Name), Pos->Line, SB_GetConstBuf (&Buf)); SB_Done (&Buf); } void CfgError (const FilePos* Pos, const char* Format, ...) /* Print an error message adding file name and line number of a given file */ { StrBuf Buf = STATIC_STRBUF_INITIALIZER; va_list ap; va_start (ap, Format); SB_VPrintf (&Buf, Format, ap); va_end (ap); Error ("%s(%u): %s", GetString (Pos->Name), Pos->Line, SB_GetConstBuf (&Buf)); SB_Done (&Buf); } /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void NextChar (void) /* Read the next character from the input file */ { /* Read from the file */ C = getc (InputFile); /* Count columns */ if (C != EOF) { ++InputPos.Col; } /* Count lines */ if (C == '\n') { ++InputPos.Line; InputPos.Col = 0; } } static unsigned DigitVal (int C) /* Return the value for a numeric digit */ { if (isdigit (C)) { return C - '0'; } else { return toupper (C) - 'A' + 10; } } static void StrVal (void) /* Parse a string value and expand escape sequences */ { /* Skip the starting double quotes */ NextChar (); /* Read input chars */ SB_Clear (&CfgSVal); while (C != '\"') { switch (C) { case EOF: case '\n': CfgError (&CfgErrorPos, "Unterminated string"); break; case '%': NextChar (); switch (C) { case EOF: case '\n': case '\"': CfgError (&CfgErrorPos, "Unterminated '%%' escape sequence"); break; case '%': SB_AppendChar (&CfgSVal, '%'); NextChar (); break; case 'O': /* Replace by output file */ if (OutputName) { SB_AppendStr (&CfgSVal, OutputName); } OutputNameUsed = 1; NextChar (); break; default: CfgWarning (&CfgErrorPos, "Unkown escape sequence '%%%c'", C); SB_AppendChar (&CfgSVal, '%'); SB_AppendChar (&CfgSVal, C); NextChar (); break; } break; default: SB_AppendChar (&CfgSVal, C); NextChar (); } } /* Skip the terminating double quotes */ NextChar (); /* Terminate the string */ SB_Terminate (&CfgSVal); /* We've read a string value */ CfgTok = CFGTOK_STRCON; } void CfgNextTok (void) /* Read the next token from the input stream */ { Again: /* Skip whitespace */ while (isspace (C)) { NextChar (); } /* Remember the current position */ CfgErrorPos = InputPos; /* Identifier? */ if (C == '_' || IsAlpha (C)) { /* Read the identifier */ SB_Clear (&CfgSVal); while (C == '_' || IsAlNum (C)) { SB_AppendChar (&CfgSVal, C); NextChar (); } SB_Terminate (&CfgSVal); CfgTok = CFGTOK_IDENT; return; } /* Hex number? */ if (C == '$') { NextChar (); if (!isxdigit (C)) { CfgError (&CfgErrorPos, "Hex digit expected"); } CfgIVal = 0; while (isxdigit (C)) { CfgIVal = CfgIVal * 16 + DigitVal (C); NextChar (); } CfgTok = CFGTOK_INTCON; return; } /* Decimal number? */ if (isdigit (C)) { CfgIVal = 0; while (isdigit (C)) { CfgIVal = CfgIVal * 10 + DigitVal (C); NextChar (); } CfgTok = CFGTOK_INTCON; return; } /* Other characters */ switch (C) { case '-': NextChar (); CfgTok = CFGTOK_MINUS; break; case '+': NextChar (); CfgTok = CFGTOK_PLUS; break; case '*': NextChar (); CfgTok = CFGTOK_MUL; break; case '/': NextChar (); CfgTok = CFGTOK_DIV; break; case '(': NextChar (); CfgTok = CFGTOK_LPAR; break; case ')': NextChar (); CfgTok = CFGTOK_RPAR; break; case '{': NextChar (); CfgTok = CFGTOK_LCURLY; break; case '}': NextChar (); CfgTok = CFGTOK_RCURLY; break; case ';': NextChar (); CfgTok = CFGTOK_SEMI; break; case '.': NextChar (); CfgTok = CFGTOK_DOT; break; case ',': NextChar (); CfgTok = CFGTOK_COMMA; break; case '=': NextChar (); CfgTok = CFGTOK_EQ; break; case ':': NextChar (); CfgTok = CFGTOK_COLON; break; case '\"': StrVal (); break; case '#': /* Comment */ while (C != '\n' && C != EOF) { NextChar (); } if (C != EOF) { goto Again; } CfgTok = CFGTOK_EOF; break; case '%': NextChar (); switch (C) { case 'O': NextChar (); if (OutputName) { SB_CopyStr (&CfgSVal, OutputName); } else { SB_Clear (&CfgSVal); } SB_Terminate (&CfgSVal); OutputNameUsed = 1; CfgTok = CFGTOK_STRCON; break; case 'S': NextChar (); CfgIVal = StartAddr; CfgTok = CFGTOK_INTCON; break; default: CfgError (&CfgErrorPos, "Invalid format specification"); } break; case EOF: CfgTok = CFGTOK_EOF; break; default: CfgError (&CfgErrorPos, "Invalid character '%c'", C); } } void CfgConsume (cfgtok_t T, const char* Msg) /* Skip a token, print an error message if not found */ { if (CfgTok != T) { CfgError (&CfgErrorPos, "%s", Msg); } CfgNextTok (); } void CfgConsumeSemi (void) /* Consume a semicolon */ { CfgConsume (CFGTOK_SEMI, "';' expected"); } void CfgConsumeColon (void) /* Consume a colon */ { CfgConsume (CFGTOK_COLON, "':' expected"); } void CfgOptionalComma (void) /* Consume a comma if there is one */ { if (CfgTok == CFGTOK_COMMA) { CfgNextTok (); } } void CfgOptionalAssign (void) /* Consume an equal sign if there is one */ { if (CfgTok == CFGTOK_EQ) { CfgNextTok (); } } void CfgAssureInt (void) /* Make sure the next token is an integer */ { if (CfgTok != CFGTOK_INTCON) { CfgError (&CfgErrorPos, "Integer constant expected"); } } void CfgAssureStr (void) /* Make sure the next token is a string constant */ { if (CfgTok != CFGTOK_STRCON) { CfgError (&CfgErrorPos, "String constant expected"); } } void CfgAssureIdent (void) /* Make sure the next token is an identifier */ { if (CfgTok != CFGTOK_IDENT) { CfgError (&CfgErrorPos, "Identifier expected"); } } void CfgRangeCheck (unsigned long Lo, unsigned long Hi) /* Check the range of CfgIVal */ { if (CfgIVal < Lo || CfgIVal > Hi) { CfgError (&CfgErrorPos, "Range error"); } } void CfgSpecialToken (const IdentTok* Table, unsigned Size, const char* Name) /* Map an identifier to one of the special tokens in the table */ { unsigned I; /* We need an identifier */ if (CfgTok == CFGTOK_IDENT) { /* Make it upper case */ SB_ToUpper (&CfgSVal); /* Linear search */ for (I = 0; I < Size; ++I) { if (SB_CompareStr (&CfgSVal, Table[I].Ident) == 0) { CfgTok = Table[I].Tok; return; } } } /* Not found or no identifier */ CfgError (&CfgErrorPos, "%s expected, got '%s'", Name, SB_GetConstBuf(&CfgSVal)); } void CfgBoolToken (void) /* Map an identifier or integer to a boolean token */ { static const IdentTok Booleans [] = { { "YES", CFGTOK_TRUE }, { "NO", CFGTOK_FALSE }, { "TRUE", CFGTOK_TRUE }, { "FALSE", CFGTOK_FALSE }, }; /* If we have an identifier, map it to a boolean token */ if (CfgTok == CFGTOK_IDENT) { CfgSpecialToken (Booleans, ENTRY_COUNT (Booleans), "Boolean"); } else { /* We expected an integer here */ if (CfgTok != CFGTOK_INTCON) { CfgError (&CfgErrorPos, "Boolean value expected"); } CfgTok = (CfgIVal == 0)? CFGTOK_FALSE : CFGTOK_TRUE; } } void CfgSetName (const char* Name) /* Set a name for a config file */ { CfgName = Name; } int CfgAvail (void) /* Return true if we have a configuration available */ { return CfgName != 0; } void CfgOpenInput (void) /* Open the input file if we have one */ { /* Open the file */ InputFile = fopen (CfgName, "r"); if (InputFile == 0) { Error ("Cannot open '%s': %s", CfgName, strerror (errno)); } /* Initialize variables */ C = ' '; InputPos.Line = 1; InputPos.Col = 0; InputPos.Name = GetStringId (CfgName); /* Start the ball rolling ... */ CfgNextTok (); } void CfgCloseInput (void) /* Close the input file if we have one */ { /* Close the input file if we had one */ if (InputFile) { (void) fclose (InputFile); InputFile = 0; } } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/scanner.h������������������������������������������������������������������������0000664�0000000�0000000�00000016236�13473601511�0015360�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* scanner.h */ /* */ /* Configuration file scanner for the ld65 linker */ /* */ /* */ /* */ /* (C) 1998-2013, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef SCANNER_H #define SCANNER_H /* common */ #include "filepos.h" #include "strbuf.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Config file tokens */ typedef enum { CFGTOK_NONE, CFGTOK_INTCON, /* Integer constant */ CFGTOK_STRCON, /* String constant */ CFGTOK_IDENT, /* Identifier */ CFGTOK_PLUS, CFGTOK_MINUS, CFGTOK_MUL, CFGTOK_DIV, CFGTOK_LPAR, CFGTOK_RPAR, CFGTOK_LCURLY, CFGTOK_RCURLY, CFGTOK_SEMI, CFGTOK_COMMA, CFGTOK_EQ, CFGTOK_COLON, CFGTOK_DOT, CFGTOK_EOF, /* Special identifiers */ CFGTOK_MEMORY, CFGTOK_FILES, CFGTOK_SEGMENTS, CFGTOK_FORMATS, CFGTOK_FEATURES, CFGTOK_SYMBOLS, CFGTOK_START, CFGTOK_SIZE, CFGTOK_TYPE, CFGTOK_FILE, CFGTOK_DEFINE, CFGTOK_BANK, CFGTOK_FILL, CFGTOK_FILLVAL, CFGTOK_EXPORT, CFGTOK_IMPORT, CFGTOK_OS, CFGTOK_ID, CFGTOK_VERSION, CFGTOK_FORMAT, CFGTOK_RUNAD, CFGTOK_INITAD, CFGTOK_LOAD, CFGTOK_RUN, CFGTOK_ALIGN, CFGTOK_ALIGN_LOAD, CFGTOK_OFFSET, CFGTOK_OPTIONAL, CFGTOK_RO, CFGTOK_RW, CFGTOK_BSS, CFGTOK_ZP, CFGTOK_OVERWRITE, CFGTOK_ATARIEXE, CFGTOK_O65, CFGTOK_BIN, CFGTOK_SMALL, CFGTOK_LARGE, CFGTOK_TRUE, CFGTOK_FALSE, CFGTOK_LUNIX, CFGTOK_OSA65, CFGTOK_CC65, CFGTOK_OPENCBM, CFGTOK_CONDES, CFGTOK_STARTADDRESS, CFGTOK_ADDRSIZE, CFGTOK_VALUE, CFGTOK_WEAK, CFGTOK_ABS, CFGTOK_FAR, CFGTOK_LONG, CFGTOK_SEGMENT, CFGTOK_LABEL, CFGTOK_COUNT, CFGTOK_ORDER, CFGTOK_CONSTRUCTOR, CFGTOK_DESTRUCTOR, CFGTOK_INTERRUPTOR, CFGTOK_DECREASING, CFGTOK_INCREASING, CFGTOK_DEFAULT } cfgtok_t; /* Mapping table entry, special identifier --> token */ typedef struct IdentTok IdentTok; struct IdentTok { const char* Ident; /* Identifier */ cfgtok_t Tok; /* Token for identifier */ }; #define ENTRY_COUNT(s) (sizeof (s) / sizeof (s [0])) /* Current token and attributes */ extern cfgtok_t CfgTok; extern StrBuf CfgSVal; extern unsigned long CfgIVal; /* Error location. PLEASE NOTE: I'm abusing the FilePos structure to some ** degree. It is used mostly to hold a file position, where the Name member ** is an index into the source file table of an object file. As used in config ** file processing, the Name member is a string pool index instead. This is ** distinguished by the object file pointer being NULL or not in the structs ** where this is relevant. */ extern FilePos CfgErrorPos; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void CfgWarning (const FilePos* Pos, const char* Format, ...) attribute((format(printf,2,3))); /* Print a warning message adding file name and line number of the config file */ void CfgError (const FilePos* Pos, const char* Format, ...) attribute((format(printf,2,3))); /* Print an error message adding file name and line number of a given file */ void CfgNextTok (void); /* Read the next token from the input stream */ void CfgConsume (cfgtok_t T, const char* Msg); /* Skip a token, print an error message if not found */ void CfgConsumeSemi (void); /* Consume a semicolon */ void CfgConsumeColon (void); /* Consume a colon */ void CfgOptionalComma (void); /* Consume a comma if there is one */ void CfgOptionalAssign (void); /* Consume an equal sign if there is one */ void CfgAssureInt (void); /* Make sure the next token is an integer */ void CfgAssureStr (void); /* Make sure the next token is a string constant */ void CfgAssureIdent (void); /* Make sure the next token is an identifier */ void CfgRangeCheck (unsigned long Lo, unsigned long Hi); /* Check the range of CfgIVal */ void CfgSpecialToken (const IdentTok* Table, unsigned Size, const char* Name); /* Map an identifier to one of the special tokens in the table */ void CfgBoolToken (void); /* Map an identifier or integer to a boolean token */ void CfgSetName (const char* Name); /* Set a name for a config file */ int CfgAvail (void); /* Return true if we have a configuration available */ void CfgOpenInput (void); /* Open the input file if we have one */ void CfgCloseInput (void); /* Close the input file if we have one */ /* End of scanner.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/scopes.c�������������������������������������������������������������������������0000664�0000000�0000000�00000014533�13473601511�0015214�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* scopes.c */ /* */ /* Scope handling for the ld65 linker */ /* */ /* */ /* */ /* (C) 2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "xmalloc.h" /* ld65 */ #include "error.h" #include "fileio.h" #include "scopes.h" #include "span.h" #include "spool.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ static Scope* NewScope (ObjData* Obj, unsigned Id) /* Create a new Scope and return it */ { /* Allocate memory */ Scope* S = xmalloc (sizeof (Scope)); /* Initialize the fields where necessary */ S->Id = Id; S->Obj = Obj; S->Size = 0; S->LabelId = ~0U; S->Spans = 0; /* Return the new entry */ return S; } Scope* ReadScope (FILE* F, ObjData* Obj, unsigned Id) /* Read a scope from a file and return it */ { /* Create a new scope */ Scope* S = NewScope (Obj, Id); /* Read the data from file */ S->ParentId = ReadVar (F); S->LexicalLevel = ReadVar (F); S->Flags = ReadVar (F); S->Type = ReadVar (F); S->Name = MakeGlobalStringId (Obj, ReadVar (F)); if (SCOPE_HAS_SIZE (S->Flags)) { S->Size = ReadVar (F); } if (SCOPE_HAS_LABEL (S->Flags)) { S->LabelId = ReadVar (F); } S->Spans = ReadSpanList (F); /* Return the new Scope */ return S; } unsigned ScopeCount (void) /* Return the total number of scopes */ { /* Count scopes from all modules we have linked into the output file */ unsigned I; unsigned Count = 0; for (I = 0; I < CollCount (&ObjDataList); ++I) { /* Get the object file */ const ObjData* O = CollAtUnchecked (&ObjDataList, I); /* Account for the scopes in this file */ Count += CollCount (&O->Scopes); } return Count; } void PrintDbgScopes (FILE* F) /* Output the scopes to a debug info file */ { unsigned I, J; /* Print scopes from all modules we have linked into the output file */ for (I = 0; I < CollCount (&ObjDataList); ++I) { /* Get the object file */ ObjData* O = CollAtUnchecked (&ObjDataList, I); /* Output the scopes for this object file */ for (J = 0; J < CollCount (&O->Scopes); ++J) { const Scope* S = CollConstAt (&O->Scopes, J); /* Output the first chunk of data */ fprintf (F, "scope\tid=%u,name=\"%s\",mod=%u", O->ScopeBaseId + S->Id, GetString (S->Name), I); /* Print the type if not module */ switch (S->Type) { case SCOPE_GLOBAL: fputs (",type=global", F); break; case SCOPE_FILE: /* default */ break; case SCOPE_SCOPE: fputs (",type=scope", F); break; case SCOPE_STRUCT: fputs (",type=struct", F); break; case SCOPE_ENUM: fputs (",type=enum", F); break; default: Error ("Module '%s': Unknown scope type %u", GetObjFileName (O), S->Type); } /* Print the size if available */ if (S->Size != 0) { fprintf (F, ",size=%lu", S->Size); } /* Print parent if available */ if (S->Id != S->ParentId) { fprintf (F, ",parent=%u", O->ScopeBaseId + S->ParentId); } /* Print the label id if the scope is labeled */ if (SCOPE_HAS_LABEL (S->Flags)) { fprintf (F, ",sym=%u", O->SymBaseId + S->LabelId); } /* Print the list of spans for this scope */ PrintDbgSpanList (F, O, S->Spans); /* Terminate the output line */ fputc ('\n', F); } } } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/scopes.h�������������������������������������������������������������������������0000664�0000000�0000000�00000010123�13473601511�0015210�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* scopes.h */ /* */ /* Scope handling for the ld65 linker */ /* */ /* */ /* */ /* (C) 2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef SCOPES_H #define SCOPES_H #include <stdio.h> /* common */ #include "coll.h" #include "scopedefs.h" /* ld65 */ #include "objdata.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Debug symbol structure */ typedef struct Scope Scope; struct Scope { unsigned Id; /* Id of scope */ ObjData* Obj; /* Object file that contains the scope */ unsigned ParentId; /* Id of parent scope */ unsigned LabelId; /* Id of the scope label if any */ unsigned LexicalLevel; /* Lexical level */ unsigned Flags; unsigned Type; /* Type of scope */ unsigned Name; /* Name of scope */ unsigned long Size; /* Size of scope */ unsigned* Spans; /* Spans for this scope */ }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ Scope* ReadScope (FILE* F, ObjData* Obj, unsigned Id); /* Read a scope from a file, insert and return it */ unsigned ScopeCount (void); /* Return the total number of scopes */ void PrintDbgScopes (FILE* F); /* Output the scopes to a debug info file */ /* End of scopes.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/segments.c�����������������������������������������������������������������������0000664�0000000�0000000�00000051125�13473601511�0015543�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* segments.c */ /* */ /* Segment handling for the ld65 linker */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdlib.h> #include <string.h> /* common */ #include "addrsize.h" #include "alignment.h" #include "check.h" #include "coll.h" #include "exprdefs.h" #include "fragdefs.h" #include "hashfunc.h" #include "print.h" #include "segdefs.h" #include "symdefs.h" #include "xmalloc.h" /* ld65 */ #include "error.h" #include "expr.h" #include "fileio.h" #include "fragment.h" #include "global.h" #include "lineinfo.h" #include "segments.h" #include "spool.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Hash table */ #define HASHTAB_MASK 0x3FU #define HASHTAB_SIZE (HASHTAB_MASK + 1) static Segment* HashTab[HASHTAB_SIZE]; /* List of all segments */ static Collection SegmentList = STATIC_COLLECTION_INITIALIZER; /*****************************************************************************/ /* Code */ /*****************************************************************************/ static Segment* NewSegment (unsigned Name, unsigned char AddrSize) /* Create a new segment and initialize it */ { unsigned Hash; /* Allocate memory */ Segment* S = xmalloc (sizeof (Segment)); /* Initialize the fields */ S->Name = Name; S->Next = 0; S->Flags = SEG_FLAG_NONE; S->Sections = EmptyCollection; S->MemArea = 0; S->PC = 0; S->Size = 0; S->OutputName = 0; S->OutputOffs = 0; S->Alignment = 1; S->FillVal = 0; S->AddrSize = AddrSize; S->ReadOnly = 0; S->Dumped = 0; /* Insert the segment into the segment list and assign the segment id */ S->Id = CollCount (&SegmentList); CollAppend (&SegmentList, S); /* Insert the segment into the segment hash list */ Hash = (S->Name & HASHTAB_MASK); S->Next = HashTab[Hash]; HashTab[Hash] = S; /* Return the new entry */ return S; } Segment* GetSegment (unsigned Name, unsigned char AddrSize, const char* ObjName) /* Search for a segment and return an existing one. If the segment does not ** exist, create a new one and return that. ObjName is only used for the error ** message and may be NULL if the segment is linker generated. */ { /* Try to locate the segment in the table */ Segment* S = SegFind (Name); /* If we don't have that segment already, allocate it using the type of ** the first section. */ if (S == 0) { /* Create a new segment */ S = NewSegment (Name, AddrSize); } else { /* Check if the existing segment has the requested address size */ if (S->AddrSize != AddrSize) { /* Allow an empty object name */ if (ObjName == 0) { ObjName = "[linker generated]"; } Error ("Module '%s': Type mismatch for segment '%s'", ObjName, GetString (Name)); } } /* Return the segment */ return S; } Section* NewSection (Segment* Seg, unsigned long Alignment, unsigned char AddrSize) /* Create a new section for the given segment */ { /* Allocate memory */ Section* S = xmalloc (sizeof (Section)); /* Initialize the data */ S->Next = 0; S->Seg = Seg; S->Obj = 0; S->FragRoot = 0; S->FragLast = 0; S->Size = 0; S->Alignment= Alignment; S->AddrSize = AddrSize; /* Calculate the alignment bytes needed for the section */ S->Fill = AlignCount (Seg->Size, S->Alignment); /* Adjust the segment size and set the section offset */ Seg->Size += S->Fill; S->Offs = Seg->Size; /* Current size is offset */ /* Insert the section into the segment */ CollAppend (&Seg->Sections, S); /* Return the struct */ return S; } Section* ReadSection (FILE* F, ObjData* O) /* Read a section from a file */ { unsigned Name; unsigned Size; unsigned long Alignment; unsigned char Type; unsigned FragCount; Segment* S; Section* Sec; /* Read the segment data */ (void) Read32 (F); /* File size of data */ Name = MakeGlobalStringId (O, ReadVar (F)); /* Segment name */ ReadVar (F); /* Segment flags (currently unused) */ Size = ReadVar (F); /* Size of data */ Alignment = ReadVar (F); /* Alignment */ Type = Read8 (F); /* Segment type */ FragCount = ReadVar (F); /* Number of fragments */ /* Print some data */ Print (stdout, 2, "Module '%s': Found segment '%s', size = %u, alignment = %lu, type = %u\n", GetObjFileName (O), GetString (Name), Size, Alignment, Type); /* Get the segment for this section */ S = GetSegment (Name, Type, GetObjFileName (O)); /* Allocate the section we will return later */ Sec = NewSection (S, Alignment, Type); /* Remember the object file this section was from */ Sec->Obj = O; /* Set up the combined segment alignment */ if (Sec->Alignment > 1) { Alignment = LeastCommonMultiple (S->Alignment, Sec->Alignment); if (Alignment > MAX_ALIGNMENT) { Error ("Combined alignment for segment '%s' is %lu which exceeds " "%lu. Last module requiring alignment was '%s'.", GetString (Name), Alignment, MAX_ALIGNMENT, GetObjFileName (O)); } else if (Alignment >= LARGE_ALIGNMENT) { Warning ("Combined alignment for segment '%s' is suspiciously " "large (%lu). Last module requiring alignment was '%s'.", GetString (Name), Alignment, GetObjFileName (O)); } S->Alignment = Alignment; } /* Start reading fragments from the file and insert them into the section . */ while (FragCount--) { Fragment* Frag; /* Read the fragment type */ unsigned char Type = Read8 (F); /* Extract the check mask from the type */ unsigned char Bytes = Type & FRAG_BYTEMASK; Type &= FRAG_TYPEMASK; /* Handle the different fragment types */ switch (Type) { case FRAG_LITERAL: Frag = NewFragment (Type, ReadVar (F), Sec); ReadData (F, Frag->LitBuf, Frag->Size); break; case FRAG_EXPR: case FRAG_SEXPR: Frag = NewFragment (Type, Bytes, Sec); Frag->Expr = ReadExpr (F, O); break; case FRAG_FILL: /* Will allocate memory, but we don't care... */ Frag = NewFragment (Type, ReadVar (F), Sec); break; default: Error ("Unknown fragment type in module '%s', segment '%s': %02X", GetObjFileName (O), GetString (S->Name), Type); /* NOTREACHED */ return 0; } /* Read the line infos into the list of the fragment */ ReadLineInfoList (F, O, &Frag->LineInfos); /* Remember the module we had this fragment from */ Frag->Obj = O; } /* Return the section */ return Sec; } Segment* SegFind (unsigned Name) /* Return the given segment or NULL if not found. */ { Segment* S = HashTab[Name & HASHTAB_MASK]; while (S) { if (Name == S->Name) { /* Found */ break; } S = S->Next; } /* Not found */ return S; } int IsBSSType (Segment* S) /* Check if the given segment is a BSS style segment, that is, it does not ** contain non-zero data. */ { /* Loop over all sections */ unsigned I; for (I = 0; I < CollCount (&S->Sections); ++I) { /* Get the next section */ Section* Sec = CollAtUnchecked (&S->Sections, I); /* Loop over all fragments */ Fragment* F = Sec->FragRoot; while (F) { if (F->Type == FRAG_LITERAL) { unsigned char* Data = F->LitBuf; unsigned long Count = F->Size; while (Count--) { if (*Data++ != 0) { return 0; } } } else if (F->Type == FRAG_EXPR || F->Type == FRAG_SEXPR) { if (GetExprVal (F->Expr) != 0) { return 0; } } F = F->Next; } } return 1; } void SegDump (void) /* Dump the segments and it's contents */ { unsigned I, J; unsigned long Count; unsigned char* Data; for (I = 0; I < CollCount (&SegmentList); ++I) { Segment* Seg = CollAtUnchecked (&SegmentList, I); printf ("Segment: %s (%lu)\n", GetString (Seg->Name), Seg->Size); for (J = 0; J < CollCount (&Seg->Sections); ++J) { Section* S = CollAtUnchecked (&Seg->Sections, J); unsigned J; Fragment* F = S->FragRoot; printf (" Section:\n"); while (F) { switch (F->Type) { case FRAG_LITERAL: printf (" Literal (%u bytes):", F->Size); Count = F->Size; Data = F->LitBuf; J = 100; while (Count--) { if (J > 75) { printf ("\n "); J = 3; } printf (" %02X", *Data++); J += 3; } printf ("\n"); break; case FRAG_EXPR: printf (" Expression (%u bytes):\n", F->Size); printf (" "); DumpExpr (F->Expr, 0); break; case FRAG_SEXPR: printf (" Signed expression (%u bytes):\n", F->Size); printf (" "); DumpExpr (F->Expr, 0); break; case FRAG_FILL: printf (" Empty space (%u bytes)\n", F->Size); break; default: Internal ("Invalid fragment type: %02X", F->Type); } F = F->Next; } } } } unsigned SegWriteConstExpr (FILE* F, ExprNode* E, int Signed, unsigned Size) /* Write a supposedly constant expression to the target file. Do a range ** check and return one of the SEG_EXPR_xxx codes. */ { static const unsigned long U_Hi[4] = { 0x000000FFUL, 0x0000FFFFUL, 0x00FFFFFFUL, 0xFFFFFFFFUL }; static const long S_Hi[4] = { 0x0000007FL, 0x00007FFFL, 0x007FFFFFL, 0x7FFFFFFFL }; static const long S_Lo[4] = { ~0x0000007FL, ~0x00007FFFL, ~0x007FFFFFL, ~0x7FFFFFFFL }; /* Get the expression value */ long Val = GetExprVal (E); /* Check the size */ CHECK (Size >= 1 && Size <= 4); /* Check for a range error */ if (Signed) { if (Val > S_Hi[Size-1] || Val < S_Lo[Size-1]) { /* Range error */ return SEG_EXPR_RANGE_ERROR; } } else { if (((unsigned long)Val) > U_Hi[Size-1]) { /* Range error */ return SEG_EXPR_RANGE_ERROR; } } /* Write the value to the file */ WriteVal (F, Val, Size); /* Success */ return SEG_EXPR_OK; } void SegWrite (const char* TgtName, FILE* Tgt, Segment* S, SegWriteFunc F, void* Data) /* Write the data from the given segment to a file. For expressions, F is ** called (see description of SegWriteFunc above). */ { unsigned I; int Sign; unsigned long Offs = 0; /* Remember the output file and offset for the segment */ S->OutputName = TgtName; S->OutputOffs = (unsigned long) ftell (Tgt); /* Loop over all sections in this segment */ for (I = 0; I < CollCount (&S->Sections); ++I) { Section* Sec = CollAtUnchecked (&S->Sections, I); Fragment* Frag; unsigned char FillVal; /* Output were this section is from */ Print (stdout, 2, " Section from \"%s\"\n", GetObjFileName (Sec->Obj)); /* If we have fill bytes, write them now. Beware: If this is the ** first section, the fill value is not considered part of the segment ** and therefore taken from the memory area. */ FillVal = (I == 0)? S->MemArea->FillVal : S->FillVal; Print (stdout, 2, " Filling 0x%lx bytes with 0x%02x\n", Sec->Fill, FillVal); WriteMult (Tgt, FillVal, Sec->Fill); Offs += Sec->Fill; /* Loop over all fragments in this section */ Frag = Sec->FragRoot; while (Frag) { /* Output fragment data */ switch (Frag->Type) { case FRAG_LITERAL: WriteData (Tgt, Frag->LitBuf, Frag->Size); break; case FRAG_EXPR: case FRAG_SEXPR: Sign = (Frag->Type == FRAG_SEXPR); /* Call the users function and evaluate the result */ switch (F (Frag->Expr, Sign, Frag->Size, Offs, Data)) { case SEG_EXPR_OK: break; case SEG_EXPR_RANGE_ERROR: Error ("Range error in module '%s', line %u", GetFragmentSourceName (Frag), GetFragmentSourceLine (Frag)); break; case SEG_EXPR_TOO_COMPLEX: Error ("Expression too complex in module '%s', line %u", GetFragmentSourceName (Frag), GetFragmentSourceLine (Frag)); break; case SEG_EXPR_INVALID: Error ("Invalid expression in module '%s', line %u", GetFragmentSourceName (Frag), GetFragmentSourceLine (Frag)); break; default: Internal ("Invalid return code from SegWriteFunc"); } break; case FRAG_FILL: WriteMult (Tgt, S->FillVal, Frag->Size); break; default: Internal ("Invalid fragment type: %02X", Frag->Type); } /* Update the offset */ Print (stdout, 2, " Fragment with 0x%x bytes\n", Frag->Size); Offs += Frag->Size; /* Next fragment */ Frag = Frag->Next; } } } unsigned SegmentCount (void) /* Return the total number of segments */ { return CollCount (&SegmentList); } static int CmpSegStart (const void* K1, const void* K2) /* Compare function for qsort */ { /* Get the real segment pointers */ const Segment* S1 = *(const Segment**)K1; const Segment* S2 = *(const Segment**)K2; /* Compare the start addresses */ if (S1->PC > S2->PC) { return 1; } else if (S1->PC < S2->PC) { return -1; } else { /* Sort segments with equal starts by name */ return strcmp (GetString (S1->Name), GetString (S2->Name)); } } void PrintSegmentMap (FILE* F) /* Print a segment map to the given file */ { /* Allocate memory for the segment pool */ Segment** SegPool = xmalloc (CollCount (&SegmentList) * sizeof (Segment*)); /* Copy the segment pointers */ unsigned I; for (I = 0; I < CollCount (&SegmentList); ++I) { SegPool[I] = CollAtUnchecked (&SegmentList, I); } /* Sort the array by increasing start addresses */ qsort (SegPool, CollCount (&SegmentList), sizeof (Segment*), CmpSegStart); /* Print a header */ fprintf (F, "Name Start End Size Align\n" "----------------------------------------------------\n"); /* Print the segments */ for (I = 0; I < CollCount (&SegmentList); ++I) { /* Get a pointer to the segment */ Segment* S = SegPool[I]; /* Print empty segments only if explicitly requested */ if (VerboseMap || S->Size > 0) { /* Print the segment data */ long End = S->PC + S->Size; if (S->Size > 0) { /* Point to last element addressed */ --End; } fprintf (F, "%-20s %06lX %06lX %06lX %05lX\n", GetString (S->Name), S->PC, End, S->Size, S->Alignment); } } /* Free the segment pool */ xfree (SegPool); } void PrintDbgSegments (FILE* F) /* Output the segments to the debug file */ { /* Walk over all segments */ unsigned I; for (I = 0; I < CollCount (&SegmentList); ++I) { /* Get the next segment */ const Segment* S = CollAtUnchecked (&SegmentList, I); /* Print the segment data */ fprintf (F, "seg\tid=%u,name=\"%s\",start=0x%06lX,size=0x%04lX,addrsize=%s,type=%s", S->Id, GetString (S->Name), S->PC, S->Size, AddrSizeToStr (S->AddrSize), S->ReadOnly? "ro" : "rw"); if (S->OutputName) { fprintf (F, ",oname=\"%s\",ooffs=%lu", S->OutputName, S->OutputOffs); } fputc ('\n', F); } } void CheckSegments (void) /* Walk through the segment list and check if there are segments that were ** not written to the output file. Output an error if this is the case. */ { unsigned I; for (I = 0; I < CollCount (&SegmentList); ++I) { /* Get the next segment */ const Segment* S = CollAtUnchecked (&SegmentList, I); /* Check it */ if (S->Size > 0 && S->Dumped == 0) { Error ("Missing memory area assignment for segment '%s'", GetString (S->Name)); } } } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/segments.h�����������������������������������������������������������������������0000664�0000000�0000000�00000016705�13473601511�0015555�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* segments.h */ /* */ /* Segment handling for the ld65 linker */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef SEGMENTS_H #define SEGMENTS_H #include <stdio.h> /* common */ #include "coll.h" #include "exprdefs.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Forwards */ struct MemoryArea; /* Segment structure */ typedef struct Segment Segment; struct Segment { unsigned Name; /* Name index of the segment */ unsigned Id; /* Segment id for debug info */ Segment* Next; /* Hash list */ unsigned Flags; /* Segment flags */ Collection Sections; /* Sections in this segment */ struct MemoryArea* MemArea; /* Run memory area once placed */ unsigned long PC; /* PC were this segment is located */ unsigned long Size; /* Size of data so far */ const char* OutputName; /* Name of output file or NULL */ unsigned long OutputOffs; /* Offset in output file */ unsigned long Alignment; /* Alignment needed */ unsigned char FillVal; /* Value to use for fill bytes */ unsigned char AddrSize; /* Address size of segment */ unsigned char ReadOnly; /* True for readonly segments (config) */ unsigned char Dumped; /* Did we dump this segment? */ }; /* Section structure (a section is a part of a segment) */ typedef struct Section Section; struct Section { Section* Next; /* List of sections in a segment */ Segment* Seg; /* Segment that contains the section */ struct ObjData* Obj; /* Object file this section comes from */ struct Fragment* FragRoot; /* Fragment list */ struct Fragment* FragLast; /* Pointer to last fragment */ unsigned long Offs; /* Offset into the segment */ unsigned long Size; /* Size of the section */ unsigned long Fill; /* Fill bytes for alignment */ unsigned long Alignment; /* Alignment */ unsigned char AddrSize; /* Address size of segment */ }; /* Prototype for a function that is used to write expressions to the target ** file (used in SegWrite). It returns one of the following values: */ #define SEG_EXPR_OK 0U /* Ok */ #define SEG_EXPR_RANGE_ERROR 1U /* Range error */ #define SEG_EXPR_TOO_COMPLEX 2U /* Expression too complex */ #define SEG_EXPR_INVALID 3U /* Expression is invalid (e.g. unmapped segment) */ typedef unsigned (*SegWriteFunc) (ExprNode* E, /* The expression to write */ int Signed, /* Signed expression? */ unsigned Size, /* Size (=range) */ unsigned long Offs, /* File offset */ void* Data); /* Callers data */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ Segment* GetSegment (unsigned Name, unsigned char AddrSize, const char* ObjName); /* Search for a segment and return an existing one. If the segment does not ** exist, create a new one and return that. ObjName is only used for the error ** message and may be NULL if the segment is linker generated. */ Section* NewSection (Segment* Seg, unsigned long Alignment, unsigned char AddrSize); /* Create a new section for the given segment */ Section* ReadSection (FILE* F, struct ObjData* O); /* Read a section from a file */ Segment* SegFind (unsigned Name); /* Return the given segment or NULL if not found. */ int IsBSSType (Segment* S); /* Check if the given segment is a BSS style segment, that is, it does not ** contain non-zero data. */ void SegDump (void); /* Dump the segments and it's contents */ unsigned SegWriteConstExpr (FILE* F, ExprNode* E, int Signed, unsigned Size); /* Write a supposedly constant expression to the target file. Do a range ** check and return one of the SEG_EXPR_xxx codes. */ void SegWrite (const char* TgtName, FILE* Tgt, Segment* S, SegWriteFunc F, void* Data); /* Write the data from the given segment to a file. For expressions, F is ** called (see description of SegWriteFunc above). */ unsigned SegmentCount (void); /* Return the total number of segments */ void PrintSegmentMap (FILE* F); /* Print a segment map to the given file */ void PrintDbgSegments (FILE* F); /* Output the segments to the debug file */ void CheckSegments (void); /* Walk through the segment list and check if there are segments that were ** not written to the output file. Output an error if this is the case. */ /* End of segments.h */ #endif �����������������������������������������������������������cc65-2.18/src/ld65/span.c���������������������������������������������������������������������������0000664�0000000�0000000�00000016733�13473601511�0014665�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* span.c */ /* */ /* A span of data within a segment */ /* */ /* */ /* */ /* (C) 2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "gentype.h" #include "xmalloc.h" /* ld65 */ #include "fileio.h" #include "objdata.h" #include "segments.h" #include "span.h" #include "tpool.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Definition of a span */ struct Span { unsigned Id; /* Id of the span */ unsigned Sec; /* Section id of this span */ unsigned long Offs; /* Offset of span within segment */ unsigned long Size; /* Size of span */ unsigned Type; /* Generic type of the data */ }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ static Span* NewSpan (unsigned Id) /* Create and return a new span */ { /* Allocate memory */ Span* S = xmalloc (sizeof (Span)); /* Initialize the fields as necessary */ S->Id = Id; /* Return the result */ return S; } Span* ReadSpan (FILE* F, ObjData* O, unsigned Id) /* Read a Span from a file and return it */ { unsigned Type; /* Create a new Span and initialize it */ Span* S = NewSpan (Id); S->Sec = ReadVar (F); S->Offs = ReadVar (F); S->Size = ReadVar (F); /* Read the type. An id of zero means an empty string (no need to check) */ Type = ReadVar (F); if (Type == 0) { S->Type = INVALID_TYPE_ID; } else { S->Type = GetTypeId (GetObjString (O, Type)); } /* Return the new span */ return S; } unsigned* ReadSpanList (FILE* F) /* Read a list of span ids from a file. The list is returned as an array of ** unsigneds, the first being the number of spans (never zero) followed by ** the span ids. If the number of spans is zero, NULL is returned. */ { unsigned* Spans; /* First is number of Spans */ unsigned Count = ReadVar (F); if (Count == 0) { return 0; } /* Allocate memory for the list and set the count */ Spans = xmalloc ((Count + 1) * sizeof (*Spans)); *Spans = Count; /* Read the spans and add them */ while (Count) { Spans[Count] = ReadVar (F); --Count; } /* Return the list */ return Spans; } unsigned* DupSpanList (const unsigned* S) /* Duplicate a span list */ { unsigned Size; /* The list may be empty */ if (S == 0) { return 0; } /* Allocate memory, copy and return the new list */ Size = (*S + 1) * sizeof (*S); return memcpy (xmalloc (Size), S, Size); } void FreeSpan (Span* S) /* Free a span structure */ { /* Just free the structure */ xfree (S); } unsigned SpanCount (void) /* Return the total number of spans */ { /* Walk over all object files */ unsigned I; unsigned Count = 0; for (I = 0; I < CollCount (&ObjDataList); ++I) { /* Get this object file */ const ObjData* O = CollAtUnchecked (&ObjDataList, I); /* Count spans */ Count += CollCount (&O->Spans); } return Count; } void PrintDbgSpanList (FILE* F, const ObjData* O, const unsigned* List) /* Output a string ",span=x[+y...]" for the given list. If the list is empty ** or NULL, output nothing. This is a helper function for other modules to ** print a list of spans read by ReadSpanList to the debug info file. */ { if (List && *List) { unsigned I; const char* Format = ",span=%u"; for (I = 0; I < *List; ++I) { fprintf (F, Format, O->SpanBaseId + List[I+1]); Format = "+%u"; } } } void PrintDbgSpans (FILE* F) /* Output the spans to a debug info file */ { unsigned I, J; StrBuf SpanType = STATIC_STRBUF_INITIALIZER; /* Walk over all object files */ for (I = 0; I < CollCount (&ObjDataList); ++I) { /* Get this object file */ ObjData* O = CollAtUnchecked (&ObjDataList, I); /* Walk over all spans in this object file */ for (J = 0; J < CollCount (&O->Spans); ++J) { /* Get this span */ const Span* S = CollAtUnchecked (&O->Spans, J); /* Get the section for this span */ const Section* Sec = GetObjSection (O, S->Sec); /* Output the data */ fprintf (F, "span\tid=%u,seg=%u,start=%lu,size=%lu", O->SpanBaseId + S->Id, Sec->Seg->Id, Sec->Offs + S->Offs, S->Size); /* If we have a type, add it */ if (S->Type != INVALID_TYPE_ID) { fprintf (F, ",type=%u", S->Type); } /* Terminate the output line */ fputc ('\n', F); } } /* Free the string buffer */ SB_Done (&SpanType); } �������������������������������������cc65-2.18/src/ld65/span.h���������������������������������������������������������������������������0000664�0000000�0000000�00000010523�13473601511�0014661�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* span.h */ /* */ /* A span of data within a segment */ /* */ /* */ /* */ /* (C) 2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef SPAN_H #define SPAN_H #include <stdio.h> /* common */ #include "coll.h" /*****************************************************************************/ /* Forwards */ /*****************************************************************************/ struct ObjData; struct Segment; /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Span is an opaque type */ typedef struct Span Span; /*****************************************************************************/ /* Code */ /*****************************************************************************/ Span* ReadSpan (FILE* F, struct ObjData* O, unsigned Id); /* Read a Span from a file and return it */ unsigned* ReadSpanList (FILE* F); /* Read a list of span ids from a file. The list is returned as an array of ** unsigneds, the first being the number of spans (never zero) followed by ** the span ids. If the number of spans is zero, NULL is returned. */ unsigned* DupSpanList (const unsigned* S); /* Duplicate a span list */ void FreeSpan (Span* S); /* Free a span structure */ unsigned SpanCount (void); /* Return the total number of spans */ void PrintDbgSpanList (FILE* F, const struct ObjData* O, const unsigned* List); /* Output a string ",span=x[+y...]" for the given list. If the list is empty ** or NULL, output nothing. This is a helper function for other modules to ** print a list of spans read by ReadSpanList to the debug info file. */ void PrintDbgSpans (FILE* F); /* Output the spans to a debug info file */ /* End of span.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/spool.c��������������������������������������������������������������������������0000664�0000000�0000000�00000006541�13473601511�0015054�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* spool.c */ /* */ /* Id and message pool for the ld65 linker */ /* */ /* */ /* */ /* (C) 2003-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* ld65 */ #include "spool.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ StringPool* StrPool = 0; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void InitStrPool (void) /* Initialize the string pool */ { /* Allocate a string pool */ StrPool = NewStringPool (1103); /* We insert a first string here, which will have id zero. This means ** that we can treat index zero later as invalid. */ SP_AddStr (StrPool, "<invalid message #0>"); } ���������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/spool.h��������������������������������������������������������������������������0000664�0000000�0000000�00000010260�13473601511�0015052�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* spool.h */ /* */ /* Id and message pool for the ld65 linker */ /* */ /* */ /* */ /* (C) 2003-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef SPOOL_H #define SPOOL_H /* common */ #include "strpool.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* An invalid message index */ #define INVALID_STRING_ID 0U /* The string pool we're using */ extern StringPool* StrPool; /*****************************************************************************/ /* Code */ /*****************************************************************************/ #if defined(HAVE_INLINE) INLINE unsigned GetStrBufId (const StrBuf* S) /* Return the id of the given string buffer */ { return SP_Add (StrPool, S); } #else # define GetStrBufId(S) SP_Add (StrPool, (S)) #endif #if defined(HAVE_INLINE) INLINE unsigned GetStringId (const char* S) /* Return the id of the given string */ { return SP_AddStr (StrPool, S); } #else # define GetStringId(S) SP_AddStr (StrPool, (S)) #endif #if defined(HAVE_INLINE) INLINE const StrBuf* GetStrBuf (unsigned Index) /* Convert a string index into a string */ { return SP_Get (StrPool, Index); } #else # define GetStrBuf(Index) SP_Get (StrPool, (Index)) #endif #if defined(HAVE_INLINE) INLINE const char* GetString (unsigned Index) /* Convert a string index into a string */ { return SB_GetConstBuf (SP_Get (StrPool, Index)); } #else # define GetString(Index) SB_GetConstBuf (SP_Get (StrPool, (Index))) #endif void InitStrPool (void); /* Initialize the string pool */ /* End of spool.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/tpool.c��������������������������������������������������������������������������0000664�0000000�0000000�00000007372�13473601511�0015060�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* tpool.c */ /* */ /* Pool for generic types */ /* */ /* */ /* */ /* (C) 2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "gentype.h" /* ld65 */ #include "tpool.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* The string pool we're using */ StringPool* TypePool = 0; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void PrintDbgTypes (FILE* F) /* Output the types to a debug info file */ { StrBuf Type = STATIC_STRBUF_INITIALIZER; /* Get the number of strings in the type pool */ unsigned Count = SP_GetCount (TypePool); /* Output all of them */ unsigned Id; for (Id = 0; Id < Count; ++Id) { /* Output it */ fprintf (F, "type\tid=%u,val=\"%s\"\n", Id, GT_AsString (SP_Get (TypePool, Id), &Type)); } /* Free the memory for the temporary string */ SB_Done (&Type); } void InitTypePool (void) /* Initialize the type pool */ { /* Allocate a type pool */ TypePool = NewStringPool (137); } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/tpool.h��������������������������������������������������������������������������0000664�0000000�0000000�00000007772�13473601511�0015071�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* tpool.h */ /* */ /* Pool for generic types */ /* */ /* */ /* */ /* (C) 2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef TPOOL_H #define TPOOL_H #include <stdio.h> /* common */ #include "strpool.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* An invalid type */ #define INVALID_TYPE_ID (~0U) /* The string pool we're using */ extern StringPool* TypePool; /*****************************************************************************/ /* Code */ /*****************************************************************************/ #if defined(HAVE_INLINE) INLINE unsigned GetTypeId (const StrBuf* Type) /* Return the id of the given generic type */ { return SP_Add (TypePool, Type); } #else # define GetTypeId(Type) SP_Add (TypePool, (Type)) #endif #if defined(HAVE_INLINE) INLINE const StrBuf* GetType (unsigned Index) /* Convert a type index into a type string */ { return SP_Get (TypePool, Index); } #else # define GetType(Index) SP_Get (TypePool, (Index)) #endif #if defined(HAVE_INLINE) INLINE unsigned TypeCount (void) /* Return the number of types in the pool */ { return SP_GetCount (TypePool); } #else # define TypeCount() SP_GetCount (TypePool) #endif void PrintDbgTypes (FILE* F); /* Output the types to a debug info file */ void InitTypePool (void); /* Initialize the type pool */ /* End of tpool.h */ #endif ������cc65-2.18/src/ld65/xex.c����������������������������������������������������������������������������0000664�0000000�0000000�00000034266�13473601511�0014531�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* xex.c */ /* */ /* Module to handle the Atari XEX binary format */ /* */ /* */ /* */ /* (C) 2018 Daniel Serpell */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> #include <errno.h> /* common */ #include "alignment.h" #include "print.h" #include "xmalloc.h" /* ld65 */ #include "xex.h" #include "config.h" #include "exports.h" #include "expr.h" #include "error.h" #include "global.h" #include "fileio.h" #include "lineinfo.h" #include "memarea.h" #include "segments.h" #include "spool.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Linked list of memory area initialization addresses */ typedef struct XexInitAd { MemoryArea *InitMem; Import *InitAd; struct XexInitAd *next; } XexInitAd; struct XexDesc { unsigned Undef; /* Count of undefined externals */ FILE* F; /* Output file */ const char* Filename; /* Name of output file */ Import* RunAd; /* Run Address */ XexInitAd* InitAds; /* List of Init Addresses */ unsigned long HeadPos; /* Position in the file of current header */ unsigned long HeadEnd; /* End address of current header */ unsigned long HeadSize; /* Last header size, can be removed if zero */ }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ XexDesc* NewXexDesc (void) /* Create a new XEX format descriptor */ { /* Allocate memory for a new XexDesc struct */ XexDesc* D = xmalloc (sizeof (XexDesc)); /* Initialize the fields */ D->Undef = 0; D->F = 0; D->Filename = 0; D->RunAd = 0; D->InitAds = 0; D->HeadPos = 0; D->HeadEnd = 0; D->HeadSize = 0; /* Return the created struct */ return D; } void FreeXexDesc (XexDesc* D) /* Free a XEX format descriptor */ { xfree (D); } void XexSetRunAd (XexDesc* D, Import *RunAd) /* Set the RUNAD export */ { D->RunAd = RunAd; } XexInitAd* XexSearchInitMem(XexDesc* D, MemoryArea *InitMem) { XexInitAd* I; for (I=D->InitAds; I != 0; I=I->next) { if (I->InitMem == InitMem) return I; } return NULL; } int XexAddInitAd (XexDesc* D, MemoryArea *InitMem, Import *InitAd) /* Sets and INITAD for the given memory area */ { XexInitAd* I; /* Search for repeated entry */ if (XexSearchInitMem (D, InitMem)) return 1; I = xmalloc (sizeof (XexInitAd)); I->InitAd = InitAd; I->InitMem = InitMem; I->next = D->InitAds; D->InitAds = I; return 0; } static unsigned XexWriteExpr (ExprNode* E, int Signed, unsigned Size, unsigned long Offs attribute ((unused)), void* Data) /* Called from SegWrite for an expression. Evaluate the expression, check the ** range and write the expression value to the file. */ { /* There's a predefined function to handle constant expressions */ return SegWriteConstExpr (((XexDesc*)Data)->F, E, Signed, Size); } static void PrintNumVal (const char* Name, unsigned long V) /* Print a numerical value for debugging */ { Print (stdout, 2, " %s = 0x%lx\n", Name, V); } static void XexStartSegment (XexDesc *D, unsigned long Addr, unsigned long Size) { /* Skip segment without size */ if (!Size) return; /* Store current position */ unsigned long Pos = ftell (D->F); unsigned long End = Addr + Size - 1; /* See if last header can be expanded into this one */ if (D->HeadPos && ((D->HeadEnd + 1) == Addr)) { /* Expand current header */ D->HeadEnd = End; D->HeadSize += Size; fseek (D->F, D->HeadPos + 2, SEEK_SET); Write16 (D->F, End); /* Seek to old position */ fseek (D->F, Pos, SEEK_SET); } else { if (D->HeadSize == 0) { /* Last header had no data, replace */ Pos = D->HeadPos; fseek (D->F, Pos, SEEK_SET); } /* If we are at start of file, write XEX heder */ if (Pos == 0) Write16 (D->F, 0xFFFF); /* Writes a new segment header */ D->HeadPos = ftell (D->F); D->HeadEnd = End; D->HeadSize = Size; Write16 (D->F, Addr); Write16 (D->F, End); } } static void XexFakeSegment (XexDesc *D, unsigned long Addr) { /* See if last header can be expanded into this one, we are done */ if (D->HeadPos && ((D->HeadEnd + 1) == Addr)) return; /* If we are at start of file, write XEX heder */ if (ftell (D->F) == 0) Write16 (D->F, 0xFFFF); /* Writes a new (invalid) segment header */ D->HeadPos = ftell (D->F); D->HeadEnd = Addr - 1; D->HeadSize = 0; Write16 (D->F, Addr); Write16 (D->F, D->HeadEnd); } static unsigned long XexWriteMem (XexDesc* D, MemoryArea* M) /* Write the segments of one memory area to a file */ { unsigned I; /* Store initial position to get total file size */ unsigned long StartPos = ftell (D->F); /* Always write a segment header for each memory area */ D->HeadPos = 0; /* Get the start address and size of this memory area */ unsigned long Addr = M->Start; /* Walk over all segments in this memory area */ for (I = 0; I < CollCount (&M->SegList); ++I) { int DoWrite; /* Get the segment */ SegDesc* S = CollAtUnchecked (&M->SegList, I); /* Keep the user happy */ Print (stdout, 1, " ATARI EXE Writing `%s'\n", GetString (S->Name)); /* Writes do only occur in the load area and not for BSS segments */ DoWrite = (S->Flags & SF_BSS) == 0 && /* No BSS segment */ S->Load == M && /* LOAD segment */ S->Seg->Dumped == 0; /* Not already written */ /* If this is the run memory area, we must apply run alignment. If ** this is not the run memory area but the load memory area (which ** means that both are different), we must apply load alignment. ** Beware: DoWrite may be true even if this is the run memory area, ** because it may be also the load memory area. */ if (S->Run == M) { /* Handle ALIGN and OFFSET/START */ if (S->Flags & SF_ALIGN) { /* Align the address */ unsigned long NewAddr = AlignAddr (Addr, S->RunAlignment); if (DoWrite || (M->Flags & MF_FILL) != 0) { XexStartSegment (D, Addr, NewAddr - Addr); WriteMult (D->F, M->FillVal, NewAddr - Addr); PrintNumVal ("SF_ALIGN", NewAddr - Addr); } Addr = NewAddr; } else if (S->Flags & (SF_OFFSET | SF_START)) { unsigned long NewAddr = S->Addr; if (S->Flags & SF_OFFSET) { /* It's an offset, not a fixed address, make an address */ NewAddr += M->Start; } if (DoWrite || (M->Flags & MF_FILL) != 0) { /* "overwrite" segments are not supported */ if (S->Flags & SF_OVERWRITE) { Error ("ATARI file format does not support overwrite for segment '%s'.", GetString (S->Name)); } else { XexStartSegment (D, Addr, NewAddr - Addr); WriteMult (D->F, M->FillVal, NewAddr-Addr); PrintNumVal ("SF_OFFSET", NewAddr - Addr); } } Addr = NewAddr; } } else if (S->Load == M) { /* Handle ALIGN_LOAD */ if (S->Flags & SF_ALIGN_LOAD) { /* Align the address */ unsigned long NewAddr = AlignAddr (Addr, S->LoadAlignment); if (DoWrite || (M->Flags & MF_FILL) != 0) { XexStartSegment (D, Addr, NewAddr - Addr); WriteMult (D->F, M->FillVal, NewAddr - Addr); PrintNumVal ("SF_ALIGN_LOAD", NewAddr - Addr); } Addr = NewAddr; } } /* Now write the segment to disk if it is not a BSS type segment and ** if the memory area is the load area. */ if (DoWrite) { /* Start a segment with only one byte, will fix later */ XexFakeSegment (D, Addr); unsigned long P = ftell (D->F); SegWrite (D->Filename, D->F, S->Seg, XexWriteExpr, D); unsigned long Size = ftell (D->F) - P; /* Fix segment size */ XexStartSegment (D, Addr, Size); PrintNumVal ("Wrote", Size); } else if (M->Flags & MF_FILL) { XexStartSegment (D, Addr, S->Seg->Size); WriteMult (D->F, S->Seg->FillVal, S->Seg->Size); PrintNumVal ("Filled", (unsigned long) S->Seg->Size); } /* If this was the load memory area, mark the segment as dumped */ if (S->Load == M) { S->Seg->Dumped = 1; } /* Calculate the new address */ Addr += S->Seg->Size; } /* If a fill was requested, fill the remaining space */ if ((M->Flags & MF_FILL) != 0 && M->FillLevel < M->Size) { unsigned long ToFill = M->Size - M->FillLevel; Print (stdout, 2, " Filling 0x%lx bytes with 0x%02x\n", ToFill, M->FillVal); XexStartSegment (D, Addr, ToFill); WriteMult (D->F, M->FillVal, ToFill); M->FillLevel = M->Size; } /* If the last segment is empty, remove */ if (D->HeadSize == 0 && D->HeadPos) { fseek (D->F, D->HeadPos, SEEK_SET); } return ftell (D->F) - StartPos; } static int XexUnresolved (unsigned Name attribute ((unused)), void* D) /* Called if an unresolved symbol is encountered */ { /* Unresolved symbols are an error in XEX format. Bump the counter ** and return zero telling the caller that the symbol is indeed ** unresolved. */ ((XexDesc*) D)->Undef++; return 0; } void XexWriteTarget (XexDesc* D, struct File* F) /* Write a XEX output file */ { unsigned I; /* Place the filename in the control structure */ D->Filename = GetString (F->Name); /* Check for unresolved symbols. The function XexUnresolved is called ** if we get an unresolved symbol. */ D->Undef = 0; /* Reset the counter */ CheckUnresolvedImports (XexUnresolved, D); if (D->Undef > 0) { /* We had unresolved symbols, cannot create output file */ Error ("%u unresolved external(s) found - cannot create output file", D->Undef); } /* Open the file */ D->F = fopen (D->Filename, "wb"); if (D->F == 0) { Error ("Cannot open `%s': %s", D->Filename, strerror (errno)); } /* Keep the user happy */ Print (stdout, 1, "Opened `%s'...\n", D->Filename); /* Dump all memory areas */ for (I = 0; I < CollCount (&F->MemoryAreas); ++I) { /* Get this entry */ MemoryArea* M = CollAtUnchecked (&F->MemoryAreas, I); /* See if we have an init address for this area */ XexInitAd* I = XexSearchInitMem (D, M); Print (stdout, 1, " ATARI EXE Dumping `%s'\n", GetString (M->Name)); if (XexWriteMem (D, M) && I) { Write16 (D->F, 0x2E2); Write16 (D->F, 0x2E3); Write16 (D->F, GetExportVal (I->InitAd->Exp)); } } /* Write RUNAD at file end */ if (D->RunAd) { Write16 (D->F, 0x2E0); Write16 (D->F, 0x2E1); Write16 (D->F, GetExportVal (D->RunAd->Exp)); } /* Close the file */ if (fclose (D->F) != 0) { Error ("Cannot write to `%s': %s", D->Filename, strerror (errno)); } /* Reset the file and filename */ D->F = 0; D->Filename = 0; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/ld65/xex.h����������������������������������������������������������������������������0000664�0000000�0000000�00000006472�13473601511�0014534�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* xex.h */ /* */ /* Module to handle the Atari EXE binary format */ /* */ /* */ /* */ /* (C) 2018 Daniel Serpell */ /* */ /* */ /* 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 XEX_H #define XEX_H #include "config.h" #include "exports.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Structure describing the format */ typedef struct XexDesc XexDesc; /*****************************************************************************/ /* Code */ /*****************************************************************************/ XexDesc* NewXexDesc (void); /* Create a new XEX format descriptor */ void FreeXexDesc (XexDesc* D); /* Free a XEX format descriptor */ void XexWriteTarget (XexDesc* D, File* F); /* Write a XEX output file */ void XexSetRunAd (XexDesc* D, Import *RunAd); /* Set the RUNAD export */ int XexAddInitAd (XexDesc* D, MemoryArea *InitMem, Import *InitAd); /* Sets and INITAD for the given memory area */ /* End of xex.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/od65.vcxproj��������������������������������������������������������������������������0000664�0000000�0000000�00000010716�13473601511�0015173�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> <ProjectConfiguration Include="Release|Win32"> <Configuration>Release</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> </ItemGroup> <PropertyGroup Label="Globals"> <ProjectGuid>{FF8576C2-1253-44FE-A51B-D9AE35F3CEAD}</ProjectGuid> <Keyword>Win32Proj</Keyword> <RootNamespace>od65</RootNamespace> <WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <UseDebugLibraries>true</UseDebugLibraries> <PlatformToolset>v141</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <UseDebugLibraries>false</UseDebugLibraries> <WholeProgramOptimization>true</WholeProgramOptimization> <PlatformToolset>v141</PlatformToolset> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <PropertyGroup Label="UserMacros" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <LinkIncremental>true</LinkIncremental> <OutDir>$(SolutionDir)..\bin\</OutDir> <IntDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</IntDir> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <OutDir>$(SolutionDir)..\bin\</OutDir> <IntDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</IntDir> </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ClCompile> <PrecompiledHeader> </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> <Link> <SubSystem>Console</SubSystem> <GenerateDebugInformation>true</GenerateDebugInformation> <AdditionalDependencies>$(IntDir)..\..\common\$(Configuration)\common.lib</AdditionalDependencies> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ClCompile> <WarningLevel>Level3</WarningLevel> <PrecompiledHeader> </PrecompiledHeader> <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> <Link> <SubSystem>Console</SubSystem> <GenerateDebugInformation>false</GenerateDebugInformation> <AdditionalDependencies>$(IntDir)..\..\common\$(Configuration)\common.lib</AdditionalDependencies> </Link> </ItemDefinitionGroup> <ItemGroup> <ClCompile Include="od65\dump.c" /> <ClCompile Include="od65\error.c" /> <ClCompile Include="od65\fileio.c" /> <ClCompile Include="od65\global.c" /> <ClCompile Include="od65\main.c" /> </ItemGroup> <ItemGroup> <ClInclude Include="od65\dump.h" /> <ClInclude Include="od65\error.h" /> <ClInclude Include="od65\fileio.h" /> <ClInclude Include="od65\global.h" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> </Project>��������������������������������������������������cc65-2.18/src/od65/���������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0013551�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/od65/dump.c���������������������������������������������������������������������������0000664�0000000�0000000�00000066167�13473601511�0014702�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* dump.c */ /* */ /* Dump subroutines for the od65 object file dump utility */ /* */ /* */ /* */ /* (C) 2002-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> #include <time.h> /* common */ #include "addrsize.h" #include "cddefs.h" #include "coll.h" #include "exprdefs.h" #include "filepos.h" #include "lidefs.h" #include "objdefs.h" #include "optdefs.h" #include "scopedefs.h" #include "symdefs.h" #include "xmalloc.h" /* od65 */ #include "error.h" #include "fileio.h" #include "dump.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void DestroyStrPool (Collection* C) /* Free all strings in the given pool plus the item pointers. Note: The ** collection may not be reused later. */ { unsigned I; for (I = 0; I < CollCount (C); ++I) { xfree (CollAtUnchecked (C, I)); } DoneCollection (C); } static const char* GetString (const Collection* C, unsigned Index) /* Get a string from a collection. In fact, this function calls CollConstAt, ** but will print a somewhat more readable error message if the index is out ** of bounds. */ { if (Index >= CollCount (C)) { Error ("Invalid string index (%u) - file corrupt!", Index); } return CollConstAt (C, Index); } static void DumpObjHeaderSection (const char* Name, unsigned long Offset, unsigned long Size) /* Dump a header section */ { printf (" %s:\n", Name); printf (" Offset:%24lu\n", Offset); printf (" Size: %24lu\n", Size); } static char* TimeToStr (unsigned long Time) /* Convert the time into a string and return it */ { /* Get the time and convert to string */ time_t T = (time_t) Time; char* S = asctime (localtime (&T)); /* Remove the trailing newline */ unsigned Len = strlen (S); if (Len > 0 && S[Len-1] == '\n') { S[Len-1 ] = '\0'; } /* Return the time string */ return S; } static void SkipLineInfoList (FILE* F) /* Skip a line info list from the given file */ { /* Count preceeds the list */ unsigned long Count = ReadVar (F); /* Skip indices */ while (Count--) { (void) ReadVar (F); } } static void SkipSpanList (FILE* F) /* Skip a span list from the given file */ { /* Count preceeds the list */ unsigned long Count = ReadVar (F); /* Skip indices */ while (Count--) { (void) ReadVar (F); } } static void SkipExpr (FILE* F) /* Skip an expression from the given file */ { /* Read the node tag and handle NULL nodes */ unsigned char Op = Read8 (F); if (Op == EXPR_NULL) { return; } /* Check the tag and handle the different expression types */ if (EXPR_IS_LEAF (Op)) { switch (Op) { case EXPR_LITERAL: (void) Read32Signed (F); break; case EXPR_SYMBOL: /* Read the import number */ (void) ReadVar (F); break; case EXPR_SECTION: case EXPR_BANK: /* Read the segment number */ (void) ReadVar (F); break; default: Error ("Invalid expression op: %02X", Op); } } else { /* Not a leaf node */ SkipExpr (F); SkipExpr (F); } } static const char* GetExportFlags (unsigned Flags, const unsigned char* ConDes) /* Get the export flags as a (static) string */ { /* Static buffer */ static char TypeDesc[256]; static char* T; unsigned Count; unsigned I; /* Symbol type */ TypeDesc[0] = '\0'; switch (Flags & SYM_MASK_TYPE) { case SYM_STD: strcat (TypeDesc, "SYM_STD"); break; case SYM_CHEAP_LOCAL: strcat (TypeDesc, "SYM_CHEAP_LOCAL"); break; } /* Symbol usage */ switch (Flags & SYM_MASK_LABEL) { case SYM_EQUATE: strcat (TypeDesc, ",SYM_EQUATE"); break; case SYM_LABEL: strcat (TypeDesc, ",SYM_LABEL"); break; } /* Type of expression */ switch (Flags & SYM_MASK_VAL) { case SYM_CONST: strcat (TypeDesc, ",SYM_CONST"); break; case SYM_EXPR: strcat (TypeDesc, ",SYM_EXPR"); break; } /* Size available? */ if (SYM_HAS_SIZE (Flags)) { strcat (TypeDesc, ",SYM_SIZE"); } /* Constructor/destructor declarations */ T = TypeDesc + strlen (TypeDesc); Count = SYM_GET_CONDES_COUNT (Flags); if (Count > 0 && ConDes) { T += sprintf (T, ",SYM_CONDES="); for (I = 0; I < Count; ++I) { unsigned Type = CD_GET_TYPE (ConDes[I]); unsigned Prio = CD_GET_PRIO (ConDes[I]); if (I > 0) { *T++ = ','; } T += sprintf (T, "[%u,%u]", Type, Prio); } } /* Return the result */ return TypeDesc; } static const char* GetScopeType (unsigned Type) /* Return the name of a scope type */ { switch (Type) { case SCOPE_GLOBAL: return "Global scope"; case SCOPE_FILE: return "File scope"; case SCOPE_SCOPE: return ".SCOPE or .PROC"; case SCOPE_STRUCT: return ".STRUCT"; case SCOPE_ENUM: return ".ENUM"; case SCOPE_UNDEF: return "Undefined"; default: return "Unknown scope type"; } } void DumpObjHeader (FILE* F, unsigned long Offset) /* Dump the header of the given object file */ { ObjHeader H; /* Seek to the header position */ FileSetPos (F, Offset); /* Read the header */ ReadObjHeader (F, &H); /* Now dump the information */ /* Output a header */ printf (" Header:\n"); /* Magic */ printf (" Magic:%17s0x%08lX\n", "", H.Magic); /* Version */ printf (" Version:%25u\n", H.Version); /* Flags */ printf (" Flags:%21s0x%04X (", "", H.Flags); if (H.Flags & OBJ_FLAGS_DBGINFO) { printf ("OBJ_FLAGS_DBGINFO"); } printf (")\n"); /* Options */ DumpObjHeaderSection ("Options", H.OptionOffs, H.OptionSize); /* Files */ DumpObjHeaderSection ("Files", H.FileOffs, H.FileSize); /* Segments */ DumpObjHeaderSection ("Segments", H.SegOffs, H.SegSize); /* Imports */ DumpObjHeaderSection ("Imports", H.ImportOffs, H.ImportSize); /* Exports */ DumpObjHeaderSection ("Exports", H.ExportOffs, H.ExportSize); /* Debug symbols */ DumpObjHeaderSection ("Debug symbols", H.DbgSymOffs, H.DbgSymSize); /* Line infos */ DumpObjHeaderSection ("Line infos", H.LineInfoOffs, H.LineInfoSize); /* String pool */ DumpObjHeaderSection ("String pool", H.StrPoolOffs, H.StrPoolSize); /* Assertions */ DumpObjHeaderSection ("Assertions", H.AssertOffs, H.AssertSize); /* Scopes */ DumpObjHeaderSection ("Scopes", H.ScopeOffs, H.ScopeSize); } void DumpObjOptions (FILE* F, unsigned long Offset) /* Dump the file options */ { ObjHeader H; Collection StrPool = AUTO_COLLECTION_INITIALIZER; unsigned Count; unsigned I; /* Seek to the header position and read the header */ FileSetPos (F, Offset); ReadObjHeader (F, &H); /* Seek to the start of the string pool and read it */ FileSetPos (F, Offset + H.StrPoolOffs); ReadStrPool (F, &StrPool); /* Seek to the start of the options */ FileSetPos (F, Offset + H.OptionOffs); /* Output a header */ printf (" Options:\n"); /* Read the number of options and print it */ Count = ReadVar (F); printf (" Count:%27u\n", Count); /* Read and print all options */ for (I = 0; I < Count; ++I) { const char* ArgStr; unsigned ArgLen; /* Read the type of the option and the value */ unsigned char Type = Read8 (F); unsigned long Val = ReadVar (F); /* Get the type of the argument */ unsigned char ArgType = Type & OPT_ARGMASK; /* Determine which option follows */ const char* TypeDesc; switch (Type) { case OPT_COMMENT: TypeDesc = "OPT_COMMENT"; break; case OPT_AUTHOR: TypeDesc = "OPT_AUTHOR"; break; case OPT_TRANSLATOR:TypeDesc = "OPT_TRANSLATOR"; break; case OPT_COMPILER: TypeDesc = "OPT_COMPILER"; break; case OPT_OS: TypeDesc = "OPT_OS"; break; case OPT_DATETIME: TypeDesc = "OPT_DATETIME"; break; default: TypeDesc = "OPT_UNKNOWN"; break; } /* Print the header */ printf (" Index:%27u\n", I); /* Print the data */ printf (" Type:%22s0x%02X (%s)\n", "", Type, TypeDesc); switch (ArgType) { case OPT_ARGSTR: ArgStr = GetString (&StrPool, Val); ArgLen = strlen (ArgStr); printf (" Data:%*s\"%s\"\n", (int)(24-ArgLen), "", ArgStr); break; case OPT_ARGNUM: printf (" Data:%26lu", Val); if (Type == OPT_DATETIME) { /* Print the time as a string */ printf (" (%s)", TimeToStr (Val)); } printf ("\n"); break; default: /* Unknown argument type. This means that we cannot determine ** the option length, so we cannot proceed. */ Error ("Unknown option type: 0x%02X", Type); break; } } /* Destroy the string pool */ DestroyStrPool (&StrPool); } void DumpObjFiles (FILE* F, unsigned long Offset) /* Dump the source files */ { ObjHeader H; Collection StrPool = AUTO_COLLECTION_INITIALIZER; unsigned Count; unsigned I; /* Seek to the header position and read the header */ FileSetPos (F, Offset); ReadObjHeader (F, &H); /* Seek to the start of the string pool and read it */ FileSetPos (F, Offset + H.StrPoolOffs); ReadStrPool (F, &StrPool); /* Seek to the start of the source files */ FileSetPos (F, Offset + H.FileOffs); /* Output a header */ printf (" Files:\n"); /* Read the number of files and print it */ Count = ReadVar (F); printf (" Count:%27u\n", Count); /* Read and print all files */ for (I = 0; I < Count; ++I) { /* Read the data for one file */ const char* Name = GetString (&StrPool, ReadVar (F)); unsigned long MTime = Read32 (F); unsigned long Size = ReadVar (F); unsigned Len = strlen (Name); /* Print the header */ printf (" Index:%27u\n", I); /* Print the data */ printf (" Name:%*s\"%s\"\n", (int)(24-Len), "", Name); printf (" Size:%26lu\n", Size); printf (" Modification time:%13lu (%s)\n", MTime, TimeToStr (MTime)); } /* Destroy the string pool */ DestroyStrPool (&StrPool); } void DumpObjSegments (FILE* F, unsigned long Offset) /* Dump the segments in the object file */ { ObjHeader H; Collection StrPool = AUTO_COLLECTION_INITIALIZER; unsigned Count; unsigned I; /* Seek to the header position and read the header */ FileSetPos (F, Offset); ReadObjHeader (F, &H); /* Seek to the start of the string pool and read it */ FileSetPos (F, Offset + H.StrPoolOffs); ReadStrPool (F, &StrPool); /* Seek to the start of the segments */ FileSetPos (F, Offset + H.SegOffs); /* Output a header */ printf (" Segments:\n"); /* Read the number of segments and print it */ Count = ReadVar (F); printf (" Count:%27u\n", Count); /* Read and print all segments */ for (I = 0; I < Count; ++I) { /* Read the data for one segments */ unsigned long DataSize = Read32 (F); unsigned long NextSeg = ftell (F) + DataSize; const char* Name = GetString (&StrPool, ReadVar (F)); unsigned Len = strlen (Name); unsigned Flags = ReadVar (F); unsigned long Size = ReadVar (F); unsigned long Align = ReadVar (F); unsigned char AddrSize = Read8 (F); unsigned long FragCount = ReadVar (F); /* Print the header */ printf (" Index:%27u\n", I); /* Print the data */ printf (" Name:%*s\"%s\"\n", (int)(24-Len), "", Name); printf (" Flags:%25u\n", Flags); printf (" Size:%26lu\n", Size); printf (" Alignment:%21lu\n", Align); printf (" Address size:%14s0x%02X (%s)\n", "", AddrSize, AddrSizeToStr (AddrSize)); printf (" Fragment count:%16lu\n", FragCount); /* Seek to the end of the segment data (start of next) */ FileSetPos (F, NextSeg); } /* Destroy the string pool */ DestroyStrPool (&StrPool); } void DumpObjImports (FILE* F, unsigned long Offset) /* Dump the imports in the object file */ { ObjHeader H; Collection StrPool = AUTO_COLLECTION_INITIALIZER; unsigned Count; unsigned I; /* Seek to the header position and read the header */ FileSetPos (F, Offset); ReadObjHeader (F, &H); /* Seek to the start of the string pool and read it */ FileSetPos (F, Offset + H.StrPoolOffs); ReadStrPool (F, &StrPool); /* Seek to the start of the imports */ FileSetPos (F, Offset + H.ImportOffs); /* Output a header */ printf (" Imports:\n"); /* Read the number of imports and print it */ Count = ReadVar (F); printf (" Count:%27u\n", Count); /* Read and print all imports */ for (I = 0; I < Count; ++I) { /* Read the data for one import */ unsigned char AddrSize = Read8 (F); const char* Name = GetString (&StrPool, ReadVar (F)); unsigned Len = strlen (Name); /* Skip both line info lists */ SkipLineInfoList (F); SkipLineInfoList (F); /* Print the header */ printf (" Index:%27u\n", I); /* Print the data */ printf (" Address size:%14s0x%02X (%s)\n", "", AddrSize, AddrSizeToStr (AddrSize)); printf (" Name:%*s\"%s\"\n", (int)(24-Len), "", Name); } /* Destroy the string pool */ DestroyStrPool (&StrPool); } void DumpObjExports (FILE* F, unsigned long Offset) /* Dump the exports in the object file */ { ObjHeader H; Collection StrPool = AUTO_COLLECTION_INITIALIZER; unsigned Count; unsigned I; /* Seek to the header position and read the header */ FileSetPos (F, Offset); ReadObjHeader (F, &H); /* Seek to the start of the string pool and read it */ FileSetPos (F, Offset + H.StrPoolOffs); ReadStrPool (F, &StrPool); /* Seek to the start of the exports */ FileSetPos (F, Offset + H.ExportOffs); /* Output a header */ printf (" Exports:\n"); /* Read the number of exports and print it */ Count = ReadVar (F); printf (" Count:%27u\n", Count); /* Read and print all exports */ for (I = 0; I < Count; ++I) { unsigned long Value = 0; unsigned long Size = 0; unsigned char ConDes[CD_TYPE_COUNT]; const char* Name; unsigned Len; /* Read the data for one export */ unsigned Type = ReadVar (F); unsigned char AddrSize = Read8 (F); ReadData (F, ConDes, SYM_GET_CONDES_COUNT (Type)); Name = GetString (&StrPool, ReadVar (F)); Len = strlen (Name); if (SYM_IS_CONST (Type)) { Value = Read32 (F); } else { SkipExpr (F); } if (SYM_HAS_SIZE (Type)) { Size = ReadVar (F); } /* Skip both line infos lists */ SkipLineInfoList (F); SkipLineInfoList (F); /* Print the header */ printf (" Index:%27u\n", I); /* Print the data */ printf (" Type:%22s0x%02X (%s)\n", "", Type, GetExportFlags (Type, ConDes)); printf (" Address size:%14s0x%02X (%s)\n", "", AddrSize, AddrSizeToStr (AddrSize)); printf (" Name:%*s\"%s\"\n", (int)(24-Len), "", Name); if (SYM_IS_CONST (Type)) { printf (" Value:%15s0x%08lX (%lu)\n", "", Value, Value); } if (SYM_HAS_SIZE (Type)) { printf (" Size:%16s0x%04lX (%lu)\n", "", Size, Size); } } /* Destroy the string pool */ DestroyStrPool (&StrPool); } void DumpObjDbgSyms (FILE* F, unsigned long Offset) /* Dump the debug symbols from an object file */ { ObjHeader H; Collection StrPool = AUTO_COLLECTION_INITIALIZER; unsigned Count; unsigned I; /* Seek to the header position and read the header */ FileSetPos (F, Offset); ReadObjHeader (F, &H); /* Seek to the start of the string pool and read it */ FileSetPos (F, Offset + H.StrPoolOffs); ReadStrPool (F, &StrPool); /* Seek to the start of the debug syms */ FileSetPos (F, Offset + H.DbgSymOffs); /* Output a header */ printf (" Debug symbols:\n"); /* Check if the object file was compiled with debug info */ if ((H.Flags & OBJ_FLAGS_DBGINFO) == 0) { /* Print that there no debug symbols and bail out */ printf (" Count:%27u\n", 0); return; } /* Read the number of exports and print it */ Count = ReadVar (F); printf (" Count:%27u\n", Count); /* Read and print all debug symbols */ for (I = 0; I < Count; ++I) { unsigned long Value = 0; unsigned long Size = 0; unsigned ImportId = 0; unsigned ExportId = 0; /* Read the data for one symbol */ unsigned Type = ReadVar (F); unsigned char AddrSize = Read8 (F); unsigned long Owner = ReadVar (F); const char* Name = GetString (&StrPool, ReadVar (F)); unsigned Len = strlen (Name); if (SYM_IS_CONST (Type)) { Value = Read32 (F); } else { SkipExpr (F); } if (SYM_HAS_SIZE (Type)) { Size = ReadVar (F); } if (SYM_IS_IMPORT (Type)) { ImportId = ReadVar (F); } if (SYM_IS_EXPORT (Type)) { ExportId = ReadVar (F); } /* Skip both line info lists */ SkipLineInfoList (F); SkipLineInfoList (F); /* Print the header */ printf (" Index:%27u\n", I); /* Print the data */ printf (" Type:%22s0x%02X (%s)\n", "", Type, GetExportFlags (Type, 0)); printf (" Address size:%14s0x%02X (%s)\n", "", AddrSize, AddrSizeToStr (AddrSize)); printf (" Owner:%25lu\n", Owner); printf (" Name:%*s\"%s\"\n", (int)(24-Len), "", Name); if (SYM_IS_CONST (Type)) { printf (" Value:%15s0x%08lX (%lu)\n", "", Value, Value); } if (SYM_HAS_SIZE (Type)) { printf (" Size:%20s0x%04lX (%lu)\n", "", Size, Size); } if (SYM_IS_IMPORT (Type)) { printf (" Import:%24u\n", ImportId); } if (SYM_IS_EXPORT (Type)) { printf (" Export:%24u\n", ExportId); } } /* Destroy the string pool */ DestroyStrPool (&StrPool); } void DumpObjLineInfo (FILE* F, unsigned long Offset) /* Dump the line info from an object file */ { ObjHeader H; Collection StrPool = AUTO_COLLECTION_INITIALIZER; unsigned Count; unsigned I; /* Seek to the header position and read the header */ FileSetPos (F, Offset); ReadObjHeader (F, &H); /* Seek to the start of the string pool and read it */ FileSetPos (F, Offset + H.StrPoolOffs); ReadStrPool (F, &StrPool); /* Seek to the start of line infos */ FileSetPos (F, Offset + H.LineInfoOffs); /* Output a header */ printf (" Line info:\n"); /* Check if the object file was compiled with debug info */ if ((H.Flags & OBJ_FLAGS_DBGINFO) == 0) { /* Print that there no line infos and bail out */ printf (" Count:%27u\n", 0); return; } /* Read the number of line infos and print it */ Count = ReadVar (F); printf (" Count:%27u\n", Count); /* Read and print all line infos */ for (I = 0; I < Count; ++I) { FilePos Pos; unsigned Type; /* File position of line info */ ReadFilePos (F, &Pos); /* Type of line info */ Type = ReadVar (F); /* Skip the spans */ SkipSpanList (F); /* Print the header */ printf (" Index:%27u\n", I); /* Print the data */ printf (" Type:%26u\n", LI_GET_TYPE (Type)); printf (" Count:%25u\n", LI_GET_COUNT (Type)); printf (" Line:%26u\n", Pos.Line); printf (" Col:%27u\n", Pos.Col); printf (" Name:%26u\n", Pos.Name); } /* Destroy the string pool */ DestroyStrPool (&StrPool); } void DumpObjScopes (FILE* F, unsigned long Offset) /* Dump the scopes from an object file */ { ObjHeader H; Collection StrPool = AUTO_COLLECTION_INITIALIZER; unsigned Count; unsigned I; /* Seek to the header position and read the header */ FileSetPos (F, Offset); ReadObjHeader (F, &H); /* Seek to the start of the string pool and read it */ FileSetPos (F, Offset + H.StrPoolOffs); ReadStrPool (F, &StrPool); /* Seek to the start of scopes */ FileSetPos (F, Offset + H.ScopeOffs); /* Output a header */ printf (" Scopes:\n"); /* Check if the object file was compiled with debug info */ if ((H.Flags & OBJ_FLAGS_DBGINFO) == 0) { /* Print that there no scopes and bail out */ printf (" Count:%27u\n", 0); return; } /* Read the number of scopes and print it */ Count = ReadVar (F); printf (" Count:%27u\n", Count); /* Read and print all scopes */ for (I = 0; I < Count; ++I) { const char* Name; unsigned Len; /* Read the data */ unsigned ParentId = ReadVar (F); unsigned LexicalLevel = ReadVar (F); unsigned Flags = ReadVar (F); const char* ScopeType = GetScopeType (ReadVar (F)); /* Print the header */ printf (" Index:%27u\n", I); /* Print the data */ printf (" Parent id:%21u\n", ParentId); printf (" Lexical level:%17u\n", LexicalLevel); printf (" Flags:%21s0x%02X\n", "", Flags); printf (" Type:%26s\n", ScopeType); /* Resolve and print the name */ Name = GetString (&StrPool, ReadVar (F)); Len = strlen (Name); printf (" Name:%*s\"%s\"\n", (int)(24-Len), "", Name); /* Size */ if (SCOPE_HAS_SIZE (Flags)) { unsigned long Size = ReadVar (F); printf (" Size:%20s0x%04lX (%lu)\n", "", Size, Size); } /* Label */ if (SCOPE_HAS_LABEL (Flags)) { unsigned LabelId = ReadVar (F); printf (" Label id:%22u\n", LabelId); } /* Skip the spans */ SkipSpanList (F); } /* Destroy the string pool */ DestroyStrPool (&StrPool); } void DumpObjSegSize (FILE* F, unsigned long Offset) /* Dump the sizes of the segment in the object file */ { ObjHeader H; Collection StrPool = AUTO_COLLECTION_INITIALIZER; unsigned Count; /* Seek to the header position and read the header */ FileSetPos (F, Offset); ReadObjHeader (F, &H); /* Seek to the start of the string pool and read it */ FileSetPos (F, Offset + H.StrPoolOffs); ReadStrPool (F, &StrPool); /* Seek to the start of the segments */ FileSetPos (F, Offset + H.SegOffs); /* Output a header */ printf (" Segment sizes:\n"); /* Read the number of segments */ Count = ReadVar (F); /* Read and print the sizes of all segments */ while (Count--) { unsigned long Size; /* Read the data for one segment */ unsigned long DataSize = Read32 (F); unsigned long NextSeg = ftell (F) + DataSize; const char* Name = GetString (&StrPool, ReadVar (F)); unsigned Len = strlen (Name); /* Skip segment flags, read size */ (void) ReadVar (F); Size = ReadVar (F); /* Skip alignment, type and fragment count */ (void) ReadVar (F); (void) Read8 (F); (void) ReadVar (F); /* Print the size for this segment */ printf (" %s:%*s%6lu\n", Name, (int)(24-Len), "", Size); /* Seek to the end of the segment data (start of next) */ FileSetPos (F, NextSeg); } /* Destroy the string pool */ DestroyStrPool (&StrPool); } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/od65/dump.h���������������������������������������������������������������������������0000664�0000000�0000000�00000007413�13473601511�0014674�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* dump.h */ /* */ /* Dump subroutines for the od65 object file dump utility */ /* */ /* */ /* */ /* (C) 2000-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #ifndef DUMP_H #define DUMP_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ void DumpObjHeader (FILE* F, unsigned long Offset); /* Dump the header of the given object file */ void DumpObjOptions (FILE* F, unsigned long Offset); /* Dump the file options */ void DumpObjFiles (FILE* F, unsigned long Offset); /* Dump the source files */ void DumpObjSegments (FILE* F, unsigned long Offset); /* Dump the segments in the object file */ void DumpObjImports (FILE* F, unsigned long Offset); /* Dump the imports in the object file */ void DumpObjExports (FILE* F, unsigned long Offset); /* Dump the exports in the object file */ void DumpObjDbgSyms (FILE* F, unsigned long Offset); /* Dump the debug symbols from an object file */ void DumpObjLineInfo (FILE* F, unsigned long Offset); /* Dump the line infos from an object file */ void DumpObjScopes (FILE* F, unsigned long Offset); /* Dump the scopes from an object file */ void DumpObjSegSize (FILE* F, unsigned long Offset); /* Dump the sizes of the segment in the object file */ /* End of dump.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/od65/error.c��������������������������������������������������������������������������0000664�0000000�0000000�00000007107�13473601511�0015053�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* error.c */ /* */ /* Error handling for the od65 object file dump utility */ /* */ /* */ /* */ /* (C) 1998-2000 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include "error.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Warning (const char* Format, ...) /* Print a warning message */ { va_list ap; va_start (ap, Format); fprintf (stderr, "Warning: "); vfprintf (stderr, Format, ap); putc ('\n', stderr); va_end (ap); } void Error (const char* Format, ...) /* Print an error message and die */ { va_list ap; va_start (ap, Format); fprintf (stderr, "Error: "); vfprintf (stderr, Format, ap); putc ('\n', stderr); va_end (ap); exit (EXIT_FAILURE); } void Internal (const char* Format, ...) /* Print an internal error message and die */ { va_list ap; va_start (ap, Format); fprintf (stderr, "Internal error: "); vfprintf (stderr, Format, ap); putc ('\n', stderr); va_end (ap); exit (EXIT_FAILURE); } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/od65/error.h��������������������������������������������������������������������������0000664�0000000�0000000�00000006273�13473601511�0015063�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* global.h */ /* */ /* Error handling for the od65 object file dump utility */ /* */ /* */ /* */ /* (C) 1998-2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef ERROR_H #define ERROR_H /* common */ #include "attrib.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Warning (const char* Format, ...) attribute((format(printf,1,2))); /* Print a warning message */ void Error (const char* Format, ...) attribute((noreturn, format(printf,1,2))); /* Print an error message and die */ void Internal (const char* Format, ...) attribute((noreturn, format(printf,1,2))); /* Print an internal error message and die */ /* End of error.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/od65/fileio.c�������������������������������������������������������������������������0000664�0000000�0000000�00000015700�13473601511�0015167�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* fileio.c */ /* */ /* File I/O for the od65 object file dump utility */ /* */ /* */ /* */ /* (C) 1998-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> #include <errno.h> /* common */ #include "xmalloc.h" /* od65 */ #include "error.h" #include "fileio.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void FileSetPos (FILE* F, unsigned long Pos) /* Seek to the given absolute position, fail on errors */ { if (fseek (F, Pos, SEEK_SET) != 0) { Error ("Cannot seek: %s", strerror (errno)); } } unsigned long FileGetPos (FILE* F) /* Return the current file position, fail on errors */ { long Pos = ftell (F); if (Pos < 0) { Error ("Error in ftell: %s", strerror (errno)); } return Pos; } unsigned Read8 (FILE* F) /* Read an 8 bit value from the file */ { int C = getc (F); if (C == EOF) { Error ("Read error (file corrupt?)"); } return C; } unsigned Read16 (FILE* F) /* Read a 16 bit value from the file */ { unsigned Lo = Read8 (F); unsigned Hi = Read8 (F); return (Hi << 8) | Lo; } unsigned long Read24 (FILE* F) /* Read a 24 bit value from the file */ { unsigned long Lo = Read16 (F); unsigned long Hi = Read8 (F); return (Hi << 16) | Lo; } unsigned long Read32 (FILE* F) /* Read a 32 bit value from the file */ { unsigned long Lo = Read16 (F); unsigned long Hi = Read16 (F); return (Hi << 16) | Lo; } long Read32Signed (FILE* F) /* Read a 32 bit value from the file. Sign extend the value. */ { /* Read a 32 bit value */ unsigned long V = Read32 (F); /* Sign extend the value */ if (V & 0x80000000UL) { /* Signed value */ V |= ~0xFFFFFFFFUL; } /* Return it as a long */ return (long) V; } unsigned long ReadVar (FILE* F) /* Read a variable size value from the file */ { /* The value was written to the file in 7 bit chunks LSB first. If there ** are more bytes, bit 8 is set, otherwise it is clear. */ unsigned char C; unsigned long V = 0; unsigned Shift = 0; do { /* Read one byte */ C = Read8 (F); /* Encode it into the target value */ V |= ((unsigned long)(C & 0x7F)) << Shift; /* Next value */ Shift += 7; } while (C & 0x80); /* Return the value read */ return V; } char* ReadStr (FILE* F) /* Read a string from the file into a malloced area */ { /* Read the length */ unsigned Len = ReadVar (F); /* Allocate memory */ char* Str = xmalloc (Len + 1); /* Read the string itself */ ReadData (F, Str, Len); /* Terminate the string and return it */ Str [Len] = '\0'; return Str; } FilePos* ReadFilePos (FILE* F, FilePos* Pos) /* Read a file position from the file */ { /* Read the data fields */ Pos->Line = ReadVar (F); Pos->Col = ReadVar (F); Pos->Name = ReadVar (F); return Pos; } void* ReadData (FILE* F, void* Data, unsigned Size) /* Read data from the file */ { /* Accept zero sized reads */ if (Size > 0) { if (fread (Data, 1, Size, F) != Size) { Error ("Read error (file corrupt?)"); } } return Data; } void ReadObjHeader (FILE* F, ObjHeader* H) /* Read an object file header from the file */ { /* Read all fields */ H->Magic = Read32 (F); H->Version = Read16 (F); H->Flags = Read16 (F); H->OptionOffs = Read32 (F); H->OptionSize = Read32 (F); H->FileOffs = Read32 (F); H->FileSize = Read32 (F); H->SegOffs = Read32 (F); H->SegSize = Read32 (F); H->ImportOffs = Read32 (F); H->ImportSize = Read32 (F); H->ExportOffs = Read32 (F); H->ExportSize = Read32 (F); H->DbgSymOffs = Read32 (F); H->DbgSymSize = Read32 (F); H->LineInfoOffs = Read32 (F); H->LineInfoSize = Read32 (F); H->StrPoolOffs = Read32 (F); H->StrPoolSize = Read32 (F); H->AssertOffs = Read32 (F); H->AssertSize = Read32 (F); H->ScopeOffs = Read32 (F); H->ScopeSize = Read32 (F); H->SpanOffs = Read32 (F); H->SpanSize = Read32 (F); } void ReadStrPool (FILE* F, Collection* C) /* Read a string pool from the current position into C. */ { /* The number of strings is the first item */ unsigned long Count = ReadVar (F); /* Read all the strings into C */ while (Count--) { CollAppend (C, ReadStr (F)); } } ����������������������������������������������������������������cc65-2.18/src/od65/fileio.h�������������������������������������������������������������������������0000664�0000000�0000000�00000007755�13473601511�0015207�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* fileio.h */ /* */ /* File I/O for the od65 object file dump utility */ /* */ /* */ /* */ /* (C) 1998-2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef FILEIO_H #define FILEIO_H #include <stdio.h> /* common */ #include "coll.h" #include "filepos.h" #include "objdefs.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void FileSetPos (FILE* F, unsigned long Pos); /* Seek to the given absolute position, fail on errors */ unsigned long FileGetPos (FILE* F); /* Return the current file position, fail on errors */ unsigned Read8 (FILE* F); /* Read an 8 bit value from the file */ unsigned Read16 (FILE* F); /* Read a 16 bit value from the file */ unsigned long Read24 (FILE* F); /* Read a 24 bit value from the file */ unsigned long Read32 (FILE* F); /* Read a 32 bit value from the file */ long Read32Signed (FILE* F); /* Read a 32 bit value from the file. Sign extend the value. */ unsigned long ReadVar (FILE* F); /* Read a variable size value from the file */ char* ReadStr (FILE* F); /* Read a string from the file into a malloced area */ FilePos* ReadFilePos (FILE* F, FilePos* Pos); /* Read a file position from the file */ void* ReadData (FILE* F, void* Data, unsigned Size); /* Read data from the file */ void ReadObjHeader (FILE* F, ObjHeader* Header); /* Read an object file header from the file */ void ReadStrPool (FILE* F, Collection* C); /* Read a string pool from the current position into C. */ /* End of fileio.h */ #endif �������������������cc65-2.18/src/od65/global.c�������������������������������������������������������������������������0000664�0000000�0000000�00000005513�13473601511�0015161�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* global.c */ /* */ /* Global variables for the od65 object file dump utility */ /* */ /* */ /* */ /* (C) 2000 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ /* EMail: uz@musoftware.de */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include "global.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ unsigned What = 0; /* What should get dumped? */ �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/od65/global.h�������������������������������������������������������������������������0000664�0000000�0000000�00000007104�13473601511�0015164�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* global.h */ /* */ /* Global variables for the od65 object file dump utility */ /* */ /* */ /* */ /* (C) 2000-2011, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef GLOBAL_H #define GLOBAL_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ #define D_HEADER 0x0001U /* Dump the header */ #define D_OPTIONS 0x0002U /* Dump the options */ #define D_FILES 0x0004U /* Dump source file info */ #define D_SEGMENTS 0x0008U /* Dump segment info */ #define D_IMPORTS 0x0010U /* Dump imported symbols */ #define D_EXPORTS 0x0020U /* Dump exported symbols */ #define D_DBGSYMS 0x0040U /* Dump debug symbols */ #define D_LINEINFO 0x0080U /* Dump line infos */ #define D_SCOPES 0x0100U /* Dump scopes */ #define D_SEGSIZE 0x0200U /* Dump segment sizes */ #define D_ALL 0xFFFFU /* Dump anything */ extern unsigned What; /* What should get dumped? */ /* End of global.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/od65/main.c���������������������������������������������������������������������������0000664�0000000�0000000�00000025355�13473601511�0014653�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* main.c */ /* */ /* Main program of the od65 object file dump utility */ /* */ /* */ /* */ /* (C) 2000-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> /* common */ #include "cmdline.h" #include "objdefs.h" #include "version.h" /* od65 */ #include "dump.h" #include "error.h" #include "fileio.h" #include "global.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ static unsigned FilesProcessed = 0; /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void Usage (void) /* Print usage information and exit */ { printf ("Usage: %s [options] file [options] [file]\n" "Short options:\n" " -h\t\t\tHelp (this text)\n" " -H\t\t\tDump the object file header\n" " -S\t\t\tDump segments sizes\n" " -V\t\t\tPrint the version number and exit\n" "\n" "Long options:\n" " --dump-all\t\tDump all object file information\n" " --dump-dbgsyms\tDump debug symbols\n" " --dump-exports\tDump exported symbols\n" " --dump-files\t\tDump the source files\n" " --dump-header\t\tDump the object file header\n" " --dump-imports\tDump imported symbols\n" " --dump-lineinfo\tDump line information\n" " --dump-options\tDump object file options\n" " --dump-segments\tDump the segments in the file\n" " --dump-segsize\tDump segments sizes\n" " --help\t\tHelp (this text)\n" " --version\t\tPrint the version number and exit\n", ProgName); } static void OptDumpAll (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Dump all object file information */ { What |= D_ALL; } static void OptDumpDbgSyms (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Dump debug symbols contained in the object file */ { What |= D_DBGSYMS; } static void OptDumpExports (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Dump the exported symbols */ { What |= D_EXPORTS; } static void OptDumpFiles (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Dump the source files */ { What |= D_FILES; } static void OptDumpHeader (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Dump the object file header */ { What |= D_HEADER; } static void OptDumpImports (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Dump the imported symbols */ { What |= D_IMPORTS; } static void OptDumpLineInfo (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Dump the line infos */ { What |= D_LINEINFO; } static void OptDumpOptions (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Dump the object file options */ { What |= D_OPTIONS; } static void OptDumpScopes (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Dump the scopes in the object file */ { What |= D_SCOPES; } static void OptDumpSegments (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Dump the segments in the object file */ { What |= D_SEGMENTS; } static void OptDumpSegSize (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Dump the segments in the object file */ { What |= D_SEGSIZE; } static void OptHelp (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Print usage information and exit */ { Usage (); exit (EXIT_SUCCESS); } static void OptVersion (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Print the assembler version */ { fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ()); exit(EXIT_SUCCESS); } static void DumpFile (const char* Name) /* Dump information from the named file */ { unsigned long Magic; /* Try to open the file */ FILE* F = fopen (Name, "rb"); if (F == 0) { Error ("Cannot open '%s': %s", Name, strerror (errno)); } /* Read the magic word */ Magic = Read32 (F); /* Do we know this type of file? */ if (Magic != OBJ_MAGIC) { /* Unknown format */ printf ("%s: (no xo65 object file)\n", Name); } else if (What == 0) { /* Special handling if no info was requested */ printf ("%s: (no information requested)\n", Name); } else { /* Print the filename */ printf ("%s:\n", Name); /* Check what to dump */ if (What & D_HEADER) { DumpObjHeader (F, 0); } if (What & D_OPTIONS) { DumpObjOptions (F, 0); } if (What & D_FILES) { DumpObjFiles (F, 0); } if (What & D_SEGMENTS) { DumpObjSegments (F, 0); } if (What & D_IMPORTS) { DumpObjImports (F, 0); } if (What & D_EXPORTS) { DumpObjExports (F, 0); } if (What & D_DBGSYMS) { DumpObjDbgSyms (F, 0); } if (What & D_LINEINFO) { DumpObjLineInfo (F, 0); } if (What & D_SCOPES) { DumpObjScopes (F, 0); } if (What & D_SEGSIZE) { DumpObjSegSize (F, 0); } } /* Close the file */ fclose (F); } int main (int argc, char* argv []) /* Assembler main program */ { /* Program long options */ static const LongOpt OptTab[] = { { "--dump-all", 0, OptDumpAll }, { "--dump-dbgsyms", 0, OptDumpDbgSyms }, { "--dump-exports", 0, OptDumpExports }, { "--dump-files", 0, OptDumpFiles }, { "--dump-header", 0, OptDumpHeader }, { "--dump-imports", 0, OptDumpImports }, { "--dump-lineinfo", 0, OptDumpLineInfo }, { "--dump-options", 0, OptDumpOptions }, { "--dump-scopes", 0, OptDumpScopes }, { "--dump-segments", 0, OptDumpSegments }, { "--dump-segsize", 0, OptDumpSegSize }, { "--help", 0, OptHelp }, { "--version", 0, OptVersion }, }; unsigned I; /* Initialize the cmdline module */ InitCmdLine (&argc, &argv, "od65"); /* Check the parameters */ I = 1; while (I < ArgCount) { /* Get the argument */ const char* Arg = ArgVec[I]; /* Check for an option */ if (Arg [0] == '-') { switch (Arg [1]) { case '-': LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0])); break; case 'h': OptHelp (Arg, 0); break; case 'H': OptDumpHeader (Arg, 0); break; case 'S': OptDumpSegSize (Arg, 0); break; case 'V': OptVersion (Arg, 0); break; default: UnknownOption (Arg); break; } } else { /* Filename. Dump it. */ DumpFile (Arg); ++FilesProcessed; } /* Next argument */ ++I; } /* Print a message if we did not process any files */ if (FilesProcessed == 0) { fprintf (stderr, "%s: No input files\n", ProgName); } /* Success */ return EXIT_SUCCESS; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sim65.vcxproj�������������������������������������������������������������������������0000664�0000000�0000000�00000011011�13473601511�0015346�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> <ProjectConfiguration Include="Release|Win32"> <Configuration>Release</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> </ItemGroup> <PropertyGroup Label="Globals"> <ProjectGuid>{002A366E-2863-46A8-BDDE-DDF534AAEC73}</ProjectGuid> <Keyword>Win32Proj</Keyword> <RootNamespace>sim65</RootNamespace> <WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <UseDebugLibraries>true</UseDebugLibraries> <PlatformToolset>v141</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <UseDebugLibraries>false</UseDebugLibraries> <WholeProgramOptimization>true</WholeProgramOptimization> <PlatformToolset>v141</PlatformToolset> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <PropertyGroup Label="UserMacros" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <LinkIncremental>true</LinkIncremental> <OutDir>$(SolutionDir)..\bin\</OutDir> <IntDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</IntDir> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <LinkIncremental>false</LinkIncremental> <OutDir>$(SolutionDir)..\bin\</OutDir> <IntDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</IntDir> </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ClCompile> <PrecompiledHeader> </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> <Link> <SubSystem>Console</SubSystem> <GenerateDebugInformation>true</GenerateDebugInformation> <AdditionalDependencies>$(IntDir)..\..\common\$(Configuration)\common.lib</AdditionalDependencies> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ClCompile> <WarningLevel>Level3</WarningLevel> <PrecompiledHeader> </PrecompiledHeader> <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> <Link> <SubSystem>Console</SubSystem> <GenerateDebugInformation>false</GenerateDebugInformation> <AdditionalDependencies>$(IntDir)..\..\common\$(Configuration)\common.lib</AdditionalDependencies> </Link> </ItemDefinitionGroup> <ItemGroup> <ClInclude Include="sim65\6502.h" /> <ClInclude Include="sim65\error.h" /> <ClInclude Include="sim65\memory.h" /> <ClInclude Include="sim65\paravirt.h" /> </ItemGroup> <ItemGroup> <ClCompile Include="sim65\6502.c" /> <ClCompile Include="sim65\error.c" /> <ClCompile Include="sim65\main.c" /> <ClCompile Include="sim65\memory.c" /> <ClCompile Include="sim65\paravirt.c" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> </Project>�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sim65/��������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0013737�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sim65/6502.c��������������������������������������������������������������������������0000664�0000000�0000000�00000205174�13473601511�0014510�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* 6502.c */ /* */ /* CPU core for the 6502 */ /* */ /* */ /* */ /* (C) 2003-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* Mar-2017, Christian Krueger, added support for 65SC02 */ /* */ /* 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. */ /* */ /*****************************************************************************/ /* Known bugs and limitations of the 65C02 simulation: * support currently only on the level of 65SC02: BBRx, BBSx, RMBx, SMBx, WAI, and STP are unsupported * BCD flag handling equals 6502 (unchecked if bug is simulated or wrong for 6502) */ #include "memory.h" #include "error.h" #include "6502.h" #include "paravirt.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Current CPU */ CPUType CPU; /* Type of an opcode handler function */ typedef void (*OPFunc) (void); /* The CPU registers */ static CPURegs Regs; /* Cycles for the current insn */ static unsigned Cycles; /* Total number of CPU cycles exec'd */ static unsigned long TotalCycles; /* NMI request active */ static unsigned HaveNMIRequest; /* IRQ request active */ static unsigned HaveIRQRequest; /* flag to print cycles at program termination */ int PrintCycles; /*****************************************************************************/ /* Helper functions and macros */ /*****************************************************************************/ /* Return the flags as boolean values (0/1) */ #define GET_CF() ((Regs.SR & CF) != 0) #define GET_ZF() ((Regs.SR & ZF) != 0) #define GET_IF() ((Regs.SR & IF) != 0) #define GET_DF() ((Regs.SR & DF) != 0) #define GET_OF() ((Regs.SR & OF) != 0) #define GET_SF() ((Regs.SR & SF) != 0) /* Set the flags. The parameter is a boolean flag that says if the flag should be ** set or reset. */ #define SET_CF(f) do { if (f) { Regs.SR |= CF; } else { Regs.SR &= ~CF; } } while (0) #define SET_ZF(f) do { if (f) { Regs.SR |= ZF; } else { Regs.SR &= ~ZF; } } while (0) #define SET_IF(f) do { if (f) { Regs.SR |= IF; } else { Regs.SR &= ~IF; } } while (0) #define SET_DF(f) do { if (f) { Regs.SR |= DF; } else { Regs.SR &= ~DF; } } while (0) #define SET_OF(f) do { if (f) { Regs.SR |= OF; } else { Regs.SR &= ~OF; } } while (0) #define SET_SF(f) do { if (f) { Regs.SR |= SF; } else { Regs.SR &= ~SF; } } while (0) /* Special test and set macros. The meaning of the parameter depends on the ** actual flag that should be set or reset. */ #define TEST_ZF(v) SET_ZF (((v) & 0xFF) == 0) #define TEST_SF(v) SET_SF (((v) & 0x80) != 0) #define TEST_CF(v) SET_CF (((v) & 0xFF00) != 0) /* Program counter halves */ #define PCL (Regs.PC & 0xFF) #define PCH ((Regs.PC >> 8) & 0xFF) /* Stack operations */ #define PUSH(Val) MemWriteByte (0x0100 | (Regs.SP-- & 0xFF), Val) #define POP() MemReadByte (0x0100 | (++Regs.SP & 0xFF)) /* Test for page cross */ #define PAGE_CROSS(addr,offs) ((((addr) & 0xFF) + offs) >= 0x100) /* #imm */ #define AC_OP_IMM(op) \ Cycles = 2; \ Regs.AC = Regs.AC op MemReadByte (Regs.PC+1); \ TEST_ZF (Regs.AC); \ TEST_SF (Regs.AC); \ Regs.PC += 2 /* zp */ #define AC_OP_ZP(op) \ Cycles = 3; \ Regs.AC = Regs.AC op MemReadByte (MemReadByte (Regs.PC+1)); \ TEST_ZF (Regs.AC); \ TEST_SF (Regs.AC); \ Regs.PC += 2 /* zp,x */ #define AC_OP_ZPX(op) \ unsigned char ZPAddr; \ Cycles = 4; \ ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; \ Regs.AC = Regs.AC op MemReadByte (ZPAddr); \ TEST_ZF (Regs.AC); \ TEST_SF (Regs.AC); \ Regs.PC += 2 /* zp,y */ #define AC_OP_ZPY(op) \ unsigned char ZPAddr; \ Cycles = 4; \ ZPAddr = MemReadByte (Regs.PC+1) + Regs.YR; \ Regs.AC = Regs.AC op MemReadByte (ZPAddr); \ TEST_ZF (Regs.AC); \ TEST_SF (Regs.AC); \ Regs.PC += 2 /* abs */ #define AC_OP_ABS(op) \ unsigned Addr; \ Cycles = 4; \ Addr = MemReadWord (Regs.PC+1); \ Regs.AC = Regs.AC op MemReadByte (Addr); \ TEST_ZF (Regs.AC); \ TEST_SF (Regs.AC); \ Regs.PC += 3 /* abs,x */ #define AC_OP_ABSX(op) \ unsigned Addr; \ Cycles = 4; \ Addr = MemReadWord (Regs.PC+1); \ if (PAGE_CROSS (Addr, Regs.XR)) { \ ++Cycles; \ } \ Regs.AC = Regs.AC op MemReadByte (Addr + Regs.XR); \ TEST_ZF (Regs.AC); \ TEST_SF (Regs.AC); \ Regs.PC += 3 /* abs,y */ #define AC_OP_ABSY(op) \ unsigned Addr; \ Cycles = 4; \ Addr = MemReadWord (Regs.PC+1); \ if (PAGE_CROSS (Addr, Regs.YR)) { \ ++Cycles; \ } \ Regs.AC = Regs.AC op MemReadByte (Addr + Regs.YR); \ TEST_ZF (Regs.AC); \ TEST_SF (Regs.AC); \ Regs.PC += 3 /* (zp,x) */ #define AC_OP_ZPXIND(op) \ unsigned char ZPAddr; \ unsigned Addr; \ Cycles = 6; \ ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; \ Addr = MemReadZPWord (ZPAddr); \ Regs.AC = Regs.AC op MemReadByte (Addr); \ TEST_ZF (Regs.AC); \ TEST_SF (Regs.AC); \ Regs.PC += 2 /* (zp),y */ #define AC_OP_ZPINDY(op) \ unsigned char ZPAddr; \ unsigned Addr; \ Cycles = 5; \ ZPAddr = MemReadByte (Regs.PC+1); \ Addr = MemReadZPWord (ZPAddr); \ if (PAGE_CROSS (Addr, Regs.YR)) { \ ++Cycles; \ } \ Addr += Regs.YR; \ Regs.AC = Regs.AC op MemReadByte (Addr); \ TEST_ZF (Regs.AC); \ TEST_SF (Regs.AC); \ Regs.PC += 2 /* (zp) */ #define AC_OP_ZPIND(op) \ unsigned char ZPAddr; \ unsigned Addr; \ Cycles = 5; \ ZPAddr = MemReadByte (Regs.PC+1); \ Addr = MemReadZPWord (ZPAddr); \ Regs.AC = Regs.AC op MemReadByte (Addr); \ TEST_ZF (Regs.AC); \ TEST_SF (Regs.AC); \ Regs.PC += 2 /* ADC */ #define ADC(v) \ do { \ unsigned old = Regs.AC; \ unsigned rhs = (v & 0xFF); \ if (GET_DF ()) { \ unsigned lo; \ int res; \ lo = (old & 0x0F) + (rhs & 0x0F) + GET_CF (); \ if (lo >= 0x0A) { \ lo = ((lo + 0x06) & 0x0F) + 0x10; \ } \ Regs.AC = (old & 0xF0) + (rhs & 0xF0) + lo; \ res = (signed char)(old & 0xF0) + \ (signed char)(rhs & 0xF0) + \ (signed char)lo; \ TEST_ZF (old + rhs + GET_CF ()); \ TEST_SF (Regs.AC); \ if (Regs.AC >= 0xA0) { \ Regs.AC += 0x60; \ } \ TEST_CF (Regs.AC); \ SET_OF ((res < -128) || (res > 127)); \ if (CPU != CPU_6502) { \ ++Cycles; \ } \ } else { \ Regs.AC += rhs + GET_CF (); \ TEST_ZF (Regs.AC); \ TEST_SF (Regs.AC); \ TEST_CF (Regs.AC); \ SET_OF (!((old ^ rhs) & 0x80) && \ ((old ^ Regs.AC) & 0x80)); \ Regs.AC &= 0xFF; \ } \ } while (0) /* branches */ #define BRANCH(cond) \ Cycles = 2; \ if (cond) { \ signed char Offs; \ unsigned char OldPCH; \ ++Cycles; \ Offs = (signed char) MemReadByte (Regs.PC+1); \ OldPCH = PCH; \ Regs.PC += 2 + (int) Offs; \ if (PCH != OldPCH) { \ ++Cycles; \ } \ } else { \ Regs.PC += 2; \ } /* compares */ #define CMP(v1, v2) \ do { \ unsigned Result = v1 - v2; \ TEST_ZF (Result & 0xFF); \ TEST_SF (Result); \ SET_CF (Result <= 0xFF); \ } while (0) /* ROL */ #define ROL(Val) \ Val <<= 1; \ if (GET_CF ()) { \ Val |= 0x01; \ } \ TEST_ZF (Val); \ TEST_SF (Val); \ TEST_CF (Val) /* ROR */ #define ROR(Val) \ if (GET_CF ()) { \ Val |= 0x100; \ } \ SET_CF (Val & 0x01); \ Val >>= 1; \ TEST_ZF (Val); \ TEST_SF (Val) /* SBC */ #define SBC(v) \ do { \ unsigned old = Regs.AC; \ unsigned rhs = (v & 0xFF); \ if (GET_DF ()) { \ unsigned lo; \ int res; \ lo = (old & 0x0F) - (rhs & 0x0F) + GET_CF () - 1; \ if (lo & 0x80) { \ lo = ((lo - 0x06) & 0x0F) - 0x10; \ } \ Regs.AC = (old & 0xF0) - (rhs & 0xF0) + lo; \ if (Regs.AC & 0x80) { \ Regs.AC -= 0x60; \ } \ res = Regs.AC - rhs + (!GET_CF ()); \ TEST_ZF (res); \ TEST_SF (res); \ SET_CF (res <= 0xFF); \ SET_OF (((old^rhs) & (old^res) & 0x80)); \ if (CPU != CPU_6502) { \ ++Cycles; \ } \ } else { \ Regs.AC -= rhs + (!GET_CF ()); \ TEST_ZF (Regs.AC); \ TEST_SF (Regs.AC); \ SET_CF (Regs.AC <= 0xFF); \ SET_OF (((old^rhs) & (old^Regs.AC) & 0x80)); \ Regs.AC &= 0xFF; \ } \ } while (0) /*****************************************************************************/ /* Opcode handling functions */ /*****************************************************************************/ static void OPC_Illegal (void) { Error ("Illegal opcode $%02X at address $%04X", MemReadByte (Regs.PC), Regs.PC); } static void OPC_6502_00 (void) /* Opcode $00: BRK */ { Cycles = 7; Regs.PC += 2; PUSH (PCH); PUSH (PCL); PUSH (Regs.SR); SET_IF (1); if (CPU != CPU_6502) { SET_DF (0); } Regs.PC = MemReadWord (0xFFFE); } static void OPC_6502_01 (void) /* Opcode $01: ORA (ind,x) */ { AC_OP_ZPXIND (|); } static void OPC_65SC02_04 (void) /* Opcode $04: TSB zp */ { unsigned char ZPAddr; unsigned char Val; Cycles = 5; ZPAddr = MemReadByte (Regs.PC+1); Val = MemReadByte (ZPAddr); SET_ZF ((Val & Regs.AC) == 0); MemWriteByte (ZPAddr, (unsigned char)(Val | Regs.AC)); Regs.PC += 2; } static void OPC_6502_05 (void) /* Opcode $05: ORA zp */ { AC_OP_ZP (|); } static void OPC_6502_06 (void) /* Opcode $06: ASL zp */ { unsigned char ZPAddr; unsigned Val; Cycles = 5; ZPAddr = MemReadByte (Regs.PC+1); Val = MemReadByte (ZPAddr) << 1; MemWriteByte (ZPAddr, (unsigned char) Val); TEST_ZF (Val & 0xFF); TEST_SF (Val); SET_CF (Val & 0x100); Regs.PC += 2; } static void OPC_6502_08 (void) /* Opcode $08: PHP */ { Cycles = 3; PUSH (Regs.SR); Regs.PC += 1; } static void OPC_6502_09 (void) /* Opcode $09: ORA #imm */ { AC_OP_IMM (|); } static void OPC_6502_0A (void) /* Opcode $0A: ASL a */ { Cycles = 2; Regs.AC <<= 1; TEST_ZF (Regs.AC & 0xFF); TEST_SF (Regs.AC); SET_CF (Regs.AC & 0x100); Regs.AC &= 0xFF; Regs.PC += 1; } static void OPC_65SC02_0C (void) /* Opcode $0C: TSB abs */ { unsigned Addr; unsigned char Val; Cycles = 6; Addr = MemReadWord (Regs.PC+1); Val = MemReadByte (Addr); SET_ZF ((Val & Regs.AC) == 0); MemWriteByte (Addr, (unsigned char) (Val | Regs.AC)); Regs.PC += 3; } static void OPC_6502_0D (void) /* Opcode $0D: ORA abs */ { AC_OP_ABS (|); } static void OPC_6502_0E (void) /* Opcode $0E: ALS abs */ { unsigned Addr; unsigned Val; Cycles = 6; Addr = MemReadWord (Regs.PC+1); Val = MemReadByte (Addr) << 1; MemWriteByte (Addr, (unsigned char) Val); TEST_ZF (Val & 0xFF); TEST_SF (Val); SET_CF (Val & 0x100); Regs.PC += 3; } static void OPC_6502_10 (void) /* Opcode $10: BPL */ { BRANCH (!GET_SF ()); } static void OPC_6502_11 (void) /* Opcode $11: ORA (zp),y */ { AC_OP_ZPINDY (|); } static void OPC_65SC02_12 (void) /* Opcode $12: ORA (zp) */ { AC_OP_ZPIND (|); } static void OPC_65SC02_14 (void) /* Opcode $14: TRB zp */ { unsigned char ZPAddr; unsigned char Val; Cycles = 5; ZPAddr = MemReadByte (Regs.PC+1); Val = MemReadByte (ZPAddr); SET_ZF ((Val & Regs.AC) == 0); MemWriteByte (ZPAddr, (unsigned char)(Val & ~Regs.AC)); Regs.PC += 2; } static void OPC_6502_15 (void) /* Opcode $15: ORA zp,x */ { AC_OP_ZPX (|); } static void OPC_6502_16 (void) /* Opcode $16: ASL zp,x */ { unsigned char ZPAddr; unsigned Val; Cycles = 6; ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; Val = MemReadByte (ZPAddr) << 1; MemWriteByte (ZPAddr, (unsigned char) Val); TEST_ZF (Val & 0xFF); TEST_SF (Val); SET_CF (Val & 0x100); Regs.PC += 2; } static void OPC_6502_18 (void) /* Opcode $18: CLC */ { Cycles = 2; SET_CF (0); Regs.PC += 1; } static void OPC_6502_19 (void) /* Opcode $19: ORA abs,y */ { AC_OP_ABSY (|); } static void OPC_65SC02_1A (void) /* Opcode $1A: INC a */ { Cycles = 2; Regs.AC = (Regs.AC + 1) & 0xFF; TEST_ZF (Regs.AC); TEST_SF (Regs.AC); Regs.PC += 1; } static void OPC_65SC02_1C (void) /* Opcode $1C: TRB abs */ { unsigned Addr; unsigned char Val; Cycles = 6; Addr = MemReadWord (Regs.PC+1); Val = MemReadByte (Addr); SET_ZF ((Val & Regs.AC) == 0); MemWriteByte (Addr, (unsigned char) (Val & ~Regs.AC)); Regs.PC += 3; } static void OPC_6502_1D (void) /* Opcode $1D: ORA abs,x */ { AC_OP_ABSX (|); } static void OPC_6502_1E (void) /* Opcode $1E: ASL abs,x */ { unsigned Addr; unsigned Val; Cycles = 7; Addr = MemReadWord (Regs.PC+1) + Regs.XR; if (CPU != CPU_6502 && !PAGE_CROSS (Addr, Regs.XR)) --Cycles; Val = MemReadByte (Addr) << 1; MemWriteByte (Addr, (unsigned char) Val); TEST_ZF (Val & 0xFF); TEST_SF (Val); SET_CF (Val & 0x100); Regs.PC += 3; } static void OPC_6502_20 (void) /* Opcode $20: JSR */ { unsigned Addr; Cycles = 6; Addr = MemReadWord (Regs.PC+1); Regs.PC += 2; PUSH (PCH); PUSH (PCL); Regs.PC = Addr; ParaVirtHooks (&Regs); } static void OPC_6502_21 (void) /* Opcode $21: AND (zp,x) */ { AC_OP_ZPXIND (&); } static void OPC_6502_24 (void) /* Opcode $24: BIT zp */ { unsigned char ZPAddr; unsigned char Val; Cycles = 3; ZPAddr = MemReadByte (Regs.PC+1); Val = MemReadByte (ZPAddr); SET_SF (Val & 0x80); SET_OF (Val & 0x40); SET_ZF ((Val & Regs.AC) == 0); Regs.PC += 2; } static void OPC_6502_25 (void) /* Opcode $25: AND zp */ { AC_OP_ZP (&); } static void OPC_6502_26 (void) /* Opcode $26: ROL zp */ { unsigned char ZPAddr; unsigned Val; Cycles = 5; ZPAddr = MemReadByte (Regs.PC+1); Val = MemReadByte (ZPAddr); ROL (Val); MemWriteByte (ZPAddr, Val); Regs.PC += 2; } static void OPC_6502_28 (void) /* Opcode $28: PLP */ { Cycles = 4; /* Bits 5 and 4 aren't used, and always are 1! */ Regs.SR = (POP () | 0x30); Regs.PC += 1; } static void OPC_6502_29 (void) /* Opcode $29: AND #imm */ { AC_OP_IMM (&); } static void OPC_6502_2A (void) /* Opcode $2A: ROL a */ { Cycles = 2; ROL (Regs.AC); Regs.AC &= 0xFF; Regs.PC += 1; } static void OPC_6502_2C (void) /* Opcode $2C: BIT abs */ { unsigned Addr; unsigned char Val; Cycles = 4; Addr = MemReadWord (Regs.PC+1); Val = MemReadByte (Addr); SET_SF (Val & 0x80); SET_OF (Val & 0x40); SET_ZF ((Val & Regs.AC) == 0); Regs.PC += 3; } static void OPC_6502_2D (void) /* Opcode $2D: AND abs */ { AC_OP_ABS (&); } static void OPC_6502_2E (void) /* Opcode $2E: ROL abs */ { unsigned Addr; unsigned Val; Cycles = 6; Addr = MemReadWord (Regs.PC+1); Val = MemReadByte (Addr); ROL (Val); MemWriteByte (Addr, Val); Regs.PC += 3; } static void OPC_6502_30 (void) /* Opcode $30: BMI */ { BRANCH (GET_SF ()); } static void OPC_6502_31 (void) /* Opcode $31: AND (zp),y */ { AC_OP_ZPINDY (&); } static void OPC_65SC02_32 (void) /* Opcode $32: AND (zp) */ { AC_OP_ZPIND (&); } static void OPC_65SC02_34 (void) /* Opcode $34: BIT zp,x */ { unsigned char ZPAddr; unsigned char Val; Cycles = 4; ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; Val = MemReadByte (ZPAddr); SET_SF (Val & 0x80); SET_OF (Val & 0x40); SET_ZF ((Val & Regs.AC) == 0); Regs.PC += 2; } static void OPC_6502_35 (void) /* Opcode $35: AND zp,x */ { AC_OP_ZPX (&); } static void OPC_6502_36 (void) /* Opcode $36: ROL zp,x */ { unsigned char ZPAddr; unsigned Val; Cycles = 6; ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; Val = MemReadByte (ZPAddr); ROL (Val); MemWriteByte (ZPAddr, Val); Regs.PC += 2; } static void OPC_6502_38 (void) /* Opcode $38: SEC */ { Cycles = 2; SET_CF (1); Regs.PC += 1; } static void OPC_6502_39 (void) /* Opcode $39: AND abs,y */ { AC_OP_ABSY (&); } static void OPC_65SC02_3A (void) /* Opcode $3A: DEC a */ { Cycles = 2; Regs.AC = (Regs.AC - 1) & 0xFF; TEST_ZF (Regs.AC); TEST_SF (Regs.AC); Regs.PC += 1; } static void OPC_65SC02_3C (void) /* Opcode $3C: BIT abs,x */ { unsigned Addr; unsigned char Val; Cycles = 4; Addr = MemReadWord (Regs.PC+1); if (PAGE_CROSS (Addr, Regs.XR)) ++Cycles; Val = MemReadByte (Addr + Regs.XR); SET_SF (Val & 0x80); SET_OF (Val & 0x40); SET_ZF ((Val & Regs.AC) == 0); Regs.PC += 3; } static void OPC_6502_3D (void) /* Opcode $3D: AND abs,x */ { AC_OP_ABSX (&); } static void OPC_6502_3E (void) /* Opcode $3E: ROL abs,x */ { unsigned Addr; unsigned Val; Cycles = 7; Addr = MemReadWord (Regs.PC+1) + Regs.XR; if (CPU != CPU_6502 && !PAGE_CROSS (Addr, Regs.XR)) --Cycles; Val = MemReadByte (Addr); ROL (Val); MemWriteByte (Addr, Val); Regs.PC += 2; } static void OPC_6502_40 (void) /* Opcode $40: RTI */ { Cycles = 6; /* Bits 5 and 4 aren't used, and always are 1! */ Regs.SR = POP () | 0x30; Regs.PC = POP (); /* PCL */ Regs.PC |= (POP () << 8); /* PCH */ } static void OPC_6502_41 (void) /* Opcode $41: EOR (zp,x) */ { AC_OP_ZPXIND (^); } static void OPC_65C02_44 (void) /* Opcode $44: 'zp' 3 cycle NOP */ { Cycles = 3; Regs.PC += 2; } static void OPC_6502_45 (void) /* Opcode $45: EOR zp */ { AC_OP_ZP (^); } static void OPC_6502_46 (void) /* Opcode $46: LSR zp */ { unsigned char ZPAddr; unsigned char Val; Cycles = 5; ZPAddr = MemReadByte (Regs.PC+1); Val = MemReadByte (ZPAddr); SET_CF (Val & 0x01); Val >>= 1; MemWriteByte (ZPAddr, Val); TEST_ZF (Val); TEST_SF (Val); Regs.PC += 2; } static void OPC_6502_48 (void) /* Opcode $48: PHA */ { Cycles = 3; PUSH (Regs.AC); Regs.PC += 1; } static void OPC_6502_49 (void) /* Opcode $49: EOR #imm */ { AC_OP_IMM (^); } static void OPC_6502_4A (void) /* Opcode $4A: LSR a */ { Cycles = 2; SET_CF (Regs.AC & 0x01); Regs.AC >>= 1; TEST_ZF (Regs.AC); TEST_SF (Regs.AC); Regs.PC += 1; } static void OPC_6502_4C (void) /* Opcode $4C: JMP abs */ { Cycles = 3; Regs.PC = MemReadWord (Regs.PC+1); ParaVirtHooks (&Regs); } static void OPC_6502_4D (void) /* Opcode $4D: EOR abs */ { AC_OP_ABS (^); } static void OPC_6502_4E (void) /* Opcode $4E: LSR abs */ { unsigned Addr; unsigned char Val; Cycles = 6; Addr = MemReadWord (Regs.PC+1); Val = MemReadByte (Addr); SET_CF (Val & 0x01); Val >>= 1; MemWriteByte (Addr, Val); TEST_ZF (Val); TEST_SF (Val); Regs.PC += 3; } static void OPC_6502_50 (void) /* Opcode $50: BVC */ { BRANCH (!GET_OF ()); } static void OPC_6502_51 (void) /* Opcode $51: EOR (zp),y */ { AC_OP_ZPINDY (^); } static void OPC_65SC02_52 (void) /* Opcode $52: EOR (zp) */ { AC_OP_ZPIND (^); } static void OPC_6502_55 (void) /* Opcode $55: EOR zp,x */ { AC_OP_ZPX (^); } static void OPC_6502_56 (void) /* Opcode $56: LSR zp,x */ { unsigned char ZPAddr; unsigned char Val; Cycles = 6; ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; Val = MemReadByte (ZPAddr); SET_CF (Val & 0x01); Val >>= 1; MemWriteByte (ZPAddr, Val); TEST_ZF (Val); TEST_SF (Val); Regs.PC += 2; } static void OPC_6502_58 (void) /* Opcode $58: CLI */ { Cycles = 2; SET_IF (0); Regs.PC += 1; } static void OPC_6502_59 (void) /* Opcode $59: EOR abs,y */ { AC_OP_ABSY (^); } static void OPC_65SC02_5A (void) /* Opcode $5A: PHY */ { Cycles = 3; PUSH (Regs.YR); Regs.PC += 1; } static void OPC_65C02_5C (void) /* Opcode $5C: 'Absolute' 8 cycle NOP */ { Cycles = 8; Regs.PC += 3; } static void OPC_6502_5D (void) /* Opcode $5D: EOR abs,x */ { AC_OP_ABSX (^); } static void OPC_6502_5E (void) /* Opcode $5E: LSR abs,x */ { unsigned Addr; unsigned char Val; Cycles = 7; Addr = MemReadWord (Regs.PC+1) + Regs.XR; if (CPU != CPU_6502 && !PAGE_CROSS (Addr, Regs.XR)) --Cycles; Val = MemReadByte (Addr); SET_CF (Val & 0x01); Val >>= 1; MemWriteByte (Addr, Val); TEST_ZF (Val); TEST_SF (Val); Regs.PC += 3; } static void OPC_6502_60 (void) /* Opcode $60: RTS */ { Cycles = 6; Regs.PC = POP (); /* PCL */ Regs.PC |= (POP () << 8); /* PCH */ Regs.PC += 1; } static void OPC_6502_61 (void) /* Opcode $61: ADC (zp,x) */ { unsigned char ZPAddr; unsigned Addr; Cycles = 6; ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; Addr = MemReadZPWord (ZPAddr); ADC (MemReadByte (Addr)); Regs.PC += 2; } static void OPC_65SC02_64 (void) /* Opcode $64: STZ zp */ { unsigned char ZPAddr; Cycles = 3; ZPAddr = MemReadByte (Regs.PC+1); MemWriteByte (ZPAddr, 0); Regs.PC += 2; } static void OPC_6502_65 (void) /* Opcode $65: ADC zp */ { unsigned char ZPAddr; Cycles = 3; ZPAddr = MemReadByte (Regs.PC+1); ADC (MemReadByte (ZPAddr)); Regs.PC += 2; } static void OPC_6502_66 (void) /* Opcode $66: ROR zp */ { unsigned char ZPAddr; unsigned Val; Cycles = 5; ZPAddr = MemReadByte (Regs.PC+1); Val = MemReadByte (ZPAddr); ROR (Val); MemWriteByte (ZPAddr, Val); Regs.PC += 2; } static void OPC_6502_68 (void) /* Opcode $68: PLA */ { Cycles = 4; Regs.AC = POP (); TEST_ZF (Regs.AC); TEST_SF (Regs.AC); Regs.PC += 1; } static void OPC_6502_69 (void) /* Opcode $69: ADC #imm */ { Cycles = 2; ADC (MemReadByte (Regs.PC+1)); Regs.PC += 2; } static void OPC_6502_6A (void) /* Opcode $6A: ROR a */ { Cycles = 2; ROR (Regs.AC); Regs.PC += 1; } static void OPC_6502_6C (void) /* Opcode $6C: JMP (ind) */ { unsigned PC, Lo, Hi; PC = Regs.PC; Lo = MemReadWord (PC+1); if (CPU == CPU_6502) { /* Emulate the 6502 bug */ Cycles = 5; Regs.PC = MemReadByte (Lo); Hi = (Lo & 0xFF00) | ((Lo + 1) & 0xFF); Regs.PC |= (MemReadByte (Hi) << 8); /* Output a warning if the bug is triggered */ if (Hi != Lo + 1) { Warning ("6502 indirect jump bug triggered at $%04X, ind addr = $%04X", PC, Lo); } } else { Cycles = 6; Regs.PC = MemReadWord(Lo); } ParaVirtHooks (&Regs); } static void OPC_65C02_6C (void) /* Opcode $6C: JMP (ind) */ { /* 6502 bug fixed here */ Cycles = 5; Regs.PC = MemReadWord (MemReadWord (Regs.PC+1)); ParaVirtHooks (&Regs); } static void OPC_6502_6D (void) /* Opcode $6D: ADC abs */ { unsigned Addr; Cycles = 4; Addr = MemReadWord (Regs.PC+1); ADC (MemReadByte (Addr)); Regs.PC += 3; } static void OPC_6502_6E (void) /* Opcode $6E: ROR abs */ { unsigned Addr; unsigned Val; Cycles = 6; Addr = MemReadWord (Regs.PC+1); Val = MemReadByte (Addr); ROR (Val); MemWriteByte (Addr, Val); Regs.PC += 3; } static void OPC_6502_70 (void) /* Opcode $70: BVS */ { BRANCH (GET_OF ()); } static void OPC_6502_71 (void) /* Opcode $71: ADC (zp),y */ { unsigned char ZPAddr; unsigned Addr; Cycles = 5; ZPAddr = MemReadByte (Regs.PC+1); Addr = MemReadZPWord (ZPAddr); if (PAGE_CROSS (Addr, Regs.YR)) { ++Cycles; } ADC (MemReadByte (Addr + Regs.YR)); Regs.PC += 2; } static void OPC_65SC02_72 (void) /* Opcode $72: ADC (zp) */ { unsigned char ZPAddr; unsigned Addr; Cycles = 5; ZPAddr = MemReadByte (Regs.PC+1); Addr = MemReadZPWord (ZPAddr); ADC (MemReadByte (Addr)); Regs.PC += 2; } static void OPC_65SC02_74 (void) /* Opcode $74: STZ zp,x */ { unsigned char ZPAddr; Cycles = 4; ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; MemWriteByte (ZPAddr, 0); Regs.PC += 2; } static void OPC_6502_75 (void) /* Opcode $75: ADC zp,x */ { unsigned char ZPAddr; Cycles = 4; ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; ADC (MemReadByte (ZPAddr)); Regs.PC += 2; } static void OPC_6502_76 (void) /* Opcode $76: ROR zp,x */ { unsigned char ZPAddr; unsigned Val; Cycles = 6; ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; Val = MemReadByte (ZPAddr); ROR (Val); MemWriteByte (ZPAddr, Val); Regs.PC += 2; } static void OPC_6502_78 (void) /* Opcode $78: SEI */ { Cycles = 2; SET_IF (1); Regs.PC += 1; } static void OPC_6502_79 (void) /* Opcode $79: ADC abs,y */ { unsigned Addr; Cycles = 4; Addr = MemReadWord (Regs.PC+1); if (PAGE_CROSS (Addr, Regs.YR)) { ++Cycles; } ADC (MemReadByte (Addr + Regs.YR)); Regs.PC += 3; } static void OPC_65SC02_7A (void) /* Opcode $7A: PLY */ { Cycles = 4; Regs.YR = POP (); TEST_ZF (Regs.YR); TEST_SF (Regs.YR); Regs.PC += 1; } static void OPC_65SC02_7C (void) /* Opcode $7C: JMP (ind,X) */ { unsigned PC, Adr; Cycles = 6; PC = Regs.PC; Adr = MemReadWord (PC+1); Regs.PC = MemReadWord(Adr+Regs.XR); ParaVirtHooks (&Regs); } static void OPC_6502_7D (void) /* Opcode $7D: ADC abs,x */ { unsigned Addr; Cycles = 4; Addr = MemReadWord (Regs.PC+1); if (PAGE_CROSS (Addr, Regs.XR)) { ++Cycles; } ADC (MemReadByte (Addr + Regs.XR)); Regs.PC += 3; } static void OPC_6502_7E (void) /* Opcode $7E: ROR abs,x */ { unsigned Addr; unsigned Val; Cycles = 7; Addr = MemReadWord (Regs.PC+1) + Regs.XR; if (CPU != CPU_6502 && !PAGE_CROSS (Addr, Regs.XR)) --Cycles; Val = MemReadByte (Addr); ROR (Val); MemWriteByte (Addr, Val); Regs.PC += 3; } static void OPC_65SC02_80 (void) /* Opcode $80: BRA */ { BRANCH (1); } static void OPC_6502_81 (void) /* Opcode $81: STA (zp,x) */ { unsigned char ZPAddr; unsigned Addr; Cycles = 6; ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; Addr = MemReadZPWord (ZPAddr); MemWriteByte (Addr, Regs.AC); Regs.PC += 2; } static void OPC_6502_84 (void) /* Opcode $84: STY zp */ { unsigned char ZPAddr; Cycles = 3; ZPAddr = MemReadByte (Regs.PC+1); MemWriteByte (ZPAddr, Regs.YR); Regs.PC += 2; } static void OPC_6502_85 (void) /* Opcode $85: STA zp */ { unsigned char ZPAddr; Cycles = 3; ZPAddr = MemReadByte (Regs.PC+1); MemWriteByte (ZPAddr, Regs.AC); Regs.PC += 2; } static void OPC_6502_86 (void) /* Opcode $86: STX zp */ { unsigned char ZPAddr; Cycles = 3; ZPAddr = MemReadByte (Regs.PC+1); MemWriteByte (ZPAddr, Regs.XR); Regs.PC += 2; } static void OPC_6502_88 (void) /* Opcode $88: DEY */ { Cycles = 2; Regs.YR = (Regs.YR - 1) & 0xFF; TEST_ZF (Regs.YR); TEST_SF (Regs.YR); Regs.PC += 1; } static void OPC_65SC02_89 (void) /* Opcode $89: BIT #imm */ { unsigned char Val; Cycles = 2; Val = MemReadByte (Regs.PC+1); SET_SF (Val & 0x80); SET_OF (Val & 0x40); SET_ZF ((Val & Regs.AC) == 0); Regs.PC += 2; } static void OPC_6502_8A (void) /* Opcode $8A: TXA */ { Cycles = 2; Regs.AC = Regs.XR; TEST_ZF (Regs.AC); TEST_SF (Regs.AC); Regs.PC += 1; } static void OPC_6502_8C (void) /* Opcode $8C: STY abs */ { unsigned Addr; Cycles = 4; Addr = MemReadWord (Regs.PC+1); MemWriteByte (Addr, Regs.YR); Regs.PC += 3; } static void OPC_6502_8D (void) /* Opcode $8D: STA abs */ { unsigned Addr; Cycles = 4; Addr = MemReadWord (Regs.PC+1); MemWriteByte (Addr, Regs.AC); Regs.PC += 3; } static void OPC_6502_8E (void) /* Opcode $8E: STX abs */ { unsigned Addr; Cycles = 4; Addr = MemReadWord (Regs.PC+1); MemWriteByte (Addr, Regs.XR); Regs.PC += 3; } static void OPC_6502_90 (void) /* Opcode $90: BCC */ { BRANCH (!GET_CF ()); } static void OPC_6502_91 (void) /* Opcode $91: sta (zp),y */ { unsigned char ZPAddr; unsigned Addr; Cycles = 6; ZPAddr = MemReadByte (Regs.PC+1); Addr = MemReadZPWord (ZPAddr) + Regs.YR; MemWriteByte (Addr, Regs.AC); Regs.PC += 2; } static void OPC_65SC02_92 (void) /* Opcode $92: sta (zp) */ { unsigned char ZPAddr; unsigned Addr; Cycles = 5; ZPAddr = MemReadByte (Regs.PC+1); Addr = MemReadZPWord (ZPAddr); MemWriteByte (Addr, Regs.AC); Regs.PC += 2; } static void OPC_6502_94 (void) /* Opcode $94: STY zp,x */ { unsigned char ZPAddr; Cycles = 4; ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; MemWriteByte (ZPAddr, Regs.YR); Regs.PC += 2; } static void OPC_6502_95 (void) /* Opcode $95: STA zp,x */ { unsigned char ZPAddr; Cycles = 4; ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; MemWriteByte (ZPAddr, Regs.AC); Regs.PC += 2; } static void OPC_6502_96 (void) /* Opcode $96: stx zp,y */ { unsigned char ZPAddr; Cycles = 4; ZPAddr = MemReadByte (Regs.PC+1) + Regs.YR; MemWriteByte (ZPAddr, Regs.XR); Regs.PC += 2; } static void OPC_6502_98 (void) /* Opcode $98: TYA */ { Cycles = 2; Regs.AC = Regs.YR; TEST_ZF (Regs.AC); TEST_SF (Regs.AC); Regs.PC += 1; } static void OPC_6502_99 (void) /* Opcode $99: STA abs,y */ { unsigned Addr; Cycles = 5; Addr = MemReadWord (Regs.PC+1) + Regs.YR; MemWriteByte (Addr, Regs.AC); Regs.PC += 3; } static void OPC_6502_9A (void) /* Opcode $9A: TXS */ { Cycles = 2; Regs.SP = Regs.XR; Regs.PC += 1; } static void OPC_65SC02_9C (void) /* Opcode $9C: STZ abs */ { unsigned Addr; Cycles = 4; Addr = MemReadWord (Regs.PC+1); MemWriteByte (Addr, 0); Regs.PC += 3; } static void OPC_6502_9D (void) /* Opcode $9D: STA abs,x */ { unsigned Addr; Cycles = 5; Addr = MemReadWord (Regs.PC+1) + Regs.XR; MemWriteByte (Addr, Regs.AC); Regs.PC += 3; } static void OPC_65SC02_9E (void) /* Opcode $9E: STZ abs,x */ { unsigned Addr; Cycles = 5; Addr = MemReadWord (Regs.PC+1) + Regs.XR; MemWriteByte (Addr, 0); Regs.PC += 3; } static void OPC_6502_A0 (void) /* Opcode $A0: LDY #imm */ { Cycles = 2; Regs.YR = MemReadByte (Regs.PC+1); TEST_ZF (Regs.YR); TEST_SF (Regs.YR); Regs.PC += 2; } static void OPC_6502_A1 (void) /* Opcode $A1: LDA (zp,x) */ { unsigned char ZPAddr; unsigned Addr; Cycles = 6; ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; Addr = MemReadZPWord (ZPAddr); Regs.AC = MemReadByte (Addr); TEST_ZF (Regs.AC); TEST_SF (Regs.AC); Regs.PC += 2; } static void OPC_6502_A2 (void) /* Opcode $A2: LDX #imm */ { Cycles = 2; Regs.XR = MemReadByte (Regs.PC+1); TEST_ZF (Regs.XR); TEST_SF (Regs.XR); Regs.PC += 2; } static void OPC_6502_A4 (void) /* Opcode $A4: LDY zp */ { unsigned char ZPAddr; Cycles = 3; ZPAddr = MemReadByte (Regs.PC+1); Regs.YR = MemReadByte (ZPAddr); TEST_ZF (Regs.YR); TEST_SF (Regs.YR); Regs.PC += 2; } static void OPC_6502_A5 (void) /* Opcode $A5: LDA zp */ { unsigned char ZPAddr; Cycles = 3; ZPAddr = MemReadByte (Regs.PC+1); Regs.AC = MemReadByte (ZPAddr); TEST_ZF (Regs.AC); TEST_SF (Regs.AC); Regs.PC += 2; } static void OPC_6502_A6 (void) /* Opcode $A6: LDX zp */ { unsigned char ZPAddr; Cycles = 3; ZPAddr = MemReadByte (Regs.PC+1); Regs.XR = MemReadByte (ZPAddr); TEST_ZF (Regs.XR); TEST_SF (Regs.XR); Regs.PC += 2; } static void OPC_6502_A8 (void) /* Opcode $A8: TAY */ { Cycles = 2; Regs.YR = Regs.AC; TEST_ZF (Regs.YR); TEST_SF (Regs.YR); Regs.PC += 1; } static void OPC_6502_A9 (void) /* Opcode $A9: LDA #imm */ { Cycles = 2; Regs.AC = MemReadByte (Regs.PC+1); TEST_ZF (Regs.AC); TEST_SF (Regs.AC); Regs.PC += 2; } static void OPC_6502_AA (void) /* Opcode $AA: TAX */ { Cycles = 2; Regs.XR = Regs.AC; TEST_ZF (Regs.XR); TEST_SF (Regs.XR); Regs.PC += 1; } static void OPC_6502_AC (void) /* Opcode $Regs.AC: LDY abs */ { unsigned Addr; Cycles = 4; Addr = MemReadWord (Regs.PC+1); Regs.YR = MemReadByte (Addr); TEST_ZF (Regs.YR); TEST_SF (Regs.YR); Regs.PC += 3; } static void OPC_6502_AD (void) /* Opcode $AD: LDA abs */ { unsigned Addr; Cycles = 4; Addr = MemReadWord (Regs.PC+1); Regs.AC = MemReadByte (Addr); TEST_ZF (Regs.AC); TEST_SF (Regs.AC); Regs.PC += 3; } static void OPC_6502_AE (void) /* Opcode $AE: LDX abs */ { unsigned Addr; Cycles = 4; Addr = MemReadWord (Regs.PC+1); Regs.XR = MemReadByte (Addr); TEST_ZF (Regs.XR); TEST_SF (Regs.XR); Regs.PC += 3; } static void OPC_6502_B0 (void) /* Opcode $B0: BCS */ { BRANCH (GET_CF ()); } static void OPC_6502_B1 (void) /* Opcode $B1: LDA (zp),y */ { unsigned char ZPAddr; unsigned Addr; Cycles = 5; ZPAddr = MemReadByte (Regs.PC+1); Addr = MemReadZPWord (ZPAddr); if (PAGE_CROSS (Addr, Regs.YR)) { ++Cycles; } Regs.AC = MemReadByte (Addr + Regs.YR); TEST_ZF (Regs.AC); TEST_SF (Regs.AC); Regs.PC += 2; } static void OPC_65SC02_B2 (void) /* Opcode $B2: LDA (zp) */ { unsigned char ZPAddr; unsigned Addr; Cycles = 5; ZPAddr = MemReadByte (Regs.PC+1); Addr = MemReadZPWord (ZPAddr); Regs.AC = MemReadByte (Addr); TEST_ZF (Regs.AC); TEST_SF (Regs.AC); Regs.PC += 2; } static void OPC_6502_B4 (void) /* Opcode $B4: LDY zp,x */ { unsigned char ZPAddr; Cycles = 4; ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; Regs.YR = MemReadByte (ZPAddr); TEST_ZF (Regs.YR); TEST_SF (Regs.YR); Regs.PC += 2; } static void OPC_6502_B5 (void) /* Opcode $B5: LDA zp,x */ { unsigned char ZPAddr; Cycles = 4; ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; Regs.AC = MemReadByte (ZPAddr); TEST_ZF (Regs.AC); TEST_SF (Regs.AC); Regs.PC += 2; } static void OPC_6502_B6 (void) /* Opcode $B6: LDX zp,y */ { unsigned char ZPAddr; Cycles = 4; ZPAddr = MemReadByte (Regs.PC+1) + Regs.YR; Regs.XR = MemReadByte (ZPAddr); TEST_ZF (Regs.XR); TEST_SF (Regs.XR); Regs.PC += 2; } static void OPC_6502_B8 (void) /* Opcode $B8: CLV */ { Cycles = 2; SET_OF (0); Regs.PC += 1; } static void OPC_6502_B9 (void) /* Opcode $B9: LDA abs,y */ { unsigned Addr; Cycles = 4; Addr = MemReadWord (Regs.PC+1); if (PAGE_CROSS (Addr, Regs.YR)) { ++Cycles; } Regs.AC = MemReadByte (Addr + Regs.YR); TEST_ZF (Regs.AC); TEST_SF (Regs.AC); Regs.PC += 3; } static void OPC_6502_BA (void) /* Opcode $BA: TSX */ { Cycles = 2; Regs.XR = Regs.SP & 0xFF; TEST_ZF (Regs.XR); TEST_SF (Regs.XR); Regs.PC += 1; } static void OPC_6502_BC (void) /* Opcode $BC: LDY abs,x */ { unsigned Addr; Cycles = 4; Addr = MemReadWord (Regs.PC+1); if (PAGE_CROSS (Addr, Regs.XR)) { ++Cycles; } Regs.YR = MemReadByte (Addr + Regs.XR); TEST_ZF (Regs.YR); TEST_SF (Regs.YR); Regs.PC += 3; } static void OPC_6502_BD (void) /* Opcode $BD: LDA abs,x */ { unsigned Addr; Cycles = 4; Addr = MemReadWord (Regs.PC+1); if (PAGE_CROSS (Addr, Regs.XR)) { ++Cycles; } Regs.AC = MemReadByte (Addr + Regs.XR); TEST_ZF (Regs.AC); TEST_SF (Regs.AC); Regs.PC += 3; } static void OPC_6502_BE (void) /* Opcode $BE: LDX abs,y */ { unsigned Addr; Cycles = 4; Addr = MemReadWord (Regs.PC+1); if (PAGE_CROSS (Addr, Regs.YR)) { ++Cycles; } Regs.XR = MemReadByte (Addr + Regs.YR); TEST_ZF (Regs.XR); TEST_SF (Regs.XR); Regs.PC += 3; } static void OPC_6502_C0 (void) /* Opcode $C0: CPY #imm */ { Cycles = 2; CMP (Regs.YR, MemReadByte (Regs.PC+1)); Regs.PC += 2; } static void OPC_6502_C1 (void) /* Opcode $C1: CMP (zp,x) */ { unsigned char ZPAddr; unsigned Addr; Cycles = 6; ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; Addr = MemReadZPWord (ZPAddr); CMP (Regs.AC, MemReadByte (Addr)); Regs.PC += 2; } static void OPC_6502_C4 (void) /* Opcode $C4: CPY zp */ { unsigned char ZPAddr; Cycles = 3; ZPAddr = MemReadByte (Regs.PC+1); CMP (Regs.YR, MemReadByte (ZPAddr)); Regs.PC += 2; } static void OPC_6502_C5 (void) /* Opcode $C5: CMP zp */ { unsigned char ZPAddr; Cycles = 3; ZPAddr = MemReadByte (Regs.PC+1); CMP (Regs.AC, MemReadByte (ZPAddr)); Regs.PC += 2; } static void OPC_6502_C6 (void) /* Opcode $C6: DEC zp */ { unsigned char ZPAddr; unsigned char Val; Cycles = 5; ZPAddr = MemReadByte (Regs.PC+1); Val = MemReadByte (ZPAddr) - 1; MemWriteByte (ZPAddr, Val); TEST_ZF (Val); TEST_SF (Val); Regs.PC += 2; } static void OPC_6502_C8 (void) /* Opcode $C8: INY */ { Cycles = 2; Regs.YR = (Regs.YR + 1) & 0xFF; TEST_ZF (Regs.YR); TEST_SF (Regs.YR); Regs.PC += 1; } static void OPC_6502_C9 (void) /* Opcode $C9: CMP #imm */ { Cycles = 2; CMP (Regs.AC, MemReadByte (Regs.PC+1)); Regs.PC += 2; } static void OPC_6502_CA (void) /* Opcode $CA: DEX */ { Cycles = 2; Regs.XR = (Regs.XR - 1) & 0xFF; TEST_ZF (Regs.XR); TEST_SF (Regs.XR); Regs.PC += 1; } static void OPC_6502_CC (void) /* Opcode $CC: CPY abs */ { unsigned Addr; Cycles = 4; Addr = MemReadWord (Regs.PC+1); CMP (Regs.YR, MemReadByte (Addr)); Regs.PC += 3; } static void OPC_6502_CD (void) /* Opcode $CD: CMP abs */ { unsigned Addr; Cycles = 4; Addr = MemReadWord (Regs.PC+1); CMP (Regs.AC, MemReadByte (Addr)); Regs.PC += 3; } static void OPC_6502_CE (void) /* Opcode $CE: DEC abs */ { unsigned Addr; unsigned char Val; Cycles = 6; Addr = MemReadWord (Regs.PC+1); Val = MemReadByte (Addr) - 1; MemWriteByte (Addr, Val); TEST_ZF (Val); TEST_SF (Val); Regs.PC += 3; } static void OPC_6502_D0 (void) /* Opcode $D0: BNE */ { BRANCH (!GET_ZF ()); } static void OPC_6502_D1 (void) /* Opcode $D1: CMP (zp),y */ { unsigned ZPAddr; unsigned Addr; Cycles = 5; ZPAddr = MemReadByte (Regs.PC+1); Addr = MemReadWord (ZPAddr); if (PAGE_CROSS (Addr, Regs.YR)) { ++Cycles; } CMP (Regs.AC, MemReadByte (Addr + Regs.YR)); Regs.PC += 2; } static void OPC_65SC02_D2 (void) /* Opcode $D2: CMP (zp) */ { unsigned ZPAddr; unsigned Addr; Cycles = 5; ZPAddr = MemReadByte (Regs.PC+1); Addr = MemReadWord (ZPAddr); CMP (Regs.AC, MemReadByte (Addr)); Regs.PC += 2; } static void OPC_6502_D5 (void) /* Opcode $D5: CMP zp,x */ { unsigned char ZPAddr; Cycles = 4; ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; CMP (Regs.AC, MemReadByte (ZPAddr)); Regs.PC += 2; } static void OPC_6502_D6 (void) /* Opcode $D6: DEC zp,x */ { unsigned char ZPAddr; unsigned char Val; Cycles = 6; ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; Val = MemReadByte (ZPAddr) - 1; MemWriteByte (ZPAddr, Val); TEST_ZF (Val); TEST_SF (Val); Regs.PC += 2; } static void OPC_6502_D8 (void) /* Opcode $D8: CLD */ { Cycles = 2; SET_DF (0); Regs.PC += 1; } static void OPC_6502_D9 (void) /* Opcode $D9: CMP abs,y */ { unsigned Addr; Cycles = 4; Addr = MemReadWord (Regs.PC+1); if (PAGE_CROSS (Addr, Regs.YR)) { ++Cycles; } CMP (Regs.AC, MemReadByte (Addr + Regs.YR)); Regs.PC += 3; } static void OPC_65SC02_DA (void) /* Opcode $DA: PHX */ { Cycles = 3; PUSH (Regs.XR); Regs.PC += 1; } static void OPC_6502_DD (void) /* Opcode $DD: CMP abs,x */ { unsigned Addr; Cycles = 4; Addr = MemReadWord (Regs.PC+1); if (PAGE_CROSS (Addr, Regs.XR)) { ++Cycles; } CMP (Regs.AC, MemReadByte (Addr + Regs.XR)); Regs.PC += 3; } static void OPC_6502_DE (void) /* Opcode $DE: DEC abs,x */ { unsigned Addr; unsigned char Val; Cycles = 7; Addr = MemReadWord (Regs.PC+1) + Regs.XR; Val = MemReadByte (Addr) - 1; MemWriteByte (Addr, Val); TEST_ZF (Val); TEST_SF (Val); Regs.PC += 3; } static void OPC_6502_E0 (void) /* Opcode $E0: CPX #imm */ { Cycles = 2; CMP (Regs.XR, MemReadByte (Regs.PC+1)); Regs.PC += 2; } static void OPC_6502_E1 (void) /* Opcode $E1: SBC (zp,x) */ { unsigned char ZPAddr; unsigned Addr; Cycles = 6; ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; Addr = MemReadZPWord (ZPAddr); SBC (MemReadByte (Addr)); Regs.PC += 2; } static void OPC_6502_E4 (void) /* Opcode $E4: CPX zp */ { unsigned char ZPAddr; Cycles = 3; ZPAddr = MemReadByte (Regs.PC+1); CMP (Regs.XR, MemReadByte (ZPAddr)); Regs.PC += 2; } static void OPC_6502_E5 (void) /* Opcode $E5: SBC zp */ { unsigned char ZPAddr; Cycles = 3; ZPAddr = MemReadByte (Regs.PC+1); SBC (MemReadByte (ZPAddr)); Regs.PC += 2; } static void OPC_6502_E6 (void) /* Opcode $E6: INC zp */ { unsigned char ZPAddr; unsigned char Val; Cycles = 5; ZPAddr = MemReadByte (Regs.PC+1); Val = MemReadByte (ZPAddr) + 1; MemWriteByte (ZPAddr, Val); TEST_ZF (Val); TEST_SF (Val); Regs.PC += 2; } static void OPC_6502_E8 (void) /* Opcode $E8: INX */ { Cycles = 2; Regs.XR = (Regs.XR + 1) & 0xFF; TEST_ZF (Regs.XR); TEST_SF (Regs.XR); Regs.PC += 1; } static void OPC_6502_E9 (void) /* Opcode $E9: SBC #imm */ { Cycles = 2; SBC (MemReadByte (Regs.PC+1)); Regs.PC += 2; } static void OPC_6502_EA (void) /* Opcode $EA: NOP */ { /* This one is easy... */ Cycles = 2; Regs.PC += 1; } static void OPC_65C02_NOP11(void) /* Opcode 'Illegal' 1 cycle NOP */ { Cycles = 1; Regs.PC += 1; } static void OPC_65C02_NOP22 (void) /* Opcode 'Illegal' 2 byte 2 cycle NOP */ { Cycles = 2; Regs.PC += 2; } static void OPC_65C02_NOP24 (void) /* Opcode 'Illegal' 2 byte 4 cycle NOP */ { Cycles = 4; Regs.PC += 2; } static void OPC_65C02_NOP34 (void) /* Opcode 'Illegal' 3 byte 4 cycle NOP */ { Cycles = 4; Regs.PC += 3; } static void OPC_6502_EC (void) /* Opcode $EC: CPX abs */ { unsigned Addr; Cycles = 4; Addr = MemReadWord (Regs.PC+1); CMP (Regs.XR, MemReadByte (Addr)); Regs.PC += 3; } static void OPC_6502_ED (void) /* Opcode $ED: SBC abs */ { unsigned Addr; Cycles = 4; Addr = MemReadWord (Regs.PC+1); SBC (MemReadByte (Addr)); Regs.PC += 3; } static void OPC_6502_EE (void) /* Opcode $EE: INC abs */ { unsigned Addr; unsigned char Val; Cycles = 6; Addr = MemReadWord (Regs.PC+1); Val = MemReadByte (Addr) + 1; MemWriteByte (Addr, Val); TEST_ZF (Val); TEST_SF (Val); Regs.PC += 3; } static void OPC_6502_F0 (void) /* Opcode $F0: BEQ */ { BRANCH (GET_ZF ()); } static void OPC_6502_F1 (void) /* Opcode $F1: SBC (zp),y */ { unsigned char ZPAddr; unsigned Addr; Cycles = 5; ZPAddr = MemReadByte (Regs.PC+1); Addr = MemReadZPWord (ZPAddr); if (PAGE_CROSS (Addr, Regs.YR)) { ++Cycles; } SBC (MemReadByte (Addr + Regs.YR)); Regs.PC += 2; } static void OPC_65SC02_F2 (void) /* Opcode $F2: SBC (zp) */ { unsigned char ZPAddr; unsigned Addr; Cycles = 5; ZPAddr = MemReadByte (Regs.PC+1); Addr = MemReadZPWord (ZPAddr); SBC (MemReadByte (Addr)); Regs.PC += 2; } static void OPC_6502_F5 (void) /* Opcode $F5: SBC zp,x */ { unsigned char ZPAddr; Cycles = 4; ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; SBC (MemReadByte (ZPAddr)); Regs.PC += 2; } static void OPC_6502_F6 (void) /* Opcode $F6: INC zp,x */ { unsigned char ZPAddr; unsigned char Val; Cycles = 6; ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; Val = MemReadByte (ZPAddr) + 1; MemWriteByte (ZPAddr, Val); TEST_ZF (Val); TEST_SF (Val); Regs.PC += 2; } static void OPC_6502_F8 (void) /* Opcode $F8: SED */ { Cycles = 2; SET_DF (1); Regs.PC += 1; } static void OPC_6502_F9 (void) /* Opcode $F9: SBC abs,y */ { unsigned Addr; Cycles = 4; Addr = MemReadWord (Regs.PC+1); if (PAGE_CROSS (Addr, Regs.YR)) { ++Cycles; } SBC (MemReadByte (Addr + Regs.YR)); Regs.PC += 3; } static void OPC_65SC02_FA (void) /* Opcode $7A: PLX */ { Cycles = 4; Regs.XR = POP (); TEST_ZF (Regs.XR); TEST_SF (Regs.XR); Regs.PC += 1; } static void OPC_6502_FD (void) /* Opcode $FD: SBC abs,x */ { unsigned Addr; Cycles = 4; Addr = MemReadWord (Regs.PC+1); if (PAGE_CROSS (Addr, Regs.XR)) { ++Cycles; } SBC (MemReadByte (Addr + Regs.XR)); Regs.PC += 3; } static void OPC_6502_FE (void) /* Opcode $FE: INC abs,x */ { unsigned Addr; unsigned char Val; Cycles = 7; Addr = MemReadWord (Regs.PC+1) + Regs.XR; Val = MemReadByte (Addr) + 1; MemWriteByte (Addr, Val); TEST_ZF (Val); TEST_SF (Val); Regs.PC += 3; } /*****************************************************************************/ /* Opcode handler tables */ /*****************************************************************************/ /* Opcode handler table for the 6502 */ static const OPFunc OP6502Table[256] = { OPC_6502_00, OPC_6502_01, OPC_Illegal, OPC_Illegal, OPC_Illegal, OPC_6502_05, OPC_6502_06, OPC_Illegal, OPC_6502_08, OPC_6502_09, OPC_6502_0A, OPC_Illegal, OPC_Illegal, OPC_6502_0D, OPC_6502_0E, OPC_Illegal, OPC_6502_10, OPC_6502_11, OPC_Illegal, OPC_Illegal, OPC_Illegal, OPC_6502_15, OPC_6502_16, OPC_Illegal, OPC_6502_18, OPC_6502_19, OPC_Illegal, OPC_Illegal, OPC_Illegal, OPC_6502_1D, OPC_6502_1E, OPC_Illegal, OPC_6502_20, OPC_6502_21, OPC_Illegal, OPC_Illegal, OPC_6502_24, OPC_6502_25, OPC_6502_26, OPC_Illegal, OPC_6502_28, OPC_6502_29, OPC_6502_2A, OPC_Illegal, OPC_6502_2C, OPC_6502_2D, OPC_6502_2E, OPC_Illegal, OPC_6502_30, OPC_6502_31, OPC_Illegal, OPC_Illegal, OPC_Illegal, OPC_6502_35, OPC_6502_36, OPC_Illegal, OPC_6502_38, OPC_6502_39, OPC_Illegal, OPC_Illegal, OPC_Illegal, OPC_6502_3D, OPC_6502_3E, OPC_Illegal, OPC_6502_40, OPC_6502_41, OPC_Illegal, OPC_Illegal, OPC_Illegal, OPC_6502_45, OPC_6502_46, OPC_Illegal, OPC_6502_48, OPC_6502_49, OPC_6502_4A, OPC_Illegal, OPC_6502_4C, OPC_6502_4D, OPC_6502_4E, OPC_Illegal, OPC_6502_50, OPC_6502_51, OPC_Illegal, OPC_Illegal, OPC_Illegal, OPC_6502_55, OPC_6502_56, OPC_Illegal, OPC_6502_58, OPC_6502_59, OPC_Illegal, OPC_Illegal, OPC_Illegal, OPC_6502_5D, OPC_6502_5E, OPC_Illegal, OPC_6502_60, OPC_6502_61, OPC_Illegal, OPC_Illegal, OPC_Illegal, OPC_6502_65, OPC_6502_66, OPC_Illegal, OPC_6502_68, OPC_6502_69, OPC_6502_6A, OPC_Illegal, OPC_6502_6C, OPC_6502_6D, OPC_6502_6E, OPC_Illegal, OPC_6502_70, OPC_6502_71, OPC_Illegal, OPC_Illegal, OPC_Illegal, OPC_6502_75, OPC_6502_76, OPC_Illegal, OPC_6502_78, OPC_6502_79, OPC_Illegal, OPC_Illegal, OPC_Illegal, OPC_6502_7D, OPC_6502_7E, OPC_Illegal, OPC_Illegal, OPC_6502_81, OPC_Illegal, OPC_Illegal, OPC_6502_84, OPC_6502_85, OPC_6502_86, OPC_Illegal, OPC_6502_88, OPC_Illegal, OPC_6502_8A, OPC_Illegal, OPC_6502_8C, OPC_6502_8D, OPC_6502_8E, OPC_Illegal, OPC_6502_90, OPC_6502_91, OPC_Illegal, OPC_Illegal, OPC_6502_94, OPC_6502_95, OPC_6502_96, OPC_Illegal, OPC_6502_98, OPC_6502_99, OPC_6502_9A, OPC_Illegal, OPC_Illegal, OPC_6502_9D, OPC_Illegal, OPC_Illegal, OPC_6502_A0, OPC_6502_A1, OPC_6502_A2, OPC_Illegal, OPC_6502_A4, OPC_6502_A5, OPC_6502_A6, OPC_Illegal, OPC_6502_A8, OPC_6502_A9, OPC_6502_AA, OPC_Illegal, OPC_6502_AC, OPC_6502_AD, OPC_6502_AE, OPC_Illegal, OPC_6502_B0, OPC_6502_B1, OPC_Illegal, OPC_Illegal, OPC_6502_B4, OPC_6502_B5, OPC_6502_B6, OPC_Illegal, OPC_6502_B8, OPC_6502_B9, OPC_6502_BA, OPC_Illegal, OPC_6502_BC, OPC_6502_BD, OPC_6502_BE, OPC_Illegal, OPC_6502_C0, OPC_6502_C1, OPC_Illegal, OPC_Illegal, OPC_6502_C4, OPC_6502_C5, OPC_6502_C6, OPC_Illegal, OPC_6502_C8, OPC_6502_C9, OPC_6502_CA, OPC_Illegal, OPC_6502_CC, OPC_6502_CD, OPC_6502_CE, OPC_Illegal, OPC_6502_D0, OPC_6502_D1, OPC_Illegal, OPC_Illegal, OPC_Illegal, OPC_6502_D5, OPC_6502_D6, OPC_Illegal, OPC_6502_D8, OPC_6502_D9, OPC_Illegal, OPC_Illegal, OPC_Illegal, OPC_6502_DD, OPC_6502_DE, OPC_Illegal, OPC_6502_E0, OPC_6502_E1, OPC_Illegal, OPC_Illegal, OPC_6502_E4, OPC_6502_E5, OPC_6502_E6, OPC_Illegal, OPC_6502_E8, OPC_6502_E9, OPC_6502_EA, OPC_Illegal, OPC_6502_EC, OPC_6502_ED, OPC_6502_EE, OPC_Illegal, OPC_6502_F0, OPC_6502_F1, OPC_Illegal, OPC_Illegal, OPC_Illegal, OPC_6502_F5, OPC_6502_F6, OPC_Illegal, OPC_6502_F8, OPC_6502_F9, OPC_Illegal, OPC_Illegal, OPC_Illegal, OPC_6502_FD, OPC_6502_FE, OPC_Illegal, }; /* Opcode handler table for the 65C02 */ static const OPFunc OP65C02Table[256] = { OPC_6502_00, OPC_6502_01, OPC_65C02_NOP22, // $02 OPC_65C02_NOP11, // $03 OPC_65SC02_04, OPC_6502_05, OPC_6502_06, OPC_Illegal, // $07: RMB0 currently unsupported OPC_6502_08, OPC_6502_09, OPC_6502_0A, OPC_65C02_NOP11, // $0B OPC_65SC02_0C, OPC_6502_0D, OPC_6502_0E, OPC_Illegal, // $0F: BBR0 currently unsupported OPC_6502_10, OPC_6502_11, OPC_65SC02_12, OPC_65C02_NOP11, // $13 OPC_65SC02_14, OPC_6502_15, OPC_6502_16, OPC_Illegal, // $17: RMB1 currently unsupported OPC_6502_18, OPC_6502_19, OPC_65SC02_1A, OPC_65C02_NOP11, // $1B OPC_65SC02_1C, OPC_6502_1D, OPC_6502_1E, OPC_Illegal, // $1F: BBR1 currently unsupported OPC_6502_20, OPC_6502_21, OPC_65C02_NOP22, // $22 OPC_65C02_NOP11, // $23 OPC_6502_24, OPC_6502_25, OPC_6502_26, OPC_Illegal, // $27: RMB2 currently unsupported OPC_6502_28, OPC_6502_29, OPC_6502_2A, OPC_65C02_NOP11, // $2B OPC_6502_2C, OPC_6502_2D, OPC_6502_2E, OPC_Illegal, // $2F: BBR2 currently unsupported OPC_6502_30, OPC_6502_31, OPC_65SC02_32, OPC_65C02_NOP11, // $33 OPC_65SC02_34, OPC_6502_35, OPC_6502_36, OPC_Illegal, // $37: RMB3 currently unsupported OPC_6502_38, OPC_6502_39, OPC_65SC02_3A, OPC_65C02_NOP11, // $3B OPC_65SC02_3C, OPC_6502_3D, OPC_6502_3E, OPC_Illegal, // $3F: BBR3 currently unsupported OPC_6502_40, OPC_6502_41, OPC_65C02_NOP22, // $42 OPC_65C02_NOP11, // $43 OPC_65C02_44, // $44 OPC_6502_45, OPC_6502_46, OPC_Illegal, // $47: RMB4 currently unsupported OPC_6502_48, OPC_6502_49, OPC_6502_4A, OPC_65C02_NOP11, // $4B OPC_6502_4C, OPC_6502_4D, OPC_6502_4E, OPC_Illegal, // $4F: BBR4 currently unsupported OPC_6502_50, OPC_6502_51, OPC_65SC02_52, OPC_65C02_NOP11, // $53 OPC_65C02_NOP24, // $54 OPC_6502_55, OPC_6502_56, OPC_Illegal, // $57: RMB5 currently unsupported OPC_6502_58, OPC_6502_59, OPC_65SC02_5A, OPC_65C02_NOP11, // $5B OPC_65C02_5C, OPC_6502_5D, OPC_6502_5E, OPC_Illegal, // $5F: BBR5 currently unsupported OPC_6502_60, OPC_6502_61, OPC_65C02_NOP22, // $62 OPC_65C02_NOP11, // $63 OPC_65SC02_64, OPC_6502_65, OPC_6502_66, OPC_Illegal, // $67: RMB6 currently unsupported OPC_6502_68, OPC_6502_69, OPC_6502_6A, OPC_65C02_NOP11, // $6B OPC_65C02_6C, OPC_6502_6D, OPC_6502_6E, OPC_Illegal, // $6F: BBR6 currently unsupported OPC_6502_70, OPC_6502_71, OPC_65SC02_72, OPC_65C02_NOP11, // $73 OPC_65SC02_74, OPC_6502_75, OPC_6502_76, OPC_Illegal, // $77: RMB7 currently unsupported OPC_6502_78, OPC_6502_79, OPC_65SC02_7A, OPC_65C02_NOP11, // $7B OPC_65SC02_7C, OPC_6502_7D, OPC_6502_7E, OPC_Illegal, // $7F: BBR7 currently unsupported OPC_65SC02_80, OPC_6502_81, OPC_65C02_NOP22, // $82 OPC_65C02_NOP11, // $83 OPC_6502_84, OPC_6502_85, OPC_6502_86, OPC_Illegal, // $87: SMB0 currently unsupported OPC_6502_88, OPC_65SC02_89, OPC_6502_8A, OPC_65C02_NOP11, // $8B OPC_6502_8C, OPC_6502_8D, OPC_6502_8E, OPC_Illegal, // $8F: BBS0 currently unsupported OPC_6502_90, OPC_6502_91, OPC_65SC02_92, OPC_65C02_NOP11, // $93 OPC_6502_94, OPC_6502_95, OPC_6502_96, OPC_Illegal, // $97: SMB1 currently unsupported OPC_6502_98, OPC_6502_99, OPC_6502_9A, OPC_65C02_NOP11, // $9B OPC_65SC02_9C, OPC_6502_9D, OPC_65SC02_9E, OPC_Illegal, // $9F: BBS1 currently unsupported OPC_6502_A0, OPC_6502_A1, OPC_6502_A2, OPC_65C02_NOP11, // $A3 OPC_6502_A4, OPC_6502_A5, OPC_6502_A6, OPC_Illegal, // $A7: SMB2 currently unsupported OPC_6502_A8, OPC_6502_A9, OPC_6502_AA, OPC_65C02_NOP11, // $AB OPC_6502_AC, OPC_6502_AD, OPC_6502_AE, OPC_Illegal, // $AF: BBS2 currently unsupported OPC_6502_B0, OPC_6502_B1, OPC_65SC02_B2, OPC_65C02_NOP11, // $B3 OPC_6502_B4, OPC_6502_B5, OPC_6502_B6, OPC_Illegal, // $B7: SMB3 currently unsupported OPC_6502_B8, OPC_6502_B9, OPC_6502_BA, OPC_65C02_NOP11, // $BB OPC_6502_BC, OPC_6502_BD, OPC_6502_BE, OPC_Illegal, // $BF: BBS3 currently unsupported OPC_6502_C0, OPC_6502_C1, OPC_65C02_NOP22, // $C2 OPC_65C02_NOP11, // $C3 OPC_6502_C4, OPC_6502_C5, OPC_6502_C6, OPC_Illegal, // $C7: SMB4 currently unsupported OPC_6502_C8, OPC_6502_C9, OPC_6502_CA, OPC_Illegal, // $CB: WAI currently unsupported OPC_6502_CC, OPC_6502_CD, OPC_6502_CE, OPC_Illegal, // $CF: BBS4 currently unsupported OPC_6502_D0, OPC_6502_D1, OPC_65SC02_D2, OPC_65C02_NOP11, // $D3 OPC_65C02_NOP24, // $D4 OPC_6502_D5, OPC_6502_D6, OPC_Illegal, // $D7: SMB5 currently unsupported OPC_6502_D8, OPC_6502_D9, OPC_65SC02_DA, OPC_Illegal, // $DB: STP currently unsupported OPC_65C02_NOP34, // $DC OPC_6502_DD, OPC_6502_DE, OPC_Illegal, // $DF: BBS5 currently unsupported OPC_6502_E0, OPC_6502_E1, OPC_65C02_NOP22, // $E2 OPC_65C02_NOP11, // $E3 OPC_6502_E4, OPC_6502_E5, OPC_6502_E6, OPC_Illegal, // $E7: SMB6 currently unsupported OPC_6502_E8, OPC_6502_E9, OPC_6502_EA, OPC_65C02_NOP11, // $EB OPC_6502_EC, OPC_6502_ED, OPC_6502_EE, OPC_Illegal, // $EF: BBS6 currently unsupported OPC_6502_F0, OPC_6502_F1, OPC_65SC02_F2, OPC_65C02_NOP11, // $F3 OPC_65C02_NOP24, // $F4 OPC_6502_F5, OPC_6502_F6, OPC_Illegal, // $F7: SMB7 currently unsupported OPC_6502_F8, OPC_6502_F9, OPC_65SC02_FA, OPC_65C02_NOP11, // $FB OPC_65C02_NOP34, // $FC OPC_6502_FD, OPC_6502_FE, OPC_Illegal, // $FF: BBS7 currently unsupported }; /* Tables with opcode handlers */ static const OPFunc* Handlers[2] = {OP6502Table, OP65C02Table}; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void IRQRequest (void) /* Generate an IRQ */ { /* Remember the request */ HaveIRQRequest = 1; } void NMIRequest (void) /* Generate an NMI */ { /* Remember the request */ HaveNMIRequest = 1; } void Reset (void) /* Generate a CPU RESET */ { /* Reset the CPU */ HaveIRQRequest = 0; HaveNMIRequest = 0; /* Bits 5 and 4 aren't used, and always are 1! */ Regs.SR = 0x30; Regs.PC = MemReadWord (0xFFFC); } unsigned ExecuteInsn (void) /* Execute one CPU instruction */ { /* If we have an NMI request, handle it */ if (HaveNMIRequest) { HaveNMIRequest = 0; PUSH (PCH); PUSH (PCL); PUSH (Regs.SR & ~BF); SET_IF (1); if (CPU != CPU_6502) { SET_DF (0); } Regs.PC = MemReadWord (0xFFFA); Cycles = 7; } else if (HaveIRQRequest && GET_IF () == 0) { HaveIRQRequest = 0; PUSH (PCH); PUSH (PCL); PUSH (Regs.SR & ~BF); SET_IF (1); if (CPU != CPU_6502) { SET_DF (0); } Regs.PC = MemReadWord (0xFFFE); Cycles = 7; } else { /* Normal instruction - read the next opcode */ unsigned char OPC = MemReadByte (Regs.PC); /* Execute it */ Handlers[CPU][OPC] (); } /* Count cycles */ TotalCycles += Cycles; /* Return the number of clock cycles needed by this insn */ return Cycles; } unsigned long GetCycles (void) /* Return the total number of cycles executed */ { /* Return the total number of cycles */ return TotalCycles; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sim65/6502.h��������������������������������������������������������������������������0000664�0000000�0000000�00000010606�13473601511�0014507�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* 6502.h */ /* */ /* CPU core for the 6502 */ /* */ /* */ /* */ /* (C) 2003-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _6502_H #define _6502_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Supported CPUs */ typedef enum CPUType { CPU_6502, CPU_65C02 } CPUType; /* Current CPU */ extern CPUType CPU; /* 6502 CPU registers */ typedef struct CPURegs CPURegs; struct CPURegs { unsigned AC; /* Accumulator */ unsigned XR; /* X register */ unsigned YR; /* Y register */ unsigned ZR; /* Z register */ unsigned SR; /* Status register */ unsigned SP; /* Stackpointer */ unsigned PC; /* Program counter */ }; /* Status register bits */ #define CF 0x01 /* Carry flag */ #define ZF 0x02 /* Zero flag */ #define IF 0x04 /* Interrupt flag */ #define DF 0x08 /* Decimal flag */ #define BF 0x10 /* Break flag */ #define OF 0x40 /* Overflow flag */ #define SF 0x80 /* Sign flag */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Reset (void); /* Generate a CPU RESET */ void IRQRequest (void); /* Generate an IRQ */ void NMIRequest (void); /* Generate an NMI */ unsigned ExecuteInsn (void); /* Execute one CPU instruction. Return the number of clock cycles for the ** executed instruction. */ unsigned long GetCycles (void); /* Return the total number of clock cycles executed */ extern int PrintCycles; /* flag to print cycles at program termination */ /* End of 6502.h */ #endif ��������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sim65/error.c�������������������������������������������������������������������������0000664�0000000�0000000�00000007547�13473601511�0015251�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* error.c */ /* */ /* Error handling for the sim65 simulator */ /* */ /* */ /* */ /* (C) 2002-2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include "error.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Warning (const char* Format, ...) /* Print a warning message */ { va_list ap; va_start (ap, Format); fprintf (stderr, "Warning: "); vfprintf (stderr, Format, ap); putc ('\n', stderr); va_end (ap); } void Error (const char* Format, ...) /* Print an error message and die */ { va_list ap; va_start (ap, Format); fprintf (stderr, "Error: "); vfprintf (stderr, Format, ap); putc ('\n', stderr); va_end (ap); exit (SIM65_ERROR); } void ErrorCode (int Code, const char* Format, ...) /* Print an error message and die with the given exit code */ { va_list ap; va_start (ap, Format); fprintf (stderr, "Error: "); vfprintf (stderr, Format, ap); putc ('\n', stderr); va_end (ap); exit (Code); } void Internal (const char* Format, ...) /* Print an internal error message and die */ { va_list ap; va_start (ap, Format); fprintf (stderr, "Internal error: "); vfprintf (stderr, Format, ap); putc ('\n', stderr); va_end (ap); exit (SIM65_ERROR); } ���������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sim65/error.h�������������������������������������������������������������������������0000664�0000000�0000000�00000007422�13473601511�0015246�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* error.h */ /* */ /* Error handling for the sim65 simulator */ /* */ /* */ /* */ /* (C) 2002-2003 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef ERROR_H #define ERROR_H /* common */ #include "attrib.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ #define SIM65_ERROR 256 /* Does not use EXIT_FAILURE because it may overlap with test results. */ #define SIM65_ERROR_TIMEOUT 257 /* An error result for max CPU instructions exceeded. */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Warning (const char* Format, ...) attribute((format(printf,1,2))); /* Print a warning message */ void Error (const char* Format, ...) attribute((noreturn, format(printf,1,2))); /* Print an error message and die */ void ErrorCode (int Code, const char* Format, ...) attribute((noreturn, format(printf,2,3))); /* Print an error message and die with the given exit code */ void Internal (const char* Format, ...) attribute((noreturn, format(printf,1,2))); /* Print an internal error message and die */ /* End of error.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sim65/main.c��������������������������������������������������������������������������0000664�0000000�0000000�00000022723�13473601511�0015035�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* main.c */ /* */ /* sim65 main program */ /* */ /* */ /* */ /* (C) 2002-2009, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> #include <stdlib.h> #include <errno.h> /* common */ #include "abend.h" #include "cmdline.h" #include "print.h" #include "version.h" /* sim65 */ #include "6502.h" #include "error.h" #include "memory.h" #include "paravirt.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Name of program file */ const char* ProgramFile; /* exit simulator after MaxCycles Cycles */ unsigned long MaxCycles; /* Header signature 'sim65' */ static const unsigned char HeaderSignature[] = { 0x73, 0x69, 0x6D, 0x36, 0x35 }; #define HEADER_SIGNATURE_LENGTH (sizeof(HeaderSignature)/sizeof(HeaderSignature[0])) static const unsigned char HeaderVersion = 2; /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void Usage (void) { printf ("Usage: %s [options] file [arguments]\n" "Short options:\n" " -h\t\t\tHelp (this text)\n" " -c\t\t\tPrint amount of executed CPU cycles\n" " -v\t\t\tIncrease verbosity\n" " -V\t\t\tPrint the simulator version number\n" " -x <num>\t\tExit simulator after <num> cycles\n" "\n" "Long options:\n" " --help\t\tHelp (this text)\n" " --cycles\t\tPrint amount of executed CPU cycles\n" " --verbose\t\tIncrease verbosity\n" " --version\t\tPrint the simulator version number\n", ProgName); } static void OptHelp (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Print usage information and exit */ { Usage (); exit (EXIT_SUCCESS); } static void OptVerbose (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Increase verbosity */ { ++Verbosity; } static void OptCycles (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Set flag to print amount of cycles at the end */ { PrintCycles = 1; } static void OptVersion (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Print the simulator version */ { fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ()); exit(EXIT_SUCCESS); } static void OptQuitXIns (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* quit after MaxCycles cycles */ { MaxCycles = strtoul(Arg, NULL, 0); } static unsigned char ReadProgramFile (void) /* Load program into memory */ { unsigned I; int Val, Val2; int Version; unsigned Addr; unsigned Load, Reset; unsigned char SPAddr = 0x00; /* Open the file */ FILE* F = fopen (ProgramFile, "rb"); if (F == 0) { Error ("Cannot open '%s': %s", ProgramFile, strerror (errno)); } /* Verify the header signature */ for (I = 0; I < HEADER_SIGNATURE_LENGTH; ++I) { if ((Val = fgetc(F)) != HeaderSignature[I]) { Error ("'%s': Invalid header signature.", ProgramFile); } } /* Get header version */ if ((Version = fgetc(F)) != HeaderVersion) { Error ("'%s': Invalid header version.", ProgramFile); } /* Get the CPU type from the file header */ if ((Val = fgetc(F)) != EOF) { if (Val != CPU_6502 && Val != CPU_65C02) { Error ("'%s': Invalid CPU type", ProgramFile); } CPU = Val; } /* Get the address of sp from the file header */ if ((Val = fgetc(F)) != EOF) { SPAddr = Val; } /* Get load address */ if (((Val = fgetc(F)) == EOF) || ((Val2 = fgetc(F)) == EOF)) { Error ("'%s': Header missing load address", ProgramFile); } Load = Val | (Val2 << 8); /* Get reset address */ if (((Val = fgetc(F)) == EOF) || ((Val2 = fgetc(F)) == EOF)) { Error ("'%s': Header missing reset address", ProgramFile); } Reset = Val | (Val2 << 8); /* Read the file body into memory */ Addr = Load; while ((Val = fgetc(F)) != EOF) { if (Addr == 0xFF00) { Error ("'%s': To large to fit into $%04X-$FFF0", ProgramFile, Addr); } MemWriteByte (Addr++, (unsigned char) Val); } /* Check for errors */ if (ferror (F)) { Error ("Error reading from '%s': %s", ProgramFile, strerror (errno)); } /* Close the file */ fclose (F); Print (stderr, 1, "Loaded '%s' at $%04X-$%04X\n", ProgramFile, Load, Addr - 1); Print (stderr, 1, "File version: %d\n", Version); Print (stderr, 1, "Reset: $%04X\n", Reset); MemWriteWord(0xFFFC, Reset); return SPAddr; } int main (int argc, char* argv[]) { /* Program long options */ static const LongOpt OptTab[] = { { "--help", 0, OptHelp }, { "--cycles", 0, OptCycles }, { "--verbose", 0, OptVerbose }, { "--version", 0, OptVersion }, }; unsigned I; unsigned char SPAddr; /* Initialize the cmdline module */ InitCmdLine (&argc, &argv, "sim65"); /* Parse the command line */ I = 1; while (I < ArgCount) { /* Get the argument */ const char* Arg = ArgVec[I]; /* Check for an option */ if (Arg [0] == '-') { switch (Arg [1]) { case '-': LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0])); break; case 'h': case '?': OptHelp (Arg, 0); break; case 'c': OptCycles (Arg, 0); break; case 'v': OptVerbose (Arg, 0); break; case 'V': OptVersion (Arg, 0); break; case 'x': OptQuitXIns (Arg, GetArg (&I, 2)); break; default: UnknownOption (Arg); break; } } else { ProgramFile = Arg; break; } /* Next argument */ ++I; } /* Do we have a program file? */ if (ProgramFile == 0) { AbEnd ("No program file"); } MemInit (); SPAddr = ReadProgramFile (); ParaVirtInit (I, SPAddr); Reset (); while (1) { ExecuteInsn (); if (MaxCycles && (GetCycles () >= MaxCycles)) { ErrorCode (SIM65_ERROR_TIMEOUT, "Maximum number of cycles reached."); } } /* Return an apropriate exit code */ return EXIT_SUCCESS; } ���������������������������������������������cc65-2.18/src/sim65/memory.c������������������������������������������������������������������������0000664�0000000�0000000�00000010106�13473601511�0015411�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* memory.h */ /* */ /* Memory subsystem for the 6502 simulator */ /* */ /* */ /* */ /* (C) 2002-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> #include "memory.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* THE memory */ static unsigned char Mem[0x10000]; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void MemWriteByte (unsigned Addr, unsigned char Val) /* Write a byte to a memory location */ { Mem[Addr] = Val; } void MemWriteWord (unsigned Addr, unsigned Val) /* Write a word to a memory location */ { MemWriteByte (Addr, Val & 0xFF); MemWriteByte (Addr + 1, Val >> 8); } unsigned char MemReadByte (unsigned Addr) /* Read a byte from a memory location */ { return Mem[Addr]; } unsigned MemReadWord (unsigned Addr) /* Read a word from a memory location */ { unsigned W = MemReadByte (Addr++); return (W | (MemReadByte (Addr) << 8)); } unsigned MemReadZPWord (unsigned char Addr) /* Read a word from the zero page. This function differs from MemReadWord in that ** the read will always be in the zero page, even in case of an address ** overflow. */ { unsigned W = MemReadByte (Addr++); return (W | (MemReadByte (Addr) << 8)); } void MemInit (void) /* Initialize the memory subsystem */ { /* Fill memory with illegal opcode */ memset (Mem, 0xFF, sizeof (Mem)); } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sim65/memory.h������������������������������������������������������������������������0000664�0000000�0000000�00000006655�13473601511�0015434�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* memory.h */ /* */ /* Memory subsystem for the 6502 simulator */ /* */ /* */ /* */ /* (C) 2002-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef MEMORY_H #define MEMORY_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ void MemWriteByte (unsigned Addr, unsigned char Val); /* Write a byte to a memory location */ void MemWriteWord (unsigned Addr, unsigned Val); /* Write a word to a memory location */ unsigned char MemReadByte (unsigned Addr); /* Read a byte from a memory location */ unsigned MemReadWord (unsigned Addr); /* Read a word from a memory location */ unsigned MemReadZPWord (unsigned char Addr); /* Read a word from the zero page. This function differs from MemReadWord in that ** the read will always be in the zero page, even in case of an address ** overflow. */ void MemInit (void); /* Initialize the memory subsystem */ /* End of memory.h */ #endif �����������������������������������������������������������������������������������cc65-2.18/src/sim65/paravirt.c����������������������������������������������������������������������0000664�0000000�0000000�00000017670�13473601511�0015746�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* paravirt.c */ /* */ /* Paravirtualization for the sim65 6502 simulator */ /* */ /* */ /* */ /* (C) 2013-2013 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <sys/stat.h> #if defined(_WIN32) # define O_INITIAL O_BINARY #else # define O_INITIAL 0 #endif #if defined(_MSC_VER) /* Microsoft compiler */ # include <io.h> #else /* Anyone else */ # include <unistd.h> #endif #ifndef S_IREAD # define S_IREAD S_IRUSR #endif #ifndef S_IWRITE # define S_IWRITE S_IWUSR #endif /* common */ #include "cmdline.h" #include "print.h" #include "xmalloc.h" /* sim65 */ #include "6502.h" #include "memory.h" #include "paravirt.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ typedef void (*PVFunc) (CPURegs* Regs); static unsigned ArgStart; static unsigned char SPAddr; /*****************************************************************************/ /* Code */ /*****************************************************************************/ static unsigned GetAX (CPURegs* Regs) { return Regs->AC + (Regs->XR << 8); } static void SetAX (CPURegs* Regs, unsigned Val) { Regs->AC = Val & 0xFF; Val >>= 8; Regs->XR = Val; } static unsigned char Pop (CPURegs* Regs) { return MemReadByte (0x0100 + ++Regs->SP); } static unsigned PopParam (unsigned char Incr) { unsigned SP = MemReadZPWord (SPAddr); unsigned Val = MemReadWord (SP); MemWriteWord (SPAddr, SP + Incr); return Val; } static void PVExit (CPURegs* Regs) { Print (stderr, 1, "PVExit ($%02X)\n", Regs->AC); if (PrintCycles) { Print (stdout, 0, "%lu cycles\n", GetCycles ()); } exit (Regs->AC); } static void PVArgs (CPURegs* Regs) { unsigned ArgC = ArgCount - ArgStart; unsigned ArgV = GetAX (Regs); unsigned SP = MemReadZPWord (SPAddr); unsigned Args = SP - (ArgC + 1) * 2; Print (stderr, 2, "PVArgs ($%04X)\n", ArgV); MemWriteWord (ArgV, Args); SP = Args; while (ArgStart < ArgCount) { unsigned I = 0; const char* Arg = ArgVec[ArgStart++]; SP -= strlen (Arg) + 1; do { MemWriteByte (SP + I, Arg[I]); } while (Arg[I++]); MemWriteWord (Args, SP); Args += 2; } MemWriteWord (Args, SPAddr); MemWriteWord (SPAddr, SP); SetAX (Regs, ArgC); } static void PVOpen (CPURegs* Regs) { char Path[1024]; int OFlag = O_INITIAL; int OMode = 0; unsigned RetVal, I = 0; unsigned Mode = PopParam (Regs->YR - 4); unsigned Flags = PopParam (2); unsigned Name = PopParam (2); if (Regs->YR - 4 < 2) { /* If the caller didn't supply the mode ** argument, use a reasonable default. */ Mode = 0x01 | 0x02; } do { Path[I] = MemReadByte (Name++); } while (Path[I++]); Print (stderr, 2, "PVOpen (\"%s\", $%04X)\n", Path, Flags); switch (Flags & 0x03) { case 0x01: OFlag |= O_RDONLY; break; case 0x02: OFlag |= O_WRONLY; break; case 0x03: OFlag |= O_RDWR; break; } if (Flags & 0x10) { OFlag |= O_CREAT; } if (Flags & 0x20) { OFlag |= O_TRUNC; } if (Flags & 0x40) { OFlag |= O_APPEND; } if (Flags & 0x80) { OFlag |= O_EXCL; } if (Mode & 0x01) { OMode |= S_IREAD; } if (Mode & 0x02) { OMode |= S_IWRITE; } RetVal = open (Path, OFlag, OMode); SetAX (Regs, RetVal); } static void PVClose (CPURegs* Regs) { unsigned RetVal; unsigned FD = GetAX (Regs); Print (stderr, 2, "PVClose ($%04X)\n", FD); RetVal = close (FD); SetAX (Regs, RetVal); } static void PVRead (CPURegs* Regs) { unsigned char* Data; unsigned RetVal, I = 0; unsigned Count = GetAX (Regs); unsigned Buf = PopParam (2); unsigned FD = PopParam (2); Print (stderr, 2, "PVRead ($%04X, $%04X, $%04X)\n", FD, Buf, Count); Data = xmalloc (Count); RetVal = read (FD, Data, Count); if (RetVal != (unsigned) -1) { while (I < RetVal) { MemWriteByte (Buf++, Data[I++]); } } xfree (Data); SetAX (Regs, RetVal); } static void PVWrite (CPURegs* Regs) { unsigned char* Data; unsigned RetVal, I = 0; unsigned Count = GetAX (Regs); unsigned Buf = PopParam (2); unsigned FD = PopParam (2); Print (stderr, 2, "PVWrite ($%04X, $%04X, $%04X)\n", FD, Buf, Count); Data = xmalloc (Count); while (I < Count) { Data[I++] = MemReadByte (Buf++); } RetVal = write (FD, Data, Count); xfree (Data); SetAX (Regs, RetVal); } static const PVFunc Hooks[] = { PVOpen, PVClose, PVRead, PVWrite, PVArgs, PVExit, }; void ParaVirtInit (unsigned aArgStart, unsigned char aSPAddr) /* Initialize the paravirtualization subsystem */ { ArgStart = aArgStart; SPAddr = aSPAddr; }; void ParaVirtHooks (CPURegs* Regs) /* Potentially execute paravirtualization hooks */ { /* Check for paravirtualization address range */ if (Regs->PC < 0xFFF4 || Regs->PC >= 0xFFF4 + sizeof (Hooks) / sizeof (Hooks[0])) { return; } /* Call paravirtualization hook */ Hooks[Regs->PC - 0xFFF4] (Regs); /* Simulate RTS */ Regs->PC = Pop(Regs) + (Pop(Regs) << 8) + 1; } ������������������������������������������������������������������������cc65-2.18/src/sim65/paravirt.h����������������������������������������������������������������������0000664�0000000�0000000�00000006013�13473601511�0015740�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* paravirt.h */ /* */ /* Paravirtualization for the sim65 6502 simulator */ /* */ /* */ /* */ /* (C) 2013-2013 Ullrich von Bassewitz */ /* Römerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef PARAVIRT_H #define PARAVIRT_H /*****************************************************************************/ /* Code */ /*****************************************************************************/ void ParaVirtInit (unsigned aArgStart, unsigned char aSPAddr); /* Initialize the paravirtualization subsystem */ void ParaVirtHooks (CPURegs* Regs); /* Potentially execute paravirtualization hooks */ /* End of paravirt.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65.vcxproj��������������������������������������������������������������������������0000664�0000000�0000000�00000013333�13473601511�0015211�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="utf-8"?> <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> <ProjectConfiguration Include="Release|Win32"> <Configuration>Release</Configuration> <Platform>Win32</Platform> </ProjectConfiguration> </ItemGroup> <PropertyGroup Label="Globals"> <ProjectGuid>{4388D1AF-C7EA-4AD4-8E80-CA1FB7BF76BF}</ProjectGuid> <Keyword>Win32Proj</Keyword> <RootNamespace>sp65</RootNamespace> <WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <UseDebugLibraries>true</UseDebugLibraries> <PlatformToolset>v141</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <UseDebugLibraries>false</UseDebugLibraries> <WholeProgramOptimization>true</WholeProgramOptimization> <PlatformToolset>v141</PlatformToolset> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> <PropertyGroup Label="UserMacros" /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <LinkIncremental>true</LinkIncremental> <OutDir>$(SolutionDir)..\bin\</OutDir> <IntDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</IntDir> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <OutDir>$(SolutionDir)..\bin\</OutDir> <IntDir>$(SolutionDir)..\wrk\$(ProjectName)\$(Configuration)\</IntDir> </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ClCompile> <PrecompiledHeader> </PrecompiledHeader> <WarningLevel>Level3</WarningLevel> <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;_DEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> <Link> <SubSystem>Console</SubSystem> <GenerateDebugInformation>true</GenerateDebugInformation> <AdditionalDependencies>$(IntDir)..\..\common\$(Configuration)\common.lib</AdditionalDependencies> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ClCompile> <WarningLevel>Level3</WarningLevel> <PrecompiledHeader> </PrecompiledHeader> <PreprocessorDefinitions>_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CONSOLE;NDEBUG</PreprocessorDefinitions> <AdditionalIncludeDirectories>common</AdditionalIncludeDirectories> <TreatWarningAsError>true</TreatWarningAsError> </ClCompile> <Link> <SubSystem>Console</SubSystem> <GenerateDebugInformation>false</GenerateDebugInformation> <AdditionalDependencies>$(IntDir)..\..\common\$(Configuration)\common.lib</AdditionalDependencies> </Link> </ItemDefinitionGroup> <ItemGroup> <ClCompile Include="sp65\asm.c" /> <ClCompile Include="sp65\attr.c" /> <ClCompile Include="sp65\bin.c" /> <ClCompile Include="sp65\bitmap.c" /> <ClCompile Include="sp65\c.c" /> <ClCompile Include="sp65\color.c" /> <ClCompile Include="sp65\convert.c" /> <ClCompile Include="sp65\error.c" /> <ClCompile Include="sp65\fileio.c" /> <ClCompile Include="sp65\geosbitmap.c" /> <ClCompile Include="sp65\geosicon.c" /> <ClCompile Include="sp65\input.c" /> <ClCompile Include="sp65\koala.c" /> <ClCompile Include="sp65\lynxsprite.c" /> <ClCompile Include="sp65\main.c" /> <ClCompile Include="sp65\output.c" /> <ClCompile Include="sp65\palette.c" /> <ClCompile Include="sp65\pcx.c" /> <ClCompile Include="sp65\raw.c" /> <ClCompile Include="sp65\vic2sprite.c" /> </ItemGroup> <ItemGroup> <ClInclude Include="sp65\asm.h" /> <ClInclude Include="sp65\attr.h" /> <ClInclude Include="sp65\bin.h" /> <ClInclude Include="sp65\bitmap.h" /> <ClInclude Include="sp65\c.h" /> <ClInclude Include="sp65\color.h" /> <ClInclude Include="sp65\convert.h" /> <ClInclude Include="sp65\error.h" /> <ClInclude Include="sp65\fileio.h" /> <ClInclude Include="sp65\geosbitmap.h" /> <ClInclude Include="sp65\geosicon.h" /> <ClInclude Include="sp65\input.h" /> <ClInclude Include="sp65\koala.h" /> <ClInclude Include="sp65\lynxsprite.h" /> <ClInclude Include="sp65\output.h" /> <ClInclude Include="sp65\palette.h" /> <ClInclude Include="sp65\pcx.h" /> <ClInclude Include="sp65\pixel.h" /> <ClInclude Include="sp65\raw.h" /> <ClInclude Include="sp65\vic2sprite.h" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> </ImportGroup> </Project>�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/���������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0013571�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/asm.c����������������������������������������������������������������������������0000664�0000000�0000000�00000017141�13473601511�0014521�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* asm.c */ /* */ /* Assembler output for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <errno.h> #include <stdio.h> #include <string.h> /* common */ #include "chartype.h" #include "check.h" #include "cmdline.h" #include "version.h" /* sp65 */ #include "attr.h" #include "asm.h" #include "error.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ static int ValidIdentifier (const char* L) /* Check an assembler label for validity */ { /* Must begin with underscore or alphabetic character */ if (*L != '_' && !IsAlpha (*L)) { return 0; } ++L; /* Remainder must be as above plus digits */ while (*L) { if (*L != '_' && !IsAlNum (*L)) { return 0; } ++L; } /* Ok */ return 1; } static unsigned GetBytesPerLine (const Collection* A) /* Return the number of bytes per line from the attribute collection A */ { char C; unsigned BytesPerLine = 16; /* Check for a bytesperline attribute */ const char* V = GetAttrVal (A, "bytesperline"); if ((V && sscanf (V, "%u%c", &BytesPerLine, &C) != 1) || (BytesPerLine < 1 || BytesPerLine > 64)) { Error ("Invalid value for attribute 'bytesperline'"); } return BytesPerLine; } static unsigned GetBase (const Collection* A) /* Return the number base from the attribute collection A */ { char C; unsigned Base = 16; /* Check for a base attribute */ const char* V = GetAttrVal (A, "base"); if ((V && sscanf (V, "%u%c", &Base, &C) != 1) || (Base != 2 && Base != 10 && Base != 16)) { Error ("Invalid value for attribute 'base'"); } return Base; } static const char* GetIdentifier (const Collection* A) /* Return the label identifier from the attribute collection A */ { /* Check for a ident attribute */ const char* Ident = GetAttrVal (A, "ident"); if (Ident && !ValidIdentifier (Ident)) { Error ("Invalid value for attribute 'ident'"); } return Ident; } void WriteAsmFile (const StrBuf* Data, const Collection* A, const Bitmap* B) /* Write the contents of Data to the given file in assembler (ca65) format */ { FILE* F; const char* D; unsigned Size; /* Get the name of the image */ const StrBuf* S = GetBitmapName (B); /* Get the file name */ const char* Name = NeedAttrVal (A, "name", "write"); /* Check the number of bytes per line */ unsigned BytesPerLine = GetBytesPerLine (A); /* Get the number base */ unsigned Base = GetBase (A); /* Get the identifier */ const char* Ident = GetIdentifier (A); /* Open the output file */ F = fopen (Name, "w"); if (F == 0) { Error ("Cannot open output file '%s': %s", Name, strerror (errno)); } /* Write a readable header */ fprintf (F, ";\n" "; This file was generated by %s %s from\n" "; %.*s (%ux%u, %u colors%s)\n" ";\n" "\n", ProgName, GetVersionAsString (), SB_GetLen (S), SB_GetConstBuf (S), GetBitmapWidth (B), GetBitmapHeight (B), GetBitmapColors (B), BitmapIsIndexed (B)? ", indexed" : ""); /* If we have an assembler label, output that */ if (Ident) { fprintf (F, ".proc %s\n" " COLORS = %u\n" " WIDTH = %u\n" " HEIGHT = %u\n", Ident, GetBitmapColors (B), GetBitmapWidth (B), GetBitmapHeight (B)); } /* Write the data */ D = SB_GetConstBuf (Data); Size = SB_GetLen (Data); while (Size) { unsigned I; /* Output one line */ unsigned Chunk = Size; if (Chunk > BytesPerLine) { Chunk = BytesPerLine; } fputs (" .byte ", F); for (I = 0; I < Chunk; ++I) { unsigned char V = *D++; if (I > 0) { fputc (',', F); } switch (Base) { case 2: fprintf (F, "%%%u%u%u%u%u%u%u%u", (V >> 7) & 0x01, (V >> 6) & 0x01, (V >> 5) & 0x01, (V >> 4) & 0x01, (V >> 3) & 0x01, (V >> 2) & 0x01, (V >> 1) & 0x01, (V >> 0) & 0x01); break; case 10: fprintf (F, "%u", V); break; case 16: fprintf (F, "$%02X", V); break; } } fputc ('\n', F); /* Bump the counters */ Size -= Chunk; } /* Terminate the .proc if we had an identifier */ if (Ident) { fputs (".endproc\n", F); } /* Add an empty line at the end */ fputc ('\n', F); /* Close the file */ if (fclose (F) != 0) { Error ("Error closing output file '%s': %s", Name, strerror (errno)); } } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/asm.h����������������������������������������������������������������������������0000664�0000000�0000000�00000006035�13473601511�0014526�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* asm.h */ /* */ /* Assembler output for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef ASM_H #define ASM_H /* common */ #include "coll.h" #include "strbuf.h" /* sp65 */ #include "bitmap.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void WriteAsmFile (const StrBuf* Data, const Collection* A, const Bitmap* B); /* Write the contents of Data to a file in assembler (ca65) format */ /* End of asm.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/attr.c���������������������������������������������������������������������������0000664�0000000�0000000�00000022266�13473601511�0014717�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* attr.c */ /* */ /* Command line attributes */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <string.h> /* common */ #include "chartype.h" #include "strbuf.h" #include "xmalloc.h" /* sp65 */ #include "attr.h" #include "error.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ Attr* NewAttr (const char* Name, const char* Value) /* Create a new attribute */ { /* Determine the string lengths */ unsigned NameLen = strlen (Name); unsigned ValueLen = strlen (Value); /* Allocate memory */ Attr* A = xmalloc (sizeof (Attr) + ValueLen + NameLen + 1); /* Initialize the fields */ A->Name = A->Value + ValueLen + 1; memcpy (A->Value, Value, ValueLen + 1); memcpy (A->Name, Name, NameLen + 1); /* Return the new struct */ return A; } void FreeAttr (Attr* A) /* Free an attribute structure */ { xfree (A); } void DumpAttrColl (const Collection* C) /* Dump a collection of attribute/value pairs for debugging */ { unsigned I; for (I = 0; I < CollCount (C); ++I) { const Attr* A = CollConstAt (C, I); printf ("%s=%s\n", A->Name, A->Value); } } int FindAttr (const Collection* C, const char* Name, unsigned* Index) /* Search for an attribute with the given name in the collection. If it is ** found, the function returns true and Index contains the index of the ** entry. If Name isn't found, the function returns false and Index ** will contain the insert position. */ { /* Do a binary search */ int Lo = 0; int Hi = (int) CollCount (C) - 1; while (Lo <= Hi) { /* Mid of range */ int Cur = (Lo + Hi) / 2; /* Get item */ const Attr* A = CollAt (C, Cur); /* Compare */ int Res = strcmp (A->Name, Name); /* Found? */ if (Res < 0) { Lo = Cur + 1; } else if (Res > 0) { Hi = Cur - 1; } else { /* Found! */ *Index = Cur; return 1; } } /* Pass back the insert position */ *Index = Lo; return 0; } const Attr* GetAttr (const Collection* C, const char* Name) /* Search for an attribute with the given name and return it. The function ** returns NULL if the attribute wasn't found. */ { /* Search for the attribute and return it */ unsigned Index; if (FindAttr (C, Name, &Index)) { return CollConstAt (C, Index); } else { /* Not found */ return 0; } } const Attr* NeedAttr (const Collection* C, const char* Name, const char* Op) /* Search for an attribute with the given name and return it. If the attribute ** is not found, the function terminates with an error using Op as additional ** context in the error message. */ { /* Search for the attribute and return it */ unsigned Index; if (!FindAttr (C, Name, &Index)) { Error ("Found no attribute named '%s' for operation %s", Name, Op); } return CollConstAt (C, Index); } const char* GetAttrVal (const Collection* C, const char* Name) /* Search for an attribute with the given name and return its value. The ** function returns NULL if the attribute wasn't found. */ { const Attr* A = GetAttr (C, Name); return (A == 0)? 0 : A->Value; } const char* NeedAttrVal (const Collection* C, const char* Name, const char* Op) /* Search for an attribute with the given name and return its value. If the ** attribute wasn't not found, the function terminates with an error using ** Op as additional context in the error message. */ { const Attr* A = NeedAttr (C, Name, Op); return (A == 0)? 0 : A->Value; } void AddAttr (Collection* C, const char* Name, const char* Value) /* Add an attribute to an alphabetically sorted attribute collection */ { /* Create a new attribute entry */ Attr* A = NewAttr (Name, Value); /* Search for the attribute. If it is there, we have a duplicate, otherwise ** we have the insert position. */ unsigned Index; if (FindAttr (C, Name, &Index)) { Error ("Duplicate command line attribute '%s'", Name); } /* Insert the attribute */ CollInsert (C, A, Index); } void SplitAddAttr (Collection* C, const char* Combined, const char* Name) /* Split a combined name/value pair and add it as an attribute to C. Some ** attributes may not need a name. If the name is missing, use Name. If ** Name is NULL, terminate with an error. */ { /* Name and value are separated by an equal sign */ const char* Pos = strchr (Combined, '='); if (Pos == 0) { /* Combined is actually a value */ if (Name == 0) { Error ("Command line attribute '%s' doesn't contain a name", Combined); } AddAttr (C, Name, Combined); } else { /* Must split name and value */ StrBuf N = AUTO_STRBUF_INITIALIZER; SB_CopyBuf (&N, Combined, Pos - Combined); SB_Terminate (&N); /* Add the attribute */ AddAttr (C, SB_GetConstBuf (&N), Pos+1); /* Release memory */ SB_Done (&N); } } Collection* ParseAttrList (const char* List, const char* const* NameList, unsigned NameCount) /* Parse a list containing name/value pairs into a sorted collection. Some ** attributes may not need a name, so NameList contains these names. If there ** were no errors, the function returns a alphabetically sorted collection ** containing Attr entries. */ { const char* Name; /* Create a new collection */ Collection* C = NewCollection (); /* Name/value pairs are separated by commas */ const char* L = List; StrBuf B = AUTO_STRBUF_INITIALIZER; while (1) { if (*L == ',' || *L == ':' || *L == '\0') { /* Terminate the string */ SB_Terminate (&B); /* Determine the default name */ if (CollCount (C) >= NameCount) { Name = 0; } else { Name = NameList[CollCount (C)]; } /* Split and add this attribute/value pair */ SplitAddAttr (C, SB_GetConstBuf (&B), Name); /* Done, clear the buffer. */ SB_Clear (&B); if (*L == '\0') { break; } } else { SB_AppendChar (&B, *L); } ++L; } /* Free memory */ SB_Done (&B); /* Return the collection with the attributes */ return C; } void FreeAttrList (Collection* C) /* Free a list of attributes */ { unsigned I; /* Walk over the collection and free all attributes */ for (I = 0; I < CollCount (C); ++I) { FreeAttr (CollAtUnchecked (C, I)); } /* Free the collection itself */ FreeCollection (C); } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/attr.h���������������������������������������������������������������������������0000664�0000000�0000000�00000013125�13473601511�0014716�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* attr.h */ /* */ /* Command line attributes */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef ATTRCOLL_H #define ATTRCOLL_H /* common */ #include "coll.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Attribute structure */ typedef struct Attr Attr; struct Attr { char* Name; /* Attribute name - points into Value */ char Value[1]; /* Attribute value followed by Name */ }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ Attr* NewAttr (const char* Name, const char* Value); /* Create a new attribute */ void FreeAttr (Attr* A); /* Free an attribute structure */ void DumpAttrColl (const Collection* C); /* Dump a collection of attribute/value pairs for debugging */ int FindAttr (const Collection* C, const char* Name, unsigned* Index); /* Search for an attribute with the given name in the collection. If it is ** found, the function returns true and Index contains the index of the ** entry. If Name isn't found, the function returns false and Index ** will contain the insert position. */ const Attr* GetAttr (const Collection* C, const char* Name); /* Search for an attribute with the given name and return it. The function ** returns NULL if the attribute wasn't found. */ const Attr* NeedAttr (const Collection* C, const char* Name, const char* Op); /* Search for an attribute with the given name and return it. If the attribute ** is not found, the function terminates with an error using Op as additional ** context in the error message. */ const char* GetAttrVal (const Collection* C, const char* Name); /* Search for an attribute with the given name and return its value. The ** function returns NULL if the attribute wasn't found. */ const char* NeedAttrVal (const Collection* C, const char* Name, const char* Op); /* Search for an attribute with the given name and return its value. If the ** attribute wasn't not found, the function terminates with an error using ** Op as additional context in the error message. */ void AddAttr (Collection* C, const char* Name, const char* Value); /* Add an attribute to an alphabetically sorted attribute collection */ void SplitAddAttr (Collection* C, const char* Combined, const char* Name); /* Split a combined name/value pair and add it as an attribute to C. Some ** attributes may not need a name. If the name is missing, use Name. If ** Name is NULL, terminate with an error. */ Collection* ParseAttrList (const char* List, const char* const* NameList, unsigned NameCount); /* Parse a list containing name/value pairs into a sorted collection. Some ** attributes may not need a name, so NameList contains these names. If there ** were no errors, the function returns a alphabetically sorted collection ** containing Attr entries. */ void FreeAttrList (Collection* C); /* Free a list of attributes */ /* End of attr.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/bin.c����������������������������������������������������������������������������0000664�0000000�0000000�00000007626�13473601511�0014520�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* bin.c */ /* */ /* Binary file output for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <errno.h> #include <stdio.h> #include <string.h> /* common */ #include "attrib.h" /* sp65 */ #include "attr.h" #include "bin.h" #include "error.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void WriteBinFile (const StrBuf* Data, const Collection* A, const Bitmap* B attribute ((unused))) /* Write the contents of Data to the given file in binary format */ { unsigned Size; /* Get the file name */ const char* Name = NeedAttrVal (A, "name", "write"); /* Open the output file */ FILE* F = fopen (Name, "wb"); if (F == 0) { Error ("Cannot open output file '%s': %s", Name, strerror (errno)); } /* Write to the file. We will use fwrite here instead of the fileio ** module, since it's just one call, so the latter doesn't have any ** advantages, and we can output a more readable error message in case of ** problems. */ Size = SB_GetLen (Data); if (fwrite (SB_GetConstBuf (Data), 1, Size, F) != Size) { Error ("Error writing to output file '%s': %s", Name, strerror (errno)); } /* Close the file */ if (fclose (F) != 0) { Error ("Error closing output file '%s': %s", Name, strerror (errno)); } } ����������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/bin.h����������������������������������������������������������������������������0000664�0000000�0000000�00000006023�13473601511�0014513�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* bin.h */ /* */ /* Binary file output for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef BIN_H #define BIN_H /* common */ #include "coll.h" #include "strbuf.h" /* sp65 */ #include "bitmap.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void WriteBinFile (const StrBuf* Data, const Collection* A, const Bitmap* B); /* Write the contents of Data to a file in binary format */ /* End of bin.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/bitmap.c�������������������������������������������������������������������������0000664�0000000�0000000�00000014063�13473601511�0015215�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* bitmap.c */ /* */ /* Bitmap definition for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "check.h" #include "xmalloc.h" /* sp65 */ #include "bitmap.h" #include "error.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ Bitmap* NewBitmap (unsigned Width, unsigned Height) /* Create a new bitmap. The type is set to unknown and the palette to NULL */ { Bitmap* B; /* Calculate the size of the bitmap in pixels */ unsigned long Size = (unsigned long) Width * Height; /* Some safety checks */ PRECONDITION (Size > 0 && Size <= BM_MAX_SIZE); /* Allocate memory */ B = xmalloc (sizeof (*B) + (Size - 1) * sizeof (B->Data[0])); /* Initialize the data */ B->Name = EmptyStrBuf; B->Width = Width; B->Height = Height; B->Pal = 0; /* Return the bitmap */ return B; } void FreeBitmap (Bitmap* B) /* Free a dynamically allocated bitmap */ { /* Alloc NULL pointers */ if (B != 0) { /* Free name, palette and then the bitmap */ SB_Done (&B->Name); xfree (B->Pal); xfree(B); } } int ValidBitmapSize (unsigned Width, unsigned Height) /* Return true if this is a valid size for a bitmap */ { /* Calculate the size of the bitmap in pixels */ unsigned long Size = (unsigned long) Width * Height; /* Check the size */ return (Size > 0 && Size <= BM_MAX_SIZE); } Bitmap* SliceBitmap (const Bitmap* O, unsigned OrigX, unsigned OrigY, unsigned Width, unsigned Height) /* Create a slice of the given bitmap. The slice starts at position X/Y of ** the original and has the given width and height. Location 0/0 is at the ** upper left corner. */ { Bitmap* B; unsigned Y; /* Check the coordinates and size */ PRECONDITION (OrigX + Width <= O->Width && OrigY + Height <= O->Height); /* Create a new bitmap with the given size */ B = NewBitmap (Width, Height); /* Copy fields from the original */ if (SB_GetLen (&O->Name) > 0) { SB_CopyStr (&B->Name, "Slice of "); SB_Append (&B->Name, &O->Name); } B->Pal = DupPalette (O->Pal); /* Copy the pixel data */ for (Y = 0; Y < Height; ++Y) { memcpy (B->Data + Y * B->Width, O->Data + (OrigY + Y) * O->Width + OrigX, Width * sizeof (O->Data[0])); } /* Return the slice */ return B; } Color GetPixelColor (const Bitmap* B, unsigned X, unsigned Y) /* Get the color for a given pixel. For indexed bitmaps, the palette entry ** is returned. */ { /* Get the pixel at the given coordinates */ Pixel P = GetPixel (B, X, Y); /* If the bitmap has a palette, return the color from the palette. For ** simplicity, we will only check the palette, not the type. */ if (B->Pal) { if (P.Index >= B->Pal->Count) { /* Palette index is invalid */ Error ("Invalid palette index %u at position %u/%u of \"%*s\"", P.Index, X, Y, SB_GetLen (&B->Name), SB_GetConstBuf (&B->Name)); } return B->Pal->Entries[P.Index]; } else { return P.C; } } Pixel GetPixel (const Bitmap* B, unsigned X, unsigned Y) /* Return a pixel from the bitmap. The returned value may either be a color ** or a palette index, depending on the type of the bitmap. */ { /* Check the coordinates */ PRECONDITION (X < B->Width && Y < B->Height); /* Return the pixel */ return B->Data[Y * B->Width + X]; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/bitmap.h�������������������������������������������������������������������������0000664�0000000�0000000�00000014253�13473601511�0015223�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* bitmap.h */ /* */ /* Bitmap definition for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef BITMAP_H #define BITMAP_H /* common */ #include "strbuf.h" /* sp65 */ #include "palette.h" #include "pixel.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Safety limit for the bitmap sizes */ #define BM_MAX_WIDTH 4096U #define BM_MAX_HEIGHT 4096U /* Safety limit for the size of the bitmap in pixels */ #define BM_MAX_SIZE 4194304UL /* Bitmap structure */ typedef struct Bitmap Bitmap; struct Bitmap { /* Name of the bitmap. This is used for error messages and should be ** something that allows the user to identify which bitmap the message ** refers to. For bitmaps loaded from a file, using the file name is ** a good idea. */ StrBuf Name; /* Size of the bitmap */ unsigned Width; unsigned Height; /* Palette for indexed bitmap types, otherwise NULL */ Palette* Pal; /* Pixel data, dynamically allocated */ Pixel Data[1]; }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ Bitmap* NewBitmap (unsigned Width, unsigned Height); /* Create a new bitmap. The type is set to unknown and the palette to NULL */ void FreeBitmap (Bitmap* B); /* Free a dynamically allocated bitmap */ int ValidBitmapSize (unsigned Width, unsigned Height); /* Return true if this is a valid size for a bitmap */ Bitmap* SliceBitmap (const Bitmap* Original, unsigned X, unsigned Y, unsigned Width, unsigned Height); /* Create a slice of the given bitmap. The slice starts at position X/Y of ** the original and has the given width and height. Location 0/0 is at the ** upper left corner. */ Color GetPixelColor (const Bitmap* B, unsigned X, unsigned Y); /* Get the color for a given pixel. For indexed bitmaps, the palette entry ** is returned. */ Pixel GetPixel (const Bitmap* B, unsigned X, unsigned Y); /* Return a pixel from the bitmap. The returned value may either be a color ** or a palette index, depending on the type of the bitmap. */ #if defined(HAVE_INLINE) INLINE int BitmapIsIndexed (const Bitmap* B) /* Return true if this is an indexed bitmap */ { return (B->Pal != 0); } #else # define BitmapIsIndexed(B) ((B)->Pal != 0) #endif #if defined(HAVE_INLINE) INLINE unsigned GetBitmapWidth (const Bitmap* B) /* Get the width of a bitmap */ { return B->Width; } #else # define GetBitmapWidth(B) ((B)->Width) #endif #if defined(HAVE_INLINE) INLINE unsigned GetBitmapHeight (const Bitmap* B) /* Get the height of a bitmap */ { return B->Height; } #else # define GetBitmapHeight(B) ((B)->Height) #endif #if defined(HAVE_INLINE) INLINE const Palette* GetBitmapPalette (const Bitmap* B) /* Get the palette of a bitmap */ { return B->Pal; } #else # define GetBitmapPalette(B) ((B)->Pal) #endif #if defined(HAVE_INLINE) INLINE const StrBuf* GetBitmapName (const Bitmap* B) /* Get the name of a bitmap */ { return &B->Name; } #else # define GetBitmapName(B) (&(B)->Name) #endif #if defined(HAVE_INLINE) INLINE unsigned GetBitmapColors (const Bitmap* B) /* Get the number of colors in an image. The function will return the number ** of palette entries for indexed bitmaps and 2^24 for non indexed bitmaps. */ { return B->Pal? B->Pal->Count : (1U << 24); } #else # define GetBitmapColors(B) ((B)->Pal? (B)->Pal->Count : (1U << 24)) #endif /* End of bitmap.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/c.c������������������������������������������������������������������������������0000664�0000000�0000000�00000016276�13473601511�0014173�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* c.c */ /* */ /* C output for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <errno.h> #include <stdio.h> #include <string.h> /* common */ #include "chartype.h" #include "check.h" #include "cmdline.h" #include "version.h" /* sp65 */ #include "attr.h" #include "c.h" #include "error.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ static int ValidIdentifier (const char* L) /* Check a C identifier for validity */ { /* Must begin with underscore or alphabetic character */ if (*L != '_' && !IsAlpha (*L)) { return 0; } ++L; /* Remainder must be as above plus digits */ while (*L) { if (*L != '_' && !IsAlNum (*L)) { return 0; } ++L; } /* Ok */ return 1; } static unsigned GetBytesPerLine (const Collection* A) /* Return the number of bytes per line from the attribute collection A */ { char C; unsigned BytesPerLine = 16; /* Check for a bytesperline attribute */ const char* V = GetAttrVal (A, "bytesperline"); if ((V && sscanf (V, "%u%c", &BytesPerLine, &C) != 1) || (BytesPerLine < 1 || BytesPerLine > 64)) { Error ("Invalid value for attribute 'bytesperline'"); } return BytesPerLine; } static unsigned GetBase (const Collection* A) /* Return the number base from the attribute collection A */ { char C; unsigned Base = 16; /* Check for a base attribute */ const char* V = GetAttrVal (A, "base"); if ((V && sscanf (V, "%u%c", &Base, &C) != 1) || (Base != 10 && Base != 16)) { Error ("Invalid value for attribute 'base'"); } return Base; } static const char* GetIdentifier (const Collection* A) /* Return the variable identifier from the attribute collection A */ { /* Check for a ident attribute */ const char* Ident = GetAttrVal (A, "ident"); if (Ident && !ValidIdentifier (Ident)) { Error ("Invalid value for attribute 'ident'"); } return Ident; } void WriteCFile (const StrBuf* Data, const Collection* A, const Bitmap* B) /* Write the contents of Data to a file in C format */ { FILE* F; const char* D; unsigned Size; /* Get the name of the image */ const StrBuf* S = GetBitmapName (B); /* Get the file name */ const char* Name = NeedAttrVal (A, "name", "write"); /* Check the number of bytes per line */ unsigned BytesPerLine = GetBytesPerLine (A); /* Get the number base */ unsigned Base = GetBase (A); /* Get the identifier */ const char* Ident = GetIdentifier (A); /* Open the output file */ F = fopen (Name, "w"); if (F == 0) { Error ("Cannot open output file '%s': %s", Name, strerror (errno)); } /* Write a readable header */ fprintf (F, "/*\n" "** This file was generated by %s %s from\n" "** %.*s (%ux%u, %u colors%s)\n" "*/\n" "\n", ProgName, GetVersionAsString (), SB_GetLen (S), SB_GetConstBuf (S), GetBitmapWidth (B), GetBitmapHeight (B), GetBitmapColors (B), BitmapIsIndexed (B)? ", indexed" : ""); /* If an identifier was given, output #defines for width, height, the ** number of colors and declare a variable for the data. */ if (Ident) { fprintf (F, "#define %s_COLORS %u\n" "#define %s_WIDTH %u\n" "#define %s_HEIGHT %u\n" "const unsigned char %s[] = {\n", Ident, GetBitmapColors (B), Ident, GetBitmapWidth (B), Ident, GetBitmapHeight (B), Ident); } /* Write the data */ D = SB_GetConstBuf (Data); Size = SB_GetLen (Data); while (Size) { unsigned I; /* Output one line */ unsigned Chunk = Size; if (Chunk > BytesPerLine) { Chunk = BytesPerLine; } fputs (" ", F); for (I = 0; I < Chunk; ++I) { switch (Base) { case 10: fprintf (F, "%u,", *D++ & 0xFF); break; case 16: fprintf (F, "0x%02X,", *D++ & 0xFF); break; } } fputc ('\n', F); /* Bump the counters */ Size -= Chunk; } /* Terminate the array if we had an identifier */ if (Ident) { fputs ("};\n", F); } /* Close the file */ if (fclose (F) != 0) { Error ("Error closing output file '%s': %s", Name, strerror (errno)); } } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/c.h������������������������������������������������������������������������������0000664�0000000�0000000�00000006006�13473601511�0014166�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* c.h */ /* */ /* C output for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef C_H #define C_H /* common */ #include "coll.h" #include "strbuf.h" /* sp65 */ #include "bitmap.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void WriteCFile (const StrBuf* Data, const Collection* A, const Bitmap* B); /* Write the contents of Data to a file in C format */ /* End of c.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/color.c��������������������������������������������������������������������������0000664�0000000�0000000�00000006210�13473601511�0015052�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* color.c */ /* */ /* Color definition for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include "color.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ #if !defined(HAVE_INLINE) Color RGB (unsigned char R, unsigned char G, unsigned char B) /* Generate a color value */ { Color C; C.R = R; C.G = G; C.B = B; C.A = 0; return C; } Color RGBA (unsigned char R, unsigned char G, unsigned char B, unsigned char A) /* Generate a color value */ { Color C; C.R = R; C.G = G; C.B = B; C.A = A; return C; } #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/color.h��������������������������������������������������������������������������0000664�0000000�0000000�00000007536�13473601511�0015073�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* color.h */ /* */ /* Color definition for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef COLOR_H #define COLOR_H /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Color structure */ typedef struct Color Color; struct Color { unsigned char R; unsigned char G; unsigned char B; unsigned char A; }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ #if defined(HAVE_INLINE) INLINE Color RGB (unsigned char R, unsigned char G, unsigned char B) /* Generate a color value */ { Color C; C.R = R; C.G = G; C.B = B; C.A = 0; return C; } INLINE Color RGBA (unsigned char R, unsigned char G, unsigned char B, unsigned char A) /* Generate a color value */ { Color C; C.R = R; C.G = G; C.B = B; C.A = A; return C; } #else Color RGB (unsigned char R, unsigned char G, unsigned char B); /* Generate a color value */ Color RGBA (unsigned char R, unsigned char G, unsigned char B, unsigned char A); /* Generate a color value */ #endif /* End of color.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/convert.c������������������������������������������������������������������������0000664�0000000�0000000�00000012060�13473601511�0015414�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* convert.c */ /* */ /* Main target conversion module for the sp65 file and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdlib.h> /* sp65 */ #include "attr.h" #include "convert.h" #include "error.h" #include "geosbitmap.h" #include "geosicon.h" #include "koala.h" #include "lynxsprite.h" #include "raw.h" #include "vic2sprite.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Type of the entry in the converter table */ typedef struct ConverterMapEntry ConverterMapEntry; struct ConverterMapEntry { const char* Format; StrBuf* (*ConvertFunc) (const Bitmap*, const Collection*); }; /* Converter table, alphabetically sorted */ static const ConverterMapEntry ConverterMap[] = { { "geos-bitmap", GenGeosBitmap }, { "geos-icon", GenGeosIcon }, { "koala", GenKoala }, { "lynx-sprite", GenLynxSprite }, { "raw", GenRaw }, { "vic2-sprite", GenVic2Sprite }, }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ static int Compare (const void* Key, const void* MapEntry) /* Compare function for bsearch */ { return strcmp (Key, ((const ConverterMapEntry*) MapEntry)->Format); } StrBuf* ConvertTo (const Bitmap* B, const Collection* A) /* Convert the bitmap B into some sort of other binary format. The output is ** stored in a string buffer (which is actually a dynamic char array) and ** returned. The actual output format is taken from the "format" attribute ** in the attribute collection A. */ { const ConverterMapEntry* E; /* Get the format to convert to */ const char* Format = NeedAttrVal (A, "format", "convert"); /* Search for the matching converter */ E = bsearch (Format, ConverterMap, sizeof (ConverterMap) / sizeof (ConverterMap[0]), sizeof (ConverterMap[0]), Compare); if (E == 0) { Error ("No such target format: '%s'", Format); } /* Do the conversion */ return E->ConvertFunc (B, A); } void ListConversionTargets (FILE* F) /* Output a list of conversion targets */ { unsigned I; for (I = 0; I < sizeof (ConverterMap) / sizeof (ConverterMap[0]); ++I) { fprintf (F, " %s\n", ConverterMap[I].Format); } } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/convert.h������������������������������������������������������������������������0000664�0000000�0000000�00000006473�13473601511�0015434�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* convert.h */ /* */ /* Main target conversion module for the sp65 file and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef CONVERT_H #define CONVERT_H #include <stdio.h> /* common */ #include "coll.h" #include "strbuf.h" /* sp65 */ #include "bitmap.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ StrBuf* ConvertTo (const Bitmap* B, const Collection* A); /* Convert the bitmap B into some sort of other binary format. The output is ** stored in a string buffer (which is actually a dynamic char array) and ** returned. The actual output format is taken from the "format" attribute ** in the attribute collection A. */ void ListConversionTargets (FILE* F); /* Output a list of conversion targets */ /* End of convert.h */ #endif �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/error.c��������������������������������������������������������������������������0000664�0000000�0000000�00000007107�13473601511�0015073�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* error.c */ /* */ /* Error handling for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include "error.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Warning (const char* Format, ...) /* Print a warning message */ { va_list ap; va_start (ap, Format); fprintf (stderr, "Warning: "); vfprintf (stderr, Format, ap); putc ('\n', stderr); va_end (ap); } void Error (const char* Format, ...) /* Print an error message and die */ { va_list ap; va_start (ap, Format); fprintf (stderr, "Error: "); vfprintf (stderr, Format, ap); putc ('\n', stderr); va_end (ap); exit (EXIT_FAILURE); } void Internal (const char* Format, ...) /* Print an internal error message and die */ { va_list ap; va_start (ap, Format); fprintf (stderr, "Internal error: "); vfprintf (stderr, Format, ap); putc ('\n', stderr); va_end (ap); exit (EXIT_FAILURE); } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/error.h��������������������������������������������������������������������������0000664�0000000�0000000�00000006273�13473601511�0015103�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* error.h */ /* */ /* Error handling for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef ERROR_H #define ERROR_H /* common */ #include "attrib.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void Warning (const char* Format, ...) attribute((format(printf,1,2))); /* Print a warning message */ void Error (const char* Format, ...) attribute((noreturn, format(printf,1,2))); /* Print an error message and die */ void Internal (const char* Format, ...) attribute((noreturn, format(printf,1,2))); /* Print an internal error message and die */ /* End of error.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/fileio.c�������������������������������������������������������������������������0000664�0000000�0000000�00000010301�13473601511�0015177�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* fileio.c */ /* */ /* File I/O for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> #include <errno.h> /* od65 */ #include "error.h" #include "fileio.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void FileSetPos (FILE* F, unsigned long Pos) /* Seek to the given absolute position, fail on errors */ { if (fseek (F, Pos, SEEK_SET) != 0) { Error ("Cannot seek: %s", strerror (errno)); } } unsigned long FileGetPos (FILE* F) /* Return the current file position, fail on errors */ { long Pos = ftell (F); if (Pos < 0) { Error ("Error in ftell: %s", strerror (errno)); } return Pos; } unsigned Read8 (FILE* F) /* Read an 8 bit value from the file */ { int C = getc (F); if (C == EOF) { Error ("Read error (file corrupt?)"); } return C; } unsigned Read16 (FILE* F) /* Read a 16 bit value from the file */ { unsigned Lo = Read8 (F); unsigned Hi = Read8 (F); return (Hi << 8) | Lo; } unsigned long Read24 (FILE* F) /* Read a 24 bit value from the file */ { unsigned long Lo = Read16 (F); unsigned long Hi = Read8 (F); return (Hi << 16) | Lo; } unsigned long Read32 (FILE* F) /* Read a 32 bit value from the file */ { unsigned long Lo = Read16 (F); unsigned long Hi = Read16 (F); return (Hi << 16) | Lo; } void* ReadData (FILE* F, void* Data, unsigned Size) /* Read data from the file */ { /* Accept zero sized reads */ if (Size > 0) { if (fread (Data, 1, Size, F) != Size) { Error ("Read error (file corrupt?)"); } } return Data; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/fileio.h�������������������������������������������������������������������������0000664�0000000�0000000�00000006601�13473601511�0015214�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* fileio.h */ /* */ /* File I/O for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 1998-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef FILEIO_H #define FILEIO_H #include <stdio.h> /*****************************************************************************/ /* Code */ /*****************************************************************************/ void FileSetPos (FILE* F, unsigned long Pos); /* Seek to the given absolute position, fail on errors */ unsigned long FileGetPos (FILE* F); /* Return the current file position, fail on errors */ unsigned Read8 (FILE* F); /* Read an 8 bit value from the file */ unsigned Read16 (FILE* F); /* Read a 16 bit value from the file */ unsigned long Read24 (FILE* F); /* Read a 24 bit value from the file */ unsigned long Read32 (FILE* F); /* Read a 32 bit value from the file */ void* ReadData (FILE* F, void* Data, unsigned Size); /* Read data from the file */ /* End of fileio.h */ #endif �������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/geosbitmap.c���������������������������������������������������������������������0000664�0000000�0000000�00000020215�13473601511�0016067�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* geosbitmap.c */ /* */ /* GEOS compacted bitmap backend for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "attrib.h" #include "print.h" #include "xmalloc.h" /* sp65 */ #include "attr.h" #include "error.h" #include "geosbitmap.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ #define UNIQUE_MAX 91U /* Maximum number of unique bytes */ #define REPEAT_MAX 127U /* Maximum number of repeated bytes */ /* Structure used for RLE compression */ struct RLE { unsigned char* Buf; /* Pointer to pixel buffer */ unsigned Remaining; /* Remaining bytes in buffer */ unsigned char LastVal; /* Last value seen */ unsigned Count; /* Number of occurrences for LastVal */ StrBuf* D; /* Buffer for compressed data */ StrBuf UniqueData; /* Temp buffer for unique data */ }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void StoreByte (struct RLE* RLE) /* Store a unique byte or a run of repeated bytes. If count is zero, the ** function will flush the internal buffers, so that all data is in RLE->D. */ { if (RLE->Count == 1 || RLE->Count == 2) { /* A run of two identical bytes is treated as two unique bytes, since ** this will usually merge with the following run. */ SB_AppendChar (&RLE->UniqueData, RLE->LastVal); if (RLE->Count == 2) { SB_AppendChar (&RLE->UniqueData, RLE->LastVal); } /* Clear the repeat counter */ RLE->Count = 0; } else { /* Run of repeated bytes. First flush the temp buffer for unique ** bytes. */ const char* Buf = SB_GetConstBuf (&RLE->UniqueData); unsigned Count = SB_GetLen (&RLE->UniqueData); while (Count) { /* Determine the count for this sequence */ unsigned Chunk = Count; if (Chunk > UNIQUE_MAX) { Chunk = UNIQUE_MAX; } /* Output the unique op */ SB_AppendChar (RLE->D, 0x80 + (unsigned char) Chunk); SB_AppendBuf (RLE->D, Buf, Chunk); /* Bump the counters */ Buf += Chunk; Count -= Chunk; } /* Clear the unique byte buffer */ SB_Clear (&RLE->UniqueData); /* Now output the repeat sequence */ while (RLE->Count) { /* Determine the count for this sequence */ unsigned Chunk = RLE->Count; if (Chunk > REPEAT_MAX) { Chunk = REPEAT_MAX; } /* Output the repeat op */ SB_AppendChar (RLE->D, (unsigned char) Chunk); SB_AppendChar (RLE->D, RLE->LastVal); /* Bump the counters */ RLE->Count -= Chunk; } } } StrBuf* GenGeosBitmap (const Bitmap* B, const Collection* A attribute ((unused))) /* Generate binary output in GEOS compacted bitmap format for the bitmap B. ** The output is stored in a string buffer (which is actually a dynamic char ** array) and returned. */ { unsigned LineWidth; unsigned char* Buf; unsigned char* BP; StrBuf* D; unsigned X, Y; struct RLE RLE; /* Output the image properties */ Print (stdout, 1, "Image is %ux%u with %u colors%s\n", GetBitmapWidth (B), GetBitmapHeight (B), GetBitmapColors (B), BitmapIsIndexed (B)? " (indexed)" : ""); /* Check the bitmap properties */ if (!BitmapIsIndexed (B) || GetBitmapColors (B) > 2) { Error ("Bitmaps converted to GEOS compacted bitmap must be " "indexed with two colors"); } /* Calculate the width of one line in bytes */ LineWidth = (GetBitmapWidth (B) + 7U) / 8U; /* Allocate a buffer for the raw image */ Buf = xmalloc (LineWidth * GetBitmapHeight (B)); /* Convert the bitmap into a raw image */ BP = Buf; for (Y = 0; Y < GetBitmapHeight (B); ++Y) { for (X = 0; X < GetBitmapWidth (B); ) { unsigned char V = 0; int Bits = 8; if ((unsigned)Bits > GetBitmapWidth (B) - X) { Bits = (GetBitmapWidth (B) - X); } while (--Bits >= 0) { V |= (GetPixel (B, X++, Y).Index & 0x01) << Bits; } *BP++ = V; } } /* Create the output buffer and resize it to something reasonable */ D = NewStrBuf (); SB_Realloc (D, 64); /* Compact the image. We're currently using only REPEAT and UNIQUE opcodes. ** BIGCOUNT is rather difficult to apply. */ RLE.Buf = Buf; RLE.Remaining = LineWidth * GetBitmapHeight (B) - 1; RLE.LastVal = *RLE.Buf++; RLE.Count = 1; RLE.D = D; RLE.UniqueData = EmptyStrBuf; while (RLE.Remaining--) { /* */ if (RLE.LastVal == *RLE.Buf) { ++RLE.Buf; ++RLE.Count; } else { StoreByte (&RLE); RLE.LastVal = *RLE.Buf++; RLE.Count = 1; } } /* If something remains, store it */ if (RLE.Count) { StoreByte (&RLE); } /* Flush the unique byte buffer */ StoreByte (&RLE); /* Release the unique byte buffer */ SB_Done (&RLE.UniqueData); /* Free the raw image buffer */ xfree (Buf); /* Return the converted bitmap */ return D; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/geosbitmap.h���������������������������������������������������������������������0000664�0000000�0000000�00000006252�13473601511�0016101�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* geosbitmap.h */ /* */ /* GEOS compacted bitmap backend for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef GEOSBITMAP_H #define GEOSBITMAP_H /* common */ #include "coll.h" #include "strbuf.h" /* sp65 */ #include "bitmap.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ StrBuf* GenGeosBitmap (const Bitmap* B, const Collection* A); /* Generate binary output in GEOS compacted bitmap format for the bitmap B. ** The output is stored in a string buffer (which is actually a dynamic char ** array) and returned. */ /* End of geosbitmap.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/geosicon.c�����������������������������������������������������������������������0000664�0000000�0000000�00000011064�13473601511�0015545�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* geosicon.c */ /* */ /* GEOS icon format backend for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "attrib.h" #include "print.h" /* sp65 */ #include "attr.h" #include "error.h" #include "geosicon.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Screen size of geos icon */ #define WIDTH 24U #define HEIGHT 21U /*****************************************************************************/ /* Code */ /*****************************************************************************/ StrBuf* GenGeosIcon (const Bitmap* B, const Collection* A attribute ((unused))) /* Generate binary output in GEOS icon format for the bitmap B. The output ** is stored in a string buffer (which is actually a dynamic char array) and ** returned. */ { StrBuf* D; unsigned X, Y; /* Output the image properties */ Print (stdout, 1, "Image is %ux%u with %u colors%s\n", GetBitmapWidth (B), GetBitmapHeight (B), GetBitmapColors (B), BitmapIsIndexed (B)? " (indexed)" : ""); /* Check the bitmap properties */ if (!BitmapIsIndexed (B) || GetBitmapHeight (B) != HEIGHT || GetBitmapWidth (B) != WIDTH || GetBitmapColors (B) > 2) { Error ("Invalid bitmap properties for conversion to GEOS icon"); } /* Create the output buffer and resize it to the required size. */ D = NewStrBuf (); SB_Realloc (D, 63); /* Convert the image */ for (Y = 0; Y < HEIGHT; ++Y) { unsigned char V = 0; for (X = 0; X < WIDTH; ++X) { /* Fetch next bit into byte buffer */ V = (V << 1) | (GetPixel (B, X, Y).Index & 0x01); /* Store full bytes into the output buffer */ if ((X & 0x07) == 0x07) { SB_AppendChar (D, V); V = 0; } } } /* Return the converted bitmap */ return D; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/geosicon.h�����������������������������������������������������������������������0000664�0000000�0000000�00000006174�13473601511�0015560�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* geosicon.h */ /* */ /* GEOS icon format backend for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef GEOSICON_H #define GEOSICON_H /* common */ #include "coll.h" #include "strbuf.h" /* sp65 */ #include "bitmap.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ StrBuf* GenGeosIcon (const Bitmap* B, const Collection* A); /* Generate binary output in GEOS icon format for the bitmap B. The output ** is stored in a string buffer (which is actually a dynamic char array) and ** returned. */ /* End of geosicon.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/input.c��������������������������������������������������������������������������0000664�0000000�0000000�00000012013�13473601511�0015071�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* input.c */ /* */ /* Input format/file definitions for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdlib.h> /* common */ #include "fileid.h" /* sp65 */ #include "attr.h" #include "error.h" #include "input.h" #include "pcx.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Possible input formats */ enum InputFormat { ifPCX, /* PCX */ ifCount /* Number of actual input formats w/o ifAuto*/ }; typedef struct InputFormatDesc InputFormatDesc; struct InputFormatDesc { /* Read routine */ Bitmap* (*Read) (const Collection*); }; /* Table with input formats indexed by InputFormat */ static InputFormatDesc InputFormatTable[ifCount] = { { ReadPCXFile }, }; /* Table that maps extensions to input formats. Must be sorted alphabetically */ static const FileId FormatTable[] = { /* Upper case stuff for obsolete operating systems */ { "PCX", ifPCX }, { "pcx", ifPCX }, }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ Bitmap* ReadInputFile (const Collection* A) /* Read a bitmap from a file and return it. Format, file name etc. must be ** given as attributes in A. If no format is given, the function tries to ** autodetect it by using the extension of the file name. */ { const FileId* F; /* Get the file format from the command line */ const char* Format = GetAttrVal (A, "format"); if (Format != 0) { /* Format is given, search for it in the table. */ F = bsearch (Format, FormatTable, sizeof (FormatTable) / sizeof (FormatTable[0]), sizeof (FormatTable[0]), CompareFileId); if (F == 0) { Error ("Unknown input format '%s'", Format); } } else { /* No format given, use file name extension */ const char* Name = NeedAttrVal (A, "name", "write"); F = GetFileId (Name, FormatTable, sizeof (FormatTable) / sizeof (FormatTable[0])); /* Found? */ if (F == 0) { Error ("Cannot determine file format of input file '%s'", Name); } } /* Call the format specific read */ return InputFormatTable[F->Id].Read (A); } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/input.h��������������������������������������������������������������������������0000664�0000000�0000000�00000006172�13473601511�0015107�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* input.h */ /* */ /* Input format/file definitions for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef INPUT_H #define INPUT_H /* common */ #include "coll.h" /* sp65 */ #include "bitmap.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ Bitmap* ReadInputFile (const Collection* A); /* Read a bitmap from a file and return it. Format, file name etc. must be ** given as attributes in A. If no format is given, the function tries to ** autodetect it by using the extension of the file name. */ /* End of input.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/koala.c��������������������������������������������������������������������������0000664�0000000�0000000�00000010552�13473601511�0015027�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* koala.c */ /* */ /* Koala format backend for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "attrib.h" /* sp65 */ #include "error.h" #include "koala.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Screen size of a koala picture */ #define WIDTH 160U #define HEIGHT 200U /*****************************************************************************/ /* Code */ /*****************************************************************************/ StrBuf* GenKoala (const Bitmap* B, const Collection* A attribute ((unused))) /* Generate binary output in koala format for the bitmap B. The output is ** stored in a string buffer (which is actually a dynamic char array) and ** returned. */ { StrBuf* D; unsigned char Screen[160][200]; unsigned char X, Y; /* Koala pictures are always 160x200 in size with 16 colors */ if (!BitmapIsIndexed (B) || GetBitmapColors (B) > 16 || GetBitmapHeight (B) != HEIGHT || GetBitmapWidth (B) != WIDTH) { Error ("Bitmaps converted to koala format must be in indexed mode " "with 16 colors max and a size of %ux%u", WIDTH, HEIGHT); } /* Read the image into Screen */ for (Y = 0; Y < HEIGHT; ++Y) { for (X = 0; X < WIDTH; ++X) { Screen[X][Y] = (unsigned char) GetPixel (B, X, Y).Index; } } /* Create the output buffer and resize it to the required size. */ D = NewStrBuf (); SB_Realloc (D, 10003); /* Add $4400 as load address */ SB_AppendChar (D, 0x00); SB_AppendChar (D, 0x44); /* TODO: The actual work ;-) */ (void) Screen; /* Return the converted bitmap */ return D; } ������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/koala.h��������������������������������������������������������������������������0000664�0000000�0000000�00000006154�13473601511�0015037�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* koala.h */ /* */ /* Koala format backend for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef KOALA_H #define KOALA_H /* common */ #include "coll.h" #include "strbuf.h" /* sp65 */ #include "bitmap.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ StrBuf* GenKoala (const Bitmap* B, const Collection* A); /* Generate binary output in koala format for the bitmap B. The output is ** stored in a string buffer (which is actually a dynamic char array) and ** returned. */ /* End of koala.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/lynxsprite.c���������������������������������������������������������������������0000664�0000000�0000000�00000040204�13473601511�0016156�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* lynxsprite.c */ /* */ /* Lynx sprite format backend for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdlib.h> /* common */ #include "attrib.h" #include "print.h" /* sp65 */ #include "attr.h" #include "error.h" #include "lynxsprite.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Sprite mode */ enum Mode { smAuto, smLiteral, smPacked, smShaped }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ static enum Mode GetMode (const Collection* A) /* Return the sprite mode from the attribute collection A */ { /* Check for a mode attribute */ const char* Mode = GetAttrVal (A, "mode"); if (Mode) { if (strcmp (Mode, "literal") == 0) { return smLiteral; } else if (strcmp (Mode, "packed") == 0) { return smPacked; } else if (strcmp (Mode, "shaped") == 0) { return smShaped; } else { Error ("Invalid value for attribute 'mode'"); } } return smAuto; } static unsigned GetActionPointX (const Collection* A) /* Return the sprite mode from the attribute collection A */ { /* Check for a action point x attribute */ const char* ActionPointX = GetAttrVal (A, "ax"); if (ActionPointX) { return atoi(ActionPointX); } else { return 0; } } static unsigned GetActionPointY (const Collection* A) /* Return the sprite mode from the attribute collection A */ { /* Check for a action point y attribute */ const char* ActionPointY = GetAttrVal (A, "ay"); if (ActionPointY) { return atoi(ActionPointY); } else { return 0; } } static unsigned GetEdgeIndex (const Collection* A) /* Return the sprite mode from the attribute collection A */ { /* Get index for edge color in shaped mode */ const char* EdgeIndex = GetAttrVal (A, "edge"); if (EdgeIndex) { return atoi(EdgeIndex); } else { return 0; } } static char OutBuffer[512]; /* The maximum size is 508 pixels */ static unsigned char OutIndex; static void AssembleByte(unsigned bits, char val) { static char bit_counter = 8, byte = 0; /* initialize */ if (!bits) { OutIndex = 0; bit_counter = 8; byte = 0; return; } /* handle end of line */ if (bits == 8) { if (bit_counter != 8) { byte <<= bit_counter; OutBuffer[OutIndex++] = byte; if (!OutIndex) { Error ("Sprite is too large for the Lynx"); } if (byte & 0x1) { OutBuffer[OutIndex++] = byte; if (!OutIndex) { Error ("Sprite is too large for the Lynx"); } } } return; } /* handle end of line for literal */ if (bits == 7) { if (bit_counter != 8) { byte <<= bit_counter; OutBuffer[OutIndex++] = byte; if (!OutIndex) { Error ("Sprite is too large for the Lynx"); } } return; } val <<= 8 - bits; do { byte <<= 1; if (val & 0x80) ++byte; if (!(--bit_counter)) { OutBuffer[OutIndex++] = byte; if (!OutIndex) { Error ("Sprite is too large for the Lynx"); } byte = 0; bit_counter = 8; } val <<= 1; } while (--bits); } static unsigned char ChoosePackagingMode(signed len, signed index, char ColorBits, char LineBuffer[512]) { --len; if (!len) { return 0; } if (LineBuffer[index] != LineBuffer[index + 1]) { return 0; } if (ColorBits > 2) { return 1; } if (LineBuffer[index] != LineBuffer[index + 2]) { return 0; } if (ColorBits > 1) { return 1; } if (LineBuffer[index] != LineBuffer[index + 3]) { return 0; } return 1; } static void WriteOutBuffer(StrBuf *D) { signed i; /* Fix bug in Lynx where the count cannot be 1 */ if (OutIndex == 1) { OutBuffer[OutIndex++] = 0; } /* Write the byte count to the end of the scanline */ if (OutIndex == 255) { Error ("Sprite is too large for the Lynx"); } SB_AppendChar (D, OutIndex+1); /* Write scanline data */ for (i = 0; i < OutIndex; i++) { SB_AppendChar (D, OutBuffer[i]); } } static void encodeSprite(StrBuf *D, enum Mode M, char ColorBits, char ColorMask, char LineBuffer[512], int len, int LastOpaquePixel) { /* ** The data starts with a byte count. It tells the number of bytes on this ** line + 1. ** Special case is a count of 1. It will change to next quadrant. ** Other special case is 0. It will end the sprite. ** ** Ordinary data packet. These are bits in a stream. ** 1=literal 0=packed ** 4 bit count (+1) ** for literal you put "count" values ** for packed you repeat the value "count" times ** Never use packed mode for one pixel ** If the last bit on a line is 1 you need to add a byte of zeroes ** A sequence 00000 ends a scan line ** ** All data is high nybble first */ unsigned char V = 0; signed i; signed count; unsigned char differ[16]; unsigned char *d_ptr; AssembleByte(0, 0); switch (M) { case smAuto: case smLiteral: for (i = 0; i < len; i++) { /* Fetch next pixel index into pixel buffer */ AssembleByte(ColorBits, LineBuffer[i] & ColorMask); } AssembleByte(7, 0); /* Write the buffer to file */ WriteOutBuffer(D); break; case smPacked: i = 0; while (len) { if (ChoosePackagingMode(len, i, ColorBits, LineBuffer)) { /* Make runlength packet */ V = LineBuffer[i]; ++i; --len; count = 0; do { ++count; ++i; --len; } while (V == LineBuffer[i] && len && count != 15); AssembleByte(5, count); AssembleByte(ColorBits, V); } else { /* Make packed literal packet */ d_ptr = differ; V = LineBuffer[i++]; *d_ptr++ = V; --len; count = 0; while (ChoosePackagingMode(len, i, ColorBits, LineBuffer) == 0 && len && count != 15) { V = LineBuffer[i++]; *d_ptr++ = V; ++count; --len; } AssembleByte(5, count | 0x10); d_ptr = differ; do { AssembleByte(ColorBits, *d_ptr++); } while (--count >= 0); } } AssembleByte(8, 0); /* Write the buffer to file */ WriteOutBuffer(D); break; case smShaped: if (LastOpaquePixel > -1) { if (LastOpaquePixel < len - 1) { len = LastOpaquePixel + 1; } i = 0; while (len) { if (ChoosePackagingMode(len, i, ColorBits, LineBuffer)) { /* Make runlength packet */ V = LineBuffer[i]; ++i; --len; count = 0; do { ++count; ++i; --len; } while (V == LineBuffer[i] && len && count != 15); AssembleByte(5, count); AssembleByte(ColorBits, V); } else { /* Make packed literal packet */ d_ptr = differ; V = LineBuffer[i++]; *d_ptr++ = V; --len; count = 0; while (ChoosePackagingMode(len, i, ColorBits, LineBuffer) == 0 && len && count != 15) { V = LineBuffer[i++]; *d_ptr++ = V; ++count; --len; } AssembleByte(5, count | 0x10); d_ptr = differ; do { AssembleByte(ColorBits, *d_ptr++); } while (--count >= 0); } } AssembleByte(5, 0); AssembleByte(8, 0); /* Write the buffer to file */ WriteOutBuffer(D); } break; } } StrBuf* GenLynxSprite (const Bitmap* B, const Collection* A) /* Generate binary output in Lynx sprite format for the bitmap B. The output ** is stored in a string buffer (which is actually a dynamic char array) and ** returned. ** ** The Lynx will draw 4 quadrants: ** - Down right ** - Up right ** - Up left ** - Down left ** ** The sprite will end with a byte 0. */ { enum Mode M; StrBuf* D; signed X, Y; unsigned OX, OY; char ColorBits; char ColorMask; char EdgeIndex; /* Get EdgeIndex */ EdgeIndex = GetEdgeIndex (A); /* Action point of the sprite */ OX = GetActionPointX (A); OY = GetActionPointY (A); if (OX >= GetBitmapWidth (B)) { Error ("Action point X cannot be larger than bitmap width"); } if (OY >= GetBitmapHeight (B)) { Error ("Action point Y cannot be larger than bitmap height"); } /* Output the image properties */ Print (stdout, 1, "Image is %ux%u with %u colors%s\n", GetBitmapWidth (B), GetBitmapHeight (B), GetBitmapColors (B), BitmapIsIndexed (B)? " (indexed)" : ""); /* Get the sprite mode */ M = GetMode (A); /* Now check if bitmap indexes are ok */ if (GetBitmapColors (B) > 16) { Error ("Too many colors for a Lynx sprite"); } ColorBits = 4; ColorMask = 0x0f; if (GetBitmapColors (B) < 9) { ColorBits = 3; ColorMask = 0x07; } if (GetBitmapColors (B) < 5) { ColorBits = 2; ColorMask = 0x03; } if (GetBitmapColors (B) < 3) { ColorBits = 1; ColorMask = 0x01; } /* Create the output buffer and resize it to the required size. */ D = NewStrBuf (); SB_Realloc (D, 63); /* Convert the image for quadrant bottom right */ for (Y = OY; Y < (signed)GetBitmapHeight (B); ++Y) { signed i = 0; signed LastOpaquePixel = -1; char LineBuffer[512]; /* The maximum size is 508 pixels */ /* Fill the LineBuffer for easier optimisation */ for (X = OX; X < (signed)GetBitmapWidth (B); ++X) { /* Fetch next bit into byte buffer */ LineBuffer[i] = GetPixel (B, X, Y).Index & ColorMask; if (LineBuffer[i] != EdgeIndex) { LastOpaquePixel = i; } ++i; } encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel); } if ((OY == 0) && (OX == 0)) { /* Trivial case only one quadrant */ /* Mark end of sprite */ SB_AppendChar (D, 0); /* Return the converted bitmap */ return D; } /* Next quadrant */ SB_AppendChar (D, 1); /* Convert the image for quadrant top right */ for (Y = OY - 1; Y >= 0; --Y) { signed i = 0; signed LastOpaquePixel = -1; char LineBuffer[512]; /* The maximum size is 508 pixels */ /* Fill the LineBuffer for easier optimisation */ for (X = OX; X < (signed)GetBitmapWidth (B); ++X) { /* Fetch next bit into byte buffer */ LineBuffer[i] = GetPixel (B, X, Y).Index & ColorMask; if (LineBuffer[i] != EdgeIndex) { LastOpaquePixel = i; } ++i; } encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel); } if (OX == 0) { /* Special case only two quadrants */ /* Mark end of sprite */ SB_AppendChar (D, 0); /* Return the converted bitmap */ return D; } /* Next quadrant */ SB_AppendChar (D, 1); /* Convert the image for quadrant top left */ for (Y = OY - 1; Y >= 0; --Y) { signed i = 0; signed LastOpaquePixel = -1; char LineBuffer[512]; /* The maximum size is 508 pixels */ /* Fill the LineBuffer for easier optimisation */ for (X = OX - 1; X >= 0; --X) { /* Fetch next bit into byte buffer */ LineBuffer[i] = GetPixel (B, X, Y).Index & ColorMask; if (LineBuffer[i] != EdgeIndex) { LastOpaquePixel = i; } ++i; } encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel); } /* Next quadrant */ SB_AppendChar (D, 1); /* Convert the image for quadrant bottom left */ for (Y = OY; Y < (signed)GetBitmapHeight (B); ++Y) { signed i = 0; signed LastOpaquePixel = -1; char LineBuffer[512]; /* The maximum size is 508 pixels */ /* Fill the LineBuffer for easier optimisation */ for (X = OX - 1; X >= 0; --X) { /* Fetch next bit into byte buffer */ LineBuffer[i] = GetPixel (B, X, Y).Index & ColorMask; if (LineBuffer[i] != EdgeIndex) { LastOpaquePixel = i; } ++i; } encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel); } /* End sprite */ SB_AppendChar (D, 0); /* Return the converted bitmap */ return D; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/lynxsprite.h���������������������������������������������������������������������0000664�0000000�0000000�00000006216�13473601511�0016170�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* lynxsprite.h */ /* */ /* Lynx sprite format backend for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef LYNXSPRITE_H #define LYNXSPRITE_H /* common */ #include "coll.h" #include "strbuf.h" /* sp65 */ #include "bitmap.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ StrBuf* GenLynxSprite (const Bitmap* B, const Collection* A); /* Generate binary output in packed Lynx sprite format for the bitmap B. The output ** is stored in a string buffer (which is actually a dynamic char array) and ** returned. */ /* End of lynxsprite.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/main.c���������������������������������������������������������������������������0000664�0000000�0000000�00000027423�13473601511�0014671�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* main.c */ /* */ /* Main program of the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> /* common */ #include "abend.h" #include "cmdline.h" #include "print.h" #include "version.h" /* sp65 */ #include "attr.h" #include "convert.h" #include "error.h" #include "input.h" #include "output.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Bitmap first read */ static Bitmap* B; /* Bitmap working copy */ static Bitmap* C; /* Output data from convertion */ static StrBuf* D; /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void Usage (void) /* Print usage information and exit */ { printf ( "Usage: %s [options] file [options] [file]\n" "Short options:\n" " -V\t\t\t\tPrint the version number and exit\n" " -c fmt[,attrlist]\t\tConvert into target format\n" " -h\t\t\t\tHelp (this text)\n" " -lc\t\t\t\tList all possible conversions\n" " -r file[,attrlist]\t\tRead an input file\n" " -v\t\t\t\tIncrease verbosity\n" " -w file[,attrlist]\t\tWrite the output to a file\n" "\n" "Long options:\n" " --convert-to fmt[,attrlist]\tConvert into target format\n" " --dump-palette\t\tDump palette as table\n" " --help\t\t\tHelp (this text)\n" " --list-conversions\t\tList all possible conversions\n" " --pop\t\t\t\tRestore the original loaded image\n" " --read file[,attrlist]\tRead an input file\n" " --slice x,y,w,h\t\tGenerate a slice from the loaded bitmap\n" " --verbose\t\t\tIncrease verbosity\n" " --version\t\t\tPrint the version number and exit\n" " --write file[,attrlist]\tWrite the output to a file\n", ProgName); } static void SetWorkBitmap (Bitmap* N) /* Delete an old working bitmap and set a new one. The new one may be NULL ** to clear it. */ { /* If we have a distinct work bitmap, delete it */ if (C != 0 && C != B) { FreeBitmap (C); } /* Set the new one */ C = N; } static void SetOutputData (StrBuf* N) /* Delete the old output data and replace it by the given one. The new one ** may be NULL to clear it. */ { /* Delete the old output data */ if (D != 0) { FreeStrBuf (D); } /* Set the new one */ D = N; } static void OptConvertTo (const char* Opt attribute ((unused)), const char* Arg) /* Convert the bitmap into a target format */ { static const char* const NameList[] = { "format" }; /* Parse the argument */ Collection* A = ParseAttrList (Arg, NameList, 2); /* We must have a bitmap */ if (C == 0) { Error ("No bitmap to convert"); } /* Convert the bitmap */ SetOutputData (ConvertTo (C, A)); /* Delete the attribute list */ FreeAttrList (A); } static void OptDumpPalette (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Dump the palette of the current work bitmap */ { /* We must have a bitmap ... */ if (C == 0) { Error ("No bitmap"); } /* ... which must be indexed */ if (!BitmapIsIndexed (C)) { Error ("Current bitmap is not indexed"); } /* Dump the palette */ DumpPalette (stdout, GetBitmapPalette (C)); } static void OptHelp (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Print usage information and exit */ { Usage (); exit (EXIT_SUCCESS); } static void OptListConversions (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Print a list of all conversions */ { ListConversionTargets (stdout); exit (EXIT_SUCCESS); } static void OptPop (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Restore the original image */ { /* C and B must differ and we must have an original */ if (B == 0 || C == 0 || C == B) { Error ("Nothing to pop"); } /* Delete the changed image and restore the original one */ SetWorkBitmap (B); } static void OptRead (const char* Opt attribute ((unused)), const char* Arg) /* Read an input file */ { static const char* const NameList[] = { "name", "format" }; /* Parse the argument */ Collection* A = ParseAttrList (Arg, NameList, 2); /* Clear the working copy */ SetWorkBitmap (0); /* Delete the original */ FreeBitmap (B); /* Read the file and use it as original and as working copy */ B = C = ReadInputFile (A); /* Delete the attribute list */ FreeAttrList (A); } static void OptSlice (const char* Opt attribute ((unused)), const char* Arg) /* Generate a slice of a bitmap */ { unsigned X, Y, W, H; unsigned char T; /* We must have a bitmap otherwise we cannot slice */ if (C == 0) { Error ("Nothing to slice"); } /* The argument is X,Y,W,H */ if (sscanf (Arg, "%u,%u,%u,%u,%c", &X, &Y, &W, &H, &T) != 4) { Error ("Invalid argument. Slice must be given as X,Y,W,H"); } /* Check the coordinates to be within the original bitmap */ if (W > BM_MAX_WIDTH || H > BM_MAX_HEIGHT || X + W > GetBitmapWidth (C) || Y + H > GetBitmapHeight (C)) { Error ("Invalid slice coordinates and/or size"); } /* Create the slice */ SetWorkBitmap (SliceBitmap (C, X, Y, W, H)); } static void OptVerbose (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Increase verbosity */ { ++Verbosity; } static void OptVersion (const char* Opt attribute ((unused)), const char* Arg attribute ((unused))) /* Print the assembler version */ { fprintf (stderr, "%s V%s\n", ProgName, GetVersionAsString ()); exit(EXIT_SUCCESS); } static void OptWrite (const char* Opt attribute ((unused)), const char* Arg) /* Write an output file */ { static const char* const NameList[] = { "name", "format" }; /* Parse the argument */ Collection* A = ParseAttrList (Arg, NameList, 2); /* We must have output data */ if (D == 0) { Error ("No conversion, so there's nothing to write"); } /* Write the file */ WriteOutputFile (D, A, C); /* Delete the attribute list */ FreeAttrList (A); } int main (int argc, char* argv []) /* sp65 main program */ { /* Program long options */ static const LongOpt OptTab[] = { { "--convert-to", 1, OptConvertTo }, { "--dump-palette", 0, OptDumpPalette }, { "--help", 0, OptHelp }, { "--list-conversions", 0, OptListConversions }, { "--pop", 0, OptPop }, { "--read", 1, OptRead }, { "--slice", 1, OptSlice }, { "--verbose", 0, OptVerbose }, { "--version", 0, OptVersion }, { "--write", 1, OptWrite }, }; unsigned I; /* Initialize the cmdline module */ InitCmdLine (&argc, &argv, "sp65"); /* Check the parameters */ I = 1; while (I < ArgCount) { /* Get the argument */ const char* Arg = ArgVec[I]; /* Check for an option */ if (Arg[0] == '-') { switch (Arg[1]) { case '-': LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0])); break; case 'V': OptVersion (Arg, 0); break; case 'c': OptConvertTo (Arg, GetArg (&I, 2)); break; case 'h': OptHelp (Arg, 0); break; case 'l': if (Arg[2] == 'c') { OptListConversions (Arg, 0); } else { UnknownOption (Arg); } break; case 'r': OptRead (Arg, GetArg (&I, 2)); break; case 'v': OptVerbose (Arg, 0); break; case 'w': OptWrite (Arg, GetArg (&I, 2)); break; default: UnknownOption (Arg); break; } } else { /* We don't accept anything else */ AbEnd ("Don't know what to do with '%s'", Arg); } /* Next argument */ ++I; } /* Do we have an input file? */ if (I == 1) { Error ("No input file"); } /* Cleanup data */ SetWorkBitmap (C); FreeBitmap (B); FreeStrBuf (D); /* Success */ return EXIT_SUCCESS; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/output.c�������������������������������������������������������������������������0000664�0000000�0000000�00000013460�13473601511�0015301�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* output.c */ /* */ /* Output format/file definitions for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <stdlib.h> /* common */ #include "fileid.h" /* sp65 */ #include "asm.h" #include "attr.h" #include "bin.h" #include "c.h" #include "error.h" #include "output.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Different types of output formats */ enum OutputFormat { ofAsm, /* Output assembler source */ ofBin, /* Output raw binary format */ ofC, /* Output C code */ ofCount /* Number of output formats without ofAuto */ }; typedef struct OutputFormatDesc OutputFormatDesc; struct OutputFormatDesc { /* Write routine */ void (*Write) (const StrBuf*, const Collection*, const Bitmap*); }; /* Table with Output formats */ static OutputFormatDesc OutputFormatTable[ofCount] = { { WriteAsmFile }, { WriteBinFile }, { WriteCFile }, }; /* Table that maps extensions to Output formats. Must be sorted alphabetically */ static const FileId FormatTable[] = { /* Upper case stuff for obsolete operating systems */ { "A", ofAsm }, { "ASM", ofAsm }, { "BIN", ofBin }, { "C", ofC }, { "INC", ofAsm }, { "S", ofAsm }, { "a", ofAsm }, { "asm", ofAsm }, { "bin", ofBin }, { "c", ofC }, { "inc", ofAsm }, { "s", ofAsm }, }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ void WriteOutputFile (const StrBuf* Data, const Collection* A, const Bitmap* B) /* Write the contents of Data to a file. Format, file name etc. must be given ** as attributes in A. If no format is given, the function tries to autodetect ** it by using the extension of the file name. The bitmap passed to the ** function is the bitmap used as source of the conversion. It may be used to ** determine the bitmap properties for documentation purposes. */ { const FileId* F; /* Get the file format from the command line */ const char* Format = GetAttrVal (A, "format"); if (Format != 0) { /* Format is given, search for it in the table. */ F = bsearch (Format, FormatTable, sizeof (FormatTable) / sizeof (FormatTable[0]), sizeof (FormatTable[0]), CompareFileId); if (F == 0) { Error ("Unknown output format '%s'", Format); } } else { /* No format given, use file name extension */ const char* Name = NeedAttrVal (A, "name", "write"); F = GetFileId (Name, FormatTable, sizeof (FormatTable) / sizeof (FormatTable[0])); /* Found? */ if (F == 0) { Error ("Cannot determine file format of output file '%s'", Name); } } /* Call the format specific write */ OutputFormatTable[F->Id].Write (Data, A, B); } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/output.h�������������������������������������������������������������������������0000664�0000000�0000000�00000006506�13473601511�0015311�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* output.h */ /* */ /* Output format/file definitions for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef OUTPUT_H #define OUTPUT_H /* common */ #include "strbuf.h" /* sp65 */ #include "bitmap.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ void WriteOutputFile (const StrBuf* Data, const Collection* A, const Bitmap* B); /* Write the contents of Data to a file. Format, file name etc. must be given ** as attributes in A. If no format is given, the function tries to autodetect ** it by using the extension of the file name. The bitmap passed to the ** function is the bitmap used as source of the conversion. It may be used to ** determine the bitmap properties for documentation purposes. */ /* End of output.h */ #endif ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/palette.c������������������������������������������������������������������������0000664�0000000�0000000�00000011432�13473601511�0015374�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* palette.c */ /* */ /* Color palette definition for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <string.h> /* common */ #include "check.h" #include "xmalloc.h" /* sp65 */ #include "palette.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ Palette* NewPalette (unsigned Entries) /* Create a new palette with the given number of entries */ { Palette* P; /* Some safety checks */ PRECONDITION (Entries > 0 && Entries <= 256); /* Allocate memory */ P = xmalloc (sizeof (*P) + (Entries - 1) * sizeof (P->Entries[0])); /* Initialize the struct, then return it */ P->Count = Entries; return P; } Palette* NewMonochromePalette (void) /* Create and return a palette with two entries (black and white) */ { /* Create a new palette */ Palette* P = NewPalette (2); /* Set the two colors */ P->Entries[0] = RGBA (0x00, 0x00, 0x00, 0x00); P->Entries[1] = RGBA (0xFF, 0xFF, 0xFF, 0x00); /* Return the new palette */ return P; } Palette* DupPalette (const Palette* P) /* Create a copy of a palette */ { Palette* N; /* Allow to pass a NULL palette */ if (P == 0) { return 0; } /* Create a new palette */ N = NewPalette (P->Count); /* Copy the palette data */ memcpy (N->Entries, P->Entries, P->Count * sizeof (P->Entries[0])); /* Return the copy */ return N; } void FreePalette (Palette* P) /* Free a dynamically allocated palette */ { xfree (P); } void DumpPalette (FILE* F, const Palette* P) /* Dump the palette in readable form to the given file */ { unsigned I; fputs ("Entry R G B A Combined\n", F); fputs ("----------------------------------------------\n", F); for (I = 0; I < P->Count; ++I) { /* Get the color entry */ const Color* C = P->Entries + I; /* Output it */ fprintf (F, " %3u %3u %3u %3u %3u #%08lX\n", I, C->R, C->G, C->B, C->A, (((unsigned long) C->A) << 24) | (((unsigned long) C->B) << 16) | (((unsigned long) C->G) << 8) | (((unsigned long) C->R) << 0)); } } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/palette.h������������������������������������������������������������������������0000664�0000000�0000000�00000007364�13473601511�0015412�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* palette.h */ /* */ /* Color palette definition for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef PALETTE_H #define PALETTE_H #include <stdio.h> /* sp65 */ #include "color.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ typedef struct Palette Palette; struct Palette { unsigned Count; /* Number of entries */ Color Entries[1]; /* Palette entries - dynamic */ }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ Palette* NewPalette (unsigned Entries); /* Create a new palette with the given number of entries */ Palette* NewMonochromePalette (void); /* Create and return a palette with two entries (black and white) */ Palette* DupPalette (const Palette* P); /* Create a copy of a palette */ void FreePalette (Palette* P); /* Free a dynamically allocated palette */ void DumpPalette (FILE* F, const Palette* P); /* Dump the palette in readable form to the given file */ /* End of palette.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/pcx.c����������������������������������������������������������������������������0000664�0000000�0000000�00000033446�13473601511�0014541�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* pcx.c */ /* */ /* Read PCX files */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #include <errno.h> #include <stdio.h> #include <string.h> /* common */ #include "print.h" #include "xmalloc.h" /* sp65 */ #include "attr.h" #include "error.h" #include "fileio.h" #include "pcx.h" /*****************************************************************************/ /* Macros */ /*****************************************************************************/ /* Some PCX constants */ #define PCX_MAGIC_ID 0x0A #define PCX_MAX_PLANES 4 /* A raw PCX header is just a block of bytes */ typedef unsigned char RawPCXHeader[128]; /* Structured PCX header */ typedef struct PCXHeader PCXHeader; struct PCXHeader { unsigned Id; unsigned FileVersion; unsigned Compressed; unsigned BPP; unsigned XMin; unsigned YMin; unsigned XMax; unsigned YMax; unsigned XDPI; unsigned YDPI; unsigned Planes; unsigned BytesPerPlane; unsigned PalInfo; unsigned ScreenWidth; unsigned ScreenHeight; /* Calculated data */ unsigned Width; unsigned Height; }; /* Read a little endian word from a byte array at offset O */ #define WORD(H, O) ((H)[O] | ((H)[O+1] << 8)) /*****************************************************************************/ /* Code */ /*****************************************************************************/ static PCXHeader* NewPCXHeader (void) /* Allocate a new PCX header and return it */ { /* No initialization here */ return xmalloc (sizeof (PCXHeader)); } static void FreePCXHeader (PCXHeader* H) /* Free a PCX header structure */ { xfree (H); } static PCXHeader* ReadPCXHeader (FILE* F, const char* Name) /* Read a structured PCX header from the given file and return it */ { RawPCXHeader H; /* Allocate a new PCXHeader structure */ PCXHeader* P = NewPCXHeader (); /* Read the raw header */ ReadData (F, H, sizeof (H)); /* Convert the data into structured form */ P->Id = H[0]; P->FileVersion = H[1]; P->Compressed = H[2]; P->BPP = H[3]; P->XMin = WORD (H, 4); P->YMin = WORD (H, 6); P->XMax = WORD (H, 8); P->YMax = WORD (H, 10); P->XDPI = WORD (H, 12); P->YDPI = WORD (H, 14); P->Planes = H[65]; P->BytesPerPlane = WORD (H, 66); P->PalInfo = WORD (H, 68); P->ScreenWidth = WORD (H, 70); P->ScreenHeight = WORD (H, 72); P->Width = P->XMax - P->XMin + 1; P->Height = P->YMax - P->YMin + 1; /* Check the header data */ if (P->Id != PCX_MAGIC_ID || P->FileVersion == 1 || P->FileVersion > 5) { Error ("'%s' is not a PCX file", Name); } if (P->Compressed > 1) { Error ("Unsupported compression (%d) in PCX file '%s'", P->Compressed, Name); } /* We support: ** - one plane with either 1 or 8 bits per pixel ** - three planes with 8 bits per pixel ** - four planes with 8 bits per pixel (does this exist?) */ if (!((P->BPP == 1 && P->Planes == 1) || (P->BPP == 8 && (P->Planes == 1 || P->Planes == 3 || P->Planes == 4)))) { /* We could support others, but currently we don't */ Error ("Unsupported PCX format: %u planes, %u bpp in PCX file '%s'", P->Planes, P->BPP, Name); } if (P->PalInfo != 1 && P->PalInfo != 2) { Error ("Unsupported palette info (%u) in PCX file '%s'", P->PalInfo, Name); } if (!ValidBitmapSize (P->Width, P->Height)) { Error ("PCX file '%s' has an unsupported size (w=%u, h=%d)", Name, P->Width, P->Height); } /* Return the structured header */ return P; } static void DumpPCXHeader (const PCXHeader* P, const char* Name) /* Dump the header of the PCX file in readable form to stdout */ { printf ("File name: %s\n", Name); printf ("PCX Version: "); switch (P->FileVersion) { case 0: puts ("2.5"); break; case 2: puts ("2.8 with palette"); break; case 3: puts ("2.8 without palette"); break; case 4: puts ("PCX for Windows without palette"); break; case 5: puts ("3.0"); break; } printf ("Image type: %s\n", P->PalInfo? "color" : "grayscale"); printf ("Compression: %s\n", P->Compressed? "RLE" : "None"); printf ("Structure: %u planes of %u bits\n", P->Planes, P->BPP); printf ("Bounding box: [%u/%u - %u/%u]\n", P->XMin, P->YMin, P->XMax, P->YMax); printf ("Resolution: %u/%u DPI\n", P->XDPI, P->YDPI); printf ("Screen size: %u/%u\n", P->ScreenWidth, P->ScreenHeight); printf ("Bytes per plane: %u\n", P->BytesPerPlane); } static void ReadPlane (FILE* F, PCXHeader* P, unsigned char* L) /* Read one (possibly compressed) plane from the file */ { if (P->Compressed) { /* Uncompress RLE data */ unsigned Remaining = P->Width; while (Remaining) { unsigned char C; /* Read the next byte */ unsigned char B = Read8 (F); /* Check for a run length */ if ((B & 0xC0) == 0xC0) { C = (B & 0x3F); /* Count */ B = Read8 (F); /* Value */ } else { C = 1; } /* Write the data to the buffer */ if (C > Remaining) { C = Remaining; } memset (L, B, C); /* Bump counters */ L += C; Remaining -= C; } } else { /* Just read one line */ ReadData (F, L, P->Width); } } Bitmap* ReadPCXFile (const Collection* A) /* Read a bitmap from a PCX file */ { PCXHeader* P; Bitmap* B; unsigned char* L; Pixel* Px; unsigned MaxIdx = 0; unsigned X, Y; /* Get the file name */ const char* Name = NeedAttrVal (A, "name", "read pcx file"); /* Open the file */ FILE* F = fopen (Name, "rb"); if (F == 0) { Error ("Cannot open PCX file '%s': %s", Name, strerror (errno)); } /* Read the PCX header */ P = ReadPCXHeader (F, Name); /* Dump the header if requested */ if (Verbosity > 0) { DumpPCXHeader (P, Name); } /* Create the bitmap */ B = NewBitmap (P->Width, P->Height); /* Copy the name */ SB_CopyStr (&B->Name, Name); /* Allocate memory for the scan line */ L = xmalloc (P->Width); /* Read the pixel data */ Px = B->Data; if (P->Planes == 1) { /* This is either monochrome or indexed */ if (P->BPP == 1) { /* Monochrome */ for (Y = 0, Px = B->Data; Y < P->Height; ++Y) { unsigned I; unsigned char Mask; /* Read the plane */ ReadPlane (F, P, L); /* Create pixels */ for (X = 0, I = 0, Mask = 0x01; X < P->Width; ++Px) { Px->Index = (L[I] & Mask) != 0; if (Mask == 0x80) { Mask = 0x01; ++I; } else { Mask <<= 1; } } } } else { /* One plane with 8bpp is indexed */ for (Y = 0, Px = B->Data; Y < P->Height; ++Y) { /* Read the plane */ ReadPlane (F, P, L); /* Create pixels */ for (X = 0; X < P->Width; ++X, ++Px) { if (L[X] > MaxIdx) { MaxIdx = L[X]; } Px->Index = L[X]; } } } /* One plane means we have a palette which is either part of the header ** or follows. */ if (P->PalInfo == 0) { /* Create the monochrome palette */ B->Pal = NewMonochromePalette (); } else { unsigned Count; unsigned I; unsigned char Palette[256][3]; unsigned long EndPos; /* Determine the current file position */ unsigned long CurPos = FileGetPos (F); /* Seek to the end of the file */ (void) fseek (F, 0, SEEK_END); /* Get this position */ EndPos = FileGetPos (F); /* There's a palette if the old location is 769 bytes from the end */ if (EndPos - CurPos == sizeof (Palette) + 1) { /* Seek back */ FileSetPos (F, CurPos); /* Check for palette marker */ if (Read8 (F) != 0x0C) { Error ("Invalid palette marker in PCX file '%s'", Name); } } else if (EndPos == CurPos) { /* The palette is in the header */ FileSetPos (F, 16); /* Check the maximum index for safety */ if (MaxIdx > 15) { Error ("PCX file '%s' contains more than 16 indexed colors " "but no extra palette", Name); } } else { Error ("Error in PCX file '%s': %lu bytes at end of pixel data", Name, EndPos - CurPos); } /* Read the palette. We will just read what we need. */ Count = MaxIdx + 1; ReadData (F, Palette, Count * sizeof (Palette[0])); /* Create the palette from the data */ B->Pal = NewPalette (Count); for (I = 0; I < Count; ++I) { B->Pal->Entries[I].R = Palette[I][0]; B->Pal->Entries[I].G = Palette[I][1]; B->Pal->Entries[I].B = Palette[I][2]; B->Pal->Entries[I].A = 0; } } } else { /* 3 or 4 planes are RGB or RGBA (don't know if this exists) */ for (Y = 0, Px = B->Data; Y < P->Height; ++Y) { /* Read the R plane and move the data */ ReadPlane (F, P, L); for (X = 0; X < P->Width; ++X, ++Px) { Px->C.R = L[X]; } /* Read the G plane and move the data */ ReadPlane (F, P, L); for (X = 0; X < P->Width; ++X, ++Px) { Px->C.G = L[X]; } /* Read the B plane and move the data */ ReadPlane (F, P, L); for (X = 0; X < P->Width; ++X, ++Px) { Px->C.B = L[X]; } /* Either read the A plane or clear it */ if (P->Planes == 4) { ReadPlane (F, P, L); for (X = 0; X < P->Width; ++X, ++Px) { Px->C.A = L[X]; } } else { for (X = 0; X < P->Width; ++X, ++Px) { Px->C.A = 0; } } } } /* Close the file */ fclose (F); /* Free memory for the scan line */ xfree (L); /* Free the PCX header */ FreePCXHeader (P); /* Return the bitmap */ return B; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/pcx.h����������������������������������������������������������������������������0000664�0000000�0000000�00000005704�13473601511�0014542�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* pcx.h */ /* */ /* Read PCX files */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef PCX_H #define PCX_H /* common */ #include "coll.h" /* sp65 */ #include "bitmap.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ Bitmap* ReadPCXFile (const Collection* A); /* Read a bitmap from a PCX file */ /* End of pcx.h */ #endif ������������������������������������������������������������cc65-2.18/src/sp65/pixel.h��������������������������������������������������������������������������0000664�0000000�0000000�00000006357�13473601511�0015076�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* pixel.h */ /* */ /* Pixel definition for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef PIXEL_H #define PIXEL_H /* sp65 */ #include "color.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* A pixel is either a color or a palette index, depending on the bitmap */ typedef union Pixel Pixel; union Pixel { Color C; unsigned Index; }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ /* End of pixel.h */ #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/raw.c����������������������������������������������������������������������������0000664�0000000�0000000�00000007701�13473601511�0014533�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* raw.c */ /* */ /* Raw image converter for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "attrib.h" #include "print.h" /* sp65 */ #include "attr.h" #include "error.h" #include "raw.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ StrBuf* GenRaw (const Bitmap* B, const Collection* A attribute ((unused))) /* Generate binary output in raw format. The output is stored in a string ** buffer (which is actually a dynamic char array) and returned. */ { StrBuf* D; unsigned X, Y; /* Output the image properties */ Print (stdout, 1, "Image is %ux%u with %u colors%s\n", GetBitmapWidth (B), GetBitmapHeight (B), GetBitmapColors (B), BitmapIsIndexed (B)? " (indexed)" : ""); /* Check the bitmap properties */ if (!BitmapIsIndexed (B)) { Error ("The raw format needs an input bitmap in indexed format"); } /* Create the output buffer and resize it to the required size. */ D = NewStrBuf (); SB_Realloc (D, GetBitmapWidth (B) * GetBitmapHeight (B)); /* Convert the image */ for (Y = 0; Y < GetBitmapHeight (B); ++Y) { for (X = 0; X < GetBitmapWidth (B); ++X) { /* Place one pixel into the buffer */ SB_AppendChar (D, (unsigned char) GetPixel (B, X, Y).Index); } } /* Return the converted bitmap */ return D; } ���������������������������������������������������������������cc65-2.18/src/sp65/raw.h����������������������������������������������������������������������������0000664�0000000�0000000�00000006116�13473601511�0014537�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* raw.h */ /* */ /* Raw image converter for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef RAW_H #define RAW_H /* common */ #include "coll.h" #include "strbuf.h" /* sp65 */ #include "bitmap.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ StrBuf* GenRaw (const Bitmap* B, const Collection* A); /* Generate binary output in raw format. The output is stored in a string ** buffer (which is actually a dynamic char array) and returned. */ /* End of raw.h */ #endif ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/vic2sprite.c���������������������������������������������������������������������0000664�0000000�0000000�00000014557�13473601511�0016043�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* vic2sprite.c */ /* */ /* VICII sprite format backend for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ /* common */ #include "attrib.h" #include "print.h" /* sp65 */ #include "attr.h" #include "error.h" #include "vic2sprite.h" /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Sprite mode */ enum Mode { smAuto, smHighRes, smMultiColor }; /* Size of a sprite */ #define WIDTH_HR 24U #define WIDTH_MC 12U #define HEIGHT 21U /*****************************************************************************/ /* Code */ /*****************************************************************************/ static enum Mode GetMode (const Collection* A) /* Return the sprite mode from the attribute collection A */ { /* Check for a mode attribute */ const char* Mode = GetAttrVal (A, "mode"); if (Mode) { if (strcmp (Mode, "highres") == 0) { return smHighRes; } else if (strcmp (Mode, "multicolor") == 0) { return smMultiColor; } else { Error ("Invalid value for attribute 'mode'"); } } return smAuto; } StrBuf* GenVic2Sprite (const Bitmap* B, const Collection* A) /* Generate binary output in VICII sprite format for the bitmap B. The output ** is stored in a string buffer (which is actually a dynamic char array) and ** returned. */ { enum Mode M; StrBuf* D; unsigned X, Y; /* Output the image properties */ Print (stdout, 1, "Image is %ux%u with %u colors%s\n", GetBitmapWidth (B), GetBitmapHeight (B), GetBitmapColors (B), BitmapIsIndexed (B)? " (indexed)" : ""); /* Get the sprite mode */ M = GetMode (A); /* Check the height of the bitmap */ if (GetBitmapHeight (B) != HEIGHT) { Error ("Invalid bitmap height (%u) for conversion to vic2 sprite", GetBitmapHeight (B)); } /* If the mode wasn't given, determine it from the image properties */ if (M == smAuto) { switch (GetBitmapWidth (B)) { case WIDTH_HR: M = smHighRes; break; case WIDTH_MC: M = smMultiColor; break; default: Error ("Cannot determine mode from image properties"); } } /* Now check if mode and the image properties match */ if (M == smMultiColor) { if (GetBitmapWidth (B) != WIDTH_MC || GetBitmapColors (B) > 4) { Error ("Invalid image properties for multicolor sprite"); } } else { if (GetBitmapWidth (B) != WIDTH_HR || GetBitmapColors (B) > 2) { Error ("Invalid image properties for highres sprite"); } } /* Create the output buffer and resize it to the required size. */ D = NewStrBuf (); SB_Realloc (D, 63); /* Convert the image */ for (Y = 0; Y < HEIGHT; ++Y) { unsigned char V = 0; if (M == smHighRes) { for (X = 0; X < WIDTH_HR; ++X) { /* Fetch next bit into byte buffer */ V = (V << 1) | (GetPixel (B, X, Y).Index & 0x01); /* Store full bytes into the output buffer */ if ((X & 0x07) == 0x07) { SB_AppendChar (D, V); V = 0; } } } else { for (X = 0; X < WIDTH_MC; ++X) { /* Fetch next bit into byte buffer */ V = (V << 2) | (GetPixel (B, X, Y).Index & 0x03); /* Store full bytes into the output buffer */ if ((X & 0x03) == 0x03) { SB_AppendChar (D, V); V = 0; } } } } /* Return the converted bitmap */ return D; } �������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/src/sp65/vic2sprite.h���������������������������������������������������������������������0000664�0000000�0000000�00000006210�13473601511�0016033�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* vic2sprite.h */ /* */ /* VICII sprite format backend for the sp65 sprite and bitmap utility */ /* */ /* */ /* */ /* (C) 2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef VIC2SPRITE_H #define VIC2SPRITE_H /* common */ #include "coll.h" #include "strbuf.h" /* sp65 */ #include "bitmap.h" /*****************************************************************************/ /* Code */ /*****************************************************************************/ StrBuf* GenVic2Sprite (const Bitmap* B, const Collection* A); /* Generate binary output in VICII sprite format for the bitmap B. The output ** is stored in a string buffer (which is actually a dynamic char array) and ** returned. */ /* End of vic2sprite.h */ #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/�������������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0013164�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/.gitignore���������������������������������������������������������������������������0000664�0000000�0000000�00000000004�13473601511�0015146�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������*.o ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/Makefile�����������������������������������������������������������������������������0000664�0000000�0000000�00000001207�13473601511�0014624�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# top-level Makefile for the regression tests ifneq ($(shell echo),) CMD_EXE = 1 endif ifdef CMD_EXE RMDIR = -rmdir /s /q $(subst /,\,$1) else RMDIR = $(RM) -r $1 endif WORKDIR = ../testwrk .PHONY: all dotests continue mostlyclean clean all: dotests .NOTPARALLEL: dotests: mostlyclean continue continue: @$(MAKE) -C asm all @$(MAKE) -C dasm all @$(MAKE) -C val all @$(MAKE) -C ref all @$(MAKE) -C err all @$(MAKE) -C misc all mostlyclean: @$(MAKE) -C asm clean @$(MAKE) -C dasm clean @$(MAKE) -C val clean @$(MAKE) -C ref clean @$(MAKE) -C err clean @$(MAKE) -C misc clean clean: mostlyclean @$(call RMDIR,$(WORKDIR)) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/asm/���������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0013744�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/asm/4510-cpudetect.ref���������������������������������������������������������������0000664�0000000�0000000�00000000074�13473601511�0017012�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������K�CPU_ISET_6502�CPU_ISET_65SC02�CPU_ISET_65C02�CPU_ISET_4510��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/asm/4510-opcodes.ref�����������������������������������������������������������������0000664�0000000�0000000�00000001064�13473601511�0016466�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000�������������������������������������������������������������������������������������������������������������������������������������������������������������������������  4 443011V4EE3 4!"E##V$$%&'()*+,4-4.4/30012311456789V:;<E=E>E?3@ABCDEFGHIJKL4M4N4O3P0QRS11TUVWXYVZ[\]E^E_3`ab c11defghijklE#m4n4o3p0qrs11tuvwxyVz{|V$}E~E3€0‚‚ƒ11„…†‡ˆ‰Š‹EŒ44Ž430‘’“11”•–—˜™Vš›Vœ4EžEŸ3 ¡¢£¤¥¦§¨©ª«4¬4­4®4¯3°0±²³11´µ¶·¸¹Vº»E¼E½E¾V¿3ÀÁÂÃÄÅÆÇÈÉÊË4Ì4Í4Î4Ï3Ð0ÑÒÓ11ÔÕÖרÙVÚÛÜ4ÝEÞEß3àáââãäåæçèéêêë4ì4í4î4ï3ð0ñòó11ôšôšõö÷øùVúûü4ü4ýEþEÿ3����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/asm/4510-opcodes.s�������������������������������������������������������������������0000664�0000000�0000000�00000006514�13473601511�0016161�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������.setcpu "4510" brk ora ($05,x) cle see tsb $02 ora $02 asl $02 rmb0 $02 php ora #$01 asl tsy tsb $1234 ora $1234 asl $1234 bbr0 $02,*+$34 bpl *+$32 ora ($06),y ora ($07),z lbpl *+$3133 ; bpl *+$3133 trb $02 ora $03,x asl $03,x rmb1 $02 clc ora $1456,y inc inz trb $1234 ora $1345,x asl $1345,x bbr1 $02,*+$34 jsr $1234 and ($05,x) jsr ($2345) jsr ($2456,x) bit $02 and $02 rol $02 rmb2 $02 plp and #$01 rol tys bit $1234 and $1234 rol $1234 bbr2 $02,*+$34 bmi *+$32 and ($06),y and ($07),z lbmi *+$3133 ; bmi *+$3133 bit $03,x and $03,x rol $03,x rmb3 $02 sec and $1456,y dec dez bit $1345,x and $1345,x rol $1345,x bbr3 $02,*+$34 rti eor ($05,x) neg asr asr $02 eor $02 lsr $02 rmb4 $02 pha eor #$01 lsr taz jmp $1234 eor $1234 lsr $1234 bbr4 $02,*+$34 bvc *+$32 eor ($06),y eor ($07),z lbvc *+$3133 ; bvc *+$3133 asr $03,x eor $03,x lsr $03,x rmb5 $02 cli eor $1456,y phy tab map eor $1345,x lsr $1345,x bbr5 $02,*+$34 rts adc ($05,x) rtn #$09 bsr *+$3133 stz $02 adc $02 ror $02 rmb6 $02 pla adc #$01 ror tza jmp ($2345) adc $1234 ror $1234 bbr6 $02,*+$34 bvs *+$32 adc ($06),y adc ($07),z lbvs *+$3133 ; bvs *+$3133 stz $03,x adc $03,x ror $03,x rmb7 $02 sei adc $1456,y ply tba jmp ($2456,x) adc $1345,x ror $1345,x bbr7 $02,*+$34 bra *+$32 sta ($05,x) sta ($0f,s),y sta ($0f,sp),y lbra *+$3133 ; bra *+$3133 sty $02 sta $02 stx $02 smb0 $02 dey bit #$01 txa sty $1345,x sty $1234 sta $1234 stx $1234 bbs0 $02,*+$34 bcc *+$32 sta ($06),y sta ($07),z lbcc *+$3133 ; bcc *+$3133 sty $03,x sta $03,x stx $04,y smb1 $02 tya sta $1456,y txs stx $1456,y stz $1234 sta $1345,x stz $1345,x bbs1 $02,*+$34 ldy #$01 lda ($05,x) ldx #$01 ldz #$01 ldy $02 lda $02 ldx $02 smb2 $02 tay lda #$01 tax ldz $1234 ldy $1234 lda $1234 ldx $1234 bbs2 $02,*+$34 bcs *+$32 lda ($06),y lda ($07),z lbcs *+$3133 ; bcs *+$3133 ldy $03,x lda $03,x ldx $04,y smb3 $02 clv lda $1456,y tsx ldz $1345,x ldy $1345,x lda $1345,x ldx $1456,y bbs3 $02,*+$34 cpy #$01 cmp ($05,x) cpz #$01 dew $02 cpy $02 cmp $02 dec $02 smb4 $02 iny cmp #$01 dex asw $1234 cpy $1234 cmp $1234 dec $1234 bbs4 $02,*+$34 bne *+$32 cmp ($06),y cmp ($07),z lbne *+$3133 ; bne *+$3133 cpz $02 cmp $03,x dec $03,x smb5 $02 cld cmp $1456,y phx phz cpz $1234 cmp $1345,x dec $1345,x bbs5 $02,*+$34 cpx #$01 sbc ($05,x) lda ($0f,s),y lda ($0f,sp),y inw $02 cpx $02 sbc $02 inc $02 smb6 $02 inx sbc #$01 eom nop row $1234 cpx $1234 sbc $1234 inc $1234 bbs6 $02,*+$34 beq *+$32 sbc ($06),y sbc ($07),z lbeq *+$3133 ; beq *+$3133 phd #$089a phw #$089a sbc $03,x inc $03,x smb7 $02 sed sbc $1456,y plx plz phd $1234 phw $1234 sbc $1345,x inc $1345,x bbs7 $02,*+$34 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/asm/6502-cpudetect.ref���������������������������������������������������������������0000664�0000000�0000000�00000000020�13473601511�0017004�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������©ê�CPU_ISET_6502����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/asm/6502-opcodes.ref�����������������������������������������������������������������0000664�0000000�0000000�00000000651�13473601511�0016472�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000�������������������������������������������������������������������������������������������������������������������������������������������������������������������������  V4V4xV4V4V4 V4!"#$%&'()*+,V4-V4.V4/0x123456789V4:;<=V4>V4?@ABCDEFGHIJKLV4MV4NV4OPxQRSTUVWXYV4Z[\]V4^V4_`abcdefghijklV4mV4nV4opxqrstuvwxyV4z{|}V4~V4€‚ƒ„…†‡ˆ‰Š‹ŒV4V4ŽV4x‘’“”•–—˜™V4š›œV4žŸ ¡¢£¤¥¦§¨©ª«¬V4­V4®V4¯°x±²³´µ¶·¸¹V4º»¼V4½V4¾V4¿ÀÁÂÃÄÅÆÇÈÉÊËÌV4ÍV4ÎV4ÏÐxÑÒÓÔÕÖרÙV4ÚÛÜÝV4ÞV4ßàáâãäåæçèéëìV4íV4îV4ïðxñòóôõö÷øùV4úûüýV4þV4ÿ���������������������������������������������������������������������������������������cc65-2.18/test/asm/6502-opcodes.s�������������������������������������������������������������������0000664�0000000�0000000�00000007512�13473601511�0016163�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������.setcpu "6502" brk ora ($12,x) .byte $02 .byte $03 .byte $04 ora $12 asl $12 .byte $07 php ora #$12 asl a .byte $0B .byte $0C ora $3456 asl $3456 .byte $0F bpl *+122 ora ($12),y .byte $12 .byte $13 .byte $14 ora $12,x asl $12,x .byte $17 clc ora $3456,y .byte $1A .byte $1B .byte $1C ora $3456,x asl $3456,x .byte $1F jsr $3456 and ($12,x) .byte $22 .byte $23 bit $12 and $12 rol $12 .byte $27 plp and #$12 rol a .byte $2B bit $3456 and $3456 rol $3456 .byte $2F bmi *+122 and ($12),y .byte $32 .byte $33 .byte $34 and $12,x rol $12,x .byte $37 sec and $3456,y .byte $3A .byte $3B .byte $3C and $3456,x rol $3456,x .byte $3F rti eor ($12,x) .byte $42 .byte $43 .byte $44 eor $12 lsr $12 .byte $47 pha eor #$12 lsr a .byte $4B jmp $3456 eor $3456 lsr $3456 .byte $4F bvc *+122 eor ($12),y .byte $52 .byte $53 .byte $54 eor $12,x lsr $12,x .byte $57 cli eor $3456,y .byte $5A .byte $5B .byte $5C eor $3456,x lsr $3456,x .byte $5F rts adc ($12,x) .byte $62 .byte $63 .byte $64 adc $12 ror $12 .byte $67 pla adc #$12 ror a .byte $6B jmp ($3456) adc $3456 ror $3456 .byte $6F bvs *+122 adc ($12),y .byte $72 .byte $73 .byte $74 adc $12,x ror $12,x .byte $77 sei adc $3456,y .byte $7A .byte $7B .byte $7C adc $3456,x ror $3456,x .byte $7F .byte $80 sta ($12,x) .byte $82 .byte $83 sty $12 sta $12 stx $12 .byte $87 dey .byte $89 txa .byte $8B sty $3456 sta $3456 stx $3456 .byte $8F bcc *+122 sta ($12),y .byte $92 .byte $93 sty $12,x sta $12,x stx $12,y .byte $97 tya sta $3456,y txs .byte $9B .byte $9C sta $3456,x .byte $9E .byte $9F ldy #$12 lda ($12,x) ldx #$12 .byte $A3 ldy $12 lda $12 ldx $12 .byte $A7 tay lda #$12 tax .byte $AB ldy $3456 lda $3456 ldx $3456 .byte $AF bcs *+122 lda ($12),y .byte $B2 .byte $B3 ldy $12,x lda $12,x ldx $12,y .byte $B7 clv lda $3456,y tsx .byte $BB ldy $3456,x lda $3456,x ldx $3456,y .byte $BF cpy #$12 cmp ($12,x) .byte $C2 .byte $C3 cpy $12 cmp $12 dec $12 .byte $C7 iny cmp #$12 dex .byte $CB cpy $3456 cmp $3456 dec $3456 .byte $CF bne *+122 cmp ($12),y .byte $D2 .byte $D3 .byte $D4 cmp $12,x dec $12,x .byte $D7 cld cmp $3456,y .byte $DA .byte $DB .byte $DC cmp $3456,x dec $3456,x .byte $DF cpx #$12 sbc ($12,x) .byte $E2 .byte $E3 cpx $12 sbc $12 inc $12 .byte $E7 inx sbc #$12 .byte $EB cpx $3456 sbc $3456 inc $3456 .byte $EF beq *+122 sbc ($12),y .byte $F2 .byte $F3 .byte $F4 sbc $12,x inc $12,x .byte $F7 sed sbc $3456,y .byte $FA .byte $FB .byte $FC sbc $3456,x inc $3456,x .byte $FF ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/asm/6502x-cpudetect.ref��������������������������������������������������������������0000664�0000000�0000000�00000000035�13473601511�0017202�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000�������������������������������������������������������������������������������������������������������������������������������������������������������������������������CPU_ISET_6502�CPU_ISET_6502X���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/asm/6502x-opcodes.ref����������������������������������������������������������������0000664�0000000�0000000�00000001040�13473601511�0016653�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000�������������������������������������������������������������������������������������������������������������������������������������������������������������������������   V4 V4V4V4xV4V4V4V4V4V4 V4!"#$%&'()*+,V4-V4.V4/V40x123456789V4:;V4<V4=V4>V4?V4@ABCDEFGHIJKLV4MV4NV4OV4PxQRSTUVWXYV4Z[V4V4]V4^V4_V4`abcdefghijklV4mV4nV4oV4pxqrstuvwxyV4z{V4|V4}V4~V4V4€‚ƒ„…†‡ˆ‰Š‹ŒV4V4ŽV4V4x‘’“”•–—˜™V4š›V4œV4V4žV4ŸV4 ¡¢£¤¥¦§¨©ª«¬V4­V4®V4¯V4°x±²³´µ¶·¸¹V4º»V4¼V4½V4¾V4¿V4ÀÁÂÃÄÅÆÇÈÉÊËÌV4ÍV4ÎV4ÏV4ÐxÑÒÓÔÕÖרÙV4ÚÛV4ÜV4ÝV4ÞV4ßV4àáâãäåæçèéêëìV4íV4îV4ïV4ðxñòóôõö÷øùV4úûV4üV4ýV4þV4ÿV4������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/asm/6502x-opcodes.s������������������������������������������������������������������0000664�0000000�0000000�00000011267�13473601511�0016355�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������.setcpu "6502X" brk ora ($12,x) jam slo ($12,x) nop $12 ora $12 asl $12 slo $12 php ora #$12 asl a anc #$12 nop $3456 ora $3456 asl $3456 slo $3456 bpl *+122 ora ($12),y .byte $12 ; jam slo ($12),y nop $12,x ora $12,x asl $12,x slo $12,x clc ora $3456,y .byte $1a ; nop slo $3456,y nop $3456,x ora $3456,x asl $3456,x slo $3456,x jsr $3456 and ($12,x) .byte $22 ; jam rla ($12,x) bit $12 and $12 rol $12 rla $12 plp and #$12 rol a .byte $2b ; anc #$12 bit $3456 and $3456 rol $3456 rla $3456 bmi *+122 and ($12),y .byte $32 ; jam rla ($12),y .byte $34,$12 ; nop $12,x and $12,x rol $12,x rla $12,x sec and $3456,y .byte $3a ; nop rla $3456,y .byte $3c,$56,$34 ; nop $3456,x and $3456,x rol $3456,x rla $3456,x rti eor ($12,x) .byte $42 ; jam sre ($12,x) .byte $44,$12 ; nop $12 eor $12 lsr $12 sre $12 pha eor #$12 lsr a alr #$12 jmp $3456 eor $3456 lsr $3456 sre $3456 bvc *+122 eor ($12),y .byte $52 ; jam sre ($12),y .byte $54,$12 ; nop $12,x eor $12,x lsr $12,x sre $12,x cli eor $3456,y .byte $5a ; nop sre $3456,y nop $3456,x eor $3456,x lsr $3456,x sre $3456,x rts adc ($12,x) .byte $62 ; jam rra ($12,x) .byte $64,$12 ; nop $12 adc $12 ror $12 rra $12 pla adc #$12 ror a arr #$12 jmp ($3456) adc $3456 ror $3456 rra $3456 bvs *+122 adc ($12),y .byte $72 ; jam rra ($12),y .byte $74,$12 ; nop $12,x adc $12,x ror $12,x rra $12,x sei adc $3456,y .byte $7a ; nop rra $3456,y .byte $7c,$56,$34 ; nop $3456,x adc $3456,x ror $3456,x rra $3456,x nop #$12 sta ($12,x) .byte $82,$12 ; nop #$12 sax ($12,x) sty $12 sta $12 stx $12 sax $12 dey .byte $89,$12 ; nop #$12 txa .byte $8b,$12 ; xaa #$12 sty $3456 sta $3456 stx $3456 sax $3456 bcc *+122 sta ($12),y .byte $92 ; jam .byte $93,$12 ; ahx ($12),y sty $12,x sta $12,x stx $12,y sax $12,y tya sta $3456,y txs tas $3456,y shy $3456,x sta $3456,x shx $3456,y .byte $9f,$56,$34 ; ahx $3456,y ldy #$12 lda ($12,x) ldx #$12 lax ($12,x) ldy $12 lda $12 ldx $12 lax $12 tay lda #$12 tax lax #$12 ldy $3456 lda $3456 ldx $3456 lax $3456 bcs *+122 lda ($12),y .byte $b2 ; jam lax ($12),y ldy $12,x lda $12,x ldx $12,y lax $12,y clv lda $3456,y tsx las $3456,y ldy $3456,x lda $3456,x ldx $3456,y lax $3456,y cpy #$12 cmp ($12,x) .byte $c2,$12 ; nop #$12 dcp ($12,x) cpy $12 cmp $12 dec $12 dcp $12 iny cmp #$12 dex axs #$12 cpy $3456 cmp $3456 dec $3456 dcp $3456 bne *+122 cmp ($12),y .byte $d2 ; jam dcp ($12),y .byte $d4,$12 ; nop $12,x cmp $12,x dec $12,x dcp $12,x cld cmp $3456,y .byte $da ; nop dcp $3456,y .byte $dc,$56,$34 ; nop $3456,x cmp $3456,x dec $3456,x dcp $3456,x cpx #$12 sbc ($12,x) .byte $e2,$12 ; nop #$12 isc ($12,x) cpx $12 sbc $12 inc $12 isc $12 inx sbc #$12 nop .byte $eb ; nop cpx $3456 sbc $3456 inc $3456 isc $3456 beq *+122 sbc ($12),y .byte $f2 ; jam isc ($12),y .byte $f4,$12 ; nop $12,x sbc $12,x inc $12,x isc $12,x sed sbc $3456,y .byte $fa ; nop isc $3456,y .byte $fc,$56,$34 ; nop $3456,x sbc $3456,x inc $3456,x isc $3456,x �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/asm/65816-cpudetect.ref��������������������������������������������������������������0000664�0000000�0000000�00000000075�13473601511�0017113�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ë�CPU_ISET_6502�CPU_ISET_65SC02�CPU_ISET_65C02�CPU_ISET_65816�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/asm/65c02-cpudetect.ref��������������������������������������������������������������0000664�0000000�0000000�00000000057�13473601511�0017161�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000�������������������������������������������������������������������������������������������������������������������������������������������������������������������������CPU_ISET_6502�CPU_ISET_65SC02�CPU_ISET_65C02���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/asm/65c02-opcodes.ref����������������������������������������������������������������0000664�0000000�0000000�00000000765�13473601511�0016643�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000�������������������������������������������������������������������������������������������������������������������������������������������������������������������������  V4 V4V4yxV4V4V4V4y V4!"#$%&'()*+,V4-V4.V4/y0x123456789V4:;<V4=V4>V4?y@ABCDEFGHIJKLV4MV4NV4OyPxQRSTUVWXYV4Z[\]V4^V4_y`abcdefghijklV4mV4nV4oypxqrstuvwxyV4z{|V4}V4~V4y€x‚ƒ„…†‡ˆ‰Š‹ŒV4V4ŽV4yx‘’“”•–—˜™V4š›œV4V4žV4Ÿy ¡¢£¤¥¦§¨©ª«¬V4­V4®V4¯y°x±²³´µ¶·¸¹V4º»¼V4½V4¾V4¿yÀÁÂÃÄÅÆÇÈÉÊËÌV4ÍV4ÎV4ÏyÐxÑÒÓÔÕÖרÙV4ÚÛÜÝV4ÞV4ßyàáâãäåæçèéêëìV4íV4îV4ïyðxñòóôõö÷øùV4úûüýV4þV4ÿy�����������cc65-2.18/test/asm/65c02-opcodes.s������������������������������������������������������������������0000664�0000000�0000000�00000007671�13473601511�0016334�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������.setcpu "65C02" brk ora ($12,x) .byte $02 .byte $03 tsb $12 ora $12 asl $12 rmb0 $12 php ora #$12 asl a .byte $0B tsb $3456 ora $3456 asl $3456 bbr0 $12,*+122 bpl *+122 ora ($12),y ora ($12) .byte $13 trb $12 ora $12,x asl $12,x rmb1 $12 clc ora $3456,y inc a .byte $1B trb $3456 ora $3456,x asl $3456,x bbr1 $12,*+122 jsr $3456 and ($12,x) .byte $22 .byte $23 bit $12 and $12 rol $12 rmb2 $12 plp and #$12 rol a .byte $2B bit $3456 and $3456 rol $3456 bbr2 $12,*+122 bmi *+122 and ($12),y and ($12) .byte $33 bit $12,x and $12,x rol $12,x rmb3 $12 sec and $3456,y dec a .byte $3B bit $3456,x and $3456,x rol $3456,x bbr3 $12,*+122 rti eor ($12,x) .byte $42 .byte $43 .byte $44 eor $12 lsr $12 rmb4 $12 pha eor #$12 lsr a .byte $4B jmp $3456 eor $3456 lsr $3456 bbr4 $12,*+122 bvc *+122 eor ($12),y eor ($12) .byte $53 .byte $54 eor $12,x lsr $12,x rmb5 $12 cli eor $3456,y phy .byte $5B .byte $5C eor $3456,x lsr $3456,x bbr5 $12,*+122 rts adc ($12,x) .byte $62 .byte $63 stz $12 adc $12 ror $12 rmb6 $12 pla adc #$12 ror a .byte $6B jmp ($3456) adc $3456 ror $3456 bbr6 $12,*+122 bvs *+122 adc ($12),y adc ($12) .byte $73 stz $12,x adc $12,x ror $12,x rmb7 $12 sei adc $3456,y ply .byte $7B jmp ($3456,x) adc $3456,x ror $3456,x bbr7 $12,*+122 bra *+122 sta ($12,x) .byte $82 .byte $83 sty $12 sta $12 stx $12 smb0 $12 dey bit #$12 txa .byte $8B sty $3456 sta $3456 stx $3456 bbs0 $12,*+122 bcc *+122 sta ($12),y sta ($12) .byte $93 sty $12,x sta $12,x stx $12,y smb1 $12 tya sta $3456,y txs .byte $9B stz $3456 sta $3456,x stz $3456,x bbs1 $12,*+122 ldy #$12 lda ($12,x) ldx #$12 .byte $A3 ldy $12 lda $12 ldx $12 smb2 $12 tay lda #$12 tax .byte $AB ldy $3456 lda $3456 ldx $3456 bbs2 $12,*+122 bcs *+122 lda ($12),y lda ($12) .byte $B3 ldy $12,x lda $12,x ldx $12,y smb3 $12 clv lda $3456,y tsx .byte $BB ldy $3456,x lda $3456,x ldx $3456,y bbs3 $12,*+122 cpy #$12 cmp ($12,x) .byte $C2 .byte $C3 cpy $12 cmp $12 dec $12 smb4 $12 iny cmp #$12 dex .byte $CB cpy $3456 cmp $3456 dec $3456 bbs4 $12,*+122 bne *+122 cmp ($12),y cmp ($12) .byte $D3 .byte $D4 cmp $12,x dec $12,x smb5 $12 cld cmp $3456,y phx .byte $DB .byte $DC cmp $3456,x dec $3456,x bbs5 $12,*+122 cpx #$12 sbc ($12,x) .byte $E2 .byte $E3 cpx $12 sbc $12 inc $12 smb6 $12 inx sbc #$12 nop .byte $EB cpx $3456 sbc $3456 inc $3456 bbs6 $12,*+122 beq *+122 sbc ($12),y sbc ($12) .byte $F3 .byte $F4 sbc $12,x inc $12,x smb7 $12 sed sbc $3456,y plx .byte $FB .byte $FC sbc $3456,x inc $3456,x bbs7 $12,*+122 �����������������������������������������������������������������������cc65-2.18/test/asm/65sc02-cpudetect.ref�������������������������������������������������������������0000664�0000000�0000000�00000000041�13473601511�0017335�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������|4�CPU_ISET_6502�CPU_ISET_65SC02�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/asm/65sc02-opcodes.ref���������������������������������������������������������������0000664�0000000�0000000�00000000705�13473601511�0017020�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000�������������������������������������������������������������������������������������������������������������������������������������������������������������������������  V4 V4V4xV4V4V4V4 V4!"#$%&'()*+,V4-V4.V4/0x123456789V4:;<V4=V4>V4?@ABCDEFGHIJKLV4MV4NV4OPxQRSTUVWXYV4Z[\]V4^V4_`abcdefghijklV4mV4nV4opxqrstuvwxyV4z{|V4}V4~V4€x‚ƒ„…†‡ˆ‰Š‹ŒV4V4ŽV4x‘’“”•–—˜™V4š›œV4V4žV4Ÿ ¡¢£¤¥¦§¨©ª«¬V4­V4®V4¯°x±²³´µ¶·¸¹V4º»¼V4½V4¾V4¿ÀÁÂÃÄÅÆÇÈÉÊËÌV4ÍV4ÎV4ÏÐxÑÒÓÔÕÖרÙV4ÚÛÜÝV4ÞV4ßàáâãäåæçèéêëìV4íV4îV4ïðxñòóôõö÷øùV4úûüýV4þV4ÿ�����������������������������������������������������������cc65-2.18/test/asm/65sc02-opcodes.s�����������������������������������������������������������������0000664�0000000�0000000�00000007532�13473601511�0016513�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������.setcpu "65SC02" brk ora ($12,x) .byte $02 .byte $03 tsb $12 ora $12 asl $12 .byte $07 php ora #$12 asl a .byte $0B tsb $3456 ora $3456 asl $3456 .byte $0F bpl *+122 ora ($12),y ora ($12) .byte $13 trb $12 ora $12,x asl $12,x .byte $17 clc ora $3456,y inc a .byte $1B trb $3456 ora $3456,x asl $3456,x .byte $1F jsr $3456 and ($12,x) .byte $22 .byte $23 bit $12 and $12 rol $12 .byte $27 plp and #$12 rol a .byte $2B bit $3456 and $3456 rol $3456 .byte $2F bmi *+122 and ($12),y and ($12) .byte $33 bit $12,x and $12,x rol $12,x .byte $37 sec and $3456,y dec a .byte $3B bit $3456,x and $3456,x rol $3456,x .byte $3F rti eor ($12,x) .byte $42 .byte $43 .byte $44 eor $12 lsr $12 .byte $47 pha eor #$12 lsr a .byte $4B jmp $3456 eor $3456 lsr $3456 .byte $4F bvc *+122 eor ($12),y eor ($12) .byte $53 .byte $54 eor $12,x lsr $12,x .byte $57 cli eor $3456,y phy .byte $5B .byte $5C eor $3456,x lsr $3456,x .byte $5F rts adc ($12,x) .byte $62 .byte $63 stz $12 adc $12 ror $12 .byte $67 pla adc #$12 ror a .byte $6B jmp ($3456) adc $3456 ror $3456 .byte $6F bvs *+122 adc ($12),y adc ($12) .byte $73 stz $12,x adc $12,x ror $12,x .byte $77 sei adc $3456,y ply .byte $7B jmp ($3456,x) adc $3456,x ror $3456,x .byte $7F bra *+122 sta ($12,x) .byte $82 .byte $83 sty $12 sta $12 stx $12 .byte $87 dey bit #$12 txa .byte $8B sty $3456 sta $3456 stx $3456 .byte $8F bcc *+122 sta ($12),y sta ($12) .byte $93 sty $12,x sta $12,x stx $12,y .byte $97 tya sta $3456,y txs .byte $9B stz $3456 sta $3456,x stz $3456,x .byte $9F ldy #$12 lda ($12,x) ldx #$12 .byte $A3 ldy $12 lda $12 ldx $12 .byte $A7 tay lda #$12 tax .byte $AB ldy $3456 lda $3456 ldx $3456 .byte $AF bcs *+122 lda ($12),y lda ($12) .byte $B3 ldy $12,x lda $12,x ldx $12,y .byte $B7 clv lda $3456,y tsx .byte $BB ldy $3456,x lda $3456,x ldx $3456,y .byte $BF cpy #$12 cmp ($12,x) .byte $C2 .byte $C3 cpy $12 cmp $12 dec $12 .byte $C7 iny cmp #$12 dex .byte $CB cpy $3456 cmp $3456 dec $3456 .byte $CF bne *+122 cmp ($12),y cmp ($12) .byte $D3 .byte $D4 cmp $12,x dec $12,x .byte $D7 cld cmp $3456,y phx .byte $DB .byte $DC cmp $3456,x dec $3456,x .byte $DF cpx #$12 sbc ($12,x) .byte $E2 .byte $E3 cpx $12 sbc $12 inc $12 .byte $E7 inx sbc #$12 nop .byte $EB cpx $3456 sbc $3456 inc $3456 .byte $EF beq *+122 sbc ($12),y sbc ($12) .byte $F3 .byte $F4 sbc $12,x inc $12,x .byte $F7 sed sbc $3456,y plx .byte $FB .byte $FC sbc $3456,x inc $3456,x .byte $FF ����������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/asm/Makefile�������������������������������������������������������������������������0000664�0000000�0000000�00000003277�13473601511�0015415�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile for the assembler regression tests ifneq ($(shell echo),) CMD_EXE = 1 endif ifdef CMD_EXE EXE = .exe MKDIR = mkdir $(subst /,\,$1) RMDIR = -rmdir /s /q $(subst /,\,$1) DEL = del /f $(subst /,\,$1) else EXE = MKDIR = mkdir -p $1 RMDIR = $(RM) -r $1 DEL = $(RM) $1 endif ifdef QUIET .SILENT: endif CL65 := $(if $(wildcard ../../bin/cl65*),../../bin/cl65,cl65) WORKDIR = ../../testwrk/asm DIFF = $(WORKDIR)/bdiff$(EXE) CC = gcc CFLAGS = -O2 .PHONY: all clean OPCODE_REFS := $(wildcard *-opcodes.ref) OPCODE_CPUS = $(foreach ref,$(OPCODE_REFS),$(ref:%-opcodes.ref=%)) OPCODE_BINS = $(foreach cpu,$(OPCODE_CPUS),$(WORKDIR)/$(cpu)-opcodes.bin) CPUDETECT_REFS := $(wildcard *-cpudetect.ref) CPUDETECT_CPUS = $(foreach ref,$(CPUDETECT_REFS),$(ref:%-cpudetect.ref=%)) CPUDETECT_BINS = $(foreach cpu,$(CPUDETECT_CPUS),$(WORKDIR)/$(cpu)-cpudetect.bin) all: $(OPCODE_BINS) $(CPUDETECT_BINS) $(WORKDIR): $(call MKDIR,$(WORKDIR)) $(DIFF): ../bdiff.c | $(WORKDIR) $(CC) $(CFLAGS) -o $@ $< define OPCODE_template $(WORKDIR)/$1-opcodes.bin: $1-opcodes.s $(DIFF) $(if $(QUIET),echo asm/$1-opcodes.bin) $(CL65) --cpu $1 -t none -l $(WORKDIR)/$1-opcodes.lst -o $$@ $$< $(DIFF) $$@ $1-opcodes.ref endef # OPCODE_template $(foreach cpu,$(OPCODE_CPUS),$(eval $(call OPCODE_template,$(cpu)))) define CPUDETECT_template $(WORKDIR)/$1-cpudetect.bin: cpudetect.s $(DIFF) $(if $(QUIET),echo asm/$1-cpudetect.bin) $(CL65) --cpu $1 -t none -l $(WORKDIR)/$1-cpudetect.lst -o $$@ $$< $(DIFF) $$@ $1-cpudetect.ref endef # CPUDETECT_template $(foreach cpu,$(CPUDETECT_CPUS),$(eval $(call CPUDETECT_template,$(cpu)))) clean: @$(call RMDIR,$(WORKDIR)) @$(call DEL,$(OPCODE_REFS:.ref=.o) cpudetect.o) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/asm/README���������������������������������������������������������������������������0000664�0000000�0000000�00000002744�13473601511�0014633�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ Assembler Testcases =================== Opcode Tests: ------------- These testcases are inspired by the ones now removed from test/assembler. The main purpose is to have each possible opcode generated at least once, either by an assembly instruction or a ".byte"-placeholder. Typically generated by disassembling a binary dump that contains data in the form of the pattern that each opcode is stated once in order followed by easy to recognise: 00 00 EA 00 01 00 EA 00 02 00 EA 00 [...] fe 00 EA 00 ff 00 EA 00 The disassembly is then put in a better readable form by replacing the leftover dummy opcode parameters with something more recognizable. The testcases for 6502, 6502x, 65sc02, 65c02, 4510, and huc6280 have been put together by Sven Oliver ("SvOlli") Moll, as well as a template for the m740 instructions set. Still to do is to find a way to implement an opcode testcase for the 65816 processor, since it's capable of executing instructions with an 8-bit and a 16-bit operator alike, only distinguished by one processor flag. CPU detect Tests ---------------- These tests all assemble the same file "cpudetect.s" which contains several conditionals for several CPUs, only using every option known to the "--cpu" commandline switch of ca65/cl65. Reference (".ref") Files ------------------------ A hint on creating these files: when running the test, it will fail due to the missing ".ref" file. Review the output of the ".lst" very pedantic, then copy the ".bin" to the ".ref" file. ����������������������������cc65-2.18/test/asm/cpudetect.s����������������������������������������������������������������������0000664�0000000�0000000�00000001762�13473601511�0016116�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ .macpack cpu ; step 1: try to assemble an instruction that's exclusive to this set ; (when possible) .ifp02 lda #$ea .endif .ifpsc02 jmp ($1234,x) .endif .ifpc02 rmb0 $12 .endif .ifp816 xba .endif .ifp4510 taz .endif ; step 2: check for bitwise compatibility of instructions sets ; (made verbose for better reading with hexdump/hd(1)) .if (.cpu .bitand CPU_ISET_NONE) .byte 0,"CPU_ISET_NONE" .endif .if (.cpu .bitand CPU_ISET_6502) .byte 0,"CPU_ISET_6502" .endif .if (.cpu .bitand CPU_ISET_6502X) .byte 0,"CPU_ISET_6502X" .endif .if (.cpu .bitand CPU_ISET_65SC02) .byte 0,"CPU_ISET_65SC02" .endif .if (.cpu .bitand CPU_ISET_65C02) .byte 0,"CPU_ISET_65C02" .endif .if (.cpu .bitand CPU_ISET_65816) .byte 0,"CPU_ISET_65816" .endif .if (.cpu .bitand CPU_ISET_SWEET16) .byte 0,"CPU_ISET_SWEET16" .endif .if (.cpu .bitand CPU_ISET_HUC6280) .byte 0,"CPU_ISET_HUC6280" .endif .if (.cpu .bitand CPU_ISET_4510) .byte 0,"CPU_ISET_4510" .endif ��������������cc65-2.18/test/asm/huc6280-cpudetect.ref������������������������������������������������������������0000664�0000000�0000000�00000000076�13473601511�0017522�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000�������������������������������������������������������������������������������������������������������������������������������������������������������������������������CPU_ISET_6502�CPU_ISET_65SC02�CPU_ISET_65C02�CPU_ISET_HUC6280������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/asm/huc6280-opcodes.ref��������������������������������������������������������������0000664�0000000�0000000�00000001043�13473601511�0017171�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000�������������������������������������������������������������������������������������������������������������������������������������������������������������������������  V4 V4V4yxV4V4V4V4y V4!"#$%&'()*+,V4-V4.V4/y0x123456789V4:;<V4=V4>V4?y@ABCDxEFGHIJKLV4MV4NV4OyPxQRSTUVWXYV4Z[\]V4^V4_y`abcdefghijklV4mV4nV4oypxqrs33sstuvwxyV4z{|V4}V4~V4y€x‚ƒê„…†‡ˆ‰Š‹ŒV4V4ŽV4yx‘’“êꔕ–—˜™V4š›œV4V4žV4Ÿy ¡¢£ê¤¥¦§¨©ª«¬V4­V4®V4¯y°x±²³êê´µ¶·¸¹V4º»¼V4½V4¾V4¿yÀÁÂÃ33ÃÃÄÅÆÇÈÉÊËÌV4ÍV4ÎV4ÏyÐxÑÒÓ33ÓÓÔÕÖרÙV4ÚÛÜÝV4ÞV4ßyàáâã33ããäåæçèéêëìV4íV4îV4ïyðxñòó33óóôõö÷øùV4úûüýV4þV4ÿy���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/asm/huc6280-opcodes.s����������������������������������������������������������������0000664�0000000�0000000�00000007754�13473601511�0016676�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������.setcpu "huc6280" brk ora ($12,x) sxy st0 #$12 tsb $12 ora $12 asl $12 rmb0 $12 php ora #$12 asl a .byte $0B tsb $3456 ora $3456 asl $3456 bbr0 $12,*+122 bpl *+122 ora ($12),y ora ($12) st1 #$12 trb $12 ora $12,x asl $12,x rmb1 $12 clc ora $3456,y inc a .byte $1B trb $3456 ora $3456,x asl $3456,x bbr1 $12,*+122 jsr $3456 and ($12,x) sax st2 #$12 bit $12 and $12 rol $12 rmb2 $12 plp and #$12 rol a .byte $2B bit $3456 and $3456 rol $3456 bbr2 $12,*+122 bmi *+122 and ($12),y and ($12) .byte $33 bit $12,x and $12,x rol $12,x rmb3 $12 sec and $3456,y dec a .byte $3B bit $3456,x and $3456,x rol $3456,x bbr3 $12,*+122 rti eor ($12,x) say tma #$02 bsr *+122 eor $12 lsr $12 rmb4 $12 pha eor #$12 lsr a .byte $4B jmp $3456 eor $3456 lsr $3456 bbr4 $12,*+122 bvc *+122 eor ($12),y eor ($12) tam #$12 csl eor $12,x lsr $12,x rmb5 $12 cli eor $3456,y phy .byte $5B .byte $5C eor $3456,x lsr $3456,x bbr5 $12,*+122 rts adc ($12,x) cla .byte $63 stz $12 adc $12 ror $12 rmb6 $12 pla adc #$12 ror a .byte $6B jmp ($3456) adc $3456 ror $3456 bbr6 $12,*+122 bvs *+122 adc ($12),y adc ($12) tii $3333,$7373,$1111 stz $12,x adc $12,x ror $12,x rmb7 $12 sei adc $3456,y ply .byte $7B jmp ($3456,x) adc $3456,x ror $3456,x bbr7 $12,*+122 bra *+122 sta ($12,x) clx tst #$12,$EA sty $12 sta $12 stx $12 smb0 $12 dey bit #$12 txa .byte $8B sty $3456 sta $3456 stx $3456 bbs0 $12,*+122 bcc *+122 sta ($12),y sta ($12) tst #$12,$EAEA sty $12,x sta $12,x stx $12,y smb1 $12 tya sta $3456,y txs .byte $9B stz $3456 sta $3456,x stz $3456,x bbs1 $12,*+122 ldy #$12 lda ($12,x) ldx #$12 tst #$12,$EA,x ldy $12 lda $12 ldx $12 smb2 $12 tay lda #$12 tax .byte $AB ldy $3456 lda $3456 ldx $3456 bbs2 $12,*+122 bcs *+122 lda ($12),y lda ($12) tst #$12,$EAEA,x ldy $12,x lda $12,x ldx $12,y smb3 $12 clv lda $3456,y tsx .byte $BB ldy $3456,x lda $3456,x ldx $3456,y bbs3 $12,*+122 cpy #$12 cmp ($12,x) cly tdd $3333,$C3C3,$1111 cpy $12 cmp $12 dec $12 smb4 $12 iny cmp #$12 dex .byte $CB cpy $3456 cmp $3456 dec $3456 bbs4 $12,*+122 bne *+122 cmp ($12),y cmp ($12) tin $3333,$D3D3,$1111 .byte $D4 cmp $12,x dec $12,x smb5 $12 cld cmp $3456,y phx .byte $DB .byte $DC cmp $3456,x dec $3456,x bbs5 $12,*+122 cpx #$12 sbc ($12,x) .byte $E2 tia $3333,$E3E3,$1111 cpx $12 sbc $12 inc $12 smb6 $12 inx sbc #$12 nop .byte $EB cpx $3456 sbc $3456 inc $3456 bbs6 $12,*+122 beq *+122 sbc ($12),y sbc ($12) tai $3333,$F3F3,$1111 .byte $F4 sbc $12,x inc $12,x smb7 $12 sed sbc $3456,y plx .byte $FB .byte $FC sbc $3456,x inc $3456,x bbs7 $12,*+122 ��������������������cc65-2.18/test/asm/m740-opcodes.s�������������������������������������������������������������������0000664�0000000�0000000�00000013201�13473601511�0016246�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������.setcpu "65C02" ; copy of 65c02, comments note changes to the m740 according to ; http://documentation.renesas.com/doc/products/mpumcu/rej09b0322_740sm.pdf brk ora ($12,x) .byte $02,$00,$00 ; jsr zp,ind .byte $03,$00,$00 ; bbs 0,a tsb $12 ; .byte $04 ora $12 asl $12 rmb0 $12 ; bbs 0,zp php ora #$12 asl a .byte $0B,$00,$00 ; seb 0,a tsb $3456 ; .byte $0c ora $3456 asl $3456 bbr0 $12,*+122 ; seb 0,zp bpl *+122 ora ($12),y ora ($12) ; clt .byte $13,$00,$00 ; bbc 0,a trb $12 ; .byte $14 ora $12,x asl $12,x rmb1 $12 ; bbc 0,zp clc ora $3456,y inc a .byte $1B,$00,$00 ; clb 0,a trb $3456 ; .byte $1c ora $3456,x asl $3456,x bbr1 $12,*+122 ; clb 0,zp jsr $3456 and ($12,x) .byte $22,$00,$00 ; jsr sp .byte $23,$00,$00 ; bbs 1,a bit $12 and $12 rol $12 rmb2 $12 ; bbs 1,zp plp and #$12 rol a .byte $2B,$00,$00 ; seb 1,a bit $3456 and $3456 rol $3456 bbr2 $12,*+122 ; seb 1,zp bmi *+122 and ($12),y and ($12) ; set .byte $33,$00,$00 ; bbc 1,a bit $12,x ; .byte $34 and $12,x rol $12,x rmb3 $12 ; bbc 1,zp sec and $3456,y dec a .byte $3B,$00,$00 ; clb 1,a bit $3456,x ; ldm zp and $3456,x rol $3456,x bbr3 $12,*+122 ; clb 1,zp rti eor ($12,x) .byte $42,$00,$00 ; stp .byte $43,$00,$00 ; bbs 2,a .byte $44,$00,$00 ; com zp eor $12 lsr $12 rmb4 $12 ; bbs 2,zp pha eor #$12 lsr a .byte $4B,$00,$00 ; seb 2,a jmp $3456 eor $3456 lsr $3456 bbr4 $12,*+122 ; seb 2,zp bvc *+122 eor ($12),y eor ($12) ; .byte $52 .byte $53,$00,$00 ; bbc 2,a .byte $54,$00,$00 eor $12,x lsr $12,x rmb5 $12 ; bbc 2,zp cli eor $3456,y phy .byte $5B,$00,$00 ; clb 2,a .byte $5C,$00,$00 eor $3456,x lsr $3456,x bbr5 $12,*+122 ; clb 2,zp rts adc ($12,x) .byte $62,$00,$00 ; mul zp,x .byte $63,$00,$00 ; bbs 3,a stz $12 ; tst zp adc $12 ror $12 rmb6 $12 ; bbs 3,zp pla adc #$12 ror a .byte $6B,$00,$00 ; seb 3,a jmp ($3456) adc $3456 ror $3456 bbr6 $12,*+122 ; seb 3,zp bvs *+122 adc ($12),y adc ($12) ; .byte $72 .byte $73,$00,$00 ; bbc 3,a stz $12,x ; .byte $74 adc $12,x ror $12,x rmb7 $12 ; bbc 3,zp sei adc $3456,y ply .byte $7B,$00,$00 ; clb 3,a jmp ($3456,x) ; .byte $7c adc $3456,x ror $3456,x bbr7 $12,*+122 ; clb 3,zp bra *+122 sta ($12,x) .byte $82,$00,$00 ; rrf zp .byte $83,$00,$00 ; bbs 4,a sty $12 sta $12 stx $12 smb0 $12 ; bbs 4,zp dey bit #$12 txa .byte $8B,$00,$00 ; seb 4,a sty $3456 sta $3456 stx $3456 bbs0 $12,*+122 ; seb 4,zp bcc *+122 sta ($12),y sta ($12) ; .byte $92 .byte $93,$00,$00 ; bbc 4,a sty $12,x sta $12,x stx $12,y smb1 $12 ; bbc 4,zp tya sta $3456,y txs .byte $9B,$00,$00 ; clb 4,a stz $3456 ; .byte $9c sta $3456,x stz $3456,x ; .byte $9e bbs1 $12,*+122 ; clb 4,zp ldy #$12 lda ($12,x) ldx #$12 .byte $A3,$00,$00 ; bbs 5,a ldy $12 lda $12 ldx $12 smb2 $12 ; bbs 5,zp tay lda #$12 tax .byte $AB,$00,$00 ; seb 5,a ldy $3456 lda $3456 ldx $3456 bbs2 $12,*+122 ; seb 5,zp bcs *+122 lda ($12),y lda ($12) ; .byte $b2 .byte $B3,$00,$00 ; bbc 5,a ldy $12,x lda $12,x ldx $12,y smb3 $12 ; bbc 5,zp clv lda $3456,y tsx .byte $BB,$00,$00 ; clb 5,a ldy $3456,x lda $3456,x ldx $3456,y bbs3 $12,*+122 ; clb 5,zp cpy #$12 cmp ($12,x) .byte $C2,$00,$00 ; wit .byte $C3,$00,$00 ; bbs 6,a cpy $12 cmp $12 dec $12 smb4 $12 ; bbs 6,zp iny cmp #$12 dex .byte $CB,$00,$00 ; seb 6,a cpy $3456 cmp $3456 dec $3456 bbs4 $12,*+122 ; seb 6,zp bne *+122 cmp ($12),y cmp ($12) ; .byte $d2 .byte $D3,$00,$00 ; bbc 6,a .byte $D4,$00,$00 cmp $12,x dec $12,x smb5 $12 ; bbc 6,zp cld cmp $3456,y phx .byte $DB,$00,$00 ; clb 6,a .byte $DC,$00,$00 cmp $3456,x dec $3456,x bbs5 $12,*+122 ; clb 6,zp cpx #$12 sbc ($12,x) .byte $E2,$00,$00 ; div zp,x .byte $E3,$00,$00 ; bbs 7,a cpx $12 sbc $12 inc $12 smb6 $12 ; bbs 7,zp inx sbc #$12 nop .byte $EB,$00,$00 ; seb 7,a cpx $3456 sbc $3456 inc $3456 bbs6 $12,*+122 ; seb 7,zp beq *+122 sbc ($12),y sbc ($12) ; .byte $f2 .byte $F3,$00,$00 ; bbc 7,a .byte $F4,$00,$00 sbc $12,x inc $12,x smb7 $12 ; bbc 7,zp sed sbc $3456,y plx .byte $FB,$00,$00 ; clb 7,a .byte $FC,$00,$00 sbc $3456,x inc $3456,x bbs7 $12,*+122 ; clb 7,zp �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/bdiff.c������������������������������������������������������������������������������0000664�0000000�0000000�00000001112�13473601511�0014375�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ // minimal tool to compare two binaries #include <stdlib.h> #include <stdio.h> int main(int argc, char *argv[]) { FILE *f1, *f2; if (argc < 3) { return EXIT_FAILURE; } f1 = fopen(argv[1], "rb"); f2 = fopen(argv[2], "rb"); if ((f1 == NULL) || (f2 == NULL)) { return EXIT_FAILURE; } for(;;) { if (feof(f1) && feof(f2)) { return EXIT_SUCCESS; } else if (feof(f1) || feof(f2)) { return EXIT_FAILURE; } if (fgetc(f1) != fgetc(f2)) { return EXIT_FAILURE; } } } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/dasm/��������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014110�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/dasm/4510-disass.s�������������������������������������������������������������������0000664�0000000�0000000�00000006322�13473601511�0016154�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������.setcpu "4510" ZP = $12 ABS = $2345 start: brk ora (ZP,x) cle see tsb ZP ora ZP asl ZP rmb0 ZP php ora #$01 asl tsy tsb ABS ora ABS asl ABS bbr0 ZP,label1 label1: bpl label2 ora (ZP),y ora (ZP),z lbpl start ; bpl start trb ZP ora ZP,x asl ZP,x rmb1 ZP clc ora ABS,y inc inz trb ABS ora ABS,x asl ABS,x bbr1 ZP,label2 label2: jsr ABS and (ZP,x) jsr ($2345) jsr ($2456,x) bit ZP and ZP rol ZP rmb2 ZP plp and #$01 rol tys bit ABS and ABS rol ABS bbr2 ZP,label3 label3: bmi label4 and (ZP),y and (ZP),z lbmi start ; bmi start bit ZP,x and ZP,x rol ZP,x rmb3 ZP sec and ABS,y dec dez bit ABS,x and ABS,x rol ABS,x bbr3 ZP,label4 label4: rti eor (ZP,x) neg asr asr ZP eor ZP lsr ZP rmb4 ZP pha eor #$01 lsr taz jmp ABS eor ABS lsr ABS bbr4 ZP,label5 label5: bvc label6 eor (ZP),y eor (ZP),z lbvc start ; bvc start asr ZP,x eor ZP,x lsr ZP,x rmb5 ZP cli eor ABS,y phy tab map eor ABS,x lsr ABS,x bbr5 ZP,label6 label6: rts adc (ZP,x) rtn #$09 bsr start stz ZP adc ZP ror ZP rmb6 ZP pla adc #$01 ror tza jmp ($2345) adc ABS ror ABS bbr6 ZP,label7 label7: bvs label8 adc (ZP),y adc (ZP),z lbvs start ; bvs start stz ZP,x adc ZP,x ror ZP,x rmb7 ZP sei adc ABS,y ply tba jmp ($2456,x) adc ABS,x ror ABS,x bbr7 ZP,label8 label8: bra label9 sta (ZP,x) sta ($0f,sp),y lbra start ; bra start sty ZP sta ZP stx ZP smb0 ZP dey bit #$01 txa sty ABS,x sty ABS sta ABS stx ABS bbs0 ZP,label9 label9: bcc labelA sta (ZP),y sta (ZP),z lbcc start ; bcc start sty ZP,x sta ZP,x stx ZP,y smb1 ZP tya sta ABS,y txs stx ABS,y stz ABS sta ABS,x stz ABS,x bbs1 ZP,labelA labelA: ldy #$01 lda (ZP,x) ldx #$01 ldz #$01 ldy ZP lda ZP ldx ZP smb2 ZP tay lda #$01 tax ldz ABS ldy ABS lda ABS ldx ABS bbs2 ZP,labelB labelB: bcs labelC lda (ZP),y lda (ZP),z lbcs start ; bcs start ldy ZP,x lda ZP,x ldx ZP,y smb3 ZP clv lda ABS,y tsx ldz ABS,x ldy ABS,x lda ABS,x ldx ABS,y bbs3 ZP,labelC labelC: cpy #$01 cmp (ZP,x) cpz #$01 dew ZP cpy ZP cmp ZP dec ZP smb4 ZP iny cmp #$01 dex asw ABS cpy ABS cmp ABS dec ABS bbs4 ZP,labelD labelD: bne labelE cmp (ZP),y cmp (ZP),z lbne start ; bne start cpz ZP cmp ZP,x dec ZP,x smb5 ZP cld cmp ABS,y phx phz cpz ABS cmp ABS,x dec ABS,x bbs5 ZP,labelE labelE: cpx #$01 sbc (ZP,x) lda ($0f,sp),y inw ZP cpx ZP sbc ZP inc ZP smb6 ZP inx sbc #$01 eom nop row ABS cpx ABS sbc ABS inc ABS bbs6 ZP,labelF labelF: beq labelG sbc (ZP),y sbc (ZP),z lbeq start ; beq start phw #$089a sbc ZP,x inc ZP,x smb7 ZP sed sbc ABS,y plx plz phd ABS phw ABS sbc ABS,x inc ABS,x bbs7 ZP,labelG labelG: brk ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/dasm/Makefile������������������������������������������������������������������������0000664�0000000�0000000�00000002607�13473601511�0015555�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile for the disassembler regression tests ifneq ($(shell echo),) CMD_EXE = 1 endif ifdef CMD_EXE EXE = .exe MKDIR = mkdir $(subst /,\,$1) RMDIR = -rmdir /s /q $(subst /,\,$1) DEL = del /f $(subst /,\,$1) else EXE = MKDIR = mkdir -p $1 RMDIR = $(RM) -r $1 DEL = $(RM) $1 endif ifdef QUIET .SILENT: endif CL65 := $(if $(wildcard ../../bin/cl65*),../../bin/cl65,cl65) DA65 := $(if $(wildcard ../../bin/da65*),../../bin/da65,da65) WORKDIR = ../../testwrk/dasm DIFF = $(WORKDIR)/bdiff$(EXE) CC = gcc CFLAGS = -O2 START = --start-addr 0x8000 .PHONY: all clean SOURCES := $(wildcard *.s) CPUS = $(foreach src,$(SOURCES),$(src:%-disass.s=%)) BINS = $(foreach cpu,$(CPUS),$(WORKDIR)/$(cpu)-reass.bin) # default target defined later all: $(BINS) $(WORKDIR): $(call MKDIR,$(WORKDIR)) $(DIFF): ../bdiff.c | $(WORKDIR) $(CC) $(CFLAGS) -o $@ $< define DISASS_template $(WORKDIR)/$1-disass.bin: $1-disass.s | $(WORKDIR) $(CL65) --cpu $1 -t none $(START) -o $$@ $$< $(WORKDIR)/$1-reass.s: $(WORKDIR)/$1-disass.bin $(DA65) --cpu $1 $(START) -o $$@ $$< $(WORKDIR)/$1-reass.bin: $(WORKDIR)/$1-reass.s $(DIFF) $(if $(QUIET),echo dasm/$1-reass.bin) $(CL65) --cpu $1 -t none $(START) -o $$@ $$< $(DIFF) $$@ $(WORKDIR)/$1-disass.bin endef # DISASS_template $(foreach cpu,$(CPUS),$(eval $(call DISASS_template,$(cpu)))) clean: @$(call RMDIR,$(WORKDIR)) @$(call DEL,$(SOURCES:.s=.o)) �������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/err/���������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0013754�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/err/Makefile�������������������������������������������������������������������������0000664�0000000�0000000�00000001307�13473601511�0015415�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile for the tests that MUST NOT compile ifneq ($(shell echo),) CMD_EXE = 1 endif ifdef CMD_EXE S = $(subst /,\,/) NOT = - # Hack NULLDEV = nul: MKDIR = mkdir $(subst /,\,$1) RMDIR = -rmdir /s /q $(subst /,\,$1) else S = / NOT = ! NULLDEV = /dev/null MKDIR = mkdir -p $1 RMDIR = $(RM) -r $1 endif ifdef QUIET .SILENT: NULLERR = 2>$(NULLDEV) endif CC65 := $(if $(wildcard ../../bin/cc65*),..$S..$Sbin$Scc65,cc65) WORKDIR = ../../testwrk/err .PHONY: all clean SOURCES := $(wildcard *.c) TESTS = $(patsubst %.c,$(WORKDIR)/%.s,$(SOURCES)) all: $(TESTS) $(WORKDIR)/%.s: %.c $(if $(QUIET),echo err/$*.s) $(NOT) $(CC65) -o $@ $< $(NULLERR) clean: @$(call RMDIR,$(WORKDIR)) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/err/bss-name-conflict.c��������������������������������������������������������������0000664�0000000�0000000�00000000512�13473601511�0017422�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! conflicting bss-name pragmas !!ORIGIN!! cc65 regression tests !!LICENCE!! Public Domain !!AUTHOR!! Piotr Fusik */ /* see: https://github.com/cc65/cc65/issues/409 */ char oam_off; #pragma bss-name (push,"ZEROPAGE") char oam_off; #pragma bss-name (pop) int main(void) { return 0; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/err/cc65091001.c���������������������������������������������������������������������0000664�0000000�0000000�00000001042�13473601511�0015330�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! invalid binary operation on pointer, should not compile !!ORIGIN!! testsuite !!LICENCE!! Public Domain !!AUTHOR!! */ /* > Gets stuck in an endless loop with -O. */ #include <assert.h> #include <string.h> #include <stdio.h> typedef unsigned char U8; char var = 0xf0; char fn(char bar) { char* ptr = (char*)0xf; var |= ptr; /* should throw an error here */ while (var > bar) var <<= 1; return 0; } int main() { fn(0x7f); assert(0); printf("it works :)\n"); return 0; }����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/err/cc65150311-1.c�������������������������������������������������������������������0000664�0000000�0000000�00000000673�13473601511�0015477�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!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; } ���������������������������������������������������������������������cc65-2.18/test/err/cc65150311-10.c������������������������������������������������������������������0000664�0000000�0000000�00000000705�13473601511�0015553�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!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; } �����������������������������������������������������������cc65-2.18/test/err/cc65150311-11.c������������������������������������������������������������������0000664�0000000�0000000�00000000704�13473601511�0015553�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!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; } ������������������������������������������������������������cc65-2.18/test/err/cc65150311-2.c�������������������������������������������������������������������0000664�0000000�0000000�00000000707�13473601511�0015476�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!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; } ���������������������������������������������������������cc65-2.18/test/err/cc65150311-3.c�������������������������������������������������������������������0000664�0000000�0000000�00000000706�13473601511�0015476�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!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; } ����������������������������������������������������������cc65-2.18/test/err/cc65150311-4.c�������������������������������������������������������������������0000664�0000000�0000000�00000000707�13473601511�0015500�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!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; } ���������������������������������������������������������cc65-2.18/test/err/cc65150311-5.c�������������������������������������������������������������������0000664�0000000�0000000�00000000710�13473601511�0015473�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!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; } ��������������������������������������������������������cc65-2.18/test/err/cc65150311-6.c�������������������������������������������������������������������0000664�0000000�0000000�00000000710�13473601511�0015474�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!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; } ��������������������������������������������������������cc65-2.18/test/err/cc65150311-7.c�������������������������������������������������������������������0000664�0000000�0000000�00000000711�13473601511�0015476�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!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; } �������������������������������������������������������cc65-2.18/test/err/cc65150311-8.c�������������������������������������������������������������������0000664�0000000�0000000�00000000705�13473601511�0015502�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!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; } �����������������������������������������������������������cc65-2.18/test/err/cc65150311-9.c�������������������������������������������������������������������0000664�0000000�0000000�00000000704�13473601511�0015502�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!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; } ������������������������������������������������������������cc65-2.18/test/err/duplicate-global-static.c��������������������������������������������������������0000664�0000000�0000000�00000000500�13473601511�0020610�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! global duplicated with static variable !!ORIGIN!! cc65 regression tests !!LICENCE!! Public Domain !!AUTHOR!! Piotr Fusik */ /* see: https://github.com/cc65/cc65/issues/191 */ int n = 0; static int n = 0; /* should give an error */ int main(void) { return n; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/err/duplicate-global.c���������������������������������������������������������������0000664�0000000�0000000�00000000475�13473601511�0017336�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! duplicate globals !!ORIGIN!! cc65 regression tests !!LICENCE!! Public Domain !!AUTHOR!! Piotr Fusik */ /* see: https://github.com/cc65/cc65/issues/191 */ #pragma warn(error, on) int n = 0; int n = 0; /* should give an error */ int main(void) { return n; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/err/duplicate-static-global.c��������������������������������������������������������0000664�0000000�0000000�00000000500�13473601511�0020610�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! static duplicated with global variable !!ORIGIN!! cc65 regression tests !!LICENCE!! Public Domain !!AUTHOR!! Piotr Fusik */ /* see: https://github.com/cc65/cc65/issues/191 */ static int n = 0; int n = 0; /* should give an error */ int main(void) { return n; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/err/duplicate-static.c���������������������������������������������������������������0000664�0000000�0000000�00000000524�13473601511�0017360�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! duplicate static variables !!ORIGIN!! cc65 regression tests !!LICENCE!! Public Domain !!AUTHOR!! Piotr Fusik */ /* see: https://github.com/cc65/cc65/issues/191 */ #pragma warn(error, on) static int n = 0; static int n = 0; /* should give an error */ int main(void) { return n; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/err/front.c��������������������������������������������������������������������������0000664�0000000�0000000�00000005043�13473601511�0015252�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! this code is not supposed to compile !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ main() { return 0; } nested(a,b) { if ((a<4 && b == 'r') || (a == 1 && (b == 'h' || b == 'i')) || (a == 2 && (b == 'o' || b == 'y')) ) a=b; } /* type name scope */ void s(struct D *d) {} /* this struct D differs from the one below */ typedef struct D D; struct D {int x, y;} Dy={0}; D Dz={1}; Dfunc(){ D a; a.y=1; s(&Dy); /* error */ } /* qualifiers */ const a; int b; const int a, *x; int b, *y; volatile unsigned z; f() { x = y; z = z + z; /* should be 2 references to z's r-value */ } f1() { x = &a; x = &b; y = &a; /* error */ y = &b; } f2(int **a, int **b) { f(&x, &y); **a = 0; return **b; } g(const int *p) { g(&a); g(&b); return *p; } h(int *p) { f(&a); f(&b); return *p; } h1(const int x, int y) { h1(a,b); h1(b,a); return x + y; } h2() { char *b; const void *p; p = b; b = p; /* error (incompatible pointer type) */ } /* static naming */ extern int yy; set1() { { static yy=1; yy=2;} yy=4;} static int yy; set2() { yy=5; {static yy=2; yy=3; }} static void goo() {} sss() { int goo; { static int goo();} goo=1;} /* rrr(p) float *p; { extern int xr; { static float xr; { extern int *xr; } p=&xr; }} */ /* local extern */ static int ss1; int ss3; extern int ss5; setstatic() { extern int ss1,ss2,ss3,ss4; ss1 = ss2; ss3 = ss4; ss5 = 0;} static int ss2; int ss4; static int ss5; /* function prototypes */ int fx1(void); int fx1(); /* int gx1(double x); */ /* int gx1(x) double x; { gx1(&x); } */ /* error */ int hx1(); /* int hx1(double x,...); */ /* error */ /* int ff1(double x, int *y); int ff1(x,y) float x; int y[]; {x=y[0];} */ int gg1(int a); int gg1(a,b){a=b;} int hh1(const int x); hh1(a) {return a;} extern int strcmp(const char*, const char*); extern void qsort(void*, int, int, int (*)(const void*, const void*)); extern int cmp(char**a, char**b) { return strcmp(*a,*b); } sort() { int n; char *a[100]; qsort(a, n, sizeof(char*), (int (*)(const void*, const void*))cmp); qsort(a, n, sizeof(char*), cmp); /* error (incompatible pointer type) */ } /* nasty calls */ onearg(){ int a,b,c,d; f( ( (a? (b = 1): (c = 2)), (d ? 3 : 4) ) ); /* 1 argument */ } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/err/static-2.c�����������������������������������������������������������������������0000664�0000000�0000000�00000000517�13473601511�0015551�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!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; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/err/static-3.c�����������������������������������������������������������������������0000664�0000000�0000000�00000000526�13473601511�0015552�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!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; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/err/static-4.c�����������������������������������������������������������������������0000664�0000000�0000000�00000000526�13473601511�0015553�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!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; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/err/void-empty.c���������������������������������������������������������������������0000664�0000000�0000000�00000000266�13473601511�0016221�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! Uninitialized void variables !!ORIGIN!! cc65 regression tests !!LICENCE!! Public Domain !!AUTHOR!! Greg King */ void test; const void list; ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/err/void-size2.c���������������������������������������������������������������������0000664�0000000�0000000�00000000311�13473601511�0016106�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! Size of void cast !!ORIGIN!! cc65 regression tests !!LICENCE!! Public Domain !!AUTHOR!! Greg King */ unsigned test (void) { return sizeof ((void)12345); } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/misc/��������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014117�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/misc/Makefile������������������������������������������������������������������������0000664�0000000�0000000�00000005320�13473601511�0015557�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile for the remaining tests that need special care in one way or another ifneq ($(shell echo),) CMD_EXE = 1 endif ifdef CMD_EXE S = $(subst /,\,/) NOT = - # Hack EXE = .exe NULLDEV = nul: MKDIR = mkdir $(subst /,\,$1) RMDIR = -rmdir /s /q $(subst /,\,$1) DEL = del /f $(subst /,\,$1) else S = / NOT = ! EXE = NULLDEV = /dev/null MKDIR = mkdir -p $1 RMDIR = $(RM) -r $1 DEL = $(RM) $1 endif ifdef QUIET .SILENT: NULLOUT = >$(NULLDEV) NULLERR = 2>$(NULLDEV) endif SIM65FLAGS = -x 200000000 CL65 := $(if $(wildcard ../../bin/cl65*),..$S..$Sbin$Scl65,cl65) SIM65 := $(if $(wildcard ../../bin/sim65*),..$S..$Sbin$Ssim65,sim65) WORKDIR = ..$S..$Stestwrk$Smisc OPTIONS = g O Os Osi Osir Osr Oi Oir Or DIFF = $(WORKDIR)$Sbdiff$(EXE) CC = gcc CFLAGS = -O2 .PHONY: all clean SOURCES := $(wildcard *.c) TESTS = $(foreach option,$(OPTIONS),$(SOURCES:%.c=$(WORKDIR)/%.$(option).6502.prg)) TESTS += $(foreach option,$(OPTIONS),$(SOURCES:%.c=$(WORKDIR)/%.$(option).65c02.prg)) all: $(TESTS) $(WORKDIR): $(call MKDIR,$(WORKDIR)) $(DIFF): ../bdiff.c | $(WORKDIR) $(CC) $(CFLAGS) -o $@ $< define PRG_template # should compile, but then hangs in an endless loop $(WORKDIR)/endless.$1.$2.prg: endless.c | $(WORKDIR) $(if $(QUIET),echo misc/endless.$1.$2.prg) $(CL65) -t sim$2 -$1 -o $$@ $$< $(NULLERR) $(NOT) $(SIM65) $(SIM65FLAGS) $$@ $(NULLOUT) $(NULLERR) # these need reference data that can't be generated by a host-compiled program, # in a useful way $(WORKDIR)/limits.$1.$2.prg: limits.c $(DIFF) $(if $(QUIET),echo misc/limits.$1.$2.prg) $(CL65) -t sim$2 -$1 -o $$@ $$< $(NULLERR) $(SIM65) $(SIM65FLAGS) $$@ > $(WORKDIR)/limits.$1.out $(DIFF) $(WORKDIR)/limits.$1.out limits.ref $(WORKDIR)/goto.$1.$2.prg: goto.c $(DIFF) $(if $(QUIET),echo misc/goto.$1.$2.prg) $(CL65) -t sim$2 -$1 -o $$@ $$< 2>$(WORKDIR)/goto.$1.out $(DIFF) $(WORKDIR)/goto.$1.out goto.ref # the rest are tests that fail currently for one reason or another $(WORKDIR)/fields.$1.$2.prg: fields.c | $(WORKDIR) @echo "FIXME: " $$@ "currently will fail." $(CL65) -t sim$2 -$1 -o $$@ $$< $(NULLERR) -$(SIM65) $(SIM65FLAGS) $$@ $(NULLOUT) $(WORKDIR)/sitest.$1.$2.prg: sitest.c | $(WORKDIR) @echo "FIXME: " $$@ "currently will fail." -$(CL65) -t sim$2 -$1 -o $$@ $$< $(NULLERR) # -$(SIM65) $(SIM65FLAGS) $$@ $(NULLOUT) $(WORKDIR)/cc65141011.$1.$2.prg: cc65141011.c | $(WORKDIR) @echo "FIXME: " $$@ "currently can fail." $(CL65) -t sim$2 -$1 -o $$@ $$< $(NULLERR) -$(SIM65) $(SIM65FLAGS) $$@ $(NULLOUT) endef # PRG_template $(foreach option,$(OPTIONS),$(eval $(call PRG_template,$(option),6502))) $(foreach option,$(OPTIONS),$(eval $(call PRG_template,$(option),65c02))) clean: @$(call RMDIR,$(WORKDIR)) @$(call DEL,$(SOURCES:.c=.o)) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/misc/cc65141011.c��������������������������������������������������������������������0000775�0000000�0000000�00000003152�13473601511�0015477�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!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; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/misc/common.h������������������������������������������������������������������������0000664�0000000�0000000�00000001012�13473601511�0015552�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ #include <stdio.h> #include <stdlib.h> #define NO_OLD_FUNC_DECL #define NO_TYPELESS_INT #define NO_TYPELESS_INT_PTR #define MAIN_RETURNS_INT #define NO_IMPLICIT_FUNC_PROTOTYPES #define NO_FLOATS #define NO_WCHAR #define NO_EMPTY_FUNC_ARGS #define NO_SLOPPY_STRUCT_INIT #define NO_FUNCS_TAKE_STRUCTS #define NO_FUNCS_RETURN_STRUCTS #define CAST_STRUCT_PTR #define NO_TYPELESS_STRUCT_PTR #define NO_IMPLICIT_FUNCPTR_CONV #define SIZEOF_INT_16BIT #define SIZEOF_LONG_32BIT #define UNSIGNED_CHARS #define UNSIGNED_BITFIELDS ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/misc/endless.c�����������������������������������������������������������������������0000664�0000000�0000000�00000000360�13473601511�0015717�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ #include <stdio.h> #include <stdlib.h> int main(void) { printf("entering endless loop\n"); for(;;) { ; } printf("error: should not come here\n"); return EXIT_SUCCESS; /* test verifies failure, not success */ } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/misc/fields.c������������������������������������������������������������������������0000664�0000000�0000000�00000003406�13473601511�0015534�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! bitfield test !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include "common.h" #ifdef NO_BITFIELDS main() { printf("NO_BITFIELDS\n\r"); } #else #ifdef SIZEOF_INT_16BIT #ifdef REFCC #include <stdint.h> struct foo { int16_t a; char b; int16_t x : 12, y : 4; int16_t zz : 1, : 0, : 4, z : 3; char c; } x = { 1, 2, 3, 4, 5, 6 }; struct baz { uint16_t a:2, b:4, c:16;} y = { 7, 8, 9}; int16_t i = 8; #else struct foo { int a; char b; int x : 12, y : 4; int zz : 1, : 0, : 4, z : 3; char c; } x = { 1, 2, 3, 4, 5, 6 }; struct baz { unsigned int a:2, b:4, c:16;} y = { 7, 8, 9}; int i = 8; #endif #else struct foo { int a; char b; int x : 12, y : 4, : 0, : 4, z : 3; char c; } x = { 1, 2, 3, 4, 5, 6 }; struct baz { unsigned int a:2, b:4, c:32;} y = { 7, 8, 9}; int i = 16; #endif #ifdef NO_IMPLICIT_FUNC_PROTOTYPES f1(struct baz *p); f2(struct baz *p); #endif main() { printf("x = %d b:%d %d %d %d c:%d\n", x.a, x.b, x.x, x.y, x.z, x.c); printf("y = %d b:%d c:%d\n", y.a, y.b, y.c); x.y = i; x.z = 070; printf("x = %d b:%d %d %d %d c:%d\n", x.a, x.b, x.x, x.y, x.z, x.c); y.a = 2; y.c = i; printf("y = %d b:%d c:%d\n", y.a, y.b, y.c); #ifdef CAST_STRUCT_PTR f2((struct baz *)&x); #else f2(&x); #endif return 0; } f1(struct baz *p) { p->a = p->b = 0; if (p->b) printf("p->b != 0!\n"); p->a = 0x3; p->b = 0xf; printf("p->a = 0x%x, p->b = 0x%x\n", p->a, p->b); } f2(struct baz *p) { p->a = (i==0); p->b = (f1(p),0); } #endif ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/misc/goto.c��������������������������������������������������������������������������0000664�0000000�0000000�00000016531�13473601511�0015241�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������void main () { goto end; { int a = 1; start: goto end; } goto start; end:; } void f2 () { int a = 2; l1: goto l1; goto l2; goto l3; goto l4; goto l5; goto l6; goto l7; goto l8; goto l9; goto la; goto lb; goto lc; goto ld; goto le; goto lf; goto lg; goto lh; goto li; { int a; l2:; goto l1; goto l2; goto l3; goto l4; goto l5; goto l6; goto l7; goto l8; goto l9; goto la; goto lb; goto lc; goto ld; goto le; goto lf; goto lg; goto lh; goto li; { int a; l3:; goto l1; goto l2; goto l3; goto l4; goto l5; goto l6; goto l7; goto l8; goto l9; goto la; goto lb; goto lc; goto ld; goto le; goto lf; goto lg; goto lh; goto li; { int a; l4:; goto l1; goto l2; goto l3; goto l4; goto l5; goto l6; goto l7; goto l8; goto l9; goto la; goto lb; goto lc; goto ld; goto le; goto lf; goto lg; goto lh; goto li; } l5:; goto l1; goto l2; goto l3; goto l4; goto l5; goto l6; goto l7; goto l8; goto l9; goto la; goto lb; goto lc; goto ld; goto le; goto lf; goto lg; goto lh; goto li; } l6:; goto l1; goto l2; goto l3; goto l4; goto l5; goto l6; goto l7; goto l8; goto l9; goto la; goto lb; goto lc; goto ld; goto le; goto lf; goto lg; goto lh; goto li; } l7:; goto l1; goto l2; goto l3; goto l4; goto l5; goto l6; goto l7; goto l8; goto l9; goto la; goto lb; goto lc; goto ld; goto le; goto lf; goto lg; goto lh; goto li; { int a = 1; l8:; goto l1; goto l2; goto l3; goto l4; goto l5; goto l6; goto l7; goto l8; goto l9; goto la; goto lb; goto lc; goto ld; goto le; goto lf; goto lg; goto lh; goto li; { int a = 1; l9:; goto l1; goto l2; goto l3; goto l4; goto l5; goto l6; goto l7; goto l8; goto l9; goto la; goto lb; goto lc; goto ld; goto le; goto lf; goto lg; goto lh; goto li; { int a = 1; la:; goto l1; goto l2; goto l3; goto l4; goto l5; goto l6; goto l7; goto l8; goto l9; goto la; goto lb; goto lc; goto ld; goto le; goto lf; goto lg; goto lh; goto li; } lb:; goto l1; goto l2; goto l3; goto l4; goto l5; goto l6; goto l7; goto l8; goto l9; goto la; goto lb; goto lc; goto ld; goto le; goto lf; goto lg; goto lh; goto li; } lc:; goto l1; goto l2; goto l3; goto l4; goto l5; goto l6; goto l7; goto l8; goto l9; goto la; goto lb; goto lc; goto ld; goto le; goto lf; goto lg; goto lh; goto li; } { int a = 1; ld:; goto l1; goto l2; goto l3; goto l4; goto l5; goto l6; goto l7; goto l8; goto l9; goto la; goto lb; goto lc; goto ld; goto le; goto lf; goto lg; goto lh; goto li; { int a = 1; le:; goto l1; goto l2; goto l3; goto l4; goto l5; goto l6; goto l7; goto l8; goto l9; goto la; goto lb; goto lc; goto ld; goto le; goto lf; goto lg; goto lh; goto li; { int a = 1; lf:; goto l1; goto l2; goto l3; goto l4; goto l5; goto l6; goto l7; goto l8; goto l9; goto la; goto lb; goto lc; goto ld; goto le; goto lf; goto lg; goto lh; goto li; } lg:; goto l1; goto l2; goto l3; goto l4; goto l5; goto l6; goto l7; goto l8; goto l9; goto la; goto lb; goto lc; goto ld; goto le; goto lf; goto lg; goto lh; goto li; } lh:; goto l1; goto l2; goto l3; goto l4; goto l5; goto l6; goto l7; goto l8; goto l9; goto la; goto lb; goto lc; goto ld; goto le; goto lf; goto lg; goto lh; goto li; } li:; goto l1; goto l2; goto l3; goto l4; goto l5; goto l6; goto l7; goto l8; goto l9; goto la; goto lb; goto lc; goto ld; goto le; goto lf; goto lg; goto lh; goto li; } /* Structure of the above function. void f2 () { int a = 2; l1: { int a; l2:; { int a; l3:; { int a; l4:; } l5:; } l6:; } l7:; { int a = 1; l8:; { int a = 1; l9:; { int a = 1; la:; } lb:; } lc:; } { int a = 1; ld:; { int a = 1; le:; { int a = 1; lf:; } lg:; } lh:; } li:; } */ �����������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/misc/goto.ref������������������������������������������������������������������������0000664�0000000�0000000�00000050103�13473601511�0015564�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������goto.c(8): Warning: Goto at line 8 to label start jumps into a block with initialization of an object that has automatic storage duration goto.c(97): Warning: 'a' is defined but never used goto.c(117): Warning: 'a' is defined but never used goto.c(137): Warning: 'a' is defined but never used goto.c(159): Warning: Goto at line 23 to label l8 jumps into a block with initialization of an object that has automatic storage duration goto.c(159): Warning: Goto at line 44 to label l8 jumps into a block with initialization of an object that has automatic storage duration goto.c(159): Warning: Goto at line 65 to label l8 jumps into a block with initialization of an object that has automatic storage duration goto.c(159): Warning: Goto at line 86 to label l8 jumps into a block with initialization of an object that has automatic storage duration goto.c(159): Warning: Goto at line 106 to label l8 jumps into a block with initialization of an object that has automatic storage duration goto.c(159): Warning: Goto at line 126 to label l8 jumps into a block with initialization of an object that has automatic storage duration goto.c(159): Warning: Goto at line 146 to label l8 jumps into a block with initialization of an object that has automatic storage duration goto.c(180): Warning: Goto at line 24 to label l9 jumps into a block with initialization of an object that has automatic storage duration goto.c(180): Warning: Goto at line 45 to label l9 jumps into a block with initialization of an object that has automatic storage duration goto.c(180): Warning: Goto at line 66 to label l9 jumps into a block with initialization of an object that has automatic storage duration goto.c(180): Warning: Goto at line 87 to label l9 jumps into a block with initialization of an object that has automatic storage duration goto.c(180): Warning: Goto at line 107 to label l9 jumps into a block with initialization of an object that has automatic storage duration goto.c(180): Warning: Goto at line 127 to label l9 jumps into a block with initialization of an object that has automatic storage duration goto.c(180): Warning: Goto at line 147 to label l9 jumps into a block with initialization of an object that has automatic storage duration goto.c(180): Warning: Goto at line 168 to label l9 jumps into a block with initialization of an object that has automatic storage duration goto.c(201): Warning: Goto at line 25 to label la jumps into a block with initialization of an object that has automatic storage duration goto.c(201): Warning: Goto at line 46 to label la jumps into a block with initialization of an object that has automatic storage duration goto.c(201): Warning: Goto at line 67 to label la jumps into a block with initialization of an object that has automatic storage duration goto.c(201): Warning: Goto at line 88 to label la jumps into a block with initialization of an object that has automatic storage duration goto.c(201): Warning: Goto at line 108 to label la jumps into a block with initialization of an object that has automatic storage duration goto.c(201): Warning: Goto at line 128 to label la jumps into a block with initialization of an object that has automatic storage duration goto.c(201): Warning: Goto at line 148 to label la jumps into a block with initialization of an object that has automatic storage duration goto.c(201): Warning: Goto at line 169 to label la jumps into a block with initialization of an object that has automatic storage duration goto.c(201): Warning: Goto at line 190 to label la jumps into a block with initialization of an object that has automatic storage duration goto.c(221): Warning: Goto at line 26 to label lb jumps into a block with initialization of an object that has automatic storage duration goto.c(221): Warning: Goto at line 47 to label lb jumps into a block with initialization of an object that has automatic storage duration goto.c(221): Warning: Goto at line 68 to label lb jumps into a block with initialization of an object that has automatic storage duration goto.c(221): Warning: Goto at line 89 to label lb jumps into a block with initialization of an object that has automatic storage duration goto.c(221): Warning: Goto at line 109 to label lb jumps into a block with initialization of an object that has automatic storage duration goto.c(221): Warning: Goto at line 129 to label lb jumps into a block with initialization of an object that has automatic storage duration goto.c(221): Warning: Goto at line 149 to label lb jumps into a block with initialization of an object that has automatic storage duration goto.c(221): Warning: Goto at line 170 to label lb jumps into a block with initialization of an object that has automatic storage duration goto.c(231): Warning: Goto at line 231 to label la jumps into a block with initialization of an object that has automatic storage duration goto.c(241): Warning: Goto at line 27 to label lc jumps into a block with initialization of an object that has automatic storage duration goto.c(241): Warning: Goto at line 48 to label lc jumps into a block with initialization of an object that has automatic storage duration goto.c(241): Warning: Goto at line 69 to label lc jumps into a block with initialization of an object that has automatic storage duration goto.c(241): Warning: Goto at line 90 to label lc jumps into a block with initialization of an object that has automatic storage duration goto.c(241): Warning: Goto at line 110 to label lc jumps into a block with initialization of an object that has automatic storage duration goto.c(241): Warning: Goto at line 130 to label lc jumps into a block with initialization of an object that has automatic storage duration goto.c(241): Warning: Goto at line 150 to label lc jumps into a block with initialization of an object that has automatic storage duration goto.c(250): Warning: Goto at line 250 to label l9 jumps into a block with initialization of an object that has automatic storage duration goto.c(251): Warning: Goto at line 251 to label la jumps into a block with initialization of an object that has automatic storage duration goto.c(252): Warning: Goto at line 252 to label lb jumps into a block with initialization of an object that has automatic storage duration goto.c(263): Warning: Goto at line 28 to label ld jumps into a block with initialization of an object that has automatic storage duration goto.c(263): Warning: Goto at line 49 to label ld jumps into a block with initialization of an object that has automatic storage duration goto.c(263): Warning: Goto at line 70 to label ld jumps into a block with initialization of an object that has automatic storage duration goto.c(263): Warning: Goto at line 91 to label ld jumps into a block with initialization of an object that has automatic storage duration goto.c(263): Warning: Goto at line 111 to label ld jumps into a block with initialization of an object that has automatic storage duration goto.c(263): Warning: Goto at line 131 to label ld jumps into a block with initialization of an object that has automatic storage duration goto.c(263): Warning: Goto at line 151 to label ld jumps into a block with initialization of an object that has automatic storage duration goto.c(263): Warning: Goto at line 172 to label ld jumps into a block with initialization of an object that has automatic storage duration goto.c(263): Warning: Goto at line 193 to label ld jumps into a block with initialization of an object that has automatic storage duration goto.c(263): Warning: Goto at line 214 to label ld jumps into a block with initialization of an object that has automatic storage duration goto.c(263): Warning: Goto at line 234 to label ld jumps into a block with initialization of an object that has automatic storage duration goto.c(263): Warning: Goto at line 254 to label ld jumps into a block with initialization of an object that has automatic storage duration goto.c(271): Warning: Goto at line 271 to label l8 jumps into a block with initialization of an object that has automatic storage duration goto.c(272): Warning: Goto at line 272 to label l9 jumps into a block with initialization of an object that has automatic storage duration goto.c(273): Warning: Goto at line 273 to label la jumps into a block with initialization of an object that has automatic storage duration goto.c(274): Warning: Goto at line 274 to label lb jumps into a block with initialization of an object that has automatic storage duration goto.c(275): Warning: Goto at line 275 to label lc jumps into a block with initialization of an object that has automatic storage duration goto.c(284): Warning: Goto at line 29 to label le jumps into a block with initialization of an object that has automatic storage duration goto.c(284): Warning: Goto at line 50 to label le jumps into a block with initialization of an object that has automatic storage duration goto.c(284): Warning: Goto at line 71 to label le jumps into a block with initialization of an object that has automatic storage duration goto.c(284): Warning: Goto at line 92 to label le jumps into a block with initialization of an object that has automatic storage duration goto.c(284): Warning: Goto at line 112 to label le jumps into a block with initialization of an object that has automatic storage duration goto.c(284): Warning: Goto at line 132 to label le jumps into a block with initialization of an object that has automatic storage duration goto.c(284): Warning: Goto at line 152 to label le jumps into a block with initialization of an object that has automatic storage duration goto.c(284): Warning: Goto at line 173 to label le jumps into a block with initialization of an object that has automatic storage duration goto.c(284): Warning: Goto at line 194 to label le jumps into a block with initialization of an object that has automatic storage duration goto.c(284): Warning: Goto at line 215 to label le jumps into a block with initialization of an object that has automatic storage duration goto.c(284): Warning: Goto at line 235 to label le jumps into a block with initialization of an object that has automatic storage duration goto.c(284): Warning: Goto at line 255 to label le jumps into a block with initialization of an object that has automatic storage duration goto.c(284): Warning: Goto at line 277 to label le jumps into a block with initialization of an object that has automatic storage duration goto.c(292): Warning: Goto at line 292 to label l8 jumps into a block with initialization of an object that has automatic storage duration goto.c(293): Warning: Goto at line 293 to label l9 jumps into a block with initialization of an object that has automatic storage duration goto.c(294): Warning: Goto at line 294 to label la jumps into a block with initialization of an object that has automatic storage duration goto.c(295): Warning: Goto at line 295 to label lb jumps into a block with initialization of an object that has automatic storage duration goto.c(296): Warning: Goto at line 296 to label lc jumps into a block with initialization of an object that has automatic storage duration goto.c(305): Warning: Goto at line 30 to label lf jumps into a block with initialization of an object that has automatic storage duration goto.c(305): Warning: Goto at line 51 to label lf jumps into a block with initialization of an object that has automatic storage duration goto.c(305): Warning: Goto at line 72 to label lf jumps into a block with initialization of an object that has automatic storage duration goto.c(305): Warning: Goto at line 93 to label lf jumps into a block with initialization of an object that has automatic storage duration goto.c(305): Warning: Goto at line 113 to label lf jumps into a block with initialization of an object that has automatic storage duration goto.c(305): Warning: Goto at line 133 to label lf jumps into a block with initialization of an object that has automatic storage duration goto.c(305): Warning: Goto at line 153 to label lf jumps into a block with initialization of an object that has automatic storage duration goto.c(305): Warning: Goto at line 174 to label lf jumps into a block with initialization of an object that has automatic storage duration goto.c(305): Warning: Goto at line 195 to label lf jumps into a block with initialization of an object that has automatic storage duration goto.c(305): Warning: Goto at line 216 to label lf jumps into a block with initialization of an object that has automatic storage duration goto.c(305): Warning: Goto at line 236 to label lf jumps into a block with initialization of an object that has automatic storage duration goto.c(305): Warning: Goto at line 256 to label lf jumps into a block with initialization of an object that has automatic storage duration goto.c(305): Warning: Goto at line 278 to label lf jumps into a block with initialization of an object that has automatic storage duration goto.c(305): Warning: Goto at line 299 to label lf jumps into a block with initialization of an object that has automatic storage duration goto.c(313): Warning: Goto at line 313 to label l8 jumps into a block with initialization of an object that has automatic storage duration goto.c(314): Warning: Goto at line 314 to label l9 jumps into a block with initialization of an object that has automatic storage duration goto.c(315): Warning: Goto at line 315 to label la jumps into a block with initialization of an object that has automatic storage duration goto.c(316): Warning: Goto at line 316 to label lb jumps into a block with initialization of an object that has automatic storage duration goto.c(317): Warning: Goto at line 317 to label lc jumps into a block with initialization of an object that has automatic storage duration goto.c(325): Warning: Goto at line 31 to label lg jumps into a block with initialization of an object that has automatic storage duration goto.c(325): Warning: Goto at line 52 to label lg jumps into a block with initialization of an object that has automatic storage duration goto.c(325): Warning: Goto at line 73 to label lg jumps into a block with initialization of an object that has automatic storage duration goto.c(325): Warning: Goto at line 94 to label lg jumps into a block with initialization of an object that has automatic storage duration goto.c(325): Warning: Goto at line 114 to label lg jumps into a block with initialization of an object that has automatic storage duration goto.c(325): Warning: Goto at line 134 to label lg jumps into a block with initialization of an object that has automatic storage duration goto.c(325): Warning: Goto at line 154 to label lg jumps into a block with initialization of an object that has automatic storage duration goto.c(325): Warning: Goto at line 175 to label lg jumps into a block with initialization of an object that has automatic storage duration goto.c(325): Warning: Goto at line 196 to label lg jumps into a block with initialization of an object that has automatic storage duration goto.c(325): Warning: Goto at line 217 to label lg jumps into a block with initialization of an object that has automatic storage duration goto.c(325): Warning: Goto at line 237 to label lg jumps into a block with initialization of an object that has automatic storage duration goto.c(325): Warning: Goto at line 257 to label lg jumps into a block with initialization of an object that has automatic storage duration goto.c(325): Warning: Goto at line 279 to label lg jumps into a block with initialization of an object that has automatic storage duration goto.c(333): Warning: Goto at line 333 to label l8 jumps into a block with initialization of an object that has automatic storage duration goto.c(334): Warning: Goto at line 334 to label l9 jumps into a block with initialization of an object that has automatic storage duration goto.c(335): Warning: Goto at line 335 to label la jumps into a block with initialization of an object that has automatic storage duration goto.c(336): Warning: Goto at line 336 to label lb jumps into a block with initialization of an object that has automatic storage duration goto.c(337): Warning: Goto at line 337 to label lc jumps into a block with initialization of an object that has automatic storage duration goto.c(340): Warning: Goto at line 340 to label lf jumps into a block with initialization of an object that has automatic storage duration goto.c(345): Warning: Goto at line 32 to label lh jumps into a block with initialization of an object that has automatic storage duration goto.c(345): Warning: Goto at line 53 to label lh jumps into a block with initialization of an object that has automatic storage duration goto.c(345): Warning: Goto at line 74 to label lh jumps into a block with initialization of an object that has automatic storage duration goto.c(345): Warning: Goto at line 95 to label lh jumps into a block with initialization of an object that has automatic storage duration goto.c(345): Warning: Goto at line 115 to label lh jumps into a block with initialization of an object that has automatic storage duration goto.c(345): Warning: Goto at line 135 to label lh jumps into a block with initialization of an object that has automatic storage duration goto.c(345): Warning: Goto at line 155 to label lh jumps into a block with initialization of an object that has automatic storage duration goto.c(345): Warning: Goto at line 176 to label lh jumps into a block with initialization of an object that has automatic storage duration goto.c(345): Warning: Goto at line 197 to label lh jumps into a block with initialization of an object that has automatic storage duration goto.c(345): Warning: Goto at line 218 to label lh jumps into a block with initialization of an object that has automatic storage duration goto.c(345): Warning: Goto at line 238 to label lh jumps into a block with initialization of an object that has automatic storage duration goto.c(345): Warning: Goto at line 258 to label lh jumps into a block with initialization of an object that has automatic storage duration goto.c(353): Warning: Goto at line 353 to label l8 jumps into a block with initialization of an object that has automatic storage duration goto.c(354): Warning: Goto at line 354 to label l9 jumps into a block with initialization of an object that has automatic storage duration goto.c(355): Warning: Goto at line 355 to label la jumps into a block with initialization of an object that has automatic storage duration goto.c(356): Warning: Goto at line 356 to label lb jumps into a block with initialization of an object that has automatic storage duration goto.c(357): Warning: Goto at line 357 to label lc jumps into a block with initialization of an object that has automatic storage duration goto.c(359): Warning: Goto at line 359 to label le jumps into a block with initialization of an object that has automatic storage duration goto.c(360): Warning: Goto at line 360 to label lf jumps into a block with initialization of an object that has automatic storage duration goto.c(361): Warning: Goto at line 361 to label lg jumps into a block with initialization of an object that has automatic storage duration goto.c(373): Warning: Goto at line 373 to label l8 jumps into a block with initialization of an object that has automatic storage duration goto.c(374): Warning: Goto at line 374 to label l9 jumps into a block with initialization of an object that has automatic storage duration goto.c(375): Warning: Goto at line 375 to label la jumps into a block with initialization of an object that has automatic storage duration goto.c(376): Warning: Goto at line 376 to label lb jumps into a block with initialization of an object that has automatic storage duration goto.c(377): Warning: Goto at line 377 to label lc jumps into a block with initialization of an object that has automatic storage duration goto.c(378): Warning: Goto at line 378 to label ld jumps into a block with initialization of an object that has automatic storage duration goto.c(379): Warning: Goto at line 379 to label le jumps into a block with initialization of an object that has automatic storage duration goto.c(380): Warning: Goto at line 380 to label lf jumps into a block with initialization of an object that has automatic storage duration goto.c(381): Warning: Goto at line 381 to label lg jumps into a block with initialization of an object that has automatic storage duration goto.c(382): Warning: Goto at line 382 to label lh jumps into a block with initialization of an object that has automatic storage duration �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/misc/limits.c������������������������������������������������������������������������0000664�0000000�0000000�00000003770�13473601511�0015573�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! display type limits !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include <stdio.h> #include <limits.h> #define SSHRT_MAX SHRT_MAX #define SINT_MAX INT_MAX #define SLONG_MAX LONG_MAX #define UCHAR_MIN 0 #define USHRT_MIN 0 #define SSHRT_MIN SHRT_MIN #define UINT_MIN 0 #define SINT_MIN INT_MIN #define ULONG_MIN 0l #define SLONG_MIN LONG_MIN int main(void) { printf("CHAR_MAX: 0x%08x=%d\n", CHAR_MAX, CHAR_MAX); printf("UCHAR_MAX: 0x%08x=%d\n", UCHAR_MAX, UCHAR_MAX); printf("SCHAR_MAX: 0x%08x=%d\n", SCHAR_MAX, SCHAR_MAX); printf("SHRT_MAX: 0x%08x=%d\n", SHRT_MAX, SHRT_MAX); printf("USHRT_MAX: 0x%08x=%d\n", USHRT_MAX, USHRT_MAX); printf("SSHRT_MAX: 0x%08x=%d\n", SSHRT_MAX, SSHRT_MAX); printf("INT_MAX: 0x%08x=%d\n", INT_MAX, INT_MAX); printf("UINT_MAX: 0x%08x=%d\n", UINT_MAX, UINT_MAX); printf("SINT_MAX: 0x%08x=%d\n", SINT_MAX, SINT_MAX); printf("LONG_MAX: 0x%08lx=%ld\n", LONG_MAX, LONG_MAX); printf("ULONG_MAX: 0x%08lx=%ld\n", ULONG_MAX, ULONG_MAX); printf("SLONG_MAX: 0x%08lx=%ld\n", SLONG_MAX, SLONG_MAX); printf("CHAR_MIN: 0x%08x=%d\n", CHAR_MIN, CHAR_MIN); printf("UCHAR_MIN: 0x%08x=%d\n", UCHAR_MIN, UCHAR_MIN); printf("SCHAR_MIN: 0x%08x=%d\n", SCHAR_MIN, SCHAR_MIN); printf("SHRT_MIN: 0x%08x=%d\n", SHRT_MIN, SHRT_MIN); printf("USHRT_MIN: 0x%08x=%d\n", USHRT_MIN, USHRT_MIN); printf("SSHRT_MIN: 0x%08x=%d\n", SSHRT_MIN, SSHRT_MIN); printf("INT_MIN: 0x%08x=%d\n", INT_MIN, INT_MIN); printf("UINT_MIN: 0x%08x=%d\n", UINT_MIN, UINT_MIN); printf("SINT_MIN: 0x%08x=%d\n", SINT_MIN, SINT_MIN); printf("LONG_MIN: 0x%08lx=%ld\n", LONG_MIN, LONG_MIN); printf("ULONG_MIN: 0x%08lx=%ld\n", ULONG_MIN, ULONG_MIN); printf("SLONG_MIN: 0x%08lx=%ld\n", SLONG_MIN, SLONG_MIN); return 0; } ��������cc65-2.18/test/misc/limits.ref����������������������������������������������������������������������0000664�0000000�0000000�00000001226�13473601511�0016117�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������CHAR_MAX: 0x000000ff=255 UCHAR_MAX: 0x000000ff=255 SCHAR_MAX: 0x0000007f=127 SHRT_MAX: 0x00007fff=32767 USHRT_MAX: 0x0000ffff=-1 SSHRT_MAX: 0x00007fff=32767 INT_MAX: 0x00007fff=32767 UINT_MAX: 0x0000ffff=-1 SINT_MAX: 0x00007fff=32767 LONG_MAX: 0x7fffffff=2147483647 ULONG_MAX: 0xffffffff=-1 SLONG_MAX: 0x7fffffff=2147483647 CHAR_MIN: 0x00000000=0 UCHAR_MIN: 0x00000000=0 SCHAR_MIN: 0x0000ff80=-128 SHRT_MIN: 0x00008000=-32768 USHRT_MIN: 0x00000000=0 SSHRT_MIN: 0x00008000=-32768 INT_MIN: 0x00008000=-32768 UINT_MIN: 0x00000000=0 SINT_MIN: 0x00008000=-32768 LONG_MIN: 0x80000000=-2147483648 ULONG_MIN: 0x00000000=0 SLONG_MIN: 0x80000000=-2147483648 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/misc/sitest.c������������������������������������������������������������������������0000664�0000000�0000000�00000217234�13473601511�0015607�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! C99 WCHAR test !!ORIGIN!! !!LICENCE!! public domain */ /* sitest -- exercise features of C99 <stdint.h> and <inttypes.h> This source code has been placed into the PUBLIC DOMAIN by its author. last edit: 1999/11/05 gwyn@arl.mil Tries to accommodate pre-C99 versions of <inttypes.h>. Takes advantage of __Q8_* symbols defined by a particular implementation of <stdint.h>, but doesn't require them. NOTE: This is not a thorough validation test of the facilities. */ #define NO_INTERNAL_WCHAR /*#define STANDALONE*/ #include <errno.h> #include <limits.h> /* for CHAR_BIT */ #include <stdio.h> #include <stddef.h> /* for ptrdiff_t */ #include <stdlib.h> #include <string.h> #if !defined(STANDARD_C99) && !defined(STANDARD_CC65) #error "this test checks C99 features, which are not available in the selected standard." #else #ifdef NO_WCHAR #warn "this test checks C99 features, but NO_WCHAR is defined so the test will most definetly fails." #endif #include <inttypes.h> /* embeds <stdint.h> */ #include <signal.h> /* for sig_atomic_t */ #if defined(INTMAX_MAX) /* <inttypes.h> has C99 features */ #include <wchar.h> #endif #include <inttypes.h> /* test idempotency */ #ifdef STANDALONE FILE *outfile=NULL; #define opentest(x) outfile=stdout; #define closetest(x) #else #endif #if __STDC_VERSION__ >= 199901 #ifndef __Q8_QT #define __Q8_QT long long #endif #endif #ifdef PRIdMAX #define HAVE_PRIdMAX #ifndef __Q8_MT #define __Q8_MT intmax_t #endif #else #ifdef PRIdLEAST64 #ifndef __Q8_MT #define __Q8_MT int_least64_t #endif #define PRIdMAX PRIdLEAST64 #else #ifndef __Q8_MT #define __Q8_MT long #endif #define PRIdMAX "ld" #endif #endif #ifdef PRIuMAX #define HAVE_PRIuMAX #define U__Q8_MT uintmax_t #else #ifdef PRIuLEAST64 #define U__Q8_MT uint_least64_t #define PRIuMAX PRIuLEAST64 #else #define U__Q8_MT unsigned long #define PRIuMAX "lu" #endif #endif #define STR_SUB(s) # s #define STRINGIZE(s) STR_SUB(s) /* extra level to expand argument */ #if defined(SCNo32) || defined(PRIo32) static int32_t int32; #endif static int_least16_t intl16; static uint_least16_t uintl16; static uint_fast16_t uintf16; static intmax_t intmax; static uintmax_t uintmax; int main() { int status = 0; /* exit status to be returned */ /* <stdint.h> features: */ printf("CHAR_BIT=%u\n", (unsigned)CHAR_BIT ); printf("sizeof(char)=%u\n", (unsigned)sizeof(char)); /* s.b. 1 */ printf("sizeof(short)=%u\n", (unsigned)sizeof(short)); printf("sizeof(int)=%u\n", (unsigned)sizeof(int)); printf("sizeof(long)=%u\n", (unsigned)sizeof(long)); #ifdef __Q8_QT printf("sizeof(long long)=%u\n", (unsigned)sizeof(__Q8_QT)); #else printf("*** long long isn't defined ***\n"); #endif printf("sizeof(intmax_t)=%u\n", (unsigned)sizeof(intmax_t)); printf("sizeof(ptrdiff_t)=%u\n", (unsigned)sizeof(ptrdiff_t)); printf("sizeof(size_t)=%u\n", (unsigned)sizeof(size_t)); printf("sizeof(sig_atomic_t)=%u\n", (unsigned)sizeof(sig_atomic_t)); printf("sizeof(wchar_t)=%u\n", (unsigned)sizeof(wchar_t)); #if defined(WINT_MAX) || __STDC_VERSION__ >= 199901 printf("sizeof(wint_t)=%u\n", (unsigned)sizeof(wint_t)); #else printf("*** wint_t isn't defined ***\n"); status = EXIT_FAILURE; #endif #ifdef INT8_MAX printf("sizeof(int8_t)=%u\n", (unsigned)sizeof(int8_t)); printf("sizeof(uint8_t)=%u\n", (unsigned)sizeof(uint8_t)); #endif #ifdef INT9_MAX printf("sizeof(int9_t)=%u\n", (unsigned)sizeof(int9_t)); printf("sizeof(uint9_t)=%u\n", (unsigned)sizeof(uint9_t)); #endif #ifdef INT12_MAX printf("sizeof(int12_t)=%u\n", (unsigned)sizeof(int12_t)); printf("sizeof(uint12_t)=%u\n", (unsigned)sizeof(uint12_t)); #endif #ifdef INT16_MAX printf("sizeof(int16_t)=%u\n", (unsigned)sizeof(int16_t)); printf("sizeof(uint16_t)=%u\n", (unsigned)sizeof(uint16_t)); #endif #ifdef INT18_MAX printf("sizeof(int18_t)=%u\n", (unsigned)sizeof(int18_t)); printf("sizeof(uint18_t)=%u\n", (unsigned)sizeof(uint18_t)); #endif #ifdef INT24_MAX printf("sizeof(int24_t)=%u\n", (unsigned)sizeof(int24_t)); printf("sizeof(uint24_t)=%u\n", (unsigned)sizeof(uint24_t)); #endif #ifdef INT32_MAX printf("sizeof(int32_t)=%u\n", (unsigned)sizeof(int32_t)); printf("sizeof(uint32_t)=%u\n", (unsigned)sizeof(uint32_t)); #endif #ifdef INT36_MAX printf("sizeof(int36_t)=%u\n", (unsigned)sizeof(int36_t)); printf("sizeof(uint36_t)=%u\n", (unsigned)sizeof(uint36_t)); #endif #ifdef INT40_MAX printf("sizeof(int40_t)=%u\n", (unsigned)sizeof(int40_t)); printf("sizeof(uint40_t)=%u\n", (unsigned)sizeof(uint40_t)); #endif #ifdef INT48_MAX printf("sizeof(int48_t)=%u\n", (unsigned)sizeof(int48_t)); printf("sizeof(uint48_t)=%u\n", (unsigned)sizeof(uint48_t)); #endif #ifdef INT60_MAX printf("sizeof(int60_t)=%u\n", (unsigned)sizeof(int60_t)); printf("sizeof(uint60_t)=%u\n", (unsigned)sizeof(uint60_t)); #endif #ifdef INT64_MAX printf("sizeof(int64_t)=%u\n", (unsigned)sizeof(int64_t)); printf("sizeof(uint64_t)=%u\n", (unsigned)sizeof(uint64_t)); #endif #ifdef INT72_MAX printf("sizeof(int72_t)=%u\n", (unsigned)sizeof(int72_t)); printf("sizeof(uint72_t)=%u\n", (unsigned)sizeof(uint72_t)); #endif #ifdef INT128_MAX printf("sizeof(int128_t)=%u\n", (unsigned)sizeof(int128_t)); printf("sizeof(uint128_t)=%u\n", (unsigned)sizeof(uint128_t)); #endif printf("sizeof(int_least8_t)=%u\n", (unsigned)sizeof(int_least8_t)); printf("sizeof(uint_least8_t)=%u\n", (unsigned)sizeof(uint_least8_t)); printf("sizeof(int_least16_t)=%u\n", (unsigned)sizeof(int_least16_t)); printf("sizeof(uint_least16_t)=%u\n", (unsigned)sizeof(uint_least16_t)); printf("sizeof(int_least32_t)=%u\n", (unsigned)sizeof(int_least32_t)); printf("sizeof(uint_least32_t)=%u\n", (unsigned)sizeof(uint_least32_t)); #ifdef INT_LEAST64_MAX printf("sizeof(int_least64_t)=%u\n", (unsigned)sizeof(int_least64_t)); printf("sizeof(uint_least64_t)=%u\n", (unsigned)sizeof(uint_least64_t)); #else printf("*** uint_least64_t isn't defined ***\n"); status = EXIT_FAILURE; #endif #ifdef INT_LEAST128_MAX printf("sizeof(int_least128_t)=%u\n", (unsigned)sizeof(int_least128_t)); printf("sizeof(uint_least128_t)=%u\n", (unsigned)sizeof(uint_least128_t)); #endif printf("sizeof(int_fast8_t)=%u\n", (unsigned)sizeof(int_fast8_t)); printf("sizeof(uint_fast8_t)=%u\n", (unsigned)sizeof(uint_fast8_t)); printf("sizeof(int_fast16_t)=%u\n", (unsigned)sizeof(int_fast16_t)); printf("sizeof(uint_fast16_t)=%u\n", (unsigned)sizeof(uint_fast16_t)); printf("sizeof(int_fast32_t)=%u\n", (unsigned)sizeof(int_fast32_t)); printf("sizeof(uint_fast32_t)=%u\n", (unsigned)sizeof(uint_fast32_t)); #ifdef INT_FAST64_MAX printf("sizeof(int_fast64_t)=%u\n", (unsigned)sizeof(int_fast64_t)); printf("sizeof(uint_fast64_t)=%u\n", (unsigned)sizeof(uint_fast64_t)); #else printf("*** int_fast64_t isn't defined ***\n"); status = EXIT_FAILURE; #endif #ifdef INT_FAST128_MAX printf("sizeof(int_fast128_t)=%u\n", (unsigned)sizeof(int_fast128_t)); printf("sizeof(uint_fast128_t)=%u\n", (unsigned)sizeof(uint_fast128_t)); #endif #if defined(INTPTR_MAX) printf("sizeof(intptr_t)=%u\n", (unsigned)sizeof(intptr_t)); #if defined(UINTPTR_MAX) printf("sizeof(uintptr_t)=%u\n", (unsigned)sizeof(uintptr_t)); #else printf("*** intptr_t is defined but uintptr_t isn't ***\n"); status = EXIT_FAILURE; #endif #elif defined(UINTPTR_MAX) printf("sizeof(uintptr_t)=%u\n", (unsigned)sizeof(uintptr_t)); printf("*** uintptr_t is defined but intptr_t isn't ***\n"); status = EXIT_FAILURE; #else printf("*** neither intptr_t nor uintptr_t is defined ***\n"); status = EXIT_FAILURE; #endif #ifdef INTMAX_MAX printf("sizeof(intmax_t)=%u\n", (unsigned)sizeof(intmax_t)); printf("sizeof(uintmax_t)=%u\n", (unsigned)sizeof(uintmax_t)); #else printf("*** intmax_t isn't defined ***\n"); status = EXIT_FAILURE; #endif #ifdef INT8_MAX printf("INT8_MIN=%"PRIdMAX"\n", (__Q8_MT)INT8_MIN); printf("INT8_MAX=%"PRIdMAX"\n", (__Q8_MT)INT8_MAX); printf("UINT8_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT8_MAX); #endif #ifdef INT9_MAX printf("INT9_MIN=%"PRIdMAX"\n", (__Q8_MT)INT9_MIN); printf("INT9_MAX=%"PRIdMAX"\n", (__Q8_MT)INT9_MAX); printf("UINT9_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT9_MAX); #endif #ifdef INT12_MAX printf("INT12_MIN=%"PRIdMAX"\n", (__Q8_MT)INT12_MIN); printf("INT12_MAX=%"PRIdMAX"\n", (__Q8_MT)INT12_MAX); printf("UINT12_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT12_MAX); #endif #ifdef INT16_MAX printf("INT16_MIN=%"PRIdMAX"\n", (__Q8_MT)INT16_MIN); printf("INT16_MAX=%"PRIdMAX"\n", (__Q8_MT)INT16_MAX); printf("UINT16_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT16_MAX); #endif #ifdef INT18_MAX printf("INT18_MIN=%"PRIdMAX"\n", (__Q8_MT)INT18_MIN); printf("INT18_MAX=%"PRIdMAX"\n", (__Q8_MT)INT18_MAX); printf("UINT18_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT18_MAX); #endif #ifdef INT24_MAX printf("INT24_MIN=%"PRIdMAX"\n", (__Q8_MT)INT24_MIN); printf("INT24_MAX=%"PRIdMAX"\n", (__Q8_MT)INT24_MAX); printf("UINT24_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT24_MAX); #endif #ifdef INT32_MAX printf("INT32_MIN=%"PRIdMAX"\n", (__Q8_MT)INT32_MIN); printf("INT32_MAX=%"PRIdMAX"\n", (__Q8_MT)INT32_MAX); printf("UINT32_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT32_MAX); #endif #ifdef INT36_MAX printf("INT36_MIN=%"PRIdMAX"\n", (__Q8_MT)INT36_MIN); printf("INT36_MAX=%"PRIdMAX"\n", (__Q8_MT)INT36_MAX); printf("UINT36_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT36_MAX); #endif #ifdef INT40_MAX printf("INT40_MIN=%"PRIdMAX"\n", (__Q8_MT)INT40_MIN); printf("INT40_MAX=%"PRIdMAX"\n", (__Q8_MT)INT40_MAX); printf("UINT40_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT40_MAX); #endif #ifdef INT48_MAX printf("INT48_MIN=%"PRIdMAX"\n", (__Q8_MT)INT48_MIN); printf("INT48_MAX=%"PRIdMAX"\n", (__Q8_MT)INT48_MAX); printf("UINT48_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT48_MAX); #endif #ifdef INT60_MAX printf("INT60_MIN=%"PRIdMAX"\n", (__Q8_MT)INT60_MIN); printf("INT60_MAX=%"PRIdMAX"\n", (__Q8_MT)INT60_MAX); printf("UINT60_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT60_MAX); #endif #ifdef INT64_MAX printf("INT64_MIN=%"PRIdMAX"\n", (__Q8_MT)INT64_MIN); printf("INT64_MAX=%"PRIdMAX"\n", (__Q8_MT)INT64_MAX); printf("UINT64_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT64_MAX); #endif #ifdef INT72_MAX printf("INT72_MIN=%"PRIdMAX"\n", (__Q8_MT)INT72_MIN); printf("INT72_MAX=%"PRIdMAX"\n", (__Q8_MT)INT72_MAX); printf("UINT72_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT72_MAX); #endif #ifdef INT128_MAX printf("INT128_MIN=%"PRIdMAX"\n", (__Q8_MT)INT128_MIN); printf("INT128_MAX=%"PRIdMAX"\n", (__Q8_MT)INT128_MAX); printf("UINT128_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT128_MAX); #endif printf("INT_LEAST8_MIN=%"PRIdMAX"\n", (__Q8_MT)INT_LEAST8_MIN); printf("INT_LEAST8_MAX=%"PRIdMAX"\n", (__Q8_MT)INT_LEAST8_MAX); printf("UINT_LEAST8_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT_LEAST8_MAX); printf("INT_LEAST16_MIN=%"PRIdMAX"\n", (__Q8_MT)INT_LEAST16_MIN); printf("INT_LEAST16_MAX=%"PRIdMAX"\n", (__Q8_MT)INT_LEAST16_MAX); printf("UINT_LEAST16_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT_LEAST16_MAX); printf("INT_LEAST32_MIN=%"PRIdMAX"\n", (__Q8_MT)INT_LEAST32_MIN); printf("INT_LEAST32_MAX=%"PRIdMAX"\n", (__Q8_MT)INT_LEAST32_MAX); printf("UINT_LEAST32_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT_LEAST32_MAX); #ifdef INT_LEAST64_MAX printf("INT_LEAST64_MIN=%"PRIdMAX"\n", (__Q8_MT)INT_LEAST64_MIN); printf("INT_LEAST64_MAX=%"PRIdMAX"\n", (__Q8_MT)INT_LEAST64_MAX); printf("UINT_LEAST64_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT_LEAST64_MAX); #endif #ifdef INT_LEAST128_MAX printf("INT_LEAST128_MIN=%"PRIdMAX"\n", (__Q8_MT)INT_LEAST128_MIN); printf("INT_LEAST128_MAX=%"PRIdMAX"\n", (__Q8_MT)INT_LEAST128_MAX); printf("UINT_LEAST128_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT_LEAST128_MAX); #endif printf("INT_FAST8_MIN=%"PRIdMAX"\n", (__Q8_MT)INT_FAST8_MIN); printf("INT_FAST8_MAX=%"PRIdMAX"\n", (__Q8_MT)INT_FAST8_MAX); printf("UINT_FAST8_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT_FAST8_MAX); printf("INT_FAST16_MIN=%"PRIdMAX"\n", (__Q8_MT)INT_FAST16_MIN); printf("INT_FAST16_MAX=%"PRIdMAX"\n", (__Q8_MT)INT_FAST16_MAX); printf("UINT_FAST16_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT_FAST16_MAX); printf("INT_FAST32_MIN=%"PRIdMAX"\n", (__Q8_MT)INT_FAST32_MIN); printf("INT_FAST32_MAX=%"PRIdMAX"\n", (__Q8_MT)INT_FAST32_MAX); printf("UINT_FAST32_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT_FAST32_MAX); #ifdef INT_FAST64_MAX printf("INT_FAST64_MIN=%"PRIdMAX"\n", (__Q8_MT)INT_FAST64_MIN); printf("INT_FAST64_MAX=%"PRIdMAX"\n", (__Q8_MT)INT_FAST64_MAX); printf("UINT_FAST64_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT_FAST64_MAX); #endif #ifdef INT_FAST128_MAX printf("INT_FAST128_MIN=%"PRIdMAX"\n", (__Q8_MT)INT_FAST128_MIN); printf("INT_FAST128_MAX=%"PRIdMAX"\n", (__Q8_MT)INT_FAST128_MAX); printf("UINT_FAST128_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINT_FAST128_MAX); #endif #ifdef INTPTR_MAX printf("INTPTR_MIN=%"PRIdMAX"\n", (__Q8_MT)INTPTR_MIN); printf("INTPTR_MAX=%"PRIdMAX"\n", (__Q8_MT)INTPTR_MAX); #endif #ifdef UINTPTR_MAX printf("UINTPTR_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINTPTR_MAX); #endif #ifdef INTMAX_MAX printf("INTMAX_MIN=%"PRIdMAX"\n", (__Q8_MT)INTMAX_MIN); printf("INTMAX_MAX=%"PRIdMAX"\n", (__Q8_MT)INTMAX_MAX); printf("UINTMAX_MAX=%"PRIuMAX"\n", (U__Q8_MT)UINTMAX_MAX); #endif #ifdef PTRDIFF_MAX printf("PTRDIFF_MIN=%"PRIdMAX"\n", (__Q8_MT)PTRDIFF_MIN); printf("PTRDIFF_MAX=%"PRIdMAX"\n", (__Q8_MT)PTRDIFF_MAX); #endif #ifdef SIG_ATOMIC_MAX #if SIG_ATOMIC_MIN < 0 printf("SIG_ATOMIC_MIN=%"PRIdMAX"\n", (__Q8_MT)SIG_ATOMIC_MIN); printf("SIG_ATOMIC_MAX=%"PRIdMAX"\n", (__Q8_MT)SIG_ATOMIC_MAX); #else printf("SIG_ATOMIC_MIN=%"PRIuMAX"\n", (U__Q8_MT)SIG_ATOMIC_MIN); printf("SIG_ATOMIC_MAX=%"PRIuMAX"\n", (U__Q8_MT)SIG_ATOMIC_MAX); #endif #endif #ifdef SIZE_MAX printf("SIZE_MAX=%"PRIuMAX"\n", (U__Q8_MT)SIZE_MAX); #endif #ifdef WCHAR_MAX #if WCHAR_MIN < 0 printf("WCHAR_MIN=%"PRIdMAX"\n", (__Q8_MT)WCHAR_MIN); printf("WCHAR_MAX=%"PRIdMAX"\n", (__Q8_MT)WCHAR_MAX); #else printf("WCHAR_MIN=%"PRIuMAX"\n", (U__Q8_MT)WCHAR_MIN); printf("WCHAR_MAX=%"PRIuMAX"\n", (U__Q8_MT)WCHAR_MAX); #endif #endif #ifdef WINT_MAX #if WINT_MIN < 0 printf("WINT_MIN=%"PRIdMAX"\n", (__Q8_MT)WINT_MIN); printf("WINT_MAX=%"PRIdMAX"\n", (__Q8_MT)WINT_MAX); #else printf("WINT_MIN=%"PRIuMAX"\n", (U__Q8_MT)WINT_MIN); printf("WINT_MAX=%"PRIuMAX"\n", (U__Q8_MT)WINT_MAX); #endif #endif /* 7.18.4 Macros for integer constants */ /* INTn_C for n=8 and 16 were at one point unimplementable on most platforms, so they're treated as "optional": */ #ifdef INT8_C if ( INT8_C(-123) != -123 ) printf("*** INT8_C(-123) produced %"PRIdMAX" ***\n", (__Q8_MT)INT8_C(-123) ); if ( UINT8_C(123) != 123 ) printf("*** UINT8_C(123) produced %"PRIuMAX" ***\n", (U__Q8_MT)UINT8_C(123) ); #endif #ifdef INT16_C if ( INT16_C(-12345) != -12345 ) printf("*** INT16_C(-12345) produced %"PRIdMAX" ***\n", (__Q8_MT)INT16_C(-12345) ); if ( UINT16_C(12345) != 12345 ) printf("*** UINT16_C(12345) produced %"PRIuMAX" ***\n", (U__Q8_MT)UINT16_C(12345) ); #endif if ( INT32_C(-123456789) != -123456789 ) printf("*** INT32_C(-123456789) produced %"PRIdMAX" ***\n", (__Q8_MT)INT32_C(-123456789) ); if ( UINT32_C(123456789) != 123456789 ) printf("*** UINT32_C(123456789) produced %"PRIuMAX" ***\n", (U__Q8_MT)UINT32_C(123456789) ); #ifdef INT_LEAST64_MAX if ( INT64_C(-1234567890123456789) != -1234567890123456789 ) printf("*** INT64_C(-1234567890123456789) produced %"PRIdMAX " ***\n", (__Q8_MT)INT64_C(-1234567890123456789) ); if ( UINT64_C(1234567890123456789) != 1234567890123456789 ) printf("*** UINT64_C(1234567890123456789) produced %"PRIuMAX " ***\n", (U__Q8_MT)UINT64_C(1234567890123456789) ); #endif #ifdef INTMAX_MAX if ( INTMAX_C(-1234567890123456789) != -1234567890123456789 ) printf("*** INTMAX_C(-1234567890123456789) produced %"PRIdMAX " ***\n", (__Q8_MT)INTMAX_C(-1234567890123456789) ); if ( UINTMAX_C(1234567890123456789) != 1234567890123456789 ) printf("*** UINTMAX_C(1234567890123456789) produced %"PRIuMAX " ***\n", (U__Q8_MT)UINTMAX_C(1234567890123456789) ); #endif /* <inttypes.h> features: */ #if __STDC_VERSION__ >= 199901 printf("sizeof(imaxdiv_t)=%u\n", (unsigned)sizeof(imaxdiv_t)); #endif /* 7.8.1 Macros for format specifiers */ { /* scanf these strings */ static const char in_dn[] = "Z119bZ"; static const char in_dmo[] = "Z-0119bZ"; static const char in_dspx[] = "Z \t\n +0X119bZ"; static const char in_dsmx[] = "Z \t\n -0x119bZ"; static const char in_dsn[] = "Z \t\n 119bZ"; static const char in_dp[] = "Z+119bZ"; static const char in_dpx[] = "Z+0X119bz"; /* sprintf into this */ static char buffer[1024]; #if 1 #define SCAN(buf,fs,var,exp) if ( sscanf(buf, "Z%" fs, &var) != 1 ) \ { \ printf("***%s=",fs, STR_SUB(fs) \ " failed ***\n" \ ); \ status = EXIT_FAILURE; \ } \ else if ( var != (exp) ) \ { \ printf("***%s=",fs, STR_SUB(fs) \ " should be: " STR_SUB(exp) \ ", was: %" fs " ***\n", var \ ); \ status = EXIT_FAILURE; \ } \ else /* for trailing semicolon */ #define PRINT(fs,var,exp) if ( sprintf(buffer, "%" fs, var ) <= 0 ) \ { \ printf("***%s=",fs, STR_SUB(fs) \ " failed ***\n" \ ); \ status = EXIT_FAILURE; \ } \ else if ( strcmp(buffer, STR_SUB(exp)) != 0 ) \ { \ printf("***%s=",fs, STR_SUB(fs) \ " should be: " STR_SUB(exp) \ ", was: %s ***\n", buffer \ ); \ status = EXIT_FAILURE; \ } \ else /* for trailing semicolon */ #else #define SCAN(buf,fs,var,exp) #define PRINT(fs,var,exp) #endif #ifdef SCNo32 SCAN(in_dn, SCNo32, int32, 9); #endif #ifdef PRIo32 PRINT(PRIo32, int32, 11); #endif SCAN(in_dmo, SCNiLEAST16, intl16, -9); SCAN(in_dspx, SCNdLEAST16, intl16, 0); SCAN(in_dsmx, SCNiLEAST16, intl16, -4507); PRINT(PRIdLEAST16, intl16, -4507); PRINT(PRIiLEAST16, intl16, -4507); SCAN(in_dsn, SCNxLEAST16, uintl16, 4507); PRINT(PRIoLEAST16, uintl16, 10633); PRINT(PRIuLEAST16, uintl16, 4507); PRINT(PRIxLEAST16, uintl16, 119b); PRINT(PRIXLEAST16, uintl16, 119B); SCAN(in_dp, SCNxFAST16, uintf16, 4507); PRINT(PRIxFAST16, uintf16, 119b); #ifdef SCNdMAX SCAN(in_dp, SCNdMAX, intmax, 119); #endif #ifdef PRIiMAX PRINT(PRIiMAX, intmax, 119); #endif #ifdef SCNoMAX SCAN(in_dpx, SCNoMAX, uintmax, 0); #endif #ifdef PRIxMAX PRINT(PRIxMAX, uintmax, 0); #endif /* Obviously there should be a much larger battery of such tests. */ } #if defined(INTMAX_MAX) /* <inttypes.h> has C99 features */ /* 7.8.2 Functions for greatest-width integer types */ { static struct { intmax_t input; intmax_t expect; } abs_data[] = { #ifdef INT8_MAX { INT8_MAX, INT8_MAX, }, { -INT8_MAX, INT8_MAX, }, { UINT8_MAX, UINT8_MAX, }, #endif #if 0 #ifdef INT16_MAX { INT16_MAX, INT16_MAX, }, { -INT16_MAX, INT16_MAX, }, { UINT16_MAX, UINT16_MAX, }, #endif #ifdef INT32_MAX { INT32_MAX, INT32_MAX, }, { -INT32_MAX, INT32_MAX, }, #ifdef INT_LEAST64_MAX /* else might support only 32 bits */ { UINT32_MAX, UINT32_MAX, }, #endif #endif #ifdef INT64_MAX { INT64_MAX, INT64_MAX, }, { -INT64_MAX, INT64_MAX, }, #endif { INT_LEAST8_MAX, INT_LEAST8_MAX, }, { -INT_LEAST8_MAX, INT_LEAST8_MAX, }, { UINT_LEAST8_MAX, UINT_LEAST8_MAX, }, { INT_LEAST16_MAX, INT_LEAST16_MAX, }, { -INT_LEAST16_MAX, INT_LEAST16_MAX, }, { UINT_LEAST16_MAX, UINT_LEAST16_MAX, }, { INT_LEAST32_MAX, INT_LEAST32_MAX, }, { -INT_LEAST32_MAX, INT_LEAST32_MAX, }, #ifdef INT_LEAST64_MAX { UINT_LEAST32_MAX, UINT_LEAST32_MAX, }, { INT_LEAST64_MAX, INT_LEAST64_MAX, }, { -INT_LEAST64_MAX, INT_LEAST64_MAX, }, #endif { INT_FAST8_MAX, INT_FAST8_MAX, }, { -INT_FAST8_MAX, INT_FAST8_MAX, }, { UINT_FAST8_MAX, UINT_FAST8_MAX, }, { INT_FAST16_MAX, INT_FAST16_MAX, }, { -INT_FAST16_MAX, INT_FAST16_MAX, }, { UINT_FAST16_MAX, UINT_FAST16_MAX, }, { INT_FAST32_MAX, INT_FAST32_MAX, }, { -INT_FAST32_MAX, INT_FAST32_MAX, }, #ifdef INT_FAST64_MAX { UINT_FAST32_MAX, UINT_FAST32_MAX, }, { INT_FAST64_MAX, INT_FAST64_MAX, }, { -INT_FAST64_MAX, INT_FAST64_MAX, }, #endif #ifdef INTPTR_MAX { INTPTR_MAX, INTPTR_MAX, }, { -INTPTR_MAX, INTPTR_MAX, }, #endif #ifdef UINTPTR_MAX { UINTPTR_MAX, UINTPTR_MAX, }, #endif { INTMAX_MAX, INTMAX_MAX, }, #ifdef PTRDIFF_MAX { PTRDIFF_MAX, PTRDIFF_MAX, }, #endif #ifdef SIG_ATOMIC_MAX { SIG_ATOMIC_MAX, SIG_ATOMIC_MAX, }, #if SIG_ATOMIC_MIN < 0 { -SIG_ATOMIC_MAX, SIG_ATOMIC_MAX, }, #endif #endif #ifdef SIZE_MAX { SIZE_MAX, SIZE_MAX, }, #endif #ifdef WCHAR_MAX { WCHAR_MAX, WCHAR_MAX, }, #if WCHAR_MIN < 0 { -WCHAR_MAX, WCHAR_MAX, }, #endif #endif #ifdef WINT_MAX { WINT_MAX, WINT_MAX, }, #if WINT_MIN < 0 { -WINT_MAX, WINT_MAX, }, #endif #endif { 127, 127, }, { -127, 127, }, { 128, 128, }, { -127-1, 128, }, { 255, 255, }, { -256+1, 255, }, { 256, 256, }, { -256, 256, }, { 32767, 32767, }, { -32767, 32767, }, { 32768, 32768, }, { -32767-1, 32768, }, { 65535, 65535, }, { -65536+1, 65535, }, { 65536, 65536, }, { -65536, 65536, }, { 2147483647, 2147483647, }, { -2147483647, 2147483647, }, { 2147483648, 2147483648, }, { -2147483647-1, 2147483648, }, #ifdef INT_LEAST64_MAX /* else might support only 32 bits */ { 4294967295, 4294967295, }, { -4294967296+1, 4294967295, }, { 4294967296, 4294967296, }, { -4294967296, 4294967296, }, { 9223372036854775807, 9223372036854775807, }, { -9223372036854775807, 9223372036854775807, }, { 1234567890123456789, 1234567890123456789, }, { -1234567890123456789, 1234567890123456789, }, #endif { 1, 1, }, { -1, 1, }, { 2, 2, }, { -2, 2, }, { 10, 10, }, { -10, 10, }, { 16, 16, }, { -16, 16, }, #endif /* Other test cases can be added here. */ { 0, 0 /* terminates the list */ }, }, *adp = abs_data; do { if ( (intmax = imaxabs(adp->input)) != adp->expect ) { printf("*** imaxabs(%"PRIdMAX") failed; should be: %" PRIdMAX", was: %"PRIdMAX" ***\n", adp->input, adp->expect, intmax ); status = EXIT_FAILURE; } // } while ( adp++->input != 0 ); } while ( (adp++)->input != 0 ); } { imaxdiv_t result; static struct { intmax_t numer; intmax_t denom; intmax_t exp_quot; intmax_t exp_rem; } div_data[] = { { 0, 1, 0, 0, }, #if 0 { 0, -1, 0, 0, }, { 0, 2, 0, 0, }, { 0, -2, 0, 0, }, { 0, 5, 0, 0, }, { 0, -5, 0, 0, }, { 1, 1, 1, 0, }, { 1, -1, -1, 0, }, { 1, 2, 0, 1, }, { 1, -2, 0, 1, }, { 1, 5, 0, 1, }, { 1, -5, 0, 1, }, { -1, 1, -1, 0, }, { -1, -1, 1, 0, }, { -1, 2, 0, -1, }, { -1, -2, 0, -1, }, { -1, 5, 0, -1, }, { -1, -5, 0, -1, }, { 2, 1, 2, 0, }, { 2, -1, -2, 0, }, { 2, 2, 1, 0, }, { 2, -2, -1, 0, }, { 2, 5, 0, 2, }, { 2, -5, 0, 2, }, { -2, 1, -2, 0, }, { -2, -1, 2, 0, }, { -2, 2, -1, 0, }, { -2, -2, 1, 0, }, { -2, 5, 0, -2, }, { -2, -5, 0, -2, }, { 17, 5, 3, 2, }, { -17, -5, 3, -2, }, { 17, -5, -3, 2, }, { -17, 5, -3, -2, }, { 2147483647, 1, 2147483647, 0, }, { -2147483647, 1, -2147483647, 0, }, { 2147483648, 1, 2147483648, 0, }, { -2147483647-1, 1, -2147483647-1, 0, }, { 2147483647, 2, 1073741823, 1, }, { -2147483647, 2, -1073741823, -1, }, { 2147483648, 2, 1073741824, 0, }, { -2147483647-1, 2, -1073741824, 0, }, #ifdef INT_LEAST64_MAX /* else might support only 32 bits */ { 4294967295, 1, 4294967295, 0, }, { -4294967296+1, 1, -4294967296+1, 0, }, { 4294967296, 1, 4294967296, 0, }, { -4294967296, 1, -4294967296, 0, }, { 4294967295, -1, -4294967296+1, 0, }, { -4294967296+1, -1, 4294967295, 0, }, { 4294967296, -1, -4294967296, 0, }, { -4294967296, -1, 4294967296, 0, }, { 4294967295, 2, 2147483647, 1, }, { -4294967296+1, 2, -2147483647, -1, }, { 4294967296, 2, 2147483648, 0, }, { -4294967296, 2, -2147483647-1, 0, }, { 4294967295, 2147483647, 2, 1, }, { -4294967296+1, 2147483647, -2, -1, }, { 4294967296, 2147483647, 2, 2, }, { -4294967296, 2147483647, -2, -2, }, { 4294967295, -2147483647, -2, 1, }, { -4294967296+1, -2147483647, 2, -1, }, { 4294967296, -2147483647, -2, 2, }, { -4294967296, -2147483647, 2, -2, }, { 4294967295, 2147483648, 1, 2147483647, }, { -4294967296+1, 2147483648, -1, -2147483647, }, { 4294967296, 2147483648, 2, 0, }, { -4294967296, 2147483648, -2, 0, }, { 4294967295, -2147483647-1, -1, 2147483647, }, { -4294967296+1, -2147483647-1, 1, -2147483647,}, { 4294967296, -2147483647-1, -2, 0, }, { -4294967296, -2147483647-1, 2, 0, }, { 9223372036854775807, 1, 9223372036854775807, 0, }, { -9223372036854775807, 1, -9223372036854775807, 0, }, { 9223372036854775807, 2, 4611686018427387903, 1, }, { -9223372036854775807, 2, -4611686018427387903, -1, }, #endif #endif /* There should be a much larger battery of such tests. */ { 0, 0, 0, 0 }, /* 0 denom terminates the list */ }, *ddp; #if 0 for ( ddp = div_data; ddp->denom != 0; ++ddp ) if ( (result = imaxdiv(ddp->numer, ddp->denom)).quot != ddp->exp_quot || result.rem != ddp->exp_rem ) { // printf("*** imaxdiv(%"PRIdMAX",%"PRIdMAX // ") failed; should be: (%"PRIdMAX",%"PRIdMAX // "), was: (%"PRIdMAX",%"PRIdMAX") ***\n", // ddp->numer, ddp->denom, ddp->exp_quot, // ddp->exp_rem, result.quot, result.rem // ); printf("err:imaxdiv(%"PRIdMAX",%"PRIdMAX ") = (%"PRIdMAX",%"PRIdMAX "), is: (%"PRIdMAX",%"PRIdMAX")\n", ddp->numer, ddp->denom, ddp->exp_quot, ddp->exp_rem, result.quot, result.rem ); status = EXIT_FAILURE; } #endif } { char *endptr; wchar_t *wendptr; static char saved[64]; /* holds copy of input string */ static wchar_t wnptr[64]; /* holds wide copy of test string */ static int warned; /* "warned for null endptr" flag */ register int i; static struct { char * nptr; int base; intmax_t exp_val; int exp_len; } str_data[] = { { "", 0, 0, 0, }, { "", 2, 0, 0, }, { "", 8, 0, 0, }, { "", 9, 0, 0, }, { "", 10, 0, 0, }, { "", 16, 0, 0, }, { "", 36, 0, 0, }, { "0", 0, 0, 1, }, { "0", 2, 0, 1, }, { "0", 8, 0, 1, }, { "0", 9, 0, 1, }, { "0", 10, 0, 1, }, { "0", 16, 0, 1, }, { "0", 36, 0, 1, }, { "+0", 0, 0, 2, }, { "+0", 2, 0, 2, }, { "+0", 8, 0, 2, }, { "+0", 9, 0, 2, }, { "+0", 10, 0, 2, }, { "+0", 16, 0, 2, }, { "+0", 36, 0, 2, }, { "-0", 0, 0, 2, }, { "-0", 2, 0, 2, }, { "-0", 8, 0, 2, }, { "-0", 9, 0, 2, }, { "-0", 10, 0, 2, }, { "-0", 16, 0, 2, }, { "-0", 36, 0, 2, }, { "Inf", 0, 0, 0, }, { "Inf", 2, 0, 0, }, { "Inf", 8, 0, 0, }, { "Inf", 9, 0, 0, }, { "Inf", 10, 0, 0, }, { "Inf", 16, 0, 0, }, { "Inf", 36, 24171, 3, }, { "+Inf", 0, 0, 0, }, { "+Inf", 2, 0, 0, }, { "+Inf", 8, 0, 0, }, { "+Inf", 9, 0, 0, }, { "+Inf", 10, 0, 0, }, { "+Inf", 16, 0, 0, }, { "+Inf", 36, 24171, 4, }, { "-Inf", 0, 0, 0, }, { "-Inf", 2, 0, 0, }, { "-Inf", 8, 0, 0, }, { "-Inf", 9, 0, 0, }, { "-Inf", 10, 0, 0, }, { "-Inf", 16, 0, 0, }, { "-Inf", 36, -24171, 4, }, { "inf", 0, 0, 0, }, { "inf", 2, 0, 0, }, { "inf", 8, 0, 0, }, { "inf", 9, 0, 0, }, { "inf", 10, 0, 0, }, { "inf", 16, 0, 0, }, { "inf", 36, 24171, 3, }, { "+inf", 0, 0, 0, }, { "+inf", 2, 0, 0, }, { "+inf", 8, 0, 0, }, { "+inf", 9, 0, 0, }, { "+inf", 10, 0, 0, }, { "+inf", 16, 0, 0, }, { "+inf", 36, 24171, 4, }, { "-inf", 0, 0, 0, }, { "-inf", 2, 0, 0, }, { "-inf", 8, 0, 0, }, { "-inf", 9, 0, 0, }, { "-inf", 10, 0, 0, }, { "-inf", 16, 0, 0, }, { "-inf", 36, -24171, 4, }, { "119b8Z", 0, 119, 3, }, { "119bZ", 0, 119, 3, }, { "-0119bZ", 0, -9, 4, }, { " \t\n 0X119bZ", 0, 4507, 10, }, { " \t\n +0X119bZ", 0, 4507, 11, }, { " \t\n -0x119bZ", 0, -4507, 11, }, { " \t\n 119bZ", 0, 119, 7, }, { "+119bZ", 0, 119, 4, }, { "+0X119bz", 0, 4507, 7, }, { "119b8Z", 2, 3, 2, }, { "119bZ", 2, 3, 2, }, { "-0119bZ", 2, -3, 4, }, { " \t\n 0X119bZ", 2, 0, 5, }, { " \t\n +0X119bZ", 2, 0, 6, }, { " \t\n -0x119bZ", 2, 0, 6, }, { " \t\n 119bZ", 2, 3, 6, }, { "+119bZ", 2, 3, 3, }, { "+0X119bz", 2, 0, 2, }, { "119b8Z", 8, 9, 2, }, { "119bZ", 8, 9, 2, }, { "-0119bZ", 8, -9, 4, }, { " \t\n 0X119bZ", 8, 0, 5, }, { " \t\n +0X119bZ", 8, 0, 6, }, { " \t\n -0x119bZ", 8, 0, 6, }, { " \t\n 119bZ", 8, 9, 6, }, { "+119bZ", 8, 9, 3, }, { "+0X119bz", 8, 0, 2, }, { "119b8Z", 9, 10, 2, }, { "119bZ", 9, 10, 2, }, { "-0119bZ", 9, -10, 4, }, { " \t\n 0X119bZ", 9, 0, 5, }, { " \t\n +0X119bZ", 9, 0, 6, }, { " \t\n -0x119bZ", 9, 0, 6, }, { " \t\n 119bZ", 9, 10, 6, }, { "+119bZ", 9, 10, 3, }, { "+0X119bz", 9, 0, 2, }, { "119b8Z", 10, 119, 3, }, { "119bZ", 10, 119, 3, }, { "-0119bZ", 10, -119, 5, }, { " \t\n 0X119bZ", 10, 0, 5, }, { " \t\n +0X119bZ", 10, 0, 6, }, { " \t\n -0x119bZ", 10, 0, 6, }, { " \t\n 119bZ", 10, 119, 7, }, { "+119bZ", 10, 119, 4, }, { "+0X119bz", 10, 0, 2, }, { "119b8Z", 16, 72120, 5, }, { "119bZ", 16, 4507, 4, }, { "-0119bZ", 16, -4507, 6, }, { " \t\n 0X119bZ", 16, 4507, 10, }, { " \t\n +0X119bZ", 16, 4507, 11, }, { " \t\n -0x119bZ", 16, -4507, 11, }, { " \t\n 119bZ", 16, 4507,8, }, { "+119bZ", 16, 4507, 5, }, { "+0X119bz", 16, 4507, 7, }, { "119b8Z", 36, 62580275, 6, }, { "119bZ", 36, 1738367, 5, }, { "-0119bZ", 36, -1738367, 7, }, { " \t\n 0X119bZ", 36, 1997122175, 11, }, { " \t\n +0X119bZ", 36, 1997122175, 12, }, { " \t\n -0x119bZ", 36, -1997122175, 12, }, { " \t\n 119bZ", 36, 1738367, 9, }, { "+119bZ", 36, 1738367, 6, }, { "+0X119bz", 36, 1997122175, 8, }, /* There should be a much larger battery of such tests. */ { "127", 0, 127, 3, }, { "-127", 0, -127, 4, }, { "128", 0, 128, 3, }, { "-128", 0, -127-1, 4, }, { "255", 0, 255, 3, }, { "-255", 0, -255, 4, }, { "256", 0, 256, 3, }, { "-256", 0, -255-1, 4, }, { "32767", 0, 32767, 5, }, { "-32767", 0, -32767, 6, }, { "32768", 0, 32768, 5, }, { "-32768", 0, -32767-1, 6, }, { "65535", 0, 65535, 5, }, { "-65535", 0, -65536+1, 6, }, { "65536", 0, 65536, 5, }, { "-65536", 0, -65536, 6, }, { "2147483647", 0, 2147483647, 10, }, { "-2147483647", 0, -2147483647, 11, }, { "2147483648", 0, 2147483648, 10, }, { "-2147483648", 0, -2147483647-1, 11, }, { "4294967295", 0, 4294967295, 10, }, { "-4294967295", 0, -4294967296+1, 11, }, { "4294967296", 0, 4294967296, 10, }, { "-4294967296", 0, -4294967296, 11, }, { "9223372036854775807", 0, 9223372036854775807, 19, }, { "-9223372036854775807", 0, -9223372036854775807, 20, }, { "1234567890123456789", 0, 1234567890123456789, 19, }, { "-1234567890123456789", 0, -1234567890123456789, 20, }, { "1", 0, 1, 1, }, { "-1", 0, -1, 2, }, { "2", 0, 2, 1, }, { "-2", 0, -2, 2, }, { "10", 0, 10, 2, }, { "-10", 0, -10, 3, }, { "16", 0, 16, 2, }, { "-16", 0, -16, 3, }, /* Other test cases can be added here. */ { NULL, 0, 0, 0 }, /* terminates the list */ }, *sdp; for ( sdp = str_data; sdp->nptr != NULL ; ++sdp ) { /* 7.8.2.3 The strtoimax and strtoumax functions */ strcpy(saved, sdp->nptr); errno = 0; /* shouldn't be changed */ if ( (intmax = strtoimax(sdp->nptr, &endptr, sdp->base)) != sdp->exp_val ) { int save = errno; printf("*** strtoimax(%s,,%d) failed; should be: %" PRIdMAX", was: %"PRIdMAX" ***\n", sdp->nptr, sdp->base, sdp->exp_val, intmax ); status = EXIT_FAILURE; errno = save; } else if ( endptr != sdp->nptr + sdp->exp_len ) { int save = errno; printf("*** strtoimax(%s,,%d) returned wrong endptr" " ***\n", sdp->nptr, sdp->base ); status = EXIT_FAILURE; errno = save; } if ( errno != 0 ) { printf("*** strtoimax modified errno ***\n"); status = EXIT_FAILURE; } if ( strcmp(sdp->nptr, saved) != 0 ) { printf("*** strtoimax modified its input ***\n"); status = EXIT_FAILURE; strcpy(saved, sdp->nptr); } if ( sdp->exp_val >= 0 ) /* else some sign extension */ { errno = 0; /* shouldn't be changed */ if ( (uintmax = strtoumax(sdp->nptr, &endptr, sdp->base ) ) != sdp->exp_val ) { int save = errno; printf("*** strtoumax(%s,,%d) failed; " "should be: %"PRIuMAX", was: %"PRIuMAX " ***\n", sdp->nptr, sdp->base, sdp->exp_val, uintmax ); status = EXIT_FAILURE; errno = save; } else if ( endptr != sdp->nptr + sdp->exp_len ) { int save = errno; printf("*** strtoumax(%s,,%d) returned wrong " "endptr ***\n", sdp->nptr, sdp->base ); status = EXIT_FAILURE; errno = save; } if ( errno != 0 ) { printf("*** strtoumax modified errno ***\n"); status = EXIT_FAILURE; } if ( strcmp(sdp->nptr, saved) != 0 ) { printf("*** strtoumax" " modified its input ***\n" ); status = EXIT_FAILURE; strcpy(saved, sdp->nptr); } } /* tests for null endptr */ #define WARN() if (!warned) warned = 1, printf("*** Using null endptr: ***\n") warned = 0; errno = 0; /* shouldn't be changed */ if ( (intmax = strtoimax(sdp->nptr, (char **)NULL, sdp->base)) != sdp->exp_val ) { int save = errno; WARN(); printf("*** strtoimax(%s,NULL,%d) failed; " "should be: %"PRIdMAX", was: %"PRIdMAX" ***\n", sdp->nptr, sdp->base, sdp->exp_val, intmax ); status = EXIT_FAILURE; errno = save; } if ( errno != 0 ) { WARN(); printf("*** strtoimax modified errno ***\n"); status = EXIT_FAILURE; } if ( strcmp(sdp->nptr, saved) != 0 ) { WARN(); printf("*** strtoimax modified its input ***\n"); status = EXIT_FAILURE; strcpy(saved, sdp->nptr); } if ( sdp->exp_val >= 0 ) /* else some sign extension */ { errno = 0; /* shouldn't be changed */ if ( (uintmax = strtoumax(sdp->nptr, (char **)NULL, sdp->base ) ) != sdp->exp_val ) { int save = errno; WARN(); printf("*** strtoumax(%s,NULL,%d) failed; " "should be: %"PRIuMAX", was: %"PRIuMAX " ***\n", sdp->nptr, sdp->base, sdp->exp_val, uintmax ); status = EXIT_FAILURE; errno = save; } if ( errno != 0 ) { WARN(); printf("*** strtoumax modified errno ***\n"); status = EXIT_FAILURE; } if ( strcmp(sdp->nptr, saved) != 0 ) { WARN(); printf("*** strtoumax" " modified its input ***\n" ); status = EXIT_FAILURE; strcpy(saved, sdp->nptr); } } /* 7.8.2.4 The wcstoimax and wcstoumax functions */ for ( i = 0; i < 64; ++i ) if ( (wnptr[i] = sdp->nptr[i]) == '\0' ) break; errno = 0; /* shouldn't be changed */ if ( (intmax = wcstoimax(wnptr, &wendptr, sdp->base)) != sdp->exp_val ) { int save = errno; printf("*** wcstoimax(%s,,%d) failed; should be: %" PRIdMAX", was: %"PRIdMAX" ***\n", sdp->nptr, sdp->base, sdp->exp_val, intmax ); status = EXIT_FAILURE; errno = save; } else if ( wendptr != wnptr + sdp->exp_len ) { int save = errno; printf("*** wcstoimax(%s,,%d) returned wrong endptr" " ***\n", sdp->nptr, sdp->base ); status = EXIT_FAILURE; errno = save; } if ( errno != 0 ) { printf("*** wcstoimax modified errno ***\n"); status = EXIT_FAILURE; } for ( i = 0; i < 64; ++i ) if ( wnptr[i] != sdp->nptr[i] ) { printf("*** wcstoimax modified its input ***\n" ); status = EXIT_FAILURE; for ( ; i < 64; ++i ) if ( (wnptr[i] = sdp->nptr[i]) == '\0' ) break; break; } else if ( wnptr[i] == '\0' ) break; if ( sdp->exp_val >= 0 ) /* else some sign extension */ { errno = 0; /* shouldn't be changed */ if ( (uintmax = wcstoumax(wnptr, &wendptr, sdp->base) ) != sdp->exp_val ) { int save = errno; printf("*** wcstoumax(%s,,%d) failed; " "should be: %"PRIuMAX", was: %"PRIuMAX " ***\n", sdp->nptr, sdp->base, sdp->exp_val, uintmax ); status = EXIT_FAILURE; errno = save; } else if ( wendptr != wnptr + sdp->exp_len ) { int save = errno; printf("*** wcstoumax(%s,,%d) returned wrong " "endptr ***\n", sdp->nptr, sdp->base ); status = EXIT_FAILURE; errno = save; } if ( errno != 0 ) { printf("*** wcstoumax modified errno ***\n"); status = EXIT_FAILURE; } for ( i = 0; i < 64; ++i ) if ( wnptr[i] != sdp->nptr[i] ) { printf("*** wcstoumax" " modified its input ***\n" ); status = EXIT_FAILURE; for ( ; i < 64; ++i ) if ( (wnptr[i] = sdp->nptr[i]) == '\0' ) break; break; } else if ( wnptr[i] == '\0' ) break; } /* tests for null endptr */ warned = 0; errno = 0; /* shouldn't be changed */ if ( (intmax = wcstoimax(wnptr, (wchar_t **)NULL, sdp->base)) != sdp->exp_val ) { int save = errno; WARN(); printf("*** wcstoimax(%s,NULL,%d) failed; should be: %" PRIdMAX", was: %"PRIdMAX" ***\n", sdp->nptr, sdp->base, sdp->exp_val, intmax ); status = EXIT_FAILURE; errno = save; } if ( errno != 0 ) { WARN(); printf("*** wcstoimax modified errno ***\n"); status = EXIT_FAILURE; } for ( i = 0; i < 64; ++i ) if ( wnptr[i] != sdp->nptr[i] ) { WARN(); printf("*** wcstoimax modified its input ***\n" ); status = EXIT_FAILURE; for ( ; i < 64; ++i ) if ( (wnptr[i] = sdp->nptr[i]) == '\0' ) break; break; } else if ( wnptr[i] == '\0' ) break; if ( sdp->exp_val >= 0 ) /* else some sign extension */ { errno = 0; /* shouldn't be changed */ if ( (uintmax = wcstoumax(wnptr, (wchar_t **)NULL, sdp->base ) ) != sdp->exp_val ) { int save = errno; WARN(); printf("*** wcstoumax(%s,NULL,%d) failed; " "should be: %"PRIuMAX", was: %"PRIuMAX " ***\n", sdp->nptr, sdp->base, sdp->exp_val, uintmax ); status = EXIT_FAILURE; errno = save; } if ( errno != 0 ) { WARN(); printf("*** wcstoumax modified errno ***\n"); status = EXIT_FAILURE; } for ( i = 0; i < 64; ++i ) if ( wnptr[i] != sdp->nptr[i] ) { WARN(); printf("*** wcstoumax" " modified its input ***\n" ); status = EXIT_FAILURE; for ( ; i < 64; ++i ) if ( (wnptr[i] = sdp->nptr[i]) == '\0' ) break; break; } else if ( wnptr[i] == '\0' ) break; } } /* 7.8.2.3 The strtoimax and strtoumax functions (continued) */ if ( (intmax = strtoimax("1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890", &endptr, 0 ) ) != INTMAX_MAX || errno != ERANGE ) { printf("*** strtoimax failed overflow test ***\n"); status = EXIT_FAILURE; } if ( (intmax = strtoimax("+1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890", &endptr, 0 ) ) != INTMAX_MAX || errno != ERANGE ) { printf("*** strtoimax failed +overflow test ***\n"); status = EXIT_FAILURE; } if ( (intmax = strtoimax("-1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890", &endptr, 0 ) ) != INTMAX_MIN || errno != ERANGE ) { printf("*** strtoimax failed -overflow test ***\n"); status = EXIT_FAILURE; } if ( (uintmax = strtoumax("1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890", &endptr, 0 ) ) != UINTMAX_MAX || errno != ERANGE ) { printf("*** strtoumax failed overflow test ***\n"); status = EXIT_FAILURE; } if ( (uintmax = strtoumax("+1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890", &endptr, 0 ) ) != UINTMAX_MAX || errno != ERANGE ) { printf("*** strtoumax failed +overflow test ***\n"); status = EXIT_FAILURE; } if ( (uintmax = strtoumax("-1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890", &endptr, 0 ) ) != UINTMAX_MAX || errno != ERANGE ) { printf("*** strtoumax failed -overflow test ***\n"); status = EXIT_FAILURE; } /* 7.8.2.4 The wcstoimax and wcstoumax functions (continued) */ #ifdef NO_INTERNAL_WCHAR printf("NO_INTERNAL_WCHAR\n"); #else if ( (intmax = wcstoimax(L"1234567890123456789012345678901234567890" L"1234567890123456789012345678901234567890" L"1234567890123456789012345678901234567890" L"1234567890123456789012345678901234567890" L"1234567890123456789012345678901234567890" L"1234567890123456789012345678901234567890", &wendptr, 0 ) ) != INTMAX_MAX || errno != ERANGE ) { printf("*** wcstoimax failed overflow test ***\n"); status = EXIT_FAILURE; } if ( (intmax = wcstoimax(L"+1234567890123456789012345678901234567890" L"1234567890123456789012345678901234567890" L"1234567890123456789012345678901234567890" L"1234567890123456789012345678901234567890" L"1234567890123456789012345678901234567890" L"1234567890123456789012345678901234567890", &wendptr, 0 ) ) != INTMAX_MAX || errno != ERANGE ) { printf("*** wcstoimax failed +overflow test ***\n"); status = EXIT_FAILURE; } if ( (intmax = wcstoimax(L"-1234567890123456789012345678901234567890" L"1234567890123456789012345678901234567890" L"1234567890123456789012345678901234567890" L"1234567890123456789012345678901234567890" L"1234567890123456789012345678901234567890" L"1234567890123456789012345678901234567890", &wendptr, 0 ) ) != INTMAX_MIN || errno != ERANGE ) { printf("*** wcstoimax failed -overflow test ***\n"); status = EXIT_FAILURE; } if ( (uintmax = wcstoumax(L"1234567890123456789012345678901234567890" L"1234567890123456789012345678901234567890" L"1234567890123456789012345678901234567890" L"1234567890123456789012345678901234567890" L"1234567890123456789012345678901234567890" L"1234567890123456789012345678901234567890", &wendptr, 0 ) ) != UINTMAX_MAX || errno != ERANGE ) { printf("*** wcstoumax failed overflow test ***\n"); status = EXIT_FAILURE; } if ( (uintmax = wcstoumax(L"+1234567890123456789012345678901234567890" L"1234567890123456789012345678901234567890" L"1234567890123456789012345678901234567890" L"1234567890123456789012345678901234567890" L"1234567890123456789012345678901234567890" L"1234567890123456789012345678901234567890", &wendptr, 0 ) ) != UINTMAX_MAX || errno != ERANGE ) { printf("*** wcstoumax failed +overflow test ***\n"); status = EXIT_FAILURE; } if ( (uintmax = wcstoumax(L"-1234567890123456789012345678901234567890" L"1234567890123456789012345678901234567890" L"1234567890123456789012345678901234567890" L"1234567890123456789012345678901234567890" L"1234567890123456789012345678901234567890" L"1234567890123456789012345678901234567890", &wendptr, 0 ) ) != UINTMAX_MAX || errno != ERANGE ) { printf("*** wcstoumax failed -overflow test ***\n"); status = EXIT_FAILURE; } #endif // NO_INTERNAL_WCHAR } #endif /* defined(INTMAX_MAX) */ if ( status != 0 ) printf("sitest failed.\n"); return status; } #endif��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/readme.txt���������������������������������������������������������������������������0000664�0000000�0000000�00000001443�13473601511�0015164�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������This directory contains test code for automatic regression testing of the CC65 compiler. /val - the bulk of tests are contained here, individual tests should exit with an exit code of EXIT_SUCCESS when they pass, or EXIT_FAILURE on error /ref - these tests produce output that must be compared with reference output /err - contains tests that MUST NOT compile /misc - a few tests that need special care of some sort to run the tests use "make" in this (top) directory, the makefile should exit with no error. when a test failed you can use "make continue" to run further tests -------------------------------------------------------------------------------- TODO: - reduce usage of "common.h" to a minimum - convert more tests from using reference output to returning an exit code �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/���������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0013740�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/8q.c�����������������������������������������������������������������������������0000664�0000000�0000000�00000002127�13473601511�0014436�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! solves the "8 queens" chess problem !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include <stdio.h> int up[15], down[15], rows[8], x[8]; void queens(int c); void print(void); int main(void) { int i; for (i = 0; i < 15; i++) up[i] = down[i] = 1; for (i = 0; i < 8; i++) rows[i] = 1; queens(0); return 0; } void queens(int c) { int r; for (r = 0; r < 8; r++) if (rows[r] && up[r-c+7] && down[r+c]) { rows[r] = up[r-c+7] = down[r+c] = 0; x[c] = r; if (c == 7) print(); else queens(c + 1); rows[r] = up[r-c+7] = down[r+c] = 1; } } void print(void) { int k; for (k = 0; k < 8; k++) { printf("%c", x[k]+'1'); if(k<7) printf(" "); } printf("\n"); } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/Makefile�������������������������������������������������������������������������0000664�0000000�0000000�00000004621�13473601511�0015403�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile for the regression tests that generate output which has to be # compared with reference output ifneq ($(shell echo),) CMD_EXE = 1 endif ifdef CMD_EXE S = $(subst /,\,/) EXE = .exe NULLDEV = nul: MKDIR = mkdir $(subst /,\,$1) RMDIR = -rmdir /s /q $(subst /,\,$1) DEL = del /f $(subst /,\,$1) else S = / EXE = NULLDEV = /dev/null MKDIR = mkdir -p $1 RMDIR = $(RM) -r $1 DEL = $(RM) $1 endif ifdef QUIET .SILENT: NULLERR = 2>$(NULLDEV) endif SIM65FLAGS = -x 200000000 CL65 := $(if $(wildcard ../../bin/cl65*),..$S..$Sbin$Scl65,cl65) SIM65 := $(if $(wildcard ../../bin/sim65*),..$S..$Sbin$Ssim65,sim65) WORKDIR = ..$S..$Stestwrk$Sref OPTIONS = g O Os Osi Osir Osr Oi Oir Or DIFF = $(WORKDIR)$Sbdiff$(EXE) CC = gcc CFLAGS = -O2 -Wall -W -Wextra -funsigned-char -fwrapv -fno-strict-overflow .PHONY: all clean SOURCES := $(wildcard *.c) REFS = $(SOURCES:%.c=$(WORKDIR)/%.ref) TESTS = $(foreach option,$(OPTIONS),$(SOURCES:%.c=$(WORKDIR)/%.$(option).6502.prg)) TESTS += $(foreach option,$(OPTIONS),$(SOURCES:%.c=$(WORKDIR)/%.$(option).65c02.prg)) all: $(REFS) $(TESTS) $(WORKDIR): $(call MKDIR,$(WORKDIR)) $(WORKDIR)/%.ref: %.c | $(WORKDIR) $(if $(QUIET),echo ref/$*.host) $(CC) $(CFLAGS) -o $(WORKDIR)/$*.host $< $(NULLERR) $(WORKDIR)$S$*.host > $@ $(DIFF): ../bdiff.c | $(WORKDIR) $(CC) $(CFLAGS) -o $@ $< # 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 \ $(WORKDIR)/switch.%.prg \ $(WORKDIR)/yacc.%.prg \ $(WORKDIR)/yaccdbg.%.prg: CC65FLAGS += -Wc --all-cdecl # "yaccdbg.c" includes "yacc.c". # yaccdbg's built files must depend on both of them. # $(WORKDIR)/yaccdbg.ref: yacc.c $(WORKDIR)/yaccdbg.%.prg: yacc.c define PRG_template $(WORKDIR)/%.$1.$2.prg: %.c $(WORKDIR)/%.ref $(DIFF) $(if $(QUIET),echo ref/$$*.$1.$2.prg) $(CL65) -t sim$2 $$(CC65FLAGS) -$1 -o $$@ $$< $(NULLERR) $(SIM65) $(SIM65FLAGS) $$@ > $(WORKDIR)/$$*.out $(DIFF) $(WORKDIR)/$$*.out $(WORKDIR)/$$*.ref endef # PRG_template $(foreach option,$(OPTIONS),$(eval $(call PRG_template,$(option),6502))) $(foreach option,$(OPTIONS),$(eval $(call PRG_template,$(option),65c02))) clean: @$(call RMDIR,$(WORKDIR)) @$(call DEL,$(SOURCES:.c=.o)) ���������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/array.c��������������������������������������������������������������������������0000664�0000000�0000000�00000002537�13473601511�0015231�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! basic array properties !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include <stdio.h> #ifndef NO_NEW_PROTOTYPES_FOR_OLD_FUNC_DECL int f(void); int g(int x[][4],int *y[]); #endif int x[3][4], *y[3]; main() { int z[3][4]; int i, j, *p; for (i = 0; i < 3; i++) { for (j = 0; j < 4; j++) x[i][j] = 1000*i + j; y[i] = x[i]; } f(); for (i = 0; i < 3; i++) { y[i] = p = &z[i][0]; for (j = 0; j < 4; j++) p[j] = x[i][j]; } g(z, y); return 0; } f() { int i, j; for (i = 0; i < 3; i++) for (j = 0; j < 4; j++) printf(" %d", x[i][j]); printf("\n"); for (i = 0; i < 3; i++) for (j = 0; j < 4; j++) printf(" %d", y[i][j]); printf("\n"); } g(x, y) int x[][4], *y[]; { int i, j; for (i = 0; i < 3; i++) for (j = 0; j < 4; j++) printf(" %d", x[i][j]); printf("\n"); for (i = 0; i < 3; i++) for (j = 0; j < 4; j++) printf(" %d", y[i][j]); printf("\n"); } �����������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/cc65070303.c���������������������������������������������������������������������0000664�0000000�0000000�00000001357�13473601511�0015327�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! !!ORIGIN!! testsuite !!LICENCE!! Public Domain !!AUTHOR!! */ #include <stdio.h> typedef signed int TypA[3]; typedef struct TypB { TypA Data[2]; } sTypB; sTypB Bs[10]; TypA * APtr; int main(int argc, char* argv[]) { Bs[7].Data[1][2]=11; APtr=&(Bs[7].Data[1]); printf("Hallo Welt! %i = %i \n",Bs[7].Data[1][2], (*APtr)[2] ); return 0; } /* ....gives test.c(20): Error: Incompatible pointer types for   APtr=&(Bs[7].Data[1]); My experience in C is very limited, but as this works both in MSVC and the 8 bit Z80 compiler i originally used, i guess its an bug in CC65. As a workaround, an typecast via  APtr=(TypA*)&(Bs[7].Data[1]); seems to work. greetings,    Andreas */���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/cc65080227.c���������������������������������������������������������������������0000664�0000000�0000000�00000001652�13473601511�0015333�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! !!ORIGIN!! testsuite !!LICENCE!! Public Domain !!AUTHOR!! */ #include <stdio.h> long a; /* must be static life */ long b; /* must be static life */ int main(void) { a = 0x00112200; /* must be immediate pattern is (1stBYTE == 4thBYTE) */ b = a; /* b is 0x11112200 ! */ printf("b (should be 0x00112200): %08lx\n",b); return 0; } /* [ command line ] cl65 -c -T -l -O test.c [ part of test.lst ] 000012r 1 ; b = a; 000012r 1 AD rr rr lda _a+2 000015r 1 85 rr sta sreg 000017r 1 AE rr rr ldx _a+1 00001Ar 1 AD rr rr lda _a 00001Dr 1 8D rr rr sta _b 000020r 1 8E rr rr stx _b+1 000023r 1 A4 rr ldy sreg 000025r 1 8C rr rr sty _b+2 000028r 1 8C rr rr sty _b+3 ; lost 4th BYTE ! */��������������������������������������������������������������������������������������cc65-2.18/test/ref/cc65080328.c���������������������������������������������������������������������0000664�0000000�0000000�00000000730�13473601511�0015331�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! !!ORIGIN!! testsuite !!LICENCE!! Public Domain !!AUTHOR!! */ /* The following code produces an 'Error: Incompatible pointer types' at the last line when compiling with snapshot-2.11.9.20080316 without optimizations. If I remove the struct inside f() it compiles fine ?!? Best, Oliver */ #include <stdio.h> void f(void){struct{int i;}d;} struct{void(*p)(void);}s={f}; int main(void) { printf("it works :)\n"); return 0; } ����������������������������������������cc65-2.18/test/ref/cc65090111.c���������������������������������������������������������������������0000664�0000000�0000000�00000001205�13473601511�0015316�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! !!ORIGIN!! testsuite !!LICENCE!! Public Domain !!AUTHOR!! */ #include <stdio.h> /* cc65 doesn't compile this, if i use the "-O"-option. but it works with "while(!0)"; instead of "for(;;);" i'm using cl65 V2.12.9 win ---- #include <stdint.h> int main(void) { static uint8_t x = 0; static uint8_t y = 0; for (x = 0; x < 16; ++x) { y = y + 1; } for(;;); } */ #include <stdint.h> int test(void) { static uint8_t x = 0; static uint8_t y = 0; for (x = 0; x < 16; ++x) { y = y + 1; } for(;;); } int main(void) { printf("it works :)\n"); return 0; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/cc65090124.c���������������������������������������������������������������������0000664�0000000�0000000�00000001730�13473601511�0015325�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! !!ORIGIN!! testsuite !!LICENCE!! Public Domain !!AUTHOR!! */ #include <stdio.h> /* there is a bug in the preprocessor (i think) ... the following works (compiles) correctly: unsigned long fs,fd,a; unsigned long _func(unsigned long x,unsigned long y) { return 0; } int main(void) { fs=(_func((fd/a),(_func(2,0x0082c90f)))); } now if i wrap _func into a macro like this: #define func(x,y) _func(x,y) int main(void) { fs=(func((fd/a),(func(2,0x0082c90f)))); } i get "Error: ')' expected" on that line. (this is with the snapshot, freshly compiled 5 minutes ago) */ unsigned long fs,fd,a; unsigned long _func1(unsigned long x,unsigned long y) { return 0; } int test1(void) { fs=(_func1((fd/a),(_func1(2,0x0082c90f)))); } #define func(x,y) _func1(x,y) int test2(void) { fs=(func((fd/a),(func(2,0x0082c90f)))); } int main(void) { printf("it works :)\n"); return 0; } ����������������������������������������cc65-2.18/test/ref/cc65090726.c���������������������������������������������������������������������0000664�0000000�0000000�00000001643�13473601511�0015340�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! !!ORIGIN!! testsuite !!LICENCE!! Public Domain !!AUTHOR!! */ #include "common.h" struct Record { struct Record *PtrComp; int x; }; typedef struct Record RecordType; typedef RecordType *RecordPtr; void Proc3(RecordPtr *PtrParOut) { /* whatever */ } void Proc1(RecordPtr PtrParIn) { #define NextRecord (*(PtrParIn->PtrComp)) Proc3((RecordPtr *)NextRecord.PtrComp); Proc3(&NextRecord.PtrComp); Proc3(&PtrParIn->PtrComp->PtrComp); #ifdef CAST_STRUCT_PTR Proc3((RecordPtr *) PtrParIn->PtrComp->PtrComp); Proc3((RecordPtr *) (*(PtrParIn->PtrComp)).PtrComp); Proc3((RecordPtr *) NextRecord.PtrComp); #else Proc3(PtrParIn->PtrComp->PtrComp); Proc3((*(PtrParIn->PtrComp)).PtrComp); Proc3(NextRecord.PtrComp); #endif #undef NextRecord } int main(void) { printf("it works :)\n"); return 0; } ���������������������������������������������������������������������������������������������cc65-2.18/test/ref/cc65090910.c���������������������������������������������������������������������0000664�0000000�0000000�00000001131�13473601511�0015323�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! optimizer bug !!ORIGIN!! testsuite !!LICENCE!! Public Domain !!AUTHOR!! Oliver Schmidt */ #include <stdio.h> /* After spending a "little" time I finally succeeded in isolating an (maybe THE) optimizer bug causing Contiki to fail. From my user perspective it is very interesting that the bug shows up with compiler option -O but does _not_ show up with -Oi. */ unsigned htons(unsigned val) { return (((unsigned) (val)) << 8) | (((unsigned) (val)) >> 8); } int main(void) { printf("%x -> %x\n", 0x1234, htons(0x1234) & 0xffff); return 0; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/cc65090913.c���������������������������������������������������������������������0000664�0000000�0000000�00000001257�13473601511�0015337�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! optimizer bug !!ORIGIN!! testsuite !!LICENCE!! Public Domain !!AUTHOR!! Oliver Schmidt */ /* > I found the problem and fixed it. cc65 treated a label as a statement, but > the standard says, that a label is part of a statement. In a loop without > curly braces like > > while (foo < bar) > label: ++foo; > > the following statement is the one that is looped over - and because cc65 > treated just the label as a statement, it created code that looped forever. */ #include <stdio.h> int foo=0,bar=2; int main(void) { while(foo<bar) label: ++foo; printf("foo: %d bar: %d\n",foo,bar); return 0; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/cc65091007.c���������������������������������������������������������������������0000664�0000000�0000000�00000000665�13473601511�0015334�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! !!ORIGIN!! testsuite !!LICENCE!! Public Domain !!AUTHOR!! Johan Kotlinski */ #include <stdio.h> /* This produces the compiler error "test.c(9): Error: Assignment to const" Shouldn't be an error, should it? baz is const, bar isn't. */ typedef struct { char foo; } Bar; int main() { Bar bar; Bar* const baz = &bar; baz->foo = 1; printf("it works :)\n"); return 0; } ���������������������������������������������������������������������������cc65-2.18/test/ref/cc65091022.c���������������������������������������������������������������������0000664�0000000�0000000�00000000544�13473601511�0015325�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! !!ORIGIN!! testsuite !!LICENCE!! Public Domain !!AUTHOR!! Johan Kotlinski */ #include <stdio.h> /* ...gives "test.c(2): Error: Variable 'foo' has unknown size" using -Cl. Is it really unknown? cc65 V2.13.0, SVN version: 4384 */ int main() { char foo[] = { 0 }; printf("it works :)\n"); return 0; } ������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/cc65101102.c���������������������������������������������������������������������0000664�0000000�0000000�00000002406�13473601511�0015313�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! !!ORIGIN!! testsuite !!LICENCE!! Public Domain !!AUTHOR!! Marc 'BlackJack' Rintsch */ /* Compiler is build from cc65-snapshot-2.13.9.20101031 sources. Expected results and also what I get from this without any optimisations are: 48663 and 49218 When I turn on ''-O'': 58096 and 58096. After swapping the two variable declaration lines in 'calculate_checksum()' the results are correct with ''-O''. But with ''--O --static-locals'' the results are incorrect again (31757 and 15408). ''--static-locals'' alone works though. */ #include <stdio.h> #include <stdint.h> // uint16_t __fastcall__ calculate_checksum(uint8_t *block); uint8_t block[256]; uint16_t calculate_checksum(uint8_t *block) { uint16_t i, result = 0xffff; uint8_t j; for (i = 0; i < 256; ++i) { result ^= block[i] << 8; for (j = 0; j < 8; ++j) { if (result & (1 << 15)) { result = (result << 1) ^ 0x1021; } else { result <<= 1; } } } return ~result; } int main(void) { uint16_t i; printf("zeroes: %u\n", calculate_checksum(block)); for (i = 0; i < 256; ++i) block[i] = i; printf("0..255: %u\n", calculate_checksum(block)); return 0; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/cc65101209.c���������������������������������������������������������������������0000664�0000000�0000000�00000001101�13473601511�0015312�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! mod operator bug !!ORIGIN!! testsuite !!LICENCE!! Public Domain !!AUTHOR!! marcas */ #include <stdlib.h> #include <stdio.h> int main(void) { int tmp; for (tmp = 0; tmp<=12345; tmp++) if (!(tmp%1000)) printf("%d mod 1000 is %d\n", tmp, tmp%1000); return 0; } /* results in (vice x64) 0 mod 1000 is 0 232 mod 1000 is 0 1000 mod 1000 is 0 Interesting: 1000 = $3E8 232 = $E8 So testing with 999 gives: 0 mod 999 is 0 231 mod 999 is 0 999 mod 999 is 0 This seems to be systematic. */���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/cc65101216.c���������������������������������������������������������������������0000664�0000000�0000000�00000000533�13473601511�0015320�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! division bug !!ORIGIN!! testsuite !!LICENCE!! Public Domain !!AUTHOR!! Stefan Wessels */ /* The output from the code below is: a / b = 6 Shouldn't that be 0? */ #include <stdio.h> #define b 10000 char a; int main() { char c; a = 100; c = a / b; printf("a / b = %d", c); return 0; }���������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/cc65110210.c���������������������������������������������������������������������0000664�0000000�0000000�00000001667�13473601511�0015323�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! linker bug !!ORIGIN!! testsuite !!LICENCE!! public domain */ /* with SVN version: 4973M $ cl65 -v -o test.prg tests/cc65110210.c Opened include file '/usr/local/lib/cc65/include/stdio.h' Opened include file '/usr/local/lib/cc65/include/stddef.h' Opened include file '/usr/local/lib/cc65/include/stdarg.h' Opened include file '/usr/local/lib/cc65/include/limits.h' 0 errors, 0 warnings Opened output file 'tests/cc65110210.s' Wrote output to 'tests/cc65110210.s' Closed output file 'tests/cc65110210.s' cl65: Subprocess 'ld65' aborted by signal 11 */ /* #define STANDALONE */ #include <stdio.h> #include <limits.h> #ifdef STANDALONE #define NO_IMPLICIT_FUNCPTR_CONV #define OPENTEST() #define CLOSETEST() #else #endif #ifdef NO_IMPLICIT_FUNCPTR_CONV void (*p1func)(void); #else void (*p1func)(); #endif void func(void) { (*p1func)(); } int main(void) { printf("it works :)\n"); return (0); } �������������������������������������������������������������������������cc65-2.18/test/ref/cc65110211.c���������������������������������������������������������������������0000664�0000000�0000000�00000002030�13473601511�0015305�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! unreachable code related bug !!ORIGIN!! Testsuite !!LICENCE!! Public Domain */ /* test2 and test3 will result in an endless loop (SVN version: 4974M) */ #include <stdio.h> #define OPENTEST() #define CLOSETEST() static char upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; int test1(void) { int res; unsigned char *p; p = upper; res = 0; while(*p) { if(*p < 0) { res = 1; } p++; } printf("test1:ok\n"); return res; } int test2(void) { int res; unsigned char *p; p = upper; res = 0; while(*p) { if(*p++ < 0) { res = 1; } } printf("test2:ok\n"); return res; } int test3(void) { int res; unsigned char *p; p = upper; res = 0; while(*p) { if(*++p < 0) { res = 1; } } printf("test3:ok\n"); return res; } int main(int n,char **args) { test1(); test2(); test3(); printf("it works :)\n"); return 0; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/cf.c�����������������������������������������������������������������������������0000664�0000000�0000000�00000007662�13473601511�0014507�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! print character frequencies !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ /* cf - print character frequencies */ #include "common.h" #include <stdlib.h> #include <stdio.h> #include <ctype.h> FILE *in; #define INFILE "cf.in" #define GETCHAR() fgetc(in) #ifndef NO_FLOATS float f[0x100]; #else signed f[0x100]; #endif #ifdef NO_OLD_FUNC_DECL int main(int argc,char **argv) #else main(argc, argv) int argc; char *argv[]; #endif { int i, c, nc; #ifndef NO_FLOATS float cutoff, atof(); #else signed cutoff; #endif in = fopen(INFILE, "rb"); if (in == NULL) { return EXIT_FAILURE; } if (argc <= 1) #ifndef NO_FLOATS cutoff = 0.0; #else cutoff = 0; #endif else #ifndef NO_FLOATS cutoff = atof(argv[1])/100; #else cutoff = atoi(argv[1])/100; #endif for (i = 0; i < 0x100; ) { #ifndef NO_FLOATS f[i++] = 0.0; #else f[i++] = 0; #endif } printf("input:\n\n"); nc = 0; while ((c = GETCHAR()) != -1) { /* printf("[%02x]",c); */ printf("%c",c); f[c] += 1; nc++; } printf("\n\ncount: %d\n\n",nc); /* now try to print a report in a way so that the order is somewhat independent from the target character set */ printf("a-z char:freq\n\n"); /* first round ... lowercase characters */ for (i = 0; i < 0x100; ++i) { if ((f[i]) && ((f[i]/nc) >= cutoff)) { if ((i >= 'a') && (i <= 'z')) { printf("%c", i); #ifndef NO_FLOATS printf(":%.1f\n", 100*f[i]/nc); #else printf(":%d\n", 100*f[i]/nc); #endif f[i]=0; } } } printf("A-Z char:freq\n\n"); /* second round ... uppercase characters */ for (i = 0; i < 0x100; ++i) { if ((f[i]) && ((f[i]/nc) >= cutoff)) { if ((i >= 'A') && (i <= 'Z')) { printf("%c", i); #ifndef NO_FLOATS printf(":%.1f\n", 100*f[i]/nc); #else printf(":%d\n", 100*f[i]/nc); #endif f[i]=0; } } } printf("0-9 char:freq\n\n"); /* third round ... numbers */ for (i = 0; i < 0x100; ++i) { if ((f[i]) && ((f[i]/nc) >= cutoff)) { if ((i >= '0') && (i <= '9')) { printf("%c", i); #ifndef NO_FLOATS printf(":%.1f\n", 100*f[i]/nc); #else printf(":%d\n", 100*f[i]/nc); #endif f[i]=0; } } } printf("isprint char:freq\n\n"); /* second last round ... remaining printable characters */ for (i = 0; i < 0x100; ++i) { if ((f[i]) && ((f[i]/nc) >= cutoff)) { if(isprint(i)) { printf("%c", i); #ifndef NO_FLOATS printf(":%.1f\n", 100*f[i]/nc); #else printf(":%d\n", 100*f[i]/nc); #endif f[i]=0; } } } printf("rest char:freq\n\n"); /* last round ... remaining non printable characters */ for (i = 0; i < 0x100; ++i) { if ((f[i]) && ((f[i]/nc) >= cutoff)) { if(i=='\n') { printf("newline"); } else { printf("%03o", i); } #ifndef NO_FLOATS printf(":%.1f\n", 100*f[i]/nc); #else printf(":%d\n", 100*f[i]/nc); #endif } } fclose(in); return 0; } ������������������������������������������������������������������������������cc65-2.18/test/ref/cf.in����������������������������������������������������������������������������0000775�0000000�0000000�00000001734�13473601511�0014670�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������start cf.input > The sky above the port was the color of television, tuned to a dead channel. "It's not like I'm using," Case heard someone say, as he shouldered his way through the crowd around the door of the Chat. "It's like my body's developed this massive drug deficiency." It was a Sprawl voice and a Sprawl joke. The Chatsubo was a bar for professional expatriates; you could drink there for a week and never hear two words in Japanese. Ratz was tending bar, his prosthetic arm jerking monotonously as he filled a tray of glasses with draft Kirin. He saw Case and smiled, his teeth a web work of East European steel and brown decay. Case found a place at the bar, between the unlikely tan on one of Lonny Zone's whores and the crisp naval uniform of a tall African whose cheekbones were ridged with Joe boys," Ratz said, shoving a draft across the bar with his good hand. "Maybe some business with you, Case?" Case shrugged. The girl to his right giggled and nudged < end cf.input ������������������������������������cc65-2.18/test/ref/charconst.c����������������������������������������������������������������������0000664�0000000�0000000�00000001704�13473601511�0016072�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! check if character constants are translated correctly !!ORIGIN!! cc65 bug report !!LICENCE!! Public Domain */ #include "common.h" #include <limits.h> #include <ctype.h> void backslash(unsigned char c) { printf("%c : ",c); switch (c) { case 'b': c = '\b'; case 'f': c = '\f'; case 'n': c = '\n'; case 'r': c = '\r'; case 't': c = '\t'; case 'v': #ifndef NO_BACKSLASH_V c = '\v'; #else c = 0x0b; #endif } if(!isprint(c)) { printf("ok.\n"); } else { printf("failed.\n"); } } void testbackslash(void) { backslash('b'); backslash('f'); backslash('n'); backslash('r'); backslash('t'); backslash('v'); } int main(void) { testbackslash(); return 0; } ������������������������������������������������������������cc65-2.18/test/ref/charset.c������������������������������������������������������������������������0000664�0000000�0000000�00000006703�13473601511�0015543�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! basic ASCII character test !!ORIGIN!! testsuite !!LICENCE!! Public Domain !!AUTHOR!! Groepaz/Hitmen */ #include <stdio.h> #if 0 /* this kind of line-continuation for strings doesnt work properly for cc65 */ const unsigned char characters[]={ /*0123456789abcdef0123456789abcdef*/ /* iso646-us control-characters */ " " /* 00-1f */ /* iso646-us printable characters */ " !\"#$%&'()*+,-./" /* 20-2f !"#$%&'()*+,-./ */ "0123456789" /* 30-39 0123456789 */ ":;<=>?@" /* 3a-40 :;<=>?@ */ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" /* 41-5a A-Z */ "[\\]^_`" /* 5b-60 [\]^_` */ "abcdefghijklmnopqrstuvwxyz" /* 61-7a a-z */ "{|}~ " /* 7b-7f {|}~ */ /* iso8859-15 extended characters */ }; #endif const unsigned char characters[]={ /*0123456789abcdef0123456789abcdef*/ /* iso646-us control-characters */ /* 00-1f */ 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,0x00,0x00,0x00,0x00, /* iso646-us printable characters */ /* 20-2f !"#$%&'()*+,-./ */ ' ','!','"','#','$','%','&','\'','(',')','*','+',',','-','.','/', /* 30-39 0123456789 */ '0','1','2','3','4','5','6','7','8','9', /* 3a-40 :;<=>?@ */ ':',';','<','=','>','?','@', /* 41-5a A-Z */ 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z', /* 5b-60 [\]^_` */ '[','\\',']','^','_','`', /* 61-7a a-z */ 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z', /* 7b-7f {|}~ */ '{','|','}','~',' ' /* iso8859-15 extended characters */ }; void printchars(unsigned char a,unsigned char b){ for(b++;a!=b;a++) /* printf("%02x ",a); */ /* printf("%02x ",characters[a]); */ printf("%c",characters[a]); printf("\n"); } int main(void) { printf("characters:\n\n"); printchars(0x61,0x7a); printchars(0x41,0x5a); printf("numbers:\n\n"); printchars(0x30,0x39); printf("other:\n\n"); printchars(0x20,0x2f); /*printchars(0x3a,0x40);*/ printchars(0x3a,0x3f); /*printchars(0x5b,0x60);*/ /*printchars(0x7b,0x7f);*/ printf("\n\n"); printf("slash: '%c'\n",'/'); printf("backslash: '%c'\n",'\\'); printf("curly braces open: '%c'\n",'{'); printf("curly braces close: '%c'\n",'}'); printf("square braces open: '%c'\n",'['); printf("square braces close: '%c'\n",']'); printf("underscore: '%c'\n",'_'); printf("tilde: '%c'\n",'~'); printf("pipe: '%c'\n",'|'); printf("apostroph: '%c'\n",'\''); printf("single quote '%c'\n",'`'); printf("xor '%c'\n",'^'); printf("at '%c'\n",'@'); return 0; } �������������������������������������������������������������cc65-2.18/test/ref/common.h�������������������������������������������������������������������������0000664�0000000�0000000�00000001012�13473601511�0015373�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ #include <stdio.h> #include <stdlib.h> #define NO_OLD_FUNC_DECL #define NO_TYPELESS_INT #define NO_TYPELESS_INT_PTR #define MAIN_RETURNS_INT #define NO_IMPLICIT_FUNC_PROTOTYPES #define NO_FLOATS #define NO_WCHAR #define NO_EMPTY_FUNC_ARGS #define NO_SLOPPY_STRUCT_INIT #define NO_FUNCS_TAKE_STRUCTS #define NO_FUNCS_RETURN_STRUCTS #define CAST_STRUCT_PTR #define NO_TYPELESS_STRUCT_PTR #define NO_IMPLICIT_FUNCPTR_CONV #define SIZEOF_INT_16BIT #define SIZEOF_LONG_32BIT #define UNSIGNED_CHARS #define UNSIGNED_BITFIELDS ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/cvt.c����������������������������������������������������������������������������0000664�0000000�0000000�00000003101�13473601511�0014673�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! type conversion !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include "common.h" #include <stdio.h> signed char c; signed short s; signed int i; signed long int l; unsigned char C; unsigned short S; unsigned int I; unsigned long int L; #ifdef NO_FLOATS signed long f; signed long d; signed long D; #else float f; double d; long double D; #endif void *p; void (*P)(void); void print(void) { #ifdef NO_FLOATS printf("%d %d %d %ld %u %u %u %lu %ld.000000 %ld.000000 %ld.000000\n",c,s,i,l,C,S,I,L,f,d,D); #else printf("%d %d %d %ld %u %u %u %lu %f %f %lf \n",c,s,i,l,C,S,I,L,f,d,D ); #endif } main() { c= 1; s=c;i=c;l=c;C=c;S=c;I=c;L=c; f=c;d=c;D=c; print(); s= 2; c=s; i=s;l=s;C=s;S=s;I=s;L=s; f=s;d=s;D=s; print(); i= 3; c=i;s=i; l=i;C=i;S=i;I=i;L=i; f=i;d=i;D=i; print(); l= 4; c=l;s=l;i=l; C=l;S=l;I=l;L=l; f=l;d=l;D=l; print(); C= 5; c=C;s=C;i=C;l=C; S=C;I=C;L=C; f=C;d=C;D=C; print(); S= 6; c=S;s=S;i=S;l=S;C=S; I=S;L=S; f=S;d=S;D=S; print(); I= 7; c=I;s=I;i=I;l=I;C=I;S=I; L=I; f=I;d=I;D=I; print(); L= 8; c=L;s=L;i=L;l=L;C=L;S=L;I=S; f=L;d=L;D=L; print(); f= 9; c=f;s=f;i=f;l=f;C=f;S=f;I=f;L=f; d=f;D=f; print(); d=10; c=d;s=d;i=d;l=d;C=d;S=d;I=d;L=d;f=d; D=d; print(); D=11; c=D;s=D;i=D;l=D;C=D;S=D;I=D;L=D;f=D;d=D; print(); p=0; p=0L; p=0U; p=0UL; p=P; P=0; P=0L; P=0U; P=0UL; P=p; return 0; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/dijkstra.c�����������������������������������������������������������������������0000664�0000000�0000000�00000017762�13473601511�0015734�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! Dijkstras Algorithm !!ORIGIN!! testsuite !!LICENCE!! Public Domain !!AUTHOR!! Groepaz/Hitmen */ #include <stdio.h> #include <stdlib.h> #ifndef NULL #define NULL ((void*)0) #endif #define DIJKSTRA_INFINITY (0xffff) #define DIJKSTRA_FLAG_UNVISITED (0x0) /* #define DIJKSTRA_FLAG_OPEN (0x1) */ #define DIJKSTRA_FLAG_CLOSED (0x2) typedef struct _DIJKSTRA_EDGE { struct _DIJKSTRA_NODE *NEXTNODE; unsigned short DISTANCE; } DIJKSTRA_EDGE; typedef struct _DIJKSTRA_NODE { DIJKSTRA_EDGE *EDGES; unsigned char TAG; unsigned char FLAG; unsigned short MINDIST; struct _DIJKSTRA_NODE *PREVIOUS; } DIJKSTRA_NODE; /* init with graph, startnode, working-array */ void Dijkstra_Init(const DIJKSTRA_NODE *graph,DIJKSTRA_NODE *start,DIJKSTRA_NODE *nodes); /* call main algo with working-array */ void Dijkstra_Search(DIJKSTRA_NODE *nodes); /* print path, call with working-array, endnode */ void Dijkstra_Path(DIJKSTRA_NODE *nodes,DIJKSTRA_NODE *end); /* print table, call with working-array, current node */ void Dijkstra_Table(DIJKSTRA_NODE *nodes,DIJKSTRA_NODE *current); /* internally used routines */ unsigned short Dijkstra_Distance(DIJKSTRA_NODE *currnode,DIJKSTRA_NODE *nextnode); void Dijkstra_Relax(DIJKSTRA_NODE *currnode,DIJKSTRA_NODE *nextnode); DIJKSTRA_NODE *Dijkstra_NextCheapest(DIJKSTRA_NODE *graph); unsigned short Dijkstra_CountUnvisited(DIJKSTRA_NODE *graph); /* define to get printed info as the algorithm proceeds */ #define DIJKSTRA_PRINTDEBUG /* the working array */ DIJKSTRA_NODE mynodes[0x10]; /* test-network data (mypoints and myedges) */ const DIJKSTRA_EDGE myedges_A[]={ {&mynodes[1],1}, {NULL} }; const DIJKSTRA_EDGE myedges_B[]={ {&mynodes[0],1}, {&mynodes[2],2}, {&mynodes[3],1}, {NULL} }; const DIJKSTRA_EDGE myedges_C[]={ {&mynodes[1],2}, {&mynodes[5],1}, {NULL} }; const DIJKSTRA_EDGE myedges_D[]={ {&mynodes[1],1}, {&mynodes[4],1}, {NULL} }; const DIJKSTRA_EDGE myedges_E[]={ {&mynodes[6],1}, {NULL} }; const DIJKSTRA_EDGE myedges_F[]={ {&mynodes[7],1}, {NULL} }; const DIJKSTRA_EDGE myedges_G[]={ {&mynodes[8],1}, {&mynodes[7],4}, {NULL} }; const DIJKSTRA_EDGE myedges_H[]={ {&mynodes[9],1}, {&mynodes[6],4}, {NULL} }; const DIJKSTRA_EDGE myedges_I[]={ {&mynodes[10],5}, {NULL} }; const DIJKSTRA_EDGE myedges_J[]={ {&mynodes[10],1}, {NULL} }; const DIJKSTRA_EDGE myedges_K[]={ {&mynodes[11],1}, {NULL} }; const DIJKSTRA_EDGE myedges_L[]={ {&mynodes[10],1}, {NULL} }; const DIJKSTRA_NODE mypoints[]={ {(DIJKSTRA_EDGE *)&myedges_A[0],'A'}, {(DIJKSTRA_EDGE *)&myedges_B[0],'B'}, {(DIJKSTRA_EDGE *)&myedges_C[0],'C'}, {(DIJKSTRA_EDGE *)&myedges_D[0],'D'}, {(DIJKSTRA_EDGE *)&myedges_E[0],'E'}, {(DIJKSTRA_EDGE *)&myedges_F[0],'F'}, {(DIJKSTRA_EDGE *)&myedges_G[0],'G'}, {(DIJKSTRA_EDGE *)&myedges_H[0],'H'}, {(DIJKSTRA_EDGE *)&myedges_I[0],'I'}, {(DIJKSTRA_EDGE *)&myedges_J[0],'J'}, {(DIJKSTRA_EDGE *)&myedges_K[0],'K'}, {(DIJKSTRA_EDGE *)&myedges_L[0],'L'}, {NULL} }; /* * initialize working-array */ void Dijkstra_Init(const DIJKSTRA_NODE *graph,DIJKSTRA_NODE *start,DIJKSTRA_NODE *nodes) { while(graph->EDGES!=NULL) { nodes->EDGES=graph->EDGES; nodes->TAG=graph->TAG; nodes->FLAG=DIJKSTRA_FLAG_UNVISITED; nodes->MINDIST=DIJKSTRA_INFINITY; nodes->PREVIOUS=NULL; graph++;nodes++; } /* start->FLAG=DIJKSTRA_FLAG_OPEN; start->PREVIOUS=NULL; */ start->MINDIST=0; } /* * compute the distance between two Nodes in the Graph */ unsigned short Dijkstra_Distance(DIJKSTRA_NODE *currnode,DIJKSTRA_NODE *nextnode){ DIJKSTRA_EDGE *edge; edge=currnode->EDGES; while(edge!=NULL) { if(edge->NEXTNODE == nextnode){ return(edge->DISTANCE); } edge++; } return(DIJKSTRA_INFINITY); } /* * 'relax' one node against another */ void Dijkstra_Relax(DIJKSTRA_NODE *currnode,DIJKSTRA_NODE *nextnode){ unsigned short newdist; #ifdef DIJKSTRA_PRINTDEBUG printf("relax >%c< to >%c<\n",currnode->TAG,nextnode->TAG); #endif newdist=currnode->MINDIST+Dijkstra_Distance(currnode,nextnode); if((nextnode->MINDIST)>(newdist)){ nextnode->MINDIST=newdist; nextnode->PREVIOUS=currnode; } } /* * find the yet unprocessed Node with the currently * smallest estimated MINDIST */ DIJKSTRA_NODE *Dijkstra_NextCheapest(DIJKSTRA_NODE *graph){ unsigned short mindist; DIJKSTRA_NODE *node; node=NULL; mindist=DIJKSTRA_INFINITY; while(graph->EDGES!=NULL) { if(graph->FLAG!=DIJKSTRA_FLAG_CLOSED){ if(!(mindist<graph->MINDIST)){ mindist=graph->MINDIST; node=graph; } } graph++; } #ifdef DIJKSTRA_PRINTDEBUG if(node!=NULL) printf("next cheapest Node: >%c<\n",node->TAG); #endif return(node); } /* * count number of Nodes that are left for processing */ unsigned short Dijkstra_CountUnvisited(DIJKSTRA_NODE *graph){ unsigned short num; num=0; while(graph->EDGES!=NULL) { if(graph->FLAG!=DIJKSTRA_FLAG_CLOSED){ num++; } graph++; } return(num); } /* * Dijkstra-Algorithmus main processing */ void Dijkstra_Search(DIJKSTRA_NODE *graph){ DIJKSTRA_NODE *currnode,*nextnode; DIJKSTRA_EDGE *edge; currnode=graph; while(Dijkstra_CountUnvisited(graph)>0){ edge=currnode->EDGES; while(edge->NEXTNODE!=NULL){ nextnode=edge->NEXTNODE; if(nextnode->FLAG!=DIJKSTRA_FLAG_CLOSED){ /* nextnode->FLAG=DIJKSTRA_FLAG_OPEN; */ Dijkstra_Relax(currnode,nextnode); #ifdef DIJKSTRA_PRINTDEBUG Dijkstra_Table(graph,currnode); #endif } edge++; } currnode=Dijkstra_NextCheapest(graph); currnode->FLAG=DIJKSTRA_FLAG_CLOSED; } } /* * print the Path from start Node to one other Node */ void Dijkstra_Path(DIJKSTRA_NODE *graph,DIJKSTRA_NODE *end){ DIJKSTRA_NODE *currnode,*nextnode; printf("Path from >%c< to >%c< : ",end->TAG,graph->TAG); currnode=end; while(currnode->PREVIOUS!=NULL){ printf(">%c< ",currnode->TAG); currnode=currnode->PREVIOUS; } printf(">%c<\n",currnode->TAG); } /* * print working-array as a table */ void Dijkstra_Table(DIJKSTRA_NODE *graph,DIJKSTRA_NODE *current){ DIJKSTRA_NODE *g; printf("----------------------\n"); printf("Node |"); g=graph;while(g->EDGES!=NULL) { printf("-->%c<-|",g->TAG); g++; } printf("\n"); printf("MinDist |"); g=graph;while(g->EDGES!=NULL) { printf(" %5u|",g->MINDIST); g++; } printf("\n"); printf("Flag |"); g=graph;while(g->EDGES!=NULL) { switch(g->FLAG){ /* case DIJKSTRA_FLAG_OPEN: printf("opened|"); break; */ case DIJKSTRA_FLAG_CLOSED: printf("closed|"); break; default: if(g->MINDIST!=DIJKSTRA_INFINITY){ printf("opened|"); } else { printf("------|"); } break; } g++; } printf("\n"); printf("Previous|"); g=graph;while(g->EDGES!=NULL) { if(g->PREVIOUS==NULL) printf("------|"); else printf(" (%c) |",g->PREVIOUS->TAG); g++; } printf("\n"); printf("----------------------\n"); } int main(void) { /* init with graph, startnode, working-array */ Dijkstra_Init(&mypoints[0],&mynodes[0],&mynodes[0]); /* call main algo with working-array */ Dijkstra_Search(&mynodes[0]); /* print table, call with working-array, endnode */ Dijkstra_Table(&mynodes[0],&mynodes[11]); /* print path, call with working-array, endnode */ Dijkstra_Path(&mynodes[0],&mynodes[11]); return 0; } ��������������cc65-2.18/test/ref/divmod.c�������������������������������������������������������������������������0000664�0000000�0000000�00000001460�13473601511�0015367�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! div/mod test !!ORIGIN!! !!LICENCE!! public domain */ #include <stdio.h> void printc(signed char a,signed char b){ signed char x=a/b,y=a%b,z=a*b; printf("%3d,%3d is %3d,%3d,%3d\n",a,b,x,y,z); } void prints(short a,short b){ short x=a/b,y=a%b,z=a*b; printf("%3d,%3d is %3d,%3d,%3d\n",a,b,x,y,z); } void printl(long a,long b){ long x=a/b,y=a%b,z=a*b; printf("%3ld,%3ld is %3ld,%3ld,%3ld\n",a,b,x,y,z); } int main(void) { printl( 3,-2); printl(-3,-2); printl(-3, 2); printl( 3, 2); printf("-\n"); prints( 3,-2); prints(-3,-2); prints(-3, 2); prints( 3, 2); printf("-\n"); printc( 3,-2); printc(-3,-2); printc(-3, 2); printc( 3, 2); return 0; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/goto.c���������������������������������������������������������������������������0000664�0000000�0000000�00000001055�13473601511�0015055�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <stdio.h> int main () { char a[200] = "xyz"; int ctr = 0; start: a[ctr] = ctr + 65; goto second; { char b[64] = "xxx"; first: b[0] = ctr + 97; goto safe; b[0] = 'Z'; safe: printf ("%c%c", a[0], b[0]); if (ctr++ > 20) goto end; else goto second; } { char c[100] = "aaa"; second:; c[0] = '1'; c[99] = '2'; goto first; } end: a[ctr] = '\n'; printf ("\n%s\n", a); return 0; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/hanoi.c��������������������������������������������������������������������������0000664�0000000�0000000�00000004405�13473601511�0015205�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! solves the "towers of hanoi" problem !!ORIGIN!! BYTE UNIX Benchmarks !!LICENCE!! Public Domain */ /******************************************************************************* * The BYTE UNIX Benchmarks - Release 3 * Module: hanoi.c SID: 3.3 5/15/91 19:30:20 * ******************************************************************************* * Bug reports, patches, comments, suggestions should be sent to: * * Ben Smith, Rick Grehan or Tom Yager * ben@bytepb.byte.com rick_g@bytepb.byte.com tyager@bytepb.byte.com * ******************************************************************************* * Modification Log: * $Header: hanoi.c,v 3.5 87/08/06 08:11:14 kenj Exp $ * August 28, 1990 - Modified timing routines (ty) * ******************************************************************************/ #define VERBOSE /*#define USECMDLINE*/ #include <stdio.h> #include <stdlib.h> unsigned short iter = 0; /* number of iterations */ char num[4]; long cnt; int disk=5, /* default number of disks */ duration=10; /* default time to run test */ void mov(unsigned char n,unsigned char f,unsigned char t) { char o; if(n == 1) { num[f]--; num[t]++; } else { o = (6-(f+t)); mov(n-1,f,o); mov(1,f,t); mov(n-1,o,t); } #ifdef VERBOSE printf("%2d: %2d %2d %2d %2d\n", (int)iter,(int)num[0],(int)num[1],(int)num[2],(int)num[3]); #endif } int main(int argc,char **argv) { #ifdef USECMDLINE if (argc < 2) { printf("Usage: %s [duration] [disks]\n", argv[0]); exit(1); } else { if(argc > 1) duration = atoi(argv[1]); if(argc > 2) disk = atoi(argv[2]); } #endif printf("towers of hanoi\ndisks: %d\n\n",disk); num[1] = disk; #ifdef VERBOSE printf("%2d: %2d %2d %2d %2d\n", (int)iter,(int)num[0],(int)num[1],(int)num[2],(int)num[3]); #endif while(num[3]<disk) { mov(disk,1,3); ++iter; } return 0; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/ifexpr.c�������������������������������������������������������������������������0000664�0000000�0000000�00000000672�13473601511�0015406�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! if/then, ? operator, compares !!ORIGIN!! cc65 devel list !!LICENCE!! Public Domain */ #include <stdio.h> #include <limits.h> void t1a(void) { int a = -0x5000; printf(a < 0x5000 ? "ok\n" : "error\n"); } void t1b(void) { int a = -0x5000; if(a<0x5000) { printf("ok\n"); } else { printf("error\n"); } } int main(void) { t1a();t1b(); return 0; } ����������������������������������������������������������������������cc65-2.18/test/ref/incr.c���������������������������������������������������������������������������0000664�0000000�0000000�00000001372�13473601511�0015042�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! increment/decrement !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include <stdio.h> int main(void) { printf("disassemble this program to check the generated code.\n"); return 0; } memchar() { char x, *p; &x, &p; x = *p++; x = *++p; x = *p--; x = *--p; } memint() { int x, *p; &x, &p; x = *p++; x = *++p; x = *p--; x = *--p; } regchar() { register char x, *p; x = *p++; x = *++p; x = *p--; x = *--p; } regint() { register int x, *p; x = *p++; x = *++p; x = *p--; x = *--p; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/init.c���������������������������������������������������������������������������0000664�0000000�0000000�00000003623�13473601511�0015053�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! variable initialization !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include "common.h" /* todo: add back conditional stuff here ! */ typedef struct { int codes[3]; char name[6]; } Word; #ifdef NO_IMPLICIT_FUNC_PROTOTYPES #ifdef NO_OLD_FUNC_DECL f(); void g(Word *p); h(); #else f(); g(); h(); #endif #endif /* Word words[] = { 1, 2, 3,"if", { { 4, 5 }, { 'f', 'o', 'r' } }, 6, 7, 8, {"else"}, { { 9, 10, 11,}, 'w', 'h', 'i', 'l', 'e', }, { 0 }, }, *wordlist = words; */ Word words[] = { {{1, 2, 3},"if"}, { { 4, 5 }, { 'f', 'o', 'r' } }, {{6, 7, 8}, "else"}, { { 9, 10, 11}, {'w', 'h', 'i', 'l', 'e', }}, {{ 0 }}, }, *wordlist = words; /*int x[][5] = { 1, 2, 3, 4, 0, { 5, 6 }, { 7 } };*/ int x[][5] = { {1, 2, 3, 4, 0 }, { 5, 6 }, { 7 } }; int *y[] = { x[0], x[1], x[2], 0 }; main() { int i, j; for (i = 0; y[i]; i++) { for (j = 0; y[i][j]; j++) printf(" %d", y[i][j]); printf("\n"); } f(); g(wordlist); return 0; } f() { static char *keywords[] = {"if", "for", "else", "while", 0, }; char **p; for (p = keywords; *p; p++) printf("%s\n", *p); } #ifdef NO_OLD_FUNC_DECL void g(Word *p) #else g(p) Word *p; #endif { int i; for ( ; p->codes[0]; p++) { for (i = 0; i < sizeof p->codes/sizeof(p->codes[0]); i++) printf("%d ", p->codes[i]); printf("%s\n", p->name); } h(); } h() { int i; for (i = 0; i < sizeof(words)/sizeof(Word); i++) printf("%d %d %d %s\n", words[i].codes[0], words[i].codes[1], words[i].codes[2], &words[i].name[0]); } �������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/macro.c��������������������������������������������������������������������������0000664�0000000�0000000�00000001115�13473601511�0015203�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! macro bug test program !!ORIGIN!! testsuite !!LICENCE!! Public Domain !!AUTHOR!! Groepaz/Hitmen */ #include <stdio.h> #include <stdlib.h> unsigned long fs=7; unsigned long fd=5; unsigned long a=3; unsigned long _func(unsigned long x,unsigned long y) { printf("x:%ld y:%ld\n",x,y); return 0; } #define func(x,y) _func(x,y) int main(void) { fs= func( (fd/a) , func(2,0x0082c90f) ); printf("fs:%ld\n",fs); fs=_func( (fd/a) , _func(2,0x0082c90f) ); printf("fs:%ld\n",fs); return 0; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/mandel.c�������������������������������������������������������������������������0000664�0000000�0000000�00000004164�13473601511�0015351�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! mandelbrot test program !!ORIGIN!! testsuite !!LICENCE!! Public Domain !!AUTHOR!! Groepaz/Hitmen */ #include <stdio.h> #include <stdlib.h> static unsigned short SCREEN_X; static unsigned char SCREEN_Y; #define MAXCOL 8 #define maxiterations 16 #define fpshift (12) #define tofp(_x) ((_x)<<fpshift) #define fromfp(_x) ((_x)>>fpshift) #define fpabs(_x) (abs(_x)) #define mulfp(_a,_b) ((((signed long)_a)*(_b))>>fpshift) #define divfp(_a,_b) ((((signed long)_a)<<fpshift)/(_b)) unsigned char dither[MAXCOL]={" .*o+0%#"}; void mandelbrot(signed short x1,signed short y1,signed short x2,signed short y2) { register signed short r,r1,i; register unsigned char count; register signed short xs,ys,xx,yy; register signed short x; register unsigned char y; /* calc stepwidth */ xs=((x2-x1)/(SCREEN_X)); ys=((y2-y1)/(SCREEN_Y)); yy=y1; for(y = 0; y < (SCREEN_Y); ++y) { yy+=ys; xx=x1; for(x = 0; x < (SCREEN_X); ++x) { xx+=xs; /* do iterations */ r=0;i=0; for(count=0;(count<maxiterations)&& (fpabs(r)<tofp(2))&& (fpabs(i)<tofp(2)) ;++count) { r1 = (mulfp(r,r)-mulfp(i,i))+xx; /* i = (mulfp(mulfp(r,i),tofp(2)))+yy; */ i = (((signed long)r*i)>>(fpshift-1))+yy; r=r1; } if(count==maxiterations) { printf(" "); } else { printf("%c",dither[(count%MAXCOL)]); } } printf("\n"); } } int main (void) { SCREEN_X = 80; SCREEN_Y = 40; /* calc mandelbrot set */ mandelbrot(tofp(-2),tofp(-2),tofp(2),tofp(2)); /* Done */ return 0; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/minimal.c������������������������������������������������������������������������0000664�0000000�0000000�00000000433�13473601511�0015532�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! minimal Program, checks if the Compiler and testsuite framework works !!ORIGIN!! testsuite !!LICENCE!! Public Domain !!AUTHOR!! Groepaz/Hitmen */ #include <stdio.h> int main(void) { #if 1 printf("it works :)\n"); #endif return 0; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/otccex.c�������������������������������������������������������������������������0000664�0000000�0000000�00000007413�13473601511�0015376�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! OTCC Example (simple K&R Style) !!ORIGIN!! OTCC !!LICENCE!! GPL (?), read COPYING.GPL */ #include "common.h" /* * Sample OTCC C example. You can uncomment the first line and install * otcc in /usr/local/bin to make otcc scripts ! */ /* Any preprocessor directive except #define are ignored. We put this include so that a standard C compiler can compile this code too. */ #include <stdio.h> #include <limits.h> /* defines are handled, but macro arguments cannot be given. No recursive defines are tolerated */ #define DEFAULT_BASE 10 #ifdef NO_IMPLICIT_FUNC_PROTOTYPES help(char *name); #endif /* * Only old style K&R prototypes are parsed. Only int arguments are * allowed (implicit types). * * By benchmarking the execution time of this function (for example * for fib(35)), you'll notice that OTCC is quite fast because it * generates native i386 machine code. */ fib(n) { printf("[fib(%d)]", n); if (n <= 2) return 1; else return fib(n-1) + fib(n-2); } /* Identifiers are parsed the same way as C: begins with letter or '_', and then letters, '_' or digits */ long fact(n) { /* local variables can be declared. Only 'int' type is supported */ int i; long r; r = 1; /* 'while' and 'for' loops are supported */ for(i=2;i<=n;i++) r = r * i; return r; } /* Well, we could use printf, but it would be too easy */ print_num(long n,int b) { int tab, p, c; /* Numbers can be entered in decimal, hexadecimal ('0x' prefix) and octal ('0' prefix) */ /* more complex programs use malloc */ tab = malloc(0x100); p = tab; while (1) { c = n % b; /* Character constants can be used */ if (c >= 10) c = c + 'a' - 10; else c = c + '0'; *(char *)p = c; p++; n = n / b; /* 'break' is supported */ if (n == 0) break; } while (p != tab) { p--; printf("%c", *(char *)p); } free(tab); } /* 'main' takes standard 'argc' and 'argv' parameters */ mymain(int argc,char **argv) { /* no local name space is supported, but local variables ARE supported. As long as you do not use a globally defined variable name as local variable (which is a bad habbit), you won't have any problem */ int s, n, f, base; /* && and || operator have the same semantics as C (left to right evaluation and early exit) */ if (argc != 2 && argc != 3) { /* '*' operator is supported with explicit casting to 'int *', 'char *' or 'int (*)()' (function pointer). Of course, 'int' are supposed to be used as pointers too. */ s = *(int *)argv; help(s); return 1; } /* Any libc function can be used because OTCC uses dynamic linking */ n = atoi(argv[1]); base = DEFAULT_BASE; if (argc >= 3) { base = atoi(argv[2]); if (base < 2 || base > 36) { /* external variables can be used too (here: 'stderr') */ fprintf(stdout, "Invalid base\n"); return 1; } } printf("fib(%d) =\n", n); print_num(fib(n), base); printf("\n"); printf("fact(%d) = ", n); if (n > 12) { printf("Overflow"); } else { /* why not using a function pointer ? */ f = &fact; print_num((*(long (*)(int))f)(n), base); } printf("\n"); return 0; } /* functions can be used before being defined */ help(char *name) { printf("usage: %s n [base]\n", name); printf("Compute fib(n) and fact(n) and output the result in base 'base'\n"); } int main(void) { char *argv[3]; argv[0]=""; argv[1]="10"; /* n */ argv[2]="8"; /* base */ mymain(3, argv); return 0; }�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/paranoia.c�����������������������������������������������������������������������0000664�0000000�0000000�00000241644�13473601511�0015711�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! a wellknown floating point test !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include "common.h" #ifdef NO_FLOATS main() { printf("NO_FLOATS\n\r"); return 0; } #else #undef V9 #define NOPAUSE /* A C version of Kahan's Floating Point Test "Paranoia" Thos Sumner, UCSF, Feb. 1985 David Gay, BTL, Jan. 1986 This is a rewrite from the Pascal version by B. A. Wichmann, 18 Jan. 1985 (and does NOT exhibit good C programming style). (C) Apr 19 1983 in BASIC version by: Professor W. M. Kahan, 567 Evans Hall Electrical Engineering & Computer Science Dept. University of California Berkeley, California 94720 USA converted to Pascal by: B. A. Wichmann National Physical Laboratory Teddington Middx TW11 OLW UK converted to C by: David M. Gay and Thos Sumner AT&T Bell Labs Computer Center, Rm. U-76 600 Mountain Avenue University of California Murray Hill, NJ 07974 San Francisco, CA 94143 USA USA with simultaneous corrections to the Pascal source (reflected in the Pascal source available over netlib). [A couple of bug fixes from dgh = sun!dhough incorporated 31 July 1986.] Reports of results on various systems from all the versions of Paranoia are being collected by Richard Karpinski at the same address as Thos Sumner. This includes sample outputs, bug reports, and criticisms. You may copy this program freely if you acknowledge its source. Comments on the Pascal version to NPL, please. The C version catches signals from floating-point exceptions. If signal(SIGFPE,...) is unavailable in your environment, you may #define NOSIGNAL to comment out the invocations of signal. This source file is too big for some C compilers, but may be split into pieces. Comments containing "SPLIT" suggest convenient places for this splitting. At the end of these comments is an "ed script" (for the UNIX(tm) editor ed) that will do this splitting. By #defining Single when you compile this source, you may obtain a single-precision C version of Paranoia. The following is from the introductory commentary from Wichmann's work: The BASIC program of Kahan is written in Microsoft BASIC using many facilities which have no exact analogy in Pascal. The Pascal version below cannot therefore be exactly the same. Rather than be a minimal transcription of the BASIC program, the Pascal coding follows the conventional style of block-structured languages. Hence the Pascal version could be useful in producing versions in other structured languages. Rather than use identifiers of minimal length (which therefore have little mnemonic significance), the Pascal version uses meaningful identifiers as follows [Note: A few changes have been made for C]: BASIC C BASIC C BASIC C A J S StickyBit A1 AInverse J0 NoErrors T B Radix [Failure] T0 Underflow B1 BInverse J1 NoErrors T2 ThirtyTwo B2 RadixD2 [SeriousDefect] T5 OneAndHalf B9 BMinusU2 J2 NoErrors T7 TwentySeven C [Defect] T8 TwoForty C1 CInverse J3 NoErrors U OneUlp D [Flaw] U0 UnderflowThreshold D4 FourD K PageNo U1 E0 L Milestone U2 E1 M V E2 Exp2 N V0 E3 N1 V8 E5 MinSqEr O Zero V9 E6 SqEr O1 One W E7 MaxSqEr O2 Two X E8 O3 Three X1 E9 O4 Four X8 F1 MinusOne O5 Five X9 Random1 F2 Half O8 Eight Y F3 Third O9 Nine Y1 F6 P Precision Y2 F9 Q Y9 Random2 G1 GMult Q8 Z G2 GDiv Q9 Z0 PseudoZero G3 GAddSub R Z1 H R1 RMult Z2 H1 HInverse R2 RDiv Z9 I R3 RAddSub IO NoTrials R4 RSqrt I3 IEEE R9 Random9 SqRWrng All the variables in BASIC are true variables and in consequence, the program is more difficult to follow since the "constants" must be determined (the glossary is very helpful). The Pascal version uses Real constants, but checks are added to ensure that the values are correctly converted by the compiler. The major textual change to the Pascal version apart from the identifiersis that named procedures are used, inserting parameters wherehelpful. New procedures are also introduced. The correspondence is as follows: BASIC Pascal lines 90- 140 Pause 170- 250 Instructions 380- 460 Heading 480- 670 Characteristics 690- 870 History 2940-2950 Random 3710-3740 NewD 4040-4080 DoesYequalX 4090-4110 PrintIfNPositive 4640-4850 TestPartialUnderflow =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*= Below is an "ed script" that splits para.c into 10 files of the form part[1-8].c, subs.c, and msgs.c, plus a header file, paranoia.h, that these files require. r paranoia.c $ ?SPLIT +,$w msgs.c .,$d ?SPLIT .d +d -,$w subs.c -,$d ?part8 +d ?include .,$w part8.c .,$d -d ?part7 +d ?include .,$w part7.c .,$d -d ?part6 +d ?include .,$w part6.c .,$d -d ?part5 +d ?include .,$w part5.c .,$d -d ?part4 +d ?include .,$w part4.c .,$d -d ?part3 +d ?include .,$w part3.c .,$d -d ?part2 +d ?include .,$w part2.c .,$d ?SPLIT .d 1,/^#include/-1d 1,$w part1.c /Computed constants/,$d 1,$s/^int/extern &/ 1,$s/^FLOAT/extern &/ 1,$s/^char/extern &/ 1,$s! = .*!;! /^Guard/,/^Round/s/^/extern / /^jmp_buf/s/^/extern / /^Sig_type/s/^/extern / s/$/\ extern void sigfpe();/ w paranoia.h q */ #include <stdio.h> #ifndef NOSIGNAL #include <signal.h> #endif #include <setjmp.h> extern double fabs(), floor(), log(), pow(), sqrt(); #ifdef Single #define FLOAT float #define FABS(x) (float)fabs((double)(x)) #define FLOOR(x) (float)floor((double)(x)) #define LOG(x) (float)log((double)(x)) #define POW(x,y) (float)pow((double)(x),(double)(y)) #define SQRT(x) (float)sqrt((double)(x)) #else #define FLOAT double #define FABS(x) fabs(x) #define FLOOR(x) floor(x) #define LOG(x) log(x) #define POW(x,y) pow(x,y) #define SQRT(x) sqrt(x) #endif jmp_buf ovfl_buf; typedef void (*Sig_type)(); Sig_type sigsave; #define KEYBOARD 0 FLOAT Radix, BInvrse, RadixD2, BMinusU2; FLOAT Sign(), Random(); /*Small floating point constants.*/ FLOAT Zero = 0.0; FLOAT Half = 0.5; FLOAT One = 1.0; FLOAT Two = 2.0; FLOAT Three = 3.0; FLOAT Four = 4.0; FLOAT Five = 5.0; FLOAT Eight = 8.0; FLOAT Nine = 9.0; FLOAT TwentySeven = 27.0; FLOAT ThirtyTwo = 32.0; FLOAT TwoForty = 240.0; FLOAT MinusOne = -1.0; FLOAT OneAndHalf = 1.5; /*Integer constants*/ int NoTrials = 20; /*Number of tests for commutativity. */ #define False 0 #define True 1 /* Definitions for declared types Guard == (Yes, No); Rounding == (Chopped, Rounded, Other); Message == packed array [1..40] of char; Class == (Flaw, Defect, Serious, Failure); */ #define Yes 1 #define No 0 #define Chopped 2 #define Rounded 1 #define Other 0 #define Flaw 3 #define Defect 2 #define Serious 1 #define Failure 0 typedef int Guard, Rounding, Class; typedef char Message; /* Declarations of Variables */ int Indx; char ch[8]; FLOAT AInvrse, A1; FLOAT C, CInvrse; FLOAT D, FourD; FLOAT E0, E1, Exp2, E3, MinSqEr; FLOAT SqEr, MaxSqEr, E9; FLOAT Third; FLOAT F6, F9; FLOAT H, HInvrse; int I; FLOAT StickyBit, J; FLOAT MyZero; FLOAT Precision; FLOAT Q, Q9; FLOAT R, Random9; FLOAT T, Underflow, S; FLOAT OneUlp, UfThold, U1, U2; FLOAT V, V0, V9; FLOAT W; FLOAT X, X1, X2, X8, Random1; FLOAT Y, Y1, Y2, Random2; FLOAT Z, PseudoZero, Z1, Z2, Z9; int ErrCnt[4]; int fpecount; int Milestone; int PageNo; int M, N, N1; Guard GMult, GDiv, GAddSub; Rounding RMult, RDiv, RAddSub, RSqrt; int Break, Done, NotMonot, Monot, Anomaly, IEEE, SqRWrng, UfNGrad; /* Computed constants. */ /*U1 gap below 1.0, i.e, 1.0-U1 is next number below 1.0 */ /*U2 gap above 1.0, i.e, 1.0+U2 is next number above 1.0 */ /* floating point exception receiver */ void sigfpe(i) { fpecount++; printf("\n* * * FLOATING-POINT ERROR * * *\n"); fflush(stdout); if (sigsave) { #ifndef NOSIGNAL signal(SIGFPE, sigsave); #endif sigsave = 0; longjmp(ovfl_buf, 1); } abort(); } main() { #ifdef mc char *out; ieee_flags("set", "precision", "double", &out); #endif /* First two assignments use integer right-hand sides. */ Zero = 0; One = 1; Two = One + One; Three = Two + One; Four = Three + One; Five = Four + One; Eight = Four + Four; Nine = Three * Three; TwentySeven = Nine * Three; ThirtyTwo = Four * Eight; TwoForty = Four * Five * Three * Four; MinusOne = -One; Half = One / Two; OneAndHalf = One + Half; ErrCnt[Failure] = 0; ErrCnt[Serious] = 0; ErrCnt[Defect] = 0; ErrCnt[Flaw] = 0; PageNo = 1; /*=============================================*/ Milestone = 0; /*=============================================*/ #ifndef NOSIGNAL signal(SIGFPE, sigfpe); #endif Instructions(); Pause(); Heading(); Pause(); Characteristics(); Pause(); History(); Pause(); /*=============================================*/ Milestone = 7; /*=============================================*/ printf("Program is now RUNNING tests on small integers:\n"); TstCond (Failure, (Zero + Zero == Zero) && (One - One == Zero) && (One > Zero) && (One + One == Two), "0+0 != 0, 1-1 != 0, 1 <= 0, or 1+1 != 2"); Z = - Zero; if (Z != 0.0) { ErrCnt[Failure] = ErrCnt[Failure] + 1; printf("Comparison alleges that -0.0 is Non-zero!\n"); U1 = 0.001; Radix = 1; TstPtUf(); } TstCond (Failure, (Three == Two + One) && (Four == Three + One) && (Four + Two * (- Two) == Zero) && (Four - Three - One == Zero), "3 != 2+1, 4 != 3+1, 4+2*(-2) != 0, or 4-3-1 != 0"); TstCond (Failure, (MinusOne == (0 - One)) && (MinusOne + One == Zero ) && (One + MinusOne == Zero) && (MinusOne + FABS(One) == Zero) && (MinusOne + MinusOne * MinusOne == Zero), "-1+1 != 0, (-1)+abs(1) != 0, or -1+(-1)*(-1) != 0"); TstCond (Failure, Half + MinusOne + Half == Zero, "1/2 + (-1) + 1/2 != 0"); /*=============================================*/ /*SPLIT part2(); part3(); part4(); part5(); part6(); part7(); part8(); } #include "paranoia.h" part2(){ */ Milestone = 10; /*=============================================*/ TstCond (Failure, (Nine == Three * Three) && (TwentySeven == Nine * Three) && (Eight == Four + Four) && (ThirtyTwo == Eight * Four) && (ThirtyTwo - TwentySeven - Four - One == Zero), "9 != 3*3, 27 != 9*3, 32 != 8*4, or 32-27-4-1 != 0"); TstCond (Failure, (Five == Four + One) && (TwoForty == Four * Five * Three * Four) && (TwoForty / Three - Four * Four * Five == Zero) && ( TwoForty / Four - Five * Three * Four == Zero) && ( TwoForty / Five - Four * Three * Four == Zero), "5 != 4+1, 240/3 != 80, 240/4 != 60, or 240/5 != 48"); if (ErrCnt[Failure] == 0) { printf("-1, 0, 1/2, 1, 2, 3, 4, 5, 9, 27, 32 & 240 are O.K.\n"); printf("\n"); } printf("Searching for Radix and Precision.\n"); W = One; do { W = W + W; Y = W + One; Z = Y - W; Y = Z - One; } while (MinusOne + FABS(Y) < Zero); /*.. now W is just big enough that |((W+1)-W)-1| >= 1 ...*/ Precision = Zero; Y = One; do { Radix = W + Y; Y = Y + Y; Radix = Radix - W; } while ( Radix == Zero); if (Radix < Two) Radix = One; printf("Radix = %f .\n", Radix); if (Radix != 1) { W = One; do { Precision = Precision + One; W = W * Radix; Y = W + One; } while ((Y - W) == One); } /*... now W == Radix^Precision is barely too big to satisfy (W+1)-W == 1 ...*/ U1 = One / W; U2 = Radix * U1; printf("Closest relative separation found is U1 = %.7e .\n\n", U1); printf("Recalculating radix and precision\n "); /*save old values*/ E0 = Radix; E1 = U1; E9 = U2; E3 = Precision; X = Four / Three; Third = X - One; F6 = Half - Third; X = F6 + F6; X = FABS(X - Third); if (X < U2) X = U2; /*... now X = (unknown no.) ulps of 1+...*/ do { U2 = X; Y = Half * U2 + ThirtyTwo * U2 * U2; Y = One + Y; X = Y - One; } while ( ! ((U2 <= X) || (X <= Zero))); /*... now U2 == 1 ulp of 1 + ... */ X = Two / Three; F6 = X - Half; Third = F6 + F6; X = Third - Half; X = FABS(X + F6); if (X < U1) X = U1; /*... now X == (unknown no.) ulps of 1 -... */ do { U1 = X; Y = Half * U1 + ThirtyTwo * U1 * U1; Y = Half - Y; X = Half + Y; Y = Half - X; X = Half + Y; } while ( ! ((U1 <= X) || (X <= Zero))); /*... now U1 == 1 ulp of 1 - ... */ if (U1 == E1) printf("confirms closest relative separation U1 .\n"); else printf("gets better closest relative separation U1 = %.7e .\n", U1); W = One / U1; F9 = (Half - U1) + Half; Radix = FLOOR(0.01 + U2 / U1); if (Radix == E0) printf("Radix confirmed.\n"); else printf("MYSTERY: recalculated Radix = %.7e .\n", Radix); TstCond (Defect, Radix <= Eight + Eight, "Radix is too big: roundoff problems"); TstCond (Flaw, (Radix == Two) || (Radix == 10) || (Radix == One), "Radix is not as good as 2 or 10"); /*=============================================*/ Milestone = 20; /*=============================================*/ TstCond (Failure, F9 - Half < Half, "(1-U1)-1/2 < 1/2 is FALSE, prog. fails?"); X = F9; I = 1; Y = X - Half; Z = Y - Half; TstCond (Failure, (X != One) || (Z == Zero), "Comparison is fuzzy,X=1 but X-1/2-1/2 != 0"); X = One + U2; I = 0; /*=============================================*/ Milestone = 25; /*=============================================*/ /*... BMinusU2 = nextafter(Radix, 0) */ BMinusU2 = Radix - One; BMinusU2 = (BMinusU2 - U2) + One; /* Purify Integers */ if (Radix != One) { X = - TwoForty * LOG(U1) / LOG(Radix); Y = FLOOR(Half + X); if (FABS(X - Y) * Four < One) X = Y; Precision = X / TwoForty; Y = FLOOR(Half + Precision); if (FABS(Precision - Y) * TwoForty < Half) Precision = Y; } if ((Precision != FLOOR(Precision)) || (Radix == One)) { printf("Precision cannot be characterized by an Integer number\n"); printf("of significant digits but, by itself, this is a minor flaw.\n"); } if (Radix == One) printf("logarithmic encoding has precision characterized solely by U1.\n"); else printf("The number of significant digits of the Radix is %f .\n", Precision); TstCond (Serious, U2 * Nine * Nine * TwoForty < One, "Precision worse than 5 decimal figures "); /*=============================================*/ Milestone = 30; /*=============================================*/ /* Test for extra-precise subepressions */ X = FABS(((Four / Three - One) - One / Four) * Three - One / Four); do { Z2 = X; X = (One + (Half * Z2 + ThirtyTwo * Z2 * Z2)) - One; } while ( ! ((Z2 <= X) || (X <= Zero))); X = Y = Z = FABS((Three / Four - Two / Three) * Three - One / Four); do { Z1 = Z; Z = (One / Two - ((One / Two - (Half * Z1 + ThirtyTwo * Z1 * Z1)) + One / Two)) + One / Two; } while ( ! ((Z1 <= Z) || (Z <= Zero))); do { do { Y1 = Y; Y = (Half - ((Half - (Half * Y1 + ThirtyTwo * Y1 * Y1)) + Half )) + Half; } while ( ! ((Y1 <= Y) || (Y <= Zero))); X1 = X; X = ((Half * X1 + ThirtyTwo * X1 * X1) - F9) + F9; } while ( ! ((X1 <= X) || (X <= Zero))); if ((X1 != Y1) || (X1 != Z1)) { BadCond(Serious, "Disagreements among the values X1, Y1, Z1,\n"); printf("respectively %.7e, %.7e, %.7e,\n", X1, Y1, Z1); printf("are symptoms of inconsistencies introduced\n"); printf("by extra-precise evaluation of arithmetic subexpressions.\n"); notify("Possibly some part of this"); if ((X1 == U1) || (Y1 == U1) || (Z1 == U1)) printf( "That feature is not tested further by this program.\n") ; } else { if ((Z1 != U1) || (Z2 != U2)) { if ((Z1 >= U1) || (Z2 >= U2)) { BadCond(Failure, ""); notify("Precision"); printf("\tU1 = %.7e, Z1 - U1 = %.7e\n",U1,Z1-U1); printf("\tU2 = %.7e, Z2 - U2 = %.7e\n",U2,Z2-U2); } else { if ((Z1 <= Zero) || (Z2 <= Zero)) { printf("Because of unusual Radix = %f", Radix); printf(", or exact rational arithmetic a result\n"); printf("Z1 = %.7e, or Z2 = %.7e ", Z1, Z2); notify("of an\nextra-precision"); } if (Z1 != Z2 || Z1 > Zero) { X = Z1 / U1; Y = Z2 / U2; if (Y > X) X = Y; Q = - LOG(X); printf("Some subexpressions appear to be calculated extra\n"); printf("precisely with about %g extra B-digits, i.e.\n", (Q / LOG(Radix))); printf("roughly %g extra significant decimals.\n", Q / LOG(10.)); } printf("That feature is not tested further by this program.\n"); } } } Pause(); /*=============================================*/ /*SPLIT } #include "paranoia.h" part3(){ */ Milestone = 35; /*=============================================*/ if (Radix >= Two) { X = W / (Radix * Radix); Y = X + One; Z = Y - X; T = Z + U2; X = T - Z; TstCond (Failure, X == U2, "Subtraction is not normalized X=Y,X+Z != Y+Z!"); if (X == U2) printf( "Subtraction appears to be normalized, as it should be."); } printf("\nChecking for guard digit in *, /, and -.\n"); Y = F9 * One; Z = One * F9; X = F9 - Half; Y = (Y - Half) - X; Z = (Z - Half) - X; X = One + U2; T = X * Radix; R = Radix * X; X = T - Radix; X = X - Radix * U2; T = R - Radix; T = T - Radix * U2; X = X * (Radix - One); T = T * (Radix - One); if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero)) GMult = Yes; else { GMult = No; TstCond (Serious, False, "* lacks a Guard Digit, so 1*X != X"); } Z = Radix * U2; X = One + Z; Y = FABS((X + Z) - X * X) - U2; X = One - U2; Z = FABS((X - U2) - X * X) - U1; TstCond (Failure, (Y <= Zero) && (Z <= Zero), "* gets too many final digits wrong.\n"); Y = One - U2; X = One + U2; Z = One / Y; Y = Z - X; X = One / Three; Z = Three / Nine; X = X - Z; T = Nine / TwentySeven; Z = Z - T; TstCond(Defect, X == Zero && Y == Zero && Z == Zero, "Division lacks a Guard Digit, so error can exceed 1 ulp\nor 1/3 and 3/9 and 9/27 may disagree"); Y = F9 / One; X = F9 - Half; Y = (Y - Half) - X; X = One + U2; T = X / One; X = T - X; if ((X == Zero) && (Y == Zero) && (Z == Zero)) GDiv = Yes; else { GDiv = No; TstCond (Serious, False, "Division lacks a Guard Digit, so X/1 != X"); } X = One / (One + U2); Y = X - Half - Half; TstCond (Serious, Y < Zero, "Computed value of 1/1.000..1 >= 1"); X = One - U2; Y = One + Radix * U2; Z = X * Radix; T = Y * Radix; R = Z / Radix; StickyBit = T / Radix; X = R - X; Y = StickyBit - Y; TstCond (Failure, X == Zero && Y == Zero, "* and/or / gets too many last digits wrong"); Y = One - U1; X = One - F9; Y = One - Y; T = Radix - U2; Z = Radix - BMinusU2; T = Radix - T; if ((X == U1) && (Y == U1) && (Z == U2) && (T == U2)) GAddSub = Yes; else { GAddSub = No; TstCond (Serious, False, "- lacks Guard Digit, so cancellation is obscured"); } if (F9 != One && F9 - One >= Zero) { BadCond(Serious, "comparison alleges (1-U1) < 1 although\n"); printf(" subtraction yields (1-U1) - 1 = 0 , thereby vitiating\n"); printf(" such precautions against division by zero as\n"); printf(" ... if (X == 1.0) {.....} else {.../(X-1.0)...}\n"); } if (GMult == Yes && GDiv == Yes && GAddSub == Yes) printf( " *, /, and - appear to have guard digits, as they should.\n"); /*=============================================*/ Milestone = 40; /*=============================================*/ Pause(); printf("Checking rounding on multiply, divide and add/subtract.\n"); RMult = Other; RDiv = Other; RAddSub = Other; RadixD2 = Radix / Two; A1 = Two; Done = False; do { AInvrse = Radix; do { X = AInvrse; AInvrse = AInvrse / A1; } while ( ! (FLOOR(AInvrse) != AInvrse)); Done = (X == One) || (A1 > Three); if (! Done) A1 = Nine + One; } while ( ! (Done)); if (X == One) A1 = Radix; AInvrse = One / A1; X = A1; Y = AInvrse; Done = False; do { Z = X * Y - Half; TstCond (Failure, Z == Half, "X * (1/X) differs from 1"); Done = X == Radix; X = Radix; Y = One / X; } while ( ! (Done)); Y2 = One + U2; Y1 = One - U2; X = OneAndHalf - U2; Y = OneAndHalf + U2; Z = (X - U2) * Y2; T = Y * Y1; Z = Z - X; T = T - X; X = X * Y2; Y = (Y + U2) * Y1; X = X - OneAndHalf; Y = Y - OneAndHalf; if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T <= Zero)) { X = (OneAndHalf + U2) * Y2; Y = OneAndHalf - U2 - U2; Z = OneAndHalf + U2 + U2; T = (OneAndHalf - U2) * Y1; X = X - (Z + U2); StickyBit = Y * Y1; S = Z * Y2; T = T - Y; Y = (U2 - Y) + StickyBit; Z = S - (Z + U2 + U2); StickyBit = (Y2 + U2) * Y1; Y1 = Y2 * Y1; StickyBit = StickyBit - Y2; Y1 = Y1 - Half; if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero) && ( StickyBit == Zero) && (Y1 == Half)) { RMult = Rounded; printf("Multiplication appears to round correctly.\n"); } else if ((X + U2 == Zero) && (Y < Zero) && (Z + U2 == Zero) && (T < Zero) && (StickyBit + U2 == Zero) && (Y1 < Half)) { RMult = Chopped; printf("Multiplication appears to chop.\n"); } else printf("* is neither chopped nor correctly rounded.\n"); if ((RMult == Rounded) && (GMult == No)) notify("Multiplication"); } else printf("* is neither chopped nor correctly rounded.\n"); /*=============================================*/ Milestone = 45; /*=============================================*/ Y2 = One + U2; Y1 = One - U2; Z = OneAndHalf + U2 + U2; X = Z / Y2; T = OneAndHalf - U2 - U2; Y = (T - U2) / Y1; Z = (Z + U2) / Y2; X = X - OneAndHalf; Y = Y - T; T = T / Y1; Z = Z - (OneAndHalf + U2); T = (U2 - OneAndHalf) + T; if (! ((X > Zero) || (Y > Zero) || (Z > Zero) || (T > Zero))) { X = OneAndHalf / Y2; Y = OneAndHalf - U2; Z = OneAndHalf + U2; X = X - Y; T = OneAndHalf / Y1; Y = Y / Y1; T = T - (Z + U2); Y = Y - Z; Z = Z / Y2; Y1 = (Y2 + U2) / Y2; Z = Z - OneAndHalf; Y2 = Y1 - Y2; Y1 = (F9 - U1) / F9; if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero) && (Y2 == Zero) && (Y2 == Zero) && (Y1 - Half == F9 - Half )) { RDiv = Rounded; printf("Division appears to round correctly.\n"); if (GDiv == No) notify("Division"); } else if ((X < Zero) && (Y < Zero) && (Z < Zero) && (T < Zero) && (Y2 < Zero) && (Y1 - Half < F9 - Half)) { RDiv = Chopped; printf("Division appears to chop.\n"); } } if (RDiv == Other) printf("/ is neither chopped nor correctly rounded.\n"); BInvrse = One / Radix; TstCond (Failure, (BInvrse * Radix - Half == Half), "Radix * ( 1 / Radix ) differs from 1"); /*=============================================*/ /*SPLIT } #include "paranoia.h" part4(){ */ Milestone = 50; /*=============================================*/ TstCond (Failure, ((F9 + U1) - Half == Half) && ((BMinusU2 + U2 ) - One == Radix - One), "Incomplete carry-propagation in Addition"); X = One - U1 * U1; Y = One + U2 * (One - U2); Z = F9 - Half; X = (X - Half) - Z; Y = Y - One; if ((X == Zero) && (Y == Zero)) { RAddSub = Chopped; printf("Add/Subtract appears to be chopped.\n"); } if (GAddSub == Yes) { X = (Half + U2) * U2; Y = (Half - U2) * U2; X = One + X; Y = One + Y; X = (One + U2) - X; Y = One - Y; if ((X == Zero) && (Y == Zero)) { X = (Half + U2) * U1; Y = (Half - U2) * U1; X = One - X; Y = One - Y; X = F9 - X; Y = One - Y; if ((X == Zero) && (Y == Zero)) { RAddSub = Rounded; printf("Addition/Subtraction appears to round correctly.\n"); if (GAddSub == No) notify("Add/Subtract"); } else printf("Addition/Subtraction neither rounds nor chops.\n"); } else printf("Addition/Subtraction neither rounds nor chops.\n"); } else printf("Addition/Subtraction neither rounds nor chops.\n"); S = One; X = One + Half * (One + Half); Y = (One + U2) * Half; Z = X - Y; T = Y - X; StickyBit = Z + T; if (StickyBit != Zero) { S = Zero; BadCond(Flaw, "(X - Y) + (Y - X) is non zero!\n"); } StickyBit = Zero; if ((GMult == Yes) && (GDiv == Yes) && (GAddSub == Yes) && (RMult == Rounded) && (RDiv == Rounded) && (RAddSub == Rounded) && (FLOOR(RadixD2) == RadixD2)) { printf("Checking for sticky bit.\n"); X = (Half + U1) * U2; Y = Half * U2; Z = One + Y; T = One + X; if ((Z - One <= Zero) && (T - One >= U2)) { Z = T + Y; Y = Z - X; if ((Z - T >= U2) && (Y - T == Zero)) { X = (Half + U1) * U1; Y = Half * U1; Z = One - Y; T = One - X; if ((Z - One == Zero) && (T - F9 == Zero)) { Z = (Half - U1) * U1; T = F9 - Z; Q = F9 - Y; if ((T - F9 == Zero) && (F9 - U1 - Q == Zero)) { Z = (One + U2) * OneAndHalf; T = (OneAndHalf + U2) - Z + U2; X = One + Half / Radix; Y = One + Radix * U2; Z = X * Y; if (T == Zero && X + Radix * U2 - Z == Zero) { if (Radix != Two) { X = Two + U2; Y = X / Two; if ((Y - One == Zero)) StickyBit = S; } else StickyBit = S; } } } } } } if (StickyBit == One) printf("Sticky bit apparently used correctly.\n"); else printf("Sticky bit used incorrectly or not at all.\n"); TstCond (Flaw, !(GMult == No || GDiv == No || GAddSub == No || RMult == Other || RDiv == Other || RAddSub == Other), "lack(s) of guard digits or failure(s) to correctly round or chop\n(noted above) count as one flaw in the final tally below"); /*=============================================*/ Milestone = 60; /*=============================================*/ printf("\n"); printf("Does Multiplication commute? "); printf("Testing on %d random pairs.\n", NoTrials); Random9 = SQRT(3.0); Random1 = Third; I = 1; do { X = Random(); Y = Random(); Z9 = Y * X; Z = X * Y; Z9 = Z - Z9; I = I + 1; } while ( ! ((I > NoTrials) || (Z9 != Zero))); if (I == NoTrials) { Random1 = One + Half / Three; Random2 = (U2 + U1) + One; Z = Random1 * Random2; Y = Random2 * Random1; Z9 = (One + Half / Three) * ((U2 + U1) + One) - (One + Half / Three) * ((U2 + U1) + One); } if (! ((I == NoTrials) || (Z9 == Zero))) BadCond(Defect, "X * Y == Y * X trial fails.\n"); else printf(" No failures found in %d integer pairs.\n", NoTrials); /*=============================================*/ Milestone = 70; /*=============================================*/ printf("\nRunning test of square root(x).\n"); TstCond (Failure, (Zero == SQRT(Zero)) && (- Zero == SQRT(- Zero)) && (One == SQRT(One)), "Square root of 0.0, -0.0 or 1.0 wrong"); MinSqEr = Zero; MaxSqEr = Zero; J = Zero; X = Radix; OneUlp = U2; SqXMinX (Serious); X = BInvrse; OneUlp = BInvrse * U1; SqXMinX (Serious); X = U1; OneUlp = U1 * U1; SqXMinX (Serious); if (J != Zero) Pause(); printf("Testing if sqrt(X * X) == X for %d Integers X.\n", NoTrials); J = Zero; X = Two; Y = Radix; if ((Radix != One)) do { X = Y; Y = Radix * Y; } while ( ! ((Y - X >= NoTrials))); OneUlp = X * U2; I = 1; while (I <= NoTrials) { X = X + One; SqXMinX (Defect); if (J > Zero) break; I = I + 1; } printf("Test for sqrt monotonicity.\n"); I = - 1; X = BMinusU2; Y = Radix; Z = Radix + Radix * U2; NotMonot = False; Monot = False; while ( ! (NotMonot || Monot)) { I = I + 1; X = SQRT(X); Q = SQRT(Y); Z = SQRT(Z); if ((X > Q) || (Q > Z)) NotMonot = True; else { Q = FLOOR(Q + Half); if ((I > 0) || (Radix == Q * Q)) Monot = True; else if (I > 0) { if (I > 1) Monot = True; else { Y = Y * BInvrse; X = Y - U1; Z = Y + U1; } } else { Y = Q; X = Y - U2; Z = Y + U2; } } } if (Monot) printf("sqrt has passed a test for Monotonicity.\n"); else { BadCond(Defect, ""); printf("sqrt(X) is non-monotonic for X near %.7e .\n", Y); } /*=============================================*/ /*SPLIT } #include "paranoia.h" part5(){ */ Milestone = 80; /*=============================================*/ MinSqEr = MinSqEr + Half; MaxSqEr = MaxSqEr - Half; Y = (SQRT(One + U2) - One) / U2; SqEr = (Y - One) + U2 / Eight; if (SqEr > MaxSqEr) MaxSqEr = SqEr; SqEr = Y + U2 / Eight; if (SqEr < MinSqEr) MinSqEr = SqEr; Y = ((SQRT(F9) - U2) - (One - U2)) / U1; SqEr = Y + U1 / Eight; if (SqEr > MaxSqEr) MaxSqEr = SqEr; SqEr = (Y + One) + U1 / Eight; if (SqEr < MinSqEr) MinSqEr = SqEr; OneUlp = U2; X = OneUlp; for( Indx = 1; Indx <= 3; ++Indx) { Y = SQRT((X + U1 + X) + F9); Y = ((Y - U2) - ((One - U2) + X)) / OneUlp; Z = ((U1 - X) + F9) * Half * X * X / OneUlp; SqEr = (Y + Half) + Z; if (SqEr < MinSqEr) MinSqEr = SqEr; SqEr = (Y - Half) + Z; if (SqEr > MaxSqEr) MaxSqEr = SqEr; if (((Indx == 1) || (Indx == 3))) X = OneUlp * Sign (X) * FLOOR(Eight / (Nine * SQRT(OneUlp))); else { OneUlp = U1; X = - OneUlp; } } /*=============================================*/ Milestone = 85; /*=============================================*/ SqRWrng = False; Anomaly = False; RSqrt = Other; /* ~dgh */ if (Radix != One) { printf("Testing whether sqrt is rounded or chopped.\n"); D = FLOOR(Half + POW(Radix, One + Precision - FLOOR(Precision))); /* ... == Radix^(1 + fract) if (Precision == Integer + fract. */ X = D / Radix; Y = D / A1; if ((X != FLOOR(X)) || (Y != FLOOR(Y))) { Anomaly = True; } else { X = Zero; Z2 = X; Y = One; Y2 = Y; Z1 = Radix - One; FourD = Four * D; do { if (Y2 > Z2) { Q = Radix; Y1 = Y; do { X1 = FABS(Q + FLOOR(Half - Q / Y1) * Y1); Q = Y1; Y1 = X1; } while ( ! (X1 <= Zero)); if (Q <= One) { Z2 = Y2; Z = Y; } } Y = Y + Two; X = X + Eight; Y2 = Y2 + X; if (Y2 >= FourD) Y2 = Y2 - FourD; } while ( ! (Y >= D)); X8 = FourD - Z2; Q = (X8 + Z * Z) / FourD; X8 = X8 / Eight; if (Q != FLOOR(Q)) Anomaly = True; else { Break = False; do { X = Z1 * Z; X = X - FLOOR(X / Radix) * Radix; if (X == One) Break = True; else Z1 = Z1 - One; } while ( ! (Break || (Z1 <= Zero))); if ((Z1 <= Zero) && (! Break)) Anomaly = True; else { if (Z1 > RadixD2) Z1 = Z1 - Radix; do { NewD(); } while ( ! (U2 * D >= F9)); if (D * Radix - D != W - D) Anomaly = True; else { Z2 = D; I = 0; Y = D + (One + Z) * Half; X = D + Z + Q; SR3750(); Y = D + (One - Z) * Half + D; X = D - Z + D; X = X + Q + X; SR3750(); NewD(); if (D - Z2 != W - Z2) Anomaly = True; else { Y = (D - Z2) + (Z2 + (One - Z) * Half); X = (D - Z2) + (Z2 - Z + Q); SR3750(); Y = (One + Z) * Half; X = Q; SR3750(); if (I == 0) Anomaly = True; } } } } } if ((I == 0) || Anomaly) { BadCond(Failure, "Anomalous arithmetic with Integer < "); printf("Radix^Precision = %.7e\n", W); printf(" fails test whether sqrt rounds or chops.\n"); SqRWrng = True; } } if (! Anomaly) { if (! ((MinSqEr < Zero) || (MaxSqEr > Zero))) { RSqrt = Rounded; printf("Square root appears to be correctly rounded.\n"); } else { if ((MaxSqEr + U2 > U2 - Half) || (MinSqEr > Half) || (MinSqEr + Radix < Half)) SqRWrng = True; else { RSqrt = Chopped; printf("Square root appears to be chopped.\n"); } } } if (SqRWrng) { printf("Square root is neither chopped nor correctly rounded.\n"); printf("Observed errors run from %.7e ", MinSqEr - Half); printf("to %.7e ulps.\n", Half + MaxSqEr); TstCond (Serious, MaxSqEr - MinSqEr < Radix * Radix, "sqrt gets too many last digits wrong"); } /*=============================================*/ Milestone = 90; /*=============================================*/ Pause(); printf("Testing powers Z^i for small Integers Z and i.\n"); N = 0; /* ... test powers of zero. */ I = 0; Z = -Zero; M = 3.0; Break = False; do { X = One; SR3980(); if (I <= 10) { I = 1023; SR3980(); } if (Z == MinusOne) Break = True; else { Z = MinusOne; PrintIfNPositive(); N = 0; /* .. if(-1)^N is invalid, replace MinusOne by One. */ I = - 4; } } while ( ! Break); PrintIfNPositive(); N1 = N; N = 0; Z = A1; M = FLOOR(Two * LOG(W) / LOG(A1)); Break = False; do { X = Z; I = 1; SR3980(); if (Z == AInvrse) Break = True; else Z = AInvrse; } while ( ! (Break)); /*=============================================*/ Milestone = 100; /*=============================================*/ /* Powers of Radix have been tested, */ /* next try a few primes */ M = NoTrials; Z = Three; do { X = Z; I = 1; SR3980(); do { Z = Z + Two; } while ( Three * FLOOR(Z / Three) == Z ); } while ( Z < Eight * Three ); if (N > 0) { printf("Errors like this may invalidate financial calculations\n"); printf("\tinvolving interest rates.\n"); } PrintIfNPositive(); N += N1; if (N == 0) printf("... no discrepancis found.\n"); if (N > 0) Pause(); else printf("\n"); /*=============================================*/ /*SPLIT } #include "paranoia.h" part6(){ */ Milestone = 110; /*=============================================*/ printf("Seeking Underflow thresholds UfThold and E0.\n"); D = U1; if (Precision != FLOOR(Precision)) { D = BInvrse; X = Precision; do { D = D * BInvrse; X = X - One; } while ( X > Zero); } Y = One; Z = D; /* ... D is power of 1/Radix < 1. */ do { C = Y; Y = Z; Z = Y * Y; } while ((Y > Z) && (Z + Z > Z)); Y = C; Z = Y * D; do { C = Y; Y = Z; Z = Y * D; } while ((Y > Z) && (Z + Z > Z)); if (Radix < Two) HInvrse = Two; else HInvrse = Radix; H = One / HInvrse; /* ... 1/HInvrse == H == Min(1/Radix, 1/2) */ CInvrse = One / C; E0 = C; Z = E0 * H; /* ...1/Radix^(BIG Integer) << 1 << CInvrse == 1/C */ do { Y = E0; E0 = Z; Z = E0 * H; } while ((E0 > Z) && (Z + Z > Z)); UfThold = E0; E1 = Zero; Q = Zero; E9 = U2; S = One + E9; D = C * S; if (D <= C) { E9 = Radix * U2; S = One + E9; D = C * S; if (D <= C) { BadCond(Failure, "multiplication gets too many last digits wrong.\n"); Underflow = E0; Y1 = Zero; PseudoZero = Z; Pause(); } } else { Underflow = D; PseudoZero = Underflow * H; UfThold = Zero; do { Y1 = Underflow; Underflow = PseudoZero; if (E1 + E1 <= E1) { Y2 = Underflow * HInvrse; E1 = FABS(Y1 - Y2); Q = Y1; if ((UfThold == Zero) && (Y1 != Y2)) UfThold = Y1; } PseudoZero = PseudoZero * H; } while ((Underflow > PseudoZero) && (PseudoZero + PseudoZero > PseudoZero)); } /* Comment line 4530 .. 4560 */ if (PseudoZero != Zero) { printf("\n"); Z = PseudoZero; /* ... Test PseudoZero for "phoney- zero" violates */ /* ... PseudoZero < Underflow or PseudoZero < PseudoZero + PseudoZero ... */ if (PseudoZero <= Zero) { BadCond(Failure, "Positive expressions can underflow to an\n"); printf("allegedly negative value\n"); printf("PseudoZero that prints out as: %g .\n", PseudoZero); X = - PseudoZero; if (X <= Zero) { printf("But -PseudoZero, which should be\n"); printf("positive, isn't; it prints out as %g .\n", X); } } else { BadCond(Flaw, "Underflow can stick at an allegedly positive\n"); printf("value PseudoZero that prints out as %g .\n", PseudoZero); } TstPtUf(); } /*=============================================*/ Milestone = 120; /*=============================================*/ if (CInvrse * Y > CInvrse * Y1) { S = H * S; E0 = Underflow; } if (! ((E1 == Zero) || (E1 == E0))) { BadCond(Defect, ""); if (E1 < E0) { printf("Products underflow at a higher"); printf(" threshold than differences.\n"); if (PseudoZero == Zero) E0 = E1; } else { printf("Difference underflows at a higher"); printf(" threshold than products.\n"); } } printf("Smallest strictly positive number found is E0 = %g .\n", E0); Z = E0; TstPtUf(); Underflow = E0; if (N == 1) Underflow = Y; I = 4; if (E1 == Zero) I = 3; if (UfThold == Zero) I = I - 2; UfNGrad = True; switch (I) { case 1: UfThold = Underflow; if ((CInvrse * Q) != ((CInvrse * Y) * S)) { UfThold = Y; BadCond(Failure, "Either accuracy deteriorates as numbers\n"); printf("approach a threshold = %.17e\n", UfThold);; printf(" coming down from %.17e\n", C); printf(" or else multiplication gets too many last digits wrong.\n"); } Pause(); break; case 2: BadCond(Failure, "Underflow confuses Comparison, which alleges that\n"); printf("Q == Y while denying that |Q - Y| == 0; these values\n"); printf("print out as Q = %.17e, Y = %.17e .\n", Q, Y2); printf ("|Q - Y| = %.17e .\n" , FABS(Q - Y2)); UfThold = Q; break; case 3: X = X; break; case 4: if ((Q == UfThold) && (E1 == E0) && (FABS( UfThold - E1 / E9) <= E1)) { UfNGrad = False; printf("Underflow is gradual; it incurs Absolute Error =\n"); printf("(roundoff in UfThold) < E0.\n"); Y = E0 * CInvrse; Y = Y * (OneAndHalf + U2); X = CInvrse * (One + U2); Y = Y / X; IEEE = (Y == E0); } } if (UfNGrad) { printf("\n"); sigsave = sigfpe; if (setjmp(ovfl_buf)) { printf("Underflow / UfThold failed!\n"); R = H + H; } else R = SQRT(Underflow / UfThold); sigsave = 0; if (R <= H) { Z = R * UfThold; X = Z * (One + R * H * (One + H)); } else { Z = UfThold; X = Z * (One + H * H * (One + H)); } if (! ((X == Z) || (X - Z != Zero))) { BadCond(Flaw, ""); printf("X = %.17e\n\tis not equal to Z = %.17e .\n", X, Z); Z9 = X - Z; printf("yet X - Z yields %.17e .\n", Z9); printf(" Should this NOT signal Underflow, "); printf("this is a SERIOUS DEFECT\nthat causes "); printf("confusion when innocent statements like\n");; printf(" if (X == Z) ... else"); printf(" ... (f(X) - f(Z)) / (X - Z) ...\n"); printf("encounter Division by Zero although actually\n"); sigsave = sigfpe; if (setjmp(ovfl_buf)) printf("X / Z fails!\n"); else printf("X / Z = 1 + %g .\n", (X / Z - Half) - Half); sigsave = 0; } } printf("The Underflow threshold is %.17e, %s\n", UfThold, " below which"); printf("calculation may suffer larger Relative error than "); printf("merely roundoff.\n"); Y2 = U1 * U1; Y = Y2 * Y2; Y2 = Y * U1; if (Y2 <= UfThold) { if (Y > E0) { BadCond(Defect, ""); I = 5; } else { BadCond(Serious, ""); I = 4; } printf("Range is too narrow; U1^%d Underflows.\n", I); } /*=============================================*/ /*SPLIT } #include "paranoia.h" part7(){ */ Milestone = 130; /*=============================================*/ Y = - FLOOR(Half - TwoForty * LOG(UfThold) / LOG(HInvrse)) / TwoForty; Y2 = Y + Y; printf("Since underflow occurs below the threshold\n"); printf("UfThold = (%.17e) ^ (%.17e)\nonly underflow ", HInvrse, Y); printf("should afflict the expression\n\t(%.17e) ^ (%.17e);\n", HInvrse, Y); V9 = POW(HInvrse, Y2); printf("actually calculating yields: %.17e .\n", V9); if (! ((V9 >= Zero) && (V9 <= (Radix + Radix + E9) * UfThold))) { BadCond(Serious, "this is not between 0 and underflow\n"); printf(" threshold = %.17e .\n", UfThold); } else if (! (V9 > UfThold * (One + E9))) printf("This computed value is O.K.\n"); else { BadCond(Defect, "this is not between 0 and underflow\n"); printf(" threshold = %.17e .\n", UfThold); } /*=============================================*/ Milestone = 140; /*=============================================*/ printf("\n"); /* ...calculate Exp2 == exp(2) == 7.389056099... */ X = Zero; I = 2; Y = Two * Three; Q = Zero; N = 0; do { Z = X; I = I + 1; Y = Y / (I + I); R = Y + Q; X = Z + R; Q = (Z - X) + R; } while(X > Z); Z = (OneAndHalf + One / Eight) + X / (OneAndHalf * ThirtyTwo); X = Z * Z; Exp2 = X * X; X = F9; Y = X - U1; printf("Testing X^((X + 1) / (X - 1)) vs. exp(2) = %.17e as X -> 1.\n", Exp2); for(I = 1;;) { Z = X - BInvrse; Z = (X + One) / (Z - (One - BInvrse)); Q = POW(X, Z) - Exp2; if (FABS(Q) > TwoForty * U2) { N = 1; V9 = (X - BInvrse) - (One - BInvrse); BadCond(Defect, "Calculated"); printf(" %.17e for\n", POW(X,Z)); printf("\t(1 + (%.17e) ^ (%.17e);\n", V9, Z); printf("\tdiffers from correct value by %.17e .\n", Q); printf("\tThis much error may spoil financial\n"); printf("\tcalculations involving tiny interest rates.\n"); break; } else { Z = (Y - X) * Two + Y; X = Y; Y = Z; Z = One + (X - F9)*(X - F9); if (Z > One && I < NoTrials) I++; else { if (X > One) { if (N == 0) printf("Accuracy seems adequate.\n"); break; } else { X = One + U2; Y = U2 + U2; Y += X; I = 1; } } } } /*=============================================*/ Milestone = 150; /*=============================================*/ printf("Testing powers Z^Q at four nearly extreme values.\n"); N = 0; Z = A1; Q = FLOOR(Half - LOG(C) / LOG(A1)); Break = False; do { X = CInvrse; Y = POW(Z, Q); IsYeqX(); Q = - Q; X = C; Y = POW(Z, Q); IsYeqX(); if (Z < One) Break = True; else Z = AInvrse; } while ( ! (Break)); PrintIfNPositive(); if (N == 0) printf(" ... no discrepancies found.\n"); printf("\n"); /*=============================================*/ Milestone = 160; /*=============================================*/ Pause(); printf("Searching for Overflow threshold:\n"); printf("This may generate an error.\n"); Y = - CInvrse; V9 = HInvrse * Y; sigsave = sigfpe; if (setjmp(ovfl_buf)) { I = 0; V9 = Y; goto overflow; } do { V = Y; Y = V9; V9 = HInvrse * Y; } while(V9 < Y); I = 1; overflow: sigsave = 0; Z = V9; printf("Can 'Z = -Y' overflow?\n"); printf("Trying it on Y = %.17e .\n", Y); V9 = - Y; V0 = V9; if (V - Y == V + V0) printf("Seems O.K.\n"); else { printf("finds a "); BadCond(Flaw, "-(-Y) differs from Y.\n"); } if (Z != Y) { BadCond(Serious, ""); printf("overflow past %.17e\n\tshrinks to %.17e .\n", Y, Z); } if (I) { Y = V * (HInvrse * U2 - HInvrse); Z = Y + ((One - HInvrse) * U2) * V; if (Z < V0) Y = Z; if (Y < V0) V = Y; if (V0 - V < V0) V = V0; } else { V = Y * (HInvrse * U2 - HInvrse); V = V + ((One - HInvrse) * U2) * Y; } printf("Overflow threshold is V = %.17e .\n", V); if (I) printf("Overflow saturates at V0 = %.17e .\n", V0); else printf("There is no saturation value because the system traps on overflow.\n"); V9 = V * One; printf("No Overflow should be signaled for V * 1 = %.17e\n", V9); V9 = V / One; printf(" nor for V / 1 = %.17e .\n", V9); printf("Any overflow signal separating this * from the one\n"); printf("above is a DEFECT.\n"); /*=============================================*/ Milestone = 170; /*=============================================*/ if (!(-V < V && -V0 < V0 && -UfThold < V && UfThold < V)) { BadCond(Failure, "Comparisons involving "); printf("+-%g, +-%g\nand +-%g are confused by Overflow.", V, V0, UfThold); } /*=============================================*/ Milestone = 175; /*=============================================*/ printf("\n"); for(Indx = 1; Indx <= 3; ++Indx) { switch (Indx) { case 1: Z = UfThold; break; case 2: Z = E0; break; case 3: Z = PseudoZero; break; } if (Z != Zero) { V9 = SQRT(Z); Y = V9 * V9; if (Y / (One - Radix * E9) < Z || Y > (One + Radix * E9) * Z) { /* dgh: + E9 --> * E9 */ if (V9 > U1) BadCond(Serious, ""); else BadCond(Defect, ""); printf("Comparison alleges that what prints as Z = %.17e\n", Z); printf(" is too far from sqrt(Z) ^ 2 = %.17e .\n", Y); } } } /*=============================================*/ Milestone = 180; /*=============================================*/ for(Indx = 1; Indx <= 2; ++Indx) { if (Indx == 1) Z = V; else Z = V0; V9 = SQRT(Z); X = (One - Radix * E9) * V9; V9 = V9 * X; if (((V9 < (One - Two * Radix * E9) * Z) || (V9 > Z))) { Y = V9; if (X < W) BadCond(Serious, ""); else BadCond(Defect, ""); printf("Comparison alleges that Z = %17e\n", Z); printf(" is too far from sqrt(Z) ^ 2 (%.17e) .\n", Y); } } /*=============================================*/ /*SPLIT } #include "paranoia.h" part8(){ */ Milestone = 190; /*=============================================*/ Pause(); X = UfThold * V; Y = Radix * Radix; if (X*Y < One || X > Y) { if (X * Y < U1 || X > Y/U1) BadCond(Defect, "Badly"); else BadCond(Flaw, ""); printf(" unbalanced range; UfThold * V = %.17e\n\t%s\n", X, "is too far from 1.\n"); } /*=============================================*/ Milestone = 200; /*=============================================*/ for (Indx = 1; Indx <= 5; ++Indx) { X = F9; switch (Indx) { case 2: X = One + U2; break; case 3: X = V; break; case 4: X = UfThold; break; case 5: X = Radix; } Y = X; sigsave = sigfpe; if (setjmp(ovfl_buf)) printf(" X / X traps when X = %g\n", X); else { V9 = (Y / X - Half) - Half; if (V9 == Zero) continue; if (V9 == - U1 && Indx < 5) BadCond(Flaw, ""); else BadCond(Serious, ""); printf(" X / X differs from 1 when X = %.17e\n", X); printf(" instead, X / X - 1/2 - 1/2 = %.17e .\n", V9); } sigsave = 0; } /*=============================================*/ Milestone = 210; /*=============================================*/ MyZero = Zero; printf("\n"); printf("What message and/or values does Division by Zero produce?\n") ; #ifndef NOPAUSE printf("This can interupt your program. You can "); printf("skip this part if you wish.\n"); printf("Do you wish to compute 1 / 0? "); fflush(stdout); read (KEYBOARD, ch, 8); if ((ch[0] == 'Y') || (ch[0] == 'y')) { #endif sigsave = sigfpe; printf(" Trying to compute 1 / 0 produces ..."); if (!setjmp(ovfl_buf)) printf(" %.7e .\n", One / MyZero); sigsave = 0; #ifndef NOPAUSE } else printf("O.K.\n"); printf("\nDo you wish to compute 0 / 0? "); fflush(stdout); read (KEYBOARD, ch, 80); if ((ch[0] == 'Y') || (ch[0] == 'y')) { #endif sigsave = sigfpe; printf("\n Trying to compute 0 / 0 produces ..."); if (!setjmp(ovfl_buf)) printf(" %.7e .\n", Zero / MyZero); sigsave = 0; #ifndef NOPAUSE } else printf("O.K.\n"); #endif /*=============================================*/ Milestone = 220; /*=============================================*/ Pause(); printf("\n"); { static char *msg[] = { "FAILUREs encountered =", "SERIOUS DEFECTs discovered =", "DEFECTs discovered =", "FLAWs discovered =" }; int i; for(i = 0; i < 4; i++) if (ErrCnt[i]) printf("The number of %-29s %d.\n", msg[i], ErrCnt[i]); } printf("\n"); if ((ErrCnt[Failure] + ErrCnt[Serious] + ErrCnt[Defect] + ErrCnt[Flaw]) > 0) { if ((ErrCnt[Failure] + ErrCnt[Serious] + ErrCnt[ Defect] == 0) && (ErrCnt[Flaw] > 0)) { printf("The arithmetic diagnosed seems "); printf("Satisfactory though flawed.\n"); } if ((ErrCnt[Failure] + ErrCnt[Serious] == 0) && ( ErrCnt[Defect] > 0)) { printf("The arithmetic diagnosed may be Acceptable\n"); printf("despite inconvenient Defects.\n"); } if ((ErrCnt[Failure] + ErrCnt[Serious]) > 0) { printf("The arithmetic diagnosed has "); printf("unacceptable Serious Defects.\n"); } if (ErrCnt[Failure] > 0) { printf("Potentially fatal FAILURE may have spoiled this"); printf(" program's subsequent diagnoses.\n"); } } else { printf("No failures, defects nor flaws have been discovered.\n"); if (! ((RMult == Rounded) && (RDiv == Rounded) && (RAddSub == Rounded) && (RSqrt == Rounded))) printf("The arithmetic diagnosed seems Satisfactory.\n"); else { if (StickyBit >= One && (Radix - Two) * (Radix - Nine - One) == Zero) { printf("Rounding appears to conform to "); printf("the proposed IEEE standard P"); if ((Radix == Two) && ((Precision - Four * Three * Two) * ( Precision - TwentySeven - TwentySeven + One) == Zero)) printf("754"); else printf("854"); if (IEEE) printf(".\n"); else { printf(",\nexcept for possibly Double Rounding"); printf(" during Gradual Underflow.\n"); } } printf("The arithmetic diagnosed appears to be Excellent!\n"); } } if (fpecount) printf("\nA total of %d floating point exceptions were registered.\n", fpecount); printf("END OF TEST.\n"); return 0; } /*SPLIT subs.c #include "paranoia.h" */ /* Sign */ FLOAT Sign (X) FLOAT X; { return X >= 0. ? 1.0 : -1.0; } /* Pause */ Pause() { #ifndef NOPAUSE char ch[8]; printf("\nTo continue, press RETURN"); fflush(stdout); read(KEYBOARD, ch, 8); #endif printf("\nDiagnosis resumes after milestone Number %d", Milestone); printf(" Page: %d\n\n", PageNo); ++Milestone; ++PageNo; } /* TstCond */ TstCond (K, Valid, T) int K, Valid; char *T; { if (! Valid) { BadCond(K,T); printf(".\n"); } } BadCond(K, T) int K; char *T; { static char *msg[] = { "FAILURE", "SERIOUS DEFECT", "DEFECT", "FLAW" }; ErrCnt [K] = ErrCnt [K] + 1; printf("%s: %s", msg[K], T); } /* Random */ /* Random computes X = (Random1 + Random9)^5 Random1 = X - FLOOR(X) + 0.000005 * X; and returns the new value of Random1 */ FLOAT Random() { FLOAT X, Y; X = Random1 + Random9; Y = X * X; Y = Y * Y; X = X * Y; Y = X - FLOOR(X); Random1 = Y + X * 0.000005; return(Random1); } /* SqXMinX */ SqXMinX (ErrKind) int ErrKind; { FLOAT XA, XB; XB = X * BInvrse; XA = X - XB; SqEr = ((SQRT(X * X) - XB) - XA) / OneUlp; if (SqEr != Zero) { if (SqEr < MinSqEr) MinSqEr = SqEr; if (SqEr > MaxSqEr) MaxSqEr = SqEr; J = J + 1.0; BadCond(ErrKind, "\n"); printf("sqrt( %.17e) - %.17e = %.17e\n", X * X, X, OneUlp * SqEr); printf("\tinstead of correct value 0 .\n"); } } /* NewD */ NewD() { X = Z1 * Q; X = FLOOR(Half - X / Radix) * Radix + X; Q = (Q - X * Z) / Radix + X * X * (D / Radix); Z = Z - Two * X * D; if (Z <= Zero) { Z = - Z; Z1 = - Z1; } D = Radix * D; } /* SR3750 */ SR3750() { if (! ((X - Radix < Z2 - Radix) || (X - Z2 > W - Z2))) { I = I + 1; X2 = SQRT(X * D); Y2 = (X2 - Z2) - (Y - Z2); X2 = X8 / (Y - Half); X2 = X2 - Half * X2 * X2; SqEr = (Y2 + Half) + (Half - X2); if (SqEr < MinSqEr) MinSqEr = SqEr; SqEr = Y2 - X2; if (SqEr > MaxSqEr) MaxSqEr = SqEr; } } /* IsYeqX */ IsYeqX() { if (Y != X) { if (N <= 0) { if (Z == Zero && Q <= Zero) printf("WARNING: computing\n"); else BadCond(Defect, "computing\n"); printf("\t(%.17e) ^ (%.17e)\n", Z, Q); printf("\tyielded %.17e;\n", Y); printf("\twhich compared unequal to correct %.17e ;\n", X); printf("\t\tthey differ by %.17e .\n", Y - X); } N = N + 1; /* ... count discrepancies. */ } } /* SR3980 */ SR3980() { do { Q = (FLOAT) I; Y = POW(Z, Q); IsYeqX(); if (++I > M) break; X = Z * X; } while ( X < W ); } /* PrintIfNPositive */ PrintIfNPositive() { if (N > 0) printf("Similar discrepancies have occurred %d times.\n", N); } /* TstPtUf */ TstPtUf() { N = 0; if (Z != Zero) { printf("Since comparison denies Z = 0, evaluating "); printf("(Z + Z) / Z should be safe.\n"); sigsave = sigfpe; if (setjmp(ovfl_buf)) goto very_serious; Q9 = (Z + Z) / Z; printf("What the machine gets for (Z + Z) / Z is %.17e .\n", Q9); if (FABS(Q9 - Two) < Radix * U2) { printf("This is O.K., provided Over/Underflow"); printf(" has NOT just been signaled.\n"); } else { if ((Q9 < One) || (Q9 > Two)) { very_serious: N = 1; ErrCnt [Serious] = ErrCnt [Serious] + 1; printf("This is a VERY SERIOUS DEFECT!\n"); } else { N = 1; ErrCnt [Defect] = ErrCnt [Defect] + 1; printf("This is a DEFECT!\n"); } } sigsave = 0; V9 = Z * One; Random1 = V9; V9 = One * Z; Random2 = V9; V9 = Z / One; if ((Z == Random1) && (Z == Random2) && (Z == V9)) { if (N > 0) Pause(); } else { N = 1; BadCond(Defect, "What prints as Z = "); printf("%.17e\n\tcompares different from ", Z); if (Z != Random1) printf("Z * 1 = %.17e ", Random1); if (! ((Z == Random2) || (Random2 == Random1))) printf("1 * Z == %g\n", Random2); if (! (Z == V9)) printf("Z / 1 = %.17e\n", V9); if (Random2 != Random1) { ErrCnt [Defect] = ErrCnt [Defect] + 1; BadCond(Defect, "Multiplication does not commute!\n"); printf("\tComparison alleges that 1 * Z = %.17e\n", Random2); printf("\tdiffers from Z * 1 = %.17e\n", Random1); } Pause(); } } } notify(s) char *s; { printf("%s test appears to be inconsistent...\n", s); printf(" PLEASE NOTIFY KARPINKSI!\n"); } /*SPLIT msgs.c */ /* Instructions */ msglist(s) char **s; { while(*s) printf("%s\n", *s++); } Instructions() { static char *instr[] = { "Lest this program stop prematurely, i.e. before displaying\n", " 'END OF TEST',\n", "try to persuade the computer NOT to terminate execution when an", "error like Over/Underflow or Division by Zero occurs, but rather", "to persevere with a surrogate value after, perhaps, displaying some", "warning. If persuasion avails naught, don't despair but run this", "program anyway to see how many milestones it passes, and then", "amend it to make further progress.\n", "Answer questions with Y, y, N or n (unless otherwise indicated).\n", 0}; msglist(instr); } /* Heading */ Heading() { static char *head[] = { "Users are invited to help debug and augment this program so it will", "cope with unanticipated and newly uncovered arithmetic pathologies.\n", "Please send suggestions and interesting results to", "\tRichard Karpinski", "\tComputer Center U-76", "\tUniversity of California", "\tSan Francisco, CA 94143-0704, USA\n", "In doing so, please include the following information:", #ifdef Single "\tPrecision:\tsingle;", #else "\tPrecision:\tdouble;", #endif "\tVersion:\t10 February 1989;", "\tComputer:\n", "\tCompiler:\n", "\tOptimization level:\n", "\tOther relevant compiler options:", 0}; msglist(head); } /* Characteristics */ Characteristics() { static char *chars[] = { "Running this program should reveal these characteristics:", " Radix = 1, 2, 4, 8, 10, 16, 100, 256 ...", " Precision = number of significant digits carried.", " U2 = Radix/Radix^Precision = One Ulp", "\t(OneUlpnit in the Last Place) of 1.000xxx .", " U1 = 1/Radix^Precision = One Ulp of numbers a little less than 1.0 .", " Adequacy of guard digits for Mult., Div. and Subt.", " Whether arithmetic is chopped, correctly rounded, or something else", "\tfor Mult., Div., Add/Subt. and Sqrt.", " Whether a Sticky Bit used correctly for rounding.", " UnderflowThreshold = an underflow threshold.", " E0 and PseudoZero tell whether underflow is abrupt, gradual, or fuzzy.", " V = an overflow threshold, roughly.", " V0 tells, roughly, whether Infinity is represented.", " Comparisions are checked for consistency with subtraction", "\tand for contamination with pseudo-zeros.", " Sqrt is tested. Y^X is not tested.", " Extra-precise subexpressions are revealed but NOT YET tested.", " Decimal-Binary conversion is NOT YET tested for accuracy.", 0}; msglist(chars); } History() { /* History */ /* Converted from Brian Wichmann's Pascal version to C by Thos Sumner, with further massaging by David M. Gay. */ static char *hist[] = { "The program attempts to discriminate among", " FLAWs, like lack of a sticky bit,", " Serious DEFECTs, like lack of a guard digit, and", " FAILUREs, like 2+2 == 5 .", "Failures may confound subsequent diagnoses.\n", "The diagnostic capabilities of this program go beyond an earlier", "program called 'MACHAR', which can be found at the end of the", "book 'Software Manual for the Elementary Functions' (1980) by", "W. J. Cody and W. Waite. Although both programs try to discover", "the Radix, Precision and range (over/underflow thresholds)", "of the arithmetic, this program tries to cope with a wider variety", "of pathologies, and to say how well the arithmetic is implemented.", "\nThe program is based upon a conventional radix representation for", "floating-point numbers, but also allows logarithmic encoding", "as used by certain early WANG machines.\n", "BASIC version of this program (C) 1983 by Prof. W. M. Kahan;", "see source comments for more history.", 0}; msglist(hist); } double pow(x, y) /* return x ^ y (exponentiation) */ double x, y; { extern double exp(), frexp(), ldexp(), log(), modf(); double xy, ye; long i; int ex, ey = 0, flip = 0; if (!y) return 1.0; if ((y < -1100. || y > 1100.) && x != -1.) return exp(y * log(x)); if (y < 0.) { y = -y; flip = 1; } y = modf(y, &ye); if (y) xy = exp(y * log(x)); else xy = 1.0; /* next several lines assume >= 32 bit integers */ x = frexp(x, &ex); if (i = ye) for(;;) { if (i & 1) { xy *= x; ey += ex; } if (!(i >>= 1)) break; x *= x; ex *= 2; if (x < .5) { x *= 2.; ex -= 1; } } if (flip) { xy = 1. / xy; ey = -ey; } return ldexp(xy, ey); } #endif /* NO_FLOATS */ ��������������������������������������������������������������������������������������������cc65-2.18/test/ref/pointer2.c�����������������������������������������������������������������������0000664�0000000�0000000�00000004147�13473601511�0015654�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! pointer test !!ORIGIN!! !!LICENCE!! public domain */ #include "common.h" #include <stdio.h> /* check behaviour on incompletely declared arrays */ char i1[]; void test1(void) { int a; a=sizeof(i1[0]); printf("%04x - ",a); if(sizeof(i1[0])==sizeof(char)) { /* gcc gives size of element */ printf("sizeof(i1[0]) gives size of element\n"); } if(sizeof(i1[0])==sizeof(char*)) { printf("sizeof(i1[0]) gives size of pointer to element\n"); } } /* check behaviour on string init */ char t1[]="abcde"; char t2[]={"abcde"}; char *t3="abcde"; char *t4={"abcde"}; void test2(void) { char c1,c2,c3,c4; int i,e=0; for(i=0;i<5;i++){ c1=t1[i];c2=t2[i];c3=t3[i];c4=t4[i]; /* printf("%02x %02x %02x %02x\n",c1,c2,c3,c4); */ printf("%c %c %c %c\n",c1,c2,c3,c4); if(!((c1==c2)&(c1==c3)&(c1==c4))) e=1; } if(e) printf("test2 failed.\n"); else printf("test2 ok.\n"); } /* check behaviour on extern-declarations inside functions */ typedef struct { char *name; void *func; } A3; #ifdef NO_SLOPPY_STRUCT_INIT A3 a3[] = { { "test3", (void*) NULL }, { "test3", (void*) NULL }, }; #else /*gcc warning: missing braces around initializer (near initialization for `a3[0]') this type of struct-initialization seems to be kinda common */ A3 a3[] = { "test3", (void*) NULL , "test3", (void*) NULL , }; #endif void test3a(A3 *list, int number){ printf("%s %d\n",list->name,number); } static void test31(void) { extern A3 a3[]; test3a(a3, -1); } #if 0 /* this variation compiles and works with cc65, but gives an error with gcc :=P */ static void test32(void) { extern A3 *a3; test3a(a3, -1); } #endif static void test30(void) { test3a(a3, -1); } /* todo: add test on function pointers in the form of (*func)(arg) ... cc65 seems to have problems here aswell ;/ */ int main(void) { test1(); test2(); test30(); test31(); /* test32(); */ return 0; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/return.c�������������������������������������������������������������������������0000664�0000000�0000000�00000003116�13473601511�0015424�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! return values, implicit type conversion on return !!ORIGIN!! cc65 devel list !!LICENCE!! Public Domain */ #include <stdio.h> #include <stdlib.h> unsigned char val_char=0x76; unsigned int val_int=0x5678; unsigned long val_long=0x12345678; int test1_int_char(void) { return val_char; } int test1_int_int(void) { return val_int; } int test2_int_char(void) { return (int)val_char; } int test2_int_int(void) { return (int)val_int; } long test1_long_char(void) { return val_char; } long test1_long_int(void) { return val_int; } long test1_long_long(void) { return val_long; } long test2_long_char(void) { return (long)val_char; } long test2_long_int(void) { return (long)val_int; } long test2_long_long(void) { return (long)val_long; } #define dotest(_n,_a,_v) \ _n=_a; \ printf("%04lx %04lx,",(unsigned long)_n,(unsigned long)_v); \ if(_n!=_v) printf("failed\n"); \ else printf("ok\n") int main(void) { int i; unsigned long l; printf("\nwithout cast:\n"); printf("return int\n"); dotest(i,test1_int_char(),0x76); dotest(i,test1_int_int(),0x5678); printf("return long\n"); dotest(l,test1_long_char(),0x76); dotest(l,test1_long_int(),0x5678); dotest(l,test1_long_long(),0x12345678); printf("\nwith cast:\n"); printf("return int\n"); dotest(i,test2_int_char(),0x76); dotest(i,test2_int_int(),0x5678); printf("return long\n"); dotest(l,test2_long_char(),0x76); dotest(l,test2_long_int(),0x5678); dotest(l,test2_long_long(),0x12345678); return 0; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/sort.c���������������������������������������������������������������������������0000664�0000000�0000000�00000003047�13473601511�0015077�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! simple quicksort, tests recursion !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include <stdlib.h> #include <stdio.h> int in[] = {10, 32, -1, 567, 3, 18, 1, -51, 789, 0}; int *xx; /* exchange - exchange *x and *y */ exchange(int *x,int *y) { int t; printf("exchange(%d,%d)\n", x - xx, y - xx); t = *x; *x = *y; *y = t; } /* partition - partition a[i..j] */ int partition(int a[], int i, int j) { int v, k; j++; k = i; v = a[k]; while (i < j) { i++; while (a[i] < v) i++; j--; while (a[j] > v) j--; if (i < j) exchange(&a[i], &a[j]); } exchange(&a[k], &a[j]); return j; } /* quick - quicksort a[lb..ub] */ void quick(int a[], int lb, int ub) { int k; if (lb >= ub) return; k = partition(a, lb, ub); quick(a, lb, k - 1); quick(a, k + 1, ub); } /* sort - sort a[0..n-1] into increasing order */ sort(int a[], int n) { quick(xx = a, 0, --n); } /* putd - output decimal number */ void putd(int n) { if (n < 0) { putchar('-'); n = -n; } if (n/10) putd(n/10); putchar(n%10 + '0'); } int main(void) { int i; sort(in, (sizeof in)/(sizeof in[0])); for (i = 0; i < (sizeof in)/(sizeof in[0]); i++) { putd(in[i]); putchar('\n'); } return 0; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/spill.c��������������������������������������������������������������������������0000664�0000000�0000000�00000002240�13473601511�0015225�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! register spilling !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include "common.h" #include <stdio.h> int main(void) { printf("disassemble this program to check the generated code.\n"); return 0; } #ifdef NO_EMPTY_FUNC_ARGS f(i){return i+i;} f2(i){return f(i)+(i?f(i):1);} f3(int i,int *p){ register r1=0,r2=0,r3=0,r4=0,r5=0,r6=0,r7=0,r8=0,r9=0,r10=0; *p++=i?f(i):0; } #else f(i){i=f()+f();} f2(i){i=f()+(i?f():1);} f3(int i,int *p){ register r1=0,r2=0,r3=0,r4=0,r5=0,r6=0,r7=0,r8=0,r9=0,r10=0; *p++=i?f():0; } #endif #ifdef NO_FLOATS signed a[10],b[10]; #else double a[10],b[10]; #endif int i; f4(){ register r6=0,r7=0,r8=0,r9=0,r10=0,r11=0; i=a[i]+b[i] && i && a[i]-b[i]; } /* f4 causes parent to spill child on vax when odd double regs are enabled */ int j, k, m, n; #ifdef NO_FLOATS signed *A, *B, x; #else double *A, *B, x; #endif f5(){ x=A[k*m]*A[j*m]+B[k*n]*B[j*n]; x=A[k*m]*B[j*n]-B[k*n]*A[j*m]; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/stdarg.c�������������������������������������������������������������������������0000664�0000000�0000000�00000005703�13473601511�0015375�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! variable argument lists !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include "common.h" #include <stdarg.h> #ifndef NO_FUNCS_TAKE_STRUCTS struct node { int a[4]; } x = { #ifdef NO_SLOPPY_STRUCT_INIT { #endif 1,2,3,4 #ifdef NO_SLOPPY_STRUCT_INIT } #endif }; #endif print(char *fmt, ...); main() { print("test 1\n"); print("test %s\n", "2"); print("test %d%c", 3, '\n'); print("%s%s %w%c", "te", "st", 4, '\n'); #ifdef NO_FLOATS print("%s%s %f%c", "te", "st", (signed long) 5, '\n'); #else print("%s%s %f%c", "te", "st", 5.0, '\n'); #endif #ifndef NO_FUNCS_TAKE_STRUCTS print("%b %b %b %b %b %b\n", x, x, x, x, x, x); #endif return 0; } print(char *fmt, ...) { va_list ap; va_start(ap, fmt); for (; *fmt; fmt++) { if (*fmt == '%') switch (*++fmt) { case 'b': { #ifdef NO_FUNCS_TAKE_STRUCTS printf("(1 2 3 4)"); #else struct node x = va_arg( ap, struct node ); printf("(%d %d %d %d)", x.a[0], x.a[1], x.a[2], x.a[3]); #endif break; } case 'c': /* printf("%c", va_arg(ap, char)); */ printf("%c", va_arg(ap, int)); break; case 'd': printf("%d", va_arg(ap, int)); break; case 'w': /* printf("%x", va_arg(ap, short)); */ printf("%x", va_arg(ap, int)); break; case 's': printf("%s", va_arg(ap, char *)); break; case 'f': #ifdef NO_FLOATS printf("%ld.000000", va_arg(ap, signed long)); #else printf("%f", va_arg(ap, double)); #endif break; default: printf("%c", *fmt); break; } else printf("%c", *fmt); } va_end(ap); } �������������������������������������������������������������cc65-2.18/test/ref/strptr.c�������������������������������������������������������������������������0000664�0000000�0000000�00000005745�13473601511�0015455�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! !!ORIGIN!! testsuite !!LICENCE!! Public Domain !!AUTHOR!! Groepaz/Hitmen */ /* this test reproduces a bug that prevented the testsuites directory reading stuff for the c64 from working before. the bug appears to only occur when optimizations are enabled. it also disappears if the buffers inside the readdir function are declared static or made global. */ /*#define STANDALONE*/ #ifdef STANDALONE FILE *outfile=NULL; #define OPENTEST() outfile=stdout; #define CLOSETEST() #else #endif #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <string.h> #define XNAME_MAX 16 struct Xdirent { char d_name[XNAME_MAX+1]; unsigned short d_off; unsigned short d_reclen; unsigned char d_type; unsigned char d_namlen; }; typedef struct { unsigned char fd; unsigned short off; char name[XNAME_MAX+1]; } XDIR; unsigned char b1[4]; unsigned char b2[0x10]={" \"test\" "}; struct Xdirent *Xreaddir(XDIR *dir) { unsigned char buffer[0x40]; unsigned char temp; unsigned char i,ii; static struct Xdirent entry; unsigned char fd; static unsigned char ch; entry.d_off=dir->off; /* basic line-link / file-length */ memcpy(buffer,b1,4); dir->off=dir->off+4; entry.d_reclen=254*(buffer[2]+(buffer[3]<<8)); /* read file entry */ memcpy(buffer,b2,0x10); dir->off=dir->off+i; printf("Xreaddir: '%s'\n",buffer); /* skip until either quote (file) or b (blocks free => end) */ i=0;ii=0; while(i==0){ temp=buffer[ii];ii++; if(ii>16){ /* something went wrong...this shouldnt happen! */ return(NULL); } else if(temp=='\"') i++; else if(temp=='b') { /* "blocks free" */ return(NULL); } } printf("Xreaddir: '%s'\n",buffer); /* process file entry */ i=0; temp=buffer[ii];ii++; while(temp!='\"'){ entry.d_name[i]=temp; i++; temp=buffer[ii];ii++; } entry.d_name[i]=0; entry.d_namlen=i; /* set type flag */ return(&entry); } int main(void) { char mydirname[XNAME_MAX+1]="."; XDIR mydir; struct Xdirent *mydirent; printf("start\n"); if((mydirent=Xreaddir(&mydir))==NULL) { printf("NULL\n"); } else { printf("=%s\n",mydirent->d_name); } printf("done\n"); return 0; } ���������������������������cc65-2.18/test/ref/struct.c�������������������������������������������������������������������������0000664�0000000�0000000�00000014002�13473601511�0015425�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! structs !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include "common.h" typedef struct point { int x,y; } point; typedef struct rect { point pt1, pt2; } rect; #define min(a, b) ((a) < (b) ? (a) : (b)) #define max(a, b) ((a) > (b) ? (a) : (b)) #ifdef NO_FUNCS_RETURN_STRUCTS # ifdef NO_FUNCS_TAKE_STRUCTS /* canonicalize rectangle coordinates */ void canonrect(rect *d,rect *r) { d->pt1.x = min(r->pt1.x, r->pt2.x); d->pt1.y = min(r->pt1.y, r->pt2.y); d->pt2.x = max(r->pt1.x, r->pt2.x); d->pt2.y = max(r->pt1.y, r->pt2.y); } /* add two points */ void addpoint(point *p, point *p1, point *p2) { p->x= p1->x + p2->x; p->y= p1->y + p2->y; } /* make a point from x and y components */ void makepoint(point *p,int x, int y) { p->x = x; p->y = y; } /* make a rectangle from two points */ void makerect(rect *d,point *p1, point *p2) { rect r; r.pt1.x = p1->x; r.pt1.y = p1->y; r.pt2.x = p2->x; r.pt2.y = p2->y; canonrect(d,&r); } #ifdef NO_SLOPPY_STRUCT_INIT struct odd {char a[3]; } y = {{'a', 'b', 0 }}; #else struct odd {char a[3]; } y = {'a', 'b', 0}; #endif odd(struct odd *y) { struct odd *x = y; printf("%s\n\r", x->a); } # else /* FUNCS_TAKE_STRUCTS */ /* canonicalize rectangle coordinates */ void canonrect(rect *d,rect r) { d->pt1.x = min(r.pt1.x, r.pt2.x); d->pt1.y = min(r.pt1.y, r.pt2.y); d->pt2.x = max(r.pt1.x, r.pt2.x); d->pt2.y = max(r.pt1.y, r.pt2.y); } /* add two points */ void addpoint(point *p, point p1, point p2) { p->x= p1.x + p2.x; p->y= p1.y + p2.y; } /* make a point from x and y components */ void makepoint(point *p,int x, int y) { p->x = x; p->y = y; } /* make a rectangle from two points */ void makerect(rect *d,point p1, point p2) { rect r; r.pt1 = p1; r.pt2 = p2; canonrect(d,r); } #ifdef NO_SLOPPY_STRUCT_INIT struct odd {char a[3]; } y = {{'a', 'b', 0}}; #else struct odd {char a[3]; } y = {'a', 'b', 0}; #endif odd(struct odd y) { struct odd x = y; printf("%s\n\r", x.a); } # endif /* FUNCS_TAKE_STRUCTS */ #else /* FUNCS_RETURN_STRUCTS */ /* add two points */ point addpoint(point p1, point p2) { p1.x += p2.x; p1.y += p2.y; return p1; } /* canonicalize rectangle coordinates */ rect canonrect(rect r) { rect temp; temp.pt1.x = min(r.pt1.x, r.pt2.x); temp.pt1.y = min(r.pt1.y, r.pt2.y); temp.pt2.x = max(r.pt1.x, r.pt2.x); temp.pt2.y = max(r.pt1.y, r.pt2.y); return temp; } /* make a point from x and y components */ point makepoint(int x, int y) { point p; p.x = x; p.y = y; return p; } /* make a rectangle from two points */ rect makerect(point p1, point p2) { rect r; r.pt1 = p1; r.pt2 = p2; return canonrect(r); } struct odd {char a[3]; } y = { #ifdef NO_SLOPPY_STRUCT_INIT { #endif 'a', 'b', 0 #ifdef NO_SLOPPY_STRUCT_INIT } #endif }; odd(struct odd y) { struct odd x = y; printf("%s\n\r", x.a); } #endif /* is p in r? */ # ifdef NO_FUNCS_TAKE_STRUCTS int ptinrect(point *p, rect *r) { return p->x >= r->pt1.x && p->x < r->pt2.x && p->y >= r->pt1.y && p->y < r->pt2.y; } #else int ptinrect(point p, rect r) { return p.x >= r.pt1.x && p.x < r.pt2.x && p.y >= r.pt1.y && p.y < r.pt2.y; } #endif #ifdef NO_FUNCS_RETURN_STRUCTS #ifdef NO_LOCAL_STRUCT_INIT #ifdef NO_SLOPPY_STRUCT_INIT point pts[] = { {-1, -1},{ 1, 1},{ 20, 300},{ 500, 400 } }; #else point pts[] = { -1, -1, 1, 1, 20, 300, 500, 400 }; #endif point origin = { 0, 0 }; point maxpt = { 320, 320 }; #endif main() { int i; point x; rect screen; #ifndef NO_LOCAL_STRUCT_INIT point origin = { 0, 0 }; point maxpt = { 320, 320 }; #ifdef NO_SLOPPY_STRUCT_INIT point pts[] = { {-1, -1},{ 1, 1},{ 20, 300},{ 500, 400 } }; #else point pts[] = { -1, -1, 1, 1, 20, 300, 500, 400 }; #endif #endif makepoint ( &x, -10, -10); #ifdef NO_FUNCS_TAKE_STRUCTS addpoint ( &maxpt, &maxpt, &x); #else addpoint ( &maxpt, maxpt, x); #endif makepoint ( &x, 10, 10); #ifdef NO_FUNCS_TAKE_STRUCTS addpoint (&origin,&origin, &x); makerect (&screen, &maxpt,&origin); #else addpoint (&origin,origin, x); makerect (&screen, maxpt,origin); #endif for (i = 0; i < sizeof pts/sizeof pts[0]; i++) { makepoint(&x,pts[i].x, pts[i].y); printf("(%d,%d) is ", pts[i].x, x.y); #ifdef NO_FUNCS_TAKE_STRUCTS if (ptinrect(&x, &screen) == 0) #else if (ptinrect(x, screen) == 0) #endif { printf("not "); } printf("within (%d,%d; %d,%d)\n\r", screen.pt1.x, screen.pt1.y, screen.pt2.x, screen.pt2.y); } #ifdef NO_FUNCS_TAKE_STRUCTS odd(&y); #else odd(y); #endif return 0; } #else /* FUNCS_RETURN_STRUCTS */ main() { int i; point x, origin = { 0, 0 }, maxpt = { 320, 320 }; #ifdef NO_SLOPPY_STRUCT_INIT point pts[] = { {-1, -1}, {1, 1}, {20, 300}, {500, 400} }; #else point pts[] = { -1, -1, 1, 1, 20, 300, 500, 400 }; #endif rect screen = makerect( addpoint(maxpt, makepoint(-10, -10)), addpoint(origin, makepoint(10, 10)) ); test1(); for (i = 0; i < sizeof pts/sizeof pts[0]; i++) { printf("(%d,%d) is ", pts[i].x, (x = makepoint(pts[i].x, pts[i].y)).y); if (ptinrect(x, screen) == 0) printf("not "); printf("within (%d,%d; %d,%d)\n\r", screen.pt1.x, screen.pt1.y, screen.pt2.x, screen.pt2.y); } odd(y); return 0; } #endif /* FUNCS_RETURN_STRUCTS */ ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/switch.c�������������������������������������������������������������������������0000664�0000000�0000000�00000012440�13473601511�0015406�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! switch statement !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include "common.h" #include <limits.h> #ifdef NO_IMPLICIT_FUNC_PROTOTYPES testbig(); testbackslash(); backslash(int c); f(); g(); h(); limit(); big( # ifdef ASSUME_32BIT_UNSIGNED unsigned # else unsigned long # endif x); #endif main() { testbackslash(); f(); g(); h(); testbig(); /* ! broken long int compare (?) */ limit(); /* ! broken long int compare (?) */ return 0; } testbig() { #ifdef ASSUME_32BIT_INT int i; #else signed long i; #endif /* 2341234 2341234 2341234 */ for (i = 0x1000000; i&0x7000000; i += 0x1000000) { /* printf("i = 0x%lx\n", i); */ big(i); } } #ifdef NO_LOCAL_STRING_INIT /* static char _s[8]={"bfnrtvx"}; */ static char _s[8]="bfnrtvx"; #endif testbackslash() { char *s; #ifdef NO_STRINGS_IN_FOR # ifndef NO_LOCAL_STRING_INIT char _s[8]={"bfnrtvx"}; # endif for (s=_s; *s; s++) { #else for (s = "bfnrtvx"; *s; s++) { #endif printf("%c = %c\n", *s, backslash(*s)); } } backslash(c) { switch (c) { case 'b': return 'b'; case 'f': return 'f'; case 'n': return 'n'; case 'r': return 'r'; case 't': return 't'; case 'v': return 'v'; } return 'x'; } f() { int i, x = 0, y; printf("f:\n"); for (i = 0; i <= 20; i++) { y = i; switch (i) { case 1: x = i; break; case 2: x = i; break; case 7: x = i; break; case 8: x = i; break; case 9: x = i; break; case 16: x = i; break; case 17: x = i; break; case 18: x = i; break; case 19: x = i; break; case 20: x = i; break; } printf("x = %d\n", x); } } g() { int i; printf("g:\n"); for (i = 1; i <= 10; i++) switch (i) { case 1: case 2: printf("1 %d\n", i); break; case 3: case 4: case 5: printf("2 %d\n", i); break; case 6: case 7: case 8: printf("3 %d\n", i); default: printf("d %d\n", i); break; case 1001: case 1002: case 1003: case 1004: printf("5 %d\n", i); break; case 3001: case 3002: case 3003: case 3004: printf("6 %d\n", i); break; } } h() { int i, n=0; printf("h:\n"); for (i = 1; i <= 500; i++) switch (i) { default: n++; continue; case 128: printf("i = %d\n", i); break; case 16: printf("i = %d\n", i); break; case 8: printf("i = %d\n", i); break; case 120: printf("i = %d\n", i); break; case 280: printf("i = %d\n", i); break; case 264: printf("i = %d\n", i); break; case 248: printf("i = %d\n", i); break; case 272: printf("i = %d\n", i); break; case 304: printf("i = %d\n", i); break; case 296: printf("i = %d\n", i); break; case 288: printf("i = %d\n", i); break; case 312: printf("i = %d\n", i); break; } printf("%d defaults\n", n); } #ifdef NO_OLD_FUNC_DECL big( #else big(x) #endif # ifdef ASSUME_32BIT_UNSIGNED unsigned # else unsigned long # endif #ifdef NO_OLD_FUNC_DECL x) { #else x; { #endif /* printf("x = 0x%x\n", x); */ switch(x&0x6000000){ case -1: case -2: case 0x0000000: printf("x = 0x%lx\n", x); break; case 0x2000000: printf("x = 0x%lx\n", x); break; case 0x4000000: printf("x = 0x%lx\n", x); break; default: printf("x = 0x%lx (default)\n", x); break; } } limit() { int i; for (i = INT_MIN; i <= INT_MIN+5; i++) /* for (i = INT_MIN; i < INT_MIN+6; i++) */ switch (i) { case INT_MIN: printf("0\n"); break; case INT_MIN+1: printf("1\n"); break; case INT_MIN+2: printf("2\n"); break; case INT_MIN+3: printf("3\n"); break; case INT_MIN+4: printf("4\n"); break; default: printf("5\n"); break; } for (i = INT_MAX; i >= INT_MAX-5; i--) switch (i) { case INT_MAX: printf("0\n"); break; case INT_MAX-1: printf("1\n"); break; case INT_MAX-2: printf("2\n"); break; case INT_MAX-3: printf("3\n"); break; case INT_MAX-4: printf("4\n"); break; default: printf("5\n"); break; } } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/switch2.c������������������������������������������������������������������������0000664�0000000�0000000�00000015452�13473601511�0015476�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! switch test !!ORIGIN!! !!LICENCE!! public domain */ /*#define STANDALONE*/ #include <stdio.h> void testlimits(int i) { printf("%d:",i); switch(i) { case -1: /* works */ /* case 0xffff: */ /* 'range error' (-1) */ printf("-1\n"); break; /* max int */ /* case 0x7fff: */ /* works */ case 32767: /* works */ /* case 32768: */ /* 'range error' (correct for that one!) */ printf("max\n"); break; /* min int */ case -32768: /* 'warning. constant is long' */ /* case 0x8000: */ /* 'range error' */ /* case -32769: */ /* 'range error' (correct for that one!) */ printf("min\n"); break; } printf("\n"); } void testdefault1(unsigned char i) { /* we want a signed char */ #ifdef REFCC #ifdef REFCC_UNSIGNED_CHARS signed char k; #else char k; #endif #else #ifdef UNSIGNED_CHARS signed char k; #else char k; #endif #endif for(;i<254;) { k = i; printf(">%d\n",i);i++; switch(k) { case 1: break; case 2: break; case 3: break; case 4: break; case 5: break; case 6: break; case 7: break; case 8: break; case 9: break; case 10: break; case 11: break; case 12: break; case 13: break; case 14: break; case 15: break; case 17: break; /* triggers bug ? */ /* gcc warning: case label value exceeds maximum value for type */ /* cc65 error: range error */ /* case 170: break; */ case 18: break; case 19: break; case 20: break; case 21: break; case 22: break; case 23: break; case 24: switch(k) { case 1: break; case 2: break; case 3: break; case 4: case 5: break; case 6: case 7: break; case 8: case 9: break; } break; case 100: break; default: printf(">>>default\n"); /* triggers bug if this break; is missing? */ /* break; */ } } } void testdefault2(unsigned char i) { /* we want a unsigned char */ #ifdef REFCC #ifdef REFCC_UNSIGNED_CHARS char k; #else unsigned char k; #endif #else #ifdef UNSIGNED_CHARS char k; #else unsigned char k; #endif #endif for(;i<254;) { k = i; printf(">%d\n",i);i++; switch(k) { case 1: break; case 2: break; case 3: break; case 4: break; case 5: break; case 6: break; case 7: break; case 8: break; case 9: break; case 10: break; case 11: break; case 12: break; case 13: break; case 14: break; case 15: break; case 17: break; /* triggers bug ? */ case 170: break; case 18: break; case 19: break; case 20: break; case 21: break; case 22: break; case 23: break; case 24: switch(k) { case 1: break; case 2: break; case 3: break; case 4: case 5: break; case 6: case 7: break; case 8: case 9: break; } break; case 100: break; default: printf(">>>default\n"); /* triggers bug if this break; is missing? */ /* break; */ } } } int main(void) { testlimits(32767); testlimits(-32768); testlimits(-1); testdefault1(1); testdefault1(2); testdefault1(3); testdefault1(4); testdefault2(1); testdefault2(2); testdefault2(3); testdefault2(4); return 0; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/varargs.c������������������������������������������������������������������������0000664�0000000�0000000�00000004343�13473601511�0015555�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! varargs test !!ORIGIN!! !!LICENCE!! public domain */ #include <stdlib.h> #include <stdio.h> #include <stdarg.h> void chk0(char *format,...); void chk1(int fd,char *format,...); #if 0 // old workaround for broken varargs void chk0(char *format,...){ __asm__ ("pha"); // save argument size { //va_list ap; char *ap; char *_format; static char string[0x100]; // va_start(ap,format); __asm__ ("pla"); // restore argument size __asm__ ("ldx #$00"); // clear hibyte of AX ap=__AX__; ap+=(char*)&format; // get value of format ap-=2; _format=*((char**)ap); // vsprintf(string,format,ap); vsprintf(&string[0],_format,ap); printf("format:%s,string:%s\n",_format,string); // va_end(ap); } } void chk1(int fd,char *format,...){ __asm__ ("pha"); // save argument size { //va_list ap; char *ap; char *_format; int _fd; static char string[0x100]; // va_start(ap,format); __asm__ ("pla"); // restore argument size __asm__ ("ldx #$00"); // clear hibyte of AX ap=__AX__; ap+=(char*)&format; // get value of fd ap-=2; _fd=*((int*)ap); // get value of format ap-=2; _format=*((char**)ap); // vsprintf(string,format,ap); vsprintf(&string[0],_format,ap); printf("fd:%d,format:%s,string:%s\n",_fd,_format,string); // va_end(ap); } } #endif void chk0(char *format,...){ va_list ap; static char string[0x100]; va_start(ap,format); vsprintf(string,format,ap); printf("format:%s,string:%s\n",format,string); va_end(ap); } void chk1(int fd,char *format,...){ va_list ap; static char string[0x100]; va_start(ap,format); vsprintf(string,format,ap); printf("fd:%d,format:%s,string:%s\n",fd,format,string); va_end(ap); } int main(int argc,char **argv) { printf("varargs test\n"); printf("\nchk0/0:\n");chk0("chk0 %s","arg0"); printf("\nchk0/1:\n");chk0("chk0 %s %s","arg0","arg1"); printf("\nchk0/2:\n");chk0("chk0 %s %s %s","arg0","arg1","arg2"); printf("\nchk1/0:\n");chk1(0xfd,"chk1 %s","arg0"); printf("\nchk1/1:\n");chk1(0xfd,"chk1 %s %s","arg0","arg1"); printf("\nchk1/2:\n");chk1(0xfd,"chk1 %s %s %s","arg0","arg1","arg2"); return 0; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/wf1.c����������������������������������������������������������������������������0000664�0000000�0000000�00000006341�13473601511�0014605�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! print word frequencies; uses structures !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include <stdlib.h> #include <stdio.h> #include <string.h> #include <ctype.h> #define MAXWORDS 250 FILE *in; #define getchar() fgetc(in) struct node { int count; /* frequency count */ struct node *left; /* left subtree */ struct node *right; /* right subtree */ char *word; /* word itself */ } words[MAXWORDS]; int next; /* index of next free entry in words */ /*struct node *lookup();*/ #if defined(NO_NEW_PROTOTYPES_FOR_OLD_FUNC_DECL) && !defined(NO_OLD_FUNC_DECL) #else int err(char *s); int getword(char *buf); void tprint(struct node *tree); struct node *lookup(char *word, struct node **p); #endif int isletter(char c); /* err - print error message s and die */ #ifndef NO_OLD_FUNC_DECL err(s) char *s; { #else int err(char *s) { #endif printf("? %s\n", s); exit(1); } /* getword - get next input word into buf, return 0 on EOF */ #ifndef NO_OLD_FUNC_DECL int getword(buf) char *buf; #else int getword(char *buf) #endif { char *s; int c; while (((c = getchar()) != -1) && (isletter(c) == 0)) ; for (s = buf; (c = isletter(c)); c = getchar()) *s++ = c; *s = 0; if (s > buf) return 1; return 0; } /* isletter - return folded version of c if it is a letter, 0 otherwise */ int isletter(char c) { if ((c >= 'A') && (c <= 'Z')) c += 'a' - 'A'; if ((c >= 'a') && (c <= 'z')) return c; return 0; } /* lookup - lookup word in tree; install if necessary */ #ifndef NO_OLD_FUNC_DECL struct node *lookup(word, p) char *word; struct node **p; #else struct node *lookup(char *word, struct node **p) #endif { int cond; /* char *malloc(); */ if (*p) { cond = strcmp(word, (*p)->word); if (cond < 0) return lookup(word, &(*p)->left); else if (cond > 0) return lookup(word, &(*p)->right); else return *p; } if (next >= MAXWORDS) err("out of node storage"); words[next].count = 0; words[next].left = words[next].right = 0; words[next].word = malloc(strlen(word) + 1); if (words[next].word == 0) err("out of word storage"); strcpy(words[next].word, word); return *p = &words[next++]; } /* tprint - print tree */ #ifndef NO_OLD_FUNC_DECL void tprint(tree) struct node *tree; { #else void tprint(struct node *tree) { #endif if (tree) { tprint(tree->left); printf("%d:%s\n", tree->count, tree->word); tprint(tree->right); } } int main(void) { struct node *root; char word[20]; in = fopen("wf1.in","rb"); if (in == NULL) { return EXIT_FAILURE; } root = 0; next = 0; while (getword(word)) lookup(word, &root)->count++; tprint(root); fclose(in); return 0; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/wf1.in���������������������������������������������������������������������������0000664�0000000�0000000�00000001674�13473601511�0014775�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������The sky above the port was the color of television, tuned to a dead channel. "It's not like I'm using," Case heard someone say, as he shouldered his way through the crowd around the door of the Chat. "It's like my body's developed this massive drug deficiency." It was a Sprawl voice and a Sprawl joke. The Chatsubo was a bar for professional expatriates; you could drink there for a week and never hear two words in Japanese. Ratz was tending bar, his prosthetic arm jerking monotonously as he filled a tray of glasses with draft Kirin. He saw Case and smiled, his teeth a web work of East European steel and brown decay. Case found a place at the bar, between the unlikely tan on one of Lonny Zone's whores and the crisp naval uniform of a tall African whose cheekbones were ridged with Joe boys," Ratz said, shoving a draft across the bar with his good hand. "Maybe some business with you, Case?" Case shrugged. The girl to his right giggled and nudged ��������������������������������������������������������������������cc65-2.18/test/ref/yacc.c���������������������������������������������������������������������������0000664�0000000�0000000�00000071307�13473601511�0015033�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ /*#define STANDALONE*/ #include "common.h" #ifndef YACCDBG #include <stdio.h> #include <stdlib.h> #include <ctype.h> /* #define LEXDEBUG #define YYDEBUG */ #endif FILE *infile, *outfile; #define getchar() fgetc(infile) /* hack the original tables to work with both petscii and ascii */ #define CHARSETHACK # define ID 257 # define CON 258 # define UNARYMINUS 259 #define yyclearin yychar = -1 #define yyerrok yyerrflag = 0 extern int yychar; extern short yyerrflag; #ifndef YYMAXDEPTH /*#define YYMAXDEPTH 150*/ #define YYMAXDEPTH 50 #endif #ifndef YYSTYPE #define YYSTYPE int #endif YYSTYPE yylval, yyval; # define YYERRCODE 256 # define U(x) x # define NLSTATE yyprevious=YYNEWLINE # define BEGIN yybgin = yysvec + 1 + # define INITIAL 0 # define YYLERR yysvec # define YYSTATE (yyestate-yysvec-1) # define YYOPTIM 1 # define YYLMAX 200 # define output(c) (void)putc(c,yyout) /* # define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):getc(yyin))==10?(yylineno++,yytchar):yytchar)==EOF?0:yytchar) */ # define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):getchar())==('\n')?(yylineno++,yytchar):yytchar)==EOF?0:yytchar) # define unput(c) {yytchar= (c);if(yytchar=='\n')yylineno--;*yysptr++=yytchar;} # define yymore() (yymorfg=1) # define ECHO fprintf(yyout, "%s",yytext) # define REJECT { nstr = yyreject(); goto yyfussy;} int yyleng; extern char yytext[]; int yymorfg; extern char *yysptr, yysbuf[]; int yytchar; #define yyin infile #define yyout outfile extern int yylineno; struct yysvf { struct yywork *yystoff; struct yysvf *yyother; int *yystops; }; struct yysvf *yyestate; extern struct yysvf yysvec[], *yybgin; /*# define YYNEWLINE 10 */ # define YYNEWLINE ('\n') #ifdef NO_IMPLICIT_FUNC_PROTOTYPES yylook(); int yywrap(); yyparse(); yyerror(char *s); yyunput(int c); yyoutput(int c); yyinput(); yyback(int *p,int m); #endif #ifdef YYDEBUG void printchar(char *name,int ch) { if((ch==YYNEWLINE)) { fprintf(yyout," %s=YYNEWLINE\n",name); } else if((ch<0)||(ch>0xf0)||(!isprint(ch))) { fprintf(yyout," %s=%04x\n",name,ch &0xffff); } else { fprintf(yyout," %s='%c'\n",name,ch); } } #endif yylex() { int nstr; extern int yyprevious; #ifdef YYDEBUG fprintf(yyout,"yylex()\n"); #endif while((nstr = yylook()) >= 0) { #ifdef YYDEBUG fprintf(yyout,"yylex: nstr=%d\n",nstr); #endif yyfussy: switch(nstr) { case 0: if(yywrap()) return(0); break; case 1: return ID; break; case 2: return CON; break; case 3: ; break; case 4: return yytext[0]; break; case -1: break; default: fprintf(yyout,"yylex: bad switch yylook %d\n",nstr); } } #ifdef YYDEBUG fprintf(yyout,"yylex: return 0\n"); #endif return(0); } /* end of yylex */ int yyvstop[] = { 0,4,0,3,4,0,2,4,0,1,4,0,2,0,1,0,0 }; # define YYTYPE char struct yywork { YYTYPE verify, advance; } yycrank[] = { {0,0}, {0,0}, {1,3}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {1,4}, {1,3}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {1,5}, {5,7}, {5,7}, {5,7}, {5,7}, {5,7}, {5,7}, {5,7}, {5,7}, {5,7}, {5,7}, {0,0}, {0,0}, {0,0}, {0,0}, /* 0x40 */ {0,0}, {0,0}, {1,6}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {0,0}, {0,0}, {0,0}, {0,0}, {6,8}, {0,0}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, /* 0x80 */ {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {0,0}, {0,0}, #ifdef CHARSETHACK {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, /* 0xc0 */ {0,0}, {0,0}, {1,6}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {0,0}, {0,0}, {0,0}, #endif {0,0} }; /* struct yysvf { struct yywork *yystoff; struct yysvf *yyother; int *yystops; }; */ struct yysvf yysvec[] = { {0, 0, 0}, {yycrank+-1, 0, 0}, {yycrank+0, yysvec+1, 0}, {yycrank+0, 0, yyvstop+1}, {yycrank+0, 0, yyvstop+3}, {yycrank+2, 0, yyvstop+6}, {yycrank+19, 0, yyvstop+9}, {yycrank+0, yysvec+5, yyvstop+12}, {yycrank+0, yysvec+6, yyvstop+14}, {0, 0, 0} }; /* 0x8d */ /* struct yywork *yytop = yycrank+141; */ /* 0xff */ struct yywork *yytop = yycrank+255; struct yysvf *yybgin = yysvec+1; /* WARNING: this table contains one entry per character in the execution character set and must match it. */ char yymatch[] = { 00 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , #ifdef CHARSETHACK 01 ,011 ,012 ,01 ,01 ,012 ,01 ,01 , #else 01 ,011 ,012 ,01 ,01 ,01 ,01 ,01 , #endif 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 011 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , 01 ,01 ,01 ,01 ,01 ,01 ,01 ,01 , '0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'0' , '0' ,'0' ,01 ,01 ,01 ,01 ,01 ,01 , /* 0x40 (ascii) @A... (petscii) @a... */ 01 ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' , 'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' , 'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' , 'A' ,'A' ,'A' ,01 ,01 ,01 ,01 ,'A' , /* 0x60 (ascii) @a... */ 01 ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' , 'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' , 'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' , 'A' ,'A' ,'A' ,01 ,01 ,01 ,01 ,01 , #ifdef CHARSETHACK /* 0x80 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0xc0 (petcii) @A... */ 01 ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' , 'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' , 'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' ,'A' , 'A' ,'A' ,'A' ,01 ,01 ,01 ,01 ,01 , 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, #endif 0 }; char yyextra[] = { 0,0,0,0,0,0,0,0,0 }; /* ncform 4.1 83/08/11 */ int yylineno =1; # define YYU(x) x # define NLSTATE yyprevious=YYNEWLINE char yytext[YYLMAX]; struct yysvf *yylstate [YYLMAX], **yylsp, **yyolsp; char yysbuf[YYLMAX]; char *yysptr = yysbuf; int *yyfnd; extern struct yysvf *yyestate; int yyprevious = YYNEWLINE; unsigned char testbreak=0; yylook() { register struct yysvf *yystate, **lsp; register struct yywork *yyt; struct yysvf *yyz; int yych; struct yywork *yyr; /* # ifdef LEXDEBUG int debug; # endif */ char *yylastch; /* start off machines */ /* # ifdef LEXDEBUG debug = 1; # else debug = 0; # endif */ # ifdef LEXDEBUG #define debug 1 # else #define debug 0 #endif #ifdef YYDEBUG fprintf(yyout,"yylook()\n"); # endif if (!yymorfg) yylastch = yytext; else { yymorfg=0; yylastch = yytext+yyleng; } #ifdef YYDEBUG fprintf(yyout,"yylook: yymorfg=%d\n",yymorfg); # endif for(;;) { #ifdef YYDEBUG fprintf(yyout,"yylook: (outer loop)"); printchar("yyprevious",yyprevious); # endif lsp = yylstate; yyestate = yystate = yybgin; if (yyprevious==YYNEWLINE) yystate++; testbreak=0; for (;;) { # ifdef LEXDEBUG fprintf(yyout,"yylook: (inner loop) state %d\n",yystate-yysvec-1); # endif if(testbreak==5) { fprintf(yyout,"yylook: error, aborted after 5 loops\n"); exit(0); } testbreak++; yyt = yystate->yystoff; /* fprintf(yyout,"yylook: yyt offs: %02x\n",yyt-yycrank); */ if(yyt == yycrank) { /* may not be any transitions */ yyz = yystate->yyother; if(yyz == 0)break; if(yyz->yystoff == yycrank)break; } *yylastch++ = yych = input(); # ifdef LEXDEBUG fprintf(yyout,"yylook: input "); printchar("yych",yych); # endif tryagain: # ifdef LEXDEBUG /* fprintf(yyout,"yylook: yych=%02x yymatch[yych]=%02x\n",yych,yymatch[yych]); */ fprintf(yyout,"yylook: tryagain\n"); # endif yyr = yyt; /* fprintf(yyout,"yylook: yyr offs: %02x\n",yyr-yycrank); */ if ( yyt > yycrank) { yyt = yyr + yych; if (yyt <= yytop && yyt->verify+yysvec == yystate) { if(yyt->advance+yysvec == YYLERR) /* error transitions */ { # ifdef LEXDEBUG fprintf(yyout,"yylook: unput (1) "); printchar("*yylastch",*yylastch); # endif unput(*--yylastch); break; } *lsp++ = yystate = yyt->advance+yysvec; # ifdef LEXDEBUG fprintf(yyout,"yylook: continue (1)\n"); # endif goto contin; } # ifdef LEXDEBUG fprintf(yyout,"yylook: ( yyt > yycrank)\n"); # endif } # ifdef YYOPTIM else if(yyt < yycrank) /* r < yycrank */ { yyt = yyr = yycrank+(yycrank-yyt); # ifdef LEXDEBUG fprintf(yyout,"yylook: compressed state\n"); # endif yyt = yyt + yych; if(yyt <= yytop && yyt->verify+yysvec == yystate) { # ifdef LEXDEBUG fprintf(yyout,"yylook: (1)\n"); # endif if(yyt->advance+yysvec == YYLERR) /* error transitions */ { # ifdef LEXDEBUG fprintf(yyout,"yylook: unput (2) "); printchar("*yylastch",*yylastch); # endif unput(*--yylastch); break; } *lsp++ = yystate = yyt->advance+yysvec; # ifdef LEXDEBUG fprintf(yyout,"yylook: continue (2)\n"); # endif goto contin; } # ifdef LEXDEBUG /* fprintf(yyout,"yylook: yych=%02x yymatch[yych]=%02x\n",yych,yymatch[yych]); fprintf(yyout,"yylook: yyt offs: %02x\n",yyt-yycrank); fprintf(yyout,"yylook: yyr offs: %02x\n",yyr-yycrank); */ # endif yyt = yyr + YYU(yymatch[yych]); # ifdef LEXDEBUG /* fprintf(yyout,"yylook: yyt offs: %02x <= yytop offs: %02x\n",yyt-yycrank,yytop-yycrank); fprintf(yyout,"yylook: yyt->verify=%04x yysvec=%04x (yyt->verify+yysvec)=%04x == yystate=%04x\n",yyt->verify,yysvec,(yyt->verify+yysvec),yystate); */ fprintf(yyout,"yylook: try fall back character\n"); # endif if(yyt <= yytop && yyt->verify+yysvec == yystate) { # ifdef LEXDEBUG fprintf(yyout,"yylook: (2a)\n"); # endif if(yyt->advance+yysvec == YYLERR) /* error transition */ { # ifdef LEXDEBUG /* cc65 compiles this ?! fprintf(yyout,"yylook: unput (3) ",); */ fprintf(yyout,"yylook: unput (3) "); printchar("*yylastch",*yylastch); # endif unput(*--yylastch); break; } *lsp++ = yystate = yyt->advance+yysvec; # ifdef LEXDEBUG /* fprintf(yyout,"yylook: yyt offs: %02x yyt->advance=%d\n",yyt-yycrank,yyt->advance); */ fprintf(yyout,"yylook: continue (3)\n"); # endif goto contin; } # ifdef LEXDEBUG fprintf(yyout,"yylook: (2)\n"); # endif } if ((yystate = yystate->yyother) && (yyt= yystate->yystoff) != yycrank) { # ifdef LEXDEBUG fprintf(yyout,"yylook: fall back to state %d\n",yystate-yysvec-1); # endif goto tryagain; } # endif else { # ifdef LEXDEBUG fprintf(yyout,"yylook: unput (4) "); printchar("*yylastch",*yylastch); # endif unput(*--yylastch); break; } contin: # ifdef LEXDEBUG fprintf(yyout,"yylook: contin state=%d\n",yystate-yysvec-1); # endif ; } # ifdef LEXDEBUG if (lsp == yylstate) { fprintf(yyout,"yylook: stopped (end)\n"); } else { fprintf(yyout,"yylook: stopped at %d with:\n",*(lsp-1)-(yysvec+1)); } # endif while (lsp-- > yylstate) { *yylastch-- = 0; if (*lsp != 0 && (yyfnd= (*lsp)->yystops) && *yyfnd > 0) { yyolsp = lsp; if(yyextra[*yyfnd]) /* must backup */ { while(yyback((*lsp)->yystops,-*yyfnd) != 1 && lsp > yylstate) { lsp--; # ifdef LEXDEBUG fprintf(yyout,"yylook: unput (5) "); printchar("*yylastch",*yylastch); # endif unput(*yylastch--); } } yyprevious = YYU(*yylastch); yylsp = lsp; yyleng = yylastch-yytext+1; yytext[yyleng] = 0; # ifdef LEXDEBUG fprintf(yyout,"yylook: match action %d\n",*yyfnd); fprintf(yyout,"yylook: done loops: %d\n",testbreak); # endif return(*yyfnd++); } unput(*yylastch); } if (yytext[0] == 0 /* && feof(yyin) */) { yysptr=yysbuf; # ifdef LEXDEBUG fprintf(yyout,"yylook: done loops: %d\n",testbreak); # endif return(0); } yyprevious = yytext[0] = input(); # ifdef LEXDEBUG fprintf(yyout,"yylook: input "); printchar("yyprevious",yyprevious); # endif if (yyprevious>0) output(yyprevious); yylastch=yytext; # ifdef LEXDEBUG /* if(debug)putchar('\n'); */ # endif } # ifdef LEXDEBUG fprintf(yyout,"yylook: done loops: %d\n",testbreak); fprintf(yyout,"yylook: return <void>\n"); # endif } yyback(p, m) int *p; { if (p==0) return(0); while (*p) { if (*p++ == m) { return(1); } } return(0); } /* the following are only used in the lex library */ yyinput() { int out=input(); #ifdef YYDEBUG fprintf(yyout,"yylook: input "); printchar("out",out); #endif return(out); } yyoutput(c) int c; { output(c); } yyunput(c) int c; { unput(c); } main() { printf("main start\n"); infile = fopen("yacc.in","rb"); if (infile == NULL) { return EXIT_FAILURE; } outfile = stdout; yyparse(); fclose(infile); printf("main end\n"); return 0; } /* yyerror - issue error message */ yyerror(s) char *s; { printf("[%s]\n", s); } short yyexca[] = { -1, 1, 0, -1, -2, 0, }; # define YYNPROD 15 # define YYLAST 249 short yyact[]= { 12, 2, 9, 8, 17, 11, 25, 17, 15, 18, 16, 10, 18, 17, 15, 7, 16, 13, 18, 5, 3, 1, 0, 19, 20, 0, 0, 21, 22, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 6 }; short yypact[]= { -1000, -9,-1000, 5, -7, -59,-1000,-1000,-1000, -40, -29, -40, -40,-1000,-1000, -40, -40, -40, -40, -38, -35, -38, -38,-1000,-1000,-1000 }; short yypgo[]= { 0, 21, 20, 17, 11 }; short yyr1[]= { 0, 1, 1, 1, 1, 2, 4, 4, 4, 4, 4, 4, 4, 4, 3 }; short yyr2[]= { 0, 0, 2, 3, 3, 3, 3, 3, 3, 3, 2, 3, 1, 1, 1 }; short yychk[]= { -1000, -1, 10, -2, 256, -3, 257, 10, 10, 61, -4, 45, 40, -3, 258, 43, 45, 42, 47, -4, -4, -4, -4, -4, -4, 41 }; short yydef[]= { 1, -2, 2, 0, 0, 0, 14, 3, 4, 0, 5, 0, 0, 12, 13, 0, 0, 0, 0, 10, 0, 6, 7, 8, 9, 11 }; # define YYFLAG -1000 # define YYERROR goto yyerrlab # define YYACCEPT return(0) # define YYABORT return(1) /* parser for yacc output */ #ifdef YYDEBUG int yydebug = 1; /* 1 for debugging */ #else int yydebug = 0; /* 1 for debugging */ #endif YYSTYPE yyv[YYMAXDEPTH]; /* where the values are stored */ int yychar = -1; /* current input token number */ int yynerrs = 0; /* number of errors */ short yyerrflag = 0; /* error recovery flag */ yyparse() { short yys[YYMAXDEPTH]; short yyj, yym; register YYSTYPE *yypvt; register short yystate, *yyps, yyn; register YYSTYPE *yypv; register short *yyxi; yystate = 0; yychar = -1; yynerrs = 0; yyerrflag = 0; yyps= &yys[-1]; yypv= &yyv[-1]; yystack: /* put a state and value onto the stack */ #ifdef YYDEBUG printf("yyparse: yystack\n"); #endif #ifdef YYDEBUG printf("yyparse: yystate=%d, ", yystate); printchar("yychar",yychar); #endif if( ++yyps> &yys[YYMAXDEPTH] ) { yyerror( "yyparse: yacc stack overflow" ); return(1); } *yyps = yystate; ++yypv; *yypv = yyval; yynewstate: #ifdef YYDEBUG printf("yyparse: yynewstate\n"); #endif yyn = yypact[yystate]; if( yyn<= YYFLAG ) goto yydefault; /* simple state */ #ifdef YYDEBUG printf("yyparse: yynewstate (1)\n"); #endif if( yychar<0 ) if( (yychar=yylex())<0 ) yychar=0; #ifdef YYDEBUG printf("yyparse: yynewstate yyn=%d ",yyn); printchar("yychar",yychar); #endif if( (yyn += yychar)<0 || yyn >= YYLAST ) goto yydefault; #ifdef YYDEBUG printf("yyparse: yynewstate (2)\n"); #endif if( yychk[ yyn=yyact[ yyn ] ] == yychar ) /* valid shift */ { yychar = -1; yyval = yylval; yystate = yyn; #ifdef YYDEBUG printf("yyparse: yynewstate (3)\n"); #endif if( yyerrflag > 0 ) --yyerrflag; goto yystack; } yydefault: #ifdef YYDEBUG printf("yyparse: yydefault yystate=%d\n",yystate); #endif /* default state action */ if( (yyn=yydef[yystate]) == -2 ) { if( yychar<0 ) if( (yychar=yylex())<0 ) yychar = 0; /* look through exception table */ for( yyxi=yyexca; (*yyxi!= (-1)) || (yyxi[1]!=yystate) ; yyxi += 2 ) ; /* VOID */ while( *(yyxi+=2) >= 0 ) { if( *yyxi == yychar ) break; } if( (yyn = yyxi[1]) < 0 ) return(0); /* accept */ } #ifdef YYDEBUG printf("yyparse: yyn=%d yyerrflag=%d\n",yyn,yyerrflag); #endif if( yyn == 0 ) /* error */ { /* error ... attempt to resume parsing */ switch( yyerrflag ){ case 0: /* brand new error */ yyerror( "yyparse: syntax error" ); yyerrlab: ++yynerrs; case 1: case 2: /* incompletely recovered error ... try again */ yyerrflag = 3; /* find a state where "error" is a legal shift action */ while ( yyps >= yys ) { yyn = yypact[*yyps] + YYERRCODE; if( yyn>= 0 && yyn < YYLAST && yychk[yyact[yyn]] == YYERRCODE ){ yystate = yyact[yyn]; /* simulate a shift of "error" */ goto yystack; } yyn = yypact[*yyps]; /* the current yyps has no shift onn "error", pop stack */ #ifdef YYDEBUG printf("yyparse: error recovery pops state %d, uncovers %d\n", *yyps, yyps[-1] ); #endif --yyps; --yypv; } /* there is no state on the stack with an error shift ... abort */ yyabort: return(1); case 3: /* no shift yet; clobber input char */ #ifdef YYDEBUG printf("yyparse: error recovery discards char "); printchar("yychar",yychar); #endif if( yychar == 0 ) goto yyabort; /* don't discard EOF, quit */ yychar = -1; goto yynewstate; /* try again in the same state */ } } /* reduction by production yyn */ #ifdef YYDEBUG printf("yyparse: reduce %d\n",yyn); #endif yyps -= yyr2[yyn]; yypvt = yypv; yypv -= yyr2[yyn]; yyval = yypv[1]; yym=yyn; /* consult goto table to find next state */ yyn = yyr1[yyn]; yyj = yypgo[yyn] + *yyps + 1; if( yyj>=YYLAST || yychk[ yystate = yyact[yyj] ] != -yyn ) yystate = yyact[yypgo[yyn]]; switch(yym) { case 4: { yyerrok; } break; case 5: { printf("[STORE]\n"); } break; case 6: { printf("[ADD]\n"); } break; case 7: { printf("[NEG]\n[ADD]\n"); } break; case 8: { printf("[MUL]\n"); } break; case 9: { printf("[DIV]\n"); } break; case 10: { printf("[NEG]\n"); } break; case 12: { printf("[LOAD]\n"); } break; case 13: { printf("[PUSH %s]\n", yytext); } break; case 14: { printf("[%s]\n", yytext); } break; } goto yystack; /* stack new state and value */ } int yywrap() { return 1; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/yacc.in��������������������������������������������������������������������������0000775�0000000�0000000�00000000022�13473601511�0015204�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������x=(e+1)*3/(3+7) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/yacc2.c��������������������������������������������������������������������������0000664�0000000�0000000�00000011574�13473601511�0015115�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! !!ORIGIN!! testsuite !!LICENCE!! Public Domain !!AUTHOR!! Groepaz/Hitmen */ #include <stdio.h> # define YYTYPE char struct yywork { YYTYPE verify, advance; } yycrank[] = { {0,0}, {0,0}, {1,3}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {1,4}, {1,3}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {1,5}, {5,7}, {5,7}, {5,7}, {5,7}, {5,7}, {5,7}, {5,7}, {5,7}, {5,7}, {5,7}, {0,0}, {0,0}, {0,0}, {0,0}, /* 0x40 */ {0,0}, {0,0}, {1,6}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {0,0}, {0,0}, {0,0}, {0,0}, {6,8}, {0,0}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, /* 0x80 */ {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {0,0}, {0,0}, #ifdef CHARSETHACK {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, /* 0xc0 */ {0,0}, {0,0}, {1,6}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {6,8}, {0,0}, {0,0}, {0,0}, #endif {0,0} }; struct yywork *yytop = yycrank+255; int yyvstop[] = { 0,4,0,3,4,0,2,4,0,1,4,0,2,0,1,0,0 }; struct yysvf { struct yywork *yystoff; struct yysvf *yyother; int *yystops; }; struct yysvf yysvec[] = { {0, 0, 0}, {yycrank+-1, 0, 0}, {yycrank+0, yysvec+1, 0}, {yycrank+0, 0, yyvstop+1}, {yycrank+0, 0, yyvstop+3}, {yycrank+2, 0, yyvstop+6}, {yycrank+19, 0, yyvstop+9}, {yycrank+0, yysvec+5, yyvstop+12}, {yycrank+0, yysvec+6, yyvstop+14}, {0, 0, 0} }; #if 0 # define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):GETCHAR())==('\n')?(yylineno++,yytchar):yytchar)==EOF?0:yytchar) // *yylastch++ = yych = input(); void subtest1(void) { *yylastch++ = yych = input(); } #endif // do some bogus operation to destroy all registers etc static int bog=1234; #if 0 void bogus(void) { bog*=0x1234; } #else #define bogus() bog+=0x1234 #endif #if 1 // yyt = yyt + yych; void subtest2(void) { register struct yywork *yyt; int yych; yyt=yycrank; yych=10; bogus(); yyt = yyt + yych; printf("yyt: %d %d\n",yyt->verify,yyt->advance); } #endif #if 1 // if(yyt <= yytop && yyt->verify+yysvec == yystate) void subtest3(void) { register struct yywork *yyt; register struct yysvf *yystate; yyt=yycrank; yystate=yysvec; bogus(); if(yyt <= yytop && yyt->verify+yysvec == yystate) { printf("if ok %d %d\n",yyt->verify,yyt->advance); } else { printf("if not ok %d %d\n",yyt->verify,yyt->advance); } } #endif short yyr2[]= { 0, 0, 2, 3, 3, 3, 3, 3, 3, 3, 2, 3, 1, 1, 1 }; // yyps -= yyr2[yyn]; void subtest4(void) { register short *yyps, yyn; yyps=0x8004; yyn=0; while(yyn<14) { bogus(); yyps -= yyr2[yyn]; yyn++; } printf("yyps: %04x\n",yyps); } #if 1 int yylookret=10; yylook() { yylookret--; return yylookret; } // while((nstr = yylook()) >= 0) void subtest5(void) { int nstr; bogus(); while((nstr = yylook()) >= 0) { printf("nstr: %04x\n",nstr); bogus(); } } #endif int main(void) { // subtest1(); subtest2(); subtest3(); subtest4(); subtest5(); return 0; } ������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/ref/yaccdbg.c������������������������������������������������������������������������0000664�0000000�0000000�00000000665�13473601511�0015507�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! verbose/debug version of yacc.c (if one fails and the other does not you most likely have a stack related problem) !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ /*#define STANDALONE*/ #include <stdio.h> #include <stdlib.h> #include <ctype.h> #define INFILE "yaccdbg.in" #define LEXDEBUG #define YYDEBUG #define YACCDBG #include "yacc.c" ���������������������������������������������������������������������������cc65-2.18/test/val/���������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0013746�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/Makefile�������������������������������������������������������������������������0000664�0000000�0000000�00000003423�13473601511�0015410�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile for the regression tests that return an error code on failure ifneq ($(shell echo),) CMD_EXE = 1 endif ifdef CMD_EXE S = $(subst /,\,/) NULLDEV = nul: MKDIR = mkdir $(subst /,\,$1) RMDIR = -rmdir /s /q $(subst /,\,$1) DEL = del /f $(subst /,\,$1) else S = / NULLDEV = /dev/null MKDIR = mkdir -p $1 RMDIR = $(RM) -r $1 DEL = $(RM) $1 endif ifdef QUIET .SILENT: NULLOUT = >$(NULLDEV) NULLERR = 2>$(NULLDEV) endif SIM65FLAGS = -x 200000000 CL65 := $(if $(wildcard ../../bin/cl65*),..$S..$Sbin$Scl65,cl65) SIM65 := $(if $(wildcard ../../bin/sim65*),..$S..$Sbin$Ssim65,sim65) WORKDIR = ../../testwrk/val OPTIONS = g O Os Osi Osir Osr Oi Oir Or .PHONY: all clean SOURCES := $(wildcard *.c) TESTS = $(foreach option,$(OPTIONS),$(SOURCES:%.c=$(WORKDIR)/%.$(option).6502.prg)) TESTS += $(foreach option,$(OPTIONS),$(SOURCES:%.c=$(WORKDIR)/%.$(option).65c02.prg)) all: $(TESTS) $(WORKDIR): $(call MKDIR,$(WORKDIR)) # 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.%.prg \ $(WORKDIR)/cq81.%.prg \ $(WORKDIR)/cq84.%.prg: CC65FLAGS += -Wc --all-cdecl define PRG_template $(WORKDIR)/%.$1.$2.prg: %.c | $(WORKDIR) $(if $(QUIET),echo val/$$*.$1.$2.prg) $(CL65) -t sim$2 $$(CC65FLAGS) -$1 -o $$@ $$< $(NULLERR) $(SIM65) $(SIM65FLAGS) $$@ $(NULLOUT) endef # PRG_template $(foreach option,$(OPTIONS),$(eval $(call PRG_template,$(option),6502))) $(foreach option,$(OPTIONS),$(eval $(call PRG_template,$(option),65c02))) clean: @$(call RMDIR,$(WORKDIR)) @$(call DEL,$(SOURCES:.c=.o)) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/add1.c���������������������������������������������������������������������������0000664�0000000�0000000�00000004717�13473601511�0014734�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! Addition tests !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> unsigned char success=0; unsigned char failures=0; unsigned char dummy=0; #ifdef SUPPORT_BIT_TYPES bit bit0 = 0; bit bit1 = 0; bit bit2 = 0; bit bit3 = 0; bit bit4 = 0; bit bit5 = 0; bit bit6 = 0; bit bit7 = 0; bit bit8 = 0; bit bit9 = 0; bit bit10 = 0; bit bit11 = 0; #endif unsigned int aint0 = 0; unsigned int aint1 = 0; unsigned char achar0 = 0; unsigned char achar1 = 0; unsigned char achar2 = 0; unsigned char achar3 = 0; unsigned char *acharP = 0; void done() { dummy++; } void add_lit2uchar(void) { achar0 = achar0 + 5; if(achar0 != 5) failures++; achar0 += 10; if(achar0 != 15) failures++; achar0 = achar0 +1; /*Should be an increment */ if(achar0 != 16) failures++; for(achar1 = 0; achar1 < 100; achar1++) achar0 += 2; if(achar0 != 216) failures++; } void add_uchar2uchar(void) { achar1 = achar1 + achar0; if(achar1 != 16) failures++; for(achar2 = 0; achar2<7; achar2++) achar1 += achar0; if(achar1 != 128) failures++; } /* assumes achar0 = 0 achar1 = 32 achar2, achar3 can be anything. */ void add_uchar2uchar2(void) { achar0++; achar0 = achar0 + 1; achar0 = achar0 + 2; achar0 = achar0 + 3; if(achar0 != 7) failures++; achar1 += achar0; if(achar1 != 39) failures++; achar2 = achar1 + achar0; if(achar2 != 46) failures++; achar3 = achar2 + achar1 + achar0; if(achar3 != 92) failures++; } #ifdef SUPPORT_BIT_TYPES void add_bits(void) { bit1 = bit0; bit0 = 1; if(bit1 != 0) failures++; bit1 = bit1+bit0; if(bit1 != 1) failures++; #ifdef SUPPORT_BIT_ARITHMETIC bit2 = bit1+bit3; if(!bit2) failures++; bit3 = bit4+bit5+bit6+bit7+bit0; if(!bit3) failures++; #endif } /* add_bit2uchar(void) - assumes bit0 = 1, achar0 = 7 */ void add_bit2uchar(void) { achar0 += bit0; if(achar0 != 8) failures++; if(achar0 == bit0) failures++; } void add_bit2uint(void) { if(aint0 != bit11) failures++; aint0 += bit0; if(aint0!=1) failures++; } #endif int main(void) { add_lit2uchar(); achar0=16; achar1=0; add_uchar2uchar(); achar0 = 0; achar1 = 32; add_uchar2uchar2(); #ifdef SUPPORT_BIT_TYPES add_bits(); add_bit2uchar(); add_bit2uint(); #endif success = failures; done(); printf("failures: %d\n",failures); return failures; } �������������������������������������������������cc65-2.18/test/val/add2.c���������������������������������������������������������������������������0000664�0000000�0000000�00000010666�13473601511�0014735�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! Addition tests - mostly int's !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> unsigned char success=0; unsigned char failures=0; unsigned char dummy=0; #ifdef SIZEOF_INT_16BIT #if defined(__LINUX__) || defined(LINUX) unsigned short aint0 = 0; unsigned short aint1 = 0; unsigned short aint2 = 0; unsigned short aint3 = 0; #else unsigned int aint0 = 0; unsigned int aint1 = 0; unsigned int aint2 = 0; unsigned int aint3 = 0; #endif #else unsigned int aint0 = 0; unsigned int aint1 = 0; unsigned int aint2 = 0; unsigned int aint3 = 0; #endif unsigned char achar0 = 0; unsigned char achar1 = 0; unsigned char achar2 = 0; unsigned char achar3 = 0; unsigned char *acharP = 0; #ifdef SUPPORT_BIT_TYPES bit bit0 = 0; bit bit1 = 0; bit bit2 = 0; bit bit3 = 0; bit bit4 = 0; bit bit5 = 0; bit bit6 = 0; bit bit7 = 0; bit bit8 = 0; bit bit9 = 0; bit bit10 = 0; bit bit11 = 0; #endif void done() { dummy++; } void add_lit2uint(void) { aint0 = aint0 + 5; if(aint0 != 5) failures++; aint0 += 10; if(aint0 != 15) failures++; aint0 = aint0 +1; /* Should be an increment */ if(aint0 != 16) failures++; for(aint1 = 0; aint1 < 100; aint1++) aint0 += 2; if(aint0 != 216) failures++; } void add_uint2uint (void) { aint1 = aint1 + aint0; if(aint1 != 16) failures++; for(aint2 = 0; aint2<7; aint2++) aint1 += aint0; if(aint1 != 128) failures++; } /* assumes aint0 = 0 aint1 = 32 aint2, aint3 can be anything. */ void add_uint2uint2(void) { aint0++; aint0 = aint0 + 1; aint0 = aint0 + 2; aint0 = aint0 + 3; if(aint0 != 7) failures++; aint1 += aint0; if(aint1 != 0x27) failures++; aint2 = aint1 + aint0; if(aint2 != 0x2e) failures++; aint3 = aint2 + aint1 + aint0; if(aint3 != 0x5c) failures++; aint3 += 0xa0; if(aint3 != 0xfc) failures++; aint3 += aint0; if(aint3 != 0x103) failures++; aint1 += 0xffc0; if(aint1 != 0xffe7) failures++; aint3 = aint2 + aint1 + aint0; if(aint3 != 0x1c) failures++; } #ifdef SUPPORT_BIT_TYPES void add_bits(void) { bit1 = bit0; bit0 = 1; if(bit1 != 0) failures++; bit1 = bit1+bit0; if(bit1 != 1) failures++; bit2 = bit1+bit3; if(!bit2) failures++; bit3 = bit4+bit5+bit6+bit7+bit0; if(!bit3) failures++; } /* add_bit2uchar(void) - assumes bit0 = 1, aint0 = 7 */ void add_bit2uchar(void) { achar0 += bit0; if(achar0 != 8) failures++; if(achar0 == bit0) failures++; } void add_bit2uint(void) { if(aint0 != bit11) failures++; aint0 += bit0; if(aint0!=1) failures++; } #endif /***********************************/ void addlits(void) { aint0 += 0x0001; if(aint0 != 1) failures++; aint0 += 0x00; if(aint0 != 1) failures++; aint0 += 0x00fe; if(aint0 != 0x00ff) failures++; aint0 += 0x0001; if(aint0 != 0x0100) failures++; aint0++; if(aint0 != 0x0101) failures++; aint0 += 0x00ff; if(aint0 != 0x0200) failures++; aint0 += 0x00a0; if(aint0 != 0x02a0) failures++; aint0 += 0x0061; if(aint0 != 0x0301) failures++; aint0 += 0x0100; if(aint0 != 0x0401) failures++; aint0 += 0x0101; if(aint0 != 0x0502) failures++; aint0 += 0x00fd; if(aint0 != 0x05ff) failures++; aint0 += 0x0101; if(aint0 != 0x0700) failures++; aint0 += 0x01ff; if(aint0 != 0x08ff) failures++; aint0 += 0x01ff; if(aint0 != 0x0afe) failures++; aint0 += 0xff02; if(aint0 != 0x0a00) failures++; aint0 += 0xffff; if(aint0 != 0x09ff) failures++; aint0 += 0xff01; if(aint0 != 0x0900) failures++; aint0 += 0xff00; if(aint0 != 0x0800) failures++; aint0 += 0xff01; if(aint0 != 0x0701) failures++; aint0 += 0x0300; if(aint0 != 0x0a01) failures++; aint0 += 0x03ff; if(aint0 != 0x0e00) failures++; aint0 += 0x0301; if(aint0 != 0x1101) failures++; aint0 += 0x03fe; if(aint0 != 0x14ff) failures++; aint0 += 0x0301; if(aint0 != 0x1800) failures++; } int main(void) { add_lit2uint(); aint0=16; aint1=0; add_uint2uint(); aint0 = 0; aint1 = 32; aint2 = 0; add_uint2uint2(); #ifdef SUPPORT_BIT_TYPES add_bits(); achar0 = 7; add_bit2uchar(); aint0 = 0; bit0 = 1; add_bit2uint(); #endif aint0 = 0; addlits(); success = failures; done(); printf("failures: %d\n",failures); return failures; } ��������������������������������������������������������������������������cc65-2.18/test/val/add3.c���������������������������������������������������������������������������0000664�0000000�0000000�00000007117�13473601511�0014733�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! Addition tests - mostly int's !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include "common.h" #include <stdio.h> #include <stdlib.h> #include <limits.h> unsigned char failures=0; char char0 = 0; char char1 = 0; char char2 = 0; /* this test assumes: sizeof(char) == 1 sizeof(int) == 2 sizeof(long) == 4 */ #ifdef REFERENCE /* make sure the reference output uses types with proper size */ #include <stdint.h> #ifdef SIZEOF_INT_16BIT int16_t int0 = 0; int16_t int1 = 0; #else int32_t int0 = 0; int32_t int1 = 0; #endif int32_t long0 = 0; int32_t long1 = 0; uint32_t ulong0 = 0; uint32_t ulong1 = 0; #else int int0 = 0; int int1 = 0; long long0 = 0; long long1 = 0; unsigned long ulong0 = 0; unsigned long ulong1 = 0; #endif #ifdef SUPPORT_BIT_TYPES bit bit0 = 0; bit bit1 = 0; bit bit2 = 0; bit bit3 = 0; bit bit4 = 0; bit bit5 = 0; bit bit6 = 0; bit bit7 = 0; bit bit8 = 0; bit bit9 = 0; bit bit10 = 0; bit bit11 = 0; #endif void done(char *name) { printf("%s done - failures: %d\n", name, failures); if(failures) exit(failures); } void add_char2char(void) { if(char0 != 4) failures++; if(char1 != 5) failures++; char0 = char0 + char1; if(char0 != 9) failures++; char0 += 127; #if (!defined(REFCC) && defined(UNSIGNED_CHARS)) || (defined(REFCC) && defined(REFCC_UNSIGNED_CHARS)) if(char0 < 0) failures++; if(char0 != (127+9)) failures++; #else if(char0 > 0) failures++; if(char0 != -0x78) failures++; #endif done("add_char2char"); } void add_compound_char(void) { char0 = char1+5; if(char0 != 9) failures++; if((char0+char1) != 13) failures++; done("add_compound_char"); } void add_int2int(void) { if(int0 != 4) failures++; if(int1 != 5) failures++; int0 += int1; if(int0 != 9) failures++; int0 += 0x7fff; if(int0 != -0x7ff8) failures++; done("add_int2int"); } void add_compound_int(void) { int0 = int1+5; if(int0 != 9) failures++; if((int0+int1) != 13) failures++; done("add_compound_int"); } void add_lit2long(void) { if(long0 != 0) failures++; long0++; if(long0 != 1) failures++; long0 = long0 + 0xff; if(long0 != 0x100) failures++; long0 = long0 + 0x100; if(long0 != 0x200) failures++; long0 = long0 + 0xfe00; if(long0 != 0x10000) failures++; long0 = long0 + 0xff0000; if(long0 != 0x1000000) failures++; long0 = long0 + 0x7e000000; if(long0 != 0x7f000000) failures++; /* wrap around zero */ long0 = long0 + 0x2000000; if(long0 != -0x7f000000) failures++; long0 = long0 + 0x7f000000; if(long0 != 0) failures++; done("add_lit2long"); } void add_lit2ulong(void) { if(ulong0 != 0) failures++; ulong0++; if(ulong0 != 1) failures++; ulong0 = ulong0 + 0xff; if(ulong0 != 0x100) failures++; ulong0 = ulong0 + 0x100; if(ulong0 != 0x200) failures++; ulong0 = ulong0 + 0xfe00; if(ulong0 != 0x10000) failures++; ulong0 = ulong0 + 0xff0000; if(ulong0 != 0x1000000) failures++; ulong0 = ulong0 + 0x7e000000; if(ulong0 != 0x7f000000) failures++; ulong0 = ulong0 + 0x2000000; if(ulong0 != 0x81000000) failures++; /* wrap around zero */ ulong0 = ulong0 + 0x7f000000; if(ulong0) failures++; done("add_lit2ulong"); } int main(void) { char0=4; char1 = char0 + 1; add_char2char(); char1=4; add_compound_char(); int0 = 4; int1 = int0 + 1; add_int2int(); int1=4; add_compound_int(); add_lit2long(); add_lit2ulong(); /* if not exit() */ return 0; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/add3a.c��������������������������������������������������������������������������0000775�0000000�0000000�00000002324�13473601511�0015072�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ /* !!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; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/add4.c���������������������������������������������������������������������������0000664�0000000�0000000�00000002231�13473601511�0014724�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> unsigned char success = 0; unsigned char failures = 0; unsigned char dummy = 0; #ifdef SUPPORT_BIT_TYPES bit bit0 = 0; #endif int int0 = 0; int int1 = 0; char char0 = 0; char char1 = 0; long long0 = 0; long long1 = 0; unsigned long ulong0 = 0; unsigned long ulong1 = 0; #define NULL 0 char *cP0=NULL; char *cP1=NULL; int *iP0=NULL; int *iP1=NULL; void done () { dummy++; } /* pointer to char arithmetic */ void pc_add(void) { if(*cP1) failures++; *cP1 += 1; if(*cP1 != 1) failures++; if(char0 != 1) failures++; char0++; if(*cP1 != 2) failures++; char1 = char0 + *cP1; if(char1 != 4) failures++; } /* pointer to integer arithmetic */ void pi_add(void) { if(*iP0) failures++; *iP0 += 1; if(*iP0 != 1) failures++; if(int0 != 1) failures++; int1 = int0 + *iP0; if(int1 != 2) failures++; } int main(void) { cP1 = &char0; pc_add(); iP0 = &int0; pi_add(); success = failures; done(); printf("failures: %d\n",failures); return failures; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/add5.c���������������������������������������������������������������������������0000664�0000000�0000000�00000007774�13473601511�0014746�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** !!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; } ����cc65-2.18/test/val/and1.c���������������������������������������������������������������������������0000664�0000000�0000000�00000003504�13473601511�0014737�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> unsigned char success=0; unsigned char failures=0; unsigned char dummy=0; unsigned int uint0 = 0; unsigned int uint1 = 0; unsigned char uchar0 = 0; unsigned char uchar1 = 0; unsigned long ulong0 = 0; void done() { dummy++; } /* uchar0 = 0xff; */ void and_lit2uchar(void) { if(uchar0 != 0xff) failures++; uchar0 &= 0x7f; if(uchar0 != 0x7f) failures++; uchar0 &= 0x3f; if(uchar0 != 0x3f) failures++; uchar0 &= 0xdf; if(uchar0 != 0x1f) failures++; } void and_lit2uint(void) { if(uint0 != 0xffff) failures++; uint0 &= 0x7fff; if(uint0 != 0x7fff) failures++; uint0 &= 0x3fff; if(uint0 != 0x3fff) failures++; uint0 &= 0xdfff; if(uint0 != 0x1fff) failures++; uint0 &= 0xff7f; if(uint0 != 0x1f7f) failures++; uint0 &= 0x0f0f; if(uint0 != 0x0f0f) failures++; uint0 &= 0xfefe; if(uint0 != 0x0e0e) failures++; uint0 &= 0xf0f0; if(uint0 != 0) failures++; } void and_lit2ulong(void) { if(ulong0 != 0xffffffff) failures++; ulong0 &= 0x7fffffff; if(ulong0 != 0x7fffffff) failures++; ulong0 &= 0xff00ffff; if(ulong0 != 0x7f00ffff) failures++; ulong0 &= 0xfeff00ff; if(ulong0 != 0x7e0000ff) failures++; } /*-----------*/ void and_uchar2uchar(void) { uchar0 &= uchar1; if(uchar0 != 0x0f) failures++; uchar1 &= 0xf7; uchar0 = uchar1 & 0xfe; if(uchar0 != 0x06) failures++; } int main(void) { uchar0 = 0xff; and_lit2uchar(); uint0 = 0xffff; and_lit2uint(); ulong0 = 0xffffffff; and_lit2ulong(); uchar0 = 0xff; uchar1 = 0x0f; and_uchar2uchar(); success = failures; done(); printf("failures: %d\n",failures); return failures; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/and2.c���������������������������������������������������������������������������0000664�0000000�0000000�00000003226�13473601511�0014741�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> unsigned char success=0; unsigned char failures=0; unsigned char dummy=0; unsigned int uint0 = 0; unsigned int uint1 = 0; unsigned char uchar0 = 0; unsigned char uchar1 = 0; unsigned long ulong0 = 0; void done() { dummy++; } /* uchar0 = 0x13; */ void and_compound1(void) { uchar0 = (uchar0 + 1) & 0x0f; if(uchar0 != 4) failures++; } /* uchar1 = 0x42; */ void and_compound2(void) { uchar0 = (uchar1 + 1) & 0x0f; if(uchar0 != 3) failures++; if(uchar1 != 0x42) failures++; } /* uchar0 = 0x13; */ void or_compound1(void) { uchar0 = (uchar0 + 0xe) | 0x0f; if(uchar0 != 0x2f) failures++; } /* uchar1 = 0x47; */ void or_compound2(void) { uchar0 = (uchar1 + 0xf) | 0x0f; if(uchar0 != 0x5f) failures++; if(uchar1 != 0x47) failures++; } /* uchar0 = 0x13; */ void xor_compound1(void) { uchar0 = (uchar0 + 1) ^ 0x0f; if(uchar0 != 0x1b) failures++; } /* uchar1 = 0x47; */ void xor_compound2(void) { uchar0 = (uchar1 + 0xf) ^ 0x0f; if(uchar0 != 0x59) failures++; if(uchar1 != 0x47) failures++; } /* uchar0 = 0x13; */ void neg_compound1(void) { uchar0 = ~(uchar0 + 1); if(uchar0 != 0xeb) failures++; } int main(void) { uchar0 = 0x13; and_compound1(); uchar1 = 0x42; and_compound2(); uchar0 = 0x13; or_compound1(); uchar1 = 0x47; or_compound2(); uchar0 = 0x13; xor_compound1(); uchar1 = 0x47; xor_compound2(); uchar0 = 0x13; neg_compound1(); success = failures; done(); printf("failures: %d\n",failures); return failures; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/anon-struct1.c�������������������������������������������������������������������0000664�0000000�0000000�00000004237�13473601511�0016456�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! Make sure that structs/unions know the sizes of anonymous struct/union members !!ORIGIN!! cc65 regression tests !!LICENCE!! Public Domain !!AUTHOR!! Greg King */ /* see https://github.com/cc65/cc65/issues/641 */ #include <stdio.h> static unsigned char fails = 0; typedef struct { short s1; struct { int i1; long l1; char c1; }; char c2; } s1_t; typedef struct { short s1; union { int i1; long l1; char c1; }; char c2; } s2_t; typedef union { short s1; struct { int i1; long l1; char c1; }; char c2; } u1_t; typedef union { short s1; union { int i1; long l1; char c1; }; char c2; } u2_t; static s1_t s1; static s2_t s2; static u1_t u1; static u2_t u2; /* We use "variables" in the comparisons, so that we can avoid "constant ** comparison" and "Unreachable code" warnings (the second one currently ** can't be suppressed). */ static size_t const four = 4; static size_t const seven = 7; static size_t const ten = 10; int main(void) { /* Check the types' sizes. */ if (sizeof (s1_t) != ten) { printf("s1_t size is %u; it should be 10.\n", sizeof (s1_t)); ++fails; } if (sizeof (s2_t) != seven) { printf("s2_t size is %u; it should be 7.\n", sizeof (s2_t)); ++fails; } if (sizeof (u1_t) != seven) { printf("u1_t size is %u; it should be 7.\n", sizeof (u1_t)); ++fails; } if (sizeof (u2_t) != four) { printf("u2_t size is %u; it should be 4.\n", sizeof (u2_t)); ++fails; } /* Check the variables' sizes. */ if (sizeof s1 != ten) { printf("s1 size is %u; it should be 10.\n", sizeof s1); ++fails; } if (sizeof s2 != seven) { printf("s2 size is %u; it should be 7.\n", sizeof s2); ++fails; } if (sizeof u1 != seven) { printf("u1 size is %u; it should be 7.\n", sizeof u1); ++fails; } if (sizeof u2 != four) { printf("u2 size is %u; it should be 4.\n", sizeof u2); ++fails; } return fails; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/anon-struct2.c�������������������������������������������������������������������0000664�0000000�0000000�00000006270�13473601511�0016456�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! Make sure that the fields of anonymous structs/unions can be reached properly. !!ORIGIN!! cc65 regression tests !!LICENCE!! Public Domain !!AUTHOR!! Greg King */ #include <stddef.h> #include <stdio.h> static unsigned char fails = 0; typedef struct { short s1; struct { char c1; int i1; long l1; }; char c2; } s1_t; typedef struct { char c2; union { int i1; char c1; long l1; }; short s1; } s2_t; typedef union { short s1; struct { int i1; long l1; char c1; }; char c2; } u1_t; typedef union { short s1; union { long l1; char c1; int i1; }; char c2; } u2_t; typedef struct { union { short s1; struct { int i1; long l1; char c1; }; char c2; }; short s2; } s3_t; static s1_t s1; static s2_t s2; static u1_t u1; static u2_t u2; static long l2; static int i2; /* We use "variables" in the comparisons, so that we can avoid "constant ** comparison" and "Unreachable code" warnings (the second one currently ** can't be suppressed). */ static size_t const zero = 0; static size_t const one = 1; static size_t const three = 3; static size_t const five = 5; static size_t const six = 6; static size_t const seven = 7; static size_t const nine = 9; int main(void) { /* Can cc65 see the names of members of anonymous structs/unions? */ l2 = s1.l1; l2 = s2.l1; l2 = u1.l1; l2 = u2.l1; i2 = s1.c1; i2 = s1.c2; i2 = s2.c1; i2 = s2.c2; i2 = u1.c1; i2 = u1.c2; i2 = u2.c1; i2 = u2.c2; /* Does cc65 use the correct offsets of ** the members of anonymous structs/unions? */ if (offsetof(s1_t, i1) != three) { printf("The offset of s1.i1 is %u; it should be 3.\n", offsetof(s1_t, i1)); ++fails; } if (offsetof(s2_t, l1) != one) { printf("The offset of s2.l1 is %u; it should be 1.\n", offsetof(s2_t, l1)); ++fails; } if (offsetof(u1_t, c1) != six) { printf("The offset of u1.c1 is %u; it should be 6.\n", offsetof(u1_t, c1)); ++fails; } if (offsetof(u2_t, i1) != zero) { printf("The offset of u2.i1 is %u; it should be 0.\n", offsetof(u2_t, i1)); ++fails; } /* Does cc65 use the correct offset of a member ** that's later than an anonymous struct/union? */ if (offsetof(s1_t, c2) != nine) { printf("The offset of s1.c2 is %u; it should be 9.\n", offsetof(s1_t, c2)); ++fails; } if (offsetof(s2_t, s1) != five) { printf("The offset of s2.s1 is %u; it should be 5.\n", offsetof(s2_t, s1)); ++fails; } if (offsetof(u1_t, c2) != zero) { printf("The offset of u1.c2 is %u; it should be 0.\n", offsetof(u1_t, c2)); ++fails; } if (offsetof(u2_t, c2) != zero) { printf("The offset of u2.c2 is %u; it should be 0.\n", offsetof(u2_t, c2)); ++fails; } if (offsetof(s3_t, s2) != seven) { printf("The offset of s3.s2 is %u; it should be 7.\n", offsetof(s3_t, s2)); ++fails; } return fails; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/assign-use1.c��������������������������������������������������������������������0000664�0000000�0000000�00000001577�13473601511�0016263�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! Assign an int; then, do an operation that depends directly on that assignment. !!ORIGIN!! cc65 regression tests !!LICENCE!! Public Domain !!AUTHOR!! Greg King */ #include <stdio.h> static unsigned char failures = 0; static unsigned int result; static const unsigned int buffer = 0xABCD; int main(void) { result = buffer; /* Shift doesn't use high byte (X register); previous assignment should be optimized. */ result <<= 8; if (result != 0xCD00) { ++failures; printf("assign-use1: left shift is $%X, not $CD00.\n", result); } result = buffer; /* Shift does use high byte; previous assignment shouldn't be optimized by OptStore5(). */ result >>= 8; if (result != 0x00AB) { ++failures; printf("assign-use1: right shift is $%X, not $00AB.\n", result); } return failures; } ���������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/bool1.c��������������������������������������������������������������������������0000664�0000000�0000000�00000003115�13473601511�0015126�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> unsigned char success=0; unsigned char failures=0; unsigned char dummy=0; #ifdef SUPPORT_BIT_TYPES bit bit0 = 0; #endif unsigned int aint0 = 0; unsigned int aint1 = 0; unsigned char achar0 = 0; unsigned char achar1 = 0; void done() { dummy++; } void bool_or1(void) { if( (achar0 >0) || (achar1 >0 )) failures++; } void bool_or2(void) { if( achar0 || achar1) failures++; } void bool_test1(void) { if( (achar0==0) || achar1) failures++; } void bool_test2(void) { if( (achar0==0) || aint0) failures++; } void bool_and1(void) { if( achar0 && achar1) failures++; } void bin_or1(void) { char t; t = achar0 | achar1; if(t) failures++; } void bin_xor1(void) { if(achar0 ^ achar1) failures++; } void bool_test3(void) { if((achar0 == 0x42) || (achar1 == 42)) failures++; } void bool_or_lit1(void) { achar0 |= 0x0f; if(achar0 > 0x10) failures++; if( (achar0 | 0x10) > 0xf0) failures++; } void bool_and_lit1(void) { achar0 &= 0xf0; if(achar0 > 0x10) failures++; if( (achar0 & 0x10) > 0xf0) failures++; achar0 &= 0xef; } int main(void) { bool_or1(); bool_or2(); bool_and1(); bin_or1(); bin_xor1(); achar0++; bool_and1(); bool_test1(); bool_test2(); bool_test3(); achar0--; achar1++; bool_and1(); achar0=0; achar1=0; bool_or_lit1(); bool_and_lit1(); success = failures; done(); printf("failures: %d\n",failures); return failures; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/bool3.c��������������������������������������������������������������������������0000664�0000000�0000000�00000001763�13473601511�0015137�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! Compound comparisons !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> unsigned char success=0; unsigned char failures=0; unsigned char dummy=0; #ifdef SUPPORT_BIT_TYPES bit bit0 = 0; bit bit1 = 0; #endif unsigned int ui0 = 0; unsigned int ui1 = 0; unsigned char uc0 = 0; unsigned char uc1 = 0; unsigned long uL0 = 0; unsigned long uL1 = 0; void done() { dummy++; } void compound_compare_uc(void) { failures += (uc0 != uc1); } void compound_compare_ui(void) { failures += (ui0 != ui1); } void compound_compare_ul(void) { failures += (uL0 != uL1); } void compound_compare_uc_lit(void) { failures += (uc0 != 0xff); failures += (uc0 != 0xff); failures += (uc0 == 0); } int main(void) { compound_compare_uc(); compound_compare_ui(); compound_compare_ul(); uc0 = 0xff; compound_compare_uc_lit(); success = failures; done(); printf("failures: %d\n",failures); return failures; } �������������cc65-2.18/test/val/bss-name-decl.c������������������������������������������������������������������0000664�0000000�0000000�00000000665�13473601511�0016533�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! bss-name pragma not affecting declarations !!ORIGIN!! cc65 regression tests !!LICENCE!! Public Domain !!AUTHOR!! Piotr Fusik */ /* see: https://github.com/cc65/cc65/issues/409 */ #pragma bss-name (push,"ZEROPAGE") char n; /* only a declaration because followed by definition */ char n = 1; /* not BSS */ #pragma bss-name (pop) int main(void) { return (unsigned) &n >= 0x100 ? 0 : 1; } ���������������������������������������������������������������������������cc65-2.18/test/val/bss-name.c�����������������������������������������������������������������������0000664�0000000�0000000�00000000521�13473601511�0015615�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! bss-name pragma !!ORIGIN!! cc65 regression tests !!LICENCE!! Public Domain !!AUTHOR!! Piotr Fusik */ /* see: https://github.com/cc65/cc65/issues/409 */ #pragma bss-name (push,"ZEROPAGE") char zp_var; #pragma bss-name (pop) int main(void) { return (unsigned) &zp_var < 0x100 ? 0 : 1; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/bug367.c�������������������������������������������������������������������������0000664�0000000�0000000�00000000350�13473601511�0015125�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "unittest.h" TEST { unsigned int y=192; unsigned int d=y&0xFFF8; unsigned int e=d*32+d*8; unsigned int f=d*40; ASSERT_AreEqual(f, e, "%u", "Multiplication results differ (should be 7680)!"); } ENDTEST ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/bug735.c�������������������������������������������������������������������������0000664�0000000�0000000�00000000302�13473601511�0015121�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <stdio.h> unsigned char failures = 0; int main(void) { int i; i = 0; if ((i > 1) && (i < 3)) { failures++; } printf("failures: %u\n", failures); return failures; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/bug830.c�������������������������������������������������������������������������0000664�0000000�0000000�00000000323�13473601511�0015120�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include "unittest.h" char test[1]; char *dst = &test[0]; TEST { char src = 0; *dst = (src == 0) ? 42 : src; ASSERT_AreEqual(42, *dst, "%u", "Incorrect ternary expression evaluation!"); } ENDTEST �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/bug895.c�������������������������������������������������������������������������0000664�0000000�0000000�00000012171�13473601511�0015137�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/** This test is related to GitHub issue 895 ** https://github.com/cc65/cc65/issues/895 ** ** The OptCmp8 optimization attempted to eliminate an unnecessary ** comparison and branch when the operands of the comparison are ** known to be constant at compile time. ** ** For 8-bit types it worked well, but for 16-bit types it failed ** to generate correct code for some cases. The bug manifest as a ** branch on an uninitialized carry flag. */ #include "unittest.h" signed char sca, scb; signed int sia, sib; signed long sla, slb; unsigned char uca, ucb; unsigned int uia, uib; unsigned long ula, ulb; #define OPTCMP8TEST_SINGLE(num,cmpop,asmprefix,vara,varb,b0,b1,a0,a1,typename,name) \ typename name ## _ ## num ## (void) { \ varb = b0; \ asm( asmprefix ); \ vara = a0; \ if (vara cmpop a1) varb = b1; \ return varb; \ } #define OPTCMP8TEST_VERIFY(num,b,desc,printterm,name) \ ASSERT_AreEqual(name ## _ ## num ##(),b,printterm,"Incorrect optimization of const comparison (" #name "_" #num ": " desc ")."); /* Generates a set of comparison tests for one type and set of test values. ** name = a name for this test (no spaces) ** typename = the type used ** b0 = result if comparison is false ** b1 = result if comparison is true ** a0 = a low value to use for the comparison tests (a0 < a1) ** a1 = a high value to use for the comparison tests (a0 < a1) ** vara = temporary variable of the type to be examined ** varb = temporary variable of the type to be examined ** printterm = printf term to display the variable type */ #define OPTCMP8TEST(name,typename,b0,b1,a0,a1,vara,varb,printterm) \ OPTCMP8TEST_SINGLE(1,<,"clc",vara,varb,b0,b1,a0,a1,typename,name); \ OPTCMP8TEST_SINGLE(2,<,"sec",vara,varb,b0,b1,a0,a1,typename,name); \ OPTCMP8TEST_SINGLE(3,<,"clc",vara,varb,b0,b1,a1,a0,typename,name); \ OPTCMP8TEST_SINGLE(4,<,"sec",vara,varb,b0,b1,a1,a0,typename,name); \ OPTCMP8TEST_SINGLE(5,>,"clc",vara,varb,b0,b1,a0,a1,typename,name); \ OPTCMP8TEST_SINGLE(6,>,"sec",vara,varb,b0,b1,a0,a1,typename,name); \ OPTCMP8TEST_SINGLE(7,>,"clc",vara,varb,b0,b1,a1,a0,typename,name); \ OPTCMP8TEST_SINGLE(8,>,"sec",vara,varb,b0,b1,a1,a0,typename,name); \ OPTCMP8TEST_SINGLE(9,<=,"clc",vara,varb,b0,b1,a0,a1,typename,name); \ OPTCMP8TEST_SINGLE(10,<=,"sec",vara,varb,b0,b1,a0,a1,typename,name); \ OPTCMP8TEST_SINGLE(11,<=,"clc",vara,varb,b0,b1,a1,a0,typename,name); \ OPTCMP8TEST_SINGLE(12,<=,"sec",vara,varb,b0,b1,a1,a0,typename,name); \ OPTCMP8TEST_SINGLE(13,>=,"clc",vara,varb,b0,b1,a0,a1,typename,name); \ OPTCMP8TEST_SINGLE(14,>=,"sec",vara,varb,b0,b1,a0,a1,typename,name); \ OPTCMP8TEST_SINGLE(15,>=,"clc",vara,varb,b0,b1,a1,a0,typename,name); \ OPTCMP8TEST_SINGLE(16,>=,"sec",vara,varb,b0,b1,a1,a0,typename,name); \ OPTCMP8TEST_SINGLE(17,==,"nop",vara,varb,b0,b1,a0,a1,typename,name); \ OPTCMP8TEST_SINGLE(18,==,"nop",vara,varb,b0,b1,a1,a1,typename,name); \ OPTCMP8TEST_SINGLE(19,!=,"nop",vara,varb,b0,b1,a0,a1,typename,name); \ OPTCMP8TEST_SINGLE(20,!=,"nop",vara,varb,b0,b1,a1,a1,typename,name); \ void name ## _ ## test(void) { \ OPTCMP8TEST_VERIFY(1,b1,"low < high, clc",printterm,name); \ OPTCMP8TEST_VERIFY(2,b1,"low < high, sec",printterm,name); \ OPTCMP8TEST_VERIFY(3,b0,"high < low, clc",printterm,name); \ OPTCMP8TEST_VERIFY(4,b0,"high < low, sec",printterm,name); \ OPTCMP8TEST_VERIFY(5,b0,"low > high, clc",printterm,name); \ OPTCMP8TEST_VERIFY(6,b0,"low > high, sec",printterm,name); \ OPTCMP8TEST_VERIFY(7,b1,"high > low, clc",printterm,name); \ OPTCMP8TEST_VERIFY(8,b1,"high > low, sec",printterm,name); \ OPTCMP8TEST_VERIFY(9,b1,"low <= high, clc",printterm,name); \ OPTCMP8TEST_VERIFY(10,b1,"low <= high, sec",printterm,name); \ OPTCMP8TEST_VERIFY(11,b0,"high <= low, clc",printterm,name); \ OPTCMP8TEST_VERIFY(12,b0,"high <= low, sec",printterm,name); \ OPTCMP8TEST_VERIFY(13,b0,"low >= high, clc",printterm,name); \ OPTCMP8TEST_VERIFY(14,b0,"low >= high, sec",printterm,name); \ OPTCMP8TEST_VERIFY(15,b1,"high >= low, clc",printterm,name); \ OPTCMP8TEST_VERIFY(16,b1,"high >= low, sec",printterm,name); \ OPTCMP8TEST_VERIFY(17,b0,"low == high, nop",printterm,name); \ OPTCMP8TEST_VERIFY(18,b1,"high == high, nop",printterm,name); \ OPTCMP8TEST_VERIFY(19,b1,"low != high, nop",printterm,name); \ OPTCMP8TEST_VERIFY(20,b0,"high != high, nop",printterm,name); \ } OPTCMP8TEST(signed_char,signed char,-20,5,60,100,sca,scb,"%d"); OPTCMP8TEST(unsigned_char,unsigned char,20,5,60,100,uca,ucb,"%u"); OPTCMP8TEST(signed_int,signed int,-2000,50,600,1000,sia,sib,"%d"); OPTCMP8TEST(unsigned_int,unsigned int,2000,50,600,1000,uia,uib,"%u"); OPTCMP8TEST(signed_long,signed long,-200000L,5000L,60000L,100000L,sla,slb,"%d"); OPTCMP8TEST(unsigned_long,unsigned long,200000UL,5000UL,60000UL,100000UL,ula,ulb,"%u"); TEST { signed_char_test(); unsigned_char_test(); signed_int_test(); unsigned_int_test(); signed_long_test(); unsigned_long_test(); } ENDTEST �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/call1.c��������������������������������������������������������������������������0000664�0000000�0000000�00000003500�13473601511�0015104�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> unsigned char success = 0; unsigned char failures = 0; unsigned char dummy = 0; #ifdef SUPPORT_BIT_TYPES bit bit0 = 0; #endif unsigned int uint0 = 0; unsigned int uint1 = 0; unsigned char uchar0 = 0; unsigned char uchar1 = 0; unsigned char call3 (void); void done () { dummy++; } void call1 (unsigned char uc0) { if (uc0) failures++; } void call2 (unsigned int ui0) { if (ui0) failures++; } unsigned char call3 (void) { if (uchar0) failures++; return (failures); } unsigned int call4 (void) { unsigned int i = 0; if (uint0) i++; return (i); } unsigned int call5 (unsigned int k) { if (k) failures++; return (k); } unsigned char call6a(unsigned char uc) { if(uc>uchar1) return 1; else return 0; } unsigned char call6(unsigned char uc) { return(call6a(uc)); } unsigned int call7a(unsigned int ui) { if(ui) return 1; else return 0; } unsigned int call7(unsigned int ui) { return(call7a(ui)); } unsigned char call8(unsigned char uc1,unsigned char uc2) { return uc1+uc2; } void call9(unsigned int ui1, unsigned int ui2) { if(ui1 != 0x1234) failures++; if(ui2 != 0x5678) failures++; } int main (void) { call1 (uchar0); call2 (uint0); uchar1 = call3 (); uint1 = call4 (); if (uint1) failures++; uint1 = call5 (uint0); if (uint1) failures++; if(call6(uchar0)) failures++; if(call7(0)) failures++; if(!call7(1)) failures++; if(!call7(0xff00)) failures++; uchar0=4; uchar1=3; uchar0 = call8(uchar0,uchar1); if(uchar0 != 7) failures++; call9(0x1234,0x5678); success = failures; done (); printf("failures: %d\n",failures); return failures; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/casttochar.c���������������������������������������������������������������������0000775�0000000�0000000�00000001526�13473601511�0016254�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ /* !!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; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/cc65091020.c���������������������������������������������������������������������0000664�0000000�0000000�00000000623�13473601511�0015327�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! bit field bug !!ORIGIN!! testsuite !!LICENCE!! Public Domain !!AUTHOR!! Johan Kotlinski */ #include <stdio.h> #include <assert.h> struct { int foo : 7; int bar : 4; } baz = { 0, 2 }; int main() { char bar = baz.bar; assert(2 == bar); printf("it works :)\n"); /* if not assert() */ return 0; } /* Assert fails. (SVN rev 4381) */�������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/cc65141002.c���������������������������������������������������������������������0000775�0000000�0000000�00000001321�13473601511�0015322�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ /* !!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; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/cc65141022.c���������������������������������������������������������������������0000775�0000000�0000000�00000002022�13473601511�0015323�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ /* !!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; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/cc65150311.c���������������������������������������������������������������������0000664�0000000�0000000�00000001320�13473601511�0015321�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!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; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/common.h�������������������������������������������������������������������������0000664�0000000�0000000�00000001012�13473601511�0015401�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ #include <stdio.h> #include <stdlib.h> #define NO_OLD_FUNC_DECL #define NO_TYPELESS_INT #define NO_TYPELESS_INT_PTR #define MAIN_RETURNS_INT #define NO_IMPLICIT_FUNC_PROTOTYPES #define NO_FLOATS #define NO_WCHAR #define NO_EMPTY_FUNC_ARGS #define NO_SLOPPY_STRUCT_INIT #define NO_FUNCS_TAKE_STRUCTS #define NO_FUNCS_RETURN_STRUCTS #define CAST_STRUCT_PTR #define NO_TYPELESS_STRUCT_PTR #define NO_IMPLICIT_FUNCPTR_CONV #define SIZEOF_INT_16BIT #define SIZEOF_LONG_32BIT #define UNSIGNED_CHARS #define UNSIGNED_BITFIELDS ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/compare1.c�����������������������������������������������������������������������0000664�0000000�0000000�00000004565�13473601511�0015633�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! test compare !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> /* compare.c */ #ifdef SUPPORT_BIT_TYPES bit bit0 = 0; bit bit1 = 0; #endif unsigned char success = 0; unsigned char failures = 0; unsigned char dummy = 0; unsigned char achar0 = 0; unsigned char achar1 = 0; unsigned int aint0 = 0; unsigned int aint1 = 0; char schar0 = 0; char schar1 = 0; void done () { dummy++; } /* achar0 should be zero */ void compare_char_to_lits1 (void) { if (achar0) failures++; if (achar0 == 1) failures++; if (achar0 == 7) failures++; if (achar0 != 0) failures++; } /* achar0 should be '5' */ void compare_char_to_lits2 (void) { if (!achar0) failures++; if (achar0 == 1) failures++; if (achar0 == 7) failures++; if (achar0 != 5) failures++; } /* achar0 should equal achar1 */ void compare_char_to_char1 (void) { if (achar0 != achar1) failures++; if (schar0 != schar1) failures++; } /* achar0 should be different than achar1 */ void compare_char_to_char2 (void) { if (achar0 == achar1) failures++; } /* aint0 should be zero */ void compare_int_to_lits1 (void) { if (aint0) failures++; if (aint0 == 1) failures++; if (aint0 == 7) failures++; if (aint0 != 0) failures++; } /* aint0 should be '5' */ void compare_int_to_lits2 (void) { if (!aint0) failures++; if (aint0 == 1) failures++; if (aint0 == 7) failures++; if (aint0 != 5) failures++; } /* aint0 should be '0x1234' */ void compare_int_to_lits3 (void) { if (!aint0) failures++; if (aint0 == 1) failures++; if (aint0 == 7) failures++; if (aint0 != 0x1234) failures++; } /* aint0 should equal aint1 */ void compare_int_to_int1 (void) { if (aint0 != aint1) failures++; } /* aint0 should be different than aint1 */ void compare_int_to_int2 (void) { if (aint0 == aint1) failures++; } int main (void) { compare_char_to_lits1 (); compare_char_to_char1 (); achar0 = 5; compare_char_to_lits2 (); compare_char_to_char2 (); compare_int_to_lits1 (); aint0 = 5; compare_int_to_lits2 (); aint0 = 0x1234; compare_int_to_lits3 (); compare_int_to_int2 (); aint0 = 0; compare_int_to_int1 (); success = failures; done (); printf("failures: %d\n",failures); return failures; } �������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/compare10.c����������������������������������������������������������������������0000664�0000000�0000000�00000012011�13473601511�0015674�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! Signed comparisons of the form: (variable>=LIT) !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> /* This regression test exercises all of the boundary conditions in literal less than comparisons. There are numerous opportunities to optimize these comparison and each one has an astonishing capability of failing a boundary condition. */ unsigned char success = 0; unsigned char failures = 0; unsigned char dummy = 0; unsigned char result = 0; #ifdef SUPPORT_BIT_TYPES bit bit0 = 0; #endif int int0 = 0; int int1 = 0; unsigned char uchar0 = 0; unsigned char uchar1 = 0; signed char char0 = 0; signed char char1 = 0; char long0 = 0; char long1 = 0; /* *** NOTE *** This particular test takes quite a while to run * ~ 10,000,000 instruction cycles. (2.5 seconds on a 20Mhz PIC). * The WDT will reset the CPU if it's enabled. So disable it... */ void done () { dummy++; } void c_char_gte_lit1(unsigned char expected_result) { result = 0; if(char0 >= -0x7f) result |= 1; if(char0 >= -1) result |= 2; if(char0 >= 0) result |= 4; if(char0 >= 1) result |= 8; if(char0 >= 0x7e) result |= 0x10; if(char0 >= 0x7f) result |= 0x20; if(result != expected_result) { /* LOG_ERROR(1); */ printf("c_char_gte_lit1: char %02x - result %02x expected: %02x\n",char0,result,expected_result); failures++; } /* printf("char %02x - %02x failures: %d\n",char0,expected_result,failures); */ } void char_compare(void) { char0 = 0x7f; c_char_gte_lit1(0x3f); char0 = 0x7e; c_char_gte_lit1(0x1f); char0 = 0x40; c_char_gte_lit1(0x0f); char0 = 0x2; c_char_gte_lit1(0x0f); char0 = 0x1; c_char_gte_lit1(0x0f); char0 = 0; c_char_gte_lit1(0x07); char0 = -1; c_char_gte_lit1(0x03); char0 = -2; c_char_gte_lit1(0x01); char0 = -0x40; c_char_gte_lit1(0x01); char0 = -0x7e; c_char_gte_lit1(0x01); char0 = -0x7f; c_char_gte_lit1(0x01); char0 = 0x80; c_char_gte_lit1(0x00); /* Now test entire range */ for(char0=1; char0 != 0x7e; char0++) c_char_gte_lit1(0x0f); for(char0=-0x7f; char0 != -1; char0++) c_char_gte_lit1(0x01); } void c_int_gte_lit1(unsigned char expected_result) { result = 0; if(int0 >= 0) result |= 1; if(int0 >= 1) result |= 2; if(int0 >= 0xff) result |= 4; if(int0 >= 0x100) result |= 8; if(int0 >= 0x0101) result |= 0x10; if(int0 >= 0x01ff) result |= 0x20; if(int0 >= 0x0200) result |= 0x40; if(int0 >= 0x0201) result |= 0x80; if(result != expected_result) failures=1; } void int_compare1(void) { int0 = -1; c_int_gte_lit1(0x00); int0 = 0; c_int_gte_lit1(0x01); int0 = 1; c_int_gte_lit1(0x03); int0 = 2; c_int_gte_lit1(0x03); int0 = 0xfe; c_int_gte_lit1(0x03); int0 = 0xff; c_int_gte_lit1(0x07); int0 = 0x100; c_int_gte_lit1(0x0f); int0 = 0x101; c_int_gte_lit1(0x1f); int0 = 0x102; c_int_gte_lit1(0x1f); int0 = 0x1fe; c_int_gte_lit1(0x1f); int0 = 0x1ff; c_int_gte_lit1(0x3f); int0 = 0x200; c_int_gte_lit1(0x7f); int0 = 0x201; c_int_gte_lit1(0xff); int0 = 0x7f00; c_int_gte_lit1(0xff); /* now check contiguous ranges */ for(int0 = -0x7fff; int0 != -1; int0++) c_int_gte_lit1(0x00); for(int0 = 1; int0 != 0xff; int0++) c_int_gte_lit1(0x03); for(int0 = 0x201; int0 != 0x7fff; int0++) c_int_gte_lit1(0xff); } void c_int_gte_lit2(unsigned char expected_result) { result = 0; if(int0 >= -0x7fff) result |= 1; if(int0 >= -0x7f00) result |= 2; if(int0 >= -0x7eff) result |= 4; if(int0 >= -0x7e00) result |= 8; if(int0 >= -0x0101) result |= 0x10; if(int0 >= -0x0100) result |= 0x20; if(int0 >= -0xff) result |= 0x40; if(int0 >= -1) result |= 0x80; if(result != expected_result) failures=1; } void int_compare2(void) { int0 = -0x7fff; c_int_gte_lit2(0x01); int0 = -0x7f00; c_int_gte_lit2(0x03); int0 = -0x7eff; c_int_gte_lit2(0x07); int0 = -0x7e00; c_int_gte_lit2(0x0f); int0 = -0x7dff; c_int_gte_lit2(0x0f); int0 = -0x4567; c_int_gte_lit2(0x0f); int0 = -0x200; c_int_gte_lit2(0x0f); int0 = -0x102; c_int_gte_lit2(0x0f); int0 = -0x101; c_int_gte_lit2(0x1f); int0 = -0x100; c_int_gte_lit2(0x3f); int0 = -0xff; c_int_gte_lit2(0x7f); int0 = -0x02; c_int_gte_lit2(0x7f); int0 = -0x01; c_int_gte_lit2(0xff); int0 = 0; c_int_gte_lit2(0xff); int0 = 1; c_int_gte_lit2(0xff); int0 = 0x7fff; c_int_gte_lit2(0xff); /* now check contiguous ranges */ for(int0 = -0x7fff; int0 != -0x7f00; int0++) c_int_gte_lit2(0x01); for(int0 = -0x7e00; int0 != -0x101; int0++) c_int_gte_lit2(0x0f); for(int0 = -1; int0 != 0x7fff; int0++) c_int_gte_lit2(0xff); } int main (void) { char_compare(); printf("failures: %d\n",failures); int_compare1(); printf("failures: %d\n",failures); int_compare2(); success = failures; done (); printf("failures: %d\n",failures); return failures; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/compare2.c�����������������������������������������������������������������������0000664�0000000�0000000�00000010111�13473601511�0015614�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> unsigned char success = 0; unsigned char failures = 0; unsigned char dummy = 0; #ifdef SUPPORT_BIT_TYPES bit bit0 = 0; #endif unsigned int aint0 = 0; unsigned int aint1 = 0; unsigned char achar0 = 0; unsigned char achar1 = 0; void done () { dummy++; } void char_lt_char (void) { if (achar0 < achar1) failures++; } void char_gt_char (void) { if (achar1 > achar0) failures++; } void char_lte_char (void) { if (achar0 <= achar1) failures++; } void char_gte_char (void) { if (achar1 >= achar0) failures++; } void char_lt_lit (void) { if (achar1 < 0x10) failures++; } void char_gt_lit (void) { if (achar1 > 0x10) failures++; } void char_lte_lit (void) { if (achar1 <= 0x0f) failures++; } void char_gte_lit (void) { if (achar1 >= 0x11) failures++; } /* now repeat test using negative logic */ void char_lt_char_else (void) { if (achar0 >= achar1) dummy++; else failures++; } void char_gt_char_else (void) { if (achar1 <= achar0) dummy++; else failures++; } void char_lte_char_else (void) { if (achar0 > achar1) dummy++; else failures++; } void char_gte_char_else (void) { if (achar1 < achar0) dummy++; else failures++; } void char_lt_lit_else (void) { if (achar1 >= 0x10) dummy++; else failures++; } void char_gt_lit_else (void) { if (achar1 <= 0x10) dummy++; else failures++; } void char_lte_lit_else (void) { if (achar1 > 0x0f) dummy++; else failures++; } void char_gte_lit_else (void) { if (achar1 < 0x11) dummy++; else failures++; } /* ints */ void int_lt_int (void) { if (aint0 < aint1) failures++; } void int_gt_int (void) { if (aint1 > aint0) failures++; } void int_lte_int (void) { if (aint0 <= aint1) failures++; } void int_gte_int (void) { if (aint1 >= aint0) failures++; } void int_lt_lit (void) { if (aint1 < 0x10) failures++; } void int_gt_lit (void) { if (aint1 > 0x10) failures++; } void int_lte_lit (void) { if (aint1 <= 0x0f) failures++; } void int_gte_lit (void) { if (aint1 >= 0x11) failures++; } /* now repeat int comparisons using negative logic */ void int_lt_int_else (void) { if (aint0 >= aint1) dummy++; else failures++; } void int_gt_int_else (void) { if (aint1 <= aint0) dummy++; else failures++; } void int_lte_int_else (void) { if (aint0 > aint1) dummy++; else failures++; } void int_gte_int_else (void) { if (aint1 < aint0) dummy++; else failures++; } void int_lt_lit_else (void) { if (aint1 >= 0x10) dummy++; else failures++; } void int_gt_lit_else (void) { if (aint1 <= 0x10) dummy++; else failures++; } void int_lte_lit_else (void) { if (aint1 > 0x0f) dummy++; else failures++; } void int_gte_lit_else (void) { if (aint1 < 0x11) dummy++; else failures++; } int main (void) { char_lt_char (); char_gt_char (); achar0++; char_lt_char (); char_gt_char (); char_gte_char (); char_lte_char (); achar1 = 0x10; char_lt_lit (); char_gt_lit (); char_lte_lit (); char_gte_lit (); achar0 = 0; achar1 = 0; char_lt_char_else (); char_gt_char_else (); achar0++; char_lt_char_else (); char_gt_char_else (); char_gte_char_else (); char_lte_char_else (); achar1 = 0x10; char_lt_lit_else (); char_gt_lit_else (); char_lte_lit_else (); char_gte_lit_else (); int_lt_int (); int_gt_int (); aint0++; int_lt_int (); int_gt_int (); int_gte_int (); int_lte_int (); aint1 = 0x10; int_lt_lit (); int_gt_lit (); int_lte_lit (); int_gte_lit (); aint0=0; aint1=0; int_lt_int_else (); int_gt_int_else (); aint0++; int_lt_int_else (); int_gt_int_else (); int_gte_int_else (); int_lte_int_else (); aint1 = 0x10; int_lt_lit_else (); int_gt_lit_else (); int_lte_lit_else (); int_gte_lit_else (); success = failures; done (); printf("failures: %d\n",failures); return failures; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/compare3.c�����������������������������������������������������������������������0000664�0000000�0000000�00000005555�13473601511�0015635�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! regression testing program for comparing literals to variables !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> /* compare3.c */ unsigned char success = 0; unsigned char failures = 0; unsigned char dummy = 0; #ifdef SUPPORT_BIT_TYPES bit bit0 = 0; #endif unsigned int aint0 = 0; unsigned int aint1 = 0; unsigned char achar0 = 0; unsigned char achar1 = 0; void done () { dummy++; } /* compare to 0 assumes achar0 == 0 achar1 != 0 aint0 == 0 aint1 != 0 */ void c_0(void) { if(achar0 != 0) failures++; if(achar0) failures++; if(achar1 == 0) failures++; if(!achar1) failures++; if(aint0 != 0) failures++; if(aint0) failures++; if(aint1 == 0) failures++; if(!aint1) failures++; } /* compare to 1 assumes achar0 != 1 achar1 == 1 aint0 != 1 aint1 == 1 */ void c_1(void) { if(achar0 == 1) failures++; if(achar1 != 1) failures++; if(aint0 == 1) failures++; if(aint1 != 1) failures++; } /* compare to 2 assumes achar0 == 2 aint0 == 2 */ void c_2(void) { if(achar0 != 2) failures++; if(aint0 != 2) failures++; } /* compare to 0xff assumes achar0 == 0xff aint0 == 0xff */ void c_ff(void) { if(achar0 != 0xff) failures++; if(aint0 != 0xff) failures++; if(aint0 == 0xfe) failures++; if(aint0 == 0xff00) failures++; } /* compare to 0x00a5 assumes achar0 == 0xa5 aint0 == 0x00a5 */ void c_a5(void) { if(achar0 != 0xa5) failures++; if(aint0 != 0xa5) failures++; if(aint0 == 0xa4) failures++; if(aint0 == 0xa500) failures++; } /* compare to 0xa500 assumes achar0 == 0xa5 aint0 == 0xa500 */ void c_a500(void) { if(achar0 == 0xa500) failures++; if(aint0 != 0xa500) failures++; if(aint0 == 0xa400) failures++; if(aint0 == 0x00a5) failures++; } /* compare to 0xabcd assumes achar0 == 0xa5 aint0 == 0xabcd */ void c_abcd(void) { if(achar0 == 0xabcd) failures++; if(aint0 != 0xabcd) failures++; if(aint0 == 0xab00) failures++; if(aint0 == 0x00cd) failures++; if(aint0 == 0x05cd) failures++; if(aint0 == 0xab05) failures++; if(aint0 == 0xab01) failures++; if(aint0 == 0x01cd) failures++; /* if(aint0 == 0x1234abcd) failures++; */ } /* assumes achar1 == 0 */ void c_ifelse1(void) { if(achar0) achar0 = achar1; else achar0 = 0; if(achar0) failures++; } int main (void) { aint1 = 1; achar1 = 1; c_0(); c_1(); aint0 = 2; achar0 = 2; c_2(); aint0 = 0xff; achar0 = 0xff; c_ff(); aint0 = 0xa5; achar0 = 0xa5; c_a5(); aint0 = 0xabcd; c_abcd(); achar0 = 0; achar1 = 0; c_ifelse1(); achar0 = 1; c_ifelse1(); success = failures; done (); printf("failures: %d\n",failures); return failures; } ���������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/compare4.c�����������������������������������������������������������������������0000664�0000000�0000000�00000010616�13473601511�0015630�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! regression testing program for comparing signed chars and ints !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> /* compare4.c */ /*#define COMPARE_OUT_OF_RANGE 1*/ unsigned char success = 0; unsigned char failures = 0; unsigned char dummy = 0; #ifdef SUPPORT_BIT_TYPES bit bit0 = 0; #endif #ifdef SIZEOF_INT_16BIT #if defined(__LINUX__) || defined(LINUX) short int0 = 0; short int1 = 0; #else int int0 = 0; int int1 = 0; #endif #else int int0 = 0; int int1 = 0; #endif signed char char0 = 0; signed char char1 = 0; void done () { dummy++; } /* compare to 0 assumes char0 == 0 char1 != 0 int0 == 0 int1 != 0 */ void c_0(void) { if(char0 != 0) failures++; if(char0) failures++; if(char1 == 0) failures++; if(!char1) failures++; if(int0 != 0) failures++; if(int0) failures++; if(int1 == 0) failures++; if(!int1) failures++; if(char0>0) failures++; if(int0>0) failures++; if(char0<0) failures++; if(int0<0) failures++; } /* compare to 1 assumes char0 != 1 char1 == 1 int0 != 1 int1 == 1 */ void c_1(void) { if(char0 == 1) failures++; if(char1 != 1) failures++; if(int0 == 1) failures++; if(int1 != 1) failures++; if(char0 < 0) failures++; if(int0 < 0) failures++; } /* compare to 2 assumes achar0 == 2 aint0 == 2 */ void c_2(void) { if(char0 != 2) failures++; if(int0 != 2) failures++; } /* compare to 0xff assumes achar0 == 0xff aint0 == 0xff */ void c_ff(void) { if((unsigned char)char0 != 0xff) failures++; if((unsigned short)int0 != 0xff) failures++; if((unsigned short)int0 == 0xfe) failures++; if((unsigned short)int0 == 0xff00) failures++; } /* compare to 0x00a5 assumes char0 == 0xa5 int0 == 0x00a5 */ void c_a5(void) { if((unsigned char)char0 != 0xa5) failures++; if((unsigned short)int0 != 0xa5) failures++; if((unsigned short)int0 == 0xa4) failures++; if((unsigned short)int0 == 0xa500) failures++; } /* compare to 0xa500 assumes char0 == 0xa5 int0 == 0xa500 */ void c_a500(void) { #ifdef COMPARE_OUT_OF_RANGE if(char0 == 0xa500) failures++; #endif if((unsigned short)int0 != 0xa500) failures++; if(int0 != 0x44) int0 = 0x28; if((unsigned short)int0 == 0xa400) failures++; if(int0 == 0x00a5) failures++; } /* compare to 0xabcd assumes char0 == 0xa5 int0 == 0xabcd */ void c_abcd(void) { #ifdef COMPARE_OUT_OF_RANGE if(char0 == 0xabcd) failures++; #endif /* if(int0 != 0xabcd) failures++; */ if((unsigned short)int0 == 0xab00) failures++; if(int0 == 0x00cd) failures++; if(int0 == 0x05cd) failures++; if((unsigned short)int0 == 0xab05) failures++; if((unsigned short)int0 == 0xab01) failures++; if(int0 == 0x01cd) failures++; if(int0 > 0) failures++; #ifdef COMPARE_OUT_OF_RANGE if(int0 == 0x1234abcd) failures++; #endif } /* assumes char1 == 0 */ void c_ifelse1(void) { if(char0) char0 = char1; else char0 = 0; if(char0) failures++; } /* assumes char0 = -1 assumes int0 = -1 */ void c_minus1(void) { if(char0 != -1) failures++; printf("%d\n",failures); if(int0 != -1) failures++; printf("%d\n",failures); if(char0 != int0) failures++; printf("%d\n",failures); if(char0>0) failures++; printf("%d\n",failures); if(int0>0) failures++; printf("%d\n",failures); } void c_c0gtc1(void) { if(char0 < char1) failures++; printf("%d\n",failures); } int main(void) { int1 = 1; char1 = 1; c_0(); printf("failures: %d\n",failures); c_1(); printf("failures: %d\n",failures); int0 = 2; char0 = 2; c_2(); printf("failures: %d\n",failures); int0 = 0xff; char0 = 0xff; c_ff(); printf("failures: %d\n",failures); int0 = 0xa5; char0 = 0xa5; c_a5(); printf("failures: %d\n",failures); int0 = 0xabcd; /*c_abcd();*/ char0 = 0; char1 = 0; c_ifelse1(); printf("failures: %d\n",failures); char0 = 1; c_ifelse1(); printf("failures: %d\n",failures); char0 = -1; int0 = -1; c_minus1(); printf("failures: %d\n",failures); char0 = 5; char1 = 3; c_c0gtc1(); printf("failures: %d\n",failures); char1 = -3; c_c0gtc1(); success = failures; done (); printf("failures: %d\n",failures); return failures; } ������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/compare5.c�����������������������������������������������������������������������0000664�0000000�0000000�00000012713�13473601511�0015631�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! regression testing program for comparing longs !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> /* compare5.c */ #define COMPARE_OUT_OF_RANGE 1 unsigned char success = 0; unsigned char failures = 0; unsigned char dummy = 0; int int0 = 0; int int1 = 0; char char0 = 0; char char1 = 0; long long0 = 0; long long1 = 0; unsigned long ulong0 = 0; unsigned long ulong1 = 0; void done () { dummy++; } /* compare to 0 assumes long0 == 0 ulong0 == 0 */ void c_0(void) { if(long0 != 0) failures++; if(long0 > 0) failures++; if(ulong0 != 0) failures++; if(ulong0 > 0) failures++; } /* compare to 1 assumes long1 == 1 ulong1 == 1 */ void c_1(void) { if(long0 == 1) failures++; if(long1 != 1) failures++; if(ulong0 == 1) failures++; if(ulong1 != 1) failures++; if(long1 < 0) failures++; if(long1 < 1) failures++; if(ulong1 < 1) failures++; if(long1 > 1) failures++; if(ulong1 > 1) failures++; } /* compare to 2 assumes long0 == 2 ulong0 == 2 */ void c_2(void) { if(long0 != 2) failures++; if(ulong0 != 2) failures++; if(long1 == 2) failures++; if(ulong1 == 2) failures++; } /* compare to 0xff assumes achar0 == 0xff aint0 == 0xff */ void c_ff(void) { if(long0 != 0xff) failures++; if(ulong0 != 0xff) failures++; if(long1 == 0xff) failures++; if(ulong1 == 0xff) failures++; } /* compare to 0x200 assumes achar0 == 0x200 aint0 == 0x200 */ void c_200(void) { if(long0 != 0x200) failures++; if(ulong0 != 0x200) failures++; if(long1 == 0x200) failures++; if(ulong1 == 0x200) failures++; } /* compare to 0x20000 assumes long0 == 0x20000 ulong0 == 0x20000 long1 != 0x20000 ulong1 != 0x20000 */ void c_20000(void) { if(long0 != 0x20000) failures++; if(ulong0 != 0x20000) failures++; if(long1 == 0x20000) failures++; if(ulong1 == 0x20000) failures++; if(long0 <= 0x10000) failures++; if(long0 < 0x10000) failures++; /* if(long0 < 0x12345) failures++; */ if(long0 == 0) failures++; } /* compare to 0x00a5 assumes char0 == 0xa5 int0 == 0x00a5 */ void c_a5(void) { if(char0 != 0xa5) failures++; if(int0 != 0xa5) failures++; if(int0 == 0xa4) failures++; if(int0 == 0xa500) failures++; } /* compare to 0xa500 assumes char0 == 0xa5 int0 == 0xa500 */ void c_a500(void) { #ifdef COMPARE_OUT_OF_RANGE if(char0 == 0xa500) failures++; #endif if(int0 != 0xa500) failures++; if(int0 == 0xa400) failures++; if(int0 == 0x00a5) failures++; } /* compare to 0xabcd assumes char0 == 0xa5 int0 == 0xabcd */ void c_abcd(void) { #ifdef COMPARE_OUT_OF_RANGE if(char0 == 0xabcd) failures++; #endif if(int0 != 0xabcd) failures++; if(int0 == 0xab00) failures++; if(int0 == 0x00cd) failures++; if(int0 == 0x05cd) failures++; if(int0 == 0xab05) failures++; if(int0 == 0xab01) failures++; if(int0 == 0x01cd) failures++; if(int0 > 0) failures++; #ifdef COMPARE_OUT_OF_RANGE if(int0 == 0x1234abcd) failures++; #endif } /* assumes char1 == 0 */ void c_ifelse1(void) { if(char0) char0 = char1; else char0 = 0; if(char0) failures++; } /* assumes long0 = -1 assumes long1 = 1 */ void c_minus1(void) { printf("long0:%ld long1:%ld\n",long0,long1); printf("(long0 != -1)\n"); if(long0 != -1) { failures++; } printf("(long0 > 0)\n"); if(long0 > 0) { failures++; } printf("(long1 < 0)\n"); if(long1 < 0) { failures++; } /* if(long1 < 2) failures++; */ } /* assumes long0 = long1 = ulong0 = ulong1 == 0 */ void c_long2long_eq(void) { if(long0 != long1) failures++; if(ulong0 != ulong1) failures++; if(long0 != ulong1) failures++; if(long0 > long1) failures++; if(long0 < long1) failures++; if(long0 > ulong0) failures++; if(long0 < ulong0) failures++; } /* assumes long0 = ulong0 == 0 long1 = ulong1 == 1 */ void c_long2long_neq(void) { if(long0 == long1) failures++; if(ulong0 == ulong1) failures++; if(long1 != ulong1) failures++; if(long1 < long0) failures++; if(long1 <= long0) failures++; if(ulong1 < ulong0) failures++; if(ulong1 <= ulong0) failures++; } /* long0=-100; long1=-1000; */ void c_long2neglit(void) { if(long0>0) failures++; if(long1>0) failures++; if(long1 > long0) failures++; if(long1 > 100) failures++; if(long0 > -50) failures++; if(long1 < -5000) failures++; } int main (void) { c_0(); printf("c_0: %d\n",failures); c_long2long_eq(); printf("c_long2long_eq: %d\n",failures); long1 = 1; ulong1 = 1; c_1(); printf("c_1: %d\n",failures); c_long2long_neq(); printf("c_long2long_neq: %d\n",failures); long0 = 2; ulong0 = 2; c_2(); printf("c_2: %d\n",failures); long0 = 0xff; ulong0 = 0xff; c_ff(); printf("c_ff: %d\n",failures); long0 = 0x200; ulong0 = 0x200; c_200(); printf("c_200: %d\n",failures); long0 = 0x20000; ulong0 = 0x20000; c_20000(); printf("c_20000: %d\n",failures); long0 = -1; c_minus1(); printf("c_minus1: %d\n",failures); long0=-100; long1=-1000; c_long2neglit(); printf("c_long2neglit: %d\n",failures); success = failures; done (); printf("failures: %d\n",failures); return failures; } �����������������������������������������������������cc65-2.18/test/val/compare6.c�����������������������������������������������������������������������0000664�0000000�0000000�00000004367�13473601511�0015640�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! Compound comparisons !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> unsigned char success = 0; unsigned char failures = 0; unsigned char dummy = 0; #ifdef SUPPORT_BIT_TYPES bit bit0 = 0; #endif int int0 = 0; int int1 = 0; unsigned char uchar0 = 0; unsigned char uchar1 = 0; char char0 = 0; char char1 = 0; char long0 = 0; char long1 = 0; void done () { dummy++; } void c_char(void) { if(char0 || char1) failures++; if(char0 && char1) failures++; if(char0 > char1) failures++; if((char0+1) < char1) failures++; if((char0+5) >= (char1+9)) failures++; char0++; if(char0 && char1) failures++; if(char0 != (char1+1) ) failures++; if(!char0) failures++; if(char1 || !char0) failures++; if((char0 >5 ) && (char0 < 10)) failures++; char0 +=5; /* char0 = 6 now */ if(!((char0 >5 ) && (char0 < 10))) failures++; } void c_int(void) { if(int0 || int1) failures++; if(int0 && int1) failures++; if(int0 > int1) failures++; if((int0+1) < int1) failures++; if((int0+5) >= (int1+9)) failures++; int0++; if(int0 && int1) failures++; if(int0 != (int1+1) ) failures++; if(!int0) failures++; if(int1 || !int0) failures++; if((int0 >5 ) && (int0 < 10)) failures++; int0 +=5; /* int0 = 6 now */ if(!((int0 >5 ) && (int0 < 10))) failures++; } void c_long(void) { if(long0 || long1) failures++; if(long0 && long1) failures++; if(long0 > long1) failures++; if((long0+1) < long1) failures++; if((long0+5) >= (long1+9)) failures++; long0++; if(long0 && long1) failures++; if(long0 != (long1+1) ) failures++; if(!long0) failures++; if(long1 || !long0) failures++; if((long0 >5 ) && (long0 < 10)) failures++; long0 +=5; /* long0 = 6 now */ if(!((long0 >5 ) && (long0 < 10))) failures++; } void c_uminus(void) { int1 = -int0; if(int1 < 0) failures++; } int main (void) { c_char(); c_int(); c_long(); int0 = -1; c_uminus(); if(int1 != 1) failures++; success = failures; done (); printf("failures: %d\n",failures); return failures; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/compare7.c�����������������������������������������������������������������������0000664�0000000�0000000�00000011145�13473601511�0015631�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! Signed comparisons of the form: (variable<LIT) !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> /* This regression test exercises all of the boundary conditions in literal less than comparisons. There are numerous opportunities to optimize these comparison and each one has an astonishing capability of failing a boundary condition. */ unsigned char success = 0; unsigned char failures = 0; unsigned char dummy = 0; unsigned char result = 0; #ifdef SUPPORT_BIT_TYPES bit bit0 = 0; #endif int int0 = 0; int int1 = 0; signed char char0 = 0; signed char char1 = 0; char long0 = 0; char long1 = 0; /* *** NOTE *** This particular test takes quite a while to run * ~ 10,000,000 instruction cycles. (2.5 seconds on a 20Mhz PIC). * The WDT will reset the CPU if it's enabled. So disable it... */ void done () { dummy++; } void c_char_lt_lit1(unsigned char expected_result) { result = 0; if(char0 < -0x7f) result |= 1; if(char0 < -1) result |= 2; if(char0 < 0) result |= 4; if(char0 < 1) result |= 8; if(char0 < 0x7f) result |= 0x10; if(result != expected_result) failures++; } void char_compare(void) { char0 = 0x7f; c_char_lt_lit1(0); /* return; */ char0 = 0x7e; c_char_lt_lit1(0x10); char0 = 0x40; c_char_lt_lit1(0x10); char0 = 0x2; c_char_lt_lit1(0x10); char0 = 0x1; c_char_lt_lit1(0x10); char0 = 0; c_char_lt_lit1(0x18); char0 = -1; c_char_lt_lit1(0x1c); char0 = -2; c_char_lt_lit1(0x1e); char0 = -0x40; c_char_lt_lit1(0x1e); char0 = -0x7e; c_char_lt_lit1(0x1e); char0 = -0x7f; c_char_lt_lit1(0x1e); char0 = 0x80; c_char_lt_lit1(0x1f); /* Now test entire range */ for(char0=1; char0 != 0x7f; char0++) c_char_lt_lit1(0x10); for(char0=-0x7f; char0 != -1; char0++) c_char_lt_lit1(0x1e); } void c_int_lt_lit1(unsigned char expected_result) { result = 0; if(int0 < 0) result |= 1; if(int0 < 1) result |= 2; if(int0 < 0xff) result |= 4; if(int0 < 0x100) result |= 8; if(int0 < 0x0101) result |= 0x10; if(int0 < 0x01ff) result |= 0x20; if(int0 < 0x0200) result |= 0x40; if(int0 < 0x0201) result |= 0x80; if(result != expected_result) failures=1; } void int_compare1(void) { int0 = -1; c_int_lt_lit1(0xff); int0 = 0; c_int_lt_lit1(0xfe); int0 = 1; c_int_lt_lit1(0xfc); int0 = 2; c_int_lt_lit1(0xfc); int0 = 0xfe; c_int_lt_lit1(0xfc); int0 = 0xff; c_int_lt_lit1(0xf8); int0 = 0x100; c_int_lt_lit1(0xf0); int0 = 0x101; c_int_lt_lit1(0xe0); int0 = 0x1fe; c_int_lt_lit1(0xe0); int0 = 0x1ff; c_int_lt_lit1(0xc0); int0 = 0x200; c_int_lt_lit1(0x80); int0 = 0x201; c_int_lt_lit1(0x0); int0 = 0x7f00; c_int_lt_lit1(0x0); /* now check contiguous ranges */ for(int0 = -0x7fff; int0 != -1; int0++) c_int_lt_lit1(0xff); for(int0 = 1; int0 != 0xff; int0++) c_int_lt_lit1(0xfc); for(int0 = 0x201; int0 != 0x7fff; int0++) c_int_lt_lit1(0); } void c_int_lt_lit2(unsigned char expected_result) { result = 0; if(int0 < -0x7fff) result |= 1; if(int0 < -0x7f00) result |= 2; if(int0 < -0x7eff) result |= 4; if(int0 < -0x7e00) result |= 8; if(int0 < -0x0101) result |= 0x10; if(int0 < -0x0100) result |= 0x20; if(int0 < -0xff) result |= 0x40; if(int0 < -1) result |= 0x80; if(result != expected_result) failures=1; } void int_compare2(void) { int0 = -0x7fff; c_int_lt_lit2(0xfe); int0 = -0x7f00; c_int_lt_lit2(0xfc); int0 = -0x7eff; c_int_lt_lit2(0xf8); int0 = -0x7e00; c_int_lt_lit2(0xf0); int0 = -0x4567; c_int_lt_lit2(0xf0); int0 = -0x200; c_int_lt_lit2(0xf0); int0 = -0x102; c_int_lt_lit2(0xf0); int0 = -0x101; c_int_lt_lit2(0xe0); int0 = -0x100; c_int_lt_lit2(0xc0); int0 = -0xff; c_int_lt_lit2(0x80); int0 = -0x02; c_int_lt_lit2(0x80); int0 = -0x01; c_int_lt_lit2(0x00); int0 = 0; c_int_lt_lit2(0x00); int0 = 1; c_int_lt_lit2(0x00); int0 = 0x7fff; c_int_lt_lit2(0x00); /* now check contiguous ranges */ int0 = -0x7f01; c_int_lt_lit2(0xfe); for(int0 = -0x7ffe; int0 != -0x7f01; int0++) c_int_lt_lit2(0xfe); for(int0 = -0x7e00; int0 != -0x101; int0++) c_int_lt_lit2(0xf0); for(int0 = -1; int0 != 0x7fff; int0++) c_int_lt_lit2(0); } int main (void) { char_compare(); printf("failures: %d\n",failures); int_compare1(); printf("failures: %d\n",failures); int_compare2(); success = failures; done (); printf("failures: %d\n",failures); return failures; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/compare8.c�����������������������������������������������������������������������0000664�0000000�0000000�00000011235�13473601511�0015632�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! Signed comparisons of the form: (variable>LIT) !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> /* This regression test exercises all of the boundary conditions in literal less than comparisons. There are numerous opportunities to optimize these comparison and each one has an astonishing capability of failing a boundary condition. */ unsigned char success = 0; unsigned char failures = 0; unsigned char dummy = 0; unsigned char result = 0; #ifdef SUPPORT_BIT_TYPES bit bit0 = 0; #endif int int0 = 0; int int1 = 0; unsigned char uchar0 = 0; unsigned char uchar1 = 0; signed char char0 = 0; signed char char1 = 0; char long0 = 0; char long1 = 0; /* *** NOTE *** This particular test takes quite a while to run * ~ 10,000,000 instruction cycles. (2.5 seconds on a 20Mhz PIC). * The WDT will reset the CPU if it's enabled. So disable it... */ void done () { dummy++; } void c_char_gt_lit1(unsigned char expected_result) { result = 0; if(char0 > -0x7f) result |= 1; if(char0 > -1) result |= 2; if(char0 > 0) result |= 4; if(char0 > 1) result |= 8; if(char0 > 0x7e) result |= 0x10; if(char0 > 0x7f) result |= 0x20; if(result != expected_result) failures++; } void char_compare(void) { char0 = 0x7f; c_char_gt_lit1(0x1f); char0 = 0x7e; c_char_gt_lit1(0x0f); char0 = 0x40; c_char_gt_lit1(0x0f); char0 = 0x2; c_char_gt_lit1(0x0f); char0 = 0x1; c_char_gt_lit1(0x07); char0 = 0; c_char_gt_lit1(0x03); char0 = -1; c_char_gt_lit1(0x01); char0 = -2; c_char_gt_lit1(0x01); char0 = -0x40; c_char_gt_lit1(0x01); char0 = -0x7e; c_char_gt_lit1(0x01); char0 = -0x7f; c_char_gt_lit1(0x00); char0 = 0x80; c_char_gt_lit1(0x00); /* Now test entire range */ for(char0=2; char0 != 0x7f; char0++) c_char_gt_lit1(0x0f); for(char0=-0x7e; char0 != -1; char0++) c_char_gt_lit1(0x01); } void c_int_gt_lit1(unsigned char expected_result) { result = 0; if(int0 > 0) result |= 1; if(int0 > 1) result |= 2; if(int0 > 0xff) result |= 4; if(int0 > 0x100) result |= 8; if(int0 > 0x0101) result |= 0x10; if(int0 > 0x01ff) result |= 0x20; if(int0 > 0x0200) result |= 0x40; if(int0 > 0x0201) result |= 0x80; if(result != expected_result) failures=1; } void int_compare1(void) { int0 = -1; c_int_gt_lit1(0x00); int0 = 0; c_int_gt_lit1(0x00); int0 = 1; c_int_gt_lit1(0x01); int0 = 2; c_int_gt_lit1(0x03); int0 = 0xfe; c_int_gt_lit1(0x03); int0 = 0xff; c_int_gt_lit1(0x03); int0 = 0x100; c_int_gt_lit1(0x07); int0 = 0x101; c_int_gt_lit1(0x0f); int0 = 0x102; c_int_gt_lit1(0x1f); int0 = 0x1fe; c_int_gt_lit1(0x1f); int0 = 0x1ff; c_int_gt_lit1(0x1f); int0 = 0x200; c_int_gt_lit1(0x3f); int0 = 0x201; c_int_gt_lit1(0x7f); int0 = 0x7f00; c_int_gt_lit1(0xff); /* now check contiguous ranges */ for(int0 = -0x7fff; int0 != -1; int0++) c_int_gt_lit1(0x00); for(int0 = 2; int0 != 0xff; int0++) c_int_gt_lit1(0x03); for(int0 = 0x202; int0 != 0x7fff; int0++) c_int_gt_lit1(0xff); } void c_int_gt_lit2(unsigned char expected_result) { result = 0; if(int0 > -0x7fff) result |= 1; if(int0 > -0x7f00) result |= 2; if(int0 > -0x7eff) result |= 4; if(int0 > -0x7e00) result |= 8; if(int0 > -0x0101) result |= 0x10; if(int0 > -0x0100) result |= 0x20; if(int0 > -0xff) result |= 0x40; if(int0 > -1) result |= 0x80; if(result != expected_result) failures=1; } void int_compare2(void) { int0 = -0x7fff; c_int_gt_lit2(0x00); int0 = -0x7f00; c_int_gt_lit2(0x01); int0 = -0x7eff; c_int_gt_lit2(0x03); int0 = -0x7e00; c_int_gt_lit2(0x07); int0 = -0x7dff; c_int_gt_lit2(0x0f); int0 = -0x4567; c_int_gt_lit2(0x0f); int0 = -0x200; c_int_gt_lit2(0x0f); int0 = -0x102; c_int_gt_lit2(0x0f); int0 = -0x101; c_int_gt_lit2(0x0f); int0 = -0x100; c_int_gt_lit2(0x1f); int0 = -0xff; c_int_gt_lit2(0x3f); int0 = -0x02; c_int_gt_lit2(0x7f); int0 = -0x01; c_int_gt_lit2(0x7f); int0 = 0; c_int_gt_lit2(0xff); int0 = 1; c_int_gt_lit2(0xff); int0 = 0x7fff; c_int_gt_lit2(0xff); /* now check contiguous ranges */ for(int0 = -0x7ffe; int0 != -0x7f01; int0++) c_int_gt_lit2(0x01); for(int0 = -0x7dff; int0 != -0x101; int0++) c_int_gt_lit2(0x0f); for(int0 = 0; int0 != 0x7fff; int0++) c_int_gt_lit2(0xff); } int main (void) { char_compare(); int_compare1(); int_compare2(); success = failures; done (); printf("failures: %d\n",failures); return failures; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/compare9.c�����������������������������������������������������������������������0000664�0000000�0000000�00000010761�13473601511�0015636�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! Signed comparisons of the form: (variable<=LIT) !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> /* This regression test exercises all of the boundary conditions in literal less than or equal comparisons. There are numerous opportunities to optimize these comparison and each one has an astonishing capability of failing a boundary condition. */ unsigned char success = 0; unsigned char failures = 0; unsigned char dummy = 0; unsigned char result = 0; int int0 = 0; int int1 = 0; signed char char0 = 0; signed char char1 = 0; /* *** NOTE *** This particular test takes quite a while to run * ~ 10,000,000 instruction cycles. (2.5 seconds on a 20Mhz PIC). * The WDT will reset the CPU if it's enabled. So disable it... */ void done () { dummy++; } void c_char_lte_lit1(unsigned char expected_result) { result = 0; if(char0 <= -0x7f) result |= 1; if(char0 <= -1) result |= 2; if(char0 <= 0) result |= 4; if(char0 <= 1) result |= 8; if(char0 <= 0x7f) result |= 0x10; if(result != expected_result) failures++; } void char_compare(void) { char0 = 0x7f; c_char_lte_lit1(0x10); char0 = 0x7e; c_char_lte_lit1(0x10); char0 = 0x40; c_char_lte_lit1(0x10); char0 = 0x2; c_char_lte_lit1(0x10); char0 = 0x1; c_char_lte_lit1(0x18); char0 = 0; c_char_lte_lit1(0x1c); char0 = -1; c_char_lte_lit1(0x1e); char0 = -2; c_char_lte_lit1(0x1e); char0 = -0x40; c_char_lte_lit1(0x1e); char0 = -0x7e; c_char_lte_lit1(0x1e); char0 = -0x7f; c_char_lte_lit1(0x1f); char0 = 0x80; /* c_char_lte_lit1(0x1f); */ /* Now test entire range */ for(char0=2; char0 != 0x7f; char0++) c_char_lte_lit1(0x10); for(char0=-0x7e; char0 != 0; char0++) c_char_lte_lit1(0x1e); } void c_int_lte_lit1(unsigned char expected_result) { result = 0; if(int0 <= 0) result |= 1; if(int0 <= 1) result |= 2; if(int0 <= 0xff) result |= 4; if(int0 <= 0x100) result |= 8; if(int0 <= 0x0101) result |= 0x10; if(int0 <= 0x01ff) result |= 0x20; if(int0 <= 0x0200) result |= 0x40; if(int0 <= 0x0201) result |= 0x80; if(result != expected_result) failures=1; } void int_compare1(void) { int0 = -1; c_int_lte_lit1(0xff); int0 = 0; c_int_lte_lit1(0xff); int0 = 1; c_int_lte_lit1(0xfe); int0 = 2; c_int_lte_lit1(0xfc); int0 = 0xfe; c_int_lte_lit1(0xfc); int0 = 0xff; c_int_lte_lit1(0xfc); int0 = 0x100; c_int_lte_lit1(0xf8); int0 = 0x101; c_int_lte_lit1(0xf0); int0 = 0x1fe; c_int_lte_lit1(0xe0); int0 = 0x1ff; c_int_lte_lit1(0xe0); int0 = 0x200; c_int_lte_lit1(0xc0); int0 = 0x201; c_int_lte_lit1(0x80); int0 = 0x7f00; c_int_lte_lit1(0x0); /* now check contiguous ranges */ for(int0 = -0x7fff; int0 != 1; int0++) c_int_lte_lit1(0xff); for(int0 = 2; int0 != 0xff; int0++) c_int_lte_lit1(0xfc); for(int0 = 0x202; int0 != 0x7fff; int0++) c_int_lte_lit1(0); } void c_int_lte_lit2(unsigned char expected_result) { result = 0; if(int0 <= -0x7fff) result |= 1; if(int0 <= -0x7f00) result |= 2; if(int0 <= -0x7eff) result |= 4; if(int0 <= -0x7e00) result |= 8; if(int0 <= -0x0101) result |= 0x10; if(int0 <= -0x0100) result |= 0x20; if(int0 <= -0xff) result |= 0x40; if(int0 <= -1) result |= 0x80; if(result != expected_result) failures=1; } void int_compare2(void) { int0 = -0x7fff; c_int_lte_lit2(0xff); int0 = -0x7f00; c_int_lte_lit2(0xfe); int0 = -0x7eff; c_int_lte_lit2(0xfc); int0 = -0x7e00; c_int_lte_lit2(0xf8); int0 = -0x4567; c_int_lte_lit2(0xf0); int0 = -0x200; c_int_lte_lit2(0xf0); int0 = -0x102; c_int_lte_lit2(0xf0); int0 = -0x101; c_int_lte_lit2(0xf0); int0 = -0x100; c_int_lte_lit2(0xe0); int0 = -0xff; c_int_lte_lit2(0xc0); int0 = -0x02; c_int_lte_lit2(0x80); int0 = -0x01; c_int_lte_lit2(0x80); int0 = 0; c_int_lte_lit2(0x00); int0 = 1; c_int_lte_lit2(0x00); int0 = 0x7fff; c_int_lte_lit2(0x00); /* now check contiguous ranges */ for(int0 = -0x7ffe; int0 != -0x7f00; int0++) c_int_lte_lit2(0xfe); for(int0 = -0x7dff; int0 != -0x101; int0++) c_int_lte_lit2(0xf0); for(int0 = 0; int0 != 0x7fff; int0++) c_int_lte_lit2(0); } int main (void) { char_compare(); int_compare1(); int_compare2(); success = failures; done (); printf("failures: %d\n",failures); return failures; } ���������������cc65-2.18/test/val/computedgoto.c�������������������������������������������������������������������0000664�0000000�0000000�00000001437�13473601511�0016630�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������static unsigned char val, val2; static void act(const unsigned char op) { static const void * const arr[] = { &&op0, &&op1, &&op2, &&op3, &&op4, &&op5, &&op6, }; goto *arr[op]; op0: val += 1; return; op1: val += 2; return; op2: val += 3; return; op3: val2 += 1; return; op4: val2 += 5; return; op5: val2 += 7; return; op6: val2 += 9; return; } int main(void) { val = val2 = 0; act(1); act(3); act(5); return val == 2 && val2 == 8 ? 0 : 1; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/cq22.c���������������������������������������������������������������������������0000664�0000000�0000000�00000010025�13473601511�0014657�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! C-Manual Chapter 2.2: identifiers (names) !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include "common.h" struct defs { int cbits; /* No. of bits per char */ int ibits; /* int */ int sbits; /* short */ int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ }; int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ /* 2.2 Identifiers (Names) */ #ifndef NO_OLD_FUNC_DECL s22(pd0) struct defs *pd0; { #else int s22(struct defs *pd0) { #endif int a234, a; int _, _234, A, rc; static char s22er[] = "s22,er%d\n"; static char qs22[8] = "s22 "; char *ps, *pt; /* Initialize */ rc = 0; ps = qs22; pt = pd0 -> rfs; while (*pt++ = *ps++); /* An identifier is a sequence of letters and digits; the first character must be a letter. The under- score _ counts as a letter. */ a=1; _=2; _234=3; a234=4; if(a+_+_234+a234 != 10) { rc = rc+1; if(pd0->flgd != 0) printf(s22er,1); } /* Upper and lower case letters are different. */ A = 2; if (A == a) { rc = rc+4; if (pd0->flgd != 0) printf(s22er,4); } return(rc); } /********************************************************************************************* the main loop that launches the sections *********************************************************************************************/ #define cq_sections 1 #ifndef NO_TYPELESS_STRUCT_PTR int section(int j,struct* pd0){ #else int section(int j,void* pd0){ #endif switch(j){ case 0: return s22(pd0); } } /* C REFERENCE MANUAL (main) */ #ifndef NO_OLD_FUNC_DECL main(n,args) int n; char **args; { #else int main(int n,char **args) { #endif int j; static struct defs d0, *pd0; d0.flgs = 1; /* These flags dictate */ d0.flgm = 1; /* the verbosity of */ d0.flgd = 1; /* the program. */ d0.flgl = 1; pd0 = &d0; for (j=0; j<cq_sections; j++) { d0.rrc=section(j,pd0); d0.crc=d0.crc+d0.rrc; if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); } if(d0.crc == 0) printf("\nNo errors detected.\n"); else printf("\nFailed.\n"); return d0.crc; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/cq241.c��������������������������������������������������������������������������0000664�0000000�0000000�00000023721�13473601511�0014751�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! C-Manual Chapter 2.41: integer constants, 2.42: explizit long constants !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include "common.h" struct defs { int cbits; /* No. of bits per char */ int ibits; /* int */ int sbits; /* short */ int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ }; int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ /* 2.4.1 Integer constants 2.4.2 Explicit long constants */ /* Calculate 2**n by multiplying, not shifting */ #ifndef NO_OLD_FUNC_DECL long pow2(n) long n; { #else long pow2(long n) { #endif long s; s = 1; while(n--) s = s*2; return s; } long d[39], o[39], x[39]; #ifndef NO_OLD_FUNC_DECL s241(pd0) struct defs *pd0; { #else int s241(struct defs *pd0) { #endif /* long pow2(); */ static char s241er[] = "s241,er%d\n"; static char qs241[8] = "s241 "; char *ps, *pt; int rc, j, lrc; static long g[39] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,6,0,8,0,12,0,16,0,18,0,20,0,24, 0,28,0,30,0,32,0,36}; /* long d[39], o[39], x[39]; */ rc = 0; lrc = 0; ps = qs241; pt = pd0 -> rfs; while (*pt++ = *ps++); /* An integer constant consisting of a sequence of digits is taken to be octal if it begins with 0 (digit zero), decimal otherwise. */ if ( 8 != 010 || 16 != 020 || 24 != 030 || 32 != 040 || 40 != 050 || 48 != 060 || 56 != 070 || 64 != 0100 || 72 != 0110 || 80 != 0120 || 9 != 0011 || 17 != 0021 || 25 != 0031 || 33 != 0041 || 41 != 0051 || 49 != 0061 || 57 != 0071 || 65 != 0101 || 73 != 0111 || 81 != 0121 ){ rc = rc+1; if( pd0->flgd != 0 ) printf(s241er,1); } /* A sequence of digits preceded by 0x or 0X (digit zero) is taken to be a hexadecimal integer. The hexadecimal digits include a or A through f or F with values 10 through 15. */ if ( 0x00abcdef != 0xabcdef || 0xabcdef != 0Xabcdef || 0Xabcdef != 0XAbcdef || 0XAbcdef != 0XABcdef || 0XABcdef != 0XABCdef || 0XABCdef != 0XABCDef || 0XABCDef != 0XABCDEf || 0XABCDEf != 0XABCDEF || 0xABCDEF != 11259375 ){ rc = rc+2; if( pd0->flgd != 0 ) printf(s241er,2); } /* A decimal constant whose value exceeds the largest signed machine integer is taken to be long; an octal or hex con- stant which exceeds the largest unsigned machine integer is likewise taken to be long. */ #if defined(REFERENCE) && defined(REFCC_SIZEOF_LONG_64BIT) /*#warning "sizeof(long)!=4, skipping test"*/ #else if ( sizeof 010000000000 != sizeof(long) /* 2**30 */ || sizeof 1073741824 != sizeof(long) /* ditto */ || sizeof 0x40000000 != sizeof(long) ){ /* " */ rc = rc+4; if( pd0->flgd != 0 ) printf(s241er,4); } #endif /* A decimal, octal, or hexadecimal constant immediately followed by l (letter ell) or L is a long constant. */ if ( sizeof 67l != sizeof(long) || sizeof 67L != sizeof(long) || sizeof 067l != sizeof(long) || sizeof 067L != sizeof(long) || sizeof 0X67l != sizeof(long) || sizeof 0x67L != sizeof(long) ){ rc = rc+8; if( pd0 -> flgd != 0 ) printf(s241er,8); } /* Finally, we test to see that decimal (d), octal (o), and hexadecimal (x) constants representing the same values agree among themselves, and with computed values, at spec- ified points over an appropriate range. The points select- ed here are those with the greatest potential for caus- ing trouble, i.e., zero, 1-16, and values of 2**n and 2**n - 1 where n is some multiple of 4 or 6. Unfortunately, just what happens when a value is too big to fit in a long is undefined; however, it would be nice if what happened were at least consistent... */ for ( j=0; j<17; j++ ) g[j] = j; for ( j=18; j<39; ) { g[j] = pow2(g[j]); g[j-1] = g[j] - 1; j = j+2; } d[0] = 0; o[0] = 00; x[0] = 0x0; d[1] = 1; o[1] = 01; x[1] = 0x1; d[2] = 2; o[2] = 02; x[2] = 0x2; d[3] = 3; o[3] = 03; x[3] = 0x3; d[4] = 4; o[4] = 04; x[4] = 0x4; d[5] = 5; o[5] = 05; x[5] = 0x5; d[6] = 6; o[6] = 06; x[6] = 0x6; d[7] = 7; o[7] = 07; x[7] = 0x7; d[8] = 8; o[8] = 010; x[8] = 0x8; d[9] = 9; o[9] = 011; x[9] = 0x9; d[10] = 10; o[10] = 012; x[10] = 0xa; d[11] = 11; o[11] = 013; x[11] = 0xb; d[12] = 12; o[12] = 014; x[12] = 0xc; d[13] = 13; o[13] = 015; x[13] = 0xd; d[14] = 14; o[14] = 016; x[14] = 0xe; d[15] = 15; o[15] = 017; x[15] = 0xf; d[16] = 16; o[16] = 020; x[16] = 0x10; d[17] = 63; o[17] = 077; x[17] = 0x3f; d[18] = 64; o[18] = 0100; x[18] = 0x40; d[19] = 255; o[19] = 0377; x[19] = 0xff; d[20] = 256; o[20] = 0400; x[20] = 0x100; d[21] = 4095; o[21] = 07777; x[21] = 0xfff; d[22] = 4096; o[22] = 010000; x[22] = 0x1000; d[23] = 65535; o[23] = 0177777; x[23] = 0xffff; d[24] = 65536; o[24] = 0200000; x[24] = 0x10000; d[25] = 262143; o[25] = 0777777; x[25] = 0x3ffff; d[26] = 262144; o[26] = 01000000; x[26] = 0x40000; d[27] = 1048575; o[27] = 03777777; x[27] = 0xfffff; d[28] = 1048576; o[28] = 04000000; x[28] = 0x100000; d[29] = 16777215; o[29] = 077777777; x[29] = 0xffffff; d[30] = 16777216; o[30] = 0100000000; x[30] = 0x1000000; d[31] = 268435455; o[31] = 01777777777; x[31] = 0xfffffff; d[32] = 268435456; o[32] = 02000000000; x[32] = 0x10000000; d[33] = 1073741823; o[33] = 07777777777; x[33] = 0x3fffffff; d[34] = 1073741824; o[34] = 010000000000; x[34] = 0x40000000; d[35] = 4294967295; o[35] = 037777777777; x[35] = 0xffffffff; d[36] = 4294967296; o[36] = 040000000000; x[36] = 0x100000000; d[37] = 68719476735; o[37] = 0777777777777; x[37] = 0xfffffffff; d[38] = 68719476736; o[38] = 01000000000000; x[38] = 0x1000000000; /* WHEW! */ for (j=0; j<39; j++){ if ( g[j] != d[j] || d[j] != o[j] || o[j] != x[j]) { if( pd0 -> flgm != 0 ) { /* printf(s241er,16); save in case opinions change... */ printf("Decimal and octal/hex constants sometimes give\n"); printf(" different results when assigned to longs.\n"); } /* lrc = 1; save... */ } } if (lrc != 0) rc =16; return rc; } /********************************************************************************************* the main loop that launches the sections *********************************************************************************************/ #define cq_sections 1 #ifndef NO_TYPELESS_STRUCT_PTR int section(int j,struct* pd0){ #else int section(int j,void* pd0){ #endif switch(j){ case 0: return s241(pd0); } } /* C REFERENCE MANUAL (main) */ #ifndef NO_OLD_FUNC_DECL main(n,args) int n; char **args; { #else int main(int n,char **args) { #endif int j; static struct defs d0, *pd0; d0.flgs = 1; /* These flags dictate */ d0.flgm = 1; /* the verbosity of */ d0.flgd = 1; /* the program. */ d0.flgl = 1; pd0 = &d0; for (j=0; j<cq_sections; j++) { d0.rrc=section(j,pd0); d0.crc=d0.crc+d0.rrc; if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); } if(d0.crc == 0) printf("\nNo errors detected.\n"); else printf("\nFailed.\n"); return d0.crc; } �����������������������������������������������cc65-2.18/test/val/cq243.c��������������������������������������������������������������������������0000664�0000000�0000000�00000020652�13473601511�0014753�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! C-Manual Chapter 2.43: character constants !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include "common.h" struct defs { int cbits; /* No. of bits per char */ int ibits; /* int */ int sbits; /* short */ int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ }; int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ /********************************************************************************************* 2.4.3 Character constants **********************************************************************************************/ #ifndef NO_OLD_FUNC_DECL zerofill(x) char *x; { #else void zerofill(char *x) { #endif int j; for (j=0; j<256; j++) *x++ = 0; } #ifndef NO_OLD_FUNC_DECL sumof(x) char *x; { #else int sumof(char *x) { #endif char *p; int total, j; p = x; total = 0; for(j=0; j<256; j++) total = total+ *p++; return total; } char chars[256]; #ifndef NO_OLD_FUNC_DECL s243(pd0) struct defs *pd0; { #else int s243(struct defs *pd0) { #endif static char s243er[] = "s243,er%d\n"; static char qs243[8] = "s243 "; char *ps, *pt; int rc; /* char chars[256]; */ rc = 0; ps = qs243; pt = pd0->rfs; while(*pt++ = *ps++); /* One of the problems that arises when testing character constants is that of definition: What, exactly, is the character set? In order to guarantee a certain amount of machine independence, the character set we will use here is the set of characters writ- able as escape sequences in C, plus those characters used in writ- ing C programs, i.e., letters: ABCDEFGHIJKLMNOPQRSTUVWXYZ 26 abcdefghijklmnopqrstuvwxyz 26 numbers: 0123456789 10 special characters: ~!"#%&()_=-^|{}[]+;*:<>,.?/ 27 extra special characters: newline \n horizontal tab \t backspace \b carriage return \r form feed \f backslash \\ single quote \' 7 blank & NUL 2 --- 98 Any specific implementation of C may of course support additional characters. */ /* Since the value of a character constant is the numerical value of the character in the machine's character set, there should be a one-to-one correspondence between characters and values. */ zerofill(chars); chars['a'] = 1; chars['A'] = 1; chars['~'] = 1; chars['0'] = 1; chars['b'] = 1; chars['B'] = 1; chars['!'] = 1; chars['1'] = 1; chars['c'] = 1; chars['C'] = 1; chars['"'] = 1; chars['2'] = 1; chars['d'] = 1; chars['D'] = 1; chars['#'] = 1; chars['3'] = 1; chars['e'] = 1; chars['E'] = 1; chars['%'] = 1; chars['4'] = 1; chars['f'] = 1; chars['F'] = 1; chars['&'] = 1; chars['5'] = 1; chars['g'] = 1; chars['G'] = 1; chars['('] = 1; chars['6'] = 1; chars['h'] = 1; chars['H'] = 1; chars[')'] = 1; chars['7'] = 1; chars['i'] = 1; chars['I'] = 1; chars['_'] = 1; chars['8'] = 1; chars['j'] = 1; chars['J'] = 1; chars['='] = 1; chars['9'] = 1; chars['k'] = 1; chars['K'] = 1; chars['-'] = 1; chars['l'] = 1; chars['L'] = 1; chars['^'] = 1; chars['m'] = 1; chars['M'] = 1; chars['|'] = 1; chars['\n'] = 1; chars['n'] = 1; chars['N'] = 1; chars['\t'] = 1; chars['o'] = 1; chars['O'] = 1; chars['{'] = 1; chars['\b'] = 1; chars['p'] = 1; chars['P'] = 1; chars['}'] = 1; chars['\r'] = 1; chars['q'] = 1; chars['Q'] = 1; chars['['] = 1; chars['\f'] = 1; chars['r'] = 1; chars['R'] = 1; chars[']'] = 1; chars['s'] = 1; chars['S'] = 1; chars['+'] = 1; chars['\\'] = 1; chars['t'] = 1; chars['T'] = 1; chars[';'] = 1; chars['\''] = 1; chars['u'] = 1; chars['U'] = 1; chars['*'] = 1; chars['v'] = 1; chars['V'] = 1; chars[':'] = 1; chars['\0'] = 1; chars['w'] = 1; chars['W'] = 1; chars['<'] = 1; chars[' '] = 1; chars['x'] = 1; chars['X'] = 1; chars['>'] = 1; chars['y'] = 1; chars['Y'] = 1; chars[','] = 1; chars['z'] = 1; chars['Z'] = 1; chars['.'] = 1; chars['?'] = 1; chars['/'] = 1; if(sumof(chars) != 98){ rc = rc+1; if(pd0->flgd != 0) printf(s243er,1); } #ifndef NO_BACKSLASH_CHARCODE /* Finally, the escape \ddd consists of the backslash followed by 1, 2, or 3 octal digits which are taken to specify the desired character. */ /* this test is non portable and inaccurate, we replace it by a more failproof version if( '\0' != 0 || '\01' != 1 || '\02' != 2 || '\03' != 3 || '\04' != 4 || '\05' != 5 || '\06' != 6 || '\07' != 7 || '\10' != 8 || '\17' != 15 || '\20' != 16 || '\77' != 63 || '\100' != 64 || '\177' != 127 ) */ if( ('0' != '\60') || ('9' != '\71') || ('A' != '\101') || ('Z' != '\132') || ('a' != '\141') || ('z' != '\172') ) { rc = rc+8; if(pd0->flgd != 0) { printf(s243er,8); } } #endif return rc; } /********************************************************************************************* the main loop that launches the sections *********************************************************************************************/ #define cq_sections 1 #ifndef NO_TYPELESS_STRUCT_PTR int section(int j,struct* pd0){ #else int section(int j,void* pd0){ #endif switch(j){ case 0: return s243(pd0); } } /* C REFERENCE MANUAL (main) */ #ifndef NO_OLD_FUNC_DECL main(n,args) int n; char **args; { #else int main(int n,char **args) { #endif int j; static struct defs d0, *pd0; d0.flgs = 1; /* These flags dictate */ d0.flgm = 1; /* the verbosity of */ d0.flgd = 1; /* the program. */ d0.flgl = 1; pd0 = &d0; for (j=0; j<cq_sections; j++) { d0.rrc=section(j,pd0); d0.crc=d0.crc+d0.rrc; if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); } if(d0.crc == 0) printf("\nNo errors detected.\n"); else printf("\nFailed.\n"); return d0.crc; } ��������������������������������������������������������������������������������������cc65-2.18/test/val/cq244.c��������������������������������������������������������������������������0000664�0000000�0000000�00000011153�13473601511�0014750�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! C-Manual Chapter 2.44: floating point constants !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include "common.h" struct defs { int cbits; /* No. of bits per char */ int ibits; /* int */ int sbits; /* short */ int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ }; int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ #ifndef NO_OLD_FUNC_DECL s244(pd0) struct defs *pd0; { #else s244(struct defs *pd0) { #endif #ifndef NO_FLOATS double a[8]; int rc, lrc, j; static char s244er[] = "s244,er%d\n"; static char qs244[8] = "s244 "; char *ps, *pt; ps = qs244; pt = pd0->rfs; while(*pt++ = *ps++); rc = 0; lrc = 0; /* Unfortunately, there's not a lot we can do with floating constants. We can check to see that the various representations can be com- piled, that the conversion is such that they yield the same hard- ware representations in all cases, and that all representations thus checked are double precision. */ a[0] = .1250E+04; a[1] = 1.250E3; a[2] = 12.50E02; a[3] = 125.0e+1; a[4] = 1250e00; a[5] = 12500.e-01; a[6] = 125000e-2; a[7] = 1250.; lrc = 0; for (j=0; j<7; j++) if(a[j] != a[j+1]) lrc = 1; if(lrc != 0) { if(pd0->flgd != 0) printf(s244er,1); rc = rc+1; } if ( (sizeof .1250E+04 ) != sizeof(double) || (sizeof 1.250E3 ) != sizeof(double) || (sizeof 12.50E02 ) != sizeof(double) || (sizeof 1.250e+1 ) != sizeof(double) || (sizeof 1250e00 ) != sizeof(double) || (sizeof 12500.e-01) != sizeof(double) || (sizeof 125000e-2 ) != sizeof(double) || (sizeof 1250. ) != sizeof(double)){ if(pd0->flgd != 0) printf(s244er,2); rc = rc+2; } return rc; #else return 0; #endif } /********************************************************************************************* the main loop that launches the sections *********************************************************************************************/ #define cq_sections 1 #ifndef NO_TYPELESS_STRUCT_PTR int section(int j,struct* pd0){ #else int section(int j,void* pd0){ #endif switch(j){ case 0: return s244(pd0); } } /* C REFERENCE MANUAL (main) */ #ifndef NO_OLD_FUNC_DECL main(n,args) int n; char **args; { #else int main(int n,char **args) { #endif int j; static struct defs d0, *pd0; d0.flgs = 1; /* These flags dictate */ d0.flgm = 1; /* the verbosity of */ d0.flgd = 1; /* the program. */ d0.flgl = 1; pd0 = &d0; for (j=0; j<cq_sections; j++) { d0.rrc=section(j,pd0); d0.crc=d0.crc+d0.rrc; if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); } if(d0.crc == 0) printf("\nNo errors detected.\n"); else printf("\nFailed.\n"); return d0.crc; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/cq25.c���������������������������������������������������������������������������0000664�0000000�0000000�00000011604�13473601511�0014666�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! C-Manual Chapter 2.5: strings !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include "common.h" struct defs { int cbits; /* No. of bits per char */ int ibits; /* int */ int sbits; /* short */ int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ }; int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ #ifndef NO_OLD_FUNC_DECL s25(pd0) struct defs *pd0; { #else int s25(struct defs *pd0) { #endif char *s, *s2; int rc, lrc, j; static char s25er[] = "s25,er%d\n"; static char qs25[8] = "s25 "; char *ps, *pt; ps = qs25; pt = pd0->rfs; while(*pt++ = *ps++); rc = 0; /* A string is a sequence of characters surrounded by double quotes, as in "...". */ s = "..."; /* A string has type "array of characters" and storage class static and is initialized with the given characters. */ if ( s[0] != s[1] || s[1] != s[2] || s[2] != '.' ) { rc = rc+1; if(pd0->flgd != 0) printf(s25er,1); } /* The compiler places a null byte \0 at the end of each string so the program which scans the string can find its end. */ if( s[3] != '\0' ){ rc = rc+4; if(pd0->flgd != 0) printf(s25er,4); } /* In a string, the double quote character " must be preceded by a \. */ if( ".\"."[1] != '"' ){ rc = rc+8; if(pd0->flgd != 0) printf(s25er,8); } /* In addition, the same escapes described for character constants may be used. */ s = "\n\t\b\r\f\\\'"; if( s[0] != '\n' || s[1] != '\t' || s[2] != '\b' || s[3] != '\r' || s[4] != '\f' || s[5] != '\\' || s[6] != '\'' ){ rc = rc+16; if( pd0->flgd != 0) printf(s25er,16); } /* Finally, a \ and an immediately following newline are ignored */ s2 = "queep!"; s = "queep!"; lrc = 0; for (j=0; j<sizeof "queep!"; j++) if(s[j] != s2[j]) lrc = 1; if (lrc != 0){ rc = rc+32; if(pd0->flgd != 0) printf(s25er,32); } return rc; } /********************************************************************************************* the main loop that launches the sections *********************************************************************************************/ #define cq_sections 1 #ifndef NO_TYPELESS_STRUCT_PTR int section(int j,struct* pd0){ #else int section(int j,void* pd0){ #endif switch(j){ case 0: return s25(pd0); } } /* C REFERENCE MANUAL (main) */ #ifndef NO_OLD_FUNC_DECL main(n,args) int n; char **args; { #else int main(int n,char **args) { #endif int j; static struct defs d0, *pd0; d0.flgs = 1; /* These flags dictate */ d0.flgm = 1; /* the verbosity of */ d0.flgd = 1; /* the program. */ d0.flgl = 1; pd0 = &d0; for (j=0; j<cq_sections; j++) { d0.rrc=section(j,pd0); d0.crc=d0.crc+d0.rrc; if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); } if(d0.crc == 0) printf("\nNo errors detected.\n"); else printf("\nFailed.\n"); return d0.crc; } ����������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/cq26.c���������������������������������������������������������������������������0000664�0000000�0000000�00000015321�13473601511�0014667�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! C-Manual Chapter 2.6: Hardware Characteristics !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include "common.h" #ifndef CQ26_INCLUDED struct defs { int cbits; /* No. of bits per char */ int ibits; /* int */ int sbits; /* short */ int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ }; int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ #endif /* section s26, which pokes around at the hardware trying to figure out the characteristics of the machine that it is running on, saves information that is subsequently used by sections s626, s72, and s757. If this program is to be broken up into smallish pieces, say for running on a microcomputer, take care to see that s26 is called before calling any of the latter three sections. */ /* 2.6 Hardware Characteristics */ #ifndef NO_OLD_FUNC_DECL s26(pd0) struct defs *pd0; { #else s26(struct defs *pd0) { #endif static char qs26[8] = "s26 "; char *ps, *pt; char c0, c1; #ifndef NO_FLOATS float temp, one, delta; double tempd, oned; #endif static char s[] = "%3d bits in %ss.\n"; static char s2[] = "%e is the least number that can be added to 1. (%s).\n"; ps = qs26; pt = pd0->rfs; while(*pt++ = *ps++); /* Here, we shake the machinery a little to see what falls out. First, we find out how many bits are in a char. */ pd0->cbits = 0; c0 = 0; c1 = 1; while(c0 != c1) { c1 = c1<<1; pd0->cbits = pd0->cbits+1; } /* That information lets us determine the size of everything else. */ pd0->ibits = pd0->cbits * sizeof(int); pd0->sbits = pd0->cbits * sizeof(short); pd0->lbits = pd0->cbits * sizeof(long); pd0->ubits = pd0->cbits * sizeof(unsigned); #ifndef NO_FLOATS pd0->fbits = pd0->cbits * sizeof(float); pd0->dbits = pd0->cbits * sizeof(double); #endif /* We have now almost reconstructed the table in section 2.6, the exception being the range of the floating point hardware. Now there are just so many ways to conjure up a floating point representation system that it's damned near impossible to guess what's going on by writing a program to interpret bit patterns. Further, the information isn't all that useful, if we consider the fact that machines that won't handle numbers between 10**30 and 10**-30 are very hard to find, and that people playing with numbers outside that range have a lot more to worry about than just the capacity of the characteristic. A much more useful measure is the precision, which can be ex- pressed in terms of the smallest number that can be added to 1. without loss of significance. We calculate that here, for float and double. */ #ifndef NO_FLOATS one = 1.; delta = 1.; temp = 0.; while(temp != one) { temp = one+delta; delta = delta/2.; } pd0->fprec = delta * 4.; oned = 1.; delta = 1.; tempd = 0.; while(tempd != oned) { tempd = oned+delta; delta = delta/2.; } pd0->dprec = delta * 4.; #endif /* Now, if anyone's interested, we publish the results. */ #ifndef CQ26_INCLUDED if(pd0->flgm != 0) { printf(s,pd0->cbits,"char"); printf(s,pd0->ibits,"int"); printf(s,pd0->sbits,"short"); printf(s,pd0->lbits,"long"); printf(s,pd0->ubits,"unsigned"); printf(s,pd0->fbits,"float"); printf(s,pd0->dbits,"double"); #ifndef NO_FLOATS printf(s2,pd0->fprec,"float"); printf(s2,pd0->dprec,"double"); #else printf("NO_FLOATS\n"); #endif } #endif /* Since we are only exploring and perhaps reporting, but not testing any features, we cannot return an error code. */ return 0; } #ifndef CQ26_INCLUDED /********************************************************************************************* the main loop that launches the sections *********************************************************************************************/ #ifndef NO_TYPELESS_STRUCT_PTR int section(int j,struct* pd0){ #else int section(int j,void* pd0){ #endif switch(j){ case 0: return s26(pd0); } } #define cq_sections 1 /* C REFERENCE MANUAL (main) */ #ifndef NO_OLD_FUNC_DECL main(n,args) int n; char **args; { #else int main(int n,char **args) { #endif int j; static struct defs d0, *pd0; d0.flgs = 1; /* These flags dictate */ d0.flgm = 1; /* the verbosity of */ d0.flgd = 1; /* the program. */ d0.flgl = 1; pd0 = &d0; for (j=0; j<cq_sections; j++) { d0.rrc=section(j,pd0); d0.crc=d0.crc+d0.rrc; if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); } if(d0.crc == 0) printf("\nNo errors detected.\n"); else printf("\nFailed.\n"); return d0.crc; } #endif ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/cq4.c����������������������������������������������������������������������������0000664�0000000�0000000�00000024611�13473601511�0014605�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! C-Manual Chapter 4: what's in a name? !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include "common.h" struct defs { int cbits; /* No. of bits per char */ int ibits; /* int */ int sbits; /* short */ int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ }; int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ #define CQ26_INCLUDED /* section s26, which pokes around at the hardware trying to figure out the characteristics of the machine that it is running on, saves information that is subsequently used by sections s626, s72, and s757. If this program is to be broken up into smallish pieces, say for running on a microcomputer, take care to see that s26 is called before calling any of the latter three sections. */ /* 2.6 Hardware Characteristics */ #ifndef NO_OLD_FUNC_DECL s26(pd0) struct defs *pd0; { #else s26(struct defs *pd0) { #endif static char qs26[8] = "s26 "; char *ps, *pt; char c0, c1; #ifndef NO_FLOATS float temp, one, delta; double tempd, oned; #endif static char s[] = "%3d bits in %ss.\n"; static char s2[] = "%e is the least number that can be added to 1. (%s).\n"; ps = qs26; pt = pd0->rfs; while(*pt++ = *ps++); /* Here, we shake the machinery a little to see what falls out. First, we find out how many bits are in a char. */ pd0->cbits = 0; c0 = 0; c1 = 1; while(c0 != c1) { c1 = c1<<1; pd0->cbits = pd0->cbits+1; } /* That information lets us determine the size of everything else. */ pd0->ibits = pd0->cbits * sizeof(int); pd0->sbits = pd0->cbits * sizeof(short); pd0->lbits = pd0->cbits * sizeof(long); pd0->ubits = pd0->cbits * sizeof(unsigned); #ifndef NO_FLOATS pd0->fbits = pd0->cbits * sizeof(float); pd0->dbits = pd0->cbits * sizeof(double); #endif /* We have now almost reconstructed the table in section 2.6, the exception being the range of the floating point hardware. Now there are just so many ways to conjure up a floating point representation system that it's damned near impossible to guess what's going on by writing a program to interpret bit patterns. Further, the information isn't all that useful, if we consider the fact that machines that won't handle numbers between 10**30 and 10**-30 are very hard to find, and that people playing with numbers outside that range have a lot more to worry about than just the capacity of the characteristic. A much more useful measure is the precision, which can be ex- pressed in terms of the smallest number that can be added to 1. without loss of significance. We calculate that here, for float and double. */ #ifndef NO_FLOATS one = 1.; delta = 1.; temp = 0.; while(temp != one) { temp = one+delta; delta = delta/2.; } pd0->fprec = delta * 4.; oned = 1.; delta = 1.; tempd = 0.; while(tempd != oned) { tempd = oned+delta; delta = delta/2.; } pd0->dprec = delta * 4.; #endif /* Now, if anyone's interested, we publish the results. */ #ifndef CQ26_INCLUDED if(pd0->flgm != 0) { printf(s,pd0->cbits,"char"); printf(s,pd0->ibits,"int"); printf(s,pd0->sbits,"short"); printf(s,pd0->lbits,"long"); printf(s,pd0->ubits,"unsigned"); printf(s,pd0->fbits,"float"); printf(s,pd0->dbits,"double"); #ifndef NO_FLOATS printf(s2,pd0->fprec,"float"); printf(s2,pd0->dprec,"double"); #else printf("NO_FLOATS\n"); #endif } #endif /* Since we are only exploring and perhaps reporting, but not testing any features, we cannot return an error code. */ return 0; } int extvar; #ifdef NO_IMPLICIT_FUNC_PROTOTYPES int s4(struct defs *pd0); int svtest(int n); zero(); testev(); setev(); #endif #ifndef NO_OLD_FUNC_DECL s4(pd0) /* 4. What's in a name? */ struct defs *pd0; { #else int s4(struct defs *pd0) { #endif static char s4er[] = "s4,er%d\n"; static char qs4[8] = "s4 "; char *ps, *pt; int j, rc; short sint; /* short integer, for size test */ int pint; /* plain */ long lint; /* long */ unsigned target; unsigned int mask; rc = 0; ps = qs4; pt = pd0->rfs; while(*pt++ = *ps++); /* There are four declarable storage classes: automatic, static, external, and register. Automatic variables have been dealt with extensively thus far, and will not be specif- ically treated in this section. Register variables are treated in section s81. Static variables are local to a block, but retain their values upon reentry to a block, even after control has left the block. */ for (j=0; j<3; j++) if(svtest(j) != zero()){ rc = 1; if(pd0->flgd != 0) printf(s4er,1); } ; /* External variables exist and retain their values throughout the execution of the entire program, and may be used for comm- unication between functions, even separately compiled functions. */ setev(); if(testev() != 0){ rc=rc+2; if(pd0->flgd != 0) printf(s4er,2); } /* Characters have been tested elsewhere (in s243). Up to three sizes of integer, declared short int, int, and long int, are available. Longer integers provide no less storage than shorter ones, but implementation may make either short integers, or long integers, or both, equivalent to plain integers. */ if(sizeof lint < sizeof pint || sizeof pint < sizeof sint){ rc = rc+4; if(pd0->flgd != 0) printf(s4er,4); } /* Unsigned integers, declared unsigned, obey the laws of arithmetic modulo 2**n, where n is the number of bits in the implementation */ target = ~0U; mask = 1; printf("sizeof target: %08x pd0->cbits: %08x\n", sizeof target, pd0->cbits); printf("mask: %08x target: %08x\n", mask, target); for(j=0; j<(sizeof target)*pd0->cbits; j++){ mask = mask⌖ target = target>>1; printf("mask: %08x target: %08x\n", mask, target); } if(mask != 1 || target != 0){ rc = rc+8; if(pd0->flgd != 0) printf(s4er,8); } return rc; } #ifndef NO_OLD_FUNC_DECL svtest(n) int n; { #else int svtest(int n) { #endif static k; int rc; switch (n) { case 0: k = 1978; rc = 0; break; case 1: if(k != 1978) rc = 1; else{ k = 1929; rc = 0; } break; case 2: if(k != 1929) rc = 1; else rc = 0; break; } return rc; } zero(){ /* Returns a value of zero, possibly */ static k; /* with side effects, as it's called */ int rc; /* alternately with svtest, above, */ k = 2; /* and has the same internal storage */ rc = 0; /* requirements. */ return rc; } testev(){ if(extvar != 1066) return 1; else return 0; } /* Sets an external variable. Used */ /* by s4, and should be compiled */ /* separately from s4. */ setev(){ #ifndef NO_SLOPPY_EXTERN extern int extvar; #endif extvar = 1066; } /********************************************************************************************* the main loop that launches the sections *********************************************************************************************/ #ifndef NO_TYPELESS_STRUCT_PTR int section(int j,struct* pd0){ #else int section(int j,void* pd0){ #endif switch(j){ case 0: return s26(pd0); case 1: return s4(pd0); } } #define cq_sections 2 /* C REFERENCE MANUAL (main) */ #ifndef NO_OLD_FUNC_DECL main(n,args) int n; char **args; { #else int main(int n,char **args) { #endif int j; static struct defs d0, *pd0; d0.flgs = 1; /* These flags dictate */ d0.flgm = 1; /* the verbosity of */ d0.flgd = 1; /* the program. */ d0.flgl = 1; pd0 = &d0; for (j=0; j<cq_sections; j++) { d0.rrc=section(j,pd0); d0.crc=d0.crc+d0.rrc; if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); } if(d0.crc == 0) printf("\nNo errors detected.\n"); else printf("\nFailed.\n"); return d0.crc; } �����������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/cq61.c���������������������������������������������������������������������������0000664�0000000�0000000�00000013106�13473601511�0014665�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! C-Manual Chapter 6.1: characters and integers !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include "common.h" struct defs { int cbits; /* No. of bits per char */ int ibits; /* int */ int sbits; /* short */ int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ }; int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ /*#include "cq26.c"*/ /* hardware check */ int extvar; #ifndef NO_OLD_FUNC_DECL s61(pd0) /* Characters and integers */ struct defs *pd0; { #else int s61(struct defs *pd0){ #endif static char s61er[] = "s61,er%d\n"; static char s61ok[] = "s61,ok%d\n"; static char qs61[8] = "s61 "; short from, shortint; long int to, longint; int rc, lrc; int j; char fromc, charint; char *wd, *pc[6]; static char upper_alpha[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; static char lower_alpha[] = "abcdefghijklmnopqrstuvwxyz"; static char numbers[] = "0123456789"; static char special_characters[] = "~!\"#%&()_=-^|{}[]+;*:<>,.?/"; static char extra_special_characters[] = "\n\t\b\r\f\\\'"; static char blank_and_NUL[] = " \0"; char *ps, *pt; ps = qs61; pt = pd0->rfs; rc = 0; printf(s61ok,0); while (*pt++ = *ps++); /* A character or a short integer may be used wherever an integer may be used. In all cases, the value is converted to integer. This principle is extensively used throughout this program, and will not be explicitly tested here. */ /* Conversion of a shorter integer to a longer always involves sign extension. */ from = -19; to = from; if(to != -19){ rc = rc+1; if(pd0->flgd != 0) printf(s61er,1); } else if(pd0->flgd != 0) printf(s61ok,1); /* It is guaranteed that a member of the standard char- acter set is nonnegative. */ pc[0] = upper_alpha; pc[1] = lower_alpha; pc[2] = numbers; pc[3] = special_characters; pc[4] = extra_special_characters; pc[5] = blank_and_NUL; lrc = 0; for (j=0; j<6; j++) while(*pc[j]) if(*pc[j]++ < 0) lrc =1; if(lrc != 0){ rc=rc+2; if(pd0->flgd != 0) printf(s61er,2); } else if(pd0->flgd != 0) printf(s61ok,2); /* When a longer integer is converted to a shorter or to a char, it is truncated on the left; excess bits are simply discarded. */ longint = 1048579; /* =2**20+3 */ shortint = longint; charint = longint; if((shortint != longint && shortint != 3) || (charint != longint && charint != 3)) { rc = rc+8; if(pd0->flgd != 0) printf(s61er,8); } else if(pd0->flgd != 0) printf(s61ok,8); return rc; } /********************************************************************************************* the main loop that launches the sections *********************************************************************************************/ #ifndef NO_TYPELESS_STRUCT_PTR int section(int j,struct* pd0){ #else int section(int j,void* pd0){ #endif switch(j){ /*case 0: return s26(pd0);*/ case 0: return s61(pd0); } } #define cq_sections 1 /* C REFERENCE MANUAL (main) */ #ifndef NO_OLD_FUNC_DECL main(n,args) int n; char **args; { #else int main(int n,char **args) { #endif int j; static struct defs d0, *pd0; d0.flgs = 1; /* These flags dictate */ d0.flgm = 1; /* the verbosity of */ d0.flgd = 1; /* the program. */ d0.flgl = 1; pd0 = &d0; for (j=0; j<cq_sections; j++) { d0.rrc=section(j,pd0); d0.crc=d0.crc+d0.rrc; if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); } if(d0.crc == 0) printf("\nNo errors detected.\n"); else printf("\nFailed.\n"); return d0.crc; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/cq626.c��������������������������������������������������������������������������0000664�0000000�0000000�00000023270�13473601511�0014757�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! C-Manual Chapter 6.2: Float and double, 6.3 Floating and integral, 6.4 Pointers and integers, 6.5 Unsigned, 6.6 Arithmetic conversions !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include "common.h" struct defs { int cbits; /* No. of bits per char */ int ibits; /* int */ int sbits; /* short */ int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ }; int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ #define CQ26_INCLUDED /* section s26, which pokes around at the hardware trying to figure out the characteristics of the machine that it is running on, saves information that is subsequently used by sections s626, s72, and s757. If this program is to be broken up into smallish pieces, say for running on a microcomputer, take care to see that s26 is called before calling any of the latter three sections. */ /* 2.6 Hardware Characteristics */ #ifndef NO_OLD_FUNC_DECL s26(pd0) struct defs *pd0; { #else s26(struct defs *pd0) { #endif static char qs26[8] = "s26 "; char *ps, *pt; char c0, c1; #ifndef NO_FLOATS float temp, one, delta; double tempd, oned; #endif static char s[] = "%3d bits in %ss.\n"; static char s2[] = "%e is the least number that can be added to 1. (%s).\n"; ps = qs26; pt = pd0->rfs; while(*pt++ = *ps++); /* Here, we shake the machinery a little to see what falls out. First, we find out how many bits are in a char. */ pd0->cbits = 0; c0 = 0; c1 = 1; while(c0 != c1) { c1 = c1<<1; pd0->cbits = pd0->cbits+1; } /* That information lets us determine the size of everything else. */ pd0->ibits = pd0->cbits * sizeof(int); pd0->sbits = pd0->cbits * sizeof(short); pd0->lbits = pd0->cbits * sizeof(long); pd0->ubits = pd0->cbits * sizeof(unsigned); #ifndef NO_FLOATS pd0->fbits = pd0->cbits * sizeof(float); pd0->dbits = pd0->cbits * sizeof(double); #endif /* We have now almost reconstructed the table in section 2.6, the exception being the range of the floating point hardware. Now there are just so many ways to conjure up a floating point representation system that it's damned near impossible to guess what's going on by writing a program to interpret bit patterns. Further, the information isn't all that useful, if we consider the fact that machines that won't handle numbers between 10**30 and 10**-30 are very hard to find, and that people playing with numbers outside that range have a lot more to worry about than just the capacity of the characteristic. A much more useful measure is the precision, which can be ex- pressed in terms of the smallest number that can be added to 1. without loss of significance. We calculate that here, for float and double. */ #ifndef NO_FLOATS one = 1.; delta = 1.; temp = 0.; while(temp != one) { temp = one+delta; delta = delta/2.; } pd0->fprec = delta * 4.; oned = 1.; delta = 1.; tempd = 0.; while(tempd != oned) { tempd = oned+delta; delta = delta/2.; } pd0->dprec = delta * 4.; #endif /* Now, if anyone's interested, we publish the results. */ #ifndef CQ26_INCLUDED if(pd0->flgm != 0) { printf(s,pd0->cbits,"char"); printf(s,pd0->ibits,"int"); printf(s,pd0->sbits,"short"); printf(s,pd0->lbits,"long"); printf(s,pd0->ubits,"unsigned"); printf(s,pd0->fbits,"float"); printf(s,pd0->dbits,"double"); #ifndef NO_FLOATS printf(s2,pd0->fprec,"float"); printf(s2,pd0->dprec,"double"); #else printf("NO_FLOATS\n"); #endif } #endif /* Since we are only exploring and perhaps reporting, but not testing any features, we cannot return an error code. */ return 0; } int extvar; #ifndef NO_OLD_FUNC_DECL s626(pd0) /* 6.2 Float and double */ /* 6.3 Floating and integral */ /* 6.4 Pointers and integers */ /* 6.5 Unsigned */ /* 6.6 Arithmetic conversions */ struct defs *pd0; { #else int s626(struct defs *pd0){ #endif static char s626er[] = "s626,er%d\n"; static char qs626[8] = "s626 "; int rc; char *ps, *pt; #ifndef NO_FLOATS float eps, f1, f2, f3, f4, f; #endif long lint1, lint2, l, ls; char c, t[28], t0; short s; int is, i, j; unsigned u, us; #ifndef NO_FLOATS double d, ds; #endif ps = qs626; pt = pd0->rfs; rc = 0; while (*pt++ = *ps++); #ifndef NO_FLOATS /* Conversions of integral values to floating type are well-behaved. */ f1 = 1.; lint1 = 1.; lint2 = 1.; for(j=0;j<pd0->lbits-2;j++){ f1 = f1*2; lint2 = (lint2<<1)|lint1; } f2 = lint2; f1 = (f1-f2)/f1; if(f1>2.*pd0->fprec){ rc = rc+2; if(pd0->flgd != 0) printf(s626er,2); } /* Pointer-integer combinations are discussed in s74, "Additive operators". The unsigned-int combination appears below. */ c = 125; s = 125; i = 125; is = 15625; u = 125; us = 15625; l = 125; ls = 15625; f = 125.; d = 125.; ds = 15625.; for(j=0;j<28;j++) t[j] = 0; if(c*c != is) t[ 0] = 1; if(s*c != is) t[ 1] = 1; if(s*s != is) t[ 2] = 1; if(i*c != is) t[ 3] = 1; if(i*s != is) t[ 4] = 1; if(i*i != is) t[ 5] = 1; if(u*c != us) t[ 6] = 1; if(u*s != us) t[ 7] = 1; if(u*i != us) t[ 8] = 1; if(u*u != us) t[ 9] = 1; if(l*c != ls) t[10] = 1; if(l*s != ls) t[11] = 1; if(l*i != ls) t[12] = 1; if(l*u != us) t[13] = 1; if(l*l != ls) t[14] = 1; if(f*c != ds) t[15] = 1; if(f*s != ds) t[16] = 1; if(f*i != ds) t[17] = 1; if(f*u != ds) t[18] = 1; if(f*l != ds) t[19] = 1; if(f*f != ds) t[20] = 1; if(d*c != ds) t[21] = 1; if(d*s != ds) t[22] = 1; if(d*i != ds) t[23] = 1; if(d*u != ds) t[24] = 1; if(d*l != ds) t[25] = 1; if(d*f != ds) t[26] = 1; if(d*d != ds) t[27] = 1; t0 = 0; for(j=0; j<28; j++) t0 = t0+t[j]; if(t0 != 0){ rc = rc+4; if(pd0->flgd != 0){ printf(s626er,4); printf(" key="); for(j=0;j<28;j++) printf("%d",t[j]); printf("\n"); } } #endif /* When an unsigned integer is converted to long, the value of the result is the same numerically as that of the unsigned integer. */ l = (unsigned)0100000; if((long)l > (unsigned)0100000){ rc = rc+8; if(pd0->flgd != 0) printf(s626er,8); } return rc; } /********************************************************************************************* the main loop that launches the sections *********************************************************************************************/ #ifndef NO_TYPELESS_STRUCT_PTR int section(int j,struct* pd0){ #else int section(int j,void* pd0){ #endif switch(j){ case 0: return s26(pd0); case 1: return s626(pd0); } } #define cq_sections 2 /* C REFERENCE MANUAL (main) */ #ifndef NO_OLD_FUNC_DECL main(n,args) int n; char **args; { #else int main(int n,char **args) { #endif int j; static struct defs d0, *pd0; d0.flgs = 1; /* These flags dictate */ d0.flgm = 1; /* the verbosity of */ d0.flgd = 1; /* the program. */ d0.flgl = 1; pd0 = &d0; for (j=0; j<cq_sections; j++) { d0.rrc=section(j,pd0); d0.crc=d0.crc+d0.rrc; if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); } if(d0.crc == 0) printf("\nNo errors detected.\n"); else printf("\nFailed.\n"); return d0.crc; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/cq71.c���������������������������������������������������������������������������0000664�0000000�0000000�00000015044�13473601511�0014671�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! C-Manual Chapter 7.1: primary expressions !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include "common.h" /*include "cq26.c"*/ /* hardware check */ struct defs { int cbits; /* No. of bits per char */ int ibits; /* int */ int sbits; /* short */ int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ }; int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ int extvar; #ifndef NO_OLD_FUNC_DECL s71(pd0) /* 7.1 Primary expressions */ struct defs *pd0; { #else int s71(struct defs *pd0){ #endif static char s71er[] = "s71,er%d\n"; static char qs71[8] = "s71 "; int rc; char *ps, *pt; static char q = 'q'; #ifndef NO_SLOPPY_EXTERN int x[10], McCarthy(), clobber(), a, b, *p; #else int x[10], a, b, *p; #endif ps = qs71; pt = pd0->rfs; rc = 0; while (*pt++ = *ps++); /* Testing of expressions and operators is quite complicated, because (a) problems are apt to surface in queer combinations of operators and operands, rather than in isolation, and (b) the number of expressions needed to provoke a case of improper behaviour may be quite large. Hence, we take the following approach: for this section, and for subsequent sections through 7.15, we will check the primitive operations in isolation, thus verifying that the primitives work, after a fashion. The job of testing combinations, we will leave to a separate, machine-generated program, to be included in the C test package at some later date. */ /* A string is a primary expression. The identifier points to the first character of a string. */ if(*"queep" != q){ rc = rc+1; if(pd0->flgd != 0) printf(s71er,1); } /* A parenthesized expression is a primary expression whose type and value are the same as those of the unadorned expression. */ if((2+3) != 2+3) { rc = rc+2; if(pd0->flgd != 0) printf(s71er,2); } /* A primary expression followed by an expression in square brackets is a primary expression. The intuitive meaning is that of a subscript. The expression E1[E2] is identical (by definition) to *((E1)+(E2)). */ x[5] = 1942; if(x[5] != 1942 || x[5] != *((x)+(5))){ rc = rc+4; if(pd0->flgd != 0) printf(s71er,4); } /* If the various flavors of function calls didn't work, we would never have gotten this far; however, we do need to show that functions can be recursive... */ if ( McCarthy(-5) != 91){ rc = rc+8; if(pd0->flgd != 0) printf(s71er,8); } /* and that argument passing is strictly by value. */ a = 2; b = 3; p = &b; clobber(a,p); if(a != 2 || b != 2){ rc = rc+16; if(pd0->flgd != 0) printf(s71er,16); } /* Finally, structures and unions are addressed thusly: */ #ifndef NO_FLOATS if(pd0->dprec != (*pd0).dprec){ rc = rc+32; if(pd0->flgd != 0) printf(s71er,32); } #endif return rc; } #ifndef NO_OLD_FUNC_DECL McCarthy(x) int x; { #else int McCarthy(int x){ #endif if(x>100) return x-10; else return McCarthy( McCarthy(x+11)); } #ifndef NO_OLD_FUNC_DECL clobber(x,y) int x,*y; #else int clobber(int x,int *y) #endif /* #ifndef NO_OLD_FUNC_DECL clobber(x,y) int x, #ifdef NO_TYPELESS_INT_PTR int #endif *y; { #else int clobber(int x, #ifdef NO_TYPELESS_INT_PTR int #endif *y ){ #endif */ { x = 3; *y = 2; } /********************************************************************************************* the main loop that launches the sections *********************************************************************************************/ #ifndef NO_TYPELESS_STRUCT_PTR int section(int j,struct* pd0){ #else int section(int j,void* pd0){ #endif switch(j){ /*case 0: return s26(pd0);*/ case 0: return s71(pd0); } } #define cq_sections 1 /* C REFERENCE MANUAL (main) */ #ifndef NO_OLD_FUNC_DECL main(n,args) int n; char **args; { #else int main(int n,char **args) { #endif int j; static struct defs d0, *pd0; d0.flgs = 1; /* These flags dictate */ d0.flgm = 1; /* the verbosity of */ d0.flgd = 1; /* the program. */ d0.flgl = 1; pd0 = &d0; for (j=0; j<cq_sections; j++) { d0.rrc=section(j,pd0); d0.crc=d0.crc+d0.rrc; if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); } if(d0.crc == 0) printf("\nNo errors detected.\n"); else printf("\nFailed.\n"); return d0.crc; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/cq714.c��������������������������������������������������������������������������0000664�0000000�0000000�00000102707�13473601511�0014760�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! C-Manual Chapter 7.14: assignment operators !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include "common.h" struct defs { int cbits; /* No. of bits per char */ int ibits; /* int */ int sbits; /* short */ int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ }; int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ #ifndef NO_OLD_FUNC_DECL s714(pd0) /* 7.14 Assignment operators */ struct defs *pd0; { #else int s714(struct defs *pd0){ #endif static char f[] = "Local error %d.\n"; static char s714er[] = "s714,er%d\n"; static char qs714[8] = "s714 "; register int prlc, lrc; int rc; char cl, cr; short sl, sr; int il, ir; long ll, lr; unsigned ul, ur; #ifndef NO_FLOATS float fl, fr; double dl, dr; #else signed fl, fr; signed dl, dr; #endif char *ps, *pt; ps = qs714; pt = pd0->rfs; rc = 0; lrc = 0; prlc = pd0->flgl; while (*pt++ = *ps++); /* This section tests the assignment operators. It is an exhaustive test of all assignment statements of the form: vl op vr where vl and vr are variables from the set {char,short,int,long,unsigned,float,double} and op is one of the assignment operators. There are 395 such statements. The initial values for the variables have been chosen so that both the initial values and the results will "fit" in just about any implementation, and that the re- sults will be such that they test for the proper form- ation of composite operators, rather than checking for the valid operation of those operators' components. For example, in checking >>=, we want to verify that a right shift and a move take place, rather than whether or not there may be some peculiarities about the right shift. Such tests have been made previously, and to repeat them here would be to throw out a red herring. The table below lists the operators, assignment targets, initial values for left and right operands, and the expected values of the results. = += -= *= /= %= >>= <<= &= ^= |= char 2 7 3 10 2 1 1 20 8 6 14 short 2 7 3 10 2 1 1 20 8 6 14 int 2 7 3 10 2 1 1 20 8 6 14 long 2 7 3 10 2 1 1 20 8 6 14 unsigned 2 7 3 10 2 1 1 20 8 6 14 float 2 7 3 10 2.5 | | double 2 7 3 10 2.5 | | | | initial (5,2) | (5,2) | (12,10) The following machine-generated program reflects the tests described in the table. */ cl = 5; cr = 2; cl = cr; if(cl != 2){ lrc = 1; if(prlc) printf(f,lrc); } cl = 5; sr = 2; cl = sr; if(cl != 2){ lrc = 2; if(prlc) printf(f,lrc); } cl = 5; ir = 2; cl = ir; if(cl != 2){ lrc = 3; if(prlc) printf(f,lrc); } cl = 5; lr = 2; cl = lr; if(cl != 2){ lrc = 4; if(prlc) printf(f,lrc); } cl = 5; ur = 2; cl = ur; if(cl != 2){ lrc = 5; if(prlc) printf(f,lrc); } cl = 5; fr = 2; cl = fr; if(cl != 2){ lrc = 6; if(prlc) printf(f,lrc); } cl = 5; dr = 2; cl = dr; if(cl != 2){ lrc = 7; if(prlc) printf(f,lrc); } sl = 5; cr = 2; sl = cr; if(sl != 2){ lrc = 8; if(prlc) printf(f,lrc); } sl = 5; sr = 2; sl = sr; if(sl != 2){ lrc = 9; if(prlc) printf(f,lrc); } sl = 5; ir = 2; sl = ir; if(sl != 2){ lrc = 10; if(prlc) printf(f,lrc); } sl = 5; lr = 2; sl = lr; if(sl != 2){ lrc = 11; if(prlc) printf(f,lrc); } sl = 5; ur = 2; sl = ur; if(sl != 2){ lrc = 12; if(prlc) printf(f,lrc); } sl = 5; fr = 2; sl = fr; if(sl != 2){ lrc = 13; if(prlc) printf(f,lrc); } sl = 5; dr = 2; sl = dr; if(sl != 2){ lrc = 14; if(prlc) printf(f,lrc); } il = 5; cr = 2; il = cr; if(il != 2){ lrc = 15; if(prlc) printf(f,lrc); } il = 5; sr = 2; il = sr; if(il != 2){ lrc = 16; if(prlc) printf(f,lrc); } il = 5; ir = 2; il = ir; if(il != 2){ lrc = 17; if(prlc) printf(f,lrc); } il = 5; lr = 2; il = lr; if(il != 2){ lrc = 18; if(prlc) printf(f,lrc); } il = 5; ur = 2; il = ur; if(il != 2){ lrc = 19; if(prlc) printf(f,lrc); } il = 5; fr = 2; il = fr; if(il != 2){ lrc = 20; if(prlc) printf(f,lrc); } il = 5; dr = 2; il = dr; if(il != 2){ lrc = 21; if(prlc) printf(f,lrc); } ll = 5; cr = 2; ll = cr; if(ll != 2){ lrc = 22; if(prlc) printf(f,lrc); } ll = 5; sr = 2; ll = sr; if(ll != 2){ lrc = 23; if(prlc) printf(f,lrc); } ll = 5; ir = 2; ll = ir; if(ll != 2){ lrc = 24; if(prlc) printf(f,lrc); } ll = 5; lr = 2; ll = lr; if(ll != 2){ lrc = 25; if(prlc) printf(f,lrc); } ll = 5; ur = 2; ll = ur; if(ll != 2){ lrc = 26; if(prlc) printf(f,lrc); } ll = 5; fr = 2; ll = fr; if(ll != 2){ lrc = 27; if(prlc) printf(f,lrc); } ll = 5; dr = 2; ll = dr; if(ll != 2){ lrc = 28; if(prlc) printf(f,lrc); } ul = 5; cr = 2; ul = cr; if(ul != 2){ lrc = 29; if(prlc) printf(f,lrc); } ul = 5; sr = 2; ul = sr; if(ul != 2){ lrc = 30; if(prlc) printf(f,lrc); } ul = 5; ir = 2; ul = ir; if(ul != 2){ lrc = 31; if(prlc) printf(f,lrc); } ul = 5; lr = 2; ul = lr; if(ul != 2){ lrc = 32; if(prlc) printf(f,lrc); } ul = 5; ur = 2; ul = ur; if(ul != 2){ lrc = 33; if(prlc) printf(f,lrc); } ul = 5; fr = 2; ul = fr; if(ul != 2){ lrc = 34; if(prlc) printf(f,lrc); } ul = 5; dr = 2; ul = dr; if(ul != 2){ lrc = 35; if(prlc) printf(f,lrc); } fl = 5; cr = 2; fl = cr; if(fl != 2){ lrc = 36; if(prlc) printf(f,lrc); } fl = 5; sr = 2; fl = sr; if(fl != 2){ lrc = 37; if(prlc) printf(f,lrc); } fl = 5; ir = 2; fl = ir; if(fl != 2){ lrc = 38; if(prlc) printf(f,lrc); } fl = 5; lr = 2; fl = lr; if(fl != 2){ lrc = 39; if(prlc) printf(f,lrc); } fl = 5; ur = 2; fl = ur; if(fl != 2){ lrc = 40; if(prlc) printf(f,lrc); } fl = 5; fr = 2; fl = fr; if(fl != 2){ lrc = 41; if(prlc) printf(f,lrc); } fl = 5; dr = 2; fl = dr; if(fl != 2){ lrc = 42; if(prlc) printf(f,lrc); } dl = 5; cr = 2; dl = cr; if(dl != 2){ lrc = 43; if(prlc) printf(f,lrc); } dl = 5; sr = 2; dl = sr; if(dl != 2){ lrc = 44; if(prlc) printf(f,lrc); } dl = 5; ir = 2; dl = ir; if(dl != 2){ lrc = 45; if(prlc) printf(f,lrc); } dl = 5; lr = 2; dl = lr; if(dl != 2){ lrc = 46; if(prlc) printf(f,lrc); } dl = 5; ur = 2; dl = ur; if(dl != 2){ lrc = 47; if(prlc) printf(f,lrc); } dl = 5; fr = 2; dl = fr; if(dl != 2){ lrc = 48; if(prlc) printf(f,lrc); } dl = 5; dr = 2; dl = dr; if(dl != 2){ lrc = 49; if(prlc) printf(f,lrc); } cl = 5; cr = 2; cl += cr; if(cl != 7){ lrc = 50; if(prlc) printf(f,lrc); } cl = 5; sr = 2; cl += sr; if(cl != 7){ lrc = 51; if(prlc) printf(f,lrc); } cl = 5; ir = 2; cl += ir; if(cl != 7){ lrc = 52; if(prlc) printf(f,lrc); } cl = 5; lr = 2; cl += lr; if(cl != 7){ lrc = 53; if(prlc) printf(f,lrc); } cl = 5; ur = 2; cl += ur; if(cl != 7){ lrc = 54; if(prlc) printf(f,lrc); } cl = 5; fr = 2; cl += fr; if(cl != 7){ lrc = 55; if(prlc) printf(f,lrc); } cl = 5; dr = 2; cl += dr; if(cl != 7){ lrc = 56; if(prlc) printf(f,lrc); } sl = 5; cr = 2; sl += cr; if(sl != 7){ lrc = 57; if(prlc) printf(f,lrc); } sl = 5; sr = 2; sl += sr; if(sl != 7){ lrc = 58; if(prlc) printf(f,lrc); } sl = 5; ir = 2; sl += ir; if(sl != 7){ lrc = 59; if(prlc) printf(f,lrc); } sl = 5; lr = 2; sl += lr; if(sl != 7){ lrc = 60; if(prlc) printf(f,lrc); } sl = 5; ur = 2; sl += ur; if(sl != 7){ lrc = 61; if(prlc) printf(f,lrc); } sl = 5; fr = 2; sl += fr; if(sl != 7){ lrc = 62; if(prlc) printf(f,lrc); } sl = 5; dr = 2; sl += dr; if(sl != 7){ lrc = 63; if(prlc) printf(f,lrc); } il = 5; cr = 2; il += cr; if(il != 7){ lrc = 64; if(prlc) printf(f,lrc); } il = 5; sr = 2; il += sr; if(il != 7){ lrc = 65; if(prlc) printf(f,lrc); } il = 5; ir = 2; il += ir; if(il != 7){ lrc = 66; if(prlc) printf(f,lrc); } il = 5; lr = 2; il += lr; if(il != 7){ lrc = 67; if(prlc) printf(f,lrc); } il = 5; ur = 2; il += ur; if(il != 7){ lrc = 68; if(prlc) printf(f,lrc); } il = 5; fr = 2; il += fr; if(il != 7){ lrc = 69; if(prlc) printf(f,lrc); } il = 5; dr = 2; il += dr; if(il != 7){ lrc = 70; if(prlc) printf(f,lrc); } ll = 5; cr = 2; ll += cr; if(ll != 7){ lrc = 71; if(prlc) printf(f,lrc); } ll = 5; sr = 2; ll += sr; if(ll != 7){ lrc = 72; if(prlc) printf(f,lrc); } ll = 5; ir = 2; ll += ir; if(ll != 7){ lrc = 73; if(prlc) printf(f,lrc); } ll = 5; lr = 2; ll += lr; if(ll != 7){ lrc = 74; if(prlc) printf(f,lrc); } ll = 5; ur = 2; ll += ur; if(ll != 7){ lrc = 75; if(prlc) printf(f,lrc); } ll = 5; fr = 2; ll += fr; if(ll != 7){ lrc = 76; if(prlc) printf(f,lrc); } ll = 5; dr = 2; ll += dr; if(ll != 7){ lrc = 77; if(prlc) printf(f,lrc); } ul = 5; cr = 2; ul += cr; if(ul != 7){ lrc = 78; if(prlc) printf(f,lrc); } ul = 5; sr = 2; ul += sr; if(ul != 7){ lrc = 79; if(prlc) printf(f,lrc); } ul = 5; ir = 2; ul += ir; if(ul != 7){ lrc = 80; if(prlc) printf(f,lrc); } ul = 5; lr = 2; ul += lr; if(ul != 7){ lrc = 81; if(prlc) printf(f,lrc); } ul = 5; ur = 2; ul += ur; if(ul != 7){ lrc = 82; if(prlc) printf(f,lrc); } ul = 5; fr = 2; ul += fr; if(ul != 7){ lrc = 83; if(prlc) printf(f,lrc); } ul = 5; dr = 2; ul += dr; if(ul != 7){ lrc = 84; if(prlc) printf(f,lrc); } fl = 5; cr = 2; fl += cr; if(fl != 7){ lrc = 85; if(prlc) printf(f,lrc); } fl = 5; sr = 2; fl += sr; if(fl != 7){ lrc = 86; if(prlc) printf(f,lrc); } fl = 5; ir = 2; fl += ir; if(fl != 7){ lrc = 87; if(prlc) printf(f,lrc); } fl = 5; lr = 2; fl += lr; if(fl != 7){ lrc = 88; if(prlc) printf(f,lrc); } fl = 5; ur = 2; fl += ur; if(fl != 7){ lrc = 89; if(prlc) printf(f,lrc); } fl = 5; fr = 2; fl += fr; if(fl != 7){ lrc = 90; if(prlc) printf(f,lrc); } fl = 5; dr = 2; fl += dr; if(fl != 7){ lrc = 91; if(prlc) printf(f,lrc); } dl = 5; cr = 2; dl += cr; if(dl != 7){ lrc = 92; if(prlc) printf(f,lrc); } dl = 5; sr = 2; dl += sr; if(dl != 7){ lrc = 93; if(prlc) printf(f,lrc); } dl = 5; ir = 2; dl += ir; if(dl != 7){ lrc = 94; if(prlc) printf(f,lrc); } dl = 5; lr = 2; dl += lr; if(dl != 7){ lrc = 95; if(prlc) printf(f,lrc); } dl = 5; ur = 2; dl += ur; if(dl != 7){ lrc = 96; if(prlc) printf(f,lrc); } dl = 5; fr = 2; dl += fr; if(dl != 7){ lrc = 97; if(prlc) printf(f,lrc); } dl = 5; dr = 2; dl += dr; if(dl != 7){ lrc = 98; if(prlc) printf(f,lrc); } cl = 5; cr = 2; cl -= cr; if(cl != 3){ lrc = 99; if(prlc) printf(f,lrc); } cl = 5; sr = 2; cl -= sr; if(cl != 3){ lrc = 100; if(prlc) printf(f,lrc); } cl = 5; ir = 2; cl -= ir; if(cl != 3){ lrc = 101; if(prlc) printf(f,lrc); } cl = 5; lr = 2; cl -= lr; if(cl != 3){ lrc = 102; if(prlc) printf(f,lrc); } cl = 5; ur = 2; cl -= ur; if(cl != 3){ lrc = 103; if(prlc) printf(f,lrc); } cl = 5; fr = 2; cl -= fr; if(cl != 3){ lrc = 104; if(prlc) printf(f,lrc); } cl = 5; dr = 2; cl -= dr; if(cl != 3){ lrc = 105; if(prlc) printf(f,lrc); } sl = 5; cr = 2; sl -= cr; if(sl != 3){ lrc = 106; if(prlc) printf(f,lrc); } sl = 5; sr = 2; sl -= sr; if(sl != 3){ lrc = 107; if(prlc) printf(f,lrc); } sl = 5; ir = 2; sl -= ir; if(sl != 3){ lrc = 108; if(prlc) printf(f,lrc); } sl = 5; lr = 2; sl -= lr; if(sl != 3){ lrc = 109; if(prlc) printf(f,lrc); } sl = 5; ur = 2; sl -= ur; if(sl != 3){ lrc = 110; if(prlc) printf(f,lrc); } sl = 5; fr = 2; sl -= fr; if(sl != 3){ lrc = 111; if(prlc) printf(f,lrc); } sl = 5; dr = 2; sl -= dr; if(sl != 3){ lrc = 112; if(prlc) printf(f,lrc); } il = 5; cr = 2; il -= cr; if(il != 3){ lrc = 113; if(prlc) printf(f,lrc); } il = 5; sr = 2; il -= sr; if(il != 3){ lrc = 114; if(prlc) printf(f,lrc); } il = 5; ir = 2; il -= ir; if(il != 3){ lrc = 115; if(prlc) printf(f,lrc); } il = 5; lr = 2; il -= lr; if(il != 3){ lrc = 116; if(prlc) printf(f,lrc); } il = 5; ur = 2; il -= ur; if(il != 3){ lrc = 117; if(prlc) printf(f,lrc); } il = 5; fr = 2; il -= fr; if(il != 3){ lrc = 118; if(prlc) printf(f,lrc); } il = 5; dr = 2; il -= dr; if(il != 3){ lrc = 119; if(prlc) printf(f,lrc); } ll = 5; cr = 2; ll -= cr; if(ll != 3){ lrc = 120; if(prlc) printf(f,lrc); } ll = 5; sr = 2; ll -= sr; if(ll != 3){ lrc = 121; if(prlc) printf(f,lrc); } ll = 5; ir = 2; ll -= ir; if(ll != 3){ lrc = 122; if(prlc) printf(f,lrc); } ll = 5; lr = 2; ll -= lr; if(ll != 3){ lrc = 123; if(prlc) printf(f,lrc); } ll = 5; ur = 2; ll -= ur; if(ll != 3){ lrc = 124; if(prlc) printf(f,lrc); } ll = 5; fr = 2; ll -= fr; if(ll != 3){ lrc = 125; if(prlc) printf(f,lrc); } ll = 5; dr = 2; ll -= dr; if(ll != 3){ lrc = 126; if(prlc) printf(f,lrc); } ul = 5; cr = 2; ul -= cr; if(ul != 3){ lrc = 127; if(prlc) printf(f,lrc); } ul = 5; sr = 2; ul -= sr; if(ul != 3){ lrc = 128; if(prlc) printf(f,lrc); } ul = 5; ir = 2; ul -= ir; if(ul != 3){ lrc = 129; if(prlc) printf(f,lrc); } ul = 5; lr = 2; ul -= lr; if(ul != 3){ lrc = 130; if(prlc) printf(f,lrc); } ul = 5; ur = 2; ul -= ur; if(ul != 3){ lrc = 131; if(prlc) printf(f,lrc); } ul = 5; fr = 2; ul -= fr; if(ul != 3){ lrc = 132; if(prlc) printf(f,lrc); } ul = 5; dr = 2; ul -= dr; if(ul != 3){ lrc = 133; if(prlc) printf(f,lrc); } fl = 5; cr = 2; fl -= cr; if(fl != 3){ lrc = 134; if(prlc) printf(f,lrc); } fl = 5; sr = 2; fl -= sr; if(fl != 3){ lrc = 135; if(prlc) printf(f,lrc); } fl = 5; ir = 2; fl -= ir; if(fl != 3){ lrc = 136; if(prlc) printf(f,lrc); } fl = 5; lr = 2; fl -= lr; if(fl != 3){ lrc = 137; if(prlc) printf(f,lrc); } fl = 5; ur = 2; fl -= ur; if(fl != 3){ lrc = 138; if(prlc) printf(f,lrc); } fl = 5; fr = 2; fl -= fr; if(fl != 3){ lrc = 139; if(prlc) printf(f,lrc); } fl = 5; dr = 2; fl -= dr; if(fl != 3){ lrc = 140; if(prlc) printf(f,lrc); } dl = 5; cr = 2; dl -= cr; if(dl != 3){ lrc = 141; if(prlc) printf(f,lrc); } dl = 5; sr = 2; dl -= sr; if(dl != 3){ lrc = 142; if(prlc) printf(f,lrc); } dl = 5; ir = 2; dl -= ir; if(dl != 3){ lrc = 143; if(prlc) printf(f,lrc); } dl = 5; lr = 2; dl -= lr; if(dl != 3){ lrc = 144; if(prlc) printf(f,lrc); } dl = 5; ur = 2; dl -= ur; if(dl != 3){ lrc = 145; if(prlc) printf(f,lrc); } dl = 5; fr = 2; dl -= fr; if(dl != 3){ lrc = 146; if(prlc) printf(f,lrc); } dl = 5; dr = 2; dl -= dr; if(dl != 3){ lrc = 147; if(prlc) printf(f,lrc); } cl = 5; cr = 2; cl *= cr; if(cl != 10){ lrc = 148; if(prlc) printf(f,lrc); } cl = 5; sr = 2; cl *= sr; if(cl != 10){ lrc = 149; if(prlc) printf(f,lrc); } cl = 5; ir = 2; cl *= ir; if(cl != 10){ lrc = 150; if(prlc) printf(f,lrc); } cl = 5; lr = 2; cl *= lr; if(cl != 10){ lrc = 151; if(prlc) printf(f,lrc); } cl = 5; ur = 2; cl *= ur; if(cl != 10){ lrc = 152; if(prlc) printf(f,lrc); } cl = 5; fr = 2; cl *= fr; if(cl != 10){ lrc = 153; if(prlc) printf(f,lrc); } cl = 5; dr = 2; cl *= dr; if(cl != 10){ lrc = 154; if(prlc) printf(f,lrc); } sl = 5; cr = 2; sl *= cr; if(sl != 10){ lrc = 155; if(prlc) printf(f,lrc); } sl = 5; sr = 2; sl *= sr; if(sl != 10){ lrc = 156; if(prlc) printf(f,lrc); } sl = 5; ir = 2; sl *= ir; if(sl != 10){ lrc = 157; if(prlc) printf(f,lrc); } sl = 5; lr = 2; sl *= lr; if(sl != 10){ lrc = 158; if(prlc) printf(f,lrc); } sl = 5; ur = 2; sl *= ur; if(sl != 10){ lrc = 159; if(prlc) printf(f,lrc); } sl = 5; fr = 2; sl *= fr; if(sl != 10){ lrc = 160; if(prlc) printf(f,lrc); } sl = 5; dr = 2; sl *= dr; if(sl != 10){ lrc = 161; if(prlc) printf(f,lrc); } il = 5; cr = 2; il *= cr; if(il != 10){ lrc = 162; if(prlc) printf(f,lrc); } il = 5; sr = 2; il *= sr; if(il != 10){ lrc = 163; if(prlc) printf(f,lrc); } il = 5; ir = 2; il *= ir; if(il != 10){ lrc = 164; if(prlc) printf(f,lrc); } il = 5; lr = 2; il *= lr; if(il != 10){ lrc = 165; if(prlc) printf(f,lrc); } il = 5; ur = 2; il *= ur; if(il != 10){ lrc = 166; if(prlc) printf(f,lrc); } il = 5; fr = 2; il *= fr; if(il != 10){ lrc = 167; if(prlc) printf(f,lrc); } il = 5; dr = 2; il *= dr; if(il != 10){ lrc = 168; if(prlc) printf(f,lrc); } ll = 5; cr = 2; ll *= cr; if(ll != 10){ lrc = 169; if(prlc) printf(f,lrc); } ll = 5; sr = 2; ll *= sr; if(ll != 10){ lrc = 170; if(prlc) printf(f,lrc); } ll = 5; ir = 2; ll *= ir; if(ll != 10){ lrc = 171; if(prlc) printf(f,lrc); } ll = 5; lr = 2; ll *= lr; if(ll != 10){ lrc = 172; if(prlc) printf(f,lrc); } ll = 5; ur = 2; ll *= ur; if(ll != 10){ lrc = 173; if(prlc) printf(f,lrc); } ll = 5; fr = 2; ll *= fr; if(ll != 10){ lrc = 174; if(prlc) printf(f,lrc); } ll = 5; dr = 2; ll *= dr; if(ll != 10){ lrc = 175; if(prlc) printf(f,lrc); } ul = 5; cr = 2; ul *= cr; if(ul != 10){ lrc = 176; if(prlc) printf(f,lrc); } ul = 5; sr = 2; ul *= sr; if(ul != 10){ lrc = 177; if(prlc) printf(f,lrc); } ul = 5; ir = 2; ul *= ir; if(ul != 10){ lrc = 178; if(prlc) printf(f,lrc); } ul = 5; lr = 2; ul *= lr; if(ul != 10){ lrc = 179; if(prlc) printf(f,lrc); } ul = 5; ur = 2; ul *= ur; if(ul != 10){ lrc = 180; if(prlc) printf(f,lrc); } ul = 5; fr = 2; ul *= fr; if(ul != 10){ lrc = 181; if(prlc) printf(f,lrc); } ul = 5; dr = 2; ul *= dr; if(ul != 10){ lrc = 182; if(prlc) printf(f,lrc); } fl = 5; cr = 2; fl *= cr; if(fl != 10){ lrc = 183; if(prlc) printf(f,lrc); } fl = 5; sr = 2; fl *= sr; if(fl != 10){ lrc = 184; if(prlc) printf(f,lrc); } fl = 5; ir = 2; fl *= ir; if(fl != 10){ lrc = 185; if(prlc) printf(f,lrc); } fl = 5; lr = 2; fl *= lr; if(fl != 10){ lrc = 186; if(prlc) printf(f,lrc); } fl = 5; ur = 2; fl *= ur; if(fl != 10){ lrc = 187; if(prlc) printf(f,lrc); } fl = 5; fr = 2; fl *= fr; if(fl != 10){ lrc = 188; if(prlc) printf(f,lrc); } fl = 5; dr = 2; fl *= dr; if(fl != 10){ lrc = 189; if(prlc) printf(f,lrc); } dl = 5; cr = 2; dl *= cr; if(dl != 10){ lrc = 190; if(prlc) printf(f,lrc); } dl = 5; sr = 2; dl *= sr; if(dl != 10){ lrc = 191; if(prlc) printf(f,lrc); } dl = 5; ir = 2; dl *= ir; if(dl != 10){ lrc = 192; if(prlc) printf(f,lrc); } dl = 5; lr = 2; dl *= lr; if(dl != 10){ lrc = 193; if(prlc) printf(f,lrc); } dl = 5; ur = 2; dl *= ur; if(dl != 10){ lrc = 194; if(prlc) printf(f,lrc); } dl = 5; fr = 2; dl *= fr; if(dl != 10){ lrc = 195; if(prlc) printf(f,lrc); } dl = 5; dr = 2; dl *= dr; if(dl != 10){ lrc = 196; if(prlc) printf(f,lrc); } cl = 5; cr = 2; cl /= cr; if(cl != 2){ lrc = 197; if(prlc) printf(f,lrc); } cl = 5; sr = 2; cl /= sr; if(cl != 2){ lrc = 198; if(prlc) printf(f,lrc); } cl = 5; ir = 2; cl /= ir; if(cl != 2){ lrc = 199; if(prlc) printf(f,lrc); } cl = 5; lr = 2; cl /= lr; if(cl != 2){ lrc = 200; if(prlc) printf(f,lrc); } cl = 5; ur = 2; cl /= ur; if(cl != 2){ lrc = 201; if(prlc) printf(f,lrc); } cl = 5; fr = 2; cl /= fr; if(cl != 2){ lrc = 202; if(prlc) printf(f,lrc); } cl = 5; dr = 2; cl /= dr; if(cl != 2){ lrc = 203; if(prlc) printf(f,lrc); } sl = 5; cr = 2; sl /= cr; if(sl != 2){ lrc = 204; if(prlc) printf(f,lrc); } sl = 5; sr = 2; sl /= sr; if(sl != 2){ lrc = 205; if(prlc) printf(f,lrc); } sl = 5; ir = 2; sl /= ir; if(sl != 2){ lrc = 206; if(prlc) printf(f,lrc); } sl = 5; lr = 2; sl /= lr; if(sl != 2){ lrc = 207; if(prlc) printf(f,lrc); } sl = 5; ur = 2; sl /= ur; if(sl != 2){ lrc = 208; if(prlc) printf(f,lrc); } sl = 5; fr = 2; sl /= fr; if(sl != 2){ lrc = 209; if(prlc) printf(f,lrc); } sl = 5; dr = 2; sl /= dr; if(sl != 2){ lrc = 210; if(prlc) printf(f,lrc); } il = 5; cr = 2; il /= cr; if(il != 2){ lrc = 211; if(prlc) printf(f,lrc); } il = 5; sr = 2; il /= sr; if(il != 2){ lrc = 212; if(prlc) printf(f,lrc); } il = 5; ir = 2; il /= ir; if(il != 2){ lrc = 213; if(prlc) printf(f,lrc); } il = 5; lr = 2; il /= lr; if(il != 2){ lrc = 214; if(prlc) printf(f,lrc); } il = 5; ur = 2; il /= ur; if(il != 2){ lrc = 215; if(prlc) printf(f,lrc); } il = 5; fr = 2; il /= fr; if(il != 2){ lrc = 216; if(prlc) printf(f,lrc); } il = 5; dr = 2; il /= dr; if(il != 2){ lrc = 217; if(prlc) printf(f,lrc); } ll = 5; cr = 2; ll /= cr; if(ll != 2){ lrc = 218; if(prlc) printf(f,lrc); } ll = 5; sr = 2; ll /= sr; if(ll != 2){ lrc = 219; if(prlc) printf(f,lrc); } ll = 5; ir = 2; ll /= ir; if(ll != 2){ lrc = 220; if(prlc) printf(f,lrc); } ll = 5; lr = 2; ll /= lr; if(ll != 2){ lrc = 221; if(prlc) printf(f,lrc); } ll = 5; ur = 2; ll /= ur; if(ll != 2){ lrc = 222; if(prlc) printf(f,lrc); } ll = 5; fr = 2; ll /= fr; if(ll != 2){ lrc = 223; if(prlc) printf(f,lrc); } ll = 5; dr = 2; ll /= dr; if(ll != 2){ lrc = 224; if(prlc) printf(f,lrc); } ul = 5; cr = 2; ul /= cr; if(ul != 2){ lrc = 225; if(prlc) printf(f,lrc); } ul = 5; sr = 2; ul /= sr; if(ul != 2){ lrc = 226; if(prlc) printf(f,lrc); } ul = 5; ir = 2; ul /= ir; if(ul != 2){ lrc = 227; if(prlc) printf(f,lrc); } ul = 5; lr = 2; ul /= lr; if(ul != 2){ lrc = 228; if(prlc) printf(f,lrc); } ul = 5; ur = 2; ul /= ur; if(ul != 2){ lrc = 229; if(prlc) printf(f,lrc); } ul = 5; fr = 2; ul /= fr; if(ul != 2){ lrc = 230; if(prlc) printf(f,lrc); } ul = 5; dr = 2; ul /= dr; if(ul != 2){ lrc = 231; if(prlc) printf(f,lrc); } #ifdef NO_FLOATS fl = 5; cr = 2; fl /= cr; if(fl != 2){ lrc = 232; if(prlc) printf(f,lrc); } fl = 5; sr = 2; fl /= sr; if(fl != 2){ lrc = 233; if(prlc) printf(f,lrc); } fl = 5; ir = 2; fl /= ir; if(fl != 2){ lrc = 234; if(prlc) printf(f,lrc); } fl = 5; lr = 2; fl /= lr; if(fl != 2){ lrc = 235; if(prlc) printf(f,lrc); } fl = 5; ur = 2; fl /= ur; if(fl != 2){ lrc = 236; if(prlc) printf(f,lrc); } fl = 5; fr = 2; fl /= fr; if(fl != 2){ lrc = 237; if(prlc) printf(f,lrc); } fl = 5; dr = 2; fl /= dr; if(fl != 2){ lrc = 238; if(prlc) printf(f,lrc); } dl = 5; cr = 2; dl /= cr; if(dl != 2){ lrc = 239; if(prlc) printf(f,lrc); } dl = 5; sr = 2; dl /= sr; if(dl != 2){ lrc = 240; if(prlc) printf(f,lrc); } dl = 5; ir = 2; dl /= ir; if(dl != 2){ lrc = 241; if(prlc) printf(f,lrc); } dl = 5; lr = 2; dl /= lr; if(dl != 2){ lrc = 242; if(prlc) printf(f,lrc); } dl = 5; ur = 2; dl /= ur; if(dl != 2){ lrc = 243; if(prlc) printf(f,lrc); } dl = 5; fr = 2; dl /= fr; if(dl != 2){ lrc = 244; if(prlc) printf(f,lrc); } dl = 5; dr = 2; dl /= dr; if(dl != 2){ lrc = 245; if(prlc) printf(f,lrc); } #else fl = 5; cr = 2; fl /= cr; if(fl != 2.5){ lrc = 232; if(prlc) printf(f,lrc); } fl = 5; sr = 2; fl /= sr; if(fl != 2.5){ lrc = 233; if(prlc) printf(f,lrc); } fl = 5; ir = 2; fl /= ir; if(fl != 2.5){ lrc = 234; if(prlc) printf(f,lrc); } fl = 5; lr = 2; fl /= lr; if(fl != 2.5){ lrc = 235; if(prlc) printf(f,lrc); } fl = 5; ur = 2; fl /= ur; if(fl != 2.5){ lrc = 236; if(prlc) printf(f,lrc); } fl = 5; fr = 2; fl /= fr; if(fl != 2.5){ lrc = 237; if(prlc) printf(f,lrc); } fl = 5; dr = 2; fl /= dr; if(fl != 2.5){ lrc = 238; if(prlc) printf(f,lrc); } dl = 5; cr = 2; dl /= cr; if(dl != 2.5){ lrc = 239; if(prlc) printf(f,lrc); } dl = 5; sr = 2; dl /= sr; if(dl != 2.5){ lrc = 240; if(prlc) printf(f,lrc); } dl = 5; ir = 2; dl /= ir; if(dl != 2.5){ lrc = 241; if(prlc) printf(f,lrc); } dl = 5; lr = 2; dl /= lr; if(dl != 2.5){ lrc = 242; if(prlc) printf(f,lrc); } dl = 5; ur = 2; dl /= ur; if(dl != 2.5){ lrc = 243; if(prlc) printf(f,lrc); } dl = 5; fr = 2; dl /= fr; if(dl != 2.5){ lrc = 244; if(prlc) printf(f,lrc); } dl = 5; dr = 2; dl /= dr; if(dl != 2.5){ lrc = 245; if(prlc) printf(f,lrc); } #endif cl = 5; cr = 2; cl %= cr; if(cl != 1){ lrc = 246; if(prlc) printf(f,lrc); } cl = 5; sr = 2; cl %= sr; if(cl != 1){ lrc = 247; if(prlc) printf(f,lrc); } cl = 5; ir = 2; cl %= ir; if(cl != 1){ lrc = 248; if(prlc) printf(f,lrc); } cl = 5; lr = 2; cl %= lr; if(cl != 1){ lrc = 249; if(prlc) printf(f,lrc); } cl = 5; ur = 2; cl %= ur; if(cl != 1){ lrc = 250; if(prlc) printf(f,lrc); } sl = 5; cr = 2; sl %= cr; if(sl != 1){ lrc = 251; if(prlc) printf(f,lrc); } sl = 5; sr = 2; sl %= sr; if(sl != 1){ lrc = 252; if(prlc) printf(f,lrc); } sl = 5; ir = 2; sl %= ir; if(sl != 1){ lrc = 253; if(prlc) printf(f,lrc); } sl = 5; lr = 2; sl %= lr; if(sl != 1){ lrc = 254; if(prlc) printf(f,lrc); } sl = 5; ur = 2; sl %= ur; if(sl != 1){ lrc = 255; if(prlc) printf(f,lrc); } if(lrc != 0) { rc = 1; if(pd0->flgd != 0) printf(s714er,1); } return rc; } /********************************************************************************************* the main loop that launches the sections *********************************************************************************************/ #ifndef NO_TYPELESS_STRUCT_PTR int section(int j,struct* pd0){ #else int section(int j,void* pd0){ #endif switch(j){ case 0: return s714(pd0); } } #define cq_sections 1 /* C REFERENCE MANUAL (main) */ #ifndef NO_OLD_FUNC_DECL main(n,args) int n; char **args; { #else int main(int n,char **args) { #endif int j; static struct defs d0, *pd0; d0.flgs = 1; /* These flags dictate */ d0.flgm = 1; /* the verbosity of */ d0.flgd = 1; /* the program. */ d0.flgl = 1; pd0 = &d0; for (j=0; j<cq_sections; j++) { d0.rrc=section(j,pd0); d0.crc=d0.crc+d0.rrc; if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); } if(d0.crc == 0) printf("\nNo errors detected.\n"); else printf("\nFailed.\n"); return d0.crc; } ���������������������������������������������������������cc65-2.18/test/val/cq714b.c�������������������������������������������������������������������������0000664�0000000�0000000�00000046541�13473601511�0015125�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! C-Manual Chapter 9: Statements !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include "common.h" struct defs { int cbits; /* No. of bits per char */ int ibits; /* int */ int sbits; /* short */ int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ }; int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ #ifndef NO_OLD_FUNC_DECL s714(pd0) /* 7.14 Assignment operators */ struct defs *pd0; { #else int s714(struct defs *pd0){ #endif static char f[] = "Local error %d.\n"; static char s714er[] = "s714,er%d\n"; static char qs714[8] = "s714 "; register int prlc, lrc; int rc; char cl, cr; short sl, sr; int il, ir; long ll, lr; unsigned ul, ur; #ifndef NO_FLOATS float fl, fr; double dl, dr; #else signed fl, fr; signed dl, dr; #endif char *ps, *pt; ps = qs714; pt = pd0->rfs; rc = 0; lrc = 0; prlc = pd0->flgl; while (*pt++ = *ps++); /* This section tests the assignment operators. It is an exhaustive test of all assignment statements of the form: vl op vr where vl and vr are variables from the set {char,short,int,long,unsigned,float,double} and op is one of the assignment operators. There are 395 such statements. The initial values for the variables have been chosen so that both the initial values and the results will "fit" in just about any implementation, and that the re- sults will be such that they test for the proper form- ation of composite operators, rather than checking for the valid operation of those operators' components. For example, in checking >>=, we want to verify that a right shift and a move take place, rather than whether or not there may be some peculiarities about the right shift. Such tests have been made previously, and to repeat them here would be to throw out a red herring. The table below lists the operators, assignment targets, initial values for left and right operands, and the expected values of the results. = += -= *= /= %= >>= <<= &= ^= |= char 2 7 3 10 2 1 1 20 8 6 14 short 2 7 3 10 2 1 1 20 8 6 14 int 2 7 3 10 2 1 1 20 8 6 14 long 2 7 3 10 2 1 1 20 8 6 14 unsigned 2 7 3 10 2 1 1 20 8 6 14 float 2 7 3 10 2.5 | | double 2 7 3 10 2.5 | | | | initial (5,2) | (5,2) | (12,10) The following machine-generated program reflects the tests described in the table. */ il = 5; cr = 2; il %= cr; if(il != 1){ lrc = 256; if(prlc) printf(f,lrc); } il = 5; sr = 2; il %= sr; if(il != 1){ lrc = 257; if(prlc) printf(f,lrc); } il = 5; ir = 2; il %= ir; if(il != 1){ lrc = 258; if(prlc) printf(f,lrc); } il = 5; lr = 2; il %= lr; if(il != 1){ lrc = 259; if(prlc) printf(f,lrc); } il = 5; ur = 2; il %= ur; if(il != 1){ lrc = 260; if(prlc) printf(f,lrc); } ll = 5; cr = 2; ll %= cr; if(ll != 1){ lrc = 261; if(prlc) printf(f,lrc); } ll = 5; sr = 2; ll %= sr; if(ll != 1){ lrc = 262; if(prlc) printf(f,lrc); } ll = 5; ir = 2; ll %= ir; if(ll != 1){ lrc = 263; if(prlc) printf(f,lrc); } ll = 5; lr = 2; ll %= lr; if(ll != 1){ lrc = 264; if(prlc) printf(f,lrc); } ll = 5; ur = 2; ll %= ur; if(ll != 1){ lrc = 265; if(prlc) printf(f,lrc); } ul = 5; cr = 2; ul %= cr; if(ul != 1){ lrc = 266; if(prlc) printf(f,lrc); } ul = 5; sr = 2; ul %= sr; if(ul != 1){ lrc = 267; if(prlc) printf(f,lrc); } ul = 5; ir = 2; ul %= ir; if(ul != 1){ lrc = 268; if(prlc) printf(f,lrc); } ul = 5; lr = 2; ul %= lr; if(ul != 1){ lrc = 269; if(prlc) printf(f,lrc); } ul = 5; ur = 2; ul %= ur; if(ul != 1){ lrc = 270; if(prlc) printf(f,lrc); } cl = 5; cr = 2; cl >>= cr; if(cl != 1){ lrc = 271; if(prlc) printf(f,lrc); } cl = 5; sr = 2; cl >>= sr; if(cl != 1){ lrc = 272; if(prlc) printf(f,lrc); } cl = 5; ir = 2; cl >>= ir; if(cl != 1){ lrc = 273; if(prlc) printf(f,lrc); } cl = 5; lr = 2; cl >>= lr; if(cl != 1){ lrc = 274; if(prlc) printf(f,lrc); } cl = 5; ur = 2; cl >>= ur; if(cl != 1){ lrc = 275; if(prlc) printf(f,lrc); } sl = 5; cr = 2; sl >>= cr; if(sl != 1){ lrc = 276; if(prlc) printf(f,lrc); } sl = 5; sr = 2; sl >>= sr; if(sl != 1){ lrc = 277; if(prlc) printf(f,lrc); } sl = 5; ir = 2; sl >>= ir; if(sl != 1){ lrc = 278; if(prlc) printf(f,lrc); } sl = 5; lr = 2; sl >>= lr; if(sl != 1){ lrc = 279; if(prlc) printf(f,lrc); } sl = 5; ur = 2; sl >>= ur; if(sl != 1){ lrc = 280; if(prlc) printf(f,lrc); } il = 5; cr = 2; il >>= cr; if(il != 1){ lrc = 281; if(prlc) printf(f,lrc); } il = 5; sr = 2; il >>= sr; if(il != 1){ lrc = 282; if(prlc) printf(f,lrc); } il = 5; ir = 2; il >>= ir; if(il != 1){ lrc = 283; if(prlc) printf(f,lrc); } il = 5; lr = 2; il >>= lr; if(il != 1){ lrc = 284; if(prlc) printf(f,lrc); } il = 5; ur = 2; il >>= ur; if(il != 1){ lrc = 285; if(prlc) printf(f,lrc); } ll = 5; cr = 2; ll >>= cr; if(ll != 1){ lrc = 286; if(prlc) printf(f,lrc); } ll = 5; sr = 2; ll >>= sr; if(ll != 1){ lrc = 287; if(prlc) printf(f,lrc); } ll = 5; ir = 2; ll >>= ir; if(ll != 1){ lrc = 288; if(prlc) printf(f,lrc); } ll = 5; lr = 2; ll >>= lr; if(ll != 1){ lrc = 289; if(prlc) printf(f,lrc); } ll = 5; ur = 2; ll >>= ur; if(ll != 1){ lrc = 290; if(prlc) printf(f,lrc); } ul = 5; cr = 2; ul >>= cr; if(ul != 1){ lrc = 291; if(prlc) printf(f,lrc); } ul = 5; sr = 2; ul >>= sr; if(ul != 1){ lrc = 292; if(prlc) printf(f,lrc); } ul = 5; ir = 2; ul >>= ir; if(ul != 1){ lrc = 293; if(prlc) printf(f,lrc); } ul = 5; lr = 2; ul >>= lr; if(ul != 1){ lrc = 294; if(prlc) printf(f,lrc); } ul = 5; ur = 2; ul >>= ur; if(ul != 1){ lrc = 295; if(prlc) printf(f,lrc); } cl = 5; cr = 2; cl <<= cr; if(cl != 20){ lrc = 296; if(prlc) printf(f,lrc); } cl = 5; sr = 2; cl <<= sr; if(cl != 20){ lrc = 297; if(prlc) printf(f,lrc); } cl = 5; ir = 2; cl <<= ir; if(cl != 20){ lrc = 298; if(prlc) printf(f,lrc); } cl = 5; lr = 2; cl <<= lr; if(cl != 20){ lrc = 299; if(prlc) printf(f,lrc); } cl = 5; ur = 2; cl <<= ur; if(cl != 20){ lrc = 300; if(prlc) printf(f,lrc); } sl = 5; cr = 2; sl <<= cr; if(sl != 20){ lrc = 301; if(prlc) printf(f,lrc); } sl = 5; sr = 2; sl <<= sr; if(sl != 20){ lrc = 302; if(prlc) printf(f,lrc); } sl = 5; ir = 2; sl <<= ir; if(sl != 20){ lrc = 303; if(prlc) printf(f,lrc); } sl = 5; lr = 2; sl <<= lr; if(sl != 20){ lrc = 304; if(prlc) printf(f,lrc); } sl = 5; ur = 2; sl <<= ur; if(sl != 20){ lrc = 305; if(prlc) printf(f,lrc); } il = 5; cr = 2; il <<= cr; if(il != 20){ lrc = 306; if(prlc) printf(f,lrc); } il = 5; sr = 2; il <<= sr; if(il != 20){ lrc = 307; if(prlc) printf(f,lrc); } il = 5; ir = 2; il <<= ir; if(il != 20){ lrc = 308; if(prlc) printf(f,lrc); } il = 5; lr = 2; il <<= lr; if(il != 20){ lrc = 309; if(prlc) printf(f,lrc); } il = 5; ur = 2; il <<= ur; if(il != 20){ lrc = 310; if(prlc) printf(f,lrc); } ll = 5; cr = 2; ll <<= cr; if(ll != 20){ lrc = 311; if(prlc) printf(f,lrc); } ll = 5; sr = 2; ll <<= sr; if(ll != 20){ lrc = 312; if(prlc) printf(f,lrc); } ll = 5; ir = 2; ll <<= ir; if(ll != 20){ lrc = 313; if(prlc) printf(f,lrc); } ll = 5; lr = 2; ll <<= lr; if(ll != 20){ lrc = 314; if(prlc) printf(f,lrc); } ll = 5; ur = 2; ll <<= ur; if(ll != 20){ lrc = 315; if(prlc) printf(f,lrc); } ul = 5; cr = 2; ul <<= cr; if(ul != 20){ lrc = 316; if(prlc) printf(f,lrc); } ul = 5; sr = 2; ul <<= sr; if(ul != 20){ lrc = 317; if(prlc) printf(f,lrc); } ul = 5; ir = 2; ul <<= ir; if(ul != 20){ lrc = 318; if(prlc) printf(f,lrc); } ul = 5; lr = 2; ul <<= lr; if(ul != 20){ lrc = 319; if(prlc) printf(f,lrc); } ul = 5; ur = 2; ul <<= ur; if(ul != 20){ lrc = 320; if(prlc) printf(f,lrc); } cl = 12; cr = 10; cl &= cr; if(cl != 8){ lrc = 321; if(prlc) printf(f,lrc); } cl = 12; sr = 10; cl &= sr; if(cl != 8){ lrc = 322; if(prlc) printf(f,lrc); } cl = 12; ir = 10; cl &= ir; if(cl != 8){ lrc = 323; if(prlc) printf(f,lrc); } cl = 12; lr = 10; cl &= lr; if(cl != 8){ lrc = 324; if(prlc) printf(f,lrc); } cl = 12; ur = 10; cl &= ur; if(cl != 8){ lrc = 325; if(prlc) printf(f,lrc); } sl = 12; cr = 10; sl &= cr; if(sl != 8){ lrc = 326; if(prlc) printf(f,lrc); } sl = 12; sr = 10; sl &= sr; if(sl != 8){ lrc = 327; if(prlc) printf(f,lrc); } sl = 12; ir = 10; sl &= ir; if(sl != 8){ lrc = 328; if(prlc) printf(f,lrc); } sl = 12; lr = 10; sl &= lr; if(sl != 8){ lrc = 329; if(prlc) printf(f,lrc); } sl = 12; ur = 10; sl &= ur; if(sl != 8){ lrc = 330; if(prlc) printf(f,lrc); } il = 12; cr = 10; il &= cr; if(il != 8){ lrc = 331; if(prlc) printf(f,lrc); } il = 12; sr = 10; il &= sr; if(il != 8){ lrc = 332; if(prlc) printf(f,lrc); } il = 12; ir = 10; il &= ir; if(il != 8){ lrc = 333; if(prlc) printf(f,lrc); } il = 12; lr = 10; il &= lr; if(il != 8){ lrc = 334; if(prlc) printf(f,lrc); } il = 12; ur = 10; il &= ur; if(il != 8){ lrc = 335; if(prlc) printf(f,lrc); } ll = 12; cr = 10; ll &= cr; if(ll != 8){ lrc = 336; if(prlc) printf(f,lrc); } ll = 12; sr = 10; ll &= sr; if(ll != 8){ lrc = 337; if(prlc) printf(f,lrc); } ll = 12; ir = 10; ll &= ir; if(ll != 8){ lrc = 338; if(prlc) printf(f,lrc); } ll = 12; lr = 10; ll &= lr; if(ll != 8){ lrc = 339; if(prlc) printf(f,lrc); } ll = 12; ur = 10; ll &= ur; if(ll != 8){ lrc = 340; if(prlc) printf(f,lrc); } ul = 12; cr = 10; ul &= cr; if(ul != 8){ lrc = 341; if(prlc) printf(f,lrc); } ul = 12; sr = 10; ul &= sr; if(ul != 8){ lrc = 342; if(prlc) printf(f,lrc); } ul = 12; ir = 10; ul &= ir; if(ul != 8){ lrc = 343; if(prlc) printf(f,lrc); } ul = 12; lr = 10; ul &= lr; if(ul != 8){ lrc = 344; if(prlc) printf(f,lrc); } ul = 12; ur = 10; ul &= ur; if(ul != 8){ lrc = 345; if(prlc) printf(f,lrc); } cl = 12; cr = 10; cl ^= cr; if(cl != 6){ lrc = 346; if(prlc) printf(f,lrc); } cl = 12; sr = 10; cl ^= sr; if(cl != 6){ lrc = 347; if(prlc) printf(f,lrc); } cl = 12; ir = 10; cl ^= ir; if(cl != 6){ lrc = 348; if(prlc) printf(f,lrc); } cl = 12; lr = 10; cl ^= lr; if(cl != 6){ lrc = 349; if(prlc) printf(f,lrc); } cl = 12; ur = 10; cl ^= ur; if(cl != 6){ lrc = 350; if(prlc) printf(f,lrc); } sl = 12; cr = 10; sl ^= cr; if(sl != 6){ lrc = 351; if(prlc) printf(f,lrc); } sl = 12; sr = 10; sl ^= sr; if(sl != 6){ lrc = 352; if(prlc) printf(f,lrc); } sl = 12; ir = 10; sl ^= ir; if(sl != 6){ lrc = 353; if(prlc) printf(f,lrc); } sl = 12; lr = 10; sl ^= lr; if(sl != 6){ lrc = 354; if(prlc) printf(f,lrc); } sl = 12; ur = 10; sl ^= ur; if(sl != 6){ lrc = 355; if(prlc) printf(f,lrc); } il = 12; cr = 10; il ^= cr; if(il != 6){ lrc = 356; if(prlc) printf(f,lrc); } il = 12; sr = 10; il ^= sr; if(il != 6){ lrc = 357; if(prlc) printf(f,lrc); } il = 12; ir = 10; il ^= ir; if(il != 6){ lrc = 358; if(prlc) printf(f,lrc); } il = 12; lr = 10; il ^= lr; if(il != 6){ lrc = 359; if(prlc) printf(f,lrc); } il = 12; ur = 10; il ^= ur; if(il != 6){ lrc = 360; if(prlc) printf(f,lrc); } ll = 12; cr = 10; ll ^= cr; if(ll != 6){ lrc = 361; if(prlc) printf(f,lrc); } ll = 12; sr = 10; ll ^= sr; if(ll != 6){ lrc = 362; if(prlc) printf(f,lrc); } ll = 12; ir = 10; ll ^= ir; if(ll != 6){ lrc = 363; if(prlc) printf(f,lrc); } ll = 12; lr = 10; ll ^= lr; if(ll != 6){ lrc = 364; if(prlc) printf(f,lrc); } ll = 12; ur = 10; ll ^= ur; if(ll != 6){ lrc = 365; if(prlc) printf(f,lrc); } ul = 12; cr = 10; ul ^= cr; if(ul != 6){ lrc = 366; if(prlc) printf(f,lrc); } ul = 12; sr = 10; ul ^= sr; if(ul != 6){ lrc = 367; if(prlc) printf(f,lrc); } ul = 12; ir = 10; ul ^= ir; if(ul != 6){ lrc = 368; if(prlc) printf(f,lrc); } ul = 12; lr = 10; ul ^= lr; if(ul != 6){ lrc = 369; if(prlc) printf(f,lrc); } ul = 12; ur = 10; ul ^= ur; if(ul != 6){ lrc = 370; if(prlc) printf(f,lrc); } cl = 12; cr = 10; cl |= cr; if(cl != 14){ lrc = 371; if(prlc) printf(f,lrc); } cl = 12; sr = 10; cl |= sr; if(cl != 14){ lrc = 372; if(prlc) printf(f,lrc); } cl = 12; ir = 10; cl |= ir; if(cl != 14){ lrc = 373; if(prlc) printf(f,lrc); } cl = 12; lr = 10; cl |= lr; if(cl != 14){ lrc = 374; if(prlc) printf(f,lrc); } cl = 12; ur = 10; cl |= ur; if(cl != 14){ lrc = 375; if(prlc) printf(f,lrc); } sl = 12; cr = 10; sl |= cr; if(sl != 14){ lrc = 376; if(prlc) printf(f,lrc); } sl = 12; sr = 10; sl |= sr; if(sl != 14){ lrc = 377; if(prlc) printf(f,lrc); } sl = 12; ir = 10; sl |= ir; if(sl != 14){ lrc = 378; if(prlc) printf(f,lrc); } sl = 12; lr = 10; sl |= lr; if(sl != 14){ lrc = 379; if(prlc) printf(f,lrc); } sl = 12; ur = 10; sl |= ur; if(sl != 14){ lrc = 380; if(prlc) printf(f,lrc); } il = 12; cr = 10; il |= cr; if(il != 14){ lrc = 381; if(prlc) printf(f,lrc); } il = 12; sr = 10; il |= sr; if(il != 14){ lrc = 382; if(prlc) printf(f,lrc); } il = 12; ir = 10; il |= ir; if(il != 14){ lrc = 383; if(prlc) printf(f,lrc); } il = 12; lr = 10; il |= lr; if(il != 14){ lrc = 384; if(prlc) printf(f,lrc); } il = 12; ur = 10; il |= ur; if(il != 14){ lrc = 385; if(prlc) printf(f,lrc); } ll = 12; cr = 10; ll |= cr; if(ll != 14){ lrc = 386; if(prlc) printf(f,lrc); } ll = 12; sr = 10; ll |= sr; if(ll != 14){ lrc = 387; if(prlc) printf(f,lrc); } ll = 12; ir = 10; ll |= ir; if(ll != 14){ lrc = 388; if(prlc) printf(f,lrc); } ll = 12; lr = 10; ll |= lr; if(ll != 14){ lrc = 389; if(prlc) printf(f,lrc); } ll = 12; ur = 10; ll |= ur; if(ll != 14){ lrc = 390; if(prlc) printf(f,lrc); } ul = 12; cr = 10; ul |= cr; if(ul != 14){ lrc = 391; if(prlc) printf(f,lrc); } ul = 12; sr = 10; ul |= sr; if(ul != 14){ lrc = 392; if(prlc) printf(f,lrc); } ul = 12; ir = 10; ul |= ir; if(ul != 14){ lrc = 393; if(prlc) printf(f,lrc); } ul = 12; lr = 10; ul |= lr; if(ul != 14){ lrc = 394; if(prlc) printf(f,lrc); } ul = 12; ur = 10; ul |= ur; if(ul != 14){ lrc = 395; if(prlc) printf(f,lrc); } if(lrc != 0) { rc = 1; if(pd0->flgd != 0) printf(s714er,1); } return rc; } /********************************************************************************************* the main loop that launches the sections *********************************************************************************************/ #ifndef NO_TYPELESS_STRUCT_PTR int section(int j,struct* pd0){ #else int section(int j,void* pd0){ #endif switch(j){ case 0: return s714(pd0); } } #define cq_sections 1 /* C REFERENCE MANUAL (main) */ #ifndef NO_OLD_FUNC_DECL main(n,args) int n; char **args; { #else int main(int n,char **args) { #endif int j; static struct defs d0, *pd0; d0.flgs = 1; /* These flags dictate */ d0.flgm = 1; /* the verbosity of */ d0.flgd = 1; /* the program. */ d0.flgl = 1; pd0 = &d0; for (j=0; j<cq_sections; j++) { d0.rrc=section(j,pd0); d0.crc=d0.crc+d0.rrc; if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); } if(d0.crc == 0) printf("\nNo errors detected.\n"); else printf("\nFailed.\n"); return d0.crc; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/cq715.c��������������������������������������������������������������������������0000664�0000000�0000000�00000011114�13473601511�0014750�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! C-Manual Chapter 7.15: Comma operator !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include "common.h" struct defs { int cbits; /* No. of bits per char */ int ibits; /* int */ int sbits; /* short */ int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ }; int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ /*#include "cq26.c"*/ /* hardware check */ #ifdef NO_IMPLICIT_FUNC_PROTOTYPES s715f(int x,int y,int z); #endif #ifndef NO_OLD_FUNC_DECL s715(pd0) /* 7.15 Comma operator */ struct defs *pd0; { #else int s715(struct defs *pd0) { #endif static char s715er[] = "s715,er%d\n"; static char qs715[8] = "s715 "; int rc; char *ps, *pt; int a, t, c, i; a = c = 0; ps = qs715; pt = pd0->rfs; rc = 0; while (*pt++ = *ps++); /* A pair of expressions separated by a comma is evaluated left to right and the value of the left expression is discarded. */ i = 1; if( i++,i++,i++,i++,++i != 6 ){ if(pd0->flgd != 0) printf(s715er,1); rc = rc+1; } /* In contexts where the comma is given a special mean- ing, for example in a list of actual arguments to functions (sic) and lists of initializers, the comma operator as described in this section can only appear in parentheses; for example f( a, (t=3, t+2), c) has three arguments, the second of which has the value 5. */ if(s715f(a, (t=3, t+2), c) != 5){ if(pd0->flgd != 0) printf(s715er,2); rc = rc+2; } return rc; } s715f(x,y,z) int x, y, z; { return y; } /********************************************************************************************* the main loop that launches the sections *********************************************************************************************/ #ifndef NO_TYPELESS_STRUCT_PTR int section(int j,struct* pd0){ #else int section(int j,void* pd0){ #endif switch(j){ /*case 0: return s26(pd0);*/ case 0: return s715(pd0); } } #define cq_sections 1 /* C REFERENCE MANUAL (main) */ #ifndef NO_OLD_FUNC_DECL main(n,args) int n; char **args; { #else int main(int n,char **args) { #endif int j; static struct defs d0, *pd0; d0.flgs = 1; /* These flags dictate */ d0.flgm = 1; /* the verbosity of */ d0.flgd = 1; /* the program. */ d0.flgl = 1; pd0 = &d0; for (j=0; j<cq_sections; j++) { d0.rrc=section(j,pd0); d0.crc=d0.crc+d0.rrc; if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); } if(d0.crc == 0) printf("\nNo errors detected.\n"); else printf("\nFailed.\n"); return d0.crc; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/cq72.c���������������������������������������������������������������������������0000664�0000000�0000000�00000023637�13473601511�0014701�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! C-Manual Chapter 7.2: Unary Operators !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include "common.h" struct defs { int cbits; /* No. of bits per char */ int ibits; /* int */ int sbits; /* short */ int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ }; int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ #define CQ26_INCLUDED /* section s26, which pokes around at the hardware trying to figure out the characteristics of the machine that it is running on, saves information that is subsequently used by sections s626, s72, and s757. If this program is to be broken up into smallish pieces, say for running on a microcomputer, take care to see that s26 is called before calling any of the latter three sections. */ /* 2.6 Hardware Characteristics */ #ifndef NO_OLD_FUNC_DECL s26(pd0) struct defs *pd0; { #else s26(struct defs *pd0) { #endif static char qs26[8] = "s26 "; char *ps, *pt; char c0, c1; #ifndef NO_FLOATS float temp, one, delta; double tempd, oned; #endif static char s[] = "%3d bits in %ss.\n"; static char s2[] = "%e is the least number that can be added to 1. (%s).\n"; ps = qs26; pt = pd0->rfs; while(*pt++ = *ps++); /* Here, we shake the machinery a little to see what falls out. First, we find out how many bits are in a char. */ pd0->cbits = 0; c0 = 0; c1 = 1; while(c0 != c1) { c1 = c1<<1; pd0->cbits = pd0->cbits+1; } /* That information lets us determine the size of everything else. */ pd0->ibits = pd0->cbits * sizeof(int); pd0->sbits = pd0->cbits * sizeof(short); pd0->lbits = pd0->cbits * sizeof(long); pd0->ubits = pd0->cbits * sizeof(unsigned); #ifndef NO_FLOATS pd0->fbits = pd0->cbits * sizeof(float); pd0->dbits = pd0->cbits * sizeof(double); #endif /* We have now almost reconstructed the table in section 2.6, the exception being the range of the floating point hardware. Now there are just so many ways to conjure up a floating point representation system that it's damned near impossible to guess what's going on by writing a program to interpret bit patterns. Further, the information isn't all that useful, if we consider the fact that machines that won't handle numbers between 10**30 and 10**-30 are very hard to find, and that people playing with numbers outside that range have a lot more to worry about than just the capacity of the characteristic. A much more useful measure is the precision, which can be ex- pressed in terms of the smallest number that can be added to 1. without loss of significance. We calculate that here, for float and double. */ #ifndef NO_FLOATS one = 1.; delta = 1.; temp = 0.; while(temp != one) { temp = one+delta; delta = delta/2.; } pd0->fprec = delta * 4.; oned = 1.; delta = 1.; tempd = 0.; while(tempd != oned) { tempd = oned+delta; delta = delta/2.; } pd0->dprec = delta * 4.; #endif /* Now, if anyone's interested, we publish the results. */ #ifndef CQ26_INCLUDED if(pd0->flgm != 0) { printf(s,pd0->cbits,"char"); printf(s,pd0->ibits,"int"); printf(s,pd0->sbits,"short"); printf(s,pd0->lbits,"long"); printf(s,pd0->ubits,"unsigned"); printf(s,pd0->fbits,"float"); printf(s,pd0->dbits,"double"); #ifndef NO_FLOATS printf(s2,pd0->fprec,"float"); printf(s2,pd0->dprec,"double"); #else printf("NO_FLOATS\n"); #endif } #endif /* Since we are only exploring and perhaps reporting, but not testing any features, we cannot return an error code. */ return 0; } #ifndef NO_OLD_FUNC_DECL s72(pd0) /* 7.2 Unary operators */ struct defs *pd0; { #else int s72(struct defs *pd0){ #endif static char s72er[] = "s72,er%d\n"; static char qs72[8] = "s72 "; int rc; char *ps, *pt; int k, j, i, lrc; char c; short s; long l; unsigned u; #ifndef NO_FLOATS double d; float f; #else signed d; signed f; #endif ps = qs72; pt = pd0->rfs; rc = 0; while (*pt++ = *ps++); /* The *, denoting indirection, and the &, denoting a pointer, are duals of each other, and ought to behave as such... */ k = 2; if(*&*&k != 2){ rc = rc+1; printf(s72er,1); } /* The unary minus has the conventional meaning. */ if(k+(-k) != 0){ rc = rc+2; printf(s72er,2); } /* The negation operator (!) has been thoroughly checked out, perhaps more thoroughly than any of the others. The ~ oper- ator gets us a ones complement. */ k = 0; for(j=0;j<pd0->ibits;j++) k = (k<<1)|1; if(~k != 0){ rc = rc+4; printf(s72er,4); } /* Now we look at the ++ and -- operators, which can be used in either prefix or suffix form. With side effects they're loaded. */ k = 5; if( ++k != 6 || --k != 5 || k++ != 5 || k-- != 6 || k != 5 ){ rc = rc+8; printf(s72er,8); } /* An expression preceded by the parenthesised name of a data type causes conversion of the value of the expression to the named type. This construction is called a cast. Here, we check to see that all of the possible casts and their simple combinations are accepted by the compiler, and that they all produce a correct result for this sample of size one. */ c = 26; l = 26; s = 26; u = 26; i = 26; #ifndef NO_FLOATS f = 26.; d = 26.; #else f = 26; d = 26; #endif lrc = 0; if( (char)s != 26 || (char)i != 26 || (char)l != 26 || (char)u != 26 || (char)f != 26 || (char)d != 26 ) lrc = lrc+1; if( (short)c != 26 || (short)i != 26 || (short)l != 26 || (short)u != 26 || (short)f != 26 || (short)d != 26) lrc = lrc+2; if( (int)c != 26 || (int)s != 26 || (int)l != 26 || (int)u != 26 || (int)f != 26 || (int)d != 26 ) lrc = lrc+4; if( (long)c != 26 || (long)s != 26 || (long)i != 26 || (long)u != 26 || (long)f != 26 || (long)d != 26 ) lrc = lrc+8; if( (unsigned)c != 26 || (unsigned)s != 26 || (unsigned)i != 26 || (unsigned)l != 26 || (unsigned)f != 26 || (unsigned)d != 26 ) lrc = lrc+16; #ifndef NO_FLOATS if( (float)c != 26. || (float)s != 26. || (float)i != 26. || (float)l != 26. || (float)u != 26. || (float)d != 26. ) lrc = lrc+32; if( (double)c != 26. || (double)s != 26. || (double)i != 26. || (double)l != 26. || (double)u != 26. || (double)f != 26. ) lrc = lrc+64; #endif if(lrc != 0){ rc = rc+16; printf(s72er,16); } /* The sizeof operator has been tested previously. */ return rc; } /********************************************************************************************* the main loop that launches the sections *********************************************************************************************/ #ifndef NO_TYPELESS_STRUCT_PTR int section(int j,struct* pd0){ #else int section(int j,void* pd0){ #endif switch(j){ case 0: return s26(pd0); case 1: return s72(pd0); } } #define cq_sections 2 /* C REFERENCE MANUAL (main) */ #ifndef NO_OLD_FUNC_DECL main(n,args) int n; char **args; { #else int main(int n,char **args) { #endif int j; static struct defs d0, *pd0; d0.flgs = 1; /* These flags dictate */ d0.flgm = 1; /* the verbosity of */ d0.flgd = 1; /* the program. */ d0.flgl = 1; pd0 = &d0; for (j=0; j<cq_sections; j++) { d0.rrc=section(j,pd0); d0.crc=d0.crc+d0.rrc; if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); } if(d0.crc == 0) printf("\nNo errors detected.\n"); else printf("\nFailed.\n"); return d0.crc; } �������������������������������������������������������������������������������������������������cc65-2.18/test/val/cq757.c��������������������������������������������������������������������������0000664�0000000�0000000�00000023355�13473601511�0014770�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! C-Manual Chapter 7.5: Shift operators, 7.6 Relational operators, 7.7 Equality operator !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include "common.h" struct defs { int cbits; /* No. of bits per char */ int ibits; /* int */ int sbits; /* short */ int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ }; int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ #define CQ26_INCLUDED /* section s26, which pokes around at the hardware trying to figure out the characteristics of the machine that it is running on, saves information that is subsequently used by sections s626, s72, and s757. If this program is to be broken up into smallish pieces, say for running on a microcomputer, take care to see that s26 is called before calling any of the latter three sections. */ /* 2.6 Hardware Characteristics */ #ifndef NO_OLD_FUNC_DECL s26(pd0) struct defs *pd0; { #else s26(struct defs *pd0) { #endif static char qs26[8] = "s26 "; char *ps, *pt; char c0, c1; #ifndef NO_FLOATS float temp, one, delta; double tempd, oned; #endif static char s[] = "%3d bits in %ss.\n"; static char s2[] = "%e is the least number that can be added to 1. (%s).\n"; ps = qs26; pt = pd0->rfs; while(*pt++ = *ps++); /* Here, we shake the machinery a little to see what falls out. First, we find out how many bits are in a char. */ pd0->cbits = 0; c0 = 0; c1 = 1; while(c0 != c1) { c1 = c1<<1; pd0->cbits = pd0->cbits+1; } /* That information lets us determine the size of everything else. */ pd0->ibits = pd0->cbits * sizeof(int); pd0->sbits = pd0->cbits * sizeof(short); pd0->lbits = pd0->cbits * sizeof(long); pd0->ubits = pd0->cbits * sizeof(unsigned); #ifndef NO_FLOATS pd0->fbits = pd0->cbits * sizeof(float); pd0->dbits = pd0->cbits * sizeof(double); #endif /* We have now almost reconstructed the table in section 2.6, the exception being the range of the floating point hardware. Now there are just so many ways to conjure up a floating point representation system that it's damned near impossible to guess what's going on by writing a program to interpret bit patterns. Further, the information isn't all that useful, if we consider the fact that machines that won't handle numbers between 10**30 and 10**-30 are very hard to find, and that people playing with numbers outside that range have a lot more to worry about than just the capacity of the characteristic. A much more useful measure is the precision, which can be ex- pressed in terms of the smallest number that can be added to 1. without loss of significance. We calculate that here, for float and double. */ #ifndef NO_FLOATS one = 1.; delta = 1.; temp = 0.; while(temp != one) { temp = one+delta; delta = delta/2.; } pd0->fprec = delta * 4.; oned = 1.; delta = 1.; tempd = 0.; while(tempd != oned) { tempd = oned+delta; delta = delta/2.; } pd0->dprec = delta * 4.; #endif /* Now, if anyone's interested, we publish the results. */ #ifndef CQ26_INCLUDED if(pd0->flgm != 0) { printf(s,pd0->cbits,"char"); printf(s,pd0->ibits,"int"); printf(s,pd0->sbits,"short"); printf(s,pd0->lbits,"long"); printf(s,pd0->ubits,"unsigned"); printf(s,pd0->fbits,"float"); printf(s,pd0->dbits,"double"); #ifndef NO_FLOATS printf(s2,pd0->fprec,"float"); printf(s2,pd0->dprec,"double"); #else printf("NO_FLOATS\n"); #endif } #endif /* Since we are only exploring and perhaps reporting, but not testing any features, we cannot return an error code. */ return 0; } #ifndef NO_OLD_FUNC_DECL s757(pd0) /* 7.5 Shift operators */ /* 7.6 Relational operators */ /* 7.7 Equality operator */ struct defs *pd0; { #else int s757(struct defs *pd0){ #endif static char s757er[] = "s757,er%d\n"; static char qs757[8] = "s757 "; int rc; char *ps, *pt; int t,lrc,k,j,a,b,c,d,x[16],*p; unsigned rs, ls, rt, lt; ps = qs757; pt = pd0->rfs; rc = 0; while (*pt++ = *ps++); /* The shift operators << and >> group left-to-right. */ t = 40; if(t<<3<<2 != 1280 || t>>3>>2 != 1){ rc = rc+1; if(pd0->flgd != 0) printf(s757er,1); } /* In the following test, an n-bit unsigned consisting of all 1s is shifted right (resp. left) k bits, 0<=k<n. We expect to find k 0s followed by n-k 1s (resp. n-k 1s followed by k 0s). If not, we complain. */ lrc = 0; for(k=0; k<pd0->ubits; k++){ rs = 1; ls = rs<<(pd0->ubits-1); rt = 0; lt = ~rt>>k; rt = ~rt<<k; for(j=0; j<pd0->ubits;j++){ if((j<k) != ((rs&rt) == 0) || (j<k) != ((ls<) == 0)) lrc = 1; rs = rs<<1; ls = ls>>1; } } if(lrc != 0){ rc = rc+2; if(pd0->flgd != 0) printf(s757er,2); } /* The relational operators group left-to-right, but this fact is not very useful; a<b<c does not mean what it seems to... */ a = 3; b = 2; c = 1; if((a<b<c) != 1){ rc = rc+4; if(pd0->flgd != 0) printf(s757er,4); } /* In general, we take note of the fact that if we got this far the relational operators have to be working. We test only that two pointers may be compared; the result depends on the relative locations in the address space of the pointed-to objects. */ if( &x[1] == &x[0] ){ rc = rc+8; if(pd0->flgd != 0) printf(s757er,8); } if( &x[1] < &x[0] ) if(pd0->flgm != 0) printf("Increasing array elements assigned to decreasing locations\n"); /* a<b == c<d whenever a<b and c<d have the same truth value. */ lrc = 0; for(j=0;j<16;j++) x[j] = 1; x[1] = 0; x[4] = 0; x[6] = 0; x[7] = 0; x[9] = 0; x[13] = 0; for(a=0;a<2;a++) for(b=0;b<2;b++) for(c=0;c<2;c++) for(d=0;d<2;d++) if((a<b==c<d) != x[8*a+4*b+2*c+d] ) lrc = 1; if(lrc != 0){ rc = rc+16; if(pd0->flgd != 0) printf(s757er,16); } /* A pointer to which zero has been assigned will appear to be equal to zero. */ p = 0; if(p != 0){ rc = rc+32; if(pd0->flgd != 0) printf(s757er,32); } return rc; } /********************************************************************************************* the main loop that launches the sections *********************************************************************************************/ #ifndef NO_TYPELESS_STRUCT_PTR int section(int j,struct* pd0){ #else int section(int j,void* pd0){ #endif switch(j){ case 0: return s26(pd0); case 1: return s757(pd0); } } #define cq_sections 2 /* C REFERENCE MANUAL (main) */ #ifndef NO_OLD_FUNC_DECL main(n,args) int n; char **args; { #else int main(int n,char **args) { #endif int j; static struct defs d0, *pd0; d0.flgs = 1; /* These flags dictate */ d0.flgm = 1; /* the verbosity of */ d0.flgd = 1; /* the program. */ d0.flgl = 1; pd0 = &d0; for (j=0; j<cq_sections; j++) { d0.rrc=section(j,pd0); d0.crc=d0.crc+d0.rrc; if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); } if(d0.crc == 0) printf("\nNo errors detected.\n"); else printf("\nFailed.\n"); return d0.crc; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/cq7813.c�������������������������������������������������������������������������0000664�0000000�0000000�00000033206�13473601511�0015044�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! C-Manual Chapter 7.8: Bitwise AND operator, 7.9 Bitwise OR operator, 7.10 Bitwise exclusive OR operator, 7.11 Logical AND operator, 7.12 Logical OR operator, 7.13 Conditional operator !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include "common.h" struct defs { int cbits; /* No. of bits per char */ int ibits; /* int */ int sbits; /* short */ int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ }; int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ #ifndef NO_OLD_FUNC_DECL s7813(pd0) /* 7.8 Bitwise AND operator 7.9 Bitwise OR operator 7.10 Bitwise exclusive OR operator 7.11 Logical AND operator 7.12 Logical OR operator 7.13 Conditional operator */ struct defs *pd0; { #else int s7813(struct defs *pd0){ #endif register int prlc, lrc; int i, j, r, zero, one; static char fl[] = "Local error %d.\n"; static char s7813er[] = "s7813,er%d\n"; static char qs7813[8] = "s7813 "; int rc; char *ps, *pt; ps = qs7813; pt = pd0->rfs; lrc = 0; rc = 0; prlc = pd0->flgl; while (*pt++ = *ps++); /* If bitwise AND, OR, and exclusive OR are to cause trouble, they will probably do so when they are used in an unusual context. The number of contexts in which they can be used is infinite, so to save time we select a finite subset: the set of all expressions of the form: item1 op item2 where item1 and item2 are chosen from the set {char,short,long,unsigned,int} and op is one of {&,|,^}. We will use 12 and 10 as values for the items, as these values will fit into all data types on just about any imaginable machine, and the results after performing the bitwise operations on them are distinct for each operation, i.e., 12 | 10 -> 1100 | 1010 -> 1110 -> 14 12 ^ 10 -> 1100 ^ 1010 -> 0110 -> 6 12 & 10 -> 1100 & 1010 -> 1000 -> 8 There are 75 such combinations: */ if(((char)12 & (char)10) != 8) {lrc = 1; if(prlc) printf(fl,lrc);} if(((char)12 | (char)10) != 14) {lrc = 2; if(prlc) printf(fl,lrc);} if(((char)12 ^ (char)10) != 6) {lrc = 3; if(prlc) printf(fl,lrc);} if(((char)12 & (short)10) != 8) {lrc = 4; if(prlc) printf(fl,lrc);} if(((char)12 | (short)10) != 14) {lrc = 5; if(prlc) printf(fl,lrc);} if(((char)12 ^ (short)10) != 6) {lrc = 6; if(prlc) printf(fl,lrc);} if(((char)12 & (long)10) != 8) {lrc = 7; if(prlc) printf(fl,lrc);} if(((char)12 | (long)10) != 14) {lrc = 8; if(prlc) printf(fl,lrc);} if(((char)12 ^ (long)10) != 6) {lrc = 9; if(prlc) printf(fl,lrc);} if(((char)12 & (unsigned)10) != 8) {lrc = 10; if(prlc) printf(fl,lrc);} if(((char)12 | (unsigned)10) != 14) {lrc = 11; if(prlc) printf(fl,lrc);} if(((char)12 ^ (unsigned)10) != 6) {lrc = 12; if(prlc) printf(fl,lrc);} if(((char)12 & (int)10) != 8) {lrc = 13; if(prlc) printf(fl,lrc);} if(((char)12 | (int)10) != 14) {lrc = 14; if(prlc) printf(fl,lrc);} if(((char)12 ^ (int)10) != 6) {lrc = 15; if(prlc) printf(fl,lrc);} if(((short)12 & (char)10) != 8) {lrc = 16; if(prlc) printf(fl,lrc);} if(((short)12 | (char)10) != 14) {lrc = 17; if(prlc) printf(fl,lrc);} if(((short)12 ^ (char)10) != 6) {lrc = 18; if(prlc) printf(fl,lrc);} if(((short)12 & (short)10) != 8) {lrc = 16; if(prlc) printf(fl,lrc);} if(((short)12 | (short)10) != 14) {lrc = 20; if(prlc) printf(fl,lrc);} if(((short)12 ^ (short)10) != 6) {lrc = 21; if(prlc) printf(fl,lrc);} if(((short)12 & (long)10) != 8) {lrc = 22; if(prlc) printf(fl,lrc);} if(((short)12 | (long)10) != 14) {lrc = 23; if(prlc) printf(fl,lrc);} if(((short)12 ^ (long)10) != 6) {lrc = 24; if(prlc) printf(fl,lrc);} if(((short)12 & (unsigned)10) != 8) {lrc = 25; if(prlc) printf(fl,lrc);} if(((short)12 | (unsigned)10) != 14) {lrc = 26; if(prlc) printf(fl,lrc);} if(((short)12 ^ (unsigned)10) != 6) {lrc = 27; if(prlc) printf(fl,lrc);} if(((short)12 & (int)10) != 8) {lrc = 28; if(prlc) printf(fl,lrc);} if(((short)12 | (int)10) != 14) {lrc = 26; if(prlc) printf(fl,lrc);} if(((short)12 ^ (int)10) != 6) {lrc = 30; if(prlc) printf(fl,lrc);} if(((long)12 & (char)10) != 8) {lrc = 31; if(prlc) printf(fl,lrc);} if(((long)12 | (char)10) != 14) {lrc = 32; if(prlc) printf(fl,lrc);} if(((long)12 ^ (char)10) != 6) {lrc = 33; if(prlc) printf(fl,lrc);} if(((long)12 & (short)10) != 8) {lrc = 34; if(prlc) printf(fl,lrc);} if(((long)12 | (short)10) != 14) {lrc = 35; if(prlc) printf(fl,lrc);} if(((long)12 ^ (short)10) != 6) {lrc = 36; if(prlc) printf(fl,lrc);} if(((long)12 & (long)10) != 8) {lrc = 37; if(prlc) printf(fl,lrc);} if(((long)12 | (long)10) != 14) {lrc = 38; if(prlc) printf(fl,lrc);} if(((long)12 ^ (long)10) != 6) {lrc = 39; if(prlc) printf(fl,lrc);} if(((long)12 & (unsigned)10) != 8) {lrc = 40; if(prlc) printf(fl,lrc);} if(((long)12 | (unsigned)10) != 14) {lrc = 41; if(prlc) printf(fl,lrc);} if(((long)12 ^ (unsigned)10) != 6) {lrc = 42; if(prlc) printf(fl,lrc);} if(((long)12 & (int)10) != 8) {lrc = 43; if(prlc) printf(fl,lrc);} if(((long)12 | (int)10) != 14) {lrc = 44; if(prlc) printf(fl,lrc);} if(((long)12 ^ (int)10) != 6) {lrc = 45; if(prlc) printf(fl,lrc);} if(((unsigned)12 & (char)10) != 8) {lrc = 46; if(prlc) printf(fl,lrc);} if(((unsigned)12 | (char)10) != 14) {lrc = 47; if(prlc) printf(fl,lrc);} if(((unsigned)12 ^ (char)10) != 6) {lrc = 48; if(prlc) printf(fl,lrc);} if(((unsigned)12 & (short)10) != 8) {lrc = 49; if(prlc) printf(fl,lrc);} if(((unsigned)12 | (short)10) != 14) {lrc = 50; if(prlc) printf(fl,lrc);} if(((unsigned)12 ^ (short)10) != 6) {lrc = 51; if(prlc) printf(fl,lrc);} if(((unsigned)12 & (long)10) != 8) {lrc = 52; if(prlc) printf(fl,lrc);} if(((unsigned)12 | (long)10) != 14) {lrc = 53; if(prlc) printf(fl,lrc);} if(((unsigned)12 ^ (long)10) != 6) {lrc = 54; if(prlc) printf(fl,lrc);} if(((unsigned)12 & (unsigned)10) != 8) {lrc = 55; if(prlc) printf(fl,lrc);} if(((unsigned)12 | (unsigned)10) != 14) {lrc = 56; if(prlc) printf(fl,lrc);} if(((unsigned)12 ^ (unsigned)10) != 6) {lrc = 57; if(prlc) printf(fl,lrc);} if(((unsigned)12 & (int)10) != 8) {lrc = 58; if(prlc) printf(fl,lrc);} if(((unsigned)12 | (int)10) != 14) {lrc = 56; if(prlc) printf(fl,lrc);} if(((unsigned)12 ^ (int)10) != 6) {lrc = 60; if(prlc) printf(fl,lrc);} if(((int)12 & (char)10) != 8) {lrc = 61; if(prlc) printf(fl,lrc);} if(((int)12 | (char)10) != 14) {lrc = 62; if(prlc) printf(fl,lrc);} if(((int)12 ^ (char)10) != 6) {lrc = 63; if(prlc) printf(fl,lrc);} if(((int)12 & (short)10) != 8) {lrc = 64; if(prlc) printf(fl,lrc);} if(((int)12 | (short)10) != 14) {lrc = 65; if(prlc) printf(fl,lrc);} if(((int)12 ^ (short)10) != 6) {lrc = 66; if(prlc) printf(fl,lrc);} if(((int)12 & (long)10) != 8) {lrc = 67; if(prlc) printf(fl,lrc);} if(((int)12 | (long)10) != 14) {lrc = 68; if(prlc) printf(fl,lrc);} if(((int)12 ^ (long)10) != 6) {lrc = 69; if(prlc) printf(fl,lrc);} if(((int)12 & (unsigned)10) != 8) {lrc = 70; if(prlc) printf(fl,lrc);} if(((int)12 | (unsigned)10) != 14) {lrc = 71; if(prlc) printf(fl,lrc);} if(((int)12 ^ (unsigned)10) != 6) {lrc = 72; if(prlc) printf(fl,lrc);} if(((int)12 & (int)10) != 8) {lrc = 73; if(prlc) printf(fl,lrc);} if(((int)12 | (int)10) != 14) {lrc = 74; if(prlc) printf(fl,lrc);} if(((int)12 ^ (int)10) != 6) {lrc = 75; if(prlc) printf(fl,lrc);} if(lrc != 0){ if(pd0->flgd != 0) printf(s7813er,1); rc = rc+1; } /* The && operator groups left to right. It returns 1 if both of the operands are nonzero; 0 otherwise. It guarantees left to right evaluation; moreover, the second operand is not evaluated if the value of the first operand is 0. */ lrc = 0; i = j = 0; r = i++ && j++; if(i!=1) {lrc = 1; if(prlc) printf(fl,lrc);} if(j!=0) {lrc = 2; if(prlc) printf(fl,lrc);} if(r!=0) {lrc = 3; if(prlc) printf(fl,lrc);} r = i && j++; if(i!=1) {lrc = 4; if(prlc) printf(fl,lrc);} if(j!=1) {lrc = 5; if(prlc) printf(fl,lrc);} if(r!=0) {lrc = 6; if(prlc) printf(fl,lrc);} r = i-- && j; if(i!=0) {lrc = 7; if(prlc) printf(fl,lrc);} if(j!=1) {lrc = 8; if(prlc) printf(fl,lrc);} if(r!=1) {lrc = 9; if(prlc) printf(fl,lrc);} r = i && j--; if(i!=0) {lrc = 10; if(prlc) printf(fl,lrc);} if(j!=1) {lrc = 11; if(prlc) printf(fl,lrc);} if(r!=0) {lrc = 12; if(prlc) printf(fl,lrc);} if(lrc!=0){ if(pd0->flgd != 0) printf(s7813er,2); rc = rc+2; } /* The || operator groups left to right. It returns 1 if either of its operands is nonzero; 0 otherwise. It guarantees left to right evaluation; moreover, the second operand is not evaluated if the value of the first operand is nonzero. */ lrc = 0; i = j = 0; r = i++ || j; if(i!=1) {lrc = 1; if(prlc) printf(fl,lrc);} if(j!=0) {lrc = 2; if(prlc) printf(fl,lrc);} if(r!=0) {lrc = 3; if(prlc) printf(fl,lrc);} r = j++ || i; if(i!=1) {lrc = 4; if(prlc) printf(fl,lrc);} if(j!=1) {lrc = 5; if(prlc) printf(fl,lrc);} if(r!=1) {lrc = 6; if(prlc) printf(fl,lrc);} r = i-- || j--; if(i!=0) {lrc = 7; if(prlc) printf(fl,lrc);} if(j!=1) {lrc = 8; if(prlc) printf(fl,lrc);} if(r!=1) {lrc = 9; if(prlc) printf(fl,lrc);} r = i || j--; if(i!=0) {lrc = 10; if(prlc) printf(fl,lrc);} if(j!=0) {lrc = 11; if(prlc) printf(fl,lrc);} if(r!=1) {lrc = 12; if(prlc) printf(fl,lrc);} if(lrc!=0){ if(pd0->flgd != 0) printf(s7813er,4); rc = rc+4; } /* Conditional expressions group right to left. */ i = j = 0; zero = 0; one = 1; r = one?zero:one?i++:j++; if(r!=0 || i!=0 || j!=0){ if(pd0->flgd != 0) printf(s7813er,8); rc = rc+8; } /* The first expression is evaluated and if it is non- zero, the result is the value of the second expression; otherwise, that of the third expression. */ if((one?zero:1) != 0 || (zero?1:zero) != 0){ if(pd0->flgd != 0) printf(s7813er,16); rc = rc+16; } return rc; } /********************************************************************************************* the main loop that launches the sections *********************************************************************************************/ #ifndef NO_TYPELESS_STRUCT_PTR int section(int j,struct* pd0){ #else int section(int j,void* pd0){ #endif switch(j){ case 0: return s7813(pd0); } } #define cq_sections 1 /* C REFERENCE MANUAL (main) */ #ifndef NO_OLD_FUNC_DECL main(n,args) int n; char **args; { #else int main(int n,char **args) { #endif int j; static struct defs d0, *pd0; d0.flgs = 1; /* These flags dictate */ d0.flgm = 1; /* the verbosity of */ d0.flgd = 1; /* the program. */ d0.flgl = 1; pd0 = &d0; for (j=0; j<cq_sections; j++) { d0.rrc=section(j,pd0); d0.crc=d0.crc+d0.rrc; if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); } if(d0.crc == 0) printf("\nNo errors detected.\n"); else printf("\nFailed.\n"); return d0.crc; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/cq81.c���������������������������������������������������������������������������0000664�0000000�0000000�00000047315�13473601511�0014700�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! C-Manual Chapter 8.1: storage class specifiers !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include "common.h" struct defs { int cbits; /* No. of bits per char */ int ibits; /* int */ int sbits; /* short */ int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ }; int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ #ifdef NO_IMPLICIT_FUNC_PROTOTYPES regc(); regp(); regi(); #endif #ifndef NO_OLD_FUNC_DECL s81(pd0) /* 8.1 Storage Class Specifiers */ struct defs *pd0; #else int s81(struct defs *pd0) #endif { static char s81er[] = "s81,er%d\n"; static char qs81[8] = "s81 "; char *ps, *pt; int k, rc, j, crc, prc, irc; register char rchar; char nrchar; register int *rptr; int *nrptr; register int rint; int nrint; static char badtest[] = "Register count for %s is unreliable.\n"; static char goodtest[] = "%d registers assigned to %s variables.\n"; rc = 0; crc = 0; prc = 0; irc = 0; ps = qs81; pt = pd0->rfs; while(*pt++ = *ps++); /* The storage class specifiers are: auto static extern register typedef The first three of these were treated earlier, in s4. The last will be checked in s88. "Register" remains. There are three flavors of register, viz., char, int and pointer. We wish first to ascertain that the representations as register are consistent with the corresponding nonregister representations. */ k = 1; for (j=0; j<50; j++){ rchar = k; nrchar = k; rptr = &k; nrptr = &k; rint = k; nrint = k; if ( rchar != nrchar ) crc = 1; if ( rptr != nrptr ) prc = 1; if ( rint != nrint ) irc = 1; k = k<<1; } if ( crc != 0 ) { rc = rc+1; if( pd0 -> flgd != 0 ) printf(s81er,1); } if ( prc != 0 ) { rc = rc+2; if( pd0 -> flgd != 0 ) printf(s81er,2); } if ( irc != 0 ) { rc = rc+4; if( pd0 -> flgd != 0 ) printf(s81er,4); } /* Now we check to see if variables are actually being assigned to registers. */ k = regc(); if ( pd0->flgm != 0 ) { if ( k < 0 ) printf(badtest,"char"); else printf(goodtest,k,"char"); } k = regp(); if ( pd0->flgm != 0 ) { if ( k<0 ) printf(badtest,"pointer"); else printf(goodtest,k,"pointer"); } k = regi(); if ( pd0->flgm != 0 ) { if ( k<0 ) printf(badtest,"int"); else printf(goodtest,k,"int"); } return rc; } regc() { /* char to register assignment */ /* Testing a variable whose storage class has been spec- ified as "register" is somewhat tricky, but it can be done in a fairly reliable fashion by taking advantage of our knowledge of the ways in which compilers operate. If we declare a collection of vari- ables of the same storage class, we would expect that, when storage for these variables is actually allocated, the variables will be bunched together and ordered according to one of the following criteria: (a) the order in which they were defined. (b) the order in which they are used. (c) alphabetically. (d) the order in which they appear in the compiler's symbol table. (e) some other way. Hence, if we define a sequence of variables in close alpha- betical order, and use them in the same order in which we define them, we would expect the differences between the addresses of successive variables to be constant, except in case (d) where the symbol table is a hash table, or in case (e). If a subsequence in the middle of this sequence is selected, and for this subsequence, every other variable is specified to be "register", and address differences are taken between adjacent nonregister variables, we would still expect to find constant differences if the "register" vari- ables were actually assigned to registers, and some other diff- erences if they were not. Specifically, if we had N variables specified as "register" of which the first n were actually ass- igned to registers, we would expect the sequence of differences to consist of a number of occurrences of some number, followed by N-n occurrences of some other number, followed by several occurr- ences of the first number. If we get a sequence like this, we can determine, by simple subtraction, how many (if any) variables are being assigned to registers. If we get some other sequence, we know that the test is invalid. */ char r00; char r01; char r02; char r03; register char r04; char r05; register char r06; char r07; register char r08; char r09; register char r10; char r11; register char r12; char r13; register char r14; char r15; register char r16; char r17; register char r18; char r19; register char r20; char r21; register char r22; char r23; register char r24; char r25; register char r26; char r27; register char r28; char r29; register char r30; char r31; register char r32; char r33; register char r34; char r35; char r36; char r37; char r38; int s, n1, n2, nr, j, d[22]; r00 = 0; r01 = 1; r02 = 2; r03 = 3; r04 = 4; r05 = 5; r06 = 6; r07 = 7; r08 = 8; r09 = 9; r10 = 10; r11 = 11; r12 = 12; r13 = 13; r14 = 14; r15 = 15; r16 = 16; r17 = 17; r18 = 18; r19 = 19; r20 = 20; r21 = 21; r22 = 22; r23 = 23; r24 = 24; r25 = 25; r26 = 26; r27 = 27; r28 = 28; r29 = 29; r30 = 30; r31 = 31; r32 = 32; r33 = 33; r34 = 34; r35 = 35; r36 = 36; r37 = 37; r38 = 38; d[0] = &r01 - &r00; d[1] = &r02 - &r01; d[2] = &r03 - &r02; d[3] = &r05 - &r03; d[4] = &r07 - &r05; d[5] = &r09 - &r07; d[6] = &r11 - &r09; d[7] = &r13 - &r11; d[8] = &r15 - &r13; d[9] = &r17 - &r15; d[10] = &r19 - &r17; d[11] = &r21 - &r19; d[12] = &r23 - &r21; d[13] = &r25 - &r23; d[14] = &r27 - &r25; d[15] = &r29 - &r27; d[16] = &r31 - &r29; d[17] = &r33 - &r31; d[18] = &r35 - &r33; d[19] = &r36 - &r35; d[20] = &r37 - &r36; d[21] = &r38 - &r37; /* The following FSM analyzes the string of differences. It accepts strings of the form a+b+a+ and returns 16 minus the number of bs, which is the number of variables that actually got into registers. Otherwise it signals rejection by returning -1., indicating that the test is unreliable. */ n1 = d[0]; s = 1; for (j=0; j<22; j++) switch (s) { case 1: if (d[j] != n1) { n2 = d[j]; s = 2; nr = 1; } break; case 2: if (d[j] == n1) { s = 3; break; } if (d[j] == n2) { nr = nr+1; break; } s = 4; break; case 3: if (d[j] != n1) s = 4; break; } ; if (s == 3) return 16-nr; else return -1; } regi() { /* int to register assignment */ /* Testing a variable whose storage class has been spec- ified as "register" is somewhat tricky, but it can be done in a fairly reliable fashion by taking advantage of our knowledge of the ways in which compilers operate. If we declare a collection of vari- ables of the same storage class, we would expect that, when storage for these variables is actually allocated, the variables will be bunched together and ordered according to one of the following criteria: (a) the order in which they were defined. (b) the order in which they are used. (c) alphabetically. (d) the order in which they appear in the compiler's symbol table. (e) some other way. Hence, if we define a sequence of variables in close alpha- betical order, and use them in the same order in which we define them, we would expect the differences between the addresses of successive variables to be constant, except in case (d) where the symbol table is a hash table, or in case (e). If a subsequence in the middle of this sequence is selected, and for this subsequence, every other variable is specified to be "register", and address differences are taken between adjacent nonregister variables, we would still expect to find constant differences if the "register" vari- ables were actually assigned to registers, and some other diff- erences if they were not. Specifically, if we had N variables specified as "register" of which the first n were actually ass- igned to registers, we would expect the sequence of differences to consist of a number of occurrences of some number, followed by N-n occurrences of some other number, followed by several occurr- ences of the first number. If we get a sequence like this, we can determine, by simple subtraction, how many (if any) variables are being assigned to registers. If we get some other sequence, we know that the test is invalid. */ int r00; int r01; int r02; int r03; register int r04; int r05; register int r06; int r07; register int r08; int r09; register int r10; int r11; register int r12; int r13; register int r14; int r15; register int r16; int r17; register int r18; int r19; register int r20; int r21; register int r22; int r23; register int r24; int r25; register int r26; int r27; register int r28; int r29; register int r30; int r31; register int r32; int r33; register int r34; int r35; int r36; int r37; int r38; int s, n1, n2, nr, j, d[22]; r00 = 0; r01 = 1; r02 = 2; r03 = 3; r04 = 4; r05 = 5; r06 = 6; r07 = 7; r08 = 8; r09 = 9; r10 = 10; r11 = 11; r12 = 12; r13 = 13; r14 = 14; r15 = 15; r16 = 16; r17 = 17; r18 = 18; r19 = 19; r20 = 20; r21 = 21; r22 = 22; r23 = 23; r24 = 24; r25 = 25; r26 = 26; r27 = 27; r28 = 28; r29 = 29; r30 = 30; r31 = 31; r32 = 32; r33 = 33; r34 = 34; r35 = 35; r36 = 36; r37 = 37; r38 = 38; d[0] = &r01 - &r00; d[1] = &r02 - &r01; d[2] = &r03 - &r02; d[3] = &r05 - &r03; d[4] = &r07 - &r05; d[5] = &r09 - &r07; d[6] = &r11 - &r09; d[7] = &r13 - &r11; d[8] = &r15 - &r13; d[9] = &r17 - &r15; d[10] = &r19 - &r17; d[11] = &r21 - &r19; d[12] = &r23 - &r21; d[13] = &r25 - &r23; d[14] = &r27 - &r25; d[15] = &r29 - &r27; d[16] = &r31 - &r29; d[17] = &r33 - &r31; d[18] = &r35 - &r33; d[19] = &r36 - &r35; d[20] = &r37 - &r36; d[21] = &r38 - &r37; /* The following FSM analyzes the string of differences. It accepts strings of the form a+b+a+ and returns 16 minus the number of bs, which is the number of variables that actually got into registers. Otherwise it signals rejection by returning -1., indicating that the test is unreliable. */ n1 = d[0]; s = 1; for (j=0; j<22; j++) switch (s) { case 1: if (d[j] != n1) { n2 = d[j]; s = 2; nr = 1; } break; case 2: if (d[j] == n1) { s = 3; break; } if (d[j] == n2) { nr = nr+1; break; } s = 4; break; case 3: if (d[j] != n1) s = 4; break; } ; if (s == 3) return 16-nr; else return -1; } regp() { /* pointer to register assignment */ /* Testing a variable whose storage class has been spec- ified as "register" is somewhat tricky, but it can be done in a fairly reliable fashion by taking advantage of our knowledge of the ways in which compilers operate. If we declare a collection of vari- ables of the same storage class, we would expect that, when storage for these variables is actually allocated, the variables will be bunched together and ordered according to one of the following criteria: (a) the order in which they were defined. (b) the order in which they are used. (c) alphabetically. (d) the order in which they appear in the compiler's symbol table. (e) some other way. Hence, if we define a sequence of variables in close alpha- betical order, and use them in the same order in which we define them, we would expect the differences between the addresses of successive variables to be constant, except in case (d) where the symbol table is a hash table, or in case (e). If a subsequence in the middle of this sequence is selected, and for this subsequence, every other variable is specified to be "register", and address differences are taken between adjacent nonregister variables, we would still expect to find constant differences if the "register" vari- ables were actually assigned to registers, and some other diff- erences if they were not. Specifically, if we had N variables specified as "register" of which the first n were actually ass- igned to registers, we would expect the sequence of differences to consist of a number of occurrences of some number, followed by N-n occurrences of some other number, followed by several occurr- ences of the first number. If we get a sequence like this, we can determine, by simple subtraction, how many (if any) variables are being assigned to registers. If we get some other sequence, we know that the test is invalid. */ int *r00; int *r01; int *r02; int *r03; register int *r04; int *r05; register int *r06; int *r07; register int *r08; int *r09; register int *r10; int *r11; register int *r12; int *r13; register int *r14; int *r15; register int *r16; int *r17; register int *r18; int *r19; register int *r20; int *r21; register int *r22; int *r23; register int *r24; int *r25; register int *r26; int *r27; register int *r28; int *r29; register int *r30; int *r31; register int *r32; int *r33; register int *r34; int *r35; int *r36; int *r37; int *r38; int s, n1, n2, nr, j, d[22]; r00 = (int *)&r00; r01 = (int *)&r01; r02 = (int *)&r02; r03 = (int *)&r03; r04 = (int *)&r05; r05 = (int *)&r05; r06 = (int *)&r07; r07 = (int *)&r07; r08 = (int *)&r09; r09 = (int *)&r09; r10 = (int *)&r11; r11 = (int *)&r11; r12 = (int *)&r13; r13 = (int *)&r13; r14 = (int *)&r15; r15 = (int *)&r15; r16 = (int *)&r17; r17 = (int *)&r17; r18 = (int *)&r19; r19 = (int *)&r19; r20 = (int *)&r21; r21 = (int *)&r21; r22 = (int *)&r23; r23 = (int *)&r23; r24 = (int *)&r25; r25 = (int *)&r25; r26 = (int *)&r27; r27 = (int *)&r27; r28 = (int *)&r29; r29 = (int *)&r29; r30 = (int *)&r31; r31 = (int *)&r31; r32 = (int *)&r33; r33 = (int *)&r33; r34 = (int *)&r35; r35 = (int *)&r35; r36 = (int *)&r36; r37 = (int *)&r37; r38 = (int *)&r38; d[0] = &r01 - &r00; d[1] = &r02 - &r01; d[2] = &r03 - &r02; d[3] = &r05 - &r03; d[4] = &r07 - &r05; d[5] = &r09 - &r07; d[6] = &r11 - &r09; d[7] = &r13 - &r11; d[8] = &r15 - &r13; d[9] = &r17 - &r15; d[10] = &r19 - &r17; d[11] = &r21 - &r19; d[12] = &r23 - &r21; d[13] = &r25 - &r23; d[14] = &r27 - &r25; d[15] = &r29 - &r27; d[16] = &r31 - &r29; d[17] = &r33 - &r31; d[18] = &r35 - &r33; d[19] = &r36 - &r35; d[20] = &r37 - &r36; d[21] = &r38 - &r37; /* The following FSM analyzes the string of differences. It accepts strings of the form a+b+a+ and returns 16 minus the number of bs, which is the number of variables that actually got into registers. Otherwise it signals rejection by returning -1., indicating that the test is unreliable. */ n1 = d[0]; s = 1; for (j=0; j<22; j++) switch (s) { case 1: if (d[j] != n1) { n2 = d[j]; s = 2; nr = 1; } break; case 2: if (d[j] == n1) { s = 3; break; } if (d[j] == n2) { nr = nr+1; break; } s = 4; break; case 3: if (d[j] != n1) s = 4; break; } ; if (s == 3) return 16-nr; else return -1; } /********************************************************************************************* the main loop that launches the sections *********************************************************************************************/ #ifndef NO_TYPELESS_STRUCT_PTR int section(int j,struct* pd0){ #else int section(int j,void* pd0){ #endif switch(j){ case 0: return s81(pd0); } } #define cq_sections 1 /* C REFERENCE MANUAL (main) */ #ifndef NO_OLD_FUNC_DECL main(n,args) int n; char **args; { #else int main(int n,char **args) { #endif int j; static struct defs d0, *pd0; d0.flgs = 1; /* These flags dictate */ d0.flgm = 1; /* the verbosity of */ d0.flgd = 1; /* the program. */ d0.flgl = 1; pd0 = &d0; for (j=0; j<cq_sections; j++) { d0.rrc=section(j,pd0); d0.crc=d0.crc+d0.rrc; if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); } if(d0.crc == 0) printf("\nNo errors detected.\n"); else printf("\nFailed.\n"); return d0.crc; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/cq84.c���������������������������������������������������������������������������0000664�0000000�0000000�00000015214�13473601511�0014674�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! C-Manual Chapter 8.4: meaning of declarators !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include "common.h" struct defs { int cbits; /* No. of bits per char */ int ibits; /* int */ int sbits; /* short */ int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ }; int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ #ifdef NO_SLOPPY_EXTERN int *fip(int x); int array(int a[],int size,int start); int glork(int x); #endif #ifndef NO_OLD_FUNC_DECL s84(pd0) /* 8.4 Meaning of declarators */ struct defs *pd0; { #else int s84(struct defs *pd0){ #endif #ifndef NO_SLOPPY_EXTERN int *ip, i, *fip(), (*pfi)(), j, k, array(), glork(); #else int *ip, i, j, k,(*pfi)(); /* extern int *fip(), array(), glork(); int *fip(int x); int array(int a[],int size,int start); */ #endif static int x3d[3][5][7]; #ifndef NO_FLOATS float fa[17], *afp[17], sum; #else signed fa[17], *afp[17], sum; #endif static char s84er[] = "s84,er%d\n"; static char qs84[8] = "s84 "; int rc; char *ps, *pt; ps = qs84; pt = pd0->rfs; rc = 0; while (*pt++ = *ps++); /* The more common varieties of declarators have al- ready been touched upon, some more than others. It is useful to compare *fip() and (*pfi)(). */ ip = fip(3); if(*ip != 3){ if(pd0->flgd != 0) printf(s84er,1); rc = rc+1; } /* kludges */ #if defined(FORCE_POINTERS) | defined(NO_OLD_FUNC_DECL) if(glork(4) != 4){ if(pd0->flgd != 0) printf(s84er,2); rc = rc+2; } #else pfi = glork; if((*pfi)(4) != 4){ if(pd0->flgd != 0) printf(s84er,2); rc = rc+2; } #endif /* Float fa[17] declares an array of floating point numbers, and *afp[17] declares an array of pointers to floats. */ for(j=0; j<17; j++){ fa[j] = j; afp[j] = &fa[j]; } #ifndef NO_FLOATS sum = 0.; #else sum = 0; #endif for(j=0; j<17; j++) sum += *afp[j]; if(sum != 136){ if(pd0->flgd != 0) printf(s84er,4); rc = rc+4; } /* static int x3d[3][5][7] declares a static three dimensional array of integers, with rank 3x5x7. In complete detail, x3d is an array of three items; each item is an array of five arrays, and each of the latter arrays is an array of seven integers. Any of the expressions x3d, x3d[i], x3d[i][j], and x3d[i][j][k] may reasonably appear in an express- ion. The first three have type "array"; the last has type int. */ for (i=0; i<3; i++) for (j=0; j<5; j++) for (k=0; k<7; k++) x3d[i][j][k] = i*35+j*7+k; i = 1; j = 2; k = 3; /* kludges */ #if defined(FORCE_POINTERS) | defined(NO_OLD_FUNC_DECL) if( array((int*)x3d,105,0) +array((int*)x3d[i],35,35) #else if( array(x3d,105,0) +array(x3d[i],35,35) #endif +array(x3d[i][j],7,49) + x3d[i][j][k]-52){ if(pd0->flgd != 0) printf(s84er,8); rc = rc+8; } return rc; } #ifndef NO_OLD_FUNC_DECL array(a,size,start) int a[],size,start; #else int array(int a[],int size,int start) #endif { /* #ifndef NO_OLD_FUNC_DECL array(a,size,start) int a[], #else int array(int a[], #endif #ifdef NO_TYPELESS_INT int #endif #ifdef NO_TYPELESS_INT int #endif #ifndef NO_OLD_FUNC_DECL start; { #else start){ #endif */ int i; for(i=0; i<size; i++) if(a[i] != i+start) return 1; return 0; } #ifndef NO_OLD_FUNC_DECL int *fip(x) int x; { #else int *fip(int x){ #endif static int y; y = x; return &y; } #ifndef NO_OLD_FUNC_DECL glork(x) int x; { #else int glork(int x){ #endif return x;} /********************************************************************************************* the main loop that launches the sections *********************************************************************************************/ #ifndef NO_TYPELESS_STRUCT_PTR int section(int j,struct* pd0){ #else int section(int j,void* pd0){ #endif switch(j){ case 0: return s84(pd0); } } #define cq_sections 1 /* C REFERENCE MANUAL (main) */ #ifndef NO_OLD_FUNC_DECL main(n,args) int n; char **args; { #else int main(int n,char **args) { #endif int j; static struct defs d0, *pd0; d0.flgs = 1; /* These flags dictate */ d0.flgm = 1; /* the verbosity of */ d0.flgd = 1; /* the program. */ d0.flgl = 1; pd0 = &d0; for (j=0; j<cq_sections; j++) { d0.rrc=section(j,pd0); d0.crc=d0.crc+d0.rrc; if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); } if(d0.crc == 0) printf("\nNo errors detected.\n"); else printf("\nFailed.\n"); return d0.crc; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/cq85.c���������������������������������������������������������������������������0000664�0000000�0000000�00000017464�13473601511�0014706�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! C-Manual Chapter 8.5: Structure and Union declarations !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include "common.h" struct defs { int cbits; /* No. of bits per char */ int ibits; /* int */ int sbits; /* short */ int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ }; int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ #ifndef NO_OLD_FUNC_DECL s85(pd0) /* 8.5 Structure and union declarations */ struct defs *pd0; { #else int s85(struct defs *pd0){ #endif static char s85er[] = "s85,er%d\n"; static char qs85[8] = "s85 "; int rc; char *ps, *pt; struct tnode { char tword[20]; int count; struct tnode *left; struct tnode *right; }; struct tnode s1, s2, *sp; struct{ char cdummy; char c; } sc; struct{ char cdummy; short s; } ss; struct{ char cdummy; int i; } si; struct{ char cdummy; long l; } sl; struct{ char cdummy; unsigned u; } su; struct{ char cdummy; #ifndef NO_FLOATS float f; #else signed f; #endif } sf; struct{ char cdummy; #ifndef NO_FLOATS double d; #else signed d; #endif } sd; int diff[7], j; static char *type[] = { "char", "short", "int", "long", "unsigned", #ifdef NO_FLOATS "signed", "signed", #else "float", "double" #endif }; static char aln[] = " alignment: "; #ifndef NO_BITFIELDS struct{ int twobit:2; int :1; int threebit:3; int onebit:1; } s3; #else struct{ unsigned char twobit; unsigned char threebit; unsigned char onebit; } s3; #endif union{ char u1[30]; short u2[30]; int u3[30]; long u4[30]; unsigned u5[30]; #ifndef NO_FLOATS float u6[30]; double u7[30]; #else signed u6[30]; signed u7[30]; #endif } u0; ps = qs85; pt = pd0->rfs; rc = 0; while (*pt++ = *ps++); /* Within a structure, the objects declared have addresses which increase as their declarations are read left to right. */ if( (char *)&s1.count - &s1.tword[0] <= 0 ||(char *)&s1.left - (char *)&s1.count <= 0 ||(char *)&s1.right - (char *)&s1.left <= 0){ if(pd0->flgd != 0) printf(s85er,1); rc = rc+1; } /* Each non-field member of a structure begins on an addressing boundary appropriate to its type. */ diff[0] = &sc.c - &sc.cdummy; diff[1] = (char *)&ss.s - &ss.cdummy; diff[2] = (char *)&si.i - &si.cdummy; diff[3] = (char *)&sl.l - &sl.cdummy; diff[4] = (char *)&su.u - &su.cdummy; diff[5] = (char *)&sf.f - &sf.cdummy; diff[6] = (char *)&sd.d - &sd.cdummy; if(pd0->flgm != 0) for(j=0; j<7; j++) printf("%s%s%d\n",type[j],aln,diff[j]); /* Field specifications are highly implementation de- pendent. About the only thing we can do here is to check is that the compiler accepts the field constructs, and that they seem to work, after a fashion, at run time... */ s3.threebit = 7; s3.twobit = s3.threebit; s3.threebit = s3.twobit; if(s3.threebit != 3){ if(s3.threebit == -1){ if(pd0->flgm != 0) printf("Sign extension in fields\n"); } else{ #ifdef NO_BITFIELDS if(pd0->flgd != 0) printf("NO_BITFIELDS\n"); #else if(pd0->flgd != 0) printf(s85er,2); rc = rc+2; #endif } } s3.onebit = 1; if(s3.onebit != 1){ if(pd0->flgm != 0) printf("Be especially careful with 1-bit fields!\n"); } /* A union may be thought of as a structure all of whose members begin at offset 0 and whose size is sufficient to contain any of its members. */ if( (char *)u0.u1 - (char *)&u0 != 0 ||(char *)u0.u2 - (char *)&u0 != 0 ||(char *)u0.u3 - (char *)&u0 != 0 ||(char *)u0.u4 - (char *)&u0 != 0 ||(char *)u0.u5 - (char *)&u0 != 0 ||(char *)u0.u6 - (char *)&u0 != 0 ||(char *)u0.u7 - (char *)&u0 != 0){ if(pd0->flgd != 0) printf(s85er,4); rc = rc+4; } if( sizeof u0 < sizeof u0.u1 ||sizeof u0 < sizeof u0.u2 ||sizeof u0 < sizeof u0.u3 ||sizeof u0 < sizeof u0.u4 ||sizeof u0 < sizeof u0.u5 ||sizeof u0 < sizeof u0.u6 ||sizeof u0 < sizeof u0.u7){ if(pd0->flgd != 0) printf(s85er,8); rc = rc+8; } /* Finally, we check that the pointers work. */ s1.right = &s2; s2.tword[0] = 2; s1.right->tword[0] += 1; if(s2.tword[0] != 3){ if(pd0->flgd != 0) printf(s85er,16); rc = rc+16; } return rc; } #ifdef NO_LOCAL_PROTOTYPES int one(); #endif /********************************************************************************************* the main loop that launches the sections *********************************************************************************************/ #ifndef NO_TYPELESS_STRUCT_PTR int section(int j,struct* pd0){ #else int section(int j,void* pd0){ #endif switch(j){ case 0: return s85(pd0); } } #define cq_sections 1 /* C REFERENCE MANUAL (main) */ #ifndef NO_OLD_FUNC_DECL main(n,args) int n; char **args; { #else int main(int n,char **args) { #endif int j; static struct defs d0, *pd0; d0.flgs = 1; /* These flags dictate */ d0.flgm = 1; /* the verbosity of */ d0.flgd = 1; /* the program. */ d0.flgl = 1; pd0 = &d0; for (j=0; j<cq_sections; j++) { d0.rrc=section(j,pd0); d0.crc=d0.crc+d0.rrc; if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); } if(d0.crc == 0) printf("\nNo errors detected.\n"); else printf("\nFailed.\n"); return d0.crc; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/cq86.c���������������������������������������������������������������������������0000664�0000000�0000000�00000014312�13473601511�0014674�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! C-Manual Chapter 8.6: Initialization !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include "common.h" struct defs { int cbits; /* No. of bits per char */ int ibits; /* int */ int sbits; /* short */ int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ }; int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ #ifdef NO_LOCAL_PROTOTYPES int one(); #endif #ifndef NO_OLD_FUNC_DECL s86(pd0) /* 8.6 Initialization */ struct defs *pd0; { #else int s86(struct defs *pd0){ #endif static char s86er[] = "s86,er%d\n"; static char qs86[8] = "s86 "; int lrc, rc; char *ps, *pt; #ifndef NO_LOCAL_PROTOTYPES int one(); #endif int i, j, k; static int x[] = {1,3,5}; static int *pint = x+2; static int zero[10]; int *apint = pint-1; register int *rpint = apint+one(); #ifndef NO_FLOATS static float y0[] = {1,3,5,2,4,6,3,5,7,0,0,0}; static float y1[4][3] = { {1,3,5}, {2,4,6}, {3,5,7}, }; static float y2[4][3] = {1,3,5,2,4,6,3,5,7}; static float y3[4][3] = { {1},{2},{3},{4} }; #else static signed y0[] = {1,3,5,2,4,6,3,5,7,0,0,0}; static signed y1[4][3] = { {1,3,5}, {2,4,6}, {3,5,7}, }; #ifndef NO_SLOPPY_STRUCT_INIT static signed y2[4][3] = {1,3,5,2,4,6,3,5,7}; #else static signed y2[4][3] = {{1,3,5},{2,4,6},{3,5,7}}; #endif static signed y3[4][3] = { {1},{2},{3},{4} }; #endif ps = qs86; pt = pd0->rfs; rc = 0; while (*pt++ = *ps++); /* The expression in an initializer for a static or external variable must be a constant expression or an expression that reduces to the address of a pre- viously declared variable, possibly offset by a constant expression. */ if(*pint != 5){ if(pd0->flgd != 0) printf(s86er,1); rc = rc+1; } /* Automatic and register variables may be initialized by arbitrary expressions involving constants and previously declared variables and functions. */ if(*apint != 3){ if(pd0->flgd != 0) printf(s86er,2); rc = rc+2; } if(*rpint != 5){ if(pd0->flgd != 0) printf(s86er,4); rc = rc+4; } /* Static variables that are not initialized are guar- anteed to start off as zero. */ lrc = 0; for(j=0; j<10; j++) if(zero[j] != 0) lrc = 1; if(lrc != 0){ if(pd0->flgd != 0) printf(s86er,8); rc = rc+8; } /* y0, y1, and y2, as declared, should define and initialize identical arrays. */ lrc = 0; for(i=0; i<4; i++) for(j=0; j<3; j++){ k = 3*i+j; if( y1[i][j] != y2[i][j] ||y1[i][j] != y0[k]) lrc = 1; } if(lrc != 0){ if(pd0->flgd != 0) printf(s86er,16); rc = rc+16; } /* y3 initializes the first column of the array and leaves the rest zero. */ lrc = 0; for(j=0; j<4; j++) if(y3[j][0] != j+1) lrc = 1; if(lrc != 0){ if(pd0->flgd != 0) printf(s86er,32); rc = rc+32; } return rc; } #ifndef NO_OLD_FUNC_DECL one(){ #else int one(){ #endif return 1; } int *metricp; /********************************************************************************************* the main loop that launches the sections *********************************************************************************************/ #ifndef NO_TYPELESS_STRUCT_PTR int section(int j,struct* pd0){ #else int section(int j,void* pd0){ #endif switch(j){ case 0: return s86(pd0); } } #define cq_sections 1 /* C REFERENCE MANUAL (main) */ #ifndef NO_OLD_FUNC_DECL main(n,args) int n; char **args; { #else int main(int n,char **args) { #endif int j; static struct defs d0, *pd0; d0.flgs = 1; /* These flags dictate */ d0.flgm = 1; /* the verbosity of */ d0.flgd = 1; /* the program. */ d0.flgl = 1; pd0 = &d0; for (j=0; j<cq_sections; j++) { d0.rrc=section(j,pd0); d0.crc=d0.crc+d0.rrc; if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); } if(d0.crc == 0) printf("\nNo errors detected.\n"); else printf("\nFailed.\n"); return d0.crc; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/cq88.c���������������������������������������������������������������������������0000664�0000000�0000000�00000012041�13473601511�0014673�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! C-Manual Chapter 8.8: typedef !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include "common.h" struct defs { int cbits; /* No. of bits per char */ int ibits; /* int */ int sbits; /* short */ int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ }; int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ one(){ return 1; } int *metricp; #ifndef NO_OLD_FUNC_DECL s88(pd0) /* 8.8 Typedef */ struct defs *pd0; { #else int s88(struct defs *pd0){ #endif static char s88er[] = "s88,er%d\n"; static char qs88[8] = "s88 "; int rc; char *ps, *pt; /* Declarations whose "storage class" is typdef do not define storage, but instead define identifiers which can later be used as if they were type keywords naming fundamental or derived types. */ typedef int MILES, *KLICKSP; #ifndef NO_FLOATS typedef struct {double re, im;} complex; #else typedef struct {signed re, im;} complex; #endif MILES distance; #ifndef NO_SLOPPY_EXTERN extern KLICKSP metricp; #else KLICKSP metricp; #endif complex z, *zp; ps = qs88; pt = pd0->rfs; rc = 0; while(*pt++ = *ps++); /* Hopefully, all of this stuff will compile. After that, we can only make some superficial tests. The type of distance is int, */ if(sizeof distance != sizeof(int)){ if(pd0->flgd != 0) printf(s88er,1); rc = rc+1; } /* that of metricp is "pointer to int", */ metricp = &distance; distance = 2; *metricp = 3; if(distance != 3){ if(pd0->flgd != 0) printf(s88er,2); rc = rc+2; } /* and that of z is the specified structure. zp is a pointer to such a structure. */ #ifndef NO_FLOATS z.re = 0.; z.im = 0.; zp = &z; zp->re = 1.; zp->im = 1.; if(z.re+z.im != 2.){ #else z.re = 0; z.im = 0; zp = &z; zp->re = 1; zp->im = 1; if(z.re+z.im != 2){ #endif if(pd0->flgd != 0) printf(s88er,4); rc = rc+4; } return rc; } /********************************************************************************************* the main loop that launches the sections *********************************************************************************************/ #ifndef NO_TYPELESS_STRUCT_PTR int section(int j,struct* pd0){ #else int section(int j,void* pd0){ #endif switch(j){ case 0: return s88(pd0); } } #define cq_sections 1 /* C REFERENCE MANUAL (main) */ #ifndef NO_OLD_FUNC_DECL main(n,args) int n; char **args; { #else int main(int n,char **args) { #endif int j; static struct defs d0, *pd0; d0.flgs = 1; /* These flags dictate */ d0.flgm = 1; /* the verbosity of */ d0.flgd = 1; /* the program. */ d0.flgl = 1; pd0 = &d0; for (j=0; j<cq_sections; j++) { d0.rrc=section(j,pd0); d0.crc=d0.crc+d0.rrc; if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); } if(d0.crc == 0) printf("\nNo errors detected.\n"); else printf("\nFailed.\n"); return d0.crc; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/cq9.c����������������������������������������������������������������������������0000664�0000000�0000000�00000011235�13473601511�0014610�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! C-Manual Chapter 9: Statements !!ORIGIN!! LCC 4.1 Testsuite !!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC */ #include "common.h" struct defs { int cbits; /* No. of bits per char */ int ibits; /* int */ int sbits; /* short */ int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ }; int lbits; /* long */ int ubits; /* unsigned */ int fbits; /* float */ int dbits; /* double */ #ifndef NO_FLOATS float fprec; /* Smallest number that can be */ float dprec; /* significantly added to 1. */ #endif int flgs; /* Print return codes, by section */ int flgm; /* Announce machine dependencies */ int flgd; /* give explicit diagnostics */ int flgl; /* Report local return codes. */ int rrc; /* recent return code */ int crc; /* Cumulative return code */ char rfs[8]; /* Return from section */ #ifndef NO_OLD_FUNC_DECL s9(pd0) /* 9 Statements */ struct defs *pd0; { #else int s9(struct defs *pd0){ #endif static char s9er[] = "s9,er%d\n"; static char qs9[8] = "s9 "; int rc; char *ps, *pt; int lrc, i; ps = qs9; pt = pd0->rfs; rc = 0; while (*pt++ = *ps++); /* One would think that the section on statements would provide the most variety in the entire sequence of tests. As it turns out, most of the material in this section has already been checked in the process of checking out everything else, and the section at this point is somewhat anticlimactic. For this reason, we restrict ourselves to testing two features not already covered. Compound statements are delimited by braces. They have the nice property that identifiers of the auto and register variety are pushed and popped. It is currently legal to transfer into a block, but we wont... */ lrc = 0; for(i=0; i<2; i++){ int j; register int k; j = k = 2; { int j; register int k; j = k = 3; if((j != 3) || (k != 3)) lrc = 1; } if((j != 2) || (k != 2)) lrc = 1; } if(lrc != 0){ if(pd0->flgd != 0) printf(s9er,1); rc = rc+1; } /* Goto statements go to labeled statements, we hope. */ goto nobarf; if(pd0->flgd != 0) printf(s9er,2); rc = rc+2; nobarf:; return rc; } /********************************************************************************************* the main loop that launches the sections *********************************************************************************************/ #ifndef NO_TYPELESS_STRUCT_PTR int section(int j,struct* pd0){ #else int section(int j,void* pd0){ #endif switch(j){ case 0: return s9(pd0); } } #define cq_sections 1 /* C REFERENCE MANUAL (main) */ #ifndef NO_OLD_FUNC_DECL main(n,args) int n; char **args; { #else int main(int n,char **args) { #endif int j; static struct defs d0, *pd0; d0.flgs = 1; /* These flags dictate */ d0.flgm = 1; /* the verbosity of */ d0.flgd = 1; /* the program. */ d0.flgl = 1; pd0 = &d0; for (j=0; j<cq_sections; j++) { d0.rrc=section(j,pd0); d0.crc=d0.crc+d0.rrc; if(d0.flgs != 0) printf("Section %s returned %d.\n",d0.rfs,d0.rrc); } if(d0.crc == 0) printf("\nNo errors detected.\n"); else printf("\nFailed.\n"); return d0.crc; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/duffs-device.c�������������������������������������������������������������������0000664�0000000�0000000�00000002357�13473601511�0016465�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! Implementation of Duff's device (loop unrolling). !!ORIGIN!! !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> #define ASIZE (100) unsigned char success=0; unsigned char failures=0; unsigned char dummy=0; #ifdef SUPPORT_BIT_TYPES bit bit0 = 0; #endif void done() { dummy++; } int acmp(char* a, char* b, int count) { int i; for(i = 0; i < count; i++) { if(a[i] != b[i]) { return 1; } } return 0; } void duffit (char* to, char* from, int count) { int n = (count + 7) / 8; switch(count % 8) { case 0: do { *to++ = *from++; case 7: *to++ = *from++; case 6: *to++ = *from++; case 5: *to++ = *from++; case 4: *to++ = *from++; case 3: *to++ = *from++; case 2: *to++ = *from++; case 1: *to++ = *from++; } while(--n > 0); } } int main(void) { char a[ASIZE] = {1}; char b[ASIZE] = {2}; /* a and b should be different */ if(!acmp(a, b, ASIZE)) { failures++; } duffit(a, b, ASIZE); /* a and b should be the same */ if(acmp(a, b, ASIZE)) { failures++; } success=failures; done(); printf("failures: %d\n",failures); return failures; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/for.c����������������������������������������������������������������������������0000664�0000000�0000000�00000002420�13473601511�0014676�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> unsigned char success=0; unsigned char failures=0; unsigned char dummy=0; #ifdef SUPPORT_BIT_TYPES bit bit0 = 0; #endif unsigned int uint0 = 0; unsigned int uint1 = 0; unsigned char uchar0 = 0; unsigned char uchar1 = 0; void done() { dummy++; } void for1(void) { unsigned char i=0; for(i=0; i<10; i++) uchar0++; if(uchar0 != 10) failures++; } void for2(void) { unsigned char i=0; for(i=0; i<10; i++) uchar0++; if(i < 10) failures++; } void for3(void) { unsigned int i=0; for(i=0; i<10; i++) uint0++; if(i < 10) failures++; } void for4(void) { for(uint0=1; uint0<10; uint0++) uchar0++; if(uchar0 != 9) failures++; } void for5(void) { for(uint0=1; uint0<=10; uint0++) uchar0++; if(uchar0 != 10) failures++; } void inc_uchar0(void) { uchar0++; } void for6(void) { uchar0 = 0; for(uint0=1; uint0<=10; uint0++) inc_uchar0(); } int main(void) { for1(); for2(); for3(); uchar0 = 0; for4(); uchar0 = 0; for5(); for6(); if(uchar0 != 10) failures++; success = failures; done(); printf("failures: %d\n",failures); return failures; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/jmp-callax.c���������������������������������������������������������������������0000664�0000000�0000000�00000000423�13473601511�0016141�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������static unsigned char val; static void foo(void) { val = 5; } static void wrap(void) { asm("lda #<%v", foo); asm("ldx #>%v", foo); asm("jmp callax"); } int main(void) { val = 0; wrap(); return val == 5 ? 0 : 1; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/lib_common_atoi.c����������������������������������������������������������������0000664�0000000�0000000�00000001607�13473601511�0017250�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! A small test for atoi. Assumes twos complement !!ORIGIN!! !!LICENCE!! !!AUTHOR!! */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <limits.h> #include <errno.h> static unsigned int Failures = 0; static void CheckAtoi (const char* Str, int Val) { int Res = atoi (Str); if (Res != Val) { printf ("atoi error in \"%s\":\n" " result = %d, should be %d\n", Str, Res, Val); ++Failures; } } int main (void) { CheckAtoi ("\t +0A", 0); CheckAtoi ("\t -0.123", 0); CheckAtoi (" -32 ", -32); CheckAtoi (" +32 ", 32); CheckAtoi ("0377", 377); CheckAtoi (" 0377 ", 377); CheckAtoi (" +0377 ", 377); CheckAtoi (" -0377 ", -377); CheckAtoi ("0x7FFF", 0); CheckAtoi (" +0x7FFF", 0); CheckAtoi (" -0x7FFF", 0); printf ("Failures: %u\n", Failures); return Failures; } �������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/lib_common_memmove.c�������������������������������������������������������������0000664�0000000�0000000�00000003604�13473601511�0017760�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <string.h> #include "unittest.h" #define BufferSize 384 // test correct page passing (>256, multiple of 128 here) static char Buffer[BufferSize+3]; // +1 to move up (and down) TEST { unsigned i, v; char* p; for (i=0; i < BufferSize; ++i) Buffer[i+1] = (i%128); Buffer[0] = 255; // to check if start position is untouched Buffer[BufferSize+2] = 255; // to check if end position is untouched // copy upwards p = memmove(Buffer+2, Buffer+1, BufferSize); // check buffer consistency before target ASSERT_AreEqual(255, (unsigned)Buffer[0], "%u", "Unexpected value before range!"); // check buffer consistency at starting point ASSERT_AreEqual(0, (unsigned)Buffer[1], "%u", "Unexpected value at range start!"); // check buffer consistency after range ASSERT_AreEqual(255, (unsigned)Buffer[BufferSize+2], "%u", "Unexpected value after range!"); // check buffer values for (i=0; i < BufferSize; ++i) { ASSERT_AreEqual(i%128, (unsigned)Buffer[i+2], "%u", "Unexpected value in buffer at position %u!" COMMA i+2); } v = Buffer[BufferSize+1]; // rember value of first untouched end-byte // copy downwards p = memmove(Buffer+1, Buffer+2, BufferSize); // check buffer consistency before target ASSERT_AreEqual(255, (unsigned)Buffer[0], "%u", "Unexpected value before range!"); // check buffer consistency at end point ASSERT_AreEqual(v, (unsigned)Buffer[BufferSize+1], "%u", "Unexpected value at range end!"); // check buffer consistency after range ASSERT_AreEqual(255, (unsigned)Buffer[BufferSize+2], "%u", "Unexpected value after range!"); // check buffer values for (i=0; i < BufferSize; ++i) { ASSERT_AreEqual(i%128, (unsigned)Buffer[i+1], "%u", "Unexpected value in buffer at position %u!" COMMA i+1); } } ENDTEST ����������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/lib_common_mulxx.c���������������������������������������������������������������0000664�0000000�0000000�00000000526�13473601511�0017470�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <cc65.h> #include "unittest.h" TEST { unsigned i; for (i=0; i < 256; ++i) { ASSERT_AreEqual(i*20, mul20(i), "%u", "Invalid 'mul20(%u)' calculation!" COMMA i); } for (i=0; i < 256; ++i) { ASSERT_AreEqual(i*40, mul40(i), "%u", "Invalid 'mul40(%u)' calculation!" COMMA i); } } ENDTEST ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/lib_common_strcat.c��������������������������������������������������������������0000664�0000000�0000000�00000003403�13473601511�0017610�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <string.h> #include "unittest.h" #define SourceStringSize 257 // test correct page passing (>256) static char SourceString[SourceStringSize+1]; // +1 room for terminating null static char DestinationString[2*SourceStringSize+1]; // will contain two times the source buffer TEST { unsigned i,j; char* p; for (i=0; i < SourceStringSize; ++i) SourceString[i] = (i%128)+1; SourceString[i] = 0; ASSERT_AreEqual(SourceStringSize, strlen(SourceString), "%u", "Source string initialization or 'strlen()' problem!"); /* Ensure empty destination string */ DestinationString[0] = 0; ASSERT_AreEqual(0, strlen(DestinationString), "%u", "Destination string initialization or 'strlen()' problem!"); /* Test concatenation to empty buffer */ strcat(DestinationString, SourceString); ASSERT_AreEqual(SourceStringSize, strlen(DestinationString), "%u", "Unexpected string length while string concatenation to empty buffer!"); /* Test concatenation to non empty buffer */ p = strcat(DestinationString, SourceString); ASSERT_AreEqual(2*SourceStringSize, strlen(DestinationString), "%u", "Unexpected string length while string concatenation to non-empty buffer!"); /* Test return value */ ASSERT_IsTrue(p == DestinationString,"Invalid return value!"); /* Test contents */ for(j=0; j <2; ++j) for(i=0; i < SourceStringSize; ++i) { unsigned position = j*SourceStringSize+i; unsigned current = DestinationString[position]; unsigned expected = (i%128)+1; ASSERT_AreEqual(expected, current, "%u", "Unexpected destination buffer contents at position %u!\n" COMMA position); } } ENDTEST �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/lib_common_strchr.c��������������������������������������������������������������0000664�0000000�0000000�00000001776�13473601511�0017630�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <string.h> #include "unittest.h" /* Test string. Must NOT have duplicate characters! */ static char S[] = "Helo wrd!\n"; static char Found[256]; TEST { unsigned Len; unsigned I; char* P; /* Get the length of the string */ Len = strlen (S); /* Search for all characters in the string, including the terminator */ for (I = 0; I < Len+1; ++I) { /* Search for this char */ P = strchr (S, S[I]); /* Check if we found it */ ASSERT_IsFalse(P == 0 || (P - S) != I, "For code 0x%02X, offset %u!\nP = %04X offset = %04X\n" COMMA S[I] COMMA I COMMA P COMMA P-S); /* Mark the char as checked */ Found[S[I]] = 1; } /* Search for all other characters and make sure they aren't found */ for (I = 0; I < 256; ++I) { if (Found[I] == 0) { ASSERT_IsFalse(strchr (S, (char)I), "Failed for code 0x%02X\n" COMMA I); } } } ENDTEST ��cc65-2.18/test/val/lib_common_strcspn.c�������������������������������������������������������������0000664�0000000�0000000�00000002075�13473601511�0020010�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <string.h> #include "unittest.h" #define EstimatedStringSize 384 // test correct page passing (>256) static char EstimatedString[EstimatedStringSize+1]; // +1 room for terminating null static char* EmptyTestChars=""; // strlen equivalent... static char* TestChars="1234567890"; // we like to find numbers TEST { unsigned i; for (i=0; i < EstimatedStringSize; ++i) EstimatedString[i] = (i%26)+'A'; // put ABCD... into the string to be estimated ASSERT_AreEqual(strlen(EstimatedString), strcspn(EstimatedString, TestChars), "%u", "Unxpected position returned for non-participant case!"); EstimatedString[EstimatedStringSize/2] = TestChars[strlen(TestChars-1)]; ASSERT_AreEqual(EstimatedStringSize/2, strcspn(EstimatedString, TestChars), "%u", "Unxpected position returned for participant case!"); ASSERT_AreEqual(strlen(EstimatedString), strcspn(EstimatedString, EmptyTestChars), "%u", "Unxpected position returned for empty test case!"); } ENDTEST �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/lib_common_strncat.c�������������������������������������������������������������0000664�0000000�0000000�00000003317�13473601511�0017772�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <string.h> #include "unittest.h" #define SourceStringSize 384 // test correct page passing (>256, multiple of 128 here) static char SourceString[SourceStringSize+1]; // +1 room for terminating null static char DestinationString[2*SourceStringSize+1]; // will contain two times the source buffer TEST { unsigned i; char* p; for (i=0; i < SourceStringSize; ++i) SourceString[i] = (i%128)+1; SourceString[i] = 0; ASSERT_AreEqual(SourceStringSize, strlen(SourceString), "%u", "Source string initialization or 'strlen()' problem!"); /* Ensure empty destination string */ DestinationString[0] = 0; ASSERT_AreEqual(0, strlen(DestinationString), "%u", "Destination string initialization or 'strlen()' problem!"); /* Test "unlimted" concatenation to empty buffer */ strncat(DestinationString, SourceString, 1024); ASSERT_AreEqual(SourceStringSize, strlen(DestinationString), "%u", "Unexpected string length while string concatenation to empty buffer!"); /* Test limited concatenation to non empty buffer */ p = strncat(DestinationString, SourceString, 128); ASSERT_AreEqual(SourceStringSize+128, strlen(DestinationString), "%u", "Unexpected string length while string concatenation to non-empty buffer!"); /* Test return value */ ASSERT_IsTrue(p == DestinationString, "Invalid return value!"); /* Test contents */ for(i=0; i < strlen(DestinationString); ++i) { unsigned current = DestinationString[i]; unsigned expected = (i%128)+1; ASSERT_AreEqual(expected, current, "%u", "Unexpected destination buffer contents at position %u!\n" COMMA i); } } ENDTEST �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/lib_common_strol.c���������������������������������������������������������������0000664�0000000�0000000�00000007314�13473601511�0017460�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! A small test for atoi/strtol. Assumes twos complement !!ORIGIN!! !!LICENCE!! !!AUTHOR!! */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <limits.h> #include <errno.h> #define ERROR 0 #define OK 1 static unsigned int Failures = 0; static void IncStr (char* Buf) /* Increment a number represented as a string by one. The string MUST not * start with a '9', we cannot handle overflow in this case. */ { int Len = strlen (Buf); while (--Len >= 0) { switch (Buf[Len]) { case '9': Buf[Len] = '0'; break; default: ++(Buf[Len]); return; } } } static void CheckStrToL (const char* Str, int Base, long Val, unsigned char Ok) { char* EndPtr; long Res = strtol (Str, &EndPtr, Base); if (Ok) { if (Res != Val) { printf ("strtol error in \"%s\":\n" " result = %ld, should be %ld, chars = %d\n", Str, Res, Val, EndPtr - Str); ++Failures; } } else { if (errno != ERANGE) { printf ("strtol error in \"%s\":\n" " should not convert, but errno = %d\n", Str, errno); ++Failures; } if (Res != Val) { printf ("strtol error in \"%s\":\n" " result = %ld, should be %ld, chars = %d\n", Str, Res, Val, EndPtr - Str); ++Failures; } } } int main (void) { char Buf[80]; /* Prefixed allowed if base = 0 */ CheckStrToL ("\t 0x10G ", 0, 16L, OK); CheckStrToL ("\t 0X10G ", 0, 16L, OK); CheckStrToL (" \t0377\t", 0, 255L, OK); CheckStrToL (" 377", 0, 377L, OK); CheckStrToL ("\t -0x10G ", 0, -16L, OK); CheckStrToL ("\t -0X10G ", 0, -16L, OK); CheckStrToL (" \t-0377\t", 0, -255L, OK); CheckStrToL (" -377", 0, -377L, OK); /* No prefixes if base = 10 */ CheckStrToL ("\t 1234 ", 10, 1234L, OK); CheckStrToL ("\t -1234 ", 10, -1234L, OK); CheckStrToL ("\t -0x10G ", 10, 0L, OK); CheckStrToL ("\t -0X10G ", 10, 0L, OK); CheckStrToL (" \t-0377\t", 10, -377L, OK); CheckStrToL (" 0377", 10, 377L, OK); /* 0x prefix is allowed if base = 16 */ CheckStrToL ("\t 0x1234 ", 16, 0x1234L, OK); CheckStrToL ("\t -0x1234 ", 16, -0x1234L, OK); CheckStrToL ("\t -010G ", 16, -16L, OK); CheckStrToL ("\t 10G ", 16, 16L, OK); /* Check LONG_MIN and LONG_MAX */ sprintf (Buf, "%ld", LONG_MIN); CheckStrToL (Buf, 0, LONG_MIN, OK); sprintf (Buf, "%ld", LONG_MAX); CheckStrToL (Buf, 0, LONG_MAX, OK); /* Check value one smaller */ sprintf (Buf+1, "%ld", LONG_MIN); Buf[1] = '0'; /* Overwrite '-' */ IncStr (Buf+1); if (Buf[1] == '0') { Buf[1] = '-'; Buf[0] = ' '; } else { Buf[0] = '-'; } CheckStrToL (Buf, 0, LONG_MIN, ERROR); /* Check value one larger */ sprintf (Buf+1, "%ld", LONG_MAX); Buf[0] = '0'; IncStr (Buf); if (Buf[0] == '0') { Buf[0] = ' '; } CheckStrToL (Buf, 0, LONG_MAX, ERROR); /* Check numbers that are much too large or small */ CheckStrToL ("-999999999999999999999999999999999999999999999999999999999", 0, LONG_MIN, ERROR); CheckStrToL ("+999999999999999999999999999999999999999999999999999999999", 0, LONG_MAX, ERROR); CheckStrToL (" 999999999999999999999999999999999999999999999999999999999", 0, LONG_MAX, ERROR); /* Check a few other bases */ CheckStrToL ("aBcD", 36, 481261L, OK); CheckStrToL ("zyaB", 35, 0L, ERROR); CheckStrToL ("zyaB", 36, 1677395L, ERROR); printf ("Failures: %u\n", Failures); return Failures; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/lib_common_strrchr.c�������������������������������������������������������������0000664�0000000�0000000�00000002045�13473601511�0020000�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <string.h> #include "unittest.h" static char TestString[] = "01234567890123456789"; // two times the same string static char Found[256]; TEST { unsigned len; unsigned i; char* p; len = strlen(TestString)/2; // test only one half of the string, to find last appearance /* Search for all characters in the string, including the terminator */ for (i = 0; i < len; ++i) { /* Search for this char */ p = strrchr (TestString, TestString[i]); ASSERT_AreEqual(i+len, p-TestString, "%u", "Unexpected location of character '%c' found!" COMMA TestString[i]); /* Mark the char as checked */ Found[TestString[i]] = 1; } /* Search for all other characters and make sure they aren't found */ for (i = 0; i < 256; ++i) { if (!Found[i]) { p = strrchr (TestString, i); ASSERT_IsFalse(p, "Unexpected location of character '%c' found!" COMMA TestString[i]); } } } ENDTEST �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/lib_common_strspn.c��������������������������������������������������������������0000664�0000000�0000000�00000002003�13473601511�0017634�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <string.h> #include "unittest.h" #define EstimatedStringSize 384 // test correct page passing (>256) static char EstimatedString[EstimatedStringSize+1]; // +1 room for terminating null static char* EmptyTestChars=""; // empty test case... static char* TestChars="1234567890"; // we like to find numbers TEST { unsigned i; for (i=0; i < EstimatedStringSize; ++i) EstimatedString[i] = (i%10)+'0'; // put 0123... into the string to be estimated ASSERT_AreEqual(strlen(EstimatedString), strspn(EstimatedString, TestChars), "%u", "Unxpected position returned for all participant case!"); EstimatedString[EstimatedStringSize/2] = 'X'; ASSERT_AreEqual(EstimatedStringSize/2, strspn(EstimatedString, TestChars), "%u", "Unxpected position returned for breaking case!"); ASSERT_AreEqual(0, strspn(EstimatedString, EmptyTestChars), "%u", "Unxpected position returned for empty test case!"); } ENDTEST �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/lib_common_strtoul.c�������������������������������������������������������������0000664�0000000�0000000�00000007020�13473601511�0020023�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! A small test for strtuol. Assumes twos complement !!ORIGIN!! !!LICENCE!! !!AUTHOR!! */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <limits.h> #include <errno.h> #define ERROR 0 #define OK 1 static unsigned int Failures = 0; static void IncStr (char* Buf) /* Increment a number represented as a string by one. The string MUST not * start with a '9', we cannot handle overflow in this case. */ { int Len = strlen (Buf); while (--Len >= 0) { switch (Buf[Len]) { case '9': Buf[Len] = '0'; break; default: ++(Buf[Len]); return; } } } static void CheckStrToUL (const char* Str, int Base, unsigned long Val, unsigned char Ok) { char* EndPtr; unsigned long Res = strtoul (Str, &EndPtr, Base); if (Ok) { if (Res != Val) { printf ("strtol error in \"%s\":\n" " result = %lu, should be %lu, chars = %d\n", Str, Res, Val, EndPtr - Str); ++Failures; } } else { if (errno != ERANGE) { printf ("strtol error in \"%s\":\n" " should not convert, but errno = %d\n", Str, errno); ++Failures; } if (Res != Val) { printf ("strtol error in \"%s\":\n" " result = %lu, should be %lu, chars = %d\n", Str, Res, Val, EndPtr - Str); ++Failures; } } } int main (void) { char Buf[80]; /* Prefixed allowed if base = 0 */ CheckStrToUL ("\t 0x10G ", 0, 16UL, OK); CheckStrToUL ("\t 0X10G ", 0, 16UL, OK); CheckStrToUL (" \t0377\t", 0, 255UL, OK); CheckStrToUL (" 377", 0, 377UL, OK); CheckStrToUL ("\t -0x10G ", 0, (unsigned long) -16L, OK); CheckStrToUL ("\t -0X10G ", 0, (unsigned long) -16L, OK); CheckStrToUL (" \t-0377\t", 0, (unsigned long) -255L, OK); CheckStrToUL (" -377", 0, (unsigned long) -377L, OK); /* No prefixes if base = 10 */ CheckStrToUL ("\t 1234 ", 10, 1234UL, OK); CheckStrToUL ("\t -1234 ", 10, (unsigned long) -1234L, OK); CheckStrToUL ("\t -0x10G ", 10, 0UL, OK); CheckStrToUL ("\t -0X10G ", 10, 0UL, OK); CheckStrToUL (" \t-0377\t", 10, (unsigned long) -377L, OK); CheckStrToUL (" 0377", 10, 377UL, OK); /* 0x prefix is allowed if base = 16 */ CheckStrToUL ("\t 0x1234 ", 16, 0x1234UL, OK); CheckStrToUL ("\t -0x1234 ", 16, (unsigned long) -0x1234L, OK); CheckStrToUL ("\t -010G ", 16, (unsigned long) -16L, OK); CheckStrToUL ("\t 10G ", 16, 16UL, OK); /* Check ULONG_MAX */ sprintf (Buf, "%lu", ULONG_MAX); CheckStrToUL (Buf, 0, ULONG_MAX, OK); /* Check value one larger */ sprintf (Buf+1, "%lu", ULONG_MAX); Buf[0] = '0'; IncStr (Buf); if (Buf[0] == '0') { Buf[0] = ' '; } CheckStrToUL (Buf, 0, ULONG_MAX, ERROR); /* Check numbers that are much too large or small */ CheckStrToUL ("-999999999999999999999999999999999999999999999999999999999", 0, ULONG_MAX, ERROR); CheckStrToUL ("+999999999999999999999999999999999999999999999999999999999", 0, ULONG_MAX, ERROR); CheckStrToUL (" 999999999999999999999999999999999999999999999999999999999", 0, ULONG_MAX, ERROR); /* Check a few other bases */ CheckStrToUL ("aBcD", 36, 481261UL, OK); CheckStrToUL ("zyaB", 35, 0UL, ERROR); CheckStrToUL ("zyaB", 36, 1677395UL, ERROR); printf ("Failures: %u\n", Failures); return Failures; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/lz4.c����������������������������������������������������������������������������0000664�0000000�0000000�00000133354�13473601511�0014634�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! lz4 decompression !!ORIGIN!! cc65 regression tests !!LICENCE!! BSD 2-clause !!AUTHOR!! Lauri Kasanen */ #include <zlib.h> #include <stdio.h> #include <lz4.h> /* The sample data is the original lz4.h, compressed with lz4 hc */ static const unsigned char compressed[] = { 0xf0, 0x1a, 0x2f, 0x2a, 0x0a, 0x20, 0x20, 0x20, 0x4c, 0x5a, 0x34, 0x20, 0x2d, 0x20, 0x46, 0x61, 0x73, 0x74, 0x20, 0x4c, 0x5a, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x27, 0x00, 0xb0, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x46, 0x69, 0x6c, 0x65, 0x0f, 0x00, 0xf0, 0x17, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x43, 0x29, 0x20, 0x32, 0x30, 0x31, 0x31, 0x2d, 0x32, 0x30, 0x31, 0x35, 0x2c, 0x20, 0x59, 0x61, 0x6e, 0x6e, 0x20, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x0a, 0x2a, 0x00, 0xf2, 0x22, 0x42, 0x53, 0x44, 0x20, 0x32, 0x2d, 0x43, 0x6c, 0x61, 0x75, 0x73, 0x65, 0x20, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x6c, 0x23, 0x00, 0x63, 0x73, 0x2f, 0x62, 0x73, 0x64, 0x2d, 0x0d, 0x00, 0x51, 0x2e, 0x70, 0x68, 0x70, 0x29, 0x4e, 0x00, 0xb1, 0x52, 0x65, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0xa3, 0x00, 0x30, 0x6e, 0x64, 0x20, 0x58, 0x00, 0x32, 0x69, 0x6e, 0x20, 0x43, 0x00, 0x01, 0x12, 0x00, 0xf1, 0x06, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x2c, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6f, 0x72, 0x08, 0x00, 0x30, 0x6f, 0x75, 0x74, 0x46, 0x00, 0x80, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x44, 0x00, 0xf0, 0x22, 0x2c, 0x20, 0x61, 0x72, 0x65, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x20, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x35, 0x00, 0x10, 0x73, 0x35, 0x00, 0x01, 0x4a, 0x00, 0x31, 0x65, 0x74, 0x3a, 0x99, 0x00, 0x00, 0x01, 0x00, 0x1b, 0x2a, 0x9f, 0x00, 0x44, 0x73, 0x20, 0x6f, 0x66, 0x98, 0x00, 0xf1, 0x01, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x72, 0x65, 0x74, 0x61, 0x69, 0x6e, 0x5a, 0x00, 0x40, 0x61, 0x62, 0x6f, 0x76, 0x1b, 0x00, 0x03, 0x4c, 0x01, 0x00, 0x48, 0x00, 0xf0, 0x02, 0x6e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x44, 0x00, 0x08, 0x78, 0x00, 0x2b, 0x6e, 0x64, 0x95, 0x00, 0xbf, 0x64, 0x69, 0x73, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x72, 0x2e, 0x89, 0x00, 0x07, 0x28, 0x69, 0x6e, 0x16, 0x01, 0x04, 0x89, 0x00, 0x76, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x8c, 0x00, 0x00, 0x41, 0x00, 0x05, 0x8f, 0x00, 0x0f, 0x8c, 0x00, 0x2a, 0x00, 0x4a, 0x00, 0x03, 0xe6, 0x00, 0x94, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0xb3, 0x01, 0xf6, 0x04, 0x2f, 0x6f, 0x72, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x77, 0x01, 0x01, 0xaf, 0x01, 0x21, 0x74, 0x68, 0x8b, 0x00, 0x08, 0xc4, 0x00, 0x02, 0x4e, 0x02, 0xf0, 0x34, 0x54, 0x48, 0x49, 0x53, 0x20, 0x53, 0x4f, 0x46, 0x54, 0x57, 0x41, 0x52, 0x45, 0x20, 0x49, 0x53, 0x20, 0x50, 0x52, 0x4f, 0x56, 0x49, 0x44, 0x45, 0x44, 0x20, 0x42, 0x59, 0x20, 0x54, 0x48, 0x45, 0x20, 0x43, 0x4f, 0x50, 0x59, 0x52, 0x49, 0x47, 0x48, 0x54, 0x20, 0x48, 0x4f, 0x4c, 0x44, 0x45, 0x52, 0x53, 0x20, 0x41, 0x4e, 0x44, 0x20, 0x43, 0x4f, 0x4e, 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, 0x4f, 0x52, 0x53, 0x47, 0x00, 0x71, 0x22, 0x41, 0x53, 0x20, 0x49, 0x53, 0x22, 0x1c, 0x00, 0xf1, 0x26, 0x41, 0x4e, 0x59, 0x20, 0x45, 0x58, 0x50, 0x52, 0x45, 0x53, 0x53, 0x20, 0x4f, 0x52, 0x20, 0x49, 0x4d, 0x50, 0x4c, 0x49, 0x45, 0x44, 0x20, 0x57, 0x41, 0x52, 0x52, 0x41, 0x4e, 0x54, 0x49, 0x45, 0x53, 0x2c, 0x20, 0x49, 0x4e, 0x43, 0x4c, 0x55, 0x44, 0x49, 0x4e, 0x47, 0x2c, 0x20, 0x42, 0x55, 0x54, 0x20, 0x4e, 0x4f, 0x54, 0x3a, 0x03, 0xa1, 0x49, 0x4d, 0x49, 0x54, 0x45, 0x44, 0x20, 0x54, 0x4f, 0x2c, 0x7b, 0x00, 0x0e, 0x3a, 0x00, 0xf1, 0x04, 0x20, 0x4f, 0x46, 0x20, 0x4d, 0x45, 0x52, 0x43, 0x48, 0x41, 0x4e, 0x54, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x73, 0x00, 0x40, 0x46, 0x49, 0x54, 0x4e, 0x6f, 0x00, 0x30, 0x46, 0x4f, 0x52, 0x49, 0x00, 0xf0, 0x06, 0x41, 0x20, 0x50, 0x41, 0x52, 0x54, 0x49, 0x43, 0x55, 0x4c, 0x41, 0x52, 0x20, 0x50, 0x55, 0x52, 0x50, 0x4f, 0x53, 0x45, 0x20, 0xe0, 0x00, 0xfa, 0x0e, 0x44, 0x49, 0x53, 0x43, 0x4c, 0x41, 0x49, 0x4d, 0x45, 0x44, 0x2e, 0x20, 0x49, 0x4e, 0x20, 0x4e, 0x4f, 0x20, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x20, 0x53, 0x48, 0x41, 0x4c, 0x4c, 0xef, 0x00, 0x00, 0x48, 0x00, 0x50, 0x4f, 0x57, 0x4e, 0x45, 0x52, 0xc4, 0x00, 0x08, 0xef, 0x00, 0xa0, 0x20, 0x42, 0x45, 0x20, 0x4c, 0x49, 0x41, 0x42, 0x4c, 0x45, 0x6f, 0x00, 0x01, 0xee, 0x00, 0x60, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0xd7, 0x00, 0x06, 0x0a, 0x00, 0x90, 0x43, 0x49, 0x44, 0x45, 0x4e, 0x54, 0x41, 0x4c, 0x2c, 0x49, 0x00, 0xf3, 0x04, 0x53, 0x50, 0x45, 0x43, 0x49, 0x41, 0x4c, 0x2c, 0x20, 0x45, 0x58, 0x45, 0x4d, 0x50, 0x4c, 0x41, 0x52, 0x59, 0x2c, 0x57, 0x00, 0xff, 0x05, 0x53, 0x45, 0x51, 0x55, 0x45, 0x4e, 0x54, 0x49, 0x41, 0x4c, 0x20, 0x44, 0x41, 0x4d, 0x41, 0x47, 0x45, 0x53, 0x20, 0x28, 0x1e, 0x01, 0x0f, 0x80, 0x50, 0x52, 0x4f, 0x43, 0x55, 0x52, 0x45, 0x4d, 0xbc, 0x00, 0xf1, 0x03, 0x4f, 0x46, 0x20, 0x53, 0x55, 0x42, 0x53, 0x54, 0x49, 0x54, 0x55, 0x54, 0x45, 0x20, 0x47, 0x4f, 0x4f, 0x44, 0x77, 0x01, 0xd1, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x53, 0x3b, 0x20, 0x4c, 0x4f, 0x53, 0x39, 0x01, 0x31, 0x55, 0x53, 0x45, 0x8d, 0x00, 0x41, 0x44, 0x41, 0x54, 0x41, 0x7f, 0x00, 0x80, 0x50, 0x52, 0x4f, 0x46, 0x49, 0x54, 0x53, 0x3b, 0x0c, 0x00, 0x41, 0x42, 0x55, 0x53, 0x49, 0x43, 0x01, 0xf1, 0x0d, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x52, 0x55, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x29, 0x20, 0x48, 0x4f, 0x57, 0x45, 0x56, 0x45, 0x52, 0x20, 0x43, 0x41, 0x55, 0x53, 0x45, 0x44, 0x6c, 0x01, 0x20, 0x4f, 0x4e, 0xf4, 0x00, 0x02, 0x3c, 0x02, 0x40, 0x45, 0x4f, 0x52, 0x59, 0x5b, 0x00, 0x23, 0x4c, 0x49, 0x8e, 0x01, 0x90, 0x2c, 0x20, 0x57, 0x48, 0x45, 0x54, 0x48, 0x45, 0x52, 0x5f, 0x01, 0x01, 0x36, 0x01, 0x10, 0x41, 0x0f, 0x01, 0x68, 0x53, 0x54, 0x52, 0x49, 0x43, 0x54, 0x27, 0x00, 0x61, 0x4f, 0x52, 0x20, 0x54, 0x4f, 0x52, 0xd9, 0x00, 0x06, 0xf0, 0x00, 0xb0, 0x20, 0x4e, 0x45, 0x47, 0x4c, 0x49, 0x47, 0x45, 0x4e, 0x43, 0x45, 0x21, 0x00, 0x10, 0x4f, 0x49, 0x00, 0xa0, 0x57, 0x49, 0x53, 0x45, 0x29, 0x20, 0x41, 0x52, 0x49, 0x53, 0x21, 0x00, 0x11, 0x49, 0x7d, 0x00, 0x71, 0x20, 0x57, 0x41, 0x59, 0x20, 0x4f, 0x55, 0xfc, 0x00, 0x00, 0xb5, 0x01, 0x31, 0x55, 0x53, 0x45, 0xaf, 0x01, 0x1a, 0x46, 0xcf, 0x02, 0x11, 0x2c, 0xde, 0x01, 0x80, 0x20, 0x49, 0x46, 0x20, 0x41, 0x44, 0x56, 0x49, 0xc0, 0x00, 0x03, 0x30, 0x00, 0x53, 0x50, 0x4f, 0x53, 0x53, 0x49, 0x3f, 0x02, 0x01, 0x3f, 0x01, 0x23, 0x43, 0x48, 0x7e, 0x01, 0x02, 0x15, 0x03, 0x70, 0x59, 0x6f, 0x75, 0x20, 0x63, 0x61, 0x6e, 0x9b, 0x03, 0x32, 0x74, 0x61, 0x63, 0xb5, 0x04, 0xb0, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x20, 0x61, 0x74, 0x20, 0x3a, 0x23, 0x00, 0x11, 0x2d, 0xe8, 0x05, 0x03, 0x8c, 0x04, 0xd0, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x20, 0x3a, 0x20, 0x8a, 0x05, 0xf6, 0x0c, 0x73, 0x3a, 0x2f, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x79, 0x61, 0x6e, 0x34, 0x39, 0x37, 0x33, 0x2f, 0x6c, 0x7a, 0x34, 0x3d, 0x00, 0x60, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x40, 0x04, 0x28, 0x75, 0x6d, 0x38, 0x00, 0xc1, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x3f, 0x00, 0x01, 0x22, 0x00, 0x32, 0x2f, 0x23, 0x21, 0x08, 0x00, 0xf0, 0x1b, 0x6c, 0x7a, 0x34, 0x63, 0x0a, 0x2a, 0x2f, 0x0a, 0x23, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x20, 0x6f, 0x6e, 0x63, 0x65, 0x0a, 0x0a, 0x23, 0x69, 0x66, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x28, 0x5f, 0x5f, 0x63, 0x70, 0x6c, 0x75, 0x73, 0x04, 0x00, 0xf0, 0x08, 0x29, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x20, 0x22, 0x43, 0x22, 0x20, 0x7b, 0x0a, 0x23, 0x65, 0x6e, 0x64, 0x69, 0x66, 0x0a, 0x0a, 0xab, 0x06, 0x74, 0x2a, 0x20, 0x6c, 0x7a, 0x34, 0x2e, 0x68, 0x2a, 0x04, 0x79, 0x73, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0xb2, 0x06, 0x41, 0x66, 0x75, 0x6e, 0x63, 0x9b, 0x04, 0x11, 0x2c, 0x9c, 0x04, 0xf1, 0x02, 0x67, 0x69, 0x76, 0x65, 0x73, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x01, 0x60, 0x72, 0x6f, 0x6c, 0x20, 0x74, 0x6f, 0x47, 0x00, 0x42, 0x67, 0x72, 0x61, 0x6d, 0x37, 0x05, 0xb0, 0x2a, 0x20, 0x49, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6e, 0x65, 0xfa, 0x05, 0x90, 0x6f, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x5a, 0x06, 0xc5, 0x74, 0x65, 0x72, 0x2d, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x6e, 0x00, 0xf0, 0x01, 0x65, 0x64, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x28, 0x72, 0x65, 0x73, 0x70, 0x65, 0x63, 0x74, 0xfd, 0x04, 0x00, 0x25, 0x01, 0x60, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x20, 0x13, 0x00, 0x05, 0x61, 0x06, 0x20, 0x29, 0x2c, 0x60, 0x00, 0x00, 0x90, 0x00, 0x00, 0xa4, 0x01, 0x22, 0x6c, 0x65, 0xa0, 0x01, 0x40, 0x6c, 0x69, 0x62, 0x72, 0x8f, 0x05, 0xf1, 0x0e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x20, 0x69, 0x74, 0x73, 0x20, 0x6f, 0x77, 0x6e, 0x20, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x2c, 0x20, 0x70, 0x6c, 0x65, 0x61, 0x73, 0x65, 0xdc, 0x06, 0x31, 0x6c, 0x7a, 0x34, 0x56, 0x00, 0xb0, 0x2e, 0x68, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x65, 0x61, 0x64, 0x2e, 0x50, 0x01, 0x3f, 0x0a, 0x2f, 0x2a, 0x01, 0x00, 0x12, 0x70, 0x0a, 0x2a, 0x20, 0x20, 0x56, 0x65, 0x72, 0x20, 0x01, 0x1f, 0x0a, 0x32, 0x00, 0x13, 0x32, 0x2f, 0x0a, 0x23, 0x9b, 0x01, 0x00, 0xd2, 0x00, 0xe0, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x41, 0x4a, 0x4f, 0x52, 0x5d, 0x06, 0x10, 0x31, 0x05, 0x00, 0x20, 0x2f, 0x2a, 0x09, 0x02, 0x60, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0xfc, 0x00, 0x01, 0x27, 0x01, 0x20, 0x66, 0x61, 0xe9, 0x06, 0x8f, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x20, 0x20, 0x48, 0x00, 0x05, 0x22, 0x49, 0x4e, 0x48, 0x00, 0x17, 0x37, 0x48, 0x00, 0x94, 0x6e, 0x65, 0x77, 0x20, 0x28, 0x6e, 0x6f, 0x6e, 0x2d, 0x51, 0x00, 0x18, 0x29, 0x52, 0x00, 0xbf, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x56, 0x00, 0x05, 0x7a, 0x52, 0x45, 0x4c, 0x45, 0x41, 0x53, 0x45, 0x9e, 0x00, 0xf0, 0x03, 0x74, 0x77, 0x65, 0x61, 0x6b, 0x73, 0x2c, 0x20, 0x62, 0x75, 0x67, 0x2d, 0x66, 0x69, 0x78, 0x65, 0x73, 0x2c, 0x08, 0x08, 0x70, 0x64, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x92, 0x06, 0x0f, 0x4e, 0x00, 0x05, 0x8e, 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x20, 0x28, 0x00, 0x01, 0x40, 0x2a, 0x31, 0x30, 0x30, 0x04, 0x00, 0x2f, 0x20, 0x2b, 0xd5, 0x00, 0x00, 0x0e, 0x19, 0x00, 0x04, 0x98, 0x00, 0x51, 0x29, 0x0a, 0x69, 0x6e, 0x74, 0x19, 0x00, 0x12, 0x76, 0x8b, 0x01, 0xef, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x20, 0x28, 0x76, 0x6f, 0x69, 0x64, 0x29, 0x3b, 0xcd, 0x01, 0x1a, 0x30, 0x54, 0x75, 0x6e, 0x72, 0x01, 0x20, 0x70, 0x61, 0x15, 0x02, 0x3f, 0x74, 0x65, 0x72, 0xd6, 0x01, 0x16, 0x02, 0x45, 0x03, 0x00, 0x85, 0x00, 0xc0, 0x4d, 0x45, 0x4d, 0x4f, 0x52, 0x59, 0x5f, 0x55, 0x53, 0x41, 0x47, 0x45, 0x20, 0x04, 0x31, 0x2a, 0x20, 0x4d, 0x78, 0x02, 0x61, 0x20, 0x75, 0x73, 0x61, 0x67, 0x65, 0x23, 0x08, 0xf0, 0x1d, 0x75, 0x6c, 0x61, 0x20, 0x3a, 0x20, 0x4e, 0x2d, 0x3e, 0x32, 0x5e, 0x4e, 0x20, 0x42, 0x79, 0x74, 0x65, 0x73, 0x20, 0x28, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x20, 0x3a, 0x20, 0x31, 0x30, 0x20, 0x2d, 0x3e, 0x20, 0x31, 0x4b, 0x42, 0x3b, 0x20, 0x31, 0x32, 0x0b, 0x00, 0x80, 0x34, 0x4b, 0x42, 0x20, 0x3b, 0x20, 0x31, 0x36, 0x0c, 0x00, 0x20, 0x36, 0x34, 0x18, 0x00, 0x12, 0x32, 0x23, 0x00, 0x91, 0x4d, 0x42, 0x3b, 0x20, 0x65, 0x74, 0x63, 0x2e, 0x29, 0x66, 0x03, 0x60, 0x6e, 0x63, 0x72, 0x65, 0x61, 0x73, 0xc0, 0x00, 0x18, 0x6d, 0x72, 0x00, 0x20, 0x69, 0x6d, 0xd6, 0x03, 0x29, 0x65, 0x73, 0xce, 0x03, 0x10, 0x72, 0x3f, 0x03, 0x12, 0x0a, 0xcd, 0x08, 0x4a, 0x75, 0x63, 0x65, 0x64, 0x33, 0x00, 0x00, 0x4d, 0x03, 0x03, 0x37, 0x00, 0x00, 0x70, 0x03, 0x70, 0x65, 0x64, 0x2c, 0x20, 0x64, 0x75, 0x65, 0xbc, 0x03, 0xc0, 0x63, 0x61, 0x63, 0x68, 0x65, 0x20, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x3f, 0x00, 0xf1, 0x05, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x69, 0x73, 0x20, 0x31, 0x34, 0x2c, 0x20, 0x02, 0xf0, 0x05, 0x31, 0x36, 0x4b, 0x42, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x6e, 0x69, 0x63, 0x65, 0x6c, 0x79, 0x20, 0x66, 0x89, 0x03, 0xf2, 0x02, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x6c, 0x20, 0x78, 0x38, 0x36, 0x20, 0x4c, 0x31, 0x53, 0x00, 0x1c, 0x0a, 0x2f, 0x02, 0x09, 0x47, 0x01, 0x3f, 0x31, 0x34, 0x0a, 0xc7, 0x01, 0x1a, 0x20, 0x53, 0x69, 0x4c, 0x01, 0x24, 0x20, 0x46, 0xb3, 0x04, 0x0f, 0xc7, 0x01, 0x16, 0x05, 0x4b, 0x02, 0x04, 0x2c, 0x01, 0x22, 0x5f, 0x64, 0xe1, 0x00, 0x60, 0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x81, 0x03, 0x23, 0x72, 0x2a, 0xeb, 0x05, 0x13, 0x2c, 0x0e, 0x00, 0x50, 0x64, 0x65, 0x73, 0x74, 0x2c, 0xd8, 0x00, 0x03, 0x18, 0x00, 0x42, 0x53, 0x69, 0x7a, 0x65, 0x10, 0x00, 0x70, 0x6d, 0x61, 0x78, 0x44, 0x65, 0x73, 0x74, 0x11, 0x00, 0x25, 0x29, 0x3b, 0x5b, 0x00, 0x25, 0x64, 0x65, 0x5d, 0x00, 0x5f, 0x73, 0x61, 0x66, 0x65, 0x20, 0x5b, 0x00, 0x12, 0x06, 0x1c, 0x05, 0x0b, 0x5f, 0x00, 0x0a, 0x19, 0x00, 0x02, 0xef, 0x02, 0x1f, 0x0a, 0xc2, 0x00, 0x02, 0x12, 0x29, 0xae, 0x06, 0x24, 0x20, 0x43, 0x32, 0x00, 0x36, 0x73, 0x20, 0x27, 0xb2, 0x00, 0x31, 0x27, 0x20, 0x62, 0x89, 0x02, 0x44, 0x66, 0x72, 0x6f, 0x6d, 0xd2, 0x05, 0x03, 0x1f, 0x00, 0x11, 0x27, 0x37, 0x00, 0x01, 0xb9, 0x01, 0xe0, 0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0xd3, 0x0b, 0x10, 0x27, 0xa4, 0x00, 0x14, 0x27, 0x32, 0x00, 0x00, 0x94, 0x0b, 0x57, 0x69, 0x7a, 0x65, 0x20, 0x27, 0xfb, 0x00, 0x29, 0x27, 0x2e, 0x77, 0x00, 0x00, 0x7e, 0x02, 0xa3, 0x69, 0x73, 0x20, 0x67, 0x75, 0x61, 0x72, 0x61, 0x6e, 0x74, 0x13, 0x06, 0x40, 0x73, 0x75, 0x63, 0x63, 0x0b, 0x00, 0x2a, 0x69, 0x66, 0x3b, 0x00, 0x39, 0x20, 0x3e, 0x3d, 0x8f, 0x01, 0x66, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x28, 0xb6, 0x00, 0x12, 0x29, 0x5c, 0x00, 0xf0, 0x11, 0x49, 0x74, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x72, 0x75, 0x6e, 0x73, 0x20, 0x66, 0x61, 0x73, 0x74, 0x65, 0x72, 0x2c, 0x20, 0x73, 0x6f, 0x20, 0x69, 0x74, 0x27, 0x73, 0x20, 0x61, 0x20, 0x72, 0x26, 0x01, 0x30, 0x6d, 0x65, 0x6e, 0x03, 0x0b, 0x30, 0x73, 0x65, 0x74, 0x51, 0x06, 0x03, 0x38, 0x00, 0x12, 0x66, 0x64, 0x0b, 0x03, 0xdb, 0x06, 0x00, 0xf8, 0x02, 0x26, 0x6e, 0x6f, 0x6d, 0x01, 0x05, 0x01, 0x01, 0x03, 0xfd, 0x00, 0x40, 0x20, 0x6d, 0x6f, 0x72, 0x5e, 0x06, 0x29, 0x6d, 0x69, 0xfa, 0x00, 0x41, 0x64, 0x67, 0x65, 0x74, 0x4e, 0x09, 0x09, 0x62, 0x03, 0xf2, 0x04, 0x73, 0x74, 0x6f, 0x70, 0x73, 0x20, 0x2a, 0x69, 0x6d, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x6c, 0x79, 0x2a, 0x3a, 0x07, 0x09, 0x72, 0x00, 0x30, 0x72, 0x65, 0x73, 0x3f, 0x03, 0x72, 0x69, 0x73, 0x20, 0x7a, 0x65, 0x72, 0x6f, 0x96, 0x00, 0x10, 0x41, 0xb4, 0x00, 0x00, 0x15, 0x02, 0x50, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x0e, 0x02, 0x03, 0x6b, 0x00, 0x00, 0x62, 0x07, 0x21, 0x65, 0x6e, 0x2e, 0x00, 0x21, 0x6e, 0x6f, 0x74, 0x03, 0x22, 0x69, 0x64, 0x33, 0x00, 0x10, 0x54, 0x46, 0x0c, 0x05, 0x55, 0x00, 0x90, 0x6e, 0x65, 0x76, 0x65, 0x72, 0x20, 0x77, 0x72, 0x69, 0xd1, 0x01, 0x7a, 0x6f, 0x75, 0x74, 0x73, 0x69, 0x64, 0x65, 0xa9, 0x01, 0x60, 0x2c, 0x20, 0x6e, 0x6f, 0x72, 0x20, 0xcc, 0x01, 0x06, 0x20, 0x00, 0x04, 0xec, 0x00, 0x02, 0x22, 0x00, 0x05, 0xf0, 0x0c, 0x07, 0xd6, 0x02, 0xe0, 0x20, 0x20, 0x3a, 0x20, 0x4d, 0x61, 0x78, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x04, 0x01, 0x05, 0xf7, 0x03, 0x01, 0xb3, 0x03, 0xe5, 0x41, 0x58, 0x5f, 0x49, 0x4e, 0x50, 0x55, 0x54, 0x5f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x41, 0x00, 0x07, 0xd1, 0x01, 0x22, 0x20, 0x3a, 0x33, 0x08, 0x20, 0x6f, 0x72, 0x64, 0x05, 0x42, 0x74, 0x69, 0x61, 0x6c, 0x30, 0x02, 0x25, 0x6f, 0x66, 0x74, 0x02, 0x02, 0xa7, 0x00, 0x12, 0x28, 0x3a, 0x04, 0x01, 0x4c, 0x0d, 0x2e, 0x62, 0x65, 0x78, 0x02, 0x15, 0x29, 0x5e, 0x00, 0x81, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x3a, 0x58, 0x01, 0x12, 0x6e, 0xfb, 0x05, 0x23, 0x6f, 0x66, 0xce, 0x02, 0x00, 0x04, 0x01, 0x32, 0x74, 0x65, 0x6e, 0xc0, 0x01, 0x0b, 0x62, 0x00, 0xe0, 0x6e, 0x65, 0x63, 0x65, 0x73, 0x73, 0x61, 0x72, 0x69, 0x6c, 0x79, 0x20, 0x3c, 0x3d, 0xa6, 0x00, 0x52, 0x4f, 0x75, 0x74, 0x70, 0x75, 0xaf, 0x03, 0x29, 0x0a, 0x20, 0x01, 0x00, 0x40, 0x6f, 0x72, 0x20, 0x30, 0x9d, 0x02, 0x09, 0x11, 0x09, 0x6f, 0x61, 0x69, 0x6c, 0x73, 0x0a, 0x0a, 0xd3, 0x03, 0x00, 0x05, 0x6b, 0x03, 0x0a, 0x9d, 0x03, 0x20, 0x20, 0x3a, 0x2a, 0x01, 0x00, 0xa7, 0x00, 0x72, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x65, 0x0c, 0x01, 0x04, 0x01, 0x01, 0x29, 0x74, 0x68, 0x03, 0x09, 0x01, 0x82, 0x09, 0x02, 0x86, 0x01, 0x0e, 0xe9, 0x03, 0x07, 0x4c, 0x00, 0x04, 0x3f, 0x00, 0x00, 0xd6, 0x00, 0x22, 0x69, 0x6e, 0x08, 0x0e, 0x04, 0xe5, 0x01, 0x0f, 0x45, 0x01, 0x0c, 0x2f, 0x2e, 0x0a, 0x41, 0x01, 0x0e, 0x17, 0x64, 0x78, 0x00, 0x02, 0x46, 0x01, 0x0e, 0x68, 0x00, 0x0e, 0x4b, 0x01, 0x0f, 0x99, 0x04, 0x00, 0x0a, 0x51, 0x01, 0x1f, 0x49, 0xb0, 0x00, 0x01, 0x04, 0xd8, 0x02, 0xd1, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x20, 0x65, 0x6e, 0x6f, 0x75, 0x67, 0x68, 0x2c, 0x82, 0x00, 0x10, 0x64, 0xd5, 0x06, 0x41, 0x77, 0x69, 0x6c, 0x6c, 0x56, 0x03, 0x01, 0x46, 0x03, 0x11, 0x6f, 0xac, 0x01, 0x92, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x04, 0x10, 0x5d, 0x28, 0x3c, 0x30, 0x29, 0x2e, 0x6a, 0x00, 0x01, 0x26, 0x01, 0x02, 0x9e, 0x0b, 0x60, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x00, 0x50, 0x64, 0x65, 0x74, 0x65, 0x63, 0xc3, 0x02, 0x30, 0x6d, 0x61, 0x6c, 0x94, 0x07, 0x00, 0xe4, 0x06, 0x09, 0x9a, 0x03, 0x06, 0x6f, 0x00, 0x05, 0x82, 0x00, 0x00, 0x78, 0x00, 0x03, 0x2e, 0x01, 0xa3, 0x61, 0x20, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0xc3, 0x03, 0x0b, 0x77, 0x00, 0x0a, 0x91, 0x03, 0x11, 0x69, 0x84, 0x0f, 0x03, 0x71, 0x00, 0x30, 0x61, 0x67, 0x61, 0x6c, 0x0a, 0x05, 0x33, 0x05, 0xf0, 0x01, 0x76, 0x65, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x20, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x69, 0x74, 0x73, 0xdd, 0x05, 0x31, 0x63, 0x6c, 0x75, 0x72, 0x00, 0x92, 0x6d, 0x61, 0x6c, 0x69, 0x63, 0x69, 0x6f, 0x75, 0x73, 0x12, 0x0b, 0x7c, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0xe3, 0x00, 0x1f, 0x74, 0xf2, 0x03, 0x03, 0x03, 0x23, 0x01, 0x0c, 0xf2, 0x03, 0x06, 0x21, 0x00, 0x26, 0x69, 0x6e, 0x20, 0x00, 0x02, 0xf8, 0x0a, 0x0f, 0x65, 0x07, 0x19, 0x50, 0x41, 0x64, 0x76, 0x61, 0x6e, 0x3b, 0x08, 0x0e, 0x67, 0x07, 0x0f, 0x04, 0x0b, 0x19, 0x06, 0x36, 0x04, 0x44, 0x53, 0x49, 0x5a, 0x45, 0xd4, 0x00, 0x51, 0x30, 0x78, 0x37, 0x45, 0x30, 0x01, 0x00, 0x02, 0x73, 0x0a, 0xd3, 0x32, 0x20, 0x31, 0x31, 0x33, 0x20, 0x39, 0x32, 0x39, 0x20, 0x32, 0x31, 0x36, 0x9c, 0x02, 0x0b, 0xaf, 0x0a, 0x31, 0x43, 0x4f, 0x4d, 0x69, 0x10, 0x70, 0x42, 0x4f, 0x55, 0x4e, 0x44, 0x28, 0x69, 0x18, 0x03, 0xe4, 0x29, 0x20, 0x20, 0x28, 0x28, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x29, 0x14, 0x00, 0x26, 0x3e, 0x20, 0x14, 0x00, 0x0f, 0x82, 0x00, 0x00, 0x64, 0x3f, 0x20, 0x30, 0x20, 0x3a, 0x20, 0x2d, 0x00, 0x33, 0x2b, 0x20, 0x28, 0x0b, 0x00, 0x40, 0x2f, 0x32, 0x35, 0x35, 0x10, 0x00, 0x3d, 0x31, 0x36, 0x29, 0x65, 0x07, 0x02, 0x98, 0x06, 0x04, 0xf7, 0x03, 0x14, 0x50, 0x46, 0x0d, 0x00, 0x51, 0x02, 0x72, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0xa8, 0x03, 0x01, 0xf8, 0x12, 0x00, 0xcc, 0x0c, 0x08, 0x49, 0x04, 0x34, 0x6d, 0x61, 0x79, 0xac, 0x01, 0x10, 0x69, 0x5a, 0x02, 0x40, 0x22, 0x77, 0x6f, 0x72, 0x11, 0x08, 0xf2, 0x00, 0x61, 0x73, 0x65, 0x22, 0x20, 0x73, 0x63, 0x65, 0x6e, 0x61, 0x72, 0x69, 0x6f, 0x20, 0x28, 0xae, 0x01, 0x01, 0x08, 0x02, 0x08, 0xa5, 0x06, 0x33, 0x69, 0x62, 0x6c, 0x5e, 0x03, 0x0f, 0x74, 0x02, 0x00, 0x22, 0x69, 0x6d, 0x95, 0x03, 0x61, 0x75, 0x73, 0x65, 0x66, 0x75, 0x6c, 0x99, 0x09, 0x03, 0xe9, 0x09, 0x03, 0x05, 0x04, 0x00, 0x2a, 0x00, 0x50, 0x70, 0x75, 0x72, 0x70, 0x6f, 0x0f, 0x08, 0x1f, 0x28, 0x94, 0x03, 0x00, 0x16, 0x73, 0x66, 0x07, 0x5f, 0x4d, 0x61, 0x63, 0x72, 0x6f, 0x6b, 0x01, 0x00, 0x10, 0x29, 0x6c, 0x00, 0x01, 0x80, 0x07, 0x05, 0x69, 0x12, 0x11, 0x66, 0x92, 0x03, 0x41, 0x6d, 0x70, 0x69, 0x6c, 0x4d, 0x00, 0x70, 0x2d, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x65, 0x2e, 0x06, 0x02, 0x5d, 0x00, 0x6f, 0x28, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x8c, 0x00, 0x00, 0x00, 0x39, 0x00, 0x03, 0x0b, 0x0b, 0x03, 0x76, 0x00, 0x36, 0x4e, 0x6f, 0x74, 0x38, 0x01, 0x0f, 0xd6, 0x08, 0x01, 0x05, 0xae, 0x07, 0x02, 0xf9, 0x07, 0x51, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x5e, 0x04, 0x08, 0xc3, 0x00, 0x00, 0xa3, 0x00, 0x0f, 0x4c, 0x08, 0x03, 0x2a, 0x72, 0x63, 0xa0, 0x04, 0x01, 0x67, 0x01, 0x04, 0xee, 0x06, 0x1f, 0x6d, 0xee, 0x06, 0x11, 0x00, 0x36, 0x02, 0x0e, 0x8f, 0x06, 0x04, 0xf8, 0x01, 0x03, 0xda, 0x01, 0x02, 0x85, 0x00, 0x0f, 0xdf, 0x01, 0x06, 0x0f, 0x70, 0x06, 0x00, 0x10, 0x2c, 0x71, 0x06, 0x26, 0x69, 0x6e, 0x3d, 0x00, 0x53, 0x73, 0x20, 0x74, 0x6f, 0x6f, 0x1e, 0x05, 0x3f, 0x28, 0x20, 0x3e, 0x86, 0x00, 0x00, 0x10, 0x29, 0xc5, 0x03, 0x0c, 0xc3, 0x0a, 0x02, 0xe8, 0x00, 0x00, 0x16, 0x00, 0x05, 0xdb, 0x00, 0x0f, 0x27, 0x0a, 0x01, 0x00, 0x3e, 0x01, 0x05, 0xc2, 0x02, 0x10, 0x53, 0x6a, 0x0f, 0x2f, 0x61, 0x73, 0x73, 0x01, 0x04, 0x00, 0xf6, 0x0d, 0x11, 0x74, 0xb6, 0x01, 0x21, 0x77, 0x73, 0xbe, 0x09, 0x41, 0x65, 0x6c, 0x65, 0x63, 0x8c, 0x05, 0x81, 0x22, 0x61, 0x63, 0x63, 0x65, 0x6c, 0x65, 0x72, 0xcd, 0x01, 0x84, 0x22, 0x20, 0x66, 0x61, 0x63, 0x74, 0x6f, 0x72, 0xa3, 0x08, 0x12, 0x65, 0xbc, 0x00, 0x12, 0x72, 0x44, 0x11, 0x07, 0x29, 0x00, 0x02, 0x59, 0x01, 0x03, 0x80, 0x05, 0x02, 0xc5, 0x01, 0x01, 0x23, 0x00, 0x04, 0x24, 0x17, 0x04, 0x70, 0x00, 0x22, 0x73, 0x6f, 0xdf, 0x0f, 0x00, 0x56, 0x06, 0x19, 0x72, 0x30, 0x07, 0x01, 0xc4, 0x14, 0x02, 0x0a, 0x0a, 0x01, 0xf2, 0x09, 0xa0, 0x74, 0x72, 0x61, 0x64, 0x65, 0x2d, 0x6f, 0x66, 0x66, 0x2e, 0x1e, 0x05, 0x00, 0xcf, 0x0c, 0x31, 0x62, 0x65, 0x20, 0x2a, 0x04, 0x53, 0x74, 0x75, 0x6e, 0x65, 0x64, 0xb9, 0x16, 0x42, 0x65, 0x61, 0x63, 0x68, 0x7b, 0x0a, 0x20, 0x73, 0x73, 0xca, 0x05, 0x02, 0xe0, 0x01, 0x02, 0xc5, 0x02, 0x00, 0x7e, 0x05, 0x10, 0x72, 0x82, 0x06, 0x71, 0x6c, 0x79, 0x20, 0x2b, 0x7e, 0x33, 0x25, 0xe8, 0x00, 0x00, 0x0b, 0x0d, 0x03, 0xa4, 0x09, 0x1f, 0x6e, 0xc2, 0x00, 0x00, 0x00, 0x37, 0x07, 0x35, 0x22, 0x31, 0x22, 0x9a, 0x07, 0x03, 0x45, 0x01, 0x7f, 0x72, 0x65, 0x67, 0x75, 0x6c, 0x61, 0x72, 0x4d, 0x01, 0x04, 0x01, 0x4f, 0x00, 0x10, 0x56, 0x3f, 0x00, 0x10, 0x73, 0x3c, 0x07, 0x12, 0x30, 0x79, 0x06, 0x11, 0x62, 0x4a, 0x12, 0x20, 0x6c, 0x61, 0x60, 0x05, 0xb0, 0x62, 0x79, 0x20, 0x41, 0x43, 0x43, 0x45, 0x4c, 0x45, 0x52, 0x41, 0x8a, 0x13, 0xc1, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x20, 0x28, 0x73, 0x65, 0xc2, 0x10, 0x34, 0x2e, 0x63, 0x29, 0xeb, 0x07, 0x00, 0x81, 0x0d, 0x1f, 0x2e, 0x05, 0x02, 0x01, 0x01, 0xdf, 0x01, 0x1f, 0x20, 0xc6, 0x0c, 0x2d, 0x02, 0x11, 0x00, 0x08, 0xf9, 0x00, 0x00, 0x4a, 0x02, 0x0f, 0x4b, 0x02, 0x02, 0x9a, 0x5f, 0x65, 0x78, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x02, 0x0f, 0x52, 0x12, 0x01, 0x30, 0x2c, 0x20, 0x6a, 0xa2, 0x08, 0x22, 0x75, 0x73, 0x64, 0x07, 0x12, 0x20, 0xa6, 0x12, 0x38, 0x61, 0x6c, 0x6c, 0x68, 0x0c, 0x03, 0x2b, 0x04, 0x41, 0x73, 0x70, 0x61, 0x63, 0x89, 0x0e, 0x20, 0x73, 0x74, 0x8c, 0x0b, 0x0a, 0x71, 0x0b, 0x32, 0x61, 0x74, 0x65, 0x9e, 0x01, 0x22, 0x55, 0x73, 0x13, 0x06, 0x00, 0x38, 0x03, 0x24, 0x6f, 0x66, 0x87, 0x00, 0xf4, 0x01, 0x74, 0x6f, 0x20, 0x6b, 0x6e, 0x6f, 0x77, 0x20, 0x68, 0x6f, 0x77, 0x20, 0x6d, 0x75, 0x63, 0x68, 0x54, 0x00, 0x06, 0x20, 0x09, 0x03, 0x6d, 0x00, 0x02, 0xcd, 0x0b, 0x00, 0xee, 0x07, 0x04, 0x13, 0x00, 0x92, 0x20, 0x69, 0x74, 0x20, 0x6f, 0x6e, 0x20, 0x38, 0x2d, 0x7a, 0x06, 0x10, 0x62, 0x53, 0x03, 0x20, 0x61, 0x72, 0x34, 0x11, 0x33, 0x28, 0x75, 0x73, 0xa9, 0x07, 0x30, 0x6c, 0x6f, 0x63, 0x65, 0x00, 0x40, 0x79, 0x70, 0x69, 0x63, 0xbc, 0x00, 0x15, 0x29, 0xf7, 0x02, 0x24, 0x6e, 0x2c, 0x19, 0x05, 0x00, 0x47, 0x00, 0x40, 0x61, 0x73, 0x20, 0x27, 0x9a, 0x10, 0x12, 0x2a, 0xb1, 0x00, 0x11, 0x27, 0x56, 0x0f, 0x0f, 0x16, 0x01, 0x00, 0x09, 0xc7, 0x01, 0x08, 0xc9, 0x00, 0x03, 0xd7, 0x10, 0x04, 0x4f, 0x0e, 0x0f, 0x76, 0x01, 0x03, 0x27, 0x20, 0x28, 0x64, 0x00, 0x2f, 0x2c, 0x20, 0xf8, 0x01, 0x11, 0x05, 0x1e, 0x04, 0x0f, 0xf7, 0x01, 0x25, 0x13, 0x64, 0x2f, 0x00, 0x05, 0xf2, 0x01, 0x10, 0x52, 0x96, 0x08, 0x12, 0x73, 0x03, 0x19, 0x60, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x2c, 0xcc, 0x02, 0x05, 0xed, 0x00, 0x00, 0xee, 0x01, 0x12, 0x73, 0x8a, 0x01, 0x01, 0xd6, 0x06, 0x52, 0x61, 0x73, 0x20, 0x70, 0x6f, 0xd1, 0x06, 0x02, 0x87, 0x0e, 0x0b, 0x93, 0x0c, 0x0f, 0x87, 0x0e, 0x09, 0x0a, 0xdc, 0x0b, 0x05, 0x87, 0x0e, 0x10, 0x74, 0x71, 0x04, 0x1b, 0x74, 0x8a, 0x0e, 0x0a, 0x2d, 0x0d, 0x21, 0x65, 0x69, 0x2e, 0x19, 0x16, 0x63, 0x16, 0x0f, 0x00, 0xaf, 0x00, 0x57, 0x65, 0x6e, 0x74, 0x69, 0x72, 0x15, 0x0d, 0x05, 0x7b, 0x0d, 0x00, 0x7f, 0x00, 0x03, 0x66, 0x00, 0x22, 0x69, 0x66, 0x61, 0x0e, 0x09, 0xb0, 0x0a, 0x13, 0x0a, 0xbf, 0x05, 0x10, 0x66, 0xc6, 0x03, 0x0a, 0x1d, 0x0f, 0x00, 0x63, 0x00, 0x20, 0x6c, 0x65, 0x0a, 0x0e, 0x02, 0x7f, 0x04, 0x0f, 0xfd, 0x00, 0x13, 0x06, 0xed, 0x09, 0x16, 0x2a, 0x9a, 0x03, 0x55, 0x50, 0x74, 0x72, 0x20, 0x3a, 0x2a, 0x04, 0x02, 0x73, 0x1b, 0x02, 0x4a, 0x0f, 0x41, 0x69, 0x6e, 0x64, 0x69, 0xb2, 0x02, 0x01, 0xe6, 0x02, 0x34, 0x61, 0x6e, 0x79, 0x0a, 0x0d, 0x42, 0x68, 0x65, 0x72, 0x65, 0xf2, 0x0d, 0x0a, 0x5c, 0x01, 0x28, 0x74, 0x6f, 0xac, 0x00, 0x0b, 0x5b, 0x0a, 0x08, 0x01, 0x00, 0x36, 0x4e, 0x65, 0x77, 0x02, 0x07, 0x0b, 0xf2, 0x0b, 0x23, 0x6f, 0x6c, 0x1e, 0x07, 0x1e, 0x2e, 0x09, 0x07, 0x2f, 0x4e, 0x62, 0x8d, 0x0d, 0x01, 0x0f, 0x86, 0x0d, 0x04, 0x0a, 0xb1, 0x01, 0x0f, 0x87, 0x0d, 0x17, 0x0e, 0xf3, 0x04, 0x06, 0x90, 0x02, 0x0f, 0xf7, 0x04, 0x12, 0x29, 0x2a, 0x20, 0x5e, 0x01, 0x02, 0xf3, 0x02, 0x0b, 0x8e, 0x00, 0x07, 0xf5, 0x02, 0x2f, 0x64, 0x65, 0x39, 0x07, 0x03, 0x8a, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0xa4, 0x0d, 0x04, 0x16, 0x00, 0x04, 0x00, 0x10, 0x30, 0x72, 0x65, 0x66, 0xbe, 0x04, 0x27, 0x75, 0x6e, 0x5d, 0x0d, 0x00, 0xb1, 0x02, 0x0f, 0x90, 0x0d, 0x0f, 0x06, 0xc1, 0x01, 0x07, 0xd6, 0x0c, 0x04, 0x87, 0x0d, 0x23, 0x69, 0x6e, 0xfb, 0x1b, 0x6c, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x2c, 0x52, 0x0e, 0x01, 0xcb, 0x09, 0x0f, 0x1e, 0x0d, 0x72, 0x1e, 0x44, 0x68, 0x0a, 0x0f, 0xa5, 0x0e, 0x07, 0x42, 0x20, 0x49, 0x74, 0x73, 0xcf, 0x03, 0x05, 0x24, 0x00, 0x42, 0x20, 0x6d, 0x69, 0x6e, 0x5d, 0x09, 0x38, 0x66, 0x20, 0x27, 0x73, 0x01, 0x03, 0xc6, 0x12, 0x02, 0x6f, 0x00, 0x10, 0x6e, 0x3a, 0x0a, 0x1b, 0x3a, 0xef, 0x03, 0x00, 0x73, 0x0f, 0x23, 0x79, 0x20, 0x5a, 0x18, 0x04, 0x02, 0x06, 0x07, 0xd0, 0x05, 0x00, 0x81, 0x0a, 0x20, 0x70, 0x72, 0x94, 0x18, 0x12, 0x6c, 0xd0, 0x1d, 0x2c, 0x65, 0x64, 0x99, 0x18, 0x2a, 0x2e, 0x0a, 0x7d, 0x0d, 0x00, 0xfe, 0x0a, 0x46, 0x20, 0x62, 0x69, 0x74, 0xbc, 0x08, 0x3f, 0x61, 0x6e, 0x20, 0x17, 0x10, 0x02, 0x09, 0x3a, 0x00, 0x30, 0x48, 0x6f, 0x77, 0x20, 0x05, 0x10, 0x2c, 0x15, 0x06, 0x32, 0x64, 0x6f, 0x65, 0xfc, 0x0e, 0x04, 0x29, 0x06, 0x00, 0xb9, 0x03, 0x03, 0x33, 0x0e, 0x01, 0xd9, 0x1d, 0x03, 0x34, 0x0e, 0x11, 0x69, 0x86, 0x04, 0x22, 0x69, 0x6f, 0x1e, 0x07, 0x05, 0xf8, 0x03, 0x01, 0x42, 0x04, 0x03, 0xbe, 0x01, 0x16, 0x28, 0x34, 0x0e, 0x01, 0xd2, 0x05, 0x0a, 0x75, 0x00, 0x00, 0x1a, 0x07, 0x1a, 0x74, 0x28, 0x0c, 0x60, 0x6e, 0x20, 0x74, 0x72, 0x75, 0x73, 0xed, 0x01, 0x71, 0x65, 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0xbe, 0x17, 0x61, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x28, 0x59, 0x00, 0x22, 0x74, 0x6f, 0xe5, 0x01, 0x01, 0x4d, 0x02, 0x04, 0x23, 0x14, 0x15, 0x61, 0x36, 0x00, 0x02, 0x3d, 0x02, 0x19, 0x29, 0xb0, 0x06, 0x2f, 0x64, 0x65, 0x79, 0x08, 0x20, 0x08, 0xc9, 0x01, 0x2f, 0x29, 0x3b, 0x6b, 0x03, 0x01, 0x00, 0x46, 0x01, 0x13, 0x5f, 0x39, 0x12, 0x05, 0x73, 0x03, 0x0a, 0xcf, 0x05, 0x06, 0x2e, 0x00, 0x2d, 0x20, 0x61, 0x4f, 0x11, 0x06, 0x19, 0x06, 0x0a, 0x9e, 0x10, 0x10, 0x27, 0xcc, 0x1b, 0x01, 0xb8, 0x1b, 0x00, 0x43, 0x00, 0x0e, 0xf7, 0x14, 0x0e, 0xf4, 0x10, 0x0d, 0x6a, 0x06, 0x0f, 0xf4, 0x10, 0x00, 0x05, 0x6f, 0x06, 0x07, 0x38, 0x03, 0x11, 0x74, 0x65, 0x02, 0x26, 0x74, 0x6f, 0x3c, 0x03, 0x06, 0x0d, 0x07, 0x24, 0x6f, 0x70, 0x4e, 0x0a, 0x52, 0x61, 0x73, 0x20, 0x73, 0x6f, 0x08, 0x00, 0x03, 0xc3, 0x06, 0x06, 0x9b, 0x12, 0x90, 0x27, 0x20, 0x68, 0x61, 0x73, 0x20, 0x62, 0x65, 0x65, 0x3d, 0x14, 0x00, 0x3b, 0x17, 0x03, 0xaf, 0x08, 0x10, 0x72, 0xc9, 0x17, 0x01, 0x28, 0x20, 0x18, 0x65, 0x1f, 0x05, 0x00, 0x7a, 0x0d, 0x0f, 0xe8, 0x11, 0x14, 0x00, 0xb9, 0x0d, 0x04, 0x57, 0x20, 0x0f, 0xe5, 0x11, 0x2b, 0x12, 0x4e, 0x7a, 0x03, 0x01, 0x69, 0x02, 0x03, 0x6a, 0x00, 0x03, 0x84, 0x0b, 0x1f, 0x3c, 0xd1, 0x00, 0x01, 0x6f, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x01, 0x13, 0x02, 0x07, 0x7d, 0x02, 0x40, 0x62, 0x65, 0x20, 0x73, 0x67, 0x09, 0x2b, 0x65, 0x72, 0x4e, 0x04, 0x65, 0x41, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x80, 0x1c, 0x0c, 0xf9, 0x06, 0x00, 0xf8, 0x06, 0x03, 0xdf, 0x00, 0x0f, 0x1c, 0x12, 0x81, 0x0f, 0xbb, 0x11, 0x03, 0x1c, 0x66, 0xbe, 0x11, 0x00, 0x60, 0x00, 0x02, 0x2b, 0x00, 0x0a, 0xc4, 0x11, 0x2a, 0x6f, 0x66, 0xc7, 0x11, 0x03, 0x91, 0x04, 0x06, 0x65, 0x06, 0x0e, 0x79, 0x12, 0x0f, 0x55, 0x12, 0x03, 0x0e, 0xbf, 0x03, 0x0d, 0x73, 0x03, 0x0f, 0xab, 0x18, 0x27, 0x0c, 0xf4, 0x01, 0x0f, 0xc1, 0x18, 0x0a, 0x0e, 0x85, 0x12, 0x0f, 0xf3, 0x19, 0x11, 0x01, 0xbe, 0x01, 0x00, 0x8a, 0x01, 0x08, 0x69, 0x18, 0x0f, 0x9b, 0x12, 0x00, 0x0f, 0xa4, 0x12, 0x21, 0x60, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x62, 0x0f, 0xdc, 0x5f, 0x55, 0x36, 0x34, 0x20, 0x28, 0x28, 0x31, 0x20, 0x3c, 0x3c, 0x20, 0x28, 0xa8, 0x1a, 0x30, 0x2d, 0x33, 0x29, 0x21, 0x12, 0x2f, 0x34, 0x29, 0x3d, 0x00, 0x04, 0x01, 0xfe, 0x01, 0x1f, 0x28, 0x51, 0x00, 0x00, 0x22, 0x2a, 0x20, 0xe1, 0x0b, 0x60, 0x28, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x05, 0x00, 0x27, 0x29, 0x29, 0x53, 0x1c, 0x02, 0x9a, 0x02, 0x11, 0x5f, 0x71, 0x1b, 0x20, 0x69, 0x6e, 0x92, 0x02, 0x02, 0x9a, 0x03, 0x81, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x11, 0x0d, 0x20, 0x74, 0x72, 0x52, 0x11, 0x02, 0x7a, 0x06, 0x03, 0xcc, 0x02, 0x01, 0x7d, 0x1f, 0x20, 0x69, 0x6d, 0xbe, 0x10, 0x30, 0x61, 0x6e, 0x74, 0x8f, 0x08, 0x32, 0x6e, 0x69, 0x74, 0x96, 0x03, 0x06, 0x3b, 0x00, 0x04, 0xda, 0x0a, 0x12, 0x62, 0x2f, 0x02, 0x31, 0x66, 0x69, 0x72, 0x8c, 0x0d, 0x30, 0x65, 0x20, 0x21, 0x3e, 0x00, 0x03, 0x44, 0x07, 0x29, 0x6f, 0x6e, 0x8d, 0x0d, 0x82, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x3f, 0x03, 0x05, 0x4b, 0x00, 0x12, 0x69, 0xe8, 0x1f, 0x00, 0xf4, 0x25, 0x00, 0x78, 0x0c, 0x02, 0x08, 0x0d, 0x53, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0xc3, 0x1f, 0x00, 0x52, 0x00, 0x06, 0x7c, 0x03, 0x04, 0x2c, 0x00, 0x02, 0x42, 0x0d, 0x60, 0x6c, 0x69, 0x62, 0x6c, 0x7a, 0x34, 0xf3, 0x04, 0x59, 0x61, 0x20, 0x44, 0x4c, 0x4c, 0xa7, 0x1f, 0x20, 0x62, 0x65, 0x21, 0x15, 0x01, 0x7d, 0x02, 0x00, 0x6c, 0x00, 0x01, 0x35, 0x13, 0x66, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0xb7, 0x1f, 0x00, 0x0f, 0x14, 0x73, 0x74, 0x79, 0x70, 0x65, 0x64, 0x65, 0x66, 0x93, 0x00, 0x35, 0x20, 0x7b, 0x20, 0x50, 0x01, 0x20, 0x20, 0x74, 0x63, 0x20, 0x1e, 0x5b, 0x7c, 0x01, 0x49, 0x5d, 0x3b, 0x20, 0x7d, 0x65, 0x01, 0x27, 0x3b, 0x0a, 0x7a, 0x01, 0x52, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5b, 0x02, 0x00, 0x13, 0x00, 0x0e, 0x3e, 0x07, 0x22, 0x74, 0x6f, 0x55, 0x01, 0x27, 0x61, 0x6e, 0x1f, 0x01, 0x08, 0x4f, 0x00, 0x06, 0x1f, 0x01, 0x01, 0xa2, 0x00, 0x00, 0x96, 0x0d, 0x0c, 0x5a, 0x00, 0x28, 0x20, 0x28, 0x31, 0x00, 0x13, 0x2a, 0xbd, 0x01, 0x49, 0x50, 0x74, 0x72, 0x29, 0x8c, 0x00, 0x00, 0xde, 0x1d, 0x23, 0x74, 0x65, 0x33, 0x00, 0x01, 0x82, 0x04, 0x05, 0x9e, 0x0e, 0x00, 0x1d, 0x04, 0x00, 0x87, 0x00, 0x30, 0x69, 0x61, 0x6c, 0x8d, 0x06, 0x2f, 0x61, 0x6e, 0x83, 0x00, 0x07, 0x01, 0x1a, 0x00, 0x34, 0x66, 0x72, 0x65, 0x49, 0x00, 0x21, 0x72, 0x65, 0x67, 0x01, 0x11, 0x73, 0x26, 0x21, 0x02, 0x0f, 0x09, 0x02, 0xb4, 0x21, 0x02, 0x09, 0x06, 0x01, 0x1e, 0x02, 0x11, 0x78, 0x9d, 0x26, 0x01, 0x97, 0x01, 0x22, 0x20, 0x28, 0xa8, 0x01, 0x19, 0x29, 0xa0, 0x01, 0x55, 0x74, 0x68, 0x65, 0x73, 0x65, 0x93, 0x01, 0x44, 0x72, 0x61, 0x74, 0x68, 0x07, 0x09, 0x24, 0x74, 0x68, 0x0c, 0x02, 0x03, 0x86, 0x00, 0x01, 0x5d, 0x00, 0x41, 0x54, 0x68, 0x65, 0x79, 0xfb, 0x01, 0x01, 0x51, 0x1b, 0x42, 0x66, 0x75, 0x74, 0x75, 0xa9, 0x04, 0x20, 0x6f, 0x66, 0x19, 0x04, 0x01, 0x1b, 0x13, 0x02, 0x72, 0x00, 0x02, 0xf1, 0x20, 0x00, 0x0c, 0x00, 0x0a, 0xd1, 0x00, 0x32, 0x69, 0x7a, 0x65, 0xf2, 0x01, 0x0a, 0x3a, 0x01, 0x0c, 0x27, 0x01, 0x08, 0x2c, 0x0f, 0x06, 0x01, 0x00, 0x0b, 0x02, 0x01, 0x0f, 0x7e, 0x01, 0x13, 0x8f, 0x6c, 0x6f, 0x61, 0x64, 0x44, 0x69, 0x63, 0x74, 0x07, 0x02, 0x06, 0x00, 0x21, 0x00, 0x24, 0x20, 0x61, 0xed, 0x00, 0x21, 0x64, 0x69, 0x19, 0x00, 0x00, 0x86, 0x22, 0x01, 0x42, 0x08, 0x06, 0x64, 0x00, 0x01, 0x95, 0x03, 0x11, 0x41, 0xdf, 0x09, 0x26, 0x65, 0x76, 0x86, 0x05, 0x04, 0xcc, 0x0d, 0x50, 0x66, 0x6f, 0x72, 0x67, 0x6f, 0x27, 0x0d, 0x12, 0x2c, 0x75, 0x03, 0x16, 0x27, 0x4a, 0x00, 0x12, 0x27, 0x25, 0x00, 0x30, 0x72, 0x65, 0x6d, 0xe4, 0x28, 0x28, 0x69, 0x6e, 0xaf, 0x01, 0x32, 0x4c, 0x6f, 0x61, 0x87, 0x06, 0x05, 0x10, 0x1a, 0x12, 0x30, 0x96, 0x15, 0x31, 0x6c, 0x6f, 0x77, 0xf8, 0x06, 0x00, 0xea, 0x1f, 0x03, 0x00, 0x08, 0x07, 0x9c, 0x00, 0x13, 0x73, 0x8c, 0x05, 0x03, 0x2c, 0x07, 0x0c, 0xe4, 0x07, 0x50, 0x36, 0x34, 0x20, 0x4b, 0x42, 0x5d, 0x20, 0x06, 0x1b, 0x06, 0x04, 0x08, 0x01, 0x0f, 0x37, 0x01, 0x06, 0x0a, 0x6d, 0x10, 0x06, 0x6c, 0x00, 0x02, 0xf3, 0x05, 0x00, 0x10, 0x00, 0x07, 0xe0, 0x09, 0x2f, 0x20, 0x2a, 0xc4, 0x10, 0x00, 0x00, 0x74, 0x02, 0x31, 0x69, 0x6e, 0x75, 0xae, 0x02, 0x04, 0xcd, 0x05, 0x08, 0x65, 0x24, 0x00, 0xae, 0x04, 0x63, 0x27, 0x73, 0x72, 0x63, 0x27, 0x2c, 0x3b, 0x04, 0x01, 0x41, 0x01, 0x01, 0x96, 0x0a, 0x04, 0x54, 0x01, 0x2d, 0x6c, 0x79, 0x4a, 0x08, 0x10, 0x73, 0x5b, 0x04, 0x07, 0xfb, 0x00, 0x25, 0x74, 0x6f, 0xe3, 0x20, 0x0d, 0x19, 0x21, 0x02, 0x02, 0x03, 0x07, 0x39, 0x05, 0x19, 0x50, 0xac, 0x01, 0x04, 0x50, 0x00, 0x10, 0x72, 0xdf, 0x13, 0x33, 0x73, 0x75, 0x6d, 0xc4, 0x1e, 0x13, 0x74, 0xc3, 0x01, 0x00, 0x4c, 0x00, 0x00, 0xa4, 0x00, 0x01, 0x41, 0x2b, 0x15, 0x6e, 0xa5, 0x0b, 0x01, 0x50, 0x05, 0x27, 0x27, 0x64, 0x11, 0x10, 0x0f, 0x99, 0x1b, 0x09, 0x01, 0x36, 0x25, 0x00, 0x21, 0x07, 0x03, 0xc4, 0x0e, 0x0f, 0xbd, 0x16, 0x0a, 0x00, 0x74, 0x01, 0x0f, 0x5e, 0x1f, 0x0f, 0x02, 0x45, 0x08, 0x07, 0x24, 0x1f, 0x04, 0x67, 0x00, 0x32, 0x6e, 0x6f, 0x74, 0x1c, 0x00, 0x2d, 0x69, 0x66, 0x85, 0x25, 0x03, 0x13, 0x1f, 0x25, 0x66, 0x69, 0xfc, 0x10, 0x07, 0xc1, 0x00, 0x02, 0x3f, 0x02, 0x0d, 0xf6, 0x1e, 0x02, 0x4d, 0x00, 0x07, 0xe4, 0x1e, 0x00, 0x79, 0x02, 0x00, 0xd8, 0x05, 0x03, 0xe4, 0x1e, 0x07, 0x4f, 0x02, 0x0f, 0xfa, 0x01, 0x03, 0x0f, 0x5d, 0x02, 0x14, 0x35, 0x73, 0x72, 0x63, 0x7f, 0x08, 0x05, 0xbe, 0x14, 0x2a, 0x72, 0x63, 0x61, 0x08, 0x0f, 0xc3, 0x12, 0x09, 0x07, 0x63, 0x07, 0x34, 0x61, 0x76, 0x65, 0xdf, 0x03, 0x2f, 0x49, 0x66, 0x48, 0x02, 0x04, 0x06, 0xfd, 0x01, 0x04, 0xab, 0x1c, 0x0a, 0x68, 0x01, 0x03, 0x9a, 0x03, 0x51, 0x61, 0x76, 0x61, 0x69, 0x6c, 0xd2, 0x26, 0x27, 0x61, 0x74, 0x57, 0x05, 0x14, 0x20, 0xe5, 0x18, 0x00, 0x64, 0x00, 0x00, 0x70, 0x00, 0x14, 0x20, 0x54, 0x01, 0x20, 0x61, 0x20, 0x66, 0x09, 0x21, 0x72, 0x20, 0xf0, 0x15, 0x23, 0x20, 0x28, 0xdd, 0x00, 0x41, 0x61, 0x66, 0x65, 0x42, 0x67, 0x01, 0x01, 0xde, 0x23, 0x03, 0x53, 0x0b, 0x00, 0x34, 0x07, 0x55, 0x64, 0x6f, 0x6e, 0x27, 0x74, 0x4e, 0x27, 0x00, 0x65, 0x07, 0x09, 0x9a, 0x03, 0xa0, 0x28, 0x29, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72, 0x77, 0x61, 0x05, 0x10, 0x07, 0x73, 0x07, 0x08, 0x94, 0x04, 0x27, 0x73, 0x20, 0x99, 0x20, 0x00, 0xf6, 0x23, 0x63, 0x62, 0x6c, 0x65, 0x2c, 0x20, 0x79, 0xed, 0x28, 0x06, 0x3e, 0x0a, 0x05, 0x5e, 0x00, 0x0f, 0xa9, 0x01, 0x03, 0x29, 0x28, 0x29, 0x5a, 0x04, 0x00, 0xd6, 0x00, 0x1c, 0x64, 0x60, 0x04, 0x0f, 0x5f, 0x04, 0x07, 0x05, 0x0d, 0x04, 0x15, 0x2c, 0xda, 0x11, 0x01, 0xcd, 0x1d, 0x09, 0x22, 0x02, 0x04, 0x9a, 0x01, 0x0f, 0x71, 0x04, 0x09, 0x0b, 0x31, 0x01, 0x0e, 0x6b, 0x04, 0x0e, 0x53, 0x0a, 0x0f, 0x54, 0x0a, 0x1b, 0x06, 0xa7, 0x0a, 0x0f, 0x56, 0x0a, 0x2a, 0x00, 0x63, 0x1d, 0x0e, 0x1b, 0x0a, 0x65, 0x44, 0x45, 0x43, 0x4f, 0x44, 0x45, 0x0d, 0x0a, 0x2f, 0x20, 0x34, 0x24, 0x00, 0x0a, 0x0c, 0x45, 0x0a, 0x0b, 0x3e, 0x00, 0x05, 0x4b, 0x0a, 0x04, 0xe3, 0x1c, 0x18, 0x20, 0x54, 0x0a, 0x0d, 0x21, 0x09, 0x0e, 0x26, 0x00, 0x0d, 0x2a, 0x09, 0x0a, 0x61, 0x00, 0x0b, 0x30, 0x09, 0x11, 0x44, 0x59, 0x0d, 0x00, 0x36, 0x09, 0x0c, 0xaf, 0x0a, 0x04, 0x1a, 0x00, 0x0f, 0xb5, 0x0a, 0x23, 0x0f, 0xa9, 0x0a, 0x08, 0x23, 0x75, 0x73, 0x4e, 0x0a, 0x15, 0x5f, 0x42, 0x09, 0x02, 0x6c, 0x00, 0x12, 0x20, 0xde, 0x1c, 0x20, 0x73, 0x65, 0x03, 0x03, 0x0f, 0xcf, 0x0a, 0x02, 0x0f, 0xd9, 0x08, 0x11, 0x04, 0xd8, 0x08, 0x30, 0x70, 0x72, 0x65, 0x94, 0x03, 0x02, 0x11, 0x27, 0x2f, 0x6f, 0x66, 0x7e, 0x0a, 0x03, 0x01, 0x99, 0x0a, 0x0f, 0xd3, 0x08, 0x2f, 0x04, 0x2c, 0x01, 0x05, 0x30, 0x03, 0x24, 0x74, 0x68, 0x44, 0x00, 0x1f, 0x2e, 0xff, 0x09, 0x01, 0x03, 0xf0, 0x00, 0x0f, 0x05, 0x0a, 0x17, 0x06, 0x61, 0x00, 0x0f, 0x0b, 0x0a, 0x07, 0x03, 0x55, 0x00, 0x0f, 0x11, 0x0a, 0x04, 0x2e, 0x2f, 0x0a, 0x4e, 0x00, 0x0f, 0x99, 0x00, 0x05, 0x0e, 0x77, 0x09, 0x0f, 0x7d, 0x09, 0x05, 0x03, 0x74, 0x00, 0x1f, 0x28, 0x5c, 0x00, 0x05, 0x02, 0x14, 0x00, 0x0b, 0xab, 0x05, 0x0a, 0xf6, 0x01, 0x0f, 0x98, 0x0b, 0x08, 0x03, 0xe6, 0x02, 0x02, 0xfb, 0x16, 0x01, 0xe8, 0x16, 0x03, 0x7f, 0x25, 0x06, 0xa2, 0x04, 0x01, 0x5f, 0x01, 0x12, 0x53, 0x14, 0x26, 0x0f, 0x3d, 0x09, 0x04, 0x21, 0x20, 0x28, 0xc9, 0x1b, 0x02, 0xf4, 0x28, 0x02, 0xd0, 0x1b, 0x4a, 0x73, 0x65, 0x74, 0x29, 0x54, 0x09, 0x10, 0x31, 0xbd, 0x04, 0x3f, 0x4f, 0x4b, 0x2c, 0xc6, 0x04, 0x06, 0x2f, 0x65, 0x74, 0xf2, 0x00, 0x19, 0x02, 0x14, 0x00, 0x0f, 0x4b, 0x09, 0x1a, 0x17, 0x2a, 0x95, 0x05, 0x05, 0x1a, 0x13, 0x00, 0x97, 0x0b, 0x05, 0xa3, 0x10, 0x05, 0xc2, 0x2d, 0x02, 0xda, 0x00, 0x0b, 0x29, 0x12, 0x80, 0x6f, 0x66, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x39, 0x29, 0x03, 0xe1, 0x08, 0x54, 0x69, 0x6e, 0x20, 0x22, 0x73, 0x04, 0x05, 0x10, 0x22, 0x6f, 0x14, 0x03, 0x4b, 0x12, 0x16, 0x50, 0x1f, 0x07, 0x04, 0x39, 0x12, 0x03, 0x64, 0x09, 0x10, 0x2a, 0xd4, 0x08, 0x1f, 0x2a, 0x0a, 0x07, 0x02, 0x01, 0x0d, 0x21, 0x02, 0x0a, 0x07, 0x05, 0x6b, 0x13, 0x03, 0x9b, 0x01, 0x00, 0x3c, 0x03, 0x08, 0xa8, 0x11, 0x40, 0x20, 0x28, 0x75, 0x70, 0xb1, 0x01, 0x04, 0x80, 0x0a, 0x25, 0x20, 0x20, 0xb7, 0x03, 0x05, 0x48, 0x03, 0x10, 0x72, 0xd3, 0x00, 0x02, 0x88, 0x08, 0x17, 0x73, 0x26, 0x24, 0x0b, 0x5b, 0x09, 0x03, 0xde, 0x19, 0x02, 0x10, 0x01, 0x51, 0x2d, 0x20, 0x45, 0x78, 0x61, 0xb8, 0x0e, 0x01, 0xd2, 0x01, 0x01, 0x3a, 0x25, 0x59, 0x61, 0x73, 0x20, 0x65, 0x6e, 0x3c, 0x00, 0x03, 0x1d, 0x1e, 0x01, 0x23, 0x00, 0x30, 0x75, 0x70, 0x64, 0x5b, 0x03, 0x62, 0x72, 0x75, 0x6c, 0x65, 0x20, 0x28, 0xfa, 0x07, 0x07, 0x2c, 0x16, 0x22, 0x61, 0x74, 0x26, 0x00, 0x04, 0xcf, 0x00, 0x14, 0x73, 0x01, 0x13, 0x23, 0x49, 0x6e, 0x90, 0x1d, 0x00, 0xaf, 0x00, 0x02, 0x3c, 0x12, 0x05, 0x86, 0x01, 0x16, 0x26, 0x70, 0x00, 0x07, 0xc3, 0x00, 0x01, 0x77, 0x07, 0x32, 0x68, 0x61, 0x76, 0xfa, 0x15, 0x04, 0x97, 0x0b, 0x04, 0x07, 0x24, 0x42, 0x76, 0x65, 0x72, 0x79, 0xfd, 0x12, 0x30, 0x20, 0x6f, 0x6e, 0x49, 0x07, 0x23, 0x20, 0x3c, 0x1c, 0x01, 0x13, 0x2e, 0xd9, 0x00, 0x14, 0x4c, 0x5a, 0x1f, 0x2e, 0x61, 0x6e, 0xd0, 0x00, 0x2a, 0x62, 0x79, 0x33, 0x17, 0x40, 0x6d, 0x61, 0x78, 0x42, 0xcc, 0x00, 0x01, 0x59, 0x0a, 0x01, 0xb0, 0x04, 0x07, 0x36, 0x17, 0x1a, 0x20, 0x1f, 0x00, 0x01, 0x2a, 0x08, 0x36, 0x70, 0x6c, 0x65, 0x65, 0x34, 0x30, 0x64, 0x65, 0x70, 0x4b, 0x29, 0x32, 0x6e, 0x74, 0x2e, 0x6e, 0x1f, 0x0d, 0xe5, 0x22, 0x00, 0x46, 0x08, 0x01, 0xa9, 0x16, 0x18, 0x64, 0xdc, 0x1c, 0x05, 0xeb, 0x08, 0x34, 0x69, 0x6e, 0x67, 0x63, 0x02, 0x1f, 0x2e, 0x30, 0x01, 0x03, 0x27, 0x65, 0x6e, 0x55, 0x13, 0x0b, 0xda, 0x01, 0x41, 0x73, 0x20, 0x64, 0x6f, 0x7b, 0x09, 0x04, 0x00, 0x09, 0x00, 0x17, 0x14, 0x94, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x0d, 0x15, 0x02, 0xbe, 0x1d, 0x0f, 0x69, 0x01, 0x1f, 0x0f, 0x64, 0x01, 0x0a, 0x40, 0x5f, 0x41, 0x74, 0x20, 0x1c, 0x05, 0x22, 0x74, 0x5f, 0x19, 0x00, 0x43, 0x20, 0x2b, 0x20, 0x38, 0xda, 0x08, 0x19, 0x2b, 0x35, 0x01, 0x0f, 0xd7, 0x00, 0x7e, 0x17, 0x6c, 0x1e, 0x02, 0x0b, 0x79, 0x00, 0x02, 0xac, 0x00, 0x32, 0x57, 0x68, 0x65, 0x5d, 0x14, 0x02, 0xca, 0x0f, 0x0a, 0x8c, 0x37, 0x02, 0x99, 0x18, 0x03, 0x9d, 0x1c, 0x12, 0x2c, 0xbb, 0x0a, 0x01, 0xd3, 0x1d, 0x00, 0xda, 0x17, 0x00, 0x90, 0x2e, 0x02, 0x7f, 0x28, 0x02, 0xba, 0x03, 0x01, 0x24, 0x0b, 0x07, 0xd6, 0x0a, 0x04, 0x85, 0x02, 0x05, 0x53, 0x1f, 0x05, 0xa1, 0x1c, 0x02, 0xfc, 0x03, 0x11, 0x69, 0xaf, 0x14, 0x02, 0x39, 0x0a, 0x0f, 0xda, 0x07, 0x06, 0x2f, 0x28, 0x29, 0x9e, 0x14, 0x09, 0x0e, 0x36, 0x0c, 0x0f, 0x55, 0x05, 0x0b, 0x0f, 0x70, 0x2d, 0x3b, 0x0f, 0xf3, 0x18, 0x04, 0x0f, 0x96, 0x00, 0x42, 0x0c, 0x22, 0x19, 0x00, 0xf8, 0x05, 0x05, 0x87, 0x27, 0x0f, 0xe8, 0x05, 0x00, 0x41, 0x3a, 0x0a, 0x2a, 0x5f, 0x55, 0x01, 0x03, 0x18, 0x0c, 0x0f, 0x17, 0x06, 0x0c, 0x48, 0x77, 0x6f, 0x72, 0x6b, 0xba, 0x22, 0x02, 0xb4, 0x01, 0x00, 0x0c, 0x01, 0x14, 0x62, 0x0d, 0x18, 0x2f, 0x6f, 0x66, 0xa0, 0x01, 0x03, 0x03, 0xa8, 0x38, 0x02, 0xae, 0x22, 0x0b, 0x0f, 0x01, 0x19, 0x78, 0x2f, 0x0c, 0x26, 0x20, 0x20, 0x2c, 0x09, 0xc2, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x2d, 0x61, 0x6c, 0x6f, 0x6e, 0x65, 0x2e, 0x16, 0x00, 0x07, 0xdc, 0x0c, 0x00, 0xb0, 0x28, 0x03, 0x80, 0x05, 0x0f, 0xcc, 0x08, 0x0c, 0x1f, 0x2e, 0x1e, 0x02, 0x09, 0x05, 0x00, 0x01, 0x0f, 0x69, 0x2f, 0x3a, 0x0e, 0x9b, 0x07, 0x5d, 0x53, 0x74, 0x61, 0x72, 0x74, 0x9a, 0x07, 0x0f, 0x1e, 0x02, 0x05, 0x0e, 0x96, 0x00, 0x0f, 0x1b, 0x1b, 0x12, 0x0f, 0x7b, 0x00, 0x19, 0x0f, 0xce, 0x29, 0x1b, 0x40, 0x4f, 0x62, 0x73, 0x6f, 0x9d, 0x20, 0x0f, 0xce, 0x29, 0x20, 0x10, 0x2f, 0x07, 0x32, 0x00, 0xd3, 0x2c, 0x00, 0xab, 0x01, 0x30, 0x57, 0x61, 0x72, 0x43, 0x33, 0x22, 0x73, 0x20, 0x19, 0x00, 0x15, 0x53, 0xdb, 0x19, 0x44, 0x73, 0x65, 0x20, 0x77, 0x1c, 0x00, 0x10, 0x6d, 0x06, 0x0e, 0x00, 0xc9, 0x34, 0x01, 0xcd, 0x1d, 0x71, 0x70, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x23, 0x04, 0x02, 0x0f, 0x04, 0x02, 0x22, 0x36, 0x00, 0x3d, 0x16, 0x05, 0x14, 0x21, 0x00, 0x08, 0x1a, 0x11, 0x69, 0xa7, 0x0e, 0x00, 0x4d, 0x00, 0x02, 0x2d, 0x00, 0x01, 0xa8, 0x07, 0x64, 0x2d, 0x57, 0x6e, 0x6f, 0x2d, 0x64, 0x80, 0x00, 0x72, 0x64, 0x2d, 0x64, 0x65, 0x63, 0x6c, 0x61, 0xe3, 0x0f, 0x02, 0xce, 0x1d, 0x42, 0x67, 0x63, 0x63, 0x0a, 0x3c, 0x20, 0x70, 0x5f, 0x43, 0x52, 0x54, 0x5f, 0x53, 0x45, 0x2f, 0x39, 0xc0, 0x5f, 0x4e, 0x4f, 0x5f, 0x57, 0x41, 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x53, 0xe8, 0x08, 0x68, 0x56, 0x69, 0x73, 0x75, 0x61, 0x6c, 0x7f, 0x28, 0x18, 0x2e, 0xfe, 0x37, 0x01, 0x7c, 0x26, 0x07, 0x95, 0x0d, 0x94, 0x44, 0x45, 0x50, 0x52, 0x45, 0x43, 0x41, 0x54, 0x45, 0x45, 0x00, 0x00, 0x95, 0x25, 0x61, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x2e, 0x97, 0x2a, 0x30, 0x69, 0x66, 0x6e, 0x67, 0x0d, 0x0f, 0x2b, 0x00, 0x0b, 0x3e, 0x0a, 0x23, 0x20, 0x54, 0x00, 0x0f, 0x29, 0x00, 0x10, 0x34, 0x47, 0x43, 0x43, 0x04, 0x35, 0x00, 0xe0, 0x37, 0x92, 0x47, 0x4e, 0x55, 0x43, 0x5f, 0x5f, 0x20, 0x2a, 0x20, 0x22, 0x35, 0x03, 0x11, 0x00, 0x01, 0x36, 0x35, 0x30, 0x5f, 0x5f, 0x29, 0x3c, 0x00, 0x4c, 0x69, 0x66, 0x20, 0x28, 0x39, 0x00, 0xa4, 0x3e, 0x3d, 0x20, 0x34, 0x30, 0x35, 0x29, 0x20, 0x7c, 0x7c, 0x2c, 0x38, 0x00, 0x2b, 0x38, 0x43, 0x6c, 0x61, 0x6e, 0x67, 0x35, 0x00, 0x0f, 0x9c, 0x00, 0x03, 0x23, 0x44, 0x28, 0xbc, 0x01, 0x62, 0x29, 0x20, 0x5f, 0x5f, 0x61, 0x74, 0x42, 0x3c, 0x56, 0x65, 0x5f, 0x5f, 0x28, 0x28, 0x83, 0x01, 0x05, 0x23, 0x00, 0x11, 0x29, 0x49, 0x00, 0x2f, 0x65, 0x6c, 0x80, 0x00, 0x04, 0x3f, 0x33, 0x30, 0x31, 0x6a, 0x00, 0x2c, 0x07, 0x61, 0x00, 0x05, 0xc5, 0x00, 0x21, 0x4d, 0x53, 0x65, 0x00, 0x0f, 0x5a, 0x00, 0x15, 0x00, 0x2f, 0x02, 0x00, 0x0c, 0x20, 0x0f, 0xc0, 0x00, 0x02, 0x02, 0x5e, 0x00, 0x22, 0x73, 0x65, 0x4c, 0x00, 0x03, 0x65, 0x39, 0x03, 0x1e, 0x00, 0x23, 0x28, 0x22, 0xa7, 0x01, 0x37, 0x3a, 0x20, 0x59, 0xdd, 0x38, 0x05, 0x2d, 0x09, 0x0b, 0x74, 0x00, 0x02, 0x35, 0x37, 0x00, 0xa4, 0x0c, 0x02, 0x18, 0x2b, 0x3f, 0x65, 0x72, 0x22, 0xa3, 0x00, 0x12, 0x01, 0x83, 0x00, 0x01, 0xa9, 0x39, 0x02, 0xb0, 0x39, 0x00, 0x0d, 0x2d, 0x0f, 0x2e, 0x02, 0x0b, 0x12, 0x20, 0xc1, 0x38, 0x06, 0xd2, 0x03, 0x0f, 0xc6, 0x39, 0x02, 0x03, 0xa0, 0x03, 0x02, 0x0c, 0x06, 0x07, 0x1a, 0x0c, 0x00, 0xb6, 0x0e, 0x44, 0x6c, 0x61, 0x6e, 0x6e, 0xd4, 0x14, 0x36, 0x61, 0x72, 0x74, 0xb1, 0x39, 0x05, 0xc1, 0x03, 0xf2, 0x01, 0x62, 0x79, 0x20, 0x72, 0x31, 0x33, 0x31, 0x20, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x6d, 0x47, 0x12, 0x0f, 0xd8, 0x13, 0x00, 0x0b, 0xfe, 0x0d, 0x0f, 0x81, 0x28, 0x1c, 0x0f, 0xe7, 0x26, 0x01, 0x03, 0x7f, 0x33, 0x02, 0x4c, 0x1c, 0x0f, 0xd2, 0x28, 0x26, 0x07, 0xeb, 0x31, 0x0f, 0x64, 0x00, 0x00, 0x00, 0x59, 0x04, 0x02, 0x47, 0x27, 0x0b, 0xbf, 0x00, 0x0f, 0x55, 0x27, 0x27, 0x0f, 0xcb, 0x00, 0x0e, 0x07, 0x75, 0x00, 0x0f, 0xbc, 0x27, 0x31, 0x0f, 0xe1, 0x00, 0x0b, 0x05, 0x9d, 0x08, 0x0c, 0xe1, 0x00, 0x0e, 0x50, 0x19, 0x0e, 0x7c, 0x15, 0x0f, 0xf1, 0x00, 0x35, 0x06, 0x85, 0x00, 0x0f, 0x77, 0x00, 0x38, 0x0f, 0x01, 0x01, 0x03, 0x09, 0x10, 0x03, 0x2f, 0x64, 0x65, 0x12, 0x03, 0x17, 0x30, 0x20, 0x6e, 0x61, 0xf3, 0x22, 0x13, 0x61, 0x6c, 0x2a, 0x03, 0xbf, 0x27, 0x06, 0x2c, 0x04, 0x01, 0xd3, 0x0a, 0x01, 0x6d, 0x0e, 0x21, 0x6e, 0x6f, 0x3f, 0x13, 0x41, 0x65, 0x72, 0x20, 0x62, 0x15, 0x1b, 0x02, 0x6d, 0x20, 0x05, 0xeb, 0x08, 0x01, 0xcd, 0x19, 0x05, 0x20, 0x2f, 0x01, 0xfb, 0x0a, 0x04, 0x25, 0x2f, 0x31, 0x61, 0x74, 0x69, 0x83, 0x3b, 0x03, 0x17, 0x28, 0x20, 0x6f, 0x6c, 0x0d, 0x44, 0x03, 0x43, 0x3d, 0x15, 0x73, 0xe1, 0x0d, 0x36, 0x5a, 0x34, 0x5f, 0x30, 0x26, 0x0c, 0x63, 0x2c, 0x0f, 0x63, 0x08, 0x00, 0x0f, 0x38, 0x00, 0x02, 0x30, 0x5f, 0x75, 0x6e, 0x03, 0x2b, 0x16, 0x6e, 0x1d, 0x01, 0x0f, 0x4a, 0x00, 0x0c, 0x00, 0x43, 0x09, 0x03, 0xc8, 0x00, 0x08, 0x16, 0x01, 0x00, 0x55, 0x20, 0x10, 0x6f, 0x4d, 0x14, 0x04, 0x21, 0x0c, 0x14, 0x77, 0x9e, 0x07, 0x22, 0x64, 0x3b, 0xd7, 0x26, 0x01, 0x03, 0x05, 0x00, 0xaa, 0x07, 0x02, 0xfa, 0x00, 0x03, 0x1b, 0x1e, 0x21, 0x72, 0x65, 0xd6, 0x07, 0x02, 0x2d, 0x05, 0x20, 0x68, 0x65, 0xed, 0x13, 0x04, 0x43, 0x25, 0x21, 0x68, 0x69, 0x6c, 0x2d, 0x08, 0xac, 0x37, 0x04, 0x27, 0x23, 0x02, 0x18, 0x0c, 0x02, 0x44, 0x08, 0x08, 0x7a, 0x00, 0x00, 0x7b, 0x01, 0x21, 0x69, 0x67, 0x9a, 0x04, 0x30, 0x74, 0x6f, 0x20, 0x72, 0x10, 0x21, 0x74, 0x61, 0xf6, 0x3e, 0x01, 0xc1, 0x0d, 0x02, 0xcf, 0x01, 0x04, 0x84, 0x02, 0x07, 0x3c, 0x01, 0x0f, 0x72, 0x09, 0x13, 0x07, 0x3f, 0x02, 0x0e, 0x4b, 0x00, 0x0f, 0x4f, 0x01, 0x01, 0x0f, 0x6c, 0x28, 0x17, 0x3f, 0x20, 0x69, 0x73, 0xaa, 0x02, 0x05, 0x0d, 0xbd, 0x05, 0x05, 0x80, 0x11, 0x06, 0xa8, 0x0b, 0x11, 0x3b, 0xd0, 0x14, 0x00, 0xd7, 0x3d, 0x06, 0x1d, 0x00, 0x06, 0x24, 0x3e, 0x14, 0x77, 0xcb, 0x0d, 0x05, 0x3b, 0x09, 0x03, 0xbc, 0x13, 0x07, 0x5d, 0x06, 0x11, 0x22, 0x30, 0x46, 0x0c, 0x2d, 0x1d, 0x14, 0x29, 0x4d, 0x1f, 0x32, 0x22, 0x29, 0x20, 0x82, 0x04, 0x06, 0xdf, 0x13, 0x04, 0x96, 0x18, 0x01, 0x68, 0x03, 0x03, 0x97, 0x18, 0x1f, 0x3b, 0x57, 0x00, 0x1f, 0x02, 0x12, 0x14, 0x08, 0xd2, 0x2c, 0x00, 0x23, 0x00, 0x09, 0xd8, 0x2c, 0x0f, 0x54, 0x00, 0x05, 0x07, 0x31, 0x1f, 0x09, 0x53, 0x00, 0x07, 0x54, 0x00, 0x07, 0x23, 0x00, 0x06, 0x53, 0x00, 0x06, 0x48, 0x05, 0x0f, 0xc1, 0x00, 0x18, 0x04, 0x75, 0x18, 0x0a, 0x6a, 0x00, 0x23, 0x20, 0x20, 0x45, 0x00, 0x01, 0x23, 0x00, 0x56, 0x6c, 0x69, 0x64, 0x65, 0x49, 0x4e, 0x00, 0x09, 0xb6, 0x05, 0x2f, 0x29, 0x3b, 0xc6, 0x01, 0x05, 0x0f, 0x77, 0x0d, 0x00, 0x0f, 0xa0, 0x01, 0x03, 0x0f, 0xcd, 0x0c, 0x0b, 0x0d, 0x56, 0x01, 0x0f, 0xfb, 0x0c, 0x01, 0x00, 0x4f, 0x04, 0xbf, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x36, 0x34, 0x6b, 0x20, 0x28, 0x3b, 0x1b, 0x0d, 0x0f, 0xfb, 0x0c, 0x05, 0x05, 0xfe, 0x2a, 0x0f, 0xa6, 0x00, 0x10, 0x0a, 0xdd, 0x0c, 0x0f, 0xa6, 0x00, 0x0d, 0x01, 0x2e, 0x00, 0x0f, 0xa6, 0x00, 0x1c, 0x0d, 0x04, 0x0f, 0x0f, 0xef, 0x42, 0x07, 0x90, 0x7d, 0x0a, 0x23, 0x65, 0x6e, 0x64, 0x69, 0x66, 0x0a, }; static unsigned char buf[18830]; int main() { unsigned long cksum = adler32(0, NULL, 0); decompress_lz4(compressed, buf, 18830); cksum = adler32(cksum, buf, 18830); return cksum == 0xf748269d ? 0 : 1; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/mult1.c��������������������������������������������������������������������������0000664�0000000�0000000�00000006524�13473601511�0015163�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> #define TESTLIT 0x05 unsigned char success=0; unsigned char failures=0; unsigned char dummy=0; signed char c1,c2,c3; unsigned char uc1,uc2,uc3; unsigned int ui1,ui2,ui3; signed int i1,i2; void done() { dummy++; } void m1(void) { c1 = c1*5; /* char = char * lit */ c2 = c1 *c3; /* char = char * char */ uc1= uc1*5; /* uchar = uchar * lit * uc2=uc1*uc3; /* uchar = uchar * uchar */ if(c2 != 25) failures++; } void m2(unsigned char uc) { uc2 = uc1 * uc; if(uc2 != 0x20) failures++; } void m3(unsigned char uc) { volatile unsigned char vuc; /* uchar = uchar * lit */ /* testing literal multiply with same source and destination */ vuc = uc; uc2 = 0; uc1 = vuc; uc1 = uc1*1; if( uc1 != (uc2+=TESTLIT) ) failures++; uc1 = vuc; uc1 = uc1*2; if( uc1 != (uc2+=TESTLIT) ) failures++; uc1 = vuc; uc1 = uc1*3; if( uc1 != (uc2+=TESTLIT) ) failures++; uc1 = vuc; uc1 = uc1*4; if( uc1 != (uc2+=TESTLIT) ) failures++; uc1 = vuc; uc1 = uc1*5; if( uc1 != (uc2+=TESTLIT) ) failures++; uc1 = vuc; uc1 = uc1*6; if( uc1 != (uc2+=TESTLIT) ) failures++; uc1 = vuc; uc1 = uc1*7; if( uc1 != (uc2+=TESTLIT) ) failures++; uc1 = vuc; uc1 = uc1*8; if( uc1 != (uc2+=TESTLIT) ) failures++; uc1 = vuc; uc1 = uc1*9; if( uc1 != (uc2+=TESTLIT) ) failures++; uc1 = vuc; uc1 = uc1*10; if( uc1 != (uc2+=TESTLIT) ) failures++; uc1 = vuc; uc1 = uc1*11; if( uc1 != (uc2+=TESTLIT) ) failures++; uc1 = vuc; uc1 = uc1*12; if( uc1 != (uc2+=TESTLIT) ) failures++; uc1 = vuc; uc1 = uc1*13; if( uc1 != (uc2+=TESTLIT) ) failures++; uc1 = vuc; uc1 = uc1*14; if( uc1 != (uc2+=TESTLIT) ) failures++; uc1 = vuc; uc1 = uc1*15; if( uc1 != (uc2+=TESTLIT) ) failures++; uc1 = vuc; uc1 = uc1*16; if( uc1 != (uc2+=TESTLIT) ) failures++; uc1 = vuc; uc1 = uc1*17; if( uc1 != (uc2+=TESTLIT) ) failures++; uc1 = vuc; uc1 = uc1*18; if( uc1 != (uc2+=TESTLIT) ) failures++; uc1 = vuc; uc1 = uc1*19; if( uc1 != (uc2+=TESTLIT) ) failures++; uc1 = vuc; uc1 = uc1*20; if( uc1 != (uc2+=TESTLIT) ) failures++; uc1 = vuc; uc1 = uc1*21; if( uc1 != (uc2+=TESTLIT) ) failures++; uc1 = vuc; uc1 = uc1*22; if( uc1 != (uc2+=TESTLIT) ) failures++; uc1 = vuc; uc1 = uc1*23; if( uc1 != (uc2+=TESTLIT) ) failures++; uc1 = vuc; uc1 = uc1*24; if( uc1 != (uc2+=TESTLIT) ) failures++; uc1 = vuc; uc1 = uc1*31; if( uc1 != ((31*TESTLIT) & 0xff) ) failures++; uc1 = vuc; uc1 = uc1*32; if( uc1 != ((32*TESTLIT) & 0xff) ) failures++; uc1 = vuc; uc1 = uc1*64; if( uc1 != ((64*TESTLIT) & 0xff) ) failures++; uc1 = vuc; uc1 = uc1*128;if( uc1 != ((128*TESTLIT)& 0xff) ) failures++; /* testing literal multiply with different source and destination */ uc1 = vuc*1; if( uc1 != ((1*TESTLIT) & 0xff) ) failures++; uc1 = vuc*2; if( uc1 != ((2*TESTLIT) & 0xff) ) failures++; uc1 = vuc*4; if( uc1 != ((4*TESTLIT) & 0xff) ) failures++; } int main(void) { dummy = 0; c1 = 1; c3 = 5; m1(); uc1 = 0x10; m2(2); ui1 = uc1*uc2; /* uint = uchar * uchar */ i1 = c1*c2; /* int = char * char */ ui3 = ui1*ui2; /* uint = uint * unit */ /*m3(TESTLIT);*/ success = failures; done(); printf("failures: %d\n",failures); return failures; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/nestfor.c������������������������������������������������������������������������0000664�0000000�0000000�00000005740�13473601511�0015600�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> unsigned char success=0; unsigned char failures=0; unsigned char dummy=0; #ifdef SUPPORT_BIT_TYPES bit bit0 = 0; #endif unsigned int uint0 = 0; unsigned int uint1 = 0; unsigned char uchar0 = 0; unsigned char uchar1 = 0; void dput(unsigned char val) { /*PORTB = val; PORTA = 0x01; PORTA = 0x00; */ } void done() { dummy++; } /* both loops use the loop variable inside the inner loop */ void for1(void) { unsigned char i, j; uchar0 = 0; uchar1 = 0; for(i = 0; i < 3; i++) { uchar0++; for(j = 0; j < 4; j++) { uchar1++; dput(i); dput(j); } } if(uchar0 != 3) failures++; if(uchar1 != 12) failures++; } /* only the outer loop's variable is used inside, inner can be optimized into a repeat-loop */ void for2(void) { unsigned char i, j; uchar0 = 0; uchar1 = 0; for(i = 0; i < 3; i++) { uchar0++; for(j = 0; j < 4; j++) { uchar1++; dput(i); } } if(uchar0 != 3) failures++; if(uchar1 != 12) failures++; } /* only the inner loop's variable is used inside */ void for3(void) { unsigned char i, j; uchar0 = 0; uchar1 = 0; for(i = 0; i < 3; i++) { uchar0++; for(j = 0; j < 4; j++) { uchar1++; dput(j); } } if(uchar0 != 3) failures++; if(uchar1 != 12) failures++; } /* neither loop variable used inside the loops */ void for4(void) { unsigned char i, j; uchar0 = 0; uchar1 = 0; for(i = 0; i < 3; i++) { uchar0++; for(j = 0; j < 4; j++) { uchar1++; dput(uchar0); dput(uchar1); } } if(uchar0 != 3) failures++; if(uchar1 != 12) failures++; } /* like for1 but different condition in inner loop */ void for5(void) { unsigned char i, j; uchar0 = 0; uchar1 = 0; for(i = 0; i < 3; i++) { uchar0++; for(j = 10; j >= 5; j--) { uchar1++; dput(i); dput(j); } } if(uchar0 != 3) failures++; if(uchar1 != 18) failures++; } int main(void) { for1(); for2(); for3(); for4(); for5(); success = failures; done(); printf("failures: %d\n",failures); return failures; } ��������������������������������cc65-2.18/test/val/or1.c����������������������������������������������������������������������������0000664�0000000�0000000�00000004507�13473601511�0014621�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> unsigned char success=0; unsigned char failures=0; unsigned char dummy=0; #if SUPPORT_BIT_TYPES bit bit0 = 0; bit bit1 = 0; bit bit2 = 0; #endif unsigned int uint0 = 0; unsigned int uint1 = 0; unsigned char uchar0 = 0; unsigned char uchar1 = 0; unsigned long ulong0 = 0; unsigned long ulong1 = 0; void done() { dummy++; } /* uchar0 = 0; */ void or_lit2uchar(void) { if(uchar0) failures++; uchar0 |= 1; if(uchar0 != 1) failures++; uchar0 |= 2; if(uchar0 != 3) failures++; uchar0 |= 0x0e; if(uchar0 != 0x0f) failures++; } void or_lit2uint(void) { if(uint0) failures++; uint0 |= 1; if(uint0 != 1) failures++; uint0 |= 2; if(uint0 != 3) failures++; uint0 |= 0x100; if(uint0 != 0x103) failures++; uint0 |= 0x102; if(uint0 != 0x103) failures++; uint0 |= 0x303; if(uint0 != 0x303) failures++; } void or_lit2ulong(void) { if(ulong0) failures++; ulong0 |= 1; if(ulong0 != 1) failures++; ulong0 |= 2; if(ulong0 != 3) failures++; ulong0 |= 0x100; if(ulong0 != 0x103) failures++; ulong0 |= 0x102; if(ulong0 != 0x103) failures++; ulong0 |= 0x303; if(ulong0 != 0x303) failures++; ulong0 |= 0x80000000; if(ulong0 != 0x80000303) failures++; } /*-----------*/ void or_uchar2uchar(void) { uchar0 |= uchar1; if(uchar0 != 1) failures++; uchar1 |= 0x0f; uchar0 = uchar1 | 0x10; if(uchar0 != 0x1f) failures++; } void or_uint2uint(void) { uint0 |= uint1; if(uint0 != 1) failures++; uint1 |= 0x0f; uint0 = uint1 | 0x10; if(uint0 != 0x1f) failures++; } #if SUPPORT_BIT_TYPES void or_bits1(void) { bit0 = bit0 | bit1 | bit2; } void or_bits2(void) { bit0 = bit1 | bit2; } #endif int main(void) { or_lit2uchar(); or_lit2uint(); or_lit2ulong(); uchar0=0; uchar1=1; or_uchar2uchar(); uint0=0; uint1=1; or_uint2uint(); #if SUPPORT_BIT_TYPES or_bits1(); if(bit0) failures++; or_bits2(); if(bit0) failures++; bit1=1; or_bits1(); if(!bit0) failures++; or_bits2(); if(!bit0) failures++; #endif success = failures; done(); printf("failures: %d\n",failures); return failures; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/pointed-array.c������������������������������������������������������������������0000664�0000000�0000000�00000004412�13473601511�0016671�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** !!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; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/pointer1.c�����������������������������������������������������������������������0000664�0000000�0000000�00000003414�13473601511�0015655�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! Pointer tests !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> unsigned char success = 0; unsigned char failures = 0; unsigned char dummy = 0; #ifdef SUPPORT_BIT_TYPES bit bit0 = 0; #endif unsigned int aint0 = 0; unsigned int aint1 = 0; unsigned char achar0 = 0; unsigned char achar1 = 0; unsigned char *acharP = 0; char buff[10]; void done () { dummy++; } void f1 (unsigned char *ucP) { if (ucP == 0) { failures++; return; } if (*ucP) failures++; } void f2 (unsigned int *uiP) { if (uiP == 0) { failures++; return; } if (*uiP) failures++; } unsigned char * f3 (void) { return &achar0; } void f4(unsigned char *ucP, unsigned char uc) { if(!ucP) { failures++; return; } if(*ucP != uc) failures++; } void init_array(char start_value) { unsigned char c; for(c=0; c<sizeof(buff); c++) buff[c] = start_value++; } void check_array(char base_value) { unsigned char c; for(c=0; c<sizeof(buff); c++) if(buff[c] != (base_value+c)) failures++; } void index_by_pointer(unsigned char *index, unsigned char expected_value) { if(buff[*index] != expected_value) failures++; } int main (void) { init_array(4); check_array(4); if(buff[achar0 + 7] != 4+7) failures++; dummy = buff[achar0]; if(dummy != 4) failures++; if(dummy != (buff[achar0+1] -1)) failures++; index_by_pointer(&dummy, 8); f1 (&achar0); f2 (&aint0); acharP = f3 (); if ((acharP == 0) || (*acharP)) failures++; achar0 = 42; if(*acharP != 42) failures++; achar0 = 5; f4(&achar0, achar0); success = failures; done (); printf("failures: %d\n",failures); return failures; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/postincdec.c���������������������������������������������������������������������0000664�0000000�0000000�00000000733�13473601511�0016250�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! char-sized post-increment and -decrement !!ORIGIN!! cc65 regression tests !!LICENCE!! Public Domain !!AUTHOR!! Lauri Kasanen */ static unsigned char val, array[2]; int main() { val = 0; array[0] = array[1] = 10; array[val++] = 2; array[val++] = 2; --val; array[val--] = 0; array[val--] = 0; return (array[0] == array[1] && array[0] == 0 && val == 0xff) ? 0 : 1; } �������������������������������������cc65-2.18/test/val/ptrfunc.c������������������������������������������������������������������������0000664�0000000�0000000�00000004436�13473601511�0015602�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #define NO_IMPLICIT_FUNCPTR_CONV unsigned char success=0; unsigned char failures=0; unsigned char dummy=0; #ifdef SUPPORT_BIT_TYPES bit bit0 = 0; #endif unsigned int uint0 = 0; unsigned int uint1 = 0; /* * BUG: if these aren't volatile, an overzealous optimizer or somthing * wreaks havoc with the simple tests like "if(uchar != 3)failures++" */ #if 0 unsigned char uchar0 = 0; unsigned char uchar1 = 0; unsigned char uchar2 = 0; #else volatile unsigned char uchar0 = 0; volatile unsigned char uchar1 = 0; volatile unsigned char uchar2 = 0; #endif #ifdef NO_IMPLICIT_FUNCPTR_CONV void (*pfunc)(void); void (*p1func)(void); unsigned char (*pcfunc)(void); #else void (*pfunc)(); void (*p1func)(); unsigned char (*pcfunc)(); #endif void done() { dummy++; } void call0(void) { uchar0++; } void call1(void) { uchar1++; } unsigned char call2(void) { return uchar0 + 9; } void docall0(void) { pfunc = call0; (pfunc)(); if(uchar0 != 1) failures++; } void docall1() { unsigned char i; for(i = 0; i < 3; i++) { (*p1func)(); } } #ifdef NO_IMPLICIT_FUNCPTR_CONV void docall2( void(*pf)(void) ) #else void docall2( void(*pf)() ) #endif { unsigned char i; for(i = 0; i < 2; i++) { pf(); } } int main(void) { docall0(); p1func = call1; docall1(); if(uchar1 != 3) failures++; if(uchar0 != 1) failures++; p1func = call0; docall1(); if(uchar1 != 3) failures++; if(uchar0 != 4) failures++; docall2(call0); if(uchar1 != 3) failures++; if(uchar0 != 6) failures++; docall2(call1); if(uchar1 != 5) failures++; if(uchar0 != 6) failures++; pcfunc = call2; uchar2 = (*pcfunc)(); if(uchar2 != 15) failures++; uchar2 += (pcfunc)(); uchar2 += pcfunc(); success = failures; done(); printf("failures: %d\n",failures); return failures; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/rotate1.c������������������������������������������������������������������������0000664�0000000�0000000�00000004423�13473601511�0015474�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! Shift bytes left and right by a constant. !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> unsigned char success=0; unsigned char failures=0; unsigned char dummy=0; #ifdef SUPPORT_BIT_TYPES bit bit0 = 0; #endif unsigned int aint0 = 0; unsigned int aint1 = 0; unsigned char achar0 = 0; unsigned char achar1 = 0; unsigned char achar2 = 0; void done() { dummy++; } void check(void) { if(achar0 != achar1) failures++; } void shift_left_1(void) { achar0 <<= 1; check(); } void shift_left_2(void) { achar0 <<= 2; if(achar0 != achar1) failures++; } void shift_left_3(void) { achar0 <<= 3; if(achar0 != achar1) failures++; } void shift_left_4(void) { achar0 <<= 4; if(achar0 != achar1) failures++; } void shift_left_5(void) { achar0 <<= 5; if(achar0 != achar1) failures++; } void shift_left_6(void) { achar0 <<= 6; if(achar0 != achar1) failures++; } void shift_left_7(void) { achar0 <<= 7; if(achar0 != achar1) failures++; } void shift_right_1(void) { achar0 >>= 1; check(); } void shift_right_2(void) { achar0 >>= 2; check(); } void shift_right_3(void) { achar0 >>= 3; check(); } void shift_right_4(void) { achar0 >>= 4; check(); } void shift_right_5(void) { achar0 >>= 5; check(); } void shift_right_6(void) { achar0 >>= 6; check(); } void shift_right_7(void) { achar0 >>= 7; check(); } int main(void) { /* call with both values zero */ shift_left_1(); achar0 = 1; achar1 = 2; for(achar2=0; achar2<6; achar2++) { shift_left_1(); achar1 <<=1; } achar0 = 1; achar1 = 4; shift_left_2(); achar0 = 1; achar1 = 8; shift_left_3(); achar0 = 1; achar1 = 0x10; shift_left_4(); achar0 = 1; achar1 = 0x20; shift_left_5(); achar0 = 1; achar1 = 0x40; shift_left_6(); achar0 = 1; achar1 = 0x80; shift_left_7(); achar0 = 2; achar1 = 1; shift_right_1(); achar0 = 4; shift_right_2(); achar0 = 8; shift_right_3(); achar0 = 0x10; shift_right_4(); achar0 = 0x20; shift_right_5(); achar0 = 0x40; shift_right_6(); achar0 = 0x80; shift_right_7(); success=failures; done(); printf("failures: %d\n",failures); return failures; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/rotate2.c������������������������������������������������������������������������0000664�0000000�0000000�00000001744�13473601511�0015500�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! Shift bytes left and right by a variable. !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> unsigned char success=0; unsigned char failures=0; unsigned char dummy=0; #ifdef SUPPORT_BIT_TYPES bit bit0 = 0; #endif unsigned int aint0 = 0; unsigned int aint1 = 0; unsigned char achar0 = 0; unsigned char achar1 = 0; unsigned char achar2 = 0; unsigned char achar3 = 0; void done() { dummy++; } void shift_right_var(void) { achar0 >>= achar1; } void shift_left_var(void) { achar0 <<= achar1; } void shift_int_left_1(void) { aint0 <<= 1; } int main(void) { char i; achar0 = 1; achar1 = 1; shift_left_var(); if(achar0 !=2) failures++; achar0 = 1; achar1 = 1; achar2 = 1; for(i=0; i<7; i++) { shift_left_var(); achar2 <<= 1; if(achar2 != achar0) failures++; } success=failures; done(); printf("failures: %d\n",failures); return failures; } ����������������������������cc65-2.18/test/val/rotate3.c������������������������������������������������������������������������0000664�0000000�0000000�00000011342�13473601511�0015474�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! Shift ints left and right !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> unsigned char success=0; unsigned char failures=0; unsigned char dummy=0; #ifdef SUPPORT_BIT_TYPES bit bit0 = 0; #endif #ifdef SIZEOF_INT_16BIT #if defined(__LINUX__) || defined(LINUX) unsigned short aint0 = 0; unsigned short aint1 = 0; #else unsigned int aint0 = 0; unsigned int aint1 = 0; #endif #else unsigned int aint0 = 0; unsigned int aint1 = 0; #endif unsigned char achar0 = 0; unsigned char achar1 = 0; unsigned char achar2 = 0; unsigned char achar3 = 0; void done() { dummy++; } void shift_int_left_1(void) { aint0 <<= 1; } void shift_int_left_2(void) { aint0 <<= 2; } void shift_int_left_3(void) { aint0 <<= 3; } void shift_int_left_4(void) { aint0 <<= 4; } void shift_int_left_5(void) { aint0 <<= 5; } void shift_int_left_6(void) { aint0 <<= 6; } void shift_int_left_7(void) { aint0 <<= 7; } void shift_int_left_8(void) { aint0 <<= 8; } void shift_int_left_9(void) { aint0 <<= 9; } void shift_int_left_10(void) { aint0 <<= 10; } void shift_int_left_11(void) { aint0 <<= 11; } void shift_int_left_12(void) { aint0 <<= 12; } void shift_int_left_13(void) { aint0 <<= 13; } void shift_int_left_14(void) { aint0 <<= 14; } void shift_int_left_15(void) { aint0 <<= 15; } /*****************************************************/ void shift_int_right_1(void) { aint0 >>= 1; } void shift_int_right_2(void) { aint0 >>= 2; } void shift_int_right_3(void) { aint0 >>= 3; } void shift_int_right_4(void) { aint0 >>= 4; } void shift_int_right_5(void) { aint0 >>= 5; } void shift_int_right_6(void) { aint0 >>= 6; } void shift_int_right_7(void) { aint0 >>= 7; } void shift_int_right_8(void) { aint0 >>= 8; } void shift_int_right_9(void) { aint0 >>= 9; } void shift_int_right_10(void) { aint0 >>= 10; } void shift_int_right_11(void) { aint0 >>= 11; } void shift_int_right_12(void) { aint0 >>= 12; } void shift_int_right_13(void) { aint0 >>= 13; } void shift_int_right_14(void) { aint0 >>= 14; } void shift_int_right_15(void) { aint0 >>= 15; } /*****************************************************/ int main(void) { /*char i;*/ aint0 = 0xabcd; shift_int_left_1(); if(aint0 != 0x579a) failures++; aint0 = 0xabcd; shift_int_left_2(); if(aint0 != 0xaf34) failures++; aint0 = 0xabcd; shift_int_left_3(); if(aint0 != 0x5e68) failures++; aint0 = 0xabcd; shift_int_left_4(); if(aint0 != 0xbcd0) failures++; aint0 = 0xabcd; shift_int_left_5(); if(aint0 != 0x79a0) failures++; aint0 = 0xabcd; shift_int_left_6(); if(aint0 != 0xf340) failures++; aint0 = 0xabcd; shift_int_left_7(); if(aint0 != 0xe680) failures++; aint0 = 0xabcd; shift_int_left_8(); if(aint0 != 0xcd00) failures++; aint0 = 0xabcd; shift_int_left_9(); if(aint0 != 0x9a00) failures++; aint0 = 0xabcd; shift_int_left_10(); if(aint0 != 0x3400) failures++; aint0 = 0xabcd; shift_int_left_11(); if(aint0 != 0x6800) failures++; aint0 = 0xabcd; shift_int_left_12(); if(aint0 != 0xd000) failures++; aint0 = 0xabcd; shift_int_left_13(); if(aint0 != 0xa000) failures++; aint0 = 0xabcd; shift_int_left_14(); if(aint0 != 0x4000) failures++; aint0 = 0xabcd; shift_int_left_15(); if(aint0 != 0x8000) failures++; /***********************/ aint0 = 0xabcd; shift_int_right_1(); if(aint0 != 0x55e6) failures++; aint0 = 0xabcd; shift_int_right_2(); if(aint0 != 0x2af3) failures++; aint0 = 0xabcd; shift_int_right_3(); if(aint0 != 0x1579) failures++; aint0 = 0xabcd; shift_int_right_4(); if(aint0 != 0x0abc) failures++; aint0 = 0xabcd; shift_int_right_5(); if(aint0 != 0x055e) failures++; aint0 = 0xabcd; shift_int_right_6(); if(aint0 != 0x02af) failures++; aint0 = 0xabcd; shift_int_right_7(); if(aint0 != 0x0157) failures++; aint0 = 0xabcd; shift_int_right_8(); if(aint0 != 0x00ab) failures++; aint0 = 0xabcd; shift_int_right_9(); if(aint0 != 0x0055) failures++; aint0 = 0xabcd; shift_int_right_10(); if(aint0 != 0x002a) failures++; aint0 = 0xabcd; shift_int_right_11(); if(aint0 != 0x0015) failures++; aint0 = 0xabcd; shift_int_right_12(); if(aint0 != 0x000a) failures++; aint0 = 0xabcd; shift_int_right_13(); if(aint0 != 0x0005) failures++; aint0 = 0xabcd; shift_int_right_14(); if(aint0 != 0x0002) failures++; aint0 = 0xabcd; shift_int_right_15(); if(aint0 != 0x0001) failures++; success=failures; done(); printf("failures: %d\n",failures); return failures; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/rotate4.c������������������������������������������������������������������������0000664�0000000�0000000�00000005311�13473601511�0015474�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! rotate bytes left and right by a constant. !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> unsigned char success=0; unsigned char failures=0; unsigned char dummy=0; #ifdef SUPPORT_BIT_TYPES bit bit0 = 0; #endif #ifdef SIZEOF_INT_16BIT #if defined(__LINUX__) || defined(LINUX) unsigned short aint0 = 0; unsigned short aint1 = 0; #else unsigned int aint0 = 0; unsigned int aint1 = 0; #endif #else unsigned int aint0 = 0; unsigned int aint1 = 0; #endif unsigned char uchar0 = 0; unsigned char uchar1 = 0; unsigned char uchar2 = 0; void done() { dummy++; } void check(void) { if(uchar0 != uchar1) failures++; } void rotate_left_1(void) { uchar0 = (uchar0<<1) | (uchar0>>7); check(); } void rotate_left_2(void) { uchar0 = (uchar0<<2) | (uchar0>>6); check(); } void rotate_left_3(void) { uchar0 <<= 3; if(uchar0 != uchar1) failures++; } void rotate_left_4(void) { uchar0 <<= 4; if(uchar0 != uchar1) failures++; } void rotate_left_5(void) { uchar0 <<= 5; if(uchar0 != uchar1) failures++; } void rotate_left_6(void) { uchar0 <<= 6; if(uchar0 != uchar1) failures++; } void rotate_left_7(void) { uchar0 <<= 7; if(uchar0 != uchar1) failures++; } void rotate_right_1(void) { uchar0 = (uchar0>>1) | (uchar0<<7); check(); } void rotate_right_2(void) { uchar0 = (uchar0>>2) | (uchar0<<6); check(); } void rotate_right_3(void) { uchar0 >>= 3; check(); } void rotate_right_4(void) { uchar0 >>= 4; check(); } void rotate_right_5(void) { uchar0 >>= 5; check(); } void rotate_right_6(void) { uchar0 >>= 6; check(); } void rotate_right_7(void) { uchar0 >>= 7; check(); } int main(void) { /* call with both values zero */ rotate_left_1(); uchar0 = 1; uchar1 = 2; rotate_left_1(); uchar0 = 0x80; uchar1 = 1; rotate_left_1(); uchar1 = 2; for(uchar2=0; uchar2<6; uchar2++) { rotate_left_1(); uchar1 <<=1; } uchar0 = 1; uchar1 = 4; rotate_left_2(); uchar0 = 1; uchar1 = 8; rotate_left_3(); uchar0 = 1; uchar1 = 0x10; rotate_left_4(); uchar0 = 1; uchar1 = 0x20; rotate_left_5(); uchar0 = 1; uchar1 = 0x40; rotate_left_6(); uchar0 = 1; uchar1 = 0x80; rotate_left_7(); uchar0 = 2; uchar1 = 1; rotate_right_1(); uchar0 = 1; uchar1 = 0x80; rotate_right_1(); uchar0 = 4; uchar1 = 1; rotate_right_2(); uchar0 = 8; rotate_right_3(); uchar0 = 0x10; rotate_right_4(); uchar0 = 0x20; rotate_right_5(); uchar0 = 0x40; rotate_right_6(); uchar0 = 0x80; rotate_right_7(); success=failures; done(); printf("failures: %d\n",failures); return failures; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/rotate5.c������������������������������������������������������������������������0000664�0000000�0000000�00000007003�13473601511�0015475�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! Shift bytes left and right by a constant. !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> unsigned char success=0; unsigned char failures=0; unsigned char dummy=0; #ifdef SUPPORT_BIT_TYPES bit bit0 = 0; #endif #ifdef SIZEOF_INT_16BIT #if defined(__LINUX__) || defined(LINUX) signed short aint0 = 0; signed short aint1 = 0; #else signed int aint0 = 0; signed int aint1 = 0; #endif #else signed int aint0 = 0; signed int aint1 = 0; #endif signed char achar0 = 0; signed char achar1 = 0; signed char achar2 = 0; void done() { dummy++; } void check(void) { if(achar0 != achar1) failures++; } void shift_left_1(void) { achar0 <<= 1; check(); } void shift_left_2(void) { achar0 <<= 2; if(achar0 != achar1) failures++; } void shift_left_3(void) { achar0 <<= 3; if(achar0 != achar1) failures++; } void shift_left_4(void) { achar0 <<= 4; if(achar0 != achar1) failures++; } void shift_left_5(void) { achar0 <<= 5; if(achar0 != achar1) failures++; } void shift_left_6(void) { achar0 <<= 6; if(achar0 != achar1) failures++; } void shift_left_7(void) { achar0 <<= 7; if(achar0 != achar1) failures++; } void shift_right_1(void) { achar0 >>= 1; check(); } void shift_right_2(void) { achar0 >>= 2; check(); } void shift_right_3(void) { achar0 >>= 3; check(); } void shift_right_4(void) { achar0 >>= 4; check(); } void shift_right_5(void) { achar0 >>= 5; check(); } void shift_right_6(void) { achar0 >>= 6; check(); } void shift_right_7(void) { achar0 >>= 7; check(); } int main(void) { /* call with both values zero */ shift_left_1(); printf("failures: %d\n",failures); achar0 = 1; achar1 = 2; for(achar2=0; achar2<6; achar2++) { shift_left_1(); achar1 <<=1; } printf("failures: %d\n",failures); achar0 = 1; achar1 = 4; shift_left_2(); printf("failures: %d\n",failures); achar0 = 1; achar1 = 8; shift_left_3(); printf("failures: %d\n",failures); achar0 = 1; achar1 = 0x10; shift_left_4(); printf("failures: %d\n",failures); achar0 = 1; achar1 = 0x20; shift_left_5(); printf("failures: %d\n",failures); achar0 = 1; achar1 = 0x40; shift_left_6(); printf("failures: %d\n",failures); achar0 = 1; achar1 = 0x80; shift_left_7(); printf("failures: %d\n",failures); achar0 = 2; achar1 = 1; shift_right_1(); printf("failures: %d\n",failures); achar0 = 4; shift_right_2(); printf("failures: %d\n",failures); achar0 = 8; shift_right_3(); printf("failures: %d\n",failures); achar0 = 0x10; shift_right_4(); printf("failures: %d\n",failures); achar0 = 0x20; shift_right_5(); printf("failures: %d\n",failures); achar0 = 0x40; shift_right_6(); printf("failures: %d\n",failures); achar0 = 0xff; achar1 = 0xff; shift_right_1(); printf("failures: %d\n",failures); achar0 = 0xfe; achar1 = 0xff; shift_right_1(); printf("failures: %d\n",failures); achar0 = 0xfc; shift_right_2(); printf("failures: %d\n",failures); achar0 = 0xf8; shift_right_3(); printf("failures: %d\n",failures); achar0 = 0xf0; shift_right_4(); printf("failures: %d\n",failures); achar0 = 0xe0; shift_right_5(); printf("failures: %d\n",failures); achar0 = 0xc0; shift_right_6(); printf("failures: %d\n",failures); achar0 = 0x80; achar1 = 0xff; shift_right_7(); success=failures; done(); printf("failures: %d\n",failures); return failures; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/rotate6.c������������������������������������������������������������������������0000664�0000000�0000000�00000004543�13473601511�0015504�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! Shift bytes left and right by a variable. !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> unsigned char success=0; unsigned char failures=0; unsigned char dummy=0; #ifdef SUPPORT_BIT_TYPES bit bit0 = 0; #endif #ifdef SIZEOF_INT_16BIT #if defined(__LINUX__) || defined(LINUX) signed short aint0 = 0; signed short aint1 = 0; #else signed int aint0 = 0; signed int aint1 = 0; #endif #else signed int aint0 = 0; signed int aint1 = 0; #endif signed char achar0 = 0; signed char achar1 = 0; signed char achar2 = 0; signed char achar3 = 0; void done() { dummy++; } void shift_right_var(void) { achar0 >>= achar1; } void shift_left_var(void) { achar0 <<= achar1; } void shift_int_left_var(void) { aint0 <<= achar1; } void shift_int_right_var(void) { aint0 >>= achar1; } void shift_int_right_var2(void) { aint0 = aint1 >> achar1; } void shift_int_left_var2(void) { aint0 = aint1 << achar1; } int main (void) { char i; achar0 = 1; achar1 = 1; shift_left_var(); if(achar0 !=2) failures++; printf("failures: %d\n",failures); achar0 = 1; achar1 = 1; achar2 = 1; for(i=0; i<7; i++) { shift_left_var(); achar2 <<= 1; if(achar2 != achar0) failures++; } printf("failures: %d\n",failures); achar1 = 4; achar0 = 0xf0; shift_right_var(); if(((unsigned char)achar0) != 0xff) failures++; printf("failures: %d\n",failures); aint0 = 1; aint1 = 1; achar1 = 1; for(i=0; i<15; i++) { shift_int_left_var(); aint1 <<= 1; if(aint0 != aint1) failures++; } printf("failures: %d\n",failures); aint0 = 0x4000; aint1 = 0x4000; for(i=0; i<15; i++) { shift_int_right_var(); aint1 >>= 1; if(aint0 != aint1) failures++; } printf("failures: %d\n",failures); aint0 = -0x4000; aint1 = -0x4000; for(i=0; i<15; i++) { shift_int_right_var(); aint1 >>= 1; if(aint0 != aint1) failures++; } printf("failures: %d\n",failures); aint1 = 0xf000; achar1 = 10; shift_int_right_var2(); if(((unsigned short)aint0) != 0xfffc) failures++; printf("failures: %d\n",failures); aint1 = aint0; shift_int_left_var2(); if(((unsigned short)aint0) != 0xf000) failures++; success=failures; done(); printf("failures: %d\n",failures); return failures; } �������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/rotate7.c������������������������������������������������������������������������0000664�0000000�0000000�00000014067�13473601511�0015507�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! Shift ints left and right !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> unsigned char success=0; unsigned char failures=0; unsigned char dummy=0; #ifdef SIZEOF_INT_16BIT #if defined(__LINUX__) || defined(LINUX) signed short aint0 = 0; signed short aint1 = 0; #else signed int aint0 = 0; signed int aint1 = 0; #endif #else signed int aint0 = 0; signed int aint1 = 0; #endif /* signed char achar0 = 0; signed char achar1 = 0; signed char achar2 = 0; signed char achar3 = 0; */ void done() { dummy++; } void shift_int_left_1(void) { aint0 <<= 1; } void shift_int_left_2(void) { aint0 <<= 2; } void shift_int_left_3(void) { aint0 <<= 3; } void shift_int_left_4(void) { aint0 <<= 4; } void shift_int_left_5(void) { aint0 <<= 5; } void shift_int_left_6(void) { aint0 <<= 6; } void shift_int_left_7(void) { aint0 <<= 7; } void shift_int_left_8(void) { aint0 <<= 8; } void shift_int_left_9(void) { aint0 <<= 9; } void shift_int_left_10(void) { aint0 <<= 10; } void shift_int_left_11(void) { aint0 <<= 11; } void shift_int_left_12(void) { aint0 <<= 12; } void shift_int_left_13(void) { aint0 <<= 13; } void shift_int_left_14(void) { aint0 <<= 14; } void shift_int_left_15(void) { aint0 <<= 15; } /*****************************************************/ void shift_int_right_1(void) { aint0 >>= 1; } void shift_int_right_2(void) { aint0 >>= 2; } void shift_int_right_3(void) { aint0 >>= 3; } void shift_int_right_4(void) { aint0 >>= 4; } void shift_int_right_5(void) { aint0 >>= 5; } void shift_int_right_6(void) { aint0 >>= 6; } void shift_int_right_7(void) { aint0 >>= 7; } void shift_int_right_8(void) { aint0 >>= 8; } void shift_int_right_9(void) { aint0 >>= 9; } void shift_int_right_10(void) { aint0 >>= 10; } void shift_int_right_11(void) { aint0 >>= 11; } void shift_int_right_12(void) { aint0 >>= 12; } void shift_int_right_13(void) { aint0 >>= 13; } void shift_int_right_14(void) { aint0 >>= 14; } void shift_int_right_15(void) { aint0 >>= 15; } /*****************************************************/ int main (void) { aint0 = 0xabcd; shift_int_left_1(); if(aint0 != 0x579a) failures++; printf("failures: %d\n",failures); aint0 = 0xabcd; shift_int_left_2(); if((unsigned short)aint0 != 0xaf34) failures++; printf("failures: %d\n",failures); aint0 = 0xabcd; shift_int_left_3(); if(aint0 != 0x5e68) failures++; printf("failures: %d\n",failures); aint0 = 0xabcd; shift_int_left_4(); if((unsigned short)aint0 != 0xbcd0) failures++; printf("failures: %d\n",failures); aint0 = 0xabcd; shift_int_left_5(); if(aint0 != 0x79a0) failures++; printf("failures: %d\n",failures); aint0 = 0xabcd; shift_int_left_6(); if((unsigned short)aint0 != 0xf340) failures++; printf("failures: %d\n",failures); aint0 = 0xabcd; shift_int_left_7(); if((unsigned short)aint0 != 0xe680) failures++; printf("failures: %d\n",failures); aint0 = 0xabcd; shift_int_left_8(); if((unsigned short)aint0 != 0xcd00) failures++; printf("failures: %d\n",failures); aint0 = 0xabcd; shift_int_left_9(); if((unsigned short)aint0 != 0x9a00) failures++; printf("failures: %d\n",failures); aint0 = 0xabcd; shift_int_left_10(); if(aint0 != 0x3400) failures++; printf("failures: %d\n",failures); aint0 = 0xabcd; shift_int_left_11(); if(aint0 != 0x6800) failures++; printf("failures: %d\n",failures); aint0 = 0xabcd; shift_int_left_12(); if((unsigned short)aint0 != 0xd000) failures++; printf("failures: %d\n",failures); aint0 = 0xabcd; shift_int_left_13(); if((unsigned short)aint0 != 0xa000) failures++; printf("failures: %d\n",failures); aint0 = 0xabcd; shift_int_left_14(); if(aint0 != 0x4000) failures++; printf("failures: %d\n",failures); aint0 = 0xabcd; shift_int_left_15(); if((unsigned short)aint0 != 0x8000) failures++; printf("failures: %d\n",failures); /***********************/ aint0 = 0xabcd; shift_int_right_1(); if((unsigned short)aint0 != 0xd5e6) failures++; printf("failures: %d\n",failures); aint0 = 0xabcd; shift_int_right_2(); if((unsigned short)aint0 != 0xeaf3) failures++; printf("failures: %d\n",failures); aint0 = 0xabcd; shift_int_right_3(); if((unsigned short)aint0 != 0xf579) failures++; printf("failures: %d\n",failures); aint0 = 0xabcd; shift_int_right_4(); if((unsigned short)aint0 != 0xfabc) failures++; printf("failures: %d\n",failures); aint0 = 0xabcd; shift_int_right_5(); if((unsigned short)aint0 != 0xfd5e) failures++; printf("failures: %d\n",failures); aint0 = 0xabcd; shift_int_right_6(); if((unsigned short)aint0 != 0xfeaf) failures++; printf("failures: %d\n",failures); aint0 = 0xabcd; shift_int_right_7(); if((unsigned short)aint0 != 0xff57) failures++; printf("failures: %d\n",failures); aint0 = 0xabcd; shift_int_right_8(); if((unsigned short)aint0 != 0xffab) failures++; printf("failures: %d\n",failures); aint0 = 0xabcd; shift_int_right_9(); if((unsigned short)aint0 != 0xffd5) failures++; printf("failures: %d\n",failures); aint0 = 0xabcd; shift_int_right_10(); if((unsigned short)aint0 != 0xffea) failures++; printf("failures: %d\n",failures); aint0 = 0xabcd; shift_int_right_11(); if((unsigned short)aint0 != 0xfff5) failures++; printf("failures: %d\n",failures); aint0 = 0xabcd; shift_int_right_12(); if((unsigned short)aint0 != 0xfffa) failures++; printf("failures: %d\n",failures); aint0 = 0xabcd; shift_int_right_13(); if((unsigned short)aint0 != 0xfffd) failures++; printf("failures: %d\n",failures); aint0 = 0xabcd; shift_int_right_14(); if((unsigned short)aint0 != 0xfffe) failures++; printf("failures: %d\n",failures); aint0 = 0xabcd; shift_int_right_15(); if(aint0 != -1) failures++; success=failures; done(); printf("failures: %d\n",failures); return failures; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/rotate8.c������������������������������������������������������������������������0000664�0000000�0000000�00000005041�13473601511�0015500�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!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; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/static-1.c�����������������������������������������������������������������������0000664�0000000�0000000�00000000536�13473601511�0015543�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!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; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/static-fwd-decl.c����������������������������������������������������������������0000664�0000000�0000000�00000001026�13473601511�0017063�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! static forward declarations !!ORIGIN!! cc65 regression tests !!LICENCE!! Public Domain !!AUTHOR!! Bob Andrews */ /* see: https://github.com/cc65/cc65/issues/204 */ #pragma warn(error, on) typedef struct _DIRMENU { const char *name; struct _DIRMENU *dest; } DIRMENU; static DIRMENU rmenu; static DIRMENU lmenu = { "left", &rmenu }; static DIRMENU rmenu = { "right", &lmenu }; int main(void) { return lmenu.dest == &rmenu && rmenu.dest == &lmenu ? 0 : 1; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/struct1.c������������������������������������������������������������������������0000664�0000000�0000000�00000002375�13473601511�0015526�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> unsigned char success = 0; unsigned char failures = 0; unsigned char dummy = 0; #if SUPPORT_BIT_TYPES bit bit0 = 0; bit bit1 = 0; bit bit2 = 0; bit bit3 = 0; bit bit4 = 0; bit bit5 = 0; bit bit6 = 0; bit bit7 = 0; bit bit8 = 0; bit bit9 = 0; bit bit10 = 0; bit bit11 = 0; #endif unsigned int aint0 = 0; unsigned int aint1 = 0; unsigned char achar0 = 0; unsigned char achar1 = 0; unsigned char *acharP = 0; struct chars { unsigned char c0, c1; unsigned int i0, i1; }; struct chars struct1; void done () { dummy++; } void struct_test (void) { if (struct1.c0 || struct1.c1) failures++; struct1.c0++; if (struct1.c0 != 1) failures++; } void ptr_to_struct (struct chars *p) { if (p->c1) failures++; p->c1++; if (p->c1 != 1) failures++; } void add_chars(void) { achar0 = struct1.c0 + struct1.c1; if(achar0 != 1) failures++; } int main (void) { struct1.c0 = 0; struct1.c1 = 0; struct_test (); ptr_to_struct (&struct1); struct1.c0 = 0; struct1.c1 = 1; add_chars(); success = failures; done (); printf("failures: %d\n",failures); return failures; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/sub1.c���������������������������������������������������������������������������0000664�0000000�0000000�00000007537�13473601511�0015000�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! Substraction Test !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> unsigned char success=0; unsigned char failures=0; unsigned char dummy=0; #if SUPPORT_BIT_TYPES bit bit0 = 0; bit bit1 = 0; bit bit2 = 0; bit bit3 = 0; bit bit4 = 0; bit bit5 = 0; bit bit6 = 0; bit bit7 = 0; bit bit8 = 0; bit bit9 = 0; bit bit10 = 0; bit bit11 = 0; #endif #ifdef SIZEOF_INT_16BIT #if defined(__LINUX__) || defined(LINUX) unsigned short aint0 = 0; unsigned short aint1 = 0; #else unsigned int aint0 = 0; unsigned int aint1 = 0; #endif #else unsigned int aint0 = 0; unsigned int aint1 = 0; #endif unsigned char achar0 = 0; unsigned char achar1 = 0; unsigned char achar2 = 0; unsigned char achar3 = 0; unsigned char *acharP = 0; void done() { dummy++; } void sub_lit_from_uchar(void) { achar0 = achar0 - 5; if(achar0 != 0xfb) failures++; achar0 -= 10; if(achar0 != 0xf1) failures++; achar0 = achar0 -1; /* Should be a decrement */ if(achar0 != 0xf0) failures++; for(achar1 = 0; achar1 < 100; achar1++) achar0 -= 2; if(achar0 != 40) failures++; } /* achar0 = 1 achar1 = 100 */ void sub_uchar2uchar(void) { achar1 = achar1 - achar0; if(achar1 != 99) failures++; for(achar2 = 0; achar2<7; achar2++) achar1 -= achar0; if(achar1 != 92) failures++; } /* assumes achar0 = 10 achar1 = 32 achar2, achar3 can be anything. */ void sub_uchar2uchar2(void) { achar0--; achar0 = achar0 - 1; achar0 = achar0 - 2; achar0 = achar0 - 3; if(achar0 != 3) failures++; achar1 -= achar0; if(achar1 != 29) failures++; achar2 = achar1 - achar0; if(achar2 != 26) failures++; achar3 = achar2 - achar1 - achar0; if(achar3 != 0xfa) failures++; } /* sub_bits all bit variables are 0 upon entry. */ #if SUPPORT_BIT_TYPES void sub_bits(void) { bit1 = bit0; bit0 = 1; if(bit1 != 0) failures++; bit1 = bit0-bit1; /* 1 - 0 => 1 */ if(bit1 != 1) failures++; #if SUPPORT_BIT_ARITHMETIC bit2 = bit1-bit0; /* 1 - 1 => 0 */ if(bit2) failures++; bit7 = bit4-bit5; bit6 = bit4+bit5; bit3 = bit4-bit5-bit6-bit7-bit0; /* 0-0-0-0-1 => 1 */ if(!bit3) failures++; #endif } /* sub_bit2uchar(void) - assumes bit0 = 1, achar0 = 7 */ void sub_bit2uchar(void) { achar0 -= bit0; if(achar0 != 6) failures++; if(achar0 == bit0) failures++; } void sub_bit2uint(void) { if(aint0 != bit11) failures++; aint0 -= bit0; if(aint0!=0xffff) failures++; } #endif void sub_ucharFromLit(void) { achar0 = 2 - achar0; if(achar0 != 2) { printf("%x != %x\n",0x02,achar0); failures++; } aint0 = 2 - aint0; if(aint0 != 2) { printf("%x != %x\n",0x02,aint0); failures++; } aint0--; if(aint0 != 1) { printf("%x != %x\n",0x01,aint0); failures++; } aint0 = 0x100 - aint0; if(aint0 != 0xff) { printf("%x != %x\n",0xff,aint0); failures++; } aint0 = 0xff00 - aint0; if(aint0 != 0xfe01) { printf("%x != %x\n",0xfe01,aint0); failures++; } aint0 = 0x0e01 - aint0; if(aint0 != 0x1000) { printf("%x != %x\n",0x1000,aint0); failures++; } aint0 = 0x10ff - aint0; if(aint0 != 0xff) { printf("%x != %x\n",0xff,aint0); failures++; } } int main(void) { sub_lit_from_uchar(); printf("failures: %d\n",failures); achar0=1; achar1=100; sub_uchar2uchar(); printf("failures: %d\n",failures); achar0 = 10; achar1 = 32; sub_uchar2uchar2(); printf("failures: %d\n",failures); #if SUPPORT_BIT_TYPES sub_bits(); achar0 = 7; bit0 = 1; sub_bit2uchar(); printf("failures: %d\n",failures); sub_bit2uint(); printf("failures: %d\n",failures); #endif aint0 = 0; achar0 = 0; sub_ucharFromLit(); success = failures; done(); printf("failures: %d\n",failures); return failures; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/sub2.c���������������������������������������������������������������������������0000664�0000000�0000000�00000004353�13473601511�0014772�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! Substraction Test !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> unsigned char success=0; unsigned char failures=0; unsigned char dummy=0; #if SUPPORT_BIT_TYPES bit bit0 = 0; bit bit1 = 0; bit bit2 = 0; bit bit3 = 0; bit bit4 = 0; bit bit5 = 0; bit bit6 = 0; bit bit7 = 0; bit bit8 = 0; bit bit9 = 0; bit bit10 = 0; bit bit11 = 0; #endif int int0 = 0; int int1 = 0; signed char char0 = 0; signed char char1 = 0; signed char char2 = 0; void done() { dummy++; } void sub_int1(void) { if(int0 != 5) failures++; if(int1 != 4) failures++; int0 = int0 - int1; if(int0 != 1) failures++; int0 = 4 - int0; if(int0 != 3) failures++; int0 = int0 - int1; if(int0 != -1) failures++; int0 = int0 - 0xff; if(int0 != -0x100) failures++; int0 = 0xff - int0; if(int0 != 0x1ff) failures++; } void sub_char_int(void) { int0 = int0 - char0; if(int0 != 3) failures++; if(int0 < char0) failures++; int0 = int0 - char0; if(int0 != 1) failures++; if(int0 > char0) failures++; int0 = int0 - char0; if(int0 != -1) failures++; if(int0>0) failures++; } void assign_char2int(void) { int0 = char0; if(int0 != 0x7f) failures++; /* printf("%2x %2x %2x %d\n",0x7f,int0,char0,failures); */ int1 = char1; if(int1 != -5) failures++; /* printf("%2x,%d %2x,%d %2x,%d %d\n",-5,-5,(int)int1,(int)int1,(int)char1,(int)char1,failures); */ } void sub_compound_char(void) { char0 = char1 - 5; if(char0 != 4) failures++; if((char1 - char0 - 5) != 0) failures++; } void sub_compound_int(void) { int0 = int1 - 5; if(int0 != 4) failures++; if((int1 - int0 - 5) != 0) failures++; } int main(void) { int0 = 5; int1 = 4; sub_int1(); printf("failures: %d\n",failures); int0 = 5; int1 = 4; char0 = 2; sub_char_int(); printf("failures: %d\n",failures); char0 = 0x7f; char1 = -5; assign_char2int(); printf("failures: %d\n",failures); char1 = 9; sub_compound_char(); printf("failures: %d\n",failures); int1 = 9; sub_compound_int(); success = failures; done(); printf("failures: %d\n",failures); return failures; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/switch1.c������������������������������������������������������������������������0000664�0000000�0000000�00000002700�13473601511�0015473�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> unsigned char success=0; unsigned char failures=0; unsigned char dummy=0; #ifdef SUPPORT_BIT_TYPES bit bit0 = 0; #endif unsigned int aint0 = 0; unsigned int aint1 = 0; unsigned char achar0 = 0; unsigned char achar1 = 0; void done() { dummy++; } void switch1(void) { switch(achar0) { case 0: achar0 = 9; break; case 1: achar0 = 18; break; default: achar0 = 0; } } void switch2(void) { switch(achar1) { case 0: achar0 = 9; break; case 1: achar0 = 8; break; case 2: achar0 = 7; break; case 3: achar0 = 6; break; case 4: achar0 = 5; break; case 5: achar0 = 4; break; case 6: achar0 = 3; break; case 7: achar0 = 2; break; case 8: achar0 = 1; break; case 9: achar0 = 0; break; case 10: achar0 = 9; break; case 11: achar0 = 8; break; case 12: achar0 = 7; break; default: achar0 = 0xff; break; } } int main(void) { achar0 = 0; switch1(); if(achar0 != 9) failures++; switch1(); if(achar0 != 0) failures++; achar0++; switch1(); if(achar0 != 18) failures++; for(achar1=0; achar1<10;achar1++){ switch2(); if(achar0 != (9-achar1)) failures++; } success=failures; done(); printf("failures: %d\n",failures); return failures; } ����������������������������������������������������������������cc65-2.18/test/val/switch2.c������������������������������������������������������������������������0000664�0000000�0000000�00000001044�13473601511�0015474�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! Testing empty bodied switch statements. !!ORIGIN!! !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> unsigned char success=0; unsigned char failures=0; unsigned char dummy=0; void done() { dummy++; } void switch_no_body(void) { switch(0); } void switch_empty_body(void) { switch(0) {} } /* only worried about this file compiling successfully */ int main(void) { switch_no_body(); switch_empty_body(); success=failures; done(); printf("failures: %d\n",failures); return failures; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/time.c���������������������������������������������������������������������������0000664�0000000�0000000�00000001560�13473601511�0015052�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <time.h> #include <stdio.h> int main(void) { int failures = 0; struct tm timeinfo; time_t rawtime; struct tm *p_timeinfo; timeinfo.tm_year = 2020 - 1900; timeinfo.tm_mon = 12 - 1; timeinfo.tm_mday = 24; timeinfo.tm_hour = 10; timeinfo.tm_min = 30; timeinfo.tm_sec = 50; timeinfo.tm_isdst = 0; rawtime = mktime(&timeinfo); failures += !(rawtime == 1608805850); p_timeinfo = localtime(&rawtime); failures += !(p_timeinfo->tm_year == timeinfo.tm_year); failures += !(p_timeinfo->tm_mon == timeinfo.tm_mon); failures += !(p_timeinfo->tm_mday == timeinfo.tm_mday); failures += !(p_timeinfo->tm_hour == timeinfo.tm_hour); failures += !(p_timeinfo->tm_min == timeinfo.tm_min); failures += !(p_timeinfo->tm_sec == timeinfo.tm_sec); printf("%lu\n%s%d\n", rawtime, asctime(p_timeinfo), failures); return failures; } ������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/trampoline-params.c��������������������������������������������������������������0000664�0000000�0000000�00000001073�13473601511�0017546�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! wrapped-call pragma w/ many params !!ORIGIN!! cc65 regression tests !!LICENCE!! Public Domain !!AUTHOR!! Lauri Kasanen */ #include <stdarg.h> static unsigned char flag; static void trampoline_set() { asm("ldy tmp4"); asm("sty %v", flag); asm("jsr callptr4"); } #pragma wrapped-call(push, trampoline_set, 4) long adder(long in); #pragma wrapped-call(pop) long adder(long in) { return in + 7; } int main() { flag = 0; return adder(70436) == 70436 + 7 && flag == 4 ? 0 : 1; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/trampoline-varargs.c�������������������������������������������������������������0000664�0000000�0000000�00000001660�13473601511�0017732�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! wrapped-call pragma w/ variadic function !!ORIGIN!! cc65 regression tests !!LICENCE!! Public Domain !!AUTHOR!! Lauri Kasanen */ #include <stdarg.h> static unsigned char flag; static void trampoline_set() { // The Y register is used for variadics - save and restore asm("sty tmp3"); asm("ldy tmp4"); asm("sty %v", flag); asm("ldy tmp3"); asm("jsr callptr4"); } #pragma wrapped-call(push, trampoline_set, 4) unsigned adder(unsigned char num, ...); #pragma wrapped-call(pop) unsigned adder(unsigned char num, ...) { unsigned char i; unsigned sum = 0; va_list ap; va_start(ap, num); for (i = 0; i < num; i++) { sum += va_arg(ap, unsigned); } va_end(ap); return sum; } int main() { flag = 0; return adder(3, 0, 5, 500) == 505 && flag == 4 ? 0 : 1; } ��������������������������������������������������������������������������������cc65-2.18/test/val/trampoline.c���������������������������������������������������������������������0000664�0000000�0000000�00000001351�13473601511�0016264�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! wrapped-call pragma used for trampolines !!ORIGIN!! cc65 regression tests !!LICENCE!! Public Domain !!AUTHOR!! Lauri Kasanen */ static unsigned char flag; static void trampoline_set() { asm("ldy tmp4"); asm("sty %v", flag); asm("jsr callptr4"); } void trampoline_inc() { asm("inc %v", flag); asm("jsr callptr4"); } void func3() { } #pragma wrapped-call(push, trampoline_inc, 0) void func2() { func3(); } #pragma wrapped-call(push, trampoline_set, 4) void func1(void); #pragma wrapped-call(pop) #pragma wrapped-call(pop) void func1() { func2(); } int main(void) { flag = 0; func1(); return flag == 5 ? 0 : 1; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/unittest.h�����������������������������������������������������������������������0000664�0000000�0000000�00000011221�13473601511�0015773�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/*****************************************************************************/ /* */ /* unittest.h */ /* */ /* Unit test helper macros */ /* */ /* */ /* */ /* (C) 2017 Christian Krueger */ /* */ /* This software is provided 'as-is', without any expressed or implied */ /* warranty. In no event will the authors be held liable for any damages */ /* arising from the use of this software. */ /* */ /* Permission is granted to anyone to use this software for any purpose, */ /* including commercial applications, and to alter it and redistribute it */ /* freely, subject to the following restrictions: */ /* */ /* 1. The origin of this software must not be misrepresented; you must not */ /* claim that you wrote the original software. If you use this software */ /* in a product, an acknowledgment in the product documentation would be */ /* appreciated but is not required. */ /* 2. Altered source versions must be plainly marked as such, and must not */ /* be misrepresented as being the original software. */ /* 3. This notice may not be removed or altered from any source */ /* distribution. */ /* */ /*****************************************************************************/ #ifndef _UNITTEST_H #define _UNITTEST_H #include <stdio.h> #include <stdlib.h> #ifndef COMMA #define COMMA , #endif #define TEST int main(void) \ {\ printf("%s: ",__FILE__); #define ENDTEST printf("Passed\n"); \ return EXIT_SUCCESS; \ } #define ASSERT_IsTrue(a,b) if (!(a)) \ {\ printf("Fail at line %d:\n",__LINE__);\ printf(b);\ printf("\n");\ printf("Expected status should be true but wasn't!\n");\ exit(EXIT_FAILURE);\ } #define ASSERT_IsFalse(a,b) if ((a)) \ {\ printf("Fail at line %d:\n",__LINE__);\ printf(b);\ printf("\n");\ printf("Expected status should be false but wasn't!\n");\ exit(EXIT_FAILURE);\ } #define ASSERT_AreEqual(a,b,c,d) if ((a) != (b)) \ {\ printf("Fail at line %d:\n",__LINE__);\ printf(d);\ printf("\n");\ printf("Expected value: "c", but is "c"!\n", (a), (b));\ exit(EXIT_FAILURE);\ } #define ASSERT_AreNotEqual(a,b,c,d) if ((a) == (b)) \ {\ printf("Fail at line %d:\n",__LINE__);\ printf(d);\ printf("\n");\ printf("Expected value not: "c", but is "c"!\n", (a), (b));\ exit(EXIT_FAILURE);\ } /* End of unittest.h */ #endif �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/void-size1.c���������������������������������������������������������������������0000664�0000000�0000000�00000001435�13473601511�0016107�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! Getting the size of a void-type variable (cc65 extension) !!ORIGIN!! cc65 regression tests !!LICENCE!! Public Domain !!AUTHOR!! Greg King */ static const void list1 = { (char)1, (char)2, (char)3, (char)4, (char)5, (char)6, (char)7, (char)8, (char)9, (char)0 }; static void list2 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; void list3 = { (char)1, (char)2, (char)3, (char)4, &list1, (char)6, (char)7, (char)8, (char)9, &list2 }; /* We know that the expression is constant; don't tell us. */ #pragma warn (const-comparison, off) int main (void) { return sizeof list1 != 10 || sizeof list2 != 20 || sizeof list3 != 12; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/while.c��������������������������������������������������������������������������0000664�0000000�0000000�00000002345�13473601511�0015226�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! while-condition tests !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> static unsigned char failures = 0x00; static unsigned char achar0 = 0; static void while1 (void) { unsigned char i = 10; do { ++achar0; } while (--i); if (achar0 != 10) { failures |= 0x01; } } static void while2 (void) { unsigned char i = 10; achar0 = 0; while (--i) { ++achar0; } if (achar0 != 10 - 1) { failures |= 0x02; } } static void while3 (void) { achar0 = 0; do { if (++achar0 == (unsigned char)0) { return; } } while (1); failures |= 0x04; } static void while4 (void) { achar0 = 0; while (1) { if (++achar0 == (unsigned char)0) { return; } } failures |= 0x08; } static void while5 (void) { achar0 = 0; do { ++achar0; } while (0); if (achar0 != 1) { failures |= 0x10; } } static void while6 (void) { achar0 = 0; while (0) { ++achar0; } if (achar0 != 1 - 1) { failures |= 0x20; } } int main (void) { while1 (); while2 (); while3 (); while4 (); while5 (); while6 (); if (failures) { printf("failures: 0x%02X\n", failures); } return failures; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/test/val/xor.c����������������������������������������������������������������������������0000664�0000000�0000000�00000001477�13473601511�0014733�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* !!DESCRIPTION!! !!ORIGIN!! SDCC regression tests !!LICENCE!! GPL, read COPYING.GPL */ #include <stdio.h> #include <limits.h> unsigned char success=0; unsigned char failures=0; unsigned char dummy=0; unsigned char achar0 = 0; unsigned char achar1 = 0; unsigned char achar2 = 0; void done() { dummy++; } void xor_chars_0_1(void) { achar2 = achar0 ^ achar1; achar0 = achar0 ^ 0x1; achar1 = achar0 ^ achar1 ^ 4; } void xor_if(void) { if(achar0 ^ achar1) failures++; achar0 ^= 0xff; if( !(achar0 ^ achar1) ) failures++; } int main(void) { xor_chars_0_1(); if(achar2) failures++; if(achar0 != 1) failures++; if(achar1 != 5) failures++; achar0 = achar1; xor_if(); success = failures; done(); printf("failures: %d\n",failures); return failures; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/���������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014017�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/assembler/�����������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015774�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/assembler/paramcount.s�����������������������������������������������������������0000664�0000000�0000000�00000000742�13473601511�0020334�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; 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 ������������������������������cc65-2.18/testcode/compiler/������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015631�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/compiler/pptest1.c���������������������������������������������������������������0000664�0000000�0000000�00000000272�13473601511�0017376�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#define hash_hash # ## # #define mkstr(a) # a #define in_between(a) mkstr(a) #define join(c, d) in_between(c hash_hash d) char p[] = join(x, y); // Comment ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/compiler/pptest2.c���������������������������������������������������������������0000664�0000000�0000000�00000000662�13473601511�0017402�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#define x 3 #define f(a) f(x * (a)) #undef x #define x 2 #define g f #define z z[0] #define h g(~ #define m(a) a(w) #define w 0,1 #define t(a) a #define p() int #define q(x) x #define r(x,y) x ## y #define str(x) # x f(y+1) + f(f(z)) % t(t(g) (0) + t)(1); g(x+(3,4)-w) | h 5) & m(f)^m(m); p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) }; char c[2][6] = { str(hello), str() }; ������������������������������������������������������������������������������cc65-2.18/testcode/compiler/pptest3.c���������������������������������������������������������������0000664�0000000�0000000�00000000761�13473601511�0017403�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#define str(s) # s #define xstr(s) str(s) #define debug(s, t) printf("x" # s "= %d, x" # t "= %s", \ x ## s, x ## t) #define INCFILE(n) vers ## n // Comment #define glue(a,b) a ## b #define xglue(a,b) glue(a,b) #define HIGHLOW "hello" #define LOW LOW ", world" debug (1, 2); fputs (str (strncmp("abc\0d", "abc", '\4') // Comment == 0) str (: @\n), s); glue (HIGH, LOW); xglue (HIGH, LOW); ���������������cc65-2.18/testcode/compiler/pptest4.c���������������������������������������������������������������0000664�0000000�0000000�00000000206�13473601511�0017376�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#define t(x,y,z) x ## y ## z int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,), t(10,,), t(,11,), t(,,12), t(,,) }; ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/compiler/pptest5.c���������������������������������������������������������������0000664�0000000�0000000�00000000177�13473601511�0017406�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#define t(x,y,z) x ## y ## z int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,), t(10,,), t(,11,), t(,,12), t(,,) }; �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/disasm/��������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015277�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/disasm/.gitignore����������������������������������������������������������������0000664�0000000�0000000�00000000016�13473601511�0017264�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������*.s image.bin ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/disasm/bank0.da������������������������������������������������������������������0000664�0000000�0000000�00000000541�13473601511�0016600�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Da65 input file before preprocessed by cpp // Bank0 ROM map #define TARGET_BANK 0 global { inputoffs $00010; inputsize $4000; startaddr $8000; cpu "6502"; }; #include "fixed.da" label { addr $8000; name "Bank0ProcA"; }; label { addr $8123; name "Bank0ProcB"; }; range { start $A000; end $BFFF; name "Bank0Data"; type ByteTable; }; ���������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/disasm/bank0.dai�����������������������������������������������������������������0000664�0000000�0000000�00000001222�13473601511�0016746�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 1 "bank0.da" # 1 "<built-in>" # 1 "<command-line>" # 1 "bank0.da" global { inputoffs $00010; inputsize $4000; startaddr $8000; cpu "6502"; }; # 1 "fixed.da" 1 # 18 "fixed.da" label { addr $00; name "VariableA"; }; label { addr $01; name "VariableB"; }; label { addr $0100; name "Stack"; size $0100; }; label { addr $C000; name "CommonProcA"; }; label { addr $C123; name "CommonProcB"; }; range { start $E123; end $FFFF; name "CommonData"; type ByteTable; }; # 13 "bank0.da" 2 label { addr $8000; name "Bank0ProcA"; }; label { addr $8123; name "Bank0ProcB"; }; range { start $A000; end $BFFF; name "Bank0Data"; type ByteTable; }; ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/disasm/bank1.da������������������������������������������������������������������0000664�0000000�0000000�00000000541�13473601511�0016601�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Da65 input file before preprocessed by cpp // Bank1 ROM map #define TARGET_BANK 1 global { inputoffs $04010; inputsize $4000; startaddr $8000; cpu "6502"; }; #include "fixed.da" range { start $8000; end $AFFF; name "Bank1Data"; type ByteTable; }; label { addr $B000; name "Bank1ProcA"; }; label { addr $B123; name "Bank1ProcB"; }; ���������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/disasm/bank1.dai�����������������������������������������������������������������0000664�0000000�0000000�00000001222�13473601511�0016747�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 1 "bank1.da" # 1 "<built-in>" # 1 "<command-line>" # 1 "bank1.da" global { inputoffs $04010; inputsize $4000; startaddr $8000; cpu "6502"; }; # 1 "fixed.da" 1 # 18 "fixed.da" label { addr $00; name "VariableA"; }; label { addr $01; name "VariableB"; }; label { addr $0100; name "Stack"; size $0100; }; label { addr $C000; name "CommonProcA"; }; label { addr $C123; name "CommonProcB"; }; range { start $E123; end $FFFF; name "CommonData"; type ByteTable; }; # 13 "bank1.da" 2 range { start $8000; end $AFFF; name "Bank1Data"; type ByteTable; }; label { addr $B000; name "Bank1ProcA"; }; label { addr $B123; name "Bank1ProcB"; }; ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/disasm/fixed.da������������������������������������������������������������������0000664�0000000�0000000�00000001341�13473601511�0016703�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// Da65 input file before preprocessed by cpp // RAM and Fixed ROM map #ifndef FIXED_DA_INCLUDED #define FIXED_DA_INCLUDED #ifndef TARGET_BANK #define TARGET_BANK -1 global { inputoffs $1C010; inputsize $4000; startaddr $C000; cpu "6502"; }; #endif /* !defined(TARGET_BANK) */ // ---- RAM map ---- label { addr $00; name "VariableA"; }; label { addr $01; name "VariableB"; }; label { addr $0100; name "Stack"; size $0100; }; #if defined(TEST_ERROR) && TARGET_BANK == 0 erroneous_line; #endif // ---- Fixed ROM map ---- label { addr $C000; name "CommonProcA"; }; label { addr $C123; name "CommonProcB"; }; range { start $E123; end $FFFF; name "CommonData"; type ByteTable; }; #endif /* !defined(FIXED_DA_INCLUDED) */ �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/disasm/fixed.dai�����������������������������������������������������������������0000664�0000000�0000000�00000000722�13473601511�0017056�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# 1 "fixed.da" # 1 "<built-in>" # 1 "<command-line>" # 1 "fixed.da" # 9 "fixed.da" global { inputoffs $1C010; inputsize $4000; startaddr $C000; cpu "6502"; }; label { addr $00; name "VariableA"; }; label { addr $01; name "VariableB"; }; label { addr $0100; name "Stack"; size $0100; }; label { addr $C000; name "CommonProcA"; }; label { addr $C123; name "CommonProcB"; }; range { start $E123; end $FFFF; name "CommonData"; type ByteTable; }; ����������������������������������������������cc65-2.18/testcode/disasm/sample-unix.mk������������������������������������������������������������0000664�0000000�0000000�00000000725�13473601511�0020076�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Sample makefile using a preprocessor against info files # and the --sync-lines option CPP = env LANG=C cpp CPPFLAGS = # -DTEST_ERROR ASMS = fixed.s bank0.s bank1.s DAIS = fixed.dai bank0.dai bank1.dai .SUFFIXES: .da .dai .s .PHONY: all clean maintainer-clean .SECONDARY: $(DAIS) .da.dai: $(CPP) -o $@ $(CPPFLAGS) $< .dai.s: da65 --sync-lines -o $@ -i $< image.bin all: $(ASMS) clean: rm -f $(ASMS) maintainer-clean: clean rm -f $(DAIS) $(DAIS): fixed.da �������������������������������������������cc65-2.18/testcode/grc/�����������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014572�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/grc/test.grc���������������������������������������������������������������������0000664�0000000�0000000�00000002523�13473601511�0016250�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; This is the proposed syntax of a general GEOS resource file for the upcoming resource compiler. ; token MENU, topname (will be escaped with _), x,y of top-left corner, bottom-right will be ; counted according to BSW font table (in x) and a multiply 15 (14?) in y ; Note that MENU is either MENU and SUBMENU ; Note that if you want to use any C operators (like '|', '&' etc.) do it WITHOUT spaces ; between arguments (parser is simple and weak) ; format: MENU "name" left,top ALIGN { "itemname" TYPE pointer ... } MENU subMenu1 15,0 VERTICAL { "subitem1" MENU_ACTION smenu1 "mubitem2" MENU_ACTION|DYN_SUB_MENU smenu2 "subitem3" MENU_ACTION smenu3 } MENU mainMenu 0,0 HORIZONTAL { "sub menu1" SUB_MENU subMenu1 ; goes for _subMenu1 "quit" MENU_ACTION EnterDeskTop ; goes for _EnterDeskTop } ; format: HEADER GEOS_TYPE "dosname" "classname" "version" HEADER APPLICATION "123456789 1234567" "Class Name" "V1.0.0" { ; not all fields are required, default and current values will be used author "Maciej Witkowiak" ; always in quotes! info "Information text" ; always in quotes! ; date yy mm dd hh ss ; always 5 fields! ; dostype seq ; can be PRG, SEQ, USR mode c64only ; can be any, 40only, 80only, c64only } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/grc/vlir.grc���������������������������������������������������������������������0000664�0000000�0000000�00000000310�13473601511�0016235�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������HEADER APPLICATION "test" "TestApp" "V1.0" { structure VLIR dostype USR author "Maciej Witkowiak" info "This is just an example." } MEMORY { stacksize 0x0000 overlaysize 0x1000 overlaynums 0 1 2 } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/grc/vlir0.s����������������������������������������������������������������������0000664�0000000�0000000�00000005343�13473601511�0016017�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; Maciej 'YTM/Elysium' Witkowiak ; 06.06.2002 ; This is the source for the main VLIR-structured program part ; include some GEOS defines .include "../../libsrc/geos/inc/const.inc" .include "../../libsrc/geos/inc/jumptab.inc" .include "../../libsrc/geos/inc/geossym.inc" .include "../../libsrc/geos/inc/geosmac.inc" ; import load addresses for all VLIR chains ; these labels are defined upon linking with ld65 .import __OVERLAYADDR__ .import __OVERLAYSIZE__ ; import names of functions defined (and exported) in each VLIR part ; of your application ; here I used an OVERLAYx_ prefix to prevent name clashes .import OVERLAY1_Function1 .import OVERLAY2_Function1 ; segments "STARTUP", "CODE", "DATA", "RODATA" and "BSS" all go to VLIR0 chain .segment "STARTUP" ; code segment for VLIR 0 chain ProgExec: LoadW r0, paramString ; show something jsr DoDlgBox MoveW dirEntryBuf+OFF_DE_TR_SC, r1 LoadW r4, fileHeader jsr GetBlock ; load back VLIR t&s table bnex error lda #1 jsr PointRecord ; we want next module (#1) LoadW r2, __OVERLAYSIZE__ ; length - as many bytes as we have room for LoadW r7, __OVERLAYADDR__ ; all VLIR segments have the same load address jsr ReadRecord ; load it bnex error jsr OVERLAY1_Function1 ; execute something lda #2 jsr PointRecord ; next module LoadW r2, __OVERLAYSIZE__ LoadW r7, __OVERLAYADDR__ jsr ReadRecord ; load it bnex error jsr OVERLAY2_Function1 ; execute something error: jmp EnterDeskTop ; end of application .segment "RODATA" ; read-only data segment paramString: .byte DEF_DB_POS | 1 .byte DBTXTSTR, TXT_LN_X, TXT_LN_2_Y .word line1 .byte DBTXTSTR, TXT_LN_X, TXT_LN_3_Y .word line2 .byte OK, DBI_X_0, DBI_Y_2 .byte NULL line1: .byte BOLDON, "Hello World!",0 line2: .byte OUTLINEON,"Hello",PLAINTEXT," world!",0 .segment "DATA" ; read/write initialized data segment counter: .word 0 .segment "BSS" ; read/write uninitialized data segment ; this space doesn't go into output file, only its size and ; position is remembered ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/grc/vlir1.s����������������������������������������������������������������������0000664�0000000�0000000�00000002564�13473601511�0016022�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; Maciej 'YTM/Elysium' Witkowiak ; 06.06.2002 ; This is the source for the loadable VLIR-structured program part ; include some GEOS defines .include "../../libsrc/geos/inc/const.inc" .include "../../libsrc/geos/inc/jumptab.inc" .include "../../libsrc/geos/inc/geossym.inc" .include "../../libsrc/geos/inc/geosmac.inc" ; export names of functions that will be used in the main program .export OVERLAY1_Function1 .export OVERLAY1_Function2 ; go into OVERLAY1 segment - everything that is here will go into ; VLIR chain #1 .segment "OVERLAY1" OVERLAY1_Function1: jmp Function1 ; jump table, not really necessary OVERLAY1_Function2: jmp Function2 ; etc. ; rodata - if this is defined in .segment "RODATA" ; it will end up in the VLIR0 part, you don't want that paramString: .byte DEF_DB_POS | 1 .byte DBTXTSTR, TXT_LN_X, TXT_LN_2_Y .word line1 .byte DBTXTSTR, TXT_LN_X, TXT_LN_3_Y .word line2 .byte OK, DBI_X_0, DBI_Y_2 .byte NULL line1: .byte "This is in module 1",0 line2: .byte "This is in module 1",0 ; code Function1: LoadW r0, paramString jsr DoDlgBox Function2: rts ��������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/grc/vlir2.s����������������������������������������������������������������������0000664�0000000�0000000�00000002111�13473601511�0016007�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; Maciej 'YTM/Elysium' Witkowiak ; 06.06.2002 ; This is the source for the loadable VLIR-structured program part ; similar to vlir1.s except the fact that this is chain #2 .include "../../libsrc/geos/inc/const.inc" .include "../../libsrc/geos/inc/jumptab.inc" .include "../../libsrc/geos/inc/geossym.inc" .include "../../libsrc/geos/inc/geosmac.inc" .export OVERLAY2_Function1 .export OVERLAY2_Function2 .segment "OVERLAY2" OVERLAY2_Function1: jmp Function1 OVERLAY2_Function2: jmp Function2 ; etc. paramString: .byte DEF_DB_POS | 1 .byte DBTXTSTR, TXT_LN_X, TXT_LN_2_Y .word line1 .byte DBTXTSTR, TXT_LN_X, TXT_LN_3_Y .word line2 .byte OK, DBI_X_0, DBI_Y_2 .byte NULL Function2: LoadW r0, paramString jsr DoDlgBox Function1: rts line1: .byte "This is in module 2",0 line2: .byte "This is in module 2",0 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/�����������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014565�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/.gitignore�������������������������������������������������������������������0000664�0000000�0000000�00000000016�13473601511�0016552�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������*.o em-test-* ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/accelerator/�����������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0017051�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/accelerator/Makefile���������������������������������������������������������0000664�0000000�0000000�00000001535�13473601511�0020515�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������CL ?= cl65 all: c64-scpu-test.prg c128-scpu-test.prg c64dtv-test.prg \ c64-c128-test.prg c128-test.prg chameleon-test.prg \ c65-test.prg turbomaster-test.prg c64-scpu-test.prg: c64-c128-scpu-test.c $(CL) -t c64 c64-c128-scpu-test.c -o c64-scpu-test.prg c128-scpu-test.prg: c64-c128-scpu-test.c $(CL) -t c128 c64-c128-scpu-test.c -o c128-scpu-test.prg c64dtv-test.prg: c64dtv-test.c $(CL) -t c64 c64dtv-test.c -o c64dtv-test.prg c64-c128-test.prg: c64-c128-test.c $(CL) -t c64 c64-c128-test.c -o c64-c128-test.prg c128-test.prg: c64-c128-test.c $(CL) -t c128 c64-c128-test.c -o c128-test.prg chameleon-test.prg: chameleon-test.c $(CL) -t c64 chameleon-test.c -o chameleon-test.prg c65-test.prg: c65-test.c $(CL) -t c64 c65-test.c -o c65-test.prg turbomaster-test.prg: turbomaster-test.c $(CL) -t c64 turbomaster-test.c -o turbomaster-test.prg �������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/accelerator/c64-c128-scpu-test.c���������������������������������������������0000664�0000000�0000000�00000000336�13473601511�0022213�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* C64/C128 SuperCPU accelerator test code. */ #define ACC_DETECT detect_scpu #define ACC_GET_SPEED get_scpu_speed #define ACC_SET_SPEED set_scpu_speed #define ACC_NAME "SuperCPU" #include "turbo-test.c" ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/accelerator/c64-c128-test.c��������������������������������������������������0000664�0000000�0000000�00000000335�13473601511�0021242�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* C128 in C64 mode accelerator test code. */ #define ACC_DETECT detect_c128 #define ACC_GET_SPEED get_c128_speed #define ACC_SET_SPEED set_c128_speed #define ACC_NAME "C128 CPU" #include "turbo-test.c" ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/accelerator/c64dtv-test.c����������������������������������������������������0000664�0000000�0000000�00000000327�13473601511�0021306�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* C64DTV accelerator test code. */ #define ACC_DETECT detect_c64dtv #define ACC_GET_SPEED get_c64dtv_speed #define ACC_SET_SPEED set_c64dtv_speed #define ACC_NAME "C64DTV" #include "turbo-test.c" ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/accelerator/c65-test.c�������������������������������������������������������0000664�0000000�0000000�00000000332�13473601511�0020565�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* C65/C64DX in C64 mode accelerator test code. */ #define ACC_DETECT detect_c65 #define ACC_GET_SPEED get_c65_speed #define ACC_SET_SPEED set_c65_speed #define ACC_NAME "C65" #include "turbo-test.c" ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/accelerator/chameleon-test.c�������������������������������������������������0000775�0000000�0000000�00000000364�13473601511�0022133�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* C64 Chameleon accelerator test code. */ #define ACC_DETECT detect_chameleon #define ACC_GET_SPEED get_chameleon_speed #define ACC_SET_SPEED set_chameleon_speed #define ACC_NAME "Chameleon cartridge" #include "turbo-test.c" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/accelerator/turbo-test.c�����������������������������������������������������0000664�0000000�0000000�00000002373�13473601511�0021332�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Accelerator test code. */ #ifndef ACC_DETECT #error This file cannot be used directly (yet) #endif #include <time.h> #include <accelerator.h> #include <stdio.h> #include <conio.h> #include <stdlib.h> static void print_time_taken(void) { clock_t curtime = clock(); clock_t newtime; unsigned long i; char buffer[10]; printf("Doing a speed test, please wait\n"); for (i = 0; i < 0x1000; i++) { } newtime = clock() - curtime; ultoa(newtime, buffer, 10); printf("Time taken : %s\n", buffer); } static void print_current_speed(void) { unsigned char status; status = ACC_GET_SPEED(); printf("Current "ACC_NAME" speed : %d\n", status + 1); } void main(void) { unsigned char status; unsigned char speed = 0; status = ACC_DETECT(); clrscr(); if (status == 0) { printf("No "ACC_NAME" detected\n"); } else { status = ACC_GET_SPEED(); print_current_speed(); /* cycle through all the speeds */ for (speed = SPEED_1X; speed <= SPEED_20X; ++speed) { printf("Setting "ACC_NAME" speed to %d\n", speed + 1); ACC_SET_SPEED(speed); print_current_speed(); print_time_taken(); } ACC_SET_SPEED(status); } } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/accelerator/turbomaster-test.c�����������������������������������������������0000775�0000000�0000000�00000000400�13473601511�0022536�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* C64 Turbo Master accelerator test code. */ #define ACC_DETECT detect_turbomaster #define ACC_GET_SPEED get_turbomaster_speed #define ACC_SET_SPEED set_turbomaster_speed #define ACC_NAME "Turbo Master cartridge" #include "turbo-test.c" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/apple2/����������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015750�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/apple2/Makefile��������������������������������������������������������������0000664�0000000�0000000�00000002542�13473601511�0017413�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# For this one see https://applecommander.github.io/ AC ?= ac.jar CL ?= cl65 all: hgr.dsk dhgr.dsk hgr.dsk: hgrshow hgrtest cp prodos.dsk $@ java -jar $(AC) -as $@ hgrshow <hgrshow java -jar $(AC) -as $@ hgrtest <hgrtest java -jar $(AC) -p $@ astronaut.hgr bin 0x2000 <astronaut.hgr java -jar $(AC) -p $@ chips.hgr bin 0x2000 <chips.hgr java -jar $(AC) -p $@ macrometer.hgr bin 0x2000 <macrometer.hgr java -jar $(AC) -p $@ mariner.hgr bin 0x2000 <mariner.hgr java -jar $(AC) -p $@ rose.hgr bin 0x2000 <rose.hgr java -jar $(AC) -p $@ werner.hgr bin 0x2000 <werner.hgr java -jar $(AC) -p $@ winston.hgr bin 0x2000 <winston.hgr hgrshow: hgrshow.c $(CL) -Oirs -t apple2 --start-addr 0x4000 -m hgrshow.map $^ hgrtest: hgrtest.c werner.s $(CL) -Oirs -t apple2 -C apple2-hgr.cfg -m hgrtest.map $^ dhgr.dsk: dhgrshow cp prodos.dsk $@ java -jar $(AC) -as $@ dhgrshow <dhgrshow java -jar $(AC) -p $@ catface.dhgr bin 0x2000 <catface.dhgr java -jar $(AC) -p $@ gatsby.dhgr bin 0x2000 <gatsby.dhgr java -jar $(AC) -p $@ girl.dhgr bin 0x2000 <girl.dhgr java -jar $(AC) -p $@ monarch.dhgr bin 0x2000 <monarch.dhgr java -jar $(AC) -p $@ superman.dhgr bin 0x2000 <superman.dhgr java -jar $(AC) -p $@ venice.dhgr bin 0x2000 <venice.dhgr dhgrshow: dhgrshow.c $(CL) -Oirs -t apple2enh --start-addr 0x4000 -m dhgrshow.map $^ ��������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/apple2/astronaut.hgr���������������������������������������������������������0000664�0000000�0000000�00000017770�13473601511�0020506�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������€€€€€€€€€À€€€€€€€€€€€€€€€€°€€€€€€€üÿÿÿ€€€€€€€€€€€€÷îݛ̀€€€€€€€€ž€¦ðîÝ›€€€€€€n];wn];w€àÌ™³€Ì™]ƒ€àÿðÿ€€wn];wn €w`];w��������€€€€€€€€€€€€€€€€€€€€€€€€€€°€€€€€€þ¿æÿùÿ€€€€€€€€€€€îÝ»ð€€€€€€€€€€€€¦ð€€€€€n];wn]À™³æŒn æ„€\wÿÿÿÿ¿ wn];7ˆ¨ød];w��������€€€€€€€€€€€€€€€€€€€€€€€€€€°€€€€€€¢€þ°€ÿ€€€€€€€€€€€îÝ»ðŸ€@:wn];€\  ¦ðîÝჀ°€€€n];°æÌ™ÿpn]@Ž€æÌé];wnM;wn\;Cˆ¼ÐÊŸŠ:wf��������€€€€€€€€€€€€€ºG3fLaÿÿÿÿÿÿÿ3fL€ Äˆ¢„€€€€€€€€€€€€îÝ»ü™(U*U*U*w.U*U¦ðîÝ€€€€€€n]C³æŒ˜³æŒè]›ðް†÷îÝ»÷€À›wM;7€ á€h];wn��������€€€€€€€€€€€î`L€€Ì™ðÿÿÿÿÿÿàÿÿ€€€ˆ‘€€€€€€€€€€€€€€îÝ»À‡"Q*UnU*U*ó ¦ð€€€€€àÌ™ƒàŒ€€æÌP‡€°†÷î‘‚÷îÝ›€€P¡ÃnM4n];wn��������€€€€€€€€€€ðîÝ»÷îæŒ€³æÌ™³æÀÿ¿þÿÿ¿€€€€€€€€€€€€€€€€€La €U*U*U*U*U*¦‡€€€€€€€€€2怘ƒ€€€€€Œ€À€€°†‡à‘‚÷îÝ›€€€¢ðn];€C;wn��������€€€€€€€€€€ðîÝ»÷ŽƒæŒ€€€€€€þÏ™óçÿÿ¿€€€€€€€€€€€€€€€€f €œ €€¼@e€@*U*T €ƒ€÷îÝ»€€€€€€€€Ìက€€€€€€€€€ˆ€‡à€÷îÝ›€ˆ‘€€Ž æÌŒ€wn��������€€€€€†€€€€÷îݻǙƒ€€€€€€€€€ÿ‡Ã§÷€€€€€€€€€€€€€0€€œæŒ€€þU"U*P€Ï‡À;wn]·vn];w€àŒ€€†€€€€€†€ D³€÷†€º·€À›€ €€³˜Œ†°æÌ™��������€€€˜€€€€€€€€€€€€€€€€€€€€€€°€€€€€€€ÿÿÿÿƒ€€€€€€€€€€€Ý»÷޳†€€€€€€€€€ž€˜Cáл÷Ž€€€€€€;wn];wn]À™³æÌ€†w†€€ðŸ€€€€];wn];•P;wn]��������€€€€€€€€€€€€€€€€€€€€€€€€€€°€€€€€€øà¿øÿ€€€€€€€„€€€º÷îü€€€€€€€€€€€€Cáл·€€€€€€€;wn];°æŒ€³:7˜œ€t]€€€€€`];wn¢¨þ…wnM]��������€€€€€€€€€€€€€€€€€€€€€€€€€€°€€€€€€ˆÁŸ„žü€€€€€€€€€€€º÷îñ‡€T€8wn]:`*€àл÷àƒ€€€€€;wnÌ™³†üÜ;wS›Œ˜³ wn];n];tn‚¿ÔŸ@n]��������€€€€€€€€€€€€Àî€fL3`ÿÿÿÿÿÿÿ‡LC‡€€‘¢Àˆ€€€€€€€€€€€€º÷îü™(U*U*U*U*U*UJáл÷€€€€€€€;w°†Ì™ƒæÌ™ƒ¸wŽÀƒÀ™Ý»÷îݙ̎]#n]¨ù€:wn];��������€€€€€€€€€€€º·3 ÷†³æ€€üÿÿÿÿÿÏÿÿÿƒ€€ „€€€€€€€€€€€€€€º÷îÀ‡"U*U*U*U*€Pàл·€€€€€€€C™³æŒ€ƒ€€˜³†pŒ€Ì™Ý»ÃˆÝ»÷޳æðèÐ;:7€P;��������€€€€€€€€€€Ð»÷îݻǙƒæÌ™³æÌ™ƒà¿øÿÿ¿€€€€€ƒ€€€€€€€€€€€3&·ˆ€Q*UP*U*U*@က€€€€€€€C™ƒ€Œ†€€€€€€À€€À™ ÃˆÝ»÷Ž€€€†Ð;wn1æLn];��������€€€€€€€€€€Ð»÷îÝ›À™ƒ€€€€€ÀÿàÀçÿÿ¿€€€€€€€€€€€€€€€@€´ˆ€€¼€ e€P*U*U „€Ü»÷€€€€€³æ€€€€€€€€€€€¢€Ý»÷îÝ»÷Ž À€ÀÀ™ƒ€Àa];��������€€€€€€€€€€Ý»÷îæ€€€€€€€€€àÿ‡ŒæÝ»÷˜€€€€€€€€€€€€€€L€€€˜³€€øƒPU*€àχðn];wœ\;wn]€€ƒ€€€€€€€€„€ˆŒ€€€€€€€€€€"Dˆ€€Ìƒ€Ì€æ��������€€€€€€€€€€€€€€€€€€€€€€€€€°€€€€€€àÿÿÿÿ€€€€€€€€€€€ôîݛ̀€€€€€€€†€€¦ðîÝ›€€€€€€n];wn];w°æÀ™³&˜]›€€€ø€ƒ wn];wn •pnM];w��������€€€€€€€€€€€€€€€€€€€€€€€€€€°€€€€€€àà¿øÿ€€€€€€€€€€€îݻ𙀀€€€€€€€€€¦ð€€€€€n];wnÌ™³àŒnà4€]t€€€€€ wn];7ˆ þƒ•];v��������€€€€€€€€€€€€€€€€€€€€€€€€€€°€€€€€€¢ÀŸÁ‡ü€€€€€€€€€€€îÝ»ð‡€U*u*U:U**U¦ðîÝჀ€€€€n];³æÌ™€€ðn]pްæÌ];wn:w\;Cˆ¿Ôð‡@;w��������€€€€€€€€€€€€À»L3f €€€ÀÿÿÿÿŸ3fLŸ€ Äˆ‘¢„€€€€€€€€€€€€îÝ»ü™(T*U*U*U*U*U¦ðîÝက€€€€n̰†€˜³æŒàšÀ†°†÷îÝ»÷ˆÀ›w`A!w¨˜€n];wn��������€€€€€€€€€Àî€îÝãÌ™³€ÀÿÿÿÿÿÏÿÿÿ€€€€€€€€€€€€€„€€€€èÝ»À‡"U*U*]*U*U*U€¦ð€€€€€æÌ™ƒ€Œ€°àÌЄˆ³†÷î‘‚÷îݛ̙“€ðn”4n ætn��������€€€€€€€€€€ðîÝ»÷îæÌ™³æÌ™³æÌáÿùÿÿ¿€€€€€€€€€€€€€€€€€La €€D*U€€*w*U*€ ‡àÜ»€€€€€€°æŒ€°€€€€€€€ÀÀ€†‡à‘‚÷îÝ›€€€€ðn];€˜C;wn��������€€€€€€€€€€ðîÝ»·€°æ€€€€€€Àƒ€Ãçÿÿ¿€€€€€€€€€€€€€€€0f€€œ€€€ð e0P*U*UŠá€ðîÝ»³wn];w€€Ìá³€€€€€€€€€€ˆ€÷îÝ»÷îÝ›€ˆ‚€n°æ€€³ wn��������€€€€€€€€€ ÷îݻÙ€€€€€€€€€æÿ‡°¦÷îÝ™€€€€€€€€€€€€€€0F;°æÌ™€à@D"`Ç];wn];€vn];w€€Œ€€†€€€€¸€¢D³€Œ€€€€€€€€€„€³†€€³àŒ˜��������€€€€€€€€€€€€€€€€€€€€€€€€€€°€€€€€€à¿þÿÿ€€€€€€€€€€€À»÷ް†€€€€€€€€À‡€€Cáл÷Ž€€€€€€;wn];wn]À™ƒà̆wn]€€€€€`];wn]¨•@;pn]��������€€€€€€€€€€€€€€€€€€€€€€€€€€°€€€€€€€à¿øÿ€€€€€€€€€€€º÷îñ€€€€(U*(€€€àл÷€ƒ€€˜€€;wn];³æŒ˜³:wPw\€€€€€`];wn ¢€þ •wnX��������€€€€€€€€€€€€€€€€€€€€€€€€€€°€€€€€€ˆð‡€àü€€€€€€€€€€€º÷îü‡(U*U;w.Á*w.U àл÷àƒ€€€€€;wnaÌ™³æÌÐ;wnPƒÌ™€€€€€€€€]tn‚Ô¼€@n]��������€€€€€€€€€€€€ðŽ0fLæÌ™ÃÿÿÿÿŸLž€€‘¢Äˆ€€€€€€€€€€€€º÷îü™(€(wnU*U*UJáл÷€€€€€€€;³†ÀƒàÌ™³ 7n€‚À™Ý»÷îÝ™ÀŽ€€h]ªž@;wn];��������€€€€€€€€€€Ð»·€Ý»÷†³æÌƒþÿÿÿÿÏÿÿÿ€€€€€€€€€€€€€€€€€€¸÷Ž€†"U*U:W*U*U*U€àÝ»·€€€€€€€K™³æŒ˜°€À³†ðŒ€Ì™Ý»ÃˆÝ»÷Ž³æ°æÐ;7:C™\;��������€€€À€€€€€€Ð»÷îݻÙƒæÌ™€€€˜³æÿùÿÿ¿€€€€€€€€€€€€€€€€3·ˆ€#*ÀA*U:U*A@éÝ»÷€€€€Œ˜³€À€€€€€€À€€"˜ ÃˆÝ»÷Ž€€€€Ð;w€°æpn];��������€€€€€€€€€€À»÷î€Ì€€€€€€°€€àÌçÿÿ€€€€€€€€€€€€€€€@€€´ˆƒ€ð T*U(Uà€€º÷îÁ];wn]€€°†Ã€€€€€€€€€"„€Ý»÷îÝ»÷Ž€¢„ˆ€8À™€àŒ˜P;��������€€€€€€€€€àÝ»÷î°†ƒ€€€€€€€€æÿŸŒàÝ»÷˜€€€€€€;wn];wn]LaàÌ™³ €à€ T€@ÿÀ'wn];wn@;wn]€€°€€€€€€€n€ˆŒ€€€€€€à€€€ D€€€Ì¼à€˜³æ��������€€€€€€€€€€€€€€€€€€€€€ €€€€°€€€€€€ø¿àÿÿ¿€€€ƒ€€€€€€€€îݻ̀€€€ €€€À‡€€¦ðî݃€€€€€€n];wn];°æŒ€³†7€\;wfÿÿ¿€ÿ'wn];wª•On]Y;w��������€€€€€€€€€€€€€€€€€€€€€€€€€€°€€€€€€‚¿øøÿ€€€€€€€€€€€îÝ»ð‡€€€@*U;W*Ua3¦ðî݃€€€€€n];wnaÌ™ÃáŒh]ap€ @€€€€€ wn];GˆÁŸ¨…\;wp��������€€€€€€€€€€€€€€€€€€€€€€€€€€°€€€€€€¢€€€ü€€€€€€€€€€€îÝ»ü(U*unU*¨U*U¦ðîÝჀ€€€€n];˜³æÌ™³†Àn];t†°†÷îÝ»÷îÝ›w8Cà•¼€P;w��������€€€€À€€€€€€Ý›L3f@™³€ðÿÿÿÿÿ0f ž€€Äˆ‘¢€€€€€€€€€€€€€îÝ»ü™(€0€ U*U*U*U¦ðîÝ€€€€€€nÌ™€àŒ€³æŒà8ƒ†³†÷îݹ÷ˆ€š€€€8w¨ž@n];wn��������€€€€ƒ€€€€€ðîÝ»÷îÝáÌ™³æŒ†üÿÿÿÏÿÿÿ€€€€€€€€€€€€€€€€€€è݃€†T*U*U*U*U*€¦÷€€€€€€æÌ™ƒ€Ì€€ÌЀ€³†‡à‘‚÷îݛ̙ƒ ðn]4n°†wn��������€€€€€€À€€ðîÝ»÷î±æÀ™ƒ€€€€àÌÿùÿÿ¿€€€€€€€€€€€€€€€€`L¢€U*€*U U*€¸÷îÝ»€€€€€€°€€€€†€€€€ŒàL€ˆ†‡à‘‚÷îÝ›€€€€ƒîàÌ™P;wn��������€€€€€€€€€€ÀîÝ»·˜³€€€€€ €Œ€€Ã‡Àÿ€€€€€€€€€€€€€€€0f€€œ€Œ€ð‡€T**D à€€€Ý»‡wn];w€€Ì€†€€€€€€€€À€÷îÝ»÷îÝ›€ˆ€€è€†€˜³€€h��������€€€€€€€€€ ÷îݻ̙€€€€€€€€ÀáÿŸ° ÷îÝ€€€€€€n];wn];w0FÀ™³æÌa€ÿ €€€pŸ°`];wn];wfn];w€€Ì€€€€€À;—€"D€³€€€€€€€ƒ€€€‚€€°†Œ€°æÌ™��������€€€€€€€€€€€€€€€€€€€€€€€€€€°€€€€€€ø¿æÿù¿€€€€€€€€€€€€º÷€€€€€€€€€€€€@áл÷€€€€€€€;wn];wnÌ™³Ì™‚tn]cÿÿÿÿÿg];wn]ª•:w`n]��������€€€€€€€€€€€€€€€€€€€€€€€€€€°€€€€€€ˆ¿øÏü€€€€€€€€€€€º÷îü‡€€€un]+U0àл÷€ƒ€€€€€;wn];˜³æÀ³8wSƒ„À€€€€n];wn ¢ÀŸªàpn]Y��������€€€€€€€€€€€€€€€€€3f€€€€ÿÿ°€€€€€€ˆ¢À‡¿€€à€€€€€€€€€º÷îü™*U*]*W* U*Uàл÷àƒ€€€€€;wæÌ™³æÌ™€ºwn]›Ì™Ý»÷îÝ»÷Ž]7n â•€wn];��������€€€€€€€€€€€ ÷†3fL3æŒþÿÿÿÿÿÿC3ž€€¢Äˆ€€€€€€€€€€€€€º÷îð(aà U*U*u.€àл÷€€€€€€€;³†€˜ƒàÌ™³€w`€Ì™Ý»·èݙĎ˜Oè];ˆžH;wn];��������€€€€€€€€€€Ð»÷îÝ»÷˜³æÌ™ƒà€þÿÿÏÿÿÿ€€€€€€€€€€€€€€€€€0¸÷€† U*U*U*U*U*àÝ›Œ€€€€€€€K™ƒ€€€€†€€°†ð€€À™Í§ÃˆÝ»÷޳æ€èÐ;w Ìa];��������€€€€€€€€€€Ð»÷îÝ»À™°†€€€€€€³†üáÿÿ¿€€€€€€€€€€€€€€€€3´ˆ€*€*A*U €îÝ»÷€€€€Œ€ƒ€€€€€€€€€€€€¢˜ ÃˆÝ»÷Ž€€€€¸7˜³†tP;��������€€€€€€€€€€Ð»÷îæŒ€€€€€€€€¿€Ì‡€ø€†€€€€€€€€€€€€€€L€€´€ƒ€À‡ T€U"EUàƒèÀ€îÍ];wn]€€°†Ì™€€€€€€€€"€€Ý»÷îÝ»÷Ž€"D€€Œ€°æŒ˜³€��������€€€€€€€€€àÝ»÷î°†€€€€€€€€Àù0ÌáÝ»÷†€€€€‚€;wn];wn]L°æÌ™³†‡€ð‡€€€ÿ‡€:wn];wn];wn]€€°†€€€€€ön€àÌ€ €€̃ D€€€Ì™€€À™³æ��������€€€€€€€€€€€€€€€€€€€€€€€€€€°€€€€€€ø¿æÿù¿€€€€€€€€€€€€îÝ»³€€€€€€€€€€€€€ ¦ðîÝ™€€€€€€n];wn];³æŒn°†‡ˆ\#wfÿÿÿÿÿ'wn];wFª…¿n]8w��������€€€€€€€€€€€€€€€€€€€€€€€€€€°€€€€€€‚ƒþÏùü€€€€€€€€€€€îÝ»ü‡ €:wn];wn]A2¦ðî݃€€€€€n];w.æÌ™üáŒh]@†Œ€Ìn €€€@;wn];Gˆð‡Šþ@;w`��������€€€€€€€€€€€€€€€€3fLð‡ÿÿÿÿóf€€€ ÄˆÁ€€€€€€€€€€€€€îÝ»ü™h];wn]; U*U¦ðîÝჀ€€€€n]K™³æÌ™³æ€î];wް†÷îÝ»÷îÝ›w :7à•`];wn��������€€€€€€€€€€€èÝaL3f@™Ãÿÿÿÿÿÿÿf þ€€Àˆ‘‚€€€€€€€€€€€€€îÝ»ð‡"€€€(U+j€@¦ð€€€€€naÌ™€æŒ€³æÌP‡€³†÷î€÷€€š€€C¡wnÀŸ€n];wn��������€€€€€€€€€€ðîÝ»÷îàÌ™ƒ€À™³àÿÿÏÿÿÿ€€€€€€€€€€€€€€€€€@i € T*Un]*U*U*¦÷€€€€€€€€€æÀ™Œ€€€€€À™Ð;€€³†‡à‘‚÷îÝ›Œ€ƒšôn]G³8wn��������€€€€€€€€€€ðîÝ»÷̀€€€€˜À™ðçÿÿ¿€€€€€€€€€€€€€€€€`Lœ¢€T(€€*U*U*€º÷îÝ»€€€€€€³€Œ€€€€€€€€€ƒ€€ˆ†‡à‘‚÷îÝ›@€€‡à æÌ™]tn��������€€€€€€€€€€ðîÝ»‡˜³€€€€€€€€€ÿÇ€€€†€€€€€€€€€€€€€€0€€àÌÀŸ€Q*DU*€þ€¸wn ‡vn];wƒ€Œ€Œ†€€€€€€€€D°€÷îÝ»÷îÝ›@ €³€Ì™³æÌ™��������€€€€€€€€€ ÷îÝ»Ìက€€€€€€€˜0° ÷î݃€€€€€€n];wn];w0Ì™³æÌ™ €Cÿ€@ÿ€@n];wn];wn];w€€À™€€€€à];—€"˜³€€ˆ"D°æŒ€‚€€°†€€°æÌ™��������€€€€€€€€€€€€€€€€€€€€€€€€€€°€€€€€€ø¿æÿù¿€€€€€€€€€€€€º÷î±€€€€€€€€€€€€€Cáл·€€€€€€€;wn];wàÌ™³:C™Œ€t]cÿÿÿÿÿg];wn]ªá¿ wn@]��������€€€€€€€€€€€€€€€€€€€€€€€€€€°€€€€€€ˆ€þÃü€€€€€€€€€€€º÷îüŸ€€j];wn];wàл÷€ƒ€€€€€;wn]€˜³†ÿC;wCƒÀƒ8wn];Gn];tn¢üÁÊŸHn]C��������€€€€€€€€€€€€€€ fL3ÿÿÿÿÿÿ`L€€ˆ‘¢°ˆ‘€€€€€€€€€€€€º÷îü™(U*]:wnU*U*U€àл÷àƒ€€€Œ€;wæÌ™³æÌ™ƒ¸wŽÜ›Ì™Ý»÷îÝ»÷Ž]Gn⃅ƒ8wn];��������€€€€€€€€€€€¸÷3fL°æðÿÿÿÿÿÿÿOÀÿ€€€¢Ä€€€€€€€€€€€€€€º÷îÀ‡"†€U*w.*wÀ àл·€€€€€€€;€³æ€˜ƒ€Ì™³€p€Ì™Ý»ÃˆÝÀŽ€€pà];C‡:wn];��������€€€€€€€€€€Ð»÷îÝ»‡˜³†À™³æÌðÿþÿÿ€€€€€€€€€€€€€€€€€08·€ Q*U+W*U*U*U@က€€€€€€€C™³æ€€€€€€€€ðn€€Ì™ ÃˆÝ»÷Ž€€À†Ü;wnMŒn];��������€€€€€€€€€€Ð»÷îÝ›Œ€ƒ€€€€€€þƒæðçÿÿ¿€€€€€€€€€€€€€€€€3€´ˆ€Œ@"e0€*U *€€àÝ»÷€€€€Ì³˜€€€€€€€€€€€¢€ ÃˆÝ»÷Ž€ À€œ‚G™³†ô€\;��������€€€€€€€€€€Ü»÷îæŒ€€€€€€€€àÿ̇À›€ž€€€€€€€€€€€€€€L€€°˜³†€þ€U("T*€€†€î];w\;wn]€€€€À™€€€€€€€€Œ€Ý»÷î€÷Ž€"€€€Œ€³€À™³æ��������€€€€€€€€€àÝ»÷î°†€€€€€€€€€ž€@áÝ»÷†€€€€€€;wn];wn]L³æÌ™³†7€€þ€€€€€\;wn];wn]8wn]Œ€°æ€€€€¸wn€àÌ€ D"À™ƒ D€€€€€€€Ì™³æ��������cc65-2.18/testcode/lib/apple2/catface.dhgr����������������������������������������������������������0000664�0000000�0000000�00000040000�13473601511�0020176�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������DDH***D�k�.JLD)$2D6K�jDJD!DDJ2��jo7 �D��"L3L3����l^@!D1L; !��@ �D+J���n##n;D��H!HM ���������J*JHDQ$�"DJD+J3**DJ !$+H+*1D�D?���@" 3L3"����nH3L+^+H� D+�T�"H3L3L;~?@;N3L3L#��6�"� L��������H#$*��D�� @*J�@JD+L!@m+���D D;DHL2*!^*,�.��� "H3L!"���@DD,{,LH2D+@!HwH H2D3^?Z?N3L37"j�!$H����������������n� hO~@ H1D1H{N $.#����L3D@)m2L!D � � " #���� *2,6,1� �D)D!DD"Z�>7?L!"HH^�T!D3L!�!���������@\;�3n��8J#l;��D1 H#j��.3HL ��L����H+-*D" @ H! #�@D6J3�� H���@+"T DiL3Lz^?J2*+k;N;\3k!�Z H:HL���������@H2? 3j�;L3T?1L3h7�3$;�9J!~7DD���D2DH,*!H3L#� � @2H3H"H1,!D@����)$- "j+<)J7j~{[+*)-*J!K H!-�(�����������J2L+f2LD;�3L3H�d7@3L3.+{NL+ �H 3LL!L3L33L7L3L3H3L3 !L$"L1L"�)D!�*Dj>7{?~w=7L�QDPH��������@"J"DHo�� T+�"L3L?��H;D!L+L D HDH 2L"H3L3sL3H3L;L!L21,D+L!�@�0)*$�@*w}~.6@ �!H�H"���������DJ+*H!j"�6J L ),2.J Z"D$*$*+J��Q;��L3l3 "����n?/�@D+*+@��@ �m2 H �l?n3�H"*!����������Da*7*��*@H2L3D1l*D!L(&*2DH,+J6NH��@7��!L1LD!���n@ H+,:n2 lD"-"2L3l;o?Do;N3L2 "!�QD��������D*+�����1 �!D32L�^3@�L�$2 l+k*J!�6����#L3� �!H!,k/J!D!�1L*� $+H3L3n?Z{N3L#L3L"{ D!D+��������D�����.�@PN ~�LH�z- ,�J1�����N+D)K6J�����#H"H��D2J+J�"H� $15 �M7HD1~7Lvn�+TDHzD����������H�n;�n��8*#|{�H2L!�$?�#j� &3H?J�L��� H)Z6 !H �@!HD7l2H���D!D ��DDM�-*;N{~{L+,2\;N;L3*��$!D1HD���������!D~ 3*+@J3h{� D#D!H�d;H2,;�9L~+�1H��1L1!J2"H3L2@ �""�2L H2JDH!�@�D@)T!J�-*-lonmn7J+/+*J@\� ����������!D@�D3J2LH?�L3JT;�3 1F3� HJ�!D1D2D#D!H�H2L33L;L{L3H3L3H�D"DJ3IL!��"$!Z�*+jo~o^+J@D�DH ���������JJ�o3!��d*�!L3J3�?� L{o�1D;J��"HD!H"H#H#D3N3 3L3H3l3"L3�"D1HL@�("@)H"(�",{~???o7-5�H"����������H2J A*-2J!Z�j!,1DL+DkJ�:D**J$J!%$;JD�~;��!H3L3H��n D2,;D����$+D!D��1n@hn�!D!"@*�����������H#D(zN��!$"�*H2*2DH*J"HH**JD2J2*H�?����H3N�� l"!1,3m+D!-��)D ���#H2L;nD~;l3 #�D1�-!!��������*+�D���**L1D3Dn2���o*D�L3L,7DD!H���" 3L2����@1Jr^6L! !� #:!*"�m"3 #L3^J?N3L3H2N!�M�H5����������� ���3n��N�o#�"D3L @L"l�&#�H��L3,@<+$1�����!H2H2 ����**J+*�D��J"H$�D;� D3m:Lz^3@�1J"6M�����������!!j7@3f��9L#l;��1D�D?�2j�&3D�D!� ��@&l3!H"D� 2"�!DD:,��$�8$!(�*$~l6owLkJ2*wn7L7L�"DJ�����������D~L2*;H9L#L?�3L l;�#,;�:L+D�� D3L1DI!L3L"HH"�2H3L!,HD��(��"*!� /6.)^/~?~7=;j2^2-!4 H$#��H���������@*D 3H3,3 �d;�"3L3�d;�1H3*3D D1DDLL�D3L3#H{l3H33L3�"D1DD3L�"@ @(*H*m{??m; J!!����������)2D!i;L"�H�H3L3@;���1L.�D,/!D1"H*"#L3L3l3L1L3L;L3LH2�DJ!D1D��D��"H$ ${~o~o{_{,*�H*� @)D��������@)*+DRz*LLD*J;* �,(%(!**D!HDD3L1!� m{ ��@!L3L ���n�D:^+H��.!H1 "H3l+�jn3!�3L"� D  ���������***!���(a1L1DLH�* !���,*DHL2JjlD!D?����@" 3L3H"@��l@HJ+mLDD!HD/���@" L3l{*;n3L3H"���sJ$@H��������D"� �"D�(1,!�"LLD!�*^�oD2HDN2,!*:D!�� �!2L"H����� D),{>;D��@M1J�-�HH2L3n{*N3L3 #D!Ld!HD������������D!@2f��J~*�HD1H H{L"d�&3�L"�l3D��J:L+H�"# "�� ,{.2,D!�DD P3LD!L3~+Hon3"�2H#,+�iD!^�����������HT;3n��9J3l��#D!H d�3j�*3l!D�L!��)*+D!H��H #H��H Hv.D �" �*Z5�J7={_7D6m/$;m;^++���+HN���������� (!zN1,; L#T?2L�\7�3,;�;L!1D��LDH+,@ 3L3�3L"H"H3H#L1H2L!1D��DMS)��*2-2m6_o~o]+k*.HH!H� ����������J3H~;�3L3�H?�L1N1Hh7�2 #,DD+J�H" LL" "L3"�3M3�"L3L3!H!D2L3L! ��ML!�"H5^~kk�J� ��������@*)D�?L3�d�"H3l3 ;��D3nK H"DsJ"HD]2 3L3l;L2L3l;N3L3L# HRHDL"��D)H@!D*J�(.m{~?~noJ!H*�2H���������$*^**Z"@*DD(+J3D1J"JJ***!DJ*;*H�;?���� 3J3"��^?�!L+n+H!@6�� D*HL3n;y?n3H3J� *����������DQ$/�� *@L1L+J+!$2D��� *: �@,*LkJ3L!H �?����!L3L1! ��l!��D+J3."J�61D!$D ��T?,?-D"@"\H6"H���������H$!�$�t%M�L+J1 !�ioD���D��l+D$;*3DD� ���H# #���H)J:^2H!�HQD6�5JH3L3m7,{M;L3 #DD"7H! J��������@�DL!Hn��J~3� 2D1H�L"j��F1�3L��l+D�!*+ +D��H�2H#�@ �*:-*D!� D�@1Z 5H3l#L1L;2D*m;LpL#(9@M$"�����������@(;�3f�:J3l;� H2L#d?�"j�F#l?��D�!�@L2HH!@�"H !D+J!��@��� -kHL/n;=J;^;J6^wm:D>�9D2T@����������!$)HmN ,9d)L#D;D#L3H�d;@3L9;LHD�L3D!H*�"L3L33L"L3@3L3 #!J$"D!� �@D5H*�J*KoZz~{o{o;>7z7_!@!1D�$����������J�{;3L3D;� H3, T;�!L3Ll?�!H+D! 1D2HH! D"L3 "�{^;�"L3L�!"DJHL!D) �JJH�-[7~7[+H*�MJ*���������H$+,�;^3�\"�L1L3�3 L;~?�J;L�!H!D"L2L3N;N2#n;n;L3 #�!D!H2L!�  �! �2=o{n{7=7J"DQ��H���������D!H�H2-3,H**L)),2D2*"*J)J*JH(k,7JH ��Z;� �!D3l3H!���n;�@D=7 �@T��� -! 3L3N{7�?n3L3"Hw�������������H%Q*;J���D+��D+H2*D$:H���J6D!J3*).:,D?��� !H3L3 ��DD"H)lz[)H2L- @J��� �,ZL!@"D!1)H���������@H�!*�qD."!D2D1D!�5^D@o!�!Dl2 $kJ2$!����� H#H# ���!D+*7k2 � �qD*�@+!D""L3\D>L3L#L25;�)DD",���������H3L3@n��(J"~;�L!�@? !j��.#�3L"�L3L��$***�� ��" H!\7Z+���@�HM�T.3L#Lw^*q;LJL1jZD+���������� !@?3f�;J2T;2L�H;@3l+�F#l{@"H���HZ+!H# !H!@�@"DH!+,�� ��!!L6� !$*Zvn*{ko,+^/,?i� HjD�����������J+uN,;j)L#$�"2Ld;�3L:JL2oH��L3DRJ2�!L3L3�3N!L33 3L"�!D2I3LH�(: ,kZ{^m?n{m+k�H��H����������$1Dj?DL#H�T7� 3L3HD{� L3Ll;AD2L�HH3D!D! "�L3 �sL3�"L3L!�""LH"HD @"$ !$5<w}~m72!*�(����������!J$H�~m3 L"L3L3H"�1��L;o�J;�@ D@�@2L3l{o2H#n;N3L3 D1D��"D� H � Di^6=?_7m{^2 � "� @���������)D***JA*@)D,D,+D J(H2<+LD!,3J:$�$���HL3LH"�� n7� H"D1n:HM!*D# 2L3l?�{n3L2 #-@�)��������@�**D����(* $D1,�J3H���$+�DL+Ji-+L���6���@"3LH"���DH,{J!D!$#�D2D @"l{J;N�!D�H3��DJ��������@���!j�tn@ D,L�5^D�o@ �� N2L!H*m+LH����"3 2 � @ DJwm+D��@7ZHT)DJ"1^{D?J3L#"�(HiMH$������������1n3�3n��(J}7� H#L3H"j��&3;L!�L3�� H2,3H "H�!H# " !@J+-2H�L!�)� 1J)@jM3L3N{mq,*~;L3N3.�)�$2q�����������?3j�J3l�D3H d;�2l+�*J~;H���@D!,+1D� !H!�!H1!H3JD�� D(@ D*$$,1jk,*M7n7-**;J6I��D"����������$DjoLn;L"H;� D3,3\7�3Lf1L1? H1�!DD1%D!�L3L33\3H2L3#L3H$1LD1L�@ DH+D�$vm+mw~_z>;Z�)#5�H���������LDTL D�D;�"L3L3D7��H2~!L:J!D #DD"HD�D3L�3L3�!L3L�H2L"D!HL1�� ��H"�*j?{??^/�)T!� D@���������*2DZo3�D@!H3L3H�L{+�1*7D� !@�!D3l~""~n3L3@,!H"���@@�HH���)Z7m7>/^/j*�D!� ��������@$j.) $"�HL(+J+DHJ*J&$)+*DDD**6L1��(;����H3N3H@���n+�$2m+DH!5D @D72L# 3n;?;n3L#H2 d��"D ��������D$7�@��2D�L2D1D!l+���$*$�,2L*m2J! H;����� 1L3����H�!J7*!HJ�D5!Z�J�njlD)L!�^!H �������� � ���&�8PNm�D3JD�:M�D�#.#���Hl+,2.3DH��2H"����D2$;+�D!��HJ#�-H! �lz{LH3"H"L!Md@����������!n3@2f��*J#|? 1LHD?2j��&#H;M��L+���D*Z+@2H"� H",z-*D!��@"u)DMQL3L3n-L^;l;l3^! M!D+����������D3j�;L#D?��H2L!�d?�#*;�)J#~;���HL!@J3HL2H��H"� #L1J1!����*d Z2Z2,2^;_/.2,2.jJJ!)H���������@I"Po!Ln*LD;�HLd;3H+n*Ly/D3D�DLHL@" 3L33l3L3N33L3 �" )D3D�(@� (@D!�$2Jzo?;mv*6H2H* ����������*1�4N���h/�H3,3LH;�"��L2D�D3D1H "# D;L33L32L3L#",*2D3L"�@D �Zzow[:DD������������H"*+H"�${~;�L�L3NH�"��lo!!Dn.D����"����1N!"n3L3��� J7D!HH��@D��H @@!,z>om{^3,H� D� ��������R"H%U%$R�HW""bY%H�@WB" R%"�$UV�I~_f� � Ffb @�b]@uUU ����@$e���b]D~w&�$m $ ��������� $ T_U"@ Ef%f% BeUdIBU]U  �Vo B��Zg�@�@bfb �d_��@Vu=%� B8"�$[� ddf=gZ]wfD$I"��"���������"$[V��PU(�"YeeB�RB��$� 4e"Ye e[V "@P��� Bfd����B""=m B��$B(BU�fbDv]o}wf $ f"}B�BB������������V�n]�$V b �w $�tr �����e e]UB��@�� DF$@� @BYU]_B$ �%Bm n��f}'Yw$D��R "@t& ����������@b]V ��7@'�$fD�]V&]��u Yo �YB���e]FB$ �f$D $[WE � ("IjUWYv}oXeb}vffB$ BX%�@�����������$H"tw VM�US �}G�@fB f]Wb_B�@�$bBBYBBFB�@ B @�d &"e $ "B���$I�B$ R�R%V5o[vWv=eVYo "� R �E���������$"} 5Ye�%�$fF@}fUUf�$ e �B bBF �$fFfYffFff �$&Y&f � P� $B�BXn[w}_w]U�&"&� ����������"Ub�V���}"fF �[���@dUU�$bB$DFBfFfff�bd b % f & ��@R$ B@�U[w}}__nYB% "H"���������$@HU5mTW�IUR & "Y&I_� ]D%U& $ �B=e @�~]g���dfB �d} @Bf=V ����� m[" @ b}?DB��$@$���������%� U )BU@"%" %Y& U% $ bU% � eIe"�$@vg����DfF�� [bYn[% �"UB�R �DFfYwov}wfF�BV $����������"%� �� e b "I" B�eB���R @U%��&R[V �$I�@��DfD @��� bf[W"��� $]BUD�"[B&fv=owoYfFe�)&�BX"����������������R �r[B b&I $]�Hp��� �f�V[eP" � @�BfB��@��"Ue4e$�" � QDB%B'Dv[eXw@B�$ &Z"HV�����������"$[F6�w V�@B& @}gf\��u ]_�B�� B�@� VY% $ DdD@B"�BUmU"�@�@ZBZ"�U&oYv{VeUUWogV$�@ W�����������"&Pwf]�\u�&�DdD@FM�WbB "��@&" VU$ bfD�$$ @ bfDVB& B���@�$R""UVV[v??oWuV}�@" @%���������� RBu6Yf�}ED fB @}BFV&YwBV� F f &""�@fff9nfFfFdbbf H BH" $o[o}}vWVT@�U DR���������� T&$4]&@��DffY��$Y &V� bdB "BfFfff$ff fD $IV"&�� E��$H%�P$5~{w}_%dI� P$���������%�"TVUU"�"]�HV "BV%v$U$H"HMJ"�R[f B�u?g����bvF��d{w�$Yu=e�� ;%D@" f}_Dw@DD� H"@���������B�"{e��$Y $fbXeY"RP"�"TYe$ �YeTwY��ug���&fF@��� ]��$VYvWF��T $ W��BDfo__{w]gYfDB�R �D �������� B5� �BPn ��"% f�mY ��r IU@ �UR]%$"�BfD�@��B RUv}W" �b " �T $fv]v}wffb $ uB$&������������@�R��w j_�@ "$ �Tw�" �t�$��YU @U=V $@"@dD �$YVe �$B"$)j(&$oFIo���Dn\�H" u����������  _&V��3@g�Df D�}'$]��u@}w$����HV5e�B$� dB�$ BDXVY$@� �� $R&i"yv}w_U^[U[vYg]UtB�4Bm ���������$B@�fM�\U�%�Bf&�fU'PWv_@"�" fd"Df$FDDFd$ V %$$�� I" u $YUe[o[_w=oYe{u  �$R����������"Y&Z_Bff&�BfdfeFXw"U�$& b $D @ffD9v=fDff@$ R%&� &  (o7o{w[7U5�j"b ��������"U%�}_fB� _�bfb(� f}dYW B B "HV $dffYff$vffFDRff��%PA"$B5m]w__w?U E�T "H$�@B����������B m[e @[�HUbRPb&IU ""% UYUB�9JUUB�Zf��@d f&@���b}U�B$IWUe�@���m @�De$f]wB f �m�@���������� B("uo ��"U� R%V" Uf��"[V�XVIVRB@TW���@�dfd@���$@� ewB��g&@(B��@ ff}w}g&� V@BB����������"$�"� "u� "&&v��z�HR��YV${e" @ �����$FF� Vm=U D�Bbm��uBFg{m[vfdF B" o���������� "�6 �w f_BBf B�4w�b\��r b��eTUUR�@���$ dB "5^UU ��B��T @$ &UfDdw=" v]& ""R)V&@����������$&b@�7 &$ b&�&f]��w@}V��� e%D B@ DF$�$$ "YVYB��� � B e5FTo}v=%Uv=f9o=_}bIB)"b������������" BPfM]U�}&�$ "D dUIcv? B��$& &VFfDf"�BDffD�R$ Bb��$�$V Bj[UYo}w}w{[v=o]n�$"�$���������T%�TBff�%DfF �ff}W�Df�bF$$ D�bfgYf�DfF�&&I$f@$ T"P�U}v__o{fIb$$ $����������"f }_oF���dVF �@f_w��"Te�$ "�b�dfvYw f$]gYffD@$ Bb�@@@B� Yo?_w}]o[f d ""��������� "$UUUUB("]�PeVV bURe� $H%eT �X&9f"@�"}g����FfB �b_G� "f;V ���H%$Y"ff}�"$ ""� ���������$�$W ���� U" &"V" YU �"[U) �YVve B��5g@�Bfd ���@ $fUoU"�I%B ��@� ���""]o{o f@�@"UH" " ��������@ ��$ �U�u�$ b" @�v@�Wz�" �VB5meB��@@Df$ �@�"VuoWe " ��vX%@o�Ddv}_[vffD4@]�)"�B j����������f�V ��wd?"�$&b Yo�b\��t f D��f��"eBB�DF$@� $[eY&�B �%�$& j�<bBVYo{bP]fd f"E�jB]����������"}gV�@S�&� & B@}&&\��w$W $���B �VU&B&� F�D $ DgB���@�$R" &)�R4o?5V9mUI_]w{B%�@ B$ @���������"" fU%]g@W�Df B@BdUwTe ]$&�Bf"e[@bf$f@DFffB�bbYf$ �  j%jUvv}~oo[V[U �BB4�� ��������� BIb f�bf�EB fF �}df@'BU�&b"bD��dffF�DfB$dBXVf�� @ $RIB e]w]e@@" D� ����������TR $�uwf��]�Dff �@wo� bU�"$ "$�Dff]w fd]wfFDD b" "��  �B "  $Uu[n{~?w{w=U"$ B���������%� TU5U %$W�HR b" &YeP%RU%QTVUV"�TUe&��@_g��� dfb����dD�bu]% � � [" bFff]EwfF$%@$���������"� 5U��� E &&HeB�$YV���$UU@ �UmU&$�@HG����FfB��@��$UXvd U$B" @eB��D@=__v"�@B UWD����������"�" �w�nU��BX& b�~|B@�Ye vYb " � ��DfD��@��BbUw[%$ �� &["4% @ Bdv]V|ofFD"9EW$$ ���������� f�V��7R]E�@b$Xw&��rv ��YU�BYVYV @$ D &D@�"U_b �$ E�bUA$fff]]bv]fYbvDPV�"$(�����������B zfV�Ps@'� dD Ed\�wB%"��� @VY%f �dD�@�BB" u"� ����UTH"U� T[m]]e5v[Vm[% &��& B���������B& fU']e�&�BfF @}FUw\e " %�b R B$U"dfFfDbFffBb("" F ��R@UI"I�UvUvWw}_[v7e ("Ib$���������R"@g�fF��}%$vb��df d"YV�b b F "B  "f�vbf $BD&Bb � @R e)B@UW}_}5%$B� $��������� RU& D�T}w]f����bvb��� Yw}&B b=U ��@B$dg]fdw]gf��BB $ F� I@ $@@V}w=o}o=^We B�$ BE@�E ���������"0"e]e$B@&V$XVVR bUeTUU@�UUV&B��{f���dfd���b}""m{e�Dj@��_fFf]%(_wffFv � B��������� "Bye��� U&�f"U $"U%����BWV �f vV $i'����dfD��@ $ "u" � @ & mT%�$ $]ww B @&BDl$���������  ��" �u[�" %&@B�r��B�YV TWV$���BdB �����$eUv"�B@"$�B�@B&?e:ofF$WVTb  ���������f2 @�w`_%�B&B �\g&\@�rg ��%�"HU5U� �@BdD�� B"5u]U@�B �$@ uET@ ^df]wT)m=wYdf$u$]B &����������" $VgV]�HW�&�Db B�&&\�7 EB��@$BeB $dB$�"d$VDB�����UhBD%"7VYe[o[oYV5}IWmmB(�����������$%�dYw e�'�Bfd dXw]f�B& � dB $ "BFfDn&fFff$�bRff��E��&(BX &Yu;ow_}?}n=U $ " R���������T$�}w"��E�$fb} DdfdXe d& "DFBDf $gYff D"""B H$% UH"�PV;w}oUE""@E���������� BY%B ]f�@�bf&B�$]_" $ f]e�� B @���"v=FrwYvD��b"D " ��"B���T@V=_[o[_WoY%"BB"� "����������B�DuVV" "[� "& V eU&$�R RXR eYeB�Y&YW " �}w��FeB@�@�d?$ bYvWV�� '���@HDff]'XwfdD�B[@@�R���������$�RUU ����UU@bH&VB�R&���"$YU �YUUUeB�(E� DfFD��$ B$]o " D$ %"@ b  f[v}w&@$ n � " &���������� ���� b �v@�$ &BP D�~r ������V @I][&"�����$ dD�"U%oYB$��Te""I$b��DVVUvFdvR"B ����������$�bFV ��7 _%� $ d��zgd]�rYw $��&��$TV%B��$FB"$]vY&��$ H��@ & B"uvg=wVU^_vff�R$4&R����������"ugf\�HS'�$Fd @}f]�wb$��& "&BDf$@D dF De"B��@P%5B dU%UUU^=_}o[UUUIVj�j����������"Hb�}dUsTf�EDfd�fs\f $R�f&&B�"fFvffFffD "d&b��$ BTBEU_}^{ww=__f��"B�E@���������%R�}w @���_DfF�|� Dv bXW�F & $" df@fDf fvDF$ JY&f��P�E�&$Ab}}_wU&�EBD"����������TRR��5[f�@�dff�d]��BVYV��@ $ "@�@ f]Fvwf D$5%B$�B@�$ "�@RUn[v7^7uB�$ @$$d���������cc65-2.18/testcode/lib/apple2/chips.hgr�������������������������������������������������������������0000664�0000000�0000000�00000017770�13473601511�0017574�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������D"@€€ @€D*UjWW*U*U*U*€€€@ U*U*€€€*"U €€€€€€p€T* T*/U *D("D *T"D€€ €€€€€€"DQ*W*U*]W*U€u T*��������"D"D"D"DU*}_*U*U*U*U*U*UD€@€U*U €€€€€€€€€@~@*U€T  U*}*U**U€"E U*T("D€ D"D(U~u/U*u+U*€€*"D��������"D"D"DU*}{_>U*U*U*U*U*U*U€ D"@€U*U P €€€€€h?€(U @*U€€€€*]zW*U*U*U€p?U U*T(Q"D"D"D"D*u/}*U}+U*@~ €"D��������"D"DU*U}_*U*U*U*U*U//€€€€ D"DU*U"€P U*€(U €€€€€€*U*U*U*U*`_"E U*U*U*E *T(U"D *UzwkU*>U*U€@? "D ��������*TQ*U~}?UU*U*U*Uj_z_j€€€€€€€+D"DU*T"D€@*€U*€€€€€€€€(Uj*UzU*U*@~W"E U*U*U*U*U*T*Q"E**u{*U*U*U* €€€"D��������*TP*UW*U*U*U*u*}/_/€€€€€€Pj€W*T(Q"DU*D"@€€*€€€€€€€€€@*U*U*ujW*U€P"T*U*U*U*U*U*U*U*U U*U*_*U*U*U*@~_€D"D ��������U*T €€T*U*U*U~_~Wz€€€€€€~+U"D*U*E("D *D €€€*€€€€€€€€€€€U*u/U*U~U*h+P"D U*U*U*U*U*U*U*Uj€@* U**U€€€TD"D ��������U*U €€€*U*}*o_€€€€€€`(U*"E"T*U"E *D €€€ €€€€€€€€*}*U*u/U €€D*"T U*U*U*U*U*U*U*U€€€€€€€T*U*hP€€"D"E*��������€€€€€€€€€€€€€€€€€€€€ D #€€€€€€€€€€€`€€€€€€€@€€€€€€€h+€(U€j€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€ D.U"D(U#@@z_€€€€€€��������€€€€€€€€€€€€€€€€Ux}?D€€ €€€€€€€€€€€€€€€€€€€€€€€€€€}?€"€€€€€€:€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€  "T*"@€€€€€€€€€€��������€€€€€€€€€€€€ @~?_ D€@ €€@€€€€€€€€€€€€€€€€€€€€P€P*€€€€€€€@>Q"€€€€€€€ W€€€€€€€€€€€€€€€€€€€€€">"*  }€€€€€€€��������€€€€€€€€"Dhzu/"D"€€ G~€€€€€€€€€€€€€€€€€€€€ €*D€€€€€€€€€€€€€€€€€€@?@€€€€€€€€€€€€€€€€€€€€q{u . €€]€€€€€€€��������€€€€ @{W("D"p?u/Q€€€€€€@€€€€€€€€€€€€€€€D€€€€€€€€€€€€€€(? w€€€|#€€€€€€€€€€€€€€€€€€€€@hu?E"@?€€€€€€€€€��������€€€€ D]"@"DbE>>€€€€€€€€@ €*€€€€€€€€€€€€€€€€€€€€€€€€€€€€€Q*U`E €(€€€€€€€€€€€€€€€€€€€€€€D*D"€|€€€€€€€€€��������€€€€€€€D \ }"€€€€€€€|?€€€€€@€€€€€€€€€€€€€€€€€€€€€€€€€€€€U"WQ"T€€@€€€€€€€€€€€€€€€€€€€P€€€€€@€€€€€€€€€€€€€��������€€€€€€€"D~jG€€€€€€€@~_€@€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€Dx?DQ"E€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€"D€P€€€€€€€€€€��������€€€€€€€€€€€€€€€€€€Q*U*W~U*U*T*U"€€€€€PU *€€€(U*€€€€€€€pU€T*€T*]?Q"D"€"D"@€€€€€€€€€€"T*U*UjW*`}?*@€"��������€€€€€€€€€€€€*U?uo_*U*U U*U*U*U €€€€€€U**T€€€€€€€€€€~_ @*U€€€U*]* D@?"D"D€€€€@"*U?U*UzW*U*€€ €€"�������� @€€€*U*_*U*U*U*D:*T*€€€ €€€€U*UD€€€€€x+€(U €*€€€@*w*U*U"D €@."D"D"D"D"DQ*U~_*UkW*U P~€€@€"�������� @€"U*u*u+W*U*U*U**U/}€€€€€€"@€€€E"D€@? U* D€€€€€€T*U*U*Q*E*`€"D "D"D"D"DUzzU*}W*U€€(€€€@€"��������D"U*uou+W*U*U*U*Uz}z*€€€€€€€ "D€D"@€€€@*€D€€€€€€€€€ }*U~#D €xU€"D*D"D"D"D*u{}+U*U*U*h€€€ @"��������D"@*U*U*U*U*U*u/U*€€€€€€€T€] "DD €€€€€€@€€€€€€€€€Pj?U*U?_*U€}+T"D *T("D "D"T*U*U*U*U*U €~W€ @"��������D€€€*U*U*U~_.U €€€€€€€x*D"D*"D"D€€€€€€€€€€€€€€€€€€U~U*UjW*U*h*@"T U*U(U"E *Tj€€€€€U*€€€€P€€ D"��������D *€€@*U*}?u+€€€€€€€€/(*D"D""D €€€€€€€€€€€€€€€@*u/]*UjU*U €€*@"T*U*U*U*E U*T(Q€€€€€€€€*U*h P€€ D"��������€€€€€€€€€€€€€€€€€€€P€€ T€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€`W€€ D€€€€h€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€:U€t €€@x€€€€€€��������€€€€€€€€€€€€€€€@€wbG€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€| €D€€€€€€ E€€€€€€€€_€€€€€€€€€€€€€€€€€€€€€@`*€P*€€€€€€€€€€€€��������€€€€€€€€€€€€€z}*"@€€€€p€€€€€€€€€€€€€€€€€€€€€€€€p/€@€€€€€€€€@"€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€@ U+(U/€€€ €€€€€€€��������€€€€€€€€€:Dh€€"€€€€€€ €€€€€€€€€€€€€€€€€€€€€€U€€€€€€€€€€€€€€€€€€€€€@?€€€€€€€€€€€€€€€€€€€€€€@~]€xU€€€€€€€€€€€€€��������€€€€€€`uku+@€"€€t:q?€€€€€€€.€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€h"€€u+€€€€@€€€€€€€€€€€€€€€€€€€€€xuh€€€€€€€T?€€€€€€€€€��������€€€€€€€€D€€€( @€€€€€€ €€€€€*€€€€€€€€€€€€€€€€€€€€€€€€€€€€€@*@ ] €€€z€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€| €€€€€€€€€��������€€€€€€€€@>u?€€€€€€€€P*€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€u+€T.€€€@?€€€€€€€€€€€€€€€€€€€p€€€€€€€€€€€(€€€€€€€€€€€��������€€€€€€€€:}h€€€€€€€€>U€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€ W€€€p€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€@€p€€€€€€€€€€�������� @€€ @€"UzU*_*U*U*U*U* @€€€@€U*U €€€(U*€€€€€€P€P+U€T*€T:u*U(Q"E* DQ"E "€€€€€€"DUz]*U*UzW*€}/ "D��������"D"D D€"UjUW/U*U*U*U*U*U* @€€€U*U P€€€€€€€ €>U@*U€@€€*u;U*U*Q*EpEU*E "DD"D"D*u+}*Uz+U*€€ €"D��������"D"D"T*U/}U*U*U*U*UzW*U*€€€ DU*U "€€€€€`_*€(U € €€€P*U/U*U*U*€€(UQ*E *DQ"D"D("T*W*U*U*UT €€"D��������"D"D*U>}*W/U*U*U*U*U*U/€€€€€P D"DU*E"€@.€U*€€€€€€€€U/U*U*U*U*h"E(U*U *T*Q"E *T*Q"U*}?U*uoW*€€€€€"D��������"EU*u_U*U*U*U*Uz*}€€€€€€`€U*D"DQ"D"€€*€*€€€€€€€€€*u/U*Uj_*U€€U"T(U*U*U*U*U*U**U(U*}}*U*U*U*z€€@"D��������Q"E @*U*U*U*U*U*U?U*€€€€€€tU*D*u*D"DQ"D€€€*€€€€€€€€€€Tj_U*_jW* }/PT(U*U*U*U*U*U*U*U**U*U*U*U*U €hW€€D"D��������U"E €€€*U*Ujz+€€€€€@>xU**DQ*U*"DQ"D€€€ €€€€€€€€€€ U~*U:/U*€*T(U*U*U*U*U*U**Uj€€€€€T* U€}P€€€D"D��������U*U €€@* }{u€€€€€€€]: E**D("D"DQ"D€€€ €€€€€€€@A*UU*U:U*U P?E TU*U*U*U*U*U*U*U€€€€€€€€(U*€z T"D"D(��������€€€€€€€€€€€€€€€€€@ u#D €€€€€€€€€€€€€€€€€€€€€€€"€€€€€€€(€"€€€€]"€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€t? @(U€€xG€€€€€€��������€€€€€€€€€€€€€€€q#w/"€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€T"€€€€€€€`] €€€€€€€h€€€€€€€€€€€€€€€€€€€€€€bEx"t/€P€€€€€€€€��������€€€€€€€€€€€*WhU"D"€€hq/€ €€€€€€€€€€€€€€€€€€€€@€@*€"€€€€€€€€@€€€€€€€€@€€€€€€€€€€€€€€€€€€€€€Q+D"u:€€h€€€€€€€��������€€€€€€`W8Q+E"D€t€€ €€€€€€ €€€€€€€€€€€€€€€U€€€€€€€€€€€€€_€€€€€€€p/€€€€€€€€€€€€€€€€€€€€@€U"_" €€€€€€€€€€€��������€€€€ h_.W"D"@QE€€€€€€t€*€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€  *W:€€€€€€€€€€€€€€€€€€€€€€€€€€@h:€€@€€t?€€€€€€€€€��������€€€€€T"D"D"]€€€€€€j€€€€*€€€€€€€€€€€€€€€€€€€€€€€€€€€€P>G>E€€@~€€€€€€€€€€€€€€€€€€€€@"D €€€@ €€€€€€€€€��������€€€€€€€ D Qkuz€€€€€€€}€P €€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€@|:Eu_€€€(€€€€€€€€€€€€€€€€€€€€€€€€€€€€~€€€€€€€€€€��������€€€€€€€€@h}€€€€€€P€(U€@€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€Du+Dh"€h€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€"€x?€€€€€€€€€€��������€€€€€€€€€€€€€€€€D*uW*U*U*U"E U*D€€€€€€€T(Q€€ U€€€€€€ }@*U€P*€Q~U "D"€D"€€€€€€€€€ @€ U**U(u+U*€p+€ ��������@€€€€€€€€€€€@*UzW*U*U*U*"U*U*€€€€€€€€T(UD€€€€€€T€*U €*E€€€€(U/]"DQt?"D"D €€€ D*u+u*Uj_/U*@z€€€ ��������@€€€€@(U*?u+U*U*U U*}k*€€€€€€€€€€T(€€€z U*€(U €€€€€P(U>U*U*D(€€("D"D"D"D"DQjW*U*U**Ut€€€ ��������@U*}+uW*U*U*U"DzU*U€€€€€€}"€€€D"€€€@*€E €€€€€€€€ TzW*U."D(€x_€"T"D"D"D"D(UU*U*UzU*€€€€€€€"��������@T*U/_*U*U*U*U*Unw/€€€€€@~€U "D€€€€€ €€€€€€€€€€*UzW*]:U"T€€€T"T(Q"D "D"D"D*U~*U*U*U*@z€€€"��������D€*U*U*U*U*U*UzU€€€€€€(D*T "D D€€€€€€€€€€€€€€€€€T*}+U*}/* +@"T*Q"E*T"D"€U*U*U*U*U€€T€€€"��������D€€€*U*ujk €€€€€€t(U"D D"U"D€€€€€€€€€€€€€€€€€(UjU*Uj_*U*€€P*@"T(U*E**T(U"D€€€€€€€P*€  €€€D"��������T*Q"€€€*€u€€€€€€~€T* Q"U"D"D€€€€€€€€€€€€€€€€@*U*W*}+U*UT*€€"T*U"E*U*T("E  €€€€€€€€T*€x €€€D"��������€€€€€€€€€€€€€€€€€€z€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€T~€D€€€€€€€U€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€z€€`€€€€€€€€€€€��������€€€€€€€€€€€€€€(t*€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€j€P€€€€€€€€*U€€€€€€€h_€€€€€€€€€€€€€€€€€€€€€€h8€€€*€€ t€€€€€€€��������€€€€€€€€€€€~#E€€€€€€nA€€€€€€€€€€€€€€€€€€€€€}@€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€p*Q#@*:€€€`€€€€€€€€��������€€€€€€€8  € €€€€€p@€€€€€€@~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€P+€€€€€€€t €€€€€€€€€€€€€€€€€€€€€ w+€€€€€€€€€€€€€€€€€��������€€€€€€ W€€€€@€€bWo€€€€€€€u€(€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€P€(Q€€€€€€€€€€€€€€€€€€€€€€€€€€€€T/€€€€€€€€}/€€€€€€€€€��������€€€€€€@€€€€P+tq€€€€€€T€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€h€€(_€€€P€€€€€€€€€€€€€€€€€€€@€€ D€€€€€€€€€€€€€€€€€€��������€€€€€€€€€:AU?€€€€€€z€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€ U €€@~€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€@~€€€€€€€€€€��������€€€€€€€@€€"€€€€€€ w€(U€€€@€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€@€jW€€€€`€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€@/€€€€€€€€€€��������cc65-2.18/testcode/lib/apple2/dhgrshow.c������������������������������������������������������������0000664�0000000�0000000�00000001615�13473601511�0017744�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// cl65 -t apple2enh --start-addr 0x4000 dhgrshow.c #include <tgi.h> #include <conio.h> #include <fcntl.h> #include <string.h> #include <unistd.h> #include <dirent.h> #include <peekpoke.h> void main (void) { unsigned old; DIR *dir; struct dirent *ent; old = videomode (VIDEOMODE_80x24); tgi_install (a2e_hi_tgi); tgi_init (); POKE (0xC05E, 0); dir = opendir ("."); while (ent = readdir (dir)) { char *ext; int hgr; ext = strrchr (ent->d_name, '.'); if (!ext || strcasecmp (ext, ".dhgr")) continue; hgr = open (ent->d_name, O_RDONLY); POKE (0xC055, 0); read (hgr, (void*)0x2000, 0x2000); POKE (0xC054, 0); read (hgr, (void*)0x2000, 0x2000); close (hgr); if (cgetc () == '\r') break; } closedir (dir); tgi_uninstall (); videomode (old); } �������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/apple2/gatsby.dhgr�����������������������������������������������������������0000664�0000000�0000000�00000040000�13473601511�0020101�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������D����������h**D**+)*���������!*�D�������;*@!$h+����������H@������������������������@**7;+���������������������������������*7~o;L/J����@�����h?���@���@m=+JA�)D.l�����������^+������������������������P$[*k+D��������������(���������������*J+)H)���7�����l;D�A�����@;^7*Aj�{/���������H�������������������������@$QD*JH��������@!����(���������������-o=wJ��h��� o�~?@���*@����0vk;k/j*����+������:�����,����������������������@@5-*$jJ)�������������!^����������������PJ*{J��m7��@ j.@�P����+m3J@������������+�����H@������������������������$+k{m/N������������@������������ ��@��0?�@��~����@{z/@@k*��@��z!H�������������������������������������������$+^[:Z�@������~����@A�����������-@�������������*DDD*�����/D.����@������������������@���������������������$*L![6D!@���������@{_"^��J��������5KA���l;*����������@�PAD)DP�������h{���������������������������������A�����������������)J���������������������Q����������,7$6Z6**J�@�������"/�������m+i;*$)Ko���������@�H���������������������������@2mz>6��������������������������������$z~?[?JzL��������h+o������>>+;�ih����������n+�������������������������*{+w;*D��������������i�����@���������A2**!!D����@���^'h@��������+<+,Dk�@�{?����������������������������������$D*J��������������H�����������������+*;^zJ���h?���!@^�~'�P)!����d{m/-6**���������z�����**���������@�������������.k***,����������}����������������K.7L��l/���  P;�D!���+Q^*H%�����������D������@����������������������� �*{^w;{*)����������������������@����!��@���^ �����{r/Z*D������z!DD����������������������Q��������������������@�$2jv>wmH���������@ _D���@��������,���������H�����:�APDi���@���?J?�����������������������Q����������������������!$6Dj/DPD����������{o2~�@�������u-� (B @./*���������� *@)A���@�h{��D������������������������������@���������������� n*�������������������@�����������****=7,7*���������P2�@ ������*Z*�(*)K?��������������������������@����������$**.m*D������@�������������������������@2}{^?J+J���������h+DkD�A�@�����~o7~�)P���������@�n�@�����������������������Jon:**D�������������@h����������������*DNDH���������~/h@E�*���@�+JD*/��@t?��������I��@D����������������������@$!*D�@a�����������������������������/l6k+D���h?���$ .�KD����t7=k\2*2��������t���@ PD����������������������@��{>w*r*2���������� �@n�����������������/Z.J��]/���@�!* �.�A@�����>)j+$)�����������������@������������������������$6=;^*1�������@ H���������������D?������~ �����w�2*A**A�����4D������@�����������������������������������@$kZ/ko+!����������!�������������������������@ @*�QDj�@����?H?���������������������������������AP���������*+DZ7H�����������i"n��D���A���-+4n**D!zn/�����������!ADj������P~��B����������������������������@����������������k;+Q�����������������@����������������J7-+n/Zo,���������HBqo����a�P��)**B*jK~����������h���������������������������*^.k*��������������������������������@kownwJ)���"������h/H*A�����@{}�Q�)�@���������� (�@�����������������������Q$/:oJ)��������������h����������������i$).*I(D��@����� }l��)�����6*)$"Z7���0/���������Q���I!�����������������������$D*DD�������������H�����������������:*j=2���l���" �*�~ �+�!@@��:v.2**,�����������4���J!������������������������H6_?J6-)���������@���n����������������@?!*+J ��l+�����"*2_�[�@����@�k1Z* R��@����������������������������������������$kkn+MD�������������������@���@�;������~ ����@;�2i*+������4H!��������@��������������������A� ����������$+m;^;MD���������� !H���������@����@�����������������*@n������>$/����������������������@��������������������"J**+D��������{ :^��J�������**R4~*nA(*o{����������P�AQ��������:��*�������������������@�������������������������k/+��������������������������������*{J2?;*;J�������H@2?��D������)**J*;!J~���������@�l*��@������������������������*i;{*��������������@�����������������j[/m?L)D���*������h+HFA�A�����~~{o@I��?����������H�������������������������46jzDP������������h���������������@�*,im2)��Hw�����_ ~�@�)������@zJ,*mJ��0/������������*�������������������@�ADD�������������N����������������>$2N**��m?���!h�*�} �;D�@�:;J2**��@��������k�P�� (A������������������������@wn{-{J��������� �.�������������@����Q$*Dh��x/�����"(1>@�����{**2$���������@������������������������������������$+^7=+-H ��������H�h����A������������?�������~ �����{1*DQ$+�����1���������������������������������P�����������H6k_.JA��������2oH���������m����@����������@�������D*@������>4/�����������������������@�����������D��������)$*!J*H����������!n����!���t**t~Jz�;z����������@@DD*@������D��;@���������������������������������������������>wn*��������������������������������,/mz^7Zv*����������hr��������@(j*A*** �����������n�������������������������Jz~/D�������������������������������+n;]6!H��+������h/HBDP������/=o{�E�(��?������������D �����������������������****JP��������@�����h�����������������2*1**D)D��H?����� ~~@�5����@/-+*wkM���@;�����������*��������������������@��D(H"������������.�����������������=H*[+*!��l?���"*N�~>@����Z***JD�����������;���NDQ������������������������D;}no,����������@�H������������������{$( ��l'�����*jr�P;DA�����{DL����������������������������������������� �$7mo^w*&��������h�����A�����@����A>�������l ����;�2JDD*D����� c$����������������������E����������@���������@$:^>mwD@����������r(��D��������5 ��A��!����������� �D*P�����~4+����������������������������������A��������5$I$3D**������ ���#h� �������iZ1<m@jo�����������BD*����������@Q; A����������������������������@����������������i^z[*���������������������������������-z>ok:\{,���������h{o�@ �����ujkn*: ~{��������� n+���������������@@���������D/o{>;�������������@������@����������2]*:wD���;������h;D@���@�7k7^#R�Q��?���������P����A�����������������������*$+J�@!��������������h�����������������*J*J+ *�������@�~��P�*���D{^2Mz^7J���+������������M"���������@D�����������@hDDDi����������@ � n����������������lD+.:,Q��\?���0�*�~@?H��@�;*$%H����������?�@� *@������������������������$jk/;7-)��������D�������������������{@D) ��~+�����:Jr}�^@�������z!H* ���������������������@���������@��������������$zZzk{,1�������!n@���@����@����>�������DE����*�2 ADA���� I����@���������������������������@��A����������$+ZjkzDQ����������z=!l��A������@@} ��������*����������H*�@)D�������}z����������������������@���������������������5JD@D+$"J�����@���{ "j�PD������(lR ()):o�����@���@�����*@P���������!(**B�����������������@�����������@������������.ko~+A�������������������������������-z>{}7*7J���������h?{/��H��Q��@��y=SD�D)$o }?����������^+�������������������������@z>.kz������� �������������@���������**+M:DD���?������l/HDj������okz>DRD��?�����������D�����������������������!$D*J�@D�����������@�h���������������@@+N6J7,)��H?����� }�}?���*D����0z^v>7]{ ���+������A�����*���������������������iJJ*�������� ���@m��������������@��hm6*!��m?���!�(�~�k�A@���+!-*A������������k����jA�������������������������$7^w^z*H��������� ���������������@���t/* ��n+�����;:/;������zD$����������������������������������������������$*>;m+.*D���������@n����$�����@@����@@.������������*�:)A@�����@+*)�������������������@���������������������������"(s*>{DH����������{/^����������mJ���@�@�H+����������!AD*�����l{���������������������@����������� ����������h*+D$,����������@JN����A����0:*@D$*:o?���������� �D*Q����������$*$**��������������������������(���������������������������������������� �����������vY%H"[RV ���������Y w � �������ew �"HUIu}%�������������������������������������tWUw[%�������������������������������� 5_owV4g(��������� ?!YU�R�� "�����w}"�%T_ ����������D_�� ������������������������Uu]u[U�������������� ]����� ����������HeUb "R��}�����D}WH �%������4mWUY tu��� �������� ��� ���������������������  HR���������� ��� ]����������������|e]v]mH$������B�Vh� "( ���[w;o[muV����h������� ����R%��������������������� �wUBUTB��������� ��vU�����������������]U[mR��� ���$�T�t_�  ( � ���QR;%H"������������x �� �d�$������������������������ow}=oU$���������$������������ ���� %����@�����PV�~ U" ������" %��������� ���������������������U������������UWv]o% ����� ��� vB������������� �� ���� @ ���U (RU ������vJT����������������������(����������������������PYW"}e"�����������g]� ����� �o���" Hu}��������� U " % �������w����� �������������������������������������������%���������������������� �����������mU%WU}UYe ���������]oo �Q������ ��UU"PIU}vW����������@����������������������������VU{}U%����������� ����������������������Ym{]%IV�� ������A]X�$� �����HwmH%]�?����������D]��( �����������������������"5uUu]U$������������ �]����� ����������HUm " R��}�����B_7C"�%������4UU"v]������������!���"������������������������" �H"(  �� ������ ���BY����������������vR5_{V("�� }���T�th�� ����U~Wu]e[%����b�����������B" B��������� ������������ Po{UUmU"����������@�@�vU�����������������}(UWUZ�� ����Tv[� ������ T]%U������������Z������(����������������������� 5VWv=v"��������B�!�������������������%� ����@�����RV� W � ����� BB �������������������� ��������� ������������[o{u[uUR�����������vU ���� ���� ����������%� ������ �����$( U ������t"t����������������������� ������������(���������"U%�"[U ���������� t[� �������u UB""b_w!����������Q(   ������_������������������������������������������������wU ������������������������������u{o[e}Rm ���������}_ � ��(����VU DZUU�]vW�������� @U����������������������������UU}_]U����������������������������������Tw^7eU� ���@����{}�"�� �� `o_[�@%U�}%����������B[�������������������������"ZUw_U" ���������������}����� ���������BV ]$U��}�����t_ � �E������VURT WW�������������� ��� ���������������������� "IU�������������"U�������������� �tRUo=eHB������T�tb��"� ����5w[VUW]"����@�����������$@"���������������������(m]VYVY$������������tS�������������� ��z "UWU��������t _ ! ������� "[& "������� ���� ��������"����������������������� Uu=_WVB����������� ������������ � ����~%������@?�����QW�!("}%��� ��"($��� �������������������( ���������U� ���������� Yv]oWv"���������wU$��� �������"�������������������  HV�"������H%z ����������������������H����������� ��������@@"RW% (����������g?� ���������oI_UUB%t_W%������ ���Q" H � �������}_� ����������������������������������������������� Wu ���������������������������������mUuU[e[v � ��������}W�~ �"���������b]"H]uu(YdW����������$U�������������������������� u]ww%���������������������������������m}U[VV)�� ����� }!}Q�"� � ����(_{~��U�}����������BU������������������������� Wm]V" ������������� {��������������� VnU"0e�}�����t?@(�%������Ie &UR}W� ������������" ���������������������@"BU�����������@P���������������h%YuU% $������G�th ) �����ImUUYU����������������D %���������������������� �tw_UwB����������B���f �����������������X "YV]�� ���$�uW�R "���� "U%I �������������������@����������������������� Yv}m{UT����������$ ����������(�������v������B}�����PW� "5% �����_$ ����������������������� ���������Q� �����������5U7_=_���������� "�����������%���%������������Q�"HU� � ���b%���������������������� ����������� ���������@U"UU=%B��������t]� ������ �oU�_UIU(UwwU��������� �Q ( I%�  �����U�� 5���������������������� ������������������������Z[oU����������������� ���������������mY^UmwR=_����������}O � ���"� ��E}T}wYb'����������B=��� ������������� ���������P v]m}&���������������������������������Tv[WWUb��P�����?}PP� �����hv}w_ %%�}����������@�� ����������������������H"]U{u ������������� }���������������HuU[U U��}�����v]@V�%�����TVUYewV������������� ��R B��������� ������������4" R B������������D����������������@%U]U%I"��� ���u�Tb?��"��$��� UUeU����������������t$�����������������������Tmwv5m"����������"���D ������������� �P U%U��@����wU� ����� BY% � �������������� ����"����������������������� 5o{=wY"����������BQ������������ ��� t������@_�����Q�o PU%�"�����_""������ ������������ ����("���������P����������� Tv[^}o�������������"�����������U��� �� � �������������Q PW"�����@G������������������� ����" �����������"����������%YR"U"H"��������g[�"�������uU_UB%U}}U�������������B ����������PW���������������� ������������(����������������]}wW"��������������������������������r5wUv}e}v ����������6  �"��� ���� V_RT]]}W]@'��������� D{��� �����������������������PH^w_%����������������!����������������m7U}'"��R������}_4B� � ���H?o{W%z��������� ��(�����������������������D uU]U��(@������������@}����������������DmUYE&���}�����v_@���%�����w eu[U��� ~����������"���R$��������� ������������U " "T"��������������f ����������������%Tvn "��� ���U�D�`_�� ������IVY%HR������������ �� T� �����������������������:_[_[VU$��������$��B������������ ��� _"U")U��@�����W� ���� � %U������������������������������������������ UW^WvI"���������BBQ ��������������h������@? ���P5�W (QT ����_ "����������������������� ��������� �������������Ym}wWUB����������� B�����������o�� ���� � ����������� Q��HU� ������@'�����������������������������������U����������UURB5"T$ ���������uU�R�� ���nW�]%% ]W����������� ���H"���������P]������������������ ������������������������vw}%��������������������������������RU^[~{UWm ���������QQ� ���"��� �V" RuU}U@����������D_��"�����������������������R47]?U��������������� U����� ����������TU}&[%(")��Y�����@{}O$�"�����4o___�T_���X�������� �� �����������������������T 5U ��������� ����"}���������������vVUb&IE��������vSh�@%����6^UUwVwo����v�������� � ��RU"����������������������V" ���������������t�����������������WU{_ P�� ���T�Dd_�� ��� � e& "������������PW�����FB������������������������uv?o]wB����������D��� ����������������� B�U��@_����W� �  �� "R �������������������� ��������� ��������������[v}u[UR �������� �D����������������`� ����]����PW UT"�"������" � ����� ���������������"����������"����������H 5W}~{V �������� $� ��������o������P�R�����������P "% ������'� ���������������������������������Q(���������eUT� 4BUR����������PG� ��������WU�5�%�]U���������� � H (�����������HUwU���������������"����������������������������H_W^W%�������������������������������PYv=w=U[_ ���������U�"��� ����u_�� %Wu�'����������B?�� �����������������������"Vo}owU)��������������U����� ����������HVRuEPB�Y����� ?{7�H �B��� ��Tv{n]T]������������ ��� ����������������������"T" �������� ����B=����������������VU[W5U"���� ��v%b�"@E�����}o]V[W=U���t�������������RUB���������"������������^R"5"����������v�����������������W m}_ P������t�tt[ �(����� RU%R�������������P����T�("�����������������������"Uo}wwm"����������"��� ������������������� "HU��@�����QO��"� � ���$& ��������������� ����"���������Q������������ [n=o7mYB����������t]�������� ��� ���@������R� ����U"R %� �����v"����������������������� ���������������������H5Vm=UH$�����������t]� ������� �w��� �]W ����������U�P%�"������_�� ��������������������( �����������U���������V" BZ"U1���������Pv��R���������m]" I]wW�����������!����T"�����������UQTU����������������"�� ��������cc65-2.18/testcode/lib/apple2/girl.dhgr�������������������������������������������������������������0000664�0000000�0000000�00000040000�13473601511�0017545�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000�������������������������������������������������������������������������������������������������������������������������������������������������������������������������DDDDQ$D)D+J+Z7m{^w]k,k!$*D��JD{�H;eW^wKmw[;]s]v={^w]7RG��y?3Z7,{<S^7K6jy^1DJ2-rZ;No-7ZrZL"@!��������AD2Jkj1]w^w%1l/^;^{es,3J2L+D @H2LE�=Ak+^w^w^7ÝùíûíúÞ·Ûû¾÷í÷Ý·­’,r@�>{?2Js,Z7^sm2IrE&\{M7\w-6]uܪ©Ñ„¡���������DDDQ)JrZij3\wZ/mk\7ewm3-))*,+E!Lsj6>%I+\{m/m{^wÝ÷Þ·½÷íïݶ޷ݗʱ¬«J�~o/1L3Z3J/lrK7Mi]wM3H2 2mwmw­«Ä‘„„!����������@D(a,/]W^r={^7e6eumz-I$Ha$+,1TD@&l7-y-7]Z^6^7k6ìîÝûåûÞûÛ·Û¯Þ·ÝëÄëE+�{?Q_~oW,+JkK+]6\3T7*2HrIk]zZ*Êé„Ò„†>&D��������bHZ&Z{K6<{^o]]{^wJI),R,bJ+JkZ*_r^{íµëûí·íûK6k6mkMye7m{í·í÷Ûó­«I&JR4q}~ooKuK7>z!!aaJ1%*o^{\E*@`oJv��������H!*Ms^^+ew];U;l!D�`QZ7Z3$HQH2LQ{<zí¶ÞûÛ÷Ý—U5ë¶í¯¬·Êû^wÝ·Ú÷ì·Ì²Ê¥¬‘!KQÿûËóÚ—.'J2,7]7I"Do]7<;J'T@!@!��������DLr,:^w]{^o]smk!�:h�%mDsew^3J',rH%LsLoí×íùÞûí÷=+Þòìò¬·Ì²^+MkNr¬«É•̲ͣD*~?ÿÿ«¶Ê·m/MsL'HwMzMrm+I P@H"��������DDR(k<{[N3T+Ti~/D5.w^7-6-kE1$D"oJNWm/]1]{jwÝ÷íó­·Ù©L+l+.k¼³Êªš²Ê’D)!oooÿÿÿ¿¬«^3\+,+Zk-v^+^wM&Ha���!"L��������D!a$+M*I3-v<qM2,+m;.2Z2HI2��I*DL!��@�_�RuJk]:[+,{^/mW^:e7Þ÷Ûúê«Ê±,�@j?~kJrZ6M7]y]k]wZ&)W\;-6=;Z+M7J3DR���������! !D+<2]k,+K+Mw-6-wj7M/%j,+ZrID)*\k/+n=v]7-/]{Êö¾÷¾·íûí·í»Þ·Ê«Ä«,w���?Jk,+Jk,rJ,+JH2-7>2./J{n{¤³Ä¢ÈÒ����������!D3./-7]o.2Mr-6-w]7,j,rJ2J2D�!H!D*MkM$Dv*+^z^w[+ʳåûÞ·Þûîû¿ûîûí×ÊñL1���?o~o?Zj\j\6[/]{l7m{,'&I']+M;¬²Š‘˜���������! 3*r.7]/lw-7]{^;^wEDQJ%7MkJ)HD1-m^w^6Jvmw=o-w^{ÝûÞ÷Þ÷½÷Þú¾÷í»Í¶M1L2)*;-2]r,5.{JL3H2HcL'6,7-s¬“Ä€€]��������ADRDr>o<3k7=7j{^7m+D"I1(2]2I2D0 Hs//-6­ûÞ·ÛïÞ¶l{_{,v=w^o[oÝï޻λڲ¬³¬²%I{}?_,2JwI2H2H'H2YI2\2M6-r(!@:��������L2j/m{l6]+lo>W+@J;-)M2%T_5K7ÞûÛ¶íûÞ÷m{Þû¬²Ë«¼«myÞúÍ»­·­—ܳʱR>!?oÿÿ¬ëìúZ2#]kr16^3KrJ@�I��������Z)-k-{Jm{m/L7EI?J >!A/]6-,++D3$Q?+-2ڷݶ½÷Þ³dyí»Û¯É«Õë,q<6Z+ʧʳ¤§¤©QDR?{oÿ¿Ï³¼ëZsm/"D2,+,3l/]2H@�`D��������)Q)DEHDu[7^w=kM23?{{oZ{m{Z3,+L qJ?,2]w\{^wlv]z®¯­¯ÞòΓZv[v\6[6]sL+@2oo{ÿþÿÿª²-o^7[q.6Z;]wM3%+�D@QD��������H�ID)I2\sJ5\+Ls*k[w]7m/,+*L!L�$Q�!i-2^w^7Z[w^w%k]{íûÞ«Íò­¦I��P{,l7[jd<3NkM2H1,7K7]o^6m{.2,&H ��������H@ qE6Jqj;-u^k^kl9]{];N+M+E+D�H#IjkH"[~;?M{^nm7>w¼ûí¶íïÝïÝïÞïåù޳͢Eq�o,2,r2K=6Ms,),+lr\/m1Z]Ͷ¬‘”DA@���������H�APD)*mk]{^zmoZ7\sm{^7K3J\Zk\1Z7:*HR-k,vm7mymwޯݷå÷í·Û¿í¶Ý·¼³¬“,+@a?6$+M+.k^7Z2[k[3IqE2QK7[rÎëÔ’Ä€@e����������@@ ()\+Z7mr]y^w^W]wm)DfT&,QLT2L1Z2!�J3Z{åë¾»Þ¯Þûm/m6Þ×ìùíûÞûí·íúÝ·Úó,'Z+�J{{{\/j3ZkZ"%H&  !Xk6m7\rª¦˜€@���������D*/e7^o]{^{]e{ZuDDD+\*,+ eH_rZkÝ÷åöÞ·í÷]w~K;j{]7^{¾÷í×½¶Ì«Å–ͪrDz~~~{¿¶Ú«­·'RI2R\6 aK+[7J2EH�Pm��������DQ$*]{UsKw^7[7M7M�P@D%<v\3ZkDQ!I%+<kå—Þï½¶åù]k½ò˯ÜòÅ÷]ÕóÞõÜéʱŪȫlq~{~ÿ¿Ê²Ê—m+Le3L'H'Ll/],QDH�@�A!!��������H3Z{j2muZ2^{^z,T }@+Q,sm{l71LrH*L/\{^{^wmyU-M3Ý·ìòÚö­²m;Jk%7­²ª¦œ•“6!??{ÿþ«êʺ^yZrLr %Z2J/[w^J&@�HDJ��������DDA!D+^w<y^7*k\6~?/J:-6[^/JrJ5Dk^~\+<7K6e{K7^í÷íûʗܦ,+<3^3l+\**&DQ(�!?~{oD/\7mu<7\sl7^y^/\!H�@��HL%��������XR!",kZ+,-5-/m7M;.kZ1%2\DH��2$AX!A�zP|wZ{-7l{®ïíûݯݷ޷޶í÷Þ×̳,R�@2]6-sL{]2KjT;\k\+Z+]wN2Eo^wZ+J@���������� �!I+\k<7\k^3%2Mv^w^okw,2,6,2 P $q,!-6j{~o>6m3^{my­ïÛûß¶¾·Þö۶ݷͩʲIw�@�{?Jk.J+<{N{>. 2JrU/[{]S@zj7¬³ÊဠH@��������HQ,vJ2.7M7\3m/K/]vjk*D1J2\*JaH H-.m3%,)Z7[o[7^/­ùíïÝûÞöý÷Þûޗۯʪ*1Kto{{~rM2,vZ2jylk.7m)'HSH">{l;ݪ…‘€€;��������DL%*6m{Z{jw]7m{.7[T +*&(I+$S% H2[7MnÞµÍ×Ýûë·^v_{e7[w>7m6Þû޳䫭ªD+L2@Qk?*2,kM+M2IRr('Hr %HkZzk+Ê’Ä‘€Ð���������A%J2\kj{^6mo^z^7M,H!H!LrJsEqT+!L2o/.;ë—¾ïíï­«nz=w\k^k.{]6íûջ˳­²Ìñ¬«}???~þ«­úͶM2D1LH'2I2=v,s,�P�H?��������\!Isl+]6];-wmy^k,A!�P�K3[kL1L2HR,rZ6Ýö½·ÛûÝ÷^6ۻܲå—ì«lsí¯í«Ê³¬ÓÌóÝÖ!|{?{ïÿÚï­·K72IjRLZu[z.wE% �D!X��������HD*,5]<;^o=7-7%Li!R^Tz^7M+M$II�7*6-vm{^7-{>oÞ÷ڻʳÊÓZwm2L+ÜëÌ묳ÜñDyoo{{{ïÿß—­ó-7-o%%LrMwl2M;Z1DA@�� ��������L$DA1e9K7U:6J+[o5!DWZ{l{Er+\s:Q?J2Kk-{^6<3-wÞ»Û÷¬ûÕ³ZuNyeo.yJ3M+J*Q%?~?o:I2.+.;K;-/[{]w=7-�@�!D1$��������!JDkJ6JrJw\kZ{\2^7m{^;\*J$rDIJzj4{,*mw[kÜùÞ¯íûÞñÝö½÷Ýû¬»•¦J ?oi,kJ+-2\/<-rJ2D2,w^zZ{m{\1¬¶Ü§Ä¡�����������D"D *$2J3J6E7l.\/Z3e{ey]qE+*QJ+THI$ ZkD-.k6\k]om7^ÔùÞ¯íûíòÝûî÷Ý÷Îó¬ë$q��~?o,1,3$&Jrms\7,&<M{l2L!H3MyÊ­Ù–Ä…���������@H!J+momjm{.w^w^s^o^2Ja&%L3\DH 6l{^+J+J3eymw^w=7ÜóÞûÞ·ÛÿÞûí·åû¬òÜóL_��y{\+K+-{-^7]y]'r&3l]+Ú§¨”���������@P H2Mk]km6]{^w]7mom2H$1\kJ1M&J1DiMr:7í÷íùÞ·½ïUw>M6^{m{=í·í÷Ý÷ͳ]rI*�6Hw?o~\+K34rHaH#E# r 2IsH;\\+*Qb@��)>w��������H,o-{-6Uw];kwe6TAD"QD*$+-2TD2D(*?s\5Þ÷ÝûÛûÞ÷]Þúê·Ü»í×>wÞ—Þ·ì¶Ü§Ê—Ų!\{~w~woÿóÊ«¾û\bI*I7 q,j&N+^M+H"D@�"T{��������Di$Kwmkmv^{^e;J!���*�<7.2MkJ"+,{ÞïÞ÷í×Þól{í·íï¬öË÷-6­·Úó­–ʲ¤²Ì²|3?ÿÿ¬³Üû<rI'L3Hs,{.7m1$I��H&��������DQaD+,7M6j2K{e+$ShU"Je{^rTsLJwL{\+^{[/e{ms\1åùζ­¶Þ¦M*</Z6ųš‘ʪĒ5@!ÿÿ¯·Êª^wN3\+ZTr-wm7m*E��@Ha,1��������D"I!�)]7m7mk,qEg=9\Q-6^7^7=sE\Dok {%7l5^W-{K.^+å÷í·Ê²Ì¦,{m]7Z3-2rI>?~E*]{]v^u^y^w>{^7J���HQH! +��������AH$)Z+,,;+2Ni^w-w]6-wE3,kDRD\RD> Pk6kw^{^6®·íûÞ·½·å·Þ¯Þ·Û²Ì±,q���~~{2E+]uZkZ{-2J/,Hk*+-w^7-6koʳª©Ä•A���������� H,+ZiM3l9[sNrm{^7^7j;\rJ2,qJ�PDqD"N6%${[Z7Z7]zm{í÷ÝúÞ·Þ¯í÷Ýû«¬ªJ3@�PESJ)I=/Zz.k]2Js,vUk,Dw>7̳š„€HV��������� H,j,{\7Z6M+l;m/-7]+IDL2Z+JaHDH#M+]v,v:kMw~z-o^{í¯Û·íûí·í·Û×Ý÷í«ª«,q:?oo2*6<vJk\zU3ewmI'II!-{j2̱ÌÒÀ„^~E����������D+Zv^6^{n7e;j{]3]a,+J1D1,3,3DSD%.wm{Ú«­·½ïîµ^{]wZ{j]6_7Ûû¾·íûêëL+,s2Ty?o~-v<.M'2 RH!X#\*DW.{^6L!A:��������DY1Z7Z+l+M+mw^7^{]!DAAH!vJ+M2 !D2?*mwí¯å¶ì÷Û·[{í÷Þ«ÍöÞ·K{íúÍ×ÚóÚ•š²Ì’V>moû©ÜöÚ¯KLs,'HrM3Is-2m{Z)J���@@��������SJvZz.z.+m/]wMD@Q�]%j7M,%M&@,{6Z2íûíû޺ݯ;wÞïÊòÚ³Úé^;Z+-/ʳ٫©«¤“H�~{o~~ÿÿÛëËö^oJ#I1H'',+]7Z7*� L��������DD!D2jw]{lw^6M1Ijkn"~[,{[2]+M2,2D$?-r,+mw^o[/mwÞ÷½ëÄ«­’l7KwJsí«Í²¬óÍñr?~~?ûÿÿõÜ·M+]-s\2M^yZz,sA��%+��������@@ X2T{>y^3%EJwEZm{mkN/L3*+t$&o~OjWZ3U+<wZvÞû¾ë¬“Ä«[7]z.+moZ+,+D@ �!{3*6j3m7mw-om7Mk,D��'D1��������@!H3J+Z-6l/J3,{m:^7lk-*J2LsIX�Ek/!)}+\kl7ewíïÛ¶åùäùÞûí÷íùì·Û—Mi��-qJs,,r],sJ&2\7m7Jv]w-;¬ª¬“˜¡@���������AH@QA2M;JZ7,;e{Zkmu-w]7E,/J$)+]{]D1Zk,rmz>7[6ÝûÞ·íïíûÛ·¾·Ý÷ųš³Ij�@�{{]2,7J7Jr^U;.+.6]+M2!Yzm;Úª¤ªÀB�@��������H"D27[6^v-w[w]7]{mo.QQIA2D2)Q 2Z6Z+Kk\3^7[7^7k7Þ÷Þ÷½·ÞúÝïý·Þ«Ú·Ì²I<$/~{*,+,kmsK3M6^zMsLsL!+MwN/Ú—„€ˆ)E�������� D2%e{e=v]w]r^wZRDIJR&JL5@+OzK6ÞûÞ·ë·Ûûm7>w^2-wmwmví·íïÞ×ܳJqE@*dr{{J+MsZq2 "H#H2'H7[6%2���Hjr��������!,iN7-wmw[{m{E3HrE/<2$*D% 6[yÝûÝïÛûÞ÷m¾û¬÷í»íù^Ú·½¶­—¬³¬«Ú«!/?ÿ—˫ܷ<#Y2]k2T&Hj\o-q,2DRH@�@ D{��������D]kmm7]w]w.y^7L!Ah�O>%H2Mv=7J+TS2Iq,{Ú·Û–ë÷®û^;å·Ý»¬¶¬³e6N;Z3Ͷʒ̲ɲ�z!?ooþ﮲¼ûE;-+# !LqKsl{.+Da�H2��������DH!D*Jk<WK7Jk,DqnQ>E]v^w^q\IkJ*I�L7m7]z={m7Z{íûí³ÝûÍ—-r<y-*ͳªëŲԑH2~?ÿû¿ûÝëj7Z7l6L/ZwZ^KD D��"HI2��������D!D��@i-rme/MwMsmk%6.w]6^7mrZ%Lz�o/3Z6lvmwm6m{m6m3M 2,7^7]w]7EqJq,q�"�{{?v-\7N/Z{]{^7]{>;M&�@��DQLj��������D�E,6MRJ+-2\/[6Zw-w^5Z6,+Z*�S%P\!}n$F?1m;[z]+ª·ýÿÞ÷Û÷Ý÷Ý·Û“­ªÄ²$s�A@�_{wI,5ZrN+,kZ+,+,kJrTk-+Jkj7˳ʦɒ���������@!Lw<k,6]z[+]wN:Z{^+^k\2J2]q!@!D,7JD%D1*5>w[om{®¯½ïÞ·Û·íûÛïåúÞëÊ¥\2�@�{~K'Z*,)]{-{liZ{Z+ju,kH!D7ZŲœ¡Á€EP@���������P�J2m{-;N+,{^{>7[7ZqDa,Z'JI%A!ZSmw<6jkm{m{[{^{­³í«Þïí÷íûîûÍö®«š²,1Dz} /?wZr-6,olo>/M"I&6Lre7m2¬±Ø¡„k���������aD+Mu\w^we;mzn/]/M!Q*%IH1,2Lq(sE Hq++<w½·ÝïÞÿÞ÷={_;E7^7^{>7ÞïÞ¶ÍöÞ²,3L21\u}~-2,+M7IRHr2H"wH2\2m7Jk,"@P�\1��������DjH1%7=yZ{^7mw^v^*H�@ A"LrN+M2DDU'oJ7Þ÷í·Ý¶íù>wÝ·Û²ÚéÞ÷=7í»Î³Êò¥“̱ʦR[!o/{o??ÿ·¬¹­ú]r WJsUk,s 2jz^E���������L$;^wZ+.3Z3m7-wJL4>�_Wk>+Jj,1J5To6[6Ýú¾÷Ý·Ú«MvÝû®·Ú«Ý«]{<6-wÚ²¬óª“¬•|~ÿÿÛ—­ë^2U'IrHr 2,o>7U2$D���@!E+��������VHA",:Kuly<vJ%r?{+oRj]+MJ",*J2\?-kZz>we7^6M+Õ¶Þ¯Ê뮡Z{[wZ7Þï̲̗̲ �?{~ÿÿÿºª²]zmrZ2-2L;m{-w\3@�DD%��������D%�4P$lo^{M2,z%/>v]kD+ko-7-+L2$U>��>{o^iL3[/[6MS,+^o]k\,kj;mkj2l+lM+Pko{~~/Dr-k-wmwm7]{n7]w$D@��P2$��������� �$"E$j5n5m;n[v=V""Y"��" E� D��hRRe=m;n[b5o[v=u<VYv=nKee9Tl��-}9mX^V;mKg]n;n=UeKmyvnv[nYe9EH��B��������$ BIVf%Yb v9o^=mUv[eeYU.�"R�Y �R}U4}^Wn[-[W½ò·þû®Ëï·îÛö«ò•¥¹ÍU ��t_fYm)VnYn5R[e4BY*5v=meYo=-ÙÖ™¤‰‚�������������$9n}b9n;]5en;vKo[V5UVYVV4@$ JYo " "(V5^[o;n[vÕíËßÛöÛöýïÛï½ïµÍ•â ] �~w9VMm^{u=m=vKrV5R $[r7f™Ö’ ‰  ��������� � )Vv[.yv9j[o{o;v{b B("R)fV EM$X.u;voTo}o}oKo{-Ûö¼î»î½ö½ï½ïËו®šÔ$5?�wVnvW\_5M8VN,9dv]nYV‹¤‰À€ÀI �����������JXe+j[o5n=r=o<.[bBRYBI"ffVF$Yye=v»ï«îÛß·ö}o{o[v;n[o;^ÛïÛåØî™ÖI&YBd W_} b5eY.FFDd;fff.j$���(-�w��������NIVKe=o=o[r<_=^B ����� dYo9MRb�*� VYVûï·öÛö¼ï=oûç›î›í½®Ke´ïÙÖ•¯µÖ‹Ö¹å�w~}w}_ÿâµò¹ïdN3oe5fb8_;e" �� $$��������"U^[m=r5b7v<rYV " "U�hZUD(v[j)e eY"V}.vÛö»Þ·Ö«ò9/ûîùî›­ÛÍ=ufWV™æ˜ÎÙ¢‰Æ8BBÿÿÙöµï;^$fNVW^}r5V(&��� �@,(e��������"0R @9r;n<oUm.~w_%m[^KvYfd MV�/j[V[v=ofrÛöÛåÙö˜Ö:o5o[n½íµÖÙÍ“¥�dw}ÿý×ãµ®5_:^;VVYn<oK.U"�����" BU��������(BBB BnK.4UYfR[W[_5m[eY*$UJ)$d�""~ � +Rv}v=/[n}_7VYmUoÛöÝî¹î‰åY|���Wf[eyuUV^5VUv fYV9V7myW;n=We. 8��$�������� H"JeY]n7n9VUrYg[n;o<nYV5fY" @e Uj{_EuYv<w=v=bûîÛî½ï·Þ½÷·ïÛïÛî‹Ö jwU&[eV[m=o. &Zee[oYVn;f•íÉ¢ˆˆ0����������� B)Jm;&=WUf{^}u]o=v=o[VYb5eYe * "B8"5V5BTYbow^Uu=o½ï»å½ï·í·î½î»Ö™æ¹¦8^ "MYf8V}uYV.+o;.EQFb=o=UÛ剤€À� ���������B eYm=roWv=u<f=oK.2TJI& "d8*"B%9fYV{u[V7v[v=mv•æËöÛõÛíÿîÛÖ»íÝâ9eX u}}weYUYV;mdFeQdB& W;u=R™Â¤¨ " ���������BTIVY.=uYu[o[nKu5. ,X.b "UUXVIJ5" ""v[o½®Û÷½îûïv=n]f]V=v]v½ö«î»åÕÅ•íÕ®*}_}w4v[o7e), d&fN9B]_}eY& ��b�]��������"4m;^5j[u=o[fYv9$0B�� � $7e;&Xf &)b(=e5o·îýß½®ÛÞ;nŸÞùåµÖ»ï;VÝÖµå¹â™¥˜â›®�. }_÷®›ÖÛæ[.VeYd$Y.[m].)J ��"A��������0d8U=nn=o.9o7b$ %�(};"o}g;V&BM�eymµßýïÛêÛïn·õ—Öµö•Ö;VYVYnµÖ©â‹å“ª J$___ÿÿ½Õ›æUe9fQN5b9e;ooZU �� � " b.�������� $ B $fYWYvVYU o7" f=v;n+UV8%T�_o[o5r7mU^{^}n½ï½ÖÛí‹åYf]V[eYeV&I$ %_ÿÿ¯¢ÙíYfIgmYe;uIv=oB ���B$+f��������� )"TVUU8"V U5f=f)v=o9VV*Y"� �BU�$�{ R?f{/[mKn5oKmZj;f:j·í»×ÝâÙÖz �__V9n gYv;v9mV[% Ev=Wf]W9d[UIBB(��B�������� @T5V[v V9ef.^;o<r eVe.0"(V5�"�e}W_7m{.[o+v½íûßÛö½öÛî½ö»æ¸åØå��p_e9m9RYe5vY^5bl9.y^=^;e8m<oÕÖ“ä �@���������  "IVv f[^YvY/[u[mKu5e T.T0$�@$ oYR$R nir[o;~[jµö½ïÛíÛï½ïûï¼ïµÕ™Í ~���_}}}YVUn9foyo=v<edJdKwy&•¤Â‚‚ �������� $,V5^Uo{Z=.KnKvKv;.H"HR$e5- &(% $ f+_mÛî¹íÚï·Þ[o{/ÛÞ»Þ·Þ½þÛßûö¼ö¹ª V"B($wRf5oYfiJ$QNENdYm[oKfÉ¢‰‚€¢0j���������" fnoUf7.7v:o;n"B("1Td9n5.& *�@Y Ye=vËíûí×ßÛÚ=m[o;m;v[o;nÛÞ»öÙÖ›ÖÙâ¹¢"S_Ùí¹ÞÙïF9$d9,9d d;vKoUe ���" R��������$YV<v[v[.Ko=_g B $������Ryv<e $$V n[nÛïÛöûï»ö<vûö—®Ùå½ò<oÛæ›ö•æ•æµ®•¢n _}wÿïõíµï5FdNNF:o5v[n$ �  �$��������) e v{Wv|oVYV ER% 4~@5r+.Ye)N5"Ib ?Vf=jKr;v;n7W¼ïùåÛæÙê9nfeÙåÙҹ敤c "wwÿÿßæõí;vKMdNY^=vYf9f"���@DB��������5J0" B/n;f=edHmwWDZm{o<of5b T0n _8VYo[o;vUeoÛ÷«æµ®ÈÖ[o[o5oVYfYeBP�F}w_ V];v[n5V5/;.[n & ��� $0J"��������P"� ")Rf+V;efVu=m[v7mYUB% �T B� @� [/n=o;&Ûö»ö½ö×ÝßýïÕæµ®•¥Y>��~_]bIV[^&|o]f7m$f9WUj{m5fK.f[&)$��*��������@I" "VV eV+oyo]eUvYnYV[UYVY%+ BRYb)VW_weY_Wo;^.Ùö½îýïÛïýöûï¼õ»ÖÓÖ!  j}_/dYf+Vn;e[&+%UeUge $Yv[V»å‰¢‰‚8����������� �B TYv{mY^<u7'7v=o}v;&9*bXe8f "0$I"%yV7M[.3V[o?v=o=v›ÞÛö½öýöÛÞ½ÖÛö™æÓæU�WbX.Y&[o;.n[o;ff$V;nmØâ‰¤€h ����������$U]o;fv[v=Wm=o=e" eKbQVeJ9b)"(Rm}fºß×ö½íÛï}v=n5v[e[o{o·í½ï»ïÛæVX%,__fY]V5V8&d$T d9V3f]fV©¢ €€ tO ��������@RyuUv;.]o[n]v[r5"$b& IVb9b&BZ.;m½ïÛö»ö½ï{v=rfKn=v}w»ö½í·íÙÕ’¦•¦b _w—ÖݦýõeN3Nb[VVYm=V. @����@4b��������Rm+o]W5v=v;n=^ ,��( f=/.8V(*T WVYuýö½ï½ö¼å[o½íøöµÖÓï;V¹Þ©îµ®“Ô‰âØÔ7]w}ÿוæÛò=e)&9d9$8db[nb " � �� ""��������B"9U5m;mnYm=e)R�n C_ $[nYu7V8e "4V4}eY_[v;nWo=&YnÛö·î•í—æUVy_5V‹Ö‹Î‰Ö˜Ê&)BÿÿÖ›Ö=Vf;V9Ve{_7u+* �  $)d��������%  , m9u=o[.YV:v]o"=v=^j]R&"y �w[m+V=.[m;_Yn·ïÙí›â‰å.;nYVn5UV $��"_oTm9o;m5uYv=v]v=W B ����BB.���������$ B�L d[e[bV5Vjy/Wo;n=V5f5V9"��$PR(�)$� w(�R=n{WKv<n½Þ¼¯«®·öûöÛö½Þ›¦Ù¦5/���]w?.f5Vym9^myvYJRUn[n8vm=oÙíˆÊ)�D���������@$Se:oIW=o[nV5o;n;v7V9f9f N��$J.b{_U=v:r7o=o»î·ïÛÞûõÛîÛòË®µå™ä9��pw_3R MYeuU5^mYn9v^{*B4o7V•ֈĠ[��������� "&mV[vn[nXnKv[n\e $ E RUX$B�@ &eZVm5e;v[mWm[/½å¶Þ×ïÛî½õÛï»ÖÛ刬5b �wwwVeo=j9oXu=vB $Fl5_<V•¢‘¢€¢YS����������)"Ie[r<v{o<mKv<o[rK )L3M%$3VU"E@&]v[_Ûò»®Ëï½î[m[o]o=v;v=vÛïËòÉâµÕXb5 "W"}/f7mY$dFfDQVbm;o8eD��} ��������"N V;n]v[r=o[n[/ $J( @&nYeJM TY$9m=oÛö½Ö½îËö<oÿîÛÝ»í»î[m½ïËîÙÖ”æ•îÙ¥8u½å»ï¹ÖYd8V dV9d n^KnR��}U��������$Yv[r;v[e[-=oe) ("@Z)mUn[e b FbU v;VÛ®×õ·íËÞ+rÛ×›êÙæšò]g›åÛâÙæÕÊÓª‹¢B"_}}ßÿ¹ÕµîyVdJNd)n[o+/B� �� � B�������� T VYV}oyw7v9.$ }W4"5o;fYfT9F" �wVn=.=o;r+m=o»îÛÕÙçÙÒ[onYe»å¹¦ÕÖ•¢ O.}}}÷÷ÛåõîUe5m9NeYV[r;oYF�� B%��������(B0��� V:gKu;f &V;](BKjKo7o9f9nUDvU? Vn+v=v}noÛõ—ÖÕÖÚÖ;n;on9eYeY"J(�Nw_wXV=f]fV;n[m;.Ke"� ���&d���������T)$V)V5.;eYe;fUj=v]ujU dYJ �B d��  (uUf;m[V»ï·îÛõÙïËï½ïÛåùí“Í9��~bVbfeYbV.d9W=bKV}v;fµå™¢¤8 � ��������"H"("mV4m;eUVkmV[W=omT.UUb$ `$Yxe$5UKbUm]_]^;jÕöÝî·ïÛï½õ½î»ö›ÖÙ¦ ��pw}_ f9V5V9v[e[VKU[j}efJXVYmµå˜¢©¢| ����������$MYn;v5g}W=_;u9o=w ""("Xee ,$-5^]m[b^<mwv=v=m¹öÛï»Þ¿ß÷ï½öí©Ö™â$ H_eYVYv;v]n7o;^+dbd9u=v{m¸ÕˆÀ àZ&����������@JVU.[Wn;o;o;v=oB" V J e MeT V5Rn½ï½õ½Þ»×=v=v n;o}o[o·î»ï»ö›æ &"Pb wwoY^Yv B F T$&M8N;nV[V"��0w"��������$eUv=_;o<o[m;Wb " �$0JYv5VK&)V BU[VU^·ïûßÛõ½ï^ÛÖ¹öÜæË÷=^ûî½ö·å™®ÙÒµÍ�` n___¿ÖÕæÕîNd;V5n3&.yoe8b0 (� -�������� "Uj]n[n=_5v[r=n B�dr"e;W5V&X*N]e]m·õ»îûö½öYn·îÝ®•í™®;nUnnµÒ˜¦™å‰Í4B7B}ÿÿ—æÝÖn Ndd JV=u;e , ���0BP$�������� $BRUmV7^[b[gb�~PEuJ;v}_4VXeURf�bYm;oUVYnYV5VÉöÛîµÞÙ®eUr.•ÖÕê“âÂ� "}ÿÿýÒ”õ:o<WeZV5mn]n*)@��� (B" &�������� % ��� (e.nUo9o)e5"n;o;^[VVe_ } wYe=v[o;o[vYV·î»å›Â‹åYu\n=WUv Vb0$�"w_}}w}?_)mYm7_UoUv=v[u=n)B���� $ bV��������) "BeeYbYVn=]vym[oUfYn5%"���"R) �jwUW.=^7o[eµöýß»î»î»ÞÛò»ö‹å”â �r}}f9f5n^yvV5eYbYUUvYo[eYe=mÙÖ“¤‰¢H�� ��������� $UV;e[n8o;mv5v7v[r<Vj.5. $b V @ %V[V{n[o}'½­Û÷Ûö·ö×ïÛï¼í½å‹åU&� j_XMe e]m=o9n;n[WYv9M$[v;VÙ®‰¤ˆì����������� �P"W]j]^[v v</=r[^;$)BT MJV"9B)"QRYo;o5V4eKo=o[o;oÕí½õ½ïýö½ö˯Ûï›åµÕ5BW{ }_VmV5%[u}m}v$D..[nV‹¤©¢ì "�����������$Ie[o9nyo}v<r}-Kv) ":eR$YV[fYT.)D%Yfuo«ÖËïÛï½ö+_[n{m=r[u{rÛßÛÖœî¨Õ;lY"$ %_wV=e8fBYNNd3f$Ue{oYe D h^V�������� "9V9n+uYr[v5v=n;-B � $mYe9N"R$Ye;v¼Þ¼öµîËò7o»î—æ›Ý»î[o½×ÙçÙîµâ“昢v~w¿åÞ›×&8M=fy_YN9vr;V9E��  ze��������b(V;o[mKv=m;.UW$�(hh Pm]veNBR5�?V;v½ïýïÛí›®mÛïµîÙÖ»ï[m;e5eÙæµåµÖµ¢Y$ $__wÿÿÙ­¹ö=edNF&5u nYVB� �B E�������� " D&[vYnoRY%oUt/R].[b9bVd(R _RV5u{v7vo[v»åµ×™æ•â[v9nygºå™æÉÅ•Ô�"�$_ÿÿÿ¦Ùæ[^Yn[V.Yv=o[o+F���� dM��������F  � T{m;o;Vr4V[bSmYr}o[o[e.5B+�u}_vYo[r[R[On{_[R)&Ym/[uYbe;f;T " ��d_Vo[n;r=.[o<n9U ����B$(b���������" $UYVZn5oyWfYev=V;VIUeY, D d �B�T EP;m;u]v=nÛïÛí×ö½òÝõ½ï½ïÙîÙæ�� j}R5VeYb7_d V& f[m7V=v7v[fµíÉ¢ˆ€� ���������B$ "R.[W]fvYV[n=m=o[uIeUe" "B$"[m9 B m;e=v=vn»ö½î½ï½ï»þ½öÛæ›æ™®8��|}_ e9VV5fn;vf=n;Jdb5o[mÕ¥©Š¤����������@$b{m5v;m=o=&n[o=o ", B&eY$& eKVUV[e^;^;m=^[v»¯»ïÛö·ï·ï»îüî¹æÙå%|]�}_}bI&YmYn;fv5o)fSf F n5Wum¹¢‚Š€ò5A(��������( b^=vWV[v;o[n;v=W" dVb UYRb""&^[RÛõ½®·íÛí;m=u5WUo7n[o½îýöûÖÛå %U.%"wuym[^=Vd$ b FT5B{^UuVQ" � X?�_��������� j=Wn7n+_[n[eK&$$(�� "zV VYe nD5n=mÛõÛïüß»æYvÝõù¯¹æÛö=v›í·íÛâ™Í¸ÍÉÖ�~wýÞ»íÝí+J dKn5OBSn[fInKV)B��BUR��������NeUv5o=o[W[o;b @Cpz V;o]N9b B e�bYVÛîÛö½ï½ï}v½Ö›åµç•öfYVbË­“ä•Í™Ò5$"w}w÷ÿµåÛÖ[ob$d9jf;o[MB @$0B"��������B "$P"Un=r;V{f b u]{.(n;w=_=.IV9&Pe( wg9v[nm[mzu5oýß›îµÞ»î.[f.‰®ÛÒ•ÖÈ %w}ýÿÿíÛ×[e[eYmym7V;f=r* � B.8b��������"( � Vf[v}m[n;o}n8v7o[v=v9VUe`H%;V7e5nYv<^;W[vfJf;m9n{_;^)V & $� �$wHRYV=rUn7w=^;uKf���$ J&��������cc65-2.18/testcode/lib/apple2/hgrshow.c�������������������������������������������������������������0000664�0000000�0000000�00000001256�13473601511�0017601�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// cl65 -t apple2 --start-addr 0x4000 hgrshow.c #include <tgi.h> #include <conio.h> #include <fcntl.h> #include <string.h> #include <unistd.h> #include <dirent.h> void main (void) { DIR *dir; struct dirent *ent; tgi_install (a2_hi_tgi); tgi_init (); dir = opendir ("."); while (ent = readdir (dir)) { char *ext; int hgr; ext = strrchr (ent->d_name, '.'); if (!ext || strcasecmp (ext, ".hgr")) continue; hgr = open (ent->d_name, O_RDONLY); read (hgr, (void*)0x2000, 0x2000); close (hgr); if (cgetc () == '\r') break; } closedir (dir); tgi_uninstall (); } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/apple2/hgrtest.c�������������������������������������������������������������0000664�0000000�0000000�00000000620�13473601511�0017572�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������// cl65 -t apple2 -C apple2-hgr.cfg hgrtest.c werner.s #include <tgi.h> #include <conio.h> #pragma code-name (push, "LOWCODE") void say (const char* text) { tgi_setcolor (TGI_COLOR_BLACK); tgi_outtextxy (41, 33, text); } #pragma code-name (pop) void main (void) { tgi_install (a2_hi_tgi); tgi_init (); cgetc (); say ("Hi Dude !"); cgetc (); tgi_uninstall (); } ����������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/apple2/macrometer.hgr��������������������������������������������������������0000664�0000000�0000000�00000017770�13473601511�0020624�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������"D(U*U*"D€D*U*U:/U**U*uWjG(}z}{w*E€€€€p]~_*U*U*U*T(U*U{"€€ €€€@("T*U*]€Wn} "}_ ��������D(U*U €€@*U*U:wU:W*U*wnE(U~_~{{_*A€p_xW*U*U*~};w€€D€€€xw*E€€U*U*D"U€€€(Uj��������~U*"D€€€€€@U*U*wW*U*UjWjU*U*U{wwk~ Q*uU*U*U*/€@€€€€w*E(U*@*€@€€(U"@:��������w"€€€€€€€€€€Q*U*u~_*U*Uz€T*U*U*un}+u?}}{?U.DU*U*Q"U*}/€€(€€€€t~?(€€ U*@*"D*U*��������}oW*E€€€€€€€@*U*un_*UT/@€*€Q*U*Q*UWzU?u/}/o_.U*}/_*qDQ"U*+€€€€€€€€€P*] €€€€€"@"D(U*U*��������U}o?U*€€€(U*T*un pW"T;€€€€€D*U*U*"U**T*~}W#Dp?|€€Q"E*€€€€€€€€€€€€€*Uz€€€€€€€€~_**U{;��������U"}~G?U"€€€j](U"EQ|?j]*€€€€€€€€*U**T* €*]W.T/?€T("U* €€€€€€€€€€€€"Uz€€€€€€€`��������U*_U €€(Q*Eqk+U*U*€€"D*€ U(U*€ U*u*U*z/€~ *D*€€€€€€€€€€€€€€€€j}*€€€€€€ ]��������€€€€ @€€€€€€€€€€ T*U*U€U€€b#E€j?ukq?U€€€€€€`*}€€@€"€€€€@*U*€€€€€€€€€€€€€€"€(U"U*€€(}��������€€€€€€€€€€€€€€€€€@(U*w P €~*u€€ U~UW>{?€€ /Q €€€€€*U*U*Uj€€€€€€€P*U€€€€("€€€€€€€€€ @j}��������{W*€€€€€€€€€€€€€@U* P€Q*@€"U*U*w }+}Q;}€€€}€€€€€;wn];wo€€€€€€€€:WnU*€€€€€€€€€€€ €€P��������~uo_:€€€€€€€€€€€€€(U*u€*@|€€€"D* UjW}+k?u/}*€€€€€€€€€;wn];w€€€€€€€€(U*];W€€€€€ €€€€€€€€��������(z*E€€€€€€€€€€€€(Q*u/€€€@€€€€€@"T€U+@U"Uj_zz/:.(€€€€€€€?~};€€€€€€€€€€€T*U€€€€€€€€ €€€€€€€ €€€��������uow_+€€€€€€ €*U~€€`€(U€€€€€€€€"D€€€€€€€(t~#€€ ~€€€€€€€;w€€€€€€€€€€€€€€(U€€€€€€€€t*€@(U:ujU��������8c_*€€€€P €€€€€8|_€P*U€€€€€€€€€@(@€€€€€€*U €zG€€€€€€€€?>€€€€€€€€€€€€€€U€€€€€€€€P*U;Wn];wnU��������*} €€€€€€€€`Gz€E€€€€€€€€€€€€€€€€ €€€€€U*A(Q|€|€€€€€€€€€€€€€€€€€€€€T*] €€€€€€€€@*U;wn}{n_��������"U*Q"D€€€€"U*Uj;UjE(U*uUj u_{_z?U €€€€pW~_*T*U*U*U*U*Un€€€€€€€€€€ T€*U Q*U*U€Q~/��������U D"€€€€€€"U*U*}*U*U*_j"Tz?}?]?UT"*D(Q*_n}€€P€€€€`;U"€€T*U*€€€Q€€€€P U~��������_?_*E€€€€€€€€€€D*U*UW*U*UjU P*U*Un}xw{{~ @z"D(Q"/€€€€€€|o}+*€ €*€@€€T*"��������?~}€€€€€€€€€€€D*U*U{W*UU~€E*U*U*U*u}}z~~{UzW8D "DQ"€€€€€€€€T:w €€€€€P**€"D*��������\~w}+€€€€€€€€€(U*U{"U€T €h€€@(U*U**]+UjUzW~w_ .u/]€€"D"€€€€€€€€€€@*u~€€€€€€€P€€€*U*U"��������Ez_ €€€€ U*Q*U*€pWu.€€€€@€€"U*U*D€P"€*U8W €€p?|€€"D"/€€€€€€€€€€€€€Uj€€€€€€€€x.U*u~o��������U*}W €€(W Ut ~/D(U*€€€€€€€€€(U*E(Q*€€€D(Un_:`c?€€€"DQ*€€€€€€€€€€€€€€Un€€€€€€€ w��������U _z/*€€€€€€p/w+D*U*€€€€@"E€@€T €€€U*U+U*~~€€€€€€€€€€€€€€€€€@:_(€€€@>€ U~��������€€€€€€€€€€€€€€€€€*UjUT€€€x U€(}o}Q?|n_ €€€€€`+t/€€€€€ €€€Q*U€€€€€€€€€€€€€€€€€€€€€*€€€Tz��������€€€€€€€€€€€€€€€€€ T*UD€€€~*q€€€U*wb#?w_€€?€h€€€€€*U*U*U+€€€€€€€@*U*€€€ A €€€€€€€€€€€€€T��������>U*E€€€€€€€€€€€€€€ T*} @€€p €€€Q*U*U:~EzW~}u?}?€€€@~€€€€€€.]*uj];€€€€€€€€(U*U*€€€€@€€€€€€€€€€��������/}zW€€€€€€€€€€€€€ T(u+€€€|€€€€€€"€U*}:G~UuoU P+Q€€€€€€€€€n];wn];€€€€€€€€€U*Un€€€€€€€€€€€€€€€€€��������xU?}~U€€€€€€€€€€€ D*U?€€€€€T€€€€€€€D€€ (A*P{ zW(€€€€€€€n];u€€€€€€€€€€€€*U€€€€€€€€€€€€€€@(€��������€Pwo€€€€€€€€U*€€€p€*U€€€€€€€€€€€€€€€€€€(Uz €€`~€€€€€€€n];€€€€€€€€€€€€€€ U€€€€€€€€€P*U Q*UjU*U��������€:€€€€*€€€€€(~€P"E€€€€€€€€€€ @€€€€€€€€€"U P€PzA€€€€€€€@n]€€€€€€€€€€€€€€€ U€€€€€€€€@*U*U*Un];w��������T:€€€€€€€€`Wj?€€€€€€€€€€€€€€€€€€€€€€€€D€€€}€| €€€€€€€€€€€€€€€€€€€€U*u€€€€€ U€*U*]:wn];w��������"D(U*U"@€€€@(U*U+/UzW*U*}WjEu/~_*€€p_x_*U*U*U*U*U*]? D€€€€€€P*T*U*DQ*U € T*��������U*EQ*T€€€€€€(U*U*U*U*U*wzE(Uj}_~o_ U uW**U* €€@€€€ _*"P*U*U€@€€D€€jU*��������wo_?*E€€€€€€€€€U*U*uW*U*Uz?U"P*U*U:w~?uu~+"T(uU *U*/€@€€€€€|o/]*€(€@ € DQ*U*��������_?_€€€€€€€€€€P*U*u~_*U"U~€Q"@(U*U*U*]zu?u?}?:UhbUQ*T*U*_€€€€€€€€€Pj}"€€€€€€"U* D*T*��������u?U*€€€€€D"U*U~ UT"D:€€€€€"U*U*U*Q*T*U*}+_#D q?|]€@*T*€€€€€€€€€€P*U€€€€€€€P*€"U*w.U*��������U*{/U €€€U*E*U*U€p"];€€€€€€P*U*"T* @ U*}W#D€p/€€"T*/€€€€€€€€€€€€"Uz€€€€€€€€xWj}��������U*|*E€€€} U*Dq*?*U*€€€€€€€€ T*"U*U€€€"U:_jW>b?€ €*T*€€€€€€€€€€€€€€"U*€€€€€€€ }{��������U*Wju€€€€€Dp/u+U*U*"D"U*U*€€€€*E€€T*U.D€A z"D€€€€€€€€€€€€€€€€t*€€€T€ U{��������€€€€€D€€€€€€€€€€€@*U*W€P€€€z#u€ }o}8\}/€€€€`/p€€€€€*U*U*U*€€€€€€€€€€€€€€€€€€€€@(€€€€*��������*€€€€€€€€€€€€€€€€U* P"€€@*u€€ T*U?uo?w/"?€u€€€€€:U*U;wn€€€€€€€@:W*€€€P*D€€€€€€€€€€€@ €��������?zU"€€€€€€€€€€€ €U*u P@€q€€"T*U*Uj_k*}/}u€€€€ €€€€€€;wn];wn€€€€€€€(U*U*W*€€€P€€€€€€€€@(��������zW~}€€€€€€€€€€€€@Q*U/€"€}€€€€€€€D U*E]#jzo?U*P*E€€€€€€€€;wn];€€€€€€€€€ U*U*€€€€€€€€€€€€€€€€€€�������� k_.€€€€€€€€€€*U>€€@?€€U€€€€€€€"D€€€€D zq{/€ |*€€€€€€€kwn]€€€€€€€€€€€€@(U€€€€€€€€€U€€€€€U*U*��������Dz}€€€€€ U€€"D€€€€x€*U€€€€€€€€€D €€€€€€€€Tj} €€(~_€€€€€€€;wn€€€€€€€€€€€€€€U€€€€€€€€P*U*UjU;wn]��������"<?E€€€€(€€€€`q€T*Q€€€€€€€€€€€€@€€€€€€(U*T~W:p€€€€€€€€€€€€€€€€€€€€€€€(U€€€€€€€€@*U;wn];wn]�������� DP/€€€€€€€€`_j?€€€€€€€€Q*E€€€€€€€€€€€€€"T€€ w~€P€€€€€€€€€€€€€€€€€€*Uj] €€€€€€€€@(U*wn_~}��������€€€"D*"@€€€€€€"T*U*]?UjU(U*}Wj T~~W~w/U€€p_xW*D**U+U*U:€€D€€€€(U€€€U*U €D(U€€€*Tz��������}*U@€€€€€€€€ T*U*]*U*UjUj"U*u~/w_/UDj"D*+€€€€€€€€w.U(U*A€€@€€€*€€t"��������{w/] €€€€€€€€€€T*U*UW*U(UzU€P*U*U*U;wG~}zz~{?E"D:Q"D"/€€€€€€€T{?U €€€ U€@ €€"D(U*��������_oW€€€€€€€€€€€@(U*Uz_"U€U~?€D€ T*U*Q*U?uj_z_~_.(] U*@ D"?€€€€€€€€€P*uo€€€€€€€€€*€€€"D"��������Uz*E€€€€€€ DQ*Uz"D€p_P.€€€€€€*U*U"D€T"T(Uj}{}WP?|€€"D"?€€€€€€€€€€€@(Un€€€€€€€@:€@U*]?W*��������U*?U(€€€P**U @€|?E(U*€€€€€€€@(U*E(P*€€€ (uG €|€€ D*/€€€€€€€€€€€€€Uj€€€€€€€€(~}{w��������U*_/€€€P D  pk/E*U*€€€€€€€€€€*€U*U€€€€€U*U(u*_x/€x€@€P* €€€€€€€€€€€€€€€(un€€€€€€€ u~��������Uj"{*U€€€€€€€p?U*T*U*D€€D(U*U+€€€€€€€€€P*U*€p€h? €€€€€€€€€€€€€€€`]{€€€€€€Uj��������€€€€€€€€€€€€€€€€€€"T*UP €€€x*u€€U|?}_{W €€€`/p€€€€€*U*U*U*€€€€€€€P€€€€"€€€€€€€ €€€€€€Tz��������*€€€€€€€€€€€€€€€"E*}D€€€@*q€€€Q*Uj}_`?owG*?€€z€€€€€*U*U*];€€€€€€€€.U*U €€@(€€€€€€€€€€€€€€��������kW>u*€€€€€€€€€€€€€ D*U+@€€p?€€€€*T(U*w/PxW~U?qW€€€€€€€€€€.U:Wn];€€€€€€€€(U*U*U€€€€@€€€€€€€€€ T��������>u+€€€€€€€€€€€€€ D*U/€€€€€€€€€€€€ €Q"WjU*E*Q?uu?@**€ €€€€€€j];wn€€€€€€€€€€€Q*U€€€€€€€€€€€€€€€€€€€€��������€U_?U€€€€€€€€€€€€(U:€€`€ U€€€€€€€€€€€€€€€€ @*Qz€€ z €€€€€€€n];€€€€€€€€€€€€€€"U€€€€€€€€€U€€€ U*U*U��������€€z} T€€€€€U€€€€€€€x_€@*U€€€€€€€€€€"€€€ €€€€€€*u €€h~€€€€€€€€n];€€€€€€€€€€€€€€ T€€€€€€€€P*U*U*U.]:u��������€.w_€€€€€€€€€`Qz€"@€€€€€€€€€€€€€€@€€€€€€ T*P"Up€|/€€€€@.€€€€€€€€€€€€€€€€*U €€€€€€€€@*UjU*wn];w��������€A@j?}W~A €€€€€€€`_*?€€€€€€€€€€€ U*€€€€€€€€€€€€€€€@€(U*€@z€€€€€€€€€€€€€€€T*U*U€€€€€€€€€ U*U+wn];w��������cc65-2.18/testcode/lib/apple2/mariner.hgr�����������������������������������������������������������0000664�0000000�0000000�00000017770�13473601511�0020123�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������€€€€€€€€€€€@*U*U*yx~_€€€€€€€€€€€€€€€€€€€€€€€@JS*U*U*8w€€€€€€€€€€€€€€€€€€€€€€€à U|~!~€€€€€€€€@€x€€€@€€€€€��������€€€€€€€€€€€Pz)U*U UJ{'U €€€€€€€€€€€€€€€€€€€€€€€@J{qOJ_c€€x€€€@€€€€€€€€€€€€€€€`Kcw€€€à€€€€€€€€@€€€€€8€€€€��������€€€€€ ¿€€€€PbT:U*U*U*U*€€ €€€€€€€€€€€€€€€€€€€`QUr{?x€€8c€€€€€€€€€€€€`€€Tp€€€€€€€€€€€€€€€`€€€€€€€€€`€€��������€€€€P"½€€€€T*U*UU*U*Urd€€€€€€€€€€€€€€€€€€€€€€€T*_qu~?x/U*}€*@o?€€€€€€€€t?P€€€€€€€€€€€€Œ€€€€€€€€€€€€€€€€��������€€@*Ôú€€€€€Ujw*U*eGe'Urn€€€€€€€€€†€€€€€€€€€€€€8U*UUrq€|:€€~A(|€€€€€€€€D|€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€��������€€Ðꇀ€€€€€TW*M*U*U|*€€€€€€€€€€€€€€€€€€€€€€p+Ub~(y€€p €€€`_€€€<€€€€€€€€€€€PU0€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€��������€€€€€€€€€€+U*U*U*U*UJ?(€€€/€€€€€€€€€€€€€€€€€€@*U*d}o €€€€*€€€€~€€€€€€€€€€€€€`W€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€��������€€€€€€€€ø€(9*U*U*(>€O<€€€€€@€€€€€€€€€€€€€€€€€U*e'yqI€€€€€ €€€>€€€€p€€€€€€€€€€~_ €€€€€€€€€€€€˜€€€€€€€€€€€€€€€€€€€€€��������€€€€€€€€€€€€€€ €ÀÍê÷êߪߧ€€€€€€€€€€€€€€€€€€€€€€°€Õ«õªÕªÕ¼ÿ€€¼€€€€€€Ž€€€€€€€€€€€€€€€ ÔªýúÕþÿ¿€€€€€€€€Š€ü†€€€¨ˆ€Ÿ€€€€€��������€€€€€€€€€€€Àÿ{€•‚ªÕªÕ݈€€€€€€°€€€€€€€€€€€€€€€€ Õïݯåÿ÷úÿÿ€€ð€€€Àƒ€€€€€˜€€€€€€€€€dW³ÿÿÿÿ•€€€€€€€€€€€€ÊÁ€€€˜€€€è€€€€��������€€€€€(¿€€€€€"€:€ÀªÑªÕªÕ¸Ý‚€€´ƒ€€€€€€€€€€€€€€€€€€`©Õºýûÿ¿Õþÿÿßøÿÿ€€ˆ¾‡€€€€€€€€€€€€à€€ªùÿÿÿÕ€€€€€€€€€€€€€ €°€€€€€€€€€€€€��������€€€€U*½€€€€ •€ÔªÕªÕªõëÏ€€€€€ž€€€€€€€€€€€€€€€€€ÐªÕï÷ª¹ÿÿûÿ¿ù¿Õªý¯ý€¨Á«ý¯‚€€€€€€€€ä¯•ìÿÿ”€€€€€€€€€€€€€€€€„ˆ€€€€€€€€€€€€€��������€€€*Õž€€€€€xp€ÔÎßñתÕì•€€€€€œ€€€€€€€€€€€€€€€€€\ªÕªÙêÿÿõÿ߀ü«ÕŠ€þÀ•üàƒ€€€€€€€€À¯Õ˜€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€��������€€Ôꀀ€€€|*„ ԺѪý¤õ©€€€€€‚€€€€€€€€€€€€€€€€HUªµ¾Äúÿÿÿ¯€ð¯•ˆ€À¿ð€€¿€€€€€€€€€€€ÑÿÕ˜€€€€€€€€€€€€°€€€€€€€€€€€€€€€€€€€€��������€€€€€€€€€@#‘˜ªÕ ÕªÕªÿÛÕŠ€€€€À€€€€€€€€€€€€€€€€¨ÕªÕªÝÿÿÿ•€€€€»•€€€þ€ÀÇ€œ€†€€€€€€„€Àÿ׊€€Œ€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€��������€€€€€€€€€€€ªÕªÕªÕŠÝ®€¾Ý€€€€€À‡€€€€€€€€€€€€€€€€ÀªÕêåþÕ¿õ‰€€€€€€…€€€¿œ€€€ˆ€€€€€€€€€€€þת€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€��������€€€€€€€€€€€P*U*UJe_€€€€€€€€€€€€€€€€€€€€€€ € ;rS*w€p€€€€€€€€€€Œ€€€€€€€€€€¨(Uxx)~€€€€€€€€€*€€€€€(€<€€€€€��������€€€€€€ÀŸ€€€qu)U*U*U*~'€€€€€€€€€€€€€€€€€€€€€€€€Prcw?r{}€€`€€€@€€€€€€€€€€€€€€€@J€€€€€€€€€€˜€€A€€€€€€`€€€��������€€€€€ Ÿ€€€€P*U:U*|T*UN€€€h€€€€€†€€€€€€€€€€€€àP*qd~_~€€€`€€€€€€€€€€€€`€€_?€€€€€€€€€€€€€€€€ €€€€€€€ €A€€��������€€€€Uªý€€€€T*Ur_*U*U*Urd€€€€€€€€€€€€€€€€€€€€€€€UJc){?x;pO€*AW^*€€€€€€€€d?€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€��������€€@ Õ€€€€€U~}+U*F?Uy€€€€€ €€€€€€€€€€€€€€€€€,U*E€|+€€|C |€|€€€€€€€€€d€€€€€€€€€à€€€€€€€€€€€€€€€€€€€€€€€€��������€€Ðú€€€€€€G_*U*U*U*ASl€€€€€€€€€€€€€€€€€€€€€€L*U|€J€€`;€€€@?~@=€€€€€€€€€€@PW@€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€��������€€€€€€€€€p#U*U*U*U*€€€€@€à€€€€€€€€€€€€€€€P*U*UJ?€€€€€*€€€~€`€8€€€€€€€€€€@W€€€€€€€€€€€€€€€€€€€€€à€€€€€€€€€€€��������€€€€€€€€†€*U*U*U*'€x€€€€€€€€€€€€€€€€€€€€€€€U*yqxG€€€€€€€U€€€€€€€€€€€€€€€€€|_ €€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€��������€€€€€€€€€€€€Š€‚°×êýêÿ¾ßª€€€€€€€€€€€€€€€€€€€€€€€€ÕîÖ«Õêïÿõ»€ ð€€€€€€€€€€€€€€€€€€€€èÔªýú×ú߯€€€€€€à€€¨ÕŽ€‚€€€ ‡ð€€€€€��������€€€€€€ø€€À?€Š€‘ȨժÕú—ªßŠ€€€€€€€€€€€€€€€€€€€€€€€ õ»Ñÿãëÿÿÿÿÿ€€À€€€À€€€€€€€€€€€€à€€`Wýÿÿÿ¿…€€€€€€€€€€€€‚Á€€€€€€Œ˜À‡€€€��������€€€€€"€€€€€€€Ðºõ¿µªåŒÿ‚€€À‡€€€€€€€€€€€€€€€€€€ ¨ÕŽßëÕÿÿÿÿÿŸÿÿÿ€€€€€€€€€€€€€€€€ð€Àªüÿÿ¯…€€†€€€€€€€€€ €€¸€€€€€€€ €Á€€��������€€€ ªß€€€€€€€xЪժժõú߀€€€€€€€€€€€€€€€€€€€€€ÀªõºÕëÿÿÿÿÿ¯ø¿ÕªõŸ€€ «ý«ƒ€€€€€€€€ä¯•þÿ¯€€€€€€€€€€€€€€€€€†Œ€€€€€€€€€Œ€€€��������€€P*Õƒ€€€€€T|€Ô†Õ¾ßªÕò”€€€€€„€€€€€€€€€€€€€€€€€VªÕªÏêÿÿßÿŸ€ü¯Õ‚€üÇ€•œ€Ÿ€€€€€€€€€Ä¿Õ€Œ€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€��������€€Ôž€€€€€€sWª(ÕªÕª­ªøŠ€€€€€ƒ€€€€€€€€€€€€€€€€&Õªþªýÿÿÿÿ€€à¯Õ€€À¿þ€Ÿ€€€€€€€€€€¨ñÿÕ‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€��������€€€€€€€€€~€‘Ъՠժըõ¯×Š€€€€€à€€€€€€€€€€€€€€€€€¨ÕªÕª×ûÿ¿…€€€€¸…€€€þƒø€à€€€€€€€€€Àÿ׊ƒ€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€��������€€€€€€€€€€ÀªÕªÕªÕÊ܈€ð߀€€€€€Ž€€€€€€€€€€€€€€€€ÀªÕúÝÿ×þß‚€€€€€€•€€€ŸŒ€€„€€Œ€€€€€€€€€ø×ˆ€€€€€€€Œ€€€€€€€€€€€€€€€€€€€€€€€€€€��������€€€€€€€€€€€@jW*U*_9'€€€€€€€€€€€€€€€€€€€€€€€€*~~S*T\€ @€€€€€€€€€€€€†€€€€€€€ø(U|d'yw€€€€€€€€€€U€€€€ €`€€€€��������€€€€€€ü‡€€ÀS*U*U*U*U*9*U€€€€€€€€€€€€€€€€€€€€€€€€À¿~Hcx€€€@@€€€€€€€€€€€€`€@~€€€€€€€€€€€€€ !€€€€€€@€€€€��������€€€€@*€€€€P*U*U*|qOUJ €€€€€€€€€€€€€€€€€€€€€€€PJ9|oUz€€€€0€€€€€€€€€€€0€€~€€€€€€€€€€€€€€€€€€€€€€€€@`€€€��������€€€€Eª›€€€€T*Uz*U*U*U"x€€€€€€€€€€€€€€€€€€€€€€€€Ueco|+€`€€(_>?@€€€€€€€d?•|€€€€à€€€€€€Œ€€€€€€ €€€€€€€€€€€€��������€€P"õ€€€€€u* u*yUJ{€€€€€€€€€€€€€€€€€€€€€€€*U*e~_€|+€€xO 8x€€€€Œ€€€€`0€†€à€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€��������€€ÐŽ€€€€€€pW*U*U*U*U*E€€€€€@€€€€€€€€€€€€€€€€€*e€€@+€€€€?€`?€€€€€€€€€€PPW`€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€��������€€€€€€€€€3 U*U*U*U*UzT€€€€€€`€€€€€€€€€€€€€€€€€P**G{€€€€€(€€€~|€€`€€€€€€€€€@_€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€��������€€€€€€€€€€(U*U*U*ew€`€°€€€€€€€€€€€€€€€€€€€€ Ur{qm~€€€€€€€€€ €€€€8€€€€€€€€€@€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€��������€€€€€€€€€€€€ˆ €„ˆ ×ªÿ¿ßº×¢€€À€€€˜€€€€€€€€€€€€€€€€Õþÿ¯Õªÿþ×ÿ€‚€‡€€€€€‡€€€€€€€€€€€€€€€ÈÕêýïߪý‹€€€€€€€€€€ˆ€€ƒ€€ðÀ…À‡€€€€��������€€€€€€üƒ€€@Àª€€€ªÕªÕªÕŠÔ‚à€€€€€€€€€€€€€€€€€€€€€€øÏ¾õÿÿÿÿÿÿÿÿ€€ÜßÏƒà€€€€€€€€€°€€€À€ Õýÿÿÿ¯€€€€€€€€€€€€€ €€€€€€€€€€œ€€€��������€€€€@(€€€€@‹€€€Äþõ¯ÕªÕªß‚€€€ž€€€€€€€€€€€€€€€€€€ÂªÑ¿×ïÿ¯½ÿÿÿ÷ÿßê¿€€€‚ð€€ü€€€Œ€€€€€ð€Àªüÿÿª€€€€€€€€€€€€€€°€€€€€€€€€€ €€€��������€€€(Eꀀ€€€€€ЪղժíúÓ€€€€€€€€€€€€€€€€€€€€€€ÐªÕªÕŠÛªýïÿü¯Õª‘¿€ …ï€àƒ€€€€€€€Äoüÿ‚€€€€€€€€€€€€€€€€€€Œ€€€à€€€€²€€€€��������€€@ªý€€€€€€Õ ÿ 0Ôêÿúߪզ…€€€€€†€€€€€€€€€€€€€€€€€ÔªÕêßÿÿÿßÿ—€ü¯Ô€€øŸ€…°ÿ€€€€€€€€€€Ð¿Õ°€€€€€€€†€€€€€€€€€€€€€€€€€€€€€€€€€€��������€€Ä‡€€€€€€<Ô¢€€!ժժպϪ€€€€€€ƒ€€€Œ€€€€€€€€€€€€ ÕªÐþÿÿÿÿÿ‚€€À¯…‚€€¿€€ðð€€€€€€€€€ÀzÁÿÕ‚€€€€€€€€€€€€€€€€€€€€€°€€€€€€€€€€€��������€€€€€€€€à€ÄÕªÕªÕªÕ¢ð‡ÖŠ€€€€´°€€€€€€€€€€€€€€€€€ªÕªõê÷ûÿ¿€€€€¨€€€þž¿€€€€€€€€€€€€Àÿת‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€��������€€€€€€€€€€ÐªÝªÕªÕªÿ‹€À€€€€€€œ€€€€€€€€€€€€€€€€Ðªõòåéÿÿ×€€€€€€€Ô€€€Œ€€€€…°€€€€€€€€€€„‚€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€��������€€€€€€€€€€€P*u*U*U*Ur''€€€€€€€€€€€€€€€€€€€€€€€€J?O*e~w€€€€€€€€€€€€€€€€€€€€€€X*e}oS2€€€€€€€€€€€€€€€€`B €€€€€��������€€€€€€}€€€P*U*U*U*U*U*&€€@€€€€€€€€€€€€€€€€€€€€üïNXA€p€X?`€€€€€€€€€€€€`€€P*|€€€€€€€€€€€€€@€€€€€€€€€€<€€€��������€€€€P*Ÿ€€€€P*U*xIS*U*€€€€H€€€€€€€€€€€€€€€€€€ƒUrOrx{ws?U*€€`€€€€€€€€p€@€€€€€€€€€€€€€€€€€€€€€€€€€ €€€��������€€€*Uúƒ€€€€T*U*1*U*~'Urn€€€€€€€€€€€€€€€€€€€€€€`U*N*U*U|m|+€€€hv€`€€€€€€€D?•|€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€��������€€Tª¿€€€€€€Uz_)e`/€€€€€€€€€€€€€€€€€€€€€€€>U*q_€€x+€€€pO 8€€€€€€€€€€p€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€��������€€ðƒ€€€€€€U*U*U*U*U*~€€@!€@€€€€€€€€€€€€€€€€P*UJ?€€€€+€€€€€€8`€€€€€€€€ `W€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€��������€€€€€€€€ð U*U*U*U*A`1w€€€€€00€€€€€€€à€€€€€€€€€T*Urnw{€€€€€ €€€~x € €€€€€€€€€€€ÿ_ €€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€��������€€€€€€€€€x/UU*U*e}€@€€€€€€ €€€€€€€€€€€€€€€€€Urpq€€€€€€€P€` €@€p€€€€€€†€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€��������€€€€€€€€€€€€@7€€Ð ÝªÕÿת媀€€€€€€€€€€€€€€€€€€€€€€€Õ¿ý«ÕïÝêýÿƒˆ€¼€€€€Àƒ€€€€€€€€€€€€€€€xÕú÷ÿÿÿÝ‚€€€€€€€€€€€ƒ€ƒ€€àƒ°à¾€€€€��������€€€€€€}€€€€€ ‰0€€ªÕªÕªÕºÝŠ€à†€€€€€€€À€€€€€€€€€€€¯ÑªÑÿÿÿÿÿÿÿÿòÿ¾€€¾à€€€€€€€€€€€€à€€¨Ùýÿÿß‚€€€€€€°€€€€€€€€€€Œ€€€€†ð€€€��������€€€€P*€€€€@ €€€þêÕªÕªÑê߀†€€À€€€€€€€€€€€€€€€€€€ªÅ¾ýþÕ¾ßþÿÿõÿÕªÿƒ€€¨àÿÇÿƒ€€€€€€€€äÈÿÿ×€€€€€€€€€€€€€€€€€œ€€€€€€€€ˆ €€€��������€€€ Qú€€€€€€€Ðª×þߪ¥î—€€€€€€Œ€€€€€€€€€€€€€€€pªÕ¨Ô¨Õ¿õïÿƒü¯ÕŠþˆ…®‡€ðƒ€€€€€€€À¯•üÓ€€€€€€€€€€€€€€€€€€€†€€€€€€€€Œ€€€€��������€€Tª€€€€€€Ô~|FÔ¢Ðêÿª×ªÄ€€€€†€€€€€€€€€€€€€€€€`WªÕþÿçÿÿÿ¿…€ø¯• €à߀€ø€€€€€€€€€€Ð¿Õ €€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€��������€€¸€€€€€€€•‚ • ÕªÕêӿТ€€€§€À€€€€€€€€€€€€€€€€¨ÕªÕïôïÿÿ߀€€€¾•‚€€ÿ€€žÀ‡€€€€€€à€Ô‚àÿ×€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€��������€€€€€€€€ø€àÕŠÕ¨ÕªÕÁï÷‚€€€€°€€€€€€€€€€€€€€€€€ÀªÕªÝú÷¿ß¯€€À€ …€€€þ¯€°€€¼€€€€€€€€€€ת€€€€€€€€€€€€€€€€€€€€€€€€€€€à€€€€€€��������€€€€€€€€€ÔªÕªÕªÕâÕ‡€€–€€€€€€œ€€€€€€€€€€€€€€€€ÀªõþÑÿÿÿ…€€€€€€€Ð¢€à‡Œ€€€€”àƒ€€€€€€€€€€€€€€€€€€€€€€€€€€€À€€€€€€€€€€€€€€€€��������cc65-2.18/testcode/lib/apple2/monarch.dhgr����������������������������������������������������������0000664�0000000�0000000�00000040000�13473601511�0020237�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������8���������������������������``" ��{cX]w 2p3L3L�#}�B n�Bn� nB �� 3xwz���;�����#6]  9n �������������������;eb &�nf �����fKnIf;������` 9B �� 2w "w2p3N;l3n���\� �@n��n&"�]"z 2m#���0 2Hc]?H#] $(&���������������������� &$�n ')b.9�$B $f;������� *�& �`w #������8N�L3L7 �r}� �BXN��� ����BH_{ #_mc_w]7_xw v]wo� $ &������������8n9bn9&n� 8" "" *���� *&�������*��@]@�<l�����;�nnN\3�rX �b $�"��n(B |w }#2 w���&� $)r�����������8' r b "bb$8& $ ���*(" �������b@x722 s2l3@;T�l�n�L��rs�B d9`*�n" $ �wm�� $B$Bdr������������g& B$B$�B (��0 3�<�$"n�&HV���`7���H3@;l�@;ln@;�;�� :7 @ j9nb�n &*" $B dB b� $("d"jf�������������g &$ $��E�~?XC@;@n�� �&n�% b��� V}H# ���@���Ln3;����+v} (B*8.')�9&b & b)&b r:��" j("b(& 'n�����������n "$���]7Ho�L\3N3���n(Bb9��"i" �]#UsX* ��#�:L;N��:Hsvo� �"b9e3�����0bnf.8f;���� "b r�A���������������������������8��������n�������������������` `d ��7_6~w]2H#�03L3L3�0} (f b�v B �4}w7X" �3��<@rHs_?Xw�B 8n�������������������Z" *fYb����. &^9������` $� @]#hwX3X?X#�n3N;�p�X� � )f��9fK'B @]7 b]#^7X 3H3 6# 3|?��B b���������������������@bnrZr�)B $""9������� &`�p7H�H#���CT8nN7\3�3pb}��$��� �� @}wX2~b]7_X!\H3]o B j������������8f.9bIg f�"Xg(B $"X �p@�"b9�������8&$�@M��N2���3 3�l3n;n3n3�c w��b� B �& $�@7_wH#{} ��x� ".�����������8r.&""j�"B *���� ���B *N�������"`~��3;3L; ;Pn�nN�P7~z$(B `" �v*B � �����$�@ $B *8"'������������vb E$F$B� �����s;L��� b fb "��� w���<�;H3n�@;@m�; 3p�Hw; *".& �fb)"*" $" "(f$B ")B jbn�������������rbB (B P&x}w BL3@3l�� " f b���.$Xw "Hp����0l�^8;�p��bMc� *("&9r$�[b &"&b9&'  *" ")"bvn�����������f�vbB$��Xc }w�lN;l3�� f f;�@vb�]6hw "H@�2@3@;l��Hw wMco� &^������'fIn9bn�����* &.8UAUUUUUUUU�������������������8N������8f������������;������`B $�?#_w]# 6�s�7\3L;� ]Bn�Bg�.)& $��_X " �p����L# 6}7   &�n9�������������������9b*0nb ���P9rb9&;������@ 8F �x_2hw^2}# `��;l3�@�<\�� ��BXn�� n9b$��x_3Hz]2mc-r#L3}2Hw_?� &��������������������� &$�fIj)bZ*8� � " v;������� *�� �`#L��3L2L�@�T�n;`sN;`3�"}��B,��"�� �_{m#m{H#_ww 2} :}� *(b������������xnfI'&n9 8r "` $ ���� *&��������"�| 0p�l#L�L#xT`;l3`7n3�sHc&*�"(�bB ��^_mwX7]7_ ��� ( *f�����������8. fIb " " "8& $�� @p���p $"Hn�������`�&n���2�#3\;@n;@nN;n<�zs�B "9`&��."$�"�� �*�$B $" $b������������.&*B $B ��"( ��3 3L��� FHn�"*9��� B ���@L3n�L;`;n�;8��z}7 " *9~d &"B *(B""b�B *(&*)"P(f�������������.&" ���]6XL;L3�@� �Bn�B g��j F �X# 2���0N�l0n;�"��@cv}� " * %.)B�9"b "')fYne� �"*(&' &nyf����������n.& $�B ��w 6hw]}�M�n3N3�w�bB n9�p.8F �{]#]+�`#�;@3@�� Xw vo ("b9n�������b[n9fn9 ������&'8v�@���������������������������8n������;n�����������@;������` �$�B ��c b}c 2H"p3@3M7L3�0}� f�$)f�;f*�@w?HbM��@��� sXs]3Xw��B j�@;�������������������*(" 9fbf���`b "b9�������8"�]7x;H32H�@������������$ f��9n^"�|]# bM#X7J#-6\c?X! s}? B b��������������������� *�.("T(r` B"9�������;" P��:l3N``D8`3�;l3@;�#^�$��F �b$@w^7a "_Hc~W]3_ � & *������������8b nrb &�"X*B "X����"b9 �������& �� u�+3l L7 0n@�3@;�3`;p#v�B�F &*��n}_]w_����� "n�����������8bj &b B$ B$B ���0��B $9f b������ "�~���#@3�3N; n;�n;n3N�@7~{Z(F` B v")B&�$� �b$B $(B *"'������������fbB B B�*������37L�� b9f*Xr���$� x �����H3(L;@;lE8N��H7?� $bX.&$�` *)" $" $B *($" b"j(& n�������������bbF �� ����Xc �L3L3 ��  b (f��"�w]2"���<�;l�L�n4�2� 2Mc�B $("&9b$�E;nh&b r n9bF�*(&b r"8bn����������.n"B � �H#}}w l��;l3�� f�$(f;�8""�"t7 O3X�3@3@;����h! {Hc_�"�*(&��������.9fn;n���������f9b n9PAUTPAUAUT�������������������8f;�����;v��������l;n:������`� B $_7X{7Xc"�3@;\sM;��}�B n�Bn�' " ��Mu 2O�������l7Lv}# � &��;�������������������9" $. bIn���&)&*9f;������� "�& ��]3x7L3_#T`@���J��� ;� �"n��;��f b�%x_r{_6XwM3\#\v!\3Xs^;$&�����������������;f� �" �v*)b * &�B "(v������� "�� ��#�@3:l#�0�;�;n�3�>\ �" ��$�n)_m#2X#u#Xvu_s}?�� d(r�����������8nbKg&b9 8""`d�0@��* &�������*����� 3M0l38`�;`3�;�;�3Oc��*(`"�n)B ��w__}? �B b* f�����������8nfbF$"$"$�� <���� $("nr9������F~�� 2@3@3l ;l0�`3n;n��r}c�% b9`jF�. & $ * BZ�B $B $(" $ r������������."$B  � �};3�sM� "n�"'��� & �@H����L;�0L;�;NU0N�� ~} �" *9~j B@"*Bb(""" �B $(" b&b)f������������ . " " ���{Mc6X�L;L3L�����n�Bn��g`P]#"H����00hn�� ��Hcv} F ")nnI$8r' rIn v['9�� �" * &H"rI.8b����������~9n B$ `w "w_ N� �n;�w� g�Bg9�Xg) x]c,]32�0�;�#�<p�\2Zw v_ " b9��������b n9n;����������`nfP@PA�A�������������������8n9f���[.3�������0fn9������`($B �]c~]# "x7�;`3N;l�0}� f$b�9"*  �]a_~Hs���<�`\2\w"Hw �@ b����������������������I* B �9rbv���v"bb9��������$P]#^���# @��2J+�0<`w���b9f��;�l �&x]#\~]c XcM7}w2h! {}; B b������������8 �@;n;n;�*�. "$(" "���`" "8�������9& �P3�@@2l3N3��E� ;8����7N?�b9�B &"�w_7Mc 2X "woPw_?$�""�����������8vI'rX" &nKj"*"p+,��"b�������" ��e7���;l0N;�0`�;�; 3 �#v �"P F �&*�xw_; � B *�"g�����������8vb "bB$8B$� �p@����B *f' �����$�n� �@;@3M 3nxU@;`;�H7~v` (&`"$�fb("$" $B & B *(" $(&.�������������v' F  $B ��x_?�3�;L� d f*r���"@ ����L3�l;;`;T�n��rH#�$(".)&$�Kj)"b& j "j($(B j(" b(& n������������)v "" $�" �~?"c �\;N7L�� b f3��"&�`w 2}# �@���#Ll��4�vc�d(& V9f&�8'Xr['(fHnb;��"(&XbvI.fn����������.)n" B $� p?_]c 0l0L3�pr�b$b;�;& �@_7H!O3#��@3�2���0h#MXw� 9&��������g9n;n������������9rn;P@UPA�AUT�������������������;" n �`9f�������;ne;������` B $��6N]6H"7�3@7l3N� \��� n� j(& �_2h= 2H�@p��3X#]#]�("���������������������� "$�`. b.�@b" T(f;������� $B �`w]3 ����b_3����@3 �P �&n��3�"@x_v {2X_v}c_Hc^2X7�$&������������8n;fn9fT�B&�r ")b j���& *v�������"�� �]���3N;l3p�N8l��;L�p~h?�& ��$ .p}7 6# "Hc\M�; �B d&�����������8.9bb &b f 9& $d� �$ f�������* fw���0 3n3L3@`E8 ;N8L@�2Os� d8`$�n)B � }_� $ �"�$ b�����������0.8&b"$B � �����$(" n�f n����p6�<��H#�3l�;l0P�3`;�� zw��Bdf b �n& "(" $� $B b�B $" $ B. f�������������n &"  ����}@;�;NC� &n�"�'��`)@ �@M#����@;�N3P;@�N<pcv}� B $uIb �9"&)&b("* &�" $" j&n9f�����������`. B d� � �?Xb]2X�L;l3M����n(.9��n `H#^3#�����:l^p 0Hso �" b9nf9F�8rn9b.f n���V(&b f ������������������n�nF$�~c}w]60n0L3 ��c� n�n3�[ �c }s 3p��;�#��� ^2Xw\s� "n ��������bn���������������P;fP@TPA�A��������������������& "n�lKn8������nr n9������`)$�B��}#X# "c�;l3N;l���h� f��9bIf ��H#~X3(����Lc 7}w2]�� b����������������������"Bf9bZb�8" "E "9�������B�.�pwX#�@<��}; �N3Ls�c� f���;|]7\6}w^V]cw} v]# {}��Bb������������8f;n9f[j9f� .(" T(" �`" b8�������8& " ^�� 8n3�;�n�n�l8N�c ?�d9�F *& $��_M7X7# wHw�� Bg�����������8b'&b&b��"�B ���B�"b9������� �x7@(p0;3L; U�N8l�M�#_: bP " & *B `�};�� �B $� $�&'������������fIb(&$@ $B$����3��� bf"v;��� �`#����L;@3N��3Nn�;�;�@H7~�$(" n)& fb " $(B (" $& B *("* f.�������������b"B T�B  �"�`]@3��l�� " f�&(b��`$��x 2�@��@3��l ;�;P ��2Mc�B $"&b$� [j%"& b9""( $" "(&"8bg�����������, e"B �"|}w {#�lN7\p  f r;��f$�Pw]2m# 2��2 3 ;l��H# wOwo��*)ff;ln �8'9fg9r n8 ���` d "'8UAUUUUUUUU��������l` bB ���7w_6X# 0l3L3L��r� f f�;b$�~ c_H6�<@3�3���#mcNH3� f��������n��������������������PAPAUAUT��������������������������v��������������������E\#H�<F{F?~1Fd�f�ff��F�11\�@7T!1@Zo;,FF��v�x��Fv{G9~�HD7\s������������������@1DD p\qEw�����sMD2M�������]@H�dodqodA�vYwx�F�0@!D�\\qL1H�odo,;���fd1F?,F?HQ����������������������T@�MDDN�@1H*DM�������x��@�{n�����`�"�wvYgv�~A�@D3��H( !;nl?~j;~;oDfyHQ ������������/\sM7\9L7\�9DT!Tq ���TDw�������2T�z�`������ �vYpp��1w� M@�@1HQ�0D!��o;n[Fd[o?o��|LDSD������������7\sD1DLDS �SHH�`���Hl7��������DL�?�@��v8f�fYwv\� wwp�vn�\eT0NS@ ����\�@�@!H!DTL������������7\LD!H!@S@�vf��HQl7L,����`���Yv]g*@w\w�@~1@!DqE3D!NDT!HDH@HMD#ETs ������������7\LHH @��?|1v��H!E11���D#( nD�����f]`Aw���nn@QDLsKD@9DDE1DQLDD@!EDLDl7\s�����������Lp\DH!T`o;lQo~f[pYgx`�@D1\��D" {o;F?nG���gY�]��fd1n~�@M1Ds]������wM7\qMNs]g����HQM7DsD( �������(�������������������w�������w�������������������Nm!@^vDFlF�n�ff��dHH9M�@SdH#��{GlG`�@`���vF{d{�@wMw������������������@TE4weNs����@7N;L3\�������]2H��1F?n[F?lD�p]gv��`�@q�H9�\sM(!�;F Fd�dF|F;d{@�5����������������������J1T!(\LD9D�D#H1D5\������@SD�?d��`f�xP*�wY`n9wx nHs���#@� @{oDozqo?~0F?/1g=~@D1������������;M7\;mDsM�@DQDHM3��H!E1\s�������EH�o�``����t@��]`�]���~;\Q�,-@pL@?n{o=f1F1v[w@�@D@QMN������������sl5NSD1HL\!@H@!x���@!1Dq��������D�;����wvfAw � ppYp�o~HDN#@pLH!@��������H!H!HD1\������������wD1DQLH#@@�@�ff�L!D90D1E��@@~F�����gY]p(@w@`1n9�TQM1ND1@�e1TQED!HQ0DHQD5TQLTSM1������������wDDT�����;FY�]�L�Hs(H���L�2@GE�����vFv@g��xYv1oDH#K7L9D@�@T1L1TL5\;LL�TL1DQL1D9L3�����������A`DD!�@D|~1F}~{f]wv� �TM��:LH�<oD{gYu�vQ]x�d[b~1oAPTSL7������7\qm3\9Mw�����@1D9L7N(**********�������������������q������s�������������������E\! HD�?|;nFd�vng��F?�1�L1\�@N H�|?fpFt�������9Gn{F~�@S�`]s������������������@1J1H!�7NSe7����\L1DsL�������}1�@�oD;nD;F|��w]���@�7@D3�L7\SE3D�o;Do,nfFl{o dnH���������������������TD@pmDDD�LH!DL������@D @?Gx�fd�*�p]�YfwY��l�@!Lw���3H�TD?n;F.|?~;B|{Bv{H ������������3Nqe\D1\qDHD1�`�� TLw�������H!n�fFdg���]�Yx ~1 �H 1H0D!�wo?~{o?l[o='��@T;E������������7NQe3DD!M�!@Q ��xASM3�������T�?x�`�v8wvYpA*�Y`]p�v1n@QD5\eH�0DQLHD�����HQH!DqM������������7N;LH!H �������vXg�@QL3AE+\���@#|F����Q�v�Y� @w��F~Q�@EDsD5D�\DDQH!DHE5�!HQEDSD1\s������������7NL1�D@�@Gl1� @!D10���D!@<n1T������Gvo!w����o~H!1<sK.!�D9DDM1DmD9�@EDL1TlNr ������������N !T~Flo?~f�]g� o��D1\��@~[F}nT�gY�`D?f9o~�E1Ds������wM3\sM7]w�������sMNqd(����������������������������5�����@7�����������]�������\lD!�p;~;FdDvYgnY�d@sADsM�@sE1H!F{o+lz�����`;f9nD[D1��]w������������������X7LS seTq���M1TSE\�������\�H@[F?lDD`������`[�DDq�Lw]7\ ��F1F=n1fYd9n,0F1v�@ 5���������������������1TQuNLDQLDH!D5\������@S�T?v��fYf�" ]�v]��fDw��@�M_n=D1B,{*Don;gw�@E2\������������sm\qD1DL7@!T!@!L�`�@Q5\s�������s@�@n��`f�dfv�*\]\g�A~~�1@!LS�pD5@!�={=~;n=~{@@@!E\������������se1TL1D!T�H�!��`���@!Ds������D0H�;��gvf�@`A(��]��o~@HD7NQ�pDD!@D@�@�H DH!T1M7\������������weD# H!�H1@����fn�@!TqRL���@@�o��x��w��Y�=�] �w�`d1o+T!D3T H�ETHQMDQ1Tq�H!TSE5DM7������������veD@Q���xn1F�Yf��@��Hs]H]���L2,{FDF�����v@vg�`�tnTM7\9e@1�TLDsD1\9e�TM5TD7NsM/\�����������LE1D!@�@�>n1D?~;o`f�\wY� �H!]HsM��?D5H�G;d[gE��Qg���D1F~1n�TsDw�������7\qM7\w��������0\;e7\(* **** *�������������������#]����Xs\���������]w]�������E\!H�x?|o;lFD�nYf[x�F�1L\�@5DQ@�o~;Gt������d[F~Fw�@���w������������������\QKHJ7NQe3���NDLM�������|�3@�|nd[o|Da���ep��=��1@L7��Lg�vE@�ofolpfl9f~1F=lo�H�����������������Xw�@!E@sdD!DDLDTl������@1T@@�ZG`xQfv( \w@w]�@��l{�@ lgT��1H�T!o?~{FDF.F~o?~{@TD������������7<9M3NL\s�9DHD1�� DLw�������5H|n@�f�GfYg�*@vYg\v\� |1n�HJ1@�0TD@@~{o?~{o@HQ�T;E������������7NSJ1HLH!E�!@Q������@HQL7IL�����@���$YwvY���w ]�]x~1@TseDNQL@1D@@HQDH!L5Tq ������������7N;L1 !H@���p}�v8f�@D7AQE\���L!�~�`���v�``X]��gx�F~Q@PHsD1D!MEDQL1DM5HSE5@DTQD1TM1L9�����������@pN H!@�@vFd`�9f�@!1\��pD}nDdx���g�`]g�F�`n n@D5TsL7N"�;L3NSl\;L\q�@!D5DLNsd3\sM�����������LND!@Fw{F?n`ff�`x n5D1\�� �~1n+oF��vg��l fYo~T�M3Ds�������wM7\s]g����������J7\9K(� (  ���������������������/\sM���\N��������wMw\�������\!LH!�x1v~1FD}�Ygn]��d�HsHM�XsL1H�p0BFB������nKd1od[w@!2���`������������������l3(�\sDTs��0L1TQJ5N�������\-H�?nF���DA�XeV�f��q�D;�\��](�;F~;F9nFf;l;D;v�@!5������������w��]w]7TQ7NSMHd@#�HE5\g������@SM�Q���vYgd��v@g�w�g�x F{�ND��# L@qo?DFd:Fd[o {o�@!D1N������������sLN9L3DL1@!@T!@!��@QE1\s�������q@�~P�fvfvw(@g\w@g@��o~H!END@pD1H�~o�@!H@!E1N������������wd14DD!T��H@`���@DTsN7�����1@�;����vgPX`v�]]`�1o TQD7N1L1@�E5D!D@@Q�!DH!DqE������������wDDH!H0��?�gnY�L!Ts,QL���L5H!�o�����Yw�`Y@Y�v��.1nT!E749L@L3D1L5DEDEDH!DDDDD�����������\pd1H#@@�oDF`Y�v�L��H9HqM��0d@ntF�����@]v��f�F~oAHE7\sM+@�D:DNqM\9M� 2DQL3Dqd3N9M7\�����������D1e2H!@�?dQo?n;nvf\�~H TM��9M1@o?d1o;fQ�Qgv���df;.1o�D3Lw�������7\s]w����������� sL7\(� (* �*�������������������3m7Ds��]9E������@7\qM�������M@#H@xdQndF?|�vYg��F1@!�\\L@@hD;o,���,V;~n;!����������������������\EHLDE\��3DDM�������\�0�nt�����!*@����n�9~�@!D7�\(@�L1�2Dofolon;n;n loD������������w]w]7\sMc�D�sDD!DD3���DTLw�������T1����Xg]wYgA� `w�@w�f{�@!L@�@H D!�;ll;FDF?@~@DD������������7\9eDD1D@SHH�@`���TSM7�������(H�*?e�vgf9ww] �w@gv�|n@TD1T!0TS@ro?[H!@!HM������������7ND1D!LH!D!@Q�0������@QM7A!e����#�����Ywv]`�w�"\]w��v1w@!DDsEH#\LD!H!@�!H! TQDT; ������������7NLH1@D@@�@~{xv\g@DA\���En����@`]`Xw]� g�BfH!DTsD3D#\qLDD1DL1DD1@!TM5DL1Dq�����������]pDD!@�?|nD`pYg��D!D\��N�?nD9d����Y`]�F,1n+~@QLTsLwMsL�sL\;M7\qM7���@QLD9e�������������������MN���;F}~;Flfff���n5!D1\�@\#2D{V|FQ�vf��Fd[G;~@@E7\s�������wMw���������������\s(� *  �(������������������@/Tq 1�M\s������\qd-\�������]#@H!x;F{n;F|{F��Ygv�d@s�H;�\;m+T!pFvF����`F9l{l{D!����������������������L1D]9MD9E��1H!D1\�������\SD@�;v�w��x*@v�gv9f�0o�Hq���s@~1G1o~qo?v{GvD?~_@!L������������sM7\sM3\s H�NSEHQD7@�`�TE1\s�������S��h1x�@�v]w�@�*pwwg��G;�\!D�  �M@^o?~1o9dD1n[p_�H!L\������������sE\LD5!�D!@!D��V@@!E1D;������� @{�vl�fvAw\�www�gl@HQMN#@pDH4�{��?w�H@!T!D1\������������we3DLH#H�H@�f���@DDq\9L����H?����gPX]v*\v\g�1oHQL7NQL��E5TQDH!H! @Q�H!DD!EHQE7������������wE1D!@�@�oxg�wY�@1Hs@9 ���L1H�o���Y�fY@�wX ���D1n�HQE749E@LTqL1TD\SL1\s�HQD1DL1NEw�����������DpE1D!���{n?[DfY`n�A��@;]HL��?M(H}n,FQd���v�]�]��fG~1oA�DE7\w]3D��7D9M\sl7\s����JDLN(**********��������NmH@��?d}ol1F�vAff��n�H]HM�@MHhFB;nf��Yg��x�dn?gq5TsMw�������s ��������������������(* ( ** *��������cc65-2.18/testcode/lib/apple2/rose.hgr��������������������������������������������������������������0000664�0000000�0000000�00000017770�13473601511�0017436�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€`E.\~ÝÊÿªÀ¿ÕªÅ²…¯Õ«Ÿ(D u"]+€€€€€€€€ (€€€*ªÕªÕªÀ€çîÙ«÷îÝ«€*D+q*D;Q*€€��������€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€0"T y®Á¿…ÎÅ«—ªÁ¨ôúŪÝ"D b€€€€€€€€€€€€€€€€ *U jÝ»×¢];ÕêA:wnQ"D*€€€€��������€€€€€€€€€€€€€€€€€€€€€€€€€€€€€Ø€Ñ‚€€€€€€€€€€€€€€€€€¸×ŠÜÂ玄ðÿ€ˆÑ€Ôªý"Y(.€€€€€€€€€€€€€@j]*Dª•ªÔŠÕ*ÕªÕ.\ UjE+€€€€€€€€€��������€€€€€€€€€€€€€€€€€@€€€€€€€@€EjÁ¨õ®€*€€€€€€€€€€€ÐªÅ¸÷®À«‡€ˆ™ê×°¢Äªõ"D Q*€€€ U;€€€€€€:qjE .D(.D(.;.E Wn]+€€€€€€€€€��������€€€€€Q  Õ*€€€€€ U+€€€€€€€€€ ]‹õ€€€€€€€€€€€€ªÕŠñãÝËÿ¢À¨„üý •¬Ôªõ*E*n];w"\ €€€€€*] qbQ*] *E:"D8n](*\+€€€€€€€€��������€€€€€€ W"\+€€€@.tª÷ëÕŽ€`]  € €€€€€€€€€n]*Un];w*Õ«—‚þ‹—îÝÀ÷£Õª‘ Õú‘ªP ";"\+€€€€€€€€€€P*U*Q*]"€wn];jE;U€€€€€€€��������€€€€€€("A€€€tîݪõ®Ý«õî]8€€ €€€€€€€€€€\8un](WbU¨×¢ÝŠ•®Å¿ÑªÕ«‘¸ÝÑŠT q*DwnU€€€€€€€€€€€€€ D bE€€€@n] w.U;W.€€€€€€��������€€€€€€wn pü«•€€°ßªÕªÐªÝú€€€U*D(W€€€€€ un] qn](ѪժծÀˆ‘ê݈ÔêÝ»ÕUq.] €€€€€€€€€€€€€€€`E("D+€€€€€€€€@n];Wn€€€€€€��������€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€"D8"<×ÂõªðªÕª•¢„Õê"E w*€€€€€€€€€E€€€€€PªÕªÕ‚ÐìÝ»÷ªÝ»÷ŠÀ"E+bU*€€��������€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€\"\«á®ÄŒ—®Ç¸áªÀ»ÕªÝ ubE(€€€€€€€€€€€€€€€€ E*A"Dº÷îÕ¨÷nß¾@j];A*DU €€€€€��������€€€€€€€€€€€€€€€€€€€€€€€€€€€€€Ð ÄŠ€€€€€€€€€€€€€€€€€üÝ‚Ÿ‚ĈÐó߃†¢Ä‚ѪýjE:€€€€€€€€€€€€€P;(E WªÕˆÕ¢U ÕªÕ;Q.\;q.€€€€€€€€��������€€€€€€€Ð €€€€€€€@€€€€€€€€@:Т݃W"€€€€€€€€€€€Ðº‘Âß»áªÜŒ€¢ÜªŸ¬„»Ñªõ(q"D €€€(u.€€€€€€n];E(\ " "\ l];.U;w*€€€€€€€€€��������€€€€€E®Eñ*€€€€€ .€€€€€€€€€ ê݃€€€€€€€€€€€€€Ð¨ÕªÄ÷‚ÜŠö¢…¿¨ÕŒÑªõ:jY;un](w €€€€€Un]("D*wBU Q.T Qh](nE(q.€€€€€€€€��������€€€€€€"TP*€€€@;}®ýÿÕŽ€0wn € €€€€€€€€€:wn];wn] Õ®Õˆø£„Œ‘À݃ժՈպźP"\.]+w.€€€€€€€€€€(€"Uq"](€€];wn];wnU€€€€€€€€��������€€€€€€ U"€€(_«×ªÕª—¢Õún€€€€€€€ €€€€tbU;Ub ªÅˆ×ªÄðÿЪծ„ÿÿ¢Õ‹P*\q\;€€€€€€€€€€€€€€ "E("€€€@:W`];w.\*€€€€€€��������€€@€pnE`þ¿…ˆ€øÕªÑªÖªõꀀ*Eb] €€€€€€\;wb];w.Ūժջ‡¢Äº—‚Ü»÷®• "D8"D€€€€€€€€€€€€€€€ "Dq"€€€€€€€€@*wn]:€€€€€€��������€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€\.\lÕ‚õŠžŠÕ¿Õ²Ñ²Ô«Ÿ*D q"]*€€€€€€€€€€€€€€*ժՀл÷îå¨÷îÝŠ*D nEQ*€€€��������€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€ƒ€€€€€€€€€€€€€€€€p.TwªÁ‹€ÏŨÕꇨ»ÄªÝ"D:j€€€€€€€€€€€€€€€€ "T QªÔª•îÝ;}ŠÞ;wn(U*U€€€€€��������€€€€€€€€€€€€€€€€€€€€€€€€€€€€€ÜˆÑꀀ€€€€€€€€€€€€€À¼×¢Ý€ñŒõ¿öàŸŠ‘ŽÄªý"D .€€€€€€€€€€€€€pnE bUªÕªÅ "DªånE;q.\;€€€€€€€€��������€€€€€€€À*€€€€€€€@€€€€€€€€€€(Ĩ÷àU(€€€€€€€€€€€€ÐªÅˆÿîá«—ª„ˆªü…¢Ôªõ*\Q€€€h]+€€€€€€€:w.E "D(e"D("T8.] un] €€€€€€€€€��������€€€€€Tª"Ô*€€€€€`E+€€€€€€€€€ ]»á‚€€€€€€€€€€€€€¢Õª•®ÜˆàŽÜ«á²€ª• ÔªýêU:`nUn] €€€€€€€:wbQQn] "D "(wn]+bE;€€€€€€€€��������€€€€€€ QD*€€€P.^ºÕîݯe.D  € €€€€€€€€€h];qnE;w*ԺעÀ»‡þ•Ë÷‹Õª‘ Õºª@ u"(wj]+€€€€€€€€€€€€€€D(*\( €€wn];jE8W€€€€€€€€��������€€€€€€€u"D€€€?WîÕª•¢Äƒõ¾Ý;€€€€€€€T*€€€T;W*] W.D¨—¢Ôª‘â€ÕªÕ‹Á¿D¨õŠP Q"\ P.€€€€€€€€€€€€€€ DbE€€€€( wnU;Q.€€€€€€��������€€€vb]"DQ Ö»•òÁ»Õ¢ÄºÖªÕ»€P""D*W€€€€€€tnU8wn];•ªÕªõª„ˆ‘î…€÷îÝ»•"EbU Q €€€€€€€€€€€€€€€`E"\(€€€€€€€€€ U*w.€€€€€€��������€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€p"\;w.<—ðõÌݾĈ•âźÕêÝ.] W*€€€€€€€€€€€€€€€€TÕªU*ÔîÝ»w«Ý»õ‚T .U"T €€€��������€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€‚À€€€€€€€€€€€€€€€€b]«ñ‚ä»—¢ÅÈ—¢…»Ñªýu"E8€€€€€€€€€€€€€€€P"D8U"T¢ÕªÅ¨×n]jwn];w€U*€€€€€€��������€€€€€€€€€€€€€€€€€€€€€€€€€€€€€– Ôª€€€€€€€€€€€€€€€àî݃×ÂÇ‹õ¿Ü¨•ªÄ‚ѪýbE:€€€€€€€€€€€€€T;*D ªÔŠÑ(D:QªÅ .E w.€€€€€€€€��������€€€€ €@(€€€€€€€@€€€€€€€€€€•ê¨*€€€€€€€€€€€€Ðª•¢Ü»Ñ®Üª•€Ø¨€ÿˆÕªõ "U€€€€:w.€€€€€€@n]+E"D*EjU Ql];.D;w €€€€€€€€€��������€€€€€ªU€Q*€€€€(W.€€€€€€€ €€€€€€€€€€ €€€€€€Ð¨Õª„¼ñ¢Äˆ÷ Á‚ÔªÕ€ÑêݸU ;.D+w €€€€€€€j];*U;WDQ"T `](n] n€€€€€€€€��������€€€€€€.D q*€€€P{ßîÝ»÷«Õ;bE€€€€€€€€€€8wn]:qjE+ÑîÝŠ‘ªä¸•þýƒÕªÕ¨Õ¾DºP"\Ql];w €€€€€€€€€€€€€€*\ "\ €€];wn];Wn]€€€€€€€€��������€€€€€€€@€T€àëݫբŸՎôªýn€€€€€€€U*€€€P"\;"\¢Ý¸×ªÅ‚€ Ôªõ®ø¿êÝŠP"DW"@+€€€€€€€€€€€€€€ "E("€€€€€€€U;wn]*€€€€€€��������€€€;"DD ôª„¿¿Õˆ•ªÖªÕ(DnU€€€€€€T;un];wnE¨ÕªÝº• Äº—®Ý»÷®•""T.D €€€€€€€€€€€€€€€ "D €€€€€€€€€€€ ];€€€€€€��������€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€@"D;•€ÿ¿‘¢Ö‚‘ªÔªß"D+W"]€€€€€€€€€€€€€€€€"TU Õ»÷n]«×êÀ€D8W"DU€€€��������€€€€€€€€€€€€€€€€€€€€€€€€€€€€€Àƒ‚€€€€€€€€€€€€€€€,DwêሕâÙˆåò«•»ÔªÝ"D8j€€€€€€€€€€€€€€€T#qnEQ¨Õª‘ªÔ:un];wn]€€€€€€€€€��������€€€€€€€€€€€€€€€€€€€€€€€€€€€€À•¨Õꀀ€€€€€€€€€€€€€Ø¿÷‚ß°ÕŽüÿ—ø…¨‘ ÄªÝ"Q:Q.€€€€€€€€€€€€€tn bU(Ñ¢Ô*Q.ªõ"U b];€€€€€€€€��������€€€€ •€€ª€€€€€€€@€€€€€€€€€ĺ‡êE €€€€€€€€€€€€ÐªÕˆùî¿‘ª…ê—‚þ¿«Ôªõ"D(€€€Pn]+€€€€€€P;W*D "D €"D8"D0.]+j]€€€€€€€€€��������€€€€€¨U"T*€€€€hE;€À‚€€€; P€€€€€€€€€€ €€€€€ U¢Õªñ°Ä‹áÂݨð¢Õª•€ÔêÝêQn];qj] €€€€€€€ wnQ unU€"T " n]+*]8€€€€€€€€��������€€€€€€ Q @;€€€pzÕ»Õîõ«÷n]8€€€€€€€€€€€hE;qjE+w.Ôºñ®Ä€á¿•»÷¢Õº‘ õ‘ŠP "D0wn] €€€€€€€€€€€€€€E W"](€€tn];j]8W€€€€€€€€��������€€€€€€€€T€T€àº÷ªÕ¨®ÕºôªÕ:€€€€€€(U*€€€@:"\;nUŠÕîݪ•ŠÄˆÑªÝ‹Ù"Ĩ׊PQbE.€€€€€€€€€€€€€€ D(bE€€€€€€€pn];W.€€€€€€��������€€€p"D"D8 Ô‹åïݪ‘‚À¨ÐªÕº‡€U bE:€€€€€€€PnU;wn];UªÕªÕª•ˆ‘®„¨÷îÝ»…"E8QbU8Q"€€€€€€€€€€€€€€€`E"\ €€€€€€€€€€€€w.€€€€€€��������€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€`"D"|»•®•Î×úÅ«ŸŠÄúÑêÝjE(W€€€€€€€€€€€€€€€€D"U(õîÝ‹u«Ý»•,U "\ "U€€€��������€€€€€€€€€€€€€€€€€€€€€€€€€€€€€à‚Ä‚€€€€€€€€€€€€€€€0b]ª‘‚ýºâá¾—£Ÿ»Ñªýu.U:€€€€€€€€€€€€€€€t"\(Q"TªÕª„ªÕªÕ+wn];w€€€€€€€€€��������€€€€€€€€€€€€€€€€€€€€€€€€€€ €‡¢Ôº€€€€€€€€€€€€€€€†ü݃øÂÅ‹ý¿ž¿• Å€ÑªÝ(.D+€€€T €€€€€€ ];*D *ŨW*T *Õ;"]8w.€€€€€€€€��������€€€€ Õ*€¨€€€€€€€@€€€€€€€€€(‘€À¸Q€€€€€€€€€€€€ÐªÕ¢ü»‡üݪ…úÅðÿ¯”Õªõ*€P;w.€€€€€€pnU"DU\*T Qb]+nE;W€€€€€€€€€��������€€€€€P¢UQ*€€€€:qnUBñ€€p.(P€€€€€€€€€*€€€€€jªÕªÅ°‘¢ä³÷ºÞ£ÕªÕ€ÑêݸÁ"€v.\:w €€€€€€€`];Q(U; Dq"T `](n] wn€€€€€€€€��������€€€€€€*D "€€€P¿õªÝªõªÝ;n€€€€€€€€€€€ qnE(.E+ÑêÅ»‘‚௕î Õ®Ä¨õ£ÄŠbE B];w€€€€€€€€€€€€€€QnU("D€€T;wj]+wb]€€€€€€€��������€€€€€€€€€PT€ðîݪ•¢Ä¼Õºüªõk€€€€€€*U(€€€€€j];wnE;qªÜ«õªÕŠ¢Äª÷¢Ðˆ‘êÝŠ*U "*€€€€€€€€€€€€€€ "D(b€€€€€€€P;wn]:€€€€€€��������€€€@ "DbAz÷ºÜ»Õ€€€¢ØªÕê‡ *D8U.€€€€€€€@:wn]*wnU¨Õêݪ• Äˆ‡êÝ»÷ª… QbEW"T*€€€€€€€€€€€€€€ "D€€€€€€€€€€€€€]*€€€€€€��������€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€ "Dy®…¸•ÎÅê׮܊õºÅªß"D Qb€€€€€€€€€€€€€€€€€"D(*Ý»÷ª\/Õª…(w.A"D€€€€��������€€€€€€€€€€€€€€€€€€€€€€€€€€€€€À‚‚€€€€€€€€€€€€€€€ D{÷êÙŠÝ¢…€÷︗¿Ôªý"U+.€€€€€€€€€€€€€€ ]"*DUªÕˆÑªÕªõ.];wn] €€€€€€€€€��������€€€€€€€€€€€€€€€€€€€€€€€€€€*àÁˆÕª€€€€€€€€€€€€€€ðÿßð÷®ØŠàÀ÷ñïÝ€— Äªý"T Q*€€€€E*€€€€€€ "D QnEhUu.;U"E:Wj]*€€€€€€€€��������€€€€ U €¢U €€€€€€P€€€€€€€€€ „€‘.D€€€€€€€€€€€€ªÕŠñîÝðõªÁˆèÝ‹”®Ôªõ"T"U €unE+€€€€€€T;.Q"U"T:"D0n]+b]€€€€€€€€€��������€€€€€P U"T*€€€@.}¿wJ÷Ž€@];(€€€€€€€€€€.€€€U:W¨Õ»•òň‘àÝŠö¢Õª• ÔªŸêÁ X WnU €€€€€€€ Uj*wnU"Tu" w.](*\8€€€€€€€€��������€€€€€€8(A(€€€tëÝ»õêõªõj] €€ €€€€€€€€€ E;w"U:"Ū•êň®…»‡ªÕº• ýÑŠT:qnEwn]€€€€€€€€€€€€€ U bEQ€€€pn]*wn] U(€€€€€€€��������€€€€€€€€€X TôªÕªÄˆ€îݪÜêÕ?€€€€ U Q*€€€€€8wn];unE ծݪժĈѪ݈¢Äº×ŠQ bE*€€€€€€€€€€€€€€`E("\8€€€€€€€Pn];W.€€€€€€��������€€€€.D8w"\bÝŠÞª•ˆ„¬”ˆ‘ªÕ«Ÿ UQ.\;€€€€€€€€j];U€U;WªÕ»Õª•€à€À«÷îÝ»… \ W"D:w €€€€€€€€€€€€€€`];wn€€€€€€€€€€€€€T €€€€€€��������€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€,D*\«…¾…ΕªÇº™ŠüúÕªÝujU(€€€€€€€€€€€€€€€€€E*D(÷îÝŠu¾Ýªj];"D"€€€€��������€€€€€€€€€€€€€€€€€€€€€€€€€€€€€ð‚Ä‚€€€€€€€€€€€€€€€0wrݪ˜‚Äˆà•»è•ŒÑªýqbE:€€€€€€€€€€€€€€(w`U*Q"Õª‘ªÔªÕªÕ;qb]+w.€€€€€€€€€��������€€€€€€€€€€€€€€€€€€€€€€€€€@*°¢Õ» €€€€€€€€€€€ÐºŸâ×»áªÄ€þ¢Ôþ•‚€¸Ñªõ("D*€€€€Q.€€€€€€hE*E*T"8"\n]8w"]+U.€€€€€€€€€��������€€€€€"• €€€€€€P €€€€€€€€€ À®Ô €€€€€€€€€€€€ÐªÕªü¸÷Âݪ²Àø÷ƒ•®Ñªõ(U"8W*];q €€€€€ ubE "D(uJE*T Q`]+n] w*€€€€€€€€€��������€€€€€@"TQ*€€€@+qï]êÿŽ€€wn€€€€€€€€€€:W€*wn] õîÅÈ÷â…¿×ÊߢժՈÕúǺ*DnU q*€€€€€€€€(Q*]+ Du"\ ];w.];q.E€€€€€€€��������€€€€€€(D("€€€\»÷®Õº•ªÕ:b€€ €€€€€€€€€€.] .U;êŨ—¢„¬ÅþÁªÕ®„ª£Ä‹Q.D;];w€€€€€€€€€€€€€ q"T("€€€P;Wb]+w.\*€€€€€€€��������€€€€€€€€8 TôªÕˆ‘‚À»×ªÐª×þ€€€@*"U*€€€€€h];w.E;*Ժתժ€¢Äª÷¢ÔªÕîÝŠU"\*q" €€€€€€€€€€€€€€€ "D(.€€€€€€€@;wn]:€€€€€€��������€€€€0.D "x÷‚ýª…îݫѠÀˆõê(*T u.€€€€€€€€(w.€P.UªÕªÕªÁ°÷ªÝ»÷®À(w*\ wb]+€€€€€€€€€€€€€€*U*U*€€€€€€€€€€€€€€€€€€€€€€��������cc65-2.18/testcode/lib/apple2/superman.dhgr���������������������������������������������������������0000664�0000000�0000000�00000040000�13473601511�0020442�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������DDDDDh!D!hh!!*{/��~ ""2"" 2H"2H"#""3DDL2L3F3 "Lo{~{~"""""3L!�������" @(]{^~��������@D1Lhhh1Lh1!**]{J�po""" "H2H2H2H"""r3H3D2l?o? #7Lz{o~?""""":LDL3L3L3 "{~@��������/ H#L3L3H#2"b!FM3�! Nn_RD��~"h;o{ 3 3H22""""1L1"" ?N:H{o?{~~~?oE3D@1DD1L1�j7^{��������??H2"""""@3L3LL3D1L33T6TZp;w~{~{o?n33" """" !L"L""Hb~{o{o?o?o??:LD3�1D@3L\^w_~{��������?~o"""""H{J;};3L!LwM3Ls ~o]+#(;w_2"#""""2L11@H23B�to?o~???~k1L3L�1D3DDp2^w~o��������o""""""x{z;~s0!D�1D;~~N#(;n"""""""""@OL����h?oo{~?~?o{~??o{HL3~/��AO2Hkw_}?�������� """#H# 2H#HJQM21��2LCJ{J�H};?"""""""""�0LL"�H oz?~o{?~{O�!D�{o?�"L"Hs_��������""H"H##H2H2"L/M7""�DA"LL{~"@3x{{~?" """""HD�@{nn;"D3 Zso;~{~{~{~?o?o{oL �2?oo{";L"#~��������!h:N!h:NDFhDF:F:N:{ �l "" """"# #""""3L HH3L3"3 2??o{o?o""""""h3L����"L@^;m��������? DDD!L*LDF!Dj*;o} ��0o"""H# 2 #H"2H""bD3 2x;~?L"3L |o?~{o{"@*""3L3\3L32{m?��������;L3L# #" "H" 2qL3@j*ln* A�o;"nn{H2 #"" #"2HbD2H""H:o;h{o{~??o{n{{N3D1LH0D3Hl{mo{��������;# """""�3\3D1L1L3L32T~T)@t:?o?_??o#H""2""2B�LL"n!"HL�ro~o?o??~~{3L1@�1 H3!n~{}w}?��������{n#"""2H7-7|;D3Ls\3D3 oM::} H""""""""HL1DLHH ~?{{?o{~{~{?~oKD1�!3HDz3_w{���������""""""h{z7o73D@DH!~T{M:j;}"""""""""@CL@$DH@h?{n??~?o{~?oD1L�/�DB#k_{�������� """H2""" 1$kD""L��1L3�?\H;~#�""#"""""�oD1L!L"�DD/mR~~{o?o?~{?o?N�L�o?o"}L"#?��������"22H2 """"2N #"$�D:DNz?m!@3h?"""""""(L��;~n3�"D3LT/?wo;o?{~?~?~?o{.M��r??� +L" 3{o{��������DD1DD1D1 !h(h:�@""""""H2H" #H"H""3D2D(3L333"?o""""""D3D2���3LC"�"(!m7D?��������3L#H!hF!!h*h(:(#*+v_1���0~"""dH2 # ## """"3D3H "h;n{L"3L }?o?""{N""3L11L3L3L3 2_?��������L3L3L2 2#"" :L3Dh!� 3l.}u~�o?"?H2H2 """""B3D1@H""Lkn;�t~?~?o{?oL3D@1LDLDDmw}7??��������nH""""2"Dh:]3DDL3L32TtJz#oon}# #""""" R�LL"l3"Dz{?o{?{{~o3L!L1�2LLmw^o��������o{~;D"""""lkM;~7DL3\3D3 >-?m**j*?m "#""""" "HL�L;"�0 o{?oo?~{K2D3D��1L#�3H^w_?�������� """""#lz~7_3H2�"L1~K{L{:l{""2""""""@ LD3LL��ho+~?~?o{~o{~~L@�.�DDN# j}��������""#" 2H# 2 �@SL7�""�H��3M307ZH0{?o""H""""""�n�LL"�L3H>,ko;o;~?~?o~?O@�P{ 9L# 2��������"" """##2HL�""�H{Nc!w"L#(~?o{�"""""L���;fn;�" 3M;o7o?o?o{~?o{?/L��{?o?~J�H+L22?��������1D!LDF!h1h!FL#hh!(:?�D""""" # 2 #2#""3L1LL3L#"1 D"Ho{{~!""""N3L��H3\s2"h+\;@��������{J H23L#FFhFhh*j**[n?��� o"""~+"H#H3L"" """D3D#L;n; #3L ~n~?O"o""3L@3L3L3D127^o?��������oN3 3H#H"H" """7LL3D"@!L!{@~;"~{o{�# # # """#"D@H""H3n3�z??o?~ooL3D@DL3@Jm{^wo~��������o;? "#H""" "^o L3DD3L1D TzMA{:v~{~{~;N2"H"""""JLL"L9"o{?~{~o{~??3LL@0H�L@-_7_{��������?o"""""hsN?~3H�L3M3L3L$?\S#h#v; #""2""""HLD0\H;��1 {o?~{?~o?oG1 3D�DL3�3}w~��������o"""""""\7~3nQ�H17T"t#n?"2H"2"""""�0LL�3��|kjo?~{~{o{~{�#L��?o� LJ"Sw_w}��������""H" "H3 22H2M3""@���3M34 kZH?{""""""""��~;D�LB"�L3LdSJ3o{~{?o{~/��l�HmL"3��������""""2H""H""H"H""0H�D;n#C{^"L"H?o{~{"""""""L��:n�n3�"�L3N;o;{~{~??{~~/L�@~o{ HL"H2~��������L1F!L L:(F1 !F:v{?X*�""""22H"H2H""""3D1H(3L9n"(]7(?n{~?o#""""L3!��LsM3!"t?!�M7*{��������;�#H#L2 3L"*F1DN#!N1!h*+o}�@ o ""o7#H2 2"#""Hb3L3H 2L;~?L"3LH{{~oo"y?3"3L!3L3L1LDc7o?~{��������?o3L2"""""23L1L3@s"1\#[Q�o�~{} 2L#H"2"""CD�H!"3n3 �o{o{~~o{~;{L3H@1DD!LH ~7^{��������~ 2""" "2_MLL!L1LL0L}o\*n7~??�2""""""E�LL"L; "Lo??o{n?o??o{~?3LL0D�L�!/~m��������?J"2""# "hkM?c!L�D3L3D3L{}?Mh:(:n;""H"H"""""#HL!L1LH;��3~~?~~?o{~~N1D30�L3�#^w}��������O"""""""h{}s_q���D!>7,28*n?~"""""""""�1LL���!Hz:{{~?~?o{~?~?o?o�L!D {�D"Hcw?��������""�2H3L#H2H""HL7L""���3]38N+J@~?~~;"""""""���n;3�DA"�L3LT5Ow{~{~?o{~?o/@�|n{~?/ 9L2H2��������"2"#""H"# ##""D�DH;D2?/"2 ?o"""""""L��@�,�"�H3�O7^;~?o{~{~o?o;o/L�@o{? LL##o��������*#/!L1DNF!h1#*!no;�\ �""""H""#2 #"""3D1DL3L?o# ]3L�~+"""""HL3D�L7M7 "z�D@�������� 2 2 #H"3j!hF1hF**-v���@~!"9o;H23L"#""""1L3DH"H2n?L"3LH{o;?~�~;"3L�3L1L1L3 c{}?��������3H2 2 2""""3L3LLs�3]z%�o@{4oo?2H22" """B2L0�H#" 3n{o{o{?o?nL3 1@1LH2LLL^{m{~{��������?"H""2""OMD1@D3D3L ~^N^_wn7" """"""HELL"3N"(L{~{~?~D!D!D1L1D�@)nw_w{~?��������o;""""""lkMo6�LD3L3D3L ;^m:N*n;"H""" #""""LLLLH"R��3D?o{{~?o{o??{DD31��DL3l#H~_}o?��������O"""""""hz}7_Q�����!1 u3M"L#n ""#"""""�1D�L!����D oz-~o{o?~?o?n�LHt~� H2Rw}��������""" 3 3 #H# #H; w #" ���3 1(.w*@"z?{o?""H"""""��n?H�DD"L3L0v/;~?n?o~?o{{/D??o{n�:L##��������"""H"H""#"2 """0H�DH;L3i-"3{~?"""""""1L������"�"D1O7^7{~?o{o{~{L{o{?"L+L"#{o{��������:~;DDDj!D!h!FDh**;�^�{O"""#H"L# "" """3D2LH3L;n;H\7Lzo{?n{~;"""""(L3H@2L7\3"{^@ i?��������O"H2L2 2H2"L"!Dh1(:(*j:n{B�@o""?^? # 2# "H"""BD1"#n;L2 ?o{dn{ob3L�3L1LD3 S{}w��������{3 #H""#""3L3L3L3D3M#|(-o ~?N=o?~w# " """""H"D H1"H"H0 ~?o???~~/LD@1!H3L!l ^w}w?��������o{""""#7N?M*3�L3L3Ds ^_q:({?o{_2""H""""L!L "@3l"Lo{~?o{~{~o?3L1LH3�D!#_{}��������+"""""#xs*{sLH3L3DD}?m~#3n?""#""""""HL\D"D@3H?o{o{~?{~o?o3L3HPHDo#~}w��������"""""""X6m7M5 ��H�1 ~kL L+~!""""""""�2D�L3�1 � kJz?o{~?oo{~{/�L ~?�"L" c��������"""L3L2 # ""H> 3H""0��@3"8 _:O#@2|? """"""E��.;D0HL"0L3L43/7o?o?{o{~o{?nL� ?/�=H"3��������"""""# " 2 """"2�HH+L#�J"3L?o{~?O""""""b3L�������"�" ^;mo{}o~{oo{*L ?n? ,;L"r~~��������1hh1LF1D1Fh!( *(**{? ,�t."""�"#2 #"2""3L2D3,{n;F3Lz~???" """4L3H� 3\sL3 "??o{��������3 #H3H2 #H"#Hh1L1hN!*:,v}RAhj�"H?"H"L2H""""C3L1D 2"d: ~?no?;?NP3L!@3LDLDJ7o{o{~?��������o~+ "#" "" �@LwL1D3L3L3#T2t~0[?}{~{~{O3 """"""B!H1L""2Ha ??~{~o{~{o>L#@2D!3D\ o?m{��������o{o?/"2""H"7-~n?3L�Lw\Ls� :_N4:h[{~{J"""2"""" L0#DH"H3L"M(~??o{o{~o?o{n{{1DLL3 12~]{��������" """"hwj;;!LD1L31L+\~*:n"#H""H"""""HN]!�"$D#D1h{~o~o{~~LL3x@�L!~/#nw_w~��������"""""""H1,k^6�"@1��1L�]5M ;~o""2""""""�HL@"�D ?~So{n;{~?o{~/�D�~;�"?L#"w}��������"""L2H"""H2H2\s""�D#3 Lov^@;to?o;"""""""���d;n�! "L3L$7Own?o?o{~oL�{~{~O�=L2H2�������� "2H""#"2H"# " ""1LDH3L3@ "L?~/""""""J3L��������" H0owmho?o{;n{{~?o? ~?"l? #s?~?��������""""""# 4P4 #P4PCUUU�@DDDDDDFDFDD$f$ ]fDfdDy_w} DDDDDDf�����@`D%b)f]��������4 "P4 &b4P2P&PBCUUUo_�T��DDDADdddDDDD" f f_w}ef}w]}'DDDDDfF�df9ffBVw~ww�������� ffFdFdFCv5TUDun_~v�vDDodddDDDDf  DD]$b`~}w}_w_w_f�f bb&=[o?ow}��������}FDdDDDDf;ffffd_U]w�_}{w}dDDDDDD ffrdD �_w}ww_}b$b�"Bey_v{o��������}_wDDDDD>viV "ff&nDAVwzuUww�DDDDDDDDi"��D gf@}__w}ww}}&&BBbd_DY?~;w��������DDDDDDd=w}&f � " &b�!e[vyu]wDdDFDDDDFf�� �� "}__}w5&B@w�B xDo?��������DDDdFdF$vfDf��f�(n w_DDDDDDDDD�"f@���byIvW}w}w_w}_w}�f@x_dI'D}��������DDDdDDDDe'DF��bq ~]dD}'DDDDDDD ��|w}�]vdb}~;}w_}w__w]wC �}D9dD|��������' BPt' BP4QFbbF B BBU���DDDDDddFdFD$f " fD&DDy}DDDDDDQf ����bB`D4 d)m{��������W�$ P4 t##4b TQuPTPTU7~�$���DDD|DDDFFDDD` & f}w]G f_wDD\BDDf" ffffD\}��������BffdDDDDb nfFPC@@)]_wt�v}@__'dfDDDDDf  DDQ$&Bw_}__f @b &b"Y?v=~_��������}wgDDFDDDUff "& fD_WX_o_w_o_FdFDDDDf bdDD}_w_}w]wfB& �b Beq;o}_w��������_w}DDDFD_oijB&nbnB�ewgzBW~DDFDFDDDDi&� ]D�n@}w}_}_ff&b �D{n_��������DDDDDDD?o~&&�F&f�AWfhT]w DDDDDDDDDXff���B_}_}__w}E&"@�$pD?~?~��������DDdDDDd� bfD�&���f��(uDr_DDDDDDDD�wE�f` �Bp5VY_}___}�B� }w�DGD}o��������DDDDFDdFIjDDD"��w UDdw}w]'DDDDDDD ��\w] ]fbBP}vY}}}}_c_w_}�@idD|��������b&""" bb " 'P4 t 4uP_�PDFDdFFDFDDD f&fD fDdQ_w}_wDDDDDDqf����fdd_ �V[v{��������]�D$" #P4 FP#' #4 4UUUu]_�$��� DDD_dDFfDDDD b& f}w_g Tf�}w_w_D D$f$fffbBZv_��������wfFFDDDD1 f"" 'FF%oh~_B`]v{oFDFDDDDf DDw]$&D_w}}}ww}& b &ddf=[w[��������_gDDDDDDfb &fb dW `ZU{~_o__w FDDDDdDf ddBDQ_}]w}}Wf " �" $`ey}~~}��������W�dDDDD?tn_$ "nffAP'{oY}GQ7 ddDDDDDDDi F f]FD(�n"}w}w}__ww} bf&�""�DQ{o{o}�������� DDDDDDD_o_}%&"b&�A}n"t]v DDDdDDDDDXf� bB�$u_}w_w}w_) b$t�BiD?o?o}��������DDDFdFD�N5VD"���fhTvB~}DDDDDDDD��w=�&bB PR9_w_w}�" �}w}�DGD}{��������DDDFDdDDfFDDF��Yw}wdD__WDDDDDDDb�T] ='D"&}}n9_w}w_}}w}g�}_�DyFDz}}��������"4 #bPF #"C4c#&U' {w} �zDDDDDDDdDDDffdFf�D_wDDDDDDEf���nddbe|��������w�fdd$B F bFP4PtU4 CIUMun����DDT_DFfDDDDDb &d^g$f�Q_w}�DwDTfB�fff&BZ_��������_fdDFDDD�fb DDdW`]�~?z{w}fFDDDDD fDDu] F_}_w_w_w__wub$ f " b "[{n}_��������}wDDDDDDwnbB&fDW[%&vw{}~{DDDDDDDb bd gD)w}_ww_}7b $��& d "�dfq?o{w��������}@DDDDD?wum_b Bf;&f`('}ouwo@DDDDDDDdy f�f]w���ft_w}w}w}_w}_ &f�&dXD=~{��������DDDDDDD=WV"�$$$ b��WFU=wDDDDDDDDDf &�"���__w}w}w!f ~a�"qF��������DDFFddddf5'DD���n&hxn[$&}DDDDDDDDuU& dbf;U5_w]w}}w]_w�$�w_w_�DeDz��������DDDDDDFd DDD"��]~o@F~wD�DDDD$d��@w_PBD$f}{m)}}w__w}}__wf�P__wdufD~_��������4b B B #4 4& " BP4 UPTUwtY�PDDDDDDFDddDf& fwdf9fB}}_DDDDDDg9& ��bn;fdw"RV��������}dFDFRCP4 BcCPBUuPTU7]����DDw}ddddFDDDB "DQw]e$b Q}__D}}Df "&fbf@]o}��������_fdFDDDDff��f!dWh]�~}'}_vDFDDDDdf & DdV= Fw__g"&b Ff B[Q=o?~}��������_DDDDDT=wf &"ff�Dt]UEGm}}w}odDDDDDFfb d�wD Q}w}_}_fb  bf@vFq[o?o}w��������_wDDDDDF_vf=&" f& f@A_otUvuDDDDDDDDDy bfY%���f}__]_w}___&& @B}D~{~_w���������DDDDDDD;W_&B� �B$f@}fdgDDDDDDDDDTf f�@���f_w}}_}}!f�)��DiD{n{~��������DDdfdFF�nUfDD��nfj4w=F`w@DDDDDDDp]b bfn u[}}w}w}_w�@DeD|��������DDFdDFDDddD$��}WDtdD_w}}DDDDDDf����p dD"&~[m9z}}}w_wf�Qw}w}DdDw_w��������BUw #4 " &P4 BB' TUB CUu}�d�DDDDdFfDDDD f& fiw]De;f!_}_wDDDDDDtf��f9f9f&Fw_��z��������dDFFFDUB # BP4GTUUUum{W �$~DDBdDFDDDDb& Fw_e$b@i}w}Dtw_Gf $ffb b�=w[}}��������}fDDDFDDffFndZt�~{w�_v}fDDDDDDf f]DDFTw}w_w}}w}'"& &f$]Q=~?w��������}_DdDDdr[wBf$f b �F5wVPT]_w__DFdDDDD " dvD"y_}_}}w__w}wfb �b�f�~Fy{v��������FDDDDD?w~&[&b `fff� ufTQw]DFDDDDDDDyff D �fw}}w]f&�}�bF;o?��������DDDDDDF]&=wf����" "�fv_m�D~gDDDdDDDDD" f������b}]v_w}___w_Cf��_w�D}wD?o{_��������DDdfFFDD5jfDD"��nDfm[~Ff}_DDDDDDDD�P]w$�& fn]~;}___w_w}B`}}@bD|��������DdDDdDdFDDDDb��]eDvff}_w_DDDDDDf ������dDB &v{b9}_}w__w}w}f �q_DFD}��������u]]&btBc #c BPb4PTUUm�BW��DDDFDFDFDDD& Ff}w_F1;f w_}BDDDDDg"�fnfFF�����������FFdfdF c& &B " 4UUs^_W����~]DDI_BdfFDFDdfdT}'DbAu_w}w_�w ff&&"Q=v}_w��������w_fFDDDDD"n&fndP}[�_�w?_wFFDDDDD ff�FDD|__w}w}_w__fF�&"f"Sq_w{w��������_wDDDDDQ~[ouf�Bfb&DUo}\t]?wDDDDDDDDQ B� \g$` }}w}_w_w_bf && ~FQ?o{_��������}DDDDDDD_&=&f f&&�!W_oYGw]DDDDDDDDDY f "!D) �f_w}}_w}_w} "&��$XD?~{��������DDDDDDD'=V�$��B�fVV�~wwDdDDDDDDD�Rbf"��� dzUnH}_w}_ww!b��_�D}wD?o��������DDdFDDFd]9fDDB��ffu[o<FGw_wBDDDDDDD��]$�b�ff[=_w_w_ww}! �tw_DdD|��������DDDDDDDDFFDD&� ]fDcDv|}}DDDDDDf������dD &mYU}w]w_w_}w_wb y}_w�f_dd_}��������]b """BP4IB & 5 4 5 U]�f��DDDDFdFdFDD& &f_w}f;f}FDDDDDf""fffF&o h���������DffDdDD"P4P" TPU 4@w]__VW ~=DD<w=GFFDDDDD b Dd_w$d@}_ww}}}�f&f ffP]o{��������_FdDDD@@ff bffd_{�}5}{wdDDFDDFff�gDD��}}}}__wb"b "fBUQ;o~_}��������dDDDD]yf&�"nfnFUWU4Q}o}V�ddDDDDDDi B��DXfb�_w_}}ff`&b�b FQ=~}~w��������]D�DDDDD?wV;&f� bb &�A~]nUGUw_DDDDDDDDDY f �D f_w]w_w}w_=f"���"xD{oo_��������DDDDDDDE;vYV�D� �f��hWD}w_DDDFDDDDD�w&�f���fxiV_}w}w_}w&}�D|WD��������DFDdddDD[nYnDD$�� Dgp[;dF}EDDDDDDD �]wU�B`b& [_w]_w}_!��~w_w�DdDtw��������DDdFDDDdDDDf ]fD!Ddw_w}_wDDDDDf ����@dDFj5f}w}w_w"by}w_}W�DdD}_��������cc65-2.18/testcode/lib/apple2/venice.dhgr�����������������������������������������������������������0000664�0000000�0000000�00000040000�13473601511�0020061�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������DPDEDPEDADDADDDhh!LD*iAE;E.?m7n2h+l;n-N;D$LrD/JJ1l3dQ,n1 -jJ}jnk_>3n+*.*znl;l;EY$o{~Fd ]y����������*D!E4FAhDADF!DFh!L!J9d9L1N!h%),k=QE}+C!{^{mL )Jn;H+J_N+jsJv*D)@-1%{L!4xk !>/j).+%+"":%+n{~;"**Z/�������� i:>n=n;{?n:*hH!D!h!d:H!hD1D!DDLi:h-m*;LfD!"U*LD7n;jQDdLN3*+*`D+\w|;B"7;i>(?n6)*m:n;*j;g9~=Z(B(&9��������D�$kon?m~>:;j:S*(*h*.;l!nj!j:+)"DDiH-y~_:j)DD3D3%6CyN^s~*kl]l;DSDh**lmw_1M?j?}k:>:~j+&hH)j+&**o>;*iC3"��������DDP;z_{mw~?}}/oo;.**+n"n+h*H+l3A"$ Tp *yNS*'LDrL1:H*7^;-nj.; *J+!2]1;n;m;Bj{*nv.km*.*D.),.n{&$H"r��������!0� *QBI:*;zno~o{?o~/7?{>n;n#"@ E!,@ *5{j EL)-5EqT7N;Un Jr*{m{N;D!A ]iLQ,+@*>-zZ:7Z*Z&)*"* E)N8n;fB" (!��������Tm@Q.Q );h*+*#.+n_/{/mz{o;zHPD$3T*j N:TQD6zn:*F*)ZP*Z+W{.{z??MdJJ� (%+jm:** "*k**^?)k-**".j(*&*����������T4HQkE+{ok/>/{>^JN;n7nSDH:m7L;|3,UDEHZ1/~Vu>:n*k*)*:*)B&jp}{K//P?E.Z(D�f!-Yjy~Vj(:"Z"*{:* * * * j(D*(*&��������PADHD$HADD!II!h!L!D!F!Db@Q.Ek7^;m+3n:Nm6A6J1Z@zl9L+L3$kZmH>:z:*>>#!n;kmZ)**+.3*1D7?oM] ^.���������h1IHhPJh!Fh!FFh#FD)JeW* [^L3:j;.IVD1DrL3PMJ\7Z3$K,$h1-yj9**/?/* k:::kJ+9nh")*o?o/*emf}��������>ok{kz^~~{;*!!FD:j+(9;!hh)h*:)$1�.15>7.5DD+LQTyJ1E3l3$�'L!NL3j(*(bM151\>DE*z{ojo>+k^.^{+n+.**[o;?*)jlv��������@w>Qw;k^.*ndN*h#*;j*l*~;DD!l*h�XP ^"C{nkM)$q 1*9EsZ3n;SiE{E_L/4i**[>;~1.{n{k:7(km+n+**h,:")R:>9n/%S_rA��������!!$ Djo{?ow{_}?kn;n;j;z;*(: H!IP,)H .6{K,1l {DS$iDhHn;JDD^D)D)B)niH9l{~^>h6m;i***)7� j&*j+.)l:E##��������D)�TB+.>o?7k>?o}{o^}/{o+*E3 "$H!D1A yEwN*$1$$Q$2Q[^lEn[jJ;^;n7TQ@Nn!DB*j7 +[7*# z-*6j)* &)*).. *�@3��������,uBQ=Ei;:n*N;J:z*z>~{on6knHP$T ^*ZD>;?{k/Z7*+jjj*1U7^~kj{;LT +D�B@)&&'m**j(:**+n^gj(*)bZj*%*&h"���������E)!E,9Ez7l:nkz;~{{Fo;.%jM!E/J+N:Z3EYP^D{j{$:zo?/.!H1j+&:n-;.z;E?K~D j6U)B RV(&/;*;*j:*+*')"(" B)%*&*jb"��������!RH!EHDDHDDDhh!L1FhhLJB,q+wm{n3n;J3nj.{)Dn$'JKL1J3JqBZq� .t*y:ko>\;:&[n) :l.rZ~_D^Zy����������*!h!nF!hF!L!Lh!NhDL!hDJ$+%:,)>D! 3H16-*1DnsP3Jk.{l+T3M2JQPQ@Q4)MHd~k">o*/^Ns;^*&{~{n;U(in{��������<`$z^.^/{;k~k.JDhh(;Nl: J1D1NhAJD( -pN,;\D1L I).1.;nL$[T�]0m3,(*(dqZ*\;*J 3k>:7^kz>*Zn{:^;**&;>>o;*(U !9��������B��y~�^^oovko;n::f1!(*jF:.;9J:MV*i( E5+{O:^qD3.3LW%:^kLmslwN]N9$2$h,R~ij;^pj;~[7u{^zu/>)Zm*)f+* *kf;{;V2L2��������*DD.>o>;}n?~_{??~;n;n+l:j;hL�h%@ *y/n1EzDEqM,3JB{n+\$lM0 Z)(]*@3N".*-{*6Z7;njH)**&:k:n)$2$"��������"Q�Z;N*z{~~{~?{?nzk- #LT!*,) *;m*:LyDUBs8+M<{n+<q.{M=m;$Dlj.DR$ "jZ-jnjo*l*,+#in+& jn:jj**$�@2��������$4HQM2{n# 3.;.+*M.;o~??on/BQDDDR*&J\De2eme/6h*o*1\:d{mL7r;I?MT Z@Bji:m{*zm+j("iz;>(R*Z)&*&b @���������X4DQ++{^;:h*n>/E>~m H!HD;j+Lls$Q< l)o7Ie{{[V>:j:Jj7n.?K_JEZ*^*DQ "$ j"(&k j.6h&i** "(d jji&)**(��������*!h!EPIDDDDd1F1!hDD]+:{n;l{N:n+iD^;T+L3M{N{J):sj DP`$ -:JuL*>/>�!:-j*.)J.+d J3o;n7�jmz��������!:n!hF*!hd!D!F!hEDF1:F!FD:1K)JJW*5lZ2,#D1(:Dm1DsL3hRMME;^sUI*)`u�-zZ{ ):k7:j*{.fxjn'>n;j.Z;o?*PD_>��������@Rm/?{>wn~?w>j:l1j*D!+n+D!D:n:!NF!J T5@Kkk3$sD!$rD,:dk.3L3\TD ^0L3D *hdyl{{Djk*ook-?)*/%.~+e:jZj/n{n;& >mD6��������A� m~{}?:;.+*!(hD!h*v:lll*@d1 .xvn+$1,*L2H)U)LrJN;jiEkj_\/!\ *nE?}1^7n[no;n_z"*h1.j)&:n/n:%1 !$I��������D(J @jk{oo~{wo~~z~o~/:/;F*(;*D!@*$dq -1]%2E&Hi*{e)En\PL\^0L:L)nkj*m;n%}7+***j)6z; "9&ijZ/&{>+.#\��������$i!H!3h#.k/?ok{n{m?nwn{_?>yL LhQ$Q$*he@.{m~^*j+*J:je-bOn;d{ ;N{N;E$HJ+E@Z);-j*:o;Zk-6jj*:*%(Z:*/. b "�"��������$iBE++o;l+h:n:*Knk/k~mz_ D7HLJ)Z KRDm7U{{zm:*yN*J*4wDV;"-e?J?~Ld$Z$P$Q * b*>)';m#cw)k*Hd"+j8V**"���������$)AE1+;n3h:+nk~Zw;[E" !D$oJl;Z3(DE *7>:B97~knN2JQ***/.*n;, L9.o>Dj6%)D"&"***j*i***"**(" T ":.I$& "�������� h!D(h!DE !E!hL!(!DL!E*IAT9Kj?_7^:nk,7^Dn7E+n3ZPJkML+e3\Xi>(Jy**kzkHkV*9j "!(;.D$$�.^o�������� ***F*1.F!DhD)l!hhhL!hHE)%$q.+^+j3L2L#EAB *3n{PJ+.?L/l3E*)hY,3j7F!~+*InZ+*.^{{n;**/~y?ZI)}5��������+:~?k~?o~/k.FT!n;z*N;j!(d9(H T)p9^ \+Z3LW)#zj7n7JID/Nl)43$ZTQ.+=3-=$+>{7y>zk_7-Z:yN+F0*9g?{ETo ${��������JZn?o?_{~?n*l:h1LLD+z+F:N:j-AQTi(M5{^3EiLJLD5/+.n;zK+L+N:DT)j*mQgn{L9~u;:n9{ijj'E.).*jy>{o9D 3H��������()HI"!!);.=k?}}{o{_/=z+.+j:h!n;D�T .5{n @9]&)DDV-%NHIX l^EiKQJ J).3^N&n{zji;j:^+&(j*&n n&2H ��������45�^a***:(*j=>~/?/w?{/]LL LHE!,)@;>;k:*9JD Zs<1K=S o3\+N/nn?%!$�B ^5&:&n*_7 & 6j*n*Z& &T &*.8f;*B ��������H5H-))?{n;n*6mCn;z?{}+A{L3L2D#*$ED*6^z.>::z.**j+j9T:.;uJ/T?D\Z@D(*);^#h:*6"(**nyn.*"%(j&+$)&"���������JtDQ-)n7n+j#j:*+n~o>E1D3R ;NwL/nsH"*>~mx }y>{sL4n/*)j:d:N$;-/pEZ mkA0H�"e(" #)#-"**** c*;(" " Bj(j " *(j �������� !DhLAPE!PAF!h!Eh!LL1L-!JD(+w~;n;):V{. jK*L3L$WNl7ZsB Zi`u@,zJz>j>zn��*+j.*:$!A1DDD�k/Z:�������� :j**h*n:hhF)J!h!F!DL!d3d1l)h!,jJl2^PD2L1H!)M%*;Lsh)^+Mz\;L3. *!@1@.6|R h/k.i7/6kn7/n;&*j;n;n{&HZ^/��������H*]{m{o/k:;?n:(1(1j;nL(+*;N1N#N3hH)@E0/7d1DiH2Hw%:DB+l3-%H{lN1T$$n"[;npJI/{jjk-7njj"F .;.%+~zn$ {A9���������$ow}{~?o{~{;j*n:F&1`9*:n+h!$:NVB d)! 8{m*,)\D1D{hZqLn{d/+{O?L;J,0*2nQ{_{LwN`>:.+n>j+/*)*jk*Zn>** n��������$`DAQ:okz?oo{_7}7~n;j:*#)n%HR I d%A *9DQD9FyMh Dd9nLE2Jn0LZD]L9d;E ;).J>.n>*z*z "*.2" *-j;.*�!L ��������$h�E*J3*:*+o?{>?:koJ1LL$h1D7n{nwn+*2*($Ib2h.;en_d>[;]{l3N$JX( Z{w*kmj**6)V*zi*(Bd)n .*j Z ���������Th@Q-1+zn?{n;h+nJz>n{o~zLD6m/L7^s*+IDj)U3Z?ej/*kd*:.DIH{l+u{?EZ. D*RD *y>)j*ik*:*){_w5j * **:j% b !��������$Y",+E:{m;"#l3j-.{oML,Je:n+L3$Q$ MQm95J:ez7-6Ly:Z*:.)^{nWl{n{/?M!j)Z6@"H")% b5)6h" :("(")" *H*(U(% &*E j")��������DDADDhDF!d!Fl1d1NE)$A@6m?m7n+n;nVnLDn3RRoJ_L+Ts$TQ)<hCy^j/? @>.*{n+! D*$B�<::>��������!*.+*:*:w%!h!F!D!dhh:FD9N9ZFEp  9>/<*m+1 !T1Dk^rn3H+ezN;L/l3j,)`+!.{:?D�$z;/j*~j*&z{{n;,&{;d0Li8y�������� n/_o}?onzmn"j"h1N*.;o:h!F+.*&h!h:ETi(PvO;M1\LSDq%zEx*n{n gJl:B3diU([2n+}1J;*+z?o7^k;+[!.k;jY&;n;o3U o_B2��������$@ }?oo{}o;n:j"L *N!((D )dEP$ ,%@-u?oB:H DLrX8nZn;u{n/F{N?L"d*$j[1H3n7B;EIk*jij-k-6h*D9n &**:k+n&D"E^��������H)����*n>o~{~~~_kz?/;**.:*:3LL#T`T,)@ .uE{JD9-5.$(E&nL\nN/JRT)J1JrU;L{D(>~j/kz*6'+.i**8j)&(j&:&+b*" ��������D)A=dJ$;(#j*l*v;z>zoz~o>/{{(D"Hq$!Y,*%ym7+Q_j**L14l7Mo}{~;t}dn/_/LTJ�D�D*->~zk:j")zk-kjjZ Bj+%&)&����������$0Aa)Eh/kon;>n;*Cm#j*.[iL;J3^9d3.**P* ,kJyo+u/>9>;[;>+$@>u?S/?h~EjUQl D! .f_6(&^*"#V.z+Z&("(&*&)*)%"(*��������( A5*7^;l;h2j:j+L3H3JJ7L+$:N3DI)~^.z}u/kz//Lsj+f;j+ZJ*2o?~* .i$j* */* * h"*H:**(" * * F(*)R)&*&X��������@ !h!hDh!HD!H8Fh1!LDDZ-*i7owRk7m:nBHD7L3DL{m=J9j3D %R`u,87:z "ky'*jh* "*&*>;n/*jlz��������!>o;n+.k=n+N!hFL:N!hh1Jdl!*$(� ,u*y\pL)T;]DR{$;$Ls,7 T**:L;=5JRHa@:i9lT�!Vnz7{{[+zkj7;m+f0*/~;o;E LJ��������QZy~?_{~w{o>/N)F(*z#(:j; 9Dh! $) .);nvN)E1L1L+%;DiJl;]D{NJ5$!$ $Fji[+_q{T?7+kjjo>m6.*n6:Jdk+n:./J��������$Hu^w~?_{o?oz;.+j:d!+n:h:3jDId) 5w^iB9LI%H2^9n;m{{{-?L=L* D(ni�+];n#*? +>Ve*d!P*)j)f-&:ky*� !Dm��������Qu@QH"Q:z;.;~?{oz~z?k~nn;j*n:3L D!DDPhqA+-;o.Q@{f9DD!`l-$n.VD{N=m9,@ D7l n3@&U7*&-*mj,:*62).:j $+j)j)" BLP��������,1 J0);n;(3j*(j.]????z>/HDDLA*"TQ-+^)$:o7.:,BL2�iD9f;n/|}+n9~M2$ lQ$IDjy~)EZ6);%-**k*>*& ")%+&;b$" ����������,mBQ*56?~?z?~k/kn*";*;#H$/N+l6]sj$�Z`*il:U;kkeQ./**Z$T'l{E/?D*U]KSDf(*n;-;*"h+(:("m~**** d8*&1j**B��������Z0$E*)k{n;;n;#l.n;6L) !^1 M2L+L3*RZJ^U!>:Ju:{>-+;I4^:%.*)j/.B!U7]!. j+�Q&(j(7T&l:($A2" "("(R(* &**Z "��������B"(" " " "("("""" &4#P"5" VH=w[g]wVQTQlg& % %I Pbvfn;"+%|��#]w]wWZ}1K]]%IuU d7_vM T���������$U (PB(""P"BPC BP&c b 4P#" "X"%UR (\w}}Rv]v�f*I,�E)UYgm.%JR(%-T]%*w}_T_}St_U]MUDKuM_w]v ][_KU��������"w_}Vw]u}UW 4 "CP%P#QC 4sHrHGUbgMTT68 V WXu9%J1BI2Tn8jIbY&=Hp�f'UCX6H_[? W]S}w]Sww[=vuWq--Jw,vHY(a!���������7_?m_}UUMT'U4QW_uPrw}7"t]2E *BvPv[Wg-f &=kYq) -j]wQ)U{[woPU`$Uv}vUQg}]vwO]}[wUVUS_&W]WU5Jr]u]6z j��������PTB�]}~_?_~}w]w]WUUQw]7QePvA&�" -];$_(_5V % * B .Tu9"[W]v*@(-Wu=uUQ -=ew}eDUvUmUw5tSM[S[ ]_U6WW$&]��������[ h � w_w]W_Ww}}}{}o__wUW]Fd VUA R5*[dw(kU"\%v QO$MW="h,]M*h?]u}^ H Rv PBTS}_}-KQEUQUSM[T=UUTS\uKu=uD�@&��������8 2�v]wuUw]u]uUVWvWuwU" "&Hb %[.KMR}]2]SRVKpv9.Z_[u+r}w  TU�("HU]_7E[DUwQT[LwW?T7MKH5T-]EE����������X!4H�v}vuw_WwWmwuiQT]WY (*J%Yv6m (% &kI6Yu}}o5e9U]-Yu+.IRI~]|xbEW "5e(" �D245t[T[TStUEQG5T[M-HQLQE5EQL5MTH��������4$ H" (B$ "PC B 4PC 4PCPc B C H" o}o]wYw]ugUI]wTH""EBHRe=fV5"H" :� gw_}s n}*UUTsUbYWYU!Tw}}wr R@U���������B4P4 r 4 $$4 4$ p "P4C &PC T 'HC(WUt5"+}~Ub$U[ou 2J6Y"+"TYe^iVIRC:��w; R}W=Dzwumu\={wJT7]w}wZ r"��������@=rWu}u}_W]w]cC B r B]7 bMT' $ 7 C" I@�SP-mW .$Jb5"YgB"A bvYnU" ]=m+7WzPw5w=o]w_TUj_Vw]WKS]u]w]5UH F.�������� Hr=^}w}{}k]UP%QtPUPU]W #Pwu{Igc)5"5]$��_WV5%nb92jIKt]I4J;YvOVT o[}#.=w_}?W=m=m[hUU5]5UUMw]_]cR R"��������*�"Wu{w[o}w{w_w]w]w]w]W_t7U#EBH"4";|B�o%W tYb)2.HR&[>"�j�vU1$T"Vv_JHuwW[][}=UUU ]TVEQUw]/\D@n&��������:!ATgUWo}o_w_o_o_}W]w]ff'4CI%5!z$^Xw\9W9* zqfY&gR]>S6kw}o_v � ("5V" "HWTUG1TUT[M]G5TQMST2UUS][M/Qf��������!4P�m�=w]GuUt]W]{]}u{__w%D  IR%T%4w"4RYw_.TU\WU U]`H/]w]&UrWwo$ R�-) "*KSL]~5u[T=o-U{muuTSHQEUL-KUTT����������! mH]wW]w]uW]Z]gUh]d$Ib9eUnYSU! "i4V[k*W]}_"uUU]W(W]grW}Ta<wW$Ur�D-D]W=M5MOU5TUOUUQKE1UU]SU!T5DD��������C "4" ("$@" ""4PC 4PB 4 44 &P�B\HrH_w=v[gUg]WYKYA(&Yb E+YvzYv=R@ |@u�vMuW_b=V}u-U4%YuU }w_w_f* r�������� k 4 #PCBPC " "BP#P#P6P#H4R &P'rt$U%]m;}o"& BBw% *1iKk�G!Zu[gm.QTU5*-t �4"P$uswUUu][UW\[Tu\UTuUw_w_WTXo7%��������C }^}_WwuwQT 44(&Xu_CP"PU RPrBT6P4 z0 v�_R;e * . .W 9fv 0]rf.=P5bxw<_�&}UW_}_]=o5w[jWu\5MUu}}w_uEB"%�������� nWv_~wW]uUt CQbQcQUQD u_k BQT-h�( [BwP_8UU+eFIFgP{V]w3+K[[gI[ "vwwHVO_^uw]T]VSK5"]5WUWTU\+wwT/b&T"��������UTH � t_?__~?{~u]u}u}]w}kQGQw` I*[Q+TwH7Rf-bV .Uw+R(/]_J" "p(v e(!(!\#g]wPu_}[|_EUEUTSV"1KSK\5UsU6U@$F��������5 (@H")ZTUwuwmw}{~{}{ww}u7'f$ WIPR"-dwp_I-U% "` i]W=Yj]o]JIw}w}n  $RTbH]~SvtV6uSuUUUU-U%M5-5Tw]2ED@f��������Y!4 uvYW]GUGUw_|_W_W}_W$0" ""B`IU ]BiUk8?UaW5[v%U\UWU-Tv]%S||w$ R% H HR2U=TQD5mUU5=]SUQE!TMQE]D���������X!4HwH_v]tUV]u]}h[w]e$J*R9gKV % V w=W�}wWu]@UWUTu]SUwF}ut4_T/ \-i% � EQMSVUUUwQU5TUMQU5UDUEJTU]*MJQD��������4 C " " "  "( (I( 4P"""""BU'" (".I}~[o]tW[t]Q" -v %s9c}&iK$ ["y �kJUU_O$�uK]U_U%nYVU& ]w]vzKR@%���������BCX5PBT]#"PCHC# " *t " B BC r " PU*Kr[W;.Xb &dw m5ZI6Y"K*TWuWVT<V !!8u]UW]}5D_wWWuU=}wUSTW|w}}rH0(m\E��������WUWw_][_u}_W'PC cPUUuu7eUQB#HGYgJ 4@�ovWRe"]J9j]7mBBQ;bE5Y- ` W[6Kf ~Y}W}ww}_MUk_Vw}wTr\wW}%E~w�|!�������� U l{o]u]~_W]U]7 ' T b'w]#P7Pt(U @R7}$�vH7YWEDaYf9.uMt]^,4sYglVRJ%7w8g#Wu4_O5o5O]uU%(U]uTS]wM7}adF ��������x%� (H]w}ww{o}_w?_W_W_WwKW]EB"TA2%[$_(_BYeK*&")bYVh,]6Z HbHfU8Ui$&]v} `T=u?kUV[VUO5%m6TuDw]uISDd(d�������� H " HYwYU]W_]w__??_o}_5dfb& %5zR�^Uv]UW).!\r5g9(j_e7buw}wv ��Rv"�*4qU5V[O6O]TUT5t2T2U-VTSMSUWT� d�������� 8@o}]tPtQEQU]iuwuwvi "Y$bR5$( JVUrUzw_mu?mUVKUY"*&Zof-zUrE rP @UDnSUQUUTQTUDuWw}?MI4SUSUqD1EQ@���������!5@m }wYgeW[wuI]%dH*HvY/V-["4%u]oEW}=}[]"UmuUW]-TW[!7}ub_TW "Ue%)$TEULSlUT5TUMUTu]E5UQDQUE5*EUE5E!��������D4B"B "$ " #B $Pb 4 c b%b# ( uX=o]w=O[v]w]H]5H&Yg H?Xgm.Q H" :�vUUuW�]}SWuU* .X-5-$% B�R;V&��������FWUC %uBC4" 4P4B "P'&P'H4X'X'P& e3mZ=voFB & $Hq %5m!KZW|vk5m9UBt [?}'k_WUW>_]m_m[Jw=6Ku]w]w]W 0(qZ��������Hm]m7v[_WwUT 6XC T]w]b Pu]7 & 4 RR4�(��r(wTY'f F):r]UmYr H=eE *[j=<W[]W]u]7RU7h]U]UMS]{]w]rDZ5 C.���������"+x?o}u}]uPbrP"4HRU]E B C) " }"o(_ U&].V]'v,;*]w]bH_m\T .Xr(R W[w=W__z+Vu "_]WU-Tu]u]5Fft%�������� @� �U}_=}?_v?}o}]wUu]7Q+]w$ 4A%=Q{$�wHw$eX6 :*$e5"E.=/"vvv)"X%=ef]sj}_V]V=o5w=u-uRH7UUESMU\_TUdIB�������� �"%GtUuu_w}w}w]o{[,f(b�$ '4"%";bUg[_[U5U RHPb=UY&U*}&_imYoUv R�U8 UM/m[muU-UUWSMSMQMoMJUM7U-U7MQ$�D��������4Tu�_w]TG]w]H]}]}_m v e$V9M RUU]m+~}U]U=_]UI'=oKB|w%Q|xb__TTR�% H2Tsm]kSvSWeM[--WT2E6TU]WTSMD���������X WH=oWYWYjUumzu}ffK"5oXgUv)4! %j[u WwWuW>]j<WW]wUUwu=_Yu}w_wU M^4"Pe ESTEQ5[uQESUSEUTTQE)E5LSTWTST5LT���������@# 4P% 4P$" "" B# "c 4P4PB 445"$ 0V(}w=o]w]o]V[I[ BK4H${KuOrH ; zw(CU}_V@uW=tS]!R "=" H"�R=uHU��������@"WUWUTPwU6@4 " &B BH'E r C 2P' b r CP9'+Ui&%mXmT"H&d% tvU6"+-Ks]w\nYV5U%=4"U_]V@Wwo/<{}SUuUY]w]eU7|s_'m d6U��������W6_v}_m}sQB 6 T]w4H6UutPCbP4  4!5 o_ Be 6]fY*9eGLIbB[Yuw,5J Ur]u[tV|Wouv_}m7wuk Tw]uI2}uuW' sURU��������  ]l}w{w{?W]WUPB GQ4 BUFU'Y7V @(""{D(wHw["b &)"9&Hv(m.[v[w5uYww~ "U EXf]&\W ]}_|uuuW=MS%BqU2MTWW7M%f&I[��������[$" � RWu_}w{}wW]7_UUUUtU m7$5"4 9!<R_(" 9eYb[]m3IZ]fU)H+}euV"X**RW .]k�rt[ouwSW]m[VUUDU]SU7U+UuU�d ��������["8��*P]EGTUW]]u_}_o?u?u D FBV M U5A\U_]URWuUWIa$u/'5et]d-zw]f_o P�UX@0 %Tuv_W_T[t[mUUUVST2UuLKu\uMQT5D� ��������X$5 o�__w]wUwuh]wuW}_ PTAYw]*f %(]YwUSM}"UwZ^[U]]U HV9.Kzxb?WWTKR( C"%-5T5u]TDQU=T_K3LSD]uM5(UDTD���������$;TVH}v]v]gUuQGU|_wuD$*HRUm}mW5$URv?w�_oXVR]Uu_]U\eX6u{_]wrUUFTMStEUEDTGQTUGTTHRUUM2,ST5E!���������B "PB B " $$ 4$ 4 44@"P"C %P"IBH8MIRH"H[~_w[w=wSoUk-HjYe Ms9g_.$M R !<@~@%2&W_]]}WK>TDA� (u$DRJ(Z}UA%���������Bu]uUUU]_e]'BHCP# ' b &"PR B RCBUTPV-ZR oYfXr4% * &#bYe}mY5v[v[_}vnUR"Zm7}G6}]_SE_WuVSu=Vu]7Mm]u]w}WTfa_"��������r[w]_]u}]{_w]'Q7PCPCUU-#bQtUW 6P7 UR8� (vH7"E(nb*Itm+U]r)Is{oo^ IP"U/v}g}=u_]uwuw_LUd UUUS:b]]\-8~!��������"hZ]??}vwwUGU7P4 CuUu]rtUui( -5=�_(_Y&e $)"]2(JYUZe]_]Yw[o_vR)Q.=oY3[W>wuwSVWtWW]%PUUeU5M7]oK-d&Q=��������<IH"""w]WuW_wwv_~}uw]GUUQ f `%JR{DvPW"?W97;V;![v5Bst]M[2BW]uMW X]jUIR#4@ao5W[O]jSU_uS/UDuTUE2TmMu]RT!�F)"��������!( �bH]w]UQuQUu_~_}w_Ww_b d$"54%UR)v[w r|UMeYM$]25&CZ]BYv5u{w}v "@V"�UKouVqO]E-V]V=V=TUTTu\UKSUUE#T���������U!4@u"}wW__w]U])]UUw_b ER9eNYQU$ $ ^5bvX}=Wu=UUUU((F'Wrxb_E/b)j "1I_uUoUM5uWEUos]VU*UQM%Uw-UEQDB��������UQ5PuH_w5wtGtQM]?^f b*,He &Kf^U!% _|@�w}}]XeZWWTuS5v_]o|wo & TYVP�DSU-O1vQT!TDT DSTQED$MU%HQMST���������B%C "4"P4B #" #BP"B b b 4Pr t " *S" uo[w]t]u=w[h ,K2VT"T?YwAh"S(8_ C(d]uwuW]]wWH"HWUu]u]W@5UuK&���������U]W]w]W~WPUP% 4 & B4PSPG &'B6I6Y"u qU]"UE fTb(JrUI*b[/ (b[eVYRI$=|W5_]%] U[wUWu|]M]M[K]_U5}w]}SLf9^4-��������"=_{w{oWwWuW]Jb T tUwmU &QT]wUt fYU,�";"}"�_@_M 5eZv*Y>mKKtY,+T?YuoR  v_ru8.}__=w[V__UuSIu]W-S/wWw7u$'��������AU$ uww}v}w}]w]U cYGUuUCU"UCT 4"!{$�wP7 ' &H"Y+Tu8}-W]IvwYW}fj;$W%+%v.}g�[OZT=}]K]vEP#u]5TUUuOs"D@&-�������� W]}_u}~_w}v_wUWYw]f$O*B*"9!,"oHw9 f;o%{*-o;E*=OyRWs{wv 4BXeTe$Y"D}5}O_}5}Uv5MUwBS]#T%ESTWUWES�` @��������7!)@W�]vQv]GwUw|u}_]u}]]""fTKRKRv=w4$UmKSUU+]IUH)"T=w]B)^V_?_WvX" RU� suwSLUWF=u5KmSMSUQ$QTQ]7TSM]D�@�������� 5/H?]}u}}}?v]i]g]uU&BReYeUv-5A Hr97o4WUWr .UWWST �"]7zx28EW$;2 %! oTO=U5WUDQdUT[U5TSMD%TS4UKTDQ,��������[!8`m }n]vUGQe]wwQte Yd(*CV]mvY&U" R+uZBw�[WuWwIUY"vm]wU6XW]Rq]w_w& j+%�@@QT2TSuUTD!'d BQtEJ%E%DUTQU55T5M��������cc65-2.18/testcode/lib/apple2/werner.hgr������������������������������������������������������������0000664�0000000�0000000�00000017770�13473601511�0017770�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������O}];xsgC�8~pn];p��������^o=?0/o0 /?/ /o?o];|w�`�H?~1w~816PATTx|c?w#wn]yC�~sxN;q~��������x~ggsp�0~?~pnaCgG;z?OÝ€U€Ý€Ý€yOO7w{co?7�0~}w~s=n{��������{o{1y`y~?~s|x;1`gg?PwygÝ€U€Ý€Ý€qO{?>x;|pAKqo|ps��������|@|~pG_7x~_q|~s��|w€.€€:€?};wpsoap?a];@��������#~?];w�~w@8�� ~pn~w€£€Á€â€AAO?~w~n];�s`��|gx wc|��������?~?~xOow?~C�0~xl]cGoG;~?ð€™€€€}_7wsGo_l=~}?~{=ls��������sgA}s<@s|?|9ycwp@OXgyo€™€ð€ð€Ggyp|_Aw�x?c?GxOyy���������@}|ys?|~~;xy?~sn]q�€*€�€¢€v~=?p0o0 0 0`0o<~|wnqsO?Fcp?S;w��������?`|?_;wnHg`x�>l]|�€*€�€¢€||~w|P;�G?`�0xOqMnG?x��������|cOw??|x?� ~�\;gOO{~>��������}_?7vwGo_o ]?~}~y9lw��������ww~agy||roh?@?~\o��������~q=`y_Co0~cN?|_s?|��������y}}xw |~?||<|yO];G��������wu~o=}?//./?/?/?/wy|~n]qs�|?gp?3w~~���������x?];wn]Hoxx�~\{?x��������Cac?~|g?x?�����p�0xq ]~x��������Oy?^w?~?|?~` ~�;wns}>~��������}_?fvgo__K{~y||{|w��������gsxe~g{|~%||/|^o��������x?|=psO^cG|gM~g��������{y~o�||?x� |yO;w~��������wu~o=}?//-??/?/?/{sy?~];qq>x~? n`?sn|��������O|?:wn];HOCx`~;wp��������x|}op���?�x�pp?~s{|q��������gs?|\w~xC ~{'wnm?w||��������}_lrpOO?'w@{y~{|w��������Oy?Nqd~gs8~�zyOp@Oo��������C=xG<~yxg_K~G��������s{C_;`x}pg��||Own=x��������.oa?/ +!80808 |gs?_;wpqOc~ |`??h}?p��������o?pvn];HCx?~w~a��������~?|?~}yoa��|p`|cwOx{��������wwyw|q_y ~{on]o?w}y��������}_mz__wf~~{cCCsxw��������|0Oa`vCgg?O~s_C`oO��������|}p@?p|}pg?GOpq��������wsg;7pyypg��x?|o];a��������w]o=}?//'/?/?/?/{g??wnqyg~ x@?\{`���������`gal];wH?~C@?|?|Nn}}C��������Gqxy{OC��~OC;qaycn_s��������sgs9w}qO|_ ~yO];gfy{��������}_}G?~~oa}xsxAwxw��������?~?~G�0ngoYN~Gw|xg_��������A?yxw`=x|cgG�|��������ggswnxy{aG�xO~^;w��������w]o=}?////?/?/?/w?N?wn]qxw?|�pH?C;C��������x`?wCY;wn|C?�y?|N]y��������sgss{_��0~1wrCsg|g��������{og3wyso?~; ~}_;wwn{��������yOFs|?~?~>~_Sxsw@wyw��������|s0?~cOYM}cg?>��w_��������x >~s~oA;x~Go!~~g����������Ooyo]xqsA�`c~?<wn |��������cc65-2.18/testcode/lib/apple2/werner.s��������������������������������������������������������������0000664�0000000�0000000�00000000044�13473601511�0017434�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������.segment "HGR" .incbin "werner.hgr" ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/apple2/winston.hgr�����������������������������������������������������������0000664�0000000�0000000�00000017770�13473601511�0020167�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������UDQ*U *U*w"@Uju; €(U*U*U*U*U*U*Uj]+u~/(Ej/U€U/U U*U*w~n?@*€@(Qzx?U8€€€€ ]{��������UQ*E*U* @:w~?U*@(U*U*U*U*U*U*Un]+w~{ Ez_z/@(Uj}{W u~/U*U*U*U~?P;Ut{w*U>€€€€€€€��������*D(U*U*U*U{ T{W*E€U*U*U*U*U*U*U*U+}€D(€|"}{UW{woU*U*U*wn€€€@?*@~_z?*E €€€€€€€€��������U"UQ*U*U*] U{w"D€*U*w*U*U*U*Uj_+_€@€||#|}/]z_~?U+U*U*€€€€€€€€z€€(U"}w_*U*\€€€€€€€€€��������"DU*U*U*]; U*E€|o]*u*U*U*U*un_{"E~/|u]>U~w];U*U*U.€€€€€€€€€€z*U(8€€€€€€€€€€��������"TU*U*Uj}(U:.E€|]*U*U*U*U*wn]"+|?w_>Wn_+_;U*U;€€€€€€€€€€€€€T{?@p€€€€€€€€€€��������"U*U*Un} € U?*D€P?U*U*U*U:#P#o_ €~]*?};U*U:€€€€€€€€€€€€€€€€€@Q*x€€€€€€€€€€€��������"D(U*U:Wj? UW*D€`w*U*U*U:w+U~/@zUW(€@~*U*U*} €€€€€€€€€€€€€€€€€ @€€|?€€€€€€€€€€€��������€€€€€€€€€€U*€€*T*}{~]€€@*TQ"D€€€€€"U*U*uUPUz]:_?nU+U €*u.]+U"D(Q*u~+U~€P€€€(t?Q{+W0€€€€€€*U��������€€€€€€€€€T(U€€U*u~o_?wnU€€€ D*U"€€*U*U*U.U@ Pt;€D*U;u € uo];U"€€€ Un?€*€hu;_*A€€€€€€€€€��������€€€€€€"T*U€(U*un{]+W.]*€€€ U(U*E€€€@("U(U*W*U €€€€€h€€(Uj{w U*u];U *TP*Uj?€€€€€€@€€ D€@zo]T`€€€€€€€€��������€€€€ @(Q"U*]€€*U:wn_;W.U+€€€:E(Q*D(Q"U*U*n];€€€8z{Ghz~?W*U+}oU*U*U*TP:u.€€€€€€€€T€€€€€h+. €€€€€€€€€��������€€€€€D€"U*€@(U;u?.U:€€xW*Q*E*D(*U*U?w~;@Ux]{+u*]*]*U*U*D P"€€€€€€€€€€€T.}_+€€€€€€€€€€€€€��������€€€€ €€Q*U*€PU:wn]:U€x*U*E"T(U*U*U+u~?~h_;~_*u*U*U*U*u*U*U(U€€€€€€€€€€€€€ U:u/€€€€8€€€€€€€€€€€��������€€€€€@*U*Uj€@*]:on]*€€ }*U*E€"D(U:un];w }A~;Wn]zw*€P*U:W(U"U(€€€€€€€€€€€€€€€€€€€€€€p€€€€€€€€€€€��������€€€€ E*U*Un€€h]{{~]*€€@.U*U€"T*U*wj*U~€U?€~{ }{W*€€€P*U "T*€€€€€€€€€€€€€€€€€€€€€€z€€€€€€€€€€€€��������D€€ D(U*E*U*U€€"U:/U€€ U*U*U*U"U*"U*u/U/(W.}}?€Uz+U"U*U*]?€*€€ }b+U8€€€€€€Tn��������D€ T*D*U*€Pj]U € U*U*U U*U*U*U;W*}?n(w*h €j_ Uz"Pz+U"U U*U{?@.](}U(>€€€€€€€€��������@ D*U*U*Uj€Un](€T*U*U*Q*E*U*U*U*}_€P*€€u+U €€@:}Wn}{+U*U**U*€€€€€@.h€@U}/E*q€€€€€€€€��������T"T*U*U*u~€U~/~U*€\*U*U*U*U*U*U*w*}_€€ |+?WzW~/]{W*U*j_z€€€€€€€€(€€€€€uWw"Q€€€€€€€€€��������€€*T*U*U*w.€ Uj~_+€|?W*U*U*U*U*U+Wn€*/|j?U>\}W*U*U*U€€€€€€€€€€€8_ €€€€€€€€€€€��������€€€P*U*U:w €(Uj+€pW*U**U*U*}w€} }UwjUW*}w.U*Un€€€€€€€€€€€€€P.u~_€€€|€€€€€€€€€€€��������€€€D(U*U:} €(u~] €\~nU*U*U*Uj}_P?}}_€(Wj/U.U*U*€€€€€€€€€€€€€€€€€€€"T €~€€€€€€€€€€€��������"U*U*]:/€€U_+€h_*Q*U*Uj}/U:€j_€?QW:€€€€U*W*U*u€€€€€€€€€€€€€€€€€€€€€€€/€€€€€€€€€€€€��������€€€€€€€D€€T*€€@ U:wn{o};U€€€€U@€€€€€€€€€Q*U*U*U @*Uh]/j];Wn];UnU €*U+U*€€€@*U;w.U{€P €€@~An?w*Ut€€€€€€ U��������€€€€€€€€€*U€€U*U*w~;w*];W€€€€Q*T€€€€ (U*U*U*UPzjU*P*€t?(U*UP U?w.€€€€ U*wn_;/€€zwo?w€€€€€€€€€��������€€€€€€*U€ U*]:wn{w*U*U €€€"D €€€€*€€ U*]:U €€€€€:W €€€€(wjU*U*U?W*U"€T(Uj€€€€€€€TP:@h]{h;E€€ €€€€€€€€€��������€€€€€"DU*U€€"U*];~}?.]*U*€€."T(€€"DP*U*]+u*€€P8~}{w/U*u+];U*U*U€P*U€€€€€€€€@€€€€€P;wU*@ €€€€€€€€€€��������€€€€€DU*€€"Un]o]:U*€€xW*U( €€ T(U*U*U:.€*@j8~/Un*U*(];U*U*U*D €€€€€€€€€€€P*u~} €€€€€€€€€€€€€€��������€€€€€ *U*€P*Uj]{_:W*€€`_*D€€*T*U*U*U;j(wn:n];wn]:W*U+@"_*U*U*U*U€€€€€€€€€€€€€€€T*Q€€€€€(€€€€€€€€€€€��������€€€€€€*D(U*€@*Uj].;u*€€€*U*U €€€€"U*U+U*U; un~n:wo_;Uj]*€@*U* T"€€€€€€€€€€€€€€€€€€€€€€|€€€€€€€€€€€��������€€€€€"E*U:U€€€un_?wn}wn;U*€€€P*U*€€*U*U;U Uz€T€z*UUn_?j]*€€€€€U*DP*€€€€€€€€€€€€€€€€€€€€€€€:€€€€€€€€€€€€��������U"@€*U*U*U*U@(U~/"(U*U*U*U*U*U*U*}?u~? ]u_W(u~/UU*U*u~?€(€€` /U8€€€€€@{��������Q"@€U*T U*U;€Tz"€U*U*U*E*U*U*U~]*{*+uo_(WTk]{W8q~/UU*U Un€P?U U*€€€€€€€€��������"U**U*U*Uz€Tz*€T*U*U*U*U*U U*U*€€€€}  |U~z.U*U*U*uo?€€€€€@zh?u/*p€€€€€€€€€��������"D Q*U*U*U? UW+€|*U*U*U*U*U*Uj};wTz/|]~w~?w~]+U*U*Uz€€€€€€€€(Q"@*_~U*Qb€€€€€€€€€��������€ @ U*U*Uj] U:+€|_*U*U*U*U*W*]z_+/|w]>U?_;U*U*u€€€€€€€€€€€`}"@€€€€€€€€€€€€�������� @Q*U*uj} €hU?.T€p_*U*U*U*U:|#}?_(q*_;U*U{€€€€€€€€€€€€€€(U"E€€ U€€€€€€€€€€€€��������"@*]:Uj}€`uw*€}j?W*U*U*U:wT"?}_ € /T:U*U €€€€€€€€€€€€€€€€€€D*U@€€€€€€€€€€€��������"D(U*]:u/ T~.€j*U*U*U{?wn/€*€|jG~]8€€€@~]*Uj]€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€��������€€€€€€€€€@*€€*un}:o€€€ U Q"€@( U*U*unU @(U*w}+w~U*woU+U €*unU+U(€"€€*Un?€ €€P:]+U€|€€€€€€€T��������€€€€€€€€D*U € U*unn];un]€€€"D*€D€€ €€*U*U:u*U @* U*€ €hU];w Q"u;U €"D€*Uj}?wk€€€€€zo] @€€€€€€€€€��������€€€€€€Q"U*U€(U*w~?+W*U+€€€*UQ*€ D  T*U*w.U+€€€€€j] €€€€€(}?w*U;uoU*U*"D€*U~€€€€€€€T@j]{~jk8€€€€€€€€€��������€€€€€@P*E*€€(U:u?w*U+€€:E*U*  D *T*U*wn_;€`}hW~/W*}+toU"U*U"D P*U€€€€€€€€€€€T*}U;T€ @€€€€€€€€€€��������€€€€€T€Q*U*€@(Uzwwn]+U€€x_*U*€@U*U*U*uo;€(U{h?]{w]+U*T*un]*u*U"E**€€€€€€€€€€€€@jU+€€€€€€€€€€€€€€��������€€€€€*Uj€P(U:u~wn]+€€`*U"T"D*U*W*]:u~?(]{Aj?~}{wn]*w*€ w*U*U*U*E*U€€€€€€€€€€€€€€€€€€€€€@ €€€€€€€€€€€€��������€€€€€D*U*Ej€@*U{n}o]*€€*Q*U*E€"D*U*W*]*uo ]?A~h}_;w*€€€n]+U E*€€€€€€€€€€€€€€€€€€€€€€ }€€€€€€€€€€€€��������€€€€"U(U*unU€€€U?]{oU;E€t*U+"D*U*U~U*U~€P €(}@U{{W €€€€€T*U"T*€€€€€€€€€€€€€€€€€€€€€€€~€€€€€€€€€€€€��������T€€€@**T*U*U€*U{/E  T*U*E*U*D(U"U:U{w/Q~_~*U?WTz_+U"U "Uz?€jU€€`/|_*>€€€€€€€ ��������D €€D U*U*Un€P~}{U €T*U*U**T*U*U*U*}?w~€*@*u€€u+U~WzU{;U*U*U"U*€€P.€€uU(A€€€€€€€€��������@("€*U*U*Uj€un}w~_ €\*U*U*U*T*U*U*U*}~_€€€€€}_€p€€ u;W~_z~]:U*U*U*Uk€€€€€€€z€uu}/E €€€€€€€€€��������D€€D**U*U>€€U~n_*€|+U*]*U*T*U*U:unU_€Pt??w~U~U:U*U*U*U:€€€€€€€€€€D:w*"U`€€€€€€€€€��������€€€€T*U*U*u€(Uj*€|W*U*U*U*U*]*Un_{ j tU?Wn]{/]W*U*U*U€€€€€€€€€€€€ uoU€€@€€€€€€€€€€��������€€€T*U*U*u€(Un}_*€@w.U**U*U*}P~@?w*}*U*U.€€€€€€€€€€€€€€€€€€€€@( €€€€€€€€€€€��������€€€€D*UjU(/€ U~] €€Ujn]**U*U*}w.U P~€?q?U€€t*U*T*U€€€€€€€€€€€€€€€€€€€€€€p€€€€€€€€€€€��������UQ"U*u*U{/(z*€\z_+U*U*U*]]*?€h€P~`~?8€€€€€8W*U*€€€€€€€€€€€€€€€€€€€€€€€}€€€€€€€€€€€€��������€€€€€€€€€€"€€T*U{wn;wn];U€€€€€Q"E€€@€€€€(U*U*U*U €€U*UtoU€€€U+U.U"€(Q;W* €€€€€U:w~}{€T €€P_h}?W*€t€€€€€€€€��������€€€€€€€@€Q"U€ U*U;wo];U*U+U €€€€"D€€€€€€( U*U*U €€€€€(€€€*unU*U*] U*U;w.U"€€@ U*w~_€€€€€€ ;n_+U €€€€€€€€€€��������€€€€€€"TQ*U€(TjU;wn]?w*U*U*€€€*"@*€€€"€Q*U*]+U €€€€€:w*€(€€zw/U*u.U;U*U*T*U;€€€€€€€t€€U**wj}+€€€€€€€€€€��������€€€€€€@€Q*€€"UjU{nU+U*€€xU"E**D€€ **U*Uzw.€€u~xw(wn}?w.U*t(U;U*U*U€€€€€€€€€€€€P*ww*€€P€€€€€€€€€€��������€€€€€€ DU*€€TjU~]+U*€€x]*U €€"E*U*U*U;/@:Pn(o};Un]{w*U*T U*U*U*U"E€€€€€€€€€€€€€ U*];W€€€€`€€€€€€€€€€��������€€€€€€"TQ*€@ Uj}{o];W*€€€_*U€€€"U*U*U*Uk u~Az/U:wn]+W*]*€€U*D*U*U"€€€€€€€€€€€€€€€€€€€€€€@€€€€€€€€€€€��������€€€€€(T*A:€€ Uj}/wo~];W*€€*@*U*€€€"U*U*E(U{€u>€~o] u~};WjU*€€€ w*@€Q*€€€€€€€€€€€€€€€€€€€€€€ _€€€€€€€€€€€€��������€€€€U*U*U;E€Tn}{Ujwn}+U*€U+U* €€"D*U:w*Qzw€P €€T€P/Tj}{w*U"p€€€€€@*U€P €€€€€€€€€€€€€€€€€€€€€€€z€€€€€€€€€€€€��������cc65-2.18/testcode/lib/arg-test.c�������������������������������������������������������������������0000664�0000000�0000000�00000000432�13473601511�0016456�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <stdio.h> #include <stdlib.h> int main (int argc, char* argv[]) { int I; printf ("argc: %d\n", argc); for (I = 0; I < argc; ++I) { printf ("argv[%2d]: \"%s\"\n", I, argv[I]); } printf ("\n"); getchar (); return EXIT_SUCCESS; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/atari/�����������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015665�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/atari/asm-xex.s��������������������������������������������������������������0000664�0000000�0000000�00000001633�13473601511�0017436�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; Sample using ATARI file format, by "atari-xex.cfg" linker configuration. ; ; This is a very simple example, shows a message to the screen, waits and ; returns to DOS. ; ; Compile with: ; cl65 -tatari -Catari-xex.cfg asm-xex.s -o prog.xex .include "atari.inc" ; Default RUNAD is "start", export that: .export start ; Write string to screen .proc puts sta ICBAL stx ICBAH lda #PUTREC sta ICCOM ldx #$FF stx ICBLL inx stx ICBLH jsr CIOV rts .endproc ; Write a message and exit .proc start lda #<msg ldx #>msg jsr puts ; Delay before returning to DOS lda #0 tax loop: inx cpx #$FF adc #0 bcc loop rts .endproc msg: .byte "Hello world", ATEOL �����������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/atari/charmapping.c����������������������������������������������������������0000664�0000000�0000000�00000003046�13473601511�0020325�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** testprogram for includes "atari_screen_charmap.h" and "atari_atascii_charmap.h" ** ** 19-Aug-2016, Christian Krueger */ #include <conio.h> #include <atari.h> #include <peekpoke.h> #include <string.h> char pcDefaultMappingString[] = "Hello Atari!"; #include <atari_screen_charmap.h> char pcScreenMappingString[] = "Hello Atari!"; #include <atari_atascii_charmap.h> char pcAtasciiMappingString[] = "Hello Atari!"; /* THIS WON'T work due to string merging/collection problems! char* pcDefaultMappingString = "Hello Atari!"; #include <atari_screen_charmap.h> char* pcScreenMappingString = "Hello Atari!"; #include <atari_atascii_charmap.h> char* pcAtasciiMappingString = "Hello Atari!"; */ int main(void) { static unsigned char expectedAtasciiValues[] = { 40,101,108,108,111,0,33,116,97,114,105,1}; int returnValue = 0; unsigned char* screen = (unsigned char*) PEEKW(88); // check default (=atascii) clrscr(); cputs(pcDefaultMappingString); returnValue |= memcmp(screen, expectedAtasciiValues, sizeof(expectedAtasciiValues)); clrscr(); memcpy(screen, pcScreenMappingString, sizeof(expectedAtasciiValues)); returnValue |= memcmp(screen, expectedAtasciiValues, sizeof(expectedAtasciiValues)); clrscr(); cputs(pcAtasciiMappingString); returnValue |= memcmp(screen, expectedAtasciiValues, sizeof(expectedAtasciiValues)); clrscr(); if (returnValue) cputs("Test FAILED!"); else cputs("Test passed."); cputs("\n\rHit any key to exit..."); cgetc(); return returnValue; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/atari/defdev.c���������������������������������������������������������������0000664�0000000�0000000�00000000477�13473601511�0017276�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** testprogram printing the default device ** ** 26-Nov-2009, Christian Groessler */ #include <stdio.h> #include <conio.h> #include <atari.h> #include <cc65.h> extern char _defdev[]; int main(void) { printf("default device: %s\n", _defdev); if (doesclrscrafterexit()) cgetc(); return 0; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/atari/displaylist.c����������������������������������������������������������0000664�0000000�0000000�00000002307�13473601511�0020374�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** test program for ANTIC instructions as defined in "_antic.h" ** ** 23-Feb-2017, Christian Krueger */ #include <conio.h> #include <atari.h> // code is only for testing purposes, as screen and display list are not aligned, // and jumps not set! unsigned char DummyScreen[400]; void DisplayList = { DL_BLK1, DL_BLK2, DL_BLK3, DL_BLK4, DL_BLK5, DL_BLK6, DL_BLK7, DL_DLI(DL_BLK8), DL_LMS(DL_CHR40x8x1), DummyScreen, DL_HSCROL(DL_CHR40x10x1), DL_VSCROL(DL_CHR40x8x4), DL_CHR40x16x4, DL_LMS(DL_HSCROL(DL_VSCROL(DL_DLI(DL_CHR20x8x2)))), DummyScreen+120, DL_CHR20x16x2, DL_MAP40x8x4, DL_MAP80x4x2, DL_MAP80x4x4, DL_MAP160x2x2, DL_MAP160x1x2, DL_MAP160x2x4, DL_MAP160x1x4, DL_MAP320x1x1, DL_JVB, DL_JMP }; /* We know that the sizeof expression is constant; don't tell us. */ #pragma warn (const-comparison, off) int main(void) { int returnValue = (sizeof DisplayList != 28); // assure only one byte per instruction! clrscr(); if (returnValue) cputs("Test FAILED!"); else cputs("Test passed."); cputs("\n\rHit any key to exit..."); cgetc(); return returnValue; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/atari/mem.c������������������������������������������������������������������0000664�0000000�0000000�00000002617�13473601511�0016615�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** show some memory stuff ** ** 04-Aug-2004, Christian Groessler */ #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <atari.h> #include <cc65.h> extern int getsp(void); /* comes from ../getsp.s */ unsigned char data = 0x12; /* data variable */ unsigned int *APPMHI = (unsigned int *)14; /* 14,15 */ unsigned char *RAMTOP = (unsigned char *)106; /* in pages */ unsigned int *LOMEM = (unsigned int *)128; /* used by BASIC */ unsigned int *MEMTOP = (unsigned int *)741; unsigned int *MEMLO = (unsigned int *)743; void *allocmem; int main(void) { allocmem = malloc(257); clrscr(); printf(" RAMTOP = %02X (%u) - $%04X (%u)\n", *RAMTOP, *RAMTOP, *RAMTOP * 256, *RAMTOP * 256); printf(" APPMHI = $%04X (%u)\n", *APPMHI, *APPMHI); printf(" LOMEM = $%04X (%u) <BASIC only>\n", *LOMEM, *LOMEM); printf(" MEMTOP = $%04X (%u)\n", *MEMTOP, *MEMTOP); printf(" MEMLO = $%04X (%u)\n", *MEMLO, *MEMLO); printf(" ----------------------\n"); printf(" main: $%04X (code)\n", &main); printf(" data: $%04X (data)\n", &data); printf(" _dos_type: $%04X (bss)\n", &_dos_type); printf(" allocmem: $%04X (dyn. data)\n", allocmem); printf(" sp: $%04X (stack ptr)\n", getsp()); if (allocmem) free(allocmem); if (doesclrscrafterexit()) cgetc(); return(0); } �����������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/atari/multi-xex.cfg����������������������������������������������������������0000664�0000000�0000000�00000002346�13473601511�0020307�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������FEATURES { STARTADDRESS: default = $2E00; } MEMORY { ZP: file = "", define = yes, start = $0082, size = $007E; # First memory segment in file, show message LOADER: file = %O, start = $680, size = 128; # First memory segment in file, load over COLOR registers: COLOR: file = %O, start = $2C4, size = 5; # Second memory segment, load at page 6: PAGE6: file = %O, start = $600, size = 128; # Third memory segment in file, load over SDLST register: SDLST: file = %O, start = $230, size = 2; # Main segment, load at "STARTADDRESS" MAIN: file = %O, start = %S, size = $BC20 - %S; } FILES { %O: format = atari; } FORMATS { atari: runad = start, initad = LOADER: show_load; } SEGMENTS { ZEROPAGE: load = ZP, type = zp, optional = yes; # Place segments in memory areas: LOADER: load = LOADER, type = rw; COLOR: load = COLOR, type = rw; PAGE6: load = PAGE6, type = rw; SDLST: load = SDLST, type = rw; CODE: load = MAIN, type = rw; RODATA: load = MAIN, type = ro optional = yes; DATA: load = MAIN, type = rw optional = yes; BSS: load = MAIN, type = bss, optional = yes, define = yes; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/atari/multi-xex.s������������������������������������������������������������0000664�0000000�0000000�00000004054�13473601511�0020010�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; Multiple segment ATARI file format sample, using custom linker script. ; ; This sample defines a custom display-list screen with no code, writing all ; memory areas directly. ; ; See the linker script (multi-xex.cfg) for the definition of memory areas and ; segments. ; ; Compile with: ; cl65 -tatari -Cmulti-xex.cfg multi-xex.s -o prog.xex .include "atari.inc" .macpack atari ; Default RUNAD is "start", export that: .export start, show_load ; Loader .segment "LOADER" show_load: ldx #0 ; channel 0 lda #<msg_load sta ICBAL,x ; address lda #>msg_load sta ICBAH,x lda #$FF sta ICBLL,x ; length sta ICBLH,x lda #PUTREC sta ICCOM,x jmp CIOV msg_load: .byte "Loading....", ATEOL ; We load color values directly into registers .segment "COLOR" .byte $16 ; COLOR0 .byte $46 ; COLOR1 .byte $00 ; COLOR2 .byte $6A ; COLOR3 .byte $82 ; COLOR4 ; We load our display list over page 6 .segment "PAGE6" display_list: .byte DL_BLK8 .byte DL_BLK8 .byte DL_BLK8 .byte DL_BLK8 .byte DL_BLK8 .byte DL_BLK8 .byte DL_CHR20x8x2 | DL_LMS .word screen_memory .byte DL_CHR40x8x1 .byte DL_JVB .word display_list screen_memory: ; first text line: 20 bytes scrcode " HeLlO wOrLd! " ; second text line, 40 bytes .byte 0, 0, 0, 0, 0, 0, 0, 0,70,71,70,71,70,71,70,71,70,71,70,71 .byte 70,71,70,71,70,71,70,71,70,71,70,71, 0, 0, 0, 0, 0, 0, 0, 0 ; We write directly to the display list pointer .segment "SDLST" .word display_list ; And we load our main program .code .proc start ; Jump forever jmp start .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/atari/multi.xex��������������������������������������������������������������0000664�0000000�0000000�00000000235�13473601511�0017545�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ÿÿ€§¢�©œD©E©ÿHI© BLVäLoading....›âã€ÄÈF�j‚�HppppppF A�����(e,l/�w/r,d������������FGFGFGFGFGFGFGFGFGFGFGFG��������01��..L�.àá�.�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/atari/ostype.c���������������������������������������������������������������0000664�0000000�0000000�00000002251�13473601511�0017354�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** testprogram for get_ostype() and get_tv() functions ** ** 09-Jul-2004, chris@groessler.org */ #include <stdio.h> #include <atari.h> int main(void) { unsigned int t, v; unsigned char palntsc; unsigned char *rev; unsigned char minor; unsigned char c; t = get_ostype(); /* get computer type */ v = get_tv(); /* get tv system */ palntsc = (v == AT_PAL); minor = (t & AT_OS_TYPE_MINOR) >> 5; switch(t & AT_OS_TYPE_MAIN) { case AT_OS_UNKNOWN: default: printf("unknown system type !!\n"); break; case AT_OS_400800: if (minor == 1) rev = "A"; else rev = "B"; printf("it's a 400/800, %s, Rev. %s\n",palntsc ? "PAL" : "NTSC",rev); break; case AT_OS_1200XL: if (minor == 1) rev = "10"; else rev = "11"; printf("it's a 1200XL, %s, Rev. %s\n",palntsc ? "PAL" : "NTSC",rev); break; case AT_OS_XLXE: printf("is'a a XL/XE, %s, Rev. %d\n",palntsc ? "PAL" : "NTSC",minor); break; } printf("hit <RETURN> to continue...\n"); c = getchar(); return 0; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/atari/scrcode.s��������������������������������������������������������������0000664�0000000�0000000�00000002136�13473601511�0017475�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; Christian Groessler, 30-Aug-2005 ; ; scrcode macro test ; ; compile with ; ca65 -I../../../asminc -tatari -o scrcode.o scrcode.s ; ld65 -tatari -o scrcode.com scrcode.o .import __CODE_LOAD__, __BSS_LOAD__ .include "atari.inc" .macpack atari .code rts ; SpartaDOS workaround ; entry point lda #0 tay tax ; display dispdata disp: lda dispdata,x sta (SAVMSC),y inx iny cpx #disp_len bne disp ; wait for key press key: lda CH cmp #255 beq key rts .data dispdata: scrcode "fooBa", 'r', $66, 3+4 disp_len = * - dispdata .segment "AUTOSTRT" .word $02E0 .word $02E1 .word __CODE_LOAD__+1 .segment "EXEHDR" .word $FFFF .word __CODE_LOAD__ .word __BSS_LOAD__ - 1 .end ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/atari/sys.c������������������������������������������������������������������0000664�0000000�0000000�00000001327�13473601511�0016652�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** testprogram for _sys() function on Atari ** ** 17-Sep-2013, chris@groessler.org ** ** uses PUTCHR IOCB function to display a string */ #include <atari.h> #include <6502.h> #include <conio.h> static struct regs regs; static struct __iocb *iocb = &IOCB; /* use IOCB #0 */ static char message[] = "I'm the sys test text\n"; int main(void) { /* setup IOCB for CIO call */ iocb->buffer = message; iocb->buflen = sizeof(message) - 1; iocb->command = IOCB_PUTCHR; /* setup input registers */ regs.x = 0; /* IOCB #0 */ regs.pc = 0xe456; /* CIOV */ /* call CIO */ _sys(®s); if (regs.y != 1) cprintf("CIO error 0x%02\r\n", regs.y); cgetc(); return 0; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/atari5200/�������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0016174�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/atari5200/hello.c������������������������������������������������������������0000664�0000000�0000000�00000005451�13473601511�0017450�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** Fancy hello world program using cc65. ** ** Ullrich von Bassewitz (ullrich@von-bassewitz.de) ** ** TEST version for atari5200 conio, using all four colors */ #include <stdlib.h> #include <string.h> #include <conio.h> #include <joystick.h> /*****************************************************************************/ /* Data */ /*****************************************************************************/ static const char Text [] = "Hello world!"; static unsigned char colors[] = { COLOR_WHITE, COLOR_GREEN, COLOR_RED, COLOR_BLACK }; /*****************************************************************************/ /* Code */ /*****************************************************************************/ int main (void) { unsigned char XSize, YSize; unsigned char PosY; unsigned char i = 0; /* Set screen colors */ (void) textcolor (COLOR_WHITE); (void) bordercolor (COLOR_BLACK); (void) bgcolor (COLOR_BLACK); /* Clear the screen, put cursor in upper left corner */ clrscr (); /* Ask for the screen size */ screensize (&XSize, &YSize); /* Install joystick driver */ joy_install (joy_static_stddrv); while (1) { /* Draw a border around the screen */ /* Top line */ cputc (CH_ULCORNER); chline (XSize - 2); cputc (CH_URCORNER); /* Vertical line, left side */ cvlinexy (0, 1, YSize - 2); /* Bottom line */ cputc (CH_LLCORNER); chline (XSize - 2); cputc (CH_LRCORNER); /* Vertical line, right side */ cvlinexy (XSize - 1, 1, YSize - 2); /* Write the greeting in the mid of the screen */ gotoxy ((XSize - strlen (Text)) / 2, YSize / 2); cprintf ("%s", Text); PosY = wherey (); textcolor (colors[i]); /* switch to color #0 */ cputsxy(3, ++PosY, "COLOR 0"); textcolor ((colors[i] + 1) & 3); /* switch to color #1 */ cputsxy(3, ++PosY, "COLOR 1"); textcolor ((colors[i] + 2) & 3); /* switch to color #2 */ cputsxy(3, ++PosY, "COLOR 2"); textcolor ((colors[i] + 3) & 3); /* switch to color #3 */ /* color #3 is the background color. So written text isn't visible. */ cputsxy(3, ++PosY, "COLOR 3"); /* Wait for the user to press and release a button */ while (!joy_read (JOY_1)) ; while (joy_read (JOY_1)) ; i = (i + 1) & 3; /* Change colors */ textcolor (colors[i]); bgcolor ((colors[i] + 3) & 3); /* Clear the screen again */ clrscr (); } /* not reached */ joy_uninstall (); /* Done */ return EXIT_SUCCESS; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/atoi-test.c������������������������������������������������������������������0000664�0000000�0000000�00000001620�13473601511�0016641�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* A small test for atoi. Assumes twos complement */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <limits.h> #include <errno.h> #define outfile stderr static unsigned int Failures = 0; static void CheckAtoi (const char* Str, int Val) { int Res = atoi (Str); if (Res != Val) { fprintf (outfile, "atoi error in \"%s\":\n" " result = %d, should be %d\n", Str, Res, Val); ++Failures; } } int main (void) { CheckAtoi ("\t +0A", 0); CheckAtoi ("\t -0.123", 0); CheckAtoi (" -32 ", -32); CheckAtoi (" +32 ", 32); CheckAtoi ("0377", 377); CheckAtoi (" 0377 ", 377); CheckAtoi (" +0377 ", 377); CheckAtoi (" -0377 ", -377); CheckAtoi ("0x7FFF", 0); CheckAtoi (" +0x7FFF", 0); CheckAtoi (" -0x7FFF", 0); fprintf (outfile, "Failures: %u\n", Failures); return (Failures != 0); } ����������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/clock-test.c�����������������������������������������������������������������0000664�0000000�0000000�00000004654�13473601511�0017012�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Clock test program * * 25-Sep-2018, chris@groessler.org */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <errno.h> #ifdef __CC65__ #include <conio.h> #include <cc65.h> #endif /* #ifdef __CC65__ */ static void print_time(void) { struct tm *cur_tm; time_t cur_time = time(NULL); if (cur_time == -1) { printf("time() failed: %s\n", strerror(errno)); return; } cur_tm = localtime(&cur_time); printf("time: %s\n", asctime(cur_tm)); // DEBUG: printf("mday=%d mon=%d year=%d\nhour=%d min=%d sec=%d\n", cur_tm->tm_mday, cur_tm->tm_mon, cur_tm->tm_year, cur_tm->tm_hour, cur_tm->tm_min, cur_tm->tm_sec); } int main(int argc, char **argv) { char c = 0; int s; struct tm cur_time; struct timespec new_time; #ifdef __CC65__ /* if DOS will automatically clear the screen after the program exits, wait for a keypress... */ if (doesclrscrafterexit()) atexit((void (*)(void))cgetc); #endif if (argc <= 1) { print_time(); return 0; } if (argc != 3 || strcasecmp(*(argv + 1), "set")) { printf("usage: CLOCKTST [set DD-MM-YY-HH-MM-SS]\n"); return 1; } memset(&cur_time, 0, sizeof(cur_time)); s = sscanf(*(argv + 2), "%d-%d-%d-%d-%d-%d", &cur_time.tm_mday, &cur_time.tm_mon, &cur_time.tm_year, &cur_time.tm_hour, &cur_time.tm_min, &cur_time.tm_sec); if (s != 6 || cur_time.tm_year > 99 /* other input values aren't being verified... */) { printf("invalid time/date format\n"); return 1; } --cur_time.tm_mon; if (cur_time.tm_year < 79) cur_time.tm_year += 100; /* adjust century */ memset(&new_time, 0, sizeof(new_time)); new_time.tv_sec = mktime(&cur_time); printf("\nyou are about to set the time to\n--> %s\n\nContinue (y/n)?", ctime(&new_time.tv_sec)); while (c != 'y' && c != 'Y' && c != 'n' && c != 'N') { #ifdef __CC65__ c = cgetc(); #else c = getchar(); #endif } printf("%c\n", c); if (c == 'n' || c == 'N') { printf("user abort\n"); return 0; } s = clock_settime(CLOCK_REALTIME, &new_time); if (s) { printf("clock_settime() failed: %s\n", strerror(errno)); return 1; } printf("time set!\n"); //DEBUG test begin print_time(); //DEBUG test end return 0; } /* Local Variables: */ /* c-file-style: "cpg" */ /* c-basic-offset: 4 */ /* End: */ ������������������������������������������������������������������������������������cc65-2.18/testcode/lib/clock.c����������������������������������������������������������������������0000664�0000000�0000000�00000000637�13473601511�0016032�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** simple clock test ** ** 06-Nov-2001, Christian Groessler */ #include <stdio.h> #include <conio.h> #include <time.h> int main(void) { printf("\ncc65 time routines test program\n"); printf("-------------------------------\n"); printf("clocks per second: %d\n", CLOCKS_PER_SEC); printf("current clock: %ld\n", clock()); printf("hit <return> to exit..."); cgetc(); printf("\n"); return(0); } �������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/conio.c����������������������������������������������������������������������0000664�0000000�0000000�00000011745�13473601511�0016050�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* * 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> #if defined(__GAMATE__) /* there is not enough screen space to show all 256 characters at the bottom */ #define NUMCHARS 128 #define NUMCOLS 4 #else #define NUMCHARS 256 #define NUMCOLS 16 #endif 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) { unsigned int i, j, n; unsigned char xsize, ysize, tcol, bgcol, bcol, inpos = 0; #if defined(__NES__) || defined(__PCE__) || defined(__GAMATE__) unsigned char joy; joy_install(joy_static_stddrv); #endif clrscr(); screensize(&xsize, &ysize); cputs("cc65 conio test\n\r"); cputs("Input:[ ]"); /* 8 spaces */ tcol = textcolor(0); /* memorize original textcolor */ bgcol = bgcolor(0); /* memorize original background color */ bcol = bordercolor(0); /* memorize original border color */ (void)bordercolor(bcol); (void)bgcolor(bgcol); cputsxy(0, 2, "Colors:" ); for (i = 0; i < 3; ++i) { gotoxy(i, 3 + i); for (j = 0; j < NUMCOLS; ++j) { (void)textcolor(j); cputc('X'); } } (void)textcolor(tcol); cprintf("\n\n\r Screensize: %ux%u", 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 - ((NUMCHARS + xsize) / xsize)); revers(1); for (i = 0; i < xsize; ++i) { cputc('0' + i % 10); } revers(0); for (i = 0; i < NUMCHARS; ++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 (;;) { /* do the "rvs" blinking */ i = textcolor(COLOR_BLACK); gotoxy(8, 2); j = (++n / 16) & 1; revers(j); cputc(j ? 'R' : ' '); revers(j ^ 1); cputs(" rvs"); revers(0); (void)textcolor(i); gotoxy(7 + inpos, 1); #if defined(__NES__) || defined(__PCE__) || defined(__GAMATE__) /* not all targets have waitvsync */ waitvsync(); /* for targets that do not have a keyboard, read the first joystick */ joy = joy_read(JOY_1); cprintf("%02x", joy); #else i = cgetc(); switch (i) { case CH_ENTER: clrscr(); return; case CH_CURS_LEFT: inpos = (inpos - 1) % 8; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': (void)textcolor(i - '0'); break; #ifdef CH_F5 case CH_F5: bcol = (bcol + 1) & 0x0f; (void)bordercolor(bcol); break; #endif #ifdef CH_F6 case CH_F6: bcol = (bcol - 1) & 0x0f; (void)bordercolor(bcol); break; #endif #ifdef CH_F7 case CH_F7: bgcol = (bgcol + 1) & 0x0f; (void)bgcolor(bgcol); break; #endif #ifdef CH_F8 case CH_F8: bgcol = (bgcol - 1) & 0x0f; (void)bgcolor(bgcol); break; #endif default: cputc(i); /* fallthrough */ case CH_CURS_RIGHT: inpos = (inpos + 1) % 8; } #endif } } ���������������������������cc65-2.18/testcode/lib/cpeek-test.c�����������������������������������������������������������������0000664�0000000�0000000�00000017360�13473601511�0017004�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* Test that the cpeek...() functions are the inverses of cputc(), ** revers(), and textcolor() for the full range of character codes. ** ** 2017-07-15, Greg King ** 2017-12-12, Groepaz */ #include <conio.h> #include <cc65.h> /* Standard location of the screen */ #if defined(__C128__) || defined(__C64__) /* only 40-column screen */ # define SCREEN_RAM ((unsigned char*)0x0400) #elif defined(__C16__) /* Plus4 also */ # define SCREEN_RAM ((unsigned char*)0x0C00) #elif defined(__CBM510__) # define SCREEN_RAM ((unsigned char*)0xF000) # define COLOR_RAM ((unsigned char*)0xd400) #elif defined(__CBM610__) # define SCREEN_RAM ((unsigned char*)0xD000) #elif defined(__PET__) # define SCREEN_RAM ((unsigned char*)0x8000) #elif defined(__VIC20__) # define SCREEN_RAM ((unsigned char*)0x1000) #else # error This program cannot test that target. # define SCREEN_RAM ((unsigned char*)0) #endif static unsigned char width; /* Move the cursor backward one char with ** the recognition of a row change. */ static void chBack (void) { unsigned char y = wherey (); unsigned char x = wherex (); if (x == 0) { x = width; --y; } --x; gotoxy (x, y); } /* Move the cursor forward one char with ** the recognition of a row change. */ static void chForth (void) { unsigned char y = wherey (); unsigned char x = wherex (); if (++x >= width) { x = 0; ++y; } gotoxy (x, y); } /* A hack to get an unmodified byte from the ** screen memory at the current cursor position. */ static unsigned char peekChWithoutTranslation (void) { #if defined(__CBM610__) return peekbsys ((unsigned)&SCREEN_RAM[wherey () * width + wherex ()]); #else return SCREEN_RAM[wherey () * width + wherex ()]; #endif } /* as above, but for color ram */ static unsigned char peekColWithoutTranslation (void) { #if defined(__CBM610__) || defined (__PET__) return COLOR_WHITE; #elif defined(__C128__) || defined(__C64__) || defined(__VIC20__) || defined(__CBM510__) return COLOR_RAM[wherey () * width + wherex ()] & 0x0f; #else return COLOR_RAM[wherey () * width + wherex ()]; #endif } /* A test which outputs the given char, reads it back from ** screen memory, outputs the returned char at the next position, ** then compares the two screen memory bytes for identity. ** ** Note: cpeekc() must be tested indirectly because some platforms "fold" their ** character code-set into a smaller screen code-set. Therefore, cpeekc() might ** return an equivalent, but not equal, character to the one that was cputc(). */ static unsigned char testCPeekC (char ch) { unsigned char ch2_a, ch2_b, ch2_c; /* Test the given char-code, but not the ** special characters NEWLINE and RETURN ** (they don't put anything on the screen). */ if (('\n' == ch) || ('\r' == ch) ) { return 1; } /* toggle revers mode every few chars so cpeekc gets tested for both */ revers ((ch >> 3) & 1); /* output additional space every now and then, that way not only even or only odd half of the character cell will be tested */ #if defined(__C64__) if ((width == 80) && ((ch % 17) == 0)) { cputc(' '); } #endif /* Output the char to the screen. */ cputc (ch); /* Move the cursor pos. to the previous output. */ chBack (); /* Get back the written char without any translation. */ ch2_b = peekChWithoutTranslation (); /* Get back the written char, ** including the translation, screen-code -> text. */ ch2_a = cpeekc (); /* Move the cursor to the following writing position. */ chForth (); /* Output again the char which was read back by cpeekc(). */ cputc (ch2_a); /* Move the cursor pos. to the second output. */ chBack (); /* Get back the second written char without any translation; ** and, compare it to the first untranslated char. */ ch2_c = peekChWithoutTranslation (); if ((ch2_c != ch2_b) #if defined(__C128__) || defined(__C64__) /* VDC memory is not accessible, soft80 has no "videoram" */ && (width == 40) #endif ){ /* The test was NOT succesful. ** Output a diagnostic; and, return FAILURE. */ revers(0); cprintf ("\r\nError on char: %#x was %#x instead.", ch, ch2_a); cprintf ("\r\nRaw screen codes: %#x, %#x.", ch2_b, ch2_c); cprintf ("\r\nscreen width: %#d", width); return 0; } /* The test was succesful. ** Move the cursor to the following writing position. */ chForth (); return 1; } static unsigned char testCPeekCol (char ch) { unsigned char ch2_a, ch2_b, ch2_c; /* Output the char to the screen. */ textcolor (ch); cputc ('*'); /* Move the cursor pos. to the previous output. */ chBack (); /* Get back the written char without any translation. */ ch2_b = peekColWithoutTranslation (); /* Get back the written char, ** including the translation, screen-code -> text. */ ch2_a = cpeekcolor (); /* Move the cursor to the following writing position. */ chForth (); /* Output again the char which was read back by cpeekc(). */ textcolor (ch2_a); cputc ('x'); /* Move the cursor pos. to the second output. */ chBack (); /* Get back the second written char without any translation; ** and, compare it to the first untranslated char. */ ch2_c = peekColWithoutTranslation (); if ((ch2_c != ch2_b) #if defined(__C128__) /* VDC memory is not accessible */ && (width == 40) #endif ){ /* The test was NOT succesful. ** Output a diagnostic; and, return FAILURE. */ revers(0); cprintf ("\r\nError on color: %#x was %#x instead.", ch, ch2_a); cprintf ("\r\nRaw color codes: %#x, %#x.", ch2_b, ch2_c); return 0; } /* The test was succesful. ** Move the cursor to the following writing position. */ chForth (); return 1; } /* The main code initiates the screen for the tests, and sets the reverse flag. ** Then, it calls testCPeekC() for every char within 0..255. ** Then, it calls testCPeekCol() for each color ** Returns zero for success, one for failure. */ int main (void) { unsigned char i, c1, c2; char s[10]; int ret = 0; clrscr (); revers (0); textcolor(1); bgcolor(0); screensize (&width, &i); #if defined(__VIC20__) /* The VIC-20's screen is too small to hold the full test. */ i = 2; #else i = 0; #endif do { if (!testCPeekC (i)) { ret = 1; goto exiterror; } } while (++i != 0); /* will wrap around when finished */ #if defined(__VIC20__) cgetc(); #endif /* test colors */ #if defined(__VIC20__) clrscr (); #endif revers (0); textcolor(1); #if defined (__CBM610__) || defined (__PET__) cprintf("\n\rno COLOR_RAM\n\r"); #elif defined (__C128__) || defined (__C64__) if (width == 40) { cprintf("\n\rCOLOR_RAM at $%04x\n\r", COLOR_RAM); } else { cprintf("\n\rno COLOR_RAM\n\r"); } #else cprintf("\n\rCOLOR_RAM at $%04x\n\r", COLOR_RAM); #endif do { if (!testCPeekCol (i)) { ret = 1; goto exiterror; } } while (++i != 16); /* max 16 colors */ /* test revers */ textcolor(1); cputc('\n'); cputc('\r'); revers(0); cputc('x'); chBack (); c1 = cpeekrevers(); chForth(); revers(1); cputc('X'); chBack (); c2 = cpeekrevers(); chForth(); cputc('\n'); cputc('\r'); revers(c1); cputc('o'); revers(c2); cputc('O'); /* test cpeeks() */ revers(0); cprintf("\n\rtest1234"); gotox(0); cpeeks(s, 8); cputs("\n"); cputs(s); exiterror: if (doesclrscrafterexit()) { cgetc(); } return ret; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/cprintf.c��������������������������������������������������������������������0000664�0000000�0000000�00000001162�13473601511�0016376�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** test program for the cprintf() function ** (for the \r and \n special operators) ** CPG ** ** The output generated by this program should look ** like this: ** ** ---- top of screen -------- ** 12345 ** 67890 ** ** ** 67890 ** ** hit return to exit.... . . . ** ---- bottom of screen ----- */ #include <stdio.h> #include <conio.h> int main(void) { clrscr(); cprintf("12345\n"); cprintf("67890\n"); gotoxy(0,4); cprintf("12345\r"); cprintf("67890\r"); printf("\n\n"); printf("hit return to exit....\n"); fgetc(stdin); return(0); } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/cursor.c���������������������������������������������������������������������0000664�0000000�0000000�00000001532�13473601511�0016247�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** test for conio cursor() function ** CPG 2002 ** ** the cursor should be in the same state as mentioned in the printfs */ #include <conio.h> #if 1 #define NEWLINE cprintf("\r\n") #define PRINTF cprintf #else #include <stdio.h> #define NEWLINE printf("\n") #define PRINTF printf #endif int main(void) { char c; NEWLINE; cursor (1); PRINTF("enter key (cursor on): "); c = cgetc(); NEWLINE; cursor (0); PRINTF("enter key (cursor off): "); c = cgetc(); NEWLINE; PRINTF("enter key (cursor on): "); cursor (1); c = cgetc(); NEWLINE; PRINTF("enter key (cursor off): "); cursor (0); c = cgetc(); NEWLINE; PRINTF("hit any key to exit..."); c = cgetc(); NEWLINE; return(0); } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/deb.c������������������������������������������������������������������������0000664�0000000�0000000�00000001155�13473601511�0015465�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** test program for the debugger ** ** press 'd' to enter the debugger ** */ #include <stdio.h> #include <conio.h> #include <6502.h> #include <dbg.h> int main(void) { char c; /* Initialize the debugger */ DbgInit (0); clrscr(); cputsxy(4,10,"Debugger test...."); cgetc(); while(1) { printf("press d to debug, q to exit....\n"); c = cgetc(); if (c == 'q') { printf("exiting....\n"); return(0); } if (c == 'd') { printf("entering debug...\n"); BREAK(); printf("return from debug...\n"); } else { printf("unknown key '%c'\n",c); } } } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/dir-test.c�������������������������������������������������������������������0000664�0000000�0000000�00000004573�13473601511�0016475�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ /* first test for posix directory routines for the c64 kludges: - currently uses cbm_open, which conflicts with standard i/o, which in turn makes it infact kindof unuseable. this can be easily changed however, since the only reason not to use open/read was that it currently appends ,u,r to filenames - the offset in current dir stream should better be calculated from the values returned by "read". - the type flag isnt filled in atm. - scandir/alphasort/versionsort is missing - some bits are currently untested (ie, unused in the testprogram) 27/02/2003 gpz */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <dirent.h> #include <cbm.h> #include <conio.h> int main(void) { char* name = "."; unsigned char go = 0; DIR *D; register struct dirent* E; /* Explain usage and wait for a key */ printf ("Use the following keys:\n" " g -> go ahead without stop\n" " q -> quit directory listing\n" " r -> return to last entry\n" " s -> seek back to start\n" "Press any key to start ...\n"); cgetc (); /* Open the directory */ D = opendir (name); if (D == 0) { printf("error opening %s: %s\n", name, strerror (errno)); return 1; } /* Output the directory */ errno = 0; printf("contents of \"%s\":\n", name); while ((E = readdir (D)) != 0) { printf ("dirent.d_name[] : \"%s\"\n", E->d_name); printf ("dirent.d_blocks : %10u\n", E->d_blocks); printf ("dirent.d_type : %10d\n", E->d_type); printf ("telldir() : %10lu\n", telldir (D)); printf ("---\n"); if (!go) { switch (cgetc ()) { case 'g': go = 1; break; case 'q': goto done; case 'r': seekdir (D, E->d_off); break; case 's': rewinddir (D); break; } } } done: if (errno == 0) { printf ("Done\n"); } else { printf("Done: %d (%s)\n", errno, strerror (errno)); } /* Close the directory */ closedir (D); return 0; } �������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/div-test.c�������������������������������������������������������������������0000664�0000000�0000000�00000001716�13473601511�0016475�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* div-test.c ** ** This program tests the division and modulo operators ** and the div() library function. */ #include <cc65.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> static bool test (int dividend, int divisor) { div_t result; result = div (dividend, divisor); printf ("%+d/%+d= %+d, %+d%%%+d= %+d, div()= %+d, %+d\n", dividend, divisor, dividend / divisor, dividend, divisor, dividend % divisor, result.quot, result.rem); return result.quot * divisor + result.rem != dividend; } int main (void) { bool t; printf ("\nTest of division and modulus operations:\n\n"); t = test (+40, +3) || test (+40, -3) || test (-40, +3) || test (-40, -3); if (t) { printf ("\nThe div() function made a wrong result!\n"); } if (doesclrscrafterexit ()) { printf ("\nTap the Return key to quit. "); getchar (); } return (int)t; } ��������������������������������������������������cc65-2.18/testcode/lib/em-test.c��������������������������������������������������������������������0000664�0000000�0000000�00000014200�13473601511�0016304�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <conio.h> #include <em.h> #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]; static void cleanup (void) /* Remove the driver on exit */ { em_unload (); } static void fill (register unsigned* page, register unsigned char count, register unsigned num) { register unsigned char i; for (i = 0; i < count; ++i, ++page) { *page = num; } } static void cmp (unsigned page, register const unsigned* buf, register unsigned char count, register unsigned num) { register unsigned char i; for (i = 0; i < count; ++i, ++buf) { if (*buf != num) { cprintf ("\r\nData mismatch in page $%04X at $%04X\r\n" "Data is $%04X (should be $%04X)\r\n", page, buf, *buf, num); #ifdef __ATARI__ cgetc (); #endif exit (EXIT_FAILURE); } } } 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" }, { '9', "65816 extra banks", "c64-65816.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" }, { '6', "Internal Function RAM", "c128-ifnram.emd" }, { '7', "External Function RAM", "c128-efnram.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) { unsigned char Res; unsigned I; unsigned Offs; 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 (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)); #ifdef __ATARI__ cgetc (); #endif exit (EXIT_FAILURE); } atexit (cleanup); /* Get the number of available pages */ PageCount = em_pagecount (); cprintf ("Loaded ok, page count = $%04X\r\n", PageCount); /* TEST #1: em_map/em_use/em_commit */ cputs ("Testing em_map/em_use/em_commit"); /* Fill all pages */ cputs ("\r\n Filling "); X = wherex (); Y = wherey (); for (I = 0; I < PageCount; ++I) { /* Fill the buffer and copy it to em */ fill (em_use (I), PAGE_SIZE, I); em_commit (); /* Keep the user happy */ gotoxy (X, Y); cputhex16 (I); } #if FORCE_ERROR1 ((unsigned*) em_map (0x03))[0x73] = 0xFFFF; em_commit (); #endif /* Check all pages */ cputs ("\r\n Comparing "); X = wherex (); Y = wherey (); for (I = 0; I < PageCount; ++I) { /* Get the buffer and compare it */ cmp (I, em_map (I), PAGE_SIZE, I); /* Keep the user happy */ gotoxy (X, Y); cputhex16 (I); } /* TEST #2: em_copyfrom/em_copyto. */ cputs ("\r\nTesting em_copyfrom/em_copyto"); /* We're filling now 384 bytes per run to test the copy routines with ** other sizes. */ PageCount = (PageCount * 2) / 3; /* Setup the copy structure */ c.buf = buf; c.count = sizeof (buf); /* Fill again all pages */ cputs ("\r\n Filling "); X = wherex (); Y = wherey (); c.page = 0; c.offs = 0; for (I = 0; I < PageCount; ++I) { /* Fill the buffer and copy it to em */ fill (buf, BUF_SIZE, I ^ 0xFFFF); em_copyto (&c); /* Adjust the em offset */ Offs = c.offs + sizeof (buf); c.offs = (unsigned char) Offs; c.page += (Offs >> 8); /* Keep the user happy */ gotoxy (X, Y); cputhex16 (I); } #if FORCE_ERROR2 c.page = 0x03; em_copyfrom (&c); buf[0x73] = 0xFFFF; em_copyto (&c); #endif /* Check all pages */ cputs ("\r\n Comparing "); X = wherex (); Y = wherey (); c.page = 0; c.offs = 0; for (I = 0; I < PageCount; ++I) { /* Get the buffer and compare it */ em_copyfrom (&c); cmp (I, buf, BUF_SIZE, I ^ 0xFFFF); /* Adjust the em offset */ Offs = c.offs + sizeof (buf); c.offs = (unsigned char) Offs; c.page += (Offs >> 8); /* Keep the user happy */ gotoxy (X, Y); cputhex16 (I); } /* Success */ cprintf ("\r\nPassed!\r\n"); #ifdef __ATARI__ cgetc (); #endif return 0; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/exec-test1.c�����������������������������������������������������������������0000664�0000000�0000000�00000001104�13473601511�0016707�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** These programs test cc65's exec() program-chaining function. ** exec-test1 runs exec-test2 -- that tests the loading and starting of another ** program. Then, exec-test2 runs arg-test -- that tests command-line argument ** passing. ** ** 2013-08-24, Greg King */ #include <unistd.h> #include <string.h> #include <errno.h> #include <conio.h> int main (void) { clrscr (); cprintf ("\nExec-test #1 -- launching #2...\r\n"); exec ("exec-test2", ""); cprintf ("\nFailed to find #2:\r\n %s.\r\n", _stroserror (_oserror)); cgetc (); return _oserror; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/exec-test2.c�����������������������������������������������������������������0000664�0000000�0000000�00000001124�13473601511�0016712�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** These programs test cc65's exec() program-chaining function. ** exec-test1 runs exec-test2 -- that tests the loading and starting of another ** program. Then, exec-test2 runs arg-test -- that tests command-line argument ** passing. ** ** 2013-08-24, Greg King */ #include <unistd.h> #include <string.h> #include <errno.h> #include <conio.h> int main (void) { cprintf ("\nExec-test #2 -- launching arg-test...\r\n\n"); exec ("arg-test", "arg1 arg2 \"\" arg4"); cprintf ("\nFailed to find arg-test:\r\n %s.\r\n", _stroserror (_oserror)); cgetc (); return _oserror; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/fileio-test.c����������������������������������������������������������������0000664�0000000�0000000�00000003663�13473601511�0017165�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <stdio.h> #include <string.h> #include <errno.h> #include <fcntl.h> FILE* Fopen (const char* Name, const char* Mode) { FILE* F; printf ("Opening %s(%s): ", Name, Mode); F = fopen (Name, Mode); if (F) { printf ("Ok (%d)\n", fileno (F)); } else { printf (strerror (errno)); } return F; } void Fwrite (FILE* F, const void* Buf, unsigned Size) { size_t Res; Res = fwrite (Buf, 1, Size, F); printf ("Writing %u bytes to %d: %u\n", Size, fileno (F), Res); } int Fread (FILE* F, void* Buf, unsigned Size) { size_t Res; Res = fread (Buf, 1, Size, F); printf ("Reading %u bytes from %d: %u\n", Size, fileno (F), Res); return Res > 0? Res : 0; } void Fclose (FILE* F) { printf ("Closing %d:", fileno (F)); if (fclose (F) == 0) { printf ("Ok\n"); } else { printf (strerror (errno)); } } int main (void) { FILE* F1; FILE* F2; int Res; static const char text1[] = "This goes into file #1\n"; static const char text2[] = "This goes into file #2\n"; static const char text3[] = "This goes into file #3\n"; static const char text4[] = "This goes into file #4\n"; static char Buf[200]; F1 = Fopen ("foobar1", "w"); F2 = Fopen ("foobar2", "w"); Fwrite (F1, text1, sizeof (text1) - 1); Fwrite (F2, text2, sizeof (text2) - 1); Fwrite (F1, text1, sizeof (text1) - 1); Fwrite (F2, text2, sizeof (text2) - 1); Fclose (F1); Fclose (F2); F1 = Fopen ("foobar3", "w"); F2 = Fopen ("foobar4", "w"); Fwrite (F1, text3, sizeof (text3) - 1); Fwrite (F2, text4, sizeof (text4) - 1); Fwrite (F1, text3, sizeof (text3) - 1); Fwrite (F2, text4, sizeof (text4) - 1); Fclose (F1); Fclose (F2); F1 = Fopen ("foobar1", "r"); Res = Fread (F1, Buf, sizeof (Buf)); printf ("%.*s", Res, Buf); Res = Fread (F1, Buf, sizeof (Buf)); Fclose (F1); return 0; } �����������������������������������������������������������������������������cc65-2.18/testcode/lib/ft.c�������������������������������������������������������������������������0000664�0000000�0000000�00000005070�13473601511�0015344�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** simple file I/O test ** ** 12-Jun-2000, Christian Groessler ** ** please compile with ** cl65 -tsystem ft.c getsp.s -o ft.com ** ** The program asks for a filename (if it hasn't ** got one from argv). I then opens the file, ** reads the the first 16 bytes and displays them ** (as hex values). ** The values of sp (cc65 runtime stack pointer) ** are displayed at some places. The displayed ** value should always be the same. */ #include <stdio.h> #include <string.h> #include <fcntl.h> #include <errno.h> #include <conio.h> #include <unistd.h> extern int getsp(void); /* is provided in getsp.s */ /* Atari's fd indirection table */ #ifdef __ATARI__ extern char __fd_index[]; struct fd_t { char usage; char iocb; char dev; char flag; }; extern struct fd_t __fd_table[]; #endif int main(int argc,char **argv) { char *filename,*x; char buf[20]; int i,l,lr; int fd; int csp; if (argc >= 2) { filename = *(argv+1); } else { printf("\nfilename: "); x = fgets(buf,19,stdin); printf("\n"); if (!x) { printf("nothing read\n"); return(0); } #if 0 l = strlen(x); printf("read: "); for (i=0; i<l; i++) printf("%02X ",*(x+i)); printf("\n"); #endif filename = x; } printf("using filename \"%s\"\n",filename); csp = getsp(); printf("now opening file... sp = %d\n",csp); fd = open(filename,O_RDONLY); csp = getsp(); if (fd == -1) { char x1 = _oserror; printf("open failed: os: %d,\n\terrno: %d, sp = %d\n",x1,errno,csp); cgetc(); return(0); } printf("open success -- handle = $%x, sp = %d\n",fd,csp); #ifdef __ATARI__ printf("fd_index:\n "); for (i=0; i<12; i++) printf("%02X ",__fd_index[i]); printf("\nfd_table:\n"); for (i=0; i<8; i++) { printf(" usa: %d, iocb: %02X, dev: %02X\n", __fd_table[i].usage, __fd_table[i].iocb, __fd_table[i].dev); } #endif lr = read(fd,buf,16); /* read first 16 bytes */ csp = getsp(); if (lr == -1) { printf("read failed: %d (sp = %d)\n",errno,csp); cgetc(); return(0); } l = close(fd); if (l == -1) { printf("close failed: %d\n",errno); cgetc(); return(0); } csp = getsp(); printf("\n\nThe data read: (%d bytes, sp = %d)\n",lr,csp); for (i=0; i<lr; i++) { printf("%02X ",buf[i]); if (!((i+1) & 7)) printf("\n"); } printf("\n\npress return to exit..."); getchar(); return(0); } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/gamate/����������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0016023�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/gamate/Makefile��������������������������������������������������������������0000664�0000000�0000000�00000002223�13473601511�0017462�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ all: audiotest.bin lcdtest.bin ctest.bin audiotest.bin: audiotest.s ../../../bin/cl65 -l audiotest.lst -t gamate -o audiotest.bin audiotest.s lcdtest.bin: lcdtest.s ../../../bin/cl65 -l lcdtest.lst -t gamate -o lcdtest.bin lcdtest.s ctest.bin: ctest.c ../../../bin/cl65 -l ctest.lst -t gamate -o ctest.bin ctest.c nachtm.bin: nachtm.c ../../../bin/cl65 -Os -l nachtm.lst -t gamate -o nachtm.bin nachtm.c gamate-fixcart nachtm.bin test1: lcdtest.bin cd ~/Desktop/mame/winmess/ && wine mess.exe gamate -window -skip_gameinfo -cart ~/Desktop/cc65/github/cc65/testcode/lib/gamate/lcdtest.bin test2: audiotest.bin cd ~/Desktop/mame/winmess/ && wine mess.exe gamate -window -skip_gameinfo -cart ~/Desktop/cc65/github/cc65/testcode/lib/gamate/audiotest.bin testc: ctest.bin cd ~/Desktop/mame/winmess/ && wine mess.exe gamate -window -skip_gameinfo -cart ~/Desktop/cc65/github/cc65/testcode/lib/gamate/ctest.bin testn: nachtm.bin cd ~/Desktop/mame/winmess/ && wine mess.exe gamate -window -skip_gameinfo -cart ~/Desktop/cc65/github/cc65/testcode/lib/gamate/nachtm.bin clean: rm -f lcdtest.o audiotest.o ctest.o rm -f lcdtest.bin audiotest.bin ctest.bin nachtm.bin �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/gamate/audiotest.s�����������������������������������������������������������0000664�0000000�0000000�00000022126�13473601511�0020213�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; original audiotest.s by PeT (mess@utanet.at) ; ; cl65 -t gamate -o audiotest.bin audiotest.s ; .include "gamate.inc" .zeropage addr: .word 0 psa: .word 0 readaddr: .word 0 editbuffer1: .byte 0,0,0,0, 0,0,0,0 writeaddr: .word 0 editbuffer2: .byte 0,0,0,0, 0,0,0,0 cursor: .byte 0 controlslast: .byte 0 controlsedge: .byte 0 .bss temp_x: .byte 0 temp_y: .byte 0 temp_a: .byte 0 irq_count: .byte 0 nmi_count: .byte 0 psx: .byte 0 psy: .byte 0 xpos: .byte 0 ypos: .byte 0 .rodata chars: .incbin "cga2.chr" hex2asc: .byte "0123456789abcdef" .code ;------------------------------------------------------------------------------- .export IRQStub, NMIStub .proc NMIStub inc nmi_count rts .endproc .proc IRQStub inc irq_count rts .endproc ;------------------------------------------------------------------------------- .export Start .proc Start sei lda #0 sta ZP_IRQ_CTRL lda #>AUDIO_BASE sta writeaddr+1 sta readaddr+1 lda #<AUDIO_BASE sta writeaddr sta readaddr lda #$10 sta editbuffer1+6 lda #$e sta editbuffer2+5 lda #$ff sta editbuffer2+3 lda #$ff sta editbuffer2+4 lda #$0f sta editbuffer2 lda #$0f sta editbuffer2+1 lda #$0e sta editbuffer2+2 lda #$38 sta editbuffer1+7 lda #0 sta LCD_XPOS sta LCD_YPOS sta irq_count sta cursor lda #1 sta nmi_count cli lda #LCD_MODE_INC_Y sta LCD_MODE jsr printy lda #1 sta ZP_IRQ_CTRL loop: lda irq_count loop1: cmp irq_count beq loop1 lda irq_count and #7 bne loop1 lda #LCD_MODE_INC_Y sta LCD_MODE ldx #3 ldy #32 lda irq_count jsr printhex lda cursor ldy #0 cmp #20 bcc firstline sec sbc #20 ldy #24 firstline: sta LCD_X sty LCD_Y lda #' ' jsr printsign norclearcursor: jsr inputs lda irq_count and #8 bne nocursor lda cursor ldy #0 cmp #20 bcc firstline2 sec sbc #20 ldy #24 firstline2: sta LCD_X sty LCD_Y lda #'x' jsr printsign nocursor: lda #LCD_MODE_INC_Y sta LCD_MODE jsr printy jmp loop .endproc .proc printy ldy #0 loop1: tya pha asl tax lda readaddr,y ldy #8 jsr printhex pla tay iny cpy #10 bne loop1 loop2: tya pha tya sec sbc #10 asl tax lda readaddr,y ldy #16 jsr printhex pla tay iny cpy #20 bne loop2 ldx #0 ldy #32 lda nmi_count jsr printhex rts .endproc ;------------------------------------------------------------------------------- .proc inputs lda controlslast eor JOY_DATA and controlslast eor #$ff sta controlsedge and #JOY_DATA_UP bne notup lda cursor lsr tay bcs uplow lda readaddr,y clc adc #$10 sta readaddr,y jmp notup uplow: lda readaddr,y clc adc #1 sta readaddr,y notup: lda controlsedge and #JOY_DATA_DOWN bne notdown lda cursor lsr tay bcs downlow lda readaddr,y sec sbc #$10 sta readaddr,y jmp notdown downlow: lda readaddr,y sec sbc #1 sta readaddr,y notdown: lda controlsedge and #JOY_DATA_LEFT bne notleft lda cursor beq notleft dec cursor notleft: lda controlsedge and #JOY_DATA_RIGHT bne notright lda cursor cmp #40 beq notright inc cursor notright: lda controlsedge and #JOY_DATA_START bne notstart lda #0 sta AUDIO_BASE sta AUDIO_BASE+1 sta AUDIO_BASE+2 sta AUDIO_BASE+3 sta AUDIO_BASE+4 sta AUDIO_BASE+5 sta AUDIO_BASE+6 sta AUDIO_BASE+8 sta AUDIO_BASE+9 sta AUDIO_BASE+10 sta AUDIO_BASE+11 sta AUDIO_BASE+12 sta AUDIO_BASE+13 sta AUDIO_BASE+7 notstart: lda controlsedge and #JOY_DATA_SELECT bne notselect lda editbuffer1 sta AUDIO_BASE lda editbuffer1+1 sta AUDIO_BASE+1 lda editbuffer1+2 sta AUDIO_BASE+2 lda editbuffer1+3 sta AUDIO_BASE+3 lda editbuffer1+4 sta AUDIO_BASE+4 lda editbuffer1+5 sta AUDIO_BASE+5 lda editbuffer1+6 sta AUDIO_BASE+6 lda editbuffer2 sta AUDIO_BASE+8 lda editbuffer2+1 sta AUDIO_BASE+9 lda editbuffer2+2 sta AUDIO_BASE+10 lda editbuffer2+3 sta AUDIO_BASE+11 lda editbuffer2+4 sta AUDIO_BASE+12 lda editbuffer2+5 sta AUDIO_BASE+13 lda editbuffer1+7 sta AUDIO_BASE+7 notselect: lda controlsedge and #JOY_DATA_FIRE_A bne notbuttona ldy #0 ldy #0 writea: lda editbuffer1,y sta (writeaddr),y iny cpy #8 bne writea writeb: lda editbuffer2-8,y sta (writeaddr),y iny cpy #16 bne writeb notbuttona: lda controlsedge and #JOY_DATA_FIRE_B bne notbuttonb ldy #0 reada: lda (readaddr),y sta editbuffer1,y iny cpy #8 bne reada readb: lda (readaddr),y sta editbuffer2-8,y iny cpy #16 bne readb notbuttonb: lda JOY_DATA sta controlslast rts .endproc ;------------------------------------------------------------------------------- .proc printstring sta psa stx psa+1 ldx #0 stx psx sty psy printstring2: ldy #0 lda (psa),y beq printstring1 ldx psx stx LCD_X ldy psy sty LCD_Y jsr printsign inc psx lda psa clc adc #1 sta psa lda psa+1 adc #0 sta psa+1 jmp printstring2 printstring1: rts .endproc .proc printstringy sta psa stx psa+1 printstring2: ldy #0 lda (psa),y beq printstring1 jsr printsign lda psa clc adc #1 sta psa lda psa+1 adc #0 sta psa+1 jmp printstring2 printstring1: rts .endproc .proc printhex pha lsr lsr lsr lsr and #$0f stx temp_x tax lda hex2asc,x ldx temp_x stx LCD_X sty LCD_Y jsr printsign pla and #$0f inx stx temp_x tax lda hex2asc,x ldx temp_x stx LCD_X sty LCD_Y jmp printsign .endproc .proc printsign sty temp_y stx temp_x sta temp_a lda temp_a sta addr lda #0 sta addr+1 asl addr rol addr+1 asl addr rol addr+1 asl addr rol addr+1 lda addr clc adc #<chars sta addr lda addr+1 adc #>chars sta addr+1 ldx #8 ldy #0 printsign1: lda (addr),y sta LCD_DATA iny dex bne printsign1 ldx temp_x ldy temp_y rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/gamate/cga2.chr��������������������������������������������������������������0000664�0000000�0000000�00000004000�13473601511�0017327�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������~¥½™~~ÿÛÿÃçÿ~lþþþ|8�8|þ|8�8|8þþÖ88|þ|8��<<��ÿÿçÃÃçÿÿ�<fBBf<�ÿÙ½½™Ãÿ}ÌÌÌx<fff<~?3?00pðàcccgæÀÛ<çç<Û€àøþøà€�>þ>�<~~<fffff�f�ÛÛ{�>c8ll8Ìx����~~~�<~~<ÿ<~�~<�� þ ���0`þ`0����ÀÀÀþ���$fÿf$���<~ÿÿ���ÿÿ~<����������0xx00�0�lll�����llþlþll�0|Àx ø0��ÆÌ0fÆ�8l8vÜÌv�``À�����0```0�`00`��f<ÿ<f���00ü00�������00`���ü���������00� 0`À€�|ÆÎÞöæ|�0p0000ü�xÌ 8`Ìü�xÌ 8 Ìx�<lÌþ �üÀø Ìx�8`ÀøÌÌx�üÌ 000�xÌÌxÌÌx�xÌÌ| p��00��00��00��00`0`À`0���ü��ü��`0 0`�xÌ 0�0�|ÆÞÞÞÀx�0xÌÌüÌÌ�üff|ffü�<fÀÀÀf<�ølffflø�þbhxhbþ�þbhxh`ð�<fÀÀÎf>�ÌÌÌüÌÌÌ�x00000x� ÌÌx�æflxlfæ�ð```bfþ�ÆîþþÖÆÆ�ÆæöÞÎÆÆ�8lÆÆÆl8�üff|``ð�xÌÌÌÜx�üff|lfæ�xÌ`0Ìx�ü´0000x�ÌÌÌÌÌÌü�ÌÌÌÌÌx0�ÆÆÆÖþîÆ�ÆÆl88lÆ�ÌÌÌx00x�þÆŒ2fþ�x`````x�À`0 �xx�8lÆ�����������ÿ00�������x |Ìv�à``|ffÜ���xÌÀÌx� |ÌÌv���xÌüÀx�8l`ð``ð���vÌÌ| øà`lvffæ�0�p000x� � ÌÌxà`flxlæ�p00000x���ÌþþÖÆ���øÌÌÌÌ���xÌÌÌx���Üff|`ð��vÌÌ| ��Üvf`ð���|Àx ø�0|004���ÌÌÌÌv���ÌÌÌx0���ÆÖþþl���Æl8lÆ���ÌÌÌ| ø��ü˜0dü�00à00���à0000à�vÜ�������8lÆÆþ�xÌÀÌx x�Ì�ÌÌÌ~��xÌüÀx�~Ã<>f?�Ì�x |Ì~�à�x |Ì~�00x |Ì~���xÀÀx 8~Ã<f~`<�Ì�xÌüÀx�à�xÌüÀx�Ì�p000x�|Æ8<�à�p000x�Æ8lÆþÆÆ�00�xÌüÌ��ü`x`ü��� Ì�>lÌþÌÌÎ�xÌ�xÌÌx��Ì�xÌÌx��à�xÌÌx�xÌ�ÌÌÌ~��à�ÌÌÌ~��Ì�ÌÌ| øÃ<ff<�Ì�ÌÌÌÌx�~ÀÀ~8ldð`æü�ÌÌxü0ü00øÌÌúÆÏÆÇ<Øp�x |Ì~�8�p000x���xÌÌx���ÌÌÌ~��ø�øÌÌÌ�ü�ÌìüÜÌ�<ll>�~��8ll8�|��0�0`ÀÌx����üÀÀ�����ü ��ÃÆÌÞ3fÌÃÆÌÛ7oÏ���3fÌf3���Ìf3fÌ��"ˆ"ˆ"ˆ"ˆUªUªUªUªÛwÛîÛwÛîøøø6666ö666����þ666��øø66öö66666666666��þö66666öþ���6666þ���øø�������ø���ÿ�������ÿ����ÿ���ÿ666676666670?�����?0766666÷�ÿ�����ÿ�÷66666707666��ÿ�ÿ���66÷�÷666ÿ�ÿ���6666ÿ�����ÿ�ÿ����ÿ6666666?������������?6666666ÿ666ÿÿø�������ÿÿÿÿÿÿÿÿ����ÿÿÿÿððððððððÿÿÿÿ������vÜÈÜv��xÌøÌøÀÀ�üÌÀÀÀÀ��þlllll�üÌ`0`Ìü���~ØØØp��ffff|`À�vÜ�ü0xÌÌx0ü8lÆþÆl8�8lÆÆllî�0|ÌÌx���~ÛÛ~�� ~ÛÛ~`À8`ÀøÀ`8�xÌÌÌÌÌÌ��ü�ü�ü��00ü00�ü�`00`�ü�0`0�ü�ØØp00�ü�00��vÜ�vÜ��8ll8����������������� ìl<xllll���p0`x�����<<<<����������cc65-2.18/testcode/lib/gamate/ctest.c���������������������������������������������������������������0000664�0000000�0000000�00000002273�13473601511�0017315�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ #include <gamate.h> #include <time.h> #include <conio.h> unsigned char y = 0; unsigned char x = 0; unsigned short n; int main(int argc, char *argv[]) { clrscr(); gotoxy(0,0);cputs("Gamate C-Test"); textcolor(0);gotoxy(0,5);cputs("abcdABCD 0"); textcolor(1);gotoxy(0,6);cputs("abcdABCD 1"); textcolor(2);gotoxy(0,7);cputs("abcdABCD 2"); textcolor(3);gotoxy(0,8);cputs("abcdABCD 3"); while(1) { textcolor(COLOR_BLACK); n = clock(); gotoxy(0,2);cprintf("%04x %02x %02x %02x", n, x, y, *((unsigned char*)JOY_DATA)); switch((*((unsigned char*)JOY_DATA))) { case 0xff ^ JOY_DATA_UP: ++y; if (y == 0xc8) y = 0; break; case 0xff ^ JOY_DATA_DOWN: --y; if (y == 0xff) y = 0xc7; break; case 0xff ^ JOY_DATA_LEFT: ++x; break; case 0xff ^ JOY_DATA_RIGHT: --x; break; case 0xff ^ JOY_DATA_FIRE_A: break; } waitvsync(); (*((unsigned char*)LCD_XPOS)) = x; (*((unsigned char*)LCD_YPOS)) = y; } return 0; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/gamate/lcdtest.s�������������������������������������������������������������0000664�0000000�0000000�00000020222�13473601511�0017647�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������; ; original lcdtest.s by PeT (mess@utanet.at) ; ; cl65 -t gamate -o lcdtest.bin lcdtest.s ; .include "gamate.inc" .zeropage addr: .word 0 psa: .word 0 .bss temp_x: .byte 0 temp_y: .byte 0 temp_a: .byte 0 irq_count: .byte 0 nmi_count: .byte 0 psx: .byte 0 psy: .byte 0 count: .word 0 counted: .word 0 xpos: .byte 0 ypos: .byte 0 .rodata chars: .incbin "cga2.chr" hex2asc: .byte "0123456789abcdef" format: .byte "IrqNmiCountXposYpos", 0 xdesc: .byte "0123456789abcdefghijklmnopqrstuv", 0 ydesc: .byte "0123456789ABCDEFGHIJKLMNOPQRSTUV", 0 .code ;------------------------------------------------------------------------------- .export IRQStub, NMIStub .proc NMIStub inc nmi_count rts .endproc .proc IRQStub inc irq_count lda count sta counted lda count+1 sta counted+1 lda #0 sta count sta count+1 rts .endproc ;------------------------------------------------------------------------------- .export Start .proc Start sei lda #0 sta ZP_IRQ_CTRL lda #0 sta LCD_XPOS sta LCD_YPOS cli lda #LCD_MODE_INC_Y sta LCD_MODE lda #0 sta LCD_X lda #<xdesc ldx #>xdesc ldy #0 jsr printstring lda #LCD_XPOS_PLANE2 sta LCD_X lda #<xdesc ldx #>xdesc ldy #128 jsr printstring lda #0 sta LCD_X lda #<ydesc ldx #>ydesc ldy #0 sty LCD_Y jsr printstringy lda #(LCD_XPOS_PLANE2|(128/8)) ; ??? sta LCD_X lda #<ydesc ldx #>ydesc ldy #0 sty LCD_Y jsr printstringy lda #<format ldx #>format ldy #8 jsr printstring lda #0 sta LCD_MODE lda #24/8 sta LCD_X lda #24 sta LCD_Y lda #'X' jsr printsign lda #$80 sta LCD_MODE lda #32/8 sta LCD_X lda #32 sta LCD_Y lda #'Y' jsr printsign lda #$c0 sta LCD_MODE lda #40/8 sta LCD_X lda #40 sta LCD_Y lda #'Z' jsr printsign lda #0 sta LCD_MODE lda #LCD_XPOS_PLANE2|(48/8) sta LCD_X lda #48 sta LCD_Y lda #'x' jsr printsign lda #$80 sta LCD_MODE lda #(LCD_XPOS_PLANE2|(56/8)) sta LCD_X lda #56 sta LCD_Y lda #'y' jsr printsign lda #$c0 sta LCD_MODE lda #(LCD_XPOS_PLANE2|(64/8)) sta LCD_X lda #64 sta LCD_Y lda #'z' jsr printsign lda #LCD_MODE_INC_Y|1 sta LCD_MODE lda #16/8 sta LCD_X lda #72 sta LCD_Y lda #'V' jsr printsign lda #LCD_MODE_INC_Y|2 sta LCD_MODE lda #24/8 sta LCD_X lda #72 sta LCD_Y lda #'V' jsr printsign lda #LCD_MODE_INC_Y|4 sta LCD_MODE lda #32/8 sta LCD_X lda #72 sta LCD_Y lda #'V' jsr printsign lda #LCD_MODE_INC_Y|8 sta LCD_MODE lda #40/8 sta LCD_X lda #72 sta LCD_Y lda #'V' jsr printsign lda #1 sta ZP_IRQ_CTRL loop: lda count clc adc #1 sta count lda count+1 adc #0 sta count+1 lda irq_count cmp irq_count beq loop jsr inputs lda #LCD_MODE_INC_Y sta LCD_MODE jsr printy jmp loop .endproc ;------------------------------------------------------------------------------- .proc printy ldx #0 ldy #16 lda irq_count jsr printhex ldx #3 ldy #16 lda nmi_count jsr printhex ldx #6 ldy #16 lda counted+1 jsr printhex ldx #8 ldy #16 lda counted jsr printhex ldx #11 ldy #16 lda xpos jsr printhex ldx #14 ldy #16 lda ypos jsr printhex rts .endproc .proc inputs lda JOY_DATA and #JOY_DATA_UP bne notup dec ypos lda ypos sta LCD_YPOS notup: lda JOY_DATA and #JOY_DATA_DOWN bne notdown inc ypos lda ypos sta LCD_YPOS notdown: lda JOY_DATA and #JOY_DATA_LEFT bne notleft dec xpos lda xpos sta LCD_XPOS notleft: lda JOY_DATA and #JOY_DATA_RIGHT bne notright inc xpos lda xpos sta LCD_XPOS notright: lda JOY_DATA and #JOY_DATA_START bne notstart notstart: lda JOY_DATA and #JOY_DATA_SELECT bne notselect notselect: lda JOY_DATA and #JOY_DATA_FIRE_A bne notbuttona notbuttona: lda JOY_DATA and #JOY_DATA_FIRE_B bne notbuttonb notbuttonb: rts .endproc ;------------------------------------------------------------------------------- .proc printstring sta psa stx psa+1 ldx #0 stx psx sty psy printstring2: ldy #0 lda (psa),y beq printstring1 ldx psx stx LCD_X ldy psy sty LCD_Y jsr printsign inc psx lda psa clc adc #1 sta psa lda psa+1 adc #0 sta psa+1 jmp printstring2 printstring1: rts .endproc .proc printstringy sta psa stx psa+1 printstring2: ldy #0 lda (psa),y beq printstring1 jsr printsign lda psa clc adc #1 sta psa lda psa+1 adc #0 sta psa+1 jmp printstring2 printstring1: rts .endproc .proc printhex pha lsr lsr lsr lsr and #$0f stx temp_x tax lda hex2asc,x ldx temp_x stx LCD_X sty LCD_Y jsr printsign pla and #$0f inx stx temp_x tax lda hex2asc,x ldx temp_x stx LCD_X sty LCD_Y jmp printsign .endproc .proc printsign sty temp_y stx temp_x sta temp_a lda temp_a sta addr lda #0 sta addr+1 asl addr rol addr+1 asl addr rol addr+1 asl addr rol addr+1 lda addr clc adc #<chars sta addr lda addr+1 adc #>chars sta addr+1 ldx #8 ldy #0 printsign1: lda (addr),y sta LCD_DATA iny dex bne printsign1 ldx temp_x ldy temp_y rts .endproc ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/gamate/nachtm.c��������������������������������������������������������������0000664�0000000�0000000�00000210322�13473601511�0017441�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** "Eine kleine Nachtmusik" by Wolfgang Amadeus Mozart, KV 525 ** ** First version in 1987 by ** Joachim von Bassewitz (joachim@von-bassewitz.de) and ** Ullrich von Bassewitz (ullrich@von-bassewitz.de). ** ** C conversion in 1998 by ** Ullrich von Bassewitz (ullrich@von-bassewitz.de) ** */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <conio.h> #include <gamate.h> /*****************************************************************************/ /* Data */ /*****************************************************************************/ /* Tables with voice data. ** ** Bit Description ** ------------------------------------------- ** 15 Pause bit. ** 12-14 Octave ** 8-11 Tone (index into frequency table) ** 7 Unused. Was thought as a control bit in the original version to ** change SID parameters, but this was never implemented. ** 0-6 Length of the tone in ticks. ** */ const unsigned Voice1 [] = { 0x5708,0x8004,0x5204,0x5708,0x8004,0x5204,0x5704,0x5204,0x5704,0x5B04, 0x6208,0x8008,0x6008,0x8004,0x5904,0x6008,0x8004,0x5904,0x6004,0x5904, 0x5604,0x5904,0x5208,0x8008,0x5704,0x8004,0x570C,0x5B01,0x5B01,0x5B01, 0x5B01,0x5904,0x5704,0x5704,0x5604,0x560C,0x5901,0x5901,0x5901,0x5901, 0x6004,0x5604,0x5901,0x5901,0x5901,0x5901,0x5704,0x570C,0x5B01,0x5B01, 0x5B01,0x5B01,0x5904,0x5704,0x5701,0x5701,0x5701,0x5701,0x5604,0x560C, 0x5901,0x5901,0x5901,0x5901,0x6004,0x5604,0x5704,0x5704,0x5601,0x5601, 0x5601,0x5601,0x5401,0x5401,0x5602,0x5704,0x5704,0x5901,0x5901,0x5901, 0x5901,0x5701,0x5701,0x5902,0x5B04,0x5B04,0x6001,0x6001,0x6001,0x6001, 0x5B01,0x5B01,0x6001,0x6001,0x6208,0x8008,0x5201,0x5201,0x5201,0x5201, 0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201, 0x5201,0x5201,0x5410,0x5008,0x5008,0x4B08,0x4B08,0x4908,0x4908,0x4701, 0x4701,0x4701,0x4701,0x4604,0x4404,0x4604,0x4704,0x8004,0x4904,0x8004, 0x4B04,0x800C,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201, 0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5410,0x5201, 0x5201,0x5201,0x5201,0x5004,0x5004,0x5004,0x5001,0x5001,0x5001,0x5001, 0x4B04,0x4B04,0x4B04,0x4B01,0x4B01,0x4B01,0x4B01,0x4904,0x4904,0x4904, 0x4701,0x4701,0x4701,0x4701,0x4601,0x4601,0x4601,0x4601,0x4401,0x4401, 0x4401,0x4401,0x4604,0x4701,0x4701,0x4701,0x4701,0x4701,0x4701,0x4701, 0x4701,0x4701,0x4701,0x4701,0x4701,0x4701,0x4701,0x4701,0x4701,0x4704, 0x4701,0x4701,0x4601,0x4701,0x4901,0x4901,0x4901,0x4901,0x4604,0x4B01, 0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01, 0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B04,0x4B01,0x4B01,0x4901,0x4B01, 0x5001,0x5001,0x5001,0x5001,0x4904,0x5210,0x5408,0x5608,0x5708,0x5908, 0x5B08,0x6108,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201, 0x6201,0x6201,0x6201,0x6201,0x5904,0x6101,0x6101,0x6101,0x6101,0x6101, 0x6101,0x5902,0x6101,0x6101,0x6101,0x6101,0x6101,0x6101,0x5902,0x6201, 0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201, 0x6201,0x5904,0x6101,0x6101,0x6101,0x6101,0x6101,0x6101,0x5902,0x6101, 0x6101,0x6101,0x6101,0x6101,0x6101,0x5902,0x6204,0x6208,0x6208,0x6208, 0x6201,0x6201,0x6201,0x6201,0x6204,0x6208,0x6208,0x6208,0x6204,0x6104, 0x5904,0x6204,0x5904,0x6004,0x5904,0x6204,0x5904,0x6104,0x4904,0x4904, 0x4904,0x4908,0x8008,0x590A,0x5702,0x5602,0x5402,0x5204,0x8004,0x5B04, 0x8004,0x5704,0x8004,0x5404,0x8004,0x5B04,0x800C,0x5601,0x5601,0x5601, 0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5401,0x5401,0x5201, 0x5201,0x5101,0x5101,0x4B04,0x8004,0x5704,0x8004,0x5601,0x5601,0x5601, 0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601, 0x5601,0x5601,0x5601,0x5408,0x8008,0x5901,0x5901,0x5901,0x5901,0x5901, 0x5901,0x5901,0x5901,0x5901,0x5901,0x5701,0x5701,0x5601,0x5601,0x5401, 0x5401,0x5204,0x8004,0x5B04,0x8004,0x5704,0x8004,0x5404,0x8004,0x5908, 0x8004,0x5704,0x6104,0x6204,0x8004,0x5B04,0x5B01,0x5B01,0x5B01,0x5B01, 0x5904,0x8004,0x5104,0x5208,0x8004,0x5904,0x6201,0x6201,0x6201,0x6201, 0x6101,0x6101,0x6101,0x6101,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x5B01, 0x5B01,0x5B01,0x5B01,0x5904,0x8004,0x5904,0x5904,0x5904,0x5904,0x5904, 0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x8004,0x5904,0x6204,0x6104,0x5B04, 0x5904,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x8004,0x5904,0x5904,0x5904, 0x5904,0x5904,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x8008,0x5B0A,0x5901, 0x5901,0x5701,0x5701,0x5601,0x5601,0x5708,0x8008,0x590A,0x5701,0x5701, 0x5601,0x5601,0x5401,0x5401,0x5608,0x8008,0x5B01,0x5B01,0x5B01,0x5B01, 0x6101,0x6101,0x6201,0x6201,0x6104,0x5B04,0x5B01,0x5B01,0x5B01,0x5B01, 0x5904,0x5604,0x5904,0x5901,0x5901,0x5901,0x5901,0x5704,0x5604,0x5404, 0x5208,0x8004,0x5904,0x6201,0x6201,0x6201,0x6201,0x6101,0x6101,0x6101, 0x6101,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x5B01,0x5B01,0x5B01,0x5B01, 0x5904,0x8004,0x5904,0x5904,0x5904,0x5904,0x5904,0x5B01,0x5B01,0x5B01, 0x5B01,0x5904,0x8004,0x5904,0x6201,0x6201,0x6201,0x6201,0x6101,0x6101, 0x6101,0x6101,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x5B01,0x5B01,0x5B01, 0x5B01,0x5904,0x8004,0x5904,0x5904,0x5904,0x5904,0x5904,0x5B01,0x5B01, 0x5B01,0x5B01,0x5904,0x8008,0x5B0A,0x5901,0x5901,0x5701,0x5701,0x5601, 0x5601,0x5708,0x8008,0x590A,0x5701,0x5701,0x5601,0x5601,0x5401,0x5401, 0x5608,0x8008,0x5B01,0x5B01,0x5B01,0x5B01,0x6101,0x6101,0x6201,0x6201, 0x6104,0x5B04,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x5604,0x5904,0x5901, 0x5901,0x5901,0x5901,0x5704,0x5604,0x5404,0x5204,0x4904,0x4B04,0x5104, 0x5204,0x5204,0x5401,0x5401,0x5401,0x5401,0x5201,0x5201,0x5401,0x5401, 0x5604,0x5104,0x5204,0x5404,0x5604,0x5604,0x5701,0x5701,0x5701,0x5701, 0x5601,0x5601,0x5701,0x5701,0x5904,0x5904,0x5A04,0x5802,0x5A02,0x5B08, 0x8008,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01, 0x4B01,0x4B01,0x4B01,0x5404,0x5201,0x5201,0x5201,0x5201,0x5101,0x5101, 0x5101,0x5101,0x5B01,0x5B01,0x5B01,0x5B01,0x5901,0x5901,0x5901,0x5901, 0x6204,0x8004,0x6604,0x8004,0x6204,0x800C,0x5708,0x8004,0x5204,0x5708, 0x8004,0x5204,0x5704,0x5204,0x5704,0x5B04,0x6208,0x8008,0x6008,0x8004, 0x5904,0x6008,0x8004,0x5904,0x6004,0x5904,0x5604,0x5904,0x5208,0x8008, 0x5704,0x8004,0x570C,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x5704,0x5704, 0x5604,0x560C,0x5901,0x5901,0x5901,0x5901,0x6004,0x5604,0x5901,0x5901, 0x5901,0x5901,0x5704,0x570C,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x5704, 0x5701,0x5701,0x5701,0x5701,0x5604,0x560C,0x5901,0x5901,0x5901,0x5901, 0x6004,0x5604,0x5704,0x5704,0x5601,0x5601,0x5601,0x5601,0x5401,0x5401, 0x5602,0x5704,0x5704,0x5901,0x5901,0x5901,0x5901,0x5701,0x5701,0x5902, 0x5B04,0x5B04,0x6001,0x6001,0x6001,0x6001,0x5B01,0x5B01,0x6001,0x6001, 0x6208,0x8008,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201, 0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5410,0x5008, 0x5008,0x4B08,0x4B08,0x4908,0x4908,0x4701,0x4701,0x4701,0x4701,0x4604, 0x4404,0x4604,0x4704,0x8004,0x4904,0x8004,0x4B04,0x800C,0x5201,0x5201, 0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201, 0x5201,0x5201,0x5201,0x5201,0x5410,0x5201,0x5201,0x5201,0x5201,0x5004, 0x5004,0x5004,0x5001,0x5001,0x5001,0x5001,0x4B04,0x4B04,0x4B04,0x4B01, 0x4B01,0x4B01,0x4B01,0x4904,0x4904,0x4904,0x4701,0x4701,0x4701,0x4701, 0x4601,0x4601,0x4601,0x4601,0x4401,0x4401,0x4401,0x4401,0x4604,0x4701, 0x4701,0x4701,0x4701,0x4701,0x4701,0x4701,0x4701,0x4701,0x4701,0x4701, 0x4701,0x4701,0x4701,0x4701,0x4701,0x4704,0x4701,0x4701,0x4601,0x4701, 0x4901,0x4901,0x4901,0x4901,0x4604,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01, 0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01, 0x4B01,0x4B04,0x4B01,0x4B01,0x4901,0x4B01,0x5001,0x5001,0x5001,0x5001, 0x4904,0x5210,0x5408,0x5608,0x5708,0x5908,0x5B08,0x6108,0x6201,0x6201, 0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201, 0x5904,0x6101,0x6101,0x6101,0x6101,0x6101,0x6101,0x5902,0x6101,0x6101, 0x6101,0x6101,0x6101,0x6101,0x5902,0x6201,0x6201,0x6201,0x6201,0x6201, 0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x5904,0x6101,0x6101, 0x6101,0x6101,0x6101,0x6101,0x5902,0x6101,0x6101,0x6101,0x6101,0x6101, 0x6101,0x5902,0x6204,0x6208,0x6208,0x6208,0x6201,0x6201,0x6201,0x6201, 0x6204,0x6208,0x6208,0x6208,0x6204,0x6104,0x5904,0x6204,0x5904,0x6004, 0x5904,0x6204,0x5904,0x6104,0x4904,0x4904,0x4904,0x4908,0x8008,0x590A, 0x5702,0x5602,0x5402,0x5204,0x8004,0x5B04,0x8004,0x5704,0x8004,0x5404, 0x8004,0x5B04,0x800C,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601, 0x5601,0x5601,0x5601,0x5401,0x5401,0x5201,0x5201,0x5101,0x5101,0x4B04, 0x8004,0x5704,0x8004,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601, 0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5408, 0x8008,0x5901,0x5901,0x5901,0x5901,0x5901,0x5901,0x5901,0x5901,0x5901, 0x5901,0x5701,0x5701,0x5601,0x5601,0x5401,0x5401,0x5204,0x8004,0x5B04, 0x8004,0x5704,0x8004,0x5404,0x8004,0x5908,0x8004,0x5704,0x6104,0x6204, 0x8004,0x5B04,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x8004,0x5104,0x5208, 0x8004,0x5904,0x6201,0x6201,0x6201,0x6201,0x6101,0x6101,0x6101,0x6101, 0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x5B01,0x5B01,0x5B01,0x5B01,0x5904, 0x8004,0x5904,0x5904,0x5904,0x5904,0x5904,0x5B01,0x5B01,0x5B01,0x5B01, 0x5904,0x8004,0x5904,0x6204,0x6104,0x5B04,0x5904,0x5B01,0x5B01,0x5B01, 0x5B01,0x5904,0x8004,0x5904,0x5904,0x5904,0x5904,0x5904,0x5B01,0x5B01, 0x5B01,0x5B01,0x5904,0x8008,0x5B0A,0x5901,0x5901,0x5701,0x5701,0x5601, 0x5601,0x5708,0x8008,0x590A,0x5701,0x5701,0x5601,0x5601,0x5401,0x5401, 0x5608,0x8008,0x5B01,0x5B01,0x5B01,0x5B01,0x6101,0x6101,0x6201,0x6201, 0x6104,0x5B04,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x5604,0x5904,0x5901, 0x5901,0x5901,0x5901,0x5704,0x5604,0x5404,0x5208,0x8004,0x5904,0x6201, 0x6201,0x6201,0x6201,0x6101,0x6101,0x6101,0x6101,0x5B01,0x5B01,0x5B01, 0x5B01,0x5904,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x8004,0x5904,0x5904, 0x5904,0x5904,0x5904,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x8004,0x5904, 0x6201,0x6201,0x6201,0x6201,0x6101,0x6101,0x6101,0x6101,0x5B01,0x5B01, 0x5B01,0x5B01,0x5904,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x8004,0x5904, 0x5904,0x5904,0x5904,0x5904,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x8008, 0x5B0A,0x5901,0x5901,0x5701,0x5701,0x5601,0x5601,0x5708,0x8008,0x590A, 0x5701,0x5701,0x5601,0x5601,0x5401,0x5401,0x5608,0x8008,0x5B01,0x5B01, 0x5B01,0x5B01,0x6101,0x6101,0x6201,0x6201,0x6104,0x5B04,0x5B01,0x5B01, 0x5B01,0x5B01,0x5904,0x5604,0x5904,0x5901,0x5901,0x5901,0x5901,0x5704, 0x5604,0x5404,0x5204,0x4904,0x4B04,0x5104,0x5204,0x5204,0x5401,0x5401, 0x5401,0x5401,0x5201,0x5201,0x5401,0x5401,0x5604,0x5104,0x5204,0x5404, 0x5604,0x5604,0x5701,0x5701,0x5701,0x5701,0x5601,0x5601,0x5701,0x5701, 0x5904,0x5904,0x5A04,0x5802,0x5A02,0x5B08,0x8008,0x4B01,0x4B01,0x4B01, 0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x5404, 0x5201,0x5201,0x5201,0x5201,0x5101,0x5101,0x5101,0x5101,0x5B01,0x5B01, 0x5B01,0x5B01,0x5901,0x5901,0x5901,0x5901,0x6204,0x8004,0x6604,0x8004, 0x6204,0x800C,0x5208,0x8004,0x4904,0x5208,0x8004,0x4904,0x5204,0x4904, 0x5204,0x5604,0x5908,0x8008,0x5908,0x8004,0x5604,0x5908,0x8004,0x5604, 0x5904,0x5604,0x5304,0x5604,0x4B08,0x8014,0x5704,0x6001,0x6001,0x6001, 0x6001,0x5B01,0x5B01,0x5B01,0x5B01,0x5901,0x5901,0x5901,0x5901,0x5704, 0x5901,0x5901,0x5901,0x5901,0x5704,0x8004,0x5704,0x5704,0x5704,0x5704, 0x5704,0x5901,0x5901,0x5901,0x5901,0x5704,0x8004,0x5704,0x6001,0x6001, 0x6001,0x6001,0x5B01,0x5B01,0x5B01,0x5B01,0x5901,0x5901,0x5901,0x5901, 0x5704,0x5901,0x5901,0x5901,0x5901,0x5704,0x8004,0x5704,0x5704,0x5704, 0x5704,0x5704,0x5901,0x5901,0x5901,0x5901,0x5704,0x8004,0x5704,0x6001, 0x6001,0x6001,0x6001,0x5B01,0x5B01,0x5B01,0x5B01,0x5901,0x5901,0x5901, 0x5901,0x5704,0x5901,0x5901,0x5901,0x5901,0x5804,0x8004,0x5804,0x5804, 0x5804,0x5804,0x5804,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x8004,0x5904, 0x6001,0x6001,0x6001,0x6001,0x5A01,0x5A01,0x5A01,0x5A01,0x5901,0x5901, 0x5901,0x5901,0x5704,0x5701,0x5701,0x5701,0x5701,0x5604,0x8004,0x5604, 0x5604,0x5604,0x5604,0x5604,0x5901,0x5901,0x5901,0x5901,0x5704,0x8004, 0x5304,0x5704,0x5504,0x5304,0x5204,0x5201,0x5201,0x5201,0x5201,0x5104, 0x8004,0x5104,0x5104,0x5104,0x5104,0x5104,0x5401,0x5401,0x5401,0x5401, 0x5204,0x8004,0x4201,0x4201,0x4201,0x4201,0x4401,0x4401,0x4401,0x4401, 0x4601,0x4601,0x4601,0x4601,0x4701,0x4701,0x4701,0x4701,0x4901,0x4901, 0x4901,0x4901,0x5001,0x5001,0x5001,0x5001,0x4A04,0x8004,0x4601,0x4601, 0x4601,0x4601,0x4701,0x4701,0x4701,0x4701,0x4901,0x4901,0x4901,0x4901, 0x4A01,0x4A01,0x4A01,0x4A01,0x5101,0x5101,0x5101,0x5101,0x5401,0x5401, 0x5401,0x5401,0x5204,0x8004,0x5201,0x5201,0x5201,0x5201,0x5401,0x5401, 0x5401,0x5401,0x5601,0x5601,0x5601,0x5601,0x5701,0x5701,0x5701,0x5701, 0x5901,0x5901,0x5901,0x5901,0x5A01,0x5A01,0x5A01,0x5A01,0x5A01,0x5A01, 0x5A01,0x5A01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01, 0x6001,0x6001,0x6001,0x6001,0x6001,0x6001,0x6001,0x6001,0x6108,0x6201, 0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201, 0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201, 0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201, 0x6201,0x6210,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601, 0x5601,0x5601,0x5601,0x5601,0x5401,0x5401,0x5602,0x5708,0x8004,0x5204, 0x5708,0x8004,0x5204,0x5704,0x5204,0x5704,0x5B04,0x6208,0x8008,0x6008, 0x8004,0x5904,0x6008,0x8004,0x5904,0x6004,0x5904,0x5604,0x5904,0x5208, 0x8008,0x5704,0x8004,0x570C,0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x5704, 0x5701,0x5701,0x5701,0x5701,0x5604,0x560C,0x5901,0x5901,0x5901,0x5901, 0x6004,0x5604,0x5901,0x5901,0x5901,0x5901,0x5704,0x570C,0x5B01,0x5B01, 0x5B01,0x5B01,0x5904,0x5704,0x5701,0x5701,0x5701,0x5701,0x5604,0x560C, 0x5901,0x5901,0x5901,0x5901,0x6004,0x5604,0x5704,0x5704,0x5601,0x5601, 0x5601,0x5601,0x5401,0x5401,0x5602,0x5704,0x5704,0x5901,0x5901,0x5901, 0x5901,0x5701,0x5701,0x5902,0x5B04,0x5B04,0x6001,0x6001,0x6001,0x6001, 0x5B01,0x5B01,0x6001,0x6001,0x6208,0x8008,0x5201,0x5201,0x5201,0x5201, 0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201, 0x5201,0x5201,0x5410,0x5008,0x5008,0x4B08,0x4B08,0x4908,0x4908,0x4701, 0x4701,0x4701,0x4701,0x4604,0x4404,0x4604,0x4704,0x8004,0x4904,0x8004, 0x4B04,0x800C,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201, 0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5410,0x5201, 0x5201,0x5201,0x5201,0x5004,0x5004,0x5004,0x5001,0x5001,0x5001,0x5001, 0x4B04,0x4B04,0x4B04,0x4B01,0x4B01,0x4B01,0x4B01,0x4904,0x4904,0x4904, 0x4701,0x4701,0x4701,0x4701,0x4604,0x4404,0x4604,0x4714,0x4701,0x4701, 0x4601,0x4701,0x4901,0x4901,0x4901,0x4901,0x4604,0x4B14,0x4B01,0x4B01, 0x4901,0x4B01,0x5001,0x5001,0x5001,0x5001,0x4904,0x5210,0x5408,0x5608, 0x5708,0x5908,0x5B08,0x5108,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201, 0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x5904,0x6101,0x6101,0x6101, 0x6101,0x6101,0x6101,0x5902,0x5101,0x5101,0x5101,0x5101,0x5101,0x5101, 0x5902,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201, 0x6201,0x6201,0x6201,0x5904,0x6101,0x6101,0x6101,0x6101,0x6101,0x6101, 0x5902,0x5101,0x5101,0x5101,0x5101,0x5101,0x5101,0x5902,0x6204,0x5904, 0x6104,0x5904,0x6204,0x5904,0x6104,0x5904,0x6204,0x4204,0x4204,0x4204, 0x4208,0x8008,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201, 0x5201,0x5201,0x5001,0x5001,0x4B01,0x4B01,0x4901,0x4901,0x4704,0x8004, 0x5404,0x8004,0x5004,0x8004,0x4904,0x8004,0x5204,0x800C,0x5B01,0x5B01, 0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5901,0x5901, 0x5701,0x5701,0x5601,0x5601,0x5404,0x8004,0x6004,0x8004,0x5B01,0x5B01, 0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01, 0x5B01,0x5B01,0x5B01,0x5B01,0x5908,0x8008,0x8004,0x6204,0x6204,0x6204, 0x6204,0x6204,0x6204,0x6204,0x6204,0x6204,0x6204,0x6204,0x6201,0x6201, 0x6201,0x6201,0x6001,0x6001,0x6001,0x6001,0x5901,0x5901,0x5901,0x5901, 0x5604,0x5601,0x5601,0x5601,0x5601,0x5704,0x8004,0x5404,0x5401,0x5401, 0x5401,0x5401,0x5204,0x8004,0x4604,0x4708,0x8004,0x5204,0x5701,0x5701, 0x5701,0x5701,0x5601,0x5601,0x5601,0x5601,0x5401,0x5401,0x5401,0x5401, 0x5204,0x5401,0x5401,0x5401,0x5401,0x5204,0x8004,0x5204,0x5204,0x5204, 0x5204,0x5204,0x5401,0x5401,0x5401,0x5401,0x5204,0x8004,0x5204,0x5704, 0x5604,0x5404,0x5204,0x5401,0x5401,0x5401,0x5401,0x5204,0x8004,0x5204, 0x5204,0x5204,0x5204,0x5204,0x5401,0x5401,0x5401,0x5401,0x5204,0x8008, 0x540A,0x5201,0x5201,0x5001,0x5001,0x4B01,0x4B01,0x5008,0x8008,0x520A, 0x5001,0x5001,0x4B01,0x4B01,0x4901,0x4901,0x4B08,0x8008,0x5401,0x5401, 0x5401,0x5401,0x5601,0x5601,0x5701,0x5701,0x5604,0x5404,0x5401,0x5401, 0x5401,0x5401,0x5204,0x4B04,0x5204,0x5201,0x5201,0x5201,0x5201,0x5004, 0x4B04,0x4904,0x4708,0x8004,0x5204,0x5701,0x5701,0x5701,0x5701,0x5601, 0x5601,0x5601,0x5601,0x5401,0x5401,0x5401,0x5401,0x5204,0x5401,0x5401, 0x5401,0x5401,0x5204,0x8004,0x5204,0x5204,0x5204,0x5204,0x5204,0x5401, 0x5401,0x5401,0x5401,0x5204,0x8004,0x5204,0x5701,0x5701,0x5701,0x5701, 0x5601,0x5601,0x5601,0x5601,0x5401,0x5401,0x5401,0x5401,0x5204,0x5401, 0x5401,0x5401,0x5401,0x5204,0x8004,0x5204,0x5204,0x5204,0x5204,0x5204, 0x5401,0x5401,0x5401,0x5401,0x5204,0x8008,0x640A,0x6201,0x6201,0x6001, 0x6001,0x5B01,0x5B01,0x6008,0x8008,0x620A,0x6001,0x6001,0x5B01,0x5B01, 0x5901,0x5901,0x5B08,0x8008,0x5401,0x5401,0x5401,0x5401,0x5601,0x5601, 0x5701,0x5701,0x5604,0x5404,0x5204,0x5704,0x5B04,0x6204,0x6201,0x6201, 0x6201,0x6201,0x6004,0x5B04,0x5904,0x5704,0x4204,0x4404,0x4604,0x4704, 0x4704,0x4901,0x4901,0x4901,0x4901,0x4701,0x4701,0x4901,0x4901,0x4B04, 0x4604,0x4704,0x4904,0x4B04,0x4B04,0x5001,0x5001,0x5001,0x5001,0x4B01, 0x4B01,0x5001,0x5001,0x5204,0x5204,0x5301,0x5301,0x5301,0x5301,0x5101, 0x5101,0x5301,0x5301,0x5408,0x8008,0x440C,0x4904,0x4704,0x4604,0x4404, 0x4204,0x5201,0x5201,0x5201,0x5201,0x5101,0x5101,0x5101,0x5101,0x5001, 0x5001,0x5001,0x5001,0x4B01,0x4B01,0x4B01,0x4B01,0x5201,0x5201,0x5201, 0x5201,0x5101,0x5101,0x5101,0x5101,0x5001,0x5001,0x5001,0x5001,0x4B04, 0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401, 0x4401,0x4401,0x4904,0x4701,0x4701,0x4701,0x4701,0x4601,0x4601,0x4601, 0x4601,0x4401,0x4401,0x4401,0x4401,0x4204,0x5201,0x5201,0x5201,0x5201, 0x5401,0x5401,0x5401,0x5401,0x5601,0x5601,0x5601,0x5601,0x5701,0x5701, 0x5701,0x5701,0x5201,0x5201,0x5201,0x5201,0x5401,0x5401,0x5401,0x5401, 0x5601,0x5601,0x5601,0x5601,0x5704,0x5908,0x8008,0x6208,0x8008,0x5708, 0x8004,0x5204,0x4B04,0x4704,0x4B04,0x5204,0x5704,0x5204,0x5704,0x5B04, 0x6208,0x5608,0x5708,0x8004,0x5204,0x4B04,0x4704,0x4B04,0x5204,0x5704, 0x5204,0x5704,0x5B04,0x6208,0x5608,0x5708,0x8008,0x5708,0x8008,0x5708, 0x4706,0x4702,0x4708,0x8008,0x5208,0x8004,0x4904,0x5208,0x8004,0x4904, 0x5204,0x4904,0x5204,0x5604,0x5908,0x8008,0x5908,0x8004,0x5604,0x5908, 0x8004,0x5604,0x5904,0x5604,0x5304,0x5604,0x4B08,0x8014,0x5704,0x6001, 0x6001,0x6001,0x6001,0x5B01,0x5B01,0x5B01,0x5B01,0x5901,0x5901,0x5901, 0x5901,0x5704,0x5901,0x5901,0x5901,0x5901,0x5704,0x8004,0x5704,0x5704, 0x5704,0x5704,0x5704,0x5901,0x5901,0x5901,0x5901,0x5704,0x8004,0x5704, 0x6001,0x6001,0x6001,0x6001,0x5B01,0x5B01,0x5B01,0x5B01,0x5901,0x5901, 0x5901,0x5901,0x5704,0x5901,0x5901,0x5901,0x5901,0x5704,0x8004,0x5704, 0x5704,0x5704,0x5704,0x5704,0x5901,0x5901,0x5901,0x5901,0x5704,0x8004, 0x5704,0x6001,0x6001,0x6001,0x6001,0x5B01,0x5B01,0x5B01,0x5B01,0x5901, 0x5901,0x5901,0x5901,0x5704,0x5901,0x5901,0x5901,0x5901,0x5804,0x8004, 0x5804,0x5804,0x5804,0x5804,0x5804,0x5B01,0x5B01,0x5B01,0x5B01,0x5904, 0x8004,0x5904,0x6001,0x6001,0x6001,0x6001,0x5A01,0x5A01,0x5A01,0x5A01, 0x5901,0x5901,0x5901,0x5901,0x5704,0x5701,0x5701,0x5701,0x5701,0x5604, 0x8004,0x5604,0x5604,0x5604,0x5604,0x5604,0x5901,0x5901,0x5901,0x5901, 0x5704,0x8004,0x5304,0x5704,0x5504,0x5304,0x5204,0x5201,0x5201,0x5201, 0x5201,0x5104,0x8004,0x5104,0x5104,0x5104,0x5104,0x5104,0x5401,0x5401, 0x5401,0x5401,0x5204,0x8004,0x4201,0x4201,0x4201,0x4201,0x4401,0x4401, 0x4401,0x4401,0x4601,0x4601,0x4601,0x4601,0x4701,0x4701,0x4701,0x4701, 0x4901,0x4901,0x4901,0x4901,0x5001,0x5001,0x5001,0x5001,0x4A04,0x8004, 0x4601,0x4601,0x4601,0x4601,0x4701,0x4701,0x4701,0x4701,0x4901,0x4901, 0x4901,0x4901,0x4A01,0x4A01,0x4A01,0x4A01,0x5101,0x5101,0x5101,0x5101, 0x5401,0x5401,0x5401,0x5401,0x5204,0x8004,0x5201,0x5201,0x5201,0x5201, 0x5401,0x5401,0x5401,0x5401,0x5601,0x5601,0x5601,0x5601,0x5701,0x5701, 0x5701,0x5701,0x5901,0x5901,0x5901,0x5901,0x5A01,0x5A01,0x5A01,0x5A01, 0x5A01,0x5A01,0x5A01,0x5A01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01, 0x5B01,0x5B01,0x6001,0x6001,0x6001,0x6001,0x6001,0x6001,0x6001,0x6001, 0x6108,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201, 0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201, 0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201, 0x6201,0x6201,0x6201,0x6210,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601, 0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5401,0x5401,0x5602,0x5708, 0x8004,0x5204,0x5708,0x8004,0x5204,0x5704,0x5204,0x5704,0x5B04,0x6208, 0x8008,0x6008,0x8004,0x5904,0x6008,0x8004,0x5904,0x6004,0x5904,0x5604, 0x5904,0x5208,0x8008,0x5704,0x8004,0x570C,0x5B01,0x5B01,0x5B01,0x5B01, 0x5904,0x5704,0x5701,0x5701,0x5701,0x5701,0x5604,0x560C,0x5901,0x5901, 0x5901,0x5901,0x6004,0x5604,0x5901,0x5901,0x5901,0x5901,0x5704,0x570C, 0x5B01,0x5B01,0x5B01,0x5B01,0x5904,0x5704,0x5701,0x5701,0x5701,0x5701, 0x5604,0x560C,0x5901,0x5901,0x5901,0x5901,0x6004,0x5604,0x5704,0x5704, 0x5601,0x5601,0x5601,0x5601,0x5401,0x5401,0x5602,0x5704,0x5704,0x5901, 0x5901,0x5901,0x5901,0x5701,0x5701,0x5902,0x5B04,0x5B04,0x6001,0x6001, 0x6001,0x6001,0x5B01,0x5B01,0x6001,0x6001,0x6208,0x8008,0x5201,0x5201, 0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201, 0x5201,0x5201,0x5201,0x5201,0x5410,0x5008,0x5008,0x4B08,0x4B08,0x4908, 0x4908,0x4701,0x4701,0x4701,0x4701,0x4604,0x4404,0x4604,0x4704,0x8004, 0x4904,0x8004,0x4B04,0x800C,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201, 0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201, 0x5410,0x5201,0x5201,0x5201,0x5201,0x5004,0x5004,0x5004,0x5001,0x5001, 0x5001,0x5001,0x4B04,0x4B04,0x4B04,0x4B01,0x4B01,0x4B01,0x4B01,0x4904, 0x4904,0x4904,0x4701,0x4701,0x4701,0x4701,0x4604,0x4404,0x4604,0x4714, 0x4701,0x4701,0x4601,0x4701,0x4901,0x4901,0x4901,0x4901,0x4604,0x4B14, 0x4B01,0x4B01,0x4901,0x4B01,0x5001,0x5001,0x5001,0x5001,0x4904,0x5210, 0x5408,0x5608,0x5708,0x5908,0x5B08,0x5108,0x6201,0x6201,0x6201,0x6201, 0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x5904,0x6101, 0x6101,0x6101,0x6101,0x6101,0x6101,0x5902,0x5101,0x5101,0x5101,0x5101, 0x5101,0x5101,0x5902,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201,0x6201, 0x6201,0x6201,0x6201,0x6201,0x6201,0x5904,0x6101,0x6101,0x6101,0x6101, 0x6101,0x6101,0x5902,0x5101,0x5101,0x5101,0x5101,0x5101,0x5101,0x5902, 0x6204,0x5904,0x6104,0x5904,0x6204,0x5904,0x6104,0x5904,0x6204,0x4204, 0x4204,0x4204,0x4208,0x8008,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201, 0x5201,0x5201,0x5201,0x5201,0x5001,0x5001,0x4B01,0x4B01,0x4901,0x4901, 0x4704,0x8004,0x5404,0x8004,0x5004,0x8004,0x4904,0x8004,0x5204,0x800C, 0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01, 0x5901,0x5901,0x5701,0x5701,0x5601,0x5601,0x5404,0x8004,0x6004,0x8004, 0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01, 0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5B01,0x5908,0x8008,0x8004,0x6204, 0x6204,0x6204,0x6204,0x6204,0x6204,0x6204,0x6204,0x6204,0x6204,0x6204, 0x6201,0x6201,0x6201,0x6201,0x6001,0x6001,0x6001,0x6001,0x5901,0x5901, 0x5901,0x5901,0x5604,0x5601,0x5601,0x5601,0x5601,0x5704,0x8004,0x5404, 0x5401,0x5401,0x5401,0x5401,0x5204,0x8004,0x4604,0x4708,0x8004,0x5204, 0x5701,0x5701,0x5701,0x5701,0x5601,0x5601,0x5601,0x5601,0x5401,0x5401, 0x5401,0x5401,0x5204,0x5401,0x5401,0x5401,0x5401,0x5204,0x8004,0x5204, 0x5204,0x5204,0x5204,0x5204,0x5401,0x5401,0x5401,0x5401,0x5204,0x8004, 0x5204,0x5704,0x5604,0x5404,0x5204,0x5401,0x5401,0x5401,0x5401,0x5204, 0x8004,0x5204,0x5204,0x5204,0x5204,0x5204,0x5401,0x5401,0x5401,0x5401, 0x5204,0x8008,0x540A,0x5201,0x5201,0x5001,0x5001,0x4B01,0x4B01,0x5008, 0x8008,0x520A,0x5001,0x5001,0x4B01,0x4B01,0x4901,0x4901,0x4B08,0x8008, 0x5401,0x5401,0x5401,0x5401,0x5601,0x5601,0x5701,0x5701,0x5604,0x5404, 0x5401,0x5401,0x5401,0x5401,0x5204,0x4B04,0x5204,0x5201,0x5201,0x5201, 0x5201,0x5004,0x4B04,0x4904,0x4708,0x8004,0x5204,0x5701,0x5701,0x5701, 0x5701,0x5601,0x5601,0x5601,0x5601,0x5401,0x5401,0x5401,0x5401,0x5204, 0x5401,0x5401,0x5401,0x5401,0x5204,0x8004,0x5204,0x5204,0x5204,0x5204, 0x5204,0x5401,0x5401,0x5401,0x5401,0x5204,0x8004,0x5204,0x5701,0x5701, 0x5701,0x5701,0x5601,0x5601,0x5601,0x5601,0x5401,0x5401,0x5401,0x5401, 0x5204,0x5401,0x5401,0x5401,0x5401,0x5204,0x8004,0x5204,0x5204,0x5204, 0x5204,0x5204,0x5401,0x5401,0x5401,0x5401,0x5204,0x8008,0x640A,0x6201, 0x6201,0x6001,0x6001,0x5B01,0x5B01,0x6008,0x8008,0x620A,0x6001,0x6001, 0x5B01,0x5B01,0x5901,0x5901,0x5B08,0x8008,0x5401,0x5401,0x5401,0x5401, 0x5601,0x5601,0x5701,0x5701,0x5604,0x5404,0x5204,0x5704,0x5B04,0x6204, 0x6201,0x6201,0x6201,0x6201,0x6004,0x5B04,0x5904,0x5704,0x4204,0x4404, 0x4604,0x4704,0x4704,0x4901,0x4901,0x4901,0x4901,0x4701,0x4701,0x4901, 0x4901,0x4B04,0x4604,0x4704,0x4904,0x4B04,0x4B04,0x5001,0x5001,0x5001, 0x5001,0x4B01,0x4B01,0x5001,0x5001,0x5204,0x5204,0x5301,0x5301,0x5301, 0x5301,0x5101,0x5101,0x5301,0x5301,0x5408,0x8008,0x440C,0x4904,0x4704, 0x4604,0x4404,0x4204,0x5201,0x5201,0x5201,0x5201,0x5101,0x5101,0x5101, 0x5101,0x5001,0x5001,0x5001,0x5001,0x4B01,0x4B01,0x4B01,0x4B01,0x5201, 0x5201,0x5201,0x5201,0x5101,0x5101,0x5101,0x5101,0x5001,0x5001,0x5001, 0x5001,0x4B04,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401, 0x4401,0x4401,0x4401,0x4401,0x4904,0x4701,0x4701,0x4701,0x4701,0x4601, 0x4601,0x4601,0x4601,0x4401,0x4401,0x4401,0x4401,0x4204,0x5201,0x5201, 0x5201,0x5201,0x5401,0x5401,0x5401,0x5401,0x5601,0x5601,0x5601,0x5601, 0x5701,0x5701,0x5701,0x5701,0x5201,0x5201,0x5201,0x5201,0x5401,0x5401, 0x5401,0x5401,0x5601,0x5601,0x5601,0x5601,0x5704,0x5908,0x8008,0x6208, 0x8008,0x5708,0x8004,0x5204,0x4B04,0x4704,0x4B04,0x5204,0x5704,0x5204, 0x5704,0x5B04,0x6208,0x5608,0x5708,0x8004,0x5204,0x4B04,0x4704,0x4B04, 0x5204,0x5704,0x5204,0x5704,0x5B04,0x6208,0x5608,0x5708,0x8008,0x5708, 0x8008,0x5708,0x4706,0x4702,0x4708,0x8008, 0x0000 }; const unsigned Voice2 [] = { 0x4708,0x8004,0x4204,0x4708,0x8004,0x4204,0x4704,0x4204,0x4704,0x4B04, 0x5208,0x8008,0x5008,0x8004,0x4904,0x5008,0x8004,0x4904,0x5004,0x4904, 0x4604,0x4904,0x4208,0x8008,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704, 0x4704,0x4704,0x4904,0x4904,0x4904,0x4904,0x4901,0x4901,0x4901,0x4901, 0x5004,0x4601,0x4601,0x4601,0x4601,0x4904,0x4704,0x4704,0x4704,0x4704, 0x4704,0x4704,0x4704,0x4704,0x4904,0x4904,0x4904,0x4904,0x4901,0x4901, 0x4901,0x4901,0x5004,0x4601,0x4601,0x4601,0x4601,0x4904,0x4210,0x4210, 0x4210,0x4208,0x8028,0x3610,0x3710,0x4008,0x4008,0x3908,0x3208,0x3204, 0x8004,0x4204,0x8004,0x4208,0x8028,0x4601,0x4601,0x4601,0x4601,0x4601, 0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601, 0x4601,0x4710,0x4008,0x4004,0x4004,0x3908,0x3904,0x3904,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x4704,0x4704,0x4704,0x4704,0x4704, 0x4904,0x4904,0x4704,0x4704,0x4604,0x4604,0x4704,0x4704,0x4404,0x4404, 0x4210,0x4410,0x4210,0x4410,0x4604,0x4704,0x4904,0x4704,0x4604,0x4704, 0x4904,0x4604,0x4B04,0x4904,0x4704,0x4904,0x4B04,0x4904,0x4804,0x4B04, 0x4904,0x4904,0x4904,0x4904,0x4904,0x4904,0x4904,0x4904,0x4904,0x3904, 0x3904,0x3904,0x3908,0x8020,0x4604,0x8004,0x3B04,0x8004,0x4704,0x8004, 0x4404,0x8004,0x4104,0x800C,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401, 0x4401,0x4401,0x4204,0x8004,0x4404,0x8004,0x4201,0x4201,0x4201,0x4201, 0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201, 0x4201,0x4201,0x4108,0x8010,0x4101,0x4101,0x4101,0x4101,0x4101,0x4101, 0x4101,0x4101,0x4204,0x8004,0x4604,0x8004,0x3B04,0x8004,0x3704,0x8004, 0x3408,0x8004,0x4404,0x4704,0x4604,0x8004,0x5704,0x5701,0x5701,0x5701, 0x5701,0x5604,0x8004,0x4704,0x4204,0x4204,0x4404,0x4404,0x4604,0x4604, 0x4204,0x4204,0x4104,0x4104,0x4204,0x4204,0x4404,0x4404,0x4104,0x4104, 0x4204,0x4204,0x4404,0x4404,0x4604,0x4604,0x4204,0x4204,0x4104,0x4104, 0x4204,0x4204,0x4404,0x4404,0x4104,0x4104,0x4204,0x4204,0x4604,0x4404, 0x4304,0x3B04,0x4104,0x4304,0x4404,0x4704,0x4404,0x4204,0x4104,0x3904, 0x3B04,0x4104,0x5204,0x5204,0x5204,0x5204,0x5204,0x5204,0x5204,0x5204, 0x5204,0x4904,0x4904,0x4904,0x4904,0x4904,0x4904,0x4704,0x4604,0x4204, 0x4404,0x4404,0x4604,0x4604,0x4204,0x4204,0x4104,0x4104,0x4204,0x4204, 0x4404,0x4404,0x4104,0x4104,0x4204,0x4204,0x4404,0x4404,0x4604,0x4604, 0x4204,0x4204,0x4104,0x4104,0x4204,0x4204,0x4404,0x4404,0x4104,0x4104, 0x4204,0x4204,0x4604,0x4404,0x4304,0x3B04,0x4104,0x4304,0x4404,0x4704, 0x4404,0x4204,0x4104,0x3904,0x3B04,0x4104,0x4204,0x5204,0x5204,0x5204, 0x5204,0x5204,0x5204,0x5204,0x5204,0x4904,0x4904,0x4904,0x4904,0x4904, 0x4904,0x4704,0x4604,0x3904,0x3B04,0x4104,0x4204,0x4204,0x4404,0x4404, 0x4604,0x4104,0x4204,0x4404,0x4604,0x4604,0x4704,0x4704,0x4904,0x4904, 0x4A04,0x4A04,0x4B08,0x8008,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401, 0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401, 0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4201,0x4201, 0x4201,0x4201,0x4104,0x5204,0x8004,0x5204,0x8004,0x5204,0x800C,0x4708, 0x8004,0x4204,0x4708,0x8004,0x4204,0x4704,0x4204,0x4704,0x4B04,0x5208, 0x8008,0x5008,0x8004,0x4904,0x5008,0x8004,0x4904,0x5004,0x4904,0x4604, 0x4904,0x4208,0x8008,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704, 0x4704,0x4904,0x4904,0x4904,0x4904,0x4901,0x4901,0x4901,0x4901,0x5004, 0x4601,0x4601,0x4601,0x4601,0x4904,0x4704,0x4704,0x4704,0x4704,0x4704, 0x4704,0x4704,0x4704,0x4904,0x4904,0x4904,0x4904,0x4901,0x4901,0x4901, 0x4901,0x5004,0x4601,0x4601,0x4601,0x4601,0x4904,0x4210,0x4210,0x4210, 0x4208,0x8028,0x3610,0x3710,0x4008,0x4008,0x3908,0x3208,0x3204,0x8004, 0x4204,0x8004,0x4208,0x8028,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601, 0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601, 0x4710,0x4008,0x4004,0x4004,0x3908,0x3904,0x3904,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4904, 0x4904,0x4704,0x4704,0x4604,0x4604,0x4704,0x4704,0x4404,0x4404,0x4210, 0x4410,0x4210,0x4410,0x4604,0x4704,0x4904,0x4704,0x4604,0x4704,0x4904, 0x4604,0x4B04,0x4904,0x4704,0x4904,0x4B04,0x4904,0x4804,0x4B04,0x4904, 0x4904,0x4904,0x4904,0x4904,0x4904,0x4904,0x4904,0x4904,0x3904,0x3904, 0x3904,0x3908,0x8020,0x4604,0x8004,0x3B04,0x8004,0x4704,0x8004,0x4404, 0x8004,0x4104,0x800C,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401, 0x4401,0x4204,0x8004,0x4404,0x8004,0x4201,0x4201,0x4201,0x4201,0x4201, 0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201, 0x4201,0x4108,0x8010,0x4101,0x4101,0x4101,0x4101,0x4101,0x4101,0x4101, 0x4101,0x4204,0x8004,0x4604,0x8004,0x3B04,0x8004,0x3704,0x8004,0x3408, 0x8004,0x4404,0x4704,0x4604,0x8004,0x5704,0x5701,0x5701,0x5701,0x5701, 0x5604,0x8004,0x4704,0x4204,0x4204,0x4404,0x4404,0x4604,0x4604,0x4204, 0x4204,0x4104,0x4104,0x4204,0x4204,0x4404,0x4404,0x4104,0x4104,0x4204, 0x4204,0x4404,0x4404,0x4604,0x4604,0x4204,0x4204,0x4104,0x4104,0x4204, 0x4204,0x4404,0x4404,0x4104,0x4104,0x4204,0x4204,0x4604,0x4404,0x4304, 0x3B04,0x4104,0x4304,0x4404,0x4704,0x4404,0x4204,0x4104,0x3904,0x3B04, 0x4104,0x5204,0x5204,0x5204,0x5204,0x5204,0x5204,0x5204,0x5204,0x5204, 0x4904,0x4904,0x4904,0x4904,0x4904,0x4904,0x4704,0x4604,0x4204,0x4404, 0x4404,0x4604,0x4604,0x4204,0x4204,0x4104,0x4104,0x4204,0x4204,0x4404, 0x4404,0x4104,0x4104,0x4204,0x4204,0x4404,0x4404,0x4604,0x4604,0x4204, 0x4204,0x4104,0x4104,0x4204,0x4204,0x4404,0x4404,0x4104,0x4104,0x4204, 0x4204,0x4604,0x4404,0x4304,0x3B04,0x4104,0x4304,0x4404,0x4704,0x4404, 0x4204,0x4104,0x3904,0x3B04,0x4104,0x4204,0x5204,0x5204,0x5204,0x5204, 0x5204,0x5204,0x5204,0x5204,0x4904,0x4904,0x4904,0x4904,0x4904,0x4904, 0x4704,0x4604,0x3904,0x3B04,0x4104,0x4204,0x4204,0x4404,0x4404,0x4604, 0x4104,0x4204,0x4404,0x4604,0x4604,0x4704,0x4704,0x4904,0x4904,0x4A04, 0x4A04,0x4B08,0x8008,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401, 0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401, 0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4401,0x4201,0x4201,0x4201, 0x4201,0x4104,0x5204,0x8004,0x5204,0x8004,0x5204,0x800C,0x4208,0x8004, 0x3904,0x4208,0x8004,0x3904,0x4204,0x3904,0x4204,0x4604,0x4908,0x8008, 0x4908,0x8004,0x4604,0x4908,0x8004,0x4604,0x4904,0x4604,0x4304,0x4604, 0x3B08,0x8008,0x4004,0x4004,0x4204,0x4204,0x4404,0x4404,0x4004,0x4004, 0x3B04,0x3B04,0x4004,0x4004,0x4204,0x4204,0x3B04,0x3B04,0x4004,0x4004, 0x4204,0x4204,0x4404,0x4404,0x4004,0x4004,0x3B04,0x3B04,0x4004,0x4004, 0x4204,0x4204,0x3B04,0x3B04,0x4004,0x4004,0x4204,0x4204,0x4404,0x4404, 0x4004,0x4004,0x3B04,0x3B04,0x4004,0x4004,0x4204,0x4204,0x3B04,0x3B04, 0x3904,0x3904,0x3B04,0x3B04,0x4004,0x4004,0x3904,0x3904,0x3904,0x3904, 0x3A04,0x3A04,0x4004,0x4004,0x3904,0x3904,0x3704,0x3704,0x3604,0x3604, 0x3704,0x3704,0x4604,0x4604,0x4704,0x4704,0x4604,0x4604,0x4704,0x3704, 0x3604,0x3704,0x3908,0x8004,0x3201,0x3201,0x3201,0x3201,0x3401,0x3401, 0x3401,0x3401,0x3601,0x3601,0x3601,0x3601,0x3701,0x3701,0x3701,0x3701, 0x3901,0x3901,0x3901,0x3901,0x4001,0x4001,0x4001,0x4001,0x3A04,0x8004, 0x3601,0x3601,0x3601,0x3601,0x3701,0x3701,0x3701,0x3701,0x3901,0x3901, 0x3901,0x3901,0x3A01,0x3A01,0x3A01,0x3A01,0x4101,0x4101,0x4101,0x4101, 0x4401,0x4401,0x4401,0x4401,0x4204,0x8038,0x4B04,0x4B04,0x4B01,0x4B01, 0x4B01,0x4B01,0x5004,0x4904,0x4904,0x4901,0x4901,0x4901,0x4901,0x4B04, 0x4704,0x4704,0x4701,0x4701,0x4701,0x4701,0x4B04,0x4B01,0x4B01,0x4B01, 0x4B01,0x4904,0x4704,0x4204,0x3B08,0x8004,0x4204,0x4708,0x8004,0x4204, 0x4704,0x4204,0x4704,0x4B04,0x5208,0x8008,0x5008,0x8004,0x4904,0x5008, 0x8004,0x4904,0x5004,0x4904,0x4604,0x4904,0x4208,0x8008,0x4704,0x4704, 0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704, 0x4701,0x4701,0x4701,0x4701,0x4B04,0x4401,0x4401,0x4401,0x4401,0x4704, 0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704, 0x4704,0x4704,0x4701,0x4701,0x4701,0x4701,0x4B04,0x4401,0x4401,0x4401, 0x4401,0x4704,0x4210,0x4210,0x4210,0x4208,0x8028,0x3610,0x3710,0x4008, 0x4008,0x3908,0x3908,0x3204,0x8004,0x4204,0x8004,0x4208,0x8028,0x4601, 0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601, 0x4601,0x4601,0x4601,0x4601,0x4601,0x4710,0x4008,0x4004,0x4004,0x3908, 0x3904,0x3904,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x4704, 0x4704,0x4704,0x4704,0x4704,0x4904,0x4904,0x4704,0x4704,0x4604,0x4604, 0x4704,0x4704,0x4404,0x4404,0x4210,0x4410,0x4210,0x4410,0x4208,0x4408, 0x4208,0x4408,0x4204,0x3204,0x3204,0x3204,0x3208,0x8020,0x3B04,0x8004, 0x3404,0x8004,0x4004,0x8004,0x3904,0x8004,0x3604,0x800C,0x4901,0x4901, 0x4901,0x4901,0x4901,0x4901,0x4901,0x4901,0x4704,0x8004,0x4904,0x8004, 0x4B10,0x4908,0x8008,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201, 0x5201,0x5201,0x5201,0x5001,0x5001,0x4B01,0x4B01,0x4901,0x4901,0x4704, 0x8004,0x5404,0x8004,0x5004,0x8004,0x4904,0x8004,0x5208,0x8004,0x5004, 0x5001,0x5001,0x5001,0x5001,0x4B04,0x8004,0x5004,0x5001,0x5001,0x5001, 0x5001,0x4B04,0x8004,0x4004,0x3704,0x3704,0x3904,0x3904,0x3B04,0x3B04, 0x3704,0x3704,0x3604,0x3604,0x3704,0x3704,0x3904,0x3904,0x3604,0x3604, 0x3704,0x3704,0x3904,0x3904,0x3B04,0x3B04,0x3704,0x3704,0x3604,0x3604, 0x3704,0x3704,0x3904,0x3904,0x3604,0x3604,0x3704,0x4704,0x4B04,0x4904, 0x4804,0x4404,0x4604,0x4804,0x4904,0x5004,0x4904,0x4704,0x4604,0x4204, 0x4404,0x4604,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704, 0x4704,0x4204,0x4204,0x4204,0x4204,0x4204,0x4204,0x4004,0x3B04,0x3704, 0x3904,0x3904,0x3B04,0x3B04,0x3704,0x3704,0x3604,0x3604,0x3704,0x3704, 0x3904,0x3904,0x3604,0x3604,0x3704,0x4704,0x4904,0x4904,0x4B04,0x4B04, 0x4704,0x4704,0x4604,0x4604,0x4704,0x4704,0x4904,0x4904,0x4604,0x4604, 0x4704,0x4704,0x4B04,0x4904,0x4804,0x4404,0x4604,0x4804,0x4904,0x5004, 0x4904,0x4704,0x4604,0x4204,0x4404,0x4604,0x4704,0x4704,0x4704,0x4704, 0x4704,0x4704,0x4704,0x4704,0x4701,0x4701,0x4701,0x4701,0x4904,0x5004, 0x5004,0x5004,0x5004,0x5004,0x4B04,0x4904,0x4204,0x4404,0x4604,0x4704, 0x4704,0x4904,0x4904,0x4B04,0x3604,0x3704,0x3904,0x3B04,0x3B04,0x4004, 0x4004,0x4004,0x4004,0x4104,0x4104,0x4208,0x8008,0x3901,0x3901,0x3901, 0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901, 0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901, 0x3901,0x3701,0x3701,0x3701,0x3701,0x3604,0x3708,0x8018,0x3901,0x3901, 0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901, 0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901, 0x3901,0x3901,0x3701,0x3701,0x3701,0x3701,0x3604,0x3708,0x8008,0x4708, 0x8008,0x4408,0x8008,0x4708,0x8008,0x3710,0x3710,0x3710,0x3708,0x3908, 0x3710,0x3710,0x3710,0x3708,0x3908,0x3704,0x3B04,0x4204,0x4704,0x4B04, 0x4704,0x5204,0x4B04,0x4708,0x3706,0x3702,0x3708,0x8008,0x4208,0x8004, 0x3904,0x4208,0x8004,0x3904,0x4204,0x3904,0x4204,0x4604,0x4908,0x8008, 0x4908,0x8004,0x4604,0x4908,0x8004,0x4604,0x4904,0x4604,0x4304,0x4604, 0x3B08,0x8008,0x4004,0x4004,0x4204,0x4204,0x4404,0x4404,0x4004,0x4004, 0x3B04,0x3B04,0x4004,0x4004,0x4204,0x4204,0x3B04,0x3B04,0x4004,0x4004, 0x4204,0x4204,0x4404,0x4404,0x4004,0x4004,0x3B04,0x3B04,0x4004,0x4004, 0x4204,0x4204,0x3B04,0x3B04,0x4004,0x4004,0x4204,0x4204,0x4404,0x4404, 0x4004,0x4004,0x3B04,0x3B04,0x4004,0x4004,0x4204,0x4204,0x3B04,0x3B04, 0x3904,0x3904,0x3B04,0x3B04,0x4004,0x4004,0x3904,0x3904,0x3904,0x3904, 0x3A04,0x3A04,0x4004,0x4004,0x3904,0x3904,0x3704,0x3704,0x3604,0x3604, 0x3704,0x3704,0x4604,0x4604,0x4704,0x4704,0x4604,0x4604,0x4704,0x3704, 0x3604,0x3704,0x3908,0x8004,0x3201,0x3201,0x3201,0x3201,0x3401,0x3401, 0x3401,0x3401,0x3601,0x3601,0x3601,0x3601,0x3701,0x3701,0x3701,0x3701, 0x3901,0x3901,0x3901,0x3901,0x4001,0x4001,0x4001,0x4001,0x3A04,0x8004, 0x3601,0x3601,0x3601,0x3601,0x3701,0x3701,0x3701,0x3701,0x3901,0x3901, 0x3901,0x3901,0x3A01,0x3A01,0x3A01,0x3A01,0x4101,0x4101,0x4101,0x4101, 0x4401,0x4401,0x4401,0x4401,0x4204,0x8038,0x4B04,0x4B04,0x4B01,0x4B01, 0x4B01,0x4B01,0x5004,0x4904,0x4904,0x4901,0x4901,0x4901,0x4901,0x4B04, 0x4704,0x4704,0x4701,0x4701,0x4701,0x4701,0x4B04,0x4B01,0x4B01,0x4B01, 0x4B01,0x4904,0x4704,0x4204,0x3B08,0x8004,0x4204,0x4708,0x8004,0x4204, 0x4704,0x4204,0x4704,0x4B04,0x5208,0x8008,0x5008,0x8004,0x4904,0x5008, 0x8004,0x4904,0x5004,0x4904,0x4604,0x4904,0x4208,0x8008,0x4704,0x4704, 0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704, 0x4701,0x4701,0x4701,0x4701,0x4B04,0x4401,0x4401,0x4401,0x4401,0x4704, 0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704, 0x4704,0x4704,0x4701,0x4701,0x4701,0x4701,0x4B04,0x4401,0x4401,0x4401, 0x4401,0x4704,0x4210,0x4210,0x4210,0x4208,0x8028,0x3610,0x3710,0x4008, 0x4008,0x3908,0x3908,0x3204,0x8004,0x4204,0x8004,0x4208,0x8028,0x4601, 0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601,0x4601, 0x4601,0x4601,0x4601,0x4601,0x4601,0x4710,0x4008,0x4004,0x4004,0x3908, 0x3904,0x3904,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x4704, 0x4704,0x4704,0x4704,0x4704,0x4904,0x4904,0x4704,0x4704,0x4604,0x4604, 0x4704,0x4704,0x4404,0x4404,0x4210,0x4410,0x4210,0x4410,0x4208,0x4408, 0x4208,0x4408,0x4204,0x3204,0x3204,0x3204,0x3208,0x8020,0x3B04,0x8004, 0x3404,0x8004,0x4004,0x8004,0x3904,0x8004,0x3604,0x800C,0x4901,0x4901, 0x4901,0x4901,0x4901,0x4901,0x4901,0x4901,0x4704,0x8004,0x4904,0x8004, 0x4B10,0x4908,0x8008,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201,0x5201, 0x5201,0x5201,0x5201,0x5001,0x5001,0x4B01,0x4B01,0x4901,0x4901,0x4704, 0x8004,0x5404,0x8004,0x5004,0x8004,0x4904,0x8004,0x5208,0x8004,0x5004, 0x5001,0x5001,0x5001,0x5001,0x4B04,0x8004,0x5004,0x5001,0x5001,0x5001, 0x5001,0x4B04,0x8004,0x4004,0x3704,0x3704,0x3904,0x3904,0x3B04,0x3B04, 0x3704,0x3704,0x3604,0x3604,0x3704,0x3704,0x3904,0x3904,0x3604,0x3604, 0x3704,0x3704,0x3904,0x3904,0x3B04,0x3B04,0x3704,0x3704,0x3604,0x3604, 0x3704,0x3704,0x3904,0x3904,0x3604,0x3604,0x3704,0x4704,0x4B04,0x4904, 0x4804,0x4404,0x4604,0x4804,0x4904,0x5004,0x4904,0x4704,0x4604,0x4204, 0x4404,0x4604,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704,0x4704, 0x4704,0x4204,0x4204,0x4204,0x4204,0x4204,0x4204,0x4004,0x3B04,0x3704, 0x3904,0x3904,0x3B04,0x3B04,0x3704,0x3704,0x3604,0x3604,0x3704,0x3704, 0x3904,0x3904,0x3604,0x3604,0x3704,0x4704,0x4904,0x4904,0x4B04,0x4B04, 0x4704,0x4704,0x4604,0x4604,0x4704,0x4704,0x4904,0x4904,0x4604,0x4604, 0x4704,0x4704,0x4B04,0x4904,0x4804,0x4404,0x4604,0x4804,0x4904,0x5004, 0x4904,0x4704,0x4604,0x4204,0x4404,0x4604,0x4704,0x4704,0x4704,0x4704, 0x4704,0x4704,0x4704,0x4704,0x4701,0x4701,0x4701,0x4701,0x4904,0x5004, 0x5004,0x5004,0x5004,0x5004,0x4B04,0x4904,0x4204,0x4404,0x4604,0x4704, 0x4704,0x4904,0x4904,0x4B04,0x3604,0x3704,0x3904,0x3B04,0x3B04,0x4004, 0x4004,0x4004,0x4004,0x4104,0x4104,0x4208,0x8008,0x3901,0x3901,0x3901, 0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901, 0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901, 0x3901,0x3701,0x3701,0x3701,0x3701,0x3604,0x3708,0x8018,0x3901,0x3901, 0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901, 0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901, 0x3901,0x3901,0x3701,0x3701,0x3701,0x3701,0x3604,0x3708,0x8008,0x4708, 0x8008,0x4408,0x8008,0x4708,0x8008,0x3710,0x3710,0x3710,0x3708,0x3908, 0x3710,0x3710,0x3710,0x3708,0x3908,0x3704,0x3B04,0x4204,0x4704,0x4B04, 0x4704,0x5204,0x4B04,0x4708,0x3706,0x3702,0x3708,0x8008, 0x0000 }; const unsigned Voice3 [] = { 0x3708,0x8004,0x3204,0x3708,0x8004,0x3204,0x3704,0x3204,0x3704,0x3B04, 0x3208,0x8008,0x4008,0x8004,0x3904,0x4008,0x8004,0x3904,0x4004,0x3904, 0x3604,0x4904,0x4208,0x8008,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3904,0x3904, 0x3B04,0x3B04,0x3604,0x3604,0x3704,0x3704,0x3904,0x3904,0x3B08,0x8028, 0x3210,0x3410,0x3008,0x3008,0x3208,0x3208,0x2B04,0x8004,0x3204,0x8004, 0x3708,0x8008,0x4B10,0x5010,0x3201,0x3201,0x3201,0x3201,0x3201,0x3201, 0x3201,0x3201,0x3201,0x3201,0x3201,0x3201,0x3201,0x3201,0x3201,0x3201, 0x3410,0x3008,0x3008,0x3208,0x3208,0x3B14,0x3B02,0x3901,0x3B01,0x4004, 0x3904,0x4714,0x4702,0x4601,0x4701,0x4904,0x4604,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3604,0x3604,0x3704, 0x3704,0x3404,0x3404,0x3204,0x3204,0x3204,0x3204,0x3204,0x3204,0x3204, 0x3204,0x3204,0x3204,0x3204,0x3204,0x3204,0x3204,0x3204,0x3204,0x3204, 0x3404,0x3604,0x3404,0x3204,0x3404,0x3604,0x3204,0x3704,0x3904,0x3B04, 0x3904,0x3704,0x3904,0x3B04,0x3804,0x3904,0x3904,0x3904,0x3904,0x3904, 0x3904,0x3904,0x3904,0x3904,0x2904,0x2904,0x2904,0x2908,0x8008,0x490A, 0x4702,0x4602,0x4402,0x4204,0x8004,0x3304,0x8004,0x3404,0x8004,0x3204, 0x8004,0x3104,0x8004,0x2904,0x800C,0x2A01,0x2A01,0x2A01,0x2A01,0x2A01, 0x2A01,0x2A01,0x2A01,0x2B04,0x8004,0x2704,0x8004,0x2908,0x3901,0x3901, 0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901, 0x3801,0x3801,0x3801,0x3801,0x3701,0x3701,0x3701,0x3701,0x3401,0x3401, 0x3401,0x3401,0x3204,0x8004,0x3404,0x8004,0x3604,0x8004,0x3304,0x8004, 0x3404,0x8004,0x3204,0x8004,0x3104,0x8004,0x2904,0x8004,0x2B04,0x8004, 0x3704,0x8004,0x3904,0x8004,0x2904,0x8004,0x4604,0x4604,0x4704,0x4704, 0x4904,0x4904,0x4604,0x4604,0x4404,0x4404,0x4604,0x4604,0x4704,0x4704, 0x4404,0x4404,0x4604,0x4604,0x4704,0x4704,0x4904,0x4904,0x4604,0x4604, 0x4404,0x4404,0x4604,0x4604,0x4704,0x4704,0x4404,0x4404,0x4608,0x8008, 0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601, 0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5408,0x8008,0x5401,0x5401, 0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401, 0x5401,0x5401,0x5401,0x5401,0x5204,0x5604,0x5704,0x5904,0x5701,0x5701, 0x5701,0x5701,0x5901,0x5901,0x5B01,0x5B01,0x5904,0x5704,0x5701,0x5701, 0x5701,0x5701,0x5604,0x5204,0x5604,0x5601,0x5601,0x5601,0x5601,0x5404, 0x5204,0x5104,0x5204,0x4604,0x4704,0x4704,0x4904,0x4904,0x4604,0x4604, 0x4404,0x4404,0x4604,0x4604,0x4704,0x4704,0x4404,0x4404,0x4604,0x4604, 0x4704,0x4704,0x4904,0x4904,0x4604,0x4604,0x4404,0x4404,0x4604,0x4604, 0x4704,0x4704,0x4404,0x4404,0x4608,0x8008,0x5601,0x5601,0x5601,0x5601, 0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601, 0x5601,0x5601,0x5408,0x8008,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401, 0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401, 0x5204,0x5504,0x5704,0x5904,0x5701,0x5701,0x5701,0x5701,0x5901,0x5901, 0x5B01,0x5B01,0x5904,0x5704,0x5701,0x5701,0x5701,0x5701,0x5604,0x5204, 0x5604,0x5601,0x5601,0x5601,0x5601,0x5404,0x5204,0x5104,0x3204,0x2904, 0x2B04,0x3104,0x3204,0x3204,0x3404,0x3404,0x3604,0x3104,0x3204,0x3404, 0x3604,0x3604,0x3704,0x3704,0x3904,0x3904,0x3A04,0x3A04,0x3B08,0x8008, 0x3710,0x3910,0x4204,0x8004,0x4204,0x8004,0x4204,0x800C,0x3708,0x8004, 0x3204,0x3708,0x8004,0x3204,0x3704,0x3204,0x3704,0x3B04,0x3208,0x8008, 0x4008,0x8004,0x3904,0x4008,0x8004,0x3904,0x4004,0x3904,0x3604,0x4904, 0x4208,0x8008,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3904,0x3904,0x3B04,0x3B04, 0x3604,0x3604,0x3704,0x3704,0x3904,0x3904,0x3B08,0x8028,0x3210,0x3410, 0x3008,0x3008,0x3208,0x3208,0x2B04,0x8004,0x3204,0x8004,0x3708,0x8008, 0x4B10,0x5010,0x3201,0x3201,0x3201,0x3201,0x3201,0x3201,0x3201,0x3201, 0x3201,0x3201,0x3201,0x3201,0x3201,0x3201,0x3201,0x3201,0x3410,0x3008, 0x3008,0x3208,0x3208,0x3B14,0x3B02,0x3901,0x3B01,0x4004,0x3904,0x4714, 0x4702,0x4601,0x4701,0x4904,0x4604,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3604,0x3604,0x3704,0x3704,0x3404, 0x3404,0x3204,0x3204,0x3204,0x3204,0x3204,0x3204,0x3204,0x3204,0x3204, 0x3204,0x3204,0x3204,0x3204,0x3204,0x3204,0x3204,0x3204,0x3404,0x3604, 0x3404,0x3204,0x3404,0x3604,0x3204,0x3704,0x3904,0x3B04,0x3904,0x3704, 0x3904,0x3B04,0x3804,0x3904,0x3904,0x3904,0x3904,0x3904,0x3904,0x3904, 0x3904,0x3904,0x2904,0x2904,0x2904,0x2908,0x8008,0x490A,0x4702,0x4602, 0x4402,0x4204,0x8004,0x3304,0x8004,0x3404,0x8004,0x3204,0x8004,0x3104, 0x8004,0x2904,0x800C,0x2A01,0x2A01,0x2A01,0x2A01,0x2A01,0x2A01,0x2A01, 0x2A01,0x2B04,0x8004,0x2704,0x8004,0x2908,0x3901,0x3901,0x3901,0x3901, 0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3901,0x3801,0x3801, 0x3801,0x3801,0x3701,0x3701,0x3701,0x3701,0x3401,0x3401,0x3401,0x3401, 0x3204,0x8004,0x3404,0x8004,0x3604,0x8004,0x3304,0x8004,0x3404,0x8004, 0x3204,0x8004,0x3104,0x8004,0x2904,0x8004,0x2B04,0x8004,0x3704,0x8004, 0x3904,0x8004,0x2904,0x8004,0x4604,0x4604,0x4704,0x4704,0x4904,0x4904, 0x4604,0x4604,0x4404,0x4404,0x4604,0x4604,0x4704,0x4704,0x4404,0x4404, 0x4604,0x4604,0x4704,0x4704,0x4904,0x4904,0x4604,0x4604,0x4404,0x4404, 0x4604,0x4604,0x4704,0x4704,0x4404,0x4404,0x4608,0x8008,0x5601,0x5601, 0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601, 0x5601,0x5601,0x5601,0x5601,0x5408,0x8008,0x5401,0x5401,0x5401,0x5401, 0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401, 0x5401,0x5401,0x5204,0x5604,0x5704,0x5904,0x5701,0x5701,0x5701,0x5701, 0x5901,0x5901,0x5B01,0x5B01,0x5904,0x5704,0x5701,0x5701,0x5701,0x5701, 0x5604,0x5204,0x5604,0x5601,0x5601,0x5601,0x5601,0x5404,0x5204,0x5104, 0x5204,0x4604,0x4704,0x4704,0x4904,0x4904,0x4604,0x4604,0x4404,0x4404, 0x4604,0x4604,0x4704,0x4704,0x4404,0x4404,0x4604,0x4604,0x4704,0x4704, 0x4904,0x4904,0x4604,0x4604,0x4404,0x4404,0x4604,0x4604,0x4704,0x4704, 0x4404,0x4404,0x4608,0x8008,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601, 0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601,0x5601, 0x5408,0x8008,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401, 0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5401,0x5204,0x5504, 0x5704,0x5904,0x5701,0x5701,0x5701,0x5701,0x5901,0x5901,0x5B01,0x5B01, 0x5904,0x5704,0x5701,0x5701,0x5701,0x5701,0x5604,0x5204,0x5604,0x5601, 0x5601,0x5601,0x5601,0x5404,0x5204,0x5104,0x3204,0x2904,0x2B04,0x3104, 0x3204,0x3204,0x3404,0x3404,0x3604,0x3104,0x3204,0x3404,0x3604,0x3604, 0x3704,0x3704,0x3904,0x3904,0x3A04,0x3A04,0x3B08,0x8008,0x3710,0x3910, 0x4204,0x8004,0x4204,0x8004,0x4204,0x800C,0x3208,0x8004,0x2904,0x3208, 0x8004,0x2904,0x3204,0x2904,0x3204,0x3604,0x4908,0x8008,0x3908,0x8004, 0x3604,0x3908,0x8004,0x3604,0x3904,0x3604,0x3304,0x3604,0x2B08,0x8008, 0x4404,0x4404,0x4504,0x4504,0x4704,0x4704,0x4404,0x4404,0x4204,0x4204, 0x4404,0x4404,0x4504,0x4504,0x4204,0x4204,0x4404,0x4404,0x4504,0x4504, 0x4704,0x4704,0x4404,0x4404,0x4204,0x4204,0x4404,0x4404,0x4504,0x4504, 0x4204,0x4204,0x4404,0x4404,0x4504,0x4504,0x4704,0x4704,0x4404,0x4404, 0x4204,0x4204,0x4404,0x4404,0x4504,0x4504,0x4204,0x4204,0x4004,0x4004, 0x4204,0x4204,0x4404,0x4404,0x4004,0x4004,0x4004,0x4004,0x4204,0x4204, 0x4304,0x4304,0x4004,0x4004,0x3A04,0x3A04,0x3904,0x3904,0x3A04,0x3A04, 0x4904,0x4904,0x4A04,0x4A04,0x4904,0x4904,0x4A04,0x4A04,0x4904,0x4704, 0x4608,0x8004,0x2201,0x2201,0x2201,0x2201,0x2401,0x2401,0x2401,0x2401, 0x2601,0x2601,0x2601,0x2601,0x2701,0x2701,0x2701,0x2701,0x2901,0x2901, 0x2901,0x2901,0x3001,0x3001,0x3001,0x3001,0x2A04,0x8004,0x2601,0x2601, 0x2601,0x2601,0x2701,0x2701,0x2701,0x2701,0x2901,0x2901,0x2901,0x2901, 0x2A01,0x2A01,0x2A01,0x2A01,0x2101,0x2101,0x2101,0x2101,0x3401,0x3401, 0x3401,0x3401,0x3204,0x8004,0x4204,0x4404,0x4504,0x4704,0x4904,0x4A08, 0x4B08,0x5008,0x5108,0x5204,0x5204,0x5201,0x5201,0x5201,0x5201,0x5404, 0x5004,0x5004,0x5001,0x5001,0x5001,0x5001,0x5204,0x4B04,0x4B04,0x4B01, 0x4B01,0x4B01,0x4B01,0x5204,0x5201,0x5201,0x5201,0x5201,0x5004,0x4B04, 0x4904,0x4708,0x8004,0x3204,0x3708,0x8004,0x3204,0x3704,0x3204,0x3704, 0x3B04,0x4208,0x8008,0x4008,0x8004,0x3904,0x4008,0x8004,0x3904,0x4004, 0x3904,0x3604,0x3904,0x3208,0x8008,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3904, 0x3904,0x3B04,0x3B04,0x3704,0x3704,0x3904,0x3904,0x3B04,0x3B04,0x4008, 0x8008,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01, 0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x5010,0x4908,0x4908, 0x4708,0x4708,0x4408,0x4408,0x4008,0x3908,0x4204,0x8004,0x4604,0x8004, 0x4704,0x800C,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01, 0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x5010,0x4B01, 0x4B01,0x4B01,0x4B01,0x4904,0x4904,0x4904,0x4901,0x4901,0x4901,0x4901, 0x4704,0x4704,0x4704,0x4408,0x4404,0x4404,0x4008,0x4004,0x4004,0x3B14, 0x3B01,0x3B01,0x3901,0x3B01,0x4001,0x4001,0x4001,0x4001,0x3904,0x4714, 0x4701,0x4701,0x4601,0x4701,0x4901,0x4901,0x4901,0x4901,0x4604,0x4B10, 0x5010,0x4B08,0x5210,0x5708,0x5610,0x5710,0x5610,0x5710,0x5608,0x5708, 0x5608,0x5708,0x5604,0x4204,0x4204,0x4204,0x4208,0x8008,0x4201,0x4201, 0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4001,0x4001, 0x3B01,0x3B01,0x3901,0x3901,0x3704,0x8004,0x4404,0x8004,0x4004,0x8004, 0x3904,0x8004,0x4204,0x800C,0x4B0A,0x4902,0x4702,0x4602,0x5404,0x8004, 0x5004,0x8004,0x3208,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201, 0x4201,0x4201,0x4201,0x4201,0x4201,0x4101,0x4101,0x4101,0x4101,0x4001, 0x4001,0x4001,0x4001,0x3901,0x3901,0x3901,0x3901,0x3704,0x8004,0x3904, 0x8004,0x3B04,0x8004,0x3804,0x8004,0x3904,0x8004,0x3704,0x8004,0x3604, 0x8004,0x3204,0x8004,0x3404,0x8004,0x3004,0x8004,0x3204,0x8004,0x3204, 0x8004,0x2708,0x8018,0x3208,0x8018,0x2708,0x8018,0x3208,0x8018,0x3B08, 0x8008,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01, 0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4908,0x8008,0x4901, 0x4901,0x4901,0x4901,0x4901,0x4901,0x4901,0x4901,0x4901,0x4901,0x4901, 0x4901,0x4901,0x4901,0x4901,0x4901,0x4704,0x4B04,0x5004,0x5204,0x5001, 0x5001,0x5001,0x5001,0x5201,0x5201,0x5401,0x5401,0x5204,0x5004,0x5001, 0x5001,0x5001,0x5001,0x4B04,0x4704,0x4B04,0x4B01,0x4B01,0x4B01,0x4B01, 0x4904,0x4704,0x4604,0x4704,0x3B04,0x4004,0x4004,0x4204,0x4204,0x3B04, 0x3B04,0x3904,0x3904,0x3B04,0x3B04,0x4004,0x4004,0x3904,0x3904,0x3B04, 0x4B04,0x5004,0x5004,0x5204,0x5204,0x4B04,0x4B04,0x4904,0x4904,0x4B04, 0x4B04,0x5004,0x5004,0x4904,0x4904,0x8004,0x3704,0x3B04,0x3904,0x3804, 0x3404,0x3604,0x3804,0x3904,0x4004,0x3904,0x3704,0x3604,0x3204,0x3404, 0x3604,0x3704,0x3704,0x3904,0x3B04,0x4004,0x4004,0x4004,0x4004,0x4204, 0x4204,0x4204,0x4204,0x3204,0x3204,0x3204,0x3204,0x3704,0x3204,0x3404, 0x3604,0x3704,0x3704,0x3904,0x3904,0x3B04,0x3604,0x3704,0x3904,0x3B04, 0x3B04,0x4004,0x4004,0x4204,0x4204,0x4304,0x4304,0x4408,0x8008,0x3001, 0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001, 0x3001,0x3001,0x3001,0x3001,0x3001,0x3210,0x2708,0x8018,0x3001,0x3001, 0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001, 0x3001,0x3001,0x3001,0x3001,0x3210,0x2708,0x8018,0x3008,0x8008,0x3208, 0x8008,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704, 0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704, 0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704, 0x2704,0x2704,0x2704,0x2704,0x2B04,0x3204,0x3704,0x3B04,0x3704,0x4204, 0x3B04,0x3708,0x2706,0x2702,0x2708,0x8008,0x3208,0x8004,0x2904,0x3208, 0x8004,0x2904,0x3204,0x2904,0x3204,0x3604,0x4908,0x8008,0x3908,0x8004, 0x3604,0x3908,0x8004,0x3604,0x3904,0x3604,0x3304,0x3604,0x2B08,0x8008, 0x4404,0x4404,0x4504,0x4504,0x4704,0x4704,0x4404,0x4404,0x4204,0x4204, 0x4404,0x4404,0x4504,0x4504,0x4204,0x4204,0x4404,0x4404,0x4504,0x4504, 0x4704,0x4704,0x4404,0x4404,0x4204,0x4204,0x4404,0x4404,0x4504,0x4504, 0x4204,0x4204,0x4404,0x4404,0x4504,0x4504,0x4704,0x4704,0x4404,0x4404, 0x4204,0x4204,0x4404,0x4404,0x4504,0x4504,0x4204,0x4204,0x4004,0x4004, 0x4204,0x4204,0x4404,0x4404,0x4004,0x4004,0x4004,0x4004,0x4204,0x4204, 0x4304,0x4304,0x4004,0x4004,0x3A04,0x3A04,0x3904,0x3904,0x3A04,0x3A04, 0x4904,0x4904,0x4A04,0x4A04,0x4904,0x4904,0x4A04,0x4A04,0x4904,0x4704, 0x4608,0x8004,0x2201,0x2201,0x2201,0x2201,0x2401,0x2401,0x2401,0x2401, 0x2601,0x2601,0x2601,0x2601,0x2701,0x2701,0x2701,0x2701,0x2901,0x2901, 0x2901,0x2901,0x3001,0x3001,0x3001,0x3001,0x2A04,0x8004,0x2601,0x2601, 0x2601,0x2601,0x2701,0x2701,0x2701,0x2701,0x2901,0x2901,0x2901,0x2901, 0x2A01,0x2A01,0x2A01,0x2A01,0x2101,0x2101,0x2101,0x2101,0x3401,0x3401, 0x3401,0x3401,0x3204,0x8004,0x4204,0x4404,0x4504,0x4704,0x4904,0x4A08, 0x4B08,0x5008,0x5108,0x5204,0x5204,0x5201,0x5201,0x5201,0x5201,0x5404, 0x5004,0x5004,0x5001,0x5001,0x5001,0x5001,0x5204,0x4B04,0x4B04,0x4B01, 0x4B01,0x4B01,0x4B01,0x5204,0x5201,0x5201,0x5201,0x5201,0x5004,0x4B04, 0x4904,0x4708,0x8004,0x3204,0x3708,0x8004,0x3204,0x3704,0x3204,0x3704, 0x3B04,0x4208,0x8008,0x4008,0x8004,0x3904,0x4008,0x8004,0x3904,0x4004, 0x3904,0x3604,0x3904,0x3208,0x8008,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704, 0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3704,0x3904, 0x3904,0x3B04,0x3B04,0x3704,0x3704,0x3904,0x3904,0x3B04,0x3B04,0x4008, 0x8008,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01, 0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x5010,0x4908,0x4908, 0x4708,0x4708,0x4408,0x4408,0x4008,0x3908,0x4204,0x8004,0x4604,0x8004, 0x4704,0x800C,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01, 0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x5010,0x4B01, 0x4B01,0x4B01,0x4B01,0x4904,0x4904,0x4904,0x4901,0x4901,0x4901,0x4901, 0x4704,0x4704,0x4704,0x4408,0x4404,0x4404,0x4008,0x4004,0x4004,0x3B14, 0x3B01,0x3B01,0x3901,0x3B01,0x4001,0x4001,0x4001,0x4001,0x3904,0x4714, 0x4701,0x4701,0x4601,0x4701,0x4901,0x4901,0x4901,0x4901,0x4604,0x4B10, 0x5010,0x4B08,0x5210,0x5708,0x5610,0x5710,0x5610,0x5710,0x5608,0x5708, 0x5608,0x5708,0x5604,0x4204,0x4204,0x4204,0x4208,0x8008,0x4201,0x4201, 0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4001,0x4001, 0x3B01,0x3B01,0x3901,0x3901,0x3704,0x8004,0x4404,0x8004,0x4004,0x8004, 0x3904,0x8004,0x4204,0x800C,0x4B0A,0x4902,0x4702,0x4602,0x5404,0x8004, 0x5004,0x8004,0x3208,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201,0x4201, 0x4201,0x4201,0x4201,0x4201,0x4201,0x4101,0x4101,0x4101,0x4101,0x4001, 0x4001,0x4001,0x4001,0x3901,0x3901,0x3901,0x3901,0x3704,0x8004,0x3904, 0x8004,0x3B04,0x8004,0x3804,0x8004,0x3904,0x8004,0x3704,0x8004,0x3604, 0x8004,0x3204,0x8004,0x3404,0x8004,0x3004,0x8004,0x3204,0x8004,0x3204, 0x8004,0x2708,0x8018,0x3208,0x8018,0x2708,0x8018,0x3208,0x8018,0x3B08, 0x8008,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01, 0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4B01,0x4908,0x8008,0x4901, 0x4901,0x4901,0x4901,0x4901,0x4901,0x4901,0x4901,0x4901,0x4901,0x4901, 0x4901,0x4901,0x4901,0x4901,0x4901,0x4704,0x4B04,0x5004,0x5204,0x5001, 0x5001,0x5001,0x5001,0x5201,0x5201,0x5401,0x5401,0x5204,0x5004,0x5001, 0x5001,0x5001,0x5001,0x4B04,0x4704,0x4B04,0x4B01,0x4B01,0x4B01,0x4B01, 0x4904,0x4704,0x4604,0x4704,0x3B04,0x4004,0x4004,0x4204,0x4204,0x3B04, 0x3B04,0x3904,0x3904,0x3B04,0x3B04,0x4004,0x4004,0x3904,0x3904,0x3B04, 0x4B04,0x5004,0x5004,0x5204,0x5204,0x4B04,0x4B04,0x4904,0x4904,0x4B04, 0x4B04,0x5004,0x5004,0x4904,0x4904,0x8004,0x3704,0x3B04,0x3904,0x3804, 0x3404,0x3604,0x3804,0x3904,0x4004,0x3904,0x3704,0x3604,0x3204,0x3404, 0x3604,0x3704,0x3704,0x3904,0x3B04,0x4004,0x4004,0x4004,0x4004,0x4204, 0x4204,0x4204,0x4204,0x3204,0x3204,0x3204,0x3204,0x3704,0x3204,0x3404, 0x3604,0x3704,0x3704,0x3904,0x3904,0x3B04,0x3604,0x3704,0x3904,0x3B04, 0x3B04,0x4004,0x4004,0x4204,0x4204,0x4304,0x4304,0x4408,0x8008,0x3001, 0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001, 0x3001,0x3001,0x3001,0x3001,0x3001,0x3210,0x2708,0x8018,0x3001,0x3001, 0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001,0x3001, 0x3001,0x3001,0x3001,0x3001,0x3210,0x2708,0x8018,0x3008,0x8008,0x3208, 0x8008,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704, 0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704, 0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704,0x2704, 0x2704,0x2704,0x2704,0x2704,0x2B04,0x3204,0x3704,0x3B04,0x3704,0x4204, 0x3B04,0x3708,0x2706,0x2702,0x2708,0x8008, 0x0000 }; const unsigned long FreqTab [12] = { 6848,6464,6100,5760,5428,5124,4836,4564,4308,4068,3844,3628, // FIXME }; typedef struct { unsigned char DoneMask; /* Set this if we're done */ unsigned char Trigger; /* Trigger value */ unsigned char Ticks; /* Ticks for this tone */ unsigned short Freq; /* Actual frequency value */ unsigned short SoftEnv; const unsigned* Data; /* Pointer to data */ int DecVal; } VoiceCtrl; /* Control structs for all three voices */ static VoiceCtrl V1 = { 0x01, 0x11, 0, 0, 0, Voice1, 0, }; static VoiceCtrl V2 = { 0x02, 0x41, 0, 0, 0, Voice2, 0, }; static VoiceCtrl V3 = { 0x04, 0x11, 0, 0, 0, Voice3, 0, }; /* Pointers to the structs for easy reference */ static VoiceCtrl* V [3] = { &V1, &V2, &V3 }; /* Screen dimensions */ static unsigned char XSize, YSize; /* Variable that contains the time of the next clock tick to play a note */ static unsigned char NextClock; /* Start- and runtime */ static clock_t StartTime; /* Number of ticks for each tone */ #define TICKS_PER_TONE 10 /* Done flag. Contains one bit for each voice. Will contain 0x07 if all ** voices have finished playing. */ static unsigned char Done; # define outb(addr,val) (*(addr)) = (val) # define outw(addr,val) (*(addr)) = (val) unsigned char I, N, Offs; unsigned char Tone; unsigned char Octave; unsigned Val; /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void MakeTeeLine (unsigned char Y) /* Make a divider line */ { cputcxy (0, Y, CH_LTEE); chline (XSize - 2); cputc (CH_RTEE); } static void MakeNiceScreen (void) /* Make a nice screen */ { typedef struct { unsigned char Y; char* Msg; } TextDesc; static TextDesc Text [] = { /*12345678901234567890*/ { 1, "Wolfgang A. Mozart" }, { 2, "Eine kleine" }, { 3, "Nachtmusik" }, { 4, "(KV 525)" }, { 6, "Ported to Gamate" }, { 7, "Groepaz / Hitmen"}, }; register const TextDesc* T; unsigned char I; unsigned char X; /* Clear the screen hide the cursor, set colors */ textcolor (COLOR_BLACK); bgcolor (COLOR_WHITE); clrscr (); cursor (0); /* Top line */ cputcxy (0, 0, CH_ULCORNER); chline (XSize - 2); cputc (CH_URCORNER); /* Left line */ cvlinexy (0, 1, YSize - 2); /* Bottom line */ cputc (CH_LLCORNER); chline (XSize - 2); cputc (CH_LRCORNER); /* Right line */ cvlinexy (XSize - 1, 1, YSize - 2); /* Several divider lines */ MakeTeeLine (5); MakeTeeLine (8); /* Write something into the frame */ for (I = 0, T = Text; I < sizeof (Text) / sizeof (Text [0]); ++I) { X = (XSize - strlen (T->Msg)) / 2; cputsxy (X, T->Y, T->Msg); ++T; } } void UpdateScreen(void) { register VoiceCtrl* VC; /* Play all three voices */ for (I = 0; I < 3; ++I) { /* Get a pointer to this voice */ VC = V [I]; Offs = (I * 6) + 1; textcolor(1); gotoxy(Offs, 9); cprintf("%02x", VC->SoftEnv >> 8); textcolor(COLOR_BLACK); for (N = 0; N < 0x8; ++N) { gotoxy(Offs, 10 + N); cputc((VC->SoftEnv >> (8+5)) >= (N ^ 0x7) ? '#' : '.' ); } } } void DoEffects(void) { register VoiceCtrl* VC; /* Play all three voices */ for (I = 0; I < 3; ++I) { /* Get a pointer to this voice */ VC = V [I]; /* do soft envelope */ if (VC->DecVal != 0) { if (VC->DecVal < 0) { // VC->DecVal = - 0x400; if ((VC->SoftEnv + VC->DecVal) > 0) { VC->SoftEnv += VC->DecVal; // VC->SoftEnv >>= 1; VC->SoftEnv = (VC->SoftEnv >> 1) + (VC->SoftEnv >> 2); } else { VC->SoftEnv = 0; VC->DecVal = 0; } } else if (VC->DecVal > 0) { VC->DecVal = 0x800; if (VC->SoftEnv < (0xffff - VC->DecVal)) { // VC->SoftEnv += VC->DecVal; VC->SoftEnv += VC->DecVal; } else { VC->SoftEnv = 0xffff; VC->DecVal = -VC->DecVal; } } } // outb ((unsigned char*)(AUDIO_BASE + 8 + I), (VC->SoftEnv & 0xf0 ) | 0x0f); // volume outb ((unsigned char*)(AUDIO_BASE + 8 + I),(VC->SoftEnv >> 8)); // volume } } static void TimeSync (void) /* Sync the time for the next tone */ { static unsigned char Clock, LastClock; while ((Clock = clock ()) < NextClock) { while ((Clock = clock ()) == LastClock) {}; LastClock = Clock; DoEffects(); } UpdateScreen(); NextClock = Clock + TICKS_PER_TONE; } unsigned char getbits(void) { return rand() >> 8; } const unsigned char Tone1[12] = { 'c','c','d','d','e','f','f','g','g','a','a','h' }; const unsigned char Tone2[12] = { '-','#','-','#','-','-','#','-','#','-','#','-' }; int main (void) { register VoiceCtrl* VC; /* Get the screen dimensions */ screensize (&XSize, &YSize); /* Make a nice screen */ MakeNiceScreen (); /* init the sound */ memset((unsigned char*)(AUDIO_BASE), 0, 8); outb ((unsigned char*)(AUDIO_BASE + 7), 0x3f); outw ((unsigned char*)(AUDIO_BASE + 12), 0xff); // env delay outb ((unsigned char*)(AUDIO_BASE + 13), 0x13); // env ctrl /* Sync the clock */ NextClock = StartTime = clock (); NextClock += TICKS_PER_TONE; /* Play each voice until all three are done */ while (Done != 0x07) { #if 0 /* Display the time in the lower left corner */ DisplayTime (); #endif /* Wait for the next run */ TimeSync (); /* Play all three voices */ for (I = 0; I < 3; ++I) { /* Get a pointer to this voice */ VC = V [I]; /* Is this voice done? */ if (Done & VC->DoneMask) { /* Voice already done */ continue; } Offs = (I * 6) + 2; /* Do we have any more ticks to play? */ if (VC->Ticks == 0) { /* We need new data */ if ((Val = *VC->Data) == 0) { /* End of data. Mark the voice as done */ Done |= VC->DoneMask; continue; } ++VC->Data; /* Get the ticks from the data */ VC->Ticks = (Val & 0x7F) - 1; /* Check if this is a tone or a pause */ if (Val & 0x8000) { /* This is a pause. */ gotoxy(Offs + 1, 9); cprintf("---"); VC->DecVal = -11 - (getbits() & 0x07); } else { /* This is a tone. Extract the attributes. */ Tone = (Val >> 8) & 0x0F; Octave = ((Val >> 12) & 0x07) ^ 0x07; /* Calculate the frequency */ VC->Freq = FreqTab [Tone] >> Octave; /* Set the frequency */ /* ~ 0xb00 is max value (lowest note) */ VC->Freq >>= 1; VC->Freq &= 0x0fff; outb ((unsigned char*)(AUDIO_BASE + (I << 1) + 1), VC->Freq >> 8); outb ((unsigned char*)(AUDIO_BASE + (I << 1)), VC->Freq & 0xff); /* Start the tone */ VC->DecVal = 1 + (getbits() & 0x07); gotoxy(Offs + 1, 9); cprintf("%c%c%d", Tone1[Tone], Tone2[Tone], Octave); } } else { /* Decrement the ticks. If this is the last tick of a tone, ** reset bit 0 of the trigger value and write it back to the ** SID to start the release phase. */ if (--(VC->Ticks) == 0) { VC->DecVal = -11 - (getbits() & 0x07); gotoxy(Offs + 1, 9); cprintf("---"); } } gotoxy(Offs, 10); cprintf("%04x", VC->Freq); } } /* Done */ return 0; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/getopt-test.c����������������������������������������������������������������0000664�0000000�0000000�00000002714�13473601511�0017214�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** This is part of a changed public domain getopt implementation that ** had the following text on top: ** ** I got this off net.sources from Henry Spencer. ** It is a public domain getopt(3) like in System V. ** I have made the following modifications: ** ** A test main program was added, ifdeffed by GETOPT. ** This main program is a public domain implementation ** of the getopt(1) program like in System V. The getopt ** program can be used to standardize shell option handling. ** e.g. cc -DGETOPT getopt.c -o getopt */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #define ARGCH ':' #define BADCH '?' #define ENDARGS "--" int main (int argc, char **argv) { char *optstring = argv[1]; char *argv0 = argv[0]; int opterr = 0; int C; char *opi; if (argc == 1) { fprintf (stderr, "Usage: %s optstring args\n", argv0); exit (1); } argv++; argc--; argv[0] = argv0; while ((C = getopt (argc, argv, optstring)) != EOF) { if (C == BADCH) opterr++; printf ("-%c ", C); opi = strchr (optstring, C); if (opi && opi[1] == ARGCH) if (optarg) printf ("\"%s\" ", optarg); else opterr++; } printf ("%s", ENDARGS); while (optind < argc) printf (" \"%s\"", argv[optind++]); putchar ('\n'); return opterr; } ����������������������������������������������������cc65-2.18/testcode/lib/getsp.s����������������������������������������������������������������������0000664�0000000�0000000�00000000203�13473601511�0016066�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ .export _getsp .importzp sp .proc _getsp ldx sp+1 lda sp rts .endproc ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/heaptest.c�������������������������������������������������������������������0000664�0000000�0000000�00000007326�13473601511�0016556�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <_heap.h> static unsigned char* V[256]; static char* Alloc (void) /* Allocate a random sized chunk of memory */ { /* Determine the size */ unsigned char Size = (((unsigned char)rand()) & 0x7F) + 1; /* Allocate memory */ unsigned char* P = malloc (Size); /* Set the string to a defined value. We use the size, since this will ** also allow us to retrieve it later. */ if (P) { memset (P, Size, Size); } else { printf ("Could not allocate %u bytes\n", Size); exit (EXIT_FAILURE); } return P; } static void Free (unsigned char* P) /* Check a memory block and free it */ { unsigned char I; /* Get the size of the block */ unsigned char Size = P[0]; /* Scan the block */ for (I = 1; I < Size; ++I) { if (P[I] != Size) { printf ("Scan failed - expected %02X, got %02X\n", Size, P[I]); exit (EXIT_FAILURE); } } /* Free the block */ free (P); } static void FillArray (void) /* Fill the array with randomly allocated memory chunks */ { unsigned char I = 0; do { V[I] = Alloc (); ++I; } while (I != 0); } static void ShowInfo (void) /* Show heap info */ { /* Count free blocks */ unsigned Count = 0; register struct freeblock* P = _heapfirst; while (P) { ++Count; P = P->next; } printf ("%04X %04X %04X %04X %04X %u\n", _heaporg, _heapptr, _heapend, _heapfirst, _heaplast, Count); if (Count) { P = _heapfirst; while (P) { printf ("%04X %04X %04X %04X(%u)\n", (unsigned) P, P[2], P[1], P[0], P[0]); P = P->next; } getchar (); } } static void Test1 (void) { unsigned char I; FillArray (); for (I = 0; I < 0x80; ++I) { Free (V[0x7F-I]); Free (V[0x80+I]); } ShowInfo (); } static void Test2 (void) { unsigned char I; FillArray (); I = 0; do { Free (V[I]); ++I; } while (I != 0); ShowInfo (); } static void Test3 (void) { unsigned char I; FillArray (); I = 0; do { --I; Free (V[I]); } while (I != 0); ShowInfo (); } static void Test4 (void) { unsigned char I; FillArray (); I = 0; do { Free (V[I]); I += 2; } while (I != 0); I = 1; do { Free (V[I]); I += 2; } while (I != 1); ShowInfo (); } static void Test5 (void) { unsigned char I; FillArray (); I = 0; do { Free (V[I]); I += 2; } while (I != 0); do { V[I] = Alloc (); I += 2; } while (I != 0); I = 1; do { Free (V[I]); I += 2; } while (I != 1); do { V[I] = Alloc (); I += 2; } while (I != 1); I = 0; do { Free (V[I]); ++I; } while (I != 0); ShowInfo (); } static void Test6 (void) { unsigned char I, J; FillArray (); I = J = 0; do { do { Free (V[I]); V[I] = Alloc (); ++I; } while (I != 0); ++J; } while (J < 5); do { Free (V[I]); ++I; } while (I != 0); ShowInfo (); } int main (void) { unsigned long T; /* Show info at start */ ShowInfo (); /* Remember the time */ T = clock (); /* Do the tests */ Test1 (); Test2 (); Test3 (); Test4 (); Test5 (); Test6 (); /* Calculate the time and print it */ T = clock () - T; printf ("Time needed: %lu ticks\n", T); /* Done */ return EXIT_SUCCESS; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/joy-test.c�������������������������������������������������������������������0000664�0000000�0000000�00000005245�13473601511�0016515�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <conio.h> #include <joystick.h> #ifdef JOYSTICK_DRIVER /* A statically linked driver was named on the compiler's command line. ** Make sure that it is used instead of a dynamic one. */ # undef DYN_DRV # define DYN_DRV 0 /* ** link existing drivers like this: ** ** cl65 -DJOYSTICK_DRIVER=c64_hitjoy_joy -o joy-test.prg joy-test.c ** ** for testing a new driver you will have to uncomment the define below, and ** link your driver like this: ** ** co65 ../../target/c64/drv/joy/c64-hitjoy.joy -o hitjoy.s --code-label _hitjoy ** cl65 -DJOYSTICK_DRIVER=hitjoy -o joy-test.prg joy-test.c hitjoy.s ** */ /* extern char JOYSTICK_DRIVER; */ #else /* Use a dynamically loaded driver, by default. */ # ifndef DYN_DRV # define DYN_DRV 1 # endif #endif int main (void) { unsigned char j; unsigned char count; unsigned char i; unsigned char Res; unsigned char ch, kb; clrscr (); #if DYN_DRV Res = joy_load_driver (joy_stddrv); #elif defined(JOYSTICK_DRIVER) Res = joy_install (&JOYSTICK_DRIVER); #else Res = joy_install (&joy_static_stddrv); #endif if (Res != JOY_ERR_OK) { cprintf ("Error in joy_load_driver: %u\r\n", Res); #if DYN_DRV cprintf ("os: %u, %s\r\n", _oserror, _stroserror (_oserror)); #endif exit (EXIT_FAILURE); } count = joy_count (); #if defined(__ATARI5200__) || defined(__CREATIVISION__) cprintf ("JOYSTICKS: %d", count); #else cprintf ("Driver supports %d joystick(s)", count); #endif while (1) { for (i = 0; i < count; ++i) { gotoxy (0, i+1); j = joy_read (i); #if defined(__ATARI5200__) || defined(__CREATIVISION__) cprintf ("%1d:%-3s%-3s%-3s%-3s%-3s %02x", i, JOY_UP(j)? " U " : " - ", JOY_DOWN(j)? " D " : " - ", JOY_LEFT(j)? " L " : " - ", JOY_RIGHT(j)? " R " : " - ", JOY_BTN_1(j)? " 1 " : " - ", j); #else cprintf ("%2d: %-6s%-6s%-6s%-6s%-6s %02x", i, JOY_UP(j)? " up " : " ---- ", JOY_DOWN(j)? " down " : " ---- ", JOY_LEFT(j)? " left " : " ---- ", JOY_RIGHT(j)? "right " : " ---- ", JOY_BTN_1(j)? "button" : " ---- ", j); #endif } /* show pressed key, so we can verify keyboard is working */ kb = kbhit (); ch = kb ? cgetc () : ' '; gotoxy (1, i+2); revers (kb); cprintf ("kbd: %c", ch); revers (0); } return 0; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/moddiv-test.c����������������������������������������������������������������0000664�0000000�0000000�00000001634�13473601511�0017174�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <stdlib.h> #include <stdio.h> int main (void) { int a, b; int div, mod; printf ("Please note that this program does an\n" "exhaustive test for the division and\n" "modulo operation and therefore runs for\n" "almost ever. On my box, it's nearly two\n" "days in warp mode of VICE.\n\n"); a = 0; do { b = 1; do { div = a / b; mod = a % b; if (div * b + mod != a) { printf ("Found problems:\n" " Result of %u / %u is %u\n" " Result of %u %% %u is %u\n", a, b, div, a, b, mod); return EXIT_FAILURE; } ++b; } while (b != 0); if ((a & 0xFF) == 0) { printf ("%5u ", a); } ++a; } while (a != 0); return EXIT_SUCCESS; } ����������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/mouse-test.c�����������������������������������������������������������������0000664�0000000�0000000�00000027614�13473601511�0017050�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** Test program for mouse drivers. ** Supportsthe C64/C128/CBM510/Atari/Apple2. ** ** 2001-09-13, Ullrich von Bassewitz ** 2013-09-05, Greg King ** ** Compile with "-DSTATIC_MOUSE" to statically link all available drivers. ** Compile with "-DMOUSE_DRIVER=<driver_sym>" to statically link the given driver. ** E.g., -DMOUSE_DRIVER=atrst_mou to just link with the Atari ST mouse driver. */ #include <stdbool.h> #include <stdlib.h> #include <string.h> #include <mouse.h> #include <pen.h> #include <conio.h> #include <ctype.h> #include <dbg.h> #include <cc65.h> #define max(a,b) (((a) > (b)) ? (a) : (b)) #define min(a,b) (((a) < (b)) ? (a) : (b)) extern int getsp(void); #define NO_DEBUG #define NO_JAIL #ifdef __ATARI__ extern const struct mouse_callbacks mouse_pm_callbacks; extern const struct mouse_callbacks mouse_txt_callbacks; //#define MOUSE_CALLBACK mouse_def_callbacks #define MOUSE_CALLBACK mouse_pm_callbacks //#define MOUSE_CALLBACK mouse_txt_callbacks #else #define MOUSE_CALLBACK mouse_def_callbacks #endif #if defined(MOUSE_DRIVER) || defined(STATIC_MOUSE) /* A statically linked driver was named on the compiler's command line. ** Make sure that it is used instead of a dynamic one. */ # undef DYN_DRV # define DYN_DRV 0 #else /* Use a dynamically loaded driver, by default. */ # ifndef DYN_DRV # define DYN_DRV 1 # endif #endif #ifdef __CBM__ /* Set dark-on-light colors. */ const unsigned char mouse_def_pointercolor = COLOR_BLACK; #endif static void __fastcall__ CheckError (const char* S, unsigned char Error) { if (Error != MOUSE_ERR_OK) { cprintf ("\n%s: %s(%u)\r\n", S, mouse_geterrormsg (Error), Error); /* Wait for a key-press, so that some platforms can show the error ** message before they remove the current screen. */ if (doesclrscrafterexit ()) { cgetc (); } exit (EXIT_FAILURE); } } #if DYN_DRV /* Points to the dynamic driver's name. */ static const char *mouse_name; static void DoWarning (void) /* Warn the user that a driver is needed for this program. */ { cprintf ("Warning: This program needs\r\n" "the driver with the name\r\n" " %s\r\n" "on a disk! Press 'y' if you have it;\r\n" "or, any other key to exit.\r\n", mouse_stddrv); if (tolower (cgetc ()) != 'y') { exit (EXIT_SUCCESS); } cprintf ("OK. Please wait patiently...\r\n"); } #else unsigned char *mouse_drv_use; #endif #ifdef __ATARI__ #ifdef __ATARIXL__ #define MSENAME_EXT "X" #define MSESTAT_0 atrxjoy_mou #define MSESTAT_1 atrxst_mou #define MSESTAT_2 atrxami_mou #define MSESTAT_3 atrxtrk_mou #define MSESTAT_4 atrxtt_mou #else #define MSENAME_EXT "" #define MSESTAT_0 atrjoy_mou #define MSESTAT_1 atrst_mou #define MSESTAT_2 atrami_mou #define MSESTAT_3 atrtrk_mou #define MSESTAT_4 atrtt_mou #endif #define MSENAME_0 "ATR" MSENAME_EXT "JOY.MOU" #define MSENAME_1 "ATR" MSENAME_EXT "ST.MOU" #define MSENAME_2 "ATR" MSENAME_EXT "AMI.MOU" #define MSENAME_3 "ATR" MSENAME_EXT "TRK.MOU" #define MSENAME_4 "ATR" MSENAME_EXT "TT.MOU" #elif defined(__C64__) || defined(__C128__) #ifdef __C64__ #define MSENAME_EXT "c64-" #define MSESTAT_0 c64_joy_mou #define MSESTAT_1 c64_1351_mou #define MSESTAT_2 c64_inkwell_mou #define MSESTAT_3 c64_pot_mou #else #define MSENAME_EXT "c128-" #define MSESTAT_0 c128_joy_mou #define MSESTAT_1 c128_1351_mou #define MSESTAT_2 c128_inkwell_mou #define MSESTAT_3 c128_pot_mou #endif #define MSENAME_0 MSENAME_EXT "joy.mou" #define MSENAME_1 MSENAME_EXT "1351.mou" #define MSENAME_2 MSENAME_EXT "inkwell.mou" #define MSENAME_3 MSENAME_EXT "pot.mou" #endif static void __fastcall__ ShowState (unsigned char Jailed, unsigned char Invisible) /* Display jail and cursor states. */ { cclearxy (0, 7, 32); gotoxy (0, 7); cprintf ("Pointer is %svisible%s.", Invisible? "in" : "", Jailed? " and jailed" : ""); } #ifdef __ATARIXL__ extern char _HIDDEN_RAM_SIZE__, _HIDDEN_RAM_LAST__, _HIDDEN_RAM_START__; #endif #if DYN_DRV int main (int argc, char *argv[]) #else int main (void) #endif { struct mouse_info info; struct mouse_box full_box, small_box; unsigned char width, height; char C; bool Invisible = true, Done = false, Jailed = false; #ifdef __ATARIXL__ cprintf ("adding heap: $%04X bytes at $%04X\r\n", &_HIDDEN_RAM_SIZE__ - (&_HIDDEN_RAM_LAST__ - &_HIDDEN_RAM_START__), &_HIDDEN_RAM_LAST__); _heapadd (&_HIDDEN_RAM_LAST__, (size_t)(&_HIDDEN_RAM_SIZE__ - (&_HIDDEN_RAM_LAST__ - &_HIDDEN_RAM_START__))); cgetc (); #endif #ifndef NO_DEBUG /* Initialize the debugger */ DbgInit (0); #endif /* Set dark-on-light colors. Clear the screen. */ #ifdef __CBM__ (void) bordercolor (COLOR_GRAY2); (void) bgcolor (COLOR_WHITE); (void) textcolor (COLOR_GRAY1); #else (void) bordercolor (COLOR_BLUE); (void) bgcolor (COLOR_WHITE); (void) textcolor (COLOR_BLACK); #endif cursor (0); clrscr (); /* 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. ** (Other drivers will ignore this.) */ #if defined(__C64__) || defined(__C128__) || defined(__CBM510__) pen_adjust ("pen.dat"); #endif #if DYN_DRV /* If a dynamically loadable driver is named on the command line, ** then use that driver instead of the standard one. */ if (argc > 1) { mouse_name = argv[1]; } else { #if defined(__ATARI__) || defined(__C64__) || defined(__C128__) char selection, flag = 0; cprintf ("Select mouse driver:\r\n" " 0 - Joystick\r\n" #ifdef __ATARI__ " 1 - ST Mouse\r\n" " 2 - Amiga Mouse\r\n" " 3 - Atari Trakball\r\n" " 4 - Atari TouchPad\r\n" #else " 1 - 1351 Mouse\r\n" " 2 - Inkwell Mouse\r\n" " 3 - Paddle\r\n" #endif "Enter selection: "); while (1) { switch (selection = cgetc ()) { case '0': mouse_name = MSENAME_0; flag = 1; break; case '1': mouse_name = MSENAME_1; flag = 1; break; case '2': mouse_name = MSENAME_2; flag = 1; break; case '3': mouse_name = MSENAME_3; flag = 1; break; #ifdef __ATARI__ case '4': mouse_name = MSENAME_4; flag = 1; break; #endif } if (flag) break; } cprintf ("%c\r\nOK, loading \"%s\",\r\nplease wait patiently...\r\n", selection, mouse_name); #else /* Output a warning about the standard driver that is needed. */ DoWarning (); mouse_name = mouse_stddrv; #endif } /* Load and install the driver. */ CheckError ("mouse_load_driver", mouse_load_driver (&MOUSE_CALLBACK, mouse_name)); #else /* not DYN_DRV */ #if !defined(MOUSE_DRIVER) && (defined(__ATARI__) || defined(__C64__) || defined(__C128__)) { char selection, flag = 0; cprintf ("Select mouse driver:\r\n" " 0 - Joystick\r\n" #ifdef __ATARI__ " 1 - ST Mouse\r\n" " 2 - Amiga Mouse\r\n" " 3 - Atari Trakball\r\n" " 4 - Atari TouchPad\r\n" #else " 1 - 1351 Mouse\r\n" " 2 - Inkwell Mouse\r\n" " 3 - Paddle\r\n" #endif "Enter selection: "); while (1) { switch (selection = cgetc ()) { case '0': mouse_drv_use = MSESTAT_0; flag = 1; break; case '1': mouse_drv_use = MSESTAT_1; flag = 1; break; case '2': mouse_drv_use = MSESTAT_2; flag = 1; break; case '3': mouse_drv_use = MSESTAT_3; flag = 1; break; #ifdef __ATARI__ case '4': mouse_drv_use = MSESTAT_4; flag = 1; break; #endif } if (flag) break; } } #else mouse_drv_use = mouse_static_stddrv; #endif /* Install the driver. */ CheckError ("mouse_install", mouse_install (&MOUSE_CALLBACK, # ifdef MOUSE_DRIVER MOUSE_DRIVER # else #if defined(__ATARI__) || defined(__C64__) || defined(__C128__) mouse_drv_use #else mouse_static_stddrv #endif # endif )); #endif #ifndef NO_JAIL /* Get the initial bounding box. */ mouse_getbox (&full_box); #endif screensize (&width, &height); top: clrscr (); /* Print a help line */ cputs (" d)ebug h)ide q)uit s)how j)ail"); gotoxy (1, 20); cprintf ("SP: $%04X", getsp()); /* Put a cross at the center of the screen. */ gotoxy (width / 2 - 3, height / 2 - 1); #if defined(__CBM__) cprintf ("%3u,%3u\r\n%*s\xDB", width / 2 * 8 + 4, height / 2 * 8 + 4, width / 2, ""); #else cprintf ("%3u,%3u\r\n%*s+", width / 2 * 8 + 4, height / 2 * 8 + 4, width / 2, ""); #endif /* Test loop */ ShowState (Jailed, Invisible); do { /* Get the current co-ordinates and button states; and, print them. */ mouse_info (&info); gotoxy (0, 2); cprintf (" X = %3d\r\n", info.pos.x); cprintf (" Y = %3d\r\n", info.pos.y); cprintf (" B1 = %c\r\n", (info.buttons & MOUSE_BTN_LEFT) ? #ifdef __CBM__ 0x5F #else 'v' #endif : '^'); cprintf (" B2 = %c", (info.buttons & MOUSE_BTN_RIGHT) ? #ifdef __CBM__ 0x5F #else 'v' #endif : '^'); /* Handle user input */ if (kbhit ()) { cclearxy (1, 9, 23); switch (tolower (C = cgetc ())) { #ifndef NO_DEBUG case 'd': BREAK(); /* The debugger might have changed the colors. ** Restore them. */ #ifdef __CBM__ (void) bordercolor (COLOR_GRAY2); (void) bgcolor (COLOR_WHITE); (void) textcolor (COLOR_GRAY1); #else (void) bordercolor (COLOR_BLUE); (void) bgcolor (COLOR_WHITE); (void) textcolor (COLOR_BLACK); #endif /* The debugger changed the screen; restore it. */ goto top; #endif case 'h': mouse_hide (); ShowState (Jailed, ++Invisible); break; #ifndef NO_JAIL case 'j': if (Jailed) { mouse_setbox (&full_box); Jailed = false; } else { small_box.minx = max (info.pos.x - 10, full_box.minx); small_box.miny = max (info.pos.y - 10, full_box.miny); small_box.maxx = min (info.pos.x + 10, full_box.maxx); small_box.maxy = min (info.pos.y + 10, full_box.maxy); mouse_setbox (&small_box); Jailed = true; } ShowState (Jailed, Invisible); break; #endif case 's': mouse_show (); if (Invisible) { ShowState (Jailed, --Invisible); } break; case 'q': Done = true; break; default: gotoxy (1, 9); cprintf ("Spurious character: $%02X", C); } } } while (!Done); #if DYN_DRV /* Uninstall and unload the driver. */ CheckError ("mouse_unload", mouse_unload ()); #else /* Uninstall the static driver. */ CheckError ("mouse_uninstall", mouse_uninstall ()); #endif /* Say goodbye */ cputsxy (0, height / 2 + 3, "Goodbye!"); return EXIT_SUCCESS; } ��������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/mul-test.c�������������������������������������������������������������������0000664�0000000�0000000�00000007553�13473601511�0016515�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* mul-test.c -- Test the multiplication operator. */ #include <time.h> #include <conio.h> #include <ctype.h> /* Number of elements in the progress bar. Use a power of 2, to avoid the ** multiplication (which is about to be tested). */ #define BAR_ELEMENTS 32U #if defined(__CBM__) static const unsigned char revers_bar[8] = { 0, 0, 0, 0, 0, 1, 1, 1 }; static const unsigned char small_bar[8] = { ' ', 0xa5, 0xb4, 0xb5, 0xa1, 0xb6, 0xaa, 0xa7 }; #elif defined(__ATARI__) #endif /* Screen co-ordinates for the progress meter */ static unsigned char Width, Height; static unsigned char X, Y; static void ProgressMeter (unsigned Val) /* Print the progress bar. */ { gotoxy (X, Y); cprintf (" %5lu/65536\r\n", (unsigned long) Val); revers (1); cclear (Val / (unsigned)(65536U / BAR_ELEMENTS)); /* Commodore and Atari computers can show eight times greater precision. */ #if defined(__CBM__) Val = (Val / (unsigned)(65536U / BAR_ELEMENTS / 8)) % 8; revers (revers_bar[Val]); cputc (small_bar[Val]); #elif defined(__ATARI__) #endif revers (0); } int main(void) { char C; /* Clock variables */ clock_t Ticks; clock_t Wait; unsigned Days; unsigned Hours; unsigned Minu; unsigned Sec; unsigned Milli; /* Actual test variables */ register unsigned lhs = 0; register unsigned rhs = 0; register unsigned res; /* Clear the screen, and output an informational message. */ clrscr (); screensize (&Width, &Height); cprintf ("This program does an exhaustive test of\r\n" "the multiplication routine. It runs for\r\n" "several days; so, please wait very\r\n" "patiently (or, speed up your emulator).\r\n" "\n" "Progress: "); /* Remember the current position for the progress bar */ X = wherex (); Y = wherey (); /* Mark the maximum limit of the bar. */ revers (1); cputcxy (BAR_ELEMENTS, Y, ' '); cputcxy (BAR_ELEMENTS, Y + 1, ' '); revers (0); /* [Targets that have clock() will define CLOCKS_PER_SEC.] */ #ifdef CLOCKS_PER_SEC /* Start timing the test. */ Ticks = clock(); #endif do { /* Update the progress bar */ ProgressMeter (lhs); /* Enable this to test the progress-meter code. ** (And, run emulators at their maximun speed.) */ #if 0 continue; #endif /* Do one row of tests */ res = 0; do { if (lhs * rhs != res) { #ifdef CLOCKS_PER_SEC Wait = clock (); #endif gotoxy (0, Y+3); cprintf ("Error on %u * %u: %u != %u\r\n", lhs, rhs, lhs * rhs, res); cprintf ("Press a key -- 'Q' to quit. "); cursor (1); C = toupper (cgetc ()); cclearxy (0, Y+3, Width); cclearxy (0, Y+4, Width); #ifdef CLOCKS_PER_SEC /* Don't time the user's interaction. */ Ticks += clock () - Wait; #endif if (C == 'Q') { goto Done; } } if (kbhit () && toupper (cgetc ()) == 'Q') { goto Done; } res += lhs; } while (++rhs != 0); } while (++lhs != 0); Done: #ifdef CLOCKS_PER_SEC /* Calculate the time used */ Ticks = clock() - Ticks; Milli = ((Ticks % CLOCKS_PER_SEC) * 1000) / CLOCKS_PER_SEC; Sec = (unsigned) (Ticks / CLOCKS_PER_SEC); Minu = Sec / 60; Hours = Minu / 60; Days = Hours / 24; Hours %= 24; Minu %= 60; Sec %= 60; /* Print the time used */ gotoxy (0, Y+3); cprintf ("Time used:\r\n" " %u days,\r\n" " %u hours,\r\n" " %u minutes,\r\n" " %u.%03u seconds.\n", Days, Hours, Minu, Sec, Milli); #endif cprintf ("\rTap a key, to exit. "); cgetc(); return 0; } �����������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/pce/�������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0015334�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/pce/Makefile�����������������������������������������������������������������0000664�0000000�0000000�00000000754�13473601511�0017002�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������.PHONY: all clean test # Size of cartridge to generate. # Possible values: # 8K = 0x2000 # 16K = 0x4000 # 32K = 0x8000 CARTSIZE := 0x2000 ifeq (${CARTSIZE},0x8000) COUNT := 3 else COUNT := 1 endif all: conio.pce %.pce: %.bin dd if=$< bs=8K skip=${COUNT} > $@ dd if=$< bs=8K count=${COUNT} >> $@ %.bin: %.c ../../../lib/pce.lib ../../../bin/cl65 -t pce $< -Wl -D__CARTSIZE__=${CARTSIZE} -m $*.map -o $@ clean: $(RM) conio.o conio.??? test: conio.pce mednafen -force_module pce $< ��������������������cc65-2.18/testcode/lib/pce/conio.c������������������������������������������������������������������0000664�0000000�0000000�00000007700�13473601511�0016613�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <pce.h> #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, i = 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, JOY_UP(j)? " up " : " ---- ", JOY_DOWN(j)? " down " : " ---- ", JOY_LEFT(j)? " left " : " ---- ", JOY_RIGHT(j)? "right " : " ---- ", JOY_BTN_I(j)? "btn I " : " ---- ", JOY_BTN_II(j)? "btn II" : " ---- ", JOY_SELECT(j)? "select" : " ---- ", JOY_RUN(j)? " 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]); } waitvsync(); ++n; } } ����������������������������������������������������������������cc65-2.18/testcode/lib/posixio-test.c���������������������������������������������������������������0000664�0000000�0000000�00000003427�13473601511�0017406�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <stdio.h> #include <errno.h> #include <fcntl.h> #include <unistd.h> int Open (const char* Name, int Flags) { int fd; printf ("Opening %s: ", Name); fd = open (Name, Flags); printf ("%d\n", fd); return fd; } void Write (int fd, const void* Buf, unsigned Size) { int Res; Res = write (fd, Buf, Size); printf ("Writing %u bytes to %d: %d\n", Size, fd, Res); } int Read (int fd, void* Buf, unsigned Size) { int Res; Res = read (fd, Buf, Size); printf ("Reading %u bytes from %d: %d\n", Size, fd, Res); return Res > 0? Res : 0; } void Close (int fd) { printf ("Closing %d: %d\n", fd, close (fd)); } int main (void) { int fd1, fd2; int Res; static const char text1[] = "This goes into file #1\n"; static const char text2[] = "This goes into file #2\n"; static const char text3[] = "This goes into file #3\n"; static const char text4[] = "This goes into file #4\n"; static char Buf[200]; fd1 = Open ("foobar1", O_WRONLY|O_CREAT|O_TRUNC); fd2 = Open ("foobar2", O_WRONLY|O_CREAT|O_TRUNC); Write (fd1, text1, sizeof (text1) - 1); Write (fd2, text2, sizeof (text2) - 1); Write (fd1, text1, sizeof (text1) - 1); Write (fd2, text2, sizeof (text2) - 1); Close (fd1); Close (fd2); fd1 = Open ("foobar3", O_WRONLY|O_CREAT|O_TRUNC); fd2 = Open ("foobar4", O_WRONLY|O_CREAT|O_TRUNC); Write (fd1, text3, sizeof (text3) - 1); Write (fd2, text4, sizeof (text4) - 1); Write (fd1, text3, sizeof (text3) - 1); Write (fd2, text4, sizeof (text4) - 1); Close (fd1); Close (fd2); fd1 = Open ("foobar1", O_RDONLY); Res = Read (fd1, Buf, sizeof (Buf)); printf ("%.*s", Res, Buf); Res = Read (fd1, Buf, sizeof (Buf)); Close (fd1); return 0; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/rename-test.c����������������������������������������������������������������0000664�0000000�0000000�00000005420�13473601511�0017156�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* rename-test.c ** ** ** A simple test of the rename function. ** ** 2008-10-06, Greg King */ #include <errno.h> #include <stdio.h> #include <stdlib.h> static FILE* file; static int r; static char name1[16], name2[16]; int main(void) { /* Generate two temporary file-names that have a random, unused spelling. */ _randomize(); for (;;) { r = rand(); sprintf(name1, "r%04.4u.1", (unsigned)r); sprintf(name2, "r%04.4u.2", (unsigned)r); /* Ensure that neither file-name exists. */ errno = 0; file = fopen(name1, "r"); if (file != NULL) { fclose(file); continue; /* try a different spelling */ } /* Make sure that fopen() failed for the right reason. */ if (errno != ENOENT) { perror("Disk error with first name"); return EXIT_FAILURE; } errno = 0; file = fopen(name2, "r"); if (file != NULL) { fclose(file); continue; } if (errno != ENOENT) { perror("Disk error with second name"); return EXIT_FAILURE; } break; /* neither one exists; do next step */ } /* Create the first file. ** Close it without writing anything because only its name is important. */ printf("Creating file: %s\n", name1); file = fopen(name1, "w"); if (file == NULL) { _poserror("Disk error making first file"); return EXIT_FAILURE; } fclose(file); /* Verify that the file-name exists now. */ file = fopen(name1, "r"); if (file == NULL) { _poserror("Cannot find first name"); return EXIT_FAILURE; } fclose(file); /* Whew! Finally, we get to the reason why this program exists: ** Confirm that the first file-name can be changed into the second ** file-name. */ printf("Renaming %s to %s\n", name1, name2); r = rename(name1, name2); if (r < 0) { _poserror("rename() failed"); return EXIT_FAILURE; } /* Verify that the first file-name no longer exists. */ file = fopen(name1, "r"); if (file != NULL) { fclose(file); _poserror("First name still exists"); return EXIT_FAILURE; } /* Verify that the second file-name exists now. */ file = fopen(name2, "r"); if (file == NULL) { _poserror("Cannot find second name"); return EXIT_FAILURE; } fclose(file); printf("Success!\n"); /* Delete the second (temporary) name. */ printf("Removing %s\n", name2); r = remove(name2); if (r < 0) { _poserror("remove() failed"); return EXIT_FAILURE; } printf("rename() passed the test.\n"); return EXIT_SUCCESS; } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/scanf-test.c�����������������������������������������������������������������0000664�0000000�0000000�00000027670�13473601511�0017014�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** scanf-test.c ** ** Tests that the scanf family of functions scans and converts its input data ** correctly. ** ** Note: When this program uses conio, it doesn't guard against printing off ** the bottom of the screen. So, you might have a problem on platforms with ** "short" screens. ** ** 2005-01-26, Greg King */ /* Define USE_STDIO, when you want to use the stdio functions. ** Do not define it, when you want to use the conio functions. */ /* #define USE_STDIO */ #include <stdio.h> #include <string.h> #ifdef USE_STDIO # define SCANF scanf # define PRINTF printf #else # include <conio.h> /* Unlike other conio input functions, cscanf() echoes what you type. */ # define SCANF cscanf # define PRINTF cprintf #endif #define ARRAYSIZE(a) (sizeof (a) / sizeof (a)[0]) static const struct { const char *input, *format; int rvalue; enum TYPE { INT, CHAR } type1; union { int nvalue; const char *svalue; } v1; enum TYPE type2; union { int nvalue; const char *svalue; } v2; } test_data[] = { /* Input sequences for character specifiers must be less than 80 characters ** long. These format strings are allowwed a maximum of two assignment ** specifications. */ /* Test that literals match, and that they aren't seen as conversions. ** Test that integer specifiers can handle end-of-file. */ {"qwerty Dvorak", "qwerty Dvorak", 0 , INT, {0}, INT, {0}}, {"qwerty" , "qwerty %d%i" , EOF, INT, {0}, INT, {0}}, {"qwerty " , "qwerty %d%i" , EOF, INT, {0}, INT, {0}}, /* Test that integer specifiers scan properly. */ {"qwerty a" , "qwerty %d%i", 0, INT, {0} , INT, {0}}, {"qwerty -" , "qwerty %d%i", 0, INT, {0} , INT, {0}}, {"qwerty -9" , "qwerty %d%i", 1, INT, {-9} , INT, {0}}, {"qwerty -95" , "qwerty %d%i", 1, INT, {-95} , INT, {0}}, {"qwerty -95a" , "qwerty %d%i", 1, INT, {-95} , INT, {0}}, {"qwerty -95a 1", "qwerty %d%i", 1, INT, {-95} , INT, {0}}, {"qwerty -a" , "qwerty %d%i", 0, INT, {0} , INT, {0}}, {"qwerty -95 1" , "qwerty %d%i", 2, INT, {-95} , INT, {1}}, {"qwerty 95 2", "qwerty %i" , 1, INT, {95} , INT, {0}}, {"qwerty -95 +2", "qwerty %x%o", 2, INT, {-0x95}, INT, {02}}, {"qwerty 0X9E 02", "qwerty %i%i", 2, INT, {0x9e} , INT, {2}}, {"qwerty 095 2", "qwerty %i%i", 2, INT, {0} , INT, {95}}, {"qwerty 0e5 2", "qwerty %i%i", 1, INT, {0} , INT, {0}}, /* [String pointers are cast as (int), ** in order to avoid cc65 warnings.] */ /* Test that character specifiers can handle end-of-file. */ {"qwerty" , "qwerty %s%s" , EOF, CHAR, {(int)""}, CHAR, {(int)""}}, {"qwerty ", "qwerty %s%s" , EOF, CHAR, {(int)""}, CHAR, {(int)""}}, {"qwerty" , "qwerty %c%c" , EOF, CHAR, {(int)""}, CHAR, {(int)""}}, {"qwerty ", "qwerty %c%c" , EOF, CHAR, {(int)""}, CHAR, {(int)""}}, {"qwerty" , "qwerty %[ a-z]%c", EOF, CHAR, {(int)""}, CHAR, {(int)""}}, {"qwerty ", "qwerty %[ a-z]%c", EOF, CHAR, {(int)""}, CHAR, {(int)""}}, {"qwerty ", "qwerty%s%s" , EOF, CHAR, {(int)""}, CHAR, {(int)""}}, /* Test that character specifiers scan properly. */ {"123456qwertyasdfghzxcvbn!@#$%^QWERTYASDFGHZXCV" "BN7890-=uiop[]\\jkl;'m,./&*()_+UIOP{}|JKL:\"M<>?", "%79s%79s", 2, CHAR, {(int)"123456qwertyasdfghzxcvbn!@#$%^QWERTYASDFGHZXCV" "BN7890-=uiop[]\\jkl;'m,./&*()_+UIO"}, CHAR, {(int)"P{}|JKL:\"M<>?"}}, {"qwerty ", "qwerty%c%c" , 2, CHAR, {(int)" "} , CHAR, {(int)" "}}, {"qwerty ", "qwerty%2c%c" , 2, CHAR, {(int)" "} , CHAR, {(int)" "}}, {"qwerty ", "qwerty%2c%2c" , 1, CHAR, {(int)" "} , CHAR, {(int)" "}}, {"qwerty ", "qwerty%[ a-z]%c", 1, CHAR, {(int)" "}, CHAR, {(int)""}}, {"qwerty q", "qwerty%[ a-z]%c", 1, CHAR, {(int)" q"}, CHAR, {(int)""}}, {"qwerty Q", "qwerty%[ a-z]%c", 2, CHAR, {(int)" "}, CHAR, {(int)"Q"}}, {"qwerty-QWERTY-", "%[q-ze-]%[-A-Z]" , 2, CHAR, {(int)"qwerty-"}, CHAR, {(int)"QWERTY-"}}, /* Test the space-separation of strings. */ {"qwerty qwerty" , "qwerty%s%s", 1, CHAR, {(int)"qwerty"}, CHAR, {(int)""}}, {"qwerty qwerty Dvorak", "qwerty%s%s", 2, CHAR, {(int)"qwerty"}, CHAR, {(int)"Dvorak"}}, /* Test the mixxing of types. */ {"qwerty abc3", "qwerty%s%X" , 1, CHAR, {(int)"abc3"} , INT , {0}}, {"qwerty abc3", "qwerty%[ a-z]%X" , 2, CHAR, {(int)" abc"} , INT , {3}}, {"qwerty abc3", "qwerty%[ a-z3]%X", 1, CHAR, {(int)" abc3"}, INT , {0}}, {"qwerty abc3", "qwerty%[ A-Z]%X" , 2, CHAR, {(int)" "} , INT , {0xabc3}}, {"qwerty 3abc", "qwerty%i%[ a-z]" , 2, INT , {3} , CHAR, {(int)"abc"}}, {"qwerty 3abc", "qwerty%i%[ A-Z]" , 1, INT , {3} , CHAR, {(int)""}}, /* Test the character-count specifier. */ {" 95 5", "%n%i" , 1, INT , {0} , INT, {95}}, {" a5 5", "%n%i" , 0, INT , {0} , INT, {0}}, {" a5 5", "%x%n" , 1, INT , {0xa5} , INT, {4}}, {" a5 5", " %4c%n", 1, CHAR, {(int)"a5 5"}, INT, {6}}, {" 05a9" , "%i%n" , 1, INT , {5} , INT, {3}}, /* Test assignment-suppression. */ {" 95 6", "%n%*i" , 0, INT , {0} , INT, {0}}, {" a5 6", "%*x%n" , 0, INT , {4} , INT, {0}}, {" a5 6", "%*x%n%o", 1, INT , {4} , INT, {6}}, {" a5 6", " %*4c%d", 0, CHAR, {(int)""}, INT, {0}}, {"The first number is 7. The second number is 8.\n", "%*[ .A-Za-z]%d%*[ .A-Za-z]%d", 2, INT, {7}, INT, {8}}, }; /* Test the char, short, and long specification-modifiers. */ static const struct { const char *input, *format; long value; } type_data[] = { {"+123456789", "%hhd", (signed char)123456789L}, {" 123456789", "%hd" , (unsigned short)123456789L}, {" 123456789", "%ld" , 123456789L}, {"-123456789", "%lld", -123456789L}, }; static void Pause(void) { #ifdef USE_STDIO printf("\n"); #else cprintf("\r\nTap a key to see the next test. "); cgetc(); clrscr(); #endif } int main(void) { long n0; unsigned t; int c, n1 = 12345, n2, n3; char s1[80], s2[80]; void *p1 = main, *p2 = main, *p3 = main, *p4 = main; #ifndef USE_STDIO clrscr(); cursor(1); #endif /* Test that scanf() can recognize percent-signs in the input. ** Test that integer converters skip white-space. ** Test that "%i" can scan a single zero digit (followed by EOF). */ sscanf("% \r\n\f\v\t 0", "%%%i", &n1); if (n1 != 0) PRINTF("sscanf()'s \"%%%%%%i\" couldn't scan either a \"%%\" " "or a single zero digit.\r\n\n"); /* Test scanf()'s return-value: EOF if input ends before the first ** conversion-attempt begins; an assignment-count, otherwise. ** Test that scanf() properly converts and assigns the correct number ** of arguments. */ PRINTF("Testing scanf()'s return-value,\r\nconversions, and assignments...\r\n"); for (t = 0; t < ARRAYSIZE(test_data); ++t) { /* Prefill the arguments with zeroes. */ n1 = n2 = 0; memset(s1, '\0', sizeof s1); memset(s2, '\0', sizeof s2); c=sscanf(test_data[t].input, test_data[t].format, /* Avoid warning messages about different ** pointer-types, by casting them to void-pointers. */ test_data[t].type1 == INT ? (void *)&n1 : (void *)s1, test_data[t].type2 == INT ? (void *)&n2 : (void *)s2); if (c != test_data[t].rvalue) PRINTF("Test #%u returned %d instead of %d.\r\n", t + 1, c, test_data[t].rvalue); if (test_data[t].type1 == INT) { if (test_data[t].v1.nvalue != n1) PRINTF("Test #%u assigned %i, instead of %i,\r\n" "\tto the first argument.\r\n\n", t + 1, n1, test_data[t].v1.nvalue); } else { /* test_data[t].type1 == CHAR */ if (strcmp(test_data[t].v1.svalue, s1)) PRINTF("Test #%u assigned\r\n\"%s\",\r\n" "\tinstead of\r\n\"%s\",\r\n" "\tto the first argument.\r\n\n", t + 1, s1, test_data[t].v1.svalue); } if (test_data[t].type2 == INT) { if (test_data[t].v2.nvalue != n2) PRINTF("Test #%u assigned %i, instead of %i,\r\n" "\tto the second argument.\r\n\n", t + 1, n2, test_data[t].v2.nvalue); } else { /* test_data[t].type2 == CHAR */ if (strcmp(test_data[t].v2.svalue, s2)) PRINTF("Test #%u assigned\r\n\"%s\",\r\n" "\tinstead of\r\n\"%s\",\r\n" "\tto the second argument.\r\n\n", t + 1, s2, test_data[t].v2.svalue); } } Pause(); /* Test the char, short, and long specification-modifiers. */ PRINTF("Testing scanf()'s type-modifiers...\r\n"); for (t = 0; t < ARRAYSIZE(type_data); ++t) { n0 = 0L; sscanf(type_data[t].input, type_data[t].format, &n0); if (type_data[t].value != n0) PRINTF("Test #%u assigned %li instead of %li.\r\n", t + 1, n0, type_data[t].value); } Pause(); /* Test that the pointer specification ** can convert what printf() generates. */ PRINTF("Testing \"%%p\"...\r\n"); sprintf(s1, "%p %p %p %p", NULL, NULL, Pause, /* static (program) storage */ &c); /* automatic (stack) storage */ sscanf(s1, "%p%p%p %p", &p1, &p2, &p3, &p4); if (p1 != NULL || p2 != NULL || p3 != (void *)Pause || p4 != (void *)&c) PRINTF("p1 is %p, p2 is %p; they should be %p.\r\n" "scanf() assigned %p to p3, instead of %p.\r\n" "scanf() assigned %p to p4, instead of %p.\r\n", p1, p2, NULL, p3, Pause, p4, &c); /* Test that scanf() can scan typed input. ** Retest that "%i" can decode radix prefixxes. */ do { Pause(); PRINTF("Type 3 signed numbers,\r\n" "separated by white-space:\r\n" "octal decimal hexadecimal\r\n" "? "); c = SCANF("%i %i %i", &n1, &n2, &n3); PRINTF("\r\n\nscanf() returned %i.\r\n" "The numbers are:\r\n" " %+o octal,\r\n" " %+d decimal,\r\n" " %+#X hexadecimal.\r\n", c, n1, n2, n3); } while (c > 0); return 0; } ������������������������������������������������������������������������cc65-2.18/testcode/lib/seek.c�����������������������������������������������������������������������0000664�0000000�0000000�00000011601�13473601511�0015657�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** seek test program */ #include <stdio.h> #include <string.h> #include <errno.h> #include <unistd.h> int main(int argc, char **argv) { char *filename,*x; char buf[20]; FILE *file; long pos; off_t fsz; int fd; if (argc <= 1) { printf("\nfilename: "); x = fgets(buf,19,stdin); printf("\n"); if (!x) { return(0); } x[strcspn(x, "\r\n")] = 0; filename = x; } else { filename = *(argv+1); } file = fopen(filename,"rb"); if (!file) { fprintf(stderr,"cannot open %s: %s\n",filename,strerror(errno)); return(1); } if (fread(buf, 10, 1, file) != 1) { fprintf(stderr,"short read, aborted\n"); fclose(file); return(1); } pos = ftell(file); if (pos == -1) { fprintf(stderr,"ftell returned -1: %s\n", strerror(errno)); fclose(file); return(1); } printf("reading 10 bytes from file\n"); printf("current file pos: %ld\n", pos); printf("get file size (lseek): "); fd = *(char *)file; /* kids, don't do this at home */ fsz = lseek(fd, 0, SEEK_END); if (fsz == -1) { fprintf(stderr,"lseek returned -1: %s\n", strerror(errno)); fclose(file); return(1); } printf("%ld (fd = %d)\n", (long)fsz, fd); printf("get file size (fseek): "); pos = fseek(file, 0, SEEK_END); if (pos != 0) { fprintf(stderr,"fseek returned -1: %s\n", strerror(errno)); fclose(file); return(1); } pos = ftell(file); if (pos == -1) { fprintf(stderr,"ftell returned -1: %s\n", strerror(errno)); fclose(file); return(1); } printf("%ld\n",pos); printf("positioning at offset 100: "); pos = fseek(file, 100, SEEK_SET); if (pos != 0) { fprintf(stderr,"fseek returned -1: %s\n", strerror(errno)); fclose(file); return(1); } pos = ftell(file); if (pos == -1) { fprintf(stderr,"ftell returned -1: %s\n", strerror(errno)); fclose(file); return(1); } if (pos == 100) { printf("Ok\n"); } else { printf("failed! cur pos = %ld\n",pos); fclose(file); return(1); } printf("seeking back 44 bytes: "); pos = fseek(file, -44, SEEK_CUR); if (pos != 0) { fprintf(stderr,"fseek returned -1: %s\n", strerror(errno)); fclose(file); return(1); } pos = ftell(file); if (pos == -1) { fprintf(stderr,"ftell returned -1: %s\n", strerror(errno)); fclose(file); return(1); } if (pos == 56) { printf("Ok\n"); } else { printf("failed! cur pos = %ld\n",pos); fclose(file); return(1); } printf("seeking forward 111 bytes: "); pos = fseek(file, 111, SEEK_CUR); if (pos != 0) { fprintf(stderr,"fseek returned -1: %s\n", strerror(errno)); fclose(file); return(1); } pos = ftell(file); if (pos == -1) { fprintf(stderr,"ftell returned -1: %s\n", strerror(errno)); fclose(file); return(1); } if (pos == 167) { printf("Ok\n"); } else { printf("failed! cur pos = %ld\n",pos); fclose(file); return(1); } printf("seeking 13 bytes before eof: "); pos = fseek(file, -13, SEEK_END); if (pos != 0) { fprintf(stderr,"fseek returned -1: %s\n", strerror(errno)); fclose(file); return(1); } pos = ftell(file); if (pos == -1) { fprintf(stderr,"ftell returned -1: %s\n", strerror(errno)); fclose(file); return(1); } if (pos == fsz - 13) { printf("Ok\n"); } else { printf("failed! cur pos = %ld\n",pos); fclose(file); return(1); } printf("seeking before sof:\n\t"); pos = fseek(file, -fsz, SEEK_CUR); if (pos != 0) { printf("Ok, error %s\n", strerror(errno)); } else { printf("NOT OK, no error\n"); fclose(file); return(1); } /* ProDOS on the Apple II only supports 24-bit file offsets, ** so anything beyond that should be an error. I don't know ** about other platforms, but I'm guessing no 6502-based ** operating systems support 32-bit offsets? */ printf("seeking to position 2^24:\n\t"); pos = lseek(fd, 0x1000000L, SEEK_SET); if (pos == -1) { printf("Ok, error %s\n", strerror(errno)); } else { printf("NOT OK, returned %ld but expected -1\n", pos); fclose(file); return(1); } printf("trying invalid value for whence:\n\t"); pos = lseek(fd, 0L, 3); if (pos == -1) { printf("Ok, error %s\n", strerror(errno)); } else { printf("NOT OK, returned %ld but expected -1\n", pos); fclose(file); return(1); } fclose(file); return(0); } �������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/ser-test.c�������������������������������������������������������������������0000664�0000000�0000000�00000003417�13473601511�0016504�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <stdio.h> #include <stdlib.h> #include <serial.h> #include <conio.h> #include <dbg.h> #if defined(__C64__) #define DRIVERNAME "c64-swlink.ser" #elif defined(__C128__) #define DRIVERNAME "c128-swlink.ser" #elif defined(__PLUS4__) #define DRIVERNAME "plus4-stdser.ser" #elif defined(__CBM610__) #define DRIVERNAME "cbm610-std.ser" #elif defined(__APPLE2ENH__) #define DRIVERNAME "a2e.ssc.ser" #elif defined(__APPLE2__) #define DRIVERNAME "a2.ssc.ser" #elif defined(__ATARIXL__) #define DRIVERNAME "atrxrdev.ser" #elif defined(__ATARI__) #define DRIVERNAME "atrrdev.ser" #else #define DRIVERNAME "unknown" #error "Unknown target system" #endif static const struct ser_params Params = { SER_BAUD_9600, /* Baudrate */ SER_BITS_8, /* Number of data bits */ SER_STOP_1, /* Number of stop bits */ SER_PAR_NONE, /* Parity setting */ SER_HS_HW /* Type of handshake to use */ }; static void CheckError (const char* Name, unsigned char Error) { if (Error != SER_ERR_OK) { fprintf (stderr, "%s: %d\n", Name, Error); exit (EXIT_FAILURE); } } int main (void) { char Res; char C; CheckError ("ser_load_driver", ser_load_driver (DRIVERNAME)); CheckError ("ser_open", ser_open (&Params)); while (1) { if (kbhit ()) { C = cgetc (); if (C == '1') { break; } else { CheckError ("ser_put", ser_put (C)); printf ("%c", C); } } Res = ser_get (&C); if (Res != SER_ERR_NO_DATA) { CheckError ("ser_get", Res); printf ("%c", C); } } CheckError ("ser_unload", ser_unload ()); return EXIT_SUCCESS; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/shift-test.c�����������������������������������������������������������������0000664�0000000�0000000�00000005257�13473601511�0017034�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <stdio.h> #include <stdlib.h> static unsigned UnsignedShiftLeft1 (unsigned Val) /* Shift an unsigned left by 1 */ { __AX__ = Val; asm ("stx tmp1"); asm ("asl a"); asm ("rol tmp1"); asm ("ldx tmp1"); return __AX__; } static unsigned UnsignedShiftRight1 (unsigned Val) /* Shift an unsigned right by 1 */ { __AX__ = Val; asm ("stx tmp1"); asm ("lsr tmp1"); asm ("ror a"); asm ("ldx tmp1"); return __AX__; } static int SignedShiftRight1 (int Val) /* Shift a signed right by 1 */ { __AX__ = Val; asm ("stx tmp1"); asm ("cpx #$80"); asm ("ror tmp1"); asm ("ror a"); asm ("ldx tmp1"); return __AX__; } static void TestUnsignedLeftShift (void) /* Test left shift. This is identical for signed and unsigned ints */ { unsigned L, R, V; printf ("Testing unsigned left shift:\n"); L = 0; do { V = L; for (R = 0; R < 16; ++R) { /* Check it */ if ((L << R) != V) { fprintf (stderr, "Failed: %u << %u != %u (%u)\n", L, R, V, L << R); exit (1); } V = UnsignedShiftLeft1 (V); } if ((L & 0xFF) == 0) { printf ("%04X ", L); } } while (++L != 0); printf ("\n"); } static void TestUnsignedRightShift (void) /* Test unsigned right shift. */ { unsigned L, R, V; printf ("Testing unsigned right shift:\n"); L = 0; do { V = L; for (R = 0; R < 16; ++R) { /* Check it */ if ((L >> R) != V) { fprintf (stderr, "Failed: %u >> %u != %u (%u)\n", L, R, V, L >> R); exit (1); } V = UnsignedShiftRight1 (V); } if ((L & 0xFF) == 0) { printf ("%04X ", L); } } while (++L != 0); printf ("\n"); } static void TestSignedRightShift (void) /* Test signed right shift. */ { int L, R, V; printf ("Testing signed right shift:\n"); L = 0; do { V = L; for (R = 0; R < 16; ++R) { /* Check it */ if ((L >> R) != V) { fprintf (stderr, "Failed: %d >> %d != %d (%d)\n", L, R, V, L >> R); exit (1); } V = SignedShiftRight1 (V); } if ((L & 0xFF) == 0) { printf ("%04X ", L); } } while (++L != 0); printf ("\n"); } int main (void) { TestUnsignedLeftShift (); TestUnsignedRightShift (); TestSignedRightShift (); printf ("\nOk!\n"); return 0; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/signal-test.c����������������������������������������������������������������0000664�0000000�0000000�00000001056�13473601511�0017165�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <stdio.h> #include <string.h> #include <errno.h> #include <signal.h> void __fastcall__ sighandler (int sig) { printf ("Got signal #%d\n", sig); } int main (void) { if (signal (SIGSEGV, sighandler) == SIG_ERR) { printf ("signal failure %d: %s\n", errno, strerror (errno)); return 1; } printf ("About to raise SIGSEGV...\n"); raise (SIGSEGV); printf ("Back from signal handler\n"); printf ("About to raise SIGILL...\n"); raise (SIGILL); printf ("Back from signal handler\n"); return 0; } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/snprintf-test.c��������������������������������������������������������������0000664�0000000�0000000�00000007606�13473601511�0017562�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** 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; } ��������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/sprintf-test.c���������������������������������������������������������������0000664�0000000�0000000�00000075656�13473601511�0017416�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <stdio.h> #include <string.h> #include <stdarg.h> #if defined(__CC65__) #include <conio.h> #endif /* Flag to #ifdef the tests out that crash the old implementation */ /*#define NOCRASH 1 */ /*****************************************************************************/ /* Code */ /*****************************************************************************/ /* Struct used to test the 'n' conversion specifier. It is machine dependent / ** not portable. */ typedef union WriteCount WriteCount; union WriteCount { signed char C; int I; long L; }; /* Count the number of tests and the number of failures */ static unsigned Tests = 0; static unsigned Failures = 0; /*****************************************************************************/ /* Code */ /*****************************************************************************/ static void OneTest (int Line, const char* RString, int RCount, const char* Format, ...) /* Test one conversion. Line is the line number (to make the life of the ** tester easier), RString the expected result and RCount the expected return ** count. The other parameters are used for formatting. */ { int Count; char Buf[128]; va_list ap; /* Count the number of tests */ ++Tests; /* Format the string using the given arguments */ va_start (ap, Format); Count = vsprintf (Buf, Format, ap); va_end (ap); /* Check the result */ if (Count != RCount || strcmp (Buf, RString) != 0) { ++Failures; printf ("%3d: \"%s\" (%d)\n" " \"%s\" (%d)\n", Line, Buf, Count, RString, RCount); } } static void WriteTest (int Line, const char* Format, WriteCount* W, long Count) /* Test one write conversion. Line is the line number (to make the life of the ** tester easier), Format is the format specification. W is a WriteCount ** variable and Count is the expected result. */ { /* Clear the counter in full length */ W->L = 0x5A5A5A5AL; /* Format the string using the given arguments */ OneTest (Line, "4200", 4, Format, 4200, W); /* Check the counter */ if (W->L != Count) { ++Failures; printf ("%3d: n = 0x%08lX\n" " n = 0x%08lX\n", Line, W->L, Count); } } int main (void) { WriteCount W; /* The one and only starter to begin with ... */ OneTest (__LINE__, "hello, world", 12, "hello, world"); /* Duplicate percent signs are used to output single ones */ OneTest (__LINE__, "hello % %", 9, "hello %% %%"); /* Simple conversions */ OneTest (__LINE__, "u", 1, "%c", 'u'); OneTest (__LINE__, "4200", 4, "%d", 4200); OneTest (__LINE__, "-4200", 5, "%d", -4200); OneTest (__LINE__, "4200", 4, "%i", 4200); OneTest (__LINE__, "-4200", 5, "%i", -4200); OneTest (__LINE__, "10150", 5, "%o", 4200U); OneTest (__LINE__, "167630", 6, "%o", -4200U); OneTest (__LINE__, "hello, world", 12, "hello, %s", "world"); OneTest (__LINE__, "4200", 4, "%u", 4200U); OneTest (__LINE__, "61336", 5, "%u", -4200U); OneTest (__LINE__, "1068", 4, "%x", 4200U); OneTest (__LINE__, "ef98", 4, "%x", -4200U); OneTest (__LINE__, "1068", 4, "%X", 4200U); OneTest (__LINE__, "EF98", 4, "%X", -4200U); /* Simple conversions with special values */ OneTest (__LINE__, "\0", 1, "%c", '\0'); OneTest (__LINE__, "0", 1, "%d", 0); OneTest (__LINE__, "0", 1, "%o", 0U); OneTest (__LINE__, "hello, ", 7, "hello, %s", ""); OneTest (__LINE__, "0", 1, "%u", 0U); OneTest (__LINE__, "0", 1, "%x", 0U); /* 'h' modifier */ OneTest (__LINE__, "4200", 4, "%hd", 4200); OneTest (__LINE__, "-4200", 5, "%hd", -4200); OneTest (__LINE__, "4200", 4, "%hi", 4200); OneTest (__LINE__, "-4200", 5, "%hi", -4200); OneTest (__LINE__, "10150", 5, "%ho", 4200U); OneTest (__LINE__, "167630", 6, "%ho", -4200U); OneTest (__LINE__, "4200", 4, "%hu", 4200U); OneTest (__LINE__, "61336", 5, "%hu", -4200U); OneTest (__LINE__, "1068", 4, "%hx", 4200U); OneTest (__LINE__, "ef98", 4, "%hx", -4200U); OneTest (__LINE__, "1068", 4, "%hX", 4200U); OneTest (__LINE__, "EF98", 4, "%hX", -4200U); /* 'hh' modifier */ OneTest (__LINE__, "104", 3, "%hhd", 4200); OneTest (__LINE__, "-104", 4, "%hhd", -4200); OneTest (__LINE__, "104", 3, "%hhi", 4200); OneTest (__LINE__, "-104", 4, "%hhi", -4200); OneTest (__LINE__, "150", 3, "%hho", 4200U); OneTest (__LINE__, "230", 3, "%hho", -4200U); OneTest (__LINE__, "104", 3, "%hhu", 4200U); OneTest (__LINE__, "152", 3, "%hhu", -4200U); OneTest (__LINE__, "68", 2, "%hhx", 4200U); OneTest (__LINE__, "98", 2, "%hhx", -4200U); OneTest (__LINE__, "68", 2, "%hhX", 4200U); OneTest (__LINE__, "98", 2, "%hhX", -4200U); /* 'j' modifier */ OneTest (__LINE__, "4200123", 7, "%jd", 4200123L); OneTest (__LINE__, "-4200123", 8, "%jd", -4200123L); OneTest (__LINE__, "4200123", 7, "%ji", 4200123L); OneTest (__LINE__, "-4200123", 8, "%ji", -4200123L); OneTest (__LINE__, "20013273", 8, "%jo", 4200123UL); OneTest (__LINE__, "37757764505", 11, "%jo", -4200123UL); OneTest (__LINE__, "4200123", 7, "%ju", 4200123UL); OneTest (__LINE__, "4290767173", 10, "%ju", -4200123UL); OneTest (__LINE__, "4016bb", 6, "%jx", 4200123UL); OneTest (__LINE__, "ffbfe945", 8, "%jx", -4200123UL); OneTest (__LINE__, "4016BB", 6, "%jX", 4200123UL); OneTest (__LINE__, "FFBFE945", 8, "%jX", -4200123UL); /* 'l' modifier */ OneTest (__LINE__, "4200123", 7, "%ld", 4200123L); OneTest (__LINE__, "-4200123", 8, "%ld", -4200123L); OneTest (__LINE__, "4200123", 7, "%li", 4200123L); OneTest (__LINE__, "-4200123", 8, "%li", -4200123L); OneTest (__LINE__, "20013273", 8, "%lo", 4200123UL); OneTest (__LINE__, "37757764505", 11, "%lo", -4200123UL); OneTest (__LINE__, "4200123", 7, "%lu", 4200123UL); OneTest (__LINE__, "4290767173", 10, "%lu", -4200123UL); OneTest (__LINE__, "4016bb", 6, "%lx", 4200123UL); OneTest (__LINE__, "ffbfe945", 8, "%lx", -4200123UL); OneTest (__LINE__, "4016BB", 6, "%lX", 4200123UL); OneTest (__LINE__, "FFBFE945", 8, "%lX", -4200123UL); /* 't' modifier */ OneTest (__LINE__, "4200", 4, "%td", 4200); OneTest (__LINE__, "-4200", 5, "%td", -4200); OneTest (__LINE__, "4200", 4, "%ti", 4200); OneTest (__LINE__, "-4200", 5, "%ti", -4200); OneTest (__LINE__, "10150", 5, "%to", 4200U); OneTest (__LINE__, "167630", 6, "%to", -4200U); OneTest (__LINE__, "4200", 4, "%tu", 4200U); OneTest (__LINE__, "61336", 5, "%tu", -4200U); OneTest (__LINE__, "1068", 4, "%tx", 4200U); OneTest (__LINE__, "ef98", 4, "%tx", -4200U); OneTest (__LINE__, "1068", 4, "%tX", 4200U); OneTest (__LINE__, "EF98", 4, "%tX", -4200U); /* 'z' modifier */ OneTest (__LINE__, "4200", 4, "%zd", 4200); OneTest (__LINE__, "-4200", 5, "%zd", -4200); OneTest (__LINE__, "4200", 4, "%zi", 4200); OneTest (__LINE__, "-4200", 5, "%zi", -4200); OneTest (__LINE__, "10150", 5, "%zo", 4200U); OneTest (__LINE__, "167630", 6, "%zo", -4200U); OneTest (__LINE__, "4200", 4, "%zu", 4200U); OneTest (__LINE__, "61336", 5, "%zu", -4200U); OneTest (__LINE__, "1068", 4, "%zx", 4200U); OneTest (__LINE__, "ef98", 4, "%zx", -4200U); OneTest (__LINE__, "1068", 4, "%zX", 4200U); OneTest (__LINE__, "EF98", 4, "%zX", -4200U); /* '+' forces a sign for signed conversions */ OneTest (__LINE__, "u", 1, "%+c", 'u'); OneTest (__LINE__, "+4200", 5, "%+d", 4200); OneTest (__LINE__, "-4200", 5, "%+d", -4200); OneTest (__LINE__, "+4200", 5, "%+i", 4200); OneTest (__LINE__, "-4200", 5, "%+i", -4200); OneTest (__LINE__, "10150", 5, "%+o", 4200U); OneTest (__LINE__, "167630", 6, "%+o", -4200U); OneTest (__LINE__, "hello, world", 12, "%+s", "hello, world"); OneTest (__LINE__, "4200", 4, "%+u", 4200U); OneTest (__LINE__, "61336", 5, "%+u", -4200U); OneTest (__LINE__, "1068", 4, "%+x", 4200U); OneTest (__LINE__, "ef98", 4, "%+x", -4200U); OneTest (__LINE__, "1068", 4, "%+X", 4200U); OneTest (__LINE__, "EF98", 4, "%+X", -4200U); /* ' ': If the first character of a signed conversion is not a sign, or if ** a signed conversion results in no characters, a space is prefixed ** to the result. */ OneTest (__LINE__, "u", 1, "% c", 'u'); OneTest (__LINE__, " 4200", 5, "% d", 4200); OneTest (__LINE__, "-4200", 5, "% d", -4200); OneTest (__LINE__, " 4200", 5, "% i", 4200); OneTest (__LINE__, "-4200", 5, "% i", -4200); OneTest (__LINE__, "10150", 5, "% o", 4200U); OneTest (__LINE__, "167630", 6, "% o", -4200U); OneTest (__LINE__, "hello, world", 12, "% s", "hello, world"); OneTest (__LINE__, "4200", 4, "% u", 4200U); OneTest (__LINE__, "61336", 5, "% u", -4200U); OneTest (__LINE__, "1068", 4, "% x", 4200U); OneTest (__LINE__, "ef98", 4, "% x", -4200U); OneTest (__LINE__, "1068", 4, "% X", 4200U); OneTest (__LINE__, "EF98", 4, "% X", -4200U); /* If the ' ' and '+' flags both appear, the ' ' flag is ignored */ OneTest (__LINE__, "u", 1, "% +c", 'u'); OneTest (__LINE__, "+4200", 5, "% +d", 4200); OneTest (__LINE__, "-4200", 5, "% +d", -4200); OneTest (__LINE__, "+4200", 5, "% +i", 4200); OneTest (__LINE__, "-4200", 5, "% +i", -4200); OneTest (__LINE__, "10150", 5, "% +o", 4200U); OneTest (__LINE__, "167630", 6, "% +o", -4200U); OneTest (__LINE__, "hello, world", 12, "% +s", "hello, world"); OneTest (__LINE__, "4200", 4, "% +u", 4200U); OneTest (__LINE__, "61336", 5, "% +u", -4200U); OneTest (__LINE__, "1068", 4, "% +x", 4200U); OneTest (__LINE__, "ef98", 4, "% +x", -4200U); OneTest (__LINE__, "1068", 4, "% +X", 4200U); OneTest (__LINE__, "EF98", 4, "% +X", -4200U); /* Field width given */ OneTest (__LINE__, " u", 15, "%15c", 'u'); OneTest (__LINE__, " 4200", 15, "%15d", 4200); OneTest (__LINE__, " -4200", 15, "%15d", -4200); OneTest (__LINE__, " 4200", 15, "%15i", 4200); OneTest (__LINE__, " -4200", 15, "%15i", -4200); OneTest (__LINE__, " 10150", 15, "%15o", 4200U); OneTest (__LINE__, " 167630", 15, "%15o", -4200U); OneTest (__LINE__, " hello, world", 15, "%15s", "hello, world"); OneTest (__LINE__, " 4200", 15, "%15u", 4200U); OneTest (__LINE__, " 61336", 15, "%15u", -4200U); OneTest (__LINE__, " 1068", 15, "%15x", 4200U); OneTest (__LINE__, " ef98", 15, "%15x", -4200U); OneTest (__LINE__, " 1068", 15, "%15X", 4200U); OneTest (__LINE__, " EF98", 15, "%15X", -4200U); /* Field width given as separate argument */ OneTest (__LINE__, " u", 15, "%*c", 15, 'u'); OneTest (__LINE__, " 4200", 15, "%*d", 15, 4200); OneTest (__LINE__, " -4200", 15, "%*d", 15, -4200); OneTest (__LINE__, " 4200", 15, "%*i", 15, 4200); OneTest (__LINE__, " -4200", 15, "%*i", 15, -4200); OneTest (__LINE__, " 10150", 15, "%*o", 15, 4200U); OneTest (__LINE__, " 167630", 15, "%*o", 15, -4200U); OneTest (__LINE__, " hello, world", 15, "%*s", 15, "hello, world"); OneTest (__LINE__, " 4200", 15, "%*u", 15, 4200U); OneTest (__LINE__, " 61336", 15, "%*u", 15, -4200U); OneTest (__LINE__, " 1068", 15, "%*x", 15, 4200U); OneTest (__LINE__, " ef98", 15, "%*x", 15, -4200U); OneTest (__LINE__, " 1068", 15, "%*X", 15, 4200U); OneTest (__LINE__, " EF98", 15, "%*X", 15, -4200U); /* Field width and '-' flag given */ OneTest (__LINE__, "u ", 15, "%-15c", 'u'); OneTest (__LINE__, "4200 ", 15, "%-15d", 4200); OneTest (__LINE__, "-4200 ", 15, "%-15d", -4200); OneTest (__LINE__, "4200 ", 15, "%-15i", 4200); OneTest (__LINE__, "-4200 ", 15, "%-15i", -4200); OneTest (__LINE__, "10150 ", 15, "%-15o", 4200U); OneTest (__LINE__, "167630 ", 15, "%-15o", -4200U); OneTest (__LINE__, "hello, world ", 15, "%-15s", "hello, world"); OneTest (__LINE__, "4200 ", 15, "%-15u", 4200U); OneTest (__LINE__, "61336 ", 15, "%-15u", -4200U); OneTest (__LINE__, "1068 ", 15, "%-15x", 4200U); OneTest (__LINE__, "ef98 ", 15, "%-15x", -4200U); OneTest (__LINE__, "1068 ", 15, "%-15X", 4200U); OneTest (__LINE__, "EF98 ", 15, "%-15X", -4200U); /* A negative field width specified via an argument is treated as if the ** '-' flag and a positive field width were given. ** ** Beware: These tests will crash the old printf routine! */ #ifndef NOCRASH OneTest (__LINE__, "u ", 15, "%*c", -15, 'u'); OneTest (__LINE__, "4200 ", 15, "%*d", -15, 4200); OneTest (__LINE__, "-4200 ", 15, "%*d", -15, -4200); OneTest (__LINE__, "4200 ", 15, "%*i", -15, 4200); OneTest (__LINE__, "-4200 ", 15, "%*i", -15, -4200); OneTest (__LINE__, "10150 ", 15, "%*o", -15, 4200U); OneTest (__LINE__, "167630 ", 15, "%*o", -15, -4200U); OneTest (__LINE__, "hello, world ", 15, "%*s", -15, "hello, world"); OneTest (__LINE__, "4200 ", 15, "%*u", -15, 4200U); OneTest (__LINE__, "61336 ", 15, "%*u", -15, -4200U); OneTest (__LINE__, "1068 ", 15, "%*x", -15, 4200U); OneTest (__LINE__, "ef98 ", 15, "%*x", -15, -4200U); OneTest (__LINE__, "1068 ", 15, "%*X", -15, 4200U); OneTest (__LINE__, "EF98 ", 15, "%*X", -15, -4200U); #endif /* Field width smaller than converted value */ OneTest (__LINE__, "u", 1, "%1c", 'u'); OneTest (__LINE__, "4200", 4, "%1d", 4200); OneTest (__LINE__, "-4200", 5, "%1d", -4200); OneTest (__LINE__, "4200", 4, "%1i", 4200); OneTest (__LINE__, "-4200", 5, "%1i", -4200); OneTest (__LINE__, "10150", 5, "%1o", 4200U); OneTest (__LINE__, "167630", 6, "%1o", -4200U); OneTest (__LINE__, "hello, world", 12, "%1s", "hello, world"); OneTest (__LINE__, "4200", 4, "%1u", 4200U); OneTest (__LINE__, "61336", 5, "%1u", -4200U); OneTest (__LINE__, "1068", 4, "%1x", 4200U); OneTest (__LINE__, "ef98", 4, "%1x", -4200U); OneTest (__LINE__, "1068", 4, "%1X", 4200U); OneTest (__LINE__, "EF98", 4, "%1X", -4200U); /* Field width specified and '0' flag given */ OneTest (__LINE__, "000000000004200", 15, "%015d", 4200); OneTest (__LINE__, "-00000000004200", 15, "%015d", -4200); OneTest (__LINE__, "000000000004200", 15, "%015i", 4200); OneTest (__LINE__, "-00000000004200", 15, "%015i", -4200); OneTest (__LINE__, "000000000010150", 15, "%015o", 4200U); OneTest (__LINE__, "000000000167630", 15, "%015o", -4200U); OneTest (__LINE__, "000000000004200", 15, "%015u", 4200U); OneTest (__LINE__, "000000000061336", 15, "%015u", -4200U); OneTest (__LINE__, "000000000001068", 15, "%015x", 4200U); OneTest (__LINE__, "00000000000ef98", 15, "%015x", -4200U); OneTest (__LINE__, "000000000001068", 15, "%015X", 4200U); OneTest (__LINE__, "00000000000EF98", 15, "%015X", -4200U); /* If the '-' and '0' flags are both specified, '0' is ignored */ OneTest (__LINE__, "4200 ", 15, "%-015d", 4200); OneTest (__LINE__, "-4200 ", 15, "%-015d", -4200); OneTest (__LINE__, "4200 ", 15, "%-015i", 4200); OneTest (__LINE__, "-4200 ", 15, "%-015i", -4200); OneTest (__LINE__, "10150 ", 15, "%-015o", 4200U); OneTest (__LINE__, "167630 ", 15, "%-015o", -4200U); OneTest (__LINE__, "4200 ", 15, "%-015u", 4200U); OneTest (__LINE__, "61336 ", 15, "%-015u", -4200U); OneTest (__LINE__, "1068 ", 15, "%-015x", 4200U); OneTest (__LINE__, "ef98 ", 15, "%-015x", -4200U); OneTest (__LINE__, "1068 ", 15, "%-015X", 4200U); OneTest (__LINE__, "EF98 ", 15, "%-015X", -4200U); /* Precision given */ OneTest (__LINE__, "u", 1, "%.15c", 'u'); OneTest (__LINE__, "000000000004200", 15, "%.15d", 4200); OneTest (__LINE__, "-000000000004200", 16, "%.15d", -4200); OneTest (__LINE__, "000000000004200", 15, "%.15i", 4200); OneTest (__LINE__, "-000000000004200", 16, "%.15i", -4200); OneTest (__LINE__, "000000000010150", 15, "%.15o", 4200U); OneTest (__LINE__, "000000000167630", 15, "%.15o", -4200U); OneTest (__LINE__, "hello, world", 12, "%.15s", "hello, world"); OneTest (__LINE__, "000000000004200", 15, "%.15u", 4200U); OneTest (__LINE__, "000000000061336", 15, "%.15u", -4200U); OneTest (__LINE__, "000000000001068", 15, "%.15x", 4200U); OneTest (__LINE__, "00000000000ef98", 15, "%.15x", -4200U); OneTest (__LINE__, "000000000001068", 15, "%.15X", 4200U); OneTest (__LINE__, "00000000000EF98", 15, "%.15X", -4200U); /* Precision given via argument */ OneTest (__LINE__, "u", 1, "%.*c", 15, 'u'); OneTest (__LINE__, "000000000004200", 15, "%.*d", 15, 4200); OneTest (__LINE__, "-000000000004200", 16, "%.*d", 15, -4200); OneTest (__LINE__, "000000000004200", 15, "%.*i", 15, 4200); OneTest (__LINE__, "-000000000004200", 16, "%.*i", 15, -4200); OneTest (__LINE__, "000000000010150", 15, "%.*o", 15, 4200U); OneTest (__LINE__, "000000000167630", 15, "%.*o", 15, -4200U); OneTest (__LINE__, "hello, world", 12, "%.*s", 15, "hello, world"); OneTest (__LINE__, "000000000004200", 15, "%.*u", 15, 4200U); OneTest (__LINE__, "000000000061336", 15, "%.*u", 15, -4200U); OneTest (__LINE__, "000000000001068", 15, "%.*x", 15, 4200U); OneTest (__LINE__, "00000000000ef98", 15, "%.*x", 15, -4200U); OneTest (__LINE__, "000000000001068", 15, "%.*X", 15, 4200U); OneTest (__LINE__, "00000000000EF98", 15, "%.*X", 15, -4200U); /* Negative precision is treated as if the precision were omitted */ #ifndef NOCRASH OneTest (__LINE__, "u", 1, "%.*c", -15, 'u'); OneTest (__LINE__, "4200", 4, "%.*d", -15, 4200); OneTest (__LINE__, "-4200", 5, "%.*d", -15, -4200); OneTest (__LINE__, "4200", 4, "%.*i", -15, 4200); OneTest (__LINE__, "-4200", 5, "%.*i", -15, -4200); OneTest (__LINE__, "10150", 5, "%.*o", -15, 4200U); OneTest (__LINE__, "167630", 6, "%.*o", -15, -4200U); OneTest (__LINE__, "hello, world", 12, "%.*s", -15, "hello, world"); OneTest (__LINE__, "4200", 4, "%.*u", -15, 4200U); OneTest (__LINE__, "61336", 5, "%.*u", -15, -4200U); OneTest (__LINE__, "1068", 4, "%.*x", -15, 4200U); OneTest (__LINE__, "ef98", 4, "%.*x", -15, -4200U); OneTest (__LINE__, "1068", 4, "%.*X", -15, 4200U); OneTest (__LINE__, "EF98", 4, "%.*X", -15, -4200U); #endif /* Field width and precision given */ OneTest (__LINE__, " u", 15, "%15.10c", 'u'); OneTest (__LINE__, " 0000004200", 15, "%15.10d", 4200); OneTest (__LINE__, " -0000004200", 15, "%15.10d", -4200); OneTest (__LINE__, " 0000004200", 15, "%15.10i", 4200); OneTest (__LINE__, " -0000004200", 15, "%15.10i", -4200); OneTest (__LINE__, " 0000010150", 15, "%15.10o", 4200U); OneTest (__LINE__, " 0000167630", 15, "%15.10o", -4200U); OneTest (__LINE__, " hello, wor", 15, "%15.10s", "hello, world"); OneTest (__LINE__, " 0000004200", 15, "%15.10u", 4200U); OneTest (__LINE__, " 0000061336", 15, "%15.10u", -4200U); OneTest (__LINE__, " 0000001068", 15, "%15.10x", 4200U); OneTest (__LINE__, " 000000ef98", 15, "%15.10x", -4200U); OneTest (__LINE__, " 0000001068", 15, "%15.10X", 4200U); OneTest (__LINE__, " 000000EF98", 15, "%15.10X", -4200U); /* For d, i, o, u, x and X conversions, if a precision is specified, the ** '0' flag is ignored. */ OneTest (__LINE__, " 0000004200", 15, "%015.10d", 4200); OneTest (__LINE__, " -0000004200", 15, "%015.10d", -4200); OneTest (__LINE__, " 0000004200", 15, "%015.10i", 4200); OneTest (__LINE__, " -0000004200", 15, "%015.10i", -4200); OneTest (__LINE__, " 0000010150", 15, "%015.10o", 4200U); OneTest (__LINE__, " 0000167630", 15, "%015.10o", -4200U); OneTest (__LINE__, " 0000004200", 15, "%015.10u", 4200U); OneTest (__LINE__, " 0000061336", 15, "%015.10u", -4200U); OneTest (__LINE__, " 0000001068", 15, "%015.10x", 4200U); OneTest (__LINE__, " 000000ef98", 15, "%015.10x", -4200U); OneTest (__LINE__, " 0000001068", 15, "%015.10X", 4200U); OneTest (__LINE__, " 000000EF98", 15, "%015.10X", -4200U); /* Zero precision, explicitly specified */ OneTest (__LINE__, "u", 1, "%.0c", 'u'); OneTest (__LINE__, "4200", 4, "%.0d", 4200); OneTest (__LINE__, "-4200", 5, "%.0d", -4200); OneTest (__LINE__, "4200", 4, "%.0i", 4200); OneTest (__LINE__, "-4200", 5, "%.0i", -4200); OneTest (__LINE__, "10150", 5, "%.0o", 4200U); OneTest (__LINE__, "167630", 6, "%.0o", -4200U); OneTest (__LINE__, "", 0, "%.0s", "hello, world"); OneTest (__LINE__, "4200", 4, "%.0u", 4200U); OneTest (__LINE__, "61336", 5, "%.0u", -4200U); OneTest (__LINE__, "1068", 4, "%.0x", 4200U); OneTest (__LINE__, "ef98", 4, "%.0x", -4200U); OneTest (__LINE__, "1068", 4, "%.0X", 4200U); OneTest (__LINE__, "EF98", 4, "%.0X", -4200U); /* Zero precision, dot only */ OneTest (__LINE__, "u", 1, "%.c", 'u'); OneTest (__LINE__, "4200", 4, "%.d", 4200); OneTest (__LINE__, "-4200", 5, "%.d", -4200); OneTest (__LINE__, "4200", 4, "%.i", 4200); OneTest (__LINE__, "-4200", 5, "%.i", -4200); OneTest (__LINE__, "10150", 5, "%.o", 4200U); OneTest (__LINE__, "167630", 6, "%.o", -4200U); OneTest (__LINE__, "", 0, "%.s", "hello, world"); OneTest (__LINE__, "4200", 4, "%.u", 4200U); OneTest (__LINE__, "61336", 5, "%.u", -4200U); OneTest (__LINE__, "1068", 4, "%.x", 4200U); OneTest (__LINE__, "ef98", 4, "%.x", -4200U); OneTest (__LINE__, "1068", 4, "%.X", 4200U); OneTest (__LINE__, "EF98", 4, "%.X", -4200U); /* Zero precision, zero value */ OneTest (__LINE__, "", 0, "%.0d", 0); OneTest (__LINE__, "", 0, "%.0i", 0); OneTest (__LINE__, "", 0, "%.0o", 0U); OneTest (__LINE__, "", 0, "%.0u", 0U); OneTest (__LINE__, "", 0, "%.0x", 0U); OneTest (__LINE__, "", 0, "%.0X", 0U); /* Field width and zero precision given */ OneTest (__LINE__, " u", 15, "%15.0c", 'u'); OneTest (__LINE__, " 4200", 15, "%15.0d", 4200); OneTest (__LINE__, " -4200", 15, "%15.0d", -4200); OneTest (__LINE__, " 4200", 15, "%15.0i", 4200); OneTest (__LINE__, " -4200", 15, "%15.0i", -4200); OneTest (__LINE__, " 10150", 15, "%15.0o", 4200U); OneTest (__LINE__, " 167630", 15, "%15.0o", -4200U); OneTest (__LINE__, " ", 15, "%15.0s", "hello, world"); OneTest (__LINE__, " 4200", 15, "%15.0u", 4200U); OneTest (__LINE__, " 61336", 15, "%15.0u", -4200U); OneTest (__LINE__, " 1068", 15, "%15.0x", 4200U); OneTest (__LINE__, " ef98", 15, "%15.0x", -4200U); OneTest (__LINE__, " 1068", 15, "%15.0X", 4200U); OneTest (__LINE__, " EF98", 15, "%15.0X", -4200U); /* Field width, zero precision and zero value */ OneTest (__LINE__, " ", 15, "%15.0d", 0); OneTest (__LINE__, " ", 15, "%15.0i", 0); OneTest (__LINE__, " ", 15, "%15.0o", 0U); OneTest (__LINE__, " ", 15, "%15.0u", 0U); OneTest (__LINE__, " ", 15, "%15.0x", 0U); OneTest (__LINE__, " ", 15, "%15.0X", 0U); /* Alternative form */ OneTest (__LINE__, "010150", 6, "%#o", 4200U); OneTest (__LINE__, "0167630", 7, "%#o", -4200U); OneTest (__LINE__, "0x1068", 6, "%#x", 4200U); OneTest (__LINE__, "0xef98", 6, "%#x", -4200U); OneTest (__LINE__, "0X1068", 6, "%#X", 4200U); OneTest (__LINE__, "0XEF98", 6, "%#X", -4200U); /* Alternative form with zero value */ #ifndef NOCRASH OneTest (__LINE__, "0", 1, "%#o", 0U); OneTest (__LINE__, "0", 1, "%#x", 0U); OneTest (__LINE__, "0", 1, "%#X", 0U); #endif /* Alternative form with zero value and precision 1 */ OneTest (__LINE__, "0", 1, "%#.1o", 0U); OneTest (__LINE__, "0", 1, "%#.1x", 0U); OneTest (__LINE__, "0", 1, "%#.1X", 0U); /* Alternative form with non zero value and precision 1 */ OneTest (__LINE__, "01", 2, "%#.1o", 1U); OneTest (__LINE__, "0x1", 3, "%#.1x", 1U); OneTest (__LINE__, "0X1", 3, "%#.1X", 1U); /* Alternative form and width given */ OneTest (__LINE__, " 010150", 15, "%#15o", 4200U); OneTest (__LINE__, " 0x1068", 15, "%#15x", 4200U); OneTest (__LINE__, " 0X1068", 15, "%#15X", 4200U); /* Alternative form, width and zero padding */ OneTest (__LINE__, "000000000010150", 15, "%#015o", 4200U); OneTest (__LINE__, "0x0000000001068", 15, "%#015x", 4200U); OneTest (__LINE__, "0X0000000001068", 15, "%#015X", 4200U); /* n conversion specifier */ WriteTest (__LINE__, "%d%n", &W, 0x5A5A0004L); WriteTest (__LINE__, "%d%hn", &W, 0x5A5A0004L); WriteTest (__LINE__, "%d%hhn", &W, 0x5A5A5A04L); WriteTest (__LINE__, "%d%ln", &W, 0x00000004L); /* Output the result */ if (Failures) { printf ("%u tests, %u failures\n", Tests, Failures); } else { printf ("%u tests: Ok\n", Tests); } /* Wait for a key so we can read the result */ #if defined(__CC65__) cgetc (); #endif return 0; } ����������������������������������������������������������������������������������cc65-2.18/testcode/lib/strdup-test.c����������������������������������������������������������������0000664�0000000�0000000�00000003750�13473601511�0017234�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> /* From _heap.h */ extern unsigned _horg; /* Bottom of heap */ extern unsigned _hptr; /* Current top */ extern unsigned _hend; /* Upper limit */ extern unsigned _hfirst; /* First free block in list */ extern unsigned _hlast; /* Last free block in list */ static unsigned char* V[256]; static void ShowInfo (void) /* Show heap info */ { /* Count free blocks */ unsigned Count = 0; unsigned** P = (unsigned**) _hfirst; while (P) { ++Count; P = P[1]; } printf ("%04X %04X %04X %04X %04X %u\n", _horg, _hptr, _hend, _hfirst, _hlast, Count); if (Count) { P = (unsigned**) _hfirst; while (P) { printf ("%04X %04X %04X %04X(%u)\n", (unsigned) P, P[2], P[1], P[0], P[0]); P = P[1]; } getchar (); } } static const char* RandStr (void) /* Create a random string */ { static char S [300]; unsigned Len = (rand () & 0xFF) + (sizeof (S) - 0xFF - 1); unsigned I; char C; for (I = 0; I < Len; ++I) { do { C = rand() & 0xFF; } while (C == 0); S[I] = C; } S[Len] = '\0'; return S; } static void FillArray (void) /* Fill the string array */ { unsigned char I = 0; do { V[I] = strdup (RandStr ()); ++I; } while (I != 0); } static void FreeArray (void) /* Free all strings in the array */ { unsigned char I = 0; do { free (V[I]); ++I; } while (I != 0); } int main (void) { unsigned long T; /* Show info at start */ ShowInfo (); /* Remember the time */ T = clock (); /* Do the tests */ FillArray (); ShowInfo (); FreeArray (); ShowInfo (); /* Calculate the time and print it */ T = clock () - T; printf ("Time needed: %lu ticks\n", T); /* Done */ return EXIT_SUCCESS; } ������������������������cc65-2.18/testcode/lib/strncmp-test.c���������������������������������������������������������������0000664�0000000�0000000�00000000622�13473601511�0017374�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <stdlib.h> #include <stdio.h> #include <string.h> static const char S1[] = { 'h', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '\0', 'A' }; static const char S2[] = { 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '\0', 'B' }; int main (void) { char I; for (I = 0; I < 20; ++I) { printf ("%02d: %d\n", I, strncmp (S1, S2, I)); } return 0; } ��������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/strnicmp-test.c��������������������������������������������������������������0000664�0000000�0000000�00000002732�13473601511�0017551�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <stdlib.h> #include <stdio.h> #include <string.h> #include <conio.h> static int do_test(const char *s1, const char *s2, size_t n) { printf("strnicmp(\"%s\", \"%s\", %d): ", s1, s2, (int)n); return strncasecmp(s1, s2, n); } int main(void) { int ret; ret = do_test("Wurzl", "wURZL", 5); if (ret) printf("fail (%d)\n", ret); else printf("OK (%d)\n", ret); ret = do_test("Wurzl", "wURZL", 6); if (ret) printf("fail (%d)\n", ret); else printf("OK (%d)\n", ret); ret = do_test("Wurzl", "wURZL", 10); if (ret) printf("fail (%d)\n", ret); else printf("OK (%d)\n", ret); ret = do_test("Wurzla", "wURZLB", 10); if (ret >= 0) printf("fail (%d)\n", ret); else printf("OK (%d)\n", ret); ret = do_test("Wurzla", "wURZLb", 5); if (ret) printf("fail (%d)\n", ret); else printf("OK (%d)\n", ret); ret = do_test("BLI", "bla", 5); if (ret <= 0) printf("fail (%d)\n", ret); else printf("OK (%d)\n", ret); ret = do_test("", "bla", 5); if (ret >= 0) printf("fail (%d)\n", ret); else printf("OK (%d)\n", ret); ret = do_test("BLI", "", 5); if (ret <= 0) printf("fail (%d)\n", ret); else printf("OK (%d)\n", ret); ret = do_test("", "", 5); if (ret) printf("fail (%d)\n", ret); else printf("OK (%d)\n", ret); cgetc(); return 0; } ��������������������������������������cc65-2.18/testcode/lib/stroserror-test.c������������������������������������������������������������0000664�0000000�0000000�00000001066�13473601511�0020135�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <stdio.h> #include <string.h> #include <conio.h> int main (void) { unsigned char error = 0; unsigned char line = 0; unsigned char maxx, maxy; screensize (&maxx, &maxy); do { printf ("%2d: %s\n", error, _stroserror (error)); if (line == maxy-3) { printf ("Press any key...\n"); if (cgetc () == 'q') { return 0; } clrscr (); line = 0; } else { ++line; } ++error; } while (error != 0); return 0; } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/strpbrk-test.c���������������������������������������������������������������0000664�0000000�0000000�00000001314�13473601511�0017374�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <stdio.h> #include <string.h> static const char fox[] = "The quick brown fox jumped over the lazy dogs."; void main (void) { printf ("Testing strpbrk():\n"); if (strpbrk (fox, "qwerty") != &fox[2]) { printf ("\nThe first 'e' wasn't found.\n"); } if (strpbrk (fox, "QWERTY") != &fox[0]) { printf ("The 'T' wasn't found.\n"); } if (strpbrk (fox, "asdfg") != &fox[16]) { printf ("The 'f' wasn't found.\n"); } if (strpbrk (fox, "nxv,zmb") != &fox[10]) { printf ("The 'b' wasn't found.\n"); } if (strpbrk (fox, "!@#$%^&*()-+=[];:',/?<>.") != &fox[45]) { printf ("The '.' wasn't found.\n"); } printf ("\nFinished.\n"); } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/strqtok-test.c���������������������������������������������������������������0000664�0000000�0000000�00000002122�13473601511�0017412�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* strqtok-test.c ** ** 2014-04-21, Paul Foerster ** 2014-05-20, Greg King ** ** This program tests that strqtok() correctly will parse strings ** with quotation marks in them. It should show this list of tokens ** from the test strings: ** ** >This< ** > is only < ** >a< ** >short< ** >quoting< ** >test , honoring blanks, commas< ** >and< ** >(4)< ** >empty< ** >< ** >< ** >< ** >< ** >strings, EOT < ** ** It shouldn't show ** ** >Bogus token< ** */ #include <string.h> #include <stdio.h> void main (void) { /* b[] and s[] are declared as automatic, not static, variables ** because strqtok() will change them. ** They must be defined together; and, b[] must be defined first ** (because they're copied onto the top-down stack). */ char b[] = "Bogus token "; char s[] = " This , \" is only \"a short " "quoting\"test , honoring blanks" ", commas\", and (4) empty \"\"\"\"\"\"\"\" \"strings, EOT "; char* t = strqtok (s, " ,"); while (t != NULL) { printf (">%s<\n", t); t = strqtok (NULL, " ,"); } } ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/strtol-test.c����������������������������������������������������������������0000664�0000000�0000000�00000007442�13473601511�0017244�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* A small test for strtol. Assumes twos complement */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <limits.h> #include <errno.h> #define outfile stderr #define ERROR 0 #define OK 1 static unsigned int Failures = 0; static void IncStr (char* Buf) /* Increment a number represented as a string by one. The string MUST not ** start with a '9', we cannot handle overflow in this case. */ { int Len = strlen (Buf); while (--Len >= 0) { switch (Buf[Len]) { case '9': Buf[Len] = '0'; break; default: ++(Buf[Len]); return; } } } static void CheckStrToL (const char* Str, int Base, long Val, unsigned char Ok) { char* EndPtr; long Res = strtol (Str, &EndPtr, Base); if (Ok) { if (Res != Val) { fprintf (outfile, "strtol error in \"%s\":\n" " result = %ld, should be %ld, chars = %d\n", Str, Res, Val, EndPtr - Str); ++Failures; } } else { if (errno != ERANGE) { fprintf (outfile, "strtol error in \"%s\":\n" " should not convert, but errno = %d\n", Str, errno); ++Failures; } if (Res != Val) { fprintf (outfile, "strtol error in \"%s\":\n" " result = %ld, should be %ld, chars = %d\n", Str, Res, Val, EndPtr - Str); ++Failures; } } } int main (void) { char Buf[80]; /* Prefixed allowed if base = 0 */ CheckStrToL ("\t 0x10G ", 0, 16L, OK); CheckStrToL ("\t 0X10G ", 0, 16L, OK); CheckStrToL (" \t0377\t", 0, 255L, OK); CheckStrToL (" 377", 0, 377L, OK); CheckStrToL ("\t -0x10G ", 0, -16L, OK); CheckStrToL ("\t -0X10G ", 0, -16L, OK); CheckStrToL (" \t-0377\t", 0, -255L, OK); CheckStrToL (" -377", 0, -377L, OK); /* No prefixes if base = 10 */ CheckStrToL ("\t 1234 ", 10, 1234L, OK); CheckStrToL ("\t -1234 ", 10, -1234L, OK); CheckStrToL ("\t -0x10G ", 10, 0L, OK); CheckStrToL ("\t -0X10G ", 10, 0L, OK); CheckStrToL (" \t-0377\t", 10, -377L, OK); CheckStrToL (" 0377", 10, 377L, OK); /* 0x prefix is allowed if base = 16 */ CheckStrToL ("\t 0x1234 ", 16, 0x1234L, OK); CheckStrToL ("\t -0x1234 ", 16, -0x1234L, OK); CheckStrToL ("\t -010G ", 16, -16L, OK); CheckStrToL ("\t 10G ", 16, 16L, OK); /* Check LONG_MIN and LONG_MAX */ sprintf (Buf, "%ld", LONG_MIN); CheckStrToL (Buf, 0, LONG_MIN, OK); sprintf (Buf, "%ld", LONG_MAX); CheckStrToL (Buf, 0, LONG_MAX, OK); /* Check value one smaller */ sprintf (Buf+1, "%ld", LONG_MIN); Buf[1] = '0'; /* Overwrite '-' */ IncStr (Buf+1); if (Buf[1] == '0') { Buf[1] = '-'; Buf[0] = ' '; } else { Buf[0] = '-'; } CheckStrToL (Buf, 0, LONG_MIN, ERROR); /* Check value one larger */ sprintf (Buf+1, "%ld", LONG_MAX); Buf[0] = '0'; IncStr (Buf); if (Buf[0] == '0') { Buf[0] = ' '; } CheckStrToL (Buf, 0, LONG_MAX, ERROR); /* Check numbers that are much too large or small */ CheckStrToL ("-999999999999999999999999999999999999999999999999999999999", 0, LONG_MIN, ERROR); CheckStrToL ("+999999999999999999999999999999999999999999999999999999999", 0, LONG_MAX, ERROR); CheckStrToL (" 999999999999999999999999999999999999999999999999999999999", 0, LONG_MAX, ERROR); /* Check a few other bases */ CheckStrToL ("aBcD", 36, 481261L, OK); CheckStrToL ("zyaB", 35, 0L, ERROR); CheckStrToL ("zyaB", 36, 1677395L, ERROR); fprintf (outfile, "Failures: %u\n", Failures); return (Failures != 0); } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/strtoul-test.c���������������������������������������������������������������0000664�0000000�0000000�00000007154�13473601511�0017431�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* A small test for strtuol. Assumes twos complement */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <limits.h> #include <errno.h> #define outfile stderr #define ERROR 0 #define OK 1 static unsigned int Failures = 0; static void IncStr (char* Buf) /* Increment a number represented as a string by one. The string MUST not ** start with a '9', we cannot handle overflow in this case. */ { int Len = strlen (Buf); while (--Len >= 0) { switch (Buf[Len]) { case '9': Buf[Len] = '0'; break; default: ++(Buf[Len]); return; } } } static void CheckStrToUL (const char* Str, int Base, unsigned long Val, unsigned char Ok) { char* EndPtr; unsigned long Res = strtoul (Str, &EndPtr, Base); if (Ok) { if (Res != Val) { fprintf (outfile, "strtol error in \"%s\":\n" " result = %lu, should be %lu, chars = %d\n", Str, Res, Val, EndPtr - Str); ++Failures; } } else { if (errno != ERANGE) { fprintf (outfile, "strtol error in \"%s\":\n" " should not convert, but errno = %d\n", Str, errno); ++Failures; } if (Res != Val) { fprintf (outfile, "strtol error in \"%s\":\n" " result = %lu, should be %lu, chars = %d\n", Str, Res, Val, EndPtr - Str); ++Failures; } } } int main (void) { char Buf[80]; /* Prefixed allowed if base = 0 */ CheckStrToUL ("\t 0x10G ", 0, 16UL, OK); CheckStrToUL ("\t 0X10G ", 0, 16UL, OK); CheckStrToUL (" \t0377\t", 0, 255UL, OK); CheckStrToUL (" 377", 0, 377UL, OK); CheckStrToUL ("\t -0x10G ", 0, (unsigned long) -16L, OK); CheckStrToUL ("\t -0X10G ", 0, (unsigned long) -16L, OK); CheckStrToUL (" \t-0377\t", 0, (unsigned long) -255L, OK); CheckStrToUL (" -377", 0, (unsigned long) -377L, OK); /* No prefixes if base = 10 */ CheckStrToUL ("\t 1234 ", 10, 1234UL, OK); CheckStrToUL ("\t -1234 ", 10, (unsigned long) -1234L, OK); CheckStrToUL ("\t -0x10G ", 10, 0UL, OK); CheckStrToUL ("\t -0X10G ", 10, 0UL, OK); CheckStrToUL (" \t-0377\t", 10, (unsigned long) -377L, OK); CheckStrToUL (" 0377", 10, 377UL, OK); /* 0x prefix is allowed if base = 16 */ CheckStrToUL ("\t 0x1234 ", 16, 0x1234UL, OK); CheckStrToUL ("\t -0x1234 ", 16, (unsigned long) -0x1234L, OK); CheckStrToUL ("\t -010G ", 16, (unsigned long) -16L, OK); CheckStrToUL ("\t 10G ", 16, 16UL, OK); /* Check ULONG_MAX */ sprintf (Buf, "%lu", ULONG_MAX); CheckStrToUL (Buf, 0, ULONG_MAX, OK); /* Check value one larger */ sprintf (Buf+1, "%lu", ULONG_MAX); Buf[0] = '0'; IncStr (Buf); if (Buf[0] == '0') { Buf[0] = ' '; } CheckStrToUL (Buf, 0, ULONG_MAX, ERROR); /* Check numbers that are much too large or small */ CheckStrToUL ("-999999999999999999999999999999999999999999999999999999999", 0, ULONG_MAX, ERROR); CheckStrToUL ("+999999999999999999999999999999999999999999999999999999999", 0, ULONG_MAX, ERROR); CheckStrToUL (" 999999999999999999999999999999999999999999999999999999999", 0, ULONG_MAX, ERROR); /* Check a few other bases */ CheckStrToUL ("aBcD", 36, 481261UL, OK); CheckStrToUL ("zyaB", 35, 0UL, ERROR); CheckStrToUL ("zyaB", 36, 1677395UL, ERROR); fprintf (outfile, "Failures: %u\n", Failures); return (Failures != 0); } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/time-test.c������������������������������������������������������������������0000664�0000000�0000000�00000001606�13473601511�0016647�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <stdio.h> #include <time.h> int main (void) { struct tm tm; time_t t; char buf[64]; tm.tm_sec = 9; tm.tm_min = 34; tm.tm_hour = 21; tm.tm_mday = 12; tm.tm_mon = 10; /* 0..11, so this is november */ tm.tm_year = 102; /* year - 1900, so this is 2002 */ tm.tm_wday = 2; /* Tuesday */ tm.tm_isdst = 0; /* Convert this broken down time into a time_t and back */ t = mktime (&tm); printf ("Test passes if the following lines are\n" "all identical:\n"); printf ("3DD173D1 - Tue Nov 12 21:34:09 2002\n"); printf ("%08lX - %s", t, asctime (&tm)); printf ("%08lX - %s", t, asctime (gmtime (&t))); strftime (buf, sizeof (buf), "%c", &tm); printf ("%08lX - %s\n", t, buf); strftime (buf, sizeof (buf), "%a %b %d %H:%M:%S %Y", &tm); printf ("%08lX - %s\n", t, buf); return 0; } ��������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/tinyshell.c������������������������������������������������������������������0000664�0000000�0000000�00000025006�13473601511�0016747�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* ** Simple ("tiny") shell to test filename and directory functions. ** Copyright (c) 2013,2016 Christian Groessler, chris@groessler.org */ #define VERSION_ASC "0.91" #ifdef __ATARI__ #define UPPERCASE /* define (e.g. for Atari) to convert filenames etc. to upper case */ #define HAVE_SUBDIRS #endif #ifdef __APPLE2__ #define HAVE_SUBDIRS #endif #ifdef __CC65__ #define CHECK_SP #endif #define KEYB_BUFSZ 127 #define PROMPT ">>> " #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <unistd.h> #ifndef __CC65__ #include <sys/stat.h> #include <sys/param.h> #define HAVE_SUBDIRS #else #define MAXPATHLEN 64 #endif #include <sys/types.h> #include <fcntl.h> #include <dirent.h> #ifdef CHECK_SP extern unsigned int getsp(void); /* comes from getsp.s */ #endif #define CMD_NOTHING 0 #define CMD_INVALID 1 #define CMD_HELP 2 #define CMD_QUIT 3 #define CMD_LS 4 #define CMD_MKDIR 5 #define CMD_RMDIR 6 #define CMD_CHDIR 7 #define CMD_RM 8 #define CMD_RENAME 9 #define CMD_COPY 10 #define CMD_PWD 11 #define CMD_CLS 12 #define CMD_VERBOSE 13 #define CMD_EXEC 14 static unsigned char verbose; static unsigned char terminate; static unsigned char cmd; static unsigned char *cmd_asc, *arg1, *arg2, *arg3, *args; /* 'args': everything after command */ static unsigned char keyb_buf[KEYB_BUFSZ + 1]; static unsigned char keyb_buf2[KEYB_BUFSZ + 1]; static size_t cpbuf_sz = 4096; struct cmd_table { unsigned char *name; unsigned char code; } cmd_table[] = { { "help", CMD_HELP }, { "quit", CMD_QUIT }, { "q", CMD_QUIT }, { "exit", CMD_QUIT }, { "ls", CMD_LS }, { "dir", CMD_LS }, { "md", CMD_MKDIR }, #ifdef HAVE_SUBDIRS { "mkdir", CMD_MKDIR }, { "rd", CMD_RMDIR }, { "rmdir", CMD_RMDIR }, { "cd", CMD_CHDIR }, { "chdir", CMD_CHDIR }, #endif { "rm", CMD_RM }, { "del", CMD_RM }, { "cp", CMD_COPY }, { "copy", CMD_COPY }, { "mv", CMD_RENAME }, { "ren", CMD_RENAME }, { "pwd", CMD_PWD }, { "exec", CMD_EXEC }, #ifdef __ATARI__ { "cls", CMD_CLS }, #endif { "verbose", CMD_VERBOSE }, { NULL, 0 } }; static void banner(void) { puts("\"tiny\" command line shell, v" VERSION_ASC); puts("written by chris@groessler.org"); puts("type 'help' for help\n"); } static void get_command(void) { unsigned char i = 0; #ifdef CHECK_SP static char firstcall = 1; static unsigned int good_sp; unsigned int sp; if (firstcall) sp = good_sp = getsp(); else sp = getsp(); if (sp != good_sp) { printf("SP: 0x%04X ***MISMATCH*** 0x%04X\n", sp, good_sp); } else if (verbose) printf("SP: 0x%04X\n", sp); #endif arg1 = arg2 = arg3 = NULL; /* issue prompt */ printf(PROMPT); /* get input from the user */ if (! fgets(keyb_buf, KEYB_BUFSZ, stdin)) { puts(""); cmd = CMD_QUIT; return; } /* put everything after first string into 'args' */ strcpy(keyb_buf2, keyb_buf); /* use a backup copy for 'args' */ /* skip over the first non-whitespace item */ cmd_asc = strtok(keyb_buf2, " \t\n"); if (cmd_asc) args = strtok(NULL, ""); /* get everything */ else *args = 0; /* no arguments */ /* split input into cmd, arg1, arg2, arg3 */ /* get and parse command */ cmd_asc = strtok(keyb_buf, " \t\n"); if (! cmd_asc) { cmd = CMD_NOTHING; return; } cmd = CMD_INVALID; while (cmd_table[i].name) { if (! strcmp(cmd_table[i].name, cmd_asc)) { cmd = cmd_table[i].code; break; } i++; } /* get arguments */ arg1 = strtok(NULL, " \t\n"); if (! arg1) return; arg2 = strtok(NULL, " \t\n"); if (! arg2) return; arg3 = strtok(NULL, " \t\n"); } static void cmd_help(void) { puts("quit, exit - exit shell"); puts("ls, dir - display current directory"); puts(" and drive contents"); puts("rm, del - delete file"); puts("cp, copy - copy file"); puts("mv, ren - rename file"); puts("cd, chdir - change directory or drive"); puts("md, mkdir - make directory or drive"); puts("rd, rmdir - remove directory or drive"); puts("exec - run program"); #ifdef __ATARI__ puts("cls - clear screen"); #endif puts("verbose - set verbosity level"); } static void cmd_ls(void) { DIR *dir; unsigned char *arg; struct dirent *dirent; #ifdef __ATARI__ char need_free = 0; #endif if (arg2) { puts("usage: ls [dir]"); return; } /* print directory listing */ if (arg1) { #ifdef UPPERCASE strupr(arg1); #endif #ifdef __ATARI__ /* not sure if this shouldn't be done by the runtime lib */ if (*(arg1 + strlen(arg1) - 1) == ':' || *(arg1 + strlen(arg1) - 1) == '>') { arg = malloc(strlen(arg1) + 4); if (! arg) { printf("malloc failed: %s", strerror(errno)); return; } need_free = 1; memcpy(arg, arg1, strlen(arg1) + 1); strcat(arg, "*.*"); } else #endif arg = arg1; } else arg = "."; if (verbose) printf("Buffer addr: %p\n", arg); dir = opendir(arg); #ifdef __ATARI__ if (need_free) free(arg); #endif if (! dir) { puts("opendir failed"); return; } while (dirent = readdir(dir)) puts(dirent->d_name); closedir(dir); } static void cmd_rm(void) { if (!arg1 || arg2) { puts("usage: rm <file>"); return; } #ifdef UPPERCASE strupr(arg1); #endif if (unlink(arg1)) printf("remove failed: %s\n", strerror(errno)); } #ifdef HAVE_SUBDIRS static void cmd_mkdir(void) { if (!arg1 || arg2) { puts("usage: mkdir <dir>"); return; } #ifdef UPPERCASE strupr(arg1); #endif if (mkdir(arg1, 0777)) printf("mkdir failed: %s\n", strerror(errno)); } static void cmd_rmdir(void) { if (!arg1 || arg2) { puts("usage: rmdir <dir>"); return; } #ifdef UPPERCASE strupr(arg1); #endif if (rmdir(arg1)) printf("rmdir failed: %s\n", strerror(errno)); } static void cmd_chdir(void) { if (!arg1 || arg2) { puts("usage: cddir <dir>"); return; } #ifdef UPPERCASE strupr(arg1); #endif if (chdir(arg1)) printf("chdir failed: %s\n", strerror(errno)); } static void cmd_pwd(void) { char *buf; if (arg1) { puts("usage: pwd"); return; } buf = malloc(MAXPATHLEN); if (! buf) { printf("malloc %u bytes failed: %s\n", MAXPATHLEN, strerror(errno)); return; } if (verbose) printf("Buffer addr: %p\n", buf); if (!getcwd(buf, MAXPATHLEN)) { printf("getcwd failed: %s\n", strerror(errno)); free(buf); return; } puts(buf); free(buf); } #endif /* #ifdef HAVE_SUBDIRS */ static void cmd_rename(void) { if (!arg2 || arg3) { puts("usage: mv <oldname> <newname>"); return; } #ifdef UPPERCASE strupr(arg1); strupr(arg2); #endif if (rename(arg1, arg2)) printf("rename failed: %s\n", strerror(errno)); } static void cmd_exec(void) { unsigned char *progname, *arguments; progname = strtok(args, " \t\n"); if (! progname) { puts("usage: exec <progname> [arguments]"); return; } arguments = strtok(NULL, ""); /*printf("exec: %s %s\n", progname, arguments ? arguments : "");*/ (void)exec(progname, arguments); printf("exec error: %s\n", strerror(errno)); } static void cmd_copy(void) { int srcfd = -1, dstfd = -1; unsigned char *buf; int readsz, writesz; if (!arg2 || arg3) { puts("usage: cp <src> <dest>"); return; } #ifdef UPPERCASE strupr(arg1); strupr(arg2); #endif buf = malloc(cpbuf_sz); if (! buf) { printf("malloc %u bytes failed: %s\n", cpbuf_sz, strerror(errno)); return; } if (verbose) printf("Buffer addr: %p\n", buf); while (1) { if (srcfd == -1) { srcfd = open(arg1, O_RDONLY); if (srcfd < 0) { printf("open(%s) failed: %s\n", arg1, strerror(errno)); break; } } readsz = read(srcfd, buf, cpbuf_sz); if (readsz < 0) { printf("read error: %s\n", strerror(errno)); break; } if (! readsz) break; if (dstfd == -1) { dstfd = open(arg2, O_WRONLY | O_CREAT | O_TRUNC, 0777); if (dstfd < 0) { printf("open(%s) failed: %s\n", arg2, strerror(errno)); break; } } writesz = write(dstfd, buf, readsz); if (writesz < 0 || writesz != readsz) { printf("write error: %s\n", strerror(errno)); break; } if (readsz != cpbuf_sz) break; } free(buf); if (srcfd >= 0) close(srcfd); if (dstfd >= 0) close(dstfd); } #ifdef __ATARI__ static void cmd_cls(void) { printf("\f"); } #endif static void cmd_verbose(void) { unsigned long verb; char *endptr; if (!arg1 || arg2) { puts("usage: verbose <level>"); return; } verb = strtoul(arg1, &endptr, 10); if (verb > 255 || *endptr) { puts("invalid verbosity level"); return; } verbose = verb; printf("verbosity level set to %d\n", verbose); } static void run_command(void) { switch (cmd) { default: puts("internal error"); return; case CMD_NOTHING: return; case CMD_INVALID: puts("invalid command"); return; case CMD_HELP: cmd_help(); return; case CMD_QUIT: terminate = 1; return; case CMD_LS: cmd_ls(); return; case CMD_RM: cmd_rm(); return; #ifdef HAVE_SUBDIRS case CMD_CHDIR: cmd_chdir(); return; case CMD_MKDIR: cmd_mkdir(); return; case CMD_RMDIR: cmd_rmdir(); return; case CMD_PWD: cmd_pwd(); return; #endif case CMD_EXEC: cmd_exec(); return; case CMD_RENAME: cmd_rename(); return; case CMD_COPY: cmd_copy(); return; #ifdef __ATARI__ case CMD_CLS: cmd_cls(); return; #endif case CMD_VERBOSE: cmd_verbose(); return; } } int main(void) { banner(); while (! terminate) { get_command(); run_command(); } return 0; } /* Local Variables: */ /* c-file-style: "cpg" */ /* c-basic-offset: 4 */ /* End: */ ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/testcode/lib/uname-test.c�����������������������������������������������������������������0000664�0000000�0000000�00000001055�13473601511�0017014�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <stdio.h> #include <stdlib.h> #include <sys/utsname.h> int main (void) { /* Get the uname data */ struct utsname buf; if (uname (&buf) != 0) { perror ("uname"); return EXIT_FAILURE; } /* Print it */ printf ("sysname: \"%s\"\n", buf.sysname); printf ("nodename: \"%s\"\n", buf.nodename); printf ("release: \"%s\"\n", buf.release); printf ("version: \"%s\"\n", buf.version); printf ("machine: \"%s\"\n", buf.machine); /* Done */ return EXIT_SUCCESS; } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/util/�������������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0013162�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/util/atari/�������������������������������������������������������������������������������0000775�0000000�0000000�00000000000�13473601511�0014262�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/util/atari/ataricvt.c���������������������������������������������������������������������0000664�0000000�0000000�00000000425�13473601511�0016244�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#include <stdio.h> int main (void) { int C; while ((C = getchar ()) != EOF) { if (C == 0x9B) { putchar ('\n'); } else if (C == 0x7F) { putchar ('\t'); } else { putchar (C); } } return 0; } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������cc65-2.18/util/ca65html�����������������������������������������������������������������������������0000664�0000000�0000000�00000114622�13473601511�0014536�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/bin/perl ############################################################################### # # # ca65html # # # # Convert a ca65 source into HTML # # # # # # # # (C) 2000-2007 Ullrich von Bassewitz # # Roemerstrasse 52 # # D-70794 Filderstadt # # EMail: uz@cc65.org # # # # # # This software is provided 'as-is', without any expressed or implied # # warranty. In no event will the authors be held liable for any damages # # arising from the use of this software. # # # # Permission is granted to anyone to use this software for any purpose, # # including commercial applications, and to alter it and redistribute it # # freely, subject to the following restrictions: # # # # 1. The origin of this software must not be misrepresented; you must not # # claim that you wrote the original software. If you use this software # # in a product, an acknowledgment in the product documentation would be # # appreciated but is not required. # # 2. Altered source versions must be plainly marked as such, and must not # # be misrepresented as being the original software. # # 3. This notice may not be removed or altered from any source # # distribution. # # # ############################################################################### # Things currently missing: # # - Scoping with .proc/.endproc, .scope/.endscope, .enum/.endenum, # .struct/.endstruct, .union/endunion, .repeat/.endrep, .local # - .global is ignored # - .case is ignored, labels are always case-sensitive # - .include handling (difficult) # - The global namespace operator :: # use strict 'vars'; use warnings; # Modules use Getopt::Long; #-----------------------------------------------------------------------------# # Variables # # ----------------------------------------------------------------------------# # Global variables my %Files = (); # List of all files. my $FileCount = 0; # Number of input files my %Exports = (); # List of exported symbols. my %Imports = (); # List of imported symbols. my %Labels = (); # List of all labels my $LabelNum = 0; # Counter to generate unique labels # Command line options my $BGColor = "#FFFFFF"; # Background color my $Colorize = 0; # Colorize the output my $CommentColor = "#B22222"; # Color for comments my $CRefs = 0; # Add references to the C file my $CtrlColor = "#228B22"; # Color for control directives my $CvtTabs = 0; # Convert tabs to spaces my $TabSize = 8; # This is how god created them my $Debug = 0; # No debugging my $Help = 0; # Help flag my $HTMLDir = ""; # Directory in which to create the files my $IndexCols = 6; # Columns in the file listing my $IndexTitle = "Index"; # Title of index page my $IndexName = "index.html"; # Name of index page my $IndexPage = 0; # Create an index page my $KeywordColor = "#A020F0"; # Color for keywords my $LineLabels = 0; # Add a HTML label to each line my $LineNumbers = 0; # Add line numbers to the output my $LinkStyle = 0; # Default link style my $ReplaceExt = 0; # Replace extension instead of appending my $StringColor = "#6169C1"; # Color for strings my $TextColor = "#000000"; # Text color my $Verbose = 0; # Be quiet # Table used to convert the label number into names my @NameTab = ('A' .. 'Z', '0' .. '9'); #-----------------------------------------------------------------------------# # Helper functions # # ----------------------------------------------------------------------------# # Terminate with an error sub Abort { print STDERR "ca65html: @_\n"; exit 1; } # Print a message if verbose is true sub Gabble { if ($Verbose) { print "ca65html: @_\n"; } } # Generate a label and return it sub GenLabel { my $I; my $L = "";; my $Num = $LabelNum++; # Generate the label for ($I = 0; $I < 4; $I++) { $L = $NameTab[$Num % 36] . $L; $Num /= 36; } return $L; } # Make an output file name from an input file name sub GetOutName { # Input name is parameter my $InName = $_[0]; # Create the output file name from the input file name if ($ReplaceExt && $InName =~ /^(.+)\.([^\.\/]*)$/) { return "$1.html"; } else { return "$InName.html"; } } # Translate some HTML characters into harmless names. sub Cleanup { my $S = shift (@_); $S =~ s/&/&/g; $S =~ s/</</g; $S =~ s/>/>/g; $S =~ s/\"/"/g; return $S; } # Strip a path from a filename and return just the name sub StripPath { # Filename is argument my $FileName = $_[0]; # Remove a path name if we have one $FileName =~ /^(.*?)([^\/]*)$/; return $2; } #-----------------------------------------------------------------------------# # Document header and footer # # ----------------------------------------------------------------------------# # Print the document header sub DocHeader { my $OUT = shift (@_); my $Asm = shift (@_); print $OUT "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"; print $OUT <<"EOF"; <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta name="GENERATOR" content="ca65html"> <title>$Asm

$Asm

EOF } # Print the document footer sub DocFooter { my $OUT = shift (@_); my $Name = shift (@_); # Get the current date and time my $Today = localtime; # Print print $OUT "
\n"; print $OUT "\n"; print $OUT "\"Valid
\n"; print $OUT "$Name; generated on $Today by ca65html
\n"; print $OUT "uz@cc65.org\n"; print $OUT "
\n"; print $OUT "\n"; } #-----------------------------------------------------------------------------# # Colorization # #-----------------------------------------------------------------------------# sub ColorizeComment { if ($Colorize && $_[0] ne "") { return "$_[0]"; } else { return $_[0]; } } sub ColorizeCtrl { if ($Colorize) { return "$_[0]"; } else { return $_[0]; } } sub ColorizeKeyword { if ($Colorize) { return "$_[0]"; } else { return $_[0]; } } sub ColorizeString { if ($Colorize) { return "$_[0]"; } else { return $_[0]; } } #-----------------------------------------------------------------------------# # File list management # #-----------------------------------------------------------------------------# sub AddFile { # Argument is file to add my $FileName = $_[0]; # Get just the name (remove a path if there is one) my $Name = StripPath ($FileName); # Check if we have the file already if (exists ($Files{$Name})) { Gabble ("File \"$FileName\" already known"); return; } # Check with the full pathname. If we don't find it, search in the current # directory if (-f $FileName && -r _) { $Files{$Name} = $FileName; $FileCount++; } elsif (-f $Name && -r _) { $Files{$Name} = $Name; $FileCount++; } else { Abort ("$FileName not found or not readable"); } } #-----------------------------------------------------------------------------# # Referencing and defining labels # #-----------------------------------------------------------------------------# # Get a label reference sub RefLabel { # Arguments are: Filename, identifier, item that should be tagged my $FileName = $_[0]; my $Id = $_[1]; my $Item = $_[2]; # Search for the identifier in the list of labels if (exists ($Labels{$FileName}{$Id})) { # It is a label (in this file) return sprintf ("%s", $Labels{$FileName}{$Id}, $Item); } elsif (exists ($Imports{$FileName}{$Id})) { # It is an import. If LinkStyle is 1, or if the file exporting the # identifier is not visible, we link to the .import statement in the # current file. Otherwise we link directly to the referenced symbol # in the file that exports it. if ($LinkStyle == 1 or not exists ($Exports{$Id})) { return sprintf ("%s", $Imports{$FileName}{$Id}, $Item); } else { # Get the filename from the export my $Label; ($FileName, $Label) = split (/#/, $Exports{$Id}); if (not defined ($Labels{$FileName}{$Id})) { # This may currently happen because we don't see .include # statements, so we may have an export but no definition. # Link to the .export statement instead $Label = $Exports{$Id}; } else { # Link to the definition in the file $Label = sprintf ("%s#%s", $FileName, $Labels{$FileName}{$Id}); } return sprintf ("%s", $Label, $Item); } } else { # The symbol is unknown, return as is return $Item; } } #-----------------------------------------------------------------------------# # Pass 1 # # ----------------------------------------------------------------------------# # Process1: Read one file for the first time. sub Process1 { # Variables my $Line; my $Id; # Filename is parameter my $InName = shift(@_); # Create the output file name from the input file name my $OutName = GetOutName ($InName); # Current cheap local label prefix is empty my $CheapPrefix = ""; # Open a the input file my $FileName = $Files{$InName}; # Includes path if needed open (INPUT, "<$FileName") or Abort ("Cannot open $FileName: $!"); # Keep the user happy Gabble ("$FileName => $OutName"); # Read and process all lines from the file while ($Line = ) { # Remove the newline chomp ($Line); # Check for a label if ($Line =~ /^\s*(([\@?]?)[_a-zA-Z]\w*)\s*(?::=?|=)/) { # Is this a local label? if ($2 ne "") { # Use the prefix $Id = "$CheapPrefix$1"; } else { # Use as is $Id = $1; # Remember the id as new cheap local prefix $CheapPrefix = $Id; } # Remember the label $Labels{$OutName}{$Id} = GenLabel(); # Check for an import statement } elsif ($Line =~ /^\s*\.(?:(?:force)?import|importzp)\s+(.*?)\s*(?:;.*)?$/i) { # Split into a list of identifiers my @Ids = split (/\s*(?::\s*[A-Za-z]+\s*)?,\s*/, $1); # Remove an address-size specifier, from the last identifier, # if there is one. $Ids[$#Ids] =~ s/\s*:\s*[A-Za-z]+//; for $Id (@Ids) { $Imports{$OutName}{$Id} = GenLabel(); } # Check for an export statement } elsif ($Line =~ /^\s*\.export(?:zp)?\s+(.*?)\s*(?:;.*)?$/i) { # Split into a list of identifiers my @Ids = split (/\s*(?::\s*[A-Za-z]+\s*)?,\s*/, $1); # Remove an address-size specifier, from the last identifier, # if there is one. $Ids[$#Ids] =~ s/\s*:\s*[A-Za-z]+//; for $Id (@Ids) { $Exports{$Id} = sprintf ("%s#%s", $OutName, GenLabel()); } # Check for an actor statement. } elsif ($Line =~ /^\s*\.(?:(?:(?:con|de)struc|interrup)tor|condes)\s+([_a-z]\w*)/i) { $Exports{$1} = sprintf ("%s#%s", $OutName, GenLabel()); # Check for a .proc statement } elsif ($Line =~ /^\s*\.proc\s+([_a-z]\w*)/i) { # Remember the ID as the new cheap-local prefix. $CheapPrefix = $1; $Labels{$OutName}{$1} = GenLabel(); } } # Close the input file close (INPUT); } # Pass1: Read all files for the first time. sub Pass1 () { # Keep the user happy Gabble ("Pass 1"); # Walk over the files for my $InName (keys (%Files)) { # Process one file Process1 ($InName); } } #-----------------------------------------------------------------------------# # Pass 2 # # ----------------------------------------------------------------------------# # Process2: Read one file the second time. sub Process2 { # Variables my $Base; my $Ext; my $Line; my $OutLine; my $Id; my $Label; my $Comment; my $Trailer; # Input file is parameter my $InName = shift(@_); # Create the output file name from the input file name my $OutName = GetOutName ($InName); # Current cheap local label prefix is empty my $CheapPrefix = ""; # Open a the input file my $FileName = $Files{$InName}; # Includes path if needed open (INPUT, "<$FileName") or Abort ("Cannot open $FileName: $!"); # Open the output file and print the HTML header open (OUTPUT, ">$HTMLDir$OutName") or Abort ("Cannot open $OutName: $!"); DocHeader (OUTPUT, $InName); print OUTPUT "
\n";

    # Keep the user happy
    Gabble ("$FileName => $OutName");

    # The instructions that will have hyperlinks if a label is used.
    # And, they will be highlighted when color is used.
    my $LabelIns = "adc|add|and|asl|bb[rs][0-7]|b[cv][cs]|beq|bge|bit|blt|".
                 "bmi|bne|bpl|br[akl]|bsr|cmp|cop|cp[axy]|dec|eor|inc|jml|".
                 "jmp|jsl|jsr|ld[axy]|lsr|mvn|mvp|ora|pe[air]|rep|".
                 "[rs]mb[0-7]|rol|ror|sbc|sep|st[012axyz]|sub|tai|tam|tdd|".
                 "ti[ain]|tma|trb|tsb|tst";

    # Instructions that have only the implied-addressing mode -- therefore,
    # no hyperlinking.  They will be highlighted only, when color is used.
    my $OtherIns = "cl[acdivxy]|csh|csl|de[axy]|in[axy]|nop|ph[abdkpxy]|".
                 "pl[abdpxy]|rt[ils]|sax|say|se[cdit]|stp|swa|sxy|ta[dsxy]|".
                 "tam[0-7]|tcd|tcs|tda|tdc|tma[0-7]|ts[acx]|tx[asy]|tya|tyx|".
                 "wai|xba|xce";

    # Read the input file, replacing references with hyperlinks; and, mark
    # labels as link targets.
    my $LineNo = 0;
    LINE: while ($Line = ) {

        # Count input lines
        $LineNo++;

        # Remove the newline at the end of line. Don't use chomp to be able to
        # read dos/windows sources on unices.
        $Line =~ s/[\r\n]*$//;

        # If requested, convert tabs to spaces
        if ($CvtTabs) {
            # Don't ask me - this is from the perl manual page
            1 while ($Line =~ s/\t+/' ' x (length($&) * $TabSize - length($`) % $TabSize)/e) ;
        }

        # Clear the output line
        $OutLine = "";

        # If requested, add a html label to each line with a name "linexxx",
        # so it can be referenced from the outside (this is the same convention
        # that is used by c2html). If we have line numbers enabled, add them.
        if ($LineLabels && $LineNumbers) {
            $OutLine .= sprintf ("%6d:  ", $LineNo, $LineNo);
        } elsif ($LineLabels) {
            $OutLine .= sprintf ("", $LineNo);
        } elsif ($LineNumbers) {
            $OutLine .= sprintf ("%6d:  ", $LineNo);
        }

        # Cut off a comment from the input line. Beware: We have to check for
        # strings, since these may contain a semicolon that is no comment
        # start.
        ($Line, $Comment) = $Line =~ /^((?:[^"';]+|".*?"|'.*?')*)(.*)$/;
        if ($Comment =~ /^["']/) {
            # Line with invalid syntax - there's a string start but
            # no string end.
            Abort (sprintf ("Invalid input at %s(%d)", $FileName, $LineNo));
        }

        # Remove trailing whitespace and move it together with the comment
        # into the $Trailer variable.
        $Line =~ s/\s*$//;
        $Trailer = $& . ColorizeComment (Cleanup ($Comment));

        # Check for a label at the start of the line. If we have one, process
        # it, and remove it from the line.
        if ($Line =~ s/^\s*?(([\@?]?)[_a-zA-Z]\w*)(\s*(?::=?|=))//) {

            # Is this a local label?
            if ($2 ne "") {
                # Use the prefix
                $Id = "$CheapPrefix$1";
            } else {
                # Use as is
                $Id = $1;
                # Remember the id as new cheap local prefix
                $CheapPrefix = $Id;
            }

            # Get the label for the id
            $Label = $Labels{$OutName}{$Id};

            # Print the label with a tag
            $OutLine .= "$1$3";

            # Is the name explicitly assigned a value?
            if ($3 =~ /=$/) {
                # Print all identifiers if there are any.
                while ($Line =~ s/^([^_a-zA-Z]*?)(([\@?]?)[_a-zA-Z]\w*)//) {
                    # Add the non-label stuff.
                    $OutLine .= Cleanup ($1);

                    # Use the prefix if the label is local.
                    # Get the reference to that label if we find it.
                    $OutLine .= RefLabel ($OutName, ($3 ne "") ? "$CheapPrefix$2" : $2, $2);
                }

                # Add a remainder if there is one.
                $OutLine .= Cleanup ($Line);

                # The line is complete; print it.
                next LINE;
            }
        }

        # Print any leading whitespace and remove it, so we don't have to
        # care about whitespace below.
        if ($Line =~ s/^\s+//) {
            $OutLine .= $&;
        }

        # Handle the import statements
        if ($Line =~ s/^\.(?:(?:force)?import|importzp)\s+//i) {

            # Print any fixed stuff from the line and remove it
            $OutLine .= $&;

            # Print all identifiers if there are any
            while ($Line =~ s/^[_a-zA-Z]\w*//) {

                # Remember the identifier
                my $Id = $&;

                # Variable to assemble HTML representation
                my $Contents = "";

                # Make this import a link target
                if (exists ($Imports{$OutName}{$Id})) {
                    $Label = $Imports{$OutName}{$Id};
                    $Contents .= sprintf (" name=\"%s\"", $Label);
                }

                # If we have an export for this import, add a link to this
                # export definition
                if (exists ($Exports{$Id})) {
                    $Label = $Exports{$Id};
                    $Contents .= sprintf (" href=\"%s\"", $Label);
                }

                # Add the HTML stuff to the output line
                if ($Contents ne "") {
                    $OutLine .= sprintf ("%s", $Contents, $Id);
                } else {
                    $OutLine .= $Id;
                }

                # Check if another identifier follows
                if ($Line =~ s/^\s*(?::\s*[A-Za-z]+\s*)?,\s*//) {
                    $OutLine .= $&;
                } else {
                    last;
                }
            }

            # Add an remainder if there is one
            $OutLine .= Cleanup ($Line);

        # Handle export statements
        } elsif ($Line =~ s/^\.export(?:zp)?\s+//i) {

            # Print the command and the whitespace.
            $OutLine .= $&;

            # Print all identifiers if there are any
            while ($Line =~ s/^[_a-zA-Z]\w*//) {

                # Remember the identifier
                my $Id = $&;

                # Variable to assemble HTML representation
                my $Contents = "";

                # If we have a definition for this export in this file, add
                # a link to the definition.
                if (exists ($Labels{$OutName}{$Id})) {
                    $Label = $Labels{$OutName}{$Id};
                    $Contents = sprintf (" href=\"#%s\"", $Label);
                }

                # If we have this identifier in the list of exports, add a
                # jump target for the export.
                if (exists ($Exports{$Id})) {
                    $Label = $Exports{$Id};
                    # Be sure to use only the label part
                    $Label =~ s/^.*#//;
                    $Contents .= sprintf (" name=\"%s\"", $Label);
                }

                # Add the HTML stuff to the output line
                if ($Contents ne "") {
                    $OutLine .= sprintf ("%s", $Contents, $Id);
                } else {
                    $OutLine .= $Id;
                }

                # Check if another identifier follows
                if ($Line =~ s/^\s*(?::\s*[A-Za-z]+\s*)?,\s*//) {
                    $OutLine .= $&;
                } else {
                    last;
                }
            }

            # Add an remainder if there is one
            $OutLine .= Cleanup ($Line);

        # Handle actor statements.
        } elsif ($Line =~ s/^(\.(?:(?:(?:con|de)struc|interrup)tor|condes)\s+)([_a-z]\w*)//i) {

            # Print the command and the whitespace.
            $OutLine .= $1;

            # Remember the identifier.
            $Id = $2;

            # Variable to assemble HTML representation
            my $Contents = "";

            # If we have a definition for this actor, in this file,
            # then add a link to that definition.
            if (exists ($Labels{$OutName}{$Id})) {
                $Contents = sprintf (" href=\"#%s\"", $Labels{$OutName}{$Id});
            }

            # Get the target, for linking from imports in other files.
            $Label = $Exports{$Id};
            # Be sure to use only the label part.
            $Label =~ s/^.*#//;

            # Add the HTML stuff and the remainder of the actor
            # to the output line.
            $OutLine .= sprintf ("%s%s", $Label,
                                 $Contents, $Id, Cleanup ($Line));

        # Check for .faraddr, .addr, .dword, .word, .dbyt, .byt, .byte, .res,
        # .elseif, .if, .align, and .org.
        } elsif ($Line =~ s/^\.(?:(?:far)?addr|d?word|d?byte?|res|(?:else)?if|align|org)\s+//i) {

            # Print the command and the white space
            $OutLine .= $&;

            # Print all identifiers if there are any
            while ($Line =~ s/^([^_a-zA-Z]*?)(([\@?]?)[_a-zA-Z]\w*)//) {
                # Add the non label stuff
                $OutLine .= Cleanup ($1);

                # Use the prefix if the label is local.
                # Get the reference to that label if we find it.
                $OutLine .= RefLabel ($OutName, ($3 ne "") ? "$CheapPrefix$2" : $2, $2);
            }

            # Add an remainder if there is one
            $OutLine .= Cleanup ($Line);

        # Handle .proc
        } elsif ($Line =~ /^(\.proc)(\s+)([_a-z]\w*)?(.*)$/i) {

            # Do we have an identifier?
            if ($3 ne "") {
                # Remember the ID as the new cheap-local prefix.
                $CheapPrefix = $3;

                # Get the label for the id
                $Label = $Labels{$OutName}{$3};

                # Print the label with a tag
                $OutLine .= "$1$2$3";

            } else {

                # Print a line that has invalid syntax (its operand isn't
                # a correctly formed name).
                $OutLine .= "$1$2";
            }

            # Add the remainder
            $OutLine .= Cleanup ($4);

        # Handle .include
        } elsif ($Line =~ /^(\.include)(\s*)\"((?:[^\"]+?|\\\")+)(\".*)$/i) {

            # Add the fixed stuff to the output line
            $OutLine .= "$1$2"";

            # Get the filename into a named variable
            my $FileName = Cleanup ($3);

            # Get the name without a path
            my $Name = StripPath ($3);

            # If the include file is among the list of our files, add a link,
            # otherwise just add the name as is.
            if (exists ($Files{$Name})) {
                $OutLine .= sprintf ("%s", GetOutName ($Name), $FileName);
            } else {
                $OutLine .= $FileName;
            }

            # Add the remainder
            $OutLine .= Cleanup ($4);

        # Handle .dbg line
        } elsif ($CRefs && $Line =~ s/^\.dbg\s+//) {

            # Add the fixed stuff to the output line
            $OutLine .= $&;

            # Check for the type of the .dbg directive
            if ($Line =~ /^(line,\s*)\"((?:[^\"]+?|\\\")+)\"(,\s*)(\d+)(.*)$/) {

                # Add the fixed stuff to the output line
                $OutLine .= "$1"";

                # Get the filename and line number into named variables
                my $DbgFile = $2;
                my $DbgLine = $4;

                # Remember the remainder
                $Line = "\"$3$4$5";

                # Get the name without a path
                my $Name = StripPath ($DbgFile);

                # We don't need FileName any longer as is, so clean it up
                $DbgFile = Cleanup ($DbgFile);

                # Add a link to the source file
                $OutLine .= sprintf ("%s", $Name, $DbgLine, $DbgFile);

                # Add the remainder
                $OutLine .= Cleanup ($Line);

            } elsif ($Line =~ /^(file,\s*)\"((?:[^\"]+?|\\\")+)\"(.*)$/) { #pf FIXME: doesn't handle \" correctly!

                # Get the filename into a named variables
                my $DbgFile = Cleanup ($2);

                # Get the name without a path
                my $Name = Cleanup (StripPath ($2));

                # Add the fixed stuff to the output line
                $OutLine .= sprintf ("%s\"%s\"%s",
                                     $1, $Name, $DbgFile, $3);

            } else {

                # Add the remainder
                $OutLine .= Cleanup ($Line);

            }

        } elsif ($CRefs && $Line =~ /^(\.dbg)(\s+line,\s*)\"((?:[^\"]+?|\\\")+)\"(,\s*)(\d+)(.*$)/) {

            # Add the fixed stuff to the output line
            $OutLine .= "$1$2"";

            # Get the filename and line number into named variables
            my $FileName = $3;
            my $LineNo   = $5;

            # Remember the remainder
            $Line = "\"$4$5$6";

            # Get the name without a path
            my $Name = StripPath ($FileName);

            # We don't need FileName any longer as is, so clean it up
            $FileName = Cleanup ($FileName);

            # Add a link to the source file
            $OutLine .= sprintf ("%s", $Name, $LineNo, $FileName);

            # Add the remainder
            $OutLine .= Cleanup ($Line);

        # Check for .ifdef, .ifndef, .ifref, and .ifnref.
        } elsif ($Line =~ s/^(\.ifn?[dr]ef\s+)(([\@?]?)[_a-z]\w*)?//i) {

            # Print the command and the whitespace.
            $OutLine .= $1;

            if ($2 ne "") {
                # Use the prefix if the label is local.
                # Get the reference to that label if we find it.
                $OutLine .= RefLabel ($OutName, ($3 ne "") ? "$CheapPrefix$2" : $2, $2);
            }

            # Add a remainder if there is one.
            $OutLine .= Cleanup ($Line);

        # Check for assertions.
        } elsif ($Line =~ s/^(\.assert\s+)(.+?)(,\s*(?:error|warning)\s*(?:,.*)?)$/$2/i) {

            # Print the command and the whitespace.
            $OutLine .= $1;

            $Comment = $3;

            # Print all identifiers if there are any.
            while ($Line =~ s/^([^_a-zA-Z]*?)(([\@?]?)[_a-zA-Z]\w*)//) {
                # Add the non-label stuff.
                $OutLine .= Cleanup ($1);

                # Use the prefix if the label is local.
                # Get the reference to that label if we find it.
                $OutLine .= RefLabel ($OutName, ($3 ne "") ? "$CheapPrefix$2" : $2, $2);
            }

            # Add a remainder if there is one.
            $OutLine .= Cleanup ($Line . $Comment);

        # Check for instructions with labels
        } elsif ($Line =~ s/^($LabelIns)\b(\s*)//io) {

            # Print the instruction and white space
            $OutLine .= ColorizeKeyword ($1) . $2;

            # Print all identifiers if there are any.
            while ($Line =~ s/^([^_a-zA-Z]*?)(([\@?]?)[_a-zA-Z]\w*)//) {

                # Add the non-label stuff.
                $OutLine .= Cleanup ($1);

                # Is this a local label?
                if ($3 ne "") {
                    # Use the prefix
                    $Id = "$CheapPrefix$2";
                } else {
                    # Use as is
                    $Id = $2;
                }

                # Get the reference to this label if we find it
                $OutLine .= RefLabel ($OutName, $Id, $2);
            }

            # Reassemble and print the line
            $OutLine .= Cleanup ($Line);

        # Check for all other instructions
        } elsif ($Line =~ /^($OtherIns)\b(.*)$/io) {

            # Colorize and print
            $OutLine .= ColorizeKeyword ($1) . Cleanup ($2);

        } else {

            # Nothing known - print the line
            $OutLine .= Cleanup ($Line);

        }

    } continue {
        # Colorize all keywords
        $OutLine =~ s/(?\n";
    DocFooter (OUTPUT, $OutName);

    # Close the files
    close (INPUT);
    close (OUTPUT);
}



# Pass2: Read all files the second time.
sub Pass2 () {

    # Keep the user happy
    Gabble ("Pass 2");

    # Walk over the files
    for my $InName (keys (%Files)) {
        # Process one file
        Process2 ($InName);
    }
}



#-----------------------------------------------------------------------------#
#                            Create an index page                             #
# ----------------------------------------------------------------------------#



# Print a list of all files
sub FileIndex {

    # File is argument
    my $INDEX = $_[0];

    # Print the file list in a table
    print $INDEX "

Files

\n"; print $INDEX "\n"; my $Count = 0; for my $File (sort (keys (%Files))) { # if (($Count % $IndexCols) == 0) { print $INDEX "\n"; } printf $INDEX "\n", GetOutName ($File), $File; if (($Count % $IndexCols) == $IndexCols-1) { print $INDEX "\n"; } $Count++; } if (($Count % $IndexCols) != 0) { print $INDEX "\n"; } print $INDEX "
%s


\n"; } # Print a list of all exports sub ExportIndex { # File is argument my $INDEX = $_[0]; # Print the file list in a table print $INDEX "

Exports

\n"; print $INDEX "\n"; my $Count = 0; for my $Export (sort (keys (%Exports))) { # Get the export my $File; my $Label; ($File, $Label) = split (/#/, $Exports{$Export}); # The label is the label of the export statement. If we can find the # actual label, use this instead. if (exists ($Labels{$File}{$Export})) { $Label = $Labels{$File}{$Export}; } # if (($Count % $IndexCols) == 0) { print $INDEX "\n"; } printf $INDEX "\n", $File, $Label, $Export; if (($Count % $IndexCols) == $IndexCols-1) { print $INDEX "\n"; } $Count++; } if (($Count % $IndexCols) != 0) { print $INDEX "\n"; } print $INDEX "
%s


\n"; } sub CreateIndex { # Open the index page file open (INDEX, ">$HTMLDir$IndexName") or Abort ("Cannot open $IndexName: $!"); # Print the header DocHeader (INDEX, $IndexTitle, 0); # Print the file list in a table FileIndex (INDEX); ExportIndex (INDEX); # Print the document footer DocFooter (INDEX, $IndexName); # Close the index file close (INDEX); } #-----------------------------------------------------------------------------# # Print usage information # # ----------------------------------------------------------------------------# sub Usage { print "Usage: ca65html [options] file ...\n"; print "Options:\n"; print " --bgcolor c Use background color c instead of $BGColor\n"; print " --colorize Add color highlights to the output\n"; print " --commentcolor c Use color c for comments instead of $CommentColor\n"; print " --crefs Generate references to the C source file(s)\n"; print " --ctrlcolor c Use color c for directives instead of $CtrlColor\n"; print " --cvttabs Convert tabs to spaces in the output\n"; print " --help This text\n"; print " --htmldir dir Specify directory for HTML files\n"; print " --indexcols n Use n columns on index page (default $IndexCols)\n"; print " --indexname file Use file for the index file instead of $IndexName\n"; print " --indexpage Create an index page\n"; print " --indextitle title Use title as the index title instead of $IndexTitle\n"; print " --keywordcolor c Use color c for keywords instead of $KeywordColor\n"; print " --linelabels Generate a linexxx HTML label for each line\n"; print " --linenumbers Add line numbers to the output\n"; print " --linkstyle style Use the given link style\n"; print " --replaceext Replace source extension instead of appending .html\n"; print " --tabsize n Use n spaces when replacing tabs (default $TabSize)\n"; print " --textcolor c Use text color c instead of $TextColor\n"; print " --verbose Be more verbose\n"; } #-----------------------------------------------------------------------------# # Main # # ----------------------------------------------------------------------------# # Get program options GetOptions ("bgcolor=s" => \$BGColor, "colorize" => \$Colorize, "commentcolor=s" => \$CommentColor, "crefs" => \$CRefs, "ctrlcolor=s" => \$CtrlColor, "cvttabs" => \$CvtTabs, "debug!" => \$Debug, "help" => \$Help, "htmldir=s" => \$HTMLDir, "indexcols=i" => \$IndexCols, "indexname=s" => \$IndexName, "indexpage" => \$IndexPage, "indextitle=s" => \$IndexTitle, "keywordcolor=s" => \$KeywordColor, "linelabels" => \$LineLabels, "linenumbers" => \$LineNumbers, "linkstyle=i" => \$LinkStyle, "replaceext" => \$ReplaceExt, "tabsize=i" => \$TabSize, "textcolor=s" => \$TextColor, "verbose!" => \$Verbose, "<>" => \&AddFile); # Check some arguments if ($IndexCols <= 0 || $IndexCols >= 20) { Abort ("Invalid value for --indexcols option"); } if ($TabSize < 1 || $TabSize > 16) { Abort ("Invalid value for --tabsize option"); } if ($HTMLDir ne "" && $HTMLDir =~ /[^\/]$/) { # Add a trailing path separator $HTMLDir .= "/"; } # Print help if requested if ($Help) { Usage (); } # Check if we have input files given if ($FileCount == 0) { Abort ("No input files"); } # Convert the documents Pass1 (); Pass2 (); # Generate an index page if requested if ($IndexPage) { CreateIndex (); } # Done exit 0; cc65-2.18/util/cbm/000077500000000000000000000000001347360151100137235ustar00rootroot00000000000000cc65-2.18/util/cbm/cbmcvt.c000066400000000000000000000044751347360151100153570ustar00rootroot00000000000000/* cbmcvt.c -- PetSCII <--> ISO-8859-1 Conversion Filter Tool */ /* 2010-09-06, Greg King */ #include #include /* 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, 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F, 0x40,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,0x5B,0xBF,0x5D,0x5E,0xA4, 0xAD,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,0xB3,0xDD,0xAB,0xB1,0xDF, 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, 0x90,0x91,0x92,0x0C,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, 0xA0,0xA1,0xA2,0xA3,0x5F,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0x7D,0xAC,0x60,0xAE,0xAF, 0xB0,0x7E,0xB2,0x7B,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0x5C, 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,0xDC,0x7C,0xDE,0x7F, 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 }; static unsigned char CTISO[256]; int main (int argc, char *argv[]) { int C; size_t I = 0u; if (isatty(fileno(stdin))) { fputs("cbmcvt v2.1 -- Conversion Filter (stdin --> stdout)\n" " -p converts ISO-8859-1 to PetSCII\n" " else, converts in other direction.\n", stderr); return 0; } if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'p') { while ((C = fgetc (stdin)) != EOF) { fputc (CTPET[C], stdout); } } else { /* Create translation table PetSCII -> ISO-8859-1 */ for (; I < sizeof CTPET; ++I) { CTISO[CTPET[I]] = I; } while ((C = fgetc (stdin)) != EOF) { fputc (CTISO[C], stdout); } } return 0; } cc65-2.18/util/gamate/000077500000000000000000000000001347360151100144205ustar00rootroot00000000000000cc65-2.18/util/gamate/gamate-fixcart.c000066400000000000000000000013201347360151100174540ustar00rootroot00000000000000 #include #include FILE *in; unsigned int n, i, c; void usage(char *arg) { printf("usage: %s [file]\n", arg); exit(-1); } int main(int argc, char *argv[]) { if (argc < 2) { usage(argv[0]); exit(-1); } if (!(in = fopen(argv[1], "r+b"))) { fprintf(stderr, "couldnt open: '%s'\n", argv[1]); exit(-1); } /* read 0x1000 bytes from 0x7000-0x7fff (offset 0x1000) */ fseek(in, 0x1000, SEEK_SET); n = 0; for (i = 0; i < 0x1000; i++) { c = fgetc(in); n += c; } /* write checksum to header */ fseek(in, 0, SEEK_SET); fputc(n & 0xff, in); fputc((n >> 8) & 0xff, in); fclose(in); return (0); } cc65-2.18/util/zlib/000077500000000000000000000000001347360151100141225ustar00rootroot00000000000000cc65-2.18/util/zlib/deflater.c000066400000000000000000000050571347360151100160630ustar00rootroot00000000000000/* ** Compresses data to the DEFLATE format. ** The compressed data is ready to use with inflatemem(). ** Compile using e.g. ** gcc -O2 -o deflater deflater.c -lz ** ** Author: Piotr Fusik */ #include #include #include #define IN_SIZE_MAX 60000U #define OUT_SIZE_MAX 60000U int main(int argc, char* argv[]) { FILE* fp; char* inbuf; char* outbuf; size_t inlen; size_t outlen; z_stream stream; /* check command line */ if (argc != 3) { fprintf(stderr, "Compresses a file to the DEFLATE format.\n" "24 Aug 2002, Piotr Fusik \n" "Usage: deflater input_file deflated_file\n" ); return 3; } /* alloc buffers */ inbuf = malloc(IN_SIZE_MAX); outbuf = malloc(OUT_SIZE_MAX); if (inbuf == NULL || outbuf == NULL) { fprintf(stderr, "deflater: Out of memory!\n"); return 1; } /* read input file */ fp = fopen(argv[1], "rb"); if (fp == NULL) { perror(argv[1]); return 1; } inlen = fread(inbuf, 1, IN_SIZE_MAX, fp); fclose(fp); /* compress */ stream.next_in = inbuf; stream.avail_in = inlen; stream.next_out = outbuf; stream.avail_out = OUT_SIZE_MAX; stream.zalloc = (alloc_func) 0; stream.zfree = (free_func) 0; if (deflateInit2(&stream, Z_BEST_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 9, Z_DEFAULT_STRATEGY) != Z_OK) { fprintf(stderr, "deflater: deflateInit2 failed\n"); return 1; } if (deflate(&stream, Z_FINISH) != Z_STREAM_END) { fprintf(stderr, "deflater: deflate failed\n"); return 1; } if (deflateEnd(&stream) != Z_OK) { fprintf(stderr, "deflater: deflateEnd failed\n"); return 1; } /* write output */ fp = fopen(argv[2], "wb"); if (fp == NULL) { perror(argv[2]); return 1; } outlen = fwrite(outbuf, 1, stream.total_out, fp); fclose(fp); if (outlen != stream.total_out) { perror(argv[2]); return 1; } /* display summary */ printf("Compressed %s (%d bytes) to %s (%d bytes)\n", argv[1], inlen, argv[2], outlen); return 0; }